diff --git a/api_calls.py b/api_calls.py index ad2478f..06e8799 100644 --- a/api_calls.py +++ b/api_calls.py @@ -6,6 +6,8 @@ import logging import aiohttp import os +from exceptions import DatabaseError + AUTH_TOKEN = {'Authorization': f'Bearer {os.environ.get("API_TOKEN")}'} try: ENV_DATABASE = os.environ.get('DATABASE').lower() @@ -14,6 +16,7 @@ except Exception as e: DB_URL = 'https://pd.manticorum.com/api' if 'prod' in ENV_DATABASE else 'https://pddev.manticorum.com/api' master_debug = True PLAYER_CACHE = {} +logger = logging.getLogger('discord_app') def param_char(other_params): @@ -37,16 +40,16 @@ def get_req_url(endpoint: str, api_ver: int = 2, object_id: int = None, params: def log_return_value(log_string: str): if master_debug: - logging.info(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}\n') + logger.info(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}\n') else: - logging.debug(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}\n') + logger.debug(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}\n') async def db_get(endpoint: str, api_ver: int = 2, object_id: int = None, params: list = None, none_okay: bool = True, timeout: int = 3): req_url = get_req_url(endpoint, api_ver=api_ver, object_id=object_id, params=params) log_string = f'db_get - get: {endpoint} id: {object_id} params: {params}' - logging.info(log_string) if master_debug else logging.debug(log_string) + logger.info(log_string) if master_debug else logger.debug(log_string) async with aiohttp.ClientSession(headers=AUTH_TOKEN) as session: async with session.get(req_url) as r: @@ -56,18 +59,18 @@ async def db_get(endpoint: str, api_ver: int = 2, object_id: int = None, params: return js elif none_okay: e = await r.text() - logging.error(e) + logger.error(e) return None else: e = await r.text() - logging.error(e) - raise ValueError(f'DB: {e}') + logger.error(e) + raise DatabaseError(e) async def db_patch(endpoint: str, object_id: int, params: list, api_ver: int = 2, timeout: int = 3): req_url = get_req_url(endpoint, api_ver=api_ver, object_id=object_id, params=params) log_string = f'db_patch - patch: {endpoint} {params}' - logging.info(log_string) if master_debug else logging.debug(log_string) + logger.info(log_string) if master_debug else logger.debug(log_string) async with aiohttp.ClientSession(headers=AUTH_TOKEN) as session: async with session.patch(req_url) as r: @@ -77,14 +80,14 @@ async def db_patch(endpoint: str, object_id: int, params: list, api_ver: int = 2 return js else: e = await r.text() - logging.error(e) - raise ValueError(f'DB: {e}') + logger.error(e) + raise DatabaseError(e) async def db_post(endpoint: str, api_ver: int = 2, payload: dict = None, timeout: int = 3): req_url = get_req_url(endpoint, api_ver=api_ver) log_string = f'db_post - post: {endpoint} payload: {payload}\ntype: {type(payload)}' - logging.info(log_string) if master_debug else logging.debug(log_string) + logger.info(log_string) if master_debug else logger.debug(log_string) async with aiohttp.ClientSession(headers=AUTH_TOKEN) as session: async with session.post(req_url, json=payload) as r: @@ -94,14 +97,14 @@ async def db_post(endpoint: str, api_ver: int = 2, payload: dict = None, timeout return js else: e = await r.text() - logging.error(e) - raise ValueError(f'DB: {e}') + logger.error(e) + raise DatabaseError(e) async def db_put(endpoint: str, api_ver: int = 2, payload: dict = None, timeout: int = 3): req_url = get_req_url(endpoint, api_ver=api_ver) log_string = f'post:\n{endpoint} payload: {payload}\ntype: {type(payload)}' - logging.info(log_string) if master_debug else logging.debug(log_string) + logger.info(log_string) if master_debug else logger.debug(log_string) async with aiohttp.ClientSession(headers=AUTH_TOKEN) as session: async with session.put(req_url, json=payload) as r: @@ -111,8 +114,8 @@ async def db_put(endpoint: str, api_ver: int = 2, payload: dict = None, timeout: return js else: e = await r.text() - logging.error(e) - raise ValueError(f'DB: {e}') + logger.error(e) + raise DatabaseError(e) # retries = 0 # while True: @@ -120,7 +123,7 @@ async def db_put(endpoint: str, api_ver: int = 2, payload: dict = None, timeout: # resp = requests.put(req_url, json=payload, headers=AUTH_TOKEN, timeout=timeout) # break # except requests.Timeout as e: - # logging.error(f'Post Timeout: {req_url} / retries: {retries} / timeout: {timeout}') + # logger.error(f'Post Timeout: {req_url} / retries: {retries} / timeout: {timeout}') # if retries > 1: # raise ConnectionError(f'DB: The internet was a bit too slow for me to grab the data I needed. Please ' # f'hang on a few extra seconds and try again.') @@ -131,19 +134,19 @@ async def db_put(endpoint: str, api_ver: int = 2, payload: dict = None, timeout: # data = resp.json() # log_string = f'{data}' # if master_debug: - # logging.info(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}') + # logger.info(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}') # else: - # logging.debug(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}') + # logger.debug(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}') # return data # else: - # logging.warning(resp.text) + # logger.warning(resp.text) # raise ValueError(f'DB: {resp.text}') async def db_delete(endpoint: str, object_id: int, api_ver: int = 2, timeout=3): req_url = get_req_url(endpoint, api_ver=api_ver, object_id=object_id) log_string = f'db_delete - delete: {endpoint} {object_id}' - logging.info(log_string) if master_debug else logging.debug(log_string) + logger.info(log_string) if master_debug else logger.debug(log_string) async with aiohttp.ClientSession(headers=AUTH_TOKEN) as session: async with session.delete(req_url) as r: @@ -153,8 +156,8 @@ async def db_delete(endpoint: str, object_id: int, api_ver: int = 2, timeout=3): return js else: e = await r.text() - logging.error(e) - raise ValueError(f'DB: {e}') + logger.error(e) + raise DatabaseError(e) async def get_team_by_abbrev(abbrev: str): diff --git a/cogs/admins.py b/cogs/admins.py index ca33b52..7684b1c 100644 --- a/cogs/admins.py +++ b/cogs/admins.py @@ -13,12 +13,7 @@ from in_game import ai_manager from in_game.gameplay_models import Play, Session, select, engine, Game, Cardset, Lineup, Team, Player -# date = f'{datetime.datetime.now().year}-{datetime.datetime.now().month}-{datetime.datetime.now().day}' -# logging.basicConfig( -# filename=f'logs/{date}.log', -# format='%(asctime)s - %(levelname)s - %(message)s', -# level=logging.WARNING -# ) +logger = logging.getLogger('discord_app') class Admins(commands.Cog): @@ -164,7 +159,7 @@ class Admins(commands.Cog): total_teams = 0 for y in all_teams['teams']: if not y['is_ai'] and 'gauntlet' not in y['abbrev'].lower(): - logging.warning(f'Giving {num_packs} pack(s) to team: {y["abbrev"]}') + logger.warning(f'Giving {num_packs} pack(s) to team: {y["abbrev"]}') await db_post( 'packs', payload={'packs': [{ @@ -197,7 +192,7 @@ class Admins(commands.Cog): await interaction.edit_original_response(content=f'Hmm...I\'m not sure who **{x.upper()}** is.') return - logging.info(f'give info: {response}') + logger.info(f'give info: {response}') await interaction.edit_original_response(content=f'{response if len(response) > 0 else "All done!"}') @commands.hybrid_command(name='post-guide', help='Mod: Post the ratings guide to team sheet') @@ -251,7 +246,7 @@ class Admins(commands.Cog): await interaction.edit_original_response(content=f'RIP. Failed to process the vR ratings.') return - logging.info(f'Data gathered:\n\n{d_player}\n\n{d_bcpc}\n\n{d_positions}\n\n{d_ratings_vl}\n\n{d_ratings_vr}') + logger.info(f'Data gathered:\n\n{d_player}\n\n{d_bcpc}\n\n{d_positions}\n\n{d_ratings_vl}\n\n{d_ratings_vr}') await interaction.edit_original_response( content='Just spit out the debug info to the log, but processing was successful!') @@ -310,7 +305,7 @@ class Admins(commands.Cog): old_cost = player['cost'] old_rarity = old_rarity new_rarity = new_rarity - logging.info(f'old_rarity: {old_rarity} / new_rarity: {new_rarity}') + logger.info(f'old_rarity: {old_rarity} / new_rarity: {new_rarity}') if old_rarity == 1: if new_rarity == 2: @@ -473,7 +468,7 @@ class Admins(commands.Cog): # Patch player with new rarity_id, cost, and positions 1 - 6 if len(updates) > 0: - logging.info(f'Updating {row[1]} - params: {updates}') + logger.info(f'Updating {row[1]} - params: {updates}') await db_patch( 'players', object_id=this_player['player_id'], @@ -486,7 +481,7 @@ class Admins(commands.Cog): if len(errors) > 0: e_string = "\n- ".join(errors) - logging.error(f'update errors:\n{e_string}') + logger.error(f'update errors:\n{e_string}') await ctx.send(f'I encountered the following errors:\n\n{e_string}') @app_commands.command(name='reset-cache', description='Reset all cached player cards for gameplay') diff --git a/cogs/economy.py b/cogs/economy.py index 73dee7f..35cc160 100644 --- a/cogs/economy.py +++ b/cogs/economy.py @@ -21,10 +21,10 @@ from api_calls import db_get, db_post, db_patch, db_delete, get_team_by_abbrev from help_text import * # date = f'{datetime.datetime.now().year}-{datetime.datetime.now().month}-{datetime.datetime.now().day}' -# logging.basicConfig( +# logger.basicConfig( # filename=f'logs/{date}.log', # format='%(asctime)s - %(levelname)s - %(message)s', -# level=logging.WARNING +# level=logger.WARNING # ) @@ -122,7 +122,7 @@ class Economy(commands.Cog): # @tasks.loop(minutes=10) # async def pd_ticker(self): # now = datetime.datetime.now() - # logging.info(f'Datetime: {now} / weekday: {now.weekday()}') + # logger.info(f'Datetime: {now} / weekday: {now.weekday()}') # guild = self.bot.get_guild(int(os.environ.get('GUILD_ID'))) # if not guild: # return @@ -183,7 +183,7 @@ class Economy(commands.Cog): # Check for notifications all_notifs = await db_get('notifs', params=[('ack', False)]) if not all_notifs: - logging.debug(f'No notifications') + logger.debug(f'No notifications') return topics = { @@ -202,7 +202,7 @@ class Economy(commands.Cog): if line['title'] in topics: topics[line['title']]['notifs'].append(line) - logging.info(f'topics:\n{topics}') + logger.info(f'topics:\n{topics}') for topic in topics: embed = get_team_embed(title=f'{topic}{"s" if len(topics[topic]["notifs"]) > 1 else ""}') embed.description = topics[topic]['desc'] @@ -219,7 +219,7 @@ class Economy(commands.Cog): p_list[x['field_name']]['message'] = f'{x["message"]}' p_list[x['field_name']]['count'] += 1 await db_patch('notifs', object_id=x['id'], params=[('ack', True)]) - logging.debug(f'p_list: {p_list}') + logger.debug(f'p_list: {p_list}') this_embed = copy.deepcopy(embed) counter = 1 @@ -535,8 +535,8 @@ class Economy(commands.Cog): daily = await db_get('rewards', params=[ ('name', 'Daily Check-in'), ('team_id', team['id']), ('created_after', midnight) ]) - logging.debug(f'midnight: {midnight} / now: {int_timestamp(now)}') - logging.debug(f'daily_return: {daily}') + logger.debug(f'midnight: {midnight} / now: {int_timestamp(now)}') + logger.debug(f'daily_return: {daily}') if daily: await interaction.edit_original_response( @@ -676,11 +676,11 @@ class Economy(commands.Cog): 'Mario': [], 'Team Choice': [] } - logging.debug(f'Parsing packs...') + logger.debug(f'Parsing packs...') for pack in p_query['packs']: p_group = None - logging.debug(f'pack: {pack}') - logging.debug(f'pack cardset: {pack["pack_cardset"]}') + logger.debug(f'pack: {pack}') + logger.debug(f'pack cardset: {pack["pack_cardset"]}') if pack['pack_team'] is None and pack['pack_cardset'] is None: if pack['pack_type']['name'] in p_data: p_group = pack['pack_type']['name'] @@ -712,7 +712,7 @@ class Economy(commands.Cog): elif pack['pack_type']['name'] == 'Promo Choice': p_group = f'Promo Choice-Cardset-{pack["pack_cardset"]["id"]}-{pack["pack_cardset"]["name"]}' - logging.info(f'p_group: {p_group}') + logger.info(f'p_group: {p_group}') if p_group is not None: p_count += 1 if p_group not in p_data: @@ -768,7 +768,7 @@ class Economy(commands.Cog): ) p_query = await db_get('players', object_id=player_id, none_okay=False) - logging.debug(f'this_player: {p_query}') + logger.debug(f'this_player: {p_query}') await self.buy_card(interaction, p_query, owner_team) @@ -819,7 +819,7 @@ class Economy(commands.Cog): return this_player = p_query['players'][0] - logging.debug(f'this_player: {this_player}') + logger.debug(f'this_player: {this_player}') await self.buy_card(interaction, this_player, owner_team) @@ -1020,14 +1020,14 @@ class Economy(commands.Cog): for card in c_query['cards']: if len(dupe_strings[str_count]) > 1500: str_count += 1 - logging.debug(f'card: {card}') + logger.debug(f'card: {card}') if skip_live and (card['player']['cardset']['id'] == LIVE_CARDSET_ID): - logging.debug(f'live series card - skipping') + logger.debug(f'live series card - skipping') elif card['player']['player_id'] not in player_ids: - logging.debug(f'not a dupe') + logger.debug(f'not a dupe') player_ids.append(card['player']['player_id']) else: - logging.info(f'{team["abbrev"]} duplicate card: {card["id"]}') + logger.info(f'{team["abbrev"]} duplicate card: {card["id"]}') dupe_cards.append(card) dupe_ids += f'{card["id"]},' dupe_strings[str_count] += f'{card["player"]["rarity"]["name"]} {card["player"]["p_name"]} - ' \ @@ -1037,12 +1037,12 @@ class Economy(commands.Cog): await interaction.edit_original_response(content=f'You currently have 0 duplicate cards!') return - logging.info(f'sending first message / length {len(dupe_strings[0])}') + logger.info(f'sending first message / length {len(dupe_strings[0])}') await interaction.edit_original_response( content=f'You currently have {len(dupe_cards)} duplicate cards:\n\n{dupe_strings[0]}' ) for x in dupe_strings[1:]: - logging.info(f'checking string: {len(x)}') + logger.info(f'checking string: {len(x)}') if len(x) > 0: await interaction.channel.send(x) else: @@ -1142,7 +1142,7 @@ class Economy(commands.Cog): poke_role = get_role(interaction, 'Pokétwo') await share_channel(op_ch, poke_role, read_only=True) except Exception as e: - logging.error(f'unable to share sheet with Poketwo') + logger.error(f'unable to share sheet with Poketwo') await interaction.response.send_message( f'Let\'s head down to your private channel: {op_ch.mention}', @@ -1195,7 +1195,7 @@ class Economy(commands.Cog): break team_string = mlb_anchor_team - logging.debug(f'team_string: {team_string} / team_choice: {team_choice}') + logger.debug(f'team_string: {team_string} / team_choice: {team_choice}') if not team_choice: # Get MLB anchor team while True: @@ -1308,7 +1308,7 @@ class Economy(commands.Cog): roster_counts[pl['rarity']['name']] += 1 for x in get_all_pos(pl): roster_counts[x] += 1 - logging.warning(f'Roster counts for {team["sname"]}: {roster_counts}') + logger.warning(f'Roster counts for {team["sname"]}: {roster_counts}') # Add anchor position coverage update_roster_counts(anchor_players) @@ -1572,7 +1572,7 @@ class Economy(commands.Cog): try: new_sheet = sheets.open_by_url(google_sheet_url) except Exception as e: - logging.error(f'Error accessing {team["abbrev"]} sheet: {e}') + logger.error(f'Error accessing {team["abbrev"]} sheet: {e}') current = await db_get('current') await ctx.send(f'I wasn\'t able to access that sheet. Did you remember to share it with my PD email?' f'\n\nHere\'s a quick refresher:\n{SHEET_SHARE_STEPS}\n\n' @@ -1599,10 +1599,10 @@ class Economy(commands.Cog): new_r_data.append([int(row[0].value)]) else: new_r_data.append([None]) - logging.debug(f'new_r_data: {new_r_data}') + logger.debug(f'new_r_data: {new_r_data}') for row in lineups_data: - logging.debug(f'row: {row}') + logger.debug(f'row: {row}') new_l_data.append([ row[0].value if row[0].value != '' else None, int(row[1].value) if row[1].value != '' else None, @@ -1611,7 +1611,7 @@ class Economy(commands.Cog): row[4].value if row[4].value != '' else None, int(row[5].value) if row[5].value != '' else None ]) - logging.debug(f'new_l_data: {new_l_data}') + logger.debug(f'new_l_data: {new_l_data}') new_r_sheet = new_sheet.worksheet_by_title(f'My Rosters') new_r_sheet.update_values( @@ -1678,7 +1678,7 @@ class Economy(commands.Cog): # # # # # Send current data to Sheets # # if not await self.write_collection(ctx, team, extra=len(roster_data['cut'])): - # # logging.error(f'There was an issue trying to update the {team.sname} roster.') + # # logger.error(f'There was an issue trying to update the {team.sname} roster.') # # await helpers.pause_then_type(ctx, 'Yikes. I had an issue with Sheets. Send help.') # # else: # # await helpers.pause_then_type(ctx, 'Alrighty, your sheet is all up to date!') @@ -1718,7 +1718,7 @@ class Economy(commands.Cog): try: await give_cards_to_team(team, player_ids=all_player_ids, pack_id=this_pack['id']) except Exception as e: - logging.error(f'failed to create cards: {e}') + logger.error(f'failed to create cards: {e}') raise ConnectionError(f'Failed to distribute these cards.') await question.edit(content=f'Alrighty, now I\'ll refresh their sheet...') diff --git a/cogs/gameplay.py b/cogs/gameplay.py index 58ef9f3..3565fca 100644 --- a/cogs/gameplay.py +++ b/cogs/gameplay.py @@ -8,9 +8,9 @@ from discord.ext import commands, tasks import pygsheets from api_calls import db_get -from command_logic.logic_gameplay import advance_runners, bunts, doubles, flyballs, get_lineups_from_sheets, checks_log_interaction, complete_play, hit_by_pitch, homeruns, popouts, show_defense_cards, singles, strikeouts, triples, undo_play, walks -from exceptions import GameNotFoundException, TeamNotFoundException, PlayNotFoundException, GameException -from helpers import DEFENSE_LITERAL, PD_PLAYERS_ROLE_NAME, team_role, user_has_role, random_gif, random_from_list +from command_logic.logic_gameplay import advance_runners, bunts, complete_game, doubles, flyballs, get_lineups_from_sheets, checks_log_interaction, complete_play, hit_by_pitch, homeruns, is_game_over, popouts, show_defense_cards, singles, strikeouts, triples, undo_play, walks +from exceptions import GameNotFoundException, TeamNotFoundException, PlayNotFoundException, GameException, log_exception +from helpers import DEFENSE_LITERAL, PD_PLAYERS_ROLE_NAME, get_channel, team_role, user_has_role, random_gif, random_from_list # from in_game import ai_manager from in_game.ai_manager import get_starting_pitcher, get_starting_lineup @@ -18,10 +18,11 @@ from in_game.game_helpers import PUBLIC_FIELDS_CATEGORY_NAME, legal_check from in_game.gameplay_models import Lineup, Play, Session, engine, player_description, select, Game from in_game.gameplay_queries import get_channel_game_or_none, get_active_games_by_team, get_game_lineups, get_team_or_none, get_card_or_none -from utilities.buttons import Confirm +from utilities.buttons import Confirm, ask_confirm CLASSIC_EMBED = True +logger = logging.getLogger('discord_app') class Gameplay(commands.Cog): @@ -33,24 +34,47 @@ class Gameplay(commands.Cog): @tasks.loop(count=1) async def get_sheets(self): - logging.info(f'Getting sheets') + logger.info(f'Getting sheets') self.sheets = pygsheets.authorize(service_file='storage/paper-dynasty-service-creds.json', retries=1) @get_sheets.before_loop async def before_get_sheets(self): - logging.info(f'Waiting to get sheets') + logger.info(f'Waiting to get sheets') await self.bot.wait_until_ready() async def cog_command_error(self, ctx, error): - logging.error(msg=error, stack_info=True) + logger.error(msg=error, stack_info=True) await ctx.send(f'{error}\n\nRun !help to see the command requirements') async def slash_error(self, ctx, error): - logging.error(msg=error, stack_info=True) + logger.error(msg=error, stack_info=True) await ctx.send(f'{error[:1600]}') async def post_play(self, session: Session, interaction: discord.Interaction, this_play: Play, buffer_message: str = None): - if buffer_message is not None: + if is_game_over(this_play): + await interaction.edit_original_response(content=f'Looks like this one is over! ') + submit_game = await ask_confirm( + interaction=interaction, + question=f'Final score: {this_play.game.away_team.abbrev} {this_play.away_score} - {this_play.home_score} {this_play.game.home_team.abbrev}\n{this_play.scorebug_ascii}\nShould I go ahead and submit this game or roll it back a play?', + custom_confirm_label='Submit', + custom_cancel_label='Roll Back' + ) + + if submit_game: + await complete_game(session, interaction, this_play) + return + else: + logger.warning(f'post_play - is_game_over - {interaction.user.display_name} rejected game completion in Game {this_play.game.id}') + + cal_channel = get_channel(interaction, 'commissioners-office') + await cal_channel.send(content=f'{interaction.user.display_name} just rejected game completion down in {interaction.channel.mention}') + + this_play = undo_play(session, this_play) + + await self.post_play(session, interaction, this_play) + await interaction.channel.send(content=f'I let Cal know his bot is stupid') + + elif buffer_message is not None: await interaction.edit_original_response( content=buffer_message ) @@ -65,8 +89,8 @@ class Gameplay(commands.Cog): ) async def complete_and_post_play(self, session: Session, interaction: discord.Interaction, this_play: Play, buffer_message: str = None): - complete_play(session, this_play) - await self.post_play(session, interaction, this_play, buffer_message) + next_play = complete_play(session, this_play) + await self.post_play(session, interaction, next_play, buffer_message) group_new_game = app_commands.Group(name='new-game', description='Start a new baseball game') @@ -123,7 +147,7 @@ class Gameplay(commands.Cog): return ai_team = away_team if away_team.is_ai else home_team - human_team = away_team if home_team.is_ai else away_team + human_team = away_team if home_team.is_ai else home_team conflict_games = get_active_games_by_team(session, team=human_team) if len(conflict_games) > 0: @@ -134,7 +158,7 @@ class Gameplay(commands.Cog): current = await db_get('current') week_num = current['week'] - logging.info(f'gameplay - new_game_mlb_campaign - Season: {current["season"]} / Week: {week_num} / Away Team: {away_team.description} / Home Team: {home_team.description}') + logger.info(f'gameplay - new_game_mlb_campaign - Season: {current["season"]} / Week: {week_num} / Away Team: {away_team.description} / Home Team: {home_team.description}') def role_error(required_role: str, league_name: str, lower_league: str): return f'Ope. Looks like you haven\'t received the **{required_role}** role, yet!\n\nTo play **{league_name}** games, you need to defeat all 30 MLB teams in the {lower_league} campaign. You can see your progress with `/record`.\n\nIf you have completed the {lower_league} campaign, go ping Cal to get your new role!' @@ -163,14 +187,14 @@ class Gameplay(commands.Cog): home_team_id=home_team.id, channel_id=interaction.channel_id, season=current['season'], - week_num=week_num, + week=week_num, first_message=None if interaction.message is None else interaction.message.channel.id, ai_team='away' if away_team.is_ai else 'home', game_type=league.value ) game_info_log = f'{league.name} game between {away_team.description} and {home_team.description} / first message: {this_game.first_message}' - logging.info(game_info_log) + logger.info(game_info_log) # Get Human SP card human_sp_card = await get_card_or_none(session, card_id=sp_card_id) @@ -181,7 +205,7 @@ class Gameplay(commands.Cog): return if human_sp_card.team_id != human_team.id: - logging.error(f'Card_id {sp_card_id} does not belong to {human_team.abbrev} in Game {this_game.id}') + logger.error(f'Card_id {sp_card_id} does not belong to {human_team.abbrev} in Game {this_game.id}') await interaction.channel.send( f'Uh oh. Card ID {sp_card_id} is {human_sp_card.player.name} and belongs to {human_sp_card.team.sname}. Will you double check that before we get started?' ) @@ -261,29 +285,29 @@ class Gameplay(commands.Cog): await ctx.send(f'I do not see a game here - are you in the right place?') return - await ctx.send( - content=None, - embed=this_game.get_scorebug_embed(session, full_length=True) + try: + await ctx.send( + content=None, + embed=this_game.get_scorebug_embed(session, full_length=True) + ) + except Exception as e: + logger.error(f'Unable to display scorebug while forcing game to end: {e}') + await ctx.send(content='This game is so boned that I can\'t display the scorebug.') + + nuke_game = await ask_confirm( + ctx, + question=f'Is this the game I should nuke?', + label_type='yes', + timeout=15, ) - view = Confirm(responders=[ctx.author], timeout=60, label_type='confirm') - question = await ctx.send(f'Is this the game I should nuke?', view=view) - await view.wait() - - if view.value: + # if view.value: + if nuke_game: session.delete(this_game) session.commit() - await question.edit( - content=random_gif(random_from_list([ - 'i killed it', 'deed is done', 'gone forever' - ])), - view=None - ) + await ctx.channel.send(content=random_gif(random_from_list(['i killed it', 'deed is done', 'gone forever']))) else: - await question.edit( - content=f'~~Is this the game I should nuke?~~\n\nIt stays.', - view=None - ) + await ctx.send(f'It stays. For now.') @app_commands.command(name='read-lineup', description='Import a saved lineup for this channel\'s PD game.') @app_commands.describe( @@ -315,7 +339,7 @@ class Gameplay(commands.Cog): lineup_team = this_game.away_team if this_game.ai_team == 'home' else this_game.home_team if interaction.user.id != lineup_team.gmid: - logging.info(f'{interaction.user.name} tried to run a command in Game {this_game.id} when they aren\'t a GM in the game.') + logger.info(f'{interaction.user.name} tried to run a command in Game {this_game.id} when they aren\'t a GM in the game.') await interaction.edit_original_response(content='Bruh. Only GMs of the active teams can pull lineups.') return @@ -374,7 +398,7 @@ class Gameplay(commands.Cog): this_game, owner_team, this_play = await checks_log_interaction(session, interaction, command_name='log flyball') this_play = await flyballs(session, interaction, this_play, flyball_type) - logging.info(f'log flyball {flyball_type} - this_play: {this_play}') + logger.info(f'log flyball {flyball_type} - this_play: {this_play}') await self.complete_and_post_play( session, @@ -390,7 +414,7 @@ class Gameplay(commands.Cog): this_game, owner_team, this_play = await checks_log_interaction(session, interaction, command_name='log single') this_play = await singles(session, interaction, this_play, single_type) - logging.info(f'log single {single_type} - this_play: {this_play}') + logger.info(f'log single {single_type} - this_play: {this_play}') await self.complete_and_post_play(session, interaction, this_play, buffer_message='Double logged' if ((this_play.on_first or this_play.on_second) and single_type == 'uncapped') else None) @@ -414,7 +438,7 @@ class Gameplay(commands.Cog): this_game, owner_team, this_play = await checks_log_interaction(session, interaction, command_name='log double') this_play = await doubles(session, interaction, this_play, double_type) - logging.info(f'log double {double_type} - this_play: {this_play}') + logger.info(f'log double {double_type} - this_play: {this_play}') await self.complete_and_post_play(session, interaction, this_play, buffer_message='Double logged' if (this_play.on_first and double_type == 'uncapped') else None) @@ -424,7 +448,7 @@ class Gameplay(commands.Cog): this_game, owner_team, this_play = await checks_log_interaction(session, interaction, command_name='log triple') this_play = await triples(session, interaction, this_play) - logging.info(f'log triple - this_play: {this_play}') + logger.info(f'log triple - this_play: {this_play}') await self.complete_and_post_play(session, interaction, this_play) @@ -434,7 +458,7 @@ class Gameplay(commands.Cog): this_game, owner_team, this_play = await checks_log_interaction(session, interaction, command_name='log homerun') this_play = await homeruns(session, interaction, this_play, homerun_type) - logging.info(f'log homerun {homerun_type} - this_play: {this_play}') + logger.info(f'log homerun {homerun_type} - this_play: {this_play}') await self.complete_and_post_play(session, interaction, this_play) @@ -444,7 +468,7 @@ class Gameplay(commands.Cog): this_game, owner_team, this_play = await checks_log_interaction(session, interaction, command_name='log walk') this_play = await walks(session, interaction, this_play, walk_type) - logging.info(f'log walk {walk_type} - this_play: {this_play}') + logger.info(f'log walk {walk_type} - this_play: {this_play}') await self.complete_and_post_play(session, interaction, this_play) @@ -454,7 +478,7 @@ class Gameplay(commands.Cog): this_game, owner_team, this_play = await checks_log_interaction(session, interaction, command_name='log strikeout') this_play = await strikeouts(session, interaction, this_play) - logging.info(f'log strikeout - this_play: {this_play}') + logger.info(f'log strikeout - this_play: {this_play}') await self.complete_and_post_play(session, interaction, this_play) @@ -464,7 +488,7 @@ class Gameplay(commands.Cog): this_game, owner_team, this_play = await checks_log_interaction(session, interaction, command_name='log popout') this_play = await popouts(session, interaction, this_play) - logging.info(f'log popout - this_play: {this_play}') + logger.info(f'log popout - this_play: {this_play}') await self.complete_and_post_play(session, interaction, this_play) @@ -474,7 +498,7 @@ class Gameplay(commands.Cog): this_game, owner_team, this_play = await checks_log_interaction(session, interaction, command_name='log hit-by-pitch') this_play = await hit_by_pitch(session, interaction, this_play) - logging.info(f'log hit-by-pitch - this_play: {this_play}') + logger.info(f'log hit-by-pitch - this_play: {this_play}') await self.complete_and_post_play(session, interaction, this_play) @@ -484,7 +508,7 @@ class Gameplay(commands.Cog): this_game, owner_team, this_play = await checks_log_interaction(session, interaction, command_name='log bunt') this_play = await bunts(session, interaction, this_play, bunt_type) - logging.info(f'log bunt - this_play: {this_play}') + logger.info(f'log bunt - this_play: {this_play}') await self.complete_and_post_play(session, interaction, this_play) @@ -494,7 +518,7 @@ class Gameplay(commands.Cog): this_game, owner_team, this_play = await checks_log_interaction(session, interaction, command_name='log undo-play') this_play = undo_play(session, this_play) - logging.info(f'log undo-play - this_play: {this_play}') + logger.info(f'log undo-play - this_play: {this_play}') await self.post_play(session, interaction, this_play) @@ -505,7 +529,7 @@ class Gameplay(commands.Cog): this_game, owner_team, this_play = await checks_log_interaction(session, interaction, command_name='show-card defense') await show_defense_cards(session, interaction, this_play, position) - logging.info(f'show-card defense - position: {position}') + logger.info(f'show-card defense - position: {position}') async def setup(bot): diff --git a/cogs/gameplay_legacy.py b/cogs/gameplay_legacy.py index 4d95461..4c52e59 100644 --- a/cogs/gameplay_legacy.py +++ b/cogs/gameplay_legacy.py @@ -33,6 +33,9 @@ from db_calls_gameplay import StratGame, StratPlay, post_game, patch_game, get_g get_plays, get_manager, get_one_game, load_ai, ai_batting, undo_subs, get_dbready_plays +logger = logging.getLogger('discord_app') + + class Gameplay(commands.Cog): def __init__(self, bot): self.bot = bot @@ -94,7 +97,7 @@ class Gameplay(commands.Cog): await score_channel.set_permissions(player_role, read_messages=False) return except Exception as e: - logging.error(f'Could not update live_scoreboard: {e}') + logger.error(f'Could not update live_scoreboard: {e}') @live_scoreboard.before_loop async def before_live_scoreboard(self): @@ -104,15 +107,15 @@ class Gameplay(commands.Cog): async def update_ratings_guides(self): guild = self.bot.get_guild(int(os.environ.get('GUILD_ID'))) if not guild: - logging.error(f'Cannot access guild; pausing ratings guide for 20 seconds') + logger.error(f'Cannot access guild; pausing ratings guide for 20 seconds') await asyncio.sleep(20) guild = self.bot.get_guild(int(os.environ.get('GUILD_ID'))) if not guild: - logging.error(f'Still cannot access guild; trying again in 1 minutes') + logger.error(f'Still cannot access guild; trying again in 1 minutes') await asyncio.sleep(60) guild = self.bot.get_guild(int(os.environ.get('GUILD_ID'))) if not guild: - logging.error(f'Still cannot access guild; dueces') + logger.error(f'Still cannot access guild; dueces') return data = get_ratings_guide(get_sheets(self.bot)) @@ -120,7 +123,7 @@ class Gameplay(commands.Cog): self.batter_ratings = data['batter_ratings'] self.pitcher_ratings = data['pitcher_ratings'] else: - logging.error(f'gameplay - pulled bad ratings guide data') + logger.error(f'gameplay - pulled bad ratings guide data') async def cog_command_error(self, ctx, error): await ctx.send(f'{error}\n\nRun !help to see the command requirements') @@ -263,8 +266,8 @@ class Gameplay(commands.Cog): if curr_play is None: away_lineup = await get_team_lineups(game.id, game.away_team_id) home_lineup = await get_team_lineups(game.id, game.home_team_id) - logging.info(f'away_lineup: {away_lineup}') - logging.info(f'home_lineup: {home_lineup}') + logger.info(f'away_lineup: {away_lineup}') + logger.info(f'home_lineup: {home_lineup}') if len(away_lineup) < 200 or len(home_lineup) < 200: game_state = { @@ -274,12 +277,12 @@ class Gameplay(commands.Cog): 'away_team': away_team, 'home_team': home_team } - logging.error(f'One ore more lineups not submitted in Game {game.id}\n\ngame_state: {game_state}') + logger.error(f'One ore more lineups not submitted in Game {game.id}\n\ngame_state: {game_state}') return game_state else: - logging.info(f'looking for home ({game.home_team_id}) pitcher in Game {game.id}') + logger.info(f'looking for home ({game.home_team_id}) pitcher in Game {game.id}') pitcher = get_one_lineup(game.id, team_id=game.home_team_id, position='P') - logging.debug(f'pitcher: {pitcher}') + logger.debug(f'pitcher: {pitcher}') curr_play = post_play({ 'game_id': game.id, 'play_num': 1, @@ -321,7 +324,7 @@ class Gameplay(commands.Cog): ) ) except Exception as e: - logging.error(f'ERROR: {e} / TYPE: {type(e)}') + logger.error(f'ERROR: {e} / TYPE: {type(e)}') away_lineup = await get_team_lineups(game.id, game.away_team_id) home_lineup = await get_team_lineups(game.id, game.home_team_id) if litmus == 0: @@ -348,14 +351,14 @@ class Gameplay(commands.Cog): game_state['pitcher']['team'] = away_team game_state['catcher']['team'] = away_team game_state['batter']['team'] = home_team - logging.debug(f'game_state: {game_state}') + logger.debug(f'game_state: {game_state}') return game_state async def initialize_play_plus_embed(self, game: StratGame, full_length=True, for_liveboard=False): game_state = await self.get_game_state(game) - logging.debug(f'game_state: {game_state}') + logger.debug(f'game_state: {game_state}') gt_string = ' - Unlimited' if game.game_type == 'minor-league': @@ -385,15 +388,15 @@ class Gameplay(commands.Cog): return embed - logging.debug(f'no errors') + logger.debug(f'no errors') pitching_sub = None ai_note = '' gm_name = '' fatigue = await ai_manager.is_pitcher_fatigued(game_state['curr_play']) - logging.debug(f'do AI stuff') + logger.debug(f'do AI stuff') # If an AI team is playing if True in [game_state['pitcher']['team']['is_ai'], game_state['batter']['team']['is_ai']]: - logging.debug(f'Checking AI stuff') + logger.debug(f'Checking AI stuff') # AI Team is pitching if game_state['pitcher']['team']['is_ai']: @@ -403,7 +406,7 @@ class Gameplay(commands.Cog): game_state = await self.get_game_state(game) ai_data = await ai_manager.pitching_ai_note(game_state['curr_play'], game_state['pitcher']) - logging.debug(f'ai_data: {ai_data}') + logger.debug(f'ai_data: {ai_data}') ai_note = ai_data['note'] gm_name = ai_data['gm_name'] @@ -424,7 +427,7 @@ class Gameplay(commands.Cog): title=f'{game_state["away_team"]["sname"]} @ {game_state["home_team"]["sname"]}{gt_string}', color=color ) - logging.info(f'got embed') + logger.info(f'got embed') footer_text = f'Paper Dynasty Season {PD_SEASON}' if game.short_game: @@ -434,16 +437,16 @@ class Gameplay(commands.Cog): embed.add_field(name='Game State', value=game_state['scorebug'], inline=False) embed.set_thumbnail(url=player_pcard(game_state['pitcher'])) - logging.info(f'check mercy') + logger.info(f'check mercy') if abs(game_state['curr_play'].home_score - game_state['curr_play'].away_score) >= 10: embed.description = '***Mercy rule in effect***' - logging.info(f'set pitcher string') + logger.info(f'set pitcher string') pitcher_string = f'{player_link(game, game_state["pitcher"])}' batter_string = f'{game_state["curr_play"].batter.batting_order}. {player_link(game, game_state["batter"])} - ' \ f'{game_state["curr_play"].batter.position}' - logging.info(f'pull bat stats') + logger.info(f'pull bat stats') all_bat_stats = get_batting_stats(game.id, lineup_id=game_state['curr_play'].batter.id) if len(all_bat_stats): b_s = all_bat_stats[0] @@ -456,7 +459,7 @@ class Gameplay(commands.Cog): if num: batter_string += f', {num if num > 1 else ""}{" " if num > 1 else ""}{stat}' - logging.info(f'pull pitcher stats') + logger.info(f'pull pitcher stats') all_pit_stats = get_pitching_stats(game.id, lineup_id=game_state['curr_play'].pitcher.id) if len(all_pit_stats): p_s = all_pit_stats[0] @@ -472,12 +475,12 @@ class Gameplay(commands.Cog): if fatigue and pitching_sub is None: pitcher_string += f'\n***F A T I G U E D***' - logging.info(f'set embed pitcher/batter') + logger.info(f'set embed pitcher/batter') embed.add_field(name='Pitcher', value=f'{pitcher_string}') embed.add_field(name='Batter', value=f'{batter_string}') embed.set_image(url=player_bcard(game_state['batter'])) - logging.info(f'get baserunners') + logger.info(f'get baserunners') baserunner_string = '' if game_state['curr_play'].on_first: runner = await get_player(game, game_state['curr_play'].on_first) @@ -489,7 +492,7 @@ class Gameplay(commands.Cog): runner = await get_player(game, game_state['curr_play'].on_third) baserunner_string += f'On Third: {player_link(game, runner)}\n' - logging.info(f'set baserunners') + logger.info(f'set baserunners') if len(baserunner_string) > 0: embed.add_field(name=' ', value=' ', inline=False) embed.add_field( @@ -517,7 +520,7 @@ class Gameplay(commands.Cog): f'**{player_desc(pitching_sub)}** to pitch' ) - logging.info(f'if not full length: return embed: {embed}') + logger.info(f'if not full length: return embed: {embed}') if not full_length: return embed @@ -855,7 +858,7 @@ class Gameplay(commands.Cog): if not num_outs: num_outs += 1 - logging.debug(f'should be patching the gb C now...') + logger.debug(f'should be patching the gb C now...') patch_play(this_play.id, pa=1, ab=1, outs=num_outs) else: @@ -890,7 +893,7 @@ class Gameplay(commands.Cog): playing_in = False await question.delete() - logging.info(f'playing_in: {playing_in} / obc: {this_play.on_base_code} / gb_type: {groundball_type}') + logger.info(f'playing_in: {playing_in} / obc: {this_play.on_base_code} / gb_type: {groundball_type}') if not playing_in: if groundball_type == 'a': @@ -1014,9 +1017,9 @@ class Gameplay(commands.Cog): advance_one_runner(this_play.id, from_base=3, num_bases=1) if this_play.starting_outs < 2 and this_play.on_second: - logging.debug(f'calling of embed') + logger.debug(f'calling of embed') await show_outfield_cards(interaction, this_play) - logging.debug(f'done with of embed') + logger.debug(f'done with of embed') ai_hint = '' if this_game.ai_team and ai_batting(this_game, this_play): @@ -1056,9 +1059,9 @@ class Gameplay(commands.Cog): patch_play(this_play.id, locked=True, pa=1, ab=1, outs=1) advance_runners(this_play.id, num_bases=0) if this_play.starting_outs < 2 and this_play.on_third: - logging.debug(f'calling of embed') + logger.debug(f'calling of embed') await show_outfield_cards(interaction, this_play) - logging.debug(f'done with of embed') + logger.debug(f'done with of embed') ai_hint = '' if ai_batting(this_game, this_play): @@ -1124,7 +1127,7 @@ class Gameplay(commands.Cog): ) return except Exception as e: - logging.error(f'Could not check channel category: {e}') + logger.error(f'Could not check channel category: {e}') away_team = await get_team_by_abbrev(away_team_abbrev) home_team = await get_team_by_abbrev(home_team_abbrev) @@ -1160,11 +1163,11 @@ class Gameplay(commands.Cog): current = await db_get('current') week_num = current['week'] - # logging.debug(f'away: {away_team} / home: {home_team} / week: {week_num} / ranked: {is_ranked}') - logging.debug(f'away: {away_team} / home: {home_team} / week: {week_num}') + # logger.debug(f'away: {away_team} / home: {home_team} / week: {week_num} / ranked: {is_ranked}') + logger.debug(f'away: {away_team} / home: {home_team} / week: {week_num}') if not away_team['is_ai'] and not home_team['is_ai']: - logging.error(f'MLB Campaign game between {away_team["abbrev"]} and {home_team["abbrev"]} has no AI') + logger.error(f'MLB Campaign game between {away_team["abbrev"]} and {home_team["abbrev"]} has no AI') await interaction.edit_original_response( content=f'I don\'t see an AI team in this MLB Campaign game. Run `/new-game mlb-campaign` again with ' f'an AI for a campaign game or `/new-game ` for a human game.' @@ -1238,7 +1241,7 @@ class Gameplay(commands.Cog): 'short_game': True if num_innings == 3 else False, 'game_type': league_name }) - logging.info( + logger.info( f'Game {this_game.id} ({league_name}) between {away_team_abbrev.upper()} and ' f'{home_team_abbrev.upper()} is posted!' ) @@ -1250,7 +1253,7 @@ class Gameplay(commands.Cog): human_sp_card = await db_get(f'cards', object_id=sp_card_id) if human_sp_card['team']['id'] != human_team['id']: - logging.error( + logger.error( f'Card_id {sp_card_id} does not belong to {human_team["abbrev"]} in Game {this_game.id}' ) patch_game(this_game.id, active=False) @@ -1317,7 +1320,7 @@ class Gameplay(commands.Cog): except Exception as e: patch_game(this_game.id, active=False) - logging.error(f'could not start an AI game with {ai_team["sname"]}: {e}') + logger.error(f'could not start an AI game with {ai_team["sname"]}: {e}') await interaction.edit_original_response( content=f'Looks like the {ai_team["sname"]} rotation didn\'t come through clearly. I\'ll sort ' f'this out with {ai_team["gmname"]} and {get_cal_user(interaction).mention}. I\'ll end ' @@ -1331,16 +1334,16 @@ class Gameplay(commands.Cog): content=f'I am getting a lineup card from the {ai_team["sname"]}...' ) - logging.info(f'new-game - calling lineup for {ai_team["abbrev"]}') + logger.info(f'new-game - calling lineup for {ai_team["abbrev"]}') batters = await ai_manager.build_lineup( ai_team, this_game.id, league_name, sp_name=ai_sp['p_name'] ) all_lineups.extend(batters) - logging.info(f'new-game - got lineup for {ai_team["abbrev"]}') + logger.info(f'new-game - got lineup for {ai_team["abbrev"]}') except Exception as e: patch_game(this_game.id, active=False) - logging.error(f'could not start an AI game with {ai_team["sname"]}: {e}') + logger.error(f'could not start an AI game with {ai_team["sname"]}: {e}') await interaction.edit_original_response( content=f'Looks like the {ai_team["sname"]} lineup card didn\'t come through clearly. I\'ll sort ' f'this out with {ai_team["gmname"]} and {get_cal_user(interaction).mention}. I\'ll end ' @@ -1348,8 +1351,8 @@ class Gameplay(commands.Cog): ) return - logging.debug(f'Setting lineup for {ai_team["sname"]} in PD game') - logging.debug(f'lineups: {all_lineups}') + logger.debug(f'Setting lineup for {ai_team["sname"]} in PD game') + logger.debug(f'lineups: {all_lineups}') post_lineups(all_lineups) await interaction.channel.send( @@ -1381,7 +1384,7 @@ class Gameplay(commands.Cog): ) return except Exception as e: - logging.error(f'Could not check channel category: {e}') + logger.error(f'Could not check channel category: {e}') away_team = await get_team_by_abbrev(away_team_abbrev) home_team = await get_team_by_abbrev(home_team_abbrev) @@ -1398,7 +1401,7 @@ class Gameplay(commands.Cog): return if away_team['is_ai'] or home_team['is_ai']: - logging.error(f'Ranked game between {away_team["abbrev"]} and {home_team["abbrev"]} has an AI') + logger.error(f'Ranked game between {away_team["abbrev"]} and {home_team["abbrev"]} has an AI') await interaction.edit_original_response( content=f'Only human vs human games can be ranked - run `/new-game` again and double-check the ' f'game type you want! If you have questions, feel free to post up in #paper-dynasty-chat' @@ -1417,7 +1420,7 @@ class Gameplay(commands.Cog): current = await db_get('current') week_num = current['week'] - logging.debug(f'away: {away_team} / home: {home_team} / week: {week_num} / ranked: True') + logger.debug(f'away: {away_team} / home: {home_team} / week: {week_num} / ranked: True') if interaction.user.id not in [away_team['gmid'], home_team['gmid']]: await interaction.edit_original_response( @@ -1437,7 +1440,7 @@ class Gameplay(commands.Cog): 'short_game': True if num_innings == 3 else False, 'game_type': 'ranked' }) - logging.info( + logger.info( f'Game {this_game.id} between {away_team_abbrev.upper()} and {home_team_abbrev.upper()} is posted!' ) away_role = await team_role(interaction, away_team) @@ -1472,7 +1475,7 @@ class Gameplay(commands.Cog): ) return except Exception as e: - logging.error(f'Could not check channel category: {e}') + logger.error(f'Could not check channel category: {e}') away_team = await get_team_by_abbrev(away_team_abbrev) home_team = await get_team_by_abbrev(home_team_abbrev) @@ -1489,7 +1492,7 @@ class Gameplay(commands.Cog): return if away_team['is_ai'] or home_team['is_ai']: - logging.error(f'Ranked game between {away_team["abbrev"]} and {home_team["abbrev"]} has an AI') + logger.error(f'Ranked game between {away_team["abbrev"]} and {home_team["abbrev"]} has an AI') await interaction.edit_original_response( content=f'This command is for human v human games - run `/new-game` again and double-check the ' f'game type you want! If you have questions, feel free to post up in #paper-dynasty-chat' @@ -1508,7 +1511,7 @@ class Gameplay(commands.Cog): current = await db_get('current') week_num = current['week'] - logging.debug(f'away: {away_team} / home: {home_team} / week: {week_num} / ranked: True') + logger.debug(f'away: {away_team} / home: {home_team} / week: {week_num} / ranked: True') if interaction.user.id not in [away_team['gmid'], home_team['gmid']]: await interaction.edit_original_response( @@ -1528,7 +1531,7 @@ class Gameplay(commands.Cog): 'short_game': True if num_innings == 3 else False, 'game_type': 'unlimited' }) - logging.info( + logger.info( f'Game {this_game.id} between {away_team_abbrev.upper()} and {home_team_abbrev.upper()} is posted!' ) away_role = await team_role(interaction, away_team) @@ -1563,7 +1566,7 @@ class Gameplay(commands.Cog): ) return except Exception as e: - logging.error(f'Could not check channel category: {e}') + logger.error(f'Could not check channel category: {e}') current = await db_get('current') week_num = current['week'] @@ -1624,7 +1627,7 @@ class Gameplay(commands.Cog): ) return else: - logging.info(f'opponent: {opponent}') + logger.info(f'opponent: {opponent}') game_code = gauntlets.get_game_code(team, this_event, this_run) this_game = post_game({ @@ -1639,7 +1642,7 @@ class Gameplay(commands.Cog): 'short_game': False, 'game_type': game_code }) - logging.info( + logger.info( f'Game {this_game.id} between {team["abbrev"]} and {opponent["abbrev"]} is posted!' ) t_role = await team_role(interaction, main_team) @@ -1649,7 +1652,7 @@ class Gameplay(commands.Cog): human_sp_card = await db_get(f'cards', object_id=sp_card_id) if human_sp_card['team']['id'] != team['id']: - logging.error( + logger.error( f'Card_id {sp_card_id} does not belong to {team["abbrev"]} in Game {this_game.id}' ) await interaction.channel.send( @@ -1657,7 +1660,7 @@ class Gameplay(commands.Cog): f'{human_sp_card["team"]["sname"]}. Will you double check that before we get started?') return - logging.info(f'Appending Human SP ({human_sp_card["player"]["p_name"]}) to all_lineups') + logger.info(f'Appending Human SP ({human_sp_card["player"]["p_name"]}) to all_lineups') all_lineups.append({ 'game_id': this_game.id, 'team_id': team['id'], @@ -1670,7 +1673,7 @@ class Gameplay(commands.Cog): # Get AI Starting Pitcher try: - logging.info(f'Getting SP for {opponent["abbrev"]}') + logger.info(f'Getting SP for {opponent["abbrev"]}') await interaction.edit_original_response( content=f'Now to decide on a Starting Pitcher...' ) @@ -1691,7 +1694,7 @@ class Gameplay(commands.Cog): except Exception as e: patch_game(this_game.id, active=False) - logging.error(f'could not start an AI game with {opponent["sname"]}: {e}') + logger.error(f'could not start an AI game with {opponent["sname"]}: {e}') await interaction.edit_original_response( content=f'Looks like the {opponent["sname"]} rotation didn\'t come through clearly. I\'ll sort ' f'this out with {opponent["gmname"]} and {get_cal_user(interaction).mention}. I\'ll end ' @@ -1705,14 +1708,14 @@ class Gameplay(commands.Cog): content=f'I am getting a lineup card from the {opponent["sname"]}...' ) - logging.info(f'new-game - calling lineup for {opponent["abbrev"]}') + logger.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"]}') + logger.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}') + logger.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 ' @@ -1720,7 +1723,7 @@ class Gameplay(commands.Cog): ) return - logging.debug(f'Setting lineup for {opponent["sname"]} in PD Gauntlet game {game_code}') + logger.debug(f'Setting lineup for {opponent["sname"]} in PD Gauntlet game {game_code}') post_lineups(all_lineups) await interaction.channel.send( @@ -1753,7 +1756,7 @@ class Gameplay(commands.Cog): ) return except Exception as e: - logging.error(f'Could not check channel category: {e}') + logger.error(f'Could not check channel category: {e}') away_team = await get_team_by_abbrev(away_team_abbrev) home_team = await get_team_by_abbrev(home_team_abbrev) @@ -1781,11 +1784,11 @@ class Gameplay(commands.Cog): current = await db_get('current') week_num = current['week'] - # logging.debug(f'away: {away_team} / home: {home_team} / week: {week_num} / ranked: {is_ranked}') - logging.debug(f'away: {away_team} / home: {home_team} / week: {week_num}') + # logger.debug(f'away: {away_team} / home: {home_team} / week: {week_num} / ranked: {is_ranked}') + logger.debug(f'away: {away_team} / home: {home_team} / week: {week_num}') if not away_team['is_ai'] and not home_team['is_ai']: - logging.error(f'Exhibition game between {away_team["abbrev"]} and {home_team["abbrev"]} has no AI') + logger.error(f'Exhibition game between {away_team["abbrev"]} and {home_team["abbrev"]} has no AI') await interaction.edit_original_response( content=f'I don\'t see an AI team in this Exhibition game. Run `/new-game mlb-campaign` again with ' f'an AI for a campaign game or `/new-game ` for a human game.' @@ -1815,7 +1818,7 @@ class Gameplay(commands.Cog): 'short_game': True if num_innings == 3 else False, 'game_type': league_name }) - logging.info( + logger.info( f'Game {this_game.id} ({league_name}) between {away_team_abbrev.upper()} and ' f'{home_team_abbrev.upper()} is posted!' ) @@ -1826,7 +1829,7 @@ class Gameplay(commands.Cog): human_sp_card = await db_get(f'cards', object_id=sp_card_id) if human_sp_card['team']['id'] != human_team['id']: - logging.error( + logger.error( f'Card_id {sp_card_id} does not belong to {human_team["abbrev"]} in Game {this_game.id}' ) patch_game(this_game.id, active=False) @@ -1873,7 +1876,7 @@ class Gameplay(commands.Cog): except Exception as e: patch_game(this_game.id, active=False) - logging.error(f'could not start an AI game with {ai_team["sname"]}: {e}') + logger.error(f'could not start an AI game with {ai_team["sname"]}: {e}') await interaction.channel.send( content=f'Looks like the {ai_team["sname"]} rotation didn\'t come through clearly. I\'ll sort ' f'this out with {ai_team["gmname"]} and {get_cal_user(interaction).mention}. I\'ll end ' @@ -1887,16 +1890,16 @@ class Gameplay(commands.Cog): content=f'I am getting a lineup card from the {ai_team["sname"]}...' ) - logging.info(f'new-game - calling lineup for {ai_team["abbrev"]}') + logger.info(f'new-game - calling lineup for {ai_team["abbrev"]}') batters = await ai_manager.build_lineup( ai_team, this_game.id, league_name, sp_name=ai_sp['p_name'] ) all_lineups.extend(batters) - logging.info(f'new-game - got lineup for {ai_team["abbrev"]}') + logger.info(f'new-game - got lineup for {ai_team["abbrev"]}') except Exception as e: patch_game(this_game.id, active=False) - logging.error(f'could not start an AI game with {ai_team["sname"]}: {e}') + logger.error(f'could not start an AI game with {ai_team["sname"]}: {e}') await interaction.edit_original_response( content=f'Looks like the {ai_team["sname"]} lineup card didn\'t come through clearly. I\'ll sort ' f'this out with {ai_team["gmname"]} and {get_cal_user(interaction).mention}. I\'ll end ' @@ -1904,8 +1907,8 @@ class Gameplay(commands.Cog): ) return - logging.debug(f'Setting lineup for {ai_team["sname"]} in PD game') - logging.debug(f'lineups: {all_lineups}') + logger.debug(f'Setting lineup for {ai_team["sname"]} in PD game') + logger.debug(f'lineups: {all_lineups}') post_lineups(all_lineups) if cardsets in ['Minor League', 'Major League', 'Hall of Fame', 'Flashback']: @@ -1969,7 +1972,7 @@ class Gameplay(commands.Cog): try: await ctx.send(content=None, embed=await self.initialize_play_plus_embed(this_game)) except Exception as e: - logging.error(f'could not post game state embed: {e}') + logger.error(f'could not post game state embed: {e}') question = await ctx.send( f'Something is very borked here and I can\'t post the embed. Imma nuke this game now...' ) @@ -2003,7 +2006,7 @@ class Gameplay(commands.Cog): if not this_game: await interaction.edit_original_response(content='Ope, I don\'t see a game in this channel.') return - logging.info(f'Ending Game {this_game.id}') + logger.info(f'Ending Game {this_game.id}') response = await interaction.edit_original_response(content=f'Let\'s see what we\'ve got here...') @@ -2036,51 +2039,51 @@ class Gameplay(commands.Cog): return valid_end = False - logging.debug(f'latest play: {latest_play}') + logger.debug(f'latest play: {latest_play}') if not this_game.short_game: if latest_play.starting_outs == 0: - logging.debug(f'no outs') + logger.debug(f'no outs') if latest_play.inning_half.lower() == 'top': - logging.debug(f'top of inning') + logger.debug(f'top of inning') if latest_play.inning_num > 9 and latest_play.away_score != latest_play.home_score: - logging.debug(f'after the ninth and not tied') + logger.debug(f'after the ninth and not tied') valid_end = True if abs(latest_play.home_score - latest_play.away_score) >= 10: - logging.debug(f'not after ninth, but mercy') + logger.debug(f'not after ninth, but mercy') valid_end = True if latest_play.inning_half.lower() == 'bot': if (latest_play.home_score > latest_play.away_score) and latest_play.inning_num >= 9: - logging.debug(f'bottom half and home team winning') + logger.debug(f'bottom half and home team winning') valid_end = True if abs(latest_play.home_score - latest_play.away_score) >= 10: - logging.debug(f'bottom half and mercy') + logger.debug(f'bottom half and mercy') valid_end = True elif abs(latest_play.home_score - latest_play.away_score) >= 10 and latest_play.inning_half.lower() == 'bot': - logging.info(f'bottom half and it is a mercy') + logger.info(f'bottom half and it is a mercy') valid_end = True elif latest_play.inning_num >= 9 and latest_play.inning_half.lower() == 'bot' and \ latest_play.home_score > latest_play.away_score: valid_end = True else: if latest_play.starting_outs == 0: - logging.debug(f'no outs') + logger.debug(f'no outs') if latest_play.inning_half.lower() == 'top': - logging.debug(f'top of inning') + logger.debug(f'top of inning') if latest_play.inning_num > 3 and latest_play.away_score != latest_play.home_score: - logging.debug(f'after the ninth and not tied') + logger.debug(f'after the ninth and not tied') valid_end = True if abs(latest_play.home_score - latest_play.away_score) >= 10: - logging.debug(f'not after ninth, but mercy') + logger.debug(f'not after ninth, but mercy') valid_end = True if latest_play.inning_half.lower() == 'bot': if (latest_play.home_score > latest_play.away_score) and latest_play.inning_num >= 3: - logging.debug(f'bottom half and home team winning') + logger.debug(f'bottom half and home team winning') valid_end = True if abs(latest_play.home_score - latest_play.away_score) >= 10: - logging.debug(f'bottom half and mercy') + logger.debug(f'bottom half and mercy') valid_end = True elif abs(latest_play.home_score - latest_play.away_score) >= 10 and latest_play.inning_half.lower() == 'bot': - logging.info(f'bottom half and it is a mercy') + logger.info(f'bottom half and it is a mercy') valid_end = True elif latest_play.inning_num >= 3 and latest_play.inning_half.lower() == 'bot' and \ latest_play.home_score > latest_play.away_score: @@ -2108,7 +2111,7 @@ class Gameplay(commands.Cog): if not resp: failure = True except Exception as e: - logging.error(f'end-game - Could not post plays: {e}') + logger.error(f'end-game - Could not post plays: {e}') failure = True # Send Decisions to db @@ -2117,24 +2120,24 @@ class Gameplay(commands.Cog): if not resp: failure = True except Exception as e: - logging.error(f'end-game - Could not post decisions: {e}') + logger.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') + logger.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') + logger.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') + logger.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 ' @@ -2179,7 +2182,7 @@ class Gameplay(commands.Cog): if not resp: failure = True except Exception as e: - logging.error(f'end-game - Could not post plays: {e}') + logger.error(f'end-game - Could not post plays: {e}') failure = True # Send Decisions to db @@ -2188,24 +2191,24 @@ class Gameplay(commands.Cog): if not resp: failure = True except Exception as e: - logging.error(f'end-game - Could not post decisions: {e}') + logger.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') + logger.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') + logger.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') + logger.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 ' @@ -2228,7 +2231,7 @@ class Gameplay(commands.Cog): loss_reward = r_data['loss_string'] # Post a notification to PD - logging.debug(f'getting inning') + logger.debug(f'getting inning') inning = f'{latest_play.inning_num if latest_play.inning_half == "Bot" else latest_play.inning_num - 1}' embed = get_team_embed( f'{away_team["lname"]} {latest_play.away_score} @ {latest_play.home_score} {home_team["lname"]} - F/' @@ -2236,7 +2239,7 @@ class Gameplay(commands.Cog): winning_team ) - logging.debug(f'setting location') + logger.debug(f'setting location') embed.add_field( name='Location', value=f'{interaction.guild.get_channel(this_game.channel_id).mention}' @@ -2244,7 +2247,7 @@ class Gameplay(commands.Cog): embed.add_field(name='Game ID', value=f'{final_game["id"]}') - logging.debug(f'getting league name') + logger.debug(f'getting league name') if this_game.game_type == 'major-league': game_des = 'Major League' elif this_game.game_type == 'minor-league': @@ -2261,7 +2264,7 @@ class Gameplay(commands.Cog): game_des = 'Unlimited' embed.description = f'Score Report - {game_des} ' \ f'{"- 3-Inning Game" if this_game.short_game else " - 9-Inning Game"}' - logging.debug(f'building box score') + logger.debug(f'building box score') embed.add_field( name='Box Score', value=f'```\n' @@ -2274,7 +2277,7 @@ class Gameplay(commands.Cog): inline=False ) - logging.debug(f'getting potg string') + logger.debug(f'getting potg string') tp = gs["top-players"][0] potg_string = f'{player_desc(tp["player"])} - ' if 'hr' in tp: @@ -2304,8 +2307,8 @@ class Gameplay(commands.Cog): inline=False ) - logging.info(f'potg: {potg_string}') - logging.debug(f'getting pitcher string') + logger.info(f'potg: {potg_string}') + logger.debug(f'getting pitcher string') pit_string = f'Win: {gs["pitchers"]["win"]["p_name"]}\n' \ f'Loss: {gs["pitchers"]["loss"]["p_name"]}\n' if gs['pitchers']['save'] is not None: @@ -2316,7 +2319,7 @@ class Gameplay(commands.Cog): ) def name_list(raw_list: list) -> str: - logging.info(f'raw_list: {raw_list}') + logger.info(f'raw_list: {raw_list}') player_dict = {} for x in raw_list: if x['player_id'] not in player_dict: @@ -2330,7 +2333,7 @@ class Gameplay(commands.Cog): data_dict[x['player_id']] += 1 r_string = '' - logging.info(f'players: {player_dict} / data: {data_dict}') + logger.info(f'players: {player_dict} / data: {data_dict}') first = True for p_id in data_dict: @@ -2341,7 +2344,7 @@ class Gameplay(commands.Cog): return r_string - logging.info(f'getting running string') + logger.info(f'getting running string') if len(gs['running']['sb']) + len(gs['running']['csc']) > 0: run_string = '' if len(gs['running']['sb']) > 0: @@ -2355,7 +2358,7 @@ class Gameplay(commands.Cog): value=run_string ) - logging.info(f'getting xbh string') + logger.info(f'getting xbh string') if len(gs['xbh']['2b']) + len(gs['xbh']['3b']) + len(gs['xbh']['hr']) > 0: bat_string = '' if len(gs['xbh']['2b']) > 0: @@ -2369,7 +2372,7 @@ class Gameplay(commands.Cog): else: bat_string = 'Oops! All bitches! No XBH from either team.' - logging.info(f'building embed') + logger.info(f'building embed') embed.add_field( name='Batting', value=bat_string, @@ -2388,7 +2391,7 @@ class Gameplay(commands.Cog): value=f'Please share the highlights in {get_channel(interaction, "pd-news-ticker").mention}!', inline=False ) - logging.info(f'sending scorebug') + logger.info(f'sending scorebug') await send_to_channel(self.bot, 'pd-network-news', embed=embed) # Gauntlet results and reward @@ -2413,7 +2416,7 @@ class Gameplay(commands.Cog): patch_game(this_game.id, active=False) - logging.info(f'Game {this_game.id} is complete') + logger.info(f'Game {this_game.id} is complete') if gauntlet_team is None: await interaction.channel.send( content=f'Good game! Go share the highlights in ' @@ -2441,32 +2444,32 @@ class Gameplay(commands.Cog): # # 'score': away_stats['p_lines'][0]['tm_runs'] # } # - # logging.debug(f'away_stats: {away_stats}\n\nhome_stats: {home_stats}') + # logger.debug(f'away_stats: {away_stats}\n\nhome_stats: {home_stats}') # # away_pitchers = await get_team_lineups( # this_game.id, team_id=away_team['id'], inc_inactive=True, pitchers_only=True, as_string=False # ) # for line in away_pitchers: # try: - # # logging.info(f'line: {line}') + # # logger.info(f'line: {line}') # this_stats = get_pitching_stats(this_game.id, lineup_id=line.id) - # # logging.info(f'away / this_stats: {this_stats}') + # # logger.info(f'away / this_stats: {this_stats}') # away_stats['p_lines'].extend(this_stats) # if 'score' not in home_stats: - # # logging.info(f'score not in home_stats') + # # logger.info(f'score not in home_stats') # home_stats['score'] = this_stats[0]['pl_runs'] # else: - # # logging.info(f'score is in home_stats') + # # logger.info(f'score is in home_stats') # home_stats['score'] += this_stats[0]['pl_runs'] # if 'hits' not in home_stats: - # # logging.info(f'hits not in home_stats') + # # logger.info(f'hits not in home_stats') # home_stats['hits'] = this_stats[0]['pl_hit'] # else: - # # logging.info(f'hits is in home_stats') + # # logger.info(f'hits is in home_stats') # home_stats['hits'] += this_stats[0]['pl_hit'] # except Exception as e: # bad_player = await get_player(this_game, line) - # logging.error(f'Unable to process stats for card_id {line.card_id} in Game {this_game.id}: ' + # logger.error(f'Unable to process stats for card_id {line.card_id} in Game {this_game.id}: ' # f'{type(e)}: {e}') # await interaction.edit_original_response( # content=f'I was not able to process stats for {bad_player["name"]} - ' @@ -2477,44 +2480,44 @@ class Gameplay(commands.Cog): # ) # for line in home_pitchers: # try: - # # logging.info(f'line: {line}') + # # logger.info(f'line: {line}') # this_stats = get_pitching_stats(this_game.id, lineup_id=line.id) - # # logging.info(f'home / this_stats: {this_stats}') + # # logger.info(f'home / this_stats: {this_stats}') # home_stats['p_lines'].extend(this_stats) # if 'score' not in away_stats: - # # logging.info(f'score not in away_stats') + # # logger.info(f'score not in away_stats') # away_stats['score'] = this_stats[0]['pl_runs'] # else: - # # logging.info(f'score is in away_stats') + # # logger.info(f'score is in away_stats') # away_stats['score'] += this_stats[0]['pl_runs'] # if 'hits' not in away_stats: - # # logging.info(f'hits not in away_stats') + # # logger.info(f'hits not in away_stats') # away_stats['hits'] = this_stats[0]['pl_hit'] # else: - # # logging.info(f'hits is in away_stats') + # # logger.info(f'hits is in away_stats') # away_stats['hits'] += this_stats[0]['pl_hit'] # except Exception as e: # bad_player = await get_player(this_game, line) - # logging.error(f'Unable to process stats for card_id {line.card_id} in Game {this_game.id}: ' + # logger.error(f'Unable to process stats for card_id {line.card_id} in Game {this_game.id}: ' # f'{type(e)}: {e}') # await interaction.edit_original_response( # content=f'I was not able to process stats for {bad_player["name"]} - ' # f'{get_cal_user(interaction).mention} help!' # ) # - # logging.debug(f'finished tallying pitcher stats') + # logger.debug(f'finished tallying pitcher stats') # # # away_stats['score'] = home_stats['p_lines'][0]['tm_runs'] # try: # decisions = get_pitching_decisions(this_game) # except AttributeError as e: - # logging.error(f'Could not pull decisions for Game {this_game.id}: {e}') + # logger.error(f'Could not pull decisions for Game {this_game.id}: {e}') # await interaction.edit_original_response( # content=f'I was not able to calculate the Winning and Losing Pitcher for this game. Is the game ' # f'ending early? {get_cal_user(interaction).mention} can probably help.' # ) # return - # logging.debug(f'decisions: {decisions}') + # logger.debug(f'decisions: {decisions}') # # winning_team = away_team if away_stats['score'] > home_stats['score'] else home_team # losing_team = away_team if away_stats['score'] < home_stats['score'] else home_team @@ -2531,11 +2534,11 @@ class Gameplay(commands.Cog): # else: # losing_team = owner_team # - # logging.debug(f'away_stats (in /endgame function)\n\n{away_stats}') - # logging.debug(f'home_stats (in /endgame function)\n\n{home_stats}') - # logging.debug(f'winning_team: {winning_team}\nlosing_team: {losing_team}') + # logger.debug(f'away_stats (in /endgame function)\n\n{away_stats}') + # logger.debug(f'home_stats (in /endgame function)\n\n{home_stats}') + # logger.debug(f'winning_team: {winning_team}\nlosing_team: {losing_team}') # - # logging.debug(f'Time to build statlines and submit the scorecard for this PD game!') + # logger.debug(f'Time to build statlines and submit the scorecard for this PD game!') # # Post result # success = await db_post( # 'results', @@ -2800,7 +2803,7 @@ class Gameplay(commands.Cog): # # patch_game(this_game.id, active=False) # - # logging.info(f'Game {this_game.id} is complete') + # logger.info(f'Game {this_game.id} is complete') # if gauntlet_team is None: # await interaction.edit_original_response( # content=f'Good game! Go share the highlights in ' @@ -2830,17 +2833,17 @@ class Gameplay(commands.Cog): return lineup_team = await get_game_team(this_game, interaction.user.id) - logging.debug(f'read_lineup_command - lineup_team: {lineup_team}') + logger.debug(f'read_lineup_command - lineup_team: {lineup_team}') if 'gauntlet' in this_game.game_type: lineup_team = await get_game_team(this_game, team_abbrev=f'Gauntlet-{lineup_team["abbrev"]}') if not lineup_team['id'] in [this_game.away_team_id, this_game.home_team_id]: - logging.info(f'{interaction.user.display_name} tried to run a command in Game {this_game.id} when they ' + logger.info(f'{interaction.user.display_name} tried to run a command in Game {this_game.id} when they ' f'aren\'t a GM in the game.') await interaction.edit_original_response(content='Bruh. Only GMs of the active teams can pull lineups.') return existing_lineups = await get_team_lineups(this_game.id, lineup_team['id'], as_string=False) - logging.debug(f'read_lineup_command - existing_lineups:\n{existing_lineups}') + logger.debug(f'read_lineup_command - existing_lineups:\n{existing_lineups}') if len(existing_lineups) > 1: await interaction.response.send_message( f'It looks like the {lineup_team["sname"]} already have a lineup. Run `/substitution` to make changes.' @@ -2927,13 +2930,13 @@ class Gameplay(commands.Cog): ) return - logging.debug(f'Setting lineup for {lineup_team["sname"]} in PD game') + logger.debug(f'Setting lineup for {lineup_team["sname"]} in PD game') post_lineups(all_lineups) try: await interaction.channel.send(content=None, embed=await self.initialize_play_plus_embed(this_game)) except IntegrityError as e: - logging.debug(f'Unable to pull game_state for game_id {this_game.id} until both lineups are in: {e}') + logger.debug(f'Unable to pull game_state for game_id {this_game.id} until both lineups are in: {e}') await interaction.response.send_message(f'Game state will be posted once both lineups are in') return @@ -3137,7 +3140,7 @@ class Gameplay(commands.Cog): if 'gauntlet' in this_game.game_type: owner_team = await get_game_team(this_game, team_abbrev=f'Gauntlet-{owner_team["abbrev"]}') if not owner_team['id'] in [this_game.away_team_id, this_game.home_team_id]: - logging.info(f'{interaction.user.display_name} tried to run a command in Game {this_game.id} when they ' + logger.info(f'{interaction.user.display_name} tried to run a command in Game {this_game.id} when they ' f'aren\'t a GM in the game.') await interaction.edit_original_response(content='Bruh. Only GMs of the active teams can log plays.') # return this_game, False, False @@ -3146,7 +3149,7 @@ class Gameplay(commands.Cog): if this_play is not None: # Allow specific commands to not rollback the play (e.g. /show-card) if this_play.locked and not block_rollback: - logging.info(f'{interaction.user.display_name} tried to run a command in Game {this_game.id} while the ' + logger.info(f'{interaction.user.display_name} tried to run a command in Game {this_game.id} while the ' f'play was locked.') undo_play(this_play.id) await interaction.edit_original_response( @@ -3156,7 +3159,7 @@ class Gameplay(commands.Cog): this_play = get_current_play(this_game.id) if not this_play.pitcher: - logging.info(f'{interaction.user.display_name} tried to run a command in Game {this_game.id} without a ' + logger.info(f'{interaction.user.display_name} tried to run a command in Game {this_game.id} without a ' f'pitcher in the lineup.') await interaction.edit_original_response(content=f'Please sub in a pitcher before logging a new play.') this_play = None @@ -3211,7 +3214,7 @@ class Gameplay(commands.Cog): curr_pitcher = get_one_lineup(this_game.id, team_id=ai_team['id'], position='P') pit_plays = get_plays(this_game.id, curr_pitcher.id) - logging.debug(f'pit_plays for sub in Game {this_game.id}: {pit_plays}') + logger.debug(f'pit_plays for sub in Game {this_game.id}: {pit_plays}') if pit_plays['count'] < 2: pitcher = await get_player(this_game, curr_pitcher) view = Confirm(responders=[interaction.user], timeout=60, label_type='yes') @@ -3233,7 +3236,7 @@ class Gameplay(commands.Cog): return # new_pitcher = await next_pitcher(this_play, ai_team, self.bot) - # logging.debug(f'new_pitcher: {new_pitcher}') + # logger.debug(f'new_pitcher: {new_pitcher}') # # this_lineup = { # 'game_id': this_game.id, @@ -3340,9 +3343,9 @@ class Gameplay(commands.Cog): ai_hint = f'*The runner will ' \ f'{ai_manager.uncapped_advance(lead_base, this_play.starting_outs)}*' - logging.debug(f'calling of embed') + logger.debug(f'calling of embed') await show_outfield_cards(interaction, this_play) - logging.debug(f'done with of embed') + logger.debug(f'done with of embed') view = Confirm(responders=[interaction.user], timeout=60, label_type='yes') question = await interaction.channel.send( f'Is {lead_runner["p_name"]} being sent {to_bases[lead_base]}?\n\n{ai_hint}', view=view @@ -3464,7 +3467,7 @@ class Gameplay(commands.Cog): else: await question.delete() - logging.debug(f'post process batter runner on_second_final: {this_play.on_second_final}') + logger.debug(f'post process batter runner on_second_final: {this_play.on_second_final}') complete_play(this_play.id, batter_to_base=batter_to_base) if single_type == 'uncapped': @@ -3487,7 +3490,7 @@ class Gameplay(commands.Cog): patch_play(this_play.id, locked=True) frame_result = dice.frame_plate_check(owner_team, this_game.id) - logging.info(f'Frame Result:\n{frame_result}') + logger.info(f'Frame Result:\n{frame_result}') await interaction.edit_original_response( content=None, embed=frame_result['embed'] @@ -3537,9 +3540,9 @@ class Gameplay(commands.Cog): ai_hint = f'*The runner will ' \ f'{this_manager.uncapped_advance(4, this_play.starting_outs)}*' - logging.debug(f'calling of embed') + logger.debug(f'calling of embed') await show_outfield_cards(interaction, this_play) - logging.debug(f'done with of embed') + logger.debug(f'done with of embed') runner_to_home = await get_player(this_game, this_play.on_first) view = Confirm(responders=[interaction.user], timeout=60, label_type='yes') @@ -4089,20 +4092,20 @@ class Gameplay(commands.Cog): patch_play(this_play.id, locked=False) try: - logging.debug(f'Undoing play {this_play.id} in Game {this_game.id}: Batter {this_play.batter}') + logger.debug(f'Undoing play {this_play.id} in Game {this_game.id}: Batter {this_play.batter}') undo_play(this_game.id) except AttributeError as e: - logging.error(f'Could not undo play {this_play.id} in game {this_game.id}') + logger.error(f'Could not undo play {this_play.id} in game {this_game.id}') try: last_completed = get_latest_play(this_game.id) - logging.debug(f'Undoing play {last_completed.id} in Game {this_game.id}') + logger.debug(f'Undoing play {last_completed.id} in Game {this_game.id}') undo_play(this_game.id) except AttributeError as e: - logging.error(f'Could not undo second play in game {this_game.id}') + logger.error(f'Could not undo second play in game {this_game.id}') latest_play = get_latest_play(this_game.id) - logging.debug(f'Latest completed play is Play {latest_play.id}; batter_to_base: {latest_play.batter_final}') + logger.debug(f'Latest completed play is Play {latest_play.id}; batter_to_base: {latest_play.batter_final}') undo_subs(this_game, latest_play.play_num) await interaction.edit_original_response( @@ -4213,12 +4216,12 @@ class Gameplay(commands.Cog): None if position.value != 'C' else 'PO'] ) question = await interaction.channel.send(f'What was the result of the play?', view=view) - logging.info(f'obc: {this_play.on_base_code}') + logger.info(f'obc: {this_play.on_base_code}') await view.wait() - logging.info(f'gameplay - view: {view} / view.value: {view.value}') + logger.info(f'gameplay - view: {view} / view.value: {view.value}') gb_type = view.value - logging.info(f'gameplay - gb_type: {gb_type}') + logger.info(f'gameplay - gb_type: {gb_type}') if not view.value: await question.edit('Okay, we can try this again later.') @@ -4240,7 +4243,7 @@ class Gameplay(commands.Cog): playing_in = False await question.delete() - logging.info(f'bot playing_in: {playing_in} / view.value: {view.value} / gb_type: {gb_type}') + logger.info(f'bot playing_in: {playing_in} / view.value: {view.value} / gb_type: {gb_type}') if gb_type == 'G1': if (not playing_in and this_play.on_base_code == 0) or \ @@ -4335,7 +4338,7 @@ class Gameplay(commands.Cog): batter_to_base = gb_result_3(this_play) else: - logging.info(f'no match; log out') + logger.info(f'no match; log out') patch_play(this_play.id, pa=1, ab=1, outs=1) advance_runners(this_play.id, 0) @@ -4433,12 +4436,12 @@ class Gameplay(commands.Cog): None if position.value != 'C' else 'PO'] ) question = await interaction.channel.send(f'What was the result of the play?', view=view) - logging.info(f'obc: {this_play.on_base_code}') + logger.info(f'obc: {this_play.on_base_code}') await view.wait() - logging.info(f'gameplay - view: {view} / view.value: {view.value}') + logger.info(f'gameplay - view: {view} / view.value: {view.value}') gb_type = view.value - logging.info(f'gameplay - gb_type: {gb_type}') + logger.info(f'gameplay - gb_type: {gb_type}') if not view.value: await question.edit('Okay, we can try this again later.') else: @@ -4567,7 +4570,7 @@ class Gameplay(commands.Cog): # defender = get_one_lineup( # this_game.id, team_id=this_play.pitcher.team_id, position=pos # ) - # logging.info(f'defender: {defender}') + # logger.info(f'defender: {defender}') # patch_play(this_play.id, defender_id=defender.id, error=1 if error_allowed != 'no-error' else 0, check_pos=pos) # # # Not hit and no error diff --git a/cogs/owner.py b/cogs/owner.py index cec2305..808d86c 100644 --- a/cogs/owner.py +++ b/cogs/owner.py @@ -8,12 +8,8 @@ from discord.ext import commands from discord.ext.commands import Greedy, Context from typing import Optional, Literal -date = f'{datetime.datetime.now().year}-{datetime.datetime.now().month}-{datetime.datetime.now().day}' -logging.basicConfig( - filename=f'logs/{date}.log', - format='%(asctime)s - %(levelname)s - %(message)s', - level=logging.WARNING -) + +logger = logging.getLogger('discord_app') class Owner(commands.Cog): @@ -25,7 +21,7 @@ class Owner(commands.Cog): async def load(self, ctx, *, cog: str): try: await self.bot.load_extension(f'cogs.{cog}') - logging.warning(f'Loaded {cog}') + logger.warning(f'Loaded {cog}') except Exception as e: await ctx.send(f'**ERROR:** {type(e).__name__} - {e}') else: @@ -36,7 +32,7 @@ class Owner(commands.Cog): async def unload(self, ctx, *, cog: str): try: await self.bot.unload_extension(f'cogs.{cog}') - logging.warning(f'Unloaded {cog}') + logger.warning(f'Unloaded {cog}') except Exception as e: await ctx.send(f'**ERROR:** {type(e).__name__} - {e}') else: @@ -47,9 +43,9 @@ class Owner(commands.Cog): async def reload(self, ctx, *, cog: str): try: await self.bot.unload_extension(f'cogs.{cog}') - logging.warning(f'Unloaded {cog}') + logger.warning(f'Unloaded {cog}') await self.bot.load_extension(f'cogs.{cog}') - logging.warning(f'Reloaded {cog}') + logger.warning(f'Reloaded {cog}') except Exception as e: await ctx.send(f'**ERROR:** {type(e).__name__} - {e}') else: @@ -63,14 +59,14 @@ class Owner(commands.Cog): for x in cogs: try: await self.bot.unload_extension(f'cogs.{x}') - logging.warning(f'Unloaded {x}') + logger.warning(f'Unloaded {x}') except Exception as e: await ctx.send(f'Failed to unload **{x}**') for x in cogs: try: await self.bot.load_extension(f'cogs.{x}') - logging.warning(f'Loaded {x}') + logger.warning(f'Loaded {x}') except Exception as e: await ctx.send(f'Failed to load **{x}**') @@ -86,9 +82,9 @@ class Owner(commands.Cog): # sync = await self.bot.tree.sync() # else: # sync = await self.bot.tree.sync(guild=discord.Object(os.environ.get('GUILD_ID'))) - # logging.warning(f'sync: {sync}') + # logger.warning(f'sync: {sync}') # except Exception as e: - # logging.error(f'failed to sync: {e}') + # logger.error(f'failed to sync: {e}') # # await ctx.send(f'Just ran the sync. Here is the output:\n{sync}') @@ -101,7 +97,7 @@ class Owner(commands.Cog): !sync * -> copies all global app commands to current guild and syncs !sync id_1 id_2 -> syncs guilds with id 1 and 2 """ - logging.info(f'{ctx.author.name} has initiated a sync from guild ID {ctx.guild.id}') + logger.info(f'{ctx.author.name} has initiated a sync from guild ID {ctx.guild.id}') if not guilds: if spec == "~": fmt = await ctx.bot.tree.sync(guild=ctx.guild) diff --git a/cogs/players.py b/cogs/players.py index 310c6f1..9288955 100644 --- a/cogs/players.py +++ b/cogs/players.py @@ -31,12 +31,7 @@ from helpers import PD_PLAYERS_ROLE_NAME, IMAGES, PD_SEASON, random_conf_gif, fu team_summary_embed, SelectView, SelectPaperdexCardset, SelectPaperdexTeam -# date = f'{datetime.datetime.now().year}-{datetime.datetime.now().month}-{datetime.datetime.now().day}' -# logging.basicConfig( -# filename=f'logs/{date}.log', -# format='%(asctime)s - %(levelname)s - %(message)s', -# level=logging.WARNING -# ) +logger = logging.getLogger('discord_app') def get_ai_records(short_games, long_games): @@ -133,7 +128,7 @@ def get_ai_records(short_games, long_games): 'major': {'w': 0, 'l': 0, 'rd': 0, 'points': 0}, 'hof': {'w': 0, 'l': 0, 'rd': 0, 'points': 0}}, } - logging.debug(f'running short games...') + logger.debug(f'running short games...') for line in short_games: home_win = True if line['home_score'] > line['away_score'] else False @@ -147,9 +142,9 @@ def get_ai_records(short_games, long_games): all_results[line['home_team']['abbrev']]['short']['l'] += 1 if home_win else 0 all_results[line['home_team']['abbrev']]['short']['points'] += 2 if not home_win else 1 all_results[line['home_team']['abbrev']]['short']['rd'] += line['away_score'] - line['home_score'] - logging.debug(f'done short games') + logger.debug(f'done short games') - logging.debug(f'running league games...') + logger.debug(f'running league games...') league = {None: 'minor', 'minor-league': 'minor', 'major-league': 'major', 'hall-of-fame': 'hof'} for line in long_games: home_win = True if line['home_score'] > line['away_score'] else False @@ -166,7 +161,7 @@ def get_ai_records(short_games, long_games): all_results[line['home_team']['abbrev']][league[line['game_type']]]['points'] += 2 if not home_win else 1 all_results[line['home_team']['abbrev']][league[line['game_type']]]['rd'] += \ line['away_score'] - line['home_score'] - logging.debug(f'done league games') + logger.debug(f'done league games') return all_results @@ -306,7 +301,7 @@ class Players(commands.Cog): async def weekly_loop(self): current = await db_get('current') now = datetime.datetime.now() - logging.debug(f'Datetime: {now} / weekday: {now.weekday()}') + logger.debug(f'Datetime: {now} / weekday: {now.weekday()}') # Begin Freeze # if now.weekday() == 0 and now.hour == 5: # Spring/Summer @@ -333,10 +328,10 @@ class Players(commands.Cog): [self.player_list.append(x['p_name'].lower()) for x in all_players['players'] if x['p_name'].lower() not in self.player_list] - logging.info(f'There are now {len(self.player_list)} player names in the fuzzy search list.') + logger.info(f'There are now {len(self.player_list)} player names in the fuzzy search list.') self.cardset_list = [x['name'].lower() for x in all_cardsets['cardsets']] - logging.info(f'There are now {len(self.cardset_list)} cardsets in the fuzzy search list.') + logger.info(f'There are now {len(self.cardset_list)} cardsets in the fuzzy search list.') @build_player_list.before_loop async def before_player_list(self): @@ -352,7 +347,7 @@ class Players(commands.Cog): # weekly_games = Result.select_season(current.season).where( # (Result.week == current.week) & (Result.game_type == "baseball") # ) - # logging.info(f'weekly_games: {weekly_games}') + # logger.info(f'weekly_games: {weekly_games}') # # if weekly_games.count() == 0: # return None @@ -398,7 +393,7 @@ class Players(commands.Cog): # for team in records: # standings_message += f'**{count}**: {team[3].sname} - {team[1]:.0f} Pts ({team[0]["w"]}-{team[0]["l"]})\n' # if count % 24 == 0 or count >= len(records): - # logging.info(f'standings_message: {standings_message}') + # logger.info(f'standings_message: {standings_message}') # all_embeds[embed_count].add_field(name='Standings', value=standings_message) # all_embeds[embed_count].set_thumbnail(url=self.logo) # @@ -482,7 +477,7 @@ class Players(commands.Cog): all_embeds = [] for x in all_cards: all_embeds.extend(await get_card_embeds(x, include_stats=True)) - logging.debug(f'embeds: {all_embeds}') + logger.debug(f'embeds: {all_embeds}') if len(all_embeds) > 1: await interaction.edit_original_response(content=f'# {all_players["players"][0]["p_name"]}') @@ -827,9 +822,9 @@ class Players(commands.Cog): all_records[line['home_team']['id']]['losses'] += 1 if not home_win else 0 all_records[line['home_team']['id']]['points'] += 2 if home_win else 0 - # logging.info(f'all_records:\n\n{all_records}') + # logger.info(f'all_records:\n\n{all_records}') sorted_records = sorted(all_records.items(), key=lambda k_v: k_v[1]['points'], reverse=True) - # logging.info(f'sorted_records: {sorted_records}') + # logger.info(f'sorted_records: {sorted_records}') # await ctx.send(f'sorted: {sorted_records}') embed = get_team_embed( @@ -839,14 +834,14 @@ class Players(commands.Cog): chunk_string = '' for index, record in enumerate(sorted_records): - # logging.info(f'index: {index} / record: {record}') + # logger.info(f'index: {index} / record: {record}') team = await db_get('teams', object_id=record[0]) if team: chunk_string += f'{record[1]["points"]} pt{"s" if record[1]["points"] != 1 else ""} ' \ f'({record[1]["wins"]}-{record[1]["losses"]}) - {team["sname"]} [{team["ranking"]}]\n' else: - logging.error(f'Could not find team {record[0]} when running standings.') + logger.error(f'Could not find team {record[0]} when running standings.') if (index + 1) == len(sorted_records): embed.add_field( @@ -879,11 +874,11 @@ class Players(commands.Cog): # Pull data from Sheets async with ctx.typing(): roster_data = get_rosters(team, self.bot) - logging.debug(f'roster_data: {roster_data}') + logger.debug(f'roster_data: {roster_data}') # Post roster team/card ids and throw error if db says no for index, roster in enumerate(roster_data): - logging.debug(f'index: {index} / roster: {roster}') + logger.debug(f'index: {index} / roster: {roster}') if (not specific_roster_num or specific_roster_num == index + 1) and roster: this_roster = await db_post( 'rosters', @@ -983,7 +978,7 @@ class Players(commands.Cog): except ZeroDivisionError as e: return except Exception as e: - logging.error(f'Failed to run {event_name} draft for the {main_team["sname"]}: {e}') + logger.error(f'Failed to run {event_name} draft for the {main_team["sname"]}: {e}') draft_team = await db_get('teams', params=[('abbrev', f'Gauntlet-{main_team["abbrev"]}')]) await gauntlets.wipe_team(draft_team, interaction) await interaction.channel.send( @@ -1124,7 +1119,7 @@ class Players(commands.Cog): # # rar_res = Rarity.get(Rarity.name == 'Reserve') # # rar_rpl = Rarity.get(Rarity.name == 'Replacement') # # except Exception as e: - # # logging.error(f'**Error**: (players inv getrars) - {e}') + # # logger.error(f'**Error**: (players inv getrars) - {e}') # # return # # all_embeds = [ @@ -1192,7 +1187,7 @@ class Players(commands.Cog): # await ctx.send('Alright, let me go open that Sheet...') # scorecard = self.sheets.open_by_url(scorecard_url).worksheet_by_title('Results') # except Exception as e: - # logging.error(f'Unable to access sheet ({scorecard_url}) submitted by {ctx.author.name}') + # logger.error(f'Unable to access sheet ({scorecard_url}) submitted by {ctx.author.name}') # await ctx.message.add_reaction('❌') # await ctx.send(f'{ctx.message.author.mention}, I can\'t access that sheet.') # return @@ -1201,7 +1196,7 @@ class Players(commands.Cog): # try: # awayteam = Team.get_season(awayabbrev) # hometeam = Team.get_season(homeabbrev) - # logging.info(f'Final: {awayabbrev} {awayscore} - {homescore} {homeabbrev}') + # logger.info(f'Final: {awayabbrev} {awayscore} - {homescore} {homeabbrev}') # if awayteam == hometeam: # await ctx.message.add_reaction('❌') # await helpers.send_to_news( @@ -1212,7 +1207,7 @@ class Players(commands.Cog): # return # except Exception as e: # error = f'**ERROR:** {type(e).__name__} - {e}' - # logging.error(error) + # logger.error(error) # await ctx.message.add_reaction('❌') # await ctx.send(f'Hey, {ctx.author.mention}, I couldn\'t find the teams you mentioned. You put ' # f'**{awayabbrev}** as the away team and **{homeabbrev}** as the home team.') @@ -1280,7 +1275,7 @@ class Players(commands.Cog): # ) # await ctx.message.add_reaction('✅') # - # logging.info('Checking for credit') + # logger.info('Checking for credit') # # Credit pack for win # economy = self.bot.get_cog('Economy') # if awayscore > homescore: @@ -1293,19 +1288,19 @@ class Players(commands.Cog): # # Check values and distribute earnings # if awayteam.team_value - hometeam.team_value <= 12: # earnings['away'] = '1 Premium Pack' - # logging.info(f'{awayteam.sname} earns 1 Premium pack for the win') + # logger.info(f'{awayteam.sname} earns 1 Premium pack for the win') # economy.give_pack(awayteam, 1, 'Premium') # else: - # logging.info(f'{awayteam.sname} earns nothing for the win - team value {awayteam.team_value} vs ' + # logger.info(f'{awayteam.sname} earns nothing for the win - team value {awayteam.team_value} vs ' # f'{hometeam.team_value}') # earnings['away'] = f'None - Team was {awayteam.team_value - hometeam.team_value} points higher' # # if hometeam.team_value - awayteam.team_value <= 12: # earnings['home'] = '1 Standard Pack' - # logging.info(f'{hometeam.sname} earns 1 Standard pack for the loss') + # logger.info(f'{hometeam.sname} earns 1 Standard pack for the loss') # economy.give_pack(hometeam, 1) # else: - # logging.info(f'{hometeam.sname} earns nothing for the loss - team value {hometeam.team_value} vs ' + # logger.info(f'{hometeam.sname} earns nothing for the loss - team value {hometeam.team_value} vs ' # f'{awayteam.team_value}') # earnings['home'] = f'None - Team was {hometeam.team_value - awayteam.team_value} points higher' # else: @@ -1317,19 +1312,19 @@ class Players(commands.Cog): # # Check values and distribute earnings # if hometeam.team_value - awayteam.team_value <= 12: # earnings['home'] = '1 Premium Pack' - # logging.info(f'{hometeam.sname} earns 1 Premium pack for the win') + # logger.info(f'{hometeam.sname} earns 1 Premium pack for the win') # economy.give_pack(hometeam, 1, 'Premium') # else: - # logging.info(f'{hometeam.sname} earns nothing for the win - team value {hometeam.team_value} vs ' + # logger.info(f'{hometeam.sname} earns nothing for the win - team value {hometeam.team_value} vs ' # f'{awayteam.team_value}') # earnings['home'] = f'None - Team was {hometeam.team_value - awayteam.team_value} points higher' # # if awayteam.team_value - hometeam.team_value <= 12: # earnings['away'] = '1 Standard Pack' - # logging.info(f'{awayteam.sname} earns 1 Standard pack for the loss') + # logger.info(f'{awayteam.sname} earns 1 Standard pack for the loss') # economy.give_pack(awayteam, 1) # else: - # logging.info(f'{awayteam.sname} earns nothing for the loss - team value {awayteam.team_value} vs ' + # logger.info(f'{awayteam.sname} earns nothing for the loss - team value {awayteam.team_value} vs ' # f'{hometeam.team_value}') # earnings['away'] = f'None - Team was {awayteam.team_value - hometeam.team_value} points higher' # @@ -1342,20 +1337,20 @@ class Players(commands.Cog): # # delta = away_team_value - home_team_value # # if delta < 0: # # increments = divmod(-delta, helpers.TEAM_DELTA_CONSTANT) - # # # logging.info(f'increments: {increments}') + # # # logger.info(f'increments: {increments}') # # packs = min(increments[0], 5) # # if packs > 0: # # earnings['away'] += packs # # earnings_away.append(f'- {packs} pack{"s" if packs > 1 else ""} for underdog\n') # # else: # # increments = divmod(delta, helpers.TEAM_DELTA_CONSTANT) - # # # logging.info(f'increments: {increments}') + # # # logger.info(f'increments: {increments}') # # packs = min(increments[0], 5) # # if packs > 0: # # earnings['home'] += packs # # earnings_home.append(f'- {packs} pack{"s" if packs > 1 else ""} for underdog\n') # - # # logging.info(f'earn away: {earnings["away"]} / earn home: {earnings["home"]}') + # # logger.info(f'earn away: {earnings["away"]} / earn home: {earnings["home"]}') # # away_packs_remaining = Current.get_by_id(1).packlimit - awayteam.weeklypacks # # home_packs_remaining = Current.get_by_id(1).packlimit - hometeam.weeklypacks # # away_final_earnings = earnings["away"] if away_packs_remaining >= earnings["away"] else max(away_packs_remaining, 0) @@ -1365,12 +1360,12 @@ class Players(commands.Cog): # # # economy = self.bot.get_cog('Economy') # # if away_final_earnings > 0: - # # logging.info(f'away_final_earnings: {away_final_earnings}') + # # logger.info(f'away_final_earnings: {away_final_earnings}') # # economy.give_pack(awayteam, away_final_earnings, True) # # else: # # away_final_earnings = 0 # # if home_final_earnings > 0: - # # logging.info(f'home_final_earnings: {home_final_earnings}') + # # logger.info(f'home_final_earnings: {home_final_earnings}') # # economy.give_pack(hometeam, home_final_earnings, True) # # else: # # home_final_earnings = 0 @@ -1643,11 +1638,11 @@ class Players(commands.Cog): if resp.status_code == 200: return resp.json() else: - logging.warning(resp.text) + logger.warning(resp.text) raise ValueError(f'DB: {resp.text}') this_player = await get_one_player(player_name) - logging.debug(f'this_player: {this_player}') + logger.debug(f'this_player: {this_player}') @app_commands.command(name='matchup', description='Simulate a matchup between a pitcher and batter') @app_commands.describe( diff --git a/command_logic/logic_gameplay.py b/command_logic/logic_gameplay.py index 3d07f36..b88fce6 100644 --- a/command_logic/logic_gameplay.py +++ b/command_logic/logic_gameplay.py @@ -7,17 +7,19 @@ from sqlmodel import Session, select, func from sqlalchemy import delete from typing import Literal +from api_calls import db_delete, db_get, db_post from exceptions import * -from helpers import DEFENSE_LITERAL +from helpers import DEFENSE_LITERAL, get_channel from in_game.game_helpers import legal_check from in_game.gameplay_models import Game, Lineup, Team, Play -from in_game.gameplay_queries import get_card_or_none, get_channel_game_or_none, get_last_team_play, get_one_lineup, get_sorted_lineups, get_team_or_none, get_players_last_pa +from in_game.gameplay_queries import get_card_or_none, get_channel_game_or_none, get_db_ready_decisions, get_db_ready_plays, 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 from utilities.buttons import ButtonOptions, Confirm, ask_confirm from utilities.dropdown import DropdownOptions, DropdownView, SelectViewDefense from utilities.embeds import image_embed from utilities.pages import Pagination +logger = logging.getLogger('discord_app') WPA_DF = pd.read_csv(f'storage/wpa_data.csv').set_index('index') @@ -78,13 +80,21 @@ def get_wpa(this_play: Play, next_play: Play): elif old_rd < -6: old_rd = -6 - new_win_ex = WPA_DF.loc[f'{next_play.inning_half}_{next_play.inning_num}_{next_play.starting_outs}_out_{next_play.on_base_code}_obc_{new_rd}_home_run_diff'].home_win_ex + # print(f'get_wpa: new_rd = {new_rd} / old_rd = {old_rd}') + if (next_play.inning_num >= 9 and new_rd > 0 and next_play.inning_half == 'bot') or (next_play.inning_num > 9 and new_rd > 0 and next_play.is_new_inning): + # print(f'manually setting new_win_ex to 1.0') + new_win_ex = 1.0 + else: + new_win_ex = WPA_DF.loc[f'{next_play.inning_half}_{next_play.inning_num}_{next_play.starting_outs}_out_{next_play.on_base_code}_obc_{new_rd}_home_run_diff'].home_win_ex + # print(f'new_win_ex = {new_win_ex}') old_win_ex = WPA_DF.loc[f'{this_play.inning_half}_{this_play.inning_num}_{this_play.starting_outs}_out_{this_play.on_base_code}_obc_{old_rd}_home_run_diff'].home_win_ex + # print(f'old_win_ex = {old_win_ex}') - wpa = round(new_win_ex - old_win_ex, 3) + wpa = float(round(new_win_ex - old_win_ex, 3)) + # print(f'final wpa: {wpa}') if this_play.inning_half == 'top': - return wpa * -1 + return wpa * -1.0 return wpa @@ -110,7 +120,7 @@ def complete_play(session:Session, this_play: Play): opponent_play = get_last_team_play(session, this_play.game, this_play.pitcher.team) nbo = opponent_play.batting_order + 1 except PlayNotFoundException as e: - logging.info(f'logic_gameplay - complete_play - No last play found for {this_play.pitcher.team.sname}, setting upcoming batting order to 1') + logger.info(f'logic_gameplay - complete_play - No last play found for {this_play.pitcher.team.sname}, setting upcoming batting order to 1') nbo = 1 finally: new_batter_team = this_play.game.away_team if nih == 'top' else this_play.game.home_team @@ -149,14 +159,14 @@ def complete_play(session:Session, this_play: Play): home_score = this_play.home_score if runs_scored > 0 and this_play.away_score <= this_play.home_score and away_score > home_score: - is_go_ahead = True + this_play.is_go_ahead = True else: away_score = this_play.away_score home_score = this_play.home_score + runs_scored if runs_scored > 0 and this_play.home_score <= this_play.away_score and home_score > away_score: - is_go_ahead = True + this_play.is_go_ahead = True obc = get_obc(on_first, on_second, on_third) @@ -183,7 +193,6 @@ def complete_play(session:Session, this_play: Play): catcher=get_one_lineup(session, this_play.game, new_pitcher_team, position='C'), is_new_inning=switch_sides, is_tied=away_score == home_score, - is_go_ahead=is_go_ahead, on_first=on_first, on_second=on_second, on_third=on_third, @@ -203,13 +212,13 @@ def complete_play(session:Session, this_play: Play): async def get_lineups_from_sheets(session: Session, sheets, this_game: Game, this_team: Team, lineup_num: int, roster_num: int) -> list[Lineup]: - logging.debug(f'sheets: {sheets}') + logger.debug(f'sheets: {sheets}') this_sheet = sheets.open_by_key(this_team.gsheet) - logging.debug(f'this_sheet: {this_sheet}') + logger.debug(f'this_sheet: {this_sheet}') r_sheet = this_sheet.worksheet_by_title('My Rosters') - logging.debug(f'r_sheet: {r_sheet}') + logger.debug(f'r_sheet: {r_sheet}') if lineup_num == 1: row_start = 9 @@ -225,15 +234,15 @@ async def get_lineups_from_sheets(session: Session, sheets, this_game: Game, thi else: l_range = f'L{row_start}:M{row_end}' - logging.debug(f'l_range: {l_range}') + logger.debug(f'l_range: {l_range}') raw_cells = r_sheet.range(l_range) - logging.debug(f'raw_cells: {raw_cells}') + logger.debug(f'raw_cells: {raw_cells}') try: lineup_cells = [(row[0].value, int(row[1].value)) for row in raw_cells] - logging.debug(f'lineup_cells: {lineup_cells}') + logger.debug(f'lineup_cells: {lineup_cells}') except ValueError as e: - logging.error(f'Could not pull roster for {this_team.abbrev}: {e}') + logger.error(f'Could not pull roster for {this_team.abbrev}: {e}') raise ValueError(f'Uh oh. Looks like your roster might not be saved. I am reading blanks when I try to get the card IDs') all_lineups = [] @@ -269,7 +278,7 @@ async def get_lineups_from_sheets(session: Session, sheets, this_game: Game, thi all_lineups.append(this_lineup) legal_data = await legal_check([card_ids], difficulty_name=this_game.game_type) - logging.debug(f'legal_data: {legal_data}') + logger.debug(f'legal_data: {legal_data}') if not legal_data['legal']: raise CardLegalityException(f'The following cards appear to be illegal for this game mode:\n{legal_data["error_string"]}') @@ -290,26 +299,26 @@ async def checks_log_interaction(session: Session, interaction: discord.Interact owner_team = await get_team_or_none(session, gm_id=interaction.user.id) if owner_team is None: - logging.exception(f'{command_name} command: No team found for GM ID {interaction.user.id}') + logger.exception(f'{command_name} command: No team found for GM ID {interaction.user.id}') raise TeamNotFoundException(f'Do I know you? I cannot find your team.') if 'gauntlet' in this_game.game_type: gauntlet_abbrev = f'Gauntlet-{owner_team.abbrev}' owner_team = await get_team_or_none(session, team_abbrev=gauntlet_abbrev) if owner_team is None: - logging.exception(f'{command_name} command: No gauntlet team found with abbrev {gauntlet_abbrev}') + logger.exception(f'{command_name} command: No gauntlet team found with abbrev {gauntlet_abbrev}') raise TeamNotFoundException(f'Hm, I was not able to find a gauntlet team for you.') if not owner_team.id in [this_game.away_team_id, this_game.home_team_id]: if interaction.user.id != 258104532423147520: - logging.exception(f'{interaction.user.display_name} tried to run a command in Game {this_game.id} when they aren\'t a GM in the game.') + logger.exception(f'{interaction.user.display_name} tried to run a command in Game {this_game.id} when they aren\'t a GM in the game.') raise TeamNotFoundException('Bruh. Only GMs of the active teams can log plays.') else: await interaction.channel.send(f'Cal is bypassing the GM check to run the {command_name} command') this_play = this_game.current_play_or_none(session) if this_play is None: - logging.error(f'{command_name} command: No play found for Game ID {this_game.id} - attempting to initialize play') + logger.error(f'{command_name} command: No play found for Game ID {this_game.id} - attempting to initialize play') this_play = activate_last_play(session, this_game) this_play.locked = True @@ -346,6 +355,7 @@ def advance_runners(session: Session, this_play: Play, num_bases: int, is_error: """ No commits """ + logger.info(f'Advancing runners {num_bases} bases in game {this_play.game.id}') this_play.rbi = 0 if num_bases == 0: @@ -362,8 +372,7 @@ def advance_runners(session: Session, this_play: Play, num_bases: int, is_error: this_play.on_second_final = 2 if this_play.on_third: this_play.on_third_final = 3 - return - + if this_play.on_second: if this_play.on_third: if num_bases > 0: @@ -433,7 +442,7 @@ async def show_outfield_cards(session: Session, interaction: discord.Interaction cf = get_one_lineup(session, this_game=this_play.game, this_team=this_play.pitcher.team, position='CF') rf = get_one_lineup(session, this_game=this_play.game, this_team=this_play.pitcher.team, position='RF') this_team = this_play.pitcher.team - logging.debug(f'lf: {lf.player.name_with_desc}\n\ncf: {cf.player.name_with_desc}\n\nrf: {rf.player.name_with_desc}\n\nteam: {this_team.lname}') + logger.debug(f'lf: {lf.player.name_with_desc}\n\ncf: {cf.player.name_with_desc}\n\nrf: {rf.player.name_with_desc}\n\nteam: {this_team.lname}') view = Pagination([interaction.user], timeout=10) view.left_button.label = f'Left Fielder' @@ -537,9 +546,9 @@ async def flyballs(session: Session, interaction: discord.Interaction, this_play log_run_scored(session, this_play.on_third, this_play) if this_play.starting_outs < 2 and this_play.on_second: - logging.debug(f'calling of embed') + logger.debug(f'calling of embed') await show_outfield_cards(session, interaction, this_play) - logging.debug(f'done with of embed') + logger.debug(f'done with of embed') runner = this_play.on_second.player view = Confirm(responders=[interaction.user], timeout=60, label_type='yes') @@ -585,9 +594,9 @@ async def flyballs(session: Session, interaction: discord.Interaction, this_play this_play.pa, this_play.ab, this_play.outs = 1, 1, 1 if this_play.starting_outs < 2 and this_play.on_third: - logging.debug(f'calling of embed') + logger.debug(f'calling of embed') await show_outfield_cards(session, interaction, this_play) - logging.debug(f'done with of embed') + logger.debug(f'done with of embed') runner = this_play.on_second.player view = Confirm(responders=[interaction.user], timeout=60, label_type='yes') @@ -641,7 +650,7 @@ async def flyballs(session: Session, interaction: discord.Interaction, this_play async def check_uncapped_advance(session: Session, interaction: discord.Interaction, this_play: Play, lead_runner: Lineup, lead_base: int, trail_runner: Lineup, trail_base: int): this_game = this_play.game outfielder = await show_outfield_cards(session, interaction, this_play) - logging.info(f'throw from {outfielder.player.name_with_desc}') + logger.info(f'throw from {outfielder.player.name_with_desc}') def_team = this_play.pitcher.team TO_BASE = { 2: 'to second', @@ -666,7 +675,7 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact throw_resp = None if this_game.ai_team: throw_resp = this_play.managerai.throw_at_uncapped(session, this_game) - logging.info(f'throw_resp: {throw_resp}') + logger.info(f'throw_resp: {throw_resp}') if throw_resp.cutoff: await interaction.channel.send(f'The {def_team.sname} will cut off the throw {TO_BASE[lead_base]}') @@ -791,18 +800,18 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact # Lead runner is thrown out if runner_thrown_out: - logging.info(f'Lead runner is thrown out.') + logger.info(f'Lead runner is thrown out.') this_play.outs += 1 # Lead runner is safe else: - logging.info(f'Lead runner is safe.') + logger.info(f'Lead runner is safe.') if this_play.on_second == lead_runner: - logging.info(f'setting lead runner on_second_final') + logger.info(f'setting lead runner on_second_final') this_play.on_second_final = None if runner_thrown_out else lead_base elif this_play.on_first == lead_runner: - logging.info(f'setting lead runner on_first') + logger.info(f'setting lead runner on_first') this_play.on_first_final = None if runner_thrown_out else lead_base else: log_exception(LineupsMissingException, f'Could not find lead runner to set final destination') @@ -904,14 +913,14 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact # Lead runner is thrown out if is_lead_out: - logging.info(f'Lead runner is thrown out.') + logger.info(f'Lead runner is thrown out.') this_play.outs += 1 if this_play.on_second == lead_runner: - logging.info(f'setting lead runner on_second_final') + logger.info(f'setting lead runner on_second_final') this_play.on_second_final = None if is_lead_out else lead_base elif this_play.on_first == lead_runner: - logging.info(f'setting lead runner on_first') + logger.info(f'setting lead runner on_first') this_play.on_first_final = None if is_lead_out else lead_base else: log_exception(LineupsMissingException, f'Could not find lead runner to set final destination') @@ -1003,9 +1012,10 @@ async def triples(session: Session, interaction: discord.Interaction, this_play: async def homeruns(session: Session, interaction: discord.Interaction, this_play: Play, homerun_type: Literal['ballpark', 'no-doubt']): - this_play.hit, this_play.homerun, this_play.batter_final, this_play.rbi, this_play.run = 1, 1, 4, 1, 1 + this_play.hit, this_play.homerun, this_play.batter_final, this_play.run = 1, 1, 4, 1 this_play.bphr = 1 if homerun_type == 'ballpark' else 0 this_play = advance_runners(session, this_play, num_bases=4) + this_play.rbi += 1 session.add(this_play) session.commit() @@ -1098,16 +1108,16 @@ def undo_play(session: Session, this_play: Play): session.add(last_pa) last_two_ids = [last_two_plays[0].id, last_two_plays[1].id] - logging.warning(f'Deleting plays: {last_two_ids}') + logger.warning(f'Deleting plays: {last_two_ids}') session.exec(delete(Play).where(Play.id.in_(last_two_ids))) session.commit() try: this_play = this_game.initialize_play(session) - logging.info(f'Initialized play: {this_play.id}') + logger.info(f'Initialized play: {this_play.id}') except PlayInitException: this_play = activate_last_play(session, this_game) - logging.info(f'Re-activated play: {this_play.id}') + logger.info(f'Re-activated play: {this_play.id}') return this_play @@ -1149,4 +1159,304 @@ async def show_defense_cards(session: Session, interaction: discord.Interaction, await interaction.edit_original_response(content=None, embed=player_embed, view=dropdown_view) - \ No newline at end of file + +def is_game_over(this_play: Play) -> bool: + print(f'1: ') + if this_play.inning_num < 9 and (abs(this_play.away_score - this_play.home_score) < 10): + return False + + if abs(this_play.away_score - this_play.home_score) >= 10: + if ((this_play.home_score - this_play.away_score) >= 10) and this_play.inning_half == 'bot': + return True + + elif ((this_play.away_score - this_play.home_score) >= 10) and this_play.is_new_inning and this_play.inning_half == 'top': + return True + + if this_play.inning_num > 9 and this_play.inning_half == 'top' and this_play.is_new_inning and this_play.home_score != this_play.away_score: + return True + + if this_play.inning_num >= 9 and this_play.inning_half == 'bot' and this_play.home_score > this_play.away_score: + return True + + return False + + +async def get_game_summary_embed(session: Session, interaction: discord.Interaction, this_play: Play, db_game_id: int, winning_team: Team, losing_team: Team, num_potg: int = 1, num_poop: int = 0): + game_summary = await db_get(f'plays/game-summary/{db_game_id}', params=[('tp_max', num_potg)]) + this_game = this_play.game + + game_embed = winning_team.embed + game_embed.title = f'{this_game.away_team.lname} {this_play.away_score} @ {this_play.home_score} {this_game.home_team.lname} - F/{this_play.inning_num}' + game_embed.add_field( + name='Location', + value=f'{interaction.guild.get_channel(this_game.channel_id).mention}' + ) + game_embed.add_field(name='Game ID', value=f'{db_game_id}') + + if this_game.game_type == 'major-league': + game_des = 'Major League' + elif this_game.game_type == 'minor-league': + game_des = 'Minor League' + elif this_game.game_type == 'hall-of-fame': + game_des = 'Hall of Fame' + elif this_game.game_type == 'flashback': + game_des = 'Flashback' + elif this_game.ranked: + game_des = 'Ranked' + elif 'gauntlet' in this_game.game_type: + game_des = 'Gauntlet' + else: + game_des = 'Unlimited' + + game_embed.description = f'Score Report - {game_des}' + game_embed.add_field( + name='Box Score', + value=f'```\n' + f'Team | R | H | E |\n' + f'{this_game.away_team.abbrev.replace("Gauntlet-", ""): <4} | {game_summary["runs"]["away"]: >2} | ' + f'{game_summary["hits"]["away"]: >2} | {game_summary["errors"]["away"]: >2} |\n' + f'{this_game.home_team.abbrev.replace("Gauntlet-", ""): <4} | {game_summary["runs"]["home"]: >2} | ' + f'{game_summary["hits"]["home"]: >2} | {game_summary["errors"]["home"]: >2} |\n' + f'\n```', + inline=False + ) + + logger.info(f'getting top players string') + potg_string = '' + for tp in game_summary['top-players']: + player_name = f'{get_player_name_from_dict(tp['player'])}' + potg_line = f'{player_name} - ' + if 'hr' in tp: + potg_line += f'{tp["hit"]}-{tp["ab"]}' + if tp['hr'] > 0: + num = f'{tp["hr"]} ' if tp["hr"] > 1 else "" + potg_line += f', {num}HR' + if tp['triple'] > 0: + num = f'{tp["triple"]} ' if tp["triple"] > 1 else "" + potg_line += f', {num}3B' + if tp['double'] > 0: + num = f'{tp["double"]} ' if tp["double"] > 1 else "" + potg_line += f', {num}2B' + if tp['run'] > 0: + potg_line += f', {tp["run"]} R' + if tp['rbi'] > 0: + potg_line += f', {tp["rbi"]} RBI' + else: + potg_line = f'{player_name} - {tp["ip"]} IP, {tp["run"]} R' + if tp['run'] != tp['e_run']: + potg_line += f' ({tp["e_run"]} ER)' + potg_line += f', {tp["hit"]} H, {tp["so"]} K' + potg_line += f', {tp["re24"]:.2f} re24\n' + potg_string += potg_line + + game_embed.add_field( + name='Players of the Game', + value=potg_string, + inline=False + ) + + pit_string = f'Win: {game_summary["pitchers"]["win"]["p_name"]}\nLoss: {game_summary["pitchers"]["loss"]["p_name"]}\n' + + hold_string = None + for player in game_summary['pitchers']['holds']: + player_name = f'{get_player_name_from_dict(player)}' + if hold_string is None: + hold_string = f'Holds: {player_name}' + else: + hold_string += f', {player_name}' + if hold_string is not None: + pit_string += f'{hold_string}\n' + + if game_summary['pitchers']['save'] is not None: + player_name = f'{get_player_name_from_dict(game_summary["pitchers"]["save"])}' + pit_string += f'Save: {player_name}' + + game_embed.add_field( + name=f'Pitching', + value=pit_string, + ) + + def name_list(raw_list: list) -> str: + logger.info(f'raw_list: {raw_list}') + player_dict = {} + for x in raw_list: + if x['player_id'] not in player_dict: + player_dict[x['player_id']] = x + + data_dict = {} + for x in raw_list: + if x['player_id'] not in data_dict: + data_dict[x['player_id']] = 1 + else: + data_dict[x['player_id']] += 1 + + r_string = '' + logger.info(f'players: {player_dict} / data: {data_dict}') + + first = True + for p_id in data_dict: + r_string += f'{", " if not first else ""}{player_dict[p_id]["p_name"]}' + if data_dict[p_id] > 1: + r_string += f' {data_dict[p_id]}' + first = False + + return r_string + + logger.info(f'getting running string') + if len(game_summary['running']['sb']) + len(game_summary['running']['csc']) > 0: + run_string = '' + if len(game_summary['running']['sb']) > 0: + run_string += f'SB: {name_list(game_summary["running"]["sb"])}\n' + + if len(game_summary['running']['csc']) > 0: + run_string += f'CSc: {name_list(game_summary["running"]["csc"])}' + + game_embed.add_field( + name=f'Baserunning', + value=run_string + ) + + logger.info(f'getting xbh string') + if len(game_summary['xbh']['2b']) + len(game_summary['xbh']['3b']) + len(game_summary['xbh']['hr']) > 0: + bat_string = '' + if len(game_summary['xbh']['2b']) > 0: + bat_string += f'2B: {name_list(game_summary["xbh"]["2b"])}\n' + + if len(game_summary['xbh']['3b']) > 0: + bat_string += f'3B: {name_list(game_summary["xbh"]["3b"])}\n' + + if len(game_summary['xbh']['hr']) > 0: + bat_string += f'HR: {name_list(game_summary["xbh"]["hr"])}\n' + else: + bat_string = 'Oops! All bitches! No XBH from either team.' + + game_embed.add_field( + name='Batting', + value=bat_string, + inline=False + ) + + return game_embed + + +async def complete_game(session: Session, interaction: discord.Interaction, this_play: Play): + # if interaction is not None: + # salutation = await interaction.channel.send('GGs, I\'ll tally this game up...') + # Add button with {winning_team} wins! and another with "Roll Back" + + this_game = this_play.game + + async def roll_back(db_game_id: int, game: bool = True, plays: bool = False, decisions: bool = False): + if decisions: + try: + await db_delete('decisions/game', object_id=db_game_id) + except DatabaseError as e: + logger.warning(f'Could not delete decisions for game {db_game_id}: {e}') + + if plays: + try: + await db_delete('plays/game', object_id=db_game_id) + except DatabaseError as e: + logger.warning(f'Could not delete plays for game {db_game_id}: {e}') + + if game: + try: + await db_delete('games', object_id=db_game_id) + except DatabaseError as e: + logger.warning(f'Could not delete game {db_game_id}: {e}') + + # Post completed game to API + game_data = this_game.model_dump() + game_data['home_team_ranking'] = this_game.home_team.ranking + game_data['away_team_ranking'] = this_game.away_team.ranking + game_data['home_team_value'] = this_game.home_team.team_value + game_data['away_team_value'] = this_game.away_team.team_value + game_data['away_score'] = this_play.away_score + game_data['home_score'] = this_play.home_score + + winning_team = this_game.home_team if this_play.home_score > this_play.away_score else this_game.away_team + losing_team = this_game.home_team if this_play.away_score > this_play.home_score else this_game.away_team + + try: + db_game = await db_post('games', payload=game_data) + db_ready_plays = get_db_ready_plays(session, this_game, db_game['id']) + db_ready_decisions = get_db_ready_decisions(session, this_game, db_game['id']) + except Exception as e: + await roll_back(db_game['id']) + log_exception(e, msg='Unable to post game to API, rolling back') + + # Post game stats to API + try: + resp = await db_post('plays', payload=db_ready_plays) + except Exception as e: + await roll_back(db_game['id'], plays=True) + log_exception(e, msg='Unable to post plays to API, rolling back') + + if len(resp) > 0: + pass + + try: + resp = await db_post('decisions', payload={'decisions': db_ready_decisions}) + except Exception as e: + await roll_back(db_game['id'], plays=True, decisions=True) + log_exception(e, msg='Unable to post decisions to API, rolling back') + + if len(resp) > 0: + pass + + # Post game rewards (gauntlet and main team) + try: + win_reward, loss_reward = await post_game_rewards( + session, + winning_team=winning_team, + losing_team=losing_team, + this_game=this_game + ) + except Exception as e: + await roll_back(db_game['id'], plays=True, decisions=True) + log_exception(e, msg='Error while posting game rewards') + + session.delete(this_play) + session.commit() + + # Pull game summary for embed + summary_embed = await get_game_summary_embed( + session, + interaction, + this_play, + db_game['id'], + winning_team=winning_team, + losing_team=losing_team, + num_potg=3, + num_poop=1 + ) + + summary_embed.add_field( + name=f'{winning_team.abbrev} Rewards', + value=win_reward + ) + summary_embed.add_field( + name=f'{losing_team.abbrev} Rewards', + value=loss_reward + ) + summary_embed.add_field( + name='Highlights', + value=f'Please share the highlights in {get_channel(interaction, "pd-news-ticker").mention}!', + inline=False + ) + + # Create and post game summary to game channel and pd-network-news + + news_ticker = get_channel(interaction, 'pd-network-news') + if news_ticker is not None: + await news_ticker.send(content=None, embed=summary_embed) + + await interaction.channel.send(content=None, embed=summary_embed) + await interaction.edit_original_response(content=None, embed=summary_embed) + + game_id = this_game.id + this_game.active = False + session.add(this_game) + session.commit() + + logger.info(f'Just ended game {game_id}') diff --git a/db_calls_gameplay.py b/db_calls_gameplay.py index 07f8a19..cc0387f 100644 --- a/db_calls_gameplay.py +++ b/db_calls_gameplay.py @@ -24,6 +24,7 @@ db = SqliteDatabase( } ) SBA_DB_URL = 'http://database/api' +logger = logging.getLogger('discord_app') def param_char(other_params): @@ -43,7 +44,7 @@ def get_sba_team(id_or_abbrev, season=None): if resp.status_code == 200: return resp.json() else: - logging.warning(resp.text) + logger.warning(resp.text) raise ValueError(f'DB: {resp.text}') @@ -56,7 +57,7 @@ def get_sba_player(id_or_name, season=None): if resp.status_code == 200: return resp.json() else: - logging.warning(resp.text) + logger.warning(resp.text) raise ValueError(f'DB: {resp.text}') @@ -69,25 +70,25 @@ def get_sba_team_by_owner(season, owner_id): else: return full_resp['teams'][0] else: - logging.warning(resp.text) + logger.warning(resp.text) raise ValueError(f'DB: {resp.text}') # def pd_await db_get(endpoint: str, api_ver: int = 1, object_id: int = None, params: list = None, none_okay: bool = True): # req_url = pd_get_req_url(endpoint, api_ver=api_ver, object_id=object_id, params=params) -# logging.info(f'get:\n{endpoint} id: {object_id} params: {params}') +# logger.info(f'get:\n{endpoint} id: {object_id} params: {params}') # # resp = requests.get(req_url, timeout=3) # if resp.status_code == 200: # data = resp.json() -# logging.info(f'return: {data}') +# logger.info(f'return: {data}') # return data # elif none_okay: # data = resp.json() -# logging.info(f'return: {data}') +# logger.info(f'return: {data}') # return None # else: -# logging.warning(resp.text) +# logger.warning(resp.text) # raise ValueError(f'DB: {resp.text}') @@ -100,10 +101,10 @@ def get_sba_team_by_owner(season, owner_id): # # resp = requests.get(req_url, timeout=3) # # if resp.status_code == 200: # # data = resp.json() -# # logging.info(f'return: {data}') +# # logger.info(f'return: {data}') # # return data['teams'][0] # # else: -# # logging.warning(resp.text) +# # logger.warning(resp.text) # # raise ValueError(f'PD DB: {resp.text}') @@ -293,7 +294,7 @@ async def get_game_team( if not gm_id and not team_abbrev and not team_id: raise KeyError(f'get_game_team requires either one of gm_id, team_abbrev, or team_id to not be None') - logging.debug(f'getting game team for game {game.id} / gm_id: {gm_id} / ' + logger.debug(f'getting game team for game {game.id} / gm_id: {gm_id} / ' f'tm_abbrev: {team_abbrev} / team_id: {team_id} / game: {game}') if game.is_pd: if team_id: @@ -430,7 +431,7 @@ def get_one_lineup( Lineup.game_id == game_id, Lineup.team_id == team_id, Lineup.position == position, Lineup.active == active ) - logging.debug(f'get_one_lineup / this_lineup: {this_lineup}') + logger.debug(f'get_one_lineup / this_lineup: {this_lineup}') if as_obj: return this_lineup @@ -538,7 +539,7 @@ def make_sub(lineup_dict: dict): Lineup.game_id == lineup_dict['game_id'], Lineup.team_id == lineup_dict['team_id'], Lineup.batting_order == lineup_dict['batting_order'], Lineup.active == True ) - logging.debug(f'subbed_player: {subbed_player}') + logger.debug(f'subbed_player: {subbed_player}') if subbed_player: subbed_player = patch_lineup(subbed_player.id, active=False) @@ -549,7 +550,7 @@ def make_sub(lineup_dict: dict): return_value = convert_stratlineup(new_lineup) curr_play = get_current_play(lineup_dict['game_id']) - logging.debug(f'\n\nreturn_value: {return_value}\n\ncurr_play: {curr_play}\n\n') + logger.debug(f'\n\nreturn_value: {return_value}\n\ncurr_play: {curr_play}\n\n') # Check current play for updates if curr_play: @@ -576,19 +577,19 @@ def make_sub(lineup_dict: dict): def undo_subs(game: StratGame, new_play_num: int): - logging.info(f'get new players') + logger.info(f'get new players') new_players = Lineup.select().where((Lineup.game_id == game.id) & (Lineup.after_play > new_play_num)) - logging.info(f'new_player count: {new_players.count()}') + logger.info(f'new_player count: {new_players.count()}') replacements = [(x.id, x.replacing_id) for x in new_players] for x in replacements: - logging.info(f'replacing {x[0]} with {x[1]}') + logger.info(f'replacing {x[0]} with {x[1]}') old_player = get_one_lineup(game_id=game.id, lineup_id=x[1]) - logging.info(f'old_player: {old_player}') + logger.info(f'old_player: {old_player}') patch_lineup(old_player.id, active=True) - logging.info(f'activated!') + logger.info(f'activated!') - logging.info(f'done activating old players') + logger.info(f'done activating old players') Lineup.delete().where((Lineup.game_id == game.id) & (Lineup.after_play > new_play_num)).execute() @@ -613,7 +614,7 @@ async def get_player(game, lineup_member, as_dict: bool = True): player = this_card['player'] player['name'] = player['p_name'] player['team'] = this_card['team'] - logging.debug(f'player: {player}') + logger.debug(f'player: {player}') return player else: return get_sba_player(lineup_member.player_id) @@ -802,7 +803,7 @@ db.create_tables([Play]) def post_play(play_dict: dict) -> StratPlay: - logging.debug(f'play_dict: {play_dict}') + logger.debug(f'play_dict: {play_dict}') new_play = Play.create(**play_dict) # return_play = model_to_dict(new_play) return_play = convert_stratplay(new_play) @@ -994,7 +995,7 @@ def get_latest_play(game_id): def undo_play(game_id): p_query = Play.delete().where(Play.game_id == game_id).order_by(-Play.id).limit(1) - logging.debug(f'p_query: {p_query}') + logger.debug(f'p_query: {p_query}') count = p_query.execute() db.close() @@ -1035,7 +1036,7 @@ def add_run_last_player_ab(lineup: Lineup, is_erun: bool = True): try: last_ab = Play.select().where(Play.batter == lineup).order_by(-Play.id).get() except DoesNotExist as e: - logging.error(f'Unable to apply run to Lineup {lineup}') + logger.error(f'Unable to apply run to Lineup {lineup}') else: last_ab.run = 1 last_ab.e_run = 1 if is_erun else 0 @@ -1066,7 +1067,7 @@ def get_dbready_plays(game_id: int, db_game_id: int): x['game_id'] = db_game_id x['on_base_code'] = obc_list[x['on_base_code']] - logging.debug(f'all_plays:\n\n{prep_plays}\n') + logger.debug(f'all_plays:\n\n{prep_plays}\n') return prep_plays @@ -1114,7 +1115,7 @@ def get_or_create_bullpen(ai_team, bot): if this_pen: return convert_bullpen_to_strat(this_pen) three_days_ago = int(datetime.datetime.timestamp(datetime.datetime.now() - datetime.timedelta(days=3))) * 1000 - logging.debug(f'3da: {three_days_ago} / last_up: {this_pen.last_updated} / L > 3: ' + logger.debug(f'3da: {three_days_ago} / last_up: {this_pen.last_updated} / L > 3: ' f'{this_pen.last_updated > three_days_ago}') if this_pen and this_pen.last_updated > three_days_ago: @@ -1128,7 +1129,7 @@ def get_or_create_bullpen(ai_team, bot): bullpen_range = f'N30:N41' raw_cells = r_sheet.range(bullpen_range) - logging.debug(f'raw_cells: {raw_cells}') + logger.debug(f'raw_cells: {raw_cells}') bullpen = Bullpen( ai_team_id=ai_team['id'], @@ -1144,7 +1145,7 @@ def get_or_create_bullpen(ai_team, bot): last_updated=int(datetime.datetime.timestamp(datetime.datetime.now())*1000) ) bullpen.save() - logging.debug(f'bullpen: {bullpen}') + logger.debug(f'bullpen: {bullpen}') return convert_bullpen_to_strat(bullpen) @@ -1271,7 +1272,7 @@ def complete_play(play_id, batter_to_base: int = None): this_play.complete = True this_play.save() - logging.debug(f'starting the inning calc') + logger.debug(f'starting the inning calc') new_inning_half = this_play.inning_half new_inning_num = this_play.inning_num if this_play.runner or this_play.wild_pitch or this_play.passed_ball or this_play.pick_off or this_play.balk: @@ -1286,7 +1287,7 @@ def complete_play(play_id, batter_to_base: int = None): new_on_third = None # score_increment = this_play.homerun # patch to handle little league home runs TODO: standardize on just _on_final for these - logging.debug(f'complete_play - this_play: {this_play}') + logger.debug(f'complete_play - this_play: {this_play}') if this_play.batter_final == 4 or batter_to_base == 4: this_play.run = 1 score_increment = 1 @@ -1294,7 +1295,7 @@ def complete_play(play_id, batter_to_base: int = None): this_play.e_run = 1 else: score_increment = 0 - logging.debug(f'complete_play - score_increment: {score_increment}') + logger.debug(f'complete_play - score_increment: {score_increment}') if this_play.on_first_final == 99: this_play.on_first_final = None @@ -1343,7 +1344,7 @@ def complete_play(play_id, batter_to_base: int = None): new_batting_order = 1 # Not an inning-ending play else: - logging.debug(f'starting the obc calc') + logger.debug(f'starting the obc calc') bases_occ = [False, False, False, False] # Set the occupied bases for the next play and lineup member occupying it @@ -1407,22 +1408,22 @@ def complete_play(play_id, batter_to_base: int = None): # A team score if score_increment: - logging.debug(f'complete_play: \n\nscore_increment: {score_increment}\n\nnew home score: {new_home_score}\n\n' + logger.debug(f'complete_play: \n\nscore_increment: {score_increment}\n\nnew home score: {new_home_score}\n\n' f'new_away_score: {new_away_score}\n\nthis_play.away_score: {this_play.away_score}\n\n' f'this_player.home_score: {this_play.home_score}') # Game is now tied if new_home_score == new_away_score: - logging.debug(f'\n\nGame {this_play.game} is now tied\n\n') + logger.debug(f'\n\nGame {this_play.game} is now tied\n\n') this_play.is_tied = 1 # One team took the lead elif (this_play.away_score <= this_play.home_score) and (new_away_score > new_home_score): - logging.debug(f'\n\nTeam {this_play.batter.team_id} took the lead\n\n') + logger.debug(f'\n\nTeam {this_play.batter.team_id} took the lead\n\n') this_play.is_go_ahead = 1 this_play.save() elif (this_play.home_score <= this_play.away_score) and (new_home_score > new_away_score): - logging.debug(f'\n\nteam {this_play.batter.team_id} took the lead\n\n') + logger.debug(f'\n\nteam {this_play.batter.team_id} took the lead\n\n') this_play.is_go_ahead = 1 this_play.save() @@ -1447,7 +1448,7 @@ def complete_play(play_id, batter_to_base: int = None): pitcher = get_one_lineup(this_play.game_id, team_id=new_pteam_id, position='P') pitcher_id = pitcher.id if pitcher else None - logging.debug(f'done the obc calc') + logger.debug(f'done the obc calc') next_play = Play.create(**{ 'game_id': this_play.game.id, 'play_num': this_play.play_num + 1, @@ -1653,7 +1654,7 @@ def get_fielding_stats(game_id, lineup_id: int = None, team_id: int = None): 'pl_csc': x.pl_csc }) - logging.debug(f'fielding_stats: {all_stats}') + logger.debug(f'fielding_stats: {all_stats}') db.close() return all_stats @@ -1710,7 +1711,7 @@ def get_fielding_stats(game_id, lineup_id: int = None, team_id: int = None): # 'pl_bplo': x.pl_bplo, # }) # done_batters.append(x.batter.id) -# logging.info(f'batting stats: {return_stats}') +# logger.info(f'batting stats: {return_stats}') # # elif team_id is not None: # batting_stats = Play.select( @@ -1735,7 +1736,7 @@ def get_fielding_stats(game_id, lineup_id: int = None, team_id: int = None): # fn.SUM(Play.bplo).over(partition_by=[Play.batter.team_id]).alias('tm_bplo') # ).join(Lineup, on=Play.batter).where((Play.game_id == game_id) & (Play.batter.team_id == team_id)) # -# logging.info(f'batting_stats count: {batting_stats.count()}') +# logger.info(f'batting_stats count: {batting_stats.count()}') # done_batters = [] # for x in batting_stats: # if x.batter.id not in done_batters: @@ -1773,7 +1774,7 @@ def get_fielding_stats(game_id, lineup_id: int = None, team_id: int = None): # team_lineups = Lineup.select().where( # (Lineup.game_id == game_id) & (Lineup.team_id == team_id) & (Lineup.batting_order < 10) # ).order_by(Lineup.batting_order) -# logging.info(f'team_lineups count: {team_lineups.count()} / lineups: {team_lineups}') +# logger.info(f'team_lineups count: {team_lineups.count()} / lineups: {team_lineups}') # # all_stats = [] # for line in team_lineups: @@ -1786,7 +1787,7 @@ def get_pitching_stats( game_id, lineup_id: int = None, team_id: int = None, in_pow: bool = None, in_innings: list = None): if in_innings is None: in_innings = [x for x in range(1, 30)] - logging.info(f'db_calls_gameplay - get_pitching_stats - in_innings: {in_innings}') + logger.info(f'db_calls_gameplay - get_pitching_stats - in_innings: {in_innings}') pitching_stats = Play.select( Play.pitcher, fn.SUM(Play.outs).over(partition_by=[Play.pitcher_id]).alias('pl_outs'), @@ -1830,14 +1831,14 @@ def get_pitching_stats( fn.SUM(Play.balk).over(partition_by=[Play.pitcher.team_id]).alias('tm_balk'), fn.SUM(Play.homerun).over(partition_by=[Play.pitcher.team_id]).alias('tm_homerun'), ).join(Lineup, on=Play.pitcher).where(Play.game_id == game_id) - logging.debug(f'db_calls_gameplay - get_pitching_stats - pitching_stats: {pitching_stats}') + logger.debug(f'db_calls_gameplay - get_pitching_stats - pitching_stats: {pitching_stats}') # This is counging plays with multiple runs scored on 1 ER and the rest unearned # earned_runs_pl = Play.select().where( # ((Play.on_first_final == 4) | (Play.on_second_final == 4) | (Play.on_third_final == 4) | # (Play.batter_final == 4)) & (Play.error == 0) # ).join(Lineup, on=Play.pitcher).where(Play.game_id == game_id) - # logging.info(f'earned_runs: {earned_runs_pl}') + # logger.info(f'earned_runs: {earned_runs_pl}') er_first = Play.select().where( (Play.on_first_final == 4) & (Play.error == 0) @@ -1865,7 +1866,7 @@ def get_pitching_stats( # if in_innings is not None: # pitching_stats = pitching_stats.where(Play.inning_num << in_innings) - # logging.info(f'db_calls_gameplay - get_pitching_stats - in_innings: {in_innings} / query: {pitching_stats} / ' + # logger.info(f'db_calls_gameplay - get_pitching_stats - in_innings: {in_innings} / query: {pitching_stats} / ' # f'stats: {pitching_stats.count()}') tm_earned_runs = None @@ -1933,7 +1934,7 @@ def get_pitching_stats( done_pitchers.append(x.pitcher_id) db.close() - logging.debug(f'pitching stats: {return_pitchers}') + logger.debug(f'pitching stats: {return_pitchers}') return return_pitchers @@ -1945,7 +1946,7 @@ def get_pitching_decisions(game: StratGame, db_game_id: int): # home_pitchers = [] # [(pitcher, first_play), (pitcher2, their_first_play)] # last_play = get_current_play(game.id) - logging.debug(f'this game: {game}') + logger.debug(f'this game: {game}') winner = None loser = None save = None @@ -1957,7 +1958,7 @@ def get_pitching_decisions(game: StratGame, db_game_id: int): away_pitcher = Lineup.get(Lineup.game_id == game.id, Lineup.team_id == game.away_team_id, Lineup.position == 'P') home_pitcher = Lineup.get(Lineup.game_id == game.id, Lineup.team_id == game.home_team_id, Lineup.position == 'P') gs.extend([away_pitcher.card_id, home_pitcher.card_id]) - logging.debug(f'SPs: {away_pitcher} / {home_pitcher}') + logger.debug(f'SPs: {away_pitcher} / {home_pitcher}') decisions = { away_pitcher.player_id: DecisionModel( @@ -1979,7 +1980,7 @@ def get_pitching_decisions(game: StratGame, db_game_id: int): } # { : DecisionModel } for x in Play.select().where(Play.game_id == game.id): - logging.debug(f'checking play num {x.play_num}') + logger.debug(f'checking play num {x.play_num}') if x.inning_half == 'Top' and home_pitcher != x.pitcher: if save == home_pitcher: if x.home_score > x.away_score: @@ -2007,7 +2008,7 @@ def get_pitching_decisions(game: StratGame, db_game_id: int): save = away_pitcher if x.is_go_ahead: - logging.debug(f'is go ahead: {x}') + logger.debug(f'is go ahead: {x}') if x.on_third_final == 4: # winning_run = x.on_third # @@ -2065,7 +2066,7 @@ def get_pitching_decisions(game: StratGame, db_game_id: int): winner = home_pitcher if x.inning_half == 'Bot' else away_pitcher if x.is_tied: - logging.debug(f'is tied: {x}') + logger.debug(f'is tied: {x}') winner, loser = None, None if save: b_save.append(save) @@ -2101,7 +2102,7 @@ def get_pitching_decisions(game: StratGame, db_game_id: int): return [x.dict() for x in decisions.values()] - logging.debug(f'\n\nWin: {winner}\nLose: {loser}\nSave: {save}\nBlown Save: {b_save}\nHolds: {holds}') + logger.debug(f'\n\nWin: {winner}\nLose: {loser}\nSave: {save}\nBlown Save: {b_save}\nHolds: {holds}') return { 'winner': winner.card_id, 'loser': loser.card_id, @@ -2400,7 +2401,7 @@ class StratManagerAi(pydantic.BaseModel): self, this_play, tot_allowed: int, is_starter: bool = False) -> bool: run_lead = this_play.ai_run_diff() obc = this_play.on_base_code - logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: ' + logger.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: ' f'outs: {this_play.starting_outs}, obc: {obc}, run_lead: {run_lead}, ' f'tot_allowed: {tot_allowed}') @@ -2408,30 +2409,30 @@ class StratManagerAi(pydantic.BaseModel): # AI up big if tot_allowed < 5 and is_starter: - logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 1') + logger.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 1') return False elif run_lead > 5 or (run_lead > 2 and self.ahead_aggression > 5): if tot_allowed <= lead_target or obc <= 3 or (this_play.starting_outs == 2 and not is_starter): - logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 2') + logger.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 2') return False elif run_lead > 2 or (run_lead >= 0 and self.ahead_aggression > 5): if tot_allowed < lead_target or obc <= 1 or (this_play.starting_outs == 2 and not is_starter): - logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 3') + logger.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 3') return False elif run_lead >= 0 or (run_lead >= -2 and self.behind_aggression > 5): if tot_allowed < 5 or obc <= run_lead or (this_play.starting_outs == 2 and not is_starter): - logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 4') + logger.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 4') return False elif run_lead >= -3 and self.behind_aggression > 5: if tot_allowed < 5 and obc <= 1: - logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 5') + logger.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 5') return False elif run_lead <= -5: if is_starter and this_play.inning_num <= 3: - logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 6') + logger.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 6') return False if this_play.starting_outs != 0: - logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 7') + logger.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 7') return False return True @@ -2453,13 +2454,13 @@ def get_manager(game) -> Optional[StratManagerAi]: manager_ai_id = ((datetime.datetime.now().day * team_id) % 3) + 1 if manager_ai_id > 3 or manager_ai_id < 1: manager_ai_id = 1 - logging.debug(f'manager id: {manager_ai_id} for game {game}') + logger.debug(f'manager id: {manager_ai_id} for game {game}') try: this_manager = ManagerAi.get_by_id(manager_ai_id) except Exception as e: e_message = f'Could not find manager id {manager_ai_id}' - logging.error(f'{e_message}: {type(e)}: {e}') + logger.error(f'{e_message}: {type(e)}: {e}') raise KeyError(f'Could not find this AI manager\'s playbook') return convert_strat_manager(this_manager) diff --git a/exceptions.py b/exceptions.py index 99bd20c..a0afdbd 100644 --- a/exceptions.py +++ b/exceptions.py @@ -1,16 +1,23 @@ import logging from typing import Literal +logger = logging.getLogger('discord_app') + def log_exception(e: Exception, msg: str = '', level: Literal['debug', 'error', 'info', 'warn'] = 'error'): if level == 'debug': - logging.debug(msg, stack_info=True) + logger.debug(msg, exc_info=True, stack_info=True) elif level == 'error': - logging.error(msg, stack_info=True) + logger.error(msg, exc_info=True, stack_info=True) elif level == 'info': - logging.info(msg, stack_info=True) + logger.info(msg, exc_info=True, stack_info=True) else: - logging.warning(msg, stack_info=True) - raise e(msg) + logger.warning(msg, exc_info=True, stack_info=True) + + # Check if 'e' is an exception class or instance + if isinstance(e, Exception): + raise e # If 'e' is already an instance of an exception + else: + raise e(msg) # If 'e' is an exception class class GameException(Exception): pass @@ -38,3 +45,7 @@ class PlayNotFoundException(GameException): class PlayInitException(GameException): pass + + +class DatabaseError(GameException): + pass diff --git a/gauntlets.py b/gauntlets.py index c7403ce..83e1f83 100644 --- a/gauntlets.py +++ b/gauntlets.py @@ -11,6 +11,9 @@ from helpers import RARITY, get_or_create_role, send_to_channel, get_channel from api_calls import db_get, db_post, db_delete, db_patch +logger = logging.getLogger('discord_app') + + async def wipe_team(this_team, interaction: discord.Interaction, delete_team: bool = False, delete_runs: bool = False): await interaction.edit_original_response(content=f'Looking for cards...') # Delete cards @@ -273,11 +276,11 @@ async def get_starting_pitcher(this_team, this_game, this_event, this_run): # timeout=10 # ) # except ConnectionError as e: - # logging.error(f'Could not get pitchers for {this_team["lname"]}: {e}') + # logger.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') + # logger.info(f'pitchers is None') # del params # params = [ # ('mlbclub', this_team['lname']), ('pos_include', 'SP'), @@ -333,7 +336,7 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra base_params = [('cardset_id', 20), ('cardset_id', 21), ('cardset_id', 22), ('cardset_id', 16), ('cardset_id', 8), ('limit', 8)] else: - logging.error(f'run_draft - Event ID {this_event["id"]} not recognized') + logger.error(f'run_draft - Event ID {this_event["id"]} not recognized') raise KeyError(f'Draft data not found for Gauntlet {this_event["id"]}') if draft_team is None: @@ -519,7 +522,7 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra 'Reserve': 0, 'Replacement': 0 } - logging.info(f'gauntlets.py - run_draft / max_counts: {max_counts}') + logger.info(f'gauntlets.py - run_draft / max_counts: {max_counts}') round_num = 1 counter = 0 @@ -615,7 +618,7 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra return [top_embed, bot_embed] - logging.info(f'getting last message') + logger.info(f'getting last message') last_message = await interaction.channel.send(content=None, embeds=get_embeds(include_links=False)) async def draft_loop(): @@ -624,7 +627,7 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra while round_num <= 26 and counter < 50: counter += 1 params = copy.deepcopy(base_params) - logging.info(f'gauntlets.py - run_draft - event_id {this_event["id"]} / round_num: {round_num} / counter: {counter} / counts: {counts} / max_counts: {max_counts}') + logger.info(f'gauntlets.py - run_draft - event_id {this_event["id"]} / round_num: {round_num} / counter: {counter} / counts: {counts} / max_counts: {max_counts}') # Set rarity based on remaining counts if counts['Hall of Fame'] < max_counts['Hall of Fame']: @@ -671,7 +674,7 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra # Slot 2 - RP elif x == 'RP': - logging.info(f'counts[RP]: {counts["RP"]}') + logger.info(f'counts[RP]: {counts["RP"]}') if counts['RP'] > 7: slot_params = [('pos_exc', 'RP')] if counts['SP'] > 5: @@ -708,9 +711,9 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra # 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}') + logger.info(f'this_batch: {this_batch}') + logger.info(f'slot_params: {slot_params}') + logger.info(f'params: {params}') # No position explicitly requested or denied if len(slot_params) == 0: @@ -744,7 +747,7 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra break if len(this_batch) < 4: - logging.error(f'Pulled less than 4 players in gauntlet draft') + logger.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: @@ -775,7 +778,7 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra round_num += 1 await last_message.edit(content=None, embeds=get_embeds(include_links=False, round_num=round_num)) - logging.info(f'going into draft') + logger.info(f'going into draft') backyard_round = None custom_player_round = None if this_event['id'] == 1: @@ -869,7 +872,7 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra # Slot 2 - RP elif x == 'RP': - logging.info(f'counts[RP]: {counts["RP"]}') + logger.info(f'counts[RP]: {counts["RP"]}') if counts['RP'] < 8: slot_params = [('pos_inc', 'RP')] elif counts['SP'] < 4: @@ -906,9 +909,9 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra 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}') + logger.info(f'this_batch: {this_batch}') + logger.info(f'slot_params: {slot_params}') + logger.info(f'params: {params}') slot_params.extend(params) p_query = await db_get('players/random', params=slot_params) @@ -924,7 +927,7 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra break if len(this_batch) < 4: - logging.error(f'Pulled less than 4 players in gauntlet draft') + logger.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: @@ -1027,7 +1030,7 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra # Slot 2 - RP elif x == 'RP': - logging.info(f'counts[RP]: {counts["RP"]}') + logger.info(f'counts[RP]: {counts["RP"]}') if counts['RP'] > 7: slot_params = [('pos_exc', 'RP')] if counts['SP'] > 5: @@ -1064,9 +1067,9 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra # 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}') + logger.info(f'this_batch: {this_batch}') + logger.info(f'slot_params: {slot_params}') + logger.info(f'params: {params}') # No position explicitly requested or denied if len(slot_params) == 0: @@ -1100,7 +1103,7 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra break if len(this_batch) < 4: - logging.error(f'Pulled less than 4 players in gauntlet draft') + logger.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: @@ -1131,7 +1134,7 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra 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}') + logger.info(f'round {round_num}') counter += 1 params = copy.deepcopy(base_params) @@ -1185,7 +1188,7 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra ('min_rarity', RARITY['Replacement']), ('max_rarity', RARITY['Replacement']) ]) - logging.info(f'starting position loop') + logger.info(f'starting position loop') this_batch = [] for x in ['SP', 'RP', 'IF', 'OF']: # Slot 1 - SP @@ -1205,7 +1208,7 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra # Slot 2 - RP elif x == 'RP': - logging.info(f'counts[RP]: {counts["RP"]}') + logger.info(f'counts[RP]: {counts["RP"]}') if counts['RP'] > 7: slot_params = [('pos_exc', 'RP')] if counts['SP'] > 5: @@ -1242,9 +1245,9 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra # 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}') + logger.info(f'this_batch: {this_batch}') + logger.info(f'slot_params: {slot_params}') + logger.info(f'params: {params}') # No position explicitly requested or denied if len(slot_params) == 0: @@ -1278,7 +1281,7 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra break if len(this_batch) < 4: - logging.error(f'Pulled less than 4 players in gauntlet draft') + logger.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: @@ -1403,7 +1406,7 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra # Slot 2 - RP elif x == 'RP': - logging.info(f'counts[RP]: {counts["RP"]}') + logger.info(f'counts[RP]: {counts["RP"]}') if counts['RP'] > 7: slot_params = [('pos_exc', 'RP')] if counts['SP'] > 5: @@ -1440,9 +1443,9 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra # 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}') + logger.info(f'this_batch: {this_batch}') + logger.info(f'slot_params: {slot_params}') + logger.info(f'params: {params}') # No position explicitly requested or denied if len(slot_params) == 0: @@ -1476,7 +1479,7 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra break if len(this_batch) < 4: - logging.error(f'Pulled less than 4 players in gauntlet draft') + logger.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: @@ -1508,7 +1511,7 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra elif this_event['id'] in [5, 6]: await draft_loop() else: - logging.error(f'run_draft - No draft logic for Event ID {this_event["id"]}') + logger.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: @@ -1545,7 +1548,7 @@ async def run_draft(interaction: discord.Interaction, main_team, this_event, dra async def get_embed(this_run=None, this_event=None, this_team=None): - logging.info(f'get_embed - this_run:\n{this_run}\n\nthis_event:\n{this_event}') + logger.info(f'get_embed - this_run:\n{this_run}\n\nthis_event:\n{this_event}') if this_run is None and this_event is None: raise KeyError('Must provide either a run or an event to get_embed') diff --git a/helpers.py b/helpers.py index d8e2afc..42eed05 100644 --- a/helpers.py +++ b/helpers.py @@ -439,7 +439,7 @@ class Pagination(discord.ui.View): @discord.ui.button(label='⏮️', style=discord.ButtonStyle.blurple) async def left_button(self, interaction: discord.Interaction, button: discord.ui.Button): if interaction.user not in self.responders: - logging.info(f'{interaction.user} is not in {self.responders}') + logger.info(f'{interaction.user} is not in {self.responders}') return self.value = 'left' @@ -449,7 +449,7 @@ class Pagination(discord.ui.View): @discord.ui.button(label='❌️', style=discord.ButtonStyle.secondary) async def cancel_button(self, interaction: discord.Interaction, button: discord.ui.Button): if interaction.user not in self.responders: - logging.info(f'{interaction.user} is not in {self.responders}') + logger.info(f'{interaction.user} is not in {self.responders}') return self.value = 'cancel' @@ -459,7 +459,7 @@ class Pagination(discord.ui.View): @discord.ui.button(label='⏭️', style=discord.ButtonStyle.blurple) async def right_button(self, interaction: discord.Interaction, button: discord.ui.Button): if interaction.user not in self.responders: - logging.info(f'{interaction.user} is not in {self.responders}') + logger.info(f'{interaction.user} is not in {self.responders}') return self.value = 'right' @@ -585,7 +585,7 @@ class SelectChoicePackTeam(discord.ui.Select): params.append(('pack_cardset_id', self.cardset_id)) p_query = await db_get('packs', params=params) if p_query['count'] == 0: - logging.error(f'open-packs - no packs found with params: {params}') + logger.error(f'open-packs - no packs found with params: {params}') raise ValueError(f'Unable to open packs') this_pack = await db_patch('packs', object_id=p_query['packs'][0]['id'], params=[('pack_team_id', team_id)]) @@ -599,9 +599,9 @@ class SelectOpenPack(discord.ui.Select): super().__init__(placeholder='Select a Pack Type', options=options) async def callback(self, interaction: discord.Interaction): - logging.info(f'SelectPackChoice - selection: {self.values[0]}') + logger.info(f'SelectPackChoice - selection: {self.values[0]}') pack_vals = self.values[0].split('-') - logging.info(f'pack_vals: {pack_vals}') + logger.info(f'pack_vals: {pack_vals}') # Get the selected packs params = [('team_id', self.owner_team['id']), ('opened', False), ('limit', 5), ('exact_match', True)] @@ -664,7 +664,7 @@ class SelectOpenPack(discord.ui.Select): p_query = await db_get('packs', params=params) if p_query['count'] == 0: - logging.error(f'open-packs - no packs found with params: {params}') + logger.error(f'open-packs - no packs found with params: {params}') raise ValueError(f'Unable to open packs') # Open the packs @@ -694,7 +694,7 @@ class SelectPaperdexCardset(discord.ui.Select): super().__init__(placeholder='Select a Cardset', options=options) async def callback(self, interaction: discord.Interaction): - logging.info(f'SelectPaperdexCardset - selection: {self.values[0]}') + logger.info(f'SelectPaperdexCardset - selection: {self.values[0]}') cardset_id = None if self.values[0] == '2022 Season': cardset_id = 3 @@ -871,7 +871,7 @@ class SelectBuyPacksCardset(discord.ui.Select): super().__init__(placeholder='Select a Cardset', options=options) async def callback(self, interaction: discord.Interaction): - logging.info(f'SelectBuyPacksCardset - selection: {self.values[0]}') + logger.info(f'SelectBuyPacksCardset - selection: {self.values[0]}') cardset_id = None if self.values[0] == '2022 Season': cardset_id = 3 @@ -1205,7 +1205,7 @@ class Dropdown(discord.ui.Select): # Select object, and the values attribute gets a list of the user's # selected options. We only want the first one. # await interaction.response.send_message(f'Your favourite colour is {self.values[0]}') - logging.info(f'Dropdown callback: {self.custom_callback}') + logger.info(f'Dropdown callback: {self.custom_callback}') await self.custom_callback(interaction, self.values) @@ -1554,7 +1554,7 @@ async def create_channel_old( category=this_category ) - logging.info(f'Creating channel ({channel_name}) in ({category_name})') + logger.info(f'Creating channel ({channel_name}) in ({category_name})') return this_channel @@ -1567,7 +1567,7 @@ async def react_and_reply(ctx, reaction, message): async def send_to_channel(bot, channel_name, content=None, embed=None): guild = bot.get_guild(int(os.environ.get('GUILD_ID'))) if not guild: - logging.error('Cannot send to channel - bot not logged in') + logger.error('Cannot send to channel - bot not logged in') return this_channel = discord.utils.get(guild.text_channels, name=channel_name) @@ -1582,11 +1582,11 @@ async def send_to_channel(bot, channel_name, content=None, embed=None): async def get_or_create_role(ctx, role_name, mentionable=True): this_role = discord.utils.get(ctx.guild.roles, name=role_name) - # logging.info(f'this_role: {this_role} / role_name: {role_name} (POST SEARCH)') + # logger.info(f'this_role: {this_role} / role_name: {role_name} (POST SEARCH)') if not this_role: this_role = await ctx.guild.create_role(name=role_name, mentionable=mentionable) - # logging.info(f'this_role: {this_role} / role_name: {role_name} (PRE RETURN)') + # logger.info(f'this_role: {this_role} / role_name: {role_name} (PRE RETURN)') return this_role @@ -1682,7 +1682,7 @@ async def create_channel( category=this_category ) - logging.info(f'Creating channel ({channel_name}) in ({category_name})') + logger.info(f'Creating channel ({channel_name}) in ({category_name})') return this_channel @@ -2208,7 +2208,7 @@ async def roll_for_cards(all_packs: list, extra_val=None) -> list: counts['HoF']['count'] += 1 elif pack['pack_type']['name'] == 'Check-In Player': - logging.info(f'Building Check-In Pack // extra_val (type): {extra_val} {type(extra_val)}') + logger.info(f'Building Check-In Pack // extra_val (type): {extra_val} {type(extra_val)}') # Single Card mod = 0 if isinstance(extra_val, int): @@ -2278,7 +2278,7 @@ async def roll_for_cards(all_packs: list, extra_val=None) -> list: pack_ids.append(pack['id']) for pull in pull_notifs: - logging.info(f'good pull: {pull}') + logger.info(f'good pull: {pull}') await db_post('notifs', payload={ 'created': int(datetime.datetime.timestamp(datetime.datetime.now())*1000), 'title': 'Rare Pull', @@ -2318,7 +2318,7 @@ def get_sheets(bot): try: return bot.get_cog('Players').sheets except Exception as e: - logging.error(f'Could not grab sheets auth: {e}') + logger.error(f'Could not grab sheets auth: {e}') raise ConnectionError(f'Bot has not authenticated with discord; please try again in 1 minute.') @@ -2329,7 +2329,7 @@ def create_team_sheet(team, email: str, current, bot): f'{team["lname"]} Roster Sheet v{current["gsheet_version"]}', '1539D0imTMjlUx2VF3NPMt7Sv85sb2XAJ' ) - logging.info(f'new_sheet: {new_sheet}') + logger.info(f'new_sheet: {new_sheet}') this_sheet = sheets.open_by_key(new_sheet['id']) this_sheet.share(email, role='writer') @@ -2338,7 +2338,7 @@ def create_team_sheet(team, email: str, current, bot): crange='B1:B2', values=[[f'{team["id"]}'], [f'\'{team_hash(team)}']] ) - logging.debug(f'this_sheet: {this_sheet}') + logger.debug(f'this_sheet: {this_sheet}') return this_sheet @@ -2422,7 +2422,7 @@ def get_rosters(team, bot, roster_num: Optional[int] = None) -> list: sheets = get_sheets(bot) this_sheet = sheets.open_by_key(team['gsheet']) r_sheet = this_sheet.worksheet_by_title(f'My Rosters') - logging.debug(f'this_sheet: {this_sheet} / r_sheet = {r_sheet}') + logger.debug(f'this_sheet: {this_sheet} / r_sheet = {r_sheet}') all_rosters = [None, None, None] @@ -2430,7 +2430,7 @@ def get_rosters(team, bot, roster_num: Optional[int] = None) -> list: if not roster_num or roster_num == 1: roster_1 = r_sheet.range('B3:B28') roster_name = r_sheet.cell('F30').value - logging.info(f'roster_1: {roster_1}') + logger.info(f'roster_1: {roster_1}') if not roster_1[0][0].value == '': all_rosters[0] = {'name': roster_name, 'roster_num': 1, 'team_id': team['id'], 'cards': None} @@ -2440,7 +2440,7 @@ def get_rosters(team, bot, roster_num: Optional[int] = None) -> list: if not roster_num or roster_num == 2: roster_2 = r_sheet.range('B29:B54') roster_name = r_sheet.cell('F31').value - logging.info(f'roster_2: {roster_2}') + logger.info(f'roster_2: {roster_2}') if not roster_2[0][0].value == '': all_rosters[1] = {'name': roster_name, 'roster_num': 2, 'team_id': team['id'], 'cards': None} @@ -2450,7 +2450,7 @@ def get_rosters(team, bot, roster_num: Optional[int] = None) -> list: if not roster_num or roster_num == 3: roster_3 = r_sheet.range('B55:B80') roster_name = r_sheet.cell('F32').value - logging.info(f'roster_3: {roster_3}') + logger.info(f'roster_3: {roster_3}') if not roster_3[0][0].value == '': all_rosters[2] = {'name': roster_name, 'roster_num': 3, 'team_id': team['id'], 'cards': None} @@ -2461,11 +2461,11 @@ def get_rosters(team, bot, roster_num: Optional[int] = None) -> list: def get_roster_lineups(team, bot, roster_num, lineup_num) -> list: sheets = get_sheets(bot) - logging.debug(f'sheets: {sheets}') + logger.debug(f'sheets: {sheets}') this_sheet = sheets.open_by_key(team['gsheet']) - logging.debug(f'this_sheet: {this_sheet}') + logger.debug(f'this_sheet: {this_sheet}') r_sheet = this_sheet.worksheet_by_title('My Rosters') - logging.debug(f'r_sheet: {r_sheet}') + logger.debug(f'r_sheet: {r_sheet}') if lineup_num == 1: row_start = 9 @@ -2481,17 +2481,17 @@ def get_roster_lineups(team, bot, roster_num, lineup_num) -> list: else: l_range = f'L{row_start}:M{row_end}' - logging.debug(f'l_range: {l_range}') + logger.debug(f'l_range: {l_range}') raw_cells = r_sheet.range(l_range) - logging.debug(f'raw_cells: {raw_cells}') + logger.debug(f'raw_cells: {raw_cells}') try: lineup_cells = [(row[0].value, int(row[1].value)) for row in raw_cells] except ValueError as e: - logging.error(f'Could not pull roster for {team["abbrev"]} due to a ValueError') + logger.error(f'Could not pull roster for {team["abbrev"]} due to a ValueError') raise ValueError(f'Uh oh. Looks like your roster might not be saved. I am reading blanks when I try to ' f'get the card IDs') - logging.debug(f'lineup_cells: {lineup_cells}') + logger.debug(f'lineup_cells: {lineup_cells}') return lineup_cells @@ -2519,7 +2519,7 @@ async def legal_channel(ctx): elif ctx.channel.name in bad_channels: # await ctx.message.add_reaction('❌') # await ctx.send(f'Slide on down to the {get_channel(ctx, "pd-bot-hole").mention} ;)') - # logging.warning(f'{ctx.author.name} posted in illegal channel.') + # logger.warning(f'{ctx.author.name} posted in illegal channel.') # return False raise discord.app_commands.AppCommandError(f'Slide on down to the {get_channel(ctx, "pd-bot-hole").mention} ;)') else: @@ -2589,7 +2589,7 @@ async def team_summary_embed(team, ctx, include_roster: bool = True): # inline=False # ) # except Exception as e: - # logging.error(f'Could not pull rosters for {team["abbrev"]}') + # logger.error(f'Could not pull rosters for {team["abbrev"]}') # embed.add_field( # name='Rosters', # value='Unable to pull current rosters. `/pullroster` to sync.', @@ -2756,7 +2756,7 @@ async def paperdex_cardset_embed(team: dict, this_cardset: dict) -> list[discord else: player['owned'] = False - logging.debug(f'player: {player} / type: {type(player)}') + logger.debug(f'player: {player} / type: {type(player)}') coll_data[player['rarity']]['players'].append(player) cover_embed = get_team_embed(f'{team["lname"]} Collection', team=team) @@ -2777,7 +2777,7 @@ async def paperdex_cardset_embed(team: dict, this_cardset: dict) -> list[discord chunk_string = '' for index, this_player in enumerate(coll_data[rarity_id]['players']): - logging.debug(f'this_player: {this_player}') + logger.debug(f'this_player: {this_player}') chunk_string += '☑ ' if this_player['owned'] else '⬜ ' chunk_string += f'{this_player["p_name"]}\n' @@ -2834,7 +2834,7 @@ async def paperdex_team_embed(team: dict, mlb_team: dict) -> list[discord.Embed] else: player['owned'] = False - logging.debug(f'player: {player} / type: {type(player)}') + logger.debug(f'player: {player} / type: {type(player)}') coll_data[x['id']]['players'].append(player) cover_embed = get_team_embed(f'{team["lname"]} Collection', team=team) @@ -2856,7 +2856,7 @@ async def paperdex_team_embed(team: dict, mlb_team: dict) -> list[discord.Embed] chunk_string = '' for index, this_player in enumerate(coll_data[cardset_id]['players']): - logging.debug(f'this_player: {this_player}') + logger.debug(f'this_player: {this_player}') chunk_string += '☑ ' if this_player['owned'] else '⬜ ' chunk_string += f'{this_player["p_name"]}\n' @@ -2903,7 +2903,7 @@ async def open_st_pr_packs(all_packs: list, team: dict, context): pack_ids = await roll_for_cards(all_packs) if not pack_ids: - logging.error(f'open_packs - unable to roll_for_cards for packs: {all_packs}') + logger.error(f'open_packs - unable to roll_for_cards for packs: {all_packs}') raise ValueError(f'I was not able to unpack these cards') all_cards = [] @@ -2912,7 +2912,7 @@ async def open_st_pr_packs(all_packs: list, team: dict, context): all_cards.extend(new_cards['cards']) if not all_cards: - logging.error(f'open_packs - unable to get cards for packs: {pack_ids}') + logger.error(f'open_packs - unable to get cards for packs: {pack_ids}') raise ValueError(f'I was not able to display these cards') # Present cards to opening channel @@ -2935,7 +2935,7 @@ async def get_choice_from_cards( {'player': x, 'team': {'lname': 'Paper Dynasty', 'season': PD_SEASON, 'logo': IMAGES['logo']}} ) for x in all_players ] - logging.debug(f'card embeds: {card_embeds}') + logger.debug(f'card embeds: {card_embeds}') if cover_title is not None and cover_image_url is not None: page_num = 0 @@ -3132,7 +3132,7 @@ async def open_choice_pack(this_pack, team: dict, context, cardset_id: Optional[ rarity_id += 3 if len(players) == 0: - logging.error(f'Could not create choice pack') + logger.error(f'Could not create choice pack') raise ConnectionError(f'Could not create choice pack') if type(context) == commands.Context: @@ -3140,7 +3140,7 @@ async def open_choice_pack(this_pack, team: dict, context, cardset_id: Optional[ else: author = context.user - logging.info(f'helpers - open_choice_pack - players: {players}') + logger.info(f'helpers - open_choice_pack - players: {players}') # Display them with pagination, prev/next/select card_embeds = [ @@ -3149,7 +3149,7 @@ async def open_choice_pack(this_pack, team: dict, context, cardset_id: Optional[ {'player': x, 'team': team} # Show team and dupe info ) for x in players ] - logging.debug(f'card embeds: {card_embeds}') + logger.debug(f'card embeds: {card_embeds}') page_num = 0 view = Pagination([author], timeout=30) @@ -3182,7 +3182,7 @@ async def open_choice_pack(this_pack, team: dict, context, cardset_id: Optional[ try: await give_cards_to_team(team, players=[players[page_num - 1]], pack_id=this_pack['id']) except Exception as e: - logging.error(f'failed to create cards: {e}') + logger.error(f'failed to create cards: {e}') raise ConnectionError(f'Failed to distribute these cards.') await db_patch('packs', object_id=this_pack['id'], params=[ @@ -3282,13 +3282,13 @@ def random_gif(search_term: str): else: return data['data']['url'] else: - logging.warning(resp.text) + logger.warning(resp.text) raise ValueError(f'DB: {resp.text}') def random_from_list(data_list: list): item = data_list[random.randint(0, len(data_list) - 1)] - logging.info(f'random_from_list: {item}') + logger.info(f'random_from_list: {item}') return item diff --git a/in_game/ai_manager.py b/in_game/ai_manager.py index b684a28..d9cef19 100644 --- a/in_game/ai_manager.py +++ b/in_game/ai_manager.py @@ -24,6 +24,7 @@ db = SqliteDatabase( 'synchronous': 0 } ) +logger = logging.getLogger('discord_app') # 2018, 2024, Mario, GAUNTLET1_PARAMS = [ @@ -127,7 +128,7 @@ async def get_or_create_card(player: dict, team: dict) -> int: ]} ) if card_id is None: - logging.error(f'Could not create card for {player["p_name"]} on the {team["lname"]}') + logger.error(f'Could not create card for {player["p_name"]} on the {team["lname"]}') raise DatabaseError(f'Could not create card for {player["p_name"]} on the {team["lname"]}') return card_id @@ -166,7 +167,7 @@ async def build_lineup_graded(team_object: dict, vs_hand: str, league_name: str, this_guy = copy.deepcopy(x) rg_data = next(x for x in batter_rg if x['player_id'] == this_guy['player_id']) grading = batter_grading(vs_hand, rg_data) - logging.info(f'player: {this_guy} / grading: {grading}') + logger.info(f'player: {this_guy} / grading: {grading}') this_guy['overall'] = grading['overall'] this_guy['raw-bat'] = grading['raw-bat'] @@ -202,21 +203,21 @@ async def build_lineup_graded(team_object: dict, vs_hand: str, league_name: str, while len(players) > 0: # Sort players dict by position with fewest eligible players this_pass_data = sorted(players.items(), key=lambda item: len(item[1])) - logging.info(f'this_pass_data: {this_pass_data}') + logger.info(f'this_pass_data: {this_pass_data}') # Pull one tuple ('', []) this_pos_data = this_pass_data[0] - logging.info(f'this_pos_data: {this_pos_data}') + logger.info(f'this_pos_data: {this_pos_data}') # Sort players at this position by blended rating (raw-bat for DH) if this_pos_data[0] == 'dh': this_pos = sorted(this_pos_data[1], key=lambda item: item['raw-bat'], reverse=True) else: this_pos = sorted(this_pos_data[1], key=lambda item: item['blended'], reverse=True) - logging.info(f'this_pos: {this_pos}') + logger.info(f'this_pos: {this_pos}') # Add top player to the lineup in_lineup.append({'position': copy.deepcopy(this_pos_data[0].upper()), 'player': copy.deepcopy(this_pos[0])}) - logging.info(f'adding player: {this_pos[0]}') - logging.info(f'deleting position: {this_pos_data[0]}') + logger.info(f'adding player: {this_pos[0]}') + logger.info(f'deleting position: {this_pos_data[0]}') # Remove this position from consideration del players[this_pos_data[0]] @@ -241,7 +242,7 @@ async def build_lineup(team_object: dict, game_id: int, league_name: str, sp_nam timeout=6 ) sorted_players = l_query['array'] - logging.info(f'sorted_players: {sorted_players}') + logger.info(f'sorted_players: {sorted_players}') grp_1 = sorted_players[:3] grp_2 = sorted_players[3:6] @@ -253,9 +254,9 @@ async def build_lineup(team_object: dict, game_id: int, league_name: str, sp_nam lineups = [] i = 1 for x in [grp_1, grp_2, grp_3]: - logging.debug(f'group: {x}') + logger.debug(f'group: {x}') for y in x: - logging.debug(f'y: {y}') + logger.debug(f'y: {y}') card_id = await get_or_create_card(y[1]['player'], team_object) lineups.append({ @@ -269,7 +270,7 @@ async def build_lineup(team_object: dict, game_id: int, league_name: str, sp_nam }) i += 1 - logging.info(f'build_lineup - final lineup: {lineups}') + logger.info(f'build_lineup - final lineup: {lineups}') return lineups @@ -281,7 +282,7 @@ async def get_starting_lineup(session: Session, team: Team, game: Game, league_n timeout=6 ) sorted_players = l_query['array'] - logging.debug(f'ai_manager - get_starting_lineup - sorted_players: {sorted_players}') + logger.debug(f'ai_manager - get_starting_lineup - sorted_players: {sorted_players}') grp_1 = sorted_players[:3] grp_2 = sorted_players[3:6] @@ -293,9 +294,9 @@ async def get_starting_lineup(session: Session, team: Team, game: Game, league_n lineups = [] i = 1 for x in [grp_1, grp_2, grp_3]: - logging.debug(f'ai_manager - get_starting_lineup - group: {x}') + logger.debug(f'ai_manager - get_starting_lineup - group: {x}') for y in x: - logging.debug(f'ai_manager - get_starting_lineup - y: {y}') + logger.debug(f'ai_manager - get_starting_lineup - y: {y}') this_player = await get_player_or_none(session, get_player_id_from_dict(y[1]['player'])) this_card = await get_or_create_ai_card(session, player=this_player, team=team) @@ -309,7 +310,7 @@ async def get_starting_lineup(session: Session, team: Team, game: Game, league_n )) i += 1 - logging.debug(f'ai_manager - get_starting_lineup - final lineup: {lineups}') + logger.debug(f'ai_manager - get_starting_lineup - final lineup: {lineups}') return lineups @@ -365,13 +366,13 @@ async def get_relief_pitcher(this_play: StratPlay, ai_team: dict, league_name: s for x in used_players: used_ids.append(f'{x.player_id}') - logging.debug(f'used ids: {used_ids}') + logger.debug(f'used ids: {used_ids}') id_string = "&used_pitcher_ids=".join(used_ids) this_game = this_play.game ai_score = this_play.away_score if this_game.away_team_id == ai_team['id'] else this_play.home_score human_score = this_play.home_score if this_game.away_team_id == ai_team['id'] else this_play.away_score - logging.debug(f'scores - ai: {ai_score} / human: {human_score}') + logger.debug(f'scores - ai: {ai_score} / human: {human_score}') if abs(ai_score - human_score) >= 7: need = 'length' elif this_play.inning_num >= 9 and abs(ai_score - human_score) <= 3: @@ -383,7 +384,7 @@ async def get_relief_pitcher(this_play: StratPlay, ai_team: dict, league_name: s else: need = 'length' - logging.debug(f'need: {need}') + logger.debug(f'need: {need}') rp_query = await db_get(f'teams/{ai_team["id"]}/rp/{league_name.split("-run")[0]}' f'?need={need}&used_pitcher_ids={id_string}{get_cardset_string(this_game)}') card_id = await get_or_create_card(rp_query, ai_team) @@ -408,7 +409,7 @@ async def get_relief_pitcher(this_play: StratPlay, ai_team: dict, league_name: s # for x in used_players: # c_query = await db_get('cards', object_id=x.card_id) # used_codes.append(c_query["player"]["strat_code"]) - # logging.info(f'get_rp - used_players: {used_codes}') + # logger.info(f'get_rp - used_players: {used_codes}') # # reliever = None # attempts = 0 @@ -440,7 +441,7 @@ async def get_relief_pitcher(this_play: StratPlay, ai_team: dict, league_name: s # if attempts == 1: # # Try to get long man # if this_play.inning_num < 6: - # logging.info(f'get_rp - game {this_play.game.id} try for long man') + # logger.info(f'get_rp - game {this_play.game.id} try for long man') # params.append(('pos_include', 'SP')) # # use_best = True # @@ -448,7 +449,7 @@ async def get_relief_pitcher(this_play: StratPlay, ai_team: dict, league_name: s # elif this_play.inning_num > 8: # if (this_play.inning_half == 'top' and this_play.home_score >= this_play.away_score) or \ # (this_play.inning_half == 'bot' and this_play.away_score >= this_play.home_score): - # logging.info(f'get_rp - game {this_play.game.id} try for closer') + # logger.info(f'get_rp - game {this_play.game.id} try for closer') # params.append(('pos_include', 'CP')) # use_best = True # else: @@ -456,7 +457,7 @@ async def get_relief_pitcher(this_play: StratPlay, ai_team: dict, league_name: s # # # Try to exclude long men # elif attempts == 1: - # logging.info(f'get_rp - game {this_play.game.id} try to exclude long men') + # logger.info(f'get_rp - game {this_play.game.id} try to exclude long men') # params.append(('pos_exclude', 'SP')) # # try: @@ -466,7 +467,7 @@ async def get_relief_pitcher(this_play: StratPlay, ai_team: dict, league_name: s # timeout=10 # ) # except ConnectionError as e: - # logging.error(f'Could not get pitchers for {ai_team["lname"]}: {e}') + # logger.error(f'Could not get pitchers for {ai_team["lname"]}: {e}') # raise ConnectionError(f'Error pulling starting pitchers for the {ai_team["lname"]}. Cal help plz.') # # if pitchers['count'] > 0: @@ -519,12 +520,12 @@ async def pitching_ai_note(this_play: StratPlay, this_pitcher: dict): # # Pitcher Substitutions # new_pitcher = None # if last_inning_ender and last_inning_ender.pitcher != this_play.pitcher: - # logging.debug(f'{this_pitcher["team"]["sname"]} not making a change.') + # logger.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.') + # logger.debug(f'{this_pitcher["team"]["sname"]} going the to pen.') # # if len(used_pitchers) < 8: # make_sub(await get_relief_pitcher( @@ -607,10 +608,10 @@ async def check_pitching_sub(this_play: StratPlay, ai_team: dict): ) p_stats = get_pitching_stats(this_play.game.id, lineup_id=this_play.pitcher.id) if len(p_stats) == 0: - logging.info(f'ai_manager - check_pitching_sub: no stats recorded yet, returning None') + logger.info(f'ai_manager - check_pitching_sub: no stats recorded yet, returning None') return False ps = p_stats[0] - logging.info(f'ai_manager - check_pitching_sub: pitcher does have stats') + logger.info(f'ai_manager - check_pitching_sub: pitcher does have stats') this_ai = get_manager(this_play.game) this_pc = await data_cache.get_pd_pitchingcard(this_play.pitcher.player_id, variant=this_play.pitcher.variant) @@ -632,7 +633,7 @@ async def check_pitching_sub(this_play: StratPlay, ai_team: dict): if rp_pitcard.card.relief_rating == 1: patch_play(this_play.id, in_pow=True) except Exception as e: - logging.info(f'ai_manager - check_pitching_sub - could not pull card for {rp_lineup.player_id}') + logger.info(f'ai_manager - check_pitching_sub - could not pull card for {rp_lineup.player_id}') return await get_player(this_play.game, rp_lineup) return None @@ -655,7 +656,7 @@ async def is_pitcher_fatigued(this_play: StratPlay) -> bool: ) p_stats = get_pitching_stats(this_play.game.id, lineup_id=this_play.pitcher.id) if len(p_stats) == 0: - logging.info(f'ai_manager - is_pitcher_fatigued: no stats recorded yet, returning False') + logger.info(f'ai_manager - is_pitcher_fatigued: no stats recorded yet, returning False') return False ps = p_stats[0] @@ -665,7 +666,7 @@ async def is_pitcher_fatigued(this_play: StratPlay) -> bool: try: this_pc = await data_cache.get_pd_pitchingcard(this_play.pitcher.player_id, variant=this_play.pitcher.variant) except: - logging.info( + logger.info( f'ai_manager - is_pitcher_fatigued: could not pull pitching card for {this_play.pitcher.player_id}, ' f'returning False') return False @@ -674,45 +675,45 @@ async def is_pitcher_fatigued(this_play: StratPlay) -> bool: # Check starter fatigue if len(used_pitchers) == 1: if ps['pl_runs'] >= 7: - logging.info(f'ai_manager - is_pitcher_fatigued: starter allowed 7+, returning True') + logger.info(f'ai_manager - is_pitcher_fatigued: starter allowed 7+, returning True') return True elif ps['pl_runs'] >= 6: - logging.info(f'ai_manager - is_pitcher_fatigued: starter allowed 6+, checking for fatigue') + logger.info(f'ai_manager - is_pitcher_fatigued: starter allowed 6+, checking for fatigue') f_query = get_pitching_stats( this_play.game.id, lineup_id=this_play.pitcher.id, in_innings=[this_play.inning_num, this_play.inning_num - 1] ) if f_query[0]['pl_in_runs'] >= 6: - logging.info(f'ai_manager - is_pitcher_fatigued: starter allowed 6 in 2, returning True') + logger.info(f'ai_manager - is_pitcher_fatigued: starter allowed 6 in 2, returning True') patch_lineup(this_play.pitcher.id, is_fatigued=True) return True elif ps['pl_runs'] >= 5: - logging.info(f'ai_manager - is_pitcher_fatigued: starter allowed 5+, checking for fatigue') + logger.info(f'ai_manager - is_pitcher_fatigued: starter allowed 5+, checking for fatigue') f_query = get_pitching_stats( this_play.game.id, lineup_id=this_play.pitcher.id, in_innings=[this_play.inning_num] ) if f_query[0]['pl_in_runs'] >= 5: - logging.info(f'ai_manager - is_pitcher_fatigued: starter allowed 5 in 1, returning True') + logger.info(f'ai_manager - is_pitcher_fatigued: starter allowed 5 in 1, returning True') patch_lineup(this_play.pitcher.id, is_fatigued=True) return True innof_work = math.ceil((ps['pl_outs'] + 1) / 3) if innof_work < pof_weakness: - logging.info(f'ai_manager - is_pitcher_fatigued: not point of weakness, returning False') + logger.info(f'ai_manager - is_pitcher_fatigued: not point of weakness, returning False') return False elif innof_work == pof_weakness: patch_play(this_play.id, in_pow=True) pow_stats = get_pitching_stats(this_play.game.id, lineup_id=this_play.pitcher.id, in_pow=True) if len(pow_stats) == 0: - logging.info(f'ai_manager - is_pitcher_fatigued: in point of weakness, no stats recorded, returning False') + logger.info(f'ai_manager - is_pitcher_fatigued: in point of weakness, no stats recorded, returning False') return False pows = pow_stats[0] if pows['pl_hit'] + pows['pl_bb'] + pows['pl_hbp'] < 3: - logging.info(f'ai_manager - is_pitcher_fatigued: in point of weakness, not fatigued, returning False') + logger.info(f'ai_manager - is_pitcher_fatigued: in point of weakness, not fatigued, returning False') return False elif innof_work > pof_weakness: @@ -720,7 +721,7 @@ async def is_pitcher_fatigued(this_play: StratPlay) -> bool: patch_lineup(this_play.pitcher.id, is_fatigued=True) return True - logging.info(f'ai_manager - is_pitcher_fatigued: beyond point of weakness, fatigued, returning True') + logger.info(f'ai_manager - is_pitcher_fatigued: beyond point of weakness, fatigued, returning True') patch_lineup(this_play.pitcher.id, is_fatigued=True) return True diff --git a/in_game/data_cache.py b/in_game/data_cache.py index 88e04dc..1fedc4a 100644 --- a/in_game/data_cache.py +++ b/in_game/data_cache.py @@ -10,6 +10,7 @@ PLAYER_CACHE = {} TEAM_CACHE = {} BATTINGCARD_CACHE = {} # { : { : BattingWrapper } } PITCHINGCARD_CACHE = {} # { : { : PitchingWrapper } } +logger = logging.getLogger('discord_app') @dataclass @@ -265,19 +266,19 @@ async def get_pd_player(player_id, as_dict: Optional[bool] = True, skip_cache: b if player_id in PLAYER_CACHE and not skip_cache: tdelta = datetime.datetime.now() - PLAYER_CACHE[player_id].created if tdelta.total_seconds() < 1209600: - logging.debug(f'this_player: {PLAYER_CACHE[player_id]}') + logger.debug(f'this_player: {PLAYER_CACHE[player_id]}') if as_dict: return PLAYER_CACHE[player_id].to_dict() else: return PLAYER_CACHE[player_id] else: - logging.error(f'Refreshing player {player_id} in cache...') + logger.error(f'Refreshing player {player_id} in cache...') this_player = await db_get('players', object_id=player_id) for bad_key in ['mlbplayer', 'paperdex']: if bad_key in this_player: del this_player[bad_key] - logging.debug(f'this_player: {this_player}') + logger.debug(f'this_player: {this_player}') PLAYER_CACHE[player_id] = Player(**this_player) if as_dict: @@ -289,13 +290,13 @@ async def get_pd_team(team_or_gm_id, as_dict: bool = True, skip_cache: bool = Fa if team_or_gm_id in TEAM_CACHE and not skip_cache: tdelta = datetime.datetime.now() - TEAM_CACHE[team_or_gm_id].created if tdelta.total_seconds() < 1209600: - logging.info(f'this_team: {TEAM_CACHE[team_or_gm_id]}') + logger.info(f'this_team: {TEAM_CACHE[team_or_gm_id]}') if as_dict: return TEAM_CACHE[team_or_gm_id].to_dict() else: return TEAM_CACHE[team_or_gm_id] else: - logging.error(f'Refreshing team {team_or_gm_id} in cache...') + logger.error(f'Refreshing team {team_or_gm_id} in cache...') this_team = await db_get('teams', object_id=team_or_gm_id, params=[('inc_packs', False)]) if this_team is None: @@ -304,7 +305,7 @@ async def get_pd_team(team_or_gm_id, as_dict: bool = True, skip_cache: bool = Fa raise KeyError(f'No team found for ID {team_or_gm_id}') this_team = t_query['teams'][0] - logging.info(f'this_team: {this_team}') + logger.info(f'this_team: {this_team}') TEAM_CACHE[team_or_gm_id] = Team(**this_team) if as_dict: @@ -316,7 +317,7 @@ async def get_pd_battingcard(player_id: int, variant: Optional[int] = 0): if player_id in BATTINGCARD_CACHE and variant in BATTINGCARD_CACHE[player_id]: tdelta = datetime.datetime.now() - BATTINGCARD_CACHE[player_id][variant].created if tdelta.total_seconds() < 609600: - logging.info(f'this_battingcard: {BATTINGCARD_CACHE[player_id][variant]}') + logger.info(f'this_battingcard: {BATTINGCARD_CACHE[player_id][variant]}') return BATTINGCARD_CACHE[player_id][variant] vl_data, vr_data = None, None @@ -334,23 +335,23 @@ async def get_pd_battingcard(player_id: int, variant: Optional[int] = 0): if None in [vl_data, vr_data]: raise KeyError(f'Could not find batting card ratings for player {player_id} variant {variant}') - logging.info(f'prepping the batting card') + logger.info(f'prepping the batting card') bc_data = vl_data['battingcard'] bc_data['player_id'] = player_id del bc_data['id'], bc_data['player'] this_bc = BattingCard(**bc_data) - logging.info(f'prepping the vl ratings') + logger.info(f'prepping the vl ratings') vl_ratings = vl_data del vl_ratings['battingcard'], vl_ratings['id'], vl_ratings['vs_hand'] this_vl = BattingRatings(**vl_ratings) - logging.info(f'prepping the vl ratings') + logger.info(f'prepping the vl ratings') vr_ratings = vr_data del vr_ratings['battingcard'], vr_ratings['id'], vr_ratings['vs_hand'] this_vr = BattingRatings(**vr_ratings) - logging.info(f'prepping the wrapper') + logger.info(f'prepping the wrapper') this_wrapper = BattingWrapper( card=this_bc, ratings_vl=this_vl, @@ -369,7 +370,7 @@ async def get_pd_pitchingcard(player_id: int, variant: Optional[int] = 0): if player_id in PITCHINGCARD_CACHE and variant in PITCHINGCARD_CACHE[player_id]: tdelta = datetime.datetime.now() - PITCHINGCARD_CACHE[player_id][variant].created if tdelta.total_seconds() < 609600: - logging.debug(f'this_pitchingcard: {PITCHINGCARD_CACHE[player_id][variant]}') + logger.debug(f'this_pitchingcard: {PITCHINGCARD_CACHE[player_id][variant]}') return PITCHINGCARD_CACHE[player_id][variant] vl_data, vr_data = None, None @@ -387,23 +388,23 @@ async def get_pd_pitchingcard(player_id: int, variant: Optional[int] = 0): if None in [vl_data, vr_data]: raise KeyError(f'Could not find pitching card ratings for player {player_id} variant {variant}') - logging.debug(f'prepping the pitching card') + logger.debug(f'prepping the pitching card') pc_data = vl_data['pitchingcard'] pc_data['player_id'] = player_id del pc_data['id'], pc_data['player'] this_pc = PitchingCard(**pc_data) - logging.debug(f'prepping the vl ratings') + logger.debug(f'prepping the vl ratings') vl_ratings = vl_data del vl_ratings['pitchingcard'], vl_ratings['id'], vl_ratings['vs_hand'] this_vl = PitchingRatings(**vl_ratings) - logging.debug(f'prepping the vr ratings') + logger.debug(f'prepping the vr ratings') vr_ratings = vr_data del vr_ratings['pitchingcard'], vr_ratings['id'], vr_ratings['vs_hand'] this_vr = PitchingRatings(**vr_ratings) - logging.debug(f'prepping the wrapper') + logger.debug(f'prepping the wrapper') this_wrapper = PitchingWrapper( card=this_pc, ratings_vl=this_vl, diff --git a/in_game/game_helpers.py b/in_game/game_helpers.py index fa5db1f..7478fa0 100644 --- a/in_game/game_helpers.py +++ b/in_game/game_helpers.py @@ -12,6 +12,7 @@ from helpers import Pagination, get_team_embed, image_embed, Confirm from typing import Literal, Optional PUBLIC_FIELDS_CATEGORY_NAME = 'Public Fields' +logger = logging.getLogger('discord_app') def single_onestar(this_play: StratPlay, comp_play: bool = True): @@ -58,12 +59,12 @@ async def next_pitcher(this_play: StratPlay, ai_team, bot): used_pitchers = await get_team_lineups( game_id=this_play.game.id, team_id=ai_team['id'], inc_inactive=True, pitchers_only=True, as_string=False ) - logging.debug(f'\n\nused_pitchers: {used_pitchers}') + logger.debug(f'\n\nused_pitchers: {used_pitchers}') used_ids = [x.card_id for x in used_pitchers] - logging.debug(f'used_ids: {used_ids}') + logger.debug(f'used_ids: {used_ids}') bullpen = get_or_create_bullpen(ai_team, bot) - logging.debug(f'bullpen: {bullpen}') + logger.debug(f'bullpen: {bullpen}') if this_play.game.short_game: if this_play.inning_num == 1: @@ -124,7 +125,7 @@ def starting_pitcher(ai_team, bot, is_home): rotation_range = f'I4:I8' raw_cells = r_sheet.range(rotation_range) d_100 = random.randint(1, 100) - logging.info(f'raw_cells: {raw_cells} / d_100: {d_100}') + logger.info(f'raw_cells: {raw_cells} / d_100: {d_100}') if is_home: if d_100 <= 30: @@ -195,7 +196,7 @@ async def show_outfield_cards(interaction: discord.Interaction, this_play: Strat this_play.game.id, team_id=this_play.pitcher.team_id, position='RF', active=True )) this_team = await db_get('teams', object_id=this_play.pitcher.team_id) - logging.debug(f'lf: {lf_player}\n\ncf: {cf_player}\n\nrf: {rf_player}\n\nteam: {this_team["lname"]}') + logger.debug(f'lf: {lf_player}\n\ncf: {cf_player}\n\nrf: {rf_player}\n\nteam: {this_team["lname"]}') view = Pagination([interaction.user], timeout=6) view.left_button.label = f'Left Fielder' @@ -275,14 +276,14 @@ def runner_on_third(this_play: StratPlay): def gb_result_1(this_play: StratPlay) -> Optional[int]: - logging.info(f'GB 1') + logger.info(f'GB 1') advance_runners(this_play.id, num_bases=0) patch_play(this_play.id, pa=1, ab=1, outs=1) return None def gb_result_2(this_play: StratPlay) -> Optional[int]: - logging.info(f'GB 2') + logger.info(f'GB 2') num_outs = 2 if this_play.starting_outs <= 1 else 1 patch_play(this_play.id, pa=1, ab=1, outs=num_outs, on_first_final=False) @@ -296,7 +297,7 @@ def gb_result_2(this_play: StratPlay) -> Optional[int]: def gb_result_3(this_play: StratPlay) -> Optional[int]: - logging.info(f'GB 3') + logger.info(f'GB 3') if this_play.starting_outs < 2: advance_runners(this_play.id, num_bases=1) patch_play(this_play.id, pa=1, ab=1, outs=1) @@ -304,7 +305,7 @@ def gb_result_3(this_play: StratPlay) -> Optional[int]: def gb_result_4(this_play: StratPlay) -> Optional[int]: - logging.info(f'GB 4') + logger.info(f'GB 4') patch_play(this_play.id, pa=1, ab=1, outs=1, on_first_final=False) if this_play.starting_outs < 2: if runner_on_second(this_play): @@ -316,7 +317,7 @@ def gb_result_4(this_play: StratPlay) -> Optional[int]: def gb_result_5(this_play: StratPlay, to_mif: bool) -> Optional[int]: - logging.info(f'GB 5') + logger.info(f'GB 5') patch_play(this_play.id, pa=1, ab=1, outs=1) if to_mif: gb_result_3(this_play) @@ -327,7 +328,7 @@ def gb_result_5(this_play: StratPlay, to_mif: bool) -> Optional[int]: def gb_result_6(this_play: StratPlay, to_right_side: bool) -> Optional[int]: - logging.info(f'GB 6') + logger.info(f'GB 6') patch_play(this_play.id, pa=1, ab=1, outs=1) if to_right_side: gb_result_3(this_play) @@ -338,24 +339,24 @@ def gb_result_6(this_play: StratPlay, to_right_side: bool) -> Optional[int]: def gb_result_7(this_play: StratPlay) -> Optional[int]: - logging.info(f'GB 7') + logger.info(f'GB 7') patch_play(this_play.id, pa=1, ab=1, outs=1) advance_runners(this_play.id, num_bases=1, only_forced=True) return None def gb_result_8(this_play: StratPlay) -> Optional[int]: - logging.info(f'GB 8') + logger.info(f'GB 8') return gb_result_7(this_play) def gb_result_9(this_play: StratPlay) -> Optional[int]: - logging.info(f'GB 9') + logger.info(f'GB 9') return gb_result_7(this_play) def gb_result_10(this_play: StratPlay) -> Optional[int]: - logging.info(f'GB 10') + logger.info(f'GB 10') num_outs = 2 if this_play.starting_outs <= 1 else 1 patch_play(this_play.id, pa=1, ab=1, outs=num_outs, on_third_final=False) advance_one_runner(this_play.id, from_base=2, num_bases=1) @@ -365,13 +366,13 @@ def gb_result_10(this_play: StratPlay) -> Optional[int]: def gb_result_11(this_play: StratPlay) -> Optional[int]: - logging.info(f'GB 11') + logger.info(f'GB 11') patch_play(this_play.id, pa=1, ab=1, outs=1, on_first_final=2, on_second_final=3, on_third_final=False) return 1 async def gb_decide(this_play: StratPlay, interaction: discord.Interaction, runner: dict, from_base: int): - logging.info(f'GB Decide') + logger.info(f'GB Decide') ai_is_batting = ai_batting(this_play.game, this_play) ai_manager = get_manager(this_play.game) bases = ['first', 'second', 'third'] @@ -445,7 +446,7 @@ async def gb_decide(this_play: StratPlay, interaction: discord.Interaction, runn async def gb_result_12(this_play: StratPlay, defender: Literal['1b-2b', '3b', 'ss-p-c'], interaction: discord.Interaction) -> Optional[int]: - logging.info(f'GB 12') + logger.info(f'GB 12') if defender == '1b-2b': return gb_result_3(this_play) elif defender == '3b': @@ -457,7 +458,7 @@ async def gb_result_12(this_play: StratPlay, defender: Literal['1b-2b', '3b', 's def gb_result_13(this_play: StratPlay, defender: Literal['c-3b', 'else']) -> Optional[int]: - logging.info(f'GB 13') + logger.info(f'GB 13') if defender == 'c-3b': num_outs = 2 if this_play.starting_outs <= 1 else 1 patch_play(this_play.id, on_second_final=False, on_first_final=False, pa=1, ab=1, outs=num_outs) diff --git a/in_game/gameplay_models.py b/in_game/gameplay_models.py index bfc0a08..809d440 100644 --- a/in_game/gameplay_models.py +++ b/in_game/gameplay_models.py @@ -13,10 +13,13 @@ from exceptions import * from in_game.managerai_responses import JumpResponse, TagResponse, ThrowResponse, UncappedRunResponse +logger = logging.getLogger('discord_app') sqlite_url = 'sqlite:///storage/gameplay.db' connect_args = {"check_same_thread": False} engine = create_engine(sqlite_url, echo=False, connect_args=connect_args) CACHE_LIMIT = 1209600 # in seconds +SBA_COLOR = 'a6ce39' +SBA_LOGO = 'https://sombaseball.ddns.net/static/images/sba-logo.png' class ManagerAiBase(SQLModel): @@ -74,6 +77,16 @@ class Team(TeamBase, table=True): lineups: list['Lineup'] = Relationship(back_populates='team', cascade_delete=True) # away_games: list['Game'] = Relationship(back_populates='away_team') # home_games: list['Game'] = Relationship(back_populates='home_team') + + @property + def embed(self) -> discord.Embed: + embed = discord.Embed( + title=f'{self.lname}', + color=int(self.color, 16) if self.color else int(SBA_COLOR, 16) + ) + embed.set_footer(text=f'Paper Dynasty Season {self.season}', icon_url=SBA_LOGO) + embed.set_thumbnail(url=self.logo if self.logo else SBA_LOGO) + return embed class Game(SQLModel, table=True): @@ -86,7 +99,7 @@ class Game(SQLModel, table=True): is_pd: bool | None = Field(default=True) ranked: bool | None = Field(default=False) short_game: bool | None = Field(default=False) - week_num: int | None = Field(default=None) + week: int | None = Field(default=None) game_num: int | None = Field(default=None) away_roster_id: int | None = Field(default=None) home_roster_id: int | None = Field(default=None) @@ -148,11 +161,11 @@ class Game(SQLModel, table=True): gt_string = ' - Flashback' elif 'exhibition' in self.game_type: gt_string = ' - Exhibition' - logging.info(f'gameplay_models - Game.get_scorebug_embed - this_game: {self} / gt_string: {gt_string}') + logger.info(f'gameplay_models - Game.get_scorebug_embed - this_game: {self} / gt_string: {gt_string}') embed = discord.Embed( title=f'{self.away_team.sname} @ {self.home_team.sname}{gt_string}', - color=int('a6ce39', 16) + color=int(SBA_COLOR, 16) ) curr_play = self.current_play_or_none(session) @@ -161,7 +174,7 @@ class Game(SQLModel, table=True): try: curr_play = self.initialize_play(session) except LineupsMissingException as e: - logging.debug(f'gameplay_models - Game.get_scorebug_embed - Could not initialize play') + logger.debug(f'gameplay_models - Game.get_scorebug_embed - Could not initialize play') if curr_play is not None: embed.add_field( @@ -187,7 +200,7 @@ class Game(SQLModel, table=True): baserunner_string += f'On Second: {curr_play.on_second.player.name_card_link('batting')}\n' if curr_play.on_third is not None: baserunner_string += f'On Third: {curr_play.on_third.player.name_card_link('batting')}' - logging.info(f'gameplay_models - Game.get_scorebug_embed - baserunner_string: {baserunner_string}') + logger.info(f'gameplay_models - Game.get_scorebug_embed - baserunner_string: {baserunner_string}') if len(baserunner_string) > 0: embed.add_field(name=' ', value=' ', inline=False) @@ -195,7 +208,7 @@ class Game(SQLModel, table=True): embed.add_field(name='Catcher', value=curr_play.catcher.player.name_card_link('batter')) ai_note = curr_play.ai_note - logging.info(f'gameplay_models - Game.get_scorebug_embed - ai_note: {ai_note}') + logger.info(f'gameplay_models - Game.get_scorebug_embed - ai_note: {ai_note}') if len(ai_note) > 0: gm_name = self.home_team.gmname if self.ai_team == 'home' else self.away_team.gmname embed.add_field(name=f'{gm_name} will...', value=ai_note, inline=False) @@ -300,7 +313,7 @@ class ManagerAi(ManagerAiBase, table=True): def get_new_ai(this_session: Session): all_ai = this_session.exec(select(ManagerAi.id)).all() if len(all_ai) == 0: - logging.info(f'Creating ManagerAI records') + logger.info(f'Creating ManagerAI records') new_ai = [ ManagerAi( name='Balanced' @@ -560,7 +573,7 @@ class PlayerBase(SQLModel): elif self.image2 is not None and 'pitching' in self.image2: return self.image2 else: - logging.error(f'gameplay_models - PlayerBase - pitching card url not found for {self.id}. {self.description} {self.name}') + logger.error(f'gameplay_models - PlayerBase - pitching card url not found for {self.id}. {self.description} {self.name}') return self.image @property @@ -570,7 +583,7 @@ class PlayerBase(SQLModel): elif self.image2 is not None and 'batting' in self.image2: return self.image2 else: - logging.error(f'gameplay_models - PlayerBase - batting card url not found for {self.id}. {self.description} {self.name}') + logger.error(f'gameplay_models - PlayerBase - batting card url not found for {self.id}. {self.description} {self.name}') return self.image def name_card_link(self, which: Literal['pitching', 'batting']): @@ -593,7 +606,7 @@ class Player(PlayerBase, table=True): def player_description(player: Player = None, player_dict: dict = None) -> str: if player is None and player_dict is None: err = 'One of "player" or "player_dict" must be included to get full description' - logging.error(f'gameplay_models - player_description - {err}') + logger.error(f'gameplay_models - player_description - {err}') raise TypeError(err) if player is not None: diff --git a/in_game/gameplay_queries.py b/in_game/gameplay_queries.py index 3365345..fb2202b 100644 --- a/in_game/gameplay_queries.py +++ b/in_game/gameplay_queries.py @@ -1,23 +1,47 @@ import datetime import logging +import math +import pydantic from sqlalchemy import func from api_calls import db_get, db_post from in_game.gameplay_models import CACHE_LIMIT, Card, CardBase, Lineup, Player, PlayerBase, Session, Team, TeamBase, select, or_, Game, Play -from exceptions import log_exception, PlayNotFoundException +from exceptions import DatabaseError, log_exception, PlayNotFoundException + + +logger = logging.getLogger('discord_app') + + +class DecisionModel(pydantic.BaseModel): + game_id: int + season: int + week: int + pitcher_id: int + pitcher_team_id: int + win: int = 0 + loss: int = 0 + hold: int = 0 + is_save: int = 0 + is_start: bool = False + b_save: int = 0 + irunners: int = 0 + irunners_scored: int = 0 + rest_ip: float = 0 + rest_required: int = 0 + game_finished: int = 0 def get_games_by_channel(session: Session, channel_id: int) -> list[Game]: - logging.info(f'Getting games in channel {channel_id}') + logger.info(f'Getting games in channel {channel_id}') return session.exec(select(Game).where(Game.channel_id == channel_id, Game.active)).all() def get_channel_game_or_none(session: Session, channel_id: int) -> Game | None: - logging.info(f'Getting one game from channel {channel_id}') + logger.info(f'Getting one game from channel {channel_id}') all_games = get_games_by_channel(session, channel_id) if len(all_games) > 1: err = 'Too many games found in get_channel_game_or_none' - logging.error(f'cogs.gameplay - get_channel_game_or_none - channel_id: {channel_id} / {err}') + logger.error(f'cogs.gameplay - get_channel_game_or_none - channel_id: {channel_id} / {err}') raise Exception(err) elif len(all_games) == 0: return None @@ -25,16 +49,16 @@ def get_channel_game_or_none(session: Session, channel_id: int) -> Game | None: def get_active_games_by_team(session: Session, team: Team) -> list[Game]: - logging.info(f'Getting game for team {team.lname}') + logger.info(f'Getting game for team {team.lname}') return session.exec(select(Game).where(Game.active, or_(Game.away_team_id == team.id, Game.home_team_id == team.id))).all() async def get_team_or_none( session: Session, team_id: int | None = None, gm_id: int | None = None, team_abbrev: str | None = None, skip_cache: bool = False) -> Team | None: - logging.info(f'Getting team or none / team_id: {team_id} / gm_id: {gm_id} / team_abbrev: {team_abbrev} / skip_cache: {skip_cache}') + logger.info(f'Getting team or none / team_id: {team_id} / gm_id: {gm_id} / team_abbrev: {team_abbrev} / skip_cache: {skip_cache}') if team_id is None and gm_id is None and team_abbrev is None: err = 'One of "team_id", "gm_id", or "team_abbrev" must be included in search' - logging.error(f'gameplay_models - get_team - {err}') + logger.error(f'gameplay_models - get_team - {err}') raise TypeError(err) if not skip_cache: @@ -48,9 +72,9 @@ async def get_team_or_none( this_team = session.exec(statement).one_or_none() if this_team is not None: - logging.debug(f'we found a team: {this_team} / created: {this_team.created}') + logger.debug(f'we found a team: {this_team} / created: {this_team.created}') tdelta = datetime.datetime.now() - this_team.created - logging.debug(f'tdelta: {tdelta}') + logger.debug(f'tdelta: {tdelta}') if tdelta.total_seconds() < CACHE_LIMIT: return this_team else: @@ -58,11 +82,11 @@ async def get_team_or_none( session.commit() def cache_team(json_data: dict) -> Team: - # logging.info(f'gameplay_models - get_team - cache_team - writing a team to cache: {json_data}') + # logger.info(f'gameplay_models - get_team - cache_team - writing a team to cache: {json_data}') valid_team = TeamBase.model_validate(json_data, from_attributes=True) - # logging.info(f'gameplay_models - get_team - cache_team - valid_team: {valid_team}') + # logger.info(f'gameplay_models - get_team - cache_team - valid_team: {valid_team}') db_team = Team.model_validate(valid_team) - # logging.info(f'gameplay_models - get_team - cache_team - db_team: {db_team}') + # logger.info(f'gameplay_models - get_team - cache_team - db_team: {db_team}') session.add(db_team) session.commit() session.refresh(db_team) @@ -89,14 +113,14 @@ async def get_team_or_none( async def get_player_or_none(session: Session, player_id: int, skip_cache: bool = False) -> Player | None: - logging.info(f'gameplay_models - get_player_or_none - player_id: {player_id}') + logger.info(f'gameplay_models - get_player_or_none - player_id: {player_id}') if not skip_cache: this_player = session.get(Player, player_id) if this_player is not None: - logging.info(f'we found a cached player: {this_player} / created: {this_player.created}') + logger.info(f'we found a cached player: {this_player} / created: {this_player.created}') tdelta = datetime.datetime.now() - this_player.created - logging.debug(f'tdelta: {tdelta}') + logger.debug(f'tdelta: {tdelta}') if tdelta.total_seconds() < CACHE_LIMIT: return this_player else: @@ -104,7 +128,7 @@ async def get_player_or_none(session: Session, player_id: int, skip_cache: bool session.commit() def cache_player(json_data: dict) -> Player: - logging.info(f'gameplay_models - get_player_or_none - cache_player - caching player data: {json_data}') + logger.info(f'gameplay_models - get_player_or_none - cache_player - caching player data: {json_data}') valid_player = PlayerBase.model_validate(json_data, from_attributes=True) db_player = Player.model_validate(valid_player) session.add(db_player) @@ -124,32 +148,39 @@ async def get_player_or_none(session: Session, player_id: int, skip_cache: bool def get_player_id_from_dict(json_data: dict) -> int: - logging.info(f'Getting player from dict {json_data}') + logger.info(f'Getting player from dict {json_data}') if 'player_id' in json_data: return json_data['player_id'] elif 'id' in json_data: return json_data['id'] - err = 'Player ID could not be extracted from json data' - logging.error(f'{err}: {json_data}') - raise KeyError(err) + log_exception(KeyError, 'Player ID could not be extracted from json data') + + +def get_player_name_from_dict(json_data: dict) -> str: + logger.info(f'Getting player from dict {json_data}') + if 'name' in json_data: + return json_data['name'] + elif 'p_name' in json_data: + return json_data['p_name'] + log_exception(KeyError, 'Player name could not be extracted from json data') async def get_or_create_ai_card(session: Session, player: Player, team: Team, skip_cache: bool = False, dev_mode: bool = False) -> Card: - logging.info(f'Getting or creating card for {player.name_with_desc} on the {team.sname}') + logger.info(f'Getting or creating card for {player.name_with_desc} on the {team.sname}') if not team.is_ai: err = f'Cannot create AI cards for human teams' - logging.error(f'gameplay_models - get_or_create_ai_card: {err}') + logger.error(f'gameplay_models - get_or_create_ai_card: {err}') raise TypeError(err) - logging.info(f'gameplay_models - get_or_create_ai_card - player.id: {player.id} / team.id: {team.id}') + logger.info(f'gameplay_models - get_or_create_ai_card - player.id: {player.id} / team.id: {team.id}') if not skip_cache: c_query = session.exec(select(Card).where(Card.player == player, Card.team == team)).all() if len(c_query) > 0: this_card = c_query[0] - logging.info(f'we found a cached card: {this_card} / created: {this_card.created}') + logger.info(f'we found a cached card: {this_card} / created: {this_card.created}') tdelta = datetime.datetime.now() - this_card.created - logging.debug(f'tdelta: {tdelta}') + logger.debug(f'tdelta: {tdelta}') if tdelta.total_seconds() < CACHE_LIMIT: return this_card else: @@ -160,7 +191,7 @@ async def get_or_create_ai_card(session: Session, player: Player, team: Team, sk c_query = await db_get('cards', params=[('team_id', t.id), ('player_id', p.id)]) if c_query['count'] > 0: json_data = c_query['cards'][0] - logging.info(f'gameplay_models - get_or_create_ai_card - pull_card - caching json_data: {json_data}') + logger.info(f'gameplay_models - get_or_create_ai_card - pull_card - caching json_data: {json_data}') json_data['team_id'] = json_data['team']['id'] json_data['player_id'] = get_player_id_from_dict(json_data['player']) valid_card = CardBase.model_validate(c_query['cards'][0], from_attributes=True) @@ -176,7 +207,7 @@ async def get_or_create_ai_card(session: Session, player: Player, team: Team, sk if this_card is not None: return this_card - logging.info(f'gameplay_models - get_or_create_ai_card: creating {player.description} {player.name} card for {team.abbrev}') + logger.info(f'gameplay_models - get_or_create_ai_card: creating {player.description} {player.name} card for {team.abbrev}') if dev_mode: this_card = Card(player=player, team=team) @@ -197,19 +228,19 @@ async def get_or_create_ai_card(session: Session, player: Player, team: Team, sk return this_card err = f'Could not create {player.name} card for {team.abbrev}' - logging.error(f'gameplay_models - get_or_create_ai_card - {err}') + logger.error(f'gameplay_models - get_or_create_ai_card - {err}') raise LookupError(err) async def get_card_or_none(session: Session, card_id: int, skip_cache: bool = False) -> Card | None: - logging.info(f'Getting card {card_id}') + logger.info(f'Getting card {card_id}') if not skip_cache: this_card = session.get(Card, card_id) if this_card is not None: - logging.info(f'we found a cached card: {this_card} / created: {this_card.created}') + logger.info(f'we found a cached card: {this_card} / created: {this_card.created}') tdelta = datetime.datetime.now() - this_card.created - logging.debug(f'tdelta: {tdelta}') + logger.debug(f'tdelta: {tdelta}') if tdelta.total_seconds() < CACHE_LIMIT: return this_card else: @@ -243,7 +274,7 @@ async def get_card_or_none(session: Session, card_id: int, skip_cache: bool = Fa def get_game_lineups(session: Session, this_game: Game, specific_team: Team = None, is_active: bool = None) -> list[Lineup]: - logging.info(f'Getting lineups for game {this_game.id} / specific_team: {specific_team} / is_active: {is_active}') + logger.info(f'Getting lineups for game {this_game.id} / specific_team: {specific_team} / is_active: {is_active}') st = select(Lineup).where(Lineup.game == this_game) if specific_team is not None: @@ -255,7 +286,7 @@ def get_game_lineups(session: Session, this_game: Game, specific_team: Team = No def get_players_last_pa(session: Session, lineup_member: Lineup, none_okay: bool = False): - logging.info(f'Getting last AB for {lineup_member.player.name_with_desc} on the {lineup_member.team.lname}') + logger.info(f'Getting last AB for {lineup_member.player.name_with_desc} on the {lineup_member.team.lname}') last_pa = session.exec(select(Play).where(Play.game == lineup_member.game, Play.batter == lineup_member).order_by(Play.id.desc()).limit(1)).all() if len(last_pa) == 1: return last_pa[0] @@ -267,7 +298,7 @@ def get_players_last_pa(session: Session, lineup_member: Lineup, none_okay: bool def get_one_lineup(session: Session, this_game: Game, this_team: Team, active: bool = True, position: str = None, batting_order: int = None) -> Lineup: - logging.info(f'Getting one lineup / this_game: {this_game.id} / this_team: {this_team.lname} / active: {active}, position: {position}, batting_order: {batting_order}') + logger.info(f'Getting one lineup / this_game: {this_game.id} / this_team: {this_team.lname} / active: {active}, position: {position}, batting_order: {batting_order}') if position is None and batting_order is None: raise KeyError('Position or batting order must be provided for get_one_lineup') @@ -281,7 +312,7 @@ def get_one_lineup(session: Session, this_game: Game, this_team: Team, active: b def get_last_team_play(session: Session, this_game: Game, this_team: Team, none_okay: bool = False): - logging.info(f'Getting last play for the {this_team.lname} in game {this_game.id}') + logger.info(f'Getting last play for the {this_team.lname} in game {this_game.id}') last_play = session.exec(select(Play).join(Lineup, onclause=Lineup.id == Play.batter_id).where(Play.game == this_game, Lineup.team == this_team).order_by(Play.id.desc()).limit(1)).all() if len(last_play) == 1: @@ -294,7 +325,7 @@ def get_last_team_play(session: Session, this_game: Game, this_team: Team, none_ def get_sorted_lineups(session: Session, this_game: Game, this_team: Team) -> list[Lineup]: - logging.info(f'Getting sorted lineups for the {this_team.lname} in game {this_game.id}') + logger.info(f'Getting sorted lineups for the {this_team.lname} in game {this_game.id}') custom_order = {'P': 1, 'C': 2, '1B': 3, '2B': 4, '3B': 5, 'SS': 6, 'LF': 7, 'CF': 8, 'RF': 9} all_lineups = session.exec(select(Lineup).where(Lineup.game == this_game, Lineup.active == True, Lineup.team == this_team)).all() @@ -302,3 +333,254 @@ def get_sorted_lineups(session: Session, this_game: Game, this_team: Team) -> li sorted_lineups = sorted(all_lineups, key=lambda x: custom_order.get(x.position, float('inf'))) return sorted_lineups + +def get_db_ready_plays(session: Session, this_game: Game, db_game_id: int): + logger.info(f'Getting db ready plays for game {this_game.id}') + all_plays = session.exec(select(Play).where(Play.game == this_game)).all() + + obc_list = ['000', '001', '010', '100', '011', '101', '110', '111'] + + return_plays = [] + for play in all_plays: + dump = play.model_dump() + dump['game_id'] = db_game_id + dump['on_base_code'] = obc_list[play.on_base_code] + dump['batter_id'] = play.batter.player.id + dump['pitcher_id'] = play.pitcher.player.id + dump['catcher_id'] = play.catcher.player.id + if 'runner_id' in dump and dump['runner_id'] is not None: + dump['runner_id'] = play.runner.player.id + if 'defender_id' in dump and dump['defender_id'] is not None: + dump['defender_id'] = play.defender.player.id + if 'on_first_id' in dump and dump['on_first_id'] is not None: + dump['on_first_id'] = play.on_first.player.id + if 'on_second_id' in dump and dump['on_second_id'] is not None: + dump['on_second_id'] = play.on_second.player.id + if 'on_third_id' in dump and dump['on_third_id'] is not None: + dump['on_third_id'] = play.on_third.player.id + return_plays.append(dump) + + return {'plays': return_plays} + + +def get_db_ready_decisions(session: Session, this_game: Game, db_game_id: int) -> list[DecisionModel]: + logger.info(f'Game {this_game.id} | Getting db ready decisions for game {this_game.id}') + winner = None + loser = None + save = None + away_starter = None + home_starter = None + away_finisher = None + home_finisher = None + b_save = [] + holds = [] + + away_pitcher = None + home_pitcher = None + + decisions = { + # { : DecisionModel } + } + + final_inning = session.exec(select(func.max(Play.inning_num)).where(Play.game == this_game)).one() + + # Get starting pitchers and update this as a pointer for the play crawl + for play in session.exec(select(Play).where(Play.game == this_game)).all(): + logger.info(f'Game {this_game.id} | Crawling play #{play.play_num}') + runs_scored = 0 + if play.inning_half == 'top': + if home_starter is None: + logger.info(f'Game {this_game.id} | Setting home starter to {play.pitcher.player.name_with_desc} on play #{play.play_num}') + home_starter = play.pitcher + + if home_finisher is None: + logger.info(f'Game {this_game.id} | Setting home finisher to {play.pitcher.player.name_with_desc} on play #{play.play_num}') + home_finisher = play.pitcher + + if home_pitcher != play.pitcher: + logger.info(f'Game {this_game.id} | Setting home pitcher to {play.pitcher.player.name_with_desc} on play #{play.play_num}') + home_pitcher = play.pitcher + + if save == play.pitcher: + if play.home_score > play.away_score: + if play.pitcher not in holds: + logger.info(f'Game {this_game.id} | Appending {play.pitcher.player.name_with_desc} to holds on play #{play.play_num}') + holds.append(play.pitcher) + else: + if play.pitcher not in b_save: + logger.info(f'Game {this_game.id} | Appending {play.pitcher.player.name_with_desc} to blown saves on play #{play.play_num}') + b_save.append(play.pitcher) + + elif play.home_score > play.away_score and play.home_score - play.away_score <= 3 and home_pitcher != home_starter and play.inning_num + 2 >= final_inning: + logger.info(f'Game {this_game.id} | Setting {play.pitcher.player.name_with_desc} to save on play #{play.play_num}') + save = home_pitcher + + elif play.inning_half == 'bot': + if away_starter is None: + logger.info(f'Game {this_game.id} | Setting away starter to {play.pitcher.player.name_with_desc} on play #{play.play_num}') + away_starter = play.pitcher + + if away_finisher is None: + logger.info(f'Game {this_game.id} | Setting away finisher to {play.pitcher.player.name_with_desc} on play #{play.play_num}') + away_finisher = play.pitcher + + if away_pitcher != play.pitcher: + logger.info(f'Game {this_game.id} | Setting away pitcher to {play.pitcher.player.name_with_desc} on play #{play.play_num}') + away_pitcher = play.pitcher + + if save == play.pitcher: + if play.away_score > play.home_score: + if play.pitcher not in holds: + logger.info(f'Game {this_game.id} | Appending {play.pitcher.player.name_with_desc} to holds on play #{play.play_num}') + holds.append(play.pitcher) + else: + if play.pitcher not in b_save: + logger.info(f'Game {this_game.id} | Appending {play.pitcher.player.name_with_desc} to blown saves on play #{play.play_num}') + b_save.append(play.pitcher) + + if play.is_go_ahead: + run_diff = play.home_score - play.away_score + for x in [play.on_first_final, play.on_second_final, play.on_third_final, play.batter_final]: + runs_scored += 1 if x == 4 else 0 + + if play.inning_half == 'top': + run_diff -= runs_scored + else: + run_diff += runs_scored + + logger.info(f'run_diff for go-ahead: {run_diff}') + logger.info(f'go-ahead play: {play}') + count = 1 + + for runner, dest in [(play.on_third, play.on_third_final), (play.on_second, play.on_second_final), (play.on_first, play.on_first_final), (play.batter, play.batter_final)]: + logger.info(f'Game {this_game.id} | Looking for go-ahead runner / runner, dest: {runner}, {dest} / count: {count}') + if dest == 4 and count == abs(run_diff): + winning_play = get_players_last_pa(session, runner) + + loser = winning_play.pitcher + logger.info(f'Game {this_game.id} | Setting loser to {loser} on play #{play.play_num}') + + if save == loser: + logger.info(f'Game {this_game.id} | Appending {loser} to blown saves on play #{play.play_num}') + b_save.append(loser) + + winner = home_pitcher if play.inning_half == 'bot' else away_pitcher + logger.info(f'Game {this_game.id} | Setting winner to {winner} on play #{play.play_num}') + break + + count += 1 + + if winner is None: + logger.info(f'Game {this_game.id} | Setting winner to {winner} by default on play #{play.play_num}') + winner = home_pitcher if play.inning_half == 'bot' else away_pitcher + + if loser is None: + logger.info(f'Game {this_game.id} | Setting loser to {loser} by default on play #{play.play_num}') + loser = play.pitcher + + if play.is_tied and runs_scored == 0: + logger.info(f'Game {this_game.id} | Clearing winner and loser on play #{play.play_num}') + winner, loser = None, None + + if save is not None: + logger.info(f'Game {this_game.id} | Appending current save pitcher {save.player.name_with_desc} to blown saves and clearing save on play #{play.play_num}') + b_save.append(save) + save = None + + if play.pitcher_id not in decisions: + logger.info(f'Game {this_game.id} | Adding {play.pitcher.player.name} to decisions dict on play #{play.play_num}') + decisions[play.pitcher.player_id] = DecisionModel( + game_id=db_game_id, + season=this_game.season, + week=0 if this_game.week is None else this_game.week, + pitcher_id=play.pitcher.player_id, + pitcher_team_id=play.pitcher.team_id + ) + + logger.info(f'winner: {winner} / loser: {loser}') + decisions[winner.player_id].win = 1 + decisions[loser.player_id].loss = 1 + decisions[away_starter.player_id].is_start = True + decisions[home_starter.player_id].is_start = True + decisions[away_finisher.player_id].game_finished = 1 + decisions[home_finisher.player_id].game_finished = 1 + + for lineup in holds: + decisions[lineup.player_id].hold = 1 + + if save is not None: + decisions[save.player_id].is_save = 1 + decisions[save.player_id].hold = 0 + + for lineup in b_save: + decisions[lineup.player_id].b_save = 1 + decisions[lineup.player_id].save = 0 + + return [x.model_dump() for x in decisions.values()] + + +async def post_game_rewards(session: Session, winning_team: Team, losing_team: Team, this_game: Game): + wr_query = await db_get( + 'gamerewards', params=[('name', f'{"Short" if this_game.short_game else "Full"} Game Win')]) + lr_query = await db_get( + 'gamerewards', params=[('name', f'{"Short" if this_game.short_game else "Full"} Game Loss')]) + if not wr_query['count'] or not lr_query['count']: + raise DatabaseError(f'Game rewards were not found. Leaving this game active.') + + win_reward = wr_query['gamerewards'][0] + loss_reward = lr_query['gamerewards'][0] + win_string = f'1x {win_reward["pack_type"]["name"]} Pack\n' + + # Post Campaign Team Choice packs + if this_game.ai_team is not None and losing_team.is_ai and 'gauntlet' not in this_game.game_type and not this_game.short_game: + g_query = await db_get('games', params=[('team1_id', winning_team.id), ('season', this_game.season), ('forfeit', False)]) + + win_points = 0 + for x in g_query['games']: + if (x['away_score'] > x['home_score'] and x['away_team']['id'] == winning_team.id) or (x['home_score'] > x['away_score'] and x['home_team']['id'] == winning_team.id): + if x['game_type'] == 'minor-league': + win_points += 1 + + elif x['game_type'] in ['major-league', 'flashback']: + win_points += 2 + + elif x['game_type'] == 'hall-of-fame': + win_points += 3 + + if this_game.game_type == 'minor-league': + this_game_points = 1 + elif this_game.game_type in ['major-league', 'flashback']: + this_game_points = 2 + else: + this_game_points = 3 + + pre_game_points = win_points - this_game_points + if math.floor(win_points / 6) > math.floor(pre_game_points / 6): + await db_post('packs/one', payload={ + 'team_id': winning_team.id, + 'pack_type_id': 8, + 'pack_team_id': losing_team.id + }) + win_string += f'1x {losing_team.abbrev} Team Choice pack\n' + + win_string += f'{win_reward["money"]}₼\n' + loss_string = f'{loss_reward["money"]}₼\n' + + if 'gauntlet' in this_game.game_type: + winning_abbrev = winning_team.abbrev.lower() + if 'gauntlet' in winning_abbrev: + winning_team = await get_team_or_none(session, team_abbrev=winning_abbrev.split('-')[1]) + if winning_team is None: + raise DatabaseError(f'Main team not found for {winning_abbrev}') + + losing_abbrev = losing_team.abbrev.lower() + if 'gauntlet' in losing_abbrev: + losing_team = await get_team_or_none(session, team_abbrev=losing_abbrev.split('-')[1]) + if losing_team is None: + raise DatabaseError(f'Main team not found for {losing_abbrev}') + + await db_post('packs/one', payload={'team_id': winning_team.id, 'pack_type_id': win_reward['pack_type']['id']}) + await db_post(f'teams/{winning_team.id}/money/{win_reward["money"]}') + await db_post(f'teams/{losing_team.id}/money/{loss_reward["money"]}') + + return win_string, loss_string diff --git a/in_game/simulations.py b/in_game/simulations.py index 2d3e99a..ec26f25 100644 --- a/in_game/simulations.py +++ b/in_game/simulations.py @@ -7,26 +7,29 @@ from in_game import data_cache from dataclasses import asdict, fields +logger = logging.getLogger('discord_app') + + def get_result(pitcher: data_cache.PitchingWrapper, batter: data_cache.BattingWrapper): which = random.choice(['pitcher', 'batter']) - logging.info(f'in_game.simulations - get_result - which: {which}') + logger.info(f'in_game.simulations - get_result - which: {which}') unused_fields = ['avg', 'obp', 'slg', 'pull_rate', 'center_rate', 'slap_rate'] pit_hand = pitcher.card.hand bat_hand = batter.card.hand if which == 'pitcher': - logging.info(f'in_game.simulations - get_result - grabbing pitcher card chances') + logger.info(f'in_game.simulations - get_result - grabbing pitcher card chances') ch_data = pitcher.ratings_vl if bat_hand.upper() == 'L' else pitcher.ratings_vr - logging.info(f'ch_data: {ch_data}') + logger.info(f'ch_data: {ch_data}') # for field in fields(ch_data): # if field.name not in unused_fields: # ch_results.append(field.name) # ch_probs.append(getattr(data_cache.PitchingRatings, field.name)) else: - logging.info(f'in_game.simulations - get_result - grabbing batter card chances') + logger.info(f'in_game.simulations - get_result - grabbing batter card chances') ch_data = batter.ratings_vl if pit_hand.upper() == 'L' else batter.ratings_vr - logging.info(f'ch_data: {ch_data}') + logger.info(f'ch_data: {ch_data}') # for field in fields(ch_data): # if field.name not in unused_fields: # ch_results.append(field.name) @@ -39,10 +42,10 @@ def get_result(pitcher: data_cache.PitchingWrapper, batter: data_cache.BattingWr ch_results = list(ch_dict.keys()) ch_probs = list(ch_dict.values()) - logging.info(f'ch_results: {ch_results}') - logging.info(f'ch_probs: {ch_probs}') + logger.info(f'ch_results: {ch_results}') + logger.info(f'ch_probs: {ch_probs}') result = random.choices(ch_results, ch_probs) - logging.info(f'result: {result}') + logger.info(f'result: {result}') return result[0] diff --git a/paperdynasty.py b/paperdynasty.py index 1365525..4c58816 100644 --- a/paperdynasty.py +++ b/paperdynasty.py @@ -1,7 +1,7 @@ import discord import datetime import logging -# import logging.handlers +from logging.handlers import RotatingFileHandler import asyncio import os @@ -19,27 +19,30 @@ elif raw_log_level == 'WARN': else: log_level = logging.ERROR -date = f'{datetime.datetime.now().year}-{datetime.datetime.now().month}-{datetime.datetime.now().day}' -logging.basicConfig( - filename=f'logs/{date}.log', - format='%(asctime)s - %(levelname)s - %(message)s', - level=log_level -) -# logging.getLogger('discord.http').setLevel(logging.INFO) -# logger = logging.getLogger('discord') -# logger.setLevel(log_level) - -# handler = logging.handlers.RotatingFileHandler( -# filename='discord.log', -# encoding='utf-8', -# maxBytes=32 * 1024 * 1024, # 32 MiB -# backupCount=5, # Rotate through 5 files +# date = f'{datetime.datetime.now().year}-{datetime.datetime.now().month}-{datetime.datetime.now().day}' +# logger.basicConfig( +# filename=f'logs/{date}.log', +# format='%(asctime)s - %(levelname)s - %(message)s', +# level=log_level # ) +# logger.getLogger('discord.http').setLevel(logger.INFO) +logger = logging.getLogger('discord_app') +logger.setLevel(log_level) + +handler = RotatingFileHandler( + filename='logs/discord.log', + # encoding='utf-8', + maxBytes=32 * 1024 * 1024, # 32 MiB + backupCount=5, # Rotate through 5 files +) + +formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') +handler.setFormatter(formatter) # dt_fmt = '%Y-%m-%d %H:%M:%S' -# formatter = logging.Formatter('[{asctime}] [{levelname:<8}] {name}: {message}', dt_fmt, style='{') +# formatter = logger.Formatter('[{asctime}] [{levelname:<8}] {name}: {message}', dt_fmt, style='{') # handler.setFormatter(formatter) -# logger.addHandler(handler) +logger.addHandler(handler) COGS = [ 'cogs.owner', @@ -62,9 +65,9 @@ bot = commands.Bot(command_prefix='.', @bot.event async def on_ready(): - logging.info('Logged in as:') - logging.info(bot.user.name) - logging.info(bot.user.id) + logger.info('Logged in as:') + logger.info(bot.user.name) + logger.info(bot.user.id) # @bot.tree.error @@ -77,10 +80,10 @@ async def main(): for c in COGS: try: await bot.load_extension(c) - logging.info(f'Loaded cog: {c}') + logger.info(f'Loaded cog: {c}') except Exception as e: - logging.error(f'Failed to load cog: {c}') - logging.error(f'{e}') + logger.error(f'Failed to load cog: {c}') + logger.error(f'{e}') async with bot: await bot.start(os.environ.get('BOT_TOKEN')) diff --git a/tests/command_logic/test_logic_gameplay.py b/tests/command_logic/test_logic_gameplay.py index 54f8ffa..015664c 100644 --- a/tests/command_logic/test_logic_gameplay.py +++ b/tests/command_logic/test_logic_gameplay.py @@ -166,7 +166,7 @@ async def test_strikeouts(session: Session): game_1 = session.get(Game, 1) play_1 = session.get(Play, 1) - play_1 = await strikeouts(session, None, game_1, play_1) + play_1 = await strikeouts(session, None, play_1) assert play_1.so == 1 assert play_1.outs == 1 @@ -181,13 +181,13 @@ async def test_doubles(session: Session): assert play_2.play_num == 2 - play_2_ghost_1 = await doubles(session, None, game_1, play_2, double_type='***') + play_2_ghost_1 = await doubles(session, None, play_2, double_type='***') assert play_2_ghost_1.double == 1 assert play_2_ghost_1.on_first_final == 4 assert play_2_ghost_1.rbi == 1 - play_2_ghost_2 = await doubles(session, None, game_1, play_2, double_type='**') + play_2_ghost_2 = await doubles(session, None, play_2, double_type='**') assert play_2_ghost_2.double == 1 assert play_2_ghost_2.rbi == 0 diff --git a/tests/factory.py b/tests/factory.py index 2d8dcc3..3400c40 100644 --- a/tests/factory.py +++ b/tests/factory.py @@ -42,8 +42,8 @@ def session_fixture(): session.commit() game_1 = Game(away_team_id=31, home_team_id=400, channel_id=1234, season=9, ai_team='away', game_type='minor-league') - game_2 = Game(away_team_id=69, home_team_id=420, channel_id=5678, season=9, active=False, is_pd=True, ranked=True, week_num=6, game_num=9, away_roster_id=69, home_roster_id=420, first_message=12345678, ai_team='home', game_type='minor-league') - game_3 = Game(away_team_id=69, home_team_id=420, channel_id=5678, season=9, active=True, is_pd=True, ranked=True, week_num=6, game_num=10, away_roster_id=69, home_roster_id=420, first_message=34567890, ai_team='home', game_type='minor-league') + game_2 = Game(away_team_id=69, home_team_id=420, channel_id=5678, season=9, active=False, is_pd=True, ranked=True, week=6, game_num=9, away_roster_id=69, home_roster_id=420, first_message=12345678, ai_team='home', game_type='minor-league') + game_3 = Game(away_team_id=69, home_team_id=420, channel_id=5678, season=9, active=True, is_pd=True, ranked=True, week=6, game_num=10, away_roster_id=69, home_roster_id=420, first_message=34567890, ai_team='home', game_type='minor-league') session.add(game_1) session.add(game_2) diff --git a/tests/gameplay_models/test_game_model.py b/tests/gameplay_models/test_game_model.py index 661df7e..c25377e 100644 --- a/tests/gameplay_models/test_game_model.py +++ b/tests/gameplay_models/test_game_model.py @@ -1,11 +1,11 @@ import pytest from sqlalchemy import delete as sadelete from sqlalchemy.sql.functions import sum, count -from sqlmodel import Session, delete +from sqlmodel import Session, delete, func -from command_logic.logic_gameplay import complete_play, singles, undo_play -from in_game.gameplay_models import Game, Lineup, GameCardsetLink, Play, select -from in_game.gameplay_queries import get_channel_game_or_none, get_active_games_by_team +from command_logic.logic_gameplay import complete_play, homeruns, is_game_over, singles, strikeouts, undo_play +from in_game.gameplay_models import Game, Lineup, GameCardsetLink, Play, Team, select +from in_game.gameplay_queries import get_channel_game_or_none, get_active_games_by_team, get_db_ready_decisions from tests.factory import session_fixture @@ -20,7 +20,7 @@ def test_create_game(session: Session): assert game_1.active == True assert game_1.is_pd == True assert game_1.ranked == False - assert game_1.week_num == None + assert game_1.week == None assert game_1.game_num == None assert game_1.away_roster_id == None assert game_1.home_roster_id == None @@ -30,7 +30,7 @@ def test_create_game(session: Session): assert game_2.active == False assert game_2.is_pd == True assert game_2.ranked == True - assert game_2.week_num == 6 + assert game_2.week == 6 assert game_2.game_num == 9 assert game_2.away_roster_id == 69 assert game_2.home_roster_id == 420 @@ -76,14 +76,15 @@ def test_games_by_channel(session: Session): def test_games_by_team(session: Session): - assert len(get_active_games_by_team(session, team_id=69)) == 1 + team_69 = session.get(Team, 69) + assert len(get_active_games_by_team(session, team=team_69)) == 1 game_2 = session.get(Game, 2) game_2.active = True session.add(game_2) session.commit() - assert len(get_active_games_by_team(session, team_id=69)) == 2 + assert len(get_active_games_by_team(session, team=team_69)) == 2 game_3 = session.get(Game, 3) game_3.active = False @@ -92,7 +93,7 @@ def test_games_by_team(session: Session): session.add(game_2) session.commit() - assert len(get_active_games_by_team(session, team_id=69)) == 0 + assert len(get_active_games_by_team(session, team=team_69)) == 0 def test_delete_game(session: Session): @@ -200,3 +201,49 @@ async def test_undo_play(session: Session): assert new_play.play_num == 4 assert new_play.on_second == on_second_play_4 + +def test_game_model_dump(session: Session): + game_1 = session.get(Game, 1) + game_data = game_1.model_dump() + + assert game_data['active'] == True + assert game_data['away_team_id'] == 31 + assert game_data['home_team_id'] == 400 + assert game_data['game_type'] == 'minor-league' + + +def test_final_inning(session: Session): + game_1 = session.get(Game, 1) + final_inning = session.exec(select(func.max(Play.inning_num)).where(Play.game == game_1)).one() + + assert final_inning == 1 + + +async def test_db_ready_decisions(session: Session): + game_1 = session.get(Game, 1) + this_play = game_1.initialize_play(session) + + assert this_play.play_num == 2 + + this_play = await strikeouts(session, None, this_play) + this_play = complete_play(session, this_play) + + this_play = await strikeouts(session, None, this_play) + this_play = complete_play(session, this_play) + + assert this_play.starting_outs == 0 + assert this_play.inning_half == 'bot' + + this_play = await homeruns(session, None, this_play, 'no-doubt') + this_play = complete_play(session, this_play) + + decisions = get_db_ready_decisions(session, game_1, 69) + + assert len(decisions) == 2 + assert decisions[0]['pitcher_team_id'] == 400 + assert decisions[1]['pitcher_team_id'] == 31 + assert decisions[0]['game_finished'] == 1 + assert decisions[0]['is_start'] == True + assert decisions[1]['game_finished'] == 1 + assert decisions[1]['is_start'] == True + diff --git a/tests/gameplay_models/test_lineup_model.py b/tests/gameplay_models/test_lineup_model.py index e610c7b..c9ee469 100644 --- a/tests/gameplay_models/test_lineup_model.py +++ b/tests/gameplay_models/test_lineup_model.py @@ -55,7 +55,7 @@ def test_get_one_lineup(session: Session): assert leadoff.position == 'C' with pytest.raises(KeyError) as exc_info: - get_one_lineup(session, session, this_game, this_game.away_team) + get_one_lineup(session, this_game, this_game.away_team) assert str(exc_info) == "" diff --git a/tests/gameplay_models/test_play_model.py b/tests/gameplay_models/test_play_model.py index 3a87227..7690cd5 100644 --- a/tests/gameplay_models/test_play_model.py +++ b/tests/gameplay_models/test_play_model.py @@ -1,10 +1,10 @@ import pytest from sqlmodel import Session, select, func -from command_logic.logic_gameplay import complete_play, singles, undo_play +from command_logic.logic_gameplay import complete_play, homeruns, is_game_over, singles, strikeouts, undo_play, walks from db_calls_gameplay import advance_runners from in_game.gameplay_models import Lineup, Play, Game -from in_game.gameplay_queries import get_last_team_play +from in_game.gameplay_queries import get_db_ready_plays, get_last_team_play from tests.factory import session_fixture @@ -107,3 +107,63 @@ async def test_undo_play(session: Session): assert len(all_plays) == 3 +def test_db_ready_plays(session: Session): + game_1 = session.get(Game, 1) + play_2 = game_1.initialize_play(session) + + db_ready_plays = get_db_ready_plays(session, game_1, 69) + plays = db_ready_plays['plays'] + + assert len(plays) == 2 + assert plays[0]['game_id'] == 69 + assert plays[0]['on_first_id'] == None + assert plays[0]['catcher_id'] == 11 + print(f'obc from return: {plays[0]["on_base_code"]}') + assert plays[0]['on_base_code'] == '000' + + +async def test_is_game_over(session: Session): + game_1 = session.get(Game, 1) + this_play = game_1.initialize_play(session) + + assert is_game_over(this_play) == False + + assert this_play.play_num == 2 + assert this_play.starting_outs == 1 + + this_play = await strikeouts(session, None, this_play) + next_play = complete_play(session, this_play) + + assert this_play.wpa == -0.015 + + this_play = await strikeouts(session, None, next_play) + this_play = complete_play(session, this_play) + + assert this_play.starting_outs == 0 + assert this_play.inning_half == 'bot' + + this_play.inning_num = 9 + session.add(this_play) + session.commit() + session.refresh(this_play) + + this_play = await strikeouts(session, None, this_play) + this_play = complete_play(session, this_play) + + this_play = await homeruns(session, None, this_play, 'no-doubt') + next_play = complete_play(session, this_play) + + assert is_game_over(next_play) == True + assert this_play.wpa == 0.402 + + +async def test_walks(session: Session): + game_1 = session.get(Game, 1) + play_2 = game_1.initialize_play(session) + + this_play = await walks(session, None, play_2) + this_play = complete_play(session, this_play) + + assert this_play.on_base_code == 1 + + diff --git a/tests/gameplay_models/test_player_model.py b/tests/gameplay_models/test_player_model.py index 7a4f64d..cb1e238 100644 --- a/tests/gameplay_models/test_player_model.py +++ b/tests/gameplay_models/test_player_model.py @@ -57,7 +57,7 @@ def test_player_id_from_dict(session: Session): with pytest.raises(KeyError) as exc_info: get_player_id_from_dict({}) - assert str(exc_info) == "" + assert str(exc_info) == "" def test_player_card_link(session: Session): diff --git a/utilities/buttons.py b/utilities/buttons.py index f57a61e..13fac8b 100644 --- a/utilities/buttons.py +++ b/utilities/buttons.py @@ -111,11 +111,14 @@ class ButtonOptions(discord.ui.View): self.stop() -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) -> bool: +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 = Confirm(responders=[interaction.user], timeout=timeout, label_type=label_type) + try: + view = Confirm(responders=[interaction.user], timeout=timeout, label_type=label_type) + except AttributeError: + view = Confirm(responders=[interaction.author], timeout=timeout, label_type=label_type) if custom_confirm_label: view.confirm.label = custom_confirm_label if custom_cancel_label: @@ -127,9 +130,13 @@ async def ask_confirm(interaction: discord.Interaction, question: str, label_typ if view.value: if delete_question: await question.delete() + else: + await question.edit(content=question, view=None) return True else: if delete_question: await question.delete() + else: + await question.edit(content=question, view=None) return False diff --git a/utilities/dropdown.py b/utilities/dropdown.py index d00e353..363c8be 100644 --- a/utilities/dropdown.py +++ b/utilities/dropdown.py @@ -4,7 +4,10 @@ import logging from sqlmodel import Session from in_game.gameplay_models import Lineup, Play -from in_game.gameplay_queries import get_sorted_lineups + + +logger = logging.getLogger('discord_app') + class DropdownOptions(discord.ui.Select): def __init__(self, option_list: list, placeholder: str = 'Make your selection', min_values: int = 1, max_values: int = 1, callback=None): @@ -35,7 +38,7 @@ class DropdownOptions(discord.ui.Select): # Select object, and the values attribute gets a list of the user's # selected options. We only want the first one. # await interaction.response.send_message(f'Your favourite colour is {self.values[0]}') - logging.info(f'Dropdown callback: {self.custom_callback}') + logger.info(f'Dropdown callback: {self.custom_callback}') await self.custom_callback(interaction, self.values) @@ -60,7 +63,7 @@ class SelectViewDefense(discord.ui.Select): super().__init__(options=options) async def callback(self, interaction: discord.Interaction): - logging.info(f'SelectViewDefense - selection: {self.values[0]}') + logger.info(f'SelectViewDefense - selection: {self.values[0]}') this_lineup = self.session.get(Lineup, self.values[0]) self.embed.set_image(url=this_lineup.player.image) @@ -81,86 +84,3 @@ class SelectViewDefense(discord.ui.Select): ) await interaction.response.edit_message(content=None, embed=self.embed, view=new_view) - - - -class SelectOpenPack(discord.ui.Select): - def __init__(self, options: list, team: dict): - self.owner_team = team - super().__init__(placeholder='Select a Pack Type', options=options) - - async def callback(self, interaction: discord.Interaction): - logging.info(f'SelectPackChoice - selection: {self.values[0]}') - pack_vals = self.values[0].split('-') - logging.info(f'pack_vals: {pack_vals}') - - # Get the selected packs - params = [('team_id', self.owner_team['id']), ('opened', False), ('limit', 5), ('exact_match', True)] - - open_type = 'standard' - if 'Standard' in pack_vals: - open_type = 'standard' - params.append(('pack_type_id', 1)) - elif 'Premium' in pack_vals: - open_type = 'standard' - params.append(('pack_type_id', 3)) - elif 'Daily' in pack_vals: - params.append(('pack_type_id', 4)) - elif 'Promo Choice' in pack_vals: - open_type = 'choice' - params.append(('pack_type_id', 9)) - elif 'MVP' in pack_vals: - open_type = 'choice' - params.append(('pack_type_id', 5)) - elif 'All Star' in pack_vals: - open_type = 'choice' - params.append(('pack_type_id', 6)) - elif 'Mario' in pack_vals: - open_type = 'choice' - params.append(('pack_type_id', 7)) - elif 'Team Choice' in pack_vals: - open_type = 'choice' - params.append(('pack_type_id', 8)) - else: - raise KeyError(f'Cannot identify pack details: {pack_vals}') - - # If team isn't already set on team choice pack, make team pack selection now - await interaction.response.edit_message(view=None) - - cardset_id = None - if 'Team Choice' in pack_vals and 'Cardset' in pack_vals: - # cardset_id = pack_vals[2] - cardset_index = pack_vals.index('Cardset') - cardset_id = pack_vals[cardset_index + 1] - params.append(('pack_cardset_id', cardset_id)) - if 'Team' not in pack_vals: - view = SelectView( - [SelectChoicePackTeam('AL', self.owner_team, cardset_id), - SelectChoicePackTeam('NL', self.owner_team, cardset_id)], - timeout=30 - ) - await interaction.channel.send( - content=None, - view=view - ) - return - - params.append(('pack_team_id', pack_vals[pack_vals.index('Team') + 1])) - else: - if 'Team' in pack_vals: - params.append(('pack_team_id', pack_vals[pack_vals.index('Team') + 1])) - if 'Cardset' in pack_vals: - cardset_id = pack_vals[pack_vals.index('Cardset') + 1] - params.append(('pack_cardset_id', cardset_id)) - - p_query = await db_get('packs', params=params) - if p_query['count'] == 0: - logging.error(f'open-packs - no packs found with params: {params}') - raise ValueError(f'Unable to open packs') - - # Open the packs - if open_type == 'standard': - await open_st_pr_packs(p_query['packs'], self.owner_team, interaction) - elif open_type == 'choice': - await open_choice_pack(p_query['packs'][0], self.owner_team, interaction, cardset_id) - diff --git a/utilities/pages.py b/utilities/pages.py index b3c49c6..aec1cab 100644 --- a/utilities/pages.py +++ b/utilities/pages.py @@ -2,6 +2,9 @@ import discord import logging +logger = logging.getLogger('discord_app') + + class Pagination(discord.ui.View): def __init__(self, responders: list, timeout: float = 300.0): super().__init__(timeout=timeout) @@ -14,7 +17,7 @@ class Pagination(discord.ui.View): @discord.ui.button(label='⏮️', style=discord.ButtonStyle.blurple) async def left_button(self, interaction: discord.Interaction, button: discord.ui.Button): if interaction.user not in self.responders: - logging.info(f'{interaction.user} is not in {self.responders}') + logger.info(f'{interaction.user} is not in {self.responders}') return self.value = 'left' @@ -24,7 +27,7 @@ class Pagination(discord.ui.View): @discord.ui.button(label='❌️', style=discord.ButtonStyle.secondary) async def cancel_button(self, interaction: discord.Interaction, button: discord.ui.Button): if interaction.user not in self.responders: - logging.info(f'{interaction.user} is not in {self.responders}') + logger.info(f'{interaction.user} is not in {self.responders}') return self.value = 'cancel' @@ -34,7 +37,7 @@ class Pagination(discord.ui.View): @discord.ui.button(label='⏭️', style=discord.ButtonStyle.blurple) async def right_button(self, interaction: discord.Interaction, button: discord.ui.Button): if interaction.user not in self.responders: - logging.info(f'{interaction.user} is not in {self.responders}') + logger.info(f'{interaction.user} is not in {self.responders}') return self.value = 'right'