import type { EnrichedResult, Stint, PitStop } from '../types' const COMPOUND_COLORS: Record = { SOFT: '#e8002d', MEDIUM: '#ffd600', HARD: '#e8e8e4', INTERMEDIATE: '#39b54a', WET: '#0067ff', } function compoundColor(c: string): string { return COMPOUND_COLORS[c.toUpperCase()] ?? '#666' } function compoundInitial(c: string): string { const abbr: Record = { SOFT: 'S', MEDIUM: 'M', HARD: 'H', INTERMEDIATE: 'I', WET: 'W', } return abbr[c.toUpperCase()] ?? c[0] ?? '?' } interface Props { results: EnrichedResult[] stints: Stint[] pit_stops: PitStop[] hasStints: boolean } export function StrategyView({ results, stints, pit_stops, hasStints }: Props) { if (!hasStints) { return (
Stints not available. This session does not have ingested tyre compound and stint ranges in /api/v1/race-hub. Strategy charts require per-driver stints: compound, lap_start, lap_end.
{results.length > 0 && ( <>
Laps Completed from results — hint at pit count
{results.map((r) => ( ))}
P Driver Laps
{r.position} {r.name_acronym || r.driver_number} 0 ? 'var(--text)' : 'var(--text-3)' }}> {r.number_of_laps > 0 ? r.number_of_laps : '—'}
)}
) } const sortedDrivers = [...results].sort((a, b) => a.position - b.position) const totalLaps = Math.max( ...stints.map((s) => s.lap_end), ...results.map((r) => r.number_of_laps), 1 ) const SVG_W = 640 const LEFT = 48 const RIGHT = 12 const ROW_H = 28 const BAR_H = 14 const BAR_Y = 7 const BAR_W = SVG_W - LEFT - RIGHT const SVG_H = sortedDrivers.length * ROW_H + 8 const lapX = (lap: number) => LEFT + ((lap - 1) / totalLaps) * BAR_W const stintW = (s: Stint) => Math.max(2, ((s.lap_end - s.lap_start + 1) / totalLaps) * BAR_W) const usedCompounds = [...new Set(stints.map((s) => s.compound.toUpperCase()))].filter( (c) => c in COMPOUND_COLORS ) return (
{sortedDrivers.map((driver, i) => { const rowY = i * ROW_H const color = driver.team_colour ? `#${driver.team_colour}` : '#888' const dStints = stints.filter((s) => s.driver_number === driver.driver_number) const dPits = pit_stops.filter((p) => p.driver_number === driver.driver_number) return ( {driver.name_acronym} {dStints.map((stint, si) => { const x = lapX(stint.lap_start) const w = stintW(stint) const fill = compoundColor(stint.compound) return ( {w > 18 && ( {compoundInitial(stint.compound)} )} ) })} {dPits.map((pit, pi) => { const x = lapX(pit.lap_number) return ( ) })} ) })}
{usedCompounds.map((c) => ( {c.charAt(0) + c.slice(1).toLowerCase()} ))} {pit_stops.length > 0 && ( Pit stop )} {totalLaps} laps
) }