コード例 #1
0
    async def refresh_channel_queue(self, channel: TextChannel, restart: bool):
        """
        Deletes the previous queue message and sends a new one in the channel

        If channel is supplied instead of a context (in the case of a bot reboot), send the reboot message instead
        """

        rows = []

        # Creating the queue visualisation requires getting the Player objects from the DB to have the names
        queue = game_queue.GameQueue(channel.id)

        for role, role_queue in queue.queue_players_dict.items():
            rows.append(f"{get_role_emoji(role)} " +
                        ", ".join(qp.player.short_name for qp in role_queue))

        # Create the queue embed
        embed = Embed(colour=embeds_color)
        embed.add_field(name="Queue", value="\n".join(rows))
        embed.set_footer(
            text=
            "Use !queue [role] to queue | All non-queue messages in this channel are deleted"
        )

        # We save the message object in our local cache
        new_queue = await channel.send(
            "The bot was restarted and all players in ready-check have been put back in queue\n"
            "The matchmaking process will restart once anybody queues or re-queues"
            if channel else None,
            embed=embed,
        )

        self.latest_queue_message_ids[channel.id] = new_queue.id
コード例 #2
0
    async def refresh_channel_queue(self, channel: TextChannel, restart: bool):
        """
        Deletes the previous queue message and sends a new one in the channel

        If channel is supplied instead of a context (in the case of a bot reboot), send the reboot message instead
        """

        # Creating the queue visualisation requires getting the Player objects from the DB to have the names
        new_queue = game_queue.GameQueue(channel.id)

        # If the new queue is the same as the cache, we simple return
        if new_queue == self._queue_cache.get(channel.id):
            return
        else:
            # Else, we update our cache (useful to not send too many messages)
            self._queue_cache[channel.id] = new_queue

        rows = []

        for role, role_queue in new_queue.queue_players_dict.items():
            rows.append(f"{get_role_emoji(role)} " +
                        ", ".join(qp.player.short_name for qp in role_queue))

        # Create the queue embed
        embed = Embed(colour=embeds_color)
        embed.add_field(name="Queue", value="\n".join(rows))
        embed.set_footer(
            text=
            "Use !queue [role] to join or !leave to leave | All non-queue messages are deleted"
        )

        message_text = ""

        if restart:
            message_text += (
                "\nThe bot was restarted and all players in ready-check have been put back in queue\n"
                "The matchmaking process will restart once anybody queues or re-queues"
            )

        # We save the message object in our local cache
        new_queue_message = await channel.send(
            message_text,
            embed=embed,
        )

        self.latest_queue_message_ids[channel.id] = new_queue_message.id
コード例 #3
0
    async def run_matchmaking_logic(
        self,
        ctx: commands.Context,
    ):
        """
        Runs the matchmaking logic in the channel defined by the context

        Should only be called inside guilds
        """
        queue = game_queue.GameQueue(ctx.channel.id)

        game = matchmaking_logic.find_best_game(queue)

        if not game:
            return

        elif game and game.matchmaking_score < 0.2:
            embed = game.get_embed(embed_type="GAME_FOUND",
                                   validated_players=[],
                                   bot=self.bot)

            # We notify the players and send the message
            ready_check_message = await ctx.send(content=game.players_ping,
                                                 embed=embed,
                                                 delete_after=60 * 15)

            # We mark the ready check as ongoing (which will be used to the queue)
            game_queue.start_ready_check(
                player_ids=game.player_ids_list,
                channel_id=ctx.channel.id,
                ready_check_message_id=ready_check_message.id,
            )

            # We update the queue in all channels
            await queue_channel_handler.update_queue_channels(
                bot=self.bot, server_id=ctx.guild.id)

            # And then we wait for the validation
            try:
                ready, players_to_drop = await checkmark_validation(
                    bot=self.bot,
                    message=ready_check_message,
                    validating_players_ids=game.player_ids_list,
                    validation_threshold=10,
                    game=game,
                )

            # We catch every error here to make sure it does not become blocking
            except Exception as e:
                self.bot.logger.error(e)
                game_queue.cancel_ready_check(
                    ready_check_id=ready_check_message.id,
                    ids_to_drop=game.player_ids_list,
                    server_id=ctx.guild.id,
                )
                await ctx.send(
                    "There was a bug with the ready-check message, all players have been dropped from queue\n"
                    "Please queue again to restart the process")

                await queue_channel_handler.update_queue_channels(
                    bot=self.bot, server_id=ctx.guild.id)

                return

            if ready is True:
                # We drop all 10 players from the queue
                game_queue.validate_ready_check(ready_check_message.id)

                # We commit the game to the database (without a winner)
                with session_scope() as session:
                    session.expire_on_commit = False
                    game = session.merge(game)  # This gets us the game ID

                queue_channel_handler.mark_queue_related_message(
                    await ctx.send(embed=game.get_embed("GAME_ACCEPTED"), ))

            elif ready is False:
                # We remove the player who cancelled
                game_queue.cancel_ready_check(
                    ready_check_id=ready_check_message.id,
                    ids_to_drop=players_to_drop,
                    channel_id=ctx.channel.id,
                )

                await ctx.send(
                    f"A player cancelled the game and was removed from the queue\n"
                    f"All other players have been put back in the queue", )

                # We restart the matchmaking logic
                await self.run_matchmaking_logic(ctx)

            elif ready is None:
                # We remove the timed out players from *all* channels (hence giving server id)
                game_queue.cancel_ready_check(
                    ready_check_id=ready_check_message.id,
                    ids_to_drop=players_to_drop,
                    server_id=ctx.guild.id,
                )

                await ctx.send(
                    "The check timed out and players who did not answer have been dropped from all queues",
                )

                # We restart the matchmaking logic
                await self.run_matchmaking_logic(ctx)

        elif game and game.matchmaking_score >= 0.2:
            # One side has over 70% predicted winrate, we do not start anything
            await ctx.send(
                f"The best match found had a side with a {(.5 + game.matchmaking_score)*100:.1f}%"
                f" predicted winrate and was not started")
コード例 #4
0
    async def refresh_channel_queue(self, channel: TextChannel, restart: bool):
        """
        Deletes the previous queue message and sends a new one in the channel

        If channel is supplied instead of a context (in the case of a bot reboot), send the reboot message instead
        """

        # Creating the queue visualisation requires getting the Player objects from the DB to have the names
        queue = game_queue.GameQueue(channel.id)

        # If the new queue is the same as the cache, we simple return
        if queue == self._queue_cache.get(channel.id):
            return
        else:
            # Else, we update our cache (useful to not send too many messages)
            self._queue_cache[channel.id] = queue

        # Create the queue embed
        embed = Embed(colour=embeds_color)

        # Adding queue field
        queue_rows = []

        for role, role_queue in queue.queue_players_dict.items():
            queue_rows.append(
                f"{get_role_emoji(role)} " + ", ".join(qp.player.short_name for qp in role_queue)
            )

        embed.add_field(name="Queue", value="\n".join(queue_rows))

        # Adding duos field if it’s not empty
        if queue.duos:
            duos_strings = []

            for duo in queue.duos:

                duos_strings.append(
                    " + ".join(f"{qp.player.short_name} {get_role_emoji(qp.role)}" for qp in duo)
                )

            embed.add_field(name="Duos", value=", ".join(duos_strings))

        embed.description = ""
        embed.add_field(name="Gamers Club", value="[**PARTICIPE DO GC RIFT BY RAZER E DISPUTE 5000 REAIS EM PREMIAÇÃO. INSCREVA-SE AGORA!**](https://bit.ly/37AqphB)", inline=False)
        embed.set_image(url="https://cdn.discordapp.com/attachments/796818933255766056/813598337793261599/ezgif.com-gif-maker_2.gif")

        embed.set_footer(
            text=f"Use {PREFIX}queue [role] para entrar ou !leave para sair"
        )

        message_text = ""

        if restart:
            message_text += (
                "\nThe bot was restarted and all players in ready-check have been put back in queue\n"
                "The matchmaking process will restart once anybody queues or re-queues"
            )

        # We save the message object in our local cache
        new_queue_message = await channel.send(message_text, embed=embed,)

        self.latest_queue_message_ids[channel.id] = new_queue_message.id
コード例 #5
0
    async def run_matchmaking_logic(
        self,
        ctx: commands.Context,
    ):
        """
        Runs the matchmaking logic in the channel defined by the context

        Should only be called inside guilds
        """
        queue = game_queue.GameQueue(ctx.channel.id)

        game = matchmaking_logic.find_best_game(queue)

        if not game:
            return

        elif game and game.matchmaking_score < 0.2:
            embed = Embed(
                title="📢 Game found 📢",
                description=
                f"Blue side expected winrate is {game.blue_expected_winrate * 100:.1f}%\n"
                "If you are ready to play, press ✅\n"
                "If you cannot play, press �",
            )

            embed = game.add_game_field(embed, [])

            # We notify the players and send the message
            ready_check_message = await ctx.send(
                content=
                f"||{' '.join([f'<@{discord_id}>' for discord_id in game.player_ids_list])}||",
                embed=embed,
            )

            # Because it still takes some time, we *directly* add it to the *no delete* list
            # That’s dirty and should likely be handled in a better way (maybe by *not* using purge
            # and choosing what to delete instead, but it also has its issues)
            # TODO HIGH PRIO Think about saving a "messages to not delete list" in the queue handler memory and
            #  use it in the cog listener, and automatically delete any other one after 5s? should work better (less bugs)

            queue_channel_handler.mark_queue_related_message(
                ready_check_message)

            # We mark the ready check as ongoing (which will be used to the queue)
            game_queue.start_ready_check(
                player_ids=game.player_ids_list,
                channel_id=ctx.channel.id,
                ready_check_message_id=ready_check_message.id,
            )

            # We update the queue in all channels
            await queue_channel_handler.update_server_queues(
                bot=self.bot, server_id=ctx.guild.id)

            # And then we wait for the validation
            ready, players_to_drop = await checkmark_validation(
                bot=self.bot,
                message=ready_check_message,
                validating_players_ids=game.player_ids_list,
                validation_threshold=10,
                timeout=3 * 60,
                game=game,
            )

            if ready is True:
                # We drop all 10 players from the queue
                game_queue.validate_ready_check(ready_check_message.id)

                # We commit the game to the database (without a winner)
                with session_scope() as session:
                    session.add(game)

                    embed = Embed(
                        title="📢 Game accepted 📢",
                        description=
                        f"Game {game.id} has been validated and added to the database\n"
                        f"Once the game has been played, one of the winners can score it with `!won`\n"
                        f"If you wish to cancel the game, use `!cancel`",
                    )

                    embed = game.add_game_field(embed)

                    queue_channel_handler.mark_queue_related_message(
                        await ctx.send(embed=embed, ))

            elif ready is False:
                # We remove the player who cancelled
                game_queue.cancel_ready_check(
                    ready_check_id=ready_check_message.id,
                    ids_to_drop=players_to_drop,
                    channel_id=ctx.channel.id,
                )

                queue_channel_handler.mark_queue_related_message(await ctx.send(
                    f"A player cancelled the game and was removed from the queue\n"
                    f"All other players have been put back in the queue"))

                # We restart the matchmaking logic
                await self.run_matchmaking_logic(ctx)

            elif ready is None:
                # We remove the timed out players from *all* channels (hence giving server id)
                game_queue.cancel_ready_check(
                    ready_check_id=ready_check_message.id,
                    ids_to_drop=players_to_drop,
                    server_id=ctx.guild.id,
                )

                queue_channel_handler.mark_queue_related_message(await ctx.send(
                    "The check timed out and players who did not answer have been dropped from all queues"
                ))

                # We restart the matchmaking logic
                await self.run_matchmaking_logic(ctx)

        elif game and game.matchmaking_score >= 0.2:
            # One side has over 70% predicted winrate, we do not start anything
            await ctx.send(
                f"The best match found had a side with a {(.5 + game.matchmaking_score)*100:.1f}%"
                f" predicted winrate and was not started")