feat: add replay track map scrubber

Spike: replay location fan-out is bounded with a semaphore at 4 concurrent GetLocation calls, covered by TestAssembleReplayFramesBoundsLocationFanOut.

Adds /api/v1/replay/frames with 5s interval floor, 3000-frame cap, nearest-sample snapping, and empty-driver omission. Wires RaceStoryCanvas to lazy-load replay frames plus cached track outlines when the map panel opens, sharing the existing scrubber/playback state across chart and map.

Tests: HOME=/private/tmp/box-box-home GOCACHE=/private/tmp/box-box-go-cache GOMODCACHE=/Users/aman/go/pkg/mod go test ./internal/web; go build ./... (same env, passed with read-only module stat-cache warning); npm run test; npx tsc --noEmit. Full go test ./... is blocked in this sandbox by existing network/listener-dependent internal/api and internal/news tests.
This commit is contained in:
2026-07-11 18:17:15 -04:00
parent 5970649a9c
commit c2617d39bb
12 changed files with 1209 additions and 15 deletions

View File

@@ -360,6 +360,23 @@ export interface TrackOutline {
bounds: TrackBounds
}
export interface ReplayCarPosition {
x: number
y: number
}
export interface ReplayFrame {
t: number
cars: Record<string, ReplayCarPosition>
}
export interface ReplayFramesResponse {
session_key: number
interval_ms: number
start_time: string
frames: ReplayFrame[]
}
export interface ChampHubDriver {
driver_number: number
name_acronym: string