From 8dccebff01d2d3c1c2c864fa06f54b01db8645e3 Mon Sep 17 00:00:00 2001 From: Chuck <33324927+ChuckBuilds@users.noreply.github.com> Date: Mon, 21 Jul 2025 16:42:24 -0500 Subject: [PATCH] centered team logos in odds ticker and removed dynamic display duration --- README.md | 1 + config/config.json | 3 ++- src/display_controller.py | 5 ----- src/nba_managers.py | 6 ++++++ src/ncaa_baseball_managers.py | 6 ++++++ src/ncaa_fb_managers.py | 6 ++++++ src/ncaam_basketball_managers.py | 6 ++++++ src/nfl_managers.py | 6 ++++++ src/nhl_managers.py | 6 ++++++ src/odds_ticker_manager.py | 35 +++++++++++--------------------- src/soccer_managers.py | 6 ++++++ 11 files changed, 57 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index c3a93f26..d4130d12 100644 --- a/README.md +++ b/README.md @@ -370,6 +370,7 @@ The odds ticker displays betting odds for upcoming sports games. To configure it - **`scroll_speed`**: Pixels to scroll per update (default: 1) - **`scroll_delay`**: Delay between scroll updates in seconds (default: 0.05) - **`display_duration`**: How long to show each game in seconds (default: 30) +- **`loop`**: Whether to continuously loop the scroll animation (default: true). When false, the scroll stops when it reaches the end of the content. **How it works:** - If `show_favorite_teams_only` is true, the ticker will show the next `games_per_favorite_team` games for each favorite team in each enabled league, deduplicated and capped at `max_games_per_league` per league. diff --git a/config/config.json b/config/config.json index df7f9625..aaa1c6cc 100644 --- a/config/config.json +++ b/config/config.json @@ -119,7 +119,8 @@ "scroll_speed": 1, "scroll_delay": 0.01, "display_duration": 60, - "future_fetch_days": 45 + "future_fetch_days": 45, + "loop": true }, "calendar": { "enabled": true, diff --git a/src/display_controller.py b/src/display_controller.py index 79a53ef1..71af0b12 100644 --- a/src/display_controller.py +++ b/src/display_controller.py @@ -448,11 +448,6 @@ class DisplayController: """Get the duration for the current display mode.""" mode_key = self.current_display_mode - if mode_key == 'odds_ticker' and self.odds_ticker: - dynamic_duration = self.odds_ticker.get_dynamic_duration() - if dynamic_duration > 0: - return dynamic_duration - # Simplify weather key handling if mode_key.startswith('weather_'): return self.display_durations.get(mode_key, 15) diff --git a/src/nba_managers.py b/src/nba_managers.py index c91d21c9..033fb040 100644 --- a/src/nba_managers.py +++ b/src/nba_managers.py @@ -427,6 +427,12 @@ class BaseNBAManager: away_team = next(c for c in competitors if c.get("homeAway") == "away") home_record = home_team.get('records', [{}])[0].get('summary', '') if home_team.get('records') else '' away_record = away_team.get('records', [{}])[0].get('summary', '') if away_team.get('records') else '' + + # Don't show "0-0" records - set to blank instead + if home_record == "0-0": + home_record = '' + if away_record == "0-0": + away_record = '' # Format game time and date for display game_time = "" diff --git a/src/ncaa_baseball_managers.py b/src/ncaa_baseball_managers.py index ab0df726..df7594a6 100644 --- a/src/ncaa_baseball_managers.py +++ b/src/ncaa_baseball_managers.py @@ -418,6 +418,12 @@ class BaseNCAABaseballManager: home_record = home_team.get('records', [{}])[0].get('summary', '') if home_team.get('records') else '' away_record = away_team.get('records', [{}])[0].get('summary', '') if away_team.get('records') else '' + # Don't show "0-0" records - set to blank instead + if home_record == "0-0": + home_record = '' + if away_record == "0-0": + away_record = '' + is_favorite_game = (home_abbr in self.favorite_teams or away_abbr in self.favorite_teams) if is_favorite_game: diff --git a/src/ncaa_fb_managers.py b/src/ncaa_fb_managers.py index 8856ce1c..d5d0a2cd 100644 --- a/src/ncaa_fb_managers.py +++ b/src/ncaa_fb_managers.py @@ -427,6 +427,12 @@ class BaseNCAAFBManager: # Renamed class away_abbr = away_team["team"]["abbreviation"] home_record = home_team.get('records', [{}])[0].get('summary', '') if home_team.get('records') else '' away_record = away_team.get('records', [{}])[0].get('summary', '') if away_team.get('records') else '' + + # Don't show "0-0" records - set to blank instead + if home_record == "0-0": + home_record = '' + if away_record == "0-0": + away_record = '' # Filter by favorite teams if the list is not empty if self.favorite_teams and not (home_abbr in self.favorite_teams or away_abbr in self.favorite_teams): diff --git a/src/ncaam_basketball_managers.py b/src/ncaam_basketball_managers.py index a7fbcff7..04656367 100644 --- a/src/ncaam_basketball_managers.py +++ b/src/ncaam_basketball_managers.py @@ -424,6 +424,12 @@ class BaseNCAAMBasketballManager: away_team = next(c for c in competitors if c.get("homeAway") == "away") home_record = home_team.get('records', [{}])[0].get('summary', '') if home_team.get('records') else '' away_record = away_team.get('records', [{}])[0].get('summary', '') if away_team.get('records') else '' + + # Don't show "0-0" records - set to blank instead + if home_record == "0-0": + home_record = '' + if away_record == "0-0": + away_record = '' # Format game time and date for display game_time = "" diff --git a/src/nfl_managers.py b/src/nfl_managers.py index 76e87f47..ccd6a6dd 100644 --- a/src/nfl_managers.py +++ b/src/nfl_managers.py @@ -427,6 +427,12 @@ class BaseNFLManager: # Renamed class away_abbr = away_team["team"]["abbreviation"] home_record = home_team.get('records', [{}])[0].get('summary', '') if home_team.get('records') else '' away_record = away_team.get('records', [{}])[0].get('summary', '') if away_team.get('records') else '' + + # Don't show "0-0" records - set to blank instead + if home_record == "0-0": + home_record = '' + if away_record == "0-0": + away_record = '' # Filter by favorite teams if the list is not empty if self.favorite_teams and not (home_abbr in self.favorite_teams or away_abbr in self.favorite_teams): diff --git a/src/nhl_managers.py b/src/nhl_managers.py index cf50e2c6..d9bcb275 100644 --- a/src/nhl_managers.py +++ b/src/nhl_managers.py @@ -367,6 +367,12 @@ class BaseNHLManager: away_team = next(c for c in competitors if c.get("homeAway") == "away") home_record = home_team.get('records', [{}])[0].get('summary', '') if home_team.get('records') else '' away_record = away_team.get('records', [{}])[0].get('summary', '') if away_team.get('records') else '' + + # Don't show "0-0" records - set to blank instead + if home_record == "0-0": + home_record = '' + if away_record == "0-0": + away_record = '' # Format game time and date for display game_time = "" diff --git a/src/odds_ticker_manager.py b/src/odds_ticker_manager.py index b0661beb..673eea2f 100644 --- a/src/odds_ticker_manager.py +++ b/src/odds_ticker_manager.py @@ -34,6 +34,7 @@ class OddsTickerManager: self.scroll_delay = self.odds_ticker_config.get('scroll_delay', 0.05) self.display_duration = self.odds_ticker_config.get('display_duration', 30) self.future_fetch_days = self.odds_ticker_config.get('future_fetch_days', 7) + self.loop = self.odds_ticker_config.get('loop', True) # Initialize managers self.cache_manager = CacheManager() @@ -47,7 +48,6 @@ class OddsTickerManager: self.current_game_index = 0 self.ticker_image = None # This will hold the single, wide image self.last_display_time = 0 - self.dynamic_display_duration = 0 # Font setup self.fonts = self._load_fonts() @@ -500,7 +500,7 @@ class OddsTickerManager: # Away Logo if away_logo: - y_pos = logo_margin + y_pos = (height - logo_size) // 2 # Center the logo vertically image.paste(away_logo, (int(current_x), y_pos), away_logo if away_logo.mode == 'RGBA' else None) current_x += logo_size + vs_padding @@ -511,7 +511,7 @@ class OddsTickerManager: # Home Logo if home_logo: - y_pos = logo_margin + y_pos = (height - logo_size) // 2 # Center the logo vertically image.paste(home_logo, (int(current_x), y_pos), home_logo if home_logo.mode == 'RGBA' else None) current_x += logo_size + section_padding @@ -578,23 +578,6 @@ class OddsTickerManager: self.ticker_image.putpixel((bar_x, y), (255, 255, 255)) current_x += gap_width - if self.ticker_image and self.scroll_speed > 0 and self.scroll_delay > 0: - # Duration for the ticker to scroll its full width - self.dynamic_display_duration = (self.ticker_image.width / self.scroll_speed) * self.scroll_delay - logger.info(f"[OddsTickerManager] Calculated dynamic display duration: {self.dynamic_display_duration:.2f} seconds for a width of {self.ticker_image.width}px, scroll_speed={self.scroll_speed}, scroll_delay={self.scroll_delay}") - else: - # Fallback to the configured duration if something is wrong - self.dynamic_display_duration = self.display_duration - logger.warning(f"[OddsTickerManager] Using fallback display duration. ticker_image exists: {self.ticker_image is not None}, scroll_speed: {self.scroll_speed}, scroll_delay: {self.scroll_delay}") - if self.ticker_image: - logger.info(f"[OddsTickerManager] Ticker image width: {self.ticker_image.width}px") - else: - logger.warning("[OddsTickerManager] No ticker image available") - - def get_dynamic_duration(self) -> float: - """Return the calculated dynamic duration for the ticker to complete one full scroll.""" - return self.dynamic_display_duration - def _draw_text_with_outline(self, draw: ImageDraw.Draw, text: str, position: tuple, font: ImageFont.FreeTypeFont, fill: tuple = (255, 255, 255), outline_color: tuple = (0, 0, 0)) -> None: """Draw text with a black outline for better readability.""" @@ -676,9 +659,15 @@ class OddsTickerManager: width = self.display_manager.matrix.width height = self.display_manager.matrix.height - # Reset position when we've scrolled past the end for a continuous loop - if self.scroll_position >= self.ticker_image.width: - self.scroll_position = 0 + # Handle looping based on configuration + if self.loop: + # Reset position when we've scrolled past the end for a continuous loop + if self.scroll_position >= self.ticker_image.width: + self.scroll_position = 0 + else: + # Stop scrolling when we reach the end + if self.scroll_position >= self.ticker_image.width - width: + self.scroll_position = self.ticker_image.width - width # Create the visible part of the image by pasting from the ticker_image visible_image = Image.new('RGB', (width, height)) diff --git a/src/soccer_managers.py b/src/soccer_managers.py index 6684a6c2..ac1ae093 100644 --- a/src/soccer_managers.py +++ b/src/soccer_managers.py @@ -555,6 +555,12 @@ class BaseSoccerManager: away_team = next(c for c in competitors if c.get("homeAway") == "away") home_record = home_team.get('records', [{}])[0].get('summary', '') if home_team.get('records') else '' away_record = away_team.get('records', [{}])[0].get('summary', '') if away_team.get('records') else '' + + # Don't show "0-0" records - set to blank instead + if home_record == "0-0": + home_record = '' + if away_record == "0-0": + away_record = '' game_time = "" game_date = ""