mirror of
https://github.com/IS1DI/x0gp.git
synced 2026-07-19 05:47:02 +00:00
Add graphify, tests and supabase migrations & config
This commit is contained in:
@@ -0,0 +1,736 @@
|
||||
# x0gp Go Codebase Map (Generated)
|
||||
|
||||
This file contains a compiled map of all packages, structures, interfaces, and public functions in the `server` directory. It is optimized for token-efficiency so AI agents and humans can understand the codebase layout without reading all files.
|
||||
|
||||
## Package `config` (`internal/config`)
|
||||
|
||||
Package config loads runtime configuration from environment variables.
|
||||
|
||||
On startup Load() reads a .env file (if present) from the current
|
||||
working directory and merges its values into the process environment.
|
||||
Existing process env vars take precedence over .env so deployments
|
||||
can override .env without modifying the file.
|
||||
|
||||
### Structs
|
||||
- **struct Config** { HTTPAddr, TickRate, TickInterval, LogLevel, MaxClients, SnapshotRate, DevMode, DatabaseURL, UDPVideoAddr, ESPCmdPort }
|
||||
|
||||
### Functions
|
||||
- func Load() (*Config, error)
|
||||
|
||||
---
|
||||
|
||||
## Package `postgres` (`internal/storage/postgres`)
|
||||
|
||||
Package postgres owns the persistence layer of the catalog.
|
||||
|
||||
It exposes a *pgxpool.Pool plus a small set of repository helpers used by
|
||||
internal/catalog. Migrations are applied at startup from the SQL files in
|
||||
the migrations/ subdirectory.
|
||||
|
||||
### Structs
|
||||
- **struct PgStore**
|
||||
- **struct Config** { URL, Host, Port, User, Password, Database, SSLMode, MaxConns, MinConns, ConnectTimeout }
|
||||
|
||||
### Functions
|
||||
- func NewPgStore(*pgxpool.Pool) *PgStore
|
||||
- func Open(context.Context, Config) (*pgxpool.Pool, error)
|
||||
- func Migrate(context.Context, *pgxpool.Pool) error
|
||||
|
||||
### Methods
|
||||
- func (*PgStore) Load(context.Context) ([]catalog.TrackMeta, []catalog.CarMeta, error)
|
||||
- func (*PgStore) UpsertTrack(context.Context, catalog.TrackMeta) error
|
||||
- func (*PgStore) DeleteTrack(context.Context, string) error
|
||||
- func (*PgStore) UpsertCar(context.Context, catalog.CarMeta) error
|
||||
- func (*PgStore) DeleteCar(context.Context, string) error
|
||||
- func (*PgStore) UpdateCarStats(context.Context, string, func) error
|
||||
- func (*PgStore) GetTrackCalendar(context.Context) ([]catalog.TrackCalendarEntry, error)
|
||||
- func (*PgStore) CreateTrackCalendar(context.Context, catalog.TrackCalendarEntry) (catalog.TrackCalendarEntry, error)
|
||||
- func (*PgStore) DeleteTrackCalendar(context.Context, int) error
|
||||
- func (Config) DSN() (string, error)
|
||||
|
||||
---
|
||||
|
||||
## Package `seed` (`internal/races/seed`)
|
||||
|
||||
### Structs
|
||||
- **struct DefaultCounts** { Finished, Live, Plans }
|
||||
- **struct Options** { Counts, Seed, Reset, Now }
|
||||
- **struct Summary** { FinishedInserted, LiveCreated, PlansInserted, QueueInserted, Duration }
|
||||
- **struct Runner**
|
||||
|
||||
### Functions
|
||||
- func NewRunner(*races.PgStore, *lobby.Service, *races.LiveStore, *clans.PgStore, *drivers.PgStore) *Runner
|
||||
|
||||
### Methods
|
||||
- func (*Runner) Run(context.Context, Options) (Summary, error)
|
||||
|
||||
---
|
||||
|
||||
## Package `realtime` (`internal/realtime`)
|
||||
|
||||
Package realtime manages WebSocket connections: registration, fan-out of
|
||||
race snapshots, and per-client send queues with backpressure handling.
|
||||
|
||||
### Structs
|
||||
- **struct Client** { ID, Send, SessionID, Done, DriverID, LastUDPCommand }
|
||||
- **struct Hub**
|
||||
- **struct Stats** { Connections, DropsTotal }
|
||||
|
||||
### Functions
|
||||
- func NewHub() *Hub
|
||||
- func MustEnvelope(transport.MessageType, any) *transport.Envelope
|
||||
|
||||
### Methods
|
||||
- func (*Client) Close()
|
||||
- func (*Hub) Stats() Stats
|
||||
- func (*Hub) Register(*Client)
|
||||
- func (*Hub) Unregister(*Client)
|
||||
- func (*Hub) Run(context.Context)
|
||||
- func (*Hub) Stop()
|
||||
- func (*Hub) Publish(*transport.Envelope)
|
||||
|
||||
---
|
||||
|
||||
## Package `catalog` (`internal/catalog`)
|
||||
|
||||
Package catalog owns the static configuration entities: tracks and
|
||||
cars. Both are first-class resources that drivers browse, pick, and
|
||||
(in later phases) author.
|
||||
|
||||
PoC: in-memory cache backed by a pluggable Store. The runtime uses
|
||||
postgres.PgStore so tracks / cars survive restarts. The cache is the
|
||||
source of truth for read paths; the Store is the source of truth for
|
||||
durability. Mutations go through the Store, then refresh the cache.
|
||||
|
||||
Design constraints come from the user's apartment layout:
|
||||
- largest room: 4.46 m × 3.19 m (446 × 319 cm)
|
||||
- car scale: 1/27 (Compact)
|
||||
- printer: Bambu A1 (220×220×250 mm build volume)
|
||||
|
||||
Tracks are sized to fit a 4.5 × 3.2 m bounding box with a safety
|
||||
margin, which keeps them physically realizable in the apartment.
|
||||
Cars are sized to a 1/27 touring envelope (~80 × 35 × 25 mm).
|
||||
|
||||
### Interfaces
|
||||
- **interface Store** { Load, UpsertTrack, DeleteTrack, UpsertCar, DeleteCar, UpdateCarStats, GetTrackCalendar, CreateTrackCalendar, DeleteTrackCalendar }
|
||||
|
||||
### Structs
|
||||
- **struct CreateTrackOptions** { ID, Name, Description, AuthorID, Visibility, Scale, LengthM, WidthM, LaneWidthM, Surface, Tags, Centerline }
|
||||
- **struct UpdateTrackOptions** { Name, Description, Visibility, LengthM, WidthM, LaneWidthM, Surface, Tags, Centerline }
|
||||
- **struct CreateCarOptions** { ID, Name, OwnerID, Visibility, Scale, LengthMm, WidthMm, HeightMm, WeightG, Chassis, Motor, Battery, Drive, TopSpeedMs, ColorHex, AvatarURL, Active, DeviceID }
|
||||
- **struct UpdateCarOptions** { Name, Visibility, LengthMm, WidthMm, HeightMm, WeightG, TopSpeedMs, ColorHex, Active, Chassis, Motor, Battery, Drive, DeviceID }
|
||||
- **struct Waypoint** { X, Y, HeadingRad, SpeedMs, Curvature }
|
||||
- **struct Bounds** { MinX, MinY, MaxX, MaxY, LengthM, WidthM }
|
||||
- **struct TrackMeta** { ID, Name, Description, AuthorID, Visibility, Scale, LengthM, WidthM, LaneWidthM, Bounds, Surface, Tags, Centerline, BestLapMs, BestLapHolder, CreatedMs, UpdatedMs }
|
||||
- **struct TrackCalendarEntry** { ID, TrackID, StartAt, EndAt }
|
||||
- **struct MotorSpec** { Kind, Class, KV, PowerW }
|
||||
- **struct BatterySpec** { VoltageV, CapacityMah, Cells, Chemistry }
|
||||
- **struct ChassisSpec** { Model, Material, Printed, WheelbaseMm, TrackMm }
|
||||
- **struct CarMeta** { ID, Name, OwnerID, Visibility, Scale, LengthMm, WidthMm, HeightMm, WeightG, Chassis, Motor, Battery, Drive, DeviceID, TopSpeedMs, ColorHex, AvatarURL, Active, TotalDistanceM, TotalRaces, TotalLaps, BestLapMs, CreatedMs, UpdatedMs }
|
||||
- **struct Snapshot** { GeneratedMs, Version, Tracks, Cars }
|
||||
- **struct Stats** { TracksTotal, TracksSystem, TracksPublic, TracksPrivate, CarsTotal, CarsSystem, CarsPublic, CarsPrivate, CarsActive }
|
||||
- **struct Event** { Kind, TrackID, CarID, Snapshot }
|
||||
- **struct Service**
|
||||
|
||||
### Functions
|
||||
- func NewService(context.Context, Store) (*Service, error)
|
||||
|
||||
### Methods
|
||||
- func (CreateTrackOptions) Validate() error
|
||||
- func (*Service) CreateTrack(context.Context, CreateTrackOptions) (TrackMeta, error)
|
||||
- func (*Service) UpdateTrack(context.Context, string, UpdateTrackOptions) (TrackMeta, error)
|
||||
- func (*Service) DeleteTrack(context.Context, string) error
|
||||
- func (CreateCarOptions) Validate() error
|
||||
- func (*Service) CreateCar(context.Context, CreateCarOptions) (CarMeta, error)
|
||||
- func (*Service) UpdateCar(context.Context, string, UpdateCarOptions) (CarMeta, error)
|
||||
- func (*Service) DeleteCar(context.Context, string) error
|
||||
- func (*Service) SetCarStats(context.Context, string, func) error
|
||||
- func (*Service) ListTracksByVisibility(Visibility) []TrackMeta
|
||||
- func (*Service) ListCarsByVisibility(Visibility) []CarMeta
|
||||
- func (*Service) ListCarsByOwner(string) []CarMeta
|
||||
- func (*Service) GetTrackCalendar(context.Context) ([]TrackCalendarEntry, error)
|
||||
- func (*Service) CreateTrackCalendar(context.Context, string, time.Time, time.Time) (TrackCalendarEntry, error)
|
||||
- func (*Service) DeleteTrackCalendar(context.Context, int) error
|
||||
- func (*memoryStore) Load(context.Context) ([]TrackMeta, []CarMeta, error)
|
||||
- func (*memoryStore) UpsertTrack(context.Context, TrackMeta) error
|
||||
- func (*memoryStore) DeleteTrack(context.Context, string) error
|
||||
- func (*memoryStore) UpsertCar(context.Context, CarMeta) error
|
||||
- func (*memoryStore) DeleteCar(context.Context, string) error
|
||||
- func (*memoryStore) UpdateCarStats(context.Context, string, func) error
|
||||
- func (*memoryStore) GetTrackCalendar(context.Context) ([]TrackCalendarEntry, error)
|
||||
- func (*memoryStore) CreateTrackCalendar(context.Context, TrackCalendarEntry) (TrackCalendarEntry, error)
|
||||
- func (*memoryStore) DeleteTrackCalendar(context.Context, int) error
|
||||
- func (*Service) Subscribe() (?, func)
|
||||
- func (*Service) Stop()
|
||||
- func (*Service) Done() ?
|
||||
- func (*Service) Snapshot() Snapshot
|
||||
- func (*Service) Stats() Stats
|
||||
- func (*Service) ListTracks() []TrackMeta
|
||||
- func (*Service) ListCars() []CarMeta
|
||||
- func (*Service) GetTrack(string) (TrackMeta, bool)
|
||||
- func (*Service) GetCar(string) (CarMeta, bool)
|
||||
|
||||
---
|
||||
|
||||
## Package `seeddefs` (`internal/catalog/seeddefs`)
|
||||
|
||||
Package seeddefs holds the canonical seed definitions for tracks and
|
||||
cars. It lives in its own package (no postgres dependencies) so both
|
||||
the catalog tests and the scripts/genseed SQL generator can consume
|
||||
the same source-of-truth data.
|
||||
|
||||
### Structs
|
||||
- **struct Waypoint** { X, Y, HeadingRad, SpeedMs, Curvature }
|
||||
- **struct Bounds** { MinX, MinY, MaxX, MaxY, LengthM, WidthM }
|
||||
- **struct Track** { ID, Name, Description, AuthorID, Visibility, Scale, LengthM, WidthM, LaneWidthM, Surface, Tags, Centerline, Bounds, BestLapMs, BestLapHolder }
|
||||
- **struct Chassis** { Model, Material, Printed, WheelbaseMm, TrackMm }
|
||||
- **struct Motor** { Kind, Class, KV, PowerW }
|
||||
- **struct Battery** { VoltageV, CapacityMah, Cells, Chemistry }
|
||||
- **struct Car** { ID, Name, OwnerID, Visibility, Scale, LengthMm, WidthMm, HeightMm, WeightG, Chassis, Motor, Battery, Drive, TopSpeedMs, ColorHex, Active, TotalDistanceM, TotalRaces, TotalLaps, BestLapMs }
|
||||
|
||||
### Functions
|
||||
- func DefaultTracks() []Track
|
||||
- func DefaultCars() []Car
|
||||
- func Monaco() Track
|
||||
- func BarcelonaCatalunya() Track
|
||||
- func AustriaRedBullRing() Track
|
||||
- func GreatBritainSilverstone() Track
|
||||
- func BelgiumSpa() Track
|
||||
- func RedBullRB20() Car
|
||||
- func FerrariSF24() Car
|
||||
- func McLarenMCL38() Car
|
||||
- func MercedesW15() Car
|
||||
- func AstonMartinAMR24() Car
|
||||
- func ComputeBounds([]Waypoint) Bounds
|
||||
|
||||
---
|
||||
|
||||
## Package `clans` (`internal/clans`)
|
||||
|
||||
Package clans owns persistence and business logic for clans.
|
||||
|
||||
A clan has a unique 3-letter tag (A-Z, uppercase, exactly 3 chars),
|
||||
a name, and an optional avatar URL. Drivers reference a clan via a
|
||||
nullable FK (see internal/drivers).
|
||||
|
||||
### Interfaces
|
||||
- **interface Store** { Exec, Create, Get, GetByTag, List, Delete, Update, Count }
|
||||
|
||||
### Structs
|
||||
- **struct Service**
|
||||
- **struct CreateInput** { ID, Tag, Name, AvatarURL }
|
||||
- **struct UpdateInput** { Name, AvatarURL }
|
||||
- **struct Clan** { ID, Tag, Name, AvatarURL, CreatedMs, UpdatedMs }
|
||||
- **struct PgStore**
|
||||
|
||||
### Functions
|
||||
- func NewService(Store) *Service
|
||||
- func IsValidTag(string) bool
|
||||
- func NewPgStore(*pgxpool.Pool) *PgStore
|
||||
|
||||
### Methods
|
||||
- func (*Service) Create(context.Context, CreateInput) (Clan, error)
|
||||
- func (*Service) Get(context.Context, string) (Clan, error)
|
||||
- func (*Service) GetByTag(context.Context, string) (Clan, error)
|
||||
- func (*Service) List(context.Context, int, int) ([]Clan, error)
|
||||
- func (*Service) Update(context.Context, string, UpdateInput) (Clan, error)
|
||||
- func (*Service) Delete(context.Context, string) error
|
||||
- func (*PgStore) Exec(context.Context, string) (int64, error)
|
||||
- func (*PgStore) Create(context.Context, Clan) error
|
||||
- func (*PgStore) Get(context.Context, string) (Clan, error)
|
||||
- func (*PgStore) GetByTag(context.Context, string) (Clan, error)
|
||||
- func (*PgStore) List(context.Context, int, int) ([]Clan, error)
|
||||
- func (*PgStore) Delete(context.Context, string) error
|
||||
- func (*PgStore) Update(context.Context, Clan) error
|
||||
- func (*PgStore) Count(context.Context) (int, error)
|
||||
|
||||
---
|
||||
|
||||
## Package `control` (`internal/control`)
|
||||
|
||||
Package control owns the authoritative race state.
|
||||
|
||||
For PoC, the physics model is intentionally simple (no tire slip, no
|
||||
collision): each car integrates position from (throttle, brake, steering).
|
||||
Realistic physics, anti-cheat checks, and CV-based ground truth will be
|
||||
added in MVP / production phases.
|
||||
|
||||
### Structs
|
||||
- **struct Car** { ID, DriverID, DriverName, DeviceID, X, Y, Heading, Speed, Lap, Sector, LastLapMs, BestLapMs, DNF, AppliedSteering, AppliedThrottle, AppliedBrake }
|
||||
- **struct Engine**
|
||||
|
||||
### Functions
|
||||
- func NewEngine(int) *Engine
|
||||
|
||||
### Methods
|
||||
- func (RacePhase) String() string
|
||||
- func (*Car) ApplyInput(transport.InputState, float64)
|
||||
- func (*Car) Snapshot() transport.CarInfo
|
||||
- func (*Engine) Snapshots() ?
|
||||
- func (*Engine) Phase() RacePhase
|
||||
- func (*Engine) SetPhase(RacePhase)
|
||||
- func (*Engine) AddCar(string, string, int, *int) (*Car, error)
|
||||
- func (*Engine) RemoveCar(string)
|
||||
- func (*Engine) GetCarByDriver(string) *Car
|
||||
- func (*Engine) Run(context.Context)
|
||||
- func (*Engine) Stop()
|
||||
|
||||
---
|
||||
|
||||
## Package `drivers` (`internal/drivers`)
|
||||
|
||||
Package drivers owns persistence and business logic for drivers
|
||||
(racers). Each driver has a unique 3-letter nickname (A-Z,
|
||||
uppercase, exactly 3 chars), a name, an optional avatar URL and an
|
||||
optional clan reference.
|
||||
|
||||
### Interfaces
|
||||
- **interface Store** { Exec, Create, Get, GetByNickname, List, Delete, Update, Count }
|
||||
|
||||
### Structs
|
||||
- **struct Service**
|
||||
- **struct CreateInput** { ID, Nickname, Name, AvatarURL, ClanID }
|
||||
- **struct UpdateInput** { Name, AvatarURL, ClanID }
|
||||
- **struct Driver** { ID, Nickname, Name, AvatarURL, ClanID, CreatedMs, UpdatedMs }
|
||||
- **struct PgStore**
|
||||
|
||||
### Functions
|
||||
- func NewService(Store) *Service
|
||||
- func IsValidNickname(string) bool
|
||||
- func NewPgStore(*pgxpool.Pool) *PgStore
|
||||
|
||||
### Methods
|
||||
- func (*Service) Create(context.Context, CreateInput) (Driver, error)
|
||||
- func (*Service) Get(context.Context, string) (Driver, error)
|
||||
- func (*Service) GetByNickname(context.Context, string) (Driver, error)
|
||||
- func (*Service) List(context.Context, int, int, string) ([]Driver, error)
|
||||
- func (*Service) Update(context.Context, string, UpdateInput) (Driver, error)
|
||||
- func (*Service) Delete(context.Context, string) error
|
||||
- func (*PgStore) Exec(context.Context, string) (int64, error)
|
||||
- func (*PgStore) Create(context.Context, Driver) error
|
||||
- func (*PgStore) Get(context.Context, string) (Driver, error)
|
||||
- func (*PgStore) GetByNickname(context.Context, string) (Driver, error)
|
||||
- func (*PgStore) List(context.Context, int, int, string) ([]Driver, error)
|
||||
- func (*PgStore) Update(context.Context, Driver) error
|
||||
- func (*PgStore) Delete(context.Context, string) error
|
||||
- func (*PgStore) Count(context.Context) (int, error)
|
||||
|
||||
---
|
||||
|
||||
## Package `lobby` (`internal/lobby`)
|
||||
|
||||
Package lobby owns the "outside any race" state of the server: which
|
||||
races are open, which drivers are connected but idle, who is the host
|
||||
of each race.
|
||||
|
||||
The lobby is the single source of truth for matchmaking and for
|
||||
rendering the "what races are available right now" list. It does NOT
|
||||
own per-race physics — that's the Engine (internal/control).
|
||||
|
||||
All operations are thread-safe. Mutations broadcast a snapshot event
|
||||
to subscribers (see Service.Subscribe).
|
||||
|
||||
### Interfaces
|
||||
- **interface Persistence** { UpsertRace, DeleteRace, AddDriver, RemoveDriver, SetRaceStatus, UpsertDriver, DeleteDriver }
|
||||
|
||||
### Structs
|
||||
- **struct CreateRaceOptions** { ID, Name, TrackID, MaxCars, Laps, TimeLimitS }
|
||||
- **struct RaceMeta** { ID, Name, TrackID, MaxCars, Laps, TimeLimitS, DriverIDs, Status, CreatedMs, StartedMs }
|
||||
- **struct DriverMeta** { ID, Name, Nickname, AvatarURL, ClanID, ClanTag, Status, RaceID, ConnectedMs, LastSeenMs, Country, AvatarHue, CarID }
|
||||
- **struct Snapshot** { GeneratedMs, Races, Drivers, Version }
|
||||
- **struct Stats** { RacesTotal, RacesOpen, RacesActive, DriversIdle, DriversTotal }
|
||||
- **struct Service**
|
||||
|
||||
### Functions
|
||||
- func NewService() *Service
|
||||
|
||||
### Methods
|
||||
- func (*Service) CreateRace(CreateRaceOptions) (RaceMeta, error)
|
||||
- func (*Service) AddRace(RaceMeta)
|
||||
- func (*Service) AddDriver(string, string, string) (DriverMeta, error)
|
||||
- func (*Service) RemoveDriver(string)
|
||||
- func (*Service) Heartbeat(string)
|
||||
- func (*Service) SetDriverProfile(string, string, string, string, string)
|
||||
- func (*Service) AddDriverToRace(string, string) error
|
||||
- func (*Service) RemoveDriverFromRace(string)
|
||||
- func (*Service) SetRaceStatus(string, RaceStatus) error
|
||||
- func (*Service) DeleteRace(string) error
|
||||
- func (*Service) QuickPlay(string, int) (RaceMeta, error)
|
||||
- func (*Service) GetRace(string) (RaceMeta, error)
|
||||
- func (*Service) GetDriver(string) (DriverMeta, error)
|
||||
- func (*Service) SelectCar(string, *string) error
|
||||
- func (*Service) ListRaces() []RaceMeta
|
||||
- func (*Service) ListDrivers() []DriverMeta
|
||||
- func (*Service) SetPersistence(Persistence)
|
||||
- func (*Service) SetRaceLifecycleHook(func, func)
|
||||
- func (*Service) Subscribe() (?, func)
|
||||
- func (*Service) Stop()
|
||||
- func (*Service) Done() ?
|
||||
- func (*Service) Snapshot() Snapshot
|
||||
- func (*Service) Stats() Stats
|
||||
|
||||
---
|
||||
|
||||
## Package `stats` (`internal/stats`)
|
||||
|
||||
Package stats collects and exposes server and per-driver metrics.
|
||||
|
||||
PoC: in-memory only, atomic counters where possible, mutex around
|
||||
driver and race records. The data lives for the lifetime of the
|
||||
process. A future storage layer will swap this for Postgres/Redis.
|
||||
|
||||
Public surface is split into:
|
||||
- lifecycle hooks (Connect/Disconnect/Race*/Lap*/Input*/RTT) —
|
||||
called from cmd/poc-server and from internal/control and lobby
|
||||
- Snapshot() — full server snapshot for /stats/detailed
|
||||
- DriverProfile(id) — per-driver summary
|
||||
- RecentLaps(n) — last N laps across all races
|
||||
|
||||
### Structs
|
||||
- **struct ServerStats** { StartedMs, UptimeMs, CurrentClients, PeakClients, TotalConnections, TotalDisconnects, TotalRacesCreated, TotalRacesStarted, TotalRacesFinished, TotalLapsRecorded, TotalInputsRecv, TotalSnapshotsSent, SnapshotsDropped, AvgRTTMs, RecentRTTs }
|
||||
- **struct DriverProfile** { ID, Name, TotalRacesStarted, TotalRacesFinished, TotalLaps, BestLapMs, LastLapMs, TotalDistanceM, TotalPlaytimeMs, Wins, Podiums, LastSeenMs }
|
||||
- **struct LapRecord** { RaceID, DriverID, LapMs, Sector1Ms, Sector2Ms, Sector3Ms, Position, TSMs }
|
||||
- **struct RaceResult** { RaceID, DriverID, FinishedAtMs, Position, TotalLaps, BestLapMs, TotalTimeMs, DNF }
|
||||
- **struct Collector**
|
||||
|
||||
### Functions
|
||||
- func NewCollector() *Collector
|
||||
|
||||
### Methods
|
||||
- func (*Collector) Start()
|
||||
- func (*Collector) OnConnect(string, string)
|
||||
- func (*Collector) OnDisconnect(string, int64)
|
||||
- func (*Collector) OnRaceCreated()
|
||||
- func (*Collector) OnRaceStarted([]string)
|
||||
- func (*Collector) OnRaceFinished(RaceResult)
|
||||
- func (*Collector) OnLapRecorded(LapRecord)
|
||||
- func (*Collector) OnInputProcessed()
|
||||
- func (*Collector) OnSnapshotSent(uint64, uint64)
|
||||
- func (*Collector) OnRTT(int64)
|
||||
- func (*Collector) OnDistance(string, float64)
|
||||
- func (*Collector) Server() ServerStats
|
||||
- func (*Collector) Driver(string, string) DriverProfile
|
||||
- func (*Collector) Drivers() []DriverProfile
|
||||
- func (*Collector) RecentLaps(int) []LapRecord
|
||||
- func (*Collector) RecentResults(int) []RaceResult
|
||||
|
||||
---
|
||||
|
||||
## Package `races` (`internal/races`)
|
||||
|
||||
Package races owns the cross-cutting "race list" surface: keyset-paginated
|
||||
listing of live and finished races, upcoming (next-N) selection, the
|
||||
driver-to-race queue and the recurring race-plan scheduler.
|
||||
|
||||
The package composes two storage backends:
|
||||
|
||||
- lobby.Service (in-memory): authoritative source for active races
|
||||
(status = lobby | countdown | racing). Used directly for the live
|
||||
page of /api/races, for the upcoming view and for the scheduler
|
||||
materialisation.
|
||||
- Postgres (pgxpool): authoritative for finished races (snapshotted
|
||||
on SetRaceStatus(finished)), for race plans and for the queue.
|
||||
Finished races are read with keyset pagination on
|
||||
(finished_ms DESC, id DESC).
|
||||
|
||||
### Structs
|
||||
- **struct Cursor** { Ms, ID }
|
||||
- **struct LeaderboardEntry** { DriverID, Name, Nickname, AvatarURL, ClanID, ClanTag, Points, BestPos, BestTimeMs, Rank }
|
||||
- **struct LeaderboardResult** { Items, Total, CurrentDriver }
|
||||
- **struct TrackCalendarInfo** { ID, TrackID, TrackName, StartAt, EndAt }
|
||||
- **struct TrackCalendarLeaderboard** { TrackID, TrackName, StartAt, EndAt, Status, Podium, CurrentDriver }
|
||||
- **struct LiveStore**
|
||||
- **struct Service**
|
||||
- **struct ListFilter** { Statuses, TrackID, Cursor, Limit }
|
||||
- **struct RaceItem** { Source, Meta, Podium }
|
||||
- **struct ListResult** { Items, NextCursor, TotalCount }
|
||||
- **struct UpcomingItem** { Meta, QueueLen, PlanID, StartAtMs }
|
||||
- **struct JoinUpcomingResult** { Joined, Skipped }
|
||||
- **struct SnapshotFinished** { Meta, FinishedMs, TotalLaps, WinnerDriverID, WinnerName, BestLapMs, Results }
|
||||
- **struct CreatePlanInput** { ID, Name, TrackID, MaxCars, Laps, TimeLimitS, StartAtMs, IntervalS, Count, Enabled }
|
||||
- **struct Scheduler**
|
||||
- **struct PodiumEntry** { Position, DriverID, Name, TotalTimeMs, Nickname, AvatarUrl, ClanID }
|
||||
- **struct DriverResult** { DriverID, Name, TotalTimeMs, BestLapMs, Position, Nickname, AvatarUrl, ClanID }
|
||||
- **struct FinishedRace** { ID, Name, TrackID, MaxCars, Laps, TimeLimitS, DriverIDs, Status, CreatedMs, StartedMs, FinishedMs, DurationMs, TotalLaps, TotalDrivers, Results, WinnerDriverID, WinnerName, BestLapMs, Podium }
|
||||
- **struct RacePlan** { ID, Name, TrackID, MaxCars, Laps, TimeLimitS, StartAtMs, IntervalS, Count, Enabled, CreatedMs, UpdatedMs, NextFireMs, FiresDone }
|
||||
- **struct QueueEntry** { DriverID, RaceID, PlanID, EnqueuedMs }
|
||||
- **struct PgStore**
|
||||
|
||||
### Functions
|
||||
- func DecodeCursor(string) (Cursor, error)
|
||||
- func NewLiveStore(*PgStore) *LiveStore
|
||||
- func NewService(*PgStore, *lobby.Service) *Service
|
||||
- func NewScheduler(*PgStore, *lobby.Service, time.Duration) *Scheduler
|
||||
- func NewPgStore(*pgxpool.Pool) *PgStore
|
||||
- func ParseStatusFilter(string) ([]StatusFilter, error)
|
||||
|
||||
### Methods
|
||||
- func (Cursor) String() string
|
||||
- func (Cursor) IsZero() bool
|
||||
- func (Cursor) Encode() string
|
||||
- func (*PgStore) GetTrackLeaderboard(context.Context, string, int, int, int) ([]LeaderboardEntry, int, error)
|
||||
- func (*PgStore) GetTrackLeaderboardDriver(context.Context, string, int, string) (*LeaderboardEntry, error)
|
||||
- func (*PgStore) GetOverallLeaderboard(context.Context, int, int, int) ([]LeaderboardEntry, int, error)
|
||||
- func (*PgStore) GetOverallLeaderboardDriver(context.Context, int, string) (*LeaderboardEntry, error)
|
||||
- func (*PgStore) GetDriverLeaderboardProfile(context.Context, string) (*LeaderboardEntry, error)
|
||||
- func (*PgStore) GetCalendarLeaderboardTracks(context.Context) ([]TrackCalendarInfo, error)
|
||||
- func (*LiveStore) UpsertRace(context.Context, lobby.RaceMeta) error
|
||||
- func (*LiveStore) DeleteRace(context.Context, string) error
|
||||
- func (*LiveStore) AddDriver(context.Context, string, string, int) error
|
||||
- func (*LiveStore) RemoveDriver(context.Context, string, string) error
|
||||
- func (*LiveStore) SetRaceStatus(context.Context, string, lobby.RaceStatus, int64) error
|
||||
- func (*LiveStore) UpsertDriver(context.Context, lobby.DriverMeta) error
|
||||
- func (*LiveStore) DeleteDriver(context.Context, string) error
|
||||
- func (*LiveStore) ListAllRaces(context.Context) ([]lobby.RaceMeta, error)
|
||||
- func (*LiveStore) ListAllDrivers(context.Context) ([]lobby.DriverMeta, error)
|
||||
- func (*LiveStore) ListLivePaged(context.Context, []string, string, Cursor, int) ([]lobby.RaceMeta, error)
|
||||
- func (*LiveStore) ListUpcoming(context.Context, int) ([]lobby.RaceMeta, error)
|
||||
- func (*LiveStore) Exec(context.Context, string) (int64, error)
|
||||
- func (*Service) SetLiveStore(*LiveStore)
|
||||
- func (*Service) RestoreFromDB(context.Context) (int, int, error)
|
||||
- func (*Service) SetMaxUpcoming(int)
|
||||
- func (*Service) ListRaces(context.Context, ListFilter) (ListResult, error)
|
||||
- func (*Service) Upcoming(context.Context, int) ([]UpcomingItem, error)
|
||||
- func (*Service) JoinUpcoming(context.Context, string, int) (JoinUpcomingResult, error)
|
||||
- func (*Service) LeaveQueue(context.Context, string, string) error
|
||||
- func (*Service) ListQueue(context.Context, string) ([]QueueEntry, error)
|
||||
- func (*Service) PersistFinished(context.Context, SnapshotFinished) error
|
||||
- func (*Service) CreatePlan(context.Context, CreatePlanInput) (RacePlan, error)
|
||||
- func (*Service) ListPlans(context.Context, Cursor, int) ([]RacePlan, error)
|
||||
- func (*Service) CountPlans(context.Context) (int, error)
|
||||
- func (*Service) DeletePlan(context.Context, string) error
|
||||
- func (*Service) GetLeaderboard(context.Context, string, int, int, int, string) (*LeaderboardResult, error)
|
||||
- func (*Service) GetCalendarLeaderboard(context.Context, int, string) ([]TrackCalendarLeaderboard, error)
|
||||
- func (*Scheduler) Run(context.Context)
|
||||
- func (*Scheduler) Stop()
|
||||
- func (*Scheduler) Done() ?
|
||||
- func (*PgStore) Exec(context.Context, string, ?) (int64, error)
|
||||
- func (*PgStore) ListTrackIDs(context.Context) ([]string, error)
|
||||
- func (*PgStore) UpsertLive(context.Context, lobby.RaceMeta) error
|
||||
- func (*PgStore) DeleteLive(context.Context, string) error
|
||||
- func (*PgStore) AddLiveDriver(context.Context, string, string, int) error
|
||||
- func (*PgStore) RemoveLiveDriver(context.Context, string, string) error
|
||||
- func (*PgStore) SetLiveStatus(context.Context, string, lobby.RaceStatus, int64) error
|
||||
- func (*PgStore) ListLivePaged(context.Context, []string, string, Cursor, int) ([]lobby.RaceMeta, error)
|
||||
- func (*PgStore) ListLiveUpcoming(context.Context, int) ([]lobby.RaceMeta, error)
|
||||
- func (*PgStore) GetLive(context.Context, string) (lobby.RaceMeta, error)
|
||||
- func (*PgStore) ListAllRaces(context.Context) ([]lobby.RaceMeta, error)
|
||||
- func (*PgStore) UpsertLobbyDriver(context.Context, lobby.DriverMeta) error
|
||||
- func (*PgStore) DeleteLobbyDriver(context.Context, string) error
|
||||
- func (*PgStore) ListLobbyDrivers(context.Context) ([]lobby.DriverMeta, error)
|
||||
- func (*PgStore) InsertFinished(context.Context, FinishedRace) error
|
||||
- func (*PgStore) ListFinished(context.Context, string, Cursor, int) ([]FinishedRace, error)
|
||||
- func (*PgStore) CountRaces(context.Context, []string, string) (int, error)
|
||||
- func (*PgStore) CreatePlan(context.Context, RacePlan) error
|
||||
- func (*PgStore) GetPlan(context.Context, string) (RacePlan, error)
|
||||
- func (*PgStore) ListPlans(context.Context, Cursor, int) ([]RacePlan, error)
|
||||
- func (*PgStore) CountPlans(context.Context) (int, error)
|
||||
- func (*PgStore) DeletePlan(context.Context, string) error
|
||||
- func (*PgStore) SetPlanEnabled(context.Context, string, bool) error
|
||||
- func (*PgStore) AdvancePlan(context.Context, string, int64) error
|
||||
- func (*PgStore) DuePlans(context.Context, int64, int) ([]RacePlan, error)
|
||||
- func (*PgStore) Enqueue(context.Context, string, string, string) (QueueEntry, error)
|
||||
- func (*PgStore) Dequeue(context.Context, string, string) error
|
||||
- func (*PgStore) ListQueueByDriver(context.Context, string) ([]QueueEntry, error)
|
||||
- func (*PgStore) ListQueueByRace(context.Context, string) ([]QueueEntry, error)
|
||||
- func (*PgStore) CountQueueByRace(context.Context, string) (int, error)
|
||||
- func (FinishedRace) ToLobbyMeta() lobby.RaceMeta
|
||||
|
||||
---
|
||||
|
||||
## Package `main` (`scripts/graphify`)
|
||||
|
||||
Package main is the graphify utility. It walks the codebase, parses Go AST,
|
||||
and outputs a highly compact symbol summary to server/CODEBASE.md.
|
||||
This is used for token savings and helping developers/AI agents quickly map out imports and structures.
|
||||
|
||||
### Structs
|
||||
- **struct PackageSummary** { Name, Path, Doc, Structs, Interfaces, Functions, Methods }
|
||||
|
||||
---
|
||||
|
||||
## Package `main` (`.`)
|
||||
|
||||
Smoke test: ws client connects, exchanges a few messages, exits.
|
||||
Run: go run ./smoke_test.go
|
||||
|
||||
---
|
||||
|
||||
## Package `transport` (`internal/transport`)
|
||||
|
||||
Package transport defines the wire format between clients and the server.
|
||||
|
||||
PoC: JSON for fast iteration. Specified by proto/client_server.proto for
|
||||
the production binary protobuf format.
|
||||
|
||||
TODO PoC: replace JSON with protobuf-generated structs (see
|
||||
../proto/client_server.proto).
|
||||
|
||||
### Structs
|
||||
- **struct Envelope** { Type, Seq, TSMs, Payload }
|
||||
- **struct ClientHello** { Version, Token, Locale, ClientID }
|
||||
- **struct ServerHello** { SessionID, RaceTick, ServerVersion, Config }
|
||||
- **struct JoinRace** { RaceID, CarSlot, CarName }
|
||||
- **struct LeaveRace** { RaceID }
|
||||
- **struct InputState** { Steering, Throttle, Brake, Gear, Buttons }
|
||||
- **struct ChatMessage** { Text }
|
||||
- **struct Ping** { ClientTSMs }
|
||||
- **struct RaceSnapshot** { Tick, TSMs, Elapsed, Cars }
|
||||
- **struct CarInfo** { ID, DriverName, X, Y, Heading, Speed, Lap, Sector, LastLapMs, BestLapMs, InputApplied, DNF }
|
||||
- **struct InputAck** { Seq, AppliedAtMs, ServerTickMs }
|
||||
- **struct Correction** { Tick, DeltaSteering, DeltaThrottle, Reason }
|
||||
- **struct RaceEvent** { RaceID, Event, CarID, Sector, LapMs, TSMs }
|
||||
- **struct Pong** { ClientTSMs, ServerTSMs }
|
||||
- **struct ErrorMsg** { Code, Message }
|
||||
- **struct LobbyRace** { ID, Name, TrackID, MaxCars, Laps, TimeLimitS, DriverIDs, Status, CreatedMs, StartedMs, Podium }
|
||||
- **struct RacePodiumEntry** { Position, DriverID, Name, TotalTimeMs, Nickname, AvatarUrl, ClanID }
|
||||
- **struct VersionResponse** { Version }
|
||||
- **struct WebRTCConnectRequest** { SDP, Type, DriverID }
|
||||
- **struct WebRTCConnectResponse** { SDP, Type }
|
||||
- **struct LobbyDriver** { ID, Name, Status, RaceID, ConnectedMs, LastSeenMs, Country, AvatarHue }
|
||||
- **struct LobbySnapshot** { GeneratedMs, Version, Races, Drivers }
|
||||
- **struct LobbyCreate** { RaceID, Name, TrackID, MaxCars, Laps, TimeLimitS }
|
||||
- **struct LobbyJoinRace** { RaceID, CarSlot, CarName }
|
||||
- **struct LobbyLeaveRace** { RaceID }
|
||||
- **struct LobbyKickDriver** { RaceID, DriverID }
|
||||
- **struct LobbyDelete** { RaceID }
|
||||
- **struct LobbyCreatedAck** { Ok, Race, Error, Driver }
|
||||
- **struct LobbyJoinAck** { Ok, Race, Error }
|
||||
- **struct TrackWaypoint** { X, Y, HeadingRad, SpeedMs, Curvature }
|
||||
- **struct TrackBounds** { MinX, MinY, MaxX, MaxY, LengthM, WidthM }
|
||||
- **struct TrackWire** { ID, Name, Description, AuthorID, Visibility, Scale, LengthM, WidthM, LaneWidthM, Bounds, Surface, Tags, Centerline, BestLapMs, BestLapHolder, CreatedMs, UpdatedMs, IsActive }
|
||||
- **struct TrackListRequest** { Scope, Tag }
|
||||
- **struct TrackGetRequest** { ID }
|
||||
- **struct TrackCreateRequest** { Track }
|
||||
- **struct TrackUpdateRequest** { ID, Patch }
|
||||
- **struct TrackPatch** { Name, Description, Visibility, Scale, LengthM, WidthM, LaneWidthM, Surface, Tags, Centerline }
|
||||
- **struct TrackDeleteRequest** { ID }
|
||||
- **struct TrackSnapshot** { GeneratedMs, Version, Tracks }
|
||||
- **struct TrackAck** { Ok, ID, Error, Track }
|
||||
- **struct MotorWire** { Kind, Class, KV, PowerW }
|
||||
- **struct BatteryWire** { VoltageV, CapacityMah, Cells, Chemistry }
|
||||
- **struct ChassisWire** { Model, Material, Printed, WheelbaseMm, TrackMm }
|
||||
- **struct CarWire** { ID, Name, OwnerID, Visibility, Scale, LengthMm, WidthMm, HeightMm, WeightG, Chassis, Motor, Battery, Drive, TopSpeedMs, ColorHex, AvatarURL, Active, TotalDistanceM, TotalRaces, TotalLaps, BestLapMs, CreatedMs, UpdatedMs, DeviceID }
|
||||
- **struct CarListRequest** { Scope, OwnerID }
|
||||
- **struct CarGetRequest** { ID }
|
||||
- **struct CarCreateRequest** { Car }
|
||||
- **struct CarUpdateRequest** { ID, Patch }
|
||||
- **struct CarPatch** { Name, Visibility, Scale, LengthMm, WidthMm, HeightMm, WeightG, Chassis, Motor, Battery, Drive, TopSpeedMs, ColorHex, AvatarURL, Active, DeviceID }
|
||||
- **struct CarDeleteRequest** { ID }
|
||||
- **struct CarSnapshot** { GeneratedMs, Version, Cars }
|
||||
- **struct CarAck** { Ok, ID, Error, Car }
|
||||
- **struct CatalogSummary** { TracksTotal, TracksSystem, TracksPublic, TracksPrivate, CarsTotal, CarsSystem, CarsPublic, CarsPrivate, CarsActive, TSMs }
|
||||
- **struct RaceListResponse** { Items, NextCursor, Count }
|
||||
- **struct RaceUpcomingItem** { Meta, QueueLen, PlanID, StartAtMs }
|
||||
- **struct RaceUpcomingResponse** { Items, Count }
|
||||
- **struct RaceQueueEntry** { DriverID, RaceID, PlanID, EnqueuedMs }
|
||||
- **struct RaceQueueJoinRequest** { DriverID, Limit }
|
||||
- **struct RaceQueueJoinResponse** { Joined, Skipped }
|
||||
- **struct RaceQueueListResponse** { Items, Count }
|
||||
- **struct RacePlan** { ID, Name, TrackID, MaxCars, Laps, TimeLimitS, StartAtMs, IntervalS, Count, Enabled, CreatedMs, UpdatedMs, NextFireMs, FiresDone }
|
||||
- **struct RacePlanCreateRequest** { ID, Name, TrackID, MaxCars, Laps, TimeLimitS, StartAtMs, IntervalS, Count, Enabled }
|
||||
- **struct RacePlanListResponse** { Items, NextCursor, Count }
|
||||
- **struct Driver** { ID, Nickname, Name, AvatarURL, ClanID, CreatedMs, UpdatedMs }
|
||||
- **struct DriverCreateRequest** { ID, Nickname, Name, AvatarURL, ClanID }
|
||||
- **struct DriverUpdateRequest** { Name, AvatarURL, ClanID }
|
||||
- **struct DriverListResponse** { Items, Count }
|
||||
- **struct Clan** { ID, Tag, Name, AvatarURL, CreatedMs, UpdatedMs }
|
||||
- **struct ClanCreateRequest** { ID, Tag, Name, AvatarURL }
|
||||
- **struct ClanUpdateRequest** { Name, AvatarURL }
|
||||
- **struct ClanListResponse** { Items, Count }
|
||||
- **struct StatsServer** { StartedMs, UptimeMs, CurrentClients, PeakClients, TotalConnections, TotalDisconnects, TotalRacesCreated, TotalRacesStarted, TotalRacesFinished, TotalLapsRecorded, TotalInputsRecv, TotalSnapshotsSent, SnapshotsDropped, AvgRTTMs }
|
||||
- **struct StatsDriver** { ID, Name, TotalRacesStarted, TotalRacesFinished, TotalLaps, BestLapMs, LastLapMs, TotalDistanceM, TotalPlaytimeMs, Wins, Podiums, LastSeenMs }
|
||||
- **struct StatsLap** { RaceID, DriverID, LapMs, Sector1Ms, Sector2Ms, Sector3Ms, Position, TSMs }
|
||||
- **struct StatsRaceResult** { RaceID, DriverID, FinishedAtMs, Position, TotalLaps, BestLapMs, TotalTimeMs, DNF }
|
||||
- **struct StatsSnapshot** { Server, Drivers, Laps, Results, TSMs }
|
||||
- **struct StatsRequest** { Scope, TargetID }
|
||||
- **struct RaceStanding** { Position, CarID, DriverID, DriverName, Lap, Sector, BestLapMs, LastLapMs, GapMs, DNF }
|
||||
- **struct RaceStandingsMsg** { RaceID, Tick, TSMs, Lap, Elapsed, Rows }
|
||||
- **struct LapRecordedMsg** { RaceID, DriverID, Lap, LapMs, Sector1Ms, Sector2Ms, Sector3Ms, TSMs, Position }
|
||||
- **struct RaceResultMsg** { RaceID, DriverID, Position, TotalLaps, BestLapMs, TotalTimeMs, DNF, FinishedAtMs }
|
||||
- **struct LeaderboardEntry** { DriverID, Nickname, Name, AvatarURL, ClanID, ClanTag, Points, BestPos, BestTimeMs, Rank }
|
||||
- **struct LeaderboardResponse** { Items, Total, Limit, Offset, CurrentDriver }
|
||||
- **struct TrackCalendarEntry** { ID, TrackID, StartAt, EndAt }
|
||||
- **struct TrackCalendarCreateRequest** { TrackID, StartAt, EndAt }
|
||||
- **struct TrackCalendarResponse** { Items }
|
||||
- **struct TrackCalendarLeaderboard** { TrackID, TrackName, StartAt, EndAt, Status, Podium, CurrentDriver }
|
||||
- **struct TrackCalendarLeaderboardResponse** { Items }
|
||||
|
||||
### Functions
|
||||
- func Encode(*Envelope) ([]byte, error)
|
||||
- func Decode([]byte) (*Envelope, error)
|
||||
|
||||
---
|
||||
|
||||
## Package `main` (`cmd/poc-server`)
|
||||
|
||||
HTTP handlers for the catalog (tracks + cars).
|
||||
|
||||
All HTTP routes live under /api/*:
|
||||
GET /api/tracks list tracks (optional ?scope=system|public|private&tag=)
|
||||
GET /api/tracks/{id} get a single track
|
||||
POST /api/tracks create a track
|
||||
PUT /api/tracks/{id} update a track
|
||||
DELETE /api/tracks/{id} delete a track
|
||||
GET /api/cars list cars (optional ?scope=...&owner_id=...)
|
||||
GET /api/cars/{id} get a single car
|
||||
POST /api/cars create a car
|
||||
PUT /api/cars/{id} update a car
|
||||
DELETE /api/cars/{id} delete a car
|
||||
GET /api/catalog combined snapshot + summary
|
||||
|
||||
WebSocket access is wired up directly in main.go's readPump switch.
|
||||
|
||||
### Structs
|
||||
- **struct Hub**
|
||||
- **struct UDPVideoService**
|
||||
- **struct WebRTCService**
|
||||
|
||||
### Functions
|
||||
- func NewHub(*slog.Logger) *Hub
|
||||
- func NewUDPVideoService(*slog.Logger, string, int) *UDPVideoService
|
||||
- func NewWebRTCService(*slog.Logger, *control.Engine, *lobby.Service, *UDPVideoService, *catalog.Service) *WebRTCService
|
||||
|
||||
### Methods
|
||||
- func (*catalogBroadcaster) Run()
|
||||
- func (*catalogBroadcaster) Stop()
|
||||
- func (*Hub) BroadcastSnapshot(transport.RaceSnapshot)
|
||||
- func (*statusRecorder) WriteHeader(int)
|
||||
- func (*statusRecorder) Hijack() (net.Conn, *bufio.ReadWriter, error)
|
||||
- func (*UDPVideoService) Start(context.Context, *sync.WaitGroup)
|
||||
- func (*UDPVideoService) SendControlPacket(uint8, []byte) error
|
||||
- func (*UDPVideoService) SendCommand(uint8, string) error
|
||||
- func (*UDPVideoService) StreamHandler() http.HandlerFunc
|
||||
- func (*UDPVideoService) ControlHandler() http.HandlerFunc
|
||||
- func (*WebRTCService) Start(context.Context, *sync.WaitGroup)
|
||||
- func (*WebRTCService) ConnectHandler() http.HandlerFunc
|
||||
- func (*WebRTCService) CloseSession(string)
|
||||
- func (*WebRTCService) CloseAll()
|
||||
|
||||
---
|
||||
|
||||
## Package `main` (`scripts/genseed`)
|
||||
|
||||
Package main contains the genseed utility. It is built into a standalone
|
||||
binary via `go build ./scripts/genseed` and is not part of the runtime.
|
||||
|
||||
Usage:
|
||||
|
||||
go run ./scripts/genseed seeds.json > 002_seed.sql
|
||||
|
||||
It reads the JSON dump produced by `DUMP_SEEDS=1 go test ./internal/catalog`
|
||||
and emits ON CONFLICT-safe INSERTs for the catalog tables.
|
||||
|
||||
---
|
||||
|
||||
## Package `main` (`scripts/genseed-json`)
|
||||
|
||||
Package main contains a small helper that prints the default seeds
|
||||
(5 F1 tracks + 5 F1 cars) as JSON to stdout. It is run as:
|
||||
|
||||
go run ./scripts/genseed-json > seeds.json
|
||||
|
||||
which is then fed into scripts/genseed to regenerate the SQL.
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user