mirror of
https://github.com/IS1DI/x0gp.git
synced 2026-07-16 20:47:55 +00:00
Add gh workflow for release, new fields in podium and versioning
This commit is contained in:
@@ -18,10 +18,13 @@ import (
|
||||
// Position (1..3). DriverID/Name are denormalised from the future
|
||||
// drivers table; TotalTimeMs is the driver's total race time.
|
||||
type PodiumEntry struct {
|
||||
Position int `json:"position" example:"1"`
|
||||
DriverID string `json:"driver_id" example:"driver-alice"`
|
||||
Name string `json:"name" example:"driver-alice"`
|
||||
TotalTimeMs int64 `json:"total_time_ms" example:"123456"`
|
||||
Position int `json:"position" example:"1"`
|
||||
DriverID string `json:"driver_id" example:"driver-alice"`
|
||||
Name string `json:"name" example:"driver-alice"`
|
||||
TotalTimeMs int64 `json:"total_time_ms" example:"123456"`
|
||||
Nickname string `json:"nickname" example:"driver-alice"`
|
||||
AvatarUrl string `json:"avatar_url"`
|
||||
ClanID string `json:"clan_id" example:"clan-bob"`
|
||||
}
|
||||
|
||||
// DriverResult is the per-driver outcome of a race. Stored in
|
||||
@@ -31,9 +34,13 @@ type PodiumEntry struct {
|
||||
// fields are derived from this row set on read.
|
||||
type DriverResult struct {
|
||||
DriverID string
|
||||
Name string
|
||||
TotalTimeMs int64
|
||||
BestLapMs int64
|
||||
Position *int // nil for DNF
|
||||
Position *int // nil for DNF
|
||||
Nickname string `json:"nickname" example:"driver-alice"`
|
||||
AvatarUrl string `json:"avatar_url"`
|
||||
ClanID string `json:"clan_id" example:"clan-bob"`
|
||||
}
|
||||
|
||||
// FinishedRace is the on-disk shape of a completed race. Mirrors the
|
||||
@@ -88,10 +95,10 @@ type RacePlan struct {
|
||||
|
||||
// QueueEntry is a single (driver, race) subscription.
|
||||
type QueueEntry struct {
|
||||
DriverID string
|
||||
RaceID string
|
||||
PlanID string
|
||||
EnqueuedMs int64
|
||||
DriverID string
|
||||
RaceID string
|
||||
PlanID string
|
||||
EnqueuedMs int64
|
||||
}
|
||||
|
||||
// PgStore is the Postgres-backed half of the races package.
|
||||
@@ -587,8 +594,8 @@ func (s *PgStore) scanFinished(ctx context.Context, rows pgx.Rows) ([]FinishedRa
|
||||
// and derives the Winner* and Podium fields.
|
||||
func (s *PgStore) hydrateFinished(ctx context.Context, r *FinishedRace) error {
|
||||
rows, err := s.pool.Query(ctx, `
|
||||
SELECT driver_id, total_time_ms, best_lap_ms, position
|
||||
FROM race_drivers
|
||||
SELECT rd.driver_id, rd.total_time_ms, rd.best_lap_ms, rd.position, d.name, d.nickname, d.avatar_url, d.clan_id
|
||||
FROM race_drivers rd left join drivers d on rd.driver_id = d.id
|
||||
WHERE race_id = $1
|
||||
ORDER BY slot ASC, joined_ms ASC`, r.ID)
|
||||
if err != nil {
|
||||
@@ -602,10 +609,28 @@ func (s *PgStore) hydrateFinished(ctx context.Context, r *FinishedRace) error {
|
||||
for rows.Next() {
|
||||
var dr DriverResult
|
||||
var pos *int
|
||||
if err := rows.Scan(&dr.DriverID, &dr.TotalTimeMs, &dr.BestLapMs, &pos); err != nil {
|
||||
var name, nick, avatar, clanID *string
|
||||
if err := rows.Scan(
|
||||
&dr.DriverID, &dr.TotalTimeMs, &dr.BestLapMs, &pos,
|
||||
&name, &nick, &avatar, &clanID,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
dr.Position = pos
|
||||
if name != nil {
|
||||
dr.Name = *name
|
||||
} else {
|
||||
dr.Name = dr.DriverID
|
||||
}
|
||||
if nick != nil {
|
||||
dr.Nickname = *nick
|
||||
}
|
||||
if avatar != nil {
|
||||
dr.AvatarUrl = *avatar
|
||||
}
|
||||
if clanID != nil {
|
||||
dr.ClanID = *clanID
|
||||
}
|
||||
r.Results = append(r.Results, dr)
|
||||
r.DriverIDs = append(r.DriverIDs, dr.DriverID)
|
||||
}
|
||||
@@ -621,7 +646,7 @@ func (s *PgStore) hydrateFinished(ctx context.Context, r *FinishedRace) error {
|
||||
if bestTotal == -1 || dr.TotalTimeMs < bestTotal {
|
||||
bestTotal = dr.TotalTimeMs
|
||||
r.WinnerDriverID = dr.DriverID
|
||||
r.WinnerName = dr.DriverID
|
||||
r.WinnerName = dr.Name
|
||||
}
|
||||
if dr.BestLapMs > 0 && (r.BestLapMs == 0 || dr.BestLapMs < r.BestLapMs) {
|
||||
r.BestLapMs = dr.BestLapMs
|
||||
@@ -629,16 +654,28 @@ func (s *PgStore) hydrateFinished(ctx context.Context, r *FinishedRace) error {
|
||||
}
|
||||
// Derive podium: top-3 drivers by total_time_ms (> 0) ASC.
|
||||
type row struct {
|
||||
id string
|
||||
t int64
|
||||
best int64
|
||||
id string
|
||||
t int64
|
||||
best int64
|
||||
name string
|
||||
nick string
|
||||
avatar string
|
||||
clanID string
|
||||
}
|
||||
var sorted []row
|
||||
for _, dr := range r.Results {
|
||||
if dr.TotalTimeMs <= 0 {
|
||||
continue
|
||||
}
|
||||
sorted = append(sorted, row{dr.DriverID, dr.TotalTimeMs, dr.BestLapMs})
|
||||
sorted = append(sorted, row{
|
||||
id: dr.DriverID,
|
||||
t: dr.TotalTimeMs,
|
||||
best: dr.BestLapMs,
|
||||
name: dr.Name,
|
||||
nick: dr.Nickname,
|
||||
avatar: dr.AvatarUrl,
|
||||
clanID: dr.ClanID,
|
||||
})
|
||||
}
|
||||
for i := 1; i < len(sorted); i++ {
|
||||
for j := i; j > 0 && sorted[j-1].t > sorted[j].t; j-- {
|
||||
@@ -649,8 +686,11 @@ func (s *PgStore) hydrateFinished(ctx context.Context, r *FinishedRace) error {
|
||||
r.Podium = append(r.Podium, PodiumEntry{
|
||||
Position: i + 1,
|
||||
DriverID: sorted[i].id,
|
||||
Name: sorted[i].id,
|
||||
Name: sorted[i].name,
|
||||
TotalTimeMs: sorted[i].t,
|
||||
Nickname: sorted[i].nick,
|
||||
AvatarUrl: sorted[i].avatar,
|
||||
ClanID: sorted[i].clanID,
|
||||
})
|
||||
}
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user