import copy import datetime import logging import random import discord import requests from peewee import DatabaseError import ai_manager import helpers from helpers import RARITY, get_cal_user, get_or_create_role, send_to_channel, get_channel from db_calls import db_get, db_post, db_delete, db_patch 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 c_query = db_get('cards', params=[('team_id', this_team['id'])]) await interaction.edit_original_response(content=f'Found {c_query["count"]} cards; deleting cards...') for x in c_query['cards']: db_delete('cards', object_id=x['id']) # Delete packs await interaction.edit_original_response(content=f'Done deleting cards; searching for packs...') p_query = db_get('packs', params=[('team_id', this_team['id'])]) await interaction.edit_original_response(content=f'Found {p_query["count"]} packs; deleting packs...') for x in p_query['packs']: db_delete('packs', object_id=x['id']) # Delete team if delete_team: await interaction.edit_original_response(content=f'Done deleting packs; now deleting team...') db_delete('teams', object_id=this_team['id']) await interaction.edit_original_response(content=f'Team is deleted; now finding the run...') if delete_runs: r_query = db_get('gauntletruns', params=[('team_id', this_team['id']), ('is_active', True)]) await interaction.edit_original_response(content=f'Found {r_query["count"]} runs; deleting now...') for x in r_query['runs']: db_delete('gauntletruns', object_id=x['id']) def get_game_code(this_team, this_event, this_run): return f'gauntlet-{this_event["id"]}-run-{this_run["id"]}-game-{games_played(this_run) + 1}' def games_played(this_run): return this_run['wins'] + this_run['losses'] def is_home_team(this_team, this_event, this_run): if this_event['id'] == 1: return True return False def get_opponent(this_team, this_event, this_run): if this_event['id'] == 1: gp = games_played(this_run) if gp == 0: t_id = 20 elif gp == 1: t_id = 9 elif gp == 2: t_id = 5 elif gp == 3: t_id = 17 elif gp == 4: t_id = 3 elif gp == 5: t_id = 21 elif gp == 6: t_id = 24 elif gp == 7: t_id = 23 elif gp == 8: t_id = 18 elif gp == 9: t_id = 11 elif gp == 10: t_id = 58 else: raise KeyError(f'Huh...I have no idea who you should be playing right now.') return db_get('teams', object_id=t_id, none_okay=False) else: return None def build_lineup(this_team, this_game, this_event): if this_event['id'] == 1: return ai_manager.build_lineup(this_team, this_game.id, f'gauntlet-{this_event["id"]}') else: raise KeyError(f'Lineups not found for Gauntlet {this_event["id"]}') def get_starting_pitcher(this_team, this_game, this_event, this_run): if this_event['id'] == 1: if this_team['id'] != 58: set_params = ai_manager.MINOR_CARDSET_PARAMS else: set_params = [] params = [ ('mlbclub', this_team['lname']), ('pos_include', 'SP'), ('pos_exclude', 'RP'), ('inc_dex', False), ('sort_by', 'cost-desc'), ('limit', 5) ] params.extend(set_params) else: raise KeyError(f'Pitcher not found for Gauntlet {this_event["id"]}') params = [ ('mlbclub', this_team['lname']), ('pos_include', 'SP'), ('pos_exclude', 'RP'), ('inc_dex', False), ('sort_by', 'cost-desc'), ('limit', 5) ] counter = 0 while True: counter += 1 # Pull starters sorted by current cost try: params.extend(set_params) pitchers = db_get( endpoint='players', params=params, timeout=10 ) except ConnectionError as e: logging.error(f'Could not get pitchers for {this_team["lname"]}: {e}') raise ConnectionError(f'Error pulling starting pitchers for the {this_team["lname"]}. Cal help plz.') if pitchers['count'] == 0: logging.info(f'pitchers is None') del params params = [ ('mlbclub', this_team['lname']), ('pos_include', 'SP'), ('inc_dex', False), ('sort_by', 'cost-desc'), ('limit', 5) ] elif counter >= 2: raise KeyError(f'Error pulling pitchers for the {this_team["lname"]}. Cal help plz.') else: break pitcher_num = games_played(this_run) % 5 card_id = ai_manager.get_or_create_card(pitchers['players'][pitcher_num], this_team) return { 'game_id': this_game.id, 'team_id': this_team['id'], 'player_id': pitchers['players'][0]['player_id'], 'card_id': card_id, 'position': 'P', 'batting_order': 10, 'after_play': 0 } async def run_draft(interaction: discord.Interaction, main_team, this_event, draft_team=None): if this_event['id'] == 1: embed_title = f'{main_team["lname"]} - {this_event["name"]} Draft' embed_description = f'{this_event["name"]}' base_params = ai_manager.MAJOR_CARDSET_PARAMS base_params.extend([('limit', 8), ('cardset_id', 8)]) else: logging.error(f'run_draft - Event ID {this_event["id"]} not recognized') raise KeyError(f'Draft data not found for Gauntlet {this_event["id"]}') if draft_team is None: # Post draft team linked to main team draft_team = db_post( 'teams', payload={ 'abbrev': f'Gauntlet-{main_team["abbrev"]}', 'sname': main_team['sname'], 'lname': main_team['lname'], 'gmid': main_team['gmid'], 'gmname': main_team['gmname'], 'gsheet': 'NONE', 'logo': main_team['logo'] if main_team['logo'] else None, 'color': main_team['color'] if main_team['color'] else None, 'season': main_team['season'], 'has_guide': main_team['has_guide'] } ) all_players = [] p_names = [] counts = { 'SP': 0, 'RP': 0, 'CP': 0, 'C': 0, '1B': 0, '2B': 0, '3B': 0, 'SS': 0, 'LF': 0, 'CF': 0, 'RF': 0, 'DH': 0, 'MVP': 0, 'All-Star': 0, 'Starter': 0, 'Reserve': 0, 'Replacement': 0, } round_num = 1 counter = 0 view = helpers.Confirm([interaction.user]) if this_event['id'] == 1: view.confirm.label = 'Let\'s a-Go!' else: view.confirm.label = 'Let\'s Go!' intro_embed = get_embed(this_event=this_event) intro_embed.title += ' - Are you ready?' await interaction.edit_original_response( content=None, embed=intro_embed, view=view ) await view.wait() if not view.value: await interaction.edit_original_response(content=None, embed=intro_embed, view=None) await interaction.channel.send('You\'ll be back') raise ZeroDivisionError() else: await interaction.edit_original_response( content=None, embed=intro_embed, view=None ) def get_embeds(include_links=True): top_embed = helpers.get_team_embed(f'{embed_title} - Round {round_num}') top_embed.description = f'Rarity Counts' bot_embed = helpers.get_team_embed(f'{embed_title} - Round {round_num}') bot_embed.description = f'Current Roster' all_str = { 'MVP': '', 'All-Star': '', 'Starter': '', 'Reserve': '', 'Replacement': '', 'C': '', '1B': '', '2B': '', '3B': '', 'SS': '', 'LF': '', 'CF': '', 'RF': '', 'DH': '', 'SP': '', 'RP': '', 'CP': '' } for y in all_players: if include_links: name_string = f'[{y["description"]}]({y["image"]})' else: name_string = f'{y["description"]}' all_str[y['rarity']['name']] += f'{name_string}\n' for z in helpers.get_all_pos(y): all_str[z] += f'{name_string}\n' top_embed.add_field(name=f'MVPs ({counts["MVP"]}/2)', value=all_str['MVP'], inline=False) top_embed.add_field(name=f'All-Stars ({counts["All-Star"]}/3)', value=all_str['All-Star'], inline=False) top_embed.add_field(name=f'Starters ({counts["Starter"]}/9)', value=all_str['Starter'], inline=False) top_embed.add_field(name=f'Reserves ({counts["Reserve"]}/7)', value=all_str['Reserve'], inline=False) top_embed.add_field( name=f'Replacements ({counts["Replacement"]}/5)', value=all_str['Replacement'], inline=False ) bot_embed.add_field(name=f'Catcher', value=all_str['C'], inline=False) bot_embed.add_field(name=f'First Base', value=all_str['1B'], inline=False) bot_embed.add_field(name=f'Second Base', value=all_str['2B'], inline=False) bot_embed.add_field(name=f'Third Base', value=all_str['3B'], inline=False) bot_embed.add_field(name=f'Shortstop', value=all_str['SS'], inline=False) bot_embed.add_field(name=f'Left Field', value=all_str['LF'], inline=False) bot_embed.add_field(name=f'Center Field', value=all_str['CF'], inline=False) bot_embed.add_field(name=f'Right Field', value=all_str['RF'], inline=False) bot_embed.add_field(name=f'Designated Hitter', value=all_str['DH'], inline=False) bot_embed.add_field(name=f'Starting Pitcher', value=all_str['SP'], inline=False) bot_embed.add_field(name=f'Relief Pitcher', value=all_str['RP'], inline=False) bot_embed.add_field(name=f'Closing Pitcher', value=all_str['CP'], inline=False) return [top_embed, bot_embed] last_message = await interaction.channel.send(content=None, embeds=get_embeds(include_links=False)) if this_event['id'] == 1: mario_round = None while round_num <= 26 and counter < 50: counter += 1 # Set params based on current round params = copy.deepcopy(base_params) if round_num == 1: params.extend([ ('min_rarity', RARITY['MVP']), ('max_rarity', RARITY['MVP']), ('pos_exc', 'RP') ]) elif round_num == 2: params.extend([ ('min_rarity', RARITY['All-Star']), ('max_rarity', RARITY['All-Star']) ]) elif round_num <= 5: params.extend([ ('min_rarity', RARITY['Starter']), ('max_rarity', RARITY['Starter']) ]) elif round_num <= 9: params.extend([ ('min_rarity', RARITY['Reserve']), ('max_rarity', RARITY['Reserve']) ]) elif round_num == 10: if random.randint(1, 2) == 1: params = [ ('min_rarity', RARITY['MVP']), ('max_rarity', RARITY['MVP']), ('cardset_id', 8) ] mario_round = 10 else: params.extend([ ('min_rarity', RARITY['MVP']), ('max_rarity', RARITY['MVP']), ('pos_exc', 'RP') ]) elif round_num == 11: if random.randint(1, 2) == 1 and mario_round is None: params = [ ('min_rarity', RARITY['All-Star']), ('max_rarity', RARITY['All-Star']), ('cardset_id', 8) ] mario_round = 11 else: params.extend([ ('min_rarity', RARITY['All-Star']), ('max_rarity', RARITY['All-Star']) ]) elif round_num == 12: if mario_round is None: params = [ ('min_rarity', RARITY['Starter']), ('max_rarity', RARITY['Starter']), ('cardset_id', 8) ] mario_round = 12 else: params.extend([ ('min_rarity', RARITY['Starter']), ('max_rarity', RARITY['Starter']) ]) elif round_num <= 15: params.extend([ ('min_rarity', RARITY['Replacement']), ('max_rarity', RARITY['Replacement']) ]) elif round_num <= 18: params.extend([ ('min_rarity', RARITY['Starter']), ('max_rarity', RARITY['Starter']) ]) elif round_num == 19: params.extend([ ('min_rarity', RARITY['All-Star']), ('max_rarity', RARITY['All-Star']) ]) elif round_num <= 21: params.extend([ ('min_rarity', RARITY['Starter']), ('max_rarity', RARITY['Starter']) ]) elif round_num <= 24: params.extend([ ('min_rarity', RARITY['Reserve']), ('max_rarity', RARITY['Reserve']) ]) elif round_num <= 26: params.extend([ ('min_rarity', RARITY['Replacement']), ('max_rarity', RARITY['Replacement']) ]) # Any positional adjustments can be added as params here for x in ['C', '1B', '2B', '3B', 'SS', 'LF', 'CF', 'RF']: if counts[x] > 2 and 0 in [ counts['C'], counts['1B'], counts['2B'], counts['3B'], counts['SS'], counts['LF'], counts['CF'], counts['RF']]: logging.info(f'0 exists in other positions; excluding {x}') params.append(('pos_exc', x)) elif counts[x] > 3: params.append(('pos_exc', x)) if round_num > 20 and counts[x] < 2: params.append(('pos_inc', x)) if counts['RP'] > 7: params.append(('pos_exc', 'RP')) if counts['SP'] > 5: params.append(('pos_exc', 'SP')) if counts['RP'] > counts['SP'] + 3: params.append(('pos_exc', 'RP')) if counts['SP'] > counts['RP'] + 3: params.append(('pos_exc', 'SP')) if round_num > 20: if counts['SP'] < 5: params.append(('pos_inc', 'SP')) if counts['RP'] < 5: params.append(('pos_inc', 'RP')) # Call /players/random to get eight cards p_query = None try: p_query = db_get('players/random', params=params) except requests.ReadTimeout as e: logging.error(f'run_draft - timeout error pulling player with params {params}') if p_query['count'] > 0: test_player_list = '' for x in p_query['players']: test_player_list += f'{x["rarity"]["name"]} - {x["description"]} - {helpers.get_all_pos(x)}\n' # Collect 4 cards with no repeat player names this_batch = [] for x in p_query['players']: if x['p_name'] not in p_names: this_batch.append(x) if len(this_batch) == 4: break # Present choices and capture selection p_choice = await helpers.get_choice_from_cards(interaction, this_batch, delete_message=True) # Add player to list and update counts p_names.append(p_choice['p_name']) counts[p_choice['rarity']['name']] += 1 all_players.append(p_choice) for x in helpers.get_all_pos(p_choice): if x in counts: counts[x] += 1 # Update roster embed round_num += 1 await last_message.edit(content=None, embeds=get_embeds(include_links=False)) else: logging.error(f'run_draft - No draft logic for Event ID {this_event["id"]}') raise KeyError(f'Draft data not found for Gauntlet {this_event["id"]}') this_pack = db_post( 'packs/one', payload={ 'team_id': draft_team['id'], 'pack_type_id': 2, 'open_time': datetime.datetime.timestamp(datetime.datetime.now()) * 1000 } ) db_post( 'cards', payload={'cards': [ {'player_id': x['player_id'], 'team_id': draft_team['id'], 'pack_id': this_pack['id']} for x in all_players ]} ) db_post( 'gauntletruns', payload={ 'team_id': draft_team['id'], 'gauntlet_id': this_event['id'] } ) final_embed = get_embeds(False)[0] final_embed.title = f'{main_team["lname"]} - {this_event["name"]} Draft' if main_team['logo']: final_embed.set_thumbnail(url=main_team["logo"]) return final_embed def get_embed(this_run=None, this_event=None): logging.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') if this_run is not None: this_event = this_run['gauntlet'] embed = helpers.image_embed( image_url=this_event['url'], title=f'{this_event["name"]}', ) if this_run is not None and this_run['team']['logo']: embed.set_thumbnail(url=this_run['team']['logo']) embed.description = this_run['team']['lname'] embed.add_field(name='Event Info', value=this_event['short_desc'], inline=False) if this_run is not None: embed.add_field(name='Record', value=f'{this_run["wins"]}-{this_run["losses"]}', inline=False) r_query = db_get('gauntletrewards', params=[('gauntlet_id', this_event['id'])]) reward_string = '' for x in r_query['rewards']: if this_run is not None: if this_run['wins'] >= x['win_num'] and this_run['losses'] <= x['loss_max']: reward_string += '✅️ ' elif this_run['losses'] > x['loss_max']: reward_string += '❌ ' else: reward_string += '⬜ ' reward_string += f'{x["win_num"]}{"-0" if x["loss_max"] == 0 else " Wins"}: ' if x['reward']['money']: reward_string += f' {x["reward"]["money"]}₼\n' elif x['reward']['player']: reward_string += f' {x["reward"]["player"]["description"]}\n' elif x['reward']['pack_type']: reward_string += f' {x["reward"]["pack_type"]["name"]} Pack\n' if len(reward_string) > 0: embed.add_field(name='Rewards', value=reward_string, inline=False) if this_run is not None: embed.add_field(name='Team Sheet', value=helpers.get_roster_sheet(this_run['team'])) return embed async def post_result(run_id: int, is_win: bool, this_team, bot, ctx): this_run = db_get('gauntletruns', object_id=run_id) this_event = db_get('events', object_id=this_run['gauntlet']['id']) main_team = db_get('teams', params=[('abbrev', f'{this_team["abbrev"].replace("Gauntlet-","")}')])['teams'][0] if is_win: this_run = db_patch( 'gauntletruns', object_id=this_run['id'], params=[('wins', this_run['wins'] + 1), ('ended', this_run['wins'] + 1 == 10)] ) r_query = db_get( 'gauntletrewards', params=[('gauntlet_id', this_event['id']), ('win_num', this_run['wins']), ('loss_max', this_run['losses'])] ) reward_string = '' for x in r_query['rewards']: if x['reward']['money']: db_post(f'teams/{main_team["id"]}/money/{x["reward"]["money"]}') reward_string += f'- {x["reward"]["money"]}₼\n' elif x['reward']['player']: # TODO: add give player code pass elif x['reward']['pack_type']: helpers.give_packs(main_team, 1, x['reward']['pack_type']) reward_string += f'- 1x {x["reward"]["pack_type"]["name"]} Pack' if this_run['wins'] == 10: choas_role = await get_or_create_role(ctx, "CHOAS ALERT", mentionable=True) await send_to_channel( bot, 'pd-network-news', content=f'{choas_role.mention}\n\nThe **{this_team["lname"]}** have completed the ' f'**{this_event["name"]} Gauntlet** with a record of {this_run["wins"]}-' f'{this_run["losses"]}!' ) final_message = f'That\'s number 10! Way to go - you have completed the **{this_event["name"]} Gauntlet** ' \ f'with a record of {this_run["wins"]}-{this_run["losses"]}! ' else: final_message = f'Big win there! Your {this_event["name"]} record is now **{this_run["wins"]}-' \ f'{this_run["losses"]}**. ' if len(reward_string) > 0: final_message += f"You earned the following rewards:\n{reward_string}" final_message += f'\n\nGo share the highlights in {get_channel(ctx, "pd-news-ticker").mention}!' await ctx.send( content=final_message, embed=get_embed(this_run) ) else: this_run = db_patch( 'gauntletruns', object_id=this_run['id'], params=[('losses', this_run['losses'] + 1), ('ended', this_run['losses'] + 1 == 2)] ) l_message = f'Tough loss. That brings your {this_event["name"]} record to ' \ f'**{this_run["wins"]}-{this_run["losses"]}**. ' if this_run['losses'] == 2: l_message += 'That\'s the end of this run - better luck next time!' c_query = db_post(f'cards/wipe-team/{this_team["id"]}') await ctx.send( content=l_message, embed=get_embed(this_run) )