def test_matchmaking_logic(): game_queue.reset_queue() # We queue for everything except the red support for player_id in range(0, 9): game_queue.add_player(player_id, roles_list[player_id % 5], 0, 0) assert not find_best_game(GameQueue(0)) # We add the last player game_queue.add_player(9, "SUP", 0, 0) game = find_best_game(GameQueue(0)) assert game # We commit the game to the database with session_scope() as session: session.add(game) # We say player 0 won his last game on server 0 score_game_from_winning_player(0, 0) # We check that everything got changed with session_scope() as session: # We recreate the game object so it’s associated with this new session game = session.query(Game).order_by(Game.start.desc()).first() for side, role in game.participants: participant = game.participants[side, role] assert participant.player.ratings[role].trueskill_mu != 25
async def games(self, ctx: commands.Context): """ Creates 100 games in the database with random results """ game_queue.reset_queue() for game_count in range(100): # We add the context creator as well game_queue.add_player( ctx.author.id, roles_list[4], ctx.channel.id, ctx.guild.id, name=ctx.author.display_name ) # We put 15 people in the queue, but only the first ones should get picked for i in range(0, 15): game_queue.add_player(i, roles_list[i % 5], ctx.channel.id, ctx.guild.id, name=str(i)) game = matchmaking_logic.find_best_game(GameQueue(ctx.channel.id)) with session_scope() as session: session.add(game) winner = game.player_ids_list[int(random.random() * 10)] game_queue.start_ready_check([i for i in range(0, 9)] + [ctx.author.id], ctx.channel.id, 0) game_queue.validate_ready_check(0) matchmaking_logic.score_game_from_winning_player(player_id=winner, server_id=ctx.guild.id) await ranking_channel_handler.update_ranking_channels(self.bot, ctx.guild.id) await ctx.send("100 games have been created in the database") await queue_channel_handler.update_queue_channels(bot=self.bot, server_id=ctx.guild.id)
async def reset(self, ctx: commands.Context, member_or_channel: Union[discord.Member, discord.TextChannel] = None): """ Resets the queue status for a channel or a player If no argument is given, resets the queue in the current channel """ if not member_or_channel or type( member_or_channel) == discord.TextChannel: channel = ctx.channel if not member_or_channel else member_or_channel game_queue.reset_queue(channel.id) # TODO Find a way to cancel the ongoing ready-checks as they *will* bug out # The current code organisation does not allow to do it easily, so maybe it’ll need some structure changes await ctx.send(f"Queue has been reset in {channel.name}") elif type(member_or_channel) == discord.Member: game_queue.remove_player(member_or_channel.id) await ctx.send( f"{member_or_channel.name} has been removed from all queues") await queue_channel_handler.update_queue_channels( bot=self.bot, server_id=ctx.guild.id)
def test_multiple_queues(): game_queue.reset_queue() game_queue.add_player(0, roles_list[0], 0, 0, name="0") # This will take a few seconds for i in range(1000): GameQueue(0)
def test_multiple_queues(): game_queue.reset_queue() game_queue.add_player(0, roles_list[0], 0, 0) # This will take at least 30s to crash because of the queue timeout for i in range(1000): GameQueue(0)
def test_duo_queue(): game_queue.reset_queue() # Adding it all except last support for player_id in range(0, 9): game_queue.add_player(player_id, roles_list[player_id % 5], 0, 0, name=str(player_id)) # Marking players 0 and 9 as duo game_queue.add_duo(0, "TOP", 9, "SUP", 0, 0, first_player_name="0", second_player_name="9") print(GameQueue(0)) print(GameQueue(0).duos) assert len(GameQueue(0)) == 10 assert len(GameQueue(0).duos) == 1 # Removing their duo status with 0 calling !solo game_queue.remove_duo(0, 0) assert len(GameQueue(0)) == 10 assert len(GameQueue(0).duos) == 0
def test_queue_full(): game_queue.reset_queue() for player_id in range(0, 10): game_queue.add_player(player_id, roles_list[player_id % 5], 0, 0, name=str(player_id)) assert len(GameQueue(0)) == 10 # We queue our player 0 in channel 1, which he should be allowed to do game_queue.add_player(0, roles_list[0], 1, 0, name="0") assert len(GameQueue(1)) == 1 # We queue our player 0 for every other role in channel 0 for role in roles_list: game_queue.add_player(0, role, 0, 0, name="0") assert len(GameQueue( 0)) == 14 # Every role should count as a different QueuePlayer # Assuming our matchmaking logic found a good game (id 0) game_queue.start_ready_check(list(range(0, 10)), 0, 0) assert len( GameQueue(0) ) == 0 # Player 0 should not be counted in queue for any role anymore # Our player 0 in channel 1 should not be counted in queue either assert len(GameQueue(1)) == 0 # We check that our player 0 is not allowed to queue in other channels with pytest.raises(game_queue.PlayerInReadyCheck): game_queue.add_player(0, roles_list[0], 2, 0, name="0") # We cancel the ready check and drop player 0 from all queues on the server game_queue.cancel_ready_check(ready_check_id=0, ids_to_drop=[0], server_id=0) assert len(GameQueue(0)) == 9 # We check player 0 got dropped from queue 1 too assert len(GameQueue(1)) == 0 # We queue again, with player 10 game_queue.add_player(10, roles_list[0], 0, 0, name="10") # We start and validate the ready check (message id 1) game_queue.start_ready_check(list(range(1, 11)), 0, 1) game_queue.validate_ready_check(1) # We verify that both queues are empty assert len(GameQueue(0)) == 0 assert len(GameQueue(1)) == 0
def unmark_queue_channel(self, channel_id): game_queue.reset_queue(channel_id) with session_scope() as session: channel_query = session.query(ChannelInformation).filter(ChannelInformation.id == channel_id) channel_query.delete(synchronize_session=False) self._queue_channels = [c for c in self._queue_channels if c.id != channel_id] queue_logger.info(f"Unmarked {channel_id} as a queue channel")
def test_queue_remove(): game_queue.reset_queue() game_queue.add_player(0, roles_list[0], 0, 0, name="0") assert len(GameQueue(0)) == 1 # We queue our player 0 in channel 1, which he should be allowed to do game_queue.remove_player(0, 0) assert len(GameQueue(0)) == 0
def daily_jobs(self): """ Runs a timer every 60 seconds, triggering jobs at the appropriate minute mark """ threading.Timer(60, self.daily_jobs).start() now = datetime.now() if now.strftime("%H:%M") == QUEUE_RESET_TIME: with session_scope() as session: server_config = get_server_config(server_id=self.guilds[0].id, session=session) if server_config.config.get('queue_reset'): game_queue.reset_queue() self.loop.create_task(queue_channel_handler.update_queue_channels(bot=self, server_id=None))
def remove_queue_channel(self, channel_id): game_queue.reset_queue(channel_id) with session_scope() as session: reset_queue(channel_id) channel_query = session.query(ChannelInformation).filter( ChannelInformation.id == channel_id) channel_query.delete(synchronize_session=False) self._queue_channels = [ c for c in self._queue_channels if c.id != channel_id ]
def test_duo_matchmaking(): game_queue.reset_queue() # Playing 100 games with random outcomes and making sure 0 and 9 are always on the same team for game_count in range(100): # We queue for everything except the red support for player_id in range(0, 9): game_queue.add_player(player_id, roles_list[player_id % 5], 0, 0, name=str(player_id)) # We add the last player as duo with player 0 game_queue.add_duo( 0, "TOP", 9, "SUP", 0, 0, second_player_name="9", first_player_name="0", ) game = find_best_game(GameQueue(0)) player_0 = next(p for p in game.participants.values() if p.player_id == 0) player_9 = next(p for p in game.participants.values() if p.player_id == 9) assert player_0.side == player_9.side with session_scope() as session: session.add(game) winner = game.player_ids_list[int(random.random() * 10)] game_queue.start_ready_check([i for i in range(0, 10)], 0, 0) game_queue.validate_ready_check(0) score_game_from_winning_player(player_id=winner, server_id=0)
def test_matchmaking_logic_priority(): """ Making sure players who spent more time in queue will be considered first """ game_queue.reset_queue() # TODO LOW PRIO Rewrite the test to make it properly test age-based matchmaking, even with an empty DB # I think even without age-based matchmaking it could pass at the moment, since on an empty DB the first # tested game has a perfect 50% evaluation. Won’t happen after other tests though so ok atm # We queue for everything, with 0, 1, 2, 3 being top, 4, 5, 6, 7 being jgl, ... for player_id in range(0, 20): game_queue.add_player(player_id, roles_list[int(player_id / 4 % 5)], 0, 0) game = find_best_game(GameQueue(0)) print(game.blue_expected_winrate) # Assert we chose 0, 1, 4, 5, 8, 9, 13, 13, 16, 17 players for participant in game.participants.values(): assert participant.player_id % 4 < 2
async def reset( self, ctx: commands.Context, member_or_channel: Union[discord.Member, discord.TextChannel] = None ): """ Resets the queue status for a channel or a player If no argument is given, resets the queue in the current channel """ # TODO LOW PRIO RESEND THE QUEUE (but it’s a QueueCog function, so will need some code rearrangement) if not member_or_channel or type(member_or_channel) == discord.TextChannel: channel = ctx.channel if not member_or_channel else member_or_channel game_queue.reset_queue(channel.id) await ctx.send(f"Queue has been reset in {channel.name}") await queue_channel_handler.update_server_queues(bot=self.bot, server_id=ctx.guild.id) elif type(member_or_channel) == discord.Member: game_queue.remove_player(member_or_channel.id) await ctx.send(f"{member_or_channel.name} has been removed from all queues") await queue_channel_handler.update_server_queues(bot=self.bot, server_id=ctx.guild.id)
async def reset(self, ctx: commands.Context, member_or_channel: Union[discord.Member, discord.TextChannel] = None): """ Resets the queue status for a channel or a player If no argument is given, resets the queue in the current channel """ if not member_or_channel or type( member_or_channel) == discord.TextChannel: channel = ctx.channel if not member_or_channel else member_or_channel game_queue.reset_queue(channel.id) await ctx.send(f"Queue has been reset in {channel.name}") elif type(member_or_channel) == discord.Member: game_queue.remove_player(member_or_channel.id) await ctx.send( f"{member_or_channel.name} has been removed from all queues") await queue_channel_handler.update_queue_channels( bot=self.bot, server_id=ctx.guild.id)