#!/usr/bin/env python3 """Pick this week's world cuisine for the weekly shop. Design goals: - RANDOM per week, but STABLE within a week (seeded by the week's Monday date) so that re-runs / retries of the Monday job never flip the cuisine mid-week. - VARIED over time: the last few chosen cuisines are excluded from the pool. - PERSISTED to cuisine-rotation.json so the daily meal job can read the active cuisine and cook on-theme meals from the same week's buys. Usage: python3 pick_cuisine.py # pick (or reuse) and persist python3 pick_cuisine.py --dry-run # print only, do not write Prints a JSON line: {"week_monday": "...", "cuisine": "...", "theme_items": [...], "reused": bool} """ import argparse import json import os from datetime import date, timedelta HERE = os.path.dirname(os.path.abspath(__file__)) ROTATION_FILE = os.path.join(HERE, "..", "cuisine-rotation.json") # Curated cuisines: all are achievable at Lidl on a ~£30 budget, high-protein, # and contain NO red meat by design. theme_items are cheap, cuisine-appropriate # buys (proteins/veg/staples/condiments) that add variety; some may already be # in inventory — the weekly job still cross-checks budget + Lidl availability. CUISINES = { "Mexican / Tex-Mex": [ "wholemeal tortilla wraps", "tinned black beans", "tinned sweetcorn", "tinned chopped tomatoes", "cheddar cheese", "lime", "cumin", "smoked paprika", "avocado", "chicken breast", "Greek yogurt", ], "Greek / Mediterranean": [ "feta", "Kalamata olives", "cucumber", "cherry tomatoes", "chickpeas", "halloumi", "dried oregano", "lemon", "red onion", "tinned tuna", "Greek yogurt", ], "Indian / South Asian": [ "red lentils", "chickpeas", "tinned tomatoes", "fresh spinach", "curry powder", "grated ginger", "onions", "Greek yogurt", "firm tofu", "microwave rice", "chicken breast", ], "Thai": [ "jasmine rice", "coconut milk (tin)", "soy sauce", "lime", "grated ginger", "red curry paste", "frozen prawns", "edamame", "fish-free: tofu", "fresh coriander", "eggs", ], "East Asian / Japanese": [ "egg noodles", "soy sauce", "edamame (frozen)", "eggs", "firm tofu", "sesame seeds", "tinned tuna", "miso paste", "frozen mixed veg", "grated ginger", "spring onions", ], "Middle Eastern / Levantine": [ "chickpeas", "red lentils", "feta", "cucumber", "tomatoes", "lemon", "cumin", "pitta breads", "halloumi", "Greek yogurt", "fresh parsley", "chicken breast", ], "Italian": [ "passata", "wholemeal pasta", "mozzarella", "tinned tuna", "cherry tomatoes", "fresh basil", "black olives", "spinach", "eggs", "chicken breast", "parmesan", ], "Korean": [ "jasmine rice", "soy sauce", "sesame oil", "sesame seeds", "gochujang (tube)", "eggs", "firm tofu", "kimchi (jar)", "frozen mixed veg", "grated ginger", "spring onions", ], } # How many recent cuisines to exclude so weeks don't repeat back-to-back. RECENT_WINDOW = 4 def week_monday(d=None): d = d or date.today() return d - timedelta(days=d.weekday()) # Monday=0 def load_rotation(): try: with open(ROTATION_FILE) as f: return json.load(f) except FileNotFoundError: return {"current": None, "history": []} def save_rotation(data): os.makedirs(os.path.dirname(ROTATION_FILE), exist_ok=True) with open(ROTATION_FILE, "w") as f: json.dump(data, f, indent=2) def pick(dry_run=False): import random monday = week_monday() monday_str = monday.isoformat() rot = load_rotation() # Same week -> reuse the locked-in cuisine (stable within the week). if rot.get("current") and rot["current"].get("week_monday") == monday_str: rot["current"]["reused"] = True print(json.dumps(rot["current"])) return pool = list(CUISINES.keys()) recent = [h["cuisine"] for h in rot.get("history", [])[-RECENT_WINDOW:]] candidates = [c for c in pool if c not in recent] or pool # Seed by the week's Monday so the pick is deterministic for that week # (re-runs in the same week always return the same cuisine). rng = random.Random(monday_str) cuisine = rng.choice(candidates) chosen = { "week_monday": monday_str, "cuisine": cuisine, "theme_items": CUISINES[cuisine], "reused": False, } if dry_run: print(json.dumps(chosen)) return history = rot.get("history", []) history.append({"week_monday": monday_str, "cuisine": cuisine}) # Keep history bounded. history = history[-12:] save_rotation({"current": chosen, "history": history}) print(json.dumps(chosen)) def main(): ap = argparse.ArgumentParser() ap.add_argument("--dry-run", action="store_true", help="print the pick without persisting") args = ap.parse_args() pick(dry_run=args.dry_run) if __name__ == "__main__": main()