Skip to content

fix(football): adaptive cards keep fitted logos, not full-size sources (3.18.6) - #619

Merged
ChuckBuilds merged 2 commits into
mainfrom
fix/football-adaptive-logos-full-size
Oct 4, 2026
Merged

ChuckBuilds merged 2 commits into
mainfrom
fix/football-adaptive-logos-full-size

Conversation

@ChuckBuilds

Copy link
Copy Markdown
Owner

What

Football's adaptive card layout (layout_mode: "adaptive") cached every team logo it loaded at full size, up to 128 per renderer, in each of the several renderers the plugin builds (a scorebug per manager, scroll cards, Vegas cards). The source files are 768x768 RGBA for the NFL (2.3 MB decoded) and 500x500 for most of NCAA, so these caches grew by hundreds of MB as a day of live games brought new teams on screen.

The card only ever draws the logo fitted into its slot, so that is what is cached now:

  • _fit_logo(abbr, path, slot) caches the fitted result, keyed by logo directory, abbreviation and slot size (same league scoping as before, see _logo_scope).
  • _load_raw_logo no longer caches: on a miss it reads the file, converts it, and the source is released after the fit.
  • Cards are pixel-identical (the fit call and its arguments are unchanged; test_adaptive_layout_mode.py goldens pass).

How it was found

Reported: the display process on ledpi (Pi 4, 1.8 GB) grew 30-40 MB/h during live sports (325 MB at 3 min, 431 MB at 90 min, 549 MB at 6 h), flat with no games. Football runs in adaptive layout there.

  • Ran the display headless as a normal user (stub matrix, private cache dir) with mallinfo2(), /proc and a PIL-image census sampled every minute. Over 15 h of Saturday games (3 arms: default arenas, MALLOC_ARENA_MAX=2, and the real service), the total footprint went 370 -> ~700 MB; the live malloc heap grew 164 -> 280 MB in the first 4 h and then stayed flat. MALLOC_ARENA_MAX=2 made no difference (677 vs 705 MB at 15 h).
  • A referrer walk over every decoded PIL image larger than the panel found only one holder: GameRenderer.__dict__['_raw_logo_cache']['nfl_logos:GB'] etc. -- 768x768 RGBA logos, unresized.
  • A/B on ledpi, same start, same live NFL slate, private cache dirs: after 30 min the unfixed arm held 16 full-size logos (31 MB decoded: 13 x 768x768, 2 x 480x480, 1 x 300x300) and the fixed arm held none; live heap 137 MB vs 98 MB, resident 307 MB vs 265 MB. That is with 8 live NFL games; the cap is 128 logos per renderer, so a full NCAA Saturday drives it far higher.

Test

test_adaptive_logos_not_kept_full_size.py draws 40 teams with 768x768 logos through one renderer and walks everything it holds:

  • before: largest held image 589,824 px (panel 9,216); 94.7 MB of logo pixels held -> FAIL
  • after: nothing larger than the panel; held pixels far below one full-size logo per team -> pass
  • cached and cold renders, and a fresh renderer's renders, are byte-identical.

test_adaptive_logo_league_scope.py's last check now looks at the fitted cache (the raw one is gone).

Plugin suite: 65 passed, 1 failed -- test_football_plugin.py, which prompts for input ("Would you like to run a 30-second emulator test?") and fails the same way without this change. Guards: check_version_bump (3.18.5 -> 3.18.6), check_manifest_version_fields, check_manifests_ascii, check_min_core_version, check_module_collisions, check_sports_drift, check_sports_helpers_parity, test_espn_dates_copies all pass. No core change; min core stays 3.8.0.

Only football has this cache: no other plugin calls fit_image or keeps unresized logos.

🤖 Generated with Claude Code

ChuckBuilds and others added 2 commits October 4, 2026 13:51
GameRenderer._load_raw_logo cached every logo unresized, up to 128 per
renderer, in each of the renderers the plugin builds. NFL logos are
768x768 RGBA (2.3 MB decoded), so the display's memory grew by hundreds
of MB over a day of live games. Cache the fitted logo instead (_fit_logo);
the source is read, fitted and released on a miss. Pixel-identical.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 2ede593b-1cbe-4a7d-adbd-eae62650e73b
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 32 complexity

Metric Results
Complexity 32

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@ChuckBuilds
ChuckBuilds merged commit 2bd3233 into main Oct 4, 2026
5 checks passed
@ChuckBuilds
ChuckBuilds deleted the fix/football-adaptive-logos-full-size branch October 4, 2026 20:52
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.

1 participant