Skip to content

Add live football detail with animated gridiron (NFL, NCAAF); unify detail options - #236

Open
gerber55555 wants to merge 7 commits into
dathbe:developmentfrom
gerber55555:feature/football-live-detail
Open

Add live football detail with animated gridiron (NFL, NCAAF); unify detail options#236
gerber55555 wants to merge 7 commits into
dathbe:developmentfrom
gerber55555:feature/football-live-detail

Conversation

@gerber55555

Copy link
Copy Markdown

What this adds

Live-game detail for football (NFL, NCAAF), following the pattern of the baseball detail feature:

  • Down & distance and field position in a compact row aligned with the timeout indicators; the game clock takes the center row at score size
  • Animated gridiron graphic: ball at the current spot (parsed from ESPN's possessionText in the provider, validated against yardLine), yellow first-down line, end zones, 10-yard hash marks
  • Play animation: on each new play the ball slides (~1s) from the previous spot to the new one with a fading green/red trail sized to the yards gained or lost; the first-down marker holds the old line-to-gain until the ball has crossed it. Turnovers slide without a trail (drive direction reverses)
  • Touchdowns: the ball slides across the goal line into the end zone and stays parked there through the PAT until the kickoff spot arrives
  • Last play description below the field (static, ellipsis-truncated), possession indicator under the possessing team's logo, timeouts remaining under each score, red-zone accents
  • Full grayscale when colored: false — every field color is gated behind .wrapper.colored, matching the baseball convention
Live play live
Gain trail trail
Red zone redzone
Touchdown td
colored: false mono

Unified config options

showDetail, detailInterval, detailViewOverride now control live detail for both baseball and football. The baseball-specific options (showBaseballDetail, baseballDetailInterval, baseballDetailViewOverride) are deprecated but still work — start() maps them onto the unified options, so existing configs are unaffected. They are removed from the README table. The baseball e2e scenarios intentionally keep the deprecated options so the suite exercises the mapping.

The baseball fast-poll mechanism was generalized to a data-driven per-sport structure (also fixes a hardcoded league-list drift); getBaseballScoresOnly is now getFastPollScoresOnly(leagues).

Robustness fixes found along the way

  • node_helper no longer throws at startup when logos/logos_custom is missing (getDirectoryTree existence guard)
  • The frontend retries the startup GET-LOCAL-LOGOS handshake until answered — previously, a reply lost during a slow start meant score polling never began (relevant on slow Pi boots)
  • e2e harness hardening: the suite had a latent ~1-failure-per-run flake — a page from a finished test can outlive teardown and socket-reconnect to the next scenario's MM on the shared port, wiping its data (instanceId is identical on every page). Fixed with a unique MM port per scenario, a real readiness check (MM core + rendered content, one reload retry), a port-free wait after stop, and a debugHours shim so runs before 3 AM local aren't broken by rolloverHours. Screenshot-only scenarios pass silently on blank pages, which is why this was never caught — the new scenarios assert DOM content

Testing

  • 16 new unit tests (computeFieldPosition coordinate math, possession mapping, halftime degradation, SDSU trailing-space abbreviation fix): 129/129 passing
  • 6 new e2e scenarios (live, red zone, halftime degradation, touchdown, monochrome + assertions on ball position, goal-to-go marker suppression, and computed mono colors): 30/30 passing, verified stable across 4+ consecutive runs
  • Manually verified in a live browser session: slide/trail animations, first-down hold, turnover suppression, punt/FG/TD sequences, fast-poll start/stop, both color modes

🤖 Generated with Claude Code

https://claude.ai/code/session_01S1UJvj9naLkkQgAGqNLVrw

dathbe and others added 7 commits June 15, 2026 17:02
In-progress football games can show the live situation, mirroring
showBaseballDetail: down & distance and field position, a gridiron
graphic with the ball spot and first-down line, the last play text,
a possession indicator under the possessing team's logo, timeouts
under each score, and red-zone accents. On each new play the ball
slides to the new spot with a green/red gain-loss trail; the
first-down marker holds the old line-to-gain until the ball has
crossed it. Touchdowns keep the field visible with the ball in the
scored end zone through the PAT. Ball position is derived from
ESPN's possessionText in the provider (computeFieldPosition, unit
tested), so the frontend never sees team ids.

Config: showFootballDetail, footballDetailInterval,
footballDetailViewOverride. The baseball fast-poll was generalized
to a data-driven per-sport mechanism (fixes the hardcoded league
list drift at the old line 1016); getBaseballScoresOnly is now
getFastPollScoresOnly(leagues).

Tests: 16 new unit tests; 4 new e2e scenarios (live, red zone,
halftime degradation, touchdown) with numeric assertions. README
documents the new options with screenshots, plus the previously
undocumented baseballDetailViewOverride.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1UJvj9naLkkQgAGqNLVrw
The e2e suite was flaky (~1 random blank-page failure per run, any
scenario): a page from a finished test can outlive its teardown, and
its socket.io client auto-reconnects to the next scenario's
MagicMirror on the shared port. Its stale noGamesToday/ydLoaded
latches produce whichDay {today:false} requests whose instant notRun
replies — addressed by an instanceId identical on every page — wipe
the live page's freshly loaded scores. Screenshot-only scenarios
passed silently on blank pages; the football-detail assertions
exposed it.

Harness fixes:
- Unique MM port per scenario (matrix.spec.js) so a zombie page can
  never reach the next scenario's server; plus waitForPortFree after
  stop() (start-mm.js) and a real readiness check (MM core global +
  rendered content, one reload retry) instead of a bare-div selector.
- debugHours shim before 3 AM local so the module's rolloverHours
  logic requests the fixture-keyed date at any wall-clock time.
- install-mm now copies logos_custom; DEBUG logLevel in the test
  config; module state dumped to test output on assertion failure.

Module robustness (real-world wins from the same investigation):
- node_helper no longer throws at startup when logos/logos_custom is
  missing (getDirectoryTree existence guard) and Log.debugs each
  GET-SCORES request and response size.
- The frontend retries the startup GET-LOCAL-LOGOS handshake until
  answered — previously a reply lost during a slow start meant score
  polling never began.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1UJvj9naLkkQgAGqNLVrw
Non-colored mode previously leaked color into the gridiron: green
turf, yellow first-down line, green/red trails, red red-zone accents.
All field colors now live behind .wrapper.colored, matching the
baseball detail convention — mono defaults are dark-gray turf, #CCC
first-down line, white/gray gain-loss trails, and white red-zone
emphasis (ball, possession indicator, field position).

Touchdowns now animate: when the scoring play arrives with a known
previous spot, the ball slides from that spot into the end zone with
a gain trail (end-zone targets sit past the 0-100% play scale, so the
slide keyframes carry it across the goal line). The PAT and later
updates render the parked end-zone ball statically, so the slide
plays once per score.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1UJvj9naLkkQgAGqNLVrw
New football-detail-mono e2e scenario locks in the colored:false
grayscale rendering (gray ball, turf, first-down line) and provides
the README screenshot. README shows the mono example and notes the
touchdown slide.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1UJvj9naLkkQgAGqNLVrw
One set of options now controls live-game detail for every supported
sport (baseball and football) instead of per-sport flags. The
baseball-specific options (showBaseballDetail, baseballDetailInterval,
baseballDetailViewOverride) are deprecated but still work — start()
maps them onto the unified options so existing configs are unaffected —
and they are no longer documented in the README. The football options
introduced on this branch were never released and are removed outright.

The baseball e2e scenarios intentionally keep the deprecated options
in their configs, so the suite exercises the compatibility mapping.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1UJvj9naLkkQgAGqNLVrw
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