From 33d2c88d09af97ef23499ca1c8c745e84a9a02eb Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Thu, 13 Apr 2023 12:14:56 -0500 Subject: [PATCH] April AI updates, Paper Sluggers draft order update, --- ai_manager.py | 101 ++++++++++++++++++++++++++++++++++++++++++++++- cogs/gameplay.py | 85 ++++++--------------------------------- gauntlets.py | 46 +++++++++++++-------- helpers.py | 29 -------------- 4 files changed, 140 insertions(+), 121 deletions(-) diff --git a/ai_manager.py b/ai_manager.py index f284e69..9cf1e71 100644 --- a/ai_manager.py +++ b/ai_manager.py @@ -3,7 +3,8 @@ import logging import random import pydantic -from db_calls_gameplay import StratPlay, StratGame, get_one_lineup +from db_calls_gameplay import StratPlay, StratGame, get_one_lineup, get_manager, get_team_lineups, \ + get_last_inning_end_play, make_sub, get_player from db_calls import db_get, db_post from peewee import * from typing import Optional, Literal @@ -18,7 +19,9 @@ db = SqliteDatabase( ) MINOR_CARDSET_PARAMS = [('cardset_id', 1), ('cardset_id', 3)] -MAJOR_CARDSET_PARAMS = [('cardset_id', 1), ('cardset_id', 3), ('cardset_id', 4), ('cardset_id', 5), ('cardset_id', 6)] +MAJOR_CARDSET_PARAMS = [ + ('cardset_id', 1), ('cardset_id', 3), ('cardset_id', 4), ('cardset_id', 5), ('cardset_id', 6), ('cardset_id', 7) +] class BaseModel(Model): @@ -492,3 +495,97 @@ def get_pitcher(this_game: StratGame, this_play: StratPlay): if this_play.inning_half == 'top': p_team_id = this_game.home_team_id return get_one_lineup(this_game.id, team_id=p_team_id, position='P', active=True) + + +async def pitching_ai_note(this_play: StratPlay, this_pitcher: dict): + this_ai = get_manager(this_play.game) + gm_name = f'{this_pitcher["team"]["gmname"]}' + used_pitchers = await get_team_lineups( + game_id=this_play.game.id, + team_id=this_pitcher["team"]['id'], + inc_inactive=True, + pitchers_only=True, + as_string=False + ) + last_inning_ender = get_last_inning_end_play( + this_play.game.id, + this_play.inning_half, + this_play.inning_num - 1 + ) + + ai_note = '' + pitcher = this_pitcher + + # Pitcher Substitutions + if last_inning_ender and last_inning_ender.pitcher != this_play.pitcher: + logging.debug(f'{this_pitcher["team"]["sname"]} not making a change.') + + ai_note += f'- have {this_pitcher["p_name"]} finish the inning\n' + + elif this_play.is_new_inning and this_play.game.short_game and this_play.inning_num != 1: + logging.debug(f'{this_pitcher["team"]["sname"]} going the to pen.') + + if len(used_pitchers) < 8: + make_sub(get_relief_pitcher( + this_play, this_pitcher['team'], used_pitchers, this_play.game.game_type + )) + pitcher = await get_player(this_play.game, get_pitcher(this_play.game, this_play)) + else: + ai_note += f'- continue with auto-fatigued {this_pitcher["p_name"]}\n' + + else: + if len(used_pitchers) < 8: + ai_note += f'- go to the pen if the pitcher fatigues (`/log ai-pitcher-sub`)\n' + else: + ai_note += f' - continue with {this_pitcher["p_name"]}\n' + + # Holding Baserunners + if this_play.starting_outs == 2 and this_play.on_base_code > 0: + if this_play.on_base_code in [1, 2]: + ai_note += f'- hold the runner\n' + elif this_play.on_base_code in [4, 7]: + ai_note += f'- hold the runners\n' + elif this_play.on_base_code == 5: + ai_note += f'- hold the runner on first\n' + elif this_play.on_base_code == 6: + ai_note += f'- hold the runner on second\n' + elif this_play.on_base_code in [1, 5]: + ai_note += f'- hold the runner on 1st if they have ***** auto-jump\n' + elif this_play.on_base_code == 2: + ai_note += f'- hold the runner on 2nd if safe range is 14+\n' + + # Defensive Alignment + if this_play.on_third and this_play.starting_outs < 2: + if this_play.on_first: + ai_note += f'- play the corners in\n' + + elif abs(this_play.away_score - this_play.home_score) <= 3: + ai_note += f'- play the whole infield in\n' + + else: + ai_note += f'- play the corners in\n' + + return { + 'note': ai_note, + 'pitcher': pitcher, + 'gm_name': gm_name + } + + +def batting_ai_note(this_play: StratPlay, this_batter: dict): + this_ai = get_manager(this_play.game) + + ai_note = '' + gm_name = f'{this_batter["team"]["gmname"]}' + + if this_play.on_first and not this_play.on_second: + ai_note += f'- {this_ai.check_jump(2, this_play.starting_outs)}\n' + + elif this_play.on_second and not this_play.on_third: + ai_note += f'- {this_ai.check_jump(3, this_play.starting_outs)}\n' + + return { + 'note': ai_note, + 'batter': this_batter, + 'gm_name': gm_name + } diff --git a/cogs/gameplay.py b/cogs/gameplay.py index bbd42c4..0fc2bd0 100644 --- a/cogs/gameplay.py +++ b/cogs/gameplay.py @@ -330,7 +330,6 @@ class Gameplay(commands.Cog): # embed.add_field(name='Matchup', value=f'Pitcher: \nvs\nBatter: ', inline=False) embed.add_field(name='Pitcher', value=f'{pitcher_string}') embed.add_field(name='Batter', value=f'{batter_string}') - embed.set_thumbnail(url=game_state["pitcher"]["image"]) if game_state['batter']['image2']: embed.set_image(url=game_state["batter"]["image2"]) else: @@ -358,81 +357,17 @@ class Gameplay(commands.Cog): # AI Team is pitching if game_state['pitcher']['team']['is_ai']: - this_ai = get_manager(game) - logging.debug(f'Pitching team is an AI') - gm_name = f'{game_state["pitcher"]["team"]["gmname"]}' - used_pitchers = await get_team_lineups( - game_id=game_state['curr_play'].game.id, - team_id=game_state["pitcher"]["team"]['id'], - inc_inactive=True, - pitchers_only=True, - as_string=False - ) - - last_inning_ender = get_last_inning_end_play( - game.id, - game_state['curr_play'].inning_half, - game_state['curr_play'].inning_num - 1 - ) - logging.debug(f'last_inning_ender: {last_inning_ender}') - - if last_inning_ender and last_inning_ender.pitcher != game_state['curr_play'].pitcher: - logging.debug(f'{game_state["pitcher"]["team"]["sname"]} not making a change.') - - ai_note += f'- have {game_state["pitcher"]["p_name"]} finish the inning\n' - - elif game_state['curr_play'].is_new_inning and game.short_game and game_state['curr_play'].inning_num != 1: - logging.debug(f'{game_state["pitcher"]["team"]["sname"]} going the to pen.') - - if len(used_pitchers) < 8: - make_sub(ai_manager.get_relief_pitcher( - game_state['curr_play'], game_state['pitcher']['team'], used_pitchers, game.game_type - )) - new_pitcher = await get_player(game, get_pitcher(game, game_state['curr_play'])) - embed.set_thumbnail(url=new_pitcher['image']) - embed.add_field( - name=f'SUBSTITUTION', - value=f'The {game_state["pitcher"]["team"]["sname"]} have brought in ' - f'[{new_pitcher["p_name"]}]({new_pitcher["image"]}) to pitch.' - ) - else: - ai_note += f'- continue with auto-fatigued {game_state["pitcher"]["p_name"]}\n' - - else: - if len(used_pitchers) < 8: - ai_note += f'- go to the pen if the pitcher fatigues (`/log ai-pitcher-sub`)\n' - else: - ai_note += f' - continue with {game_state["pitcher"]["p_name"]}\n' - - logging.debug(f'past the first conditional in AI stuff') - - if game_state['curr_play'].on_base_code > 0 and game_state['curr_play'].starting_outs == 2: - ai_note += f'- hold the runners' - elif game_state['curr_play'].on_base_code == 1: - ai_note += f'- only hold baserunners with an ***** auto-jump\n' - elif game_state['curr_play'].on_base_code == 2: - ai_note += f'- only hold baserunners with a safe range of 14+\n' - - if game_state['curr_play'].on_third and game_state['curr_play'].starting_outs < 2: - if game_state['curr_play'].on_first: - ai_note += f'- play the corners in\n' - - elif abs(game_state['curr_play'].away_score - game_state['curr_play'].home_score) <= 3: - ai_note += f'- play the whole infield in\n' - - else: - ai_note += f'- play the corners in\n' + ai_data = await ai_manager.pitching_ai_note(game_state['curr_play'], game_state['pitcher']) + ai_note = ai_data['note'] + gm_name = ai_data['gm_name'] + embed.set_thumbnail(url=ai_data['pitcher']["image"]) # AI Team is batting elif game_state['batter']['team']['is_ai']: - this_ai = get_manager(game) - logging.debug(f'Batting team is an AI') - gm_name = f'{game_state["batter"]["team"]["gmname"]}' - if game_state['curr_play'].on_first and not game_state['curr_play'].on_second: - ai_note += f'- {this_ai.check_jump(2, game_state["curr_play"])}\n' - - elif game_state['curr_play'].on_second and not game_state['curr_play'].on_third: - ai_note += f'- {this_ai.check_jump(3, game_state["curr_play"])}\n' + embed.set_thumbnail(url=game_state["pitcher"]["image"]) + ai_data = ai_manager.batting_ai_note(game_state['curr_player'], game_state['batter']) + ai_note = ai_data['note'] + gm_name = ai_data['gm_name'] if ai_note: embed.add_field( @@ -2818,6 +2753,10 @@ class Gameplay(commands.Cog): patch_play( this_play.id, sb=1, on_second_final=3, runner_id=this_play.on_second.id, catcher_id=catcher.id ) + if this_play.on_first: + advance_one_runner( + this_play.id, from_base=1, num_bases=1 + ) else: this_runner = await get_player(this_game, this_play.on_second) await interaction.edit_original_response( diff --git a/gauntlets.py b/gauntlets.py index 0a9a07e..7590627 100644 --- a/gauntlets.py +++ b/gauntlets.py @@ -134,7 +134,7 @@ def get_starting_pitcher(this_team, this_game, this_event, this_run): ('mlbclub', this_team['lname']), ('pos_include', 'SP'), ('inc_dex', False), ('sort_by', 'cost-desc'), ('limit', 5) ] - elif counter >= 2: + elif counter > 2: raise KeyError(f'Error pulling pitchers for the {this_team["lname"]}. Cal help plz.') else: break @@ -310,31 +310,27 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra params.extend([ ('min_rarity', RARITY['Starter']), ('max_rarity', RARITY['Starter']) ]) - elif round_num <= 9: - params.extend([ - ('min_rarity', RARITY['Reserve']), ('max_rarity', RARITY['Reserve']) - ]) - elif round_num == 10: + elif round_num == 6: if random.randint(1, 2) == 1: params = [ ('min_rarity', RARITY['MVP']), ('max_rarity', RARITY['MVP']), ('cardset_id', 8) ] - mario_round = 10 + mario_round = 6 else: params.extend([ ('min_rarity', RARITY['MVP']), ('max_rarity', RARITY['MVP']), ('pos_exc', 'RP') ]) - elif round_num == 11: + elif round_num == 7: if random.randint(1, 2) == 1 and mario_round is None: params = [ ('min_rarity', RARITY['All-Star']), ('max_rarity', RARITY['All-Star']), ('cardset_id', 8) ] - mario_round = 11 + mario_round = 7 else: params.extend([ ('min_rarity', RARITY['All-Star']), ('max_rarity', RARITY['All-Star']) ]) - elif round_num == 12: + elif round_num == 8: if mario_round is None: params = [ ('min_rarity', RARITY['Starter']), ('max_rarity', RARITY['Starter']), ('cardset_id', 8) @@ -344,13 +340,17 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra params.extend([ ('min_rarity', RARITY['Starter']), ('max_rarity', RARITY['Starter']) ]) + elif round_num <= 11: + params.extend([ + ('min_rarity', RARITY['Starter']), ('max_rarity', RARITY['Starter']) + ]) elif round_num <= 15: params.extend([ - ('min_rarity', RARITY['Replacement']), ('max_rarity', RARITY['Replacement']) + ('min_rarity', RARITY['Reserve']), ('max_rarity', RARITY['Reserve']) ]) elif round_num <= 18: params.extend([ - ('min_rarity', RARITY['Starter']), ('max_rarity', RARITY['Starter']) + ('min_rarity', RARITY['Replacement']), ('max_rarity', RARITY['Replacement']) ]) elif round_num == 19: params.extend([ @@ -376,14 +376,18 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra counts['CF'], counts['RF']]: logging.info(f'0 exists in other positions; excluding {x}') params.append(('pos_exc', x)) - elif counts[x] > 3: + elif x == 'C' and counts[x] > 2: + params.append(('pos_exc', x)) + elif x in ['1B', '2B', '3B', 'SS'] and counts[x] > 3: + params.append(('pos_exc', x)) + elif x in ['LF', 'CF', 'RF'] and counts[x] > 4: params.append(('pos_exc', x)) if round_num > 20 and counts[x] < 2: params.append(('pos_inc', x)) if counts['RP'] > 7: params.append(('pos_exc', 'RP')) - if counts['SP'] > 5: + if counts['SP'] > 4: params.append(('pos_exc', 'SP')) if counts['RP'] > counts['SP'] + 3: params.append(('pos_exc', 'RP')) @@ -422,9 +426,13 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra p_names.append(p_choice['p_name']) counts[p_choice['rarity']['name']] += 1 all_players.append(p_choice) - for x in helpers.get_all_pos(p_choice): - if x in counts: - counts[x] += 1 + + 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 @@ -433,6 +441,10 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra logging.error(f'run_draft - No draft logic for Event ID {this_event["id"]}') raise KeyError(f'Draft data not found for Gauntlet {this_event["id"]}') + if len(all_players) < 26: + raise KeyError(f'I gotta be honest - I shit the bed here and wasn\'t able to get you enough players to fill ' + f'a team. I have to wipe this team, but please draft again after you tell Cal his bot sucks.') + this_pack = db_post( 'packs/one', payload={ diff --git a/helpers.py b/helpers.py index fbf2b56..70947c1 100644 --- a/helpers.py +++ b/helpers.py @@ -875,35 +875,6 @@ class SelectView(discord.ui.View): for x in select_objects: self.add_item(x) -# class Email(discord.ui.Modal, title='Team Sheet Share'): -# def __init__(self, title: str, timeout: float = 300.0, custom_id: int = None): -# super().__init__(timeout=timeout) -# self.title = title -# self.custom_id = custom_id -# logging.info(f'Modal init') -# -# email = discord.ui.TextInput( -# label='Email address', -# style=discord.TextStyle.short, -# placeholder='paper.domo@gmail.com', -# required=True -# ) -# -# async def on_submit(self, interaction: discord.Interaction): -# logging.info(f'on_submit: {self.email} for team_id: {self.custom_id}') -# team = get_team_by_owner(int(self.custom_id)) -# share_sheet(team, self.email) -# await interaction.response.send_message( -# f'Got it, {team["gmname"]}. Just shared your team sheet with you!' -# ) -# await interaction.followup.send_message(get_roster_sheet(team)) -# -# async def on_error(self, interaction: discord.Interaction, error: Exception) -> None: -# await interaction.response.send_message('Oops! Something went wrong.', ephemeral=True) -# -# # Make sure we know what the error actually is -# traceback.print_tb(error.__traceback__) - def random_conf_gif(): conf_gifs = [