diff --git a/ai_manager.py b/ai_manager.py index de53a28..21f23f6 100644 --- a/ai_manager.py +++ b/ai_manager.py @@ -101,6 +101,7 @@ 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"]}') + raise DatabaseError(f'Could not create card for {player["p_name"]} on the {team["lname"]}') return card_id @@ -222,6 +223,8 @@ def build_lineup(team_object: dict, game_id: int, league_name: str, vs_hand: str set_params = MINOR_CARDSET_PARAMS elif league_name == 'major-league': set_params = MAJOR_CARDSET_PARAMS + elif league_name == 'gauntlet-1': + set_params = MINOR_CARDSET_PARAMS # Pull players sorted by current cost try: @@ -295,23 +298,7 @@ def build_lineup(team_object: dict, game_id: int, league_name: str, vs_hand: str i = 1 for x in [grp_1, grp_2, grp_3]: for y in x: - # get player card; create one if none found - z = 0 - card_id = None - while z < 2 and card_id is None: - z += 1 - c_query = db_get('cards', params=[('team_id', team_object['id']), ('player_id', y[1]['player_id'])]) - if c_query['count'] > 0: - card_id = c_query['cards'][0]['id'] - else: - db_post( - 'cards', - payload={'cards': [ - {'player_id': y[1]['player_id'], 'team_id': team_object['id'], 'pack_id': 1} - ]} - ) - if card_id is None: - logging.error(f'Could not create card for {y[1]["p_name"]} on the {team_object["lname"]}') + card_id = get_or_create_card(y[1], team_object) lineups.append({ 'game_id': game_id, @@ -335,6 +322,8 @@ def get_starting_pitcher(team_object: dict, game_id: int, is_home: bool, league_ set_params = MINOR_CARDSET_PARAMS elif league_name == 'major-league': set_params = MAJOR_CARDSET_PARAMS + elif league_name == 'gauntlet-1': + set_params = MINOR_CARDSET_PARAMS # Pull starters sorted by current cost try: @@ -386,22 +375,7 @@ def get_starting_pitcher(team_object: dict, game_id: int, is_home: bool, league_ starter = pitchers['players'][0] # get player card; create one if none found - z = 0 - card_id = None - while z < 2 and card_id is None: - z += 1 - c_query = db_get('cards', params=[('team_id', team_object['id']), ('player_id', starter['player_id'])]) - if c_query['count'] > 0: - card_id = c_query['cards'][0]['id'] - else: - db_post( - 'cards', - payload={'cards': [ - {'player_id': starter['player_id'], 'team_id': team_object['id'], 'pack_id': 1} - ]} - ) - if card_id is None: - logging.error(f'Could not create card for {starter["p_name"]} on the {team_object["lname"]}') + card_id = get_or_create_card(starter, team_object) return { 'game_id': game_id, @@ -425,11 +399,14 @@ def get_relief_pitcher(this_play: StratPlay, ai_team: dict, used_pitchers: list, if attempts > 3: raise ValueError(f'Could not find a reliever for the {ai_team["sname"]}. Cal plz.') + logging.info(f'TEST GAME - league_name: {league_name}') set_params = [('cardset_id_exclude', 2)] if league_name == 'minor-league': set_params = MINOR_CARDSET_PARAMS elif league_name == 'major-league': set_params = MAJOR_CARDSET_PARAMS + elif 'gauntlet-1' in league_name: + set_params = MINOR_CARDSET_PARAMS # Pull relievers sorted by current cost params = [ diff --git a/cogs/admins.py b/cogs/admins.py index 6c3c5bb..f19a76c 100644 --- a/cogs/admins.py +++ b/cogs/admins.py @@ -7,6 +7,7 @@ import discord import pygsheets import requests +import gauntlets from helpers import * from db_calls import * from discord import Member @@ -33,42 +34,108 @@ class Admins(commands.Cog): async def cog_command_error(self, ctx, error): await ctx.send(f'{error}') - # @tasks.loop(minutes=10) - # async def weekly_loop(self): - # now = datetime.datetime.now() - # if now.hour == 6 and now.weekday() == 0 and not self.weekly_reset_done: - # weekly_packs = await self.increment_week() - # self.weekly_reset_done = True - # - # sba = self.bot.get_guild(613880856032968834) - # news_ticker = discord.utils.get(sba.text_channels, name='pd-news-ticker') - # await news_ticker.send('The new week is here! Run `.comeonmanineedthis` for your weekly pack!\n\n' - # 'Cal will hand out packs for the final standings when he wakes his lazy ass up. ') - # - # cal_private = discord.utils.get(sba.text_channels, name='hello-manticorum67') - # await cal_private.send(f'Weekly packs:\n\n{weekly_packs}') - # - # if now.weekday() != 0 and self.weekly_reset_done: - # self.weekly_reset_done = False - # - # db.close() + async def dev_startup(self): + # Check for Paper Sluggers event + e_query = db_get('events', params=[('name', 'Paper Sluggers')]) + if e_query is None: + this_event = db_post( + 'events', + payload={ + "name": "Paper Sluggers", + "short_desc": f'Draft a team to win you ten games as we celebrate the introduction of the ' + f'Mario Super Sluggers cardset to Paper Dynasty!', + "long_desc": "", + "url": f'https://cdn.discordapp.com/attachments/603421569972305921/1087862987215347805/' + f'PD-Mario-Full.png', + "active": True + } + ) + else: + this_event = e_query['events'][0] - # @staticmethod - # async def increment_week(): - # current = Current.get() - # current.week += 1 - # current.save() - # - # weekly_string = '' - # all_teams = Team.select() - # for x in all_teams: - # weekly_string += f'{x.sname}: {x.weeklypacks} packs\n' - # x.weeklyclaim = False - # x.dailyclaim = False - # x.weeklypacks = 0 - # x.save() - # - # return weekly_string + # Check for Game Rewards + gr_query = db_get('gamerewards', params=[('name', 'MVP Pack')]) + if gr_query['count'] == 0: + mv_pack = db_post( + 'gamerewards', + payload={ + 'name': 'MVP', + 'pack_type_id': 5 + } + ) + else: + mv_pack = gr_query['gamerewards'][0] + + gr_query = db_get('gamerewards', params=[('name', 'All-Star Pack')]) + if gr_query['count'] == 0: + as_pack = db_post( + 'gamerewards', + payload={ + 'name': 'All-Star Pack', + 'pack_type_id': 6 + } + ) + else: + as_pack = gr_query['gamerewards'][0] + + gr_query = db_get('gamerewards', params=[('name', 'Mario Pack')]) + if gr_query['count'] == 0: + m_pack = db_post( + 'gamerewards', + payload={ + 'name': 'Mario Pack', + 'pack_type_id': 7 + } + ) + else: + m_pack = gr_query['gamerewards'][0] + + # Check for Gauntlet rewards + gr_query = db_get('gauntletrewards', params=[('gauntlet_id', this_event['id'])]) + if gr_query['count'] == 0: + db_post( + 'gauntletrewards', + payload={ + 'rewards': [ + { + 'name': '3 Wins', + 'gauntlet_id': this_event['id'], + 'reward_id': m_pack['id'], + 'win_num': 3 + }, + { + 'name': '6 Wins', + 'gauntlet_id': this_event['id'], + 'reward_id': as_pack['id'], + 'win_num': 6 + }, + { + 'name': '8 Wins', + 'gauntlet_id': this_event['id'], + 'reward_id': m_pack['id'], + 'win_num': 8 + }, + { + 'name': '10 Wins', + 'gauntlet_id': this_event['id'], + 'reward_id': mv_pack['id'], + 'win_num': 10 + }, + { + 'name': '10-0', + 'gauntlet_id': this_event['id'], + 'reward_id': m_pack['id'], + 'win_num': 10, + 'loss_max': 0 + } + ] + } + ) + + @commands.command(name='dev_startup', help='Run startup function') + async def dev_startup_command(self, ctx): + await self.dev_startup() + await ctx.send(random_conf_gif()) group_give = app_commands.Group(name='give', description='Mod: Distribute packs or tokens') @@ -259,6 +326,29 @@ class Admins(commands.Cog): e_string = "\n- ".join(errors) await ctx.send(f'I encountered the following errors:\n\n{e_string}') + @app_commands.command(name='tc', description='Mod: Test command') + async def test_choices_command(self, interaction: discord.Interaction): + # await interaction.response.send_message(f'Let\'s test this function!') + # pl = db_get('players/random', params=[ + # ('min_rarity', 5), ('max_rarity', 5), ('limit', 4) + # ]) + # if pl['count']: + # players = pl['players'] + # else: + # raise ConnectionError(f'Could not create MVP pack') + # + # def p_callback(player): + # db_get('players', object_id=player['player_id']) + # + # choice = await get_choice_from_cards( + # interaction, players, callback=p_callback, temp_message='Hello!', conf_message='All done - great choice!' + # ) + # await interaction.edit_original_response(content=f'The choice was: {choice}') + + await interaction.response.defer() + draft_team = db_get('teams', params=[('abbrev', f'Gauntlet-NCB')]) + await gauntlets.wipe_team(draft_team['teams'][0], interaction) + # @commands.command(name='refresh') # @commands.is_owner() # async def import_players(self, ctx): diff --git a/cogs/economy.py b/cogs/economy.py index 5dca7e7..7655e44 100644 --- a/cogs/economy.py +++ b/cogs/economy.py @@ -562,17 +562,15 @@ class Economy(commands.Cog): 'Standard': [], 'Premium': [], 'Daily': [], - 'MVP': [] + 'MVP': [], + 'All Star': [], + 'Mario': [] } for pack in p_query['packs']: p_group = None if pack['pack_team'] is None and pack['pack_cardset'] is None: - if pack['pack_type']['name'] == 'Standard': - p_group = 'Standard' - elif pack['pack_type']['name'] == 'Premium': - p_group = 'Premium' - elif pack['pack_type']['name'] == 'MVP': - p_group = 'MVP' + if pack['pack_type']['name'] in p_data: + p_group = pack['pack_type']['name'] elif pack['pack_team'] is not None: if pack['pack_type']['name'] == 'Standard': @@ -1152,6 +1150,7 @@ class Economy(commands.Cog): roster_counts = { 'SP': 0, 'RP': 0, + 'CP': 0, 'C': 0, '1B': 0, '2B': 0, @@ -1398,12 +1397,13 @@ class Economy(commands.Cog): @commands.has_any_role(PD_PLAYERS) async def share_sheet_command( self, ctx, google_sheet_url: str, team_abbrev: Optional[str], copy_rosters: Optional[bool] = True): - team = get_team_by_owner(ctx.author.id) - if not team: + owner_team = get_team_by_owner(ctx.author.id) + if not owner_team: await ctx.send(f'I don\'t see a team for you, yet. You can sign up with the `/newteam` command!') return + team = owner_team - if team_abbrev and team_abbrev != team['abbrev']: + if team_abbrev and team_abbrev != owner_team['abbrev']: if ctx.author.id != 258104532423147520: await ctx.send(f'You can only update the team sheet for your own team, you goober.') return @@ -1415,6 +1415,21 @@ class Economy(commands.Cog): await ctx.send(f'Ope, looks like that is the template sheet. Would you please make a copy and then share?') return + gauntlet_team = get_team_by_abbrev(f'Gauntlet-{owner_team["abbrev"]}') + if gauntlet_team: + view = ButtonOptions([ctx.author], timeout=30, labels=['Main Team', 'Gauntlet Team', None, None, None]) + question = await ctx.send(f'Is this sheet for your main PD team or your active Gauntlet team?', view=view) + await view.wait() + + if not view.value: + await question.edit( + content=f'Okay you keep thinking on it and get back to me when you\'re ready.', view=None + ) + return + elif view.value == 'Gauntlet Team': + await question.delete() + team = gauntlet_team + sheets = get_sheets(self.bot) response = await ctx.send(f'I\'ll go grab that sheet...') try: @@ -1428,12 +1443,13 @@ class Economy(commands.Cog): return team_data = new_sheet.worksheet_by_title('Team Data') - team_data.update_values( - crange='B1:B2', - values=[[f'{team["id"]}'], [f'\'{team_hash(team)}']] - ) + if not gauntlet_team or owner_team != gauntlet_team: + team_data.update_values( + crange='B1:B2', + values=[[f'{team["id"]}'], [f'\'{team_hash(team)}']] + ) - if copy_rosters and team['gsheet'] != 'None': + if copy_rosters and team['gsheet'].lower() != 'none': old_sheet = sheets.open_by_key(team['gsheet']) r_sheet = old_sheet.worksheet_by_title(f'My Rosters') roster_ids = r_sheet.range('B3:B80') @@ -1476,8 +1492,13 @@ class Economy(commands.Cog): team = db_patch('teams', object_id=team['id'], params=[('gsheet', new_sheet.id)]) await refresh_sheet(team, self.bot, sheets) - await response.edit(content=f'Alright, your sheet is linked to your team - good luck this season!\n\n' - f'{HELP_SHEET_SCRIPTS}') + conf_message = f'Alright, your sheet is linked to your team - good luck' + if owner_team == team: + conf_message += 'this season!' + else: + conf_message += 'on your run!' + conf_message += f'\n\n{HELP_SHEET_SCRIPTS}' + await response.edit(content=f'{conf_message}') @commands.hybrid_command(name='refresh', help='Refresh team data in Sheets') @commands.has_any_role(PD_PLAYERS) diff --git a/cogs/gameplay.py b/cogs/gameplay.py index 4d6a504..89c296c 100644 --- a/cogs/gameplay.py +++ b/cogs/gameplay.py @@ -6,6 +6,7 @@ import os import ai_manager import discord +import gauntlets from discord import app_commands from discord.app_commands import Choice from discord.ext import commands, tasks @@ -16,7 +17,8 @@ from typing import Optional, Literal from dice import sa_fielding_roll from helpers import SBA_PLAYERS_ROLE_NAME, PD_PLAYERS_ROLE_NAME, random_conf_gif, SBA_SEASON, PD_SEASON, IMAGES, \ get_team_embed, Confirm, get_pos_abbrev, SBA_COLOR, get_roster_lineups, Question, give_packs, send_to_channel, \ - get_channel, get_or_create_role, team_role, get_cal_user, get_card_embeds, ButtonOptions, get_ratings_guide + get_channel, get_or_create_role, team_role, get_cal_user, get_card_embeds, ButtonOptions, get_ratings_guide, \ + get_team_by_owner, get_roster_sheet from gameplay_helpers import * from db_calls import db_get, db_patch, db_post, db_delete, get_team_by_abbrev from db_calls_gameplay import StratGame, StratPlay, StratLineup, StratManagerAi, get_sba_team, get_sba_player, \ @@ -160,10 +162,10 @@ class Gameplay(commands.Cog): outs = '' game_string = f'```\n' \ - f'{away_team["abbrev"]: ^4}{curr_play.away_score: ^3} {second_base}' \ + f'{away_team["abbrev"].replace("Gauntlet-", ""): ^4}{curr_play.away_score: ^3} {second_base}' \ f'{inning: >10}\n' \ - f'{home_team["abbrev"]: ^4}{curr_play.home_score: ^3} {third_base} {first_base}' \ - f'{outs: >8}\n```' + f'{home_team["abbrev"].replace("Gauntlet-", ""): ^4}{curr_play.home_score: ^3} {third_base} ' \ + f'{first_base}{outs: >8}\n```' return game_string @@ -295,7 +297,8 @@ class Gameplay(commands.Cog): embed.description = '***Mercy rule in effect***' pitcher_string = f'{player_link(game, game_state["pitcher"])}' - batter_string = f'{player_link(game, game_state["batter"])}' + batter_string = f'{game_state["curr_play"].batter.batting_order}. {player_link(game, game_state["batter"])} - ' \ + f'{game_state["curr_play"].batter.position}' all_bat_stats = get_batting_stats(game.id, lineup_id=game_state['curr_play'].batter.id) if len(all_bat_stats): @@ -358,8 +361,6 @@ class Gameplay(commands.Cog): this_ai = get_manager(game) logging.debug(f'Pitching team is an AI') gm_name = f'{game_state["pitcher"]["team"]["gmname"]}' - # n_pitcher = await next_pitcher(game_state['curr_play'], game_state["pitcher"]["team"], self.bot) - # logging.debug(f'n_pitcher: {n_pitcher}') used_pitchers = await get_team_lineups( game_id=game_state['curr_play'].game.id, team_id=game_state["pitcher"]["team"]['id'], @@ -387,7 +388,7 @@ class Gameplay(commands.Cog): make_sub(ai_manager.get_relief_pitcher( game_state['curr_play'], game_state['pitcher']['team'], used_pitchers, game.game_type )) - new_pitcher = await get_player(game, ai_manager.get_pitcher(game, game_state['curr_play'])) + new_pitcher = await get_player(game, get_pitcher(game, game_state['curr_play'])) embed.set_thumbnail(url=new_pitcher['image']) embed.add_field( name=f'SUBSTITUTION', @@ -880,32 +881,32 @@ class Gameplay(commands.Cog): if comp_play: complete_play(this_play.id) - @commands.command(name='tl') - @commands.is_owner() - async def test_lineup_command(self, ctx, team_abbrev: str): - t_query = db_get('teams', params=[('abbrev', team_abbrev)]) - if t_query['count'] > 0: - team = t_query['teams'][0] - await ctx.send(f'Pulling a lineup for the {team["lname"]}...') - lineups = ai_manager.build_lineup(team, 69420, 'l', 'minor-league') - l_output = '' - for line in lineups: - l_output += f'{line["batting_order"]} - {line["player_name"]} - {line["position"]}\n' - await ctx.send(f'Lineups:\n\n{l_output}') - else: - await ctx.send(f'No team found with abbrev {team_abbrev}') - - @commands.command(name='tr') - @commands.is_owner() - async def test_reliever_command(self, ctx, game_id: int): - this_game = get_one_game(game_id=game_id) - ai_id = this_game.away_team_id if this_game.ai_team == 'away' else this_game.home_team_id - ai_team = db_get('teams', object_id=ai_id) - used_pitchers = await get_team_lineups( - game_id=game_id, team_id=ai_team['id'], inc_inactive=True, pitchers_only=True, as_string=False - ) - reliever = ai_manager.get_relief_pitcher(get_current_play(game_id), ai_team, used_pitchers) - await ctx.send(f'Reliever selected:\n\n{reliever}') + # @commands.command(name='tl') + # @commands.is_owner() + # async def test_lineup_command(self, ctx, team_abbrev: str): + # t_query = db_get('teams', params=[('abbrev', team_abbrev)]) + # if t_query['count'] > 0: + # team = t_query['teams'][0] + # await ctx.send(f'Pulling a lineup for the {team["lname"]}...') + # lineups = ai_manager.build_lineup(team, 69420, 'l', 'minor-league') + # l_output = '' + # for line in lineups: + # l_output += f'{line["batting_order"]} - {line["player_name"]} - {line["position"]}\n' + # await ctx.send(f'Lineups:\n\n{l_output}') + # else: + # await ctx.send(f'No team found with abbrev {team_abbrev}') + # + # @commands.command(name='tr') + # @commands.is_owner() + # async def test_reliever_command(self, ctx, game_id: int): + # this_game = get_one_game(game_id=game_id) + # ai_id = this_game.away_team_id if this_game.ai_team == 'away' else this_game.home_team_id + # ai_team = db_get('teams', object_id=ai_id) + # used_pitchers = await get_team_lineups( + # game_id=game_id, team_id=ai_team['id'], inc_inactive=True, pitchers_only=True, as_string=False + # ) + # reliever = ai_manager.get_relief_pitcher(get_current_play(game_id), ai_team, used_pitchers) + # await ctx.send(f'Reliever selected:\n\n{reliever}') group_new_game = app_commands.Group(name='new-game', description='Start a new baseball game') @@ -958,7 +959,7 @@ class Gameplay(commands.Cog): @group_new_game.command(name='mlb-campaign', description='Start a new MLB Campaign game against an AI') @commands.has_any_role(PD_PLAYERS_ROLE_NAME) - async def new_game_command( + async def new_game_campaign_command( self, interaction: discord.Interaction, league: Literal['Minor League', 'Major League', 'Hall of Fame'], away_team_abbrev: str, home_team_abbrev: str, num_innings: Literal[9, 3]): await interaction.response.defer() @@ -1142,7 +1143,7 @@ class Gameplay(commands.Cog): @group_new_game.command(name='ranked', description='Start a new Ranked game against another human') @commands.has_any_role(PD_PLAYERS_ROLE_NAME) - async def new_game_command( + async def new_game_ranked_command( self, interaction: discord.Interaction, away_team_abbrev: str, home_team_abbrev: str, num_innings: Literal[9, 3]): await interaction.response.defer() @@ -1233,7 +1234,7 @@ class Gameplay(commands.Cog): @group_new_game.command(name='unlimited', description='Start a new Unlimited game against another human') @commands.has_any_role(PD_PLAYERS_ROLE_NAME) - async def new_game_command( + async def new_game_unlimited_command( self, interaction: discord.Interaction, away_team_abbrev: str, home_team_abbrev: str, num_innings: Literal[9, 3]): await interaction.response.defer() @@ -1322,6 +1323,161 @@ class Gameplay(commands.Cog): ) return + @group_new_game.command(name='gauntlet', description='Start a new Gauntlet game against an AI') + @commands.has_any_role(PD_PLAYERS_ROLE_NAME) + async def new_game_gauntlet_command(self, interaction: discord.Interaction, event_name: Literal['Paper Sluggers']): + await interaction.response.defer() + + conflict = get_one_game(channel_id=interaction.channel.id, active=True) + if conflict: + await interaction.edit_original_response( + content=f'Ope. There is already a game going on in this channel. Please wait for it to complete ' + f'before starting a new one.') + return + + try: + if interaction.channel.category.name != 'Public Fields': + await interaction.response.send_message( + f'Why don\'t you head down to one of the Public Fields that way other humans can help if anything ' + f'pops up?' + ) + return + except Exception as e: + logging.error(f'Could not check channel category: {e}') + + current = db_get('current') + week_num = current['week'] + + e_query = db_get('events', params=[("name", event_name), ("active", True)]) + if e_query['count'] == 0: + await interaction.edit_original_response( + content=f'It looks like the {event_name} has ended! Cal should really remove it from this list.' + ) + return + this_event = e_query['events'][0] + + main_team = get_team_by_owner(interaction.user.id) + team = get_team_by_abbrev(f'Gauntlet-{main_team["abbrev"]}') + if not main_team: + await interaction.edit_original_response( + content=f'I don\'t see a team for you, yet. You can sign up with the `/newteam` command!' + ) + return + if not team: + await interaction.edit_original_response( + content=f'I don\'t see an active run for you. You can get started with the `/gauntlets start` command!' + ) + return + + conflict = count_team_games(team['id']) + if conflict['count']: + await interaction.edit_original_response( + content=f'Ope. The {team["sname"]} are already playing over in ' + f'{interaction.guild.get_channel(conflict["games"][0]["channel_id"]).mention}' + ) + return + + # Get Gauntlet run + r_query = db_get( + 'gauntletruns', + params=[('team_id', team['id']), ('gauntlet_id', this_event['id']), ('is_active', True)] + ) + + if r_query['count'] == 0: + await interaction.channel.send( + f'I don\'t see an active run for you. If you would like to start a new one, run ' + f'`/new-game gauntlet {this_event["name"]}` and we can get you started in no time!' + ) + return + + this_run = r_query['runs'][0] + + # If not new or after draft, create new AI game + is_home = gauntlets.is_home_team(team, this_event, this_run) + opponent = gauntlets.get_opponent(team, this_event, this_run) + if opponent is None: + await interaction.edit_original_response( + content=f'Yike. I\'m not sure who your next opponent is. {get_cal_user(interaction)} help plz!' + ) + return + + game_code = gauntlets.get_game_code(team, this_event, this_run) + this_game = post_game({ + 'away_team_id': opponent['id'] if is_home else team['id'], + 'home_team_id': team['id'] if is_home else opponent['id'], + 'week_num': week_num, + 'channel_id': interaction.channel.id, + 'active': True, + 'is_pd': True, + 'ranked': False, + 'season': current['season'], + 'short_game': False, + 'game_type': game_code + }) + logging.info( + f'Game {this_game.id} between {team["abbrev"]} and {opponent["abbrev"]} is posted!' + ) + t_role = await team_role(interaction, main_team) + + # Get AI Lineup + try: + await interaction.edit_original_response( + content=f'I am getting a lineup card from the {opponent["sname"]}...' + ) + + logging.info(f'new-game - calling lineup for {opponent["abbrev"]}') + all_lineups = gauntlets.build_lineup(opponent, this_game, this_event) + logging.info(f'new-game-gauntlet - got lineup for {opponent["abbrev"]}') + + except Exception as e: + patch_game(this_game.id, active=False) + logging.error(f'could not start a gauntlet game with {opponent["sname"]}: {e}') + await interaction.edit_original_response( + content=f'Looks like the {opponent["sname"]} lineup card didn\'t come through clearly. I\'ll sort ' + f'this out with {opponent["gmname"]} and {get_cal_user(interaction).mention}. I\'ll end ' + f'this game - why don\'t you play against somebody else for now?' + ) + return + + # Get AI Starting Pitcher + try: + await interaction.edit_original_response( + content=f'Now to decide on a Starting Pitcher...' + ) + if opponent['id'] == this_game.away_team_id: + patch_game(this_game.id, away_roster_num=69, ai_team='away') + else: + patch_game(this_game.id, home_roster_num=69, ai_team='home') + + starter = gauntlets.get_starting_pitcher(opponent, this_game, this_event, this_run) + all_lineups.append(starter) + + this_card = db_get(f'cards', object_id=starter['card_id']) + await interaction.channel.send( + content=f'The {opponent["sname"]} are starting **{this_card["player"]["description"]}**:\n\n' + f'{this_card["player"]["image"]}' + ) + + except Exception as e: + patch_game(this_game.id, active=False) + logging.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 ' + f'this game - why don\'t you play against somebody else for now?' + ) + return + + logging.debug(f'Setting lineup for {opponent["sname"]} in PD Gauntlet game {game_code}') + post_lineups(all_lineups) + + await interaction.channel.send( + content=f'Game {gauntlets.games_played(this_run) + 1} of the run is set!\n\n' + f'Go ahead and set lineups with the `/readlineup` command!', + embed=await self.get_game_state_embed(this_game, full_length=False) + ) + return + @commands.command(name='force-endgame', help='Mod: Force a game to end without stats') @commands.is_owner() async def force_end_game_command(self, ctx: commands.Context): @@ -1367,7 +1523,15 @@ class Gameplay(commands.Cog): response = await ctx.send(f'Let\'s see what we\'ve got here...') owner_team = await get_game_team(this_game, ctx.author.id) - if not owner_team['id'] in [this_game.away_team_id, this_game.home_team_id] and \ + gauntlet_team = None + if 'gauntlet' in this_game.game_type: + gauntlet_team = await get_game_team(this_game, team_abbrev=f'Gauntlet-{owner_team["abbrev"]}') + + if not {owner_team['id'], gauntlet_team['id']}.intersection( + [this_game.away_team_id, this_game.home_team_id]): + await ctx.send('Bruh. Only GMs of the active teams can end games.') + return + elif not owner_team['id'] in [this_game.away_team_id, this_game.home_team_id] and \ ctx.author.id != self.bot.owner_id: await ctx.send('Bruh. Only GMs of the active teams can end games.') return @@ -1481,6 +1645,13 @@ class Gameplay(commands.Cog): 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 + # Check for Gauntlet game so rewards go to main team + if gauntlet_team is not None: + if winning_team['gmid'] == gauntlet_team['gmid']: + winning_team = owner_team + 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}') @@ -1665,6 +1836,8 @@ class Gameplay(commands.Cog): game_des = 'Minor League' elif this_game.ranked: game_des = 'Ranked' + elif 'gauntlet' in this_game.game_type: + game_des = 'Gauntlet' else: game_des = 'Unlimited' embed.description = f'Score Report - {game_des} ' \ @@ -1720,6 +1893,17 @@ class Gameplay(commands.Cog): give_packs(winning_team, num_packs=1, pack_type=win_reward['pack_type']) db_post(f'teams/{winning_team["id"]}/money/{win_reward["money"]}') db_post(f'teams/{losing_team["id"]}/money/{loss_reward["money"]}') + + # Gauntlet results and reward + if gauntlet_team is not None: + await gauntlets.post_result( + int(this_game.game_type.split('-')[3]), + is_win=winning_team['gmid'] == gauntlet_team['gmid'], + this_team=gauntlet_team, + bot=self.bot, + ctx=ctx + ) + else: logging.debug(f'Time to build statlines and share the scorecard for this SBa game!') # Send stats to sheets @@ -1729,169 +1913,8 @@ class Gameplay(commands.Cog): patch_game(this_game.id, active=False) logging.info(f'Game {this_game.id} is complete') - await ctx.send(f'Good game! Go share the highlights in {get_channel(ctx, "pd-news-ticker").mention}!') - - @app_commands.command( - name='setlineup', - description='Manually set lineups for for SBa games', - ) - @app_commands.describe( - order_1_player='SBa: Player Name; PD: Card #', - order_1_pos='C for Catcher, 1B for first base, P for pitcher, etc.', - order_2_player='SBa: Player Name; PD: Card #', - order_2_pos='C for Catcher, 1B for first base, P for pitcher, etc.', - order_3_player='SBa: Player Name; PD: Card #', - order_3_pos='C for Catcher, 1B for first base, P for pitcher, etc.', - order_4_player='SBa: Player Name; PD: Card #', - order_4_pos='C for Catcher, 1B for first base, P for pitcher, etc.', - order_5_player='SBa: Player Name; PD: Card #', - order_5_pos='C for Catcher, 1B for first base, P for pitcher, etc.', - order_6_player='SBa: Player Name; PD: Card #', - order_6_pos='C for Catcher, 1B for first base, P for pitcher, etc.', - order_7_player='SBa: Player Name; PD: Card #', - order_7_pos='C for Catcher, 1B for first base, P for pitcher, etc.', - order_8_player='SBa: Player Name; PD: Card #', - order_8_pos='C for Catcher, 1B for first base, P for pitcher, etc.', - order_9_player='SBa: Player Name; PD: Card #', - order_9_pos='C for Catcher, 1B for first base, P for pitcher, etc.', - order_10_player='SBa: Player Name; PD: Card #; only used with a DH', - order_10_pos='P for pitcher; only used with a DH' - ) - @app_commands.checks.has_any_role(SBA_PLAYERS_ROLE_NAME, PD_PLAYERS_ROLE_NAME) - async def set_lineup_command( - self, interaction: discord.Interaction, team_abbrev: str, order_1_player: str, order_1_pos: str, - order_2_player: str, order_2_pos: str, order_3_player: str, order_3_pos: str, order_4_player: str, - order_4_pos: str, order_5_player: str, order_5_pos: str, order_6_player: str, order_6_pos: str, - order_7_player: str, order_7_pos: str, order_8_player: str, order_8_pos: str, order_9_player: str, - order_9_pos: str, order_10_player: Optional[str] = None, order_10_pos: Optional[str] = 'P'): - this_game = get_one_game(channel_id=interaction.channel_id, active=True) - if not this_game: - await interaction.response.send_message(f'I dont\'t see an active game in this channel!') - return - - owner_team = await get_game_team(this_game, interaction.user.id) - lineup_team = await get_game_team(this_game, team_abbrev=team_abbrev) - - if not owner_team['id'] in [this_game.away_team_id, this_game.home_team_id]: - await interaction.response.send_message('Bruh. Only GMs of the active teams can set lineups.') - return - if not lineup_team['id'] in [this_game.away_team_id, this_game.home_team_id]: - await interaction.response.send_message( - f'I do not see {lineup_team["sname"]} in this game. Please check the team abbrev and try again' - ) - return - - existing_lineups = await get_team_lineups(this_game.id, lineup_team['id']) - if not existing_lineups or not len(existing_lineups): - await interaction.response.send_message( - f'It looks like the {lineup_team["sname"]} already have a lineup. Run `/substitution` to make changes.' - ) - return - - await interaction.response.defer() - - all_lineups = [] - all_pos = [] - lineup_data = [ - (order_1_pos, order_1_player), (order_2_pos, order_2_player), (order_3_pos, order_3_player), - (order_4_pos, order_4_player), (order_5_pos, order_5_player), (order_6_pos, order_6_player), - (order_7_pos, order_7_player), (order_8_pos, order_8_player), (order_9_pos, order_9_player), - (order_10_pos, order_10_player) - ] - for index, pair in enumerate(lineup_data): - if not pair[1]: - break - - if pair[0].upper() not in all_pos: - all_pos.append(pair[0].upper()) - else: - raise SyntaxError(f'You have more than one {pair[0].upper()} in this lineup. Please update and set the ' - f'lineup again.') - - if this_game.is_pd: - this_card = db_get(f'cards', object_id=int(pair[1])) - if this_card['team']['id'] != lineup_team['id']: - raise SyntaxError(f'Easy there, champ. Looks like card ID {pair[1]} belongs to the ' - f'{this_card["team"]["sname"]}. Try again with only cards you own.') - player_id = this_card['player']['player_id'] - card_id = pair[1] - else: - this_player = get_sba_player(pair[1], season=SBA_SEASON) - if this_player['team']['id'] != lineup_team['id']: - raise SyntaxError(f'Easy there, champ. Looks like {pair[1]} is on ' - f'{this_player["team"]["sname"]}. Try again with only your own players.') - player_id = this_player['id'] - card_id = None - - this_lineup = { - 'game_id': this_game.id, - 'team_id': lineup_team['id'], - 'player_id': player_id, - 'card_id': card_id, - 'position': pair[0].upper(), - 'batting_order': index + 1, - 'after_play': 0 - } - - all_lineups.append(this_lineup) - - if len(all_lineups) < 9: - await interaction.edit_original_response( - content=f'Looks like the {lineup_team["sname"]} lineup card didn\'t come through clearly. I\'ll sort ' - f'this out with {lineup_team["gmname"]} and {get_cal_user(interaction).mention}. I\'ll end ' - f'this game - why don\'t you play against somebody else for now?' - ) - patch_game(this_game.id, active=False) - return - - logging.info(f'Setting lineup for {owner_team["sname"]} in {"PD" if this_game.is_pd else "SBa"} game') - post_lineups(all_lineups) - - try: - await interaction.edit_original_response(content=None, embed=await self.get_game_state_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}') - await interaction.response.send_message(f'Game state will be posted once both lineups are in') - return - - # @app_commands.command(name='starting-pitcher') - # @app_commands.checks.has_any_role(SBA_PLAYERS_ROLE_NAME, PD_PLAYERS_ROLE_NAME) - # async def starting_pitcher_command( - # self, interaction: discord.Interaction, team_abbrev: str, sp_card_id: int, batting_order: int = 10): - # this_game = get_one_game(channel_id=interaction.channel_id, active=True) - # if not this_game: - # await interaction.response.send_message(f'I dont\'t see an active game in this channel!') - # return - # - # await interaction.response.defer() - # - # owner_team = await get_game_team(this_game, interaction.user.id) - # lineup_team = await get_game_team(this_game, team_abbrev=team_abbrev) - # this_card = db_get(f'cards', object_id=sp_card_id) - # if this_card['team']['id'] != lineup_team['id']: - # await interaction.edit_original_response( - # content=f'Uh oh, it looks like that copy of {this_card["player"]["p_name"]} doesn\'t belong to you. ' - # f'Please enter the card_id of a card from your collection.' - # ) - # return - # - # this_lineup = { - # 'game_id': this_game.id, - # 'team_id': lineup_team['id'], - # 'player_id': this_card['player']['player_id'], - # 'card_id': sp_card_id, - # 'position': 'P', - # 'batting_order': batting_order, - # 'after_play': 0 - # } - # post_lineups([this_lineup]) - # - # try: - # await interaction.edit_original_response(content=None, embed=await self.get_game_state_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}') - # await interaction.response.send_message(f'Game state will be posted once both lineups are in') - # return + if gauntlet_team is None: + await ctx.send(f'Good game! Go share the highlights in {get_channel(ctx, "pd-news-ticker").mention}!') @app_commands.command( name='readlineup', @@ -1899,14 +1922,14 @@ class Gameplay(commands.Cog): ) @app_commands.describe( team_abbrev='The 2- to 4-digit abbreviation for the team being set', - roster_num='1, 2, or 3: 1 is Primary, 2 is Secondary, 3 is Tertiary; Enter 1 for AI team', - lineup_num='1 or 2: 1 is top lineup in sheet, 2 is bottom; Enter 1 for AI team', + roster='Which roster to pull from your sheet?', + lineup='Which handedness lineup are you using?', sp_card_id='Light gray number to the left of the pitcher\'s name on your depth chart' ) @app_commands.checks.has_any_role(PD_PLAYERS_ROLE_NAME) async def read_lineup_command( - self, interaction: discord.Interaction, team_abbrev: str, roster_num: Literal[1, 2, 3], - lineup_num: Literal[1, 2], sp_card_id: int): + self, interaction: discord.Interaction, team_abbrev: str, roster: Literal['Primary', 'Secondary', 'Ranked'], + lineup: Literal['v Right', 'v Left'], sp_card_id: int): this_game = get_one_game(channel_id=interaction.channel_id, active=True) if not this_game: await interaction.response.send_message(f'I dont\'t see an active game in this channel!') @@ -1918,9 +1941,12 @@ class Gameplay(commands.Cog): return owner_team = await get_game_team(this_game, interaction.user.id) - lineup_team = await get_game_team(this_game, team_abbrev=team_abbrev) + if 'gauntlet' in this_game.game_type: + lineup_team = await get_game_team(this_game, team_abbrev=f'Gauntlet-{owner_team["abbrev"]}') + else: + lineup_team = await get_game_team(this_game, team_abbrev=team_abbrev) - if not owner_team['id'] in [this_game.away_team_id, this_game.home_team_id]: + if owner_team['gmid'] != lineup_team['gmid']: await interaction.response.send_message('Bruh. Only GMs of the active teams can set lineups.') return if not lineup_team['id'] in [this_game.away_team_id, this_game.home_team_id]: @@ -1937,12 +1963,19 @@ class Gameplay(commands.Cog): return await interaction.response.send_message(f'Let\'s put this lineup card together...') - lineup_cells = get_roster_lineups( - lineup_team, - self.bot, - roster_num, - lineup_num if not lineup_team['is_ai'] else 1 - ) + + if lineup == 'v Right': + l_num = 1 + else: + l_num = 2 + + if roster == 'Primary': + roster_num = 1 + elif roster == 'Secondary': + roster_num = 2 + else: + roster_num = 3 + lineup_cells = get_roster_lineups(lineup_team, self.bot, roster_num, l_num) all_lineups = [] all_pos = [] @@ -2081,12 +2114,14 @@ class Gameplay(commands.Cog): return owner_team = await get_game_team(this_game, ctx.author.id) - lineup_team = await get_game_team(this_game, team_abbrev=team_abbrev) + if 'gauntlet' in this_game.game_type: + lineup_team = await get_game_team(this_game, team_abbrev=f'Gauntlet-{owner_team["abbrev"]}') + else: + lineup_team = await get_game_team(this_game, team_abbrev=team_abbrev) - if not owner_team['id'] in [this_game.away_team_id, this_game.home_team_id]: + if owner_team['gmid'] != lineup_team['gmid']: await ctx.send('Bruh. Only GMs of the active teams can set lineups.') return - if not lineup_team['id'] in [this_game.away_team_id, this_game.home_team_id]: await ctx.send(f'I do not see {lineup_team["sname"]} in this game. Please check the team abbrev and ' f'try again') @@ -2156,14 +2191,16 @@ class Gameplay(commands.Cog): this_game = get_one_game(channel_id=interaction.channel.id, active=True) if not this_game: - await interaction.response.send_message('I don\'t see a game in this channel.') + await interaction.edit_original_response(content='I don\'t see a game in this channel.') return False, False, False owner_team = await get_game_team(this_game, interaction.user.id) + 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 ' f'aren\'t a GM in the game.') - await interaction.response.send_message('Bruh. Only GMs of the active teams can log plays.') + await interaction.edit_original_response(content='Bruh. Only GMs of the active teams can log plays.') # return this_game, False, False this_play = get_current_play(this_game.id) @@ -2181,7 +2218,7 @@ class Gameplay(commands.Cog): if not this_play.pitcher: logging.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.response.send_message(f'Please sub in a pitcher before logging a new play.') + await interaction.edit_original_response(content=f'Please sub in a pitcher before logging a new play.') this_play = None return this_game, owner_team, this_play diff --git a/cogs/players.py b/cogs/players.py index bb8206c..1ec9c29 100644 --- a/cogs/players.py +++ b/cogs/players.py @@ -14,7 +14,9 @@ from discord.ext import commands, tasks from difflib import get_close_matches from discord.ext.commands import Greedy -from db_calls import db_get, db_post, db_patch + +import gauntlets +from db_calls import db_get, db_post, db_patch, get_team_by_abbrev from helpers import PD_PLAYERS_ROLE_NAME, IMAGES, PD_SEASON, random_conf_gif, fuzzy_player_search, ALL_MLB_TEAMS, \ fuzzy_search, get_channel, display_cards, get_card_embeds, get_team_embed, cardset_search, get_blank_team_card, \ get_team_by_owner, get_rosters, get_roster_sheet, legal_channel, random_conf_word, embed_pagination, get_cal_user, \ @@ -727,6 +729,103 @@ class Players(commands.Cog): await ctx.send(random_conf_gif()) + group_gauntlet = app_commands.Group(name='gauntlets', description='Check your progress or start a new Gauntlet') + + @group_gauntlet.command(name='status', description='View status of current Gauntlet run') + @app_commands.describe( + team_abbrev='To check the status of a team\'s active run, enter their abbreviation' + ) + @app_commands.checks.has_any_role(PD_PLAYERS_ROLE_NAME) + async def gauntlet_run_command( + self, interaction: discord.Interaction, event_name: Literal['Paper Sluggers'], team_abbrev: str = None): + await interaction.response.defer() + + e_query = db_get('events', params=[("name", event_name), ("active", True)]) + if e_query['count'] == 0: + await interaction.response.send_message(f'Hmm...looks like that event has ended already.') + return + else: + this_event = e_query['events'][0] + + this_run = None + if team_abbrev: + if 'Gauntlet-' not in team_abbrev: + team_abbrev = f'Gauntlet-{team_abbrev}' + t_query = db_get('teams', params=[('abbrev', team_abbrev)]) + if t_query['count'] != 0: + this_team = t_query['teams'][0] + r_query = db_get('gauntletruns', params=[('team_id', this_team['id']), ('is_active', True)]) + + if r_query['count'] != 0: + this_run = r_query['runs'][0] + else: + await interaction.channel.send( + content=f'I do not see an active run for the {this_team["lname"]}.' + ) + else: + await interaction.channel.send( + content=f'I do not see an active run for {team_abbrev.upper()}.' + ) + + await interaction.edit_original_response( + content=None, + embed=gauntlets.get_embed(this_run, this_event) + ) + + @group_gauntlet.command(name='start', description='Start a new Gauntlet run') + @app_commands.checks.has_any_role(PD_PLAYERS_ROLE_NAME) + async def gauntlet_start_command(self, interaction: discord.Interaction, event_name: Literal['Paper Sluggers']): + await interaction.response.defer() + main_team = get_team_by_owner(interaction.user.id) + draft_team = get_team_by_abbrev(f'Gauntlet-{main_team["abbrev"]}') + + e_query = db_get('events', params=[("name", event_name), ("active", True)]) + if e_query['count'] == 0: + await interaction.response.send_message(f'Hmm...looks like that event has ended already.') + return + else: + this_event = e_query['events'][0] + + first_flag = draft_team is None + if draft_team is not None: + r_query = db_get( + 'gauntletruns', + params=[('team_id', draft_team['id']), ('gauntlet_id', this_event['id']), ('is_active', True)] + ) + + if r_query['count'] != 0: + await interaction.edit_original_response( + content=f'Looks like you already have a {event_name} run active! You can check it out with the ' + f'`/gauntlets status` command.' + ) + return + + try: + await gauntlets.run_draft(interaction, main_team, this_event, draft_team) + except Exception as e: + logging.error(f'Failed to run {event_name} draft for the {main_team["sname"]}: {e}') + draft_team = db_get('teams', params=[('abbrev', f'Gauntlet-{main_team["abbrev"]}')]) + await gauntlets.wipe_team(draft_team, interaction) + await interaction.channel.send( + content=f'Shoot - it looks like we ran into an issue running the draft. I had to clear it all out ' + f'for now. I let {get_cal_user(interaction).mention} know what happened so he better ' + f'fix it quick.' + ) + return + + if first_flag: + await interaction.channel.send( + f'Good luck, champ in the making! To start playing, follow these steps:\n\n' + f'1) Make a copy of the Team Sheet Template found in `/help-pd links`\n' + f'2) Run `/newsheet` to link it to your Gauntlet team\n' + f'3) Go play your first game with `/new-game gauntlet {this_event["name"]}`' + ) + else: + await interaction.channel.send( + f'Good luck, champ in the making! Go ahead and set your lineup here and you\'ll be ready to go!\n\n' + f'{get_roster_sheet(draft_team)}' + ) + # @commands.command(name='standings', aliases=['leaders', 'points', 'weekly'], help='Weekly standings') # async def standings_command(self, ctx, *week_or_season): # if not await legal_channel(ctx): diff --git a/db_calls.py b/db_calls.py index a7cf961..fc3c34c 100644 --- a/db_calls.py +++ b/db_calls.py @@ -115,7 +115,7 @@ def db_post(endpoint: str, api_ver: int = 1, payload: dict = None, timeout: int raise ValueError(f'DB: {resp.text}') -def db_delete(endpoint: str, object_id: int, api_ver: int = 3): +def db_delete(endpoint: str, object_id: int, api_ver: int = 1): req_url = get_req_url(endpoint, api_ver=api_ver, object_id=object_id) log_string = f'delete:\n{endpoint} {object_id}' logging.info(log_string) if master_debug else logging.debug(log_string) diff --git a/db_calls_gameplay.py b/db_calls_gameplay.py index 07bc04a..53759b3 100644 --- a/db_calls_gameplay.py +++ b/db_calls_gameplay.py @@ -2117,9 +2117,11 @@ def get_pitching_decisions(game: StratGame): def get_final_scorebug(away_team, home_team, away_stats, home_stats): return f'```' \ f'Team | R | H | E |\n' \ - f'{away_team["abbrev"]: <4} | {away_stats["score"]: >2} | {away_stats["hits"]: >2} | ' \ + f'{away_team["abbrev"].replace("Gauntlet-", ""): <4} | {away_stats["score"]: >2} | ' \ + f'{away_stats["hits"]: >2} | ' \ f'{away_stats["f_lines"][0]["tm_error"] if away_stats["f_lines"] else 0: >2} |\n' \ - f'{home_team["abbrev"]: <4} | {home_stats["score"]: >2} | {home_stats["hits"]: >2} | ' \ + f'{home_team["abbrev"].replace("Gauntlet-", ""): <4} | {home_stats["score"]: >2} | ' \ + f'{home_stats["hits"]: >2} | ' \ f'{home_stats["f_lines"][0]["tm_error"] if home_stats["f_lines"] else 0: >2} |\n' \ f'```' diff --git a/gameplay_helpers.py b/gameplay_helpers.py index 787eb2c..ddbfa55 100644 --- a/gameplay_helpers.py +++ b/gameplay_helpers.py @@ -1,6 +1,7 @@ import logging import random +import db_calls_gameplay from db_calls_gameplay import StratGame, StratPlay, StratLineup, StratManagerAi, patch_play, advance_runners, \ complete_play, get_team_lineups, get_or_create_bullpen, get_player, get_sheets, make_sub from db_calls import db_get @@ -155,3 +156,10 @@ def replace_pitcher(ai_team, this_play, pitcher_card_id): } make_sub(new_lineup) + +def get_pitcher(this_game: StratGame, this_play: StratPlay): + p_team_id = this_game.away_team_id + if this_play.inning_half == 'top': + p_team_id = this_game.home_team_id + return db_calls_gameplay.get_one_lineup(this_game.id, team_id=p_team_id, position='P', active=True) + diff --git a/gauntlets.py b/gauntlets.py new file mode 100644 index 0000000..c710d3c --- /dev/null +++ b/gauntlets.py @@ -0,0 +1,548 @@ +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 = 14 + 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: + set_params = ai_manager.MINOR_CARDSET_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"]}') + + # Pull pitchers + try: + 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: + raise DatabaseError(f'Could not find any SP for {this_team["abbrev"]}. Seems like a Cal issue.') + 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]) + 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') + return + + 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"]}/8)', value=all_str['Reserve'], inline=False) + top_embed.add_field( + name=f'Replacements ({counts["Replacement"]}/4)', 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] + + await interaction.edit_original_response( + content=None, + embeds=get_embeds(), + view=None + ) + + 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', 'RP')) + 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 is not None: + test_player_list = '' + for x in p_query['players']: + test_player_list += f'{x["rarity"]["name"]} - {x["description"]} - {helpers.get_all_pos(x)}\n' + # await interaction.channel.send(f'The Round {round_num} players drawn are:\n\n{test_player_list}') + + # 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 + await interaction.edit_original_response( + content=None, + embeds=get_embeds(include_links=False) + ) + round_num += 1 + 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'] + } + ) + + +def get_embed(this_run=None, this_event=None): + 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!' + + await ctx.send( + content=l_message, + embed=get_embed(this_run) + ) + diff --git a/help_text.py b/help_text.py index 7ee2b29..4642804 100644 --- a/help_text.py +++ b/help_text.py @@ -26,13 +26,16 @@ HELP_GAMEMODES = ( f'the playoffs at the end of the season and fight for the Paper Cup.\n' f'- Unlimited Play: Play against another PD manager or an AI with either of your un-ranked rosters. Great for ' f'casual play, playtesting rosters, and event games.\n' - f'- Gauntlets: Coming soon' + f'- Gauntlets: Draft a team of 26 and attempt to win 10 games before losing 2. Rewards escalate based on the ' + f'number of wins.' ) HELP_NEWGAME = ( - f'- Run `/newgame` and add the prompted info\n' - f'- Set starting lineups with `/read-lineup` for each team\n' - f'- Set your starting pitcher with `/starting-pitcher`\n\n' + f'- Run `/new-game` and select a game mode:\n' + f'** **- gauntlet: Draft a team and attempt to go 10-0 against the AI teams\n' + f'** **- mlb-campaign: Progress from Minors -> Majors -> Hall of Fame by defeating all 30 MLB teams\n' + f'** **- ranked/unlimited: Play against another human player\n' + f'- Set starting lineups with `/read-lineup` for each team\n\n' f'From here, the game scorebug will be posted and you are ready to start rolling dice!' ) @@ -109,7 +112,6 @@ HELP_REWARDS_STANDARD = ( HELP_REWARDS_MONEY = ( '- 75₼ for playing a 9-inning game\n' '- 25₼ for playing a 3-inning game\n' - '- Variable per cardset collections (`/paperdex`)' ) HELP_REWARDS_SHOP = ( diff --git a/helpers.py b/helpers.py index f947aab..68f92b8 100644 --- a/helpers.py +++ b/helpers.py @@ -64,6 +64,7 @@ IMAGES = { 'mvp-hype': f'{PD_CARD_URL}/mvp.png', 'pack-sta': f'{PD_CARD_URL}/pack-standard.png', 'pack-pre': f'{PD_CARD_URL}/pack-premium.png', + 'pack-mar': f'{PD_CARD_URL}/sluggers/mario-gauntlet.png', 'mvp': { 'Arizona Diamondbacks': f'{PD_CARD_URL}/mvp/arizona-diamondbacks.gif', 'Atlanta Braves': f'{PD_CARD_URL}/mvp/atlanta-braves.gif', @@ -97,7 +98,8 @@ IMAGES = { 'Texas Rangers': f'{PD_CARD_URL}/mvp/texas-rangers.gif', 'Toronto Blue Jays': f'{PD_CARD_URL}/mvp/toronto-blue-jays.gif', 'Washington Nationals': f'{PD_CARD_URL}/mvp/washington-nationals.gif', - } + }, + 'gauntlets': f'{PD_CARD_URL}/gauntlets.png' } INFIELD_X_CHART = { 'si1': { @@ -214,6 +216,14 @@ OUTFIELD_X_CHART = { 'no': 'Flyball C' } } +RARITY = { + 'HoF': 8, + 'MVP': 5, + 'All-Star': 3, + 'Starter': 2, + 'Reserve': 1, + 'Replacement': 0 +} class Question: @@ -462,6 +472,12 @@ class SelectOpenPack(discord.ui.Select): 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)) else: raise KeyError(f'Cannot identify pack details: {pack_vals}') @@ -1331,7 +1347,7 @@ def get_all_pos(player): all_pos = [] for x in range(1, 8): - if player[f'pos_{x}'] and player[f'pos_{x}'] != 'CP': + if player[f'pos_{x}']: all_pos.append(player[f'pos_{x}']) return all_pos @@ -2525,6 +2541,8 @@ def get_pack_cover(pack): return IMAGES['pack-pre'] elif pack['pack_type']['name'] == 'Standard': return IMAGES['pack-sta'] + elif pack['pack_type']['name'] == 'Mario': + return IMAGES['pack-mar'] else: return None @@ -2563,25 +2581,137 @@ async def open_st_pr_packs(all_packs: list, team: dict, context): await display_cards(all_cards, team, pack_channel, author, pack_cover=pack_cover) +async def get_choice_from_cards( + interaction: discord.Interaction, all_players: list = None, cover_title: str = None, + cover_desc: str = None, cover_image_url: str = None, callback=None, temp_message: str = None, + conf_message: str = None, delete_message: bool = False): + # Display them with pagination, prev/next/select + card_embeds = [ + await get_card_embeds( + {'player': x, 'team': {'lname': 'Paper Dynasty', 'season': PD_SEASON, 'logo': IMAGES['logo']}} + ) for x in all_players + ] + logging.info(f'card embeds: {card_embeds}') + + if cover_title is not None and cover_image_url is not None: + page_num = 0 + + view = Pagination([interaction.user], timeout=30) + view.left_button.disabled = True + view.left_button.label = f'Prev: -/{len(card_embeds)}' + view.cancel_button.label = f'Take This Card' + view.cancel_button.style = discord.ButtonStyle.success + view.cancel_button.disabled = True + view.right_button.label = f'Next: 1/{len(card_embeds)}' + + msg = await interaction.channel.send( + content=None, + embed=image_embed( + image_url=cover_image_url, + title=cover_title, + desc=cover_desc + ), + view=view + ) + else: + page_num = 1 + + view = Pagination([interaction.user], timeout=30) + view.left_button.label = f'Prev: -/{len(card_embeds)}' + view.left_button.disabled = True + view.cancel_button.label = f'Take This Card' + view.cancel_button.style = discord.ButtonStyle.success + view.right_button.label = f'Next: {page_num + 1}/{len(card_embeds)}' + + msg = await interaction.channel.send(content=None, embeds=card_embeds[page_num - 1], view=view) + + if temp_message is not None: + temp_msg = await interaction.channel.send(content=temp_message) + else: + temp_msg = None + + while True: + await view.wait() + + if view.value: + if view.value == 'cancel': + await msg.edit(view=None) + + if callback is not None: + callback(all_players[page_num - 1]) + + if conf_message is not None: + if temp_msg is not None: + await temp_msg.edit(content=conf_message) + else: + await interaction.channel.send(content=conf_message) + break + if view.value == 'left': + page_num -= 1 if page_num > 1 else len(card_embeds) + if view.value == 'right': + page_num += 1 if page_num < len(card_embeds) else 1 + else: + if page_num == len(card_embeds): + page_num = 1 + else: + page_num += 1 + + view.value = None + + view = Pagination([interaction.user], timeout=30) + view.left_button.label = f'Prev: {page_num - 1}/{len(card_embeds)}' + view.cancel_button.label = f'Take This Card' + view.cancel_button.style = discord.ButtonStyle.success + view.right_button.label = f'Next: {page_num + 1}/{len(card_embeds)}' + if page_num == 1: + view.left_button.label = f'Prev: -/{len(card_embeds)}' + view.left_button.disabled = True + elif page_num == len(card_embeds): + view.right_button.label = f'Next: -/{len(card_embeds)}' + view.right_button.disabled = True + + await msg.edit(content=None, embeds=card_embeds[page_num - 1], view=view) + + if delete_message: + await msg.delete() + return all_players[page_num - 1] + + async def open_choice_pack(this_pack, team: dict, context): pack_channel = get_channel(context, 'pack-openings') pack_cover = get_pack_cover(this_pack) pack_type = this_pack['pack_type']['name'] - # Get 4 MVP cards - rarity_id = 5 - if pack_type == 'HoF': - rarity_id = 8 - elif pack_type == 'All-Star': - rarity_id = 3 + if pack_type == 'Mario': + d1000 = random.randint(1, 1000) + if d1000 > 800: + rarity_id = 5 + elif d1000 > 550: + rarity_id = 3 + else: + rarity_id = 2 + pl = db_get( + 'players/random', + params=[ + ('cardset_id', 8), ('min_rarity', rarity_id), ('max_rarity', rarity_id), ('limit', 4) + ] + ) + else: + # Get 4 MVP cards + rarity_id = 5 + if pack_type == 'HoF': + rarity_id = 8 + elif pack_type == 'All Star': + rarity_id = 3 + + pl = db_get('players/random', params=[ + ('min_rarity', rarity_id), ('max_rarity', rarity_id), ('limit', 4) + ]) - pl = db_get('players/random', params=[ - ('min_rarity', rarity_id), ('max_rarity', rarity_id), ('limit', 4) - ]) if pl['count']: players = pl['players'] else: - raise ConnectionError(f'Could not create MVP pack') + raise ConnectionError(f'Could not create choice pack') if type(context) == commands.Context: author = context.author @@ -2612,7 +2742,10 @@ async def open_choice_pack(this_pack, team: dict, context): embed=image_embed(pack_cover, title=f'{team["lname"]}', desc=f'{pack_type} Pack - Choose 1 of 4 {pack_type}s!'), view=view ) - tmp_msg = await pack_channel.send(content=f'@here we\'ve got an MVP!') + if rarity_id >= 5: + tmp_msg = await pack_channel.send(content=f'@here we\'ve got an MVP!') + else: + tmp_msg = await pack_channel.send(content=f'We\'ve got a choice pack here!') while True: await view.wait()