Files
box-box/internal/live/types.go
AmanTahiliani 6c72c12821 feat(live): add team radio ticker
Subscribe to TeamRadio on the F1 live feed, parse defensive capture snapshots and patches, and relay capped captures through live snapshots with the SessionInfo static path. Add the frontend CDN URL helper and ticker using one shared audio element.
2026-07-03 23:56:19 -04:00

176 lines
5.3 KiB
Go

package live
import (
"encoding/json"
"time"
)
// F1SignalRMessage is the top-level envelope from the official F1 SignalR feed.
type F1SignalRMessage struct {
M []struct {
A []json.RawMessage `json:"A"`
} `json:"M"`
R json.RawMessage `json:"R"`
}
// F1TimingLine is a single driver's timing row from TimingData.
type F1TimingLine struct {
GapToLeader interface{} `json:"GapToLeader"`
IntervalToPositionAhead struct {
Value interface{} `json:"Value"`
} `json:"IntervalToPositionAhead"`
Position interface{} `json:"Position"`
RacingNumber string `json:"RacingNumber"`
LastLapTime struct {
Value string `json:"Value"`
PersonalFastest bool `json:"PersonalFastest"`
OverallFastest bool `json:"OverallFastest"`
} `json:"LastLapTime"`
BestLapTime struct {
Value string `json:"Value"`
PersonalFastest bool `json:"PersonalFastest"`
OverallFastest bool `json:"OverallFastest"`
Lap int `json:"Lap"`
} `json:"BestLapTime"`
InPit interface{} `json:"InPit"`
PitOut interface{} `json:"PitOut"`
Retired interface{} `json:"Retired"`
KnockedOut interface{} `json:"KnockedOut"`
Cutoff interface{} `json:"Cutoff"`
NumberOfLaps interface{} `json:"NumberOfLaps"`
Sectors json.RawMessage `json:"Sectors"`
Speeds map[string]json.RawMessage `json:"Speeds"`
}
// F1DriverListEntry is driver metadata from the DriverList topic.
type F1DriverListEntry struct {
RacingNumber string `json:"RacingNumber"`
BroadcastName string `json:"BroadcastName"`
Tla string `json:"Tla"`
TeamName string `json:"TeamName"`
TeamColour string `json:"TeamColour"`
FirstName string `json:"FirstName"`
LastName string `json:"LastName"`
}
// LiveTyreData holds current tyre compound and age for a driver.
type LiveTyreData struct {
Compound string // SOFT, MEDIUM, HARD, INTERMEDIATE, WET
New bool
Age int // laps on current set
}
// LiveRCMessage is a parsed race control message.
type LiveRCMessage struct {
Time string // "15:04" formatted
Category string // Flag, SafetyCar, Drs, Other
Flag string // GREEN, YELLOW, RED, etc.
Message string
Lap int
}
// LiveWeatherData holds session weather readings.
type LiveWeatherData struct {
AirTemp float64
TrackTemp float64
Humidity float64
WindSpeed float64
WindDir int
Rainfall bool
}
// LiveSessionMeta holds session and meeting metadata.
type LiveSessionMeta struct {
MeetingName string
CircuitName string
SessionType string
SessionName string
Path string
}
// LivePositionData is the latest raw F1 GPS position for one driver.
type LivePositionData struct {
X float64 `json:"x"`
Y float64 `json:"y"`
Z float64 `json:"z"`
Status string `json:"status"`
}
// LiveTelemetryData is the latest car telemetry for one driver.
type LiveTelemetryData struct {
Speed int `json:"Speed"`
Throttle int `json:"Throttle"`
Brake int `json:"Brake"`
DRS int `json:"DRS"`
NGear int `json:"NGear"`
RPM int `json:"RPM"`
}
// LiveSectorData holds a single sector time and flags.
type LiveSectorData struct {
Value string
PersonalFastest bool
OverallFastest bool
}
// LiveDriverData is the normalized timing state for one driver.
type LiveDriverData struct {
RacingNumber string
Position int
PrevPosition int
GapToLeader string
Interval string
LastLapTime string
LastLapPB bool // personal best
LastLapOB bool // overall best
BestLapTime string
BestLapPB bool // just set a new personal best
BestLapOB bool // overall fastest in session
BestLapNum int // lap number when best was set
InPit bool
PitOut bool
Retired bool
KnockedOut bool // eliminated in qualifying
Cutoff bool // currently in elimination zone (danger zone)
OnFlyingLap bool // currently running a timed lap (derived from sector state)
NumberOfLaps int
SpeedTrap string // fastest recorded speed at speed trap
Sectors [3]LiveSectorData
}
// LiveStintData is one stint in a driver's tyre history.
type LiveStintData struct {
Compound string
New bool
Laps int
}
// LiveRadioCapture is one team radio audio clip from the live timing feed.
type LiveRadioCapture struct {
Utc string
RacingNumber string
Path string
}
// LiveStreamData is an immutable snapshot of all live timing state.
type LiveStreamData struct {
Drivers map[string]LiveDriverData
DriverInfo map[string]F1DriverListEntry
Tyres map[string]LiveTyreData
Telemetry map[string]LiveTelemetryData
RCMessages []LiveRCMessage
Weather LiveWeatherData
Session LiveSessionMeta
TeamRadio []LiveRadioCapture
TrackStatus string // "1"=green "2"=yellow "4"=SC "5"=red "6"=VSC
CurrentLap int
TotalLaps int
Clock string // "HH:MM:SS" remaining at ClockRefTime
ClockRefTime time.Time // UTC when Clock was accurate
ClockExtrapolating bool // true = actively counting down
Stints map[string][]LiveStintData
Positions map[string]LivePositionData `json:"-"`
PositionUpdated bool `json:"-"`
SnapshotUpdated bool `json:"-"`
}