Add confirmation_message param to ask_with_buttons

This commit is contained in:
Cal Corum 2025-02-01 21:33:12 -06:00
parent 7d54d9ea34
commit cd9d5e49d0
4 changed files with 197 additions and 12 deletions

View File

@ -1,5 +1,6 @@
import datetime
import logging
import math
from typing import Literal
import discord
@ -658,14 +659,89 @@ class ManagerAi(ManagerAiBase, table=True):
logger.info(f'gb_decide_throw response: {this_resp}')
return this_resp
def replace_pitcher(self, session: Session, this_game: Game):
def replace_pitcher(self, session: Session, this_game: Game) -> bool:
logger.info(f'Checking if fatigued pitcher should be replaced')
this_play = this_game.current_play_or_none(session)
if this_play is None:
raise GameException(f'No game found while checking replace_pitcher')
# TODO: Add replace pitcher algorithms
return False
this_pitcher = this_play.pitcher
outs = session.exec(select(func.sum(Play.outs)).where(
Play.game == this_game, Play.pitcher == this_pitcher, Play.complete == True
)).one()
logger.info(f'Pitcher: {this_pitcher.card.player.name_with_desc} / Outs: {outs}')
allowed_runners = session.exec(select(func.count(Play.id)).where(
Play.game == this_game, Play.pitcher == this_pitcher, or_(Play.hit == 1, Play.bb == 1)
)).one()
run_diff = this_play.ai_run_diff
logger.info(f'run diff: {run_diff} / allowed runners: {allowed_runners} / behind aggro: {self.behind_aggression} / ahead aggro: {self.ahead_aggression}')
logger.info(f'this play: {this_play}')
if this_pitcher.replacing_id is None:
pitcher_pow = this_pitcher.card.pitcherscouting.pitchingcard.starter_rating
logger.info(f'Starter POW: {pitcher_pow}')
if outs > pitcher_pow * 3 + 8:
logger.info(f'Starter has thrown POW + 3 - being pulled')
return True
elif allowed_runners < 5:
logger.info(f'Starter is cooking with {allowed_runners} runners allowed - staying in')
return False
elif run_diff > 5 or (run_diff > 2 and self.ahead_aggression > 5) and (allowed_runners < run_diff or this_play.on_base_code <= 3):
logger.info(f'AI team has big lead of {run_diff} - staying in')
return False
elif run_diff > 2 or (run_diff >= 0 and self.ahead_aggression > 5) and (allowed_runners < run_diff or this_play.on_base_code <= 1):
logger.info(f'AI team has lead of {run_diff} - staying in')
return False
elif run_diff >= 0 or (run_diff >= -2 and self.behind_aggression > 5) and (allowed_runners < 5 and this_play.on_base_code <= run_diff):
logger.info(f'AI team in close game with run diff of {run_diff} - staying in')
return False
elif run_diff >= -3 and self.behind_aggression > 5 and allowed_runners < 5 and this_play.on_base_code <= 1:
logger.info(f'AI team is close behind with run diff of {run_diff} - staying in')
return False
elif run_diff <= -5 and this_play.inning_num <= 3:
logger.info(f'AI team is way behind and starter is going to wear it - staying in')
return False
else:
logger.info(f'AI team found no exceptions - pull starter')
return True
else:
pitcher_pow = this_pitcher.card.pitcherscouting.pitchingcard.relief_rating
logger.info(f'Reliever POW: {pitcher_pow}')
if run_diff > 5 or (run_diff > 2 and self.ahead_aggression > 5) and (this_play.starting_outs == 2 or allowed_runners <= run_diff or this_play.on_base_code <= 3 or this_play.starting_outs == 2):
logger.info(f'AI team has big lead of {run_diff} - staying in')
return False
elif run_diff > 2 or (run_diff >= 0 and self.ahead_aggression > 5) and (allowed_runners < run_diff or this_play.on_base_code <= 1 or this_play.starting_outs == 2):
logger.info(f'AI team has lead of {run_diff} - staying in')
return False
elif run_diff >= 0 or (run_diff >= -2 and self.behind_aggression > 5) and (allowed_runners < 5 or this_play.on_base_code <= run_diff or this_play.starting_outs == 2):
logger.info(f'AI team in close game with run diff of {run_diff} - staying in')
return False
elif run_diff >= -3 and self.behind_aggression > 5 and allowed_runners < 5 and this_play.on_base_code <= 1:
logger.info(f'AI team is close behind with run diff of {run_diff} - staying in')
return False
elif run_diff <= -5 and this_play.starting_outs != 0:
logger.info(f'AI team is way behind and reliever is going to wear it - staying in')
return False
else:
logger.info(f'AI team found no exceptions - pull reliever')
return True
class CardsetBase(SQLModel):

View File

@ -886,7 +886,7 @@ def get_available_pitchers(session: Session, this_game: Game, this_team: Team, s
def sort_by_pow(this_card: Card):
s_pow = this_card.pitcherscouting.pitchingcard.starter_rating
r_pow = this_card.pitcherscouting.pitchingcard.relief_rating
c_pow = this_card.pitcherscouting.pitchingcard.closer_rating
c_pow = this_card.pitcherscouting.pitchingcard.closer_rating if this_card.pitcherscouting.pitchingcard.closer_rating is not None else 0
if sort == 'starter-desc':
r_val = (s_pow * 3) + r_pow

View File

@ -213,15 +213,18 @@ async def ask_confirm(interaction: discord.Interaction, question: str, label_typ
return False
async def ask_with_buttons(interaction: discord.Interaction, button_options: list[str], question: str = None, timeout: int = 60, delete_question: bool = True, embeds: list[discord.Embed] = None, delete_embeds: bool = False, edit_original_interaction: bool = False, none_okay: bool = False) -> str:
async def ask_with_buttons(interaction: discord.Interaction, button_options: list[str], question: str = None, timeout: int = 60, delete_question: bool = True, embeds: list[discord.Embed] = None, delete_embeds: bool = False, edit_original_interaction: bool = False, none_okay: bool = False, confirmation_message: str = None) -> str:
"""
Returns text of button pressed
"""
logger.info(f'ask_with_buttons - button_options: {button_options} / question: {question} / timeout: {timeout} / delete_question: {delete_question} / embeds: {embeds} / delete_embeds: {delete_embeds} / edit_original_transaction: {edit_original_interaction}')
logger.info(f'ask_with_buttons - button_options: {button_options} / question: {question} / timeout: {timeout} / delete_question: {delete_question} / embeds: {embeds} / delete_embeds: {delete_embeds} / edit_original_transaction: {edit_original_interaction} / confirmation_message: {confirmation_message}')
if question is None and embeds is None:
log_exception(KeyError, 'At least one of question or embed must be provided')
if confirmation_message is not None and (delete_question or delete_embeds):
log_exception(KeyError, 'Posting a confirmation message is not supported while deleting the message or embeds')
view = ButtonOptions(
responders=[interaction.user],
timeout=timeout,
@ -244,11 +247,19 @@ async def ask_with_buttons(interaction: discord.Interaction, button_options: lis
# embeds=embeds
# )
logger.info(f'posting message')
q_message = await interaction.channel.send(
content=question,
view=view,
embeds=embeds
)
if edit_original_interaction:
q_message = await interaction.edit_original_response(
content=question,
view=view,
embeds=embeds
)
else:
q_message = await interaction.channel.send(
content=question,
view=view,
embeds=embeds
)
logger.info(f'waiting for response')
await view.wait()
if view.value:
@ -256,6 +267,7 @@ async def ask_with_buttons(interaction: discord.Interaction, button_options: lis
else:
return_val = None
logger.info(f'return_val: {return_val}')
if question is not None and embeds is not None:
logger.info(f'checking for deletion with question and embeds')
@ -274,7 +286,10 @@ async def ask_with_buttons(interaction: discord.Interaction, button_options: lis
)
elif return_val is None:
logger.info(f'remove view')
new_content = confirmation_message if confirmation_message is not None else question
logger.info(f'Confirmation message: {new_content}')
await q_message.edit(
content=new_content,
view=None
)
@ -289,6 +304,14 @@ async def ask_with_buttons(interaction: discord.Interaction, button_options: lis
)
if return_val is not None or none_okay:
logger.info(f'Returning: {return_val}')
if confirmation_message is not None:
new_content = confirmation_message if confirmation_message is not None else question
logger.info(f'Confirmation message: {new_content}')
await q_message.edit(
content=new_content,
view=None
)
return return_val
log_exception(ButtonOptionNotChosen, 'Selecting an option is mandatory')

View File

@ -173,6 +173,92 @@ class SelectStartingPitcher(discord.ui.Select):
log_exception(e, 'Couldn\'t clean up after selecting sp')
class SelectReliefPitcher(discord.ui.Select):
def __init__(self, this_game: Game, this_team: Team, batting_order: int, session: Session, custom_id: str = MISSING, placeholder: str | None = None, options: List[SelectOption] = ..., responders: list[discord.User] = None) -> None:
logger.info(f'Inside SelectReliefPitcher init function')
self.game = this_game
self.team = this_team
self.batting_order = int(batting_order)
self.session = session
self.responders = responders
super().__init__(custom_id=custom_id, placeholder=placeholder, options=options)
async def callback(self, interaction: discord.Interaction):
if self.responders is not None and interaction.user not in self.responders:
await interaction.response.send_message(
content=random_insult(),
ephemeral=True,
delete_after=5
)
await interaction.response.defer(thinking=True)
logger.info(f'SelectReliefPitcher - selection: {self.values[0]}')
this_play = self.game.current_play_or_none(self.session)
if this_play is None:
log_exception(PlayNotFoundException, 'Could not find current play to make pitching change. If you are trying to swap SPs, run `/set pitcher` again.')
# Get Human RP card
human_rp_card = await get_card_or_none(self.session, card_id=self.values[0])
if human_rp_card is None:
log_exception(CardNotFoundException, f'Card ID {self.values[0]} not found')
if human_rp_card.team_id != self.team.id:
logger.error(f'Card_id {self.values[0]} does not belong to {self.team.abbrev} in Game {self.game.id}')
await interaction.channel.send(
f'Uh oh. Card ID {self.values[0]} is {human_rp_card.player.name} and belongs to {human_rp_card.team.sname}. Will you double check that?'
)
return
await get_position(self.session, human_rp_card, 'P')
logger.info(f'Adding the RP lineup')
human_rp_lineup = Lineup(
team_id=self.team.id,
player_id=human_rp_card.player.id,
card_id=self.values[0],
position='P',
batting_order=self.batting_order,
is_fatigued=False,
game=self.game,
replacing_id=this_play.pitcher.id,
after_play=max(this_play.play_num - 1, 0)
)
self.session.add(human_rp_lineup)
logger.info(f'De-activating the old pitcher')
this_play.pitcher.active = False
self.session.add(this_play.pitcher)
logger.info(f'Checking for batting order != 10 ({self.batting_order})')
if self.batting_order != 10:
logger.info(f'Getting the player in the {self.batting_order} spot')
this_lineup = get_one_lineup(self.session, self.game, self.team, active=True, batting_order=self.batting_order)
logger.info(f'subbing lineup: {this_lineup.player.name_with_desc}')
if this_lineup != this_play.pitcher:
this_lineup.active = False
self.session.add(this_lineup)
logger.info(f'Setting new pitcher on current play')
this_play.pitcher = human_rp_lineup
self.session.add(this_play)
logger.info(f'Committing changes')
try:
self.session.commit()
except Exception as e:
log_exception(e, 'Couldn\'t commit database changes')
try:
logger.info(f'Responding to player')
await interaction.edit_original_response(
content=f'**{human_rp_card.player.name_with_desc}** has entered for the {human_rp_card.team.lname}!\n\nRun `/substitute` to make any other moves and `/gamestate` if you are ready to continue.',
view=None
)
except Exception as e:
log_exception(e, 'Couldn\'t clean up after selecting rp')
class SelectSubPosition(discord.ui.Select):
def __init__(self, session: Session, this_lineup: Lineup, custom_id = ..., placeholder = None, options: List[SelectOption] = ..., responders: list[discord.User] = None):
self.session = session