:PROPERTIES: :ID: ff8aa6b7-61ff-444c-9301-c0b666b0b573 :END: #+title: trmn/schedule #+filetags: :project: :knowledge: :schedule: :PROPERTIES: :ID: trmn-schedule :END: #+title: trmn/schedule #+filetags: :project: :knowledge: :schedule: ** Architecture ~schedule.js~ is a standalone ES module that exports: - ~generateDaySchedule(today, traits, dayEvents, currentDay, masterSeed)~ → ~ScheduleEntry[]~ - ~SCENES~ — plain object catalog of all ~68 scenes - ~slotToTime(slot)~ → ~"HH:MM"~ string (slot 0 = 06:00) - ~SLOTS~ (96), ~SLOT_MIN~ (15) ~ScheduleEntry~: ~{ slot, duration, sceneId, location, label }~. Array is sorted by slot, non-overlapping, always covers all 96 slots with no gaps (builder fills remainder with ~sleep~). RNG isolation: schedule uses ~makeRng(masterSeed, currentDay + 50000)~. Offset of 50,000 clears the life sim's 0–36,500 range — no interference with protagonist daily streams. ~window.__life~ exposes ~{ ..., schedule }~ alongside ~buf~, ~eventLog~, ~people~. ** Slot Layout #+begin_example Slots 0–11 06:00–09:00 morning routine (12 slots) Slots 12–23 09:00–12:00 early daytime (12 slots) Slots 24–43 12:00–17:00 afternoon (20 slots) Slots 44–55 17:00–20:00 early evening (12 slots) Slots 56–63 20:00–22:00 late evening (8 slots) Slots 64–95 22:00–06:00 sleep (32 slots) #+end_example ** Life Stage Detection ~detectLifeStage(today, age)~ → one of 10 tags, checked in priority order: ~very_sick~ (sick + health<25) → ~sick~ → ~toddler~ (age<5) → ~kindergarten~ (eduStage=1) → ~school~ (eduStage=2/3) → ~college~ (inCollege) → ~retired~ → ~worker~ (employed) → ~unemployed~ (age≥16) → ~child~ ** Forced Events Events in ~dayEvents~ (from ~eventLog.get(currentDay)~) that override normal blocks: | Event ID | Override | |---|---| | ~illness_acute~ | daytime → rest_in_bed; skip work/school | | ~serious_accident~ / ~injury_serious~ | afternoon → emergency_room | | ~first_child~ / ~subsequent_child~ | daytime → hospital_stay | | ~marry~ | afternoon → wedding_ceremony; evening → wedding_reception | | ~family_member_death~ (attended=true) | afternoon → funeral_ceremony + wake | | ~move_city~ | full day → moving_boxes | | ~premature_death~ | minimal day, idle | ** Gotchas - ~jobCategory~ is NOT in the packed ~Float32Array~ buffer (not a field in ~F~). Schedule derives a stable per-character type from ~makeRng(masterSeed ^ 0x5A5A5A5A, 0)~. This is deterministic per character but may not match what was rolled in the life sim. - Young-child stages (~toddler~, ~kindergarten~, ~school~, ~child~) must be branched BEFORE adult defaults in morning and evening blocks. The ~isYoungChild~ flag gates: no ~make_breakfast~, no ~cook_dinner~, no ~morning_coffee~, no ~morning_exercise~. The adult fallthrough path always ran these — easy to regress. - ~go_to_park_with_parents~ is from the CHILD's perspective; ~hasYoungChildren~ is from the PARENT's perspective. They are mutually exclusive: ~hasYoungChildren = numChildren > 0 && age < 40~. - The schedule builder (~makeBuilder~) clamps at slot 96: ~push~ is a no-op once cursor ≥ SLOTS. ~fill(sceneId, toSlot)~ is safe to call even if cursor is already past ~toSlot~. ** Debug Tool ~schedule-debug.mjs~ — CLI tool, ~nix run .#schedule~ - No args: random seed + random day from character's living years, full output - Prints seed, day, age, full state, traits, events, then schedule table - All state fields overridable: ~--seed~, ~--day~, ~--age~, ~--health~, ~--sick~, ~--employed~, ~--retired~, ~--married~, ~--children~, ~--friends~, ~--job-tier~, ~--loneliness~ - ~--event ~ injects a forced event (repeatable); injected events are labelled ~(injected)~ in output - ~--help~ prints usage