From 2b93eafcdf8b657d9051523cd86f3fd52709b6e7 Mon Sep 17 00:00:00 2001 From: ChuckBuilds <33324927+ChuckBuilds@users.noreply.github.com> Date: Mon, 18 Aug 2025 19:23:20 -0500 Subject: [PATCH] improve odds ticker dynamic duration --- src/music_manager.py | 14 +++++++++++++- src/ncaam_basketball_managers.py | 11 +++++++++++ src/odds_manager.py | 22 +++++++++++++++++----- src/odds_ticker_manager.py | 10 +++++++++- src/soccer_managers.py | 15 +++++++++++++++ src/youtube_display.py | 12 ++++++++++++ templates/index_v2.html | 3 +++ web_interface_v2.py | 24 ++++++++++++++++++++++++ 8 files changed, 104 insertions(+), 7 deletions(-) diff --git a/src/music_manager.py b/src/music_manager.py index ab5a4929..4b24c269 100644 --- a/src/music_manager.py +++ b/src/music_manager.py @@ -6,7 +6,7 @@ import json import os from io import BytesIO import requests -from typing import Union +from typing import Union, Dict, Any, Optional from PIL import Image, ImageEnhance import queue # Added import @@ -15,6 +15,14 @@ from .spotify_client import SpotifyClient from .ytm_client import YTMClient # Removed: import config +# Import the API counter function from web interface +try: + from web_interface_v2 import increment_api_counter +except ImportError: + # Fallback if web interface is not available + def increment_api_counter(kind: str, count: int = 1): + pass + # Configure logging logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) @@ -313,6 +321,10 @@ class MusicManager: try: response = requests.get(url, timeout=5) # 5-second timeout for image download response.raise_for_status() # Raise an exception for bad status codes + + # Increment API counter for music data + increment_api_counter('music', 1) + img_data = BytesIO(response.content) img = Image.open(img_data) diff --git a/src/ncaam_basketball_managers.py b/src/ncaam_basketball_managers.py index 5e7a79f9..d4dc967a 100644 --- a/src/ncaam_basketball_managers.py +++ b/src/ncaam_basketball_managers.py @@ -13,6 +13,14 @@ from src.config_manager import ConfigManager from src.odds_manager import OddsManager import pytz +# Import the API counter function from web interface +try: + from web_interface_v2 import increment_api_counter +except ImportError: + # Fallback if web interface is not available + def increment_api_counter(kind: str, count: int = 1): + pass + # Constants ESPN_NCAAMB_SCOREBOARD_URL = "https://site.api.espn.com/apis/site/v2/sports/basketball/mens-college-basketball/scoreboard" @@ -328,6 +336,9 @@ class BaseNCAAMBasketballManager: response.raise_for_status() data = response.json() + # Increment API counter for sports data + increment_api_counter('sports', 1) + if use_cache: self.cache_manager.set(cache_key, data) diff --git a/src/odds_manager.py b/src/odds_manager.py index b1a221d0..7b11b6b5 100644 --- a/src/odds_manager.py +++ b/src/odds_manager.py @@ -1,13 +1,22 @@ -import requests +import time import logging +import requests import json -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone from src.cache_manager import CacheManager -from src.config_manager import ConfigManager -from typing import Optional, List, Dict, Any +import pytz +from typing import Dict, Any, Optional, List + +# Import the API counter function from web interface +try: + from web_interface_v2 import increment_api_counter +except ImportError: + # Fallback if web interface is not available + def increment_api_counter(kind: str, count: int = 1): + pass class OddsManager: - def __init__(self, cache_manager: CacheManager, config_manager: ConfigManager): + def __init__(self, cache_manager: CacheManager, config_manager=None): self.cache_manager = cache_manager self.config_manager = config_manager self.logger = logging.getLogger(__name__) @@ -31,6 +40,9 @@ class OddsManager: response = requests.get(url, timeout=10) response.raise_for_status() raw_data = response.json() + + # Increment API counter for odds data + increment_api_counter('odds', 1) self.logger.debug(f"Received raw odds data from ESPN: {json.dumps(raw_data, indent=2)}") odds_data = self._extract_espn_data(raw_data) diff --git a/src/odds_ticker_manager.py b/src/odds_ticker_manager.py index 3c7315d5..ef3a9c43 100644 --- a/src/odds_ticker_manager.py +++ b/src/odds_ticker_manager.py @@ -1194,6 +1194,8 @@ class OddsTickerManager: def calculate_dynamic_duration(self): """Calculate the exact time needed to display all odds ticker content""" + logger.debug(f"calculate_dynamic_duration called - dynamic_duration_enabled: {self.dynamic_duration_enabled}, total_scroll_width: {self.total_scroll_width}") + # If dynamic duration is disabled, use fixed duration from config if not self.dynamic_duration_enabled: self.dynamic_duration = self.odds_ticker_config.get('display_duration', 60) @@ -1202,6 +1204,7 @@ class OddsTickerManager: if not self.total_scroll_width: self.dynamic_duration = self.min_duration # Use configured minimum + logger.debug(f"total_scroll_width is 0, using minimum duration: {self.min_duration}s") return try: @@ -1257,7 +1260,12 @@ class OddsTickerManager: logger.debug("get_dynamic_duration called but total_scroll_width is 0, attempting update...") try: # Force an update to get the data and calculate proper duration - self._perform_update() + # Bypass the update interval check for duration calculation + self.games_data = self._fetch_upcoming_games() + self.scroll_position = 0 + self.current_game_index = 0 + self._create_ticker_image() # Create the composite image + logger.debug(f"Force update completed, total_scroll_width: {self.total_scroll_width}px") except Exception as e: logger.error(f"Error updating odds ticker for dynamic duration: {e}") diff --git a/src/soccer_managers.py b/src/soccer_managers.py index 186177fe..66eb276b 100644 --- a/src/soccer_managers.py +++ b/src/soccer_managers.py @@ -14,6 +14,14 @@ from src.config_manager import ConfigManager from src.odds_manager import OddsManager import pytz +# Import the API counter function from web interface +try: + from web_interface_v2 import increment_api_counter +except ImportError: + # Fallback if web interface is not available + def increment_api_counter(kind: str, count: int = 1): + pass + # Constants # ESPN_SOCCER_SCOREBOARD_URL = "https://site.api.espn.com/apis/site/v2/sports/soccer/scoreboards" # Old URL ESPN_SOCCER_LEAGUE_SCOREBOARD_URL_FORMAT = "http://site.api.espn.com/apis/site/v2/sports/soccer/{}/scoreboard" # New format string @@ -192,6 +200,9 @@ class BaseSoccerManager: response = requests.get(url, params=params, timeout=10) # Add timeout response.raise_for_status() data = response.json() + + # Increment API counter for sports data + increment_api_counter('sports', 1) cls.logger.debug(f"[Soccer Map Build] Fetched data for {league_slug}") for event in data.get("events", []): @@ -264,6 +275,10 @@ class BaseSoccerManager: response = requests.get(url, params=params) response.raise_for_status() data = response.json() + + # Increment API counter for sports data + increment_api_counter('sports', 1) + self.logger.info(f"[Soccer] Fetched data from ESPN API for {league_slug} on {fetch_date}") if use_cache: diff --git a/src/youtube_display.py b/src/youtube_display.py index d827c970..3299b499 100644 --- a/src/youtube_display.py +++ b/src/youtube_display.py @@ -8,6 +8,14 @@ from rgbmatrix import RGBMatrix, RGBMatrixOptions import os from typing import Dict, Any +# Import the API counter function from web interface +try: + from web_interface_v2 import increment_api_counter +except ImportError: + # Fallback if web interface is not available + def increment_api_counter(kind: str, count: int = 1): + pass + # Get logger without configuring logger = logging.getLogger(__name__) @@ -57,6 +65,10 @@ class YouTubeDisplay: try: response = requests.get(url) data = response.json() + + # Increment API counter for YouTube data + increment_api_counter('youtube', 1) + if data['items']: channel = data['items'][0] return { diff --git a/templates/index_v2.html b/templates/index_v2.html index 60276621..1b2c71c5 100644 --- a/templates/index_v2.html +++ b/templates/index_v2.html @@ -1996,6 +1996,9 @@