Add local navigation API

This commit is contained in:
2026-05-25 02:25:06 -04:00
parent b5d87775a6
commit 1661f8dec3
13 changed files with 637 additions and 91 deletions

50
internal/store/counts.go Normal file
View File

@@ -0,0 +1,50 @@
package store
import "database/sql"
// SessionDatasetCounts holds row counts for session-scoped datasets.
type SessionDatasetCounts struct {
Drivers int
Results int
StartingGrid int
Stints int
PitStops int
Positions int
RaceControl int
Weather int
Laps int
}
// CountSessionDatasets returns row counts for ingested session datasets.
func (s *Store) CountSessionDatasets(sessionKey int) (SessionDatasetCounts, error) {
var c SessionDatasetCounts
err := s.db.QueryRow(`
SELECT
(SELECT COUNT(*) FROM session_drivers WHERE session_key = ?),
(SELECT COUNT(*) FROM session_results WHERE session_key = ?),
(SELECT COUNT(*) FROM starting_grid WHERE session_key = ?),
(SELECT COUNT(*) FROM stints WHERE session_key = ?),
(SELECT COUNT(*) FROM pit_stops WHERE session_key = ?),
(SELECT COUNT(*) FROM positions WHERE session_key = ?),
(SELECT COUNT(*) FROM race_control WHERE session_key = ?),
(SELECT COUNT(*) FROM weather WHERE session_key = ?),
(SELECT COUNT(*) FROM laps WHERE session_key = ?)
`,
sessionKey, sessionKey, sessionKey, sessionKey, sessionKey,
sessionKey, sessionKey, sessionKey, sessionKey,
).Scan(
&c.Drivers,
&c.Results,
&c.StartingGrid,
&c.Stints,
&c.PitStops,
&c.Positions,
&c.RaceControl,
&c.Weather,
&c.Laps,
)
if err == sql.ErrNoRows {
return SessionDatasetCounts{}, nil
}
return c, err
}

View File

@@ -100,6 +100,30 @@ func (s *Store) GetMeeting(meetingKey int) (Meeting, error) {
return m, nil
}
// ListYears returns distinct meeting years ordered newest first.
func (s *Store) ListYears() ([]int, error) {
rows, err := s.db.Query(`
SELECT DISTINCT year
FROM meetings
WHERE year > 0
ORDER BY year DESC
`)
if err != nil {
return nil, err
}
defer rows.Close()
var years []int
for rows.Next() {
var year int
if err := rows.Scan(&year); err != nil {
return nil, err
}
years = append(years, year)
}
return years, rows.Err()
}
// ListMeetingsByYear returns meetings for a season ordered by start date.
func (s *Store) ListMeetingsByYear(year int) ([]Meeting, error) {
rows, err := s.db.Query(`

View File

@@ -319,6 +319,25 @@ func TestMeetingSessionDriverUpsertsAreIdempotent(t *testing.T) {
t.Fatalf("ListSessionsByMeeting() len = %d, want 1", len(sessions))
}
years, err := s.ListYears()
if err != nil {
t.Fatalf("ListYears() error = %v", err)
}
if len(years) != 1 || years[0] != 2025 {
t.Fatalf("ListYears() = %v, want [2025]", years)
}
counts, err := s.CountSessionDatasets(session.SessionKey)
if err != nil {
t.Fatalf("CountSessionDatasets() error = %v", err)
}
if counts.Drivers != 1 {
t.Fatalf("CountSessionDatasets().Drivers = %d, want 1", counts.Drivers)
}
if counts.Results != 0 {
t.Fatalf("CountSessionDatasets().Results = %d, want 0", counts.Results)
}
sessionDrivers, err := s.ListSessionDrivers(session.SessionKey)
if err != nil {
t.Fatalf("ListSessionDrivers() error = %v", err)