Add race control visuals and driver names in laps view

This commit is contained in:
2026-05-25 15:55:36 -04:00
parent 3eb74a9083
commit a2aa772838
21 changed files with 458 additions and 118 deletions

View File

@@ -7,13 +7,13 @@ import (
func TestCoverageCRUD(t *testing.T) {
s := openTestStore(t)
// Verify schema migration version is 5 (since we added 005_news_enriched.sql)
// Verify all migrations are applied.
version, err := s.SchemaVersion()
if err != nil {
t.Fatalf("SchemaVersion() error = %v", err)
}
if version != 5 {
t.Fatalf("SchemaVersion() = %d, want 5", version)
if version != 6 {
t.Fatalf("SchemaVersion() = %d, want 6", version)
}
// Verify session_coverage table exists

View File

@@ -0,0 +1,6 @@
ALTER TABLE session_drivers ADD COLUMN broadcast_name TEXT;
ALTER TABLE session_drivers ADD COLUMN first_name TEXT;
ALTER TABLE session_drivers ADD COLUMN full_name TEXT;
ALTER TABLE session_drivers ADD COLUMN last_name TEXT;
ALTER TABLE session_drivers ADD COLUMN name_acronym TEXT;
ALTER TABLE session_drivers ADD COLUMN headshot_url TEXT;

View File

@@ -42,16 +42,16 @@ type NewsSource struct {
// NewsItem stores a normalized feed item deduplicated by URL.
type NewsItem struct {
URL string
Source string
Title string
PublishedAt *time.Time
Summary string
Category string
FetchedAt time.Time
OGImageURL string
OGDescription string
ReadAt *time.Time
URL string
Source string
Title string
PublishedAt *time.Time
Summary string
Category string
FetchedAt time.Time
OGImageURL string
OGDescription string
ReadAt *time.Time
}
// Meeting is a race weekend record.
@@ -100,11 +100,17 @@ type Driver struct {
// SessionDriver links a driver to a session with session-specific team info.
type SessionDriver struct {
SessionKey int
DriverNumber int
MeetingKey int
TeamName string
TeamColour string
SessionKey int
DriverNumber int
MeetingKey int
BroadcastName string
FirstName string
FullName string
LastName string
NameAcronym string
HeadshotURL string
TeamName string
TeamColour string
}
// SessionResult is a final classification row for a session.

View File

@@ -88,16 +88,29 @@ func (s *Store) GetDriver(driverNumber int) (Driver, error) {
func (s *Store) UpsertSessionDriver(sd SessionDriver) error {
_, err := s.db.Exec(`
INSERT INTO session_drivers (
session_key, driver_number, meeting_key, team_name, team_colour
) VALUES (?, ?, ?, ?, ?)
session_key, driver_number, meeting_key, broadcast_name, first_name,
full_name, last_name, name_acronym, headshot_url, team_name, team_colour
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT(session_key, driver_number) DO UPDATE SET
meeting_key = excluded.meeting_key,
broadcast_name = excluded.broadcast_name,
first_name = excluded.first_name,
full_name = excluded.full_name,
last_name = excluded.last_name,
name_acronym = excluded.name_acronym,
headshot_url = excluded.headshot_url,
team_name = excluded.team_name,
team_colour = excluded.team_colour
`,
sd.SessionKey,
sd.DriverNumber,
sd.MeetingKey,
nullString(sd.BroadcastName),
nullString(sd.FirstName),
nullString(sd.FullName),
nullString(sd.LastName),
nullString(sd.NameAcronym),
nullString(sd.HeadshotURL),
nullString(sd.TeamName),
nullString(sd.TeamColour),
)
@@ -110,7 +123,8 @@ func (s *Store) UpsertSessionDriver(sd SessionDriver) error {
// ListSessionDrivers returns drivers entered for a session ordered by number.
func (s *Store) ListSessionDrivers(sessionKey int) ([]SessionDriver, error) {
rows, err := s.db.Query(`
SELECT session_key, driver_number, meeting_key, team_name, team_colour
SELECT session_key, driver_number, meeting_key, broadcast_name, first_name,
full_name, last_name, name_acronym, headshot_url, team_name, team_colour
FROM session_drivers
WHERE session_key = ?
ORDER BY driver_number ASC
@@ -123,16 +137,29 @@ func (s *Store) ListSessionDrivers(sessionKey int) ([]SessionDriver, error) {
var out []SessionDriver
for rows.Next() {
var sd SessionDriver
var broadcastName, firstName, fullName, lastName, nameAcronym, headshotURL sql.NullString
var teamName, teamColour sql.NullString
if err := rows.Scan(
&sd.SessionKey,
&sd.DriverNumber,
&sd.MeetingKey,
&broadcastName,
&firstName,
&fullName,
&lastName,
&nameAcronym,
&headshotURL,
&teamName,
&teamColour,
); err != nil {
return nil, err
}
sd.BroadcastName = broadcastName.String
sd.FirstName = firstName.String
sd.FullName = fullName.String
sd.LastName = lastName.String
sd.NameAcronym = nameAcronym.String
sd.HeadshotURL = headshotURL.String
sd.TeamName = teamName.String
sd.TeamColour = teamColour.String
out = append(out, sd)

View File

@@ -28,8 +28,8 @@ func TestOpenAppliesMigrations(t *testing.T) {
if err != nil {
t.Fatalf("SchemaVersion() error = %v", err)
}
if version != 5 {
t.Fatalf("SchemaVersion() = %d, want 5", version)
if version != 6 {
t.Fatalf("SchemaVersion() = %d, want 6", version)
}
tables := []string{