Spaces:
Sleeping
Sleeping
| """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)) | |