Some checks failed
CI / build-test (push) Has been cancelled
Reviewed-on: #3 Co-authored-by: jableader <jacobdunk@gmail.com> Co-committed-by: jableader <jacobdunk@gmail.com>
139 lines
3.3 KiB
TypeScript
139 lines
3.3 KiB
TypeScript
const UNIT_KEYS_ARRAY: readonly ['kg', 'litres', 'items'] = ['kg', 'litres', 'items']
|
|
type UnitKey = typeof UNIT_KEYS_ARRAY[number]
|
|
|
|
const equivalentUnits: Record<UnitKey, Record<string, number>> = {
|
|
kg: {
|
|
kgs: 1,
|
|
kilograms: 1,
|
|
kilogram: 1,
|
|
|
|
g: 1000,
|
|
gram: 1000,
|
|
grams: 1000,
|
|
|
|
lb: 2.20462,
|
|
lbs: 2.20462,
|
|
pound: 2.20462,
|
|
pounds: 2.20462,
|
|
},
|
|
litres: {
|
|
l: 1,
|
|
liter: 1,
|
|
litre: 1,
|
|
|
|
ml: 1000,
|
|
milliliters: 1000,
|
|
milliliter: 1000,
|
|
|
|
'fl oz': 33.814,
|
|
'fluid ounce': 33.814,
|
|
'fluid ounces': 33.814,
|
|
|
|
cup: 4.22675,
|
|
cups: 4.22675,
|
|
|
|
tbsp: 67.628,
|
|
tablespoon: 67.628,
|
|
tablespoons: 67.628,
|
|
|
|
tsp: 202.884,
|
|
teaspoon: 202.884,
|
|
teaspoons: 202.884,
|
|
|
|
pt: 2.11338,
|
|
pint: 2.11338,
|
|
pints: 2.11338,
|
|
|
|
qt: 1.05669,
|
|
quart: 1.05669,
|
|
quarts: 1.05669,
|
|
|
|
gal: 0.264172,
|
|
gallon: 0.264172,
|
|
gallons: 0.264172,
|
|
|
|
oz: 35.1951,
|
|
ounce: 35.1951,
|
|
},
|
|
items: {
|
|
item: 1,
|
|
items: 1,
|
|
pcs: 1,
|
|
piece: 1,
|
|
pieces: 1,
|
|
florets: 8, // Broccoli
|
|
head: 1, // Broccoli
|
|
heads: 1, // Broccoli
|
|
slice: 10, // Bread
|
|
slices: 10, // Bread
|
|
loaf: 1, // Bread
|
|
loaves: 1, // Bread
|
|
cloves: 8, // Garlic
|
|
bulb: 1, // Garlic
|
|
bulbs: 1, // Garlic
|
|
stalk: 1, // Celery
|
|
stalks: 1, // Celery
|
|
bunch: 1, // Cilantro
|
|
bunches: 1, // Cilantro
|
|
sprig: 1, // Cilantro
|
|
sprigs: 1, // Cilantro
|
|
cans: 1, // Canned goods
|
|
can: 1, // Canned goods
|
|
pack: 1, // Packaged goods
|
|
packs: 1, // Packaged goods
|
|
package: 1, // Packaged goods
|
|
packages: 1, // Packaged goods
|
|
container: 1, // Packaged goods
|
|
containers: 1, // Packaged goods
|
|
},
|
|
}
|
|
|
|
const UNIT_KEYS_SET: ReadonlySet<string> = new Set(UNIT_KEYS_ARRAY)
|
|
function isUnitKey(value: string): value is UnitKey {
|
|
return UNIT_KEYS_SET.has(value)
|
|
}
|
|
|
|
function getBaseUnit(unit: string): UnitKey | null {
|
|
for (const type of UNIT_KEYS_ARRAY) {
|
|
const group = equivalentUnits[type]
|
|
if (unit in group) return type
|
|
}
|
|
return null
|
|
}
|
|
|
|
export function getConversionFactor(unit: string): { unit: UnitKey | string; factor: number } | null {
|
|
if (isUnitKey(unit)) return { unit, factor: 1 }
|
|
|
|
const unitLower = String(unit).toLowerCase()
|
|
if (isUnitKey(unitLower)) return { unit: unitLower, factor: 1 }
|
|
|
|
const baseUnit = getBaseUnit(unit)
|
|
if (baseUnit) {
|
|
const factor = equivalentUnits[baseUnit]?.[unit]
|
|
if (typeof factor === 'number') return { unit: baseUnit, factor }
|
|
return null
|
|
}
|
|
|
|
const baseUnitLower = getBaseUnit(unitLower)
|
|
if (baseUnitLower) {
|
|
const factor = equivalentUnits[baseUnitLower]?.[unitLower]
|
|
if (typeof factor === 'number') return { unit: baseUnitLower, factor }
|
|
return null
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
type Quantity = { quantity: number; unit: string }
|
|
type Total = { unit: string; quantity: number }
|
|
|
|
export function calculateTotals(quantityList: Quantity[]): Total[] {
|
|
const totals: Record<string, number> = {}
|
|
for (const quantity of quantityList) {
|
|
const baseUnit = getConversionFactor(quantity.unit) ?? { unit: quantity.unit, factor: 1 }
|
|
const factor = baseUnit.factor
|
|
const unit = String(baseUnit.unit)
|
|
totals[unit] = (totals[unit] ?? 0) + quantity.quantity / factor
|
|
}
|
|
return Object.keys(totals).map((unit) => ({ unit, quantity: totals[unit] ?? 0 }))
|
|
}
|