New postion sub logic

This commit is contained in:
Cal Corum 2025-03-09 00:59:10 -06:00
parent 35a62362ce
commit a416e90db9
3 changed files with 165 additions and 47 deletions

View File

@ -6,15 +6,15 @@ logger = logging.getLogger('discord_app')
def log_errors(func):
"""
This wrapper function will force all exceptions to be logged with executiona and stack info.
This wrapper function will force all exceptions to be logged with execution and stack info.
"""
def wrap(*args, **kwargs):
try:
result = func(*args, **kwargs)
except Exception as e:
logger.error(func.__name__)
log_exception(e)
logger.info(func.__name__)
return result
return wrap
@ -113,3 +113,7 @@ class MissingRosterException(GameException):
class LegalityCheckNotRequired(GameException):
pass
class InvalidResponder(GameException):
pass

View File

@ -4,11 +4,19 @@ from typing import Coroutine, Literal
from dice import ab_roll, jump_roll
from exceptions import *
from helpers import random_insult
from in_game.gameplay_models import Game, Play, Team
logger = logging.getLogger('discord_app')
# def check_responder(func):
# def wrap(*args, **kwargs):
# try:
# result = func(*args, **kwargs)
# except Exc
class Confirm(discord.ui.View):
def __init__(self, responders: list, timeout: float = 300.0, label_type: Literal['yes', 'confirm'] = 'confirm'):
super().__init__(timeout=timeout)
@ -182,6 +190,107 @@ class ButtonOptions(discord.ui.View):
await interaction.edit_original_response(view=self)
class SelectPosition(discord.ui.View):
def __init__(self, *, timeout: int = 30, responders: list[discord.User]):
if not isinstance(responders, list):
raise TypeError('responders must be a list')
super().__init__(timeout=timeout)
self.value = None
self.responders = responders
async def check_responders(self, interaction: discord.Interaction):
if interaction.user not in self.responders:
await interaction.response.send_message(
content=random_insult(),
ephemeral=True,
delete_after=10.0
)
log_exception(InvalidResponder, f'{interaction.user.name} not in responders: {self.responders}')
async def button_press(self, interaction: discord.Interaction, this_position: str):
await self.check_responders(interaction)
self.stop()
self.value = this_position
await interaction.edit_original_response(view=self)
@discord.ui.button(label='LF', style=discord.ButtonStyle.blurple, row=0)
async def left_field(self, interaction: discord.Interaction, button: discord.ui.Button):
await self.button_press(interaction, button.label)
@discord.ui.button(label='CF', style=discord.ButtonStyle.blurple, row=0)
async def center_field(self, interaction: discord.Interaction, button: discord.ui.Button):
await self.button_press(interaction, button.label)
@discord.ui.button(label='RF', style=discord.ButtonStyle.blurple, row=0)
async def right_field(self, interaction: discord.Interaction, button: discord.ui.Button):
await self.button_press(interaction, button.label)
@discord.ui.button(label='3B', style=discord.ButtonStyle.green, row=1)
async def third_base(self, interaction: discord.Interaction, button: discord.ui.Button):
await self.button_press(interaction, button.label)
@discord.ui.button(label='SS', style=discord.ButtonStyle.green, row=1)
async def shortstop(self, interaction: discord.Interaction, button: discord.ui.Button):
await self.button_press(interaction, button.label)
@discord.ui.button(label='2B', style=discord.ButtonStyle.green, row=1)
async def second_base(self, interaction: discord.Interaction, button: discord.ui.Button):
await self.button_press(interaction, button.label)
@discord.ui.button(label='1B', style=discord.ButtonStyle.green, row=1)
async def first_base(self, interaction: discord.Interaction, button: discord.ui.Button):
await self.button_press(interaction, button.label)
@discord.ui.button(label='C', style=discord.ButtonStyle.gray, row=2)
async def catcher(self, interaction: discord.Interaction, button: discord.ui.Button):
await self.button_press(interaction, button.label)
@discord.ui.button(label='P', style=discord.ButtonStyle.gray, row=2)
async def pitcher(self, interaction: discord.Interaction, button: discord.ui.Button):
await self.button_press(interaction, button.label)
@discord.ui.button(label='PH/PR', style=discord.ButtonStyle.gray, row=2)
async def pinch_hitter(self, interaction: discord.Interaction, button: discord.ui.Button):
await self.button_press(interaction, button.label)
async def ask_position(interaction: discord.Interaction):
view = SelectPosition(
responders=[interaction.user],
timeout=15
)
p_message = await interaction.channel.send(
content='Please select a position',
view=view
)
await view.wait()
if view.value:
await p_message.delete()
return view.value
else:
await p_message.edit(
content='To move things along, I will set the position to PH.',
view=None
)
return 'PH'
async def ask_confirm(interaction: discord.Interaction, question: str, label_type: Literal['yes', 'confirm'] = 'confirm', timeout: int = 60, delete_question: bool = True, custom_confirm_label: str = None, custom_cancel_label: str = None, embed: discord.Embed = None, delete_embed: bool = False) -> bool:
"""
button_callbacks: keys are button values, values are async functions

View File

@ -14,7 +14,7 @@ from helpers import get_card_embeds, random_insult
from in_game.game_helpers import legal_check
from in_game.gameplay_models import Game, Lineup, Play, Team
from in_game.gameplay_queries import get_one_lineup, get_position, get_card_or_none
from utilities.buttons import ask_confirm
from utilities.buttons import ask_confirm, ask_position
from utilities.embeds import image_embed
@ -369,12 +369,17 @@ class SelectBatterSub(discord.ui.Select):
if same_position:
logger.info(f'same_position is True')
position = last_lineup.position
pos_text = ''
view = None
# pos_text = ''
# view = None
else:
logger.info(f'same_position is False')
position = 'PH'
pos_text = 'What position will they play?'
position = await ask_position(interaction)
if position == 'PH/PR':
if this_play.batter == last_lineup:
position = 'PH'
else:
position = 'PR'
logger.info(f'Deactivating last_lineup')
last_lineup.active = False
@ -409,57 +414,57 @@ class SelectBatterSub(discord.ui.Select):
# self.session.commit()
logger.info(f'Inserted {human_bat_lineup.card.player.name_with_desc} in the {self.batting_order} spot')
this_play.batter = human_bat_lineup
this_play.batter_pos = position
if this_play.batter == last_lineup:
logger.info(f'Setting new sub to current play batter')
this_play.batter = human_bat_lineup
this_play.batter_pos = position
logger.info(f'Adding play to session: {this_play}')
self.session.add(this_play)
self.session.commit()
if not same_position:
pos_dict_list = {
'Pinch Hitter': 'PH',
'Catcher': 'C',
'First Base': '1B',
'Second Base': '2B',
'Third Base': '3B',
'Shortstop': 'SS',
'Left Field': 'LF',
'Center Field': 'CF',
'Right Field': 'RF',
'Pinch Runner': 'PR',
'Pitcher': 'P'
}
# if not same_position:
# pos_dict_list = {
# 'Pinch Hitter': 'PH',
# 'Catcher': 'C',
# 'First Base': '1B',
# 'Second Base': '2B',
# 'Third Base': '3B',
# 'Shortstop': 'SS',
# 'Left Field': 'LF',
# 'Center Field': 'CF',
# 'Right Field': 'RF',
# 'Pinch Runner': 'PR',
# 'Pitcher': 'P'
# }
logger.info(f'Prepping sub position')
pos_text = f'What position will {human_batter_card.player.name} play?'
options=[
SelectOption(
label=f'{pos_name}',
value=pos_dict_list[pos_name],
default=pos_name=='Pinch Hitter'
)
for pos_name in pos_dict_list.keys()
]
logger.info(f'options: {options}')
view = SelectSubPosition(
self.session,
this_lineup=human_bat_lineup,
placeholder='Select Position',
options=options,
responders=[interaction.user]
)
# logger.info(f'Prepping sub position')
# pos_text = f'What position will {human_batter_card.player.name} play?'
# options=[
# SelectOption(
# label=f'{pos_name}',
# value=pos_dict_list[pos_name],
# default=pos_name=='Pinch Hitter'
# )
# for pos_name in pos_dict_list.keys()
# ]
# logger.info(f'options: {options}')
# view = SelectSubPosition(
# self.session,
# this_lineup=human_bat_lineup,
# placeholder='Select Position',
# options=options,
# responders=[interaction.user]
# )
logger.info(f'view: {view}')
logger.info(f'SelectSubPosition view is ready')
# logger.info(f'view: {view}')
# logger.info(f'SelectSubPosition view is ready')
logger.info(f'Posting final sub message')
this_content = f'{human_batter_card.player.name_with_desc} has entered in the {self.batting_order} spot. {pos_text}'
this_content = f'{human_batter_card.player.name_with_desc} has entered in the {self.batting_order} spot.\n\nIf you have additional subs to make, run `/substitution` again or run `/gamestate` to see the current plate appearance.'
await interaction.edit_original_response(
content=this_content,
view=view
content=this_content
)
await interaction.channel.send(content='If you have additional subs to make, run `/substitution` again or run `/gamestate` to see the current plate appearance.')
class SelectPokemonEvolution(discord.ui.Select):