mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-08-01 16:58:06 +00:00
Phase B2 of the sports unification. Both features exist in only some of
the nine scoreboards, so they ship as capabilities the plugin composes,
never as `if self.<feature>_enabled` branches inside the base classes: a
sport that does not opt in has none of this code in its MRO.
CelebrationMixin (afl, nrl, soccer, football)
The two lineages spelled this differently -- _check_for_goal /
celebrate_opponent_goals vs _check_for_score / celebrate_opponent_scores
-- but the bodies were identical apart from three things, each now a
seam rather than a branch:
- wording -> score_phrase() / win_phrase() hooks
- follow-up suppression -> COALESCE_SCORING_SEQUENCE, on for football
where a touchdown lands as +6 then +1, off where two increments are
two real goals
- team identity -> _favorite_key, so nrl matches on team id without
core learning why its abbreviations are ambiguous
Both config spellings are read, so a plugin adopting the mixin keeps
working with the keys already in its published schema.
Rotation strategies
The three "dialects" turned out to be one algorithm (SWRR) in two
shapes: an incremental picker holding state across calls, and a
precomputed per-cycle list. They agree within a cycle and differ only at
the boundary, so core ships both behind a name registry rather than
declaring a winner. weight_for is supplied by the host, so rotation.py
never learns what a favorite is; an unknown name degrades to "simple"
because it arrives from user config.
Each strategy is checked against a verbatim transcription of the plugin
code it replaces, over every live-game shape up to four games -- the
differential B5 will delete the bundled copies on the strength of.
185 new tests. Gates: 648 core unit, 60 plugin safety.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FgbA8SMutQQpXkMG8LMmC4
33 lines
1012 B
Python
33 lines
1012 B
Python
"""Opt-in capabilities for the sports scoreboards.
|
|
|
|
Each module here is a feature that only *some* sports want. They are composed
|
|
by inheritance (mixins) or selected by name (strategies) — never enabled by an
|
|
``if self.<feature>_enabled:`` branch inside the base classes.
|
|
|
|
The distinction matters: hockey has no celebrations, so ``HockeyLive`` does not
|
|
inherit :class:`~.celebrations.CelebrationMixin` and the celebration code is not
|
|
in hockey's MRO at all. A bug in it cannot reach a plugin that never opted in.
|
|
|
|
See ``docs/SPORTS_UNIFICATION.md`` for the full rationale.
|
|
"""
|
|
|
|
from .celebrations import CelebrationMixin
|
|
from .rotation import (
|
|
RotationStrategy,
|
|
SimpleRotation,
|
|
SmoothWeightedRotation,
|
|
WeightedCycleRotation,
|
|
get_rotation_strategy,
|
|
register_rotation_strategy,
|
|
)
|
|
|
|
__all__ = [
|
|
"CelebrationMixin",
|
|
"RotationStrategy",
|
|
"SimpleRotation",
|
|
"SmoothWeightedRotation",
|
|
"WeightedCycleRotation",
|
|
"get_rotation_strategy",
|
|
"register_rotation_strategy",
|
|
]
|