import type { Driver, Lap } from '../types' import { formatGap, formatLapTime, teamColor } from '../utils' interface Props { laps: Lap[] drivers?: Driver[] } interface DriverLapSummary { driver_number: number total: number best: Lap | null lastLap: number pitOuts: number } export function LapsView({ laps, drivers = [] }: Props) { if (laps.length === 0) { return (
Laps not ingested. Run box-box --ingest-session <key> to load this dataset.
) } const byDriver = new Map() for (const lap of laps) { const summary = byDriver.get(lap.driver_number) ?? { driver_number: lap.driver_number, total: 0, best: null, lastLap: 0, pitOuts: 0, } summary.total += 1 summary.lastLap = Math.max(summary.lastLap, lap.lap_number) if (lap.is_pit_out_lap) summary.pitOuts += 1 if ( lap.lap_duration != null && lap.lap_duration > 0 && (!summary.best || summary.best.lap_duration == null || lap.lap_duration < summary.best.lap_duration) ) { summary.best = lap } byDriver.set(lap.driver_number, summary) } const rows = [...byDriver.values()].sort((a, b) => { const aBest = a.best?.lap_duration ?? Number.POSITIVE_INFINITY const bBest = b.best?.lap_duration ?? Number.POSITIVE_INFINITY if (aBest !== bBest) return aBest - bBest return a.driver_number - b.driver_number }) const driversByNumber = new Map(drivers.map((driver) => [driver.driver_number, driver])) const fastest = rows.find((row) => row.best?.lap_duration != null)?.best const fastestTime = fastest?.lap_duration ?? null return (
{rows.map((row) => { const driver = driversByNumber.get(row.driver_number) const driverName = driver?.full_name || driver?.broadcast_name || driver?.name_acronym || `#${row.driver_number}` const colour = teamColor(driver?.team_colour) const isFastest = fastest && row.best?.driver_number === fastest.driver_number && row.best?.lap_number === fastest.lap_number const gap = row.best?.lap_duration != null && fastestTime != null ? row.best.lap_duration - fastestTime : null return ( ) })}
Driver Best Lap Best Time Gap Laps Pit Outs
{driverName} {row.driver_number} {row.best ? row.best.lap_number : '—'} {formatLapTime(row.best?.lap_duration)} {isFastest ? '—' : formatGap(gap)} {row.lastLap || row.total} {row.pitOuts || '—'}
) }