Skip to content

Commit

Permalink
Postgame banner 75% finished
Browse files Browse the repository at this point in the history
  • Loading branch information
ty-porter committed Mar 13, 2024
1 parent 803eea9 commit bc0de05
Show file tree
Hide file tree
Showing 10 changed files with 223 additions and 42 deletions.
15 changes: 9 additions & 6 deletions rewrite/config/colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,19 @@ def __fetch_colors(self, reference_filename):

return reference_colors

def team_graphics_color(self, keypath):
return self.__fetch_color(self._team_json, keypath)
def team_graphics_color(self, keypath, default=True):
return self.__fetch_color(self._team_json, keypath, default)

def graphics_color(self, keypath):
return self.__fetch_color(self._scoreboard_json, keypath)
def graphics_color(self, keypath, default=True):
return self.__fetch_color(self._scoreboard_json, keypath, default)

def __fetch_color(self, config, keypath):
def __fetch_color(self, config, keypath, default):
color = value_at_keypath(config, keypath)

if color:
return (color["r"], color["g"], color["b"])

return Colors.DEFAULT_COLOR
if default:
return Colors.DEFAULT_COLOR

return None
110 changes: 91 additions & 19 deletions rewrite/data/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from data import status as GameState

from utils import logger as ScoreboardLogger
from utils import value_at_keypath


class Game:
Expand Down Expand Up @@ -114,28 +115,10 @@ def is_inning_break(inning_state):
return inning_state not in GameState.GAME_STATE_INNING_LIVE

def datetime(self):
time_utc = self.data["gameData"]["datetime"]["dateTime"]
time_utc = value_at_keypath(self.data, "gameData.datetime.dateTime")

return dt.fromisoformat(time_utc.replace("Z", "+00:00"))

def home_score(self):
return self.data["liveData"]["linescore"]["teams"]["home"].get("runs", 0)

def away_score(self):
return self.data["liveData"]["linescore"]["teams"]["away"].get("runs", 0)

def home_hits(self):
return self.data["liveData"]["linescore"]["teams"]["home"].get("hits", 0)

def away_hits(self):
return self.data["liveData"]["linescore"]["teams"]["away"].get("hits", 0)

def home_errors(self):
return self.data["liveData"]["linescore"]["teams"]["home"].get("errors", 0)

def away_errors(self):
return self.data["liveData"]["linescore"]["teams"]["away"].get("errors", 0)

def winning_team(self):
if self.status == GameState.FINAL:
if self.home_score() > self.away_score():
Expand All @@ -150,6 +133,95 @@ def losing_team(self):

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

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

def full_name(self, player):
ID = Game.format_id(player)

return value_at_keypath(self.data, f"gameData.players.{ID}").get("fullName", "")

def pitcher_stat(self, player, stat, team=None):
ID = Game.format_id(player)

keypath = lambda team, ID: value_at_keypath(
self.data, f"liveData.boxscore.teams.{team}.players.{ID}.seasonStats"
)

if team is not None:
stats = keypath(team, ID).get("pitching", {})
else:
stats = keypath(team, ID).get("pitching", None) or keypath(team, ID).get("pitching", {})

return stats[stat]

def series_status(self):
# TODO: Reimplement series status
return "0-0"

@staticmethod
def format_id(ID):
if "ID" in str(ID):
return ID

return "ID" + str(ID)

"""
Home / Away data accessors.
TODO: Make this dynamic somehow?
"""

def home_hits(self):
return self.__hits("home")

def away_hits(self):
return self.__hits("away")

def __hits(self, variant):
return value_at_keypath(self.data, f"liveData.linescore.teams.{variant}").get("hits", 0)

def home_errors(self):
return self.__errors("home")

def away_errors(self):
return self.__errors("away")

def __errors(self, variant):
return value_at_keypath(self.data, f"liveData.linescore.teams.{variant}").get("errors", 0)

def home_score(self):
return self.__score("home")

def away_score(self):
return self.__score("away")

def __score(self, variant):
return value_at_keypath(self.data, f"liveData.linescore.teams.{variant}").get("runs", 0)

def home_name(self):
return self.__name("home")

def away_name(self):
return self.__name("away")

def __name(self, variant):
return value_at_keypath(self.data, f"gameData.teams.{variant}").get("teamName", "")

def home_abbreviation(self):
return self.__abbreviation("home")

def away_abbreviation(self):
return self.__abbreviation("away")

def __abbreviation(self, variant):
return value_at_keypath(self.data, f"gameData.teams.{variant}").get("abbreviation", "")

def home_record(self):
return self.__record("home")

def away_record(self):
return self.__record("away")

def __record(self, variant):
return value_at_keypath(self.data, f"gameData.teams.{variant}.record")
3 changes: 2 additions & 1 deletion rewrite/data/schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ def update(self):
return UpdateStatus.SUCCESS

def __fetch_updated_schedule(self, date):
self._games = statsapi.schedule(date.strftime("%Y-%m-%d"))
# self._games = statsapi.schedule(date.strftime("%Y-%m-%d"))
self._games = statsapi.schedule(date.strftime("2024-03-12"))

self.games = [Game.from_schedule(game) for game in self._games]

Expand Down
30 changes: 15 additions & 15 deletions rewrite/presenters/postgame.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,23 @@ def __init__(self, game):
self.save_pitcher = None
self.save_pitcher_saves = None

# winner = game.decision_pitcher_id("winner")
# if winner is not None:
# self.winning_pitcher = game.full_name(winner)
# self.winning_pitcher_wins = game.pitcher_stat(winner, "wins", winner_side)
# self.winning_pitcher_losses = game.pitcher_stat(winner, "losses", winner_side)
winner = game.decision_pitcher_id("winner")
if winner is not None:
self.winning_pitcher = game.full_name(winner)
self.winning_pitcher_wins = game.pitcher_stat(winner, "wins", winner_side)
self.winning_pitcher_losses = game.pitcher_stat(winner, "losses", winner_side)

# save = game.decision_pitcher_id("save")
# if save is not None:
# self.save_pitcher = game.full_name(save)
# self.save_pitcher_saves = game.pitcher_stat(save, "saves", winner_side)
save = game.decision_pitcher_id("save")
if save is not None:
self.save_pitcher = game.full_name(save)
self.save_pitcher_saves = game.pitcher_stat(save, "saves", winner_side)

# loser = game.decision_pitcher_id("loser")
# if loser is not None:
# loser_side = game.losing_team()
# self.losing_pitcher = game.full_name(loser)
# self.losing_pitcher_wins = game.pitcher_stat(loser, "wins", loser_side)
# self.losing_pitcher_losses = game.pitcher_stat(loser, "losses", loser_side)
loser = game.decision_pitcher_id("loser")
if loser is not None:
loser_side = game.losing_team()
self.losing_pitcher = game.full_name(loser)
self.losing_pitcher_wins = game.pitcher_stat(loser, "wins", loser_side)
self.losing_pitcher_losses = game.pitcher_stat(loser, "losses", loser_side)

self.series_status = game.series_status()

Expand Down
Empty file.
82 changes: 82 additions & 0 deletions rewrite/screens/components/team.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
from driver import graphics

from utils.graphics import DrawRect


class TeamBanner:
def __init__(self, kind, screen):
self.kind = kind

# Can reach into the screen to access config for that screen
self.screen = screen

# breakpoint()
self.team_name = self.game.home_name() if kind == "home" else self.game.away_name()
self.team_abbreviation = self.game.home_abbreviation() if kind == "home" else self.game.away_abbreviation()

self.__load_colors()

def render(self):
self.__render_background()
self.__render_accents()
self.__render_team_name()
self.__render_score()

def __render_background(self):
coords = self.layout.coords(f"teams.background.{self.kind}")

DrawRect(self.canvas, coords.x, coords.y, coords.width, coords.height, self.bg_color)

def __render_accents(self):
coords = self.layout.coords(f"teams.accent.{self.kind}")

DrawRect(self.canvas, coords.x, coords.y, coords.width, coords.height, self.accent_color)

def __render_team_name(self):
keypath = f"teams.name.{self.kind}"

coords = self.layout.coords(keypath)
font, font_size = self.layout.font_for(keypath)

# TODO: Trunc on long RHE
if self.config.full_team_names:
text = "{:13s}".format(self.team_name)
else:
text = "{:3s}".format(self.team_abbreviation.upper())

graphics.DrawText(self.canvas, font, coords.x, coords.y, self.text_color, text)

def __load_colors(self):
team_key = self.team_abbreviation.lower()

self.bg_color = self.__color(f"{team_key}.home", "default.home")
self.text_color = self.__color(f"{team_key}.text", "default.text")
self.accent_color = self.__color(f"{team_key}.accent", "default.accent")

def __color(self, keypath, default_keypath):
color = self.colors.team_graphics_color(keypath, default=False)

if color:
return color

return self.colors.team_graphics_color(default_keypath)

@property
def game(self):
return self.screen.game

@property
def canvas(self):
return self.screen.canvas

@property
def config(self):
return self.screen.config

@property
def colors(self):
return self.screen.colors

@property
def layout(self):
return self.screen.layout
Empty file.
4 changes: 4 additions & 0 deletions rewrite/screens/games/base.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from screens.base import ScreenBase
from screens.components.team import TeamBanner


class GameScreen(ScreenBase):
Expand All @@ -12,3 +13,6 @@ def __init__(self, *args, game=None, **kwargs):

if self.game is None:
raise GameScreen.MissingGame("Game screens cannot be instantiated without a game object!")

self.away_team_banner = TeamBanner("away", self)
self.home_team_banner = TeamBanner("home", self)
6 changes: 5 additions & 1 deletion rewrite/screens/games/postgame.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ def render(self):
self.__render_final_inning(presenter)
self.__render_decision_scroll(presenter)

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

def __render_final_inning(self, presenter):
text = "FINAL"
color = self.colors.graphics_color("final.inning")
Expand Down Expand Up @@ -56,7 +60,7 @@ def __render_decision_scroll(self, presenter):
)

if presenter.save_pitcher:
scroll_text += " SV: {} ({})".format(self.game.save_pitcher, self.game.save_pitcher_saves)
text += " SV: {} ({})".format(presenter.save_pitcher, presenter.save_pitcher_saves)

# TODO: Playoffs
# if is_playoffs:
Expand Down
15 changes: 15 additions & 0 deletions rewrite/utils/graphics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from driver import graphics


def DrawRect(canvas, x, y, width, height, color):
"""
Draws a rectangle on screen with (X, Y) given as screen coordinates where (0, 0) is top left.
Chooses the smallest dimension as the render direction to prevent extra draw calls.
"""
if width > height:
for offset in range(0, height):
graphics.DrawLine(canvas, x, y + offset, x + width - 1, y + offset, color)
else:
for offset in range(0, width):
graphics.DrawLine(canvas, x + offset, y, x + offset, y + height - 1, color)

0 comments on commit bc0de05

Please sign in to comment.