From 5fc89b5ce4b25e0203789663635213fc23c25ee2 Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Mon, 14 Oct 2024 23:24:13 -0500 Subject: [PATCH] Added play table --- cogs/gameplay.py | 7 +- in_game/gameplay_models.py | 109 ++++++++++++++++++++++- in_game/gameplay_queries.py | 2 +- tests/gameplay_models/factory.py | 23 ++++- tests/gameplay_models/test_game_model.py | 23 ++++- tests/gameplay_models/test_play_model.py | 23 +++++ 6 files changed, 178 insertions(+), 9 deletions(-) create mode 100644 tests/gameplay_models/test_play_model.py diff --git a/cogs/gameplay.py b/cogs/gameplay.py index 20b5960..7783110 100644 --- a/cogs/gameplay.py +++ b/cogs/gameplay.py @@ -11,7 +11,8 @@ from api_calls import db_get from command_logic.gameplay import get_lineups_from_sheets from helpers import PD_PLAYERS_ROLE_NAME, team_role, user_has_role, random_gif, random_from_list -from in_game import ai_manager +# from in_game import ai_manager +from in_game.ai_manager import get_starting_pitcher, get_starting_lineup from in_game.game_helpers import PUBLIC_FIELDS_CATEGORY_NAME, legal_check from in_game.gameplay_models import Lineup, Session, engine, player_description, select, Game from in_game.gameplay_queries import get_channel_game_or_none, get_active_games_by_team, get_game_lineups, get_team_or_none, get_card_or_none @@ -183,7 +184,7 @@ class Gameplay(commands.Cog): await interaction.edit_original_response( content=f'{ai_team.gmname} is looking for a SP to counter {human_sp_card.player.name}...' ) - ai_sp_lineup = await ai_manager.get_starting_pitcher( + ai_sp_lineup = await get_starting_pitcher( session, ai_team, this_game, @@ -198,7 +199,7 @@ class Gameplay(commands.Cog): final_message = await interaction.channel.send( content=f'{ai_team.gmname} is filling out the {ai_team.sname} lineup card...' ) - batter_lineups = await ai_manager.get_starting_lineup( + batter_lineups = await get_starting_lineup( session, team=ai_team, game=this_game, diff --git a/in_game/gameplay_models.py b/in_game/gameplay_models.py index 58742a1..7bb4bde 100644 --- a/in_game/gameplay_models.py +++ b/in_game/gameplay_models.py @@ -54,7 +54,6 @@ class Team(TeamBase, table=True): # home_games: list['Game'] = Relationship(back_populates='home_team') - class Game(SQLModel, table=True): id: int | None = Field(default=None, primary_key=True) away_team_id: int = Field(foreign_key='team.id') @@ -93,6 +92,7 @@ class Game(SQLModel, table=True): sa_relationship_kwargs=dict(foreign_keys="[Game.home_team_id]") ) lineups: list['Lineup'] = Relationship(back_populates='game', cascade_delete=True) + plays: list['Play'] = Relationship(back_populates='game', cascade_delete=True) @property def cardset_param_string(self) -> str: @@ -110,6 +110,11 @@ class Game(SQLModel, table=True): title=f'{self.away_team_id} @ {self.home_team_id}', color=int('a6ce39', 16) ) + + def current_play(self, session: Session): + this_play = session.exec(select(Play).where(Play.game == self).order_by(Play.id.desc()).limit(1)).one() + return this_play + # @property # def game_prop(self) -> str: # return f'Game {self.id} / Week {self.week_num} / Type {self.game_type}' @@ -213,7 +218,6 @@ class Card(CardBase, table=True): lineups: list['Lineup'] = Relationship(back_populates='card', cascade_delete=True) - class Lineup(SQLModel, table=True): id: int | None = Field(default=None, primary_key=True) position: str = Field(index=True) @@ -236,6 +240,107 @@ class Lineup(SQLModel, table=True): card: Card = Relationship(back_populates='lineups') +class PlayBase(SQLModel): + id: int | None = Field(default=None, primary_key=True) + game_id: int = Field(foreign_key='game.id') + play_num: int + batter_id: int = Field(foreign_key='lineup.id') + pitcher_id: int = Field(foreign_key='lineup.id') + on_base_code: int = Field(default=0) + inning_half: str = Field(default='away') + inning_num: int = Field(default=1, ge=1) + batting_order: int = Field(default=1, ge=1, le=9) + starting_outs: int = Field(default=0, ge=0, le=2) + away_score: int = Field(default=0) + home_score: int = Field(default=0) + batter_pos: str | None = Field(default=None) + in_pow: bool = Field(default=False) + + on_first_id: int | None = Field(default=None, foreign_key='lineup.id') + on_first_final: int | None = Field(default=None) + on_second_id: int | None = Field(default=None, foreign_key='lineup.id') + on_second_final: int | None = Field(default=None) + on_third_id: int | None = Field(default=None, foreign_key='lineup.id') + on_third_final: int | None = Field(default=None) + batter_final: int | None = Field(default=None) + + pa: int = Field(default=0) + ab: int = Field(default=0) + run: int = Field(default=0) + e_run: int = Field(default=0) + hit: int = Field(default=0) + rbi: int = Field(default=0) + double: int = Field(default=0) + triple: int = Field(default=0) + homerun: int = Field(default=0) + bb: int = Field(default=0) + so: int = Field(default=0) + hbp: int = Field(default=0) + sac: int = Field(default=0) + ibb: int = Field(default=0) + gidp: int = Field(default=0) + bphr: int = Field(default=0) + bpfo: int = Field(default=0) + bp1b: int = Field(default=0) + bplo: int = Field(default=0) + sb: int = Field(default=0) + cs: int = Field(default=0) + outs: int = Field(default=0) + + wpa: float = Field(default=0) + re24: float = Field(default=0) + + catcher_id: int | None = Field(default=None, foreign_key='lineup.id') + defender_id: int | None = Field(default=None, foreign_key='lineup.id') + runner_id: int | None = Field(default=None, foreign_key='lineup.id') + + check_pos: str | None = Field(default=None) + error: int = Field(default=0) + wild_pitch: int = Field(default=0) + passed_ball: int = Field(default=0) + pick_off: int = Field(default=0) + balk: int = Field(default=0) + complete: bool = Field(default=False) + locked: bool = Field(default=False) + is_go_ahead: bool = Field(default=False) + is_tied: bool = Field(default=False) + is_new_inning: bool = Field(default=False) + + def ai_run_diff(self): + if self.game.ai_team == 'away': + return self.away_score - self.home_score + else: + return self.home_score - self.away_score + + +class Play(PlayBase, table=True): + game: Game = Relationship(back_populates='plays') + batter: Lineup = Relationship( + sa_relationship_kwargs=dict(foreign_keys="[Play.batter_id]") + ) + pitcher: Lineup = Relationship( + sa_relationship_kwargs=dict(foreign_keys="[Play.pitcher_id]") + ) + on_first: Lineup = Relationship( + sa_relationship_kwargs=dict(foreign_keys="[Play.on_first_id]") + ) + on_second: Lineup = Relationship( + sa_relationship_kwargs=dict(foreign_keys="[Play.on_second_id]") + ) + on_third: Lineup = Relationship( + sa_relationship_kwargs=dict(foreign_keys="[Play.on_third_id]") + ) + catcher: Lineup = Relationship( + sa_relationship_kwargs=dict(foreign_keys="[Play.catcher_id]") + ) + defender: Lineup = Relationship( + sa_relationship_kwargs=dict(foreign_keys="[Play.defender_id]") + ) + runner: Lineup = Relationship( + sa_relationship_kwargs=dict(foreign_keys="[Play.runner_id]") + ) + + """ BEGIN DEVELOPMENT HELPERS """ diff --git a/in_game/gameplay_queries.py b/in_game/gameplay_queries.py index 9d22fca..aab21b6 100644 --- a/in_game/gameplay_queries.py +++ b/in_game/gameplay_queries.py @@ -3,7 +3,7 @@ import logging from sqlalchemy import func from api_calls import db_get, db_post -from in_game.gameplay_models import CACHE_LIMIT, Card, CardBase, Lineup, Player, PlayerBase, Session, Team, TeamBase, select, or_, Game +from in_game.gameplay_models import CACHE_LIMIT, Card, CardBase, Lineup, Player, PlayerBase, Session, Team, TeamBase, select, or_, Game, Play def get_games_by_channel(session: Session, channel_id: int) -> list[Game]: diff --git a/tests/gameplay_models/factory.py b/tests/gameplay_models/factory.py index 228c1a6..eb23bb0 100644 --- a/tests/gameplay_models/factory.py +++ b/tests/gameplay_models/factory.py @@ -4,7 +4,7 @@ from sqlmodel import Session, SQLModel, create_engine from sqlmodel.pool import StaticPool from typing import Literal -from in_game.gameplay_models import Card, Cardset, Game, GameCardsetLink, Lineup, Team, Player +from in_game.gameplay_models import Card, Cardset, Game, GameCardsetLink, Lineup, Play, Team, Player @pytest.fixture(name='session') @@ -147,6 +147,27 @@ def session_fixture(): for lineup in all_lineups: session.add(lineup) + game_1_play_1 = Play( + game=game_1, + play_num=1, + batter=all_lineups[0], + batter_pos=all_lineups[0].position, + pitcher=all_lineups[19], + pa=1, + so=1 + ) + game_1_play_2 = Play( + game=game_1, + play_num=2, + batter=all_lineups[1], + batter_pos=all_lineups[1].position, + pitcher=all_lineups[19], + starting_outs=1 + ) + + session.add(game_1_play_1) + session.add(game_1_play_2) + session.commit() yield session diff --git a/tests/gameplay_models/test_game_model.py b/tests/gameplay_models/test_game_model.py index 4ee53f7..40d2371 100644 --- a/tests/gameplay_models/test_game_model.py +++ b/tests/gameplay_models/test_game_model.py @@ -1,5 +1,6 @@ import pytest from sqlalchemy import delete as sadelete +from sqlalchemy.sql.functions import sum, count from sqlmodel import Session, delete from in_game.gameplay_models import Game, Lineup, GameCardsetLink, select @@ -58,10 +59,10 @@ def test_games_by_channel(session: Session): session.add(game_2) session.commit() - with pytest.raises(LookupError) as exc_info: + with pytest.raises(Exception) as exc_info: get_channel_game_or_none(session, 5678) - assert str(exc_info) == "" + assert str(exc_info) == "" game_3 = session.get(Game, 3) game_2.active = False @@ -112,3 +113,21 @@ def test_get_scorebug(session: Session): assert scorebug.title == '31 @ 400' assert scorebug.color.value == int('a6ce39', 16) + + +def test_sum_function(session: Session): + """ + Testing out the sqlalchemy functions + """ + st = select( + sum(Game.away_team_id).label('nice'), + count(Game.active) + ) + print(f'sql: {st}') + result = session.exec(st) + print(f'result: {result}') + one_result = result.one() + print(f'one: {one_result}') + print(f'sum: {one_result[0]} / count: {one_result[1]}') + + assert False == False diff --git a/tests/gameplay_models/test_play_model.py b/tests/gameplay_models/test_play_model.py new file mode 100644 index 0000000..20fd5e5 --- /dev/null +++ b/tests/gameplay_models/test_play_model.py @@ -0,0 +1,23 @@ +from sqlmodel import Session, select + +from in_game.gameplay_models import Play, Game +from factory import session_fixture + + +def test_create_play(session: Session): + all_plays = session.exec(select(Play)).all() + + assert len(all_plays) == 2 + + play_1 = session.get(Play, 1) + + assert play_1.game_id == 1 + assert play_1.pa == 1 + assert play_1.pitcher_id == 20 + + +def test_get_current_play(session: Session): + game_1 = session.get(Game, 1) + curr_play = game_1.current_play(session) + + assert curr_play.play_num == 2 \ No newline at end of file