mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-04-10 21:03:01 +00:00
1px black outline on text in sports displays
This commit is contained in:
@@ -63,6 +63,27 @@ class BaseMLBManager:
|
|||||||
logger.error(f"Error loading logo for team {team_abbr}: {e}")
|
logger.error(f"Error loading logo for team {team_abbr}: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def _draw_text_with_outline(self, draw, text, position, font, fill=(255, 255, 255), outline_color=(0, 0, 0)):
|
||||||
|
"""
|
||||||
|
Draw text with a black outline for better readability.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
draw: ImageDraw object
|
||||||
|
text: Text to draw
|
||||||
|
position: (x, y) position to draw the text
|
||||||
|
font: Font to use
|
||||||
|
fill: Text color (default: white)
|
||||||
|
outline_color: Outline color (default: black)
|
||||||
|
"""
|
||||||
|
x, y = position
|
||||||
|
|
||||||
|
# Draw the outline by drawing the text in black at 8 positions around the text
|
||||||
|
for dx, dy in [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]:
|
||||||
|
draw.text((x + dx, y + dy), text, font=font, fill=outline_color)
|
||||||
|
|
||||||
|
# Draw the text in the specified color
|
||||||
|
draw.text((x, y), text, font=font, fill=fill)
|
||||||
|
|
||||||
def _draw_base_indicators(self, draw: ImageDraw.Draw, bases_occupied: List[bool], center_x: int, y: int) -> None:
|
def _draw_base_indicators(self, draw: ImageDraw.Draw, bases_occupied: List[bool], center_x: int, y: int) -> None:
|
||||||
"""Draw base indicators on the display."""
|
"""Draw base indicators on the display."""
|
||||||
base_size = 8 # Increased from 6 to 8 for better visibility
|
base_size = 8 # Increased from 6 to 8 for better visibility
|
||||||
@@ -165,13 +186,15 @@ class BaseMLBManager:
|
|||||||
date_width = draw.textlength(game_date, font=date_font)
|
date_width = draw.textlength(game_date, font=date_font)
|
||||||
date_x = (width - date_width) // 2
|
date_x = (width - date_width) // 2
|
||||||
date_y = (height - date_font.size) // 2 - 3
|
date_y = (height - date_font.size) // 2 - 3
|
||||||
draw.text((date_x, date_y), game_date, font=date_font, fill=(255, 255, 255))
|
# draw.text((date_x, date_y), game_date, font=date_font, fill=(255, 255, 255))
|
||||||
|
self._draw_text_with_outline(draw, game_date, (date_x, date_y), date_font)
|
||||||
|
|
||||||
# Draw time below date
|
# Draw time below date
|
||||||
time_width = draw.textlength(game_time_str, font=time_font)
|
time_width = draw.textlength(game_time_str, font=time_font)
|
||||||
time_x = (width - time_width) // 2
|
time_x = (width - time_width) // 2
|
||||||
time_y = date_y + 10
|
time_y = date_y + 10
|
||||||
draw.text((time_x, time_y), game_time_str, font=time_font, fill=(255, 255, 255))
|
# draw.text((time_x, time_y), game_time_str, font=time_font, fill=(255, 255, 255))
|
||||||
|
self._draw_text_with_outline(draw, game_time_str, (time_x, time_y), time_font)
|
||||||
|
|
||||||
# For recent/final games, show scores and status
|
# For recent/final games, show scores and status
|
||||||
elif game_data['status'] in ['status_final', 'final', 'completed']:
|
elif game_data['status'] in ['status_final', 'final', 'completed']:
|
||||||
@@ -198,7 +221,8 @@ class BaseMLBManager:
|
|||||||
score_width = draw.textlength(score_text, font=score_font)
|
score_width = draw.textlength(score_text, font=score_font)
|
||||||
score_x = (width - score_width) // 2
|
score_x = (width - score_width) // 2
|
||||||
score_y = height - score_font.size - 2
|
score_y = height - score_font.size - 2
|
||||||
draw.text((score_x, score_y), score_text, font=score_font, fill=(255, 255, 255))
|
# draw.text((score_x, score_y), score_text, font=score_font, fill=(255, 255, 255))
|
||||||
|
self._draw_text_with_outline(draw, score_text, (score_x, score_y), score_font)
|
||||||
|
|
||||||
return image
|
return image
|
||||||
|
|
||||||
@@ -615,7 +639,8 @@ class MLBLiveManager(BaseMLBManager):
|
|||||||
inning_width = inning_bbox[2] - inning_bbox[0]
|
inning_width = inning_bbox[2] - inning_bbox[0]
|
||||||
inning_x = (width - inning_width) // 2
|
inning_x = (width - inning_width) // 2
|
||||||
inning_y = 0 # Position near top center
|
inning_y = 0 # Position near top center
|
||||||
draw.text((inning_x, inning_y), inning_text, fill=(255, 255, 255), font=self.display_manager.font)
|
# draw.text((inning_x, inning_y), inning_text, fill=(255, 255, 255), font=self.display_manager.font)
|
||||||
|
self._draw_text_with_outline(draw, inning_text, (inning_x, inning_y), self.display_manager.font)
|
||||||
|
|
||||||
# --- REVISED BASES AND OUTS DRAWING ---
|
# --- REVISED BASES AND OUTS DRAWING ---
|
||||||
bases_occupied = game_data['bases_occupied'] # [1st, 2nd, 3rd]
|
bases_occupied = game_data['bases_occupied'] # [1st, 2nd, 3rd]
|
||||||
@@ -718,7 +743,9 @@ class MLBLiveManager(BaseMLBManager):
|
|||||||
|
|
||||||
# Ensure draw object is set and draw text
|
# Ensure draw object is set and draw text
|
||||||
self.display_manager.draw = draw
|
self.display_manager.draw = draw
|
||||||
self.display_manager._draw_bdf_text(count_text, count_x, count_y, text_color, font=bdf_font)
|
# self.display_manager._draw_bdf_text(count_text, count_x, count_y, text_color, font=bdf_font)
|
||||||
|
# Use _draw_text_with_outline for count text
|
||||||
|
self._draw_text_with_outline(draw, count_text, (count_x, count_y), bdf_font, fill=text_color)
|
||||||
|
|
||||||
# Draw Team:Score at the bottom
|
# Draw Team:Score at the bottom
|
||||||
score_font = self.display_manager.font # Use PressStart2P
|
score_font = self.display_manager.font # Use PressStart2P
|
||||||
@@ -728,12 +755,13 @@ class MLBLiveManager(BaseMLBManager):
|
|||||||
# Helper function for outlined text
|
# Helper function for outlined text
|
||||||
def draw_bottom_outlined_text(x, y, text):
|
def draw_bottom_outlined_text(x, y, text):
|
||||||
# Draw outline
|
# Draw outline
|
||||||
draw.text((x-1, y), text, font=score_font, fill=outline_color)
|
# draw.text((x-1, y), text, font=score_font, fill=outline_color)
|
||||||
draw.text((x+1, y), text, font=score_font, fill=outline_color)
|
# draw.text((x+1, y), text, font=score_font, fill=outline_color)
|
||||||
draw.text((x, y-1), text, font=score_font, fill=outline_color)
|
# draw.text((x, y-1), text, font=score_font, fill=outline_color)
|
||||||
draw.text((x, y+1), text, font=score_font, fill=outline_color)
|
# draw.text((x, y+1), text, font=score_font, fill=outline_color)
|
||||||
# Draw main text
|
# # Draw main text
|
||||||
draw.text((x, y), text, font=score_font, fill=score_text_color)
|
# draw.text((x, y), text, font=score_font, fill=score_text_color)
|
||||||
|
self._draw_text_with_outline(draw, text, (x,y), score_font, fill=score_text_color, outline_color=outline_color)
|
||||||
|
|
||||||
away_abbr = game_data['away_team']
|
away_abbr = game_data['away_team']
|
||||||
home_abbr = game_data['home_team']
|
home_abbr = game_data['home_team']
|
||||||
|
|||||||
@@ -66,6 +66,27 @@ class BaseNCAABaseballManager:
|
|||||||
logger.error(f"[NCAABaseball] Error loading logo for team {team_abbr}: {e}")
|
logger.error(f"[NCAABaseball] Error loading logo for team {team_abbr}: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def _draw_text_with_outline(self, draw, text, position, font, fill=(255, 255, 255), outline_color=(0, 0, 0)):
|
||||||
|
"""
|
||||||
|
Draw text with a black outline for better readability.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
draw: ImageDraw object
|
||||||
|
text: Text to draw
|
||||||
|
position: (x, y) position to draw the text
|
||||||
|
font: Font to use
|
||||||
|
fill: Text color (default: white)
|
||||||
|
outline_color: Outline color (default: black)
|
||||||
|
"""
|
||||||
|
x, y = position
|
||||||
|
|
||||||
|
# Draw the outline by drawing the text in black at 8 positions around the text
|
||||||
|
for dx, dy in [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]:
|
||||||
|
draw.text((x + dx, y + dy), text, font=font, fill=outline_color)
|
||||||
|
|
||||||
|
# Draw the text in the specified color
|
||||||
|
draw.text((x, y), text, font=font, fill=fill)
|
||||||
|
|
||||||
def _draw_base_indicators(self, draw: ImageDraw.Draw, bases_occupied: List[bool], center_x: int, y: int) -> None:
|
def _draw_base_indicators(self, draw: ImageDraw.Draw, bases_occupied: List[bool], center_x: int, y: int) -> None:
|
||||||
"""Draw base indicators on the display."""
|
"""Draw base indicators on the display."""
|
||||||
base_size = 8
|
base_size = 8
|
||||||
@@ -120,7 +141,8 @@ class BaseNCAABaseballManager:
|
|||||||
status_x = (width - status_width) // 2
|
status_x = (width - status_width) // 2
|
||||||
status_y = 2
|
status_y = 2
|
||||||
self.display_manager.draw = draw
|
self.display_manager.draw = draw
|
||||||
self.display_manager._draw_bdf_text(status_text, status_x, status_y, color=(255, 255, 255), font=self.display_manager.calendar_font)
|
status_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6) # Using a default small font
|
||||||
|
self._draw_text_with_outline(draw, status_text, (status_x, status_y), status_font)
|
||||||
|
|
||||||
game_time = datetime.fromisoformat(game_data['start_time'].replace('Z', '+00:00'))
|
game_time = datetime.fromisoformat(game_data['start_time'].replace('Z', '+00:00'))
|
||||||
timezone_str = self.config.get('timezone', 'UTC')
|
timezone_str = self.config.get('timezone', 'UTC')
|
||||||
@@ -140,23 +162,23 @@ class BaseNCAABaseballManager:
|
|||||||
|
|
||||||
date_width = draw.textlength(game_date, font=date_font)
|
date_width = draw.textlength(game_date, font=date_font)
|
||||||
date_x = (width - date_width) // 2
|
date_x = (width - date_width) // 2
|
||||||
date_y = (height - date_font.size) // 2 - 3
|
date_y = (height - date_font.getmetrics()[0]) // 2 - 3 # Adjusted for font metrics
|
||||||
draw.text((date_x, date_y), game_date, font=date_font, fill=(255, 255, 255))
|
self._draw_text_with_outline(draw, game_date, (date_x, date_y), date_font)
|
||||||
|
|
||||||
time_width = draw.textlength(game_time_str, font=time_font)
|
time_width = draw.textlength(game_time_str, font=time_font)
|
||||||
time_x = (width - time_width) // 2
|
time_x = (width - time_width) // 2
|
||||||
time_y = date_y + 10
|
time_y = date_y + 10
|
||||||
draw.text((time_x, time_y), game_time_str, font=time_font, fill=(255, 255, 255))
|
self._draw_text_with_outline(draw, game_time_str, (time_x, time_y), time_font)
|
||||||
|
|
||||||
# For recent/final games, show scores and status
|
# For recent/final games, show scores and status
|
||||||
elif game_data['status'] in ['status_final', 'final', 'completed']:
|
elif game_data['status'] in ['status_final', 'final', 'completed']:
|
||||||
status_text = "Final"
|
status_text = "Final"
|
||||||
self.display_manager.calendar_font.set_char_size(height=7*64)
|
status_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6) # Using a default small font
|
||||||
status_width = self.display_manager.get_text_width(status_text, self.display_manager.calendar_font)
|
status_width = draw.textlength(status_text, font=status_font)
|
||||||
status_x = (width - status_width) // 2
|
status_x = (width - status_width) // 2
|
||||||
status_y = 2
|
status_y = 2
|
||||||
self.display_manager.draw = draw
|
self.display_manager.draw = draw
|
||||||
self.display_manager._draw_bdf_text(status_text, status_x, status_y, color=(255, 255, 255), font=self.display_manager.calendar_font)
|
self._draw_text_with_outline(draw, status_text, (status_x, status_y), status_font)
|
||||||
|
|
||||||
away_score = str(game_data['away_score'])
|
away_score = str(game_data['away_score'])
|
||||||
home_score = str(game_data['home_score'])
|
home_score = str(game_data['home_score'])
|
||||||
@@ -165,8 +187,8 @@ class BaseNCAABaseballManager:
|
|||||||
|
|
||||||
score_width = draw.textlength(score_text, font=score_font)
|
score_width = draw.textlength(score_text, font=score_font)
|
||||||
score_x = (width - score_width) // 2
|
score_x = (width - score_width) // 2
|
||||||
score_y = height - score_font.size - 2
|
score_y = height - score_font.getmetrics()[0] - 2 # Adjusted for font metrics
|
||||||
draw.text((score_x, score_y), score_text, font=score_font, fill=(255, 255, 255))
|
self._draw_text_with_outline(draw, score_text, (score_x, score_y), score_font)
|
||||||
|
|
||||||
return image
|
return image
|
||||||
|
|
||||||
@@ -494,7 +516,7 @@ class NCAABaseballLiveManager(BaseNCAABaseballManager):
|
|||||||
inning_width = inning_bbox[2] - inning_bbox[0]
|
inning_width = inning_bbox[2] - inning_bbox[0]
|
||||||
inning_x = (width - inning_width) // 2
|
inning_x = (width - inning_width) // 2
|
||||||
inning_y = 0
|
inning_y = 0
|
||||||
draw.text((inning_x, inning_y), inning_text, fill=(255, 255, 255), font=self.display_manager.font)
|
self._draw_text_with_outline(draw, inning_text, (inning_x, inning_y), self.display_manager.font)
|
||||||
|
|
||||||
bases_occupied = game_data['bases_occupied']
|
bases_occupied = game_data['bases_occupied']
|
||||||
outs = game_data.get('outs', 0)
|
outs = game_data.get('outs', 0)
|
||||||
@@ -555,13 +577,11 @@ class NCAABaseballLiveManager(BaseNCAABaseballManager):
|
|||||||
count_y = cluster_bottom_y + 2
|
count_y = cluster_bottom_y + 2
|
||||||
count_x = bases_origin_x + (base_cluster_width - count_text_width) // 2
|
count_x = bases_origin_x + (base_cluster_width - count_text_width) // 2
|
||||||
self.display_manager.draw = draw
|
self.display_manager.draw = draw
|
||||||
self.display_manager._draw_bdf_text(count_text, count_x, count_y, text_color, font=bdf_font)
|
self._draw_text_with_outline(draw, count_text, (count_x, count_y), bdf_font, fill=text_color)
|
||||||
|
|
||||||
score_font = self.display_manager.font; outline_color = (0, 0, 0); score_text_color = (255, 255, 255)
|
score_font = self.display_manager.font; outline_color = (0, 0, 0); score_text_color = (255, 255, 255)
|
||||||
def draw_bottom_outlined_text(x, y, text):
|
def draw_bottom_outlined_text(x, y, text):
|
||||||
draw.text((x-1, y), text, font=score_font, fill=outline_color); draw.text((x+1, y), text, font=score_font, fill=outline_color)
|
self._draw_text_with_outline(draw, text, (x,y), score_font, fill=score_text_color, outline_color=outline_color)
|
||||||
draw.text((x, y-1), text, font=score_font, fill=outline_color); draw.text((x, y+1), text, font=score_font, fill=outline_color)
|
|
||||||
draw.text((x, y), text, font=score_font, fill=score_text_color)
|
|
||||||
away_abbr = game_data['away_team']; home_abbr = game_data['home_team']
|
away_abbr = game_data['away_team']; home_abbr = game_data['home_team']
|
||||||
away_score_str = str(game_data['away_score']); home_score_str = str(game_data['home_score'])
|
away_score_str = str(game_data['away_score']); home_score_str = str(game_data['home_score'])
|
||||||
away_text = f"{away_abbr}:{away_score_str}"; home_text = f"{home_abbr}:{home_score_str}"
|
away_text = f"{away_abbr}:{away_score_str}"; home_text = f"{home_abbr}:{home_score_str}"
|
||||||
|
|||||||
@@ -249,6 +249,27 @@ class BaseNCAAMBasketballManager:
|
|||||||
self.logger.error(f"Error loading logo for {team_abbrev}: {e}", exc_info=True)
|
self.logger.error(f"Error loading logo for {team_abbrev}: {e}", exc_info=True)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def _draw_text_with_outline(self, draw, text, position, font, fill=(255, 255, 255), outline_color=(0, 0, 0)):
|
||||||
|
"""
|
||||||
|
Draw text with a black outline for better readability.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
draw: ImageDraw object
|
||||||
|
text: Text to draw
|
||||||
|
position: (x, y) position to draw the text
|
||||||
|
font: Font to use
|
||||||
|
fill: Text color (default: white)
|
||||||
|
outline_color: Outline color (default: black)
|
||||||
|
"""
|
||||||
|
x, y = position
|
||||||
|
|
||||||
|
# Draw the outline by drawing the text in black at 8 positions around the text
|
||||||
|
for dx, dy in [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]:
|
||||||
|
draw.text((x + dx, y + dy), text, font=font, fill=outline_color)
|
||||||
|
|
||||||
|
# Draw the text in the specified color
|
||||||
|
draw.text((x, y), text, font=font, fill=fill)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _fetch_shared_data(cls, date_str: str = None) -> Optional[Dict]:
|
def _fetch_shared_data(cls, date_str: str = None) -> Optional[Dict]:
|
||||||
"""Fetch and cache data for all managers to share."""
|
"""Fetch and cache data for all managers to share."""
|
||||||
@@ -472,19 +493,19 @@ class BaseNCAAMBasketballManager:
|
|||||||
status_width = draw.textlength(status_text, font=self.fonts['status'])
|
status_width = draw.textlength(status_text, font=self.fonts['status'])
|
||||||
status_x = (self.display_width - status_width) // 2
|
status_x = (self.display_width - status_width) // 2
|
||||||
status_y = 2
|
status_y = 2
|
||||||
draw.text((status_x, status_y), status_text, font=self.fonts['status'], fill=(255, 255, 255))
|
self._draw_text_with_outline(draw, status_text, (status_x, status_y), self.fonts['status'])
|
||||||
|
|
||||||
# Calculate position for the date text (centered horizontally, below "Next Game")
|
# Calculate position for the date text (centered horizontally, below "Next Game")
|
||||||
date_width = draw.textlength(game_date, font=self.fonts['time'])
|
date_width = draw.textlength(game_date, font=self.fonts['time'])
|
||||||
date_x = (self.display_width - date_width) // 2
|
date_x = (self.display_width - date_width) // 2
|
||||||
date_y = center_y - 5 # Position in center
|
date_y = center_y - 5 # Position in center
|
||||||
draw.text((date_x, date_y), game_date, font=self.fonts['time'], fill=(255, 255, 255))
|
self._draw_text_with_outline(draw, game_date, (date_x, date_y), self.fonts['time'])
|
||||||
|
|
||||||
# Calculate position for the time text (centered horizontally, in center)
|
# Calculate position for the time text (centered horizontally, in center)
|
||||||
time_width = draw.textlength(game_time, font=self.fonts['time'])
|
time_width = draw.textlength(game_time, font=self.fonts['time'])
|
||||||
time_x = (self.display_width - time_width) // 2
|
time_x = (self.display_width - time_width) // 2
|
||||||
time_y = date_y + 10 # Position below date
|
time_y = date_y + 10 # Position below date
|
||||||
draw.text((time_x, time_y), game_time, font=self.fonts['time'], fill=(255, 255, 255))
|
self._draw_text_with_outline(draw, game_time, (time_x, time_y), self.fonts['time'])
|
||||||
else:
|
else:
|
||||||
# For live/final games, show scores and period/time
|
# For live/final games, show scores and period/time
|
||||||
home_score = str(game.get("home_score", "0"))
|
home_score = str(game.get("home_score", "0"))
|
||||||
@@ -495,7 +516,7 @@ class BaseNCAAMBasketballManager:
|
|||||||
score_width = draw.textlength(score_text, font=self.fonts['score'])
|
score_width = draw.textlength(score_text, font=self.fonts['score'])
|
||||||
score_x = (self.display_width - score_width) // 2
|
score_x = (self.display_width - score_width) // 2
|
||||||
score_y = self.display_height - 10
|
score_y = self.display_height - 10
|
||||||
draw.text((score_x, score_y), score_text, font=self.fonts['score'], fill=(255, 255, 255))
|
self._draw_text_with_outline(draw, score_text, (score_x, score_y), self.fonts['score'])
|
||||||
|
|
||||||
# Draw period and time or Final
|
# Draw period and time or Final
|
||||||
if game.get("is_final", False):
|
if game.get("is_final", False):
|
||||||
@@ -503,13 +524,13 @@ class BaseNCAAMBasketballManager:
|
|||||||
status_width = draw.textlength(status_text, font=self.fonts['time'])
|
status_width = draw.textlength(status_text, font=self.fonts['time'])
|
||||||
status_x = (self.display_width - status_width) // 2
|
status_x = (self.display_width - status_width) // 2
|
||||||
status_y = 5
|
status_y = 5
|
||||||
draw.text((status_x, status_y), status_text, font=self.fonts['time'], fill=(255, 255, 255))
|
self._draw_text_with_outline(draw, status_text, (status_x, status_y), self.fonts['time'])
|
||||||
elif game.get("is_halftime", False):
|
elif game.get("is_halftime", False):
|
||||||
status_text = "Halftime"
|
status_text = "Halftime"
|
||||||
status_width = draw.textlength(status_text, font=self.fonts['time'])
|
status_width = draw.textlength(status_text, font=self.fonts['time'])
|
||||||
status_x = (self.display_width - status_width) // 2
|
status_x = (self.display_width - status_width) // 2
|
||||||
status_y = 5
|
status_y = 5
|
||||||
draw.text((status_x, status_y), status_text, font=self.fonts['time'], fill=(255, 255, 255))
|
self._draw_text_with_outline(draw, status_text, (status_x, status_y), self.fonts['time'])
|
||||||
else:
|
else:
|
||||||
period = game.get("period", 0)
|
period = game.get("period", 0)
|
||||||
clock = game.get("clock", "0:00")
|
clock = game.get("clock", "0:00")
|
||||||
@@ -530,13 +551,13 @@ class BaseNCAAMBasketballManager:
|
|||||||
period_width = draw.textlength(period_text, font=self.fonts['time'])
|
period_width = draw.textlength(period_text, font=self.fonts['time'])
|
||||||
period_x = (self.display_width - period_width) // 2
|
period_x = (self.display_width - period_width) // 2
|
||||||
period_y = 1
|
period_y = 1
|
||||||
draw.text((period_x, period_y), period_text, font=self.fonts['time'], fill=(255, 255, 255))
|
self._draw_text_with_outline(draw, period_text, (period_x, period_y), self.fonts['time'])
|
||||||
|
|
||||||
# Draw clock below period
|
# Draw clock below period
|
||||||
clock_width = draw.textlength(clock, font=self.fonts['time'])
|
clock_width = draw.textlength(clock, font=self.fonts['time'])
|
||||||
clock_x = (self.display_width - clock_width) // 2
|
clock_x = (self.display_width - clock_width) // 2
|
||||||
clock_y = period_y + 10 # Position below period
|
clock_y = period_y + 10 # Position below period
|
||||||
draw.text((clock_x, clock_y), clock, font=self.fonts['time'], fill=(255, 255, 255))
|
self._draw_text_with_outline(draw, clock, (clock_x, clock_y), self.fonts['time'])
|
||||||
|
|
||||||
# Display the image
|
# Display the image
|
||||||
self.display_manager.image.paste(main_img, (0, 0))
|
self.display_manager.image.paste(main_img, (0, 0))
|
||||||
@@ -606,29 +627,33 @@ class NCAAMBasketballLiveManager(BaseNCAAMBasketballManager):
|
|||||||
if self.test_mode:
|
if self.test_mode:
|
||||||
# For testing, update the clock and maybe period
|
# For testing, update the clock and maybe period
|
||||||
if self.current_game:
|
if self.current_game:
|
||||||
minutes = int(self.current_game["clock"].split(":")[0])
|
try: # Add try-except for robust clock parsing
|
||||||
seconds = int(self.current_game["clock"].split(":")[1])
|
minutes_str, seconds_str = self.current_game["clock"].split(":")
|
||||||
seconds -= 1
|
minutes = int(minutes_str)
|
||||||
if seconds < 0:
|
seconds = int(seconds_str)
|
||||||
seconds = 59
|
seconds -= 1
|
||||||
minutes -= 1
|
if seconds < 0:
|
||||||
if minutes < 0:
|
seconds = 59
|
||||||
# Simulate moving from H1 to H2 or H2 to OT
|
minutes -= 1
|
||||||
if self.current_game["period"] == 1:
|
if minutes < 0:
|
||||||
self.current_game["period"] = 2
|
# Simulate moving from H1 to H2 or H2 to OT
|
||||||
minutes = 19 # Reset clock for H2
|
if self.current_game["period"] == 1:
|
||||||
seconds = 59
|
self.current_game["period"] = 2
|
||||||
elif self.current_game["period"] == 2:
|
minutes = 19 # Reset clock for H2
|
||||||
self.current_game["period"] = 3 # Go to OT
|
seconds = 59
|
||||||
minutes = 4 # Reset clock for OT
|
elif self.current_game["period"] == 2:
|
||||||
seconds = 59
|
self.current_game["period"] = 3 # Go to OT
|
||||||
elif self.current_game["period"] >= 3: # OT+
|
minutes = 4 # Reset clock for OT
|
||||||
self.current_game["period"] += 1
|
seconds = 59
|
||||||
minutes = 4
|
elif self.current_game["period"] >= 3: # OT+
|
||||||
seconds = 59
|
self.current_game["period"] += 1
|
||||||
self.current_game["clock"] = f"{minutes:02d}:{seconds:02d}"
|
minutes = 4
|
||||||
# Always update display in test mode
|
seconds = 59
|
||||||
self.display(force_clear=True)
|
self.current_game["clock"] = f"{minutes:02d}:{seconds:02d}"
|
||||||
|
# Always update display in test mode
|
||||||
|
self.display(force_clear=True)
|
||||||
|
except ValueError:
|
||||||
|
self.logger.warning(f"[NCAAMBasketball] Could not parse clock in test mode: {self.current_game.get('clock')}")
|
||||||
else:
|
else:
|
||||||
# Fetch live game data from ESPN API
|
# Fetch live game data from ESPN API
|
||||||
data = self._fetch_data()
|
data = self._fetch_data()
|
||||||
@@ -665,7 +690,19 @@ class NCAAMBasketballLiveManager(BaseNCAAMBasketballManager):
|
|||||||
if new_live_games:
|
if new_live_games:
|
||||||
self.logger.info(f"[NCAAMBasketball] Found {len(new_live_games)} live games")
|
self.logger.info(f"[NCAAMBasketball] Found {len(new_live_games)} live games")
|
||||||
for game in new_live_games:
|
for game in new_live_games:
|
||||||
status_str = f"H{game['period']}" if game['period'] <=2 else f"OT{game['period']-2 if game['period'] > 3 else ''}"
|
period = game.get('period', 0)
|
||||||
|
if game.get('is_halftime'):
|
||||||
|
status_str = "Halftime"
|
||||||
|
elif period == 1:
|
||||||
|
status_str = "H1"
|
||||||
|
elif period == 2:
|
||||||
|
status_str = "H2"
|
||||||
|
elif period == 3:
|
||||||
|
status_str = "OT"
|
||||||
|
elif period > 3:
|
||||||
|
status_str = f"{period-2}OT"
|
||||||
|
else:
|
||||||
|
status_str = f"P{period}" # Fallback
|
||||||
self.logger.info(f"[NCAAMBasketball] Live game: {game['away_abbr']} vs {game['home_abbr']} - {status_str}, {game['clock']}")
|
self.logger.info(f"[NCAAMBasketball] Live game: {game['away_abbr']} vs {game['home_abbr']} - {status_str}, {game['clock']}")
|
||||||
if has_favorite_team:
|
if has_favorite_team:
|
||||||
self.logger.info("[NCAAMBasketball] Found live game(s) for favorite team(s)")
|
self.logger.info("[NCAAMBasketball] Found live game(s) for favorite team(s)")
|
||||||
@@ -676,24 +713,23 @@ class NCAAMBasketballLiveManager(BaseNCAAMBasketballManager):
|
|||||||
if new_live_games:
|
if new_live_games:
|
||||||
# Update the current game with the latest data if it matches
|
# Update the current game with the latest data if it matches
|
||||||
current_game_updated = False
|
current_game_updated = False
|
||||||
for new_game in new_live_games:
|
if self.current_game: # Ensure current_game is not None
|
||||||
if self.current_game and (
|
for new_game in new_live_games:
|
||||||
(new_game["home_abbr"] == self.current_game["home_abbr"] and
|
if (new_game["home_abbr"] == self.current_game["home_abbr"] and
|
||||||
new_game["away_abbr"] == self.current_game["away_abbr"]) or
|
new_game["away_abbr"] == self.current_game["away_abbr"]) or \
|
||||||
(new_game["home_abbr"] == self.current_game["away_abbr"] and
|
(new_game["home_abbr"] == self.current_game["away_abbr"] and
|
||||||
new_game["away_abbr"] == self.current_game["home_abbr"])
|
new_game["away_abbr"] == self.current_game["home_abbr"]):
|
||||||
):
|
self.current_game = new_game
|
||||||
self.current_game = new_game
|
current_game_updated = True
|
||||||
current_game_updated = True
|
break
|
||||||
break
|
|
||||||
|
|
||||||
# Only update the games list if there's a structural change
|
# Only update the games list if there's a structural change
|
||||||
if not self.live_games or set(game["away_abbr"] + game["home_abbr"] for game in new_live_games) != set(game["away_abbr"] + game["home_abbr"] for game in self.live_games):
|
if not self.live_games or set(game["away_abbr"] + game["home_abbr"] for game in new_live_games) != set(game["away_abbr"] + game["home_abbr"] for game in self.live_games):
|
||||||
self.live_games = new_live_games
|
self.live_games = new_live_games
|
||||||
# If we don't have a current game, it's not in the new list, or the list was empty, reset
|
# If we don't have a current game, it's not in the new list, or the list was empty, reset
|
||||||
if not self.current_game or not current_game_updated or not self.live_games:
|
if not self.current_game or not current_game_updated or not self.live_games: # Check self.live_games is not empty
|
||||||
self.current_game_index = 0
|
self.current_game_index = 0
|
||||||
self.current_game = self.live_games[0] if self.live_games else None
|
self.current_game = self.live_games[0] if self.live_games else None # Handle empty self.live_games
|
||||||
self.last_game_switch = current_time
|
self.last_game_switch = current_time
|
||||||
|
|
||||||
# Cycle through games if multiple are present
|
# Cycle through games if multiple are present
|
||||||
|
|||||||
@@ -426,14 +426,14 @@ class BaseNHLManager:
|
|||||||
center_y = self.display_height // 2
|
center_y = self.display_height // 2
|
||||||
|
|
||||||
# Draw home team logo (far right, extending beyond screen)
|
# Draw home team logo (far right, extending beyond screen)
|
||||||
home_x = self.display_width - home_logo.width
|
home_x = self.display_width - home_logo.width + 2
|
||||||
home_y = center_y - (home_logo.height // 2)
|
home_y = center_y - (home_logo.height // 2)
|
||||||
|
|
||||||
# Paste the home logo onto the overlay
|
# Paste the home logo onto the overlay
|
||||||
overlay.paste(home_logo, (home_x, home_y), home_logo)
|
overlay.paste(home_logo, (home_x, home_y), home_logo)
|
||||||
|
|
||||||
# Draw away team logo (far left, extending beyond screen)
|
# Draw away team logo (far left, extending beyond screen)
|
||||||
away_x = 0
|
away_x = -2
|
||||||
away_y = center_y - (away_logo.height // 2)
|
away_y = center_y - (away_logo.height // 2)
|
||||||
|
|
||||||
# Paste the away logo onto the overlay
|
# Paste the away logo onto the overlay
|
||||||
|
|||||||
Reference in New Issue
Block a user