Skip to content

Commit

Permalink
Pregame screen rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
ty-porter committed Mar 15, 2024
1 parent af3646a commit 439c762
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 14 deletions.
22 changes: 20 additions & 2 deletions rewrite/config/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import logging
import logging, platform

from datetime import datetime, timedelta

Expand All @@ -11,8 +11,12 @@

class Config:
REFERENCE_FILENAME = "config.json.example"

DATE_FORMAT = "%Y-%m-%d"

TIME_FORMAT_24H = "%H"
TIME_FORMAT_12H = "%#I" if platform.system() == "Windows" else "%-I"

def __init__(self, config_filename, width, height):
self.width = width
self.height = height
Expand All @@ -27,6 +31,7 @@ def __init__(self, config_filename, width, height):
self.colors = Colors()

self.__set_end_of_day()
self.__set_time_format()

def today(self):
if self.demo_date:
Expand Down Expand Up @@ -96,7 +101,20 @@ def __set_end_of_day(self):
hours, minutes = [int(part) for part in self.end_of_day.split(":")]
except:
hours, minutes = 0, 0
ScoreboardLogger.warning(f"Expected 24 hour time for end_of_day in format '12:34'. Received {self.end_of_day}. Defaulting to '00:00'.")
ScoreboardLogger.warning(
f"Expected 24 hour time for end_of_day in format '12:34'. Received {self.end_of_day}. Defaulting to '00:00'."
)

self.eod_hours = hours
self.eod_minutes = minutes

def __set_time_format(self):
if self.time_format == "24h":
self.time_format = Config.TIME_FORMAT_24H
elif self.time_format == "12h":
self.time_format = Config.TIME_FORMAT_12H
else:
ScoreboardLogger.warning(
f"Expected to be one of ('12h', '24h'). Received {self.time_format}. Defaulting to '12h'."
)
self.time_format = Config.TIME_FORMAT_24H
7 changes: 7 additions & 0 deletions rewrite/data/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ def is_pregame(self):
"""Returns whether the game is in a pregame state"""
return self.status in GameState.GAME_STATE_PREGAME

def is_warmup(self):
"""Returns whether the game is in a warmup state"""
return self.status == GameState.WARMUP

def is_complete(self):
"""Returns whether the game has been completed"""
return self.status in GameState.GAME_STATE_COMPLETE
Expand Down Expand Up @@ -134,6 +138,9 @@ def losing_team(self):

return opposite.get(self.winning_team(), None)

def probable_pitcher_id(self, team):
return value_at_keypath(self.data, f"gameData.probablePitchers.{team}").get("id", None)

def decision_pitcher_id(self, decision):
return value_at_keypath(self.data, f"liveData.decisions.{decision}").get("id", None)

Expand Down
5 changes: 4 additions & 1 deletion rewrite/presenters/postgame.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
class PostgamePresenter:
PITCHER_UNKNOWN = "Unknown"

def __init__(self, game):
def __init__(self, game, config):
self.game = game
self.config = config

winner_side = game.winning_team()

# Defaults
Expand Down
83 changes: 83 additions & 0 deletions rewrite/presenters/pregame.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import tzlocal


class PregamePresenter:
TBD = "TBD"

def __init__(self, game, config):
self.game = game
self.config = config

self.home_team = game.home_abbreviation()
self.away_team = game.away_abbreviation()

# TODO: No weather object yet.
# self.pregame_weather = game.pregame_weather()

self.status = game.status

away_id = game.probable_pitcher_id("away")
if away_id is not None:
name = game.full_name(away_id)
wins = game.pitcher_stat(away_id, "wins", "away")
losses = game.pitcher_stat(away_id, "losses", "away")
era = game.pitcher_stat(away_id, "era", "away")
self.away_starter = "{} ({}-{} {} ERA)".format(name, wins, losses, era)
else:
self.away_starter = PregamePresenter.TBD

home_id = game.probable_pitcher_id("home")
if home_id is not None:
name = game.full_name(home_id)
wins = game.pitcher_stat(home_id, "wins", "home")
losses = game.pitcher_stat(home_id, "losses", "home")
era = game.pitcher_stat(home_id, "era", "home")
self.home_starter = "{} ({}-{} {} ERA)".format(name, wins, losses, era)
else:
self.home_starter = PregamePresenter.TBD

# TODO: No broadcasts yet
# self.national_broadcasts = game.broadcasts()
# self.series_status = game.series_status()

@property
def start_time(self):
"""Converts MLB's pregame times (UTC) into the local time zone"""
try:
time_str = "{}:%M".format(self.config.time_format)
if self.config.time_format == self.config.TIME_FORMAT_12H:
time_str += "%p"

return self.game.datetime().astimezone(tzlocal.get_localzone()).strftime(time_str)
except:
return PregamePresenter.TBD

def pregame_info(self):
text = self.away_starter + " vs " + self.home_starter

# TODO: Add weather, broadcasts, playoffs
# if pregame.national_broadcasts:
# pitchers_text += " TV: " + ", ".join(pregame.national_broadcasts)
# if pregame_weather and pregame.pregame_weather:
# pitchers_text += " Weather: " + pregame.pregame_weather

# if is_playoffs:
# pitchers_text += " " + pregame.series_status

return text

def __str__(self):
s = "<{} {}> {} @ {}; {}; {} vs {}; Forecast: {}; TV: {}".format(
self.__class__.__name__,
hex(id(self)),
self.away_team,
self.home_team,
self.start_time,
self.away_starter,
self.home_starter
# TODO: re-add broadcasts
# ,
# self.pregame_weather,
# self.national_broadcasts,
)
return s
4 changes: 3 additions & 1 deletion rewrite/screens/components/team.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ def render(self):
self.__render_background()
self.__render_accents()
self.__render_team_name()
self.__render_scoreline()

if not self.game.is_pregame():
self.__render_scoreline()

def __render_background(self):
coords = self.layout.coords(f"teams.background.{self.kind}")
Expand Down
4 changes: 2 additions & 2 deletions rewrite/screens/games/postgame.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class PostgameScreen(GameScreen):
MAX_DURATION_SECONDS = 5

def render(self):
presenter = self.create_cached_object("postgame_presenter", PostgamePresenter, self.game)
presenter = self.create_cached_object("postgame_presenter", PostgamePresenter, self.game, self.config)

self.__render_final_inning(presenter)
self.__render_decision_scroll(presenter)
Expand All @@ -31,7 +31,7 @@ def __render_final_inning(self, presenter):
# text += " " + str(scoreboard.inning.number)

center_text = self.create_cached_object(
"postgame_center_text", CenteredText, self.canvas, coords.x, coords.y, font, font_size, color, text
"postgame_final", CenteredText, self.canvas, coords.x, coords.y, font, font_size, color, text
)
center_text.render_text()

Expand Down
70 changes: 63 additions & 7 deletions rewrite/screens/games/pregame.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,75 @@

from screens.games.base import GameScreen

from presenters.pregame import PregamePresenter

from utils.text import ScrollingText, CenteredText


class PregameScreen(GameScreen):
MAX_DURATION_SECONDS = 5

def render(self):
self.__render_start_time()
presenter = self.create_cached_object("pregame_presenter", PregamePresenter, self.game, self.config)

if self.game.is_warmup():
self.__render_warmup(presenter)
else:
self.__render_start_time(presenter)

def __render_start_time(self):
time_text = str(self.game.datetime())
self.__render_info(presenter)

# Overlay banners
self.away_team_banner.render()
self.home_team_banner.render()

def __render_start_time(self, presenter):
text = presenter.start_time
color = self.colors.graphics_color("pregame.start_time")
coords = self.layout.coords("pregame.start_time")
font, font_size = self.layout.font_for("pregame.start_time")
# color = colors.graphics_color("pregame.start_time")
# time_x = center_text_position(time_text, coords["x"], font["size"]["width"])

color = (255, 255, 255)
graphics.DrawText(self.canvas, font, 0, coords.y, color, time_text)
center_text = self.create_cached_object(
"pregame_start_time", CenteredText, self.canvas, coords.x, coords.y, font, font_size, color, text
)
center_text.render_text()

def __render_warmup(self, presenter):
text = presenter.status
color = self.colors.graphics_color("pregame.warmup_text")
coords = self.layout.coords("pregame.warmup_text")
font, font_size = self.layout.font_for("pregame.warmup_text")

center_text = self.create_cached_object(
"pregame_start_time", CenteredText, self.canvas, coords.x, coords.y, font, font_size, color, text
)
center_text.render_text()

def __render_info(self, presenter):
text = presenter.pregame_info()

coords = self.layout.coords("pregame.scrolling_text")
font, font_size = self.layout.font_for("pregame.scrolling_text")

color = self.colors.graphics_color("pregame.scrolling_text")
bgcolor = self.colors.graphics_color("default.background")

scroller = self.create_cached_object(
"pregame_scroller",
ScrollingText,
self.canvas,
coords.x,
coords.y,
coords.width,
coords.width,
font,
font_size,
color,
bgcolor,
text,
)
scroller.render_text()

# TODO: This can be better, but for now this screen is done when the text is gone.
if scroller.finished:
self.data.schedule.request_next_game()
2 changes: 1 addition & 1 deletion rewrite/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import argparse, os, json
import argparse, json, os

from utils import logger as ScoreboardLogger

Expand Down

0 comments on commit 439c762

Please sign in to comment.