Skip to content

feat(scoreboards): give the odds their own font, size and colour - #402

Merged
ChuckBuilds merged 1 commit into
mainfrom
feat/odds-text-setting
Sep 3, 2026
Merged

feat(scoreboards): give the odds their own font, size and colour#402
ChuckBuilds merged 1 commit into
mainfrom
feat/odds-text-setting

Conversation

@ChuckBuilds

Copy link
Copy Markdown
Owner

The betting line and over/under borrowed detail_text, so enlarging them on a big panel also enlarged the team records and the date row — and their green was hard-coded in the drawing call, where no setting could reach it.

A new customization.odds_text block controls the odds alone, in both the full-screen scorebug and the scroll/Vegas card.

"odds_text": { "font": "4x6-font.ttf", "font_size": 6, "text_color": [0, 255, 0] }

Nothing changes unless you set it

Defaults are exactly what was rendered before — same font, same size, same green — and a config saved before this existed falls back to detail_text.

safety-harness renders vs main 176/176 byte-identical
plugin tests 246 passed, 0 failed
repo gates 5/5 pass

Three bugs the tests caught that reading the diff did not

  • _element_color is not universally available. It exists on SportsCore, but the plugins' own probe harnesses build minimal managers that borrow only _draw_dynamic_odds. Calling it raised, the surrounding except swallowed it, and the odds silently disappeared. The colour now goes through _odds_color(), which falls back to green when the helper is absent — a missing dependency degrades to today's rendering instead of dropping the odds.
  • The odds slot initially read detail_config, so the colour setting worked and the font setting did nothing.
  • On football the mapping must go in _FONT_ELEMENT_KEYS as well as _ELEMENT_FOR_FONT; its style-resolver path reads the former.

Worth noting the render check could not have caught any of these — every harness fixture sets show_odds: false, so 176 identical renders say nothing about the odds path. The fleet did.

The white-default invariant

test_element_text_colors.py asserts every advertised text_color default is white, because the store materialises every schema default into config.json and a materialised default must be indistinguishable from unset.

odds_text is exempted rather than changed: green is its unset value, so advertising white would both lie about the default and repaint the odds the moment the store writes it. A second check asserts odds_text advertises exactly that green, so the exemption cannot silently drift.

Deliberately not included

ufc-scoreboard. Its loader takes no element_key, it has no per-element colour system, and after adapting for both, its ufc_upcoming renders still differed from main reproducibly (main-vs-main was 24/24 identical, so not flakiness) with zero odds pixels involved. Unexplained, so not shipped.

Pre-existing, not introduced here: on football, setting the font to the alias "four_by_six" falls back to PressStart2P on the style-resolver path — it does the same on main for detail_text. Use the filename "4x6-font.ttf".

Independent of the consolidation

Floor stays 3.2.0 and no new core imports, so this does not wait on 3.3.0, #515 or #359. It touches the same files as #359/#366, so merging this first and rebasing those two is the cleanest order.

The betting line and over/under borrowed detail_text, so enlarging them on a
big panel also enlarged the team records and the date row, and their green was
hard-coded in the drawing call where no setting could reach it. A new
customization.odds_text block controls the odds alone, in both the full-screen
scorebug and the scroll/Vegas card.

Nothing changes unless it is set. The defaults are exactly what was rendered
before -- the same 4x6 font at the same size, and the same green -- and a
config saved before this existed falls back to detail_text. All 176
safety-harness renders are byte-identical to the previous version.

Three things the tests caught that reading the diff did not:

- _element_color is not universally available. It exists on SportsCore, but the
  plugins' own probe harnesses build minimal managers that borrow only
  _draw_dynamic_odds. Calling it raised, the surrounding except swallowed it,
  and the odds silently disappeared. The colour now goes through _odds_color(),
  which falls back to green when the helper is absent, so a missing dependency
  degrades to today's rendering instead of dropping the odds.
- The odds slot initially read detail_config, so the colour setting worked and
  the font setting did nothing.
- On football the element mapping has to be added to _FONT_ELEMENT_KEYS as well
  as _ELEMENT_FOR_FONT; its style-resolver path reads the former.

test_element_text_colors.py asserted that every advertised text_color default
is white, because the store materialises every schema default into config.json
and a materialised default must be indistinguishable from unset. odds_text is
exempted rather than changed: green IS its unset value, so advertising white
would both lie and repaint the odds the moment the store writes it. A second
check asserts odds_text advertises exactly that green, so the exemption cannot
drift.

ufc-scoreboard is deliberately not included. Its loader takes no element_key,
it has no per-element colour system, and after adapting for both its
ufc_upcoming renders still differed from main reproducibly with no odds pixels
involved -- unexplained, so not shipped.

Known and pre-existing, not introduced here: on football, setting the font to
the alias "four_by_six" falls back to PressStart2P on the style-resolver path.
It does the same on main for detail_text. Use the filename "4x6-font.ttf".

Floor stays at 3.2.0 -- no new core imports, so this is independent of the
sports consolidation work.
@coderabbitai

coderabbitai Bot commented Sep 3, 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: Team

Run ID: c371518b-9cbb-41b9-9dd4-03897bab575a


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

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 5d10b43 into main Sep 3, 2026
3 of 4 checks passed
ChuckBuilds pushed a commit that referenced this pull request Sep 3, 2026
main gained the odds_text setting (#402), which bumped every scoreboard to the
version numbers this branch had claimed. All eight manifests conflicted for
that reason alone; no code conflicted.

Versions recomputed as the next minor above main's: afl 1.21.0, baseball
1.39.0, basketball 1.28.0, football 3.3.0, hockey 1.24.0, lacrosse 1.23.0,
nrl 1.20.0, soccer 2.23.0. plugins.json regenerated.

Checked that #402's work survived rather than assuming it: fonts["odds"],
_odds_color() and the odds_text schema block are all still present in every
plugin this branch touches. #402 added an odds font slot and colour helper to
the same game_renderer.py files this branch delegates twenty methods from, so
the two changes had to compose rather than one silently reverting the other.
ChuckBuilds pushed a commit that referenced this pull request Sep 3, 2026
main gained the odds_text setting (#402) and the card-helper delegation (#359),
which together bumped every scoreboard past the numbers this branch claimed.
All eight manifests conflicted for that reason alone; no code conflicted.

Versions recomputed above main's: afl 1.22.0, baseball 1.40.0, basketball
1.29.0, football 3.4.0, hockey 1.25.0, lacrosse 1.24.0, nrl 1.21.0, soccer
2.24.0. plugins.json regenerated.

Checked that the three layers compose rather than assuming it. #402 added an
odds font slot and _odds_color() to the same game_renderer.py files #359
delegates twenty methods from, and this branch removes forty-five more methods
from sports.py next to them. All three are present together in every plugin:
the sports_shared mixin, the sports_card delegations, and the odds wiring.

Re-verified against main at the #359 merge: all 176 safety-harness renders
byte-identical.

The previous CI failure on this branch was stale, not a defect. It ran on
2026-09-02 20:17, and #515 -- which puts src/common/sports_shared.py on core
main -- merged 2026-09-03 17:29, twenty-one hours later. The workflow checks
the core out at CORE_REF: main, so the module simply did not exist yet when
that run imported it.
ChuckBuilds added a commit that referenced this pull request Sep 3, 2026
…#403)

#402 added customization.odds_text to the schema but not to x-propertyOrder.
The config form iterates that list and nothing else, so the font, size and
colour controls shipped and could not be reached -- the setting existed only
for anyone hand-editing config.json.

scripts/test_property_order_coverage.py exists to catch exactly this and is
currently failing on main: "43 schemas, none hiding a declared setting (8
hidden)". This turns it green again.

odds_text is placed immediately after detail_text, which is what it was split
off from, so the two sit together in the form.

Nothing drawn changes -- this only makes existing settings editable.

Co-authored-by: Claude <noreply@anthropic.com>
ChuckBuilds pushed a commit that referenced this pull request Sep 3, 2026
main gained #403, which adds odds_text to x-propertyOrder in all eight
scoreboards and bumps each a patch level. That is the only reason the manifests
conflicted again; no code conflicted.

Versions recomputed above main's: afl 1.22.0, baseball 1.40.0, basketball
1.29.0, football 3.4.0, hockey 1.25.0, lacrosse 1.24.0, nrl 1.21.0, soccer
2.24.0.

Verified all four layers coexist rather than assuming it -- the sports_shared
mixin, #359's sports_card delegations, #402's odds wiring, and #403's
x-propertyOrder entry are present together in every plugin. Four changes have
now landed on the same files this branch edits, so composition is the thing
most likely to break silently.

test_property_order_coverage.py, the guard that was failing this branch, now
passes: it was #402's omission, fixed by #403, not a defect here.
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