- The reused Vegas renderer always gets the current rankings, empty
included, so ranks cleared since are not kept drawn.
- render_plugin.py: --timeline refuses --no-live (a timeline shows live
elements changing), --timeline/--no-live need --vegas, and the Vegas
paths create the output's directory like the display path does.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One live element per game, drawn only when what the card shows changes, so
a score changes on a card already crossing the panel. The shared part, so
each scoreboard adopts it in a few lines:
- src/common/sports_vegas.py: game_key, game_fingerprint (the whole game
dict, frozen: no drawn field can be missed), dedupe_games, VegasCardCache,
StickyOdds (odds a live poll left out stay drawn), finished_games /
with_finished_games (a game that just went final keeps its card, after its
league's live games; one a heuristic only judged over keeps its live
state, so a tied end of regulation never shows FINAL early).
- SportsScrollDisplay.make_vegas_renderer() is the override point;
build_vegas_elements() and SportsScrollDisplayManager
.get_vegas_elements_for() do the rest. A card's version includes its
teams' ranks, which the renderer draws from the rankings cache.
- SportsLiveSharedMixin._record_finished_game() / finished_games_snapshot():
held for FINISHED_GAME_TTL after it leaves the live list.
A sport that does not implement make_vegas_renderer keeps its ordinary Vegas
content, so no scoreboard changes until it opts in.
scripts/render_plugin.py --vegas renders a plugin's Vegas block as the
ticker lays it out, and --timeline stacks it at successive moments as
the ticker would update it in place; the join is now
render_pipeline.join_plugin_rows().
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>