Commit Graph

32 Commits

Author SHA1 Message Date
larssand
72d83ad183 feat(overlay): show places gained since the start in the OBS tower
Heats and finals started together show ▲/▼ against the start order
(new OBS option, on by default). In practice the best lap is no longer
printed twice as both result and best.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 20:13:10 +02:00
larssand
42e53fd356 docs(guide): add a Series / cup tab to the in-app guide
Explains creating a series, running each round from the series page,
points and standings, and a worked winter-series example.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 19:31:19 +02:00
larssand
1bc75f8ec1 feat(race-day): add warm-up transponder check before a heat
Race Day gets a 1-3 minute warm-up per heat with a green check per
driver when their transponder is seen, countdown announcements
(sv/en), quick transponder fix from the panel, and a start warning
that still allows starting when someone is missing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 20:47:15 +02:00
larssand
e8a2799a92 feat(audio): add offline local neural voice via Piper (sv + en)
Announcements can use Piper, a free local neural TTS, instead of the browser's system
voice. No account, no paid service, and it keeps working with no internet at the track.

- npm run tts:install (or Settings -> Audio -> Install) downloads the standalone Piper
  release for Linux/Windows/macOS plus Swedish and English voices into piper/ once
- server/tts.js generates each line once, one at a time, and caches it as WAV under
  data/tts/; a new line takes ~0.3 s with the standalone build
- src/piper_speech.js plays it and falls back to the browser voice if Piper is missing,
  errors, or takes over 2.5 s, so no announcement is lost and timing is never held up
- "Pre-generate phrases and driver names" renders every fixed phrase and name in both
  languages before race day

Browser voice stays the default. Generation routes fall under the admin PIN.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 19:28:15 +02:00
larssand
9016ce02e4 feat(auth): add optional admin PIN for all API writes
Off by default. Once a PIN is set in Settings -> System & backup, every non-GET /api/*
request (plus GET /api/ammc/config) needs a signed 30-day HttpOnly cookie, which also
closes the unauthenticated /api/update/run restart trigger. A 401 opens a PIN dialog
and the pending save is retried after login. Reads stay open because the public overlay
hydrates through GET /api/state. Optional RC_ADMIN_ALLOWED_CIDRS restricts the same
routes by client address.

The PIN hash and signing secret live in data/, outside the app_state blob, so they
never leak through GET /api/state, exports or backups.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 22:14:58 +02:00
larssand
922bd704eb Split the Guide page into tabs, matching the Settings/Event Manager pattern
The page had grown to ~20 stacked panels on one very long scroll - the same problem
already fixed twice this session for Settings and Event Manager. Grouped into 5 tabs
(Getting started, Create a race, Run a race, Training & results, Video guides) using
the same activeGuideTab-as-module-state approach so the selection survives an in-place
re-render (e.g. a language switch). The always-visible overview cards at the top are
unchanged.

Also investigated a "feels slow" concern raised alongside this: measured the page's
actual render cost in a real browser (median 0.6ms, on par with or faster than Settings/
Timing) and confirmed the periodic tickClock/updateSyncStatus intervals never re-render
an idle Guide page. No performance issue found - the perceived slowness was the page's
length, which this change addresses directly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-12 19:59:15 +02:00
larssand
3e02ba9aad Link the video guides from README, README.sv, and the in-app Guide page
Commit all 7 recorded clips to docs/videos/ (alongside the existing docs/screenshots/)
instead of leaving them in the gitignored video-guides/ folder from the earlier
feasibility spike - they're meant to be shipped, discoverable assets now, not scratch
output. scripts/record-video-guides.mjs writes there by default going forward.

Added a "Video Guides" section to README.md/README.sv.md (Getting started + Interface
tour groups) and a matching in-app "Video guides" panel on the Guide page, right after
the overview cards - the most discoverable spot for a brand-new user. Links point at
/docs/videos/<name>.mkv, served by the server's existing /docs static route.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-11 18:29:32 +02:00
larssand
2624ce8262 Update the in-app Guide for this session's shipped features
Documents the new race-day Schedule feature (new section + overview
card), staggered-start car call-outs and the per-driver "Done" flag,
the new Settings and Event Manager tab layouts, and the driver
transponder-conflict warning. Also corrects a bullet that had gone
stale: it claimed Open/Free Practice was the only thing that skipped
the start ceremony, which stopped being true once scheduled "Practice"
sessions started getting the full sequence too.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-11 13:54:42 +02:00
larssand
fd6efe2c7e Add track layout tracking so lap-time stats stay comparable
Clubs that reconfigure their track (e.g. running indoors in the same
building) can now add named track layouts under Settings, each with
just a start date/time - layouts are contiguous, so a layout's end is
implicitly the next one's start, with no separate field to keep in
sync. Every session freezes which layout was active when it started,
so the "track record" audio cue and the Results Archive (which now
shows each session's layout) only compare laps run on the same
physical track. With no layouts configured, everything behaves
exactly as before - the feature is fully inert until a club uses it.

Design settled through conversation with the user: global scope (not
per class), start-date-only (no redundant stop date), and no changes
needed to driver/transponder mapping, since that's already fully
independent of track geometry in this app.

Deliberately out of scope for this pass: the mobile/driver training
profile's own cross-session personal-best trend stats still compare
across a driver's whole lap ledger regardless of layout - logged in
ROADMAP.md as a real remaining gap for a later pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-10 14:17:06 +02:00
larssand
f1959029c7 Document exercise session history and session-count goals in the Guide
Two new Training walkthrough steps covering the previous commit's
feature: completed-session history (verified server-side, never
just claimed by the mobile page) and the sessions-metric goal option.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 20:46:03 +02:00
larssand
bed0dfd9f2 Update in-app Guide for this session's features, extend passing purge to Clear data
The in-app Guide page hadn't been updated for the guided practice
exercises, their mobile self-service controls, the end-of-practice
summary, or the new Resultatarkiv view - none of it was documented
anywhere a user would find it. Added three new Training walkthrough
steps and a new Resultatarkiv section (overview card + 5-step guide).

While correcting guide text that claimed raw SQLite passing rows are
always retained, found the same gap the results-archive work already
fixed for deleting a single event/session also applies to "Rensa data"
(Settings -> Clear data): the drivers/cars/races/all-competition-data
scopes all reset resultsBySession for every current session, not just
ones tied to the cleared scope, so every session's raw rows became
orphaned at once. clearDataScope now purges those sessions' rows too,
through the same /api/passings/purge endpoint.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 18:31:03 +02:00
larssand
4068cc7c19 add more stats to mobile profile 2026-09-04 16:17:45 +02:00
larssand
142c45be04 add replay session 2026-09-04 15:58:24 +02:00
larssand
4f847610dc Improve training statistics, achievements and stable pace audio 2026-09-03 06:36:17 +02:00
larssand
f561dd8feb new raceday and backup 2026-09-01 07:07:23 +02:00
larssand
694aba5f3d Add motivational training challenges and shared club goals 2026-08-30 09:16:11 +02:00
larssand
e5e1754185 add more train stats per driver 2026-08-29 09:56:45 +02:00
larssand
375bfb2416 förbättreing tränings 2026-08-28 21:44:23 +02:00
larssand
c6262aceab fix live leaderbord details 2026-08-28 21:12:43 +02:00
larssand
3cf68cf34a branding och namechange 2026-08-28 20:56:58 +02:00
larssand
5f79228941 Add configurable manifest-driven race audio system 2026-08-28 13:29:27 +02:00
larssand
e5af42ce2d Add CSV imports and granular competition data cleanup 2026-08-27 17:56:50 +02:00
larssand
808d5b2657 Decoder-dokumentationen är nu tydligare och mer komplett 2026-08-26 08:55:19 +02:00
larssand
abf887dccd Split- och depåstatistik är implementerad 2026-08-25 20:00:55 +02:00
larssand
8ea8b3a84e Add multi-decoder split and pit timing support 2026-08-25 19:45:40 +02:00
larssand
6f02e955a5 Add class-specific driver training profiles and metadata 2026-08-24 22:05:50 +02:00
larssand
3aeb77a042 add stat 2026-08-24 21:28:38 +02:00
larssand
355a1ad3b0 Förbättrat ljudsystemet 2026-08-24 19:40:39 +02:00
larssand
2e6866a013 Add simplified Open Practice flow and reorganize 2026-08-24 19:25:21 +02:00
larssand
4a74785791 Add secure public driver training profiles 2026-08-24 16:54:35 +02:00
larssand
c2ed00861a Add persistent driver training history and progression 2026-08-24 16:06:36 +02:00
larssand
65c3c3c03c Extract guide and overlay views into module 2026-03-26 08:35:53 +01:00