Skip to content

fix(vegas): return individual game cards and all weather modes#29

Merged
ChuckBuilds merged 6 commits intomainfrom
fix/sports-vegas-content
Feb 16, 2026
Merged

fix(vegas): return individual game cards and all weather modes#29
ChuckBuilds merged 6 commits intomainfrom
fix/sports-vegas-content

Conversation

@ChuckBuilds
Copy link
Copy Markdown
Owner

@ChuckBuilds ChuckBuilds commented Feb 16, 2026

Summary

  • Sports plugins (hockey, soccer, baseball, basketball, football, ufc): get_vegas_content() now returns individual game card images instead of the pre-composed scroll strip that included 192px leading blank padding. Reduces hockey from 672px to 432px for 2 games.
  • Logo clipping fix (hockey, baseball, basketball, football): Removed negative x-offset logo positioning (away_x = -10, home_x = display_width - logo_width + 10) that caused PIL to clip logos at canvas edges when rendered as individual cards.
  • Weather plugin: Added get_vegas_content() that renders all enabled display modes (current conditions, hourly forecast, daily forecast) instead of only capturing whichever single mode was active at the time.
  • Cache check alignment: All sports plugins now check _vegas_content_items directly instead of has_cached_content()/cached_image, preventing regeneration from being skipped when scroll cache exists but Vegas items are empty.
  • UFC flat manager fix: Handle UFC's flat ScrollDisplayManager (no _scroll_displays dict) by reading _vegas_content_items directly from the manager instance.
  • Weather side-effect removal: Extracted pure _render_*_image() methods so get_vegas_content() no longer calls display_manager.clear()/update_display().

Test plan

  • Deployed hockey + baseball + weather to devpi, verified in logs
  • Hockey: [Hockey Vegas] Returning 2 image(s), 432px total (was 672px)
  • Weather: [Weather Vegas] Returning 3 image(s), 576px total (was 1 image, 192px)
  • Logos render flush with card edges, no clipping in Vegas scroll
  • Verify UFC plugin loads without AttributeError on _scroll_displays
  • Verify basketball/football regeneration triggers correctly

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Adjusted team logo horizontal placement on baseball, basketball, football, and hockey scoreboards for better visual alignment.
  • New Features

    • Scoreboard plugins now aggregate per-display Vegas content into ordered image lists for Vegas-style output.
    • Scroll displays cache individual Vegas content items for more accurate Vegas composition.
    • Weather plugin can produce Vegas-style image outputs.
  • Refactor

    • Weather rendering split into image-rendering paths to support previews and Vegas generation.

Chuck and others added 3 commits February 15, 2026 18:29
All 6 sports plugins were returning scroll_helper.cached_image (a
pre-composed scroll strip with 192px leading blank padding) or None
from get_vegas_content(). This wasted space in Vegas mode's scroll
and prevented proper content display.

Changes:
- Store individual content_items on ScrollDisplay as _vegas_content_items
  before passing to create_scrolling_image()
- Update get_vegas_content() in all 6 managers to return individual
  game card images instead of the scroll strip
- Fix soccer ScrollHelper constructor (3-arg signature + setter methods)
- Fix soccer is_scroll_complete() method name

This matches the Olympics pattern of returning a list of individual
card images, letting Vegas compose them with its own gaps.

Affected plugins: hockey, soccer, baseball, basketball, football, ufc

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Logos were positioned with negative x offsets (away at -10, home at
display_width - logo_width + 10) which worked for full-screen display
but got clipped by PIL when rendering individual game cards for Vegas
mode. Position logos flush with card edges instead.

Affects: hockey, baseball (all 3 render modes), basketball, football.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Weather plugin's get_vegas_content() was returning None, so Vegas
mode only captured whichever single display was active at the time
(usually hourly). Now renders all enabled modes (current conditions,
hourly forecast, daily forecast) and returns them as separate images.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 16, 2026

Warning

Rate limit exceeded

@ChuckBuilds has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 10 minutes and 54 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📝 Walkthrough

Walkthrough

Aggregates per-display Vegas images and exposes them via manager get_vegas_content across multiple scoreboard plugins; also removes 10-pixel horizontal offsets from home/away logos in several game_renderers and adds per-scroll _vegas_content_items storage in ScrollDisplay classes.

Changes

Cohort / File(s) Summary
Logo Positioning Adjustments
plugins/baseball-scoreboard/game_renderer.py, plugins/basketball-scoreboard/game_renderer.py, plugins/football-scoreboard/game_renderer.py, plugins/hockey-scoreboard/game_renderer.py
Removed prior ±10px horizontal offsets for home/away logos; home logos now flush at display_width - logo.width, away logos at 0.
ScrollDisplay Vegas Item Storage
plugins/baseball-scoreboard/scroll_display.py, plugins/basketball-scoreboard/scroll_display.py, plugins/football-scoreboard/scroll_display.py, plugins/hockey-scoreboard/scroll_display.py, plugins/soccer-scoreboard/scroll_display.py, plugins/ufc-scoreboard/scroll_display.py
Added self._vegas_content_items: List[Image.Image] and store a copy of rendered content_items after prepare_scroll_content for Vegas-mode use.
Vegas Content Aggregation in Managers
plugins/baseball-scoreboard/manager.py, plugins/basketball-scoreboard/manager.py, plugins/football-scoreboard/manager.py, plugins/hockey-scoreboard/manager.py, plugins/soccer-scoreboard/manager.py, plugins/ufc-scoreboard/manager.py
Refactored get_vegas_content to ensure scroll content exists, collect _vegas_content_items from each scroll display, log totals, and return a combined List[Image.Image] (or None if empty) instead of relying on a single cached image or returning None immediately.
Weather Plugin: Vegas & Renderers
plugins/ledmatrix-weather/manager.py
Introduced image-renderer helpers (_render_current_weather_image, _render_hourly_forecast_image, _render_daily_forecast_image), added public get_vegas_content to collect mode images, and refactored display methods to use non-side-effect renderers.

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant Manager
    participant ScrollManager
    participant ScrollDisplay

    Caller->>Manager: get_vegas_content()
    Manager->>ScrollManager: ensure scroll manager present
    alt no scroll manager
        ScrollManager-->>Manager: None
        Manager-->>Caller: None
    else scroll manager present
        Manager->>ScrollManager: for each ScrollDisplay -> ensure_scroll_content()
        ScrollManager->>ScrollDisplay: prepare_scroll_content()
        ScrollDisplay-->>ScrollDisplay: render content_items and set _vegas_content_items
        ScrollDisplay-->>ScrollManager: return (ready)
        ScrollManager-->>Manager: list of ScrollDisplay instances
        Manager->>Manager: collect all _vegas_content_items into images[]
        alt images not empty
            Manager-->>Caller: return images[]
        else empty
            Manager-->>Caller: return None
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: returning individual game cards and all weather modes for Vegas content.
Docstring Coverage ✅ Passed Docstring coverage is 97.44% which is sufficient. The required threshold is 80.00%.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/sports-vegas-content

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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (12)
plugins/baseball-scoreboard/scroll_display.py (1)

506-515: ⚠️ Potential issue | 🟡 Minor

_vegas_content_items is not cleared in clear().

When clear() is called, _vegas_content_items retains stale images from the previous scroll content. The manager's get_vegas_content() iterates over _vegas_content_items and could return outdated game cards after the scroll display has been cleared.

Proposed fix
     def clear(self) -> None:
         """Clear scroll content and reset state."""
         if self.scroll_helper:
             self.scroll_helper.clear_cache()
         self._current_games = []
         self._current_game_type = ""
         self._current_leagues = []
+        self._vegas_content_items = []
         self._is_scrolling = False
         self._scroll_start_time = None
         self.logger.debug("Scroll display cleared")
plugins/baseball-scoreboard/manager.py (1)

3625-3657: ⚠️ Potential issue | 🟡 Minor

Version not bumped for new Vegas content feature.

get_vegas_content() now returns a list of images instead of None — this is new functionality. The version at line 2552 is still "2.0.0". As per coding guidelines, "**/plugins/*/{manager.py,config_schema.json}: Bump MINOR version (1.x.0) for new features added, new config options (backward compatible), or new display modes/functionality".

plugins/football-scoreboard/scroll_display.py (2)

485-494: ⚠️ Potential issue | 🟡 Minor

_vegas_content_items not cleared in clear() — stale images may persist.

When clear() is called, _vegas_content_items retains stale images from the previous scroll content, which could cause get_vegas_content() in the manager to return outdated game cards.

Proposed fix
     def clear(self) -> None:
         """Clear scroll content and reset state."""
         if self.scroll_helper:
             self.scroll_helper.clear_cache()
         self._current_games = []
         self._current_game_type = ""
         self._current_leagues = []
+        self._vegas_content_items = []
         self._is_scrolling = False
         self._scroll_start_time = None
         self.logger.debug("Scroll display cleared")

346-353: ⚠️ Potential issue | 🟠 Major

Remove stale padding — logo overhang offsets no longer exist in GameRenderer.

The comment at line 347 references logos positioned at -10 and display_width+10, but those negative x-offsets have been removed from GameRenderer. Logos are now positioned flush at 0 and display_width - home_logo.width (lines 329 and 333). The 12px-per-side padding is a workaround for the old clipping behavior and is no longer needed, adding 24px of dead space to every game card and unnecessarily inflating the total scroll width.

plugins/hockey-scoreboard/scroll_display.py (1)

513-522: ⚠️ Potential issue | 🟡 Minor

_vegas_content_items not cleared in clear() — stale Vegas content may be served.

When clear() is called (e.g., no games available), _current_games and scroll state are reset but _vegas_content_items retains the old images. A subsequent get_vegas_content() call could return stale card images.

Proposed fix
     def clear(self) -> None:
         """Clear scroll content and reset state."""
         if self.scroll_helper:
             self.scroll_helper.clear_cache()
         self._current_games = []
         self._current_game_type = ""
         self._current_leagues = []
+        self._vegas_content_items = []
         self._is_scrolling = False
         self._scroll_start_time = None
         self.logger.debug("Scroll display cleared")
plugins/ufc-scoreboard/scroll_display.py (1)

375-381: ⚠️ Potential issue | 🟡 Minor

_vegas_content_items not cleared in reset() — stale content risk.

Same pattern as the other scroll displays: reset() clears fights and frame count but doesn't reset _vegas_content_items.

Proposed fix
     def reset(self) -> None:
         """Reset scroll state."""
         self._is_scrolling = False
         self._current_fights = []
+        self._vegas_content_items = []
         self._frame_count = 0
         if self.scroll_helper:
             self.scroll_helper.reset()
plugins/soccer-scoreboard/scroll_display.py (1)

460-467: ⚠️ Potential issue | 🟡 Minor

_vegas_content_items not cleared in clear_cache() — stale content risk.

Proposed fix
     def clear_cache(self) -> None:
         """Clear the scroll cache."""
         if self.scroll_helper:
             self.scroll_helper.clear_cache()
         self._current_games = []
         self._current_game_type = ""
         self._current_leagues = []
+        self._vegas_content_items = []
         self._is_scrolling = False
plugins/basketball-scoreboard/scroll_display.py (1)

521-530: ⚠️ Potential issue | 🟡 Minor

_vegas_content_items not cleared in clear() — stale content risk.

Proposed fix
     def clear(self) -> None:
         """Clear scroll content and reset state."""
         if self.scroll_helper:
             self.scroll_helper.clear_cache()
         self._current_games = []
         self._current_game_type = ""
         self._current_leagues = []
+        self._vegas_content_items = []
         self._is_scrolling = False
         self._scroll_start_time = None
         self.logger.debug("Scroll display cleared")
plugins/soccer-scoreboard/manager.py (1)

2073-2113: ⚠️ Potential issue | 🟡 Minor

Bump plugin minor version for new Vegas output behavior.

This change switches Vegas output to a list of individual images; please bump the plugin version in get_info (Line 1687) from 2.0.0 to the next minor (e.g., 2.1.0).

As per coding guidelines, "Bump MINOR version (1.x.0) for new features added, new config options (backward compatible), or new display modes/functionality".

plugins/basketball-scoreboard/manager.py (1)

3250-3280: ⚠️ Potential issue | 🟡 Minor

Bump plugin minor version for new Vegas output behavior.

This change adds new Vegas functionality (returning multiple images). Please bump the plugin version in get_info (Line 2292) from 2.0.0 to the next minor (e.g., 2.1.0).

As per coding guidelines, "Bump MINOR version (1.x.0) for new features added, new config options (backward compatible), or new display modes/functionality".

plugins/ledmatrix-weather/manager.py (1)

15-15: ⚠️ Potential issue | 🟡 Minor

Version should be bumped to 1.1.0 for the new get_vegas_content feature.

Adding a new public method (get_vegas_content) constitutes new functionality. As per coding guidelines, "Bump MINOR version (1.x.0) for new features added, new config options (backward compatible), or new display modes/functionality".

plugins/hockey-scoreboard/manager.py (1)

2919-2919: ⚠️ Potential issue | 🟡 Minor

Version should be bumped to 1.1.0 for the updated get_vegas_content behavior.

The method now returns individual game card images instead of a single cached scroll strip — this is new functionality. As per coding guidelines, "Bump MINOR version (1.x.0) for new features added, new config options (backward compatible), or new display modes/functionality".

🤖 Fix all issues with AI agents
In `@plugins/basketball-scoreboard/manager.py`:
- Around line 3263-3273: The current gating uses
self._scroll_manager.has_cached_content() which returns true for any cached
scroll so Vegas may skip regeneration when the existing cache is a non‑Vegas
type; change the condition to force regeneration unless a mixed Vegas cache is
present—e.g. check for the specific cache type (like comparing
self._scroll_manager.cache_type == 'mixed' or using a
has_cached_content_of_type('mixed') helper) before skipping calling
self._ensure_scroll_content_for_vegas(); update the logic around
_scroll_manager.has_cached_content() and the call to
_ensure_scroll_content_for_vegas() and ensure you still iterate
_scroll_manager._scroll_displays and use each display's _vegas_content_items as
before.

In `@plugins/football-scoreboard/manager.py`:
- Around line 3385-3390: The current cache presence check only calls
has_cached_content() (which inspects scroll_helper.cached_image) while Vegas
uses _vegas_content_items via get_vegas_content(), so the two can diverge;
update the logic in the block containing has_cached_content() (in manager.py) to
ensure both sources are consistent by checking get_vegas_content() /
_vegas_content_items as well (e.g., only treat cache as present if
scroll_helper.has_cached_content() AND self.get_vegas_content() returns
non-empty), and/or ensure any clear_cache()/clear() implementation also clears
_vegas_content_items in prepare_scroll_content()/scroll_display.clear() so both
caches are kept in sync (reference has_cached_content(), cached_image,
get_vegas_content(), _vegas_content_items, prepare_scroll_content(),
clear_cache()).

In `@plugins/hockey-scoreboard/manager.py`:
- Around line 3097-3117: The content-presence check currently inspects
scroll_display.scroll_helper.cached_image but the method actually collects and
returns scroll_display._vegas_content_items; update the presence check to look
at vegas_items (scroll_display._vegas_content_items) instead of
scroll_helper.cached_image so regeneration via _ensure_scroll_content_for_vegas
occurs when _vegas_content_items is empty or missing. Concretely, in the loop
over self._scroll_manager._scroll_displays.values() replace the cached_image
check with a check for getattr(scroll_display, '_vegas_content_items', None)
(and that it is truthy/non-empty); leave calls to
_ensure_scroll_content_for_vegas, prepare_scroll_content and
create_scrolling_image untouched but ensure the check aligns with
_vegas_content_items to avoid desyncs.

In `@plugins/ledmatrix-weather/manager.py`:
- Around line 838-881: get_vegas_content is causing side effects because it
calls _display_current_weather, _display_hourly_forecast and
_display_daily_forecast which mutate display_manager (clear, set image, and call
update_display); change the rendering so get_vegas_content does not touch the
physical display by either (a) adding a non‑side‑effect mode/flag to those
methods (e.g., render_to_image=False -> render_to_image=True) so they return a
Pillow Image instead of calling display_manager.clear/update_display and setting
display_manager.image, or (b) extracting the pure rendering logic into new
helper functions that return an Image (e.g., render_current_weather_image,
render_hourly_forecast_image, render_daily_forecast_image) and have the existing
_display_* methods call those helpers and then set
display_manager.image/update_display; ensure get_vegas_content uses the pure
render functions or the flag to build images without calling
display_manager.update_display.

In `@plugins/ufc-scoreboard/manager.py`:
- Around line 1050-1055: The code assumes self._scroll_manager._scroll_displays
exists which causes AttributeError for UFC where ScrollDisplayManager is flat
and exposes _vegas_content_items directly; update the collection logic in
manager.py to first check getattr(self._scroll_manager, '_scroll_displays',
None) and iterate its values to collect _vegas_content_items, and if that
attribute is None treat self._scroll_manager itself as the display and read its
_vegas_content_items (use getattr with a default None) before extending images
so both manager→displays and flat manager cases are supported.

In `@plugins/ufc-scoreboard/scroll_display.py`:
- Line 85: ScrollDisplayManager defines _vegas_content_items (attribute on
ScrollDisplayManager) but manager.py's get_vegas_content iterates
self._scroll_manager._scroll_displays.values(), causing AttributeError because
ScrollDisplayManager has no _scroll_displays; fix by changing get_vegas_content
to access the correct attribute or collection on ScrollDisplayManager (use
self._scroll_manager._vegas_content_items or add a proper _scroll_displays
mapping on ScrollDisplayManager), updating references in get_vegas_content and
any iteration logic so they iterate the actual container (e.g.,
_vegas_content_items) and not a non-existent _scroll_displays.
🧹 Nitpick comments (6)
plugins/baseball-scoreboard/manager.py (1)

3643-3647: Reaching into private _scroll_displays breaks encapsulation.

get_vegas_content() directly accesses self._scroll_manager._scroll_displays, which is an internal detail of ScrollDisplayManager. If the internal structure changes, this code silently breaks.

Consider adding a public method to ScrollDisplayManager (e.g., get_all_vegas_content_items()) that encapsulates this iteration.

Example: Add accessor to ScrollDisplayManager

In scroll_display.py, add to ScrollDisplayManager:

def get_all_vegas_content_items(self) -> list:
    """Collect all Vegas content items from all scroll displays."""
    images = []
    for scroll_display in self._scroll_displays.values():
        vegas_items = getattr(scroll_display, '_vegas_content_items', None)
        if vegas_items:
            images.extend(vegas_items)
    return images

Then in manager.py:

-        images = []
-        for scroll_display in self._scroll_manager._scroll_displays.values():
-            vegas_items = getattr(scroll_display, '_vegas_content_items', None)
-            if vegas_items:
-                images.extend(vegas_items)
+        images = self._scroll_manager.get_all_vegas_content_items()
plugins/football-scoreboard/manager.py (1)

3392-3397: Accessing private _scroll_displays breaks encapsulation.

get_vegas_content() reaches into ScrollDisplayManager._scroll_displays (a private attribute) to collect _vegas_content_items. If the internal structure of ScrollDisplayManager changes, this silently breaks.

Consider adding a method to ScrollDisplayManager (e.g., get_all_vegas_content_items()) that encapsulates this aggregation logic, consistent with how has_cached_content() already iterates over internal displays.

Proposed approach

In scroll_display.py, add to ScrollDisplayManager:

def get_all_vegas_content_items(self) -> list:
    """Collect all Vegas content items from all scroll displays."""
    items = []
    for scroll_display in self._scroll_displays.values():
        vegas_items = getattr(scroll_display, '_vegas_content_items', None)
        if vegas_items:
            items.extend(vegas_items)
    return items

Then in manager.py:

-        images = []
-        for scroll_display in self._scroll_manager._scroll_displays.values():
-            vegas_items = getattr(scroll_display, '_vegas_content_items', None)
-            if vegas_items:
-                images.extend(vegas_items)
+        images = self._scroll_manager.get_all_vegas_content_items()
plugins/hockey-scoreboard/scroll_display.py (1)

374-376: Stale comment: logos are no longer positioned at ±10.

The game_renderer now places logos flush at 0 and display_width - width, so this comment is outdated. The 12px padding may still be useful for visual spacing in scroll mode, but the rationale should be updated.

-                # Add horizontal padding to prevent logos from being cut off at edges
-                # Logos are positioned at -10 and display_width+10, so we need padding
-                padding = 12  # Padding on each side to ensure logos aren't cut off
+                # Add horizontal padding for visual spacing between adjacent cards in scroll mode
+                padding = 12
plugins/soccer-scoreboard/scroll_display.py (1)

340-342: Stale comment: logos no longer at ±10 offsets.

Same as the other scroll displays — the game_renderer no longer uses negative offsets for logo positioning. Update the comment to reflect the actual purpose of the padding (visual spacing).

plugins/ufc-scoreboard/manager.py (1)

1037-1041: Version not bumped for bug fix.

The coding guidelines require a PATCH version bump (1.2.x) for bug fixes in plugin files.

plugins/basketball-scoreboard/scroll_display.py (1)

382-384: Stale comment: logos no longer at ±10 offsets.

Same as the other scroll displays.

…ide effects

- Sports plugins (hockey, basketball, football, baseball): Replace
  has_cached_content()/cached_image checks with _vegas_content_items
  checks so regeneration triggers correctly when Vegas items are missing.

- UFC: Handle flat ScrollDisplayManager that has _vegas_content_items
  directly (no _scroll_displays dict), fixing AttributeError.

- Weather: Extract pure _render_*_image() methods that return PIL Images
  without touching display_manager. get_vegas_content() now calls these
  instead of the _display_*() methods that mutate display state.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
plugins/ledmatrix-weather/manager.py (1)

15-15: ⚠️ Potential issue | 🟡 Minor

Bump the API version for the new get_vegas_content feature.

Adding get_vegas_content() and the new _render_*_image() public-ish API constitutes new functionality. As per coding guidelines, "**/plugins/*/{manager.py,config_schema.json}: Bump MINOR version (1.x.0) for … new features added … or new display modes/functionality."

-API Version: 1.0.0
+API Version: 1.1.0
plugins/basketball-scoreboard/manager.py (1)

2292-2292: ⚠️ Potential issue | 🟡 Minor

Bump PATCH version for this bug fix.

The PR fixes Vegas content to return individual game cards and corrects logo clipping — both qualify as bug fixes. The version should be bumped from "2.0.0" to "2.0.1".

Suggested fix
-                "version": "2.0.0",
+                "version": "2.0.1",

As per coding guidelines, **/plugins/**/*.py: "Bump PATCH version (1.2.x) for bug fixes, performance improvements, documentation updates, or minor tweaks".

plugins/hockey-scoreboard/manager.py (1)

2917-2917: ⚠️ Potential issue | 🟡 Minor

Version bump needed per coding guidelines.

The get_vegas_content() method behavior has changed (returning individual game card images instead of a single scroll strip). The version at line 2917 is still "1.0.0". A PATCH bump to "1.0.1" is warranted for this bug fix.

Suggested fix
-                "version": "1.0.0",
+                "version": "1.0.1",

As per coding guidelines, **/plugins/**/*.py: "Bump PATCH version (1.2.x) for bug fixes, performance improvements, documentation updates, or minor tweaks".

🤖 Fix all issues with AI agents
In `@plugins/baseball-scoreboard/manager.py`:
- Around line 3629-3662: The plugin changes alter Vegas output behavior so you
must bump the patch version in the plugin metadata: update the version returned
by get_info() (or equivalent version constant/function) from the current 3-part
semantic version (e.g., 2.0.0) to the next patch (e.g., 2.0.1), and ensure any
other version references (package metadata or docs) are consistent; keep the
rest of get_info() unchanged.
🧹 Nitpick comments (2)
plugins/ledmatrix-weather/manager.py (1)

618-620: Use logger.exception instead of logger.error to preserve stack traces.

In the _render_*_image() catch blocks, logger.error(f"…: {e}") loses the traceback. logger.exception() automatically attaches it, which is valuable for debugging rendering failures on hardware.

Suggested fix (apply to all three renderers)
-            self.logger.error(f"Error rendering current weather: {e}")
+            self.logger.exception("Error rendering current weather")
-            self.logger.error(f"Error rendering hourly forecast: {e}")
+            self.logger.exception("Error rendering hourly forecast")
-            self.logger.error(f"Error rendering daily forecast: {e}")
+            self.logger.exception("Error rendering daily forecast")

Also applies to: 737-739, 808-810

plugins/football-scoreboard/manager.py (1)

3385-3411: Consider encapsulating _scroll_displays access through a public method on ScrollDisplayManager.

get_vegas_content() directly accesses self._scroll_manager._scroll_displays (lines 3391, 3400), creating tight coupling to ScrollDisplayManager's internal structure. While this pattern is consistent across all sports plugins, adding a public method like get_all_vegas_content_items() to ScrollDisplayManager would improve encapsulation and reduce maintenance burden if the internal structure changes.

The cache-check alignment with _vegas_content_items (instead of the prior has_cached_content() / cached_image approach) is correct and resolves the previously flagged mismatch.

♻️ Optional: Suggested encapsulation in ScrollDisplayManager

Add a method to ScrollDisplayManager:

def get_all_vegas_content_items(self):
    """Collect _vegas_content_items from all scroll displays."""
    items = []
    for sd in self._scroll_displays.values():
        vegas_items = getattr(sd, '_vegas_content_items', None)
        if vegas_items:
            items.extend(vegas_items)
    return items

Then simplify get_vegas_content():

-        has_content = any(
-            getattr(sd, '_vegas_content_items', None)
-            for sd in self._scroll_manager._scroll_displays.values()
-        )
+        images = self._scroll_manager.get_all_vegas_content_items()
+        has_content = bool(images)

         if not has_content:
             self.logger.info("[Football Vegas] Triggering scroll content generation")
             self._ensure_scroll_content_for_vegas()
+            images = self._scroll_manager.get_all_vegas_content_items()

-        # Collect individual game card images for Vegas (not the scroll strip)
-        images = []
-        for scroll_display in self._scroll_manager._scroll_displays.values():
-            vegas_items = getattr(scroll_display, '_vegas_content_items', None)
-            if vegas_items:
-                images.extend(vegas_items)
-
         if images:

Comment on lines +3629 to 3662
Triggers scroll content generation if cache is empty, then returns
the cached scroll image(s) for Vegas to compose into its scroll strip.

Returns:
None - PluginAdapter will extract scroll_helper.cached_image automatically
List of PIL Images from scroll displays, or None if no content
"""
# Ensure scroll content is generated for Vegas mode
if hasattr(self, '_scroll_manager') and self._scroll_manager:
if not self._scroll_manager.has_cached_content():
self.logger.info("[Baseball Vegas] Triggering scroll content generation")
self._ensure_scroll_content_for_vegas()
if not hasattr(self, '_scroll_manager') or not self._scroll_manager:
return None

# Check if any scroll display has vegas content items
has_content = any(
getattr(sd, '_vegas_content_items', None)
for sd in self._scroll_manager._scroll_displays.values()
)

if not has_content:
self.logger.info("[Baseball Vegas] Triggering scroll content generation")
self._ensure_scroll_content_for_vegas()

# Collect individual game card images for Vegas (not the scroll strip)
images = []
for scroll_display in self._scroll_manager._scroll_displays.values():
vegas_items = getattr(scroll_display, '_vegas_content_items', None)
if vegas_items:
images.extend(vegas_items)

if images:
total_width = sum(img.width for img in images)
self.logger.info(
"[Baseball Vegas] Returning %d image(s), %dpx total",
len(images), total_width
)
return images

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Bump the plugin patch version for this Vegas content fix.

This change alters Vegas output behavior, so the plugin version should be incremented (e.g., 2.0.02.0.1) in version metadata such as get_info().

Suggested patch
-                "version": "2.0.0",
+                "version": "2.0.1",

As per coding guidelines, “/plugins//*.py: Bump PATCH version (1.2.x) for bug fixes, performance improvements, documentation updates, or minor tweaks”.

🤖 Prompt for AI Agents
In `@plugins/baseball-scoreboard/manager.py` around lines 3629 - 3662, The plugin
changes alter Vegas output behavior so you must bump the patch version in the
plugin metadata: update the version returned by get_info() (or equivalent
version constant/function) from the current 3-part semantic version (e.g.,
2.0.0) to the next patch (e.g., 2.0.1), and ensure any other version references
(package metadata or docs) are consistent; keep the rest of get_info()
unchanged.

Chuck and others added 2 commits February 15, 2026 19:18
- Add get_all_vegas_content_items() to all ScrollDisplayManagers,
  replacing direct _scroll_displays iteration in get_vegas_content().
  UFC's flat manager returns its own items; others iterate displays.

- Weather: use logger.exception() in _render_*_image() catch blocks
  to preserve stack traces for debugging rendering failures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
baseball-scoreboard: 2.0.0 → 2.0.1
basketball-scoreboard: 1.1.0 → 1.1.1
football-scoreboard: 2.1.0 → 2.1.1
hockey-scoreboard: 1.1.0 → 1.1.1
soccer-scoreboard: 1.3.0 → 1.3.1
ufc-scoreboard: 1.0.0 → 1.0.1
ledmatrix-weather: 2.1.0 → 2.1.1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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