41 lines
1.3 KiB
TypeScript
41 lines
1.3 KiB
TypeScript
import { UNIT_INFO, type Unit } from "@app/shared-types";
|
|
|
|
export interface ScalableIngredient {
|
|
canonicalIngredientId: string;
|
|
displayNameSv: string;
|
|
quantity: number;
|
|
unit: Unit;
|
|
optional: boolean;
|
|
}
|
|
|
|
/** Enheter som avrundas till "köksvänliga" mängder vid skalning. */
|
|
const SPOON_UNITS: ReadonlySet<Unit> = new Set(["TABLESPOON", "TEASPOON", "PINCH"]);
|
|
|
|
/**
|
|
* Skala recept till annat antal portioner (Cooking Mode: "skala till sex personer").
|
|
* Kryddmått avrundas till halva mått; styck till kvartar.
|
|
*/
|
|
export function scaleIngredients(
|
|
ingredients: ScalableIngredient[],
|
|
fromPortions: number,
|
|
toPortions: number,
|
|
): ScalableIngredient[] {
|
|
if (fromPortions <= 0 || toPortions <= 0) {
|
|
throw new Error("Portioner måste vara > 0");
|
|
}
|
|
const factor = toPortions / fromPortions;
|
|
return ingredients.map((ing) => ({
|
|
...ing,
|
|
quantity: roundForUnit(ing.quantity * factor, ing.unit),
|
|
}));
|
|
}
|
|
|
|
function roundForUnit(value: number, unit: Unit): number {
|
|
if (SPOON_UNITS.has(unit)) return Math.round(value * 2) / 2;
|
|
if (UNIT_INFO[unit].kind === "count") return Math.round(value * 4) / 4;
|
|
if (unit === "KILOGRAM" || unit === "LITER" || unit === "POUND")
|
|
return Math.round(value * 100) / 100;
|
|
if (unit === "CUP_US") return Math.round(value * 4) / 4;
|
|
return Math.round(value * 10) / 10;
|
|
}
|