"""Built-in schedule templates: duty, explore, and restore_fun menus. Escape (porn binge, family courtroom) is NOT explore. """ from __future__ import annotations from typing import Any # Each template: default_min, kind, intent, utility U, fse_load, default priority. TEMPLATES: list[dict[str, Any]] = [ { "id": "earn_one_ship", "title": "Earn one ship", "kind": "earn_ship", "intent": "duty", "priority": "P1", "default_min": 45, "utility": 0.9, "fse_load": 0.2, "label": "Work / earn", }, { "id": "admin_task", "title": "Trip / admin task", "kind": "admin_spain", "intent": "duty", "priority": "P0", "default_min": 30, "utility": 0.85, "fse_load": 0.3, "label": "Trip / admin", "locked": True, }, { "id": "body_room", "title": "Body or room care", "kind": "body_care", "intent": "duty", "priority": "P2", "default_min": 20, "utility": 0.55, "fse_load": 0.1, "label": "Body or room", }, { "id": "move_out_line", "title": "Move-out one line", "kind": "move_out", "intent": "duty", "priority": "P1", "default_min": 15, "utility": 0.7, "fse_load": 0.25, "label": "Move-out step", }, { "id": "food_outside", "title": "Food outside", "kind": "food_out", "intent": "duty", "priority": "P0", "default_min": 45, "utility": 0.8, "fse_load": 0.15, "label": "Food", "locked": True, }, { "id": "boundary_5m", "title": "Boundary practice 5m", "kind": "boundary", "intent": "duty", "priority": "P2", "default_min": 10, "utility": 0.5, "fse_load": 0.2, "label": "Boundary practice", }, { "id": "walk_new_route", "title": "Timed walk new route 20m", "kind": "explore", "intent": "explore", "priority": "P2", "default_min": 20, "utility": 0.45, "fse_load": 0.05, "label": "Try something new", "measure": "rate urge/mood after", }, { "id": "music_album", "title": "Music full album + fun rating", "kind": "restore_fun", "intent": "restore_fun", "priority": "P2", "default_min": 40, "utility": 0.4, "fse_load": 0.05, "label": "Fun recharge", }, { "id": "cook_simple", "title": "Cook simple meal", "kind": "explore", "intent": "explore", "priority": "P2", "default_min": 35, "utility": 0.5, "fse_load": 0.1, "label": "Try something new", "money_optional": True, }, { "id": "photo_challenge", "title": "Photo challenge 20 shots", "kind": "explore", "intent": "explore", "priority": "P2", "default_min": 25, "utility": 0.45, "fse_load": 0.05, "label": "Try something new", }, { "id": "spanish_15", "title": "Spanish 15m light practice", "kind": "explore", "intent": "explore", "priority": "P2", "default_min": 15, "utility": 0.55, "fse_load": 0.1, "label": "Try something new", }, { "id": "cafe_45", "title": "Cafe 45m + short journal", "kind": "restore_fun", "intent": "restore_fun", "priority": "P2", "default_min": 45, "utility": 0.5, "fse_load": 0.1, "label": "Fun recharge", "money_optional": True, }, { "id": "stabilize_10", "title": "Stabilize: walk/move 10m", "kind": "stabilize", "intent": "measure", "priority": "P1", "default_min": 10, "utility": 0.6, "fse_load": 0.0, "label": "Stabilize / reset", "measure": "after urge", }, { "id": "sleep_wind", "title": "Sleep wind-down", "kind": "sleep_window", "intent": "duty", "priority": "P0", "default_min": 45, "utility": 0.85, "fse_load": 0.0, "label": "Sleep wind-down", "locked": True, }, { "id": "fantasy_slot_25", "title": "Scheduled movie/fantasy (timer)", "kind": "restore_fun", "intent": "restore_fun", "priority": "P2", "default_min": 25, "utility": 0.35, "fse_load": 0.15, "label": "Fun recharge", "notes": "Containment slot — timer on; not a lecture. After timer, one proof brick.", }, ] KIND_LABELS: dict[str, str] = { "earn_ship": "Work / earn", "admin_spain": "Trip / admin", "body_care": "Body or room", "move_out": "Move-out step", "food_out": "Food", "stabilize": "Stabilize / reset", "explore": "Try something new", "restore_fun": "Fun recharge", "boundary": "Boundary practice", "sleep_window": "Sleep wind-down", "other": "Other", } def list_templates() -> list[dict[str, Any]]: return list(TEMPLATES) def template_by_id(template_id: str) -> dict[str, Any] | None: for row in TEMPLATES: if row["id"] == template_id: return dict(row) return None # Default clock slots for empty-day seed (P0 locked first). SEED_SLOTS: list[tuple[str, str, str]] = [ ("earn_one_ship", "09:00", "09:45"), ("food_outside", "12:30", "13:15"), ("stabilize_10", "15:00", "15:15"), ("walk_new_route", "16:30", "16:50"), ("sleep_wind", "22:00", "22:45"), ] def seed_template_ids(*, capacity_hint: float) -> list[str]: """Pick starter template ids under capacity (P0 always; cut P2 when low).""" ids = ["food_outside", "sleep_wind"] if capacity_hint >= 0.45: ids.insert(0, "earn_one_ship") if capacity_hint < 0.55: ids.append("stabilize_10") if capacity_hint >= 0.4: ids.append("walk_new_route") # Preserve SEED_SLOTS order order = {tid: i for i, (tid, _, _) in enumerate(SEED_SLOTS)} return sorted(set(ids), key=lambda t: order.get(t, 99))