When a driver's personal 5-minute practice timer finishes, a "Pass
avslutat" card now appears immediately: how this pass's pace and
consistency compared to their recent sessions, any goal or lap-count
milestone crossed during the pass with its reward text made prominent,
and one suggested next goal (reusing the existing pace recommendation,
falling back to the next milestone when there isn't enough data yet).
Scoped to the driver's current class, and explicit about insufficient
sample sizes instead of showing a misleading number.
Adds a per-session consistency calculation to
buildPublicTrainingWindowStats server-side; everything else needed
(stats, goals, recommendation, milestone) was already sent to the
client, so the summary itself is computed there from data already in
hand - no raw laps or driver IDs added to what the public endpoint
exposes.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Investigated whether two admin browsers open at once can overwrite each
other's changes, per an explicit request to report the risk before
making bigger changes. Found that POST /api/state always replaces the
entire stored document with a client's in-memory copy, with no version
check and no per-field merge - and a browser only ever pushes, never
re-fetching server state after page load except on the Overlay view.
An idle browser's next save, even an unrelated edit, could silently
revert another browser's more recent changes, worst case a live race's
in-progress results.
Two scoped fixes instead of the bigger optimistic-locking rework (that
needs real UX decisions about conflicting saves, deferred separately):
1. server.js now remembers which session results were just written by
a real live decoder passing (/api/passings) and protects that key
for 15 seconds against being reverted by a stale full-state save,
while still applying the rest of that save normally.
2. Every non-Overlay view now quietly refreshes its data in the
background every 15 seconds (skipped while a local edit is
pending), without ever calling renderView(), so it can never
discard an open, unsaved edit form - shrinking how stale a
browser's next save can be from hours to seconds.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A fresh Windows install reported the server failing around backups.
createBackupService created the backups subdirectory once, synchronously,
at startup with no error handling - any failure there (permissions, a
path beyond Windows' MAX_PATH, a OneDrive/cloud-sync lock, antivirus)
crashed the entire Node process before it started listening, taking
down timing with it instead of just leaving backups unavailable.
Directory creation is now retried lazily and non-fatally on each backup
attempt, and a post-backup file rename retries briefly on EBUSY/EPERM
since a freshly written file is sometimes momentarily locked by
antivirus/cloud-sync scanning on Windows.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
"Jämna varv" and "Stegträning" previously only lived on the admin
Training page. A driver's own personal mobile profile link now offers
the same self-service configure/start/stop flow already used for the
5-minute practice timer there, with live progress computed server-side
from the driver's own share token so raw lap rows and driver IDs never
reach the client.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Andra guidade träningsövningen i Open Practice: konfigurera en
stegserie (antal varv + lugnt/kontrollerat/snabbt per steg),
förvalt till klassiska pyramiden. Training-sidan visar aktuellt
steg, kvarvarande varv och en progress-pill per steg. När
sekvensen är klar jämförs de två kontrollerade stegens snitt
neutralt (t.ex. "+0.90s"), utan att kalla en försämring för
trötthet.
syncTrainingLedger sprider nu resten av det normaliserade
training-objektet istället för att lista fält manuellt, så
samma klass av bugg som drabbade Jämna varv inte kan upprepas
för framtida fält.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Ny guidad träningsövning i Open Practice: sätt måltid, tolerans
och antal varv, se aktuell serie och dagens bästa live på
Training-sidan. Ett missat varv startar en ny serie utan att
radera bästa resultatet.
Hittade och fixade två buggar under vägen:
- syncTrainingLedger byggde om training-state vid varje sparning
utan att föra vidare det nya evenLaps-fältet, så sparade
konfigurationer försvann direkt
- Training-sidan kraschade för alla förare med färre än 3 varv i
varje stint (t.ex. de första varven i ett pass) eftersom en
dedupe-funktion läste en egenskap på ett null-värde
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Nytt browser-test för start/paus/fortsätt/finish och byte till
nästa heat i kön, mot en simulerad decoder-socket (ingen riktig
AMMC-hårdvara). Hittade och fixade två buggar under vägen:
- Open Practice på sponsor/track-event kunde inte startas trots
grönt ljus i förkontrollen (separat, striktare kontroll saknade
samma undantag)
- Race Day-vyn ritades aldrig om när decodern anslöt/kopplades ner
Testramverket hanterar nu även native alert()/confirm()-dialoger
automatiskt, annars fryser en headless körning helt.