more splitting

This commit is contained in:
2026-06-17 23:27:36 -04:00
parent bc12f25e84
commit cc759bca59
2 changed files with 239 additions and 227 deletions
+221
View File
@@ -0,0 +1,221 @@
import utils.image_utils as image_utils
from rgbmatrix import graphics
from scoreboard import Colors, data
from time import time, sleep
def get_scores(sport, league):
url = f"https://site.api.espn.com/apis/site/v2/sports/{sport}/{league}/scoreboard"
try:
resp = requests.get(url, timeout=5)
resp.raise_for_status()
games = []
for event in resp.json().get("events", []):
comp = event["competitions"][0]
teams = comp["competitors"]
home = next(t for t in teams if t["homeAway"] == "home")
away = next(t for t in teams if t["homeAway"] == "away")
status = event["status"]["type"]["shortDetail"]
games.append(
{
"league": league,
"away": away["team"]["abbreviation"].upper(),
"away_score": away["score"],
"home": home["team"]["abbreviation"].upper(),
"home_score": home["score"],
"status": status,
"id": event["id"],
}
)
return games
except Exception as e:
print(f"Fetch error ({league}): {e}")
return []
def get_all_scores():
print('fetching game scores from espn')
games = []
games += get_scores("hockey", "nhl")
games += get_scores("football", "nfl")
games += get_scores("basketball", "nba")
games += get_scores("baseball", "mlb")
return games
def draw_all_games(canvas, games, start_index):
for i in range(4):
game_index = (start_index + i) % len(games)
game = games[game_index]
offset = i * 64
league = game["league"]
away_logo = image_utils.load_logo(league, game["away"])
home_logo = image_utils.load_logo(league, game["home"])
image_utils.draw_logo(canvas, away_logo, offset + 0, 0)
image_utils.draw_logo(canvas, home_logo, offset + 0, 16)
graphics.DrawText(
canvas,
data['fonts']['font_small'],
offset + 18,
11,
graphics.Color(*Colors.RED.value),
game["away"],
)
graphics.DrawText(
canvas,
data['fonts']['font_small'],
offset + 18,
27,
graphics.Color(*Colors.WHITE.value),
game["home"],
)
graphics.DrawText(
canvas,
data['fonts']['font'],
offset + 40,
13,
graphics.Color(*Colors.WHITE.value),
str(game["away_score"]),
)
graphics.DrawText(
canvas,
data['fonts']['font'],
offset + 40,
29,
graphics.Color(*Colors.WHITE.value),
str(game["home_score"]),
)
if i < 3:
for row in range(32):
canvas.SetPixel(offset + 63, row, 40, 40, 40)
def draw_single_game(canvas, game):
league = game["league"]
home_logo = image_utils.load_logo(league, game["home"])
away_logo = image_utils.load_logo(league, game["away"])
image_utils.draw_logo(canvas, away_logo, 0, 0)
image_utils.draw_logo(canvas, home_logo, 0, 16)
graphics.DrawText(
canvas,
data['fonts']['font_small'],
18,
11,
graphics.Color(*Colors.WHITE.value),
game["away"],
)
graphics.DrawText(
canvas,
data['fonts']['font_small'],
18,
27,
graphics.Color(*Colors.WHITE.value),
game["home"],
)
graphics.DrawText(
canvas,
data['fonts']['font'],
40,
13,
graphics.Color(*Colors.WHITE.value),
str(game["away_score"]),
)
graphics.DrawText(
canvas,
data['fonts']['font'],
40,
29,
graphics.Color(*Colors.WHITE.value),
str(game["home_score"]),
)
graphics.DrawText(
canvas,
data['fonts']['font'],
55,
22,
graphics.Color(*Colors.WHITE.value),
str(game["status"])
)
def run_board(canvas, matrix):
# preferred games
current_preferred_game = 0
preferred_games = []
preferred_teams = [
("BUF", "nfl"),
("BUF", "nhl"),
("TOR", "mlb"),
("LAL", "nba"),
]
# data
games = []
last_fetch = 0
current_page = 0
page_display_time = 8
last_switch = time()
show_preferred = True
while true:
now = time()
if now - last_fetch > 30 or len(games) <= 0:
games = get_all_scores()
last_fetch = now
if games:
canvas.Clear()
# clear bad preferred games out
if len(preferred_games) > 0:
for preferred_game in preferred_games:
shown_game = [g for g in games if preferred_game == g['id']]
if len(shown_game) <= 0 or "Final" in shown_game[0]['status']:
preferred_games.remove(preferred_game)
# get new preferred games
for game in games:
if (game['away'], game['league']) in preferred_teams or (game['home'], game['league']) in preferred_teams:
if 'Final' not in game['status'] and game['id'] not in preferred_games:
preferred_games.append(game['id'])
print(preferred_games)
if now - last_switch > page_display_time:
last_switch = now
if show_preferred and len(preferred_games) > 0:
single_preferred_game = next(
(g for g in games if g['id'] == preferred_games[current_preferred_game]), None
)
if single_preferred_game:
print(f'Showing preferred game {single_preferred_game["home"]} vs {single_preferred_game["away"]}')
draw_single_game(canvas, single_preferred_game)
current_preferred_game += 1
if current_preferred_game >= len(preferred_games):
show_preferred = False
current_preferred_game = 0
current_page = 0
else:
print(f'Showing all games page {current_page} / {len(games)}')
draw_all_games(canvas, games, current_page)
current_page += 4
if current_page >= len(games):
current_page = 0
if len(preferred_games) > 0:
show_preferred = True
else:
canvas.Clear()
print('No games available')
# no games available, just draw placeholder
graphics.DrawText(canvas, data["fonts"]["font"], 10, 22, graphics.Color(*Colors.RED.value), "No games today")
canvas = matrix.SwapOnVSync(canvas)
sleep(10)
+18 -227
View File
@@ -1,13 +1,13 @@
import requests
import os import os
import utils.govee as govee import utils.govee as govee
import utils.image_utils as image_utils
from enum import Enum from enum import Enum
from time import sleep, time
from pathlib import Path from pathlib import Path
from rgbmatrix import RGBMatrix, RGBMatrixOptions, graphics from rgbmatrix import RGBMatrix, RGBMatrixOptions, graphics
from dotenv import load_dotenv from dotenv import load_dotenv
# modes
import modes.score_mode as score_mode
# --- Load environment vars --- # --- Load environment vars ---
load_dotenv() load_dotenv()
@@ -16,6 +16,20 @@ SCRIPT_DIR = Path(__file__).parent.resolve()
ASSET_DIR = os.path.join(SCRIPT_DIR, "assets") ASSET_DIR = os.path.join(SCRIPT_DIR, "assets")
LOGO_DIR = os.path.join(ASSET_DIR, "logos") LOGO_DIR = os.path.join(ASSET_DIR, "logos")
# --- importable data dict ---
data = {
"paths": {
"SCRIPT_DIR": SCRIPT_DIR,
"ASSET_DIR": ASSET_DIR,
"LOGO_DIR": LOGO_DIR
},
"fonts": {
"font": graphics.Font().LoadFont(os.path.join(ASSET_DIR, "fonts/7x13.bdf")),
"font_small": graphics.Font().LoadFont(os.path.join(ASSET_DIR, "fonts/5x7.bdf")),
"font_big": graphics.Font().LoadFont(os.path.join(ASSET_DIR, "fonts/9x18.bdf"))
}
}
# --- Matrix config --- # --- Matrix config ---
options = RGBMatrixOptions() options = RGBMatrixOptions()
options.rows = 32 options.rows = 32
@@ -30,17 +44,6 @@ options.brightness = 80
matrix = RGBMatrix(options=options) matrix = RGBMatrix(options=options)
canvas = matrix.CreateFrameCanvas() canvas = matrix.CreateFrameCanvas()
# --- Font initialization ---
font = graphics.Font()
font_small = graphics.Font()
font_big = graphics.Font()
font.LoadFont(os.path.join(ASSET_DIR, "fonts/7x13.bdf"))
font_small.LoadFont(os.path.join(ASSET_DIR, "fonts/5x7.bdf"))
font_big.LoadFont(os.path.join(ASSET_DIR, "fonts/9x18.bdf"))
# --- Logo cache ---
logo_cache = {}
# --- Pre-built colors --- # --- Pre-built colors ---
class Colors(Enum): class Colors(Enum):
WHITE = (255, 255, 255) WHITE = (255, 255, 255)
@@ -59,223 +62,11 @@ if os.environ['GOVEE_API_KEY']:
# pygame.mixer.music.load(os.path.join(ASSET_DIR, filename)) # pygame.mixer.music.load(os.path.join(ASSET_DIR, filename))
# pygame.mixer.music.play() # pygame.mixer.music.play()
# --- Fetch scores ---
def get_scores(sport, league):
url = f"https://site.api.espn.com/apis/site/v2/sports/{sport}/{league}/scoreboard"
try:
resp = requests.get(url, timeout=5)
resp.raise_for_status()
games = []
for event in resp.json().get("events", []):
comp = event["competitions"][0]
teams = comp["competitors"]
home = next(t for t in teams if t["homeAway"] == "home")
away = next(t for t in teams if t["homeAway"] == "away")
status = event["status"]["type"]["shortDetail"]
games.append(
{
"league": league,
"away": away["team"]["abbreviation"].upper(),
"away_score": away["score"],
"home": home["team"]["abbreviation"].upper(),
"home_score": home["score"],
"status": status,
"id": event["id"],
}
)
return games
except Exception as e:
print(f"Fetch error ({league}): {e}")
return []
def get_all_scores():
print('fetching game scores from espn')
games = []
games += get_scores("hockey", "nhl")
games += get_scores("football", "nfl")
games += get_scores("basketball", "nba")
games += get_scores("baseball", "mlb")
return games
# --- Game drawing ---
def draw_all_games(canvas, games, start_index):
for i in range(4):
game_index = (start_index + i) % len(games)
game = games[game_index]
offset = i * 64
league = game["league"]
away_logo = image_utils.load_logo(league, game["away"])
home_logo = image_utils.load_logo(league, game["home"])
image_utils.draw_logo(canvas, away_logo, offset + 0, 0)
image_utils.draw_logo(canvas, home_logo, offset + 0, 16)
graphics.DrawText(
canvas,
font_small,
offset + 18,
11,
graphics.Color(*Colors.RED.value),
game["away"],
)
graphics.DrawText(
canvas,
font_small,
offset + 18,
27,
graphics.Color(*Colors.WHITE.value),
game["home"],
)
graphics.DrawText(
canvas,
font,
offset + 40,
13,
graphics.Color(*Colors.WHITE.value),
str(game["away_score"]),
)
graphics.DrawText(
canvas,
font,
offset + 40,
29,
graphics.Color(*Colors.WHITE.value),
str(game["home_score"]),
)
if i < 3:
for row in range(32):
canvas.SetPixel(offset + 63, row, 40, 40, 40)
def draw_single_game(canvas, game):
league = game["league"]
home_logo = image_utils.load_logo(league, game["home"])
away_logo = image_utils.load_logo(league, game["away"])
image_utils.draw_logo(canvas, away_logo, 0, 0)
image_utils.draw_logo(canvas, home_logo, 0, 16)
graphics.DrawText(
canvas,
font_small,
18,
11,
graphics.Color(*Colors.WHITE.value),
game["away"],
)
graphics.DrawText(
canvas,
font_small,
18,
27,
graphics.Color(*Colors.WHITE.value),
game["home"],
)
graphics.DrawText(
canvas,
font,
40,
13,
graphics.Color(*Colors.WHITE.value),
str(game["away_score"]),
)
graphics.DrawText(
canvas,
font,
40,
29,
graphics.Color(*Colors.WHITE.value),
str(game["home_score"]),
)
graphics.DrawText(
canvas,
font,
55,
22,
graphics.Color(*Colors.WHITE.value),
str(game["status"])
)
# --- Main loop --- # --- Main loop ---
def run(): def run():
global canvas global canvas
games = []
last_fetch = 0
current_page = 0
page_display_time = 8
last_switch = time()
show_preferred = True
# preferred games score_mode(canvas, matrix)
current_preferred_game = 0
preferred_games = []
preferred_teams = [
("BUF", "nfl"),
("BUF", "nhl"),
("TOR", "mlb"),
("LAL", "nba"),
]
while True:
now = time()
if now - last_fetch > 30 or len(games) <= 0:
games = get_all_scores()
last_fetch = now
if games:
canvas.Clear()
# clear bad preferred games out
if len(preferred_games) > 0:
for preferred_game in preferred_games:
shown_game = [g for g in games if preferred_game == g['id']]
if len(shown_game) <= 0 or "Final" in shown_game[0]['status']:
preferred_games.remove(preferred_game)
# get new preferred games
for game in games:
if (game['away'], game['league']) in preferred_teams or (game['home'], game['league']) in preferred_teams:
if 'Final' not in game['status'] and game['id'] not in preferred_games:
preferred_games.append(game['id'])
print(preferred_games)
if now - last_switch > page_display_time:
last_switch = now
if show_preferred and len(preferred_games) > 0:
single_preferred_game = next(
(g for g in games if g['id'] == preferred_games[current_preferred_game]), None
)
if single_preferred_game:
print(f'Showing preferred game {single_preferred_game["home"]} vs {single_preferred_game["away"]}')
draw_single_game(canvas, single_preferred_game)
current_preferred_game += 1
if current_preferred_game >= len(preferred_games):
show_preferred = False
current_preferred_game = 0
current_page = 0
else:
print(f'Showing all games page {current_page} / {len(games)}')
draw_all_games(canvas, games, current_page)
current_page += 4
if current_page >= len(games):
current_page = 0
if len(preferred_games) > 0:
show_preferred = True
else:
canvas.Clear()
print('No games available')
# no games available, just draw placeholder
graphics.DrawText(canvas, font, 10, 22, graphics.Color(*Colors.RED.value), "No games today")
canvas = matrix.SwapOnVSync(canvas)
sleep(10)
if __name__ == "__main__": if __name__ == "__main__":
run() run()