From c1379f42ac722c39bfd1ee836725bf5880d499fb Mon Sep 17 00:00:00 2001 From: Maris Popens Date: Sun, 27 Sep 2026 09:16:06 +0300 Subject: [PATCH] chore: trim comments --- .github/workflows/auto-merge.yml | 3 +-- Dockerfile | 9 ++------- cache.go | 6 ++---- cmd/gentrackmaps/main.go | 15 ++++----------- internal/trackmap/trackmap.go | 19 ++++++------------- latest.go | 18 ++++++------------ main.go | 5 ++--- tyres.go | 11 ++++------- widgets/latest-session/f1_latest_session.yml | 9 +++------ widgets/tyre-usage/f1_tyre_usage.yml | 12 +++--------- 10 files changed, 33 insertions(+), 74 deletions(-) diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml index ef2b7dc..8b83f43 100644 --- a/.github/workflows/auto-merge.yml +++ b/.github/workflows/auto-merge.yml @@ -19,8 +19,7 @@ jobs: github.event.workflow_run.actor.login == 'dnb-robot[bot]') uses: drumandbytes/reusable-actions/.github/workflows/auto-merge.yml@v1 with: - # dnb-robot opens release-please PRs (patch-only) and track-map PRs, which - # never touch the manifest and so always count as patch. + # dnb-robot's release-please and track-map PRs never touch the manifest, so always patch. patch-only-authors: '["dnb-robot[bot]"]' # A GITHUB_TOKEN merge triggers no workflows: no release, no publish.yml run. use-app-token-for-merge: true diff --git a/Dockerfile b/Dockerfile index 956c82c..7ac9366 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,10 +10,7 @@ COPY . . RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-s -w" -o paddock-api . RUN mkdir /data -# scratch has no CA bundle and no /usr/share/zoneinfo of its own - the CA -# bundle is copied in below, and the binary embeds tzdata itself (see the -# time/tzdata blank import in main.go) since there's nowhere on this image to -# read it from at runtime. +# scratch has no CA bundle or zoneinfo: CAs copied below, tzdata embedded (main.go). FROM scratch COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt @@ -21,9 +18,7 @@ WORKDIR /app COPY --from=builder /build/paddock-api /app/paddock-api COPY static ./static -# Durable cache for data that never changes once it exists (finished sessions). -# Owned by the non-root user so a volume mounted here is writable; without a -# volume it just lives in the container's writable layer. +# Durable cache for finished sessions; non-root-owned so a mounted volume is writable. COPY --from=builder --chown=65532:65532 /data /data ENV CACHE_DIR=/data diff --git a/cache.go b/cache.go index 27dd2b8..48e7075 100644 --- a/cache.go +++ b/cache.go @@ -48,10 +48,8 @@ func (c *cacheStore) set(key string, value any, expiresAt time.Time) { c.mu.Unlock() } -// getDurable/setDurable are for data that never changes once it exists (a -// finished session's results). Kept in memory like any entry and, when a -// directory is configured, mirrored to disk so it survives a restart - the -// upstream (OpenF1) can be unreachable for long stretches around sessions. +// getDurable/setDurable: data that never changes (finished sessions), mirrored +// to disk when a dir is set, since OpenF1 can be unreachable for long stretches. func (c *cacheStore) getDurable(key string, now time.Time) (any, bool) { if value, ok := c.get(key, now); ok { return value, true diff --git a/cmd/gentrackmaps/main.go b/cmd/gentrackmaps/main.go index 6335162..2652e0c 100644 --- a/cmd/gentrackmaps/main.go +++ b/cmd/gentrackmaps/main.go @@ -1,11 +1,6 @@ -// Command gentrackmaps pre-renders every known circuit's track-outline SVG -// into static/track_maps/.svg from bacinger/f1-circuits' static -// GeoJSON dataset, so the API's /f1/next_map handler can serve a static file -// on the request path with no live lookup at all. -// -// Run via `go run ./cmd/gentrackmaps` (or the regenerate-track-maps.yml -// workflow, monthly). Always renders at the reference colour #e5d486 - -// map.go swaps that for the request's configured TRACK_COLOUR at serve time. +// Command gentrackmaps pre-renders static/track_maps/.svg from +// bacinger/f1-circuits so /f1/next_map serves a static file. Renders in +// #e5d486; map.go swaps in TRACK_COLOUR at serve time. package main import ( @@ -34,9 +29,7 @@ func main() { os.Exit(1) } - // One circuit per goroutine - raw.githubusercontent.com is a static CDN - // built for exactly this, and 26 fetches is nowhere near anything it'd - // blink at. + // one goroutine per circuit; 26 fetches is nothing for raw.githubusercontent.com client := &http.Client{Timeout: 15 * time.Second} results := make(chan result, len(trackmap.CircuitGeometryIDs)) var wg sync.WaitGroup diff --git a/internal/trackmap/trackmap.go b/internal/trackmap/trackmap.go index c146e0d..ffb0dab 100644 --- a/internal/trackmap/trackmap.go +++ b/internal/trackmap/trackmap.go @@ -1,6 +1,4 @@ -// Package trackmap fetches circuit outline geometry from bacinger/f1-circuits -// and renders it as a track-map SVG. Shared by the API's live /f1/next_map -// fallback (main.go) and the offline pre-renderer (cmd/gentrackmaps). +// Package trackmap fetches circuit outlines from bacinger/f1-circuits and renders track-map SVGs. package trackmap import ( @@ -16,10 +14,8 @@ import ( const DefaultGeometryBase = "https://raw.githubusercontent.com/bacinger/f1-circuits/master/circuits" -// CircuitGeometryIDs maps our circuitId (matches the schedule's circuit ids -// and the static SVG filenames) to bacinger/f1-circuits' own -// - id. Update when a new circuit joins the -// calendar. +// CircuitGeometryIDs maps our circuitId to bacinger's - id. +// Add new circuits here when they join the calendar. var CircuitGeometryIDs = map[string]string{ "albert_park": "au-1953", "shanghai": "cn-2004", "suzuka": "jp-1962", "bahrain": "bh-2002", "jeddah": "sa-2021", "miami": "us-2022", "imola": "it-1953", "monaco": "mc-1929", @@ -30,8 +26,7 @@ var CircuitGeometryIDs = map[string]string{ "losail": "qa-2004", "yas_marina": "ae-2009", } -// FetchGeometry returns the [lon, lat] outline and circuit name for the -// given geojson id (a CircuitGeometryIDs value). +// FetchGeometry returns the [lon, lat] outline and name for a CircuitGeometryIDs value. func FetchGeometry(client *http.Client, base, geometryID string) ([][]float64, string, error) { response, err := client.Get(fmt.Sprintf("%s/%s.geojson", base, geometryID)) if err != nil { @@ -59,10 +54,8 @@ func FetchGeometry(client *http.Client, base, geometryID string) ([][]float64, s return geo.Features[0].Geometry.Coordinates, geo.Features[0].Properties.Name, nil } -// RenderSVG projects [lon, lat] coordinates to local meters (equirectangular - -// good enough for a track a few km across) and draws them as a track-outline -// SVG: a black outline with the given colour on top, sized to a 300px-wide -// dashboard tile. +// RenderSVG draws a 300px-wide track outline; equirectangular projection is +// fine at a few km. func RenderSVG(coordinates [][]float64, name, colour string) ([]byte, error) { if len(coordinates) == 0 { return nil, errors.New("No track coordinates to draw") diff --git a/latest.go b/latest.go index f9ff48d..ee715f3 100644 --- a/latest.go +++ b/latest.go @@ -11,16 +11,14 @@ import ( "github.com/labstack/echo/v4" ) -// raceWindow is how long after its start a race is still treated as running - -// F1 races are capped at 3h including stoppages, but almost all finish inside 2. +// raceWindow: races are capped at 3h incl. stoppages, almost all finish inside 2. const raceWindow = 2 * time.Hour var sessionLabels = map[string]string{"fp1": "Free Practice 1", "fp2": "Free Practice 2", "fp3": "Free Practice 3", "sprintQualy": "Sprint Qualifying", "sprintRace": "Sprint Race", "qualy": "Qualifying", "race": "Race"} var openF1SessionNames = map[string]string{"fp1": "Practice 1", "fp2": "Practice 2", "fp3": "Practice 3", "sprintQualy": "Sprint Qualifying", "sprintRace": "Sprint", "qualy": "Qualifying", "race": "Race"} -// sessionWindows is how long after its scheduled start a session counts as -// still running, so it isn't picked as the "latest" one before it's over. +// sessionWindows keep a running session from being picked as "latest". var sessionWindows = map[string]time.Duration{"fp1": time.Hour, "fp2": time.Hour, "fp3": time.Hour, "sprintQualy": 45 * time.Minute, "sprintRace": 45 * time.Minute, "qualy": time.Hour} func matchOpenF1Session(sessions []openF1Session, key string, at time.Time) *openF1Session { @@ -89,8 +87,7 @@ func (a *app) latestSession(c echo.Context) error { latest := sessions[0] result := a.sessionResponse(year, latest, []any{}) ttl, have := 2*time.Minute, false - // A finished session's classification never changes, so it's kept for - // good - OpenF1's free tier locks out all access while any session is live. + // cached for good: OpenF1's free tier locks out all access while any session is live cacheKey := sessionResultsKey(year, latest) if cached, ok := a.cache.getDurable(cacheKey, now); ok { result["results"], ttl, have = cached, 5*time.Minute, true @@ -104,8 +101,7 @@ func (a *app) latestSession(c echo.Context) error { } } if !have { - // Latest results aren't available yet (typically the lockout right after a - // session): show the newest earlier session we still hold, and say what's pending. + // no latest results yet (post-session lockout): show the newest one we hold for _, s := range sessions[1:] { if cached, ok := a.cache.getDurable(sessionResultsKey(year, s), now); ok { fallback := a.sessionResponse(year, s, cached) @@ -204,8 +200,7 @@ func sessionTimeCell(duration, gap json.RawMessage, dnf, dns, dsq, leader bool) return "" } -// lastNumber reads a JSON number, or the last non-null entry of an array of -// them (OpenF1 returns per-phase values for qualifying, e.g. [Q1, Q2, Q3]). +// lastNumber reads a number or the last non-null array entry (qualifying is [Q1, Q2, Q3]). func lastNumber(raw json.RawMessage) (float64, bool) { if len(raw) == 0 || string(raw) == "null" { return 0, false @@ -235,8 +230,7 @@ func formatSessionDuration(seconds float64) string { return fmt.Sprintf("%d:%02d.%03d", m, s, ms) } -// shortTeamName maps OpenF1's team names onto the short names the rest of -// the API uses (from Ergast constructor ids), so tiles read consistently. +// shortTeamName maps OpenF1 team names onto the API's Ergast-derived short names. func shortTeamName(name string) string { switch name { case "Red Bull Racing": diff --git a/main.go b/main.go index d329c7e..756d8a3 100644 --- a/main.go +++ b/main.go @@ -97,9 +97,8 @@ func (a *app) fetchJSON(url string, target any) error { return decoder.Decode(target) } -// fetchOpenF1 spaces out calls to OpenF1, whose free tier allows 3 requests -// per second - the tyre and latest-session widgets each need several per -// refresh and load together. +// fetchOpenF1 spaces calls out: OpenF1's free tier allows 3 req/s and widgets +// load together. func (a *app) fetchOpenF1(url string, target any) error { a.openF1Mu.Lock() if wait := time.Until(a.openF1Next); wait > 0 { diff --git a/tyres.go b/tyres.go index 35c62a4..a8de464 100644 --- a/tyres.go +++ b/tyres.go @@ -17,9 +17,8 @@ type openF1Session struct { End string `json:"date_end"` } -// currentWeekend is the latest race weekend whose first session has started - -// it stays current until the next weekend's first session starts, so a -// finished race's tyre usage keeps showing through the week. +// currentWeekend is the latest weekend whose first session has started; it +// stays current until the next one's does, so tyre usage shows all week. func currentWeekend(races []race, now time.Time) *race { var current *race for i := range races { @@ -61,10 +60,8 @@ func (a *app) tyreUsage(c echo.Context) error { if at.IsZero() || at.After(now) { continue } - // A finished session's stints never change, so once fetched they're - // kept for good - OpenF1's free tier locks out all access (even past - // sessions) while any session is live, which would otherwise blank - // data we already had. + // stints never change once finished; keep them, since OpenF1 locks out + // even past sessions while any session is live sessionCacheKey := fmt.Sprintf("tyre_session:%d:%d:%s", year, selected.Round, key) if cached, ok := a.cache.getDurable(sessionCacheKey, now); ok { sessions[key] = cached diff --git a/widgets/latest-session/f1_latest_session.yml b/widgets/latest-session/f1_latest_session.yml index 431b3bb..83f3e43 100644 --- a/widgets/latest-session/f1_latest_session.yml +++ b/widgets/latest-session/f1_latest_session.yml @@ -2,12 +2,9 @@ title: Latest Session cache: 5m url: http://${F1_API_URL}:4463/f1/latest_session/ - # The most recently finished non-race session of the current weekend - # (practice, sprint qualifying, qualifying, sprint) - the Grand Prix itself - # is Last Race Results' job. Practice/qualifying results only exist on - # OpenF1, which locks out free access while any session is live, so a - # just-finished session can take a while to show up - until it does, the - # previous session's results are shown with a note. + # Latest finished non-race session (the GP is Last Race Results' job). OpenF1 + # locks out free access while a session is live, so until the new one shows up + # the previous session's results are shown with a note. template: | {{ $session := .JSON.String "session" }} {{ $rows := .JSON.Array "results" }} diff --git a/widgets/tyre-usage/f1_tyre_usage.yml b/widgets/tyre-usage/f1_tyre_usage.yml index c8c9230..eac7da4 100644 --- a/widgets/tyre-usage/f1_tyre_usage.yml +++ b/widgets/tyre-usage/f1_tyre_usage.yml @@ -2,15 +2,9 @@ title: Tyre Usage cache: 5m url: http://${F1_API_URL}:4463/f1/tyre_usage/ - # Usage only, not allocation: there's no structured source anywhere for a - # driver's pre-weekend tyre-compound allocation, so this only ever reports - # what OpenF1 recorded being used stint-by-stint once a session's actually - # run. Each session key is only present once its scheduled time has - # passed; a still-null key's sessions.Array returns an empty slice, so - # between race weekends - when every session is still null - this shows a - # deliberate "no data yet" message instead of a blank box under the title - # (Glance itself always renders the widget's title/container regardless of - # template output, so there's no way to hide the whole tile from in here). + # Usage only: there's no source for pre-weekend allocation. Session keys are null + # until scheduled, so between weekends this prints an explicit "no data yet" + # (Glance renders the title regardless, so the tile can't be hidden). template: |
{{ $fp1 := .JSON.Array "sessions.fp1" }}