From 724b8922f298b14cbab50af80f58c57601912973 Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Fri, 27 Dec 2024 16:12:25 -0600 Subject: [PATCH] Update gauntlet get SP for new objects Handle gamestates without full lineups Added /set command for lineup and SP Fixed uncapped hit bugs Added league_name property to Games Fix get_team for gauntlets Fixed SelectSP dropdown bug --- cogs/gameplay.py | 146 ++++++++++++++++++++++++++------ command_logic/logic_gameplay.py | 57 +++++++------ exceptions.py | 4 + gauntlets.py | 38 ++++++--- in_game/gameplay_models.py | 23 ++++- in_game/gameplay_queries.py | 21 +++-- utilities/dropdown.py | 14 ++- 7 files changed, 225 insertions(+), 78 deletions(-) diff --git a/cogs/gameplay.py b/cogs/gameplay.py index ed07c6b..0f5ec8c 100644 --- a/cogs/gameplay.py +++ b/cogs/gameplay.py @@ -1,3 +1,4 @@ +import asyncio import logging from typing import Literal @@ -8,12 +9,13 @@ from discord.app_commands import Choice from discord.ext import commands, tasks import pygsheets +import sqlalchemy from sqlmodel import or_ from api_calls import db_get from command_logic.logic_gameplay import advance_runners, bunts, chaos, complete_game, doubles, flyballs, frame_checks, get_full_roster_from_sheets, get_lineups_from_sheets, checks_log_interaction, complete_play, get_scorebug_embed, groundballs, hit_by_pitch, homeruns, is_game_over, lineouts, manual_end_game, new_game_conflicts, popouts, read_lineup, show_defense_cards, singles, starting_pitcher_dropdown_view, steals, strikeouts, sub_batter_dropdown_view, triples, undo_play, update_game_settings, walks, xchecks, activate_last_play from dice import ab_roll -from exceptions import GameNotFoundException, GoogleSheetsException, TeamNotFoundException, PlayNotFoundException, GameException, log_exception +from exceptions import GameNotFoundException, GoogleSheetsException, LineupsMissingException, TeamNotFoundException, PlayNotFoundException, GameException, log_exception import gauntlets from helpers import DEFENSE_LITERAL, PD_PLAYERS_ROLE_NAME, get_channel, team_role, user_has_role, random_gif, random_from_list @@ -21,7 +23,7 @@ from helpers import DEFENSE_LITERAL, PD_PLAYERS_ROLE_NAME, get_channel, team_rol 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, Play, Session, engine, player_description, select, Game -from in_game.gameplay_queries import get_position, get_available_pitchers, get_channel_game_or_none, get_active_games_by_team, get_game_lineups, get_team_or_none, get_card_or_none +from in_game.gameplay_queries import get_one_lineup, get_position, get_available_pitchers, get_channel_game_or_none, get_active_games_by_team, get_game_lineups, get_team_or_none, get_card_or_none from utilities.buttons import Confirm, ScorebugButtons, ask_confirm from utilities.dropdown import DropdownView, SelectStartingPitcher @@ -62,7 +64,11 @@ class Gameplay(commands.Cog): if this_play is None: logger.info(f'this_play is None, searching for game in channel {interaction.channel.id}') this_game = get_channel_game_or_none(session, interaction.channel.id) - this_play = activate_last_play(session, this_game) + try: + this_play = activate_last_play(session, this_game) + except Exception as e: + this_play = this_game.initialize_play(session) + if this_play is None: log_exception(PlayNotFoundException, f'Attempting to display gamestate, but cannot find current play') @@ -312,13 +318,20 @@ class Gameplay(commands.Cog): await final_message.edit( content=f'{away_role.mention} @ {home_role.mention} is set!\n\n' - f'Go ahead and set lineups with the `/read-lineup` command!', + f'Go ahead and set your lineup with the `/set lineup` command!', embed=embed ) @group_new_game.command(name='gauntlet', description='Start a new Gauntlet game against an AI') + @app_commands.choices( + roster=[ + Choice(value='1', name='Primary'), + Choice(value='2', name='Secondary'), + Choice(value='3', name='Ranked') + ] + ) @app_commands.checks.has_any_role(PD_PLAYERS_ROLE_NAME) - async def new_game_gauntlet_command(self, interaction: discord.Interaction): + async def new_game_gauntlet_command(self, interaction: discord.Interaction, roster: Choice[str]): await interaction.response.defer() with Session(engine) as session: @@ -401,7 +414,7 @@ class Gameplay(commands.Cog): logger.info(f'opponent: {ai_team}') ai_role = await team_role(interaction, ai_team) - human_role = await team_role(interaction, human_team) + human_role = await team_role(interaction, main_team) away_role = ai_role if is_home else human_role home_role = human_role if is_home else ai_role @@ -423,22 +436,24 @@ class Gameplay(commands.Cog): week=current['week'], first_message=None if interaction.message is None else interaction.message.channel.id, ai_team='away' if is_home else 'home', + away_roster_id=69 if is_home else int(roster.value), + home_roster_id=int(roster.value) if is_home else 69, game_type=game_code ) logger.info( - f'Game {this_game.id} between {human_team.abbrev} and {ai_team.abbrev} is initializing!' + f'Game between {human_team.abbrev} and {ai_team.abbrev} is initializing!' ) # Get AI SP await interaction.edit_original_response( content=f'{ai_team.gmname} is looking for a Starting Pitcher...' ) - ai_sp_lineup = await get_starting_pitcher( + ai_sp_lineup = await gauntlets.get_starting_pitcher( session, ai_team, this_game, - is_home=True if not is_home else False, - league_name=game_code + this_event, + this_run ) logger.info(f'Chosen SP in Game {this_game.id}: {ai_sp_lineup.player.name_with_desc}') await interaction.edit_original_response( @@ -454,14 +469,10 @@ class Gameplay(commands.Cog): session, team=ai_team, game=this_game, - league_name=game_code, + league_name=f'gauntlet-{this_event["id"]}', sp_name=ai_sp_lineup.player.name ) - await interaction.edit_original_response( - content=f'Creating this game for {t_role.mention}:\n{this_game}' - ) - # Check for last game settings logger.info(f'Checking human team\'s automation preferences...') g_query = session.exec(select(Game).where(or_(Game.home_team == human_team, Game.away_team == human_team)).order_by(Game.id.desc()).limit(1)).all() @@ -491,8 +502,8 @@ class Gameplay(commands.Cog): # Get pitchers from rosterlinks done = await get_full_roster_from_sheets(session, interaction, self.sheets, this_game, human_team, 1) if done: - sp_view = starting_pitcher_dropdown_view(session, this_game, human_team) - await interaction.channel.send(content=f'### {human_team.lname} Starting Pitcher', view=sp_view) + sp_view = starting_pitcher_dropdown_view(session, this_game, human_team, game_type=f'gauntlet-{this_event["id"]}') + sp_message = await interaction.channel.send(content=f'### {human_team.lname} Starting Pitcher', view=sp_view) await final_message.edit( content=f'{away_role.mention} @ {home_role.mention} is set!', @@ -535,7 +546,9 @@ class Gameplay(commands.Cog): else: await ctx.send(f'It stays. For now.') - @app_commands.command(name='read-lineup', description='Import a saved lineup for this channel\'s PD game.') + group_set_rosters = app_commands.Group(name='set', description='Set SP and lineup') + + @group_set_rosters.command(name='lineup', description='Import a saved lineup for this channel\'s PD game.') @app_commands.describe( lineup='Which handedness lineup are you using?' ) @@ -563,18 +576,85 @@ class Gameplay(commands.Cog): await interaction.edit_original_response(content='Bruh. Only GMs of the active teams can pull lineups.') return - this_play = await read_lineup( - session, - interaction, - this_game=this_game, - lineup_team=this_team, - sheets_auth=self.sheets, - lineup=lineup, - league_name=this_game.game_type - ) + logger.info(f'lineup: {lineup} / value: {lineup.value} / name: {lineup.name}') + try: + this_play = await read_lineup( + session, + interaction, + this_game=this_game, + lineup_team=this_team, + sheets_auth=self.sheets, + lineup_num=int(lineup.value), + league_name=this_game.game_type + ) + except LineupsMissingException as e: + await interaction.edit_original_response(content='Run `/set starting-pitcher` to select your SP') + return + if this_play is not None: await self.post_play(session, interaction, this_play) + @group_set_rosters.command(name='starting-pitcher') + @app_commands.checks.has_any_role(PD_PLAYERS_ROLE_NAME) + async def set_starting_pitcher(self, interaction: discord.Interaction): + await interaction.response.defer() + + with Session(engine) as session: + this_game = get_channel_game_or_none(session, interaction.channel_id) + if this_game is None: + await interaction.edit_original_response( + content=f'Hm. I don\'t see a game going on in this channel. Am I drunk?' + ) + return + + this_team = this_game.human_team + if interaction.user.id != this_team.gmid: + logger.info(f'{interaction.user.name} tried to run a command in Game {this_game.id} when they aren\'t a GM in the game.') + await interaction.edit_original_response(content='Bruh. Only GMs of the active teams can pull lineups.') + return + + try: + check_sp = get_one_lineup(session, this_game, this_team, position='P') + except sqlalchemy.exc.NoResultFound as e: + # if 'NoResultFound' not in str(e): + # logger.error(f'Error checking for existing sp: {e}') + # log_exception(e, 'Unable to check your lineup for an existing SP') + # else: + logger.info(f'No pitcher in game, good to go') + check_sp = None + + if check_sp is not None: + logger.info(f'Already an SP in Game {this_game.id}, asking if we should swap') + swap_sp = await ask_confirm( + interaction, + question=f'{check_sp.player.name} is already scheduled to start this game - would you like to switch?', + label_type='yes' + ) + if not swap_sp: + logger.info(f'No swap being made') + await interaction.edit_original_response(content=f'We will leave {check_sp.player.name} on the lineup card.') + return + + session.delete(check_sp) + session.commit() + + sp_view = starting_pitcher_dropdown_view(session, this_game, this_team, game_type=this_game.league_name) + await interaction.edit_original_response(content=f'### {this_team.lname} Starting Pitcher', view=sp_view) + + await sp_view.wait() + if not sp_view.values: + await interaction.edit_original_response(content=f'Run `/set starting-pitcher` command again to select your SP', view=None) + + for x in range(15): + try: + this_play = this_game.initialize_play(session) + await self.post_play(session, interaction, this_play) + return + + except LineupsMissingException as e: + logger.info(f'Waiting for SP to be set in game {this_game.id}') + await asyncio.sleep(2) + @app_commands.command(name='gamestate', description='Post the current game state') async def gamestate_command(self, interaction: discord.Interaction, include_lineups: bool = False): await interaction.response.defer(ephemeral=True, thinking=True) @@ -588,7 +668,17 @@ class Gameplay(commands.Cog): return this_play = this_game.current_play_or_none(session) - await self.post_play(session, interaction, this_play, full_length=include_lineups) + try: + await self.post_play(session, interaction, this_play, full_length=include_lineups) + except LineupsMissingException as e: + logger.info(f'Could not post full scorebug embed, posting lineups') + ai_team = this_game.away_team if this_game.ai_team == 'away' else this_game.home_team + embed = await get_scorebug_embed(session, this_game) + embed.clear_fields() + embed.add_field( + name=f'{ai_team.abbrev} Lineup', + value=this_game.team_lineup(session, ai_team) + ) @app_commands.command(name='settings-ingame', description='Change in-game settings') @app_commands.describe( diff --git a/command_logic/logic_gameplay.py b/command_logic/logic_gameplay.py index 38dd3d9..56aea09 100644 --- a/command_logic/logic_gameplay.py +++ b/command_logic/logic_gameplay.py @@ -261,14 +261,14 @@ async def get_scorebug_embed(session: Session, this_game: Game, full_length: boo return embed -def starting_pitcher_dropdown_view(session: Session, this_game: Game, human_team: Team): +def starting_pitcher_dropdown_view(session: Session, this_game: Game, human_team: Team, game_type: str = None): pitchers = get_available_pitchers(session, this_game, human_team, sort='starter-desc') logger.info(f'sorted pitchers: {pitchers}') sp_selection = SelectStartingPitcher( this_game=this_game, this_team=human_team, session=session, - league_name=this_game.game_type, + league_name=this_game.game_type if game_type is None else game_type, options=[SelectOption(label=f'{x.player.name_with_desc} (S{x.pitcherscouting.pitchingcard.starter_rating}/R{x.pitcherscouting.pitchingcard.relief_rating})', value=x.id) for x in pitchers], placeholder='Select your starting pitcher' ) @@ -289,7 +289,7 @@ def sub_batter_dropdown_view(session: Session, this_game: Game, human_team: Team return DropdownView(dropdown_objects=[bat_selection]) -async def read_lineup(session: Session, interaction: discord.Interaction, this_game: Game, lineup_team: Team, sheets_auth, lineup: Choice[str], league_name: str): +async def read_lineup(session: Session, interaction: discord.Interaction, this_game: Game, lineup_team: Team, sheets_auth, lineup_num: int, league_name: str): """ Commits lineups and rosterlinks """ @@ -309,17 +309,10 @@ async def read_lineup(session: Session, interaction: discord.Interaction, this_g session.add(this_game) - human_lineups = await get_lineups_from_sheets(session, sheets_auth, this_game, this_team=lineup_team, lineup_num=lineup.name, roster_num=this_game.away_roster_id if this_game.home_team.is_ai else this_game.home_roster_id) + human_lineups = await get_lineups_from_sheets(session, sheets_auth, this_game, this_team=lineup_team, lineup_num=lineup_num, roster_num=this_game.away_roster_id if this_game.home_team.is_ai else this_game.home_roster_id) await interaction.edit_original_response(content='Heard from sheets, pulling in scouting data...') - legal_data = await legal_check([lineup.card.id for lineup in human_lineups], difficulty_name=league_name) - if not legal_data['legal']: - await interaction.edit_original_response( - content=f'It looks like this is a Ranked Legal game and {legal_data["error_string"]} is not legal in {league_name} games. You can start a new game once you update this lineup.' - ) - return None - for batter in human_lineups: session.add(batter) @@ -531,14 +524,15 @@ def complete_play(session:Session, this_play: Play): async def get_lineups_from_sheets(session: Session, sheets, this_game: Game, this_team: Team, lineup_num: int, roster_num: int) -> list[Lineup]: - logger.debug(f'get_lineups_from_sheets - sheets: {sheets}') + logger.info(f'get_lineups_from_sheets - sheets: {sheets}') this_sheet = sheets.open_by_key(this_team.gsheet) - logger.debug(f'this_sheet: {this_sheet}') + logger.info(f'this_sheet: {this_sheet}') r_sheet = this_sheet.worksheet_by_title('My Rosters') - logger.debug(f'r_sheet: {r_sheet}') + logger.info(f'r_sheet: {r_sheet}') + logger.info(f'lineup_num: {roster_num}') if lineup_num == 1: row_start = 9 row_end = 17 @@ -546,20 +540,21 @@ async def get_lineups_from_sheets(session: Session, sheets, this_game: Game, thi row_start = 18 row_end = 26 - if roster_num == 1: + logger.info(f'roster_num: {roster_num}') + if int(roster_num) == 1: l_range = f'H{row_start}:I{row_end}' - elif roster_num == 2: + elif int(roster_num) == 2: l_range = f'J{row_start}:K{row_end}' else: l_range = f'L{row_start}:M{row_end}' - logger.debug(f'l_range: {l_range}') + logger.info(f'l_range: {l_range}') raw_cells = r_sheet.range(l_range) - logger.debug(f'raw_cells: {raw_cells}') + logger.info(f'raw_cells: {raw_cells}') try: lineup_cells = [(row[0].value, int(row[1].value)) for row in raw_cells] - logger.debug(f'lineup_cells: {lineup_cells}') + logger.info(f'lineup_cells: {lineup_cells}') except ValueError as e: logger.error(f'Could not pull roster for {this_team.abbrev}: {e}') log_exception(GoogleSheetsException, f'Uh oh. Looks like your lineup might not be saved. I am reading blanks when I try to get the card IDs') @@ -596,7 +591,7 @@ async def get_lineups_from_sheets(session: Session, sheets, this_game: Game, thi ) all_lineups.append(this_lineup) - legal_data = await legal_check([card_ids], difficulty_name=this_game.game_type) + legal_data = await legal_check([card_ids], difficulty_name=this_game.league_name) logger.debug(f'legal_data: {legal_data}') if not legal_data['legal']: raise CardLegalityException(f'The following cards appear to be illegal for this game mode:\n{legal_data["error_string"]}') @@ -1366,7 +1361,7 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact logger.info(f'trail_safe_range: {trail_safe_range}') if trail_base == 3 and outfielder.position != 'CF': - of_mod = 2 if outfielder.position == 'LF' else -2 + of_mod = -2 if outfielder.position == 'LF' else 2 logger.info(f'{outfielder.position} to 3B mod: {of_mod}') trail_safe_range += of_mod @@ -1732,7 +1727,7 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact lead_runner_embed.add_field(name='Runner Not Held', value='+1') logger.info(f'runner was not held, +1 to lead safe range: {lead_safe_range}') - if lead_safe_range > run_resp.min_safe: + if lead_safe_range < run_resp.min_safe: logger.info(f'AI is not advancing with lead runner') return this_play @@ -1771,23 +1766,34 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact trail_safe_range += 1 logger.info(f'Trail runner not held, +1 to safe range: {trail_safe_range}') + trail_strings = at_third_strings(trail_safe_range) + trail_runner_embed.add_field(name='', value='', inline=False) + trail_runner_embed.add_field(name='Safe Range', value=trail_strings['safe']) + trail_runner_embed.add_field(name='Out Range', value=trail_strings['out']) + await interaction.channel.send(embeds=[lead_runner_embed, trail_runner_embed]) is_defense_throwing = await ask_confirm( interaction=interaction, - question=f'{lead_runner.player.name} is advancing {TO_BASE[lead_base]} with a safe range of **1->{safe_range}**! Is the defense throwing?', + question=f'{lead_runner.player.name} is advancing {TO_BASE[lead_base]} with a safe range of **1->{lead_safe_range if lead_base == 3 else {lead_safe_range - 1}}**! Is the defense throwing?', label_type='yes' ) - # Human defense is throwing for lead runner + # Human defense is not throwing for lead runner if not is_defense_throwing: + logger.info(f'Defense is not throwing for lead runner') if this_play.on_second == lead_runner: this_play.rbi += 1 this_play.on_second_final = 4 log_run_scored(session, lead_runner, this_play) elif this_play.on_first == lead_runner: - this_play.on_first_final = 3 + if this_play.double: + this_play.rbi += 1 + this_play.on_first_final = 4 + log_run_scored(session, lead_runner, this_play) + else: + this_play.on_first_final = 3 return this_play @@ -1853,6 +1859,7 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact # Ball is going to lead base, ask if safe logger.info(f'Throw is going to lead base') + await interaction.channel.send(content=None, embeds=this_roll.embeds) runner_thrown_out = await out_at_home(lead_safe_range) if lead_base == 4 else await out_at_base(lead_safe_range, trail_runner, trail_base) runner_thrown_out = await ask_confirm( interaction=interaction, diff --git a/exceptions.py b/exceptions.py index 036a3fe..0b8b38d 100644 --- a/exceptions.py +++ b/exceptions.py @@ -47,6 +47,10 @@ class PlayNotFoundException(GameException): pass +class PlayerNotFoundException(GameException): + pass + + class PlayInitException(GameException): pass diff --git a/gauntlets.py b/gauntlets.py index 3d06248..c58c89e 100644 --- a/gauntlets.py +++ b/gauntlets.py @@ -8,12 +8,13 @@ import discord from sqlmodel import Session from discord import SelectOption +from exceptions import * from in_game import ai_manager import helpers from helpers import RARITY, get_or_create_role, send_to_channel, get_channel from api_calls import db_get, db_post, db_delete, db_patch -from in_game.gameplay_models import Team -from in_game.gameplay_queries import get_team_or_none +from in_game.gameplay_models import Lineup, Team +from in_game.gameplay_queries import get_player_or_none, get_team_or_none, get_or_create_ai_card, get_player_id_from_dict from utilities.dropdown import DropdownView, SelectPokemonEvolution @@ -252,22 +253,31 @@ async def build_lineup(this_team, this_game, this_event, sp_name): return await ai_manager.build_lineup(this_team, this_game.id, f'gauntlet-{this_event["id"]}', sp_name) -async def get_starting_pitcher(this_team, this_game, this_event, this_run): +async def get_starting_pitcher(session, this_team, this_game, this_event, this_run): sp_rank = (games_played(this_run) % 5) + 1 - starter = await db_get(f'teams/{this_team["id"]}/sp/gauntlet-{this_event["id"]}?sp_rank={sp_rank}') + starter = await db_get(f'teams/{this_team.id}/sp/gauntlet-{this_event["id"]}?sp_rank={sp_rank}') + logger.info(f'starter: {starter}') + this_player = await get_player_or_none(session, get_player_id_from_dict(starter)) + if this_player is None: + log_exception(PlayerNotFoundException, 'Could not pull the AI\'s starting pitcher') # get player card; create one if none found - card_id = await ai_manager.get_or_create_card(starter, this_team) + logger.info(f'SP this_player: {this_player}') + this_card = await get_or_create_ai_card( + session, + this_player, + this_team + ) - return { - 'game_id': this_game.id, - 'team_id': this_team['id'], - 'player_id': starter['player_id'], - 'card_id': card_id, - 'position': 'P', - 'batting_order': 10, - 'after_play': 0 - } + return Lineup( + team=this_team, + player=this_player, + card=this_card, + position='P', + batting_order=10, + is_fatigued=False, + game=this_game + ) async def run_draft(interaction: discord.Interaction, main_team: Team, this_event, draft_team: Team = None): diff --git a/in_game/gameplay_models.py b/in_game/gameplay_models.py index 43cadad..65b787c 100644 --- a/in_game/gameplay_models.py +++ b/in_game/gameplay_models.py @@ -244,6 +244,14 @@ class Game(SQLModel, table=True): raise NoHumanTeamsException else: raise MultipleHumanTeamsException + + @property + def league_name(self): + if 'gauntlet' in self.game_type: + parts = self.game_type.split('-') + return f'{parts[0]}-{parts[1]}' + else: + return self.game_type class ManagerAi(ManagerAiBase, table=True): @@ -300,7 +308,7 @@ class ManagerAi(ManagerAiBase, table=True): def check_jump(self, session: Session, this_game: Game, to_base: Literal[2, 3, 4]) -> JumpResponse: logger.info(f'Checking jump to {to_base} in Game {this_game.id}') - this_resp = JumpResponse() + this_resp = JumpResponse(min_safe=20) this_play = this_game.current_play_or_none(session) if this_play is None: raise GameException(f'No game found while checking for jump') @@ -401,7 +409,11 @@ class ManagerAi(ManagerAiBase, table=True): elif this_play.inning_num > 7 and self.steal >= 5: this_resp.min_safe = 6 elif self.steal > 5: - this_resp.min_safe = 7 + this_resp.min_safe = 7 + elif self.steal > 2: + this_resp.min_safe = 8 + else: + this_resp.min_safe = 10 runner_card = runner.card.batterscouting.battingcard jump_safe_range = runner_card.steal_low - 9 @@ -434,6 +446,7 @@ class ManagerAi(ManagerAiBase, table=True): else: this_resp.min_safe += 2 + logger.info(f'tag_from_second response: {this_resp}') return this_resp def tag_from_third(self, session: Session, this_game: Game) -> TagResponse: @@ -459,6 +472,7 @@ class ManagerAi(ManagerAiBase, table=True): if this_play.starting_outs == 1: this_resp.min_safe -= 2 + logger.info(f'tag_from_third response: {this_resp}') return this_resp def throw_at_uncapped(self, session: Session, this_game: Game) -> ThrowResponse: @@ -498,6 +512,7 @@ class ManagerAi(ManagerAiBase, table=True): this_resp.at_trail_runner = True this_resp.trail_max_safe_delta = -4 + logger.info(f'throw_at_uncapped response: {this_resp}') return this_resp def uncapped_advance(self, session: Session, this_game: Game, lead_base: int, trail_base: int) -> UncappedRunResponse: @@ -546,6 +561,7 @@ class ManagerAi(ManagerAiBase, table=True): if this_resp.trail_min_safe < 1: this_resp.min_safe = 1 + logger.info(f'Uncapped advance response: {this_resp}') return this_resp def defense_alignment(self, session: Session, this_game: Game) -> DefenseResponse: @@ -611,6 +627,7 @@ class ManagerAi(ManagerAiBase, table=True): if len(this_resp.ai_note) == 0 and this_play.on_base_code > 0: this_resp.ai_note += f'- play straight up\n' + logger.info(f'Defense alignment response: {this_resp}') return this_resp def gb_decide_run(self, session: Session, this_game: Game) -> RunResponse: @@ -623,6 +640,7 @@ class ManagerAi(ManagerAiBase, table=True): aggression = self.ahead_aggression - 5 if ai_rd > 0 else self.behind_aggression - 5 this_resp.min_safe = 15 - aggression # TODO: write this algorithm + logger.info(f'gb_decide_run response: {this_resp}') return this_resp def gb_decide_throw(self, session: Session, this_game: Game, runner_speed: int, defender_range: int) -> ThrowResponse: @@ -637,6 +655,7 @@ class ManagerAi(ManagerAiBase, table=True): if (runner_speed - 4 + defender_range) <= (10 + aggression): this_resp.at_lead_runner = True + logger.info(f'gb_decide_throw response: {this_resp}') return this_resp diff --git a/in_game/gameplay_queries.py b/in_game/gameplay_queries.py index aad5373..9391511 100644 --- a/in_game/gameplay_queries.py +++ b/in_game/gameplay_queries.py @@ -62,6 +62,8 @@ def get_active_games_by_team(session: Session, team: Team) -> list[Game]: async def get_team_or_none( session: Session, team_id: int | None = None, gm_id: int | None = None, team_abbrev: str | None = None, skip_cache: bool = False, main_team: bool = None, gauntlet_team: bool = None, include_packs: bool = False) -> Team | None: logger.info(f'Getting team or none / team_id: {team_id} / gm_id: {gm_id} / team_abbrev: {team_abbrev} / skip_cache: {skip_cache} / main_team: {main_team} / gauntlet_team: {gauntlet_team}') + + this_team = None if gm_id is not None: if main_team is None and gauntlet_team is None: main_team = True @@ -69,19 +71,25 @@ async def get_team_or_none( elif main_team == gauntlet_team: log_exception(KeyError, 'Must select either main_team or gauntlet_team') + logger.info(f'main_team: {main_team} / gauntlet_team: {gauntlet_team}') if team_id is None and gm_id is None and team_abbrev is None: log_exception(KeyError, 'One of "team_id", "gm_id", or "team_abbrev" must be included in search') if not skip_cache: if team_id is not None: + logger.info(f'Getting team by team_id: {team_id}') this_team = session.get(Team, team_id) else: if gm_id is not None: + logger.info(f'Getting team by gm_id: {gm_id}') for team in session.exec(select(Team).where(Team.gmid == gm_id)).all(): if ('gauntlet' in team.abbrev.lower() and gauntlet_team) or ('gauntlet' not in team.abbrev.lower() and main_team): + logger.info(f'Found the team: {team}') this_team = team break + logger.info(f'post loop, this_team: {this_team}') else: + logger.info(f'Getting team by abbrev: {team_abbrev}') this_team = session.exec(select(Team).where(func.lower(Team.abbrev) == team_abbrev.lower())).one_or_none() if this_team is not None: @@ -113,8 +121,10 @@ async def get_team_or_none( elif gm_id is not None: t_query = await db_get('teams', params=[('gm_id', gm_id), ('inc_packs', include_packs)]) if t_query['count'] != 0: - for team in [x for x in t_query['teams'] if 'gauntlet' not in x['abbrev'].lower()]: - return cache_team(team) + for team in t_query['teams']: + logger.info(f'in t_query loop / team: {team} / gauntlet_team: {gauntlet_team} / main_team: {main_team}') + if (gauntlet_team and 'gauntlet' in team['abbrev'].lower()) or (main_team and 'gauntlet' not in team['abbrev'].lower()): + return cache_team(team) elif team_abbrev is not None: t_query = await db_get('teams', params=[('abbrev', team_abbrev), ('inc_packs', include_packs)]) @@ -484,10 +494,11 @@ async def get_card_or_none(session: Session, card_id: int, skip_cache: bool = Fa logger.info(f'Caching card ID {card_id} now') this_card = cache_card(c_query) - if this_player.pos_1 not in ['SP', 'RP']: - this_card.batterscouting = await shared_get_scouting(session, this_card, 'batter') - else: + all_pos = [x for x in [this_player.pos_1, this_player.pos_2, this_player.pos_3, this_player.pos_3, this_player.pos_4, this_player.pos_5, this_player.pos_6, this_player.pos_7, this_player.pos_8] if x is not None] + if 'SP' in all_pos or 'RP' in all_pos: this_card.pitcherscouting = await shared_get_scouting(session, this_card, 'pitcher') + if any(item in all_pos for item in ['DH', 'C', '1B', '2B', '3B', 'SS', 'LF', 'CF', 'RF']): + this_card.batterscouting = await shared_get_scouting(session, this_card, 'batter') session.add(this_card) session.commit() diff --git a/utilities/dropdown.py b/utilities/dropdown.py index f980582..929d17a 100644 --- a/utilities/dropdown.py +++ b/utilities/dropdown.py @@ -107,6 +107,7 @@ class SelectStartingPitcher(discord.ui.Select): super().__init__(custom_id=custom_id, placeholder=placeholder, options=options) async def callback(self, interaction: discord.Interaction): + await interaction.response.defer() logger.info(f'SelectStartingPitcher - selection: {self.values[0]}') # Get Human SP card @@ -142,11 +143,16 @@ class SelectStartingPitcher(discord.ui.Select): self.session.add(human_sp_lineup) self.session.commit() + logger.info(f'trying to delete interaction: {interaction}') + try: + # await interaction.delete_original_response() + await interaction.edit_original_response( + content=f'The {self.team.lname} are starting **{human_sp_card.player.name_with_desc}**!\n\nRun `/set lineup` to import your lineup and `/gamestate` if you are ready to play.', + view=None + ) + except Exception as e: + log_exception(e, 'Couldn\'t clean up after selecting sp') - await interaction.response.edit_message( - content=f'The {self.team.lname} are starting **{human_sp_card.player.name_with_desc}**!\n\nRun `/read-lineup` when you are ready to begin.', - view=None - ) class SelectSubPosition(discord.ui.Select):