Live timing page: connect and show the running order #20

Closed
opened 2026-10-19 20:42:14 +00:00 by mintopia · 3 comments
Owner

What to build

A static page in examples/live-timing/ connects to the feed (?ws= URL parameter, default port 9000) and shows the running order as an F1-style timing screen.

  • Header: track name (large), LAP n / N, race clock. The clock is the leader's race_ms from standings, frozen at the winner's time once the leader finishes.
  • One row per racer, ordered by position: POS, colour stripe (stable hash of the name; AI grey), RACER (name in caps with ellipsis, car in grey after it; AI racers as CPU 07 dimmed; the local racer gets a YOU tag, a yellow left edge bar and a slightly lighter row), GAP (to leader; LEADER on the leader; +1 LAP when a lap or more down, from dist), INT (to the car ahead), LAST LAP, BEST LAP, LAP, MPH.
  • Black only. Right-aligned tabular figures; column headers aligned to their data; thin dividers before the LAP group. Titillium Web (OFL) committed as a woff2 so it works offline; 700 for names, 400 for numbers. Font size scales with viewport width.
  • A racer at 0 mph is grey (#8a8a8a) with STOPPED after the car. No red for stopped racers.
  • Disconnected: a red bar replaces the header rule and the page reconnects every 2 s. No feed message for 2 s: the clock turns grey. No status chip.
  • Before any race: a "Waiting for race" state with the header.
  • Commit the feed recorder/player (ws_tap.py, now untracked under work/ws-capture/): record <port> <out.jsonl> and play <in.jsonl> <port> [speed]. A recorded race played into the page is the demo and test path; the page has no replay mode of its own.
  • A short README for the example: how to run the game with BLUR_STATE_WS, open the page, record and replay.

Acceptance criteria

  • Opening the page against a game (or a played-back capture) shows every racer in position order with the columns above, updating about 5 times a second
  • 20 racers fit without scrolling at 1280×800 and 1920×1080
  • AI racers show CPU nn; the local racer is marked YOU; a stopped racer is grey with STOPPED
  • Killing the feed shows the red disconnected bar; restarting it reconnects within ~2 s without reloading
  • ws_tap.py is committed and a capture played with it drives the page end to end

Blocked by

None (can start immediately)

## What to build A static page in `examples/live-timing/` connects to the feed (`?ws=` URL parameter, default port 9000) and shows the running order as an F1-style timing screen. - Header: track name (large), `LAP n / N`, race clock. The clock is the leader's `race_ms` from `standings`, frozen at the winner's time once the leader finishes. - One row per racer, ordered by `position`: POS, colour stripe (stable hash of the name; AI grey), RACER (name in caps with ellipsis, car in grey after it; AI racers as `CPU 07` dimmed; the local racer gets a `YOU` tag, a yellow left edge bar and a slightly lighter row), GAP (to leader; `LEADER` on the leader; `+1 LAP` when a lap or more down, from `dist`), INT (to the car ahead), LAST LAP, BEST LAP, LAP, MPH. - Black only. Right-aligned tabular figures; column headers aligned to their data; thin dividers before the LAP group. Titillium Web (OFL) committed as a woff2 so it works offline; 700 for names, 400 for numbers. Font size scales with viewport width. - A racer at 0 mph is grey (`#8a8a8a`) with `STOPPED` after the car. No red for stopped racers. - Disconnected: a red bar replaces the header rule and the page reconnects every 2 s. No feed message for 2 s: the clock turns grey. No status chip. - Before any race: a "Waiting for race" state with the header. - Commit the feed recorder/player (`ws_tap.py`, now untracked under `work/ws-capture/`): `record <port> <out.jsonl>` and `play <in.jsonl> <port> [speed]`. A recorded race played into the page is the demo and test path; the page has no replay mode of its own. - A short README for the example: how to run the game with `BLUR_STATE_WS`, open the page, record and replay. ## Acceptance criteria - [ ] Opening the page against a game (or a played-back capture) shows every racer in position order with the columns above, updating about 5 times a second - [ ] 20 racers fit without scrolling at 1280×800 and 1920×1080 - [ ] AI racers show `CPU nn`; the local racer is marked YOU; a stopped racer is grey with STOPPED - [ ] Killing the feed shows the red disconnected bar; restarting it reconnects within ~2 s without reloading - [ ] `ws_tap.py` is committed and a capture played with it drives the page end to end ## Blocked by None (can start immediately)
Author
Owner

Target design (final mockup v7, random data; the milestone tickets fill in the colours, sectors, icons and classification):

live timing mockup

Target design (final mockup v7, random data; the milestone tickets fill in the colours, sectors, icons and classification): ![live timing mockup](https://git.mintopia.net/attachments/5feb4df1-b856-4ad7-b5fa-e279f0670126)
Author
Owner

Implemented in commit 8d84a26 on harmonic/task-25: examples/live-timing/ has index.html (single static page, ?ws= port or URL, default 9000), offline Titillium Web woff2 subsets + OFL.txt, ws_tap.py (record/play) and a README. Verified in headless Chrome against a played-back capture and a synthetic 20-racer feed: all rows fit at 1280x800 and 1920x1080; CPU nn / YOU tag / STOPPED grey rendering; red bar when the feed is down (reconnect every 2s); Waiting for race state; record then play round-trip works. Notes: finished racers are not marked STOPPED; track name uses the undocumented track_name key, falling back to a prettified track. I did not test killing and restarting the feed against a live page.

Implemented in commit 8d84a26 on harmonic/task-25: `examples/live-timing/` has `index.html` (single static page, `?ws=` port or URL, default 9000), offline Titillium Web woff2 subsets + OFL.txt, `ws_tap.py` (record/play) and a README. Verified in headless Chrome against a played-back capture and a synthetic 20-racer feed: all rows fit at 1280x800 and 1920x1080; CPU nn / YOU tag / STOPPED grey rendering; red bar when the feed is down (reconnect every 2s); Waiting for race state; record then play round-trip works. Notes: finished racers are not marked STOPPED; track name uses the undocumented `track_name` key, falling back to a prettified `track`. I did not test killing and restarting the feed against a live page.
Author
Owner

Completed and merged by Harmonic (task 25).

Completed and merged by Harmonic (task 25).
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Blocks
Reference
mintopia/blur#20
No description provided.