diff --git a/src/lib/server/recipes/scaler.ts b/src/lib/server/recipes/scaler.ts new file mode 100644 index 0000000..c3390cd --- /dev/null +++ b/src/lib/server/recipes/scaler.ts @@ -0,0 +1,16 @@ +import type { Ingredient } from '$lib/types'; + +export function roundQuantity(q: number): number { + if (q === 0) return 0; + if (q < 1) return Math.round(q * 100) / 100; + if (q < 10) return Math.round(q * 10) / 10; + return Math.round(q); +} + +export function scaleIngredients(ings: Ingredient[], factor: number): Ingredient[] { + if (factor <= 0) throw new Error('factor must be positive'); + return ings.map((i) => ({ + ...i, + quantity: i.quantity === null ? null : roundQuantity(i.quantity * factor) + })); +} diff --git a/tests/unit/scaler.test.ts b/tests/unit/scaler.test.ts new file mode 100644 index 0000000..ec77cd6 --- /dev/null +++ b/tests/unit/scaler.test.ts @@ -0,0 +1,43 @@ +import { describe, it, expect } from 'vitest'; +import { scaleIngredients, roundQuantity } from '../../src/lib/server/recipes/scaler'; +import type { Ingredient } from '../../src/lib/types'; + +const mk = (q: number | null, unit: string | null, name: string): Ingredient => ({ + position: 0, + quantity: q, + unit, + name, + note: null, + raw_text: '' +}); + +describe('roundQuantity', () => { + it.each([ + [0.333333, 0.33], + [12.345, 12], + [1.55, 1.6], + [100.49, 100], + [0.5, 0.5] + ] as const)('rounds %f to %f', (input, expected) => { + expect(roundQuantity(input)).toBe(expected); + }); +}); + +describe('scaleIngredients', () => { + it('scales parsed quantities', () => { + const scaled = scaleIngredients([mk(200, 'g', 'Mehl'), mk(3, null, 'Eier')], 2); + expect(scaled[0].quantity).toBe(400); + expect(scaled[1].quantity).toBe(6); + }); + + it('leaves null quantities alone', () => { + const scaled = scaleIngredients([mk(null, null, 'etwas Salz')], 2); + expect(scaled[0].quantity).toBeNull(); + expect(scaled[0].name).toBe('etwas Salz'); + }); + + it('rounds sensibly', () => { + const scaled = scaleIngredients([mk(100, 'g', 'Butter')], 1 / 3); + expect(scaled[0].quantity).toBe(33); + }); +});