diff options
author | 2021-10-23 15:24:02 -0400 | |
---|---|---|
committer | 2022-02-09 18:13:36 -0500 | |
commit | c00acc579015a5bdb407ab96d05a1368e3894c53 (patch) | |
tree | 26cb5a98136cfedf57db0603115766e650a843ef | |
parent | added functionality (diff) |
added question and list command
-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()) |