Files
calcount/backend/services/nutrition.py
T
Craig e047d884b6 Initial project scaffold: FastAPI backend + Svelte 5 frontend
Backend (uv): FastAPI app with routers (foods, log, targets, OFF proxy),
SQLAlchemy models, Pydantic schemas, migration runner + 0001 initial schema,
example pytest suite (7 tests).
Frontend (npm): Vite 7 + Svelte 5 runes, lib/ (api, stores, scanner, format)
per spec §7, placeholder components, example vitest suite (4 tests).
SPEC.md §1: registered uvicorn and Vitest (rule §8.3.3).
2026-07-26 10:26:08 +01:00

31 lines
1.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Nutrition math — the ONLY place nutrition is computed (spec §8.1 rule 1).
Routers never compute nutrition; the frontend never re-derives it.
`quantity` is interpreted by context (spec §2.1):
- unit_type "weight": quantity is grams; nutrition = (quantity / 100) × per_unit
- unit_type "count": quantity is item count; nutrition = quantity × per_unit
- meal: quantity is a scaling factor (1.0 = one full meal)
"""
from models import Food
def scale_to_quantity(per_unit: float | None, quantity: float, unit_type: str) -> float:
"""Scale a per-unit nutrition value to a logged quantity. Missing values count as 0."""
if per_unit is None:
return 0.0
if unit_type == "weight":
return per_unit * quantity / 100.0
if unit_type == "count":
return per_unit * quantity
raise ValueError(f"unknown unit_type: {unit_type!r}")
def entry_calories(food: Food, quantity: float) -> float:
"""Calories for a single (non-meal) food at a logged quantity.
TODO: handle is_meal foods by summing scaled component nutrition
(recursively, with cycle detection — spec §2.2).
"""
return scale_to_quantity(food.calories_per_unit, quantity, food.unit_type)