From 96f783bb63610dc91301b11392922a29154a09d5 Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Mon, 23 Oct 2023 00:58:10 -0500 Subject: [PATCH] 2018 gauntlet in place --- cogs/gameplay.py | 93 +++++++++---- cogs/players.py | 4 +- gauntlets.py | 356 +++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 369 insertions(+), 84 deletions(-) diff --git a/cogs/gameplay.py b/cogs/gameplay.py index 18438b7..02b8a08 100644 --- a/cogs/gameplay.py +++ b/cogs/gameplay.py @@ -1422,7 +1422,7 @@ class Gameplay(commands.Cog): @group_new_game.command(name='gauntlet', description='Start a new Gauntlet game against an AI') @commands.has_any_role(PD_PLAYERS_ROLE_NAME) async def new_game_gauntlet_command( - self, interaction: discord.Interaction, event_name: Literal['Paper Sluggers', 'Flashback Gauntlet']): + self, interaction: discord.Interaction, event_name: Literal['Taste of 2018']): await interaction.response.defer() conflict = get_one_game(channel_id=interaction.channel.id, active=True) @@ -1516,26 +1516,7 @@ class Gameplay(commands.Cog): ) t_role = await team_role(interaction, main_team) - # Get AI Lineup - try: - await interaction.edit_original_response( - content=f'I am getting a lineup card from the {opponent["sname"]}...' - ) - - logging.info(f'new-game - calling lineup for {opponent["abbrev"]}') - all_lineups = await gauntlets.build_lineup(opponent, this_game, this_event) - logging.info(f'new-game-gauntlet - got lineup for {opponent["abbrev"]}') - - except Exception as e: - patch_game(this_game.id, active=False) - logging.error(f'could not start a gauntlet game with {opponent["sname"]}: {e}') - await interaction.edit_original_response( - content=f'Looks like the {opponent["sname"]} lineup card didn\'t come through clearly. I\'ll sort ' - f'this out with {opponent["gmname"]} and {get_cal_user(interaction).mention}. I\'ll end ' - f'this game - why don\'t you play against somebody else for now?' - ) - return - + all_lineups = [] # Get AI Starting Pitcher try: await interaction.edit_original_response( @@ -1548,6 +1529,7 @@ class Gameplay(commands.Cog): starter = await gauntlets.get_starting_pitcher(opponent, this_game, this_event, this_run) all_lineups.append(starter) + ai_sp = await db_get('players', object_id=starter['player_id']) this_card = await db_get(f'cards', object_id=starter['card_id']) await interaction.channel.send( @@ -1565,6 +1547,27 @@ class Gameplay(commands.Cog): ) return + # Get AI Lineup + try: + await interaction.edit_original_response( + content=f'I am getting a lineup card from the {opponent["sname"]}...' + ) + + logging.info(f'new-game - calling lineup for {opponent["abbrev"]}') + batters = await gauntlets.build_lineup(opponent, this_game, this_event, ai_sp["p_name"]) + all_lineups.extend(batters) + logging.info(f'new-game-gauntlet - got lineup for {opponent["abbrev"]}') + + except Exception as e: + patch_game(this_game.id, active=False) + logging.error(f'could not start a gauntlet game with {opponent["sname"]}: {e}') + await interaction.edit_original_response( + content=f'Looks like the {opponent["sname"]} lineup card didn\'t come through clearly. I\'ll sort ' + f'this out with {opponent["gmname"]} and {get_cal_user(interaction).mention}. I\'ll end ' + f'this game - why don\'t you play against somebody else for now?' + ) + return + logging.debug(f'Setting lineup for {opponent["sname"]} in PD Gauntlet game {game_code}') post_lineups(all_lineups) @@ -1661,7 +1664,7 @@ class Gameplay(commands.Cog): elif abs(latest_play.home_score - latest_play.away_score) >= 10 and latest_play.inning_half == 'bot': valid_end = True - valid_end = True # TODO: REMOVE THIS BEFORE GO-LIVE + # valid_end = True # TODO: REMOVE THIS BEFORE GO-LIVE if not valid_end: view = Confirm(responders=[interaction.user]) question = await interaction.channel.send( @@ -1673,8 +1676,50 @@ class Gameplay(commands.Cog): await view.wait() if view.value: - await question.delete() - await self.post_stratgame(this_game, forfeit=True) + await question.delete()# New database driven stat submission + failure = False + final_game = await self.post_stratgame(this_game) + + # Send Plays to db + try: + resp = await self.post_allplays(this_game, final_game['id']) + if not resp: + failure = True + except Exception as e: + logging.error(f'end-game - Could not post plays: {e}') + failure = True + + # Send Decisions to db + try: + resp = await self.post_decisions(this_game, final_game['id']) + if not resp: + failure = True + except Exception as e: + logging.error(f'end-game - Could not post decisions: {e}') + failure = True + + if failure: + try: + await db_delete(f'decisions/game', object_id=final_game["id"]) + except Exception as e: + logging.error(f'could not delete decisions') + + try: + await db_delete(f'plays/game', object_id=final_game["id"]) + except Exception as e: + logging.error(f'could not delete plays') + + try: + await db_delete(f'games', object_id=final_game["id"]) + except Exception as e: + logging.error(f'could not delete game') + + await interaction.channel.send( + content=f'That did not go well and I wasn\'t able to submit this game. I recommend pinging Cal so he ' + f'can fix this.' + ) + return + await send_to_channel( self.bot, 'pd-network-news', f'The **{owner_team["lname"]}** had to cut out early from their game down in ' diff --git a/cogs/players.py b/cogs/players.py index 48b66b5..64a796b 100644 --- a/cogs/players.py +++ b/cogs/players.py @@ -822,7 +822,7 @@ class Players(commands.Cog): ) @app_commands.checks.has_any_role(PD_PLAYERS_ROLE_NAME) async def gauntlet_run_command( - self, interaction: discord.Interaction, event_name: Literal['Paper Sluggers', 'Flashback Gauntlet'], + self, interaction: discord.Interaction, event_name: Literal['Taste of 2018'], team_abbrev: str = None): await interaction.response.defer() @@ -863,7 +863,7 @@ class Players(commands.Cog): @group_gauntlet.command(name='start', description='Start a new Gauntlet run') @app_commands.checks.has_any_role(PD_PLAYERS_ROLE_NAME) async def gauntlet_start_command( - self, interaction: discord.Interaction, event_name: Literal['Paper Sluggers', 'Flashback Gauntlet']): + self, interaction: discord.Interaction, event_name: Literal['Taste of 2018']): if 'hello' not in interaction.channel.name: await interaction.response.send_message( content='The draft will probably take you about 15 minutes. Why don\'t you head to your private ' diff --git a/gauntlets.py b/gauntlets.py index 6ea9e36..4ba554d 100644 --- a/gauntlets.py +++ b/gauntlets.py @@ -42,7 +42,7 @@ async def wipe_team(this_team, interaction: discord.Interaction, delete_team: bo def get_game_code(this_team, this_event, this_run): - return f'gauntlet-{this_event["id"]}-run-{this_run["id"]}-game-{games_played(this_run) + 1}' + return f'gauntlet-{this_event["id"]}-run-{this_run["id"]}' def games_played(this_run): @@ -109,79 +109,121 @@ async def get_opponent(this_team, this_event, this_run): else: raise KeyError(f'Huh...I have no idea who you should be playing right now.') return await db_get('teams', object_id=t_id, none_okay=False) + elif this_event['id'] == 3: + if gp == 0: + t_id = 26 + elif gp == 1: + t_id = 6 + elif gp == 2: + t_id = 12 + elif gp == 3: + t_id = 18 + elif gp == 4: + t_id = 7 + elif gp == 5: + t_id = 20 + elif gp == 6: + t_id = 22 + elif gp == 7: + t_id = 3 + elif gp == 8: + t_id = 21 + elif gp == 9: + t_id = 1 + elif gp == 10: + t_id = 27 + else: + raise KeyError(f'Huh...I have no idea who you should be playing right now.') + return await db_get('teams', object_id=t_id, none_okay=False) else: return None -async def build_lineup(this_team, this_game, this_event): - return await ai_manager.build_lineup(this_team, this_game.id, f'gauntlet-{this_event["id"]}') +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): - if this_event['id'] == 1: - if this_team['id'] != 58: - set_params = copy.deepcopy(ai_manager.MINOR_CARDSET_PARAMS) - else: - set_params = [] - params = [ - ('mlbclub', this_team['lname']), ('pos_include', 'SP'), ('pos_exclude', 'RP'), - ('inc_dex', False), ('sort_by', 'cost-desc'), ('limit', 5) - ] - params.extend(set_params) - elif this_event['id'] == 2: - set_params = copy.deepcopy(ai_manager.GAUNTLET2_PARAMS) - params = [ - ('mlbclub', this_team['lname']), ('pos_include', 'SP'), ('pos_exclude', 'RP'), - ('inc_dex', False), ('sort_by', 'cost-desc'), ('limit', 5) - ] - params.extend(set_params) - else: - raise KeyError(f'Pitcher not found for Gauntlet {this_event["id"]}') + 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}') - params = [ - ('mlbclub', this_team['lname']), ('pos_include', 'SP'), ('pos_exclude', 'RP'), - ('inc_dex', False), ('sort_by', 'cost-desc'), ('limit', 5) - ] - counter = 0 - while True: - counter += 1 - # Pull starters sorted by current cost - try: - params.extend(set_params) - pitchers = await db_get( - endpoint='players', - params=params, - timeout=10 - ) - except ConnectionError as e: - logging.error(f'Could not get pitchers for {this_team["lname"]}: {e}') - raise ConnectionError(f'Error pulling starting pitchers for the {this_team["lname"]}. Cal help plz.') - - if pitchers['count'] == 0: - logging.info(f'pitchers is None') - del params - params = [ - ('mlbclub', this_team['lname']), ('pos_include', 'SP'), - ('inc_dex', False), ('sort_by', 'cost-desc'), ('limit', 5) - ] - elif counter > 2: - raise KeyError(f'Error pulling pitchers for the {this_team["lname"]}. Cal help plz.') - else: - break - - pitcher_num = games_played(this_run) % 5 - card_id = await ai_manager.get_or_create_card(pitchers['players'][pitcher_num], this_team) + # get player card; create one if none found + card_id = await ai_manager.get_or_create_card(starter, this_team) return { - 'game_id': this_game.id, + 'game_id': this_game['id'], 'team_id': this_team['id'], - 'player_id': pitchers['players'][0]['player_id'], + 'player_id': starter['player_id'], 'card_id': card_id, 'position': 'P', 'batting_order': 10, 'after_play': 0 } + # if this_event['id'] == 1: + # if this_team['id'] != 58: + # set_params = copy.deepcopy(ai_manager.MINOR_CARDSET_PARAMS) + # else: + # set_params = [] + # params = [ + # ('mlbclub', this_team['lname']), ('pos_include', 'SP'), ('pos_exclude', 'RP'), + # ('inc_dex', False), ('sort_by', 'cost-desc'), ('limit', 5) + # ] + # params.extend(set_params) + # elif this_event['id'] == 2: + # set_params = copy.deepcopy(ai_manager.GAUNTLET2_PARAMS) + # params = [ + # ('mlbclub', this_team['lname']), ('pos_include', 'SP'), ('pos_exclude', 'RP'), + # ('inc_dex', False), ('sort_by', 'cost-desc'), ('limit', 5) + # ] + # params.extend(set_params) + # else: + # raise KeyError(f'Pitcher not found for Gauntlet {this_event["id"]}') + # + # params = [ + # ('mlbclub', this_team['lname']), ('pos_include', 'SP'), ('pos_exclude', 'RP'), + # ('inc_dex', False), ('sort_by', 'cost-desc'), ('limit', 5) + # ] + # counter = 0 + # while True: + # counter += 1 + # # Pull starters sorted by current cost + # try: + # params.extend(set_params) + # pitchers = await db_get( + # endpoint='players', + # params=params, + # timeout=10 + # ) + # except ConnectionError as e: + # logging.error(f'Could not get pitchers for {this_team["lname"]}: {e}') + # raise ConnectionError(f'Error pulling starting pitchers for the {this_team["lname"]}. Cal help plz.') + # + # if pitchers['count'] == 0: + # logging.info(f'pitchers is None') + # del params + # params = [ + # ('mlbclub', this_team['lname']), ('pos_include', 'SP'), + # ('inc_dex', False), ('sort_by', 'cost-desc'), ('limit', 5) + # ] + # elif counter > 2: + # raise KeyError(f'Error pulling pitchers for the {this_team["lname"]}. Cal help plz.') + # else: + # break + # + # pitcher_num = games_played(this_run) % 5 + # card_id = await ai_manager.get_or_create_card(pitchers['players'][pitcher_num], this_team) + # + # return { + # 'game_id': this_game.id, + # 'team_id': this_team['id'], + # 'player_id': pitchers['players'][0]['player_id'], + # 'card_id': card_id, + # 'position': 'P', + # 'batting_order': 10, + # 'after_play': 0 + # } + async def run_draft(interaction: discord.Interaction, main_team, this_event, draft_team=None): if this_event['id'] == 1: @@ -194,6 +236,10 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra embed_description = f'{this_event["name"]}' base_params = copy.deepcopy(ai_manager.GAUNTLET2_PARAMS) base_params.extend([('limit', 8)]) + elif this_event['id'] == 3: + embed_title = f'{main_team["lname"]} - {this_event["name"]} Draft' + embed_description = f'{this_event["name"]}' + base_params = [('cardset_id', 8), ('cardset_id', 13), ('limit', 8)] else: logging.error(f'run_draft - Event ID {this_event["id"]} not recognized') raise KeyError(f'Draft data not found for Gauntlet {this_event["id"]}') @@ -231,6 +277,7 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra 'CF': 0, 'RF': 0, 'DH': 0, + 'Hall of Fame': 0, 'MVP': 0, 'All-Star': 0, 'Starter': 0, @@ -274,6 +321,7 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra bot_embed = helpers.get_team_embed(f'{embed_title} - Round {round_num}') bot_embed.description = f'Current Roster' all_str = { + 'Hall of Fame': '', 'MVP': '', 'All-Star': '', 'Starter': '', @@ -302,7 +350,11 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra for z in helpers.get_all_pos(y): all_str[z] += f'{name_string}\n' - top_embed.add_field(name=f'MVPs ({counts["MVP"]}/2)', value=all_str['MVP'], inline=False) + if this_event['id'] == 3: + top_embed.add_field(name=f'HoFs ({counts["Hall of Fame"]}/1)', value=all_str['Hall of Fame'], inline=False) + top_embed.add_field(name=f'MVPs ({counts["MVP"]}/1)', value=all_str['MVP'], inline=False) + else: + top_embed.add_field(name=f'MVPs ({counts["MVP"]}/2)', value=all_str['MVP'], inline=False) top_embed.add_field(name=f'All-Stars ({counts["All-Star"]}/3)', value=all_str['All-Star'], inline=False) top_embed.add_field(name=f'Starters ({counts["Starter"]}/9)', value=all_str['Starter'], inline=False) top_embed.add_field(name=f'Reserves ({counts["Reserve"]}/7)', value=all_str['Reserve'], inline=False) @@ -325,8 +377,10 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra return [top_embed, bot_embed] + logging.info(f'getting last message') last_message = await interaction.channel.send(content=None, embeds=get_embeds(include_links=False)) + logging.info(f'going into draft') if this_event['id'] == 1: mario_round = None while round_num <= 26 and counter < 50: @@ -668,6 +722,184 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra counts[p_choice['rarity']['name']] += 1 all_players.append(p_choice) + if p_choice['pos_1'] in ['SP', 'RP']: + counts[p_choice['pos_1']] += 1 + else: + for x in helpers.get_all_pos(p_choice): + if x in counts: + counts[x] += 1 + + # Update roster embed + round_num += 1 + await last_message.edit(content=None, embeds=get_embeds(include_links=False)) + elif this_event['id'] == 3: + while round_num <= 26 and counter < 50: + logging.info(f'round {round_num}') + counter += 1 + params = copy.deepcopy(base_params) + + # Set rarity param based on round number + if round_num == 1: + params.extend([ + ('min_rarity', RARITY['HoF']), ('max_rarity', RARITY['HoF']) + ]) + elif round_num == 2: + params.extend([ + ('min_rarity', RARITY['All-Star']), ('max_rarity', RARITY['All-Star']) + ]) + elif round_num <= 5: + params.extend([ + ('min_rarity', RARITY['Starter']), ('max_rarity', RARITY['Starter']) + ]) + elif round_num == 6: + params.extend([ + ('min_rarity', RARITY['MVP']), ('max_rarity', RARITY['MVP']), ('pos_exc', 'RP') + ]) + elif round_num == 7: + params.extend([ + ('min_rarity', RARITY['All-Star']), ('max_rarity', RARITY['All-Star']) + ]) + elif round_num <= 11: + params.extend([ + ('min_rarity', RARITY['Starter']), ('max_rarity', RARITY['Starter']) + ]) + elif round_num <= 15: + params.extend([ + ('min_rarity', RARITY['Reserve']), ('max_rarity', RARITY['Reserve']) + ]) + elif round_num <= 18: + params.extend([ + ('min_rarity', RARITY['Replacement']), ('max_rarity', RARITY['Replacement']) + ]) + elif round_num == 19: + params.extend([ + ('min_rarity', RARITY['All-Star']), ('max_rarity', RARITY['All-Star']) + ]) + elif round_num <= 21: + params.extend([ + ('min_rarity', RARITY['Starter']), ('max_rarity', RARITY['Starter']) + ]) + elif round_num <= 24: + params.extend([ + ('min_rarity', RARITY['Reserve']), ('max_rarity', RARITY['Reserve']) + ]) + elif round_num <= 26: + params.extend([ + ('min_rarity', RARITY['Replacement']), ('max_rarity', RARITY['Replacement']) + ]) + + logging.info(f'starting position loop') + this_batch = [] + for x in ['SP', 'RP', 'IF', 'OF']: + # Slot 1 - SP + if x == 'SP': + if counts['SP'] > 5: + slot_params = [('pos_exc', 'RP')] + if counts['RP'] > 7: + slot_params = [('pos_exc', 'SP')] + else: + slot_params = [('pos_inc', 'SP')] + # if counts['SP'] > 5: + # slot_params = [('pos_exc', 'SP')] + # elif counts['RP'] < 6: + # slot_params = [('pos_inc', 'RP')] + # else: + # slot_params = [('pos_exc', 'SP'), ('pos_exc', 'RP')] + + # Slot 2 - RP + elif x == 'RP': + logging.info(f'counts[RP]: {counts["RP"]}') + if counts['RP'] > 7: + slot_params = [('pos_exc', 'RP')] + if counts['SP'] > 5: + slot_params = [('pos_exc', 'SP')] + else: + slot_params = [('pos_inc', 'RP')] + + # Slot 3 - IF + elif x == 'IF': + slot_params = [] + for y in ['1B', '2B', '3B', 'SS', 'C']: + if (counts[y] > 1) and 0 in [ + counts['C'], counts['1B'], counts['2B'], counts['3B'], counts['SS'] + ]: + slot_params.append(('pos_exc', y)) + elif (y == 'C' and counts['C'] < 3) or (y != 'C' and counts[y] < 4): + slot_params.append(('pos_inc', y)) + # if counts['C'] < 2: + # slot_params.append(('pos_inc', 'C')) + # if len(slot_params) == 0: + # slot_params = [('pos_exc', 'C'), ('pos_exc', '1B'), ('pos_exc', '2B'), ('pos_exc', '3B'), + # ('pos_exc', 'SS')] + + # Slot 4 - OF + else: + slot_params = [] + for y in ['LF', 'CF', 'RF']: + if counts[y] > 4: + slot_params.append(('pos_exc', y)) + elif counts[y] > 1 and 0 in [counts['LF'], counts['CF'], counts['RF']]: + slot_params.append(('pos_exc', y)) + elif counts[y] < 5: + slot_params.append(('pos_inc', y)) + # if len(slot_params) == 0: + # slot_params = [('pos_exc', 'LF'), ('pos_exc', 'CF'), ('pos_exc', 'RF')] + + logging.info(f'this_batch: {this_batch}') + logging.info(f'slot_params: {slot_params}') + logging.info(f'params: {params}') + + # No position explicitly requested or denied + if len(slot_params) == 0: + if (counts['SP'] + counts['RP']) > ( + counts['C'] + counts['1B'] + counts['2B'] + counts['SS'] + counts['LF'] + counts['CF'] + + counts['RF']): + pos_counts = [ + ('C', counts['C']), ('1B', counts['1B']), ('2B', counts['2B']), ('3B', counts['3B']), + ('SS', counts['SS']), ('LF', counts['LF']), ('CF', counts['CF']), ('RF', counts['RF']) + ] + pos_counts.sort(key=lambda z: z[1]) + slot_params = [('pos_inc', pos_counts[0][0])] + else: + if counts['SP'] >= counts['RP']: + slot_params = [('pos_inc', 'RP')] + else: + slot_params = [('pos_inc', 'SP')] + + slot_params.extend(params) + p_query = await db_get('players/random', params=slot_params) + + if p_query['count'] > 0: + # test_player_list = '' + # for z in p_query['players']: + # test_player_list += f'{z["rarity"]["name"]} - {z["description"]} - {helpers.get_all_pos(x)}\n' + + # Collect 1 cards with no repeat player names + for i in p_query['players']: + if i['p_name'] not in p_names and i not in this_batch: + this_batch.append(i) + break + + if len(this_batch) < 4: + logging.error(f'Pulled less than 4 players in gauntlet draft') + p_query = await db_get('players/random', params=params) + for i in p_query['players']: + if i['p_name'] not in p_names and i not in this_batch: + this_batch.append(i) + if len(this_batch) >= 4: + break + + if len(this_batch) < 4: + raise KeyError(f'This is embarassing, but I couldn\'t find enough players for you to draft from.') + + # Present choices and capture selection + p_choice = await helpers.get_choice_from_cards(interaction, this_batch, delete_message=True) + + # Add player to list and update counts + p_names.append(p_choice['p_name']) + counts[p_choice['rarity']['name']] += 1 + all_players.append(p_choice) + if p_choice['pos_1'] in ['SP', 'RP']: counts[p_choice['pos_1']] += 1 else: @@ -814,6 +1046,14 @@ async def post_result(run_id: int, is_win: bool, this_team, bot, channel): elif x['reward']['player']: # TODO: add give player code pass + elif x['reward']['pack_type'] and this_event['id'] == 3: + await db_post( + 'packs', payload={'packs': [{ + 'team_id': main_team['id'], + 'pack_type_id': x['reward']['pack_type']['id'], + 'pack_cardset_id': 13 + }]} + ) elif x['reward']['pack_type']: await helpers.give_packs(main_team, 1, x['reward']['pack_type']) reward_string += f'- 1x {x["reward"]["pack_type"]["name"]} Pack'