diff --git a/hockey/api.py b/hockey/api.py index d1552c4ab0..147e0c96ee 100644 --- a/hockey/api.py +++ b/hockey/api.py @@ -113,6 +113,9 @@ class GameEventTypeCode(Enum): DELAYED_PENALTY = 535 FAILED_SHOT_ATTEMPT = 537 + def __str__(self): + return self.name.title().replace("_", " ") + class Situation: def __init__(self, code: str): @@ -140,9 +143,13 @@ def strength(self, home: bool) -> str: if self.home_skaters == self.away_skaters == 3: return _("3v3") if home and self.home_skaters > self.away_skaters: + if self.away_skaters == 0: + return _("Shootout") return _("Power Play") if not home and self.home_skaters > self.away_skaters: - return _("Shorthanded Goal") + if self.away_skaters == 0: + return _("Shootout") + return _("Shorthanded") def empty_net(self, home: bool) -> str: """ @@ -158,6 +165,35 @@ def empty_net(self, home: bool) -> str: return "" +@dataclass +class Player: + teamId: int + playerId: int + firstName: dict + lastName: dict + sweaterNumber: int + positionCode: str + headshot: str + + @property + def name(self) -> str: + first = self.firstName.get("default", _("Unknown")) + last = self.lastName.get("default", _("Unknown")) + return f"{first} {last}" + + @classmethod + def from_json(cls, data: dict) -> Player: + return cls( + teamId=data.get("teamId"), + playerId=data.get("playerId"), + firstName=data.get("firstName"), + lastName=data.get("lastName"), + sweaterNumber=data.get("sweaterNumber", 0), + positionCode=data.get("positionCode"), + headshot=data.get("headshot"), + ) + + @dataclass class Event: id: int @@ -211,14 +247,14 @@ def description(self, data: dict) -> str: first_name = player.get("firstName", {}).get("default", "") last_name = player.get("lastName", {}).get("default", "") total = self.details.get("scoringPlayerTotal", 0) - description += f"{first_name} {last_name} ({total}) {shot_type}, " + description += f"{first_name} {last_name} ({total}) {shot_type}" if key == "assist1PlayerId": player = self.get_player(value, data) first_name = player.get("firstName", {}).get("default", "") last_name = player.get("lastName", {}).get("default", "") total = self.details.get("assist1PlayerTotal", 0) - description += _("assists: {first_name} {last_name} ({total}), ").format( + description += _(" assists: {first_name} {last_name} ({total})").format( first_name=first_name, last_name=last_name, total=total ) if key == "assist2PlayerId": @@ -226,7 +262,7 @@ def description(self, data: dict) -> str: first_name = player.get("firstName", {}).get("default", "") last_name = player.get("lastName", {}).get("default", "") total = self.details.get("assist1PlayerTotal", 0) - description += _("{first_name} {last_name} ({total})").format( + description += _(", {first_name} {last_name} ({total})").format( first_name=first_name, last_name=last_name, total=total ) @@ -273,7 +309,7 @@ def to_goal(self, data: dict, content: Optional[dict] = None) -> Goal: strength=self.situation.strength(home), strength_code=self.situation.code, empty_net=self.situation.empty_net(home), - event="", + event=str(self.type_code), link=self.get_highlight(content), ) @@ -366,6 +402,9 @@ async def close(self): async def get_game_content(self, game_id: int): raise NotImplementedError() + async def get_standings(self) -> Standings: + raise NotImplementedError + async def get_schedule( self, team: Optional[str] = None, @@ -915,14 +954,25 @@ async def to_game(self, data: dict, content: Optional[dict] = None) -> Game: game_start = data["startTimeUTC"] period_ord = ORDINALS.get(period, "") + period_descriptor = data.get("periodDescriptor", {}).get("periodType", "REG") + if period_descriptor != "REG": + period_ord = period_descriptor events = [Event.from_json(i) for i in data["plays"]] goals = [ e.to_goal(data, content=content) for e in events if e.type_code is GameEventTypeCode.GOAL ] - home_roster = [p for p in data["rosterSpots"] if p["teamId"] == home_id] - away_roster = [p for p in data["rosterSpots"] if p["teamId"] == away_id] + home_roster = { + p["playerId"]: Player.from_json(p) + for p in data["rosterSpots"] + if p["teamId"] == home_id + } + away_roster = { + p["playerId"]: Player.from_json(p) + for p in data["rosterSpots"] + if p["teamId"] == away_id + } game_type = GameType.from_int(data["gameType"]) first_star = None second_star = None diff --git a/hockey/game.py b/hockey/game.py index e2fcfcf733..c8d20f3f83 100644 --- a/hockey/game.py +++ b/hockey/game.py @@ -19,7 +19,7 @@ from .standings import LeagueRecord, Playoffs if TYPE_CHECKING: - from .api import GameData + from .api import GameData, Player _ = Translator("Hockey", __file__) @@ -263,8 +263,8 @@ class Game: first_star: Optional[str] second_star: Optional[str] third_star: Optional[str] - away_roster: Optional[dict] - home_roster: Optional[dict] + away_roster: Dict[int, Player] + home_roster: Dict[int, Player] link: Optional[str] def __init__(self, **kwargs): @@ -313,8 +313,8 @@ def __init__(self, **kwargs): self.first_star = kwargs.get("first_star") self.second_star = kwargs.get("second_star") self.third_star = kwargs.get("third_star") - self.away_roster = kwargs.get("away_roster") - self.home_roster = kwargs.get("home_roster") + self.away_roster = kwargs.get("away_roster", {}) + self.home_roster = kwargs.get("home_roster", {}) self.game_type: GameType = kwargs.get("game_type", GameType.unknown) self.link = kwargs.get("link") self.season = kwargs.get("season") diff --git a/hockey/goal.py b/hockey/goal.py index 44309911a2..fa3f0d4d5d 100644 --- a/hockey/goal.py +++ b/hockey/goal.py @@ -458,15 +458,14 @@ async def get_shootout_display(self, game: Game) -> Tuple[str, str]: away_msg = "" score = "☑ {scorer}\n" miss = "❌ {scorer}\n" - players = game.home_roster - players.update(game.away_roster) + for goal in game.home_goals: scorer = "" scorer_num = "" if goal.time > self.time: break - if f"ID{goal.scorer_id}" in players: - scorer = players[f"ID{goal.scorer_id}"]["person"]["fullName"] + if goal.scorer_id in game.home_roster: + scorer = game.home_roster[goal.scorer_id].name if goal.event in ["Shot", "Missed Shot"] and goal.period_ord == "SO": home_msg += miss.format(scorer=scorer) if goal.event in ["Goal"] and goal.period_ord == "SO": @@ -479,8 +478,8 @@ async def get_shootout_display(self, game: Game) -> Tuple[str, str]: # is in the shootout and we reach a goal that happened *after* # this goal object, we break for a cleaner looking shootout display. break - if f"ID{goal.scorer_id}" in players: - scorer = players[f"ID{goal.scorer_id}"]["person"]["fullName"] + if goal.scorer_id in game.away_roster: + scorer = game.away_roster[goal.scorer_id].name if goal.event in ["Shot", "Missed Shot"] and goal.period_ord == "SO": away_msg += miss.format(scorer=scorer) if goal.event in ["Goal"] and goal.period_ord == "SO": diff --git a/hockey/hockey_commands.py b/hockey/hockey_commands.py index df3885182b..ce9aba730c 100644 --- a/hockey/hockey_commands.py +++ b/hockey/hockey_commands.py @@ -50,7 +50,10 @@ async def version(self, ctx: commands.Context) -> None: """ Display the current version """ - await ctx.send(_("Hockey version ") + self.__version__) + ret = _("Hockey version ") + self.__version__ + if self._commit: + ret += f"\n- Commit: [{self._commit[:9]}]({self._repo}/tree/{self._commit})" + await ctx.send(ret) @commands.command() async def hockeyhub(self, ctx: commands.Context, *, search: str) -> None: diff --git a/hockey/hockeyset.py b/hockey/hockeyset.py index 17bc8b0715..f6f057fc75 100644 --- a/hockey/hockeyset.py +++ b/hockey/hockeyset.py @@ -562,7 +562,7 @@ async def post_standings( await ctx.send(msg) return try: - standings = await Standings.get_team_standings(session=self.session) + standings = await self.api.get_standings() except aiohttp.ClientConnectorError: await ctx.send( _("There's an issue accessing the NHL API at the moment. Try again later.") diff --git a/hockey/pickems.py b/hockey/pickems.py index 34226bc6d2..b0ee371ce1 100644 --- a/hockey/pickems.py +++ b/hockey/pickems.py @@ -194,9 +194,9 @@ def add_vote(self, user_id: int, team: discord.Emoji) -> None: time_now = datetime.now(timezone.utc) team_choice = None - if str(team.id) in self.home_emoji: + if str(team.id) in str(self.home_emoji): team_choice = self.home_team - if str(team.id) in self.away_emoji: + if str(team.id) in str(self.away_emoji): team_choice = self.away_team if team_choice is None: raise NotAValidTeamError()