async def problems(self, ctx, member: discord.Member = None): if not member: member = ctx.author if not self.db.in_a_round(ctx.guild.id, member.id): await discord_.send_message(ctx, f"{member.mention} is not in a round") return round_info = self.db.get_round_info(ctx.guild.id, member.id) await ctx.send(embed=discord_.round_problems_embed(round_info))
async def update_rounds(client): rounds = db.get_all_rounds() global api if api is None: api = challonge_api.ChallongeAPI(client) for round in rounds: try: guild = client.get_guild(round.guild) resp = await updation.update_round(round) if not resp[0]: logging_channel = await client.fetch_channel( os.environ.get("LOGGING_CHANNEL")) await logging_channel.send( f"Error while updating rounds: {resp[1]}") continue resp = resp[1] channel = client.get_channel(round.channel) if resp[2] or resp[1]: await channel.send( f"{' '.join([(await guild.fetch_member(int(m))).mention for m in round.users.split()])} there is an update in standings" ) for i in range(len(resp[0])): if len(resp[0][i]): await channel.send(embed=discord.Embed( description= f"{' '.join([(await guild.fetch_member(m)).mention for m in resp[0][i]])} has solved problem worth **{round.points.split()[i]}** points", color=discord.Color.blue())) if not resp[1] and resp[2]: new_info = db.get_round_info(round.guild, round.users) await channel.send( embed=discord_.round_problems_embed(new_info)) if resp[1]: round_info = db.get_round_info(round.guild, round.users) ranklist = updation.round_score( list(map(int, round_info.users.split())), list(map(int, round_info.status.split())), list(map(int, round_info.times.split()))) eloChanges = elo.calculateChanges([[ (await guild.fetch_member(user.id)), user.rank, db.get_match_rating(round_info.guild, user.id)[-1] ] for user in ranklist]) for id in list(map(int, round_info.users.split())): db.add_rating_update(round_info.guild, id, eloChanges[id][0]) db.delete_round(round_info.guild, round_info.users) db.add_to_finished_rounds(round_info) embed = discord.Embed(color=discord.Color.dark_magenta()) pos, name, ratingChange = '', '', '' for user in ranklist: handle = db.get_handle(round_info.guild, user.id) emojis = [ ":first_place:", ":second_place:", ":third_place:" ] pos += f"{emojis[user.rank - 1] if user.rank <= len(emojis) else str(user.rank)} **{user.points}**\n" name += f"[{handle}](https://codeforces.com/profile/{handle})\n" ratingChange += f"{eloChanges[user.id][0]} (**{'+' if eloChanges[user.id][1] >= 0 else ''}{eloChanges[user.id][1]}**)\n" embed.add_field(name="Position", value=pos) embed.add_field(name="User", value=name) embed.add_field(name="Rating changes", value=ratingChange) embed.set_author(name=f"Round over! Final standings") await channel.send(embed=embed) if round_info.tournament == 1: tournament_info = db.get_tournament_info(round_info.guild) if not tournament_info or tournament_info.status != 2: continue if ranklist[1].rank == 1 and tournament_info.type != 2: await discord_.send_message( channel, "Since the round ended in a draw, you will have to compete again for it to be counted in the tournament" ) else: res = await tournament_helper.validate_match( round_info.guild, ranklist[0].id, ranklist[1].id, api, db) if not res[0]: await discord_.send_message( channel, res[1] + "\n\nIf you think this is a mistake, type `.tournament forcewin <handle>` to grant victory to a user" ) else: draw = True if ranklist[1].rank == 1 else False scores = f"{ranklist[0].points}-{ranklist[1].points}" if res[ 1]['player1'] == res[1][ ranklist[0]. id] else f"{ranklist[1].points}-{ranklist[0].points}" match_resp = await api.post_match_results( res[1]['tournament_id'], res[1]['match_id'], scores, res[1][ranklist[0].id] if not draw else "tie") if not match_resp or 'errors' in match_resp: await discord_.send_message( channel, "Some error occurred while validating tournament match. \n\nType `.tournament forcewin <handle>` to grant victory to a user manually" ) if match_resp and 'errors' in match_resp: logging_channel = await client.fetch_channel( os.environ.get("LOGGING_CHANNEL")) await logging_channel.send( f"Error while validating tournament rounds: {match_resp['errors']}" ) continue winner_handle = db.get_handle( round_info.guild, ranklist[0].id) await discord_.send_message( channel, f"{f'Congrats **{winner_handle}** for qualifying to the next round. :tada:' if not draw else 'The round ended in a draw!'}\n\nTo view the list of future tournament rounds, type `.tournament matches`" ) if await tournament_helper.validate_tournament_completion( round_info.guild, api, db): await api.finish_tournament( res[1]['tournament_id']) await asyncio.sleep(3) winner_handle = await tournament_helper.get_winner( res[1]['tournament_id'], api) await channel.send( embed=tournament_helper. tournament_over_embed( round_info.guild, winner_handle, db)) db.add_to_finished_tournaments( db.get_tournament_info(round_info.guild), winner_handle) db.delete_tournament(round_info.guild) except Exception as e: logging_channel = await client.fetch_channel( os.environ.get("LOGGING_CHANNEL")) await logging_channel.send( f"Error while updating rounds: {str(traceback.format_exc())}")
async def challenge(self, ctx, *users: discord.Member): users = list(set(users)) if len(users) == 0: await discord_.send_message( ctx, f"The correct usage is `.round challenge @user1 @user2...`") return if ctx.author not in users: users.append(ctx.author) if len(users) > MAX_ROUND_USERS: await ctx.send( f"{ctx.author.mention} atmost {MAX_ROUND_USERS} users can compete at a time" ) return for i in users: if not self.db.get_handle(ctx.guild.id, i.id): await discord_.send_message( ctx, f"Handle for {i.mention} not set! Use `.handle identify` to register" ) return if self.db.in_a_round(ctx.guild.id, i.id): await discord_.send_message( ctx, f"{i.mention} is already in a round!") return embed = discord.Embed( description= f"{' '.join(x.mention for x in users)} react on the message with ✅ within 30 seconds to join the round. {'Since you are the only participant, this will be a practice round and there will be no rating changes' if len(users) == 1 else ''}", color=discord.Color.purple()) message = await ctx.send(embed=embed) await message.add_reaction("✅") all_reacted = False reacted = [] def check(reaction, user): return reaction.message.id == message.id and reaction.emoji == "✅" and user in users while True: try: reaction, user = await self.client.wait_for('reaction_add', timeout=30, check=check) reacted.append(user) if all(item in reacted for item in users): all_reacted = True break except asyncio.TimeoutError: break if not all_reacted: await discord_.send_message( ctx, f"Unable to start round, some participant(s) did not react in time!" ) return problem_cnt = await discord_.get_time_response( self.client, ctx, f"{ctx.author.mention} enter the number of problems between [1, {MAX_PROBLEMS}]", 30, ctx.author, [1, MAX_PROBLEMS]) if not problem_cnt[0]: await discord_.send_message( ctx, f"{ctx.author.mention} you took too long to decide") return problem_cnt = problem_cnt[1] duration = await discord_.get_time_response( self.client, ctx, f"{ctx.author.mention} enter the duration of match in minutes between {MATCH_DURATION}", 30, ctx.author, MATCH_DURATION) if not duration[0]: await discord_.send_message( ctx, f"{ctx.author.mention} you took too long to decide") return duration = duration[1] rating = await discord_.get_seq_response( self.client, ctx, f"{ctx.author.mention} enter {problem_cnt} space seperated integers denoting the ratings of problems (between {LOWER_RATING} and {UPPER_RATING})", 60, problem_cnt, ctx.author, [LOWER_RATING, UPPER_RATING]) if not rating[0]: await discord_.send_message( ctx, f"{ctx.author.mention} you took too long to decide") return rating = rating[1] points = await discord_.get_seq_response( self.client, ctx, f"{ctx.author.mention} enter {problem_cnt} space seperated integer denoting the points of problems (between 100 and 10,000)", 60, problem_cnt, ctx.author, [100, 10000]) if not points[0]: await discord_.send_message( ctx, f"{ctx.author.mention} you took too long to decide") return points = points[1] repeat = await discord_.get_time_response( self.client, ctx, f"{ctx.author.mention} do you want a new problem to appear when someone solves a problem (type 1 for yes and 0 for no)", 30, ctx.author, [0, 1]) if not repeat[0]: await discord_.send_message( ctx, f"{ctx.author.mention} you took too long to decide") return repeat = repeat[1] for i in users: if self.db.in_a_round(ctx.guild.id, i.id): await discord_.send_message( ctx, f"{i.name} is already in a round!") return alts = await discord_.get_alt_response( self.client, ctx, f"{ctx.author.mention} Do you want to add any alts? Type none if not applicable else type `alts: handle_1 handle_2 ...` You can add upto **{MAX_ALTS}** alt(s)", MAX_ALTS, 60, ctx.author) if not alts: await discord_.send_message( ctx, f"{ctx.author.mention} you took too long to decide") return alts = alts[1] tournament = 0 if len(users) == 2 and (await tournament_helper.is_a_match( ctx.guild.id, users[0].id, users[1].id, self.api, self.db)): tournament = await discord_.get_time_response( self.client, ctx, f"{ctx.author.mention} this round is a part of the tournament. Do you want the result of this round to be counted in the tournament. Type `1` for yes and `0` for no", 30, ctx.author, [0, 1]) if not tournament[0]: await discord_.send_message( ctx, f"{ctx.author.mention} you took too long to decide") return tournament = tournament[1] await ctx.send(embed=discord.Embed(description="Starting the round...", color=discord.Color.green())) problems = await codeforces.find_problems( [self.db.get_handle(ctx.guild.id, x.id) for x in users] + alts, rating) if not problems[0]: await discord_.send_message(ctx, problems[1]) return problems = problems[1] self.db.add_to_ongoing_round(ctx, users, rating, points, problems, duration, repeat, alts, tournament) round_info = self.db.get_round_info(ctx.guild.id, users[0].id) await ctx.send(embed=discord_.round_problems_embed(round_info))