mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-04-12 13:42:59 +00:00
Implement NHL managers with proper display handling - Add BaseNHLManager with common functionality - Add NHLLiveManager for live games (30s updates) - Add NHLRecentManager for recent games (1h updates) - Add NHLUpcomingManager for upcoming games (1h updates) - Fix display dimensions handling from config - Add proper error handling and logging - Support test mode and favorite teams filtering
This commit is contained in:
@@ -25,8 +25,18 @@ class BaseNHLManager:
|
|||||||
self.current_game = None
|
self.current_game = None
|
||||||
self.fonts = self._load_fonts()
|
self.fonts = self._load_fonts()
|
||||||
self.favorite_teams = self.nhl_config.get("favorite_teams", [])
|
self.favorite_teams = self.nhl_config.get("favorite_teams", [])
|
||||||
|
|
||||||
|
# Get display dimensions from config
|
||||||
|
display_config = config.get("display", {})
|
||||||
|
hardware_config = display_config.get("hardware", {})
|
||||||
|
cols = hardware_config.get("cols", 64)
|
||||||
|
chain = hardware_config.get("chain_length", 1)
|
||||||
|
self.display_width = int(cols * chain)
|
||||||
|
self.display_height = hardware_config.get("rows", 32)
|
||||||
|
|
||||||
logging.info(f"[NHL] Test mode: {'enabled' if self.test_mode else 'disabled'}")
|
logging.info(f"[NHL] Test mode: {'enabled' if self.test_mode else 'disabled'}")
|
||||||
logging.info(f"[NHL] Favorite teams: {self.favorite_teams}")
|
logging.info(f"[NHL] Favorite teams: {self.favorite_teams}")
|
||||||
|
logging.info(f"[NHL] Display dimensions: {self.display_width}x{self.display_height}")
|
||||||
|
|
||||||
def _load_fonts(self):
|
def _load_fonts(self):
|
||||||
"""Load fonts used by the scoreboard."""
|
"""Load fonts used by the scoreboard."""
|
||||||
@@ -132,6 +142,66 @@ class BaseNHLManager:
|
|||||||
logging.error(f"[NHL] Error extracting game details: {e}")
|
logging.error(f"[NHL] Error extracting game details: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def display(self, force_clear: bool = False):
|
||||||
|
"""Display game information."""
|
||||||
|
if not self.current_game:
|
||||||
|
logging.warning("[NHL] No game data available to display")
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Create a new black image
|
||||||
|
img = Image.new('RGB', (self.display_width, self.display_height), 'black')
|
||||||
|
draw = ImageDraw.Draw(img)
|
||||||
|
|
||||||
|
# Calculate logo sizes
|
||||||
|
max_size = (self.display_width // 3, self.display_height // 2)
|
||||||
|
|
||||||
|
# Load and resize logos
|
||||||
|
home_logo = self._load_and_resize_logo(self.current_game["home_logo_path"], max_size)
|
||||||
|
away_logo = self._load_and_resize_logo(self.current_game["away_logo_path"], max_size)
|
||||||
|
|
||||||
|
# Draw home team logo
|
||||||
|
if home_logo:
|
||||||
|
home_x = self.display_width // 4 - home_logo.width // 2
|
||||||
|
home_y = self.display_height // 4 - home_logo.height // 2
|
||||||
|
temp_img = Image.new('RGB', (self.display_width, self.display_height), 'black')
|
||||||
|
temp_draw = ImageDraw.Draw(temp_img)
|
||||||
|
temp_draw.im.paste(home_logo, (home_x, home_y), home_logo)
|
||||||
|
draw.im.paste(temp_img, (0, 0))
|
||||||
|
|
||||||
|
# Draw away team logo
|
||||||
|
if away_logo:
|
||||||
|
away_x = self.display_width // 4 - away_logo.width // 2
|
||||||
|
away_y = 3 * self.display_height // 4 - away_logo.height // 2
|
||||||
|
temp_img = Image.new('RGB', (self.display_width, self.display_height), 'black')
|
||||||
|
temp_draw = ImageDraw.Draw(temp_img)
|
||||||
|
temp_draw.im.paste(away_logo, (away_x, away_y), away_logo)
|
||||||
|
draw.im.paste(temp_img, (0, 0))
|
||||||
|
|
||||||
|
# Draw scores
|
||||||
|
home_score = str(self.current_game["home_score"])
|
||||||
|
away_score = str(self.current_game["away_score"])
|
||||||
|
|
||||||
|
home_score_x = self.display_width // 2 - 10
|
||||||
|
home_score_y = self.display_height // 4 - 8
|
||||||
|
away_score_x = self.display_width // 2 - 10
|
||||||
|
away_score_y = 3 * self.display_height // 4 - 8
|
||||||
|
|
||||||
|
draw.text((home_score_x, home_score_y), home_score, font=self.fonts['score'], fill=(255, 255, 255))
|
||||||
|
draw.text((away_score_x, away_score_y), away_score, font=self.fonts['score'], fill=(255, 255, 255))
|
||||||
|
|
||||||
|
# Draw game status
|
||||||
|
status_x = self.display_width // 2 - 20
|
||||||
|
status_y = self.display_height // 2 - 8
|
||||||
|
draw.text((status_x, status_y), self.current_game["status_text"], font=self.fonts['status'], fill=(255, 255, 255))
|
||||||
|
|
||||||
|
# Display the image
|
||||||
|
self.display_manager.display_image(img)
|
||||||
|
logging.debug("[NHL] Successfully displayed game")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"[NHL] Error displaying game: {e}", exc_info=True)
|
||||||
|
|
||||||
class NHLLiveManager(BaseNHLManager):
|
class NHLLiveManager(BaseNHLManager):
|
||||||
"""Manager for live NHL games."""
|
"""Manager for live NHL games."""
|
||||||
def __init__(self, config: dict, display_manager):
|
def __init__(self, config: dict, display_manager):
|
||||||
@@ -207,11 +277,11 @@ class NHLLiveManager(BaseNHLManager):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# Create a new black image
|
# Create a new black image
|
||||||
img = Image.new('RGB', (self.display_manager.width, self.display_manager.height), 'black')
|
img = Image.new('RGB', (self.display_width, self.display_height), 'black')
|
||||||
draw = ImageDraw.Draw(img)
|
draw = ImageDraw.Draw(img)
|
||||||
|
|
||||||
# Calculate logo sizes
|
# Calculate logo sizes
|
||||||
max_size = (self.display_manager.width // 3, self.display_manager.height // 2)
|
max_size = (self.display_width // 3, self.display_height // 2)
|
||||||
|
|
||||||
# Load and resize logos
|
# Load and resize logos
|
||||||
home_logo = self._load_and_resize_logo(self.current_game["home_logo_path"], max_size)
|
home_logo = self._load_and_resize_logo(self.current_game["home_logo_path"], max_size)
|
||||||
@@ -219,18 +289,18 @@ class NHLLiveManager(BaseNHLManager):
|
|||||||
|
|
||||||
# Draw home team logo
|
# Draw home team logo
|
||||||
if home_logo:
|
if home_logo:
|
||||||
home_x = self.display_manager.width // 4 - home_logo.width // 2
|
home_x = self.display_width // 4 - home_logo.width // 2
|
||||||
home_y = self.display_manager.height // 4 - home_logo.height // 2
|
home_y = self.display_height // 4 - home_logo.height // 2
|
||||||
temp_img = Image.new('RGB', (self.display_manager.width, self.display_manager.height), 'black')
|
temp_img = Image.new('RGB', (self.display_width, self.display_height), 'black')
|
||||||
temp_draw = ImageDraw.Draw(temp_img)
|
temp_draw = ImageDraw.Draw(temp_img)
|
||||||
temp_draw.im.paste(home_logo, (home_x, home_y), home_logo)
|
temp_draw.im.paste(home_logo, (home_x, home_y), home_logo)
|
||||||
draw.im.paste(temp_img, (0, 0))
|
draw.im.paste(temp_img, (0, 0))
|
||||||
|
|
||||||
# Draw away team logo
|
# Draw away team logo
|
||||||
if away_logo:
|
if away_logo:
|
||||||
away_x = self.display_manager.width // 4 - away_logo.width // 2
|
away_x = self.display_width // 4 - away_logo.width // 2
|
||||||
away_y = 3 * self.display_manager.height // 4 - away_logo.height // 2
|
away_y = 3 * self.display_height // 4 - away_logo.height // 2
|
||||||
temp_img = Image.new('RGB', (self.display_manager.width, self.display_manager.height), 'black')
|
temp_img = Image.new('RGB', (self.display_width, self.display_height), 'black')
|
||||||
temp_draw = ImageDraw.Draw(temp_img)
|
temp_draw = ImageDraw.Draw(temp_img)
|
||||||
temp_draw.im.paste(away_logo, (away_x, away_y), away_logo)
|
temp_draw.im.paste(away_logo, (away_x, away_y), away_logo)
|
||||||
draw.im.paste(temp_img, (0, 0))
|
draw.im.paste(temp_img, (0, 0))
|
||||||
@@ -239,10 +309,10 @@ class NHLLiveManager(BaseNHLManager):
|
|||||||
home_score = str(self.current_game["home_score"])
|
home_score = str(self.current_game["home_score"])
|
||||||
away_score = str(self.current_game["away_score"])
|
away_score = str(self.current_game["away_score"])
|
||||||
|
|
||||||
home_score_x = self.display_manager.width // 2 - 10
|
home_score_x = self.display_width // 2 - 10
|
||||||
home_score_y = self.display_manager.height // 4 - 8
|
home_score_y = self.display_height // 4 - 8
|
||||||
away_score_x = self.display_manager.width // 2 - 10
|
away_score_x = self.display_width // 2 - 10
|
||||||
away_score_y = 3 * self.display_manager.height // 4 - 8
|
away_score_y = 3 * self.display_height // 4 - 8
|
||||||
|
|
||||||
draw.text((home_score_x, home_score_y), home_score, font=self.fonts['score'], fill=(255, 255, 255))
|
draw.text((home_score_x, home_score_y), home_score, font=self.fonts['score'], fill=(255, 255, 255))
|
||||||
draw.text((away_score_x, away_score_y), away_score, font=self.fonts['score'], fill=(255, 255, 255))
|
draw.text((away_score_x, away_score_y), away_score, font=self.fonts['score'], fill=(255, 255, 255))
|
||||||
@@ -252,8 +322,8 @@ class NHLLiveManager(BaseNHLManager):
|
|||||||
clock = self.current_game["clock"]
|
clock = self.current_game["clock"]
|
||||||
period_str = f"{period}{'st' if period==1 else 'nd' if period==2 else 'rd' if period==3 else 'th'}"
|
period_str = f"{period}{'st' if period==1 else 'nd' if period==2 else 'rd' if period==3 else 'th'}"
|
||||||
|
|
||||||
status_x = self.display_manager.width // 2 - 20
|
status_x = self.display_width // 2 - 20
|
||||||
status_y = self.display_manager.height // 2 - 8
|
status_y = self.display_height // 2 - 8
|
||||||
draw.text((status_x, status_y), f"{period_str} {clock}", font=self.fonts['status'], fill=(255, 255, 255))
|
draw.text((status_x, status_y), f"{period_str} {clock}", font=self.fonts['status'], fill=(255, 255, 255))
|
||||||
|
|
||||||
# Display the image
|
# Display the image
|
||||||
@@ -336,11 +406,11 @@ class NHLRecentManager(BaseNHLManager):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# Create a new black image
|
# Create a new black image
|
||||||
img = Image.new('RGB', (self.display_manager.width, self.display_manager.height), 'black')
|
img = Image.new('RGB', (self.display_width, self.display_height), 'black')
|
||||||
draw = ImageDraw.Draw(img)
|
draw = ImageDraw.Draw(img)
|
||||||
|
|
||||||
# Calculate logo sizes
|
# Calculate logo sizes
|
||||||
max_size = (self.display_manager.width // 3, self.display_manager.height // 2)
|
max_size = (self.display_width // 3, self.display_height // 2)
|
||||||
|
|
||||||
# Load and resize logos
|
# Load and resize logos
|
||||||
home_logo = self._load_and_resize_logo(self.current_game["home_logo_path"], max_size)
|
home_logo = self._load_and_resize_logo(self.current_game["home_logo_path"], max_size)
|
||||||
@@ -348,18 +418,18 @@ class NHLRecentManager(BaseNHLManager):
|
|||||||
|
|
||||||
# Draw home team logo
|
# Draw home team logo
|
||||||
if home_logo:
|
if home_logo:
|
||||||
home_x = self.display_manager.width // 4 - home_logo.width // 2
|
home_x = self.display_width // 4 - home_logo.width // 2
|
||||||
home_y = self.display_manager.height // 4 - home_logo.height // 2
|
home_y = self.display_height // 4 - home_logo.height // 2
|
||||||
temp_img = Image.new('RGB', (self.display_manager.width, self.display_manager.height), 'black')
|
temp_img = Image.new('RGB', (self.display_width, self.display_height), 'black')
|
||||||
temp_draw = ImageDraw.Draw(temp_img)
|
temp_draw = ImageDraw.Draw(temp_img)
|
||||||
temp_draw.im.paste(home_logo, (home_x, home_y), home_logo)
|
temp_draw.im.paste(home_logo, (home_x, home_y), home_logo)
|
||||||
draw.im.paste(temp_img, (0, 0))
|
draw.im.paste(temp_img, (0, 0))
|
||||||
|
|
||||||
# Draw away team logo
|
# Draw away team logo
|
||||||
if away_logo:
|
if away_logo:
|
||||||
away_x = self.display_manager.width // 4 - away_logo.width // 2
|
away_x = self.display_width // 4 - away_logo.width // 2
|
||||||
away_y = 3 * self.display_manager.height // 4 - away_logo.height // 2
|
away_y = 3 * self.display_height // 4 - away_logo.height // 2
|
||||||
temp_img = Image.new('RGB', (self.display_manager.width, self.display_manager.height), 'black')
|
temp_img = Image.new('RGB', (self.display_width, self.display_height), 'black')
|
||||||
temp_draw = ImageDraw.Draw(temp_img)
|
temp_draw = ImageDraw.Draw(temp_img)
|
||||||
temp_draw.im.paste(away_logo, (away_x, away_y), away_logo)
|
temp_draw.im.paste(away_logo, (away_x, away_y), away_logo)
|
||||||
draw.im.paste(temp_img, (0, 0))
|
draw.im.paste(temp_img, (0, 0))
|
||||||
@@ -368,17 +438,17 @@ class NHLRecentManager(BaseNHLManager):
|
|||||||
home_score = str(self.current_game["home_score"])
|
home_score = str(self.current_game["home_score"])
|
||||||
away_score = str(self.current_game["away_score"])
|
away_score = str(self.current_game["away_score"])
|
||||||
|
|
||||||
home_score_x = self.display_manager.width // 2 - 10
|
home_score_x = self.display_width // 2 - 10
|
||||||
home_score_y = self.display_manager.height // 4 - 8
|
home_score_y = self.display_height // 4 - 8
|
||||||
away_score_x = self.display_manager.width // 2 - 10
|
away_score_x = self.display_width // 2 - 10
|
||||||
away_score_y = 3 * self.display_manager.height // 4 - 8
|
away_score_y = 3 * self.display_height // 4 - 8
|
||||||
|
|
||||||
draw.text((home_score_x, home_score_y), home_score, font=self.fonts['score'], fill=(255, 255, 255))
|
draw.text((home_score_x, home_score_y), home_score, font=self.fonts['score'], fill=(255, 255, 255))
|
||||||
draw.text((away_score_x, away_score_y), away_score, font=self.fonts['score'], fill=(255, 255, 255))
|
draw.text((away_score_x, away_score_y), away_score, font=self.fonts['score'], fill=(255, 255, 255))
|
||||||
|
|
||||||
# Draw "FINAL" status
|
# Draw "FINAL" status
|
||||||
status_x = self.display_manager.width // 2 - 20
|
status_x = self.display_width // 2 - 20
|
||||||
status_y = self.display_manager.height // 2 - 8
|
status_y = self.display_height // 2 - 8
|
||||||
draw.text((status_x, status_y), "FINAL", font=self.fonts['status'], fill=(255, 255, 255))
|
draw.text((status_x, status_y), "FINAL", font=self.fonts['status'], fill=(255, 255, 255))
|
||||||
|
|
||||||
# Display the image
|
# Display the image
|
||||||
@@ -470,11 +540,11 @@ class NHLUpcomingManager(BaseNHLManager):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# Create a new black image
|
# Create a new black image
|
||||||
img = Image.new('RGB', (self.display_manager.width, self.display_manager.height), 'black')
|
img = Image.new('RGB', (self.display_width, self.display_height), 'black')
|
||||||
draw = ImageDraw.Draw(img)
|
draw = ImageDraw.Draw(img)
|
||||||
|
|
||||||
# Calculate logo sizes
|
# Calculate logo sizes
|
||||||
max_size = (self.display_manager.width // 3, self.display_manager.height // 2)
|
max_size = (self.display_width // 3, self.display_height // 2)
|
||||||
|
|
||||||
# Load and resize logos
|
# Load and resize logos
|
||||||
home_logo = self._load_and_resize_logo(self.current_game["home_logo_path"], max_size)
|
home_logo = self._load_and_resize_logo(self.current_game["home_logo_path"], max_size)
|
||||||
@@ -482,25 +552,25 @@ class NHLUpcomingManager(BaseNHLManager):
|
|||||||
|
|
||||||
# Draw home team logo
|
# Draw home team logo
|
||||||
if home_logo:
|
if home_logo:
|
||||||
home_x = self.display_manager.width // 4 - home_logo.width // 2
|
home_x = self.display_width // 4 - home_logo.width // 2
|
||||||
home_y = self.display_manager.height // 4 - home_logo.height // 2
|
home_y = self.display_height // 4 - home_logo.height // 2
|
||||||
temp_img = Image.new('RGB', (self.display_manager.width, self.display_manager.height), 'black')
|
temp_img = Image.new('RGB', (self.display_width, self.display_height), 'black')
|
||||||
temp_draw = ImageDraw.Draw(temp_img)
|
temp_draw = ImageDraw.Draw(temp_img)
|
||||||
temp_draw.im.paste(home_logo, (home_x, home_y), home_logo)
|
temp_draw.im.paste(home_logo, (home_x, home_y), home_logo)
|
||||||
draw.im.paste(temp_img, (0, 0))
|
draw.im.paste(temp_img, (0, 0))
|
||||||
|
|
||||||
# Draw away team logo
|
# Draw away team logo
|
||||||
if away_logo:
|
if away_logo:
|
||||||
away_x = self.display_manager.width // 4 - away_logo.width // 2
|
away_x = self.display_width // 4 - away_logo.width // 2
|
||||||
away_y = 3 * self.display_manager.height // 4 - away_logo.height // 2
|
away_y = 3 * self.display_height // 4 - away_logo.height // 2
|
||||||
temp_img = Image.new('RGB', (self.display_manager.width, self.display_manager.height), 'black')
|
temp_img = Image.new('RGB', (self.display_width, self.display_height), 'black')
|
||||||
temp_draw = ImageDraw.Draw(temp_img)
|
temp_draw = ImageDraw.Draw(temp_img)
|
||||||
temp_draw.im.paste(away_logo, (away_x, away_y), away_logo)
|
temp_draw.im.paste(away_logo, (away_x, away_y), away_logo)
|
||||||
draw.im.paste(temp_img, (0, 0))
|
draw.im.paste(temp_img, (0, 0))
|
||||||
|
|
||||||
# Draw game time
|
# Draw game time
|
||||||
status_x = self.display_manager.width // 2 - 20
|
status_x = self.display_width // 2 - 20
|
||||||
status_y = self.display_manager.height // 2 - 8
|
status_y = self.display_height // 2 - 8
|
||||||
draw.text((status_x, status_y), self.current_game["status_text"], font=self.fonts['status'], fill=(255, 255, 255))
|
draw.text((status_x, status_y), self.current_game["status_text"], font=self.fonts['status'], fill=(255, 255, 255))
|
||||||
|
|
||||||
# Display the image
|
# Display the image
|
||||||
|
|||||||
Reference in New Issue
Block a user