diff options
Diffstat (limited to 'bot/exts')
| -rw-r--r-- | bot/exts/events/trivianight/_questions.py | 72 | ||||
| -rw-r--r-- | bot/exts/events/trivianight/_scoreboard.py | 17 | ||||
| -rw-r--r-- | bot/exts/events/trivianight/trivianight.py | 31 | 
3 files changed, 101 insertions, 19 deletions
| diff --git a/bot/exts/events/trivianight/_questions.py b/bot/exts/events/trivianight/_questions.py index f558c50e..df3f237a 100644 --- a/bot/exts/events/trivianight/_questions.py +++ b/bot/exts/events/trivianight/_questions.py @@ -1,6 +1,6 @@  from random import choice, randrange  from time import perf_counter -from typing import Union +from typing import TypedDict, Union  import discord  from discord import Embed, Interaction @@ -10,6 +10,15 @@ from bot.constants import Colours, NEGATIVE_REPLIES  from ._scoreboard import Scoreboard +class CurrentQuestion(TypedDict): +    """Representing the different 'keys' of the question taken from the JSON.""" + +    number: str +    description: str +    answers: list +    correct: str + +  class QuestionButton(Button):      """Button subclass for the options of the questions.""" @@ -25,10 +34,26 @@ class QuestionButton(Button):          """When a user interacts with the button, this will be called."""          if interaction.user.id not in self.users_picked.keys():              self.users_picked[interaction.user.id] = [self.label, 1, perf_counter() - self._time] +            await interaction.response.send_message( +                embed=Embed( +                    title="Success!", +                    description=f"You chose answer choice {self.label}.", +                    color=Colours.soft_green +                ), +                ephemeral=True +            )          elif self.users_picked[interaction.user.id][1] < 2:              self.users_picked[interaction.user.id] = [                  self.label, self.users_picked[interaction.user.id][1] + 1, perf_counter() - self._time              ] +            await interaction.response.send_message( +                embed=Embed( +                    title="Success!", +                    description=f"You changed your answer to answer choice {self.label}.", +                    color=Colours.soft_green +                ), +                ephemeral=True +            )          else:              await interaction.response.send_message(                  embed=Embed( @@ -45,7 +70,7 @@ class QuestionView(View):      def __init__(self):          super().__init__() -        self.current_question = {} +        self.current_question: CurrentQuestion          self.users_picked = {}          self.buttons = [QuestionButton(label, self.users_picked) for label in ("A", "B", "C", "D")]          for button in self.buttons: @@ -91,26 +116,51 @@ class Questions:      def __init__(self, scoreboard: Scoreboard):          self.scoreboard = scoreboard          self.questions = [] -        self._ptr = -1      def set_questions(self, questions: list) -> None:          """Setting `self.questions` dynamically via a function to set it."""          self.questions = questions -    def next_question(self) -> Union[Embed, None]: -        """Uses another, new question.""" -        if all("visited" in question.keys() for question in self.questions.values()): +    def next_question(self, number: int = None) -> Union[Embed, None]: +        """ +        Chooses a random unvisited question from the question bank. + +        If the number parameter is specified, it'll head to that specific question. +        """ +        if all("visited" in question.keys() for question in self.questions):              return Embed(                  title=choice(NEGATIVE_REPLIES),                  description="All of the questions in the question bank have been used.",                  color=Colours.soft_red              ) -        while "visited" in self.questions[self._ptr].keys(): -            self._ptr = randrange(0, len(self.questions)) +        if number is None: +            question_number = randrange(0, len(self.questions)) +            while "visited" in self.questions[question_number].keys(): +                question_number = randrange(0, len(self.questions)) +        else: +            question_number = number + +        self.questions[question_number]["visited"] = True +        self.view.current_question = self.questions[question_number] + +    def list_questions(self) -> str: +        """ +        Lists all questions from the question bank. + +        It will put the following into a message: +            - Question number +            - Question description +            - If the question was already 'visited' (displayed) +        """ +        spaces = len(sorted(self.questions, key=lambda question: len(question['description']))[-1]["description"]) + 3 +        formatted_string = "" +        for question in self.questions: +            formatted_string += f"`Q{question['number']}: {question['description']!r}" \ +                                f"{' ' * (spaces - len(question['description']) + 2)}" \ +                                f"|` {':x:' if not question.get('visited') else ':checkmark:'}\n" -        self.questions[self._ptr]["visited"] = True -        self.view.current_question = self.questions[self._ptr] +        return formatted_string.strip()      def current_question(self) -> tuple[Embed, QuestionView]:          """Returns an embed entailing the current question as an embed with a view.""" @@ -120,7 +170,7 @@ class Questions:          """Terminates answering of the question and displays the correct answer."""          scores, answer_embed = self.view.end_question()          for user, score in scores.items(): -            self.scoreboard[f"points: {user}"] = score[1] +            self.scoreboard[f"points: {user}"] = 1              self.scoreboard[f"speed: {user}"] = score[2]          return answer_embed diff --git a/bot/exts/events/trivianight/_scoreboard.py b/bot/exts/events/trivianight/_scoreboard.py index cab0288f..7eb7a6a8 100644 --- a/bot/exts/events/trivianight/_scoreboard.py +++ b/bot/exts/events/trivianight/_scoreboard.py @@ -25,14 +25,14 @@ class ScoreboardView(View):              color=Colours.python_blue,          ) -        # Limit self.points.items() to 10 items at maximum (top 10 users) in the future -        for user, points in list(self.points.items()): +        current_placement = 1 +        for user, points in self.points.items():              user = await self.bot.fetch_user(int(user))              main_embed.add_field( -                name=f"{user.name}#{user.discriminator}", -                value=f"`{points}` pts", -                inline=False +                name=f"{current_placement}. {user.name}#{user.discriminator}", +                value=f"`{points}` pts"              ) +            current_placement += 1          return main_embed @@ -43,13 +43,14 @@ class ScoreboardView(View):              description="See the leaderboard for how fast each user took to answer a question correctly!",              color=Colours.python_blue,          ) -        for user, time_taken in list(self.speed.items()): +        current_placement = 1 +        for user, time_taken in self.speed.items():              user = await self.bot.fetch_user(int(user))              speed_embed.add_field( -                name=f"{user.name}#{user.discriminator}", +                name=f"{current_placement}. {user.name}#{user.discriminator}",                  value=f"`{(time_taken[1] / time_taken[0]):.3f}s` (on average)", -                inline=False              ) +            current_placement += 1          return speed_embed diff --git a/bot/exts/events/trivianight/trivianight.py b/bot/exts/events/trivianight/trivianight.py index 609f6651..2ec869ab 100644 --- a/bot/exts/events/trivianight/trivianight.py +++ b/bot/exts/events/trivianight/trivianight.py @@ -41,6 +41,20 @@ class TriviaNight(commands.Cog):          await ctx.send(embed=success_embed)      @trivianight.command() +    async def reset(self, ctx: commands.Context) -> None: +        """Resets previous questions and scoreboards.""" +        self.scoreboard.view = ScoreboardView(self.bot) +        for question in self.questions.questions: +            del question["visited"] + +        success_embed = Embed( +            title=choice(POSITIVE_REPLIES), +            description="The scoreboards were reset and questions marked unvisited!", +            color=Colours.soft_green +        ) +        await ctx.send(embed=success_embed) + +    @trivianight.command()      async def next(self, ctx: commands.Context) -> None:          """Gets a random question from the unanswered question list and lets user choose the answer."""          next_question = self.questions.next_question() @@ -52,6 +66,23 @@ class TriviaNight(commands.Cog):          await ctx.send(embed=question_embed, view=question_view)      @trivianight.command() +    async def question(self, ctx: commands.Context, question_number: int) -> None: +        """Gets a question from the question bank depending on the question number provided.""" +        question = self.questions.next_question(question_number) +        if isinstance(question, Embed): +            await ctx.send(embed=question) +            return + +        question_embed, question_view = self.questions.current_question() +        await ctx.send(embed=question_embed, view=question_view) + +    @trivianight.command() +    async def list(self, ctx: commands.Context) -> None: +        """Displays all the questions from the question bank.""" +        formatted_string = self.questions.list_questions() +        await ctx.send(formatted_string) + +    @trivianight.command()      async def stop(self, ctx: commands.Context) -> None:          """End the ongoing question to show the correct question."""          await ctx.send(embed=self.questions.end_question()) | 
