add granular control over records display and troubleshooting odds ticker. Enabled Team Records for all sports

This commit is contained in:
Chuck
2025-07-20 20:52:55 -05:00
parent 5741cdee9a
commit 1dcd79f758
10 changed files with 340 additions and 71 deletions

View File

@@ -24,6 +24,7 @@ class BaseMLBManager:
self.mlb_config = config.get('mlb', {})
self.show_odds = self.mlb_config.get("show_odds", False)
self.favorite_teams = self.mlb_config.get('favorite_teams', [])
self.show_records = self.mlb_config.get('show_records', False)
self.cache_manager = CacheManager()
self.odds_manager = OddsManager(self.cache_manager, self.config)
self.logger = logging.getLogger(__name__)
@@ -315,7 +316,7 @@ class BaseMLBManager:
pass
# Draw records for upcoming and recent games
if game_data['status'] in ['status_scheduled', 'status_final', 'final', 'completed']:
if self.show_records and game_data['status'] in ['status_scheduled', 'status_final', 'final', 'completed']:
try:
record_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
except IOError:

View File

@@ -45,6 +45,7 @@ class BaseNBAManager:
self.show_odds = self.nba_config.get("show_odds", False)
self.test_mode = self.nba_config.get("test_mode", False)
self.logo_dir = self.nba_config.get("logo_dir", "assets/sports/nba_logos")
self.show_records = self.nba_config.get('show_records', False)
self.update_interval = self.nba_config.get("update_interval_seconds", 300)
self.last_update = 0
self.current_game = None
@@ -424,6 +425,8 @@ class BaseNBAManager:
home_team = next(c for c in competitors if c.get("homeAway") == "home")
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 ''
# Format game time and date for display
game_time = ""
@@ -452,9 +455,11 @@ class BaseNBAManager:
"is_within_window": is_within_window,
"home_abbr": home_team["team"]["abbreviation"],
"home_score": home_team.get("score", "0"),
"home_record": home_record,
"home_logo_path": os.path.join(self.logo_dir, f"{home_team['team']['abbreviation']}.png"),
"away_abbr": away_team["team"]["abbreviation"],
"away_score": away_team.get("score", "0"),
"away_record": away_record,
"away_logo_path": os.path.join(self.logo_dir, f"{away_team['team']['abbreviation']}.png"),
"game_time": game_time,
"game_date": game_date
@@ -581,6 +586,30 @@ class BaseNBAManager:
if 'odds' in game and game['odds']:
self._draw_dynamic_odds(draw, game['odds'], self.display_width, self.display_height)
# Draw records if enabled
if self.show_records:
try:
record_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
except IOError:
record_font = ImageFont.load_default()
away_record = game.get('away_record', '')
home_record = game.get('home_record', '')
record_bbox = draw.textbbox((0,0), "0-0", font=record_font)
record_height = record_bbox[3] - record_bbox[1]
record_y = self.display_height - record_height - 1
if away_record:
away_record_x = 2
self._draw_text_with_outline(draw, away_record, (away_record_x, record_y), record_font)
if home_record:
home_record_bbox = draw.textbbox((0,0), home_record, font=record_font)
home_record_width = home_record_bbox[2] - home_record_bbox[0]
home_record_x = self.display_width - home_record_width - 2
self._draw_text_with_outline(draw, home_record, (home_record_x, record_y), record_font)
# Display the image
self.display_manager.image.paste(main_img, (0, 0))
self.display_manager.update_display()

View File

@@ -26,6 +26,7 @@ class BaseNCAABaseballManager:
self.display_manager = display_manager
self.ncaa_baseball_config = config.get('ncaa_baseball_scoreboard', {})
self.show_odds = self.ncaa_baseball_config.get('show_odds', False)
self.show_records = self.ncaa_baseball_config.get('show_records', False)
self.favorite_teams = self.ncaa_baseball_config.get('favorite_teams', [])
self.cache_manager = CacheManager()
self.odds_manager = OddsManager(self.cache_manager, self.config)
@@ -276,6 +277,29 @@ class BaseNCAABaseballManager:
score_y = height - score_font.getmetrics()[0] - 2 # Adjusted for font metrics
self._draw_text_with_outline(draw, score_text, (score_x, score_y), score_font)
if self.show_records and game_data['status'] in ['status_scheduled', 'status_final', 'final', 'completed']:
try:
record_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
except IOError:
record_font = ImageFont.load_default()
away_record = game_data.get('away_record', '')
home_record = game_data.get('home_record', '')
record_bbox = draw.textbbox((0, 0), "0-0", font=record_font)
record_height = record_bbox[3] - record_bbox[1]
record_y = height - record_height - 1
if away_record:
away_record_x = 2
self._draw_text_with_outline(draw, away_record, (away_record_x, record_y), record_font)
if home_record:
home_record_bbox = draw.textbbox((0, 0), home_record, font=record_font)
home_record_width = home_record_bbox[2] - home_record_bbox[0]
home_record_x = width - home_record_width - 2
self._draw_text_with_outline(draw, home_record, (home_record_x, record_y), record_font)
# Draw betting odds if available and enabled
if self.show_odds and 'odds' in game_data:
odds_details = game_data['odds'].get('details', 'N/A')
@@ -393,6 +417,8 @@ class BaseNCAABaseballManager:
home_abbr = home_team['team'].get('abbreviation', 'N/A')
away_abbr = away_team['team'].get('abbreviation', 'N/A')
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 ''
is_favorite_game = (home_abbr in self.favorite_teams or away_abbr in self.favorite_teams)
@@ -455,6 +481,8 @@ class BaseNCAABaseballManager:
'home_team': home_abbr,
'away_score': away_team.get('score', '0'),
'home_score': home_team.get('score', '0'),
'away_record': away_record,
'home_record': home_record,
'status': status,
'status_state': status_state,
'inning': inning,

View File

@@ -97,6 +97,7 @@ class BaseNCAAFBManager: # Renamed class
self.test_mode = self.ncaa_fb_config.get("test_mode", False)
self.logo_dir = self.ncaa_fb_config.get("logo_dir", "assets/sports/ncaa_fbs_logos") # Changed logo dir
self.update_interval = self.ncaa_fb_config.get("update_interval_seconds", 60)
self.show_records = self.ncaa_fb_config.get('show_records', False)
self.last_update = 0
self.current_game = None
self.fonts = self._load_fonts()
@@ -424,6 +425,8 @@ class BaseNCAAFBManager: # Renamed class
home_abbr = home_team["team"]["abbreviation"]
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 ''
# 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):
@@ -497,10 +500,12 @@ class BaseNCAAFBManager: # Renamed class
"is_halftime": status["type"]["state"] == "halftime", # Added halftime check
"home_abbr": home_abbr,
"home_score": home_team.get("score", "0"),
"home_record": home_record,
"home_logo_path": os.path.join(self.logo_dir, f"{home_abbr}.png"),
"home_timeouts": home_timeouts,
"away_abbr": away_abbr,
"away_score": away_team.get("score", "0"),
"away_record": away_record,
"away_logo_path": os.path.join(self.logo_dir, f"{away_abbr}.png"),
"away_timeouts": away_timeouts,
"game_time": game_time,
@@ -1019,6 +1024,30 @@ class NCAAFBRecentManager(BaseNCAAFBManager): # Renamed class
if 'odds' in game and game['odds']:
self._draw_dynamic_odds(draw_overlay, game['odds'], self.display_width, self.display_height)
# Draw records if enabled
if self.show_records:
try:
record_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
except IOError:
record_font = ImageFont.load_default()
away_record = game.get('away_record', '')
home_record = game.get('home_record', '')
record_bbox = draw_overlay.textbbox((0,0), "0-0", font=record_font)
record_height = record_bbox[3] - record_bbox[1]
record_y = self.display_height - record_height - 1
if away_record:
away_record_x = 2
self._draw_text_with_outline(draw_overlay, away_record, (away_record_x, record_y), record_font)
if home_record:
home_record_bbox = draw_overlay.textbbox((0,0), home_record, font=record_font)
home_record_width = home_record_bbox[2] - home_record_bbox[0]
home_record_x = self.display_width - home_record_width - 2
self._draw_text_with_outline(draw_overlay, home_record, (home_record_x, record_y), record_font)
# Composite and display
main_img = Image.alpha_composite(main_img, overlay)
main_img = main_img.convert('RGB')
@@ -1213,6 +1242,30 @@ class NCAAFBUpcomingManager(BaseNCAAFBManager): # Renamed class
if 'odds' in game and game['odds']:
self._draw_dynamic_odds(draw_overlay, game['odds'], self.display_width, self.display_height)
# Draw records if enabled
if self.show_records:
try:
record_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
except IOError:
record_font = ImageFont.load_default()
away_record = game.get('away_record', '')
home_record = game.get('home_record', '')
record_bbox = draw_overlay.textbbox((0,0), "0-0", font=record_font)
record_height = record_bbox[3] - record_bbox[1]
record_y = self.display_height - record_height - 1
if away_record:
away_record_x = 2
self._draw_text_with_outline(draw_overlay, away_record, (away_record_x, record_y), record_font)
if home_record:
home_record_bbox = draw_overlay.textbbox((0,0), home_record, font=record_font)
home_record_width = home_record_bbox[2] - home_record_bbox[0]
home_record_x = self.display_width - home_record_width - 2
self._draw_text_with_outline(draw_overlay, home_record, (home_record_x, record_y), record_font)
# Composite and display
main_img = Image.alpha_composite(main_img, overlay)
main_img = main_img.convert('RGB')

View File

@@ -44,8 +44,9 @@ class BaseNCAAMBasketballManager:
self.is_enabled = self.ncaam_basketball_config.get("enabled", False)
self.show_odds = self.ncaam_basketball_config.get("show_odds", False)
self.test_mode = self.ncaam_basketball_config.get("test_mode", False)
self.logo_dir = self.ncaam_basketball_config.get("logo_dir", "assets/sports/ncaam_logos")
self.update_interval = self.ncaam_basketball_config.get("update_interval_seconds", 300)
self.logo_dir = self.ncaam_basketball_config.get("logo_dir", "assets/sports/ncaa_fbs_logos")
self.update_interval = self.ncaam_basketball_config.get("update_interval_seconds", 60)
self.show_records = self.ncaam_basketball_config.get('show_records', False)
self.last_update = 0
self.current_game = None
self.fonts = self._load_fonts()
@@ -421,6 +422,8 @@ class BaseNCAAMBasketballManager:
home_team = next(c for c in competitors if c.get("homeAway") == "home")
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 ''
# Format game time and date for display
game_time = ""
@@ -450,9 +453,11 @@ class BaseNCAAMBasketballManager:
"is_within_window": is_within_window,
"home_abbr": home_team["team"]["abbreviation"],
"home_score": home_team.get("score", "0"),
"home_record": home_record,
"home_logo_path": os.path.join(self.logo_dir, f"{home_team['team']['abbreviation']}.png"),
"away_abbr": away_team["team"]["abbreviation"],
"away_score": away_team.get("score", "0"),
"away_record": away_record,
"away_logo_path": os.path.join(self.logo_dir, f"{away_team['team']['abbreviation']}.png"),
"game_time": game_time,
"game_date": game_date,
@@ -589,23 +594,32 @@ class BaseNCAAMBasketballManager:
self._draw_text_with_outline(draw, clock, (clock_x, clock_y), self.fonts['time'])
# Display odds if available
if 'odds' in game:
odds = game['odds']
spread = odds.get('spread', {}).get('point', None)
if spread is not None:
# Format spread text
spread_text = f"{spread:+.1f}" if spread > 0 else f"{spread:.1f}"
# Choose color and position based on which team has the spread
if odds.get('spread', {}).get('team') == game['home_abbr']:
text_color = (255, 100, 100) # Reddish
spread_x = self.display_width - draw.textlength(spread_text, font=self.fonts['status']) - 2
else:
text_color = (100, 255, 100) # Greenish
spread_x = 2
spread_y = self.display_height - 8
self._draw_text_with_outline(draw, spread_text, (spread_x, spread_y), self.fonts['status'], fill=text_color)
if 'odds' in game and game['odds']:
self._draw_dynamic_odds(draw, game['odds'], self.display_width, self.display_height)
# Draw records if enabled
if self.show_records:
try:
record_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
except IOError:
record_font = ImageFont.load_default()
away_record = game.get('away_record', '')
home_record = game.get('home_record', '')
record_bbox = draw.textbbox((0,0), "0-0", font=record_font)
record_height = record_bbox[3] - record_bbox[1]
record_y = self.display_height - record_height - 1
if away_record:
away_record_x = 2
self._draw_text_with_outline(draw, away_record, (away_record_x, record_y), record_font)
if home_record:
home_record_bbox = draw.textbbox((0,0), home_record, font=record_font)
home_record_width = home_record_bbox[2] - home_record_bbox[0]
home_record_x = self.display_width - home_record_width - 2
self._draw_text_with_outline(draw, home_record, (home_record_x, record_y), record_font)
# Display the image
self.display_manager.image.paste(main_img, (0, 0))

View File

@@ -97,6 +97,7 @@ class BaseNFLManager: # Renamed class
self.test_mode = self.nfl_config.get("test_mode", False)
self.logo_dir = self.nfl_config.get("logo_dir", "assets/sports/nfl_logos") # Changed logo dir
self.update_interval = self.nfl_config.get("update_interval_seconds", 60)
self.show_records = self.nfl_config.get('show_records', False)
self.last_update = 0
self.current_game = None
self.fonts = self._load_fonts()
@@ -424,6 +425,8 @@ class BaseNFLManager: # Renamed class
home_abbr = home_team["team"]["abbreviation"]
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 ''
# 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):
@@ -498,10 +501,12 @@ class BaseNFLManager: # Renamed class
"is_halftime": status["type"]["state"] == "halftime", # Added halftime check
"home_abbr": home_abbr,
"home_score": home_team.get("score", "0"),
"home_record": home_record,
"home_logo_path": os.path.join(self.logo_dir, f"{home_abbr}.png"),
"home_timeouts": home_timeouts,
"away_abbr": away_abbr,
"away_score": away_team.get("score", "0"),
"away_record": away_record,
"away_logo_path": os.path.join(self.logo_dir, f"{away_abbr}.png"),
"away_timeouts": away_timeouts,
"game_time": game_time,
@@ -1008,6 +1013,30 @@ class NFLRecentManager(BaseNFLManager): # Renamed class
if 'odds' in game and game['odds']:
self._draw_dynamic_odds(draw_overlay, game['odds'], self.display_width, self.display_height)
# Draw records if enabled
if self.show_records:
try:
record_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
except IOError:
record_font = ImageFont.load_default()
away_record = game.get('away_record', '')
home_record = game.get('home_record', '')
record_bbox = draw_overlay.textbbox((0,0), "0-0", font=record_font)
record_height = record_bbox[3] - record_bbox[1]
record_y = self.display_height - record_height - 1
if away_record:
away_record_x = 2
self._draw_text_with_outline(draw_overlay, away_record, (away_record_x, record_y), record_font)
if home_record:
home_record_bbox = draw_overlay.textbbox((0,0), home_record, font=record_font)
home_record_width = home_record_bbox[2] - home_record_bbox[0]
home_record_x = self.display_width - home_record_width - 2
self._draw_text_with_outline(draw_overlay, home_record, (home_record_x, record_y), record_font)
# Composite and display
main_img = Image.alpha_composite(main_img, overlay)
main_img = main_img.convert('RGB')
@@ -1205,6 +1234,30 @@ class NFLUpcomingManager(BaseNFLManager): # Renamed class
if 'odds' in game and game['odds']:
self._draw_dynamic_odds(draw_overlay, game['odds'], self.display_width, self.display_height)
# Draw records if enabled
if self.show_records:
try:
record_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
except IOError:
record_font = ImageFont.load_default()
away_record = game.get('away_record', '')
home_record = game.get('home_record', '')
record_bbox = draw_overlay.textbbox((0,0), "0-0", font=record_font)
record_height = record_bbox[3] - record_bbox[1]
record_y = self.display_height - record_height - 1
if away_record:
away_record_x = 2
self._draw_text_with_outline(draw_overlay, away_record, (away_record_x, record_y), record_font)
if home_record:
home_record_bbox = draw_overlay.textbbox((0,0), home_record, font=record_font)
home_record_width = home_record_bbox[2] - home_record_bbox[0]
home_record_x = self.display_width - home_record_width - 2
self._draw_text_with_outline(draw_overlay, home_record, (home_record_x, record_y), record_font)
# Composite and display
main_img = Image.alpha_composite(main_img, overlay)
main_img = main_img.convert('RGB')

View File

@@ -95,6 +95,7 @@ class BaseNHLManager:
self.test_mode = self.nhl_config.get("test_mode", False) # Use test_mode from config
self.logo_dir = self.nhl_config.get("logo_dir", "assets/sports/nhl_logos")
self.update_interval = self.nhl_config.get("update_interval_seconds", 60)
self.show_records = self.nhl_config.get('show_records', False)
self.last_update = 0
self.current_game = None
self.fonts = self._load_fonts()
@@ -364,6 +365,8 @@ class BaseNHLManager:
home_team = next(c for c in competitors if c.get("homeAway") == "home")
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 ''
# Format game time and date for display
game_time = ""
@@ -400,9 +403,11 @@ class BaseNHLManager:
"is_within_window": is_within_window,
"home_abbr": home_team["team"]["abbreviation"],
"home_score": home_team.get("score", "0"),
"home_record": home_record,
"home_logo_path": os.path.join(self.logo_dir, f"{home_team['team']['abbreviation']}.png"),
"away_abbr": away_team["team"]["abbreviation"],
"away_score": away_team.get("score", "0"),
"away_record": away_record,
"away_logo_path": os.path.join(self.logo_dir, f"{away_team['team']['abbreviation']}.png"),
"game_time": game_time,
"game_date": game_date,
@@ -551,6 +556,30 @@ class BaseNHLManager:
spread_y = self.display_height - 8
self._draw_text_with_outline(draw, spread_text, (spread_x, spread_y), self.fonts['status'], fill=text_color)
# Draw records if enabled
if self.show_records:
try:
record_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
except IOError:
record_font = ImageFont.load_default()
away_record = game.get('away_record', '')
home_record = game.get('home_record', '')
record_bbox = draw.textbbox((0,0), "0-0", font=record_font)
record_height = record_bbox[3] - record_bbox[1]
record_y = self.display_height - record_height - 1
if away_record:
away_record_x = 2
self._draw_text_with_outline(draw, away_record, (away_record_x, record_y), record_font)
if home_record:
home_record_bbox = draw.textbbox((0,0), home_record, font=record_font)
home_record_width = home_record_bbox[2] - home_record_bbox[0]
home_record_x = self.display_width - home_record_width - 2
self._draw_text_with_outline(draw, home_record, (home_record_x, record_y), record_font)
# Display the image
self.display_manager.image.paste(main_img, (0, 0))
self.display_manager.update_display()

View File

@@ -102,14 +102,30 @@ class OddsTickerManager:
# This is a simplified implementation; a more robust solution would cache team data
try:
sport = 'baseball' if league == 'mlb' else 'football' if league in ['nfl', 'college-football'] else 'basketball'
url = f"https://site.api.espn.com/apis/site/v2/sports/{sport}/{league}/teams/{team_abbr}"
# Use a more specific endpoint for college sports
if league == 'college-football':
url = f"https://site.api.espn.com/apis/site/v2/sports/football/college-football/teams/{team_abbr}"
else:
url = f"https://site.api.espn.com/apis/site/v2/sports/{sport}/{league}/teams/{team_abbr}"
response = requests.get(url, timeout=10)
response.raise_for_status()
data = response.json()
record = data.get('team', {}).get('record', {}).get('summary', 'N/A')
return record
# Different path for college sports records
if league == 'college-football':
record_items = data.get('team', {}).get('record', {}).get('items', [])
if record_items:
return record_items[0].get('summary', 'N/A')
else:
return 'N/A'
else:
record = data.get('team', {}).get('record', {}).get('summary', 'N/A')
return record
except Exception as e:
logger.error(f"Error fetching record for {team_abbr}: {e}")
logger.error(f"Error fetching record for {team_abbr} in league {league}: {e}")
return "N/A"
def _get_team_logo(self, team_abbr: str, logo_dir: str) -> Optional[Image.Image]:
@@ -219,6 +235,10 @@ class OddsTickerManager:
home_abbr = home_team['team']['abbreviation']
away_abbr = away_team['team']['abbreviation']
# Get records directly from the scoreboard feed
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 ''
# Check if this game involves favorite teams BEFORE fetching odds
if self.show_favorite_teams_only:
favorite_teams = league_config.get('favorite_teams', [])
@@ -253,10 +273,6 @@ class OddsTickerManager:
logger.debug(f"Game {game_id} has no valid odds data, setting odds to None")
odds_data = None
# Fetch team records
home_record = self._fetch_team_record(home_abbr, league)
away_record = self._fetch_team_record(away_abbr, league)
game_data = {
'id': game_id,
'league': league_config['league'],
@@ -385,29 +401,34 @@ class OddsTickerManager:
# "vs." text
vs_text = "vs."
vs_width = temp_draw.textlength(vs_text, font=vs_font)
vs_width = int(temp_draw.textlength(vs_text, font=vs_font))
# Team and record text
away_team_text = f"{game.get('away_team', 'N/A')} ({game.get('away_record', '')})"
home_team_text = f"{game.get('home_team', 'N/A')} ({game.get('home_record', '')})"
away_team_width = temp_draw.textlength(away_team_text, font=team_font)
home_team_width = temp_draw.textlength(home_team_text, font=team_font)
away_team_text = f"{game.get('away_team', 'N/A')} ({game.get('away_record', '') or 'N/A'})"
home_team_text = f"{game.get('home_team', 'N/A')} ({game.get('home_record', '') or 'N/A'})"
away_team_width = int(temp_draw.textlength(away_team_text, font=team_font))
home_team_width = int(temp_draw.textlength(home_team_text, font=team_font))
team_info_width = max(away_team_width, home_team_width)
# Odds text
odds = game.get('odds') or {}
home_team_odds = odds.get('home_team_odds', {})
away_team_odds = odds.get('away_team_odds', {})
home_spread = home_team_odds.get('spread_odds')
away_spread = away_team_odds.get('spread_odds')
# Determine the favorite and get the spread
home_spread = home_team_odds.get('point_spread')
away_spread = away_team_odds.get('point_spread')
# Check for valid spread values before comparing
home_favored = isinstance(home_spread, (int, float)) and home_spread < 0
away_favored = isinstance(away_spread, (int, float)) and away_spread < 0
over_under = odds.get('over_under')
home_favored = home_spread is not None and home_spread < 0
away_favored = away_spread is not None and away_spread < 0
away_odds_text = ""
home_odds_text = ""
# Simplified odds placement logic
if home_favored:
home_odds_text = f"{home_spread}"
if over_under:
@@ -416,11 +437,11 @@ class OddsTickerManager:
away_odds_text = f"{away_spread}"
if over_under:
home_odds_text = f"O/U {over_under}"
elif over_under: # No clear favorite, put O/U on home line
elif over_under:
home_odds_text = f"O/U {over_under}"
away_odds_width = temp_draw.textlength(away_odds_text, font=odds_font)
home_odds_width = temp_draw.textlength(home_odds_text, font=odds_font)
away_odds_width = int(temp_draw.textlength(away_odds_text, font=odds_font))
home_odds_width = int(temp_draw.textlength(home_odds_text, font=odds_font))
odds_width = max(away_odds_width, home_odds_width)
# --- Calculate total width ---
@@ -463,8 +484,12 @@ class OddsTickerManager:
odds_font_height = odds_font.size if hasattr(odds_font, 'size') else 6
odds_y_away = 2
odds_y_home = height - odds_font_height - 2
draw.text((current_x, odds_y_away), away_odds_text, font=odds_font, fill=(255, 255, 0)) # Yellow for odds
draw.text((current_x, odds_y_home), home_odds_text, font=odds_font, fill=(0, 255, 0)) # Green for favorite
# Use a consistent color for all odds text
odds_color = (255, 255, 0) # Yellow
draw.text((current_x, odds_y_away), away_odds_text, font=odds_font, fill=odds_color)
draw.text((current_x, odds_y_home), home_odds_text, font=odds_font, fill=odds_color)
return image

View File

@@ -115,6 +115,7 @@ class BaseSoccerManager:
self.test_mode = self.soccer_config.get("test_mode", False)
self.logo_dir = self.soccer_config.get("logo_dir", "assets/sports/soccer_logos") # Soccer logos
self.update_interval = self.soccer_config.get("update_interval_seconds", 60) # General fallback
self.show_records = self.soccer_config.get('show_records', False)
self.last_update = 0
self.current_game = None
self.fonts = self._load_fonts()
@@ -552,6 +553,8 @@ class BaseSoccerManager:
home_team = next(c for c in competitors if c.get("homeAway") == "home")
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 ''
game_time = ""
game_date = ""
@@ -589,9 +592,11 @@ class BaseSoccerManager:
"is_within_window": is_within_window,
"home_abbr": home_team["team"]["abbreviation"],
"home_score": home_team.get("score", "0"),
"home_record": home_record,
"home_logo": self._load_and_resize_logo(home_team["team"]["abbreviation"]),
"away_abbr": away_team["team"]["abbreviation"],
"away_score": away_team.get("score", "0"),
"away_record": away_record,
"away_logo": self._load_and_resize_logo(away_team["team"]["abbreviation"]),
"game_time": game_time, # Formatted local time (e.g., 2:30pm)
"game_date": game_date, # Formatted local date (e.g., 7/21)
@@ -732,6 +737,30 @@ class BaseSoccerManager:
spread_y = self.display_height - 8
self._draw_text_with_outline(draw, spread_text, (spread_x, spread_y), self.fonts['status'], fill=text_color)
# Draw records if enabled
if self.show_records:
try:
record_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
except IOError:
record_font = ImageFont.load_default()
away_record = game.get('away_record', '')
home_record = game.get('home_record', '')
record_bbox = draw.textbbox((0,0), "0-0", font=record_font)
record_height = record_bbox[3] - record_bbox[1]
record_y = self.display_height - record_height - 1
if away_record:
away_record_x = 2
self._draw_text_with_outline(draw, away_record, (away_record_x, record_y), record_font)
if home_record:
home_record_bbox = draw.textbbox((0,0), home_record, font=record_font)
home_record_width = home_record_bbox[2] - home_record_bbox[0]
home_record_x = self.display_width - home_record_width - 2
self._draw_text_with_outline(draw, home_record, (home_record_x, record_y), record_font)
# --- Display Image ---
self.display_manager.image.paste(main_img, (0, 0))
self.display_manager.update_display()