Add a time-of-day race day schedule to Event Manager

Events can now be given a start time and a gap between sessions on a
new "Schedule" panel; every session's planned clock time cascades
automatically in running order (practice, qualifying, finals), and
once a session actually starts or finishes, everything after it
re-anchors to that real time - a late start or a session that ran
long (including any pause) pushes the rest of the day forward with
no manual reschedule step. The scheduled time now also shows on the
printed/PDF start lists.

Printable start lists and manually moving a driver to start last in
their own heat (for a mechanic-time request) already existed, so
this only builds the missing piece: the schedule itself.

Also fixes a real pre-existing bug in the same session-ordering logic
this feature relies on: getSessionSortWeight used `order[type] || 99`,
which silently treated open_practice's own weight of 0 as falsy and
sorted practice sessions dead last instead of first in print/PDF
output.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
larssand
2026-09-10 22:33:57 +02:00
parent a449bec07d
commit cf89086dff
11 changed files with 250 additions and 8 deletions

View File

@@ -367,6 +367,23 @@ Reported 2026-09-10 by the user: the "select session" dropdown (Timing) and the
Verified 2026-09-10 with a live headless-browser check against a real, isolated server: seeded 3 events with a mix of practice/qualifying/final sessions and confirmed the rendered `<select>` groups them into 3 correctly-labeled, newest-first `<optgroup>`s with each event's own sessions nested inside.
## Time-of-day race day schedule
Requested 2026-09-10 by the user: when running a race day, should be able to set it up as time-scheduled - start Practice 1 at 12:34, and once it's done the next session (with drivers) is automatically set to start e.g. 3 minutes later at 12:42, and so on; must be pausable if something goes wrong, printable start lists, and a driver who's TQ in a qualifying heat but needs to request work time on their car should be able to start last in that heat instead.
Investigated first and confirmed two of the three pieces already existed, before building the missing one:
- Printable/PDF start lists already existed (`events.print_startlists`/`events.pdf_startlists` in Event Manager).
- Manually moving a driver to start last in their own heat already existed via the drag-and-drop grid editor (`gridDragList` in `event_manager_controller.js`, reordering `session.manualGridIds`) - already covers the "request mech time, start last" scenario without any new work.
Built the genuinely missing piece, confirmed with the user before starting given its size:
- [x] `buildEventSchedule` (`src/event_race_logic.js`, new) computes each race-mode session's planned clock time in running order (reusing the same `getSessionSortWeight` ordering the print/PDF output already uses: practice, then qualifying, then finals), cascading from a configured day-start time plus each session's own duration/follow-up plus a configurable gap between sessions. Once a session has actually started or finished, everything scheduled after it re-anchors to that real time instead of the original plan - a late start or a session that ran long (a paused session's real `endedAt` already reflects the full wall-clock time it took) automatically pushes the rest of the day forward with no separate "reschedule" action, which is what covers "must be able to pause" without any extra pause-specific schedule logic.
- [x] New "Schedule" panel in Event Manager (`src/event_manager_view.js`/`event_manager_controller.js`): a start-time + gap-between-sessions form, and (once set) a table of every session with its planned time range, its real start/end once it has one, and a "Delayed" flag for a session that started more than a minute late. New `event.raceConfig.scheduleStartAt`/`scheduleGapMin` fields, added to `normalizeEvent`'s explicit field allowlist (an event's `raceConfig` is fully rebuilt from that allowlist on every save - any field not listed there is silently dropped, caught during this work before it shipped).
- [x] The scheduled time is now also shown on the printed/PDF start lists (`buildRaceStartListsHtml` in `src/race_render_helpers.js`) next to each session's name.
Found and fixed a real, previously-existing bug while building this, unrelated to the new feature but affecting the same ordering logic: `getSessionSortWeight` (`src/race_render_helpers.js`) used `order[type] || 99` - since `open_practice`'s own weight is `0`, a falsy value, `||` silently replaced it with the 99 "unknown type" fallback, sorting practice sessions dead last (tied with genuinely unrecognized types) in the print/PDF start lists and results, instead of first. Fixed to `??`.
Verified 2026-09-10: new unit tests cover `getSessionSortWeight`'s fix directly, and `buildEventSchedule`'s cascading math, the running-order sort, track-mode sessions being excluded, and the re-anchoring behavior for both a late-but-still-running session and a finished one whose real duration (including a pause) differed from the plan. A full headless-browser run against a real, isolated server reproduced the exact reported workflow: set a 12:34 start time with a 3-minute gap on a real Open Practice + Q1 H1, confirmed the schedule panel showed practice at 12:34-12:39 and qualifying at 12:42-12:47, confirmed the printed start list included "12:34" next to Open Practice, then made practice actually start 2 minutes late and confirmed the panel flagged it "Delayed" and qualifying's planned time shifted forward to 12:44 automatically.
## Documentation maintenance
- [ ] Update the architecture's module/dependency inventory as modules change.