Skip to content

fix: show the crossing animation only on racing pages - #132

Merged
TheAngryRaven merged 1 commit into
BETAfrom
claude/crossing-overlay-race-pages
Aug 5, 2026
Merged

fix: show the crossing animation only on racing pages#132
TheAngryRaven merged 1 commit into
BETAfrom
claude/crossing-overlay-race-pages

Conversation

@TheAngryRaven

Copy link
Copy Markdown
Owner

Summary

Reported from the bench: setting a course-creator point while parked near an existing timing line showed the crossing flags over the creator screen.

The overlay was gated by a blocklist — six pages it must not draw over — which means it drew over everything else by default, and that list never grew as pages were added:

if (currentPage != GPS_STATS &&
    currentPage != GPS_DEBUG &&
    currentPage != LOGGING_STOP &&
    currentPage != LOGGING_STOP_CONFIRM &&
    currentPage != PAGE_INTERNAL_FAULT &&
    currentPage != PAGE_INTERNAL_WARNING &&
    isCrossing && !inEndurance) { displayCrossing(); ... }

So the camera pages, the replay browser, the transfer menus, the main menu and (newest) the course creator all inherited it. This is not a rare trigger either: the crossing zone reads true while stationary inside it, which is exactly the state of someone standing at a timing line using the device.

Inverted to a positive test. The running rotation is a contiguous id block (GPS_DEBUGLOGGING_STOP, see BirdsEye.ino), so "is this a racing page" is a range check:

const bool onRacingPage = (currentPage > GPS_STATS && currentPage < LOGGING_STOP);

The two diagnostic pages at the bottom and the stop-logging page at the top stay excluded exactly as before; everything outside the block — negative menu ids, the 90+ confirm/warning/fault pages, the 900+ boot pages — is now excluded by construction rather than by remembering to list it. Strictly more restrictive than the old condition on every input, so no racing page loses the animation.

Type of change

  • Bug fix (no user-visible behavior change beyond the fix)
  • New feature / Refactor / Tests only / CI / Breaking change

How it was verified

  • Host unit tests pass — 297 cases / 4269 assertions
  • Simulator: all 6 ctest targets pass
  • clang-tidy clean — not run locally (CI covers it)
  • Compiles for the XIAO nRF52840 Sense — not verified locally, no arduino-cli here
  • Tested on real hardware — not yet; this is the fix for a bug found on hardware

Checklist

  • CHANGELOG.md updated under [Unreleased]
  • ARCHITECTURE.md / CLAUDE.md — no interface change; the overlay's behaviour is described only by the code comment, which is rewritten
  • New testable logic has a matching test — with the caveat below, stated plainly
  • Branch is focused — one commit

Notes for reviewers

Read this before trusting the new fixture. main_menu_parked_on_line parks on the OKC start/finish line with the track detected and locks that the menu still renders as a menu (its hash is identical to main_menu_race). It is not a regression test for this bug, and the comment in the fixture says so.

I tried to make it one and it doesn't work: reaching a true crossing flag needs an armed timer, and the sim's bundled OKC track ships eight courses, so CourseDetector never locks one without driving a real lap. I confirmed this by restoring the old blocklist and re-running — the fixture does not budge. Shipping it while implying it covers the bug would repeat the exact failure mode we just hit in the web app, where a test asserted the broken behaviour and thereby protected it.

So the gate is argued from the page-id ranges rather than proven by test. The argument is small enough to check by hand: every id the old condition admitted and the new one rejects is a non-racing page, and no id in (GPS_STATS, LOGGING_STOP) changed status.

A real regression test wants a single-course track in the sim assets so detection locks immediately, or a hook to arm the timer directly. Worth doing, bigger than this fix.

Related issues

Third bug from the same bench session, alongside #131 (auto-race hijacking the menu) and the web-app sync/render fixes. Found via the course creator in #128 but entirely pre-existing, which is why it targets BETA on its own.


Generated by Claude Code

@TheAngryRaven
TheAngryRaven force-pushed the claude/crossing-overlay-race-pages branch from 7112d60 to 2fb961d Compare August 5, 2026 00:25
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

Coverage — host-testable units

📂 Overall coverage

Metric Coverage
Lines 🟢 1166/1188 (98.1%)
Functions 🟢 123/123 (100.0%)
Branches 🟡 862/966 (89.2%)

📄 File coverage

File Lines Functions Branches
BirdsEye/camera_fsm.cpp 🟢 222/230 (96.5%) 🟢 20/20 (100.0%) 🟡 126/144 (87.5%)
BirdsEye/course_creator.cpp 🟢 209/217 (96.3%) 🟢 21/21 (100.0%) 🟡 114/131 (87.0%)
BirdsEye/crc32.cpp 🟢 30/30 (100.0%) 🟢 4/4 (100.0%) 🟢 24/24 (100.0%)
BirdsEye/crossing_pattern.cpp 🟢 15/15 (100.0%) 🟢 1/1 (100.0%) 🟢 12/12 (100.0%)
BirdsEye/dovex_header.cpp 🟢 106/107 (99.1%) 🟢 7/7 (100.0%) 🔴 62/88 (70.5%)
BirdsEye/filename_validator.cpp 🟢 14/14 (100.0%) 🟢 1/1 (100.0%) 🟢 30/30 (100.0%)
BirdsEye/gps_stats.cpp 🟢 25/25 (100.0%) 🟢 3/3 (100.0%) 🟢 8/8 (100.0%)
BirdsEye/gps_status_page.cpp 🟢 29/29 (100.0%) 🟢 4/4 (100.0%) 🟢 28/28 (100.0%)
BirdsEye/gps_time.cpp 🟢 45/45 (100.0%) 🟢 6/6 (100.0%) 🟢 30/32 (93.8%)
BirdsEye/gps_validation.cpp 🟢 24/24 (100.0%) 🟢 2/2 (100.0%) 🟢 66/66 (100.0%)
BirdsEye/haversine.cpp 🟢 8/8 (100.0%) 🟢 1/1 (100.0%) ⚫ 0/0 (0.0%)
BirdsEye/insta360_protocol.cpp 🟢 140/140 (100.0%) 🟢 16/16 (100.0%) 🟡 86/98 (87.8%)
BirdsEye/lap_format.cpp 🟢 18/18 (100.0%) 🟢 1/1 (100.0%) 🟢 9/9 (100.0%)
BirdsEye/sat_bars.cpp 🟢 33/33 (100.0%) 🟢 2/2 (100.0%) 🟢 51/54 (94.4%)
BirdsEye/sd_access_policy.cpp 🟢 9/9 (100.0%) 🟢 3/3 (100.0%) 🟢 18/18 (100.0%)
BirdsEye/sd_format_page.cpp 🟢 25/25 (100.0%) 🟢 3/3 (100.0%) 🟢 25/26 (96.2%)
BirdsEye/sensoregg_protocol.cpp 🟢 44/45 (97.8%) 🟢 7/7 (100.0%) 🟢 33/34 (97.1%)
BirdsEye/sprint_select.cpp 🟢 25/25 (100.0%) 🟢 4/4 (100.0%) 🟢 46/48 (95.8%)
BirdsEye/tach_filter.cpp 🟢 15/15 (100.0%) 🟢 3/3 (100.0%) 🟡 7/8 (87.5%)
BirdsEye/track_json.cpp 🟢 116/120 (96.7%) 🟢 12/12 (100.0%) 🟡 67/88 (76.1%)
BirdsEye/wake_cause.cpp 🟢 14/14 (100.0%) 🟢 2/2 (100.0%) 🟢 20/20 (100.0%)

Reported from the bench: setting a course-creator point while parked near
an existing timing line showed the crossing flags over the creator screen.

The overlay was gated by a BLOCKLIST — six pages it must not draw over —
which meant it drew over everything else by default. That list never grew
as pages were added, so the camera pages, the replay browser, the transfer
menus, the main menu and (newest) the course creator all inherited it. And
the trigger is not rare: the crossing zone reads true while STATIONARY
inside it, which is precisely the state of someone standing at a timing
line using the device.

Inverted to a positive test. The running rotation is a contiguous id block,
so "is this a racing page" is a range check; the two diagnostic pages at the
bottom and the stop-logging page at the top stay excluded exactly as before,
and everything outside the block — negative menu ids, the 90+
confirm/warning/fault pages, the 900+ boot pages — is now excluded by
construction rather than by remembering to list it. Strictly more
restrictive than the old condition on every input.

The new golden fixture parks on the OKC start/finish line with the track
detected and locks that the menu still renders as a menu. It is NOT a
regression test for this bug and says so: a true crossing flag needs an
ARMED timer, and OKC ships eight courses so CourseDetector never locks one
without driving a real lap. Confirmed by restoring the old blocklist — the
fixture does not budge. The gate itself is argued from the page-id ranges.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ESkRRtF4vRrANPL6huSgmD
@TheAngryRaven
TheAngryRaven force-pushed the claude/crossing-overlay-race-pages branch from 2fb961d to e8d9a5b Compare August 5, 2026 04:34
@TheAngryRaven
TheAngryRaven merged commit 9ae6d46 into BETA Aug 5, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants