mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-10 09:06:36 +00:00
feat(common): sports_rotation -- the reconciled other-games rotation (sports family 7) (#786)
* feat(common): sports_rotation -- the reconciled other-games rotation (sports family 7) New hardware-free module src/common/sports_rotation.py, copied from ledmatrix-plugins claude/family7-reconcile once the nine scoreboards made _by_importance, _other_games_window, _advance_other_games_if_due (two bodies each), _rotate_other_games_on_display (two) and _attach_odds_to_rotated_games (three; ufc had none) one body each. All of them live on the plugins' SportsCore, so one mixin, SportsRotationMixin, carries exactly those five plus the default _rankings_loaded, and no manager gains a method it lacks today. - The window advances under _games_lock: update() and display() both advance it, and interleaved, each added a width and skipped a window. - The display path's due-check reads the pool _compose_selection will cut, unfiltered fallback included. - Rotated-in games get odds when show_odds is on (decided 2026-10-09: ufc too), skipped without an odds manager. - _rankings_loaded() is the seam _by_importance asks: the abbreviation table by default; football overrides it to count its by-id rankings. - test/test_sports_rotation.py: the plugins' pinned cases (importance order per rankings table and the seam, the window over time, the display-path rotation incl. the card on screen, redraws and recompose counts, update() and display() in sequence and interleaved on two threads -- with and without the lock -- and rotated-in odds), plus the host contract. - test/test_sports_rotation_parity.py: with LEDMATRIX_PLUGINS, compares each body with every plugin copy (drift-report normalisation plus decorators), checks no other plugin class carries a copy, and that only football overrides _rankings_loaded. Passes against claude/family7-reconcile; fails against the pre-reconcile tree, as it should. - mypy ratchet, src/common/README.md, CHANGELOG (Unreleased, New modules). - sports_shared docstring: _by_importance and _other_games_window (and the long-promoted _is_favorite_game) leave the "stay per-plugin" list. - docs/SPORTS_UNIFICATION.md: family 7 status, decisions, the _rankings_loaded seam; families 5 and 6 marked done and adopted (3.8.1 / ledmatrix-plugins #631, 3.8.2 / #637) instead of "adoption waits". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(sports): stage 4 is adopted (core 3.8.0, ledmatrix-plugins #594) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: cite ledmatrix-plugins #641 for the family 7 reconcile Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -53,6 +53,7 @@ Rules for the package:
|
||||
| [`sports_helpers`](#sports_helpers) | Small helpers every scoreboard `sports.py` copies | Yes (scoreboards) | 3.5.0 |
|
||||
| [`sports_live_scroll`](#sports_live_scroll) | Rebuild a live scroll strip mid-cycle without moving it | Yes (scoreboards) | 3.8.0 |
|
||||
| [`sports_plugin_host`](#sports_plugin_host) | Helpers of a scoreboard's plugin class (`manager.py`) | Yes (scoreboards) | 3.8.0 |
|
||||
| [`sports_rotation`](#sports_rotation) | Which non-favourite games a scoreboard shows, and when the slice moves | Yes (scoreboards) | next release |
|
||||
| [`sports_scroll`](#sports_scroll) | Scoreboard scroll-display orchestration | Yes (scoreboards) | 3.2.0 |
|
||||
| [`sports_shared`](#sports_shared) | Sport-independent `sports.py` methods | Yes (scoreboards) | 3.3.0 |
|
||||
| [`sports_vegas`](#sports_vegas) | Live Vegas cards: keys, card cache, sticky odds, finished games | Yes (scoreboards) | 3.8.0 |
|
||||
@@ -368,6 +369,21 @@ shape), `_dispatch_switch_refresh()` (a manager refresh on a daemon thread, so
|
||||
`display()` never waits on the network), `get_vegas_content_type()` and small
|
||||
dynamic-duration helpers. List it before `BasePlugin`.
|
||||
|
||||
### sports_rotation
|
||||
|
||||
[`sports_rotation.py`](sports_rotation.py). Sports family 7:
|
||||
`SportsRotationMixin` (`SportsCore`), the other-games rotation.
|
||||
`_by_importance` orders the non-favourite pool best matchup first, one game per
|
||||
team, when `_rankings_loaded()` says a poll loaded (football overrides that to
|
||||
count its by-id rankings). `_other_games_window` cuts the slice on screen,
|
||||
advancing by its width every `other_rotation_interval_seconds` under
|
||||
`_games_lock`, catching up on missed intervals and wrapping.
|
||||
`_rotate_other_games_on_display` (with `_advance_other_games_if_due`) re-cuts
|
||||
it from `display()` between fetches, looking at the pool `_compose_selection`
|
||||
will cut, unfiltered fallback included, and keeps the card on screen when it
|
||||
survives; `_attach_odds_to_rotated_games` fetches odds for the games it brought
|
||||
in when `show_odds` is on.
|
||||
|
||||
### sports_scroll
|
||||
|
||||
[`sports_scroll.py`](sports_scroll.py). `SportsScrollDisplay` and
|
||||
|
||||
Reference in New Issue
Block a user