Skip to content

fix: **Keep the starting grid correct when the feed duplicates a grid position** - #811

Merged
Nicxe merged 3 commits into
Nicxe:devfrom
nicandris:fix/duplicate-gridpos
Oct 10, 2026
Merged

Nicxe merged 3 commits into
Nicxe:devfrom
nicandris:fix/duplicate-gridpos

Conversation

@nicandris

Copy link
Copy Markdown
Contributor

Description

The live TimingAppData feed can send the same GridPos for two cars. Before the 2026 Singapore Sprint (snapshot read 2026-10-10 ~10:45 CEST, SessionStatus: Inactive), car 1 (NOR) lined up 5th but was sent GridPos "1":

{"1":  {"RacingNumber": "1",  "Line": 5, "GridPos": "1"}}
{"3":  {"RacingNumber": "3",  "Line": 1, "GridPos": "1"}}

The other 20 cars had GridPos == Line. The starting-grid sensor trusted GridPos, so the confirmed grid showed NOR P1 (Δ -4) next to VER P1, and no P5. The official F1 app showed the correct order.

StartingGridCoordinator now stores each car's Line next to its GridPos. A car whose GridPos is shared by another car falls back to that Line, but only when no other car's GridPos already claims the slot.

Line is recorded only while the session status is Inactive, and is frozen once the session starts. After the start it is the running order, and a reconnect snapshot or a cold start mid-race would otherwise reshuffle the grid. If no pre-start Line was seen, the grid stays as it is today.

Related issue

No issue filed; observed live during the 2026 Singapore Sprint weekend.

Type of change

  • 🐛 Bug fix (corrects existing behavior without breaking anything)

How has this been tested?

  • New test_duplicate_gridpos_falls_back_to_pre_start_line. It covers the duplicate fallback, a GridPos-only delta after the start, and a mid-race reconnect snapshot with new Lines. It fails on dev.
  • New test_duplicate_gridpos_ignores_line_without_pre_start_status, for a cold start mid-race with no session status.
  • scripts/run_ci_tests.py: 1676 passed, 6 deselected, line coverage 96.5%.
  • Checked every archived 2026 Race and Sprint (21 sessions) in the F1 live-timing archive. In each, every car's last pre-start Line equals its GridPos, including the 15 sessions where the grid differs from qualifying (penalties, back-of-grid starts). No archived session had a duplicate GridPos.
  • Ran the coordinator on the full real feed snapshot (SessionStatus, SessionInfo, then TimingAppData): it produces positions 1–22 with NOR at P5.

Checklist

  • I have read CONTRIBUTING.md and am targeting the correct branch
  • Code is formatted and passes lint check (ruff format and ruff check)
  • Tests have been added or updated and pass locally
  • No merge conflicts with the target branch

… position**

The live TimingAppData feed for the 2026 Singapore Sprint sent car 1
GridPos 1 while it lined up 5th, so the confirmed grid showed two P1s
and no P5. When a GridPos is shared, use the car's pre-start Line if
that slot is otherwise empty. Line is only recorded while the session
is Inactive, since afterwards it is the running order.
@Nicxe

Nicxe commented Oct 10, 2026

Copy link
Copy Markdown
Owner

I can reproduce the reported duplicate grid position, but the fix does not handle the actual sequence in the Singapore Sprint TimingAppData stream.

Car 1 first receives GridPos: "1", Line: 1. The later correction to Line: 5 arrives without GridPos, so _on_timing_app_data skips it. When car 3 then receives GridPos: "1", Line: 1, the coordinator still has Line: 1 for car 1. Replaying those pre-start messages through the PR logic leaves two cars at P1 and none at P5.

Could you retain pre-start Line updates even when GridPos is absent, and add a regression test that sends these messages separately in their original order? The current test combines Line: 5 and GridPos: "1" in one message, which does not cover the observed failure.

@Nicxe

Nicxe commented Oct 10, 2026

Copy link
Copy Markdown
Owner

TimingAppData.txt

The Singapore Sprint feed moved car 1 to Line 5 in a delta without
GridPos, which was skipped, so the duplicate fallback still saw Line 1.
@nicandris

Copy link
Copy Markdown
Contributor Author

Thanks a lot for digging into the raw stream and attaching it. You're right, and that was my miss. I had diagnosed the bug from a REST snapshot taken before the session. In a snapshot each car's Line and GridPos are already merged, so car 1 showed up as {"Line": 5, "GridPos": "1"}. I wrote both the fix and the test against that merged shape. My archive check compared final pre-start state too, so it never replayed the deltas in their real order. In the live stream, the Line: 5 correction comes as its own delta without GridPos, and _on_timing_app_data skipped it.

The new commit keeps pre-start Line updates even when GridPos is missing: the car keeps its known GridPos and only its Line is updated. test_duplicate_gridpos_uses_line_correction_without_gridpos sends the messages separately in the original order (car 1 on pole, then Line: 5 alone, then car 3 with GridPos: "1"). It fails on the previous commit. I also replayed your TimingAppData.txt through the coordinator. Before the change it gives two cars at P1 and none at P5; after it, P1–P22 with car 1 at P5. The full test suite passes.

@Nicxe

Nicxe commented Oct 10, 2026

Copy link
Copy Markdown
Owner

Thank you for you contribution

@Nicxe
Nicxe merged commit ba9d9a2 into Nicxe:dev Oct 10, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants