mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2026-01-04 21:58:54 -05:00
first working number scaling
This commit is contained in:
34
vue3/src/components/display/InstructionsCompileComponent.vue
Normal file
34
vue3/src/components/display/InstructionsCompileComponent.vue
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<template>
|
||||||
|
<component :is="compiled" :ingredient_factor="ingredient_factor" :code="code"></component>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import {defineComponent} from "vue";
|
||||||
|
|
||||||
|
import ScalableNumber from "@/components/display/ScalableNumber.vue";
|
||||||
|
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'InstructionsCompileComponent',
|
||||||
|
computed: {},
|
||||||
|
components: {ScalableNumber},
|
||||||
|
props: [
|
||||||
|
'code', 'ingredient_factor'
|
||||||
|
],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
compiled: defineComponent( {
|
||||||
|
name: 'compiled-instructions-component',
|
||||||
|
props: ['ingredient_factor', 'code'],
|
||||||
|
components: { ScalableNumber, },
|
||||||
|
template: `<div>${this.code}</div>`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
25
vue3/src/components/display/ScalableNumber.vue
Normal file
25
vue3/src/components/display/ScalableNumber.vue
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<template>
|
||||||
|
<span class="step__scalable-num" :class="[this.factor===1 ? 'step__scalable-num_scaled_false' : (this.factor > 1 ? 'step__scalable-num_scaled_up':'step__scalable-num_scaled_down')]" v-html="calculateAmount(number)"></span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
|
||||||
|
import {calculateFoodAmount} from "@/utils/number_utils.ts";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ScalableNumber',
|
||||||
|
props: {
|
||||||
|
number: Number,
|
||||||
|
factor: {
|
||||||
|
type: Number,
|
||||||
|
default: 4
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
calculateAmount: function (x) {
|
||||||
|
return calculateFoodAmount(x, this.factor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -19,8 +19,8 @@
|
|||||||
|
|
||||||
<IngredientsTable :ingredients="step.ingredients"></IngredientsTable>
|
<IngredientsTable :ingredients="step.ingredients"></IngredientsTable>
|
||||||
|
|
||||||
<v-card-text v-if="step.instruction?.length > 0">
|
<v-card-text v-if="step.instructionsMarkdown.length > 0">
|
||||||
{{ step.instruction }}
|
<instructions-compile-component :code="step.instructionsMarkdown" :ingredient_factor="1"></instructions-compile-component>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</v-card>
|
</v-card>
|
||||||
</template>
|
</template>
|
||||||
@@ -31,6 +31,8 @@ import IngredientsTable from "@/components/display/IngredientsTable.vue";
|
|||||||
import {Step} from "@/openapi";
|
import {Step} from "@/openapi";
|
||||||
import {DateTime, Duration, Interval} from "luxon";
|
import {DateTime, Duration, Interval} from "luxon";
|
||||||
|
|
||||||
|
import InstructionsCompileComponent from "@/components/display/InstructionsCompileComponent.vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "Step",
|
name: "Step",
|
||||||
computed: {
|
computed: {
|
||||||
@@ -59,7 +61,7 @@ export default defineComponent({
|
|||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {IngredientsTable},
|
components: {InstructionsCompileComponent, IngredientsTable},
|
||||||
props: {
|
props: {
|
||||||
step: {
|
step: {
|
||||||
type: {} as PropType<Step>,
|
type: {} as PropType<Step>,
|
||||||
|
|||||||
82
vue3/src/utils/number_utils.ts
Normal file
82
vue3/src/utils/number_utils.ts
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
function getUserPreference(pref: string) {
|
||||||
|
return false // TODO only placeholder, add real function
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* round to the number of decimals specified in user preferences
|
||||||
|
* @param num number to round
|
||||||
|
*/
|
||||||
|
export function roundDecimals(num: number) {
|
||||||
|
let decimals = 2 //TODO get user preference
|
||||||
|
return num.toFixed(decimals)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* calculates the amount of food, based on the factor and converts it to a fraction if that is the users preference
|
||||||
|
* @param amount food amount to calculate based upon
|
||||||
|
* @param factor factor to scale food amount by
|
||||||
|
*/
|
||||||
|
export function calculateFoodAmount(amount: number, factor: number) {
|
||||||
|
if (getUserPreference("use_fractions")) {
|
||||||
|
let return_string = ""
|
||||||
|
let fraction = frac(amount * factor, 16, true)
|
||||||
|
|
||||||
|
if (fraction[0] === 0 && fraction[1] === 0 && fraction[2] === 1) {
|
||||||
|
return roundDecimals(amount * factor)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fraction[0] > 0) {
|
||||||
|
return_string += fraction[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fraction[1] > 0) {
|
||||||
|
return_string += ` <sup>${fraction[1]}</sup>⁄<sub>${fraction[2]}</sub>`
|
||||||
|
}
|
||||||
|
|
||||||
|
return return_string
|
||||||
|
} else {
|
||||||
|
return roundDecimals(amount * factor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* frac.js (C) 2012-present SheetJS -- http://sheetjs.com */
|
||||||
|
|
||||||
|
/* https://www.npmjs.com/package/frac Apache license*/
|
||||||
|
/**
|
||||||
|
* calculates the closest approximation of a fraction for a given decimal number
|
||||||
|
* @param x decimal number to convert into fraction
|
||||||
|
* @param D the maximum denominator to return
|
||||||
|
* @param mixed true to return mixed fractions (e.g. 2 1/2) or false to return improper fractions (e.g. 5/2)
|
||||||
|
* @returns [quot, num, den] array of numbers, quot is either 0 for improper fractions or the whole number, num is the numerator of the fraction and den the denominator
|
||||||
|
*/
|
||||||
|
export function frac(x, D, mixed) {
|
||||||
|
let n1 = Math.floor(x), d1 = 1;
|
||||||
|
let n2 = n1 + 1, d2 = 1;
|
||||||
|
if (x !== n1) while (d1 <= D && d2 <= D) {
|
||||||
|
let m = (n1 + n2) / (d1 + d2);
|
||||||
|
if (x === m) {
|
||||||
|
if (d1 + d2 <= D) {
|
||||||
|
d1 += d2;
|
||||||
|
n1 += n2;
|
||||||
|
d2 = D + 1;
|
||||||
|
} else if (d1 > d2) d2 = D + 1;
|
||||||
|
else d1 = D + 1;
|
||||||
|
break;
|
||||||
|
} else if (x < m) {
|
||||||
|
n2 = n1 + n2;
|
||||||
|
d2 = d1 + d2;
|
||||||
|
} else {
|
||||||
|
n1 = n1 + n2;
|
||||||
|
d1 = d1 + d2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (d1 > D) {
|
||||||
|
d1 = d2;
|
||||||
|
n1 = n2;
|
||||||
|
}
|
||||||
|
if (!mixed) return [0, n1, d1];
|
||||||
|
let q = Math.floor(n1 / d1);
|
||||||
|
return [q, n1 - q * d1, d1];
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user