Files
Meal-Planner/backend/app/services/planner/config.py
T
admin 7b5e65087e feat: 21 meals per week (3/day) + approve/deny + generate single meal
Backend:
- Planner config: set_size=21 (was 3), top_k=30 (was 20)
- generate.py: distribute 21 recipes across 7 days × 3 meal types
- meals.py: add POST /items/{id}/approve, /items/{id}/deny
- meals.py: add POST /{plan_id}/generate-item for empty slots

Frontend:
- Dashboard: Approve/Deny buttons on pending meal cards
- Dashboard: Generate button in empty meal slots
- API client: approveItem, denyItem, generateItem methods

Build: TypeScript compiles clean, Python syntax verified.
2026-05-15 11:44:04 -07:00

43 lines
1.6 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.
"""Planner constants. Tune here without touching algorithm code."""
from __future__ import annotations
from dataclasses import dataclass
@dataclass(frozen=True)
class PlannerConfig:
# Hard constraints
recency_weeks: int = 4 # constraint #3: no repeat within N weeks
calorie_tolerance_pct: int = 20 # constraint #4: ±X% of family.calorie_target
max_total_minutes: int = 45 # constraint #5: prep + cook
max_meal_cost: float = 30.00 # constraint #6: dollars per meal
# Scoring weights (must sum to 1.0)
w_savings: float = 0.30
w_coverage: float = 0.25
w_pantry: float = 0.10
w_time: float = 0.15
w_recency: float = 0.20
# Time bonus boundaries
time_ideal_minutes: int = 25 # full bonus at <= this
time_full_minutes: int = 45 # zero bonus at this; matches max_total_minutes
# Recency bonus boundary
recency_full_weeks: int = 12 # full bonus when last cooked >= this many weeks ago
# Set selection
top_k: int = 20 # how many feasible recipes to enumerate over
set_size: int = 21 # 21 meals/week (3 per day × 7 days)
p_protein: float = 0.15 # diversity penalty per shared-protein pair
p_cuisine: float = 0.10 # diversity penalty per shared-cuisine pair
def validate(self) -> None:
total = self.w_savings + self.w_coverage + self.w_pantry + self.w_time + self.w_recency
if abs(total - 1.0) > 1e-6:
raise ValueError(f"weights must sum to 1.0, got {total}")
DEFAULT = PlannerConfig()
DEFAULT.validate()