add fantasy module
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
import requests
|
||||
from PIL import Image
|
||||
from time import time
|
||||
from rgbmatrix import graphics
|
||||
from vars import PANEL_HEIGHT, PANEL_WIDTH, GAME_WIDTH, DIVIDER_COLOR, Colors, font, font_small
|
||||
|
||||
players = {
|
||||
"team1": [],
|
||||
"team2": []
|
||||
}
|
||||
last_fetch = 0
|
||||
|
||||
scroll_x = 0
|
||||
scroll_speed = 10
|
||||
frames_per_tick = 2
|
||||
tick = 0
|
||||
times_scrolled = 0
|
||||
virtual_canvas = None
|
||||
virtual_dirty = True
|
||||
|
||||
def rbg(color_tuple):
|
||||
r, g, b = color_tuple
|
||||
return graphics.Color(r, b, g)
|
||||
|
||||
def fetch_data():
|
||||
try:
|
||||
resp = requests.get("https://api.alexav.gg/v4/sports/fantasy", timeout=5)
|
||||
resp.raise_for_status()
|
||||
|
||||
for player in resp["team1"]["players"]:
|
||||
players['team1'].append({
|
||||
"first_name": player['first_name'],
|
||||
"last_name": player['last_name'],
|
||||
"abbr_name": f"{player['first_name'][0]}. {player['last_name']}",
|
||||
"position": player['position'],
|
||||
"team": player['team'],
|
||||
"injury_status": player['injury_status'],
|
||||
"injury_body_part": player['injury_body_part']
|
||||
})
|
||||
for player in resp["team2"]["players"]:
|
||||
players['team1'].append({
|
||||
"first_name": player['first_name'],
|
||||
"last_name": player['last_name'],
|
||||
"abbr_name": f"{player['first_name'][0]}. {player['last_name']}",
|
||||
"position": player['position'],
|
||||
"team": player['team'],
|
||||
"injury_status": player['injury_status'],
|
||||
"injury_body_part": player['injury_body_part']
|
||||
})
|
||||
|
||||
return players
|
||||
except Exception as e:
|
||||
print(f"[fantasy] fetch error: {e}")
|
||||
return None
|
||||
|
||||
def draw_text_overlay(canvas, players, scroll_x):
|
||||
total_width = GAME_WIDTH * len(players)
|
||||
|
||||
for i, player in enumerate(players):
|
||||
base_x = (i * GAME_WIDTH) - scroll_x
|
||||
|
||||
# draw twice to handle the wrap-around copy
|
||||
for wrap in [0, total_width]:
|
||||
x = base_x + wrap
|
||||
|
||||
# cull slots fully off screen
|
||||
if x + GAME_WIDTH < 0 or x >= PANEL_WIDTH:
|
||||
continue
|
||||
|
||||
graphics.DrawText(canvas, font_small, x + 18, 11,
|
||||
rbg(Colors.WHITE.value), player['abbr_name'])
|
||||
graphics.DrawText(canvas, font_small, x + 18, 27,
|
||||
rbg(Colors.WHITE.value), player['team'])
|
||||
# graphics.DrawText(canvas, font, x + 40, 13,
|
||||
# rbg(Colors.WHITE.value), str(game["away_score"]))
|
||||
# graphics.DrawText(canvas, font, x + 40, 29,
|
||||
# rbg(Colors.WHITE.value), str(game["home_score"]))
|
||||
|
||||
# # if the time is shown it should be split between lines
|
||||
# # if not, just display the status
|
||||
# if "AM" in game["status"] or "PM" in game["status"]:
|
||||
# game_status_split = game["status"].split("-")
|
||||
# date = game_status_split[0].strip()
|
||||
# time = game_status_split[1].strip()
|
||||
|
||||
# graphics.DrawText(canvas, font_small, x + 60, 10,
|
||||
# rbg(Colors.YELLOW.value), date)
|
||||
# graphics.DrawText(canvas, font_small, x + 60, 20,
|
||||
# rbg(Colors.YELLOW.value), time)
|
||||
# graphics.DrawText(canvas, font_small, x + 60, 30,
|
||||
# rbg(Colors.YELLOW.value), game["venue"])
|
||||
# else:
|
||||
# graphics.DrawText(canvas, font_small, x + 65, 20,
|
||||
# rbg(Colors.YELLOW.value), game["status"])
|
||||
|
||||
def render_player(matrix, img, player, x_offset):
|
||||
league = "nfl"
|
||||
|
||||
away_logo = matrix.load_logo(league, player['team'])
|
||||
home_logo = matrix.load_logo(league, player['team'])
|
||||
if away_logo:
|
||||
img.paste(away_logo.resize((14, 14)), (x_offset, 0))
|
||||
if home_logo:
|
||||
img.paste(home_logo.resize((14, 14)), (x_offset, 16))
|
||||
|
||||
# divider on right edge (except last slot handled by wrapping)
|
||||
for row in range(PANEL_HEIGHT):
|
||||
img.putpixel((x_offset + GAME_WIDTH - 1, row), DIVIDER_COLOR)
|
||||
|
||||
def build_canvas(matrix, team):
|
||||
total_players = len(players[team])
|
||||
total_width = GAME_WIDTH * (total_players + 4)
|
||||
img = Image.new("RGB", (total_width, PANEL_HEIGHT), (0,0,0))
|
||||
|
||||
for i, player in enumerate(total_players * 2):
|
||||
if i >= total_players + 4:
|
||||
break
|
||||
render_player(matrix, img, player, i * GAME_WIDTH)
|
||||
|
||||
return img, total_players
|
||||
|
||||
def blit_slice(canvas, pil_img, x_offset):
|
||||
total_width = pil_img.width
|
||||
for x in range(PANEL_WIDTH):
|
||||
src_x = (x_offset + x) % total_width
|
||||
for y in range(PANEL_HEIGHT):
|
||||
r, g, b = pil_img.getpixel((src_x, y))
|
||||
canvas.SetPixel(x, y, r, b, g)
|
||||
|
||||
def draw_frame(matrix):
|
||||
global players, last_fetch, virtual_canvas, virtual_dirty, scroll_x, tick
|
||||
global total_players
|
||||
current_team = "team1"
|
||||
now = time()
|
||||
|
||||
if now - last_fetch > 30 or not players['team1'] or not players['team2']:
|
||||
players = fetch_data()
|
||||
last_fetch = now
|
||||
virtual_dirty = True
|
||||
|
||||
if virtual_dirty or virtual_canvas is None:
|
||||
result = build_canvas(matrix, current_team)
|
||||
if result:
|
||||
virtual_canvas, total_players = result
|
||||
virtual_dirty = False
|
||||
scroll_x = 0
|
||||
|
||||
matrix.canvas.Clear()
|
||||
|
||||
if not len(players[current_team] > 0):
|
||||
graphics.DrawText(matrix.canvas, font, 10, 22,
|
||||
rbg(Colors.RED.value),
|
||||
"No players found")
|
||||
scroll_x = tick = 0
|
||||
return matrix.canvas
|
||||
|
||||
total_scroll_width = GAME_WIDTH * len(players[current_team])
|
||||
if virtual_canvas:
|
||||
blit_slice(matrix.canvas, virtual_canvas, scroll_x)
|
||||
draw_text_overlay(matrix.canvas, players[current_team], scroll_x)
|
||||
|
||||
tick += 1
|
||||
if tick >= frames_per_tick:
|
||||
tick = 0
|
||||
next_x = scroll_x + scroll_speed
|
||||
if next_x >= total_scroll_width:
|
||||
scroll_x = 0
|
||||
tick = 0
|
||||
|
||||
if current_team == "team1":
|
||||
current_team = "team2"
|
||||
return matrix.canvas
|
||||
else:
|
||||
current_team = "team1"
|
||||
return None
|
||||
scroll_x = next_x
|
||||
|
||||
return matrix.canvas
|
||||
Reference in New Issue
Block a user