Add responders check to dropdowns

Add colors and insults to helpers
Finish /set commands with helpers post /new-game
Add POW check for pitchers
This commit is contained in:
Cal Corum 2024-12-27 22:33:25 -06:00
parent 724b8922f2
commit 965ceebd35
7 changed files with 147 additions and 47 deletions

View File

@ -604,7 +604,7 @@ class Admins(commands.Cog):
@commands.is_owner()
async def test_evolution(self, ctx, team_abbrev: str):
this_team = await get_team_by_abbrev(team_abbrev)
await evolve_pokemon(this_team, ctx.channel)
await evolve_pokemon(this_team, ctx.channel, responders=ctx.author)
async def setup(bot):

View File

@ -10,7 +10,7 @@ from discord.ext import commands, tasks
import pygsheets
import sqlalchemy
from sqlmodel import or_
from sqlmodel import func, 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
@ -313,7 +313,7 @@ class Gameplay(commands.Cog):
done = await get_full_roster_from_sheets(session, interaction, self.sheets, this_game, human_team, int(roster.value))
logger.info(f'done: {done}')
if done:
sp_view = starting_pitcher_dropdown_view(session, this_game, human_team)
sp_view = starting_pitcher_dropdown_view(session, this_game, human_team, this_game.league_name, [interaction.user])
await interaction.channel.send(content=f'### {human_team.lname} Starting Pitcher', view=sp_view)
await final_message.edit(
@ -502,7 +502,7 @@ 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, game_type=f'gauntlet-{this_event["id"]}')
sp_view = starting_pitcher_dropdown_view(session, this_game, human_team, game_type=this_game.league_name, responders=[interaction.user])
sp_message = await interaction.channel.send(content=f'### {human_team.lname} Starting Pitcher', view=sp_view)
await final_message.edit(
@ -576,6 +576,15 @@ class Gameplay(commands.Cog):
await interaction.edit_original_response(content='Bruh. Only GMs of the active teams can pull lineups.')
return
all_lineups = get_game_lineups(session, this_game, this_team)
if len(all_lineups) > 1:
play_count = session.exec(select(func.count(Play.id)).where(Play.game == this_game, Play.complete == True)).one()
if play_count > 0:
await interaction.edit_original_response(
content=f'Since {play_count} play{"s" if play_count != 1 else ""} ha{"ve" if play_count != 1 else "s"} been logged, you will have to run `/substitution batter` to replace any of your batters.'
)
return
logger.info(f'lineup: {lineup} / value: {lineup.value} / name: {lineup.name}')
try:
this_play = await read_lineup(
@ -615,6 +624,13 @@ class Gameplay(commands.Cog):
try:
check_sp = get_one_lineup(session, this_game, this_team, position='P')
play_count = session.exec(select(func.count(Play.id)).where(Play.game == this_game, Play.complete == True, Play.pitcher == check_sp)).one()
if play_count > 0:
await interaction.edit_original_response(
content=f'Since {play_count} play{"s" if play_count != 1 else ""} ha{"ve" if play_count != 1 else "s"} been logged, you will have to run `/substitution pitcher` to replace {check_sp.player.name}.'
)
return
except sqlalchemy.exc.NoResultFound as e:
# if 'NoResultFound' not in str(e):
# logger.error(f'Error checking for existing sp: {e}')
@ -638,22 +654,8 @@ class Gameplay(commands.Cog):
session.delete(check_sp)
session.commit()
sp_view = starting_pitcher_dropdown_view(session, this_game, this_team, game_type=this_game.league_name)
sp_view = starting_pitcher_dropdown_view(session, this_game, this_team, game_type=this_game.league_name, responders=[interaction.user])
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):
@ -719,7 +721,7 @@ class Gameplay(commands.Cog):
this_order = int(batting_order)
logger.info(f'sub batter - this_play: {this_play}')
bat_view = sub_batter_dropdown_view(session, this_game, owner_team, this_order)
bat_view = sub_batter_dropdown_view(session, this_game, owner_team, this_order, [interaction.user])
await interaction.edit_original_response(content=f'### {owner_team.lname} Substitution', view=bat_view)
group_log = app_commands.Group(name='log', description='Log a play in this channel\'s game')

View File

@ -2401,7 +2401,8 @@ class Gameplay(commands.Cog):
is_win=winning_team['gmid'] == gauntlet_team['gmid'],
this_team=gauntlet_team,
bot=self.bot,
channel=interaction.channel
channel=interaction.channel,
responders=[interaction.user]
)
this_run = await db_get('gauntletruns', object_id=int(this_game.game_type.split('-')[3]))

View File

@ -13,7 +13,7 @@ from typing import Literal
from api_calls import db_delete, db_get, db_post
from dice import DTwentyRoll, d_twenty_roll, frame_plate_check, sa_fielding_roll
from exceptions import *
from helpers import DEFENSE_LITERAL, SBA_COLOR, get_channel
from helpers import COLORS, DEFENSE_LITERAL, SBA_COLOR, get_channel
from in_game.game_helpers import PUBLIC_FIELDS_CATEGORY_NAME, legal_check
from in_game.gameplay_models import BattingCard, Game, Lineup, PositionRating, RosterLink, Team, Play
from in_game.gameplay_queries import get_available_batters, get_batter_card, get_batting_statline, get_pitching_statline, get_position, get_available_pitchers, get_card_or_none, get_channel_game_or_none, get_db_ready_decisions, get_db_ready_plays, get_game_lineups, get_last_team_play, get_one_lineup, get_player_id_from_dict, get_player_name_from_dict, get_player_or_none, get_sorted_lineups, get_team_or_none, get_players_last_pa, post_game_rewards
@ -61,13 +61,20 @@ async def get_scorebug_embed(session: Session, this_game: Game, full_length: boo
gt_string = ' - Exhibition'
logger.info(f'get_scorebug_embed - this_game: {this_game} / gt_string: {gt_string}')
curr_play = this_game.current_play_or_none(session)
if curr_play.pitcher.is_fatigued:
embed_color = COLORS['red']
elif curr_play.is_new_inning:
embed_color = COLORS['yellow']
else:
embed_color = COLORS['sba']
embed = discord.Embed(
title=f'{this_game.away_team.sname} @ {this_game.home_team.sname}{gt_string}',
color=int(SBA_COLOR, 16)
color=embed_color
)
curr_play = this_game.current_play_or_none(session)
if curr_play is None:
try:
curr_play = this_game.initialize_play(session)
@ -178,6 +185,8 @@ async def get_scorebug_embed(session: Session, this_game: Game, full_length: boo
battingcard = curr_play.batter.card.batterscouting.battingcard
pit_string = f'{pitchingcard.hand.upper()}HP | {curr_play.pitcher.player.name_card_link('pitching')}'
if curr_play.pitcher.is_fatigued:
pit_string += f'\n***F A T I G U E D***'
if len(baserunner_string) > 0:
logger.info(f'Adding pitcher hold to scorebug')
pitchingcard = curr_play.pitcher.card.pitcherscouting.pitchingcard
@ -261,7 +270,7 @@ 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, game_type: str = None):
def starting_pitcher_dropdown_view(session: Session, this_game: Game, human_team: Team, game_type: str = None, responders: list[discord.User] = None):
pitchers = get_available_pitchers(session, this_game, human_team, sort='starter-desc')
logger.info(f'sorted pitchers: {pitchers}')
sp_selection = SelectStartingPitcher(
@ -270,12 +279,13 @@ def starting_pitcher_dropdown_view(session: Session, this_game: Game, human_team
session=session,
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'
placeholder='Select your starting pitcher',
responders=responders
)
return DropdownView(dropdown_objects=[sp_selection])
def sub_batter_dropdown_view(session: Session, this_game: Game, human_team: Team, batting_order: int):
def sub_batter_dropdown_view(session: Session, this_game: Game, human_team: Team, batting_order: int, responders: list[discord.User]):
batters = get_available_batters(session, this_game, human_team)
logger.info(f'batters: {batters}')
bat_selection = SelectBatterSub(
@ -284,7 +294,8 @@ def sub_batter_dropdown_view(session: Session, this_game: Game, human_team: Team
session=session,
batting_order=batting_order,
options=[SelectOption(label=f'{x.batterscouting.battingcard.hand.upper()} | {x.player.name_with_desc}', value=x.id) for x in batters],
placeholder='Select your Sub'
placeholder='Select your Sub',
responders=responders
)
return DropdownView(dropdown_objects=[bat_selection])
@ -464,13 +475,15 @@ def complete_play(session:Session, this_play: Play):
away_score = this_play.away_score + runs_scored
home_score = this_play.home_score
logger.info(f'Check for go-ahead run')
if runs_scored > 0 and this_play.away_score <= this_play.home_score and away_score > home_score:
this_play.is_go_ahead = True
else:
away_score = this_play.away_score
home_score = this_play.home_score + runs_scored
logger.info(f'Check for go-ahead run')
if runs_scored > 0 and this_play.home_score <= this_play.away_score and home_score > away_score:
this_play.is_go_ahead = True
@ -485,6 +498,21 @@ def complete_play(session:Session, this_play: Play):
new_batter = get_one_lineup(session, this_play.game, new_batter_team, batting_order=nbo)
logger.info(f'new_batter: {new_batter}')
new_pitcher = get_one_lineup(session, this_play.game, new_pitcher_team, position='P')
logger.info(f'Check for {new_pitcher.player.name} POW')
outs = session.exec(select(func.sum(Play.outs)).where(
Play.game == this_play.game, Play.pitcher == new_pitcher, Play.complete == True
)).one()
pow_outs = new_pitcher.card.pitcherscouting.pitchingcard.starter_rating * 3
if outs >= pow_outs and not new_pitcher.is_fatigued:
new_pitcher.is_fatigued = True
session.add(new_pitcher)
if outs >= (pow_outs - 3):
in_pow = True
else:
in_pow = False
new_play = Play(
game=this_play.game,
play_num=this_play.play_num + 1,
@ -497,7 +525,7 @@ def complete_play(session:Session, this_play: Play):
home_score=home_score,
batter=new_batter,
batter_pos=new_batter.position,
pitcher=get_one_lineup(session, this_play.game, new_pitcher_team, position='P'),
pitcher=new_pitcher,
catcher=get_one_lineup(session, this_play.game, new_pitcher_team, position='C'),
is_new_inning=switch_sides,
is_tied=away_score == home_score,
@ -505,6 +533,7 @@ def complete_play(session:Session, this_play: Play):
on_second=on_second,
on_third=on_third,
managerai=this_play.managerai,
in_pow=in_pow,
re24=get_re24(this_play, runs_scored, new_obc=obc, new_starting_outs=nso)
)
@ -2711,7 +2740,8 @@ async def show_defense_cards(session: Session, interaction: discord.Interaction,
this_play=this_play,
base_embed=player_embed,
session=session,
sorted_lineups=sorted_lineups
sorted_lineups=sorted_lineups,
responders=[interaction.user]
)
dropdown_view = DropdownView(dropdown_objects=[player_dropdown], timeout=60)
@ -3171,6 +3201,9 @@ async def manual_end_game(session: Session, interaction: discord.Interaction, th
async def groundballs(session: Session, interaction: discord.Interaction, this_play: Play, groundball_letter: Literal['a', 'b', 'c']):
if this_play.starting_outs == 2:
return await gb_result(session, interaction, this_play, 1)
if this_play.on_base_code == 2 and groundball_letter in ['a', 'b']:
logger.info(f'Groundball {groundball_letter} with runner on second')
to_right_side = await ask_confirm(

View File

@ -1786,7 +1786,7 @@ async def end_run(this_run, this_event, this_team, force_end: bool = False):
return l_message
async def evolve_pokemon(this_team, channel):
async def evolve_pokemon(this_team, channel, responders):
c_query = await db_get(
'cards',
params=[('team_id', this_team['id']), ('order_by', 'new'), ('limit', 26)]
@ -1799,7 +1799,7 @@ async def evolve_pokemon(this_team, channel):
SelectOption(label=f'{x["player"]["rarity"]["name"]} | {x["player"]["p_name"]}', value=x['id']) for x in evolvable_mons
]
view = DropdownView(
dropdown_objects=[SelectPokemonEvolution(options=evo_target_options, this_team=this_team)]
dropdown_objects=[SelectPokemonEvolution(options=evo_target_options, this_team=this_team, responders=responders)]
)
await channel.send(
content='What? One of your pokemon is ready to evolve!\n\n-# The selected pokemon will be removed from your team and replaced with its evolution',
@ -1809,7 +1809,7 @@ async def evolve_pokemon(this_team, channel):
await channel.send('All of your Pokemon are fully evolved!')
async def post_result(run_id: int, is_win: bool, this_team, bot, channel):
async def post_result(run_id: int, is_win: bool, this_team, bot, channel, responders: list[discord.User] = None):
this_run = await db_get('gauntletruns', object_id=run_id)
this_event = await db_get('events', object_id=this_run['gauntlet']['id'])
t_query = await db_get('teams', params=[('abbrev', f'{this_team["abbrev"].replace("Gauntlet-","")}')])
@ -1936,7 +1936,7 @@ async def post_result(run_id: int, is_win: bool, this_team, bot, channel):
logging.info(f'Post-game evolution check: Gauntlet ID {this_run["id"]} / Wins: {this_run["wins"]} / Losses: {this_run["losses"]}')
if this_event['id'] == 7 and this_run['wins'] < 10 and this_run['losses'] < 2:
logging.info(f'trying to evolve now')
await evolve_pokemon(this_team, channel)
await evolve_pokemon(this_team, channel, responders)

View File

@ -249,6 +249,30 @@ SELECT_CARDSET_OPTIONS = [
ACTIVE_EVENT_LITERAL = Literal['1998 Season']
DEFENSE_LITERAL = Literal['Pitcher', 'Catcher', 'First Base', 'Second Base', 'Third Base', 'Shortstop', 'Left Field', 'Center Field', 'Right Field']
ACTIVE_EVENT_LITERAL = Literal['1998 Season', 'Brilliant Stars']
COLORS = {
'sba': int('a6ce39', 16),
'yellow': int('FFEA00', 16),
'red': int('C70039', 16)
}
INSULTS = [
'Ugh, who even are you?',
'Ugh, who even are you? Go away.',
'Ugh, who even are you? Leave me alone.',
'I will call the fucking cops!',
'I will call the fucking cops! Go away.',
'I will call the fucking cops! Leave me alone',
'Please don\'t talk to me',
'Don\'t talk to me.',
'Eww, don\'t talk to me.',
'Get away from me.',
'Get away from me, creep.',
'Get away from me, loser.',
'Get away from me, pedobear.',
'Why are you even here?',
'Why are you even here? Get lost.',
'Why are you even here? Scram.',
'Why are you even here? No one knows who you are.',
]
class Question:
@ -3343,3 +3367,7 @@ def user_has_role(user: discord.User | discord.Member, role_name: str) -> bool:
return True
return False
def random_insult() -> str:
return random_from_list(INSULTS)

View File

@ -10,7 +10,7 @@ from sqlmodel import Session
from api_calls import db_delete, db_get, db_post
from exceptions import CardNotFoundException, PlayNotFoundException, log_exception
from helpers import get_card_embeds
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
@ -66,14 +66,22 @@ class DropdownView(discord.ui.View):
class SelectViewDefense(discord.ui.Select):
def __init__(self, options: list, this_play: Play, base_embed: discord.Embed, session: Session, sorted_lineups: list[Lineup]):
def __init__(self, options: list, this_play: Play, base_embed: discord.Embed, session: Session, sorted_lineups: list[Lineup], responders: list[discord.User] = None):
self.embed = base_embed
self.session = session
self.play = this_play
self.sorted_lineups = sorted_lineups
self.responders = responders
super().__init__(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'SelectViewDefense - selection: {self.values[0]}')
this_lineup = self.session.get(Lineup, self.values[0])
@ -87,27 +95,35 @@ class SelectViewDefense(discord.ui.Select):
this_play=self.play,
base_embed=self.embed,
session=self.session,
sorted_lineups=self.sorted_lineups
sorted_lineups=self.sorted_lineups,
responders=self.responders
)
new_view = DropdownView(
dropdown_objects=[player_dropdown],
timeout=60
)
await interaction.response.edit_message(content=None, embed=self.embed, view=new_view)
await interaction.edit_original_response(content=None, embed=self.embed, view=new_view)
class SelectStartingPitcher(discord.ui.Select):
def __init__(self, this_game: Game, this_team: Team, session: Session, league_name: str, custom_id: str = MISSING, placeholder: str | None = None, options: List[SelectOption] = ...) -> None:
def __init__(self, this_game: Game, this_team: Team, session: Session, league_name: str, custom_id: str = MISSING, placeholder: str | None = None, options: List[SelectOption] = ..., responders: list[discord.User] = None) -> None:
logger.info(f'Inside SelectStartingPitcher init function')
self.game = this_game
self.team = this_team
self.session = session
self.league_name = league_name
self.responders = responders
super().__init__(custom_id=custom_id, placeholder=placeholder, options=options)
async def callback(self, interaction: discord.Interaction):
await interaction.response.defer()
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'SelectStartingPitcher - selection: {self.values[0]}')
# Get Human SP card
@ -154,14 +170,20 @@ class SelectStartingPitcher(discord.ui.Select):
log_exception(e, 'Couldn\'t clean up after selecting sp')
class SelectSubPosition(discord.ui.Select):
def __init__(self, session: Session, this_lineup: Lineup, custom_id = ..., placeholder = None, options: List[SelectOption] = ...):
def __init__(self, session: Session, this_lineup: Lineup, custom_id = ..., placeholder = None, options: List[SelectOption] = ..., responders: list[discord.User] = None):
self.session = session
self.this_lineup = this_lineup
self.responders = responders
super().__init__(custom_id=custom_id, placeholder=placeholder, min_values=1, max_values=1, options=options, disabled=False)
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
)
logger.info(f'Setting sub position to {self.values[0]}')
await interaction.edit_original_response(view=None)
@ -185,16 +207,23 @@ class SelectSubPosition(discord.ui.Select):
class SelectBatterSub(discord.ui.Select):
def __init__(self, this_game: Game, this_team: Team, session: Session, batting_order: int, custom_id: str = MISSING, placeholder: str | None = None, options: List[SelectOption] = ...):
def __init__(self, this_game: Game, this_team: Team, session: Session, batting_order: int, custom_id: str = MISSING, placeholder: str | None = None, options: List[SelectOption] = ..., responders: list[discord.User] = None):
logger.info(f'Inside SelectBatterSub init function')
self.game = this_game
self.team = this_team
self.session = session
# self.league_name = league_name
self.batting_order = batting_order
self.responders = responders
super().__init__(custom_id=custom_id, placeholder=placeholder, min_values=1, max_values=1, 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()
logger.info(f'Setting batter sub to Card ID: {self.values[0]}')
@ -258,7 +287,7 @@ class SelectBatterSub(discord.ui.Select):
position = 'PH'
pos_text = 'What position will they play?'
options=[SelectSubPosition(label=f'{x}', value=pos_dict_list[x], default=x=='Pinch Hitter') for x in pos_dict_list]
options=[SelectSubPosition(label=f'{x}', value=pos_dict_list[x], default=x=='Pinch Hitter', responders=[interaction.user]) for x in pos_dict_list]
view = DropdownView(dropdown_objects=options)
@ -298,13 +327,20 @@ class SelectBatterSub(discord.ui.Select):
class SelectPokemonEvolution(discord.ui.Select):
def __init__(self, *, placeholder = 'Evolve the selected Pokemon', min_values = 1, max_values = 1, options = List[SelectOption], this_team):
def __init__(self, *, placeholder = 'Evolve the selected Pokemon', min_values = 1, max_values = 1, options = List[SelectOption], this_team: Team, responders: list[discord.User] = None):
logging.info(f'Inside SelectPokemonEvolution init function')
self.team = this_team
self.responders = responders
super().__init__(placeholder=placeholder, min_values=min_values, max_values=max_values, 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()
try: