milb logging and manual cache clearing

This commit is contained in:
Chuck
2025-08-09 10:44:58 -05:00
parent a672abba6a
commit b4d5aef876
4 changed files with 168 additions and 1 deletions

131
clear_cache.py Normal file
View File

@@ -0,0 +1,131 @@
#!/usr/bin/env python3
"""
Cache clearing utility for LEDMatrix
This script allows manual clearing of specific cache keys or all cache data.
"""
import os
import sys
import json
import argparse
from pathlib import Path
# Add the src directory to the path so we can import our modules
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))
from cache_manager import CacheManager
def list_cache_keys(cache_dir):
"""List all available cache keys."""
if not os.path.exists(cache_dir):
print(f"Cache directory does not exist: {cache_dir}")
return []
cache_files = []
for file in os.listdir(cache_dir):
if file.endswith('.json'):
cache_files.append(file[:-5]) # Remove .json extension
return cache_files
def clear_specific_cache(cache_manager, key):
"""Clear a specific cache key."""
try:
cache_manager.clear_cache(key)
print(f"✓ Cleared cache key: {key}")
return True
except Exception as e:
print(f"✗ Error clearing cache key '{key}': {e}")
return False
def clear_all_cache(cache_manager):
"""Clear all cache data."""
try:
cache_manager.clear_cache()
print("✓ Cleared all cache data")
return True
except Exception as e:
print(f"✗ Error clearing all cache: {e}")
return False
def show_cache_info(cache_manager, key=None):
"""Show information about cache entries."""
if key:
try:
data = cache_manager.get(key)
if data is not None:
print(f"Cache key '{key}' exists with data type: {type(data)}")
if isinstance(data, dict):
print(f" Keys: {list(data.keys())}")
if 'games' in data:
print(f" Number of games: {len(data['games']) if isinstance(data['games'], dict) else 'N/A'}")
elif isinstance(data, list):
print(f" Number of items: {len(data)}")
else:
print(f" Data: {str(data)[:100]}...")
else:
print(f"Cache key '{key}' does not exist or is expired")
except Exception as e:
print(f"Error checking cache key '{key}': {e}")
else:
# Show all cache keys
cache_dir = cache_manager.cache_dir
keys = list_cache_keys(cache_dir)
if keys:
print("Available cache keys:")
for key in sorted(keys):
print(f" - {key}")
else:
print("No cache keys found")
def main():
parser = argparse.ArgumentParser(description='Clear LEDMatrix cache data')
parser.add_argument('--list', '-l', action='store_true',
help='List all available cache keys')
parser.add_argument('--clear-all', '-a', action='store_true',
help='Clear all cache data')
parser.add_argument('--clear', '-c', type=str, metavar='KEY',
help='Clear a specific cache key')
parser.add_argument('--info', '-i', type=str, metavar='KEY',
help='Show information about a specific cache key')
parser.add_argument('--cache-dir', type=str, default='cache',
help='Cache directory path (default: cache)')
args = parser.parse_args()
# Initialize cache manager
cache_manager = CacheManager(cache_dir=args.cache_dir)
if args.list:
show_cache_info(cache_manager)
elif args.clear_all:
print("Clearing all cache data...")
clear_all_cache(cache_manager)
elif args.clear:
print(f"Clearing cache key: {args.clear}")
clear_specific_cache(cache_manager, args.clear)
elif args.info:
show_cache_info(cache_manager, args.info)
else:
# Default: show available options
print("LEDMatrix Cache Utility")
print("=" * 30)
print()
print("Available commands:")
print(" --list, -l List all cache keys")
print(" --clear-all, -a Clear all cache data")
print(" --clear KEY, -c Clear specific cache key")
print(" --info KEY, -i Show info about cache key")
print()
print("Examples:")
print(" python clear_cache.py --list")
print(" python clear_cache.py --clear milb_live_api_data")
print(" python clear_cache.py --clear-all")
print(" python clear_cache.py --info milb_upcoming_api_data")
print()
# Show current cache status
show_cache_info(cache_manager)
if __name__ == "__main__":
main()

View File

@@ -1104,7 +1104,13 @@ class DisplayController:
logger.debug(f"[DisplayController] Calling MiLB live display with {len(self.milb_live.live_games)} live games") logger.debug(f"[DisplayController] Calling MiLB live display with {len(self.milb_live.live_games)} live games")
self.milb_live.display(force_clear=self.force_clear) self.milb_live.display(force_clear=self.force_clear)
elif self.current_display_mode == 'milb_live' and self.milb_live: elif self.current_display_mode == 'milb_live' and self.milb_live:
logger.debug(f"[DisplayController] MiLB live manager exists but has {len(self.milb_live.live_games)} live games, skipping display") logger.debug(f"[DisplayController] MiLB live manager exists but has {len(self.milb_live.live_games)} live games, switching to next mode")
# Switch to next mode since there are no live games
self.current_mode_index = (self.current_mode_index + 1) % len(self.available_modes)
self.current_display_mode = self.available_modes[self.current_mode_index]
self.force_clear = True
self.last_switch = current_time
logger.info(f"[DisplayController] Switched from milb_live (no games) to {self.current_display_mode}")
elif self.current_display_mode == 'ncaa_fb_upcoming' and self.ncaa_fb_upcoming: elif self.current_display_mode == 'ncaa_fb_upcoming' and self.ncaa_fb_upcoming:
self.ncaa_fb_upcoming.display(force_clear=self.force_clear) self.ncaa_fb_upcoming.display(force_clear=self.force_clear)
elif self.current_display_mode == 'ncaam_basketball_recent' and self.ncaam_basketball_recent: elif self.current_display_mode == 'ncaam_basketball_recent' and self.ncaam_basketball_recent:

View File

@@ -534,6 +534,9 @@ class BaseMiLBManager:
if not self.favorite_teams or is_favorite_game: if not self.favorite_teams or is_favorite_game:
status_obj = game['status'] status_obj = game['status']
status_state = status_obj.get('abstractGameState', 'Final') status_state = status_obj.get('abstractGameState', 'Final')
# Debug: Log the original status information
self.logger.debug(f"[MiLB] Status mapping for {away_abbr} @ {home_abbr}: original abstractGameState='{status_state}', full status_obj={status_obj}")
mapped_status = 'unknown' mapped_status = 'unknown'
mapped_status_state = 'unknown' mapped_status_state = 'unknown'
@@ -737,8 +740,29 @@ class MiLBLiveManager(BaseMiLBManager):
# Find all live games involving favorite teams # Find all live games involving favorite teams
new_live_games = [] new_live_games = []
for game in games.values(): for game in games.values():
# Debug: Log the status for all games to understand what's happening
self.logger.debug(f"[MiLB] Game status check: {game['away_team']} @ {game['home_team']} - status_state='{game['status_state']}', status='{game['status']}', abstractGameState='{game.get('abstractGameState', 'N/A')}'")
# Only process games that are actually in progress # Only process games that are actually in progress
if game['status_state'] == 'in' and game['status'] == 'status_in_progress': if game['status_state'] == 'in' and game['status'] == 'status_in_progress':
# Additional check: Verify the game is from today or very recent
game_date_str = game.get('start_time', '')
if game_date_str:
try:
# Parse the game date (assuming it's in ISO format)
game_date = datetime.fromisoformat(game_date_str.replace('Z', '+00:00'))
current_utc = datetime.now(timezone.utc)
hours_diff = (current_utc - game_date).total_seconds() / 3600
# If game is more than 6 hours old, it's probably not actually live
if hours_diff > 6:
self.logger.warning(f"[MiLB] Skipping potentially stale live game: {game['away_team']} @ {game['home_team']} - game date: {game_date_str}, hours old: {hours_diff:.1f}")
continue
else:
self.logger.debug(f"[MiLB] Game time check passed: {game['away_team']} @ {game['home_team']} - hours old: {hours_diff:.1f}")
except Exception as e:
self.logger.warning(f"[MiLB] Could not parse game date {game_date_str}: {e}")
self.logger.debug(f"[MiLB] Found live game: {game['away_team']} @ {game['home_team']}") self.logger.debug(f"[MiLB] Found live game: {game['away_team']} @ {game['home_team']}")
if not self.favorite_teams or ( if not self.favorite_teams or (
game['home_team'] in self.favorite_teams or game['home_team'] in self.favorite_teams or

View File

@@ -97,6 +97,12 @@ class BaseSoccerManager:
self.config_manager = ConfigManager(config) self.config_manager = ConfigManager(config)
def _get_timezone(self):
try:
return pytz.timezone(self.config_manager.get_timezone())
except pytz.UnknownTimeZoneError:
return pytz.utc
def _fetch_odds(self, game: Dict) -> None: def _fetch_odds(self, game: Dict) -> None:
"""Fetch odds for a game and attach it to the game dictionary.""" """Fetch odds for a game and attach it to the game dictionary."""
# Check if odds should be shown for this sport # Check if odds should be shown for this sport