Files
box-box/frontend/src/types.ts
AmanTahiliani 7212eb9b44 feat: detect race replay chapters
Add deterministic server-side chapter detection for starts, flag periods, pit phases, decisive top-five swings, and finishes, then expose chapters on the race-hub payload.

Spike result: race-hub already loads race control, positions, and laps in one read model. The requested Detect signature does not include pit stops, so pit phases use IsPitOutLap clusters as the local deterministic pit-stop proxy.
2026-07-11 18:04:44 -04:00

418 lines
7.9 KiB
TypeScript

export interface DatasetInfo {
status: 'available' | 'missing' | 'skipped'
source: 'local' | 'openf1' | 'none' | 'na'
count?: number
}
export interface Meeting {
meeting_key: number
meeting_name: string
meeting_official_name: string
location: string
country_name: string
country_code: string
country_flag: string
circuit_short_name: string
date_start: string
date_end: string
year: number
is_cancelled?: boolean
}
export interface Session {
session_key: number
session_name: string
session_type: string
meeting_key: number
date_start: string
date_end: string
gmt_offset: string
is_cancelled?: boolean
}
export interface Driver {
driver_number: number
name_acronym: string
full_name: string
first_name: string
last_name: string
team_name: string
team_colour: string
headshot_url: string
broadcast_name: string
session_key: number
meeting_key: number
}
export interface EnrichedResult {
driver_number: number
position: number
name_acronym: string
full_name: string
team_name: string
team_colour: string
dnf: boolean
dns: boolean
dsq: boolean
duration: number | number[] | null
gap_to_leader: number | string | number[] | null
number_of_laps: number
points: number
session_key: number
meeting_key: number
}
export interface EnrichedGrid {
driver_number: number
position: number
name_acronym: string
full_name: string
team_name: string
team_colour: string
session_key: number
meeting_key: number
lap_duration: number | null
}
export interface RaceHub {
source: 'local' | 'partial' | 'none' | 'cancelled'
session_key: number
datasets: Record<string, DatasetInfo>
meeting?: Meeting
session?: Session
drivers: Driver[]
results: EnrichedResult[]
starting_grid: EnrichedGrid[]
stints: Stint[]
pit_stops: PitStop[]
positions: PositionSample[]
race_control: RaceControlMessage[]
weather: WeatherSample[]
laps: Lap[]
chapters: Chapter[]
}
export interface Chapter {
kind: 'start' | 'safety_car' | 'virtual_safety_car' | 'red_flag' | 'pit_phase' | 'decisive_swing' | 'finish' | string
title: string
start_lap: number
end_lap: number
start_time?: string
end_time?: string
driver_numbers: number[]
}
export interface Stint {
session_key: number
driver_number: number
meeting_key: number
stint_number: number
compound: string
lap_start: number
lap_end: number
tyre_age_at_start: number
}
export interface PitStop {
session_key: number
driver_number: number
meeting_key: number
lap_number: number
date: string
pit_duration: number
lane_duration: number
stop_duration: number
}
export interface PositionSample {
session_key: number
driver_number: number
meeting_key: number
date: string
position: number
}
export interface RaceControlMessage {
session_key: number
meeting_key: number
date: string
category: string
flag: string
message: string
scope: string
driver_number: number | null
lap_number: number | null
sector: number | null
qualifying_phase: number | null
}
export interface WeatherSample {
session_key: number
meeting_key: number
date: string
air_temperature: number
track_temperature: number
humidity: number
pressure: number
rainfall: number
wind_direction: number
wind_speed: number
}
export interface Lap {
session_key: number
driver_number: number
meeting_key: number
lap_number: number
date_start: string
lap_duration: number | null
is_pit_out_lap: boolean
}
export interface CarDataSample {
brake: number
date: string
driver_number: number
drs: number
meeting_key: number
n_gear: number
rpm: number
session_key: number
speed: number
throttle: number
}
export interface ComparisonLap extends Lap {
compound?: string
}
export interface ComparisonDriver {
driver_number: number
name_acronym: string
team_colour: string
laps: ComparisonLap[]
}
export interface LapsComparisonResponse {
session_key: number
sc_periods: unknown[]
pit_laps: Record<string, number[]>
drivers: ComparisonDriver[]
}
export interface WeekendSession {
session: Session
source: 'local' | 'partial' | 'none' | 'cancelled'
datasets: Record<string, DatasetInfo>
}
export interface Weekend {
source: 'local' | 'partial' | 'none' | 'cancelled'
meeting_key: number
meeting: Meeting
sessions: WeekendSession[]
default_session_key?: number
}
export interface LiveStateResponse {
is_live: boolean
data: LiveStreamData | null
last_snapshot?: LiveStreamData | null
last_positions?: Record<string, LivePosition> | null
last_snapshot_at?: string
}
export interface LivePosition {
x: number
y: number
z: number
status: string
}
export interface LiveTelemetry {
Speed: number
Throttle: number
Brake: number
DRS: number
NGear: number
RPM: number
}
export interface LiveSectorData {
Value: string
PersonalFastest: boolean
OverallFastest: boolean
}
export interface LiveDriverData {
RacingNumber: string
Position: number
PrevPosition: number
GapToLeader: string
Interval: string
LastLapTime: string
LastLapPB: boolean
LastLapOB: boolean
BestLapTime: string
BestLapPB: boolean
BestLapOB: boolean
BestLapNum: number
InPit: boolean
PitOut: boolean
Retired: boolean
KnockedOut: boolean
Cutoff: boolean
OnFlyingLap: boolean
NumberOfLaps: number
SpeedTrap: string
Sectors: LiveSectorData[]
}
export interface LiveDriverInfo {
RacingNumber: string
BroadcastName: string
Tla: string
TeamName: string
TeamColour: string
FirstName: string
LastName: string
}
export interface LiveTyreData {
Compound: string
New: boolean
Age: number
}
export interface LiveRCMessage {
Time: string
Category: string
Flag: string
Message: string
Lap: number
}
export interface LiveWeatherData {
AirTemp: number
TrackTemp: number
Humidity: number
WindSpeed: number
WindDir: number
Rainfall: boolean
}
export interface LiveSessionMeta {
MeetingName: string
CircuitName: string
SessionType: string
SessionName: string
Path: string
}
export interface LiveStintData {
Compound: string
New: boolean
Laps: number
}
export interface LiveRadioCapture {
Utc: string
RacingNumber: string
Path: string
}
export interface LiveStreamData {
Drivers: Record<string, LiveDriverData>
DriverInfo: Record<string, LiveDriverInfo>
Tyres: Record<string, LiveTyreData>
Telemetry?: Record<string, LiveTelemetry>
RCMessages: LiveRCMessage[]
Weather: LiveWeatherData
Session: LiveSessionMeta
TeamRadio: LiveRadioCapture[]
SessionStatus?: string
TrackStatus: string
CurrentLap: number
TotalLaps: number
Clock: string
ClockRefTime: string
ClockExtrapolating: boolean
Stints: Record<string, LiveStintData[]>
}
export interface TrackPoint {
x: number
y: number
}
export interface TrackBounds {
minX: number
maxX: number
minY: number
maxY: number
}
export interface TrackOutline {
circuit_key: number
points: TrackPoint[]
bounds: TrackBounds
}
export interface ChampHubDriver {
driver_number: number
name_acronym: string
full_name: string
team_name: string
team_colour: string
points: number
position: number
wins: number
podiums: number
poles: number
form: number[]
cumulative: number[]
teammate_wins: number
teammate_losses: number
}
export interface ChampHubTeam {
team_name: string
team_colour: string
points: number
position: number
wins: number
}
export interface ChampionshipHub {
season: number
round: number
total_rounds: number
rounds_left: number
last_race: string
round_labels: string[]
drivers: ChampHubDriver[]
teams: ChampHubTeam[]
}
export interface NewsItem {
source: string
title: string
url: string
published_at?: string
summary?: string
category?: string
fetched_at: string
og_image_url?: string
og_description?: string
read_at?: string
}
export interface ArticleContent {
title: string
byline?: string
excerpt?: string
image_url?: string
content: string
site_name?: string
}