Fix malformed race clock format and refresh docs screenshots

formatRaceClock rendered a doubled-up, garbled time (e.g.
"02:48.20:207") everywhere a race clock is shown - Timing, Overlay,
Results archive, Judging, Training stint logs - because it
concatenated both a centiseconds and a milliseconds computation into
the same string. Only the milliseconds part was ever meant to be
there. Found while building realistic demo data for new screenshots,
since every prior test/demo session was empty and never exercised
this code path with a real result.

Also regenerates all screenshots in docs/screenshots against a
realistic seeded race (drivers, cars, qualifying heats, finals,
practice history, a real judging correction) instead of empty demo
data, adds two new ones (Managed AMMC config, the in-app Guide page)
aimed at helping a new user understand initial setup, removes 6
screenshots orphaned by an earlier README revision, and updates both
README.md and README.sv.md's screenshot tables accordingly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
larssand
2026-09-10 20:03:10 +02:00
parent f988ad2690
commit 50586e8859
24 changed files with 38 additions and 7 deletions

View File

@@ -8,6 +8,12 @@ The application version is maintained in `package.json` and displayed in the adm
No changes recorded yet. No changes recorded yet.
## 1.12.2 - 2026-09-10
### Fixed
- The race clock shown next to a driver's result (e.g. laps/total time in Timing, Overlay, Results archive, Team Race stint logs, and Training's stint duration) rendered a malformed, doubled-up time like `02:48.20:207` instead of a clean `02:48.207`. `formatRaceClock` computed both a 2-digit centiseconds value and a 3-digit milliseconds value and concatenated both into the string; only the milliseconds part was ever meant to be there. This had been broken since the feature was first written and was easy to miss because it only shows once a session actually has recorded lap results - found while building fuller demo data for the documentation screenshots below.
## 1.12.1 - 2026-09-10 ## 1.12.1 - 2026-09-10
### Fixed ### Fixed

View File

@@ -76,6 +76,10 @@ Current layouts for race operation, live presentation, training and system confi
</tr> </tr>
<tr> <tr>
<td width="50%"><a href="docs/screenshots/decoder-settings.jpg"><img src="docs/screenshots/decoder-settings.jpg" alt="Decoder configuration" /></a><br><strong>Decoder configuration</strong></td> <td width="50%"><a href="docs/screenshots/decoder-settings.jpg"><img src="docs/screenshots/decoder-settings.jpg" alt="Decoder configuration" /></a><br><strong>Decoder configuration</strong></td>
<td width="50%"><a href="docs/screenshots/managed-ammc.jpg"><img src="docs/screenshots/managed-ammc.jpg" alt="Managed AMMC configuration" /></a><br><strong>Managed AMMC configuration</strong></td>
</tr>
<tr>
<td width="50%"><a href="docs/screenshots/guide.jpg"><img src="docs/screenshots/guide.jpg" alt="In-app setup guide" /></a><br><strong>In-app setup guide</strong></td>
<td width="50%"></td> <td width="50%"></td>
</tr> </tr>
</table> </table>

View File

@@ -74,6 +74,10 @@ Aktuella layouter för racedrift, livevisning, träning och systemkonfiguration.
</tr> </tr>
<tr> <tr>
<td width="50%"><a href="docs/screenshots/decoder-settings.jpg"><img src="docs/screenshots/decoder-settings.jpg" alt="Decoderinställningar" /></a><br><strong>Decoderinställningar</strong></td> <td width="50%"><a href="docs/screenshots/decoder-settings.jpg"><img src="docs/screenshots/decoder-settings.jpg" alt="Decoderinställningar" /></a><br><strong>Decoderinställningar</strong></td>
<td width="50%"><a href="docs/screenshots/managed-ammc.jpg"><img src="docs/screenshots/managed-ammc.jpg" alt="Hanterad AMMC-konfiguration" /></a><br><strong>Hanterad AMMC-konfiguration</strong></td>
</tr>
<tr>
<td width="50%"><a href="docs/screenshots/guide.jpg"><img src="docs/screenshots/guide.jpg" alt="Inbyggd uppstartsguide" /></a><br><strong>Inbyggd uppstartsguide</strong></td>
<td width="50%"></td> <td width="50%"></td>
</tr> </tr>
</table> </table>

View File

@@ -288,6 +288,26 @@ Reported 2026-09-10 by the user, noticed right after the settings-tabs restructu
Verified 2026-09-10: a headless-browser check against a real, isolated server confirmed both the general race-sounds "Test" button and a per-event "Test" button in the sound table no longer issue a `POST /api/state` (watched over the real network layer, not just state inspection), while the "Save" button and directly editing a race-audio field (e.g. toggling mute) both still do, exactly as before. Verified 2026-09-10: a headless-browser check against a real, isolated server confirmed both the general race-sounds "Test" button and a per-event "Test" button in the sound table no longer issue a `POST /api/state` (watched over the real network layer, not just state inspection), while the "Save" button and directly editing a race-audio field (e.g. toggling mute) both still do, exactly as before.
## Race clock rendered as a malformed doubled-up time
Found 2026-09-10 while building realistic seeded demo data for the documentation screenshots below - the very first time in this repo's history that a screenshot was taken with an actual, real, multi-driver result on screen (every earlier demo/test fixture only ever had empty "No laps yet" sessions, so this was invisible until now).
- [x] `formatRaceClock` (`src/app.js`) computed both `centiseconds` (2-digit) and `millis` (3-digit) from the same elapsed value and concatenated both into the returned string - `${m}:${s}.${centiseconds}:${millis}` - producing a garbled result like `02:48.20:207` everywhere a race clock is shown (Timing, Overlay/leaderboard-overlay, Results archive, Team Race stint logs, Training's stint duration column). Only the milliseconds portion was ever meant to be there, matching the sibling `formatLap` helper's format; the `centiseconds` computation and its extra `:` separator were dead, wrong code present since this function's first commit. Fixed to `${m}:${s}.${millis}` (e.g. `02:48.207`).
Verified 2026-09-10: the full unit test suite (193 tests) and the full browser regression suite passed unchanged (the function had no prior coverage - the existing tests only ever exercised stubbed versions of it - which is exactly how this shipped unnoticed). Visually confirmed fixed via the live-rendered Overlay, Results archive/Training stint tables, and Judging views in the regenerated screenshots below, all now showing a clean time instead of the doubled-up one.
## Documentation: refreshed and expanded screenshots
Requested 2026-09-10 by the user: "create screenshots and update the images in the repo, and maybe add some more important images for a new user, so they get a good overview and understand how it needs to be set up." Every existing screenshot in `docs/screenshots/` predated this whole session's work and, on inspection, was captured against essentially empty demo data (0 cars, "No laps yet", a broken multi-day-old "running" clock) - not representative of what the app actually looks like in use, and not helpful for a new user trying to picture their own setup.
- [x] Seeded a realistic demo dataset (via a scratch script, run only against an isolated temp server/SQLite dir - never the real installation) into an isolated headless-browser session: 2 classes, 10 drivers, 8 cars, one race event ("Klubbmästare Race 4") with 2 rounds of qualifying heats and A/B finals all carrying real recorded lap results, a live "running" A Final, and 4 days of varied practice history for one driver (for Training stats' weekday/pace-block/stint-analysis breakdowns).
- [x] Regenerated all 9 previously-referenced screenshots against this real data instead of an empty session: `overview-active-session.jpg`, `race-setup-wizard.jpg`, `overlay.jpg`, `leaderboard-overlay.jpg`, `training-overview.jpg`, `training-extra-stats.jpg`, `judging-current.jpg` (now shows a real manual +5s correction applied through the actual Judging UI), `race-audio-settings.jpg`, `decoder-settings.jpg` (now shows the new tabbed Settings layout from the earlier entry above).
- [x] Added two new screenshots aimed specifically at a new user's setup, filling gaps nothing previously covered: `managed-ammc.jpg` (the Managed AMMC configuration section - the actual first thing a new user configures, previously never pictured at all) and `guide.jpg` (the in-app Guide/documentation page, so a new user knows it exists before hunting for the README).
- [x] Deleted 6 stale, already-unreferenced screenshots left over from an earlier README revision (`event.jpg`, `judging.jpg`, `overview.jpg`, `race-setup.jpg`, `team-overlay.jpg`, `timing.jpg`).
- [x] Updated both `README.md` and `README.sv.md`'s screenshot tables: filled the previously-empty cell with Managed AMMC and added a new row for the Guide page, with matching Swedish alt text/captions in `README.sv.md`.
- [x] Redacted incidental local-machine details that don't belong in a public screenshot before capturing (the dev machine's resolved AMMC executable path, and the ephemeral test server's random localhost ports) by overwriting just those specific form fields/text nodes in the DOM right before each shot - cosmetic only, never saved back to any backend.
- [x] While building this data, found and fixed a real, previously-invisible formatting bug (see the entry directly above) purely as a side effect of finally exercising the app with real results for the first time.
## Documentation maintenance ## Documentation maintenance
- [ ] Update the architecture's module/dependency inventory as modules change. - [ ] Update the architecture's module/dependency inventory as modules change.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 937 KiB

After

Width:  |  Height:  |  Size: 503 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 309 KiB

BIN
docs/screenshots/guide.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 579 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 879 KiB

After

Width:  |  Height:  |  Size: 403 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 387 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 416 KiB

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 877 KiB

After

Width:  |  Height:  |  Size: 435 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 477 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 397 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 986 KiB

After

Width:  |  Height:  |  Size: 455 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 407 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 374 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 300 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 425 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 612 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 554 KiB

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "rc-racecore", "name": "rc-racecore",
"version": "1.12.1", "version": "1.12.2",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "rc-racecore", "name": "rc-racecore",
"version": "1.12.1", "version": "1.12.2",
"hasInstallScript": true, "hasInstallScript": true,
"dependencies": { "dependencies": {
"better-sqlite3": "^12.11.1", "better-sqlite3": "^12.11.1",

View File

@@ -1,6 +1,6 @@
{ {
"name": "rc-racecore", "name": "rc-racecore",
"version": "1.12.1", "version": "1.12.2",
"private": true, "private": true,
"description": "RC RaceCore live timing and race control with AMMC ingest and SQLite persistence", "description": "RC RaceCore live timing and race control with AMMC ingest and SQLite persistence",
"engines": { "engines": {

View File

@@ -5225,13 +5225,10 @@ function formatRaceClock(ms) {
const s = Math.floor((total % 60000) / 1000) const s = Math.floor((total % 60000) / 1000)
.toString() .toString()
.padStart(2, "0"); .padStart(2, "0");
const centiseconds = Math.floor((total % 1000) / 10)
.toString()
.padStart(2, "0");
const millis = Math.floor(total % 1000) const millis = Math.floor(total % 1000)
.toString() .toString()
.padStart(3, "0"); .padStart(3, "0");
return `${m}:${s}.${centiseconds}:${millis}`; return `${m}:${s}.${millis}`;
} }
function getSeedMethodLabel(method) { function getSeedMethodLabel(method) {