feat(live): add web track map (#32)

Subscribe to SignalR Position.z and CarData.z, decode DEFLATE payloads, stream throttled positions over SSE, and render live car dots against cached track outline bounds with tap telemetry.

Alignment spike: no checked-in or locally cached real Position.z samples were available in this isolated worktree; verified both streams expose the official raw F1 X/Y/Z coordinate contract and implemented shared-bounds normalization against prefetched OpenF1 outlines. Fallback build-outline-from-stream was not taken.

Playwright remains out of scope for live rendering because BOXBOX_DISABLE_LIVE is used there; coverage is via parser, web handler/SSE, pure transform, and seeded component tests.
This commit is contained in:
Aman Tahiliani
2026-07-03 19:34:09 -04:00
committed by GitHub
parent 5408a45bbd
commit 7263949260
15 changed files with 1076 additions and 18 deletions

View File

@@ -0,0 +1,39 @@
import { describe, expect, it } from 'vitest'
import {
buildOutlinePath,
canvasToSvg,
isOnTrack,
normalizeRawPoint,
outlinePointToCanvas,
} from '../lib/trackmap'
describe('track map transforms', () => {
it('normalizes raw F1 coordinates into canvas space', () => {
const point = normalizeRawPoint(
{ x: 50, y: 75 },
{ minX: 0, maxX: 100, minY: 50, maxY: 100 },
)
expect(point).toEqual({ x: 0.5, y: 0.5 })
expect(canvasToSvg(point)).toEqual({ x: 50, y: 50 })
})
it('centers zero-range bounds and clamps out-of-range points', () => {
expect(normalizeRawPoint({ x: 10, y: 20 }, { minX: 10, maxX: 10, minY: 20, maxY: 20 }))
.toEqual({ x: 0.5, y: 0.5 })
expect(normalizeRawPoint({ x: 20, y: 5 }, { minX: 10, maxX: 15, minY: 10, maxY: 15 }))
.toEqual({ x: 1, y: 1 })
})
it('builds an SVG path from normalized outline points', () => {
expect(outlinePointToCanvas({ x: 0.25, y: 0.75 })).toEqual({ x: 0.25, y: 0.25 })
expect(buildOutlinePath([{ x: 0, y: 0 }, { x: 1, y: 1 }]))
.toBe('M 0.00 100.00 L 100.00 0.00')
expect(buildOutlinePath([{ x: 0, y: 0 }])).toBe('')
})
it('classifies on-track status defensively', () => {
expect(isOnTrack('OnTrack')).toBe(true)
expect(isOnTrack('OffTrack')).toBe(false)
expect(isOnTrack('')).toBe(true)
})
})