aboutsummaryrefslogtreecommitdiffstats
path: root/bot
diff options
context:
space:
mode:
authorGravatar Shom770 <[email protected]>2021-10-20 20:44:42 -0400
committerGravatar Shom770 <[email protected]>2022-02-09 18:13:36 -0500
commit00b2f33e3366f885ad7d24bade546f604e065710 (patch)
tree3522743ad27da52117fc388d9a363301faa59d34 /bot
parentadd trivianight structure in the main cog (diff)
added functionality
trivianight next, trivianight stop, trivianight end added
Diffstat (limited to 'bot')
-rw-r--r--bot/exts/events/trivianight/_questions.py74
-rw-r--r--bot/exts/events/trivianight/_scoreboard.py30
-rw-r--r--bot/exts/events/trivianight/trivianight.py32
3 files changed, 89 insertions, 47 deletions
diff --git a/bot/exts/events/trivianight/_questions.py b/bot/exts/events/trivianight/_questions.py
index ef56ee81..f558c50e 100644
--- a/bot/exts/events/trivianight/_questions.py
+++ b/bot/exts/events/trivianight/_questions.py
@@ -1,7 +1,9 @@
-from random import choice
+from random import choice, randrange
from time import perf_counter
+from typing import Union
-from discord import ButtonStyle, Embed, Interaction
+import discord
+from discord import Embed, Interaction
from discord.ui import Button, View
from bot.constants import Colours, NEGATIVE_REPLIES
@@ -11,22 +13,21 @@ from ._scoreboard import Scoreboard
class QuestionButton(Button):
"""Button subclass for the options of the questions."""
- def __init__(self, label: str):
- self._time = perf_counter()
- self.users_picked = {}
- super().__init__(label=label, style=ButtonStyle.green)
+ def __init__(self, label: str, users_picked: dict):
+ self.users_picked = users_picked
+ super().__init__(label=label, style=discord.ButtonStyle.green)
- def answer(self, label: str) -> dict:
- """Returns the dictionary of the users who picked the answer only if it was correct."""
- return self.users_picked if label == self.label else {}
+ def set_time(self) -> None:
+ """Sets an instance attribute to a perf counter simulating the question beginning."""
+ self._time = perf_counter()
async def callback(self, interaction: Interaction) -> None:
"""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]
- elif self.users_picked[interaction.user.id][1] < 3:
+ elif self.users_picked[interaction.user.id][1] < 2:
self.users_picked[interaction.user.id] = [
- self.label, self.users_picked[interaction.user.id][0] + 1, perf_counter() - self._time
+ self.label, self.users_picked[interaction.user.id][1] + 1, perf_counter() - self._time
]
else:
await interaction.response.send_message(
@@ -43,7 +44,12 @@ class QuestionView(View):
"""View for the questions."""
def __init__(self):
+ super().__init__()
self.current_question = {}
+ self.users_picked = {}
+ self.buttons = [QuestionButton(label, self.users_picked) for label in ("A", "B", "C", "D")]
+ for button in self.buttons:
+ self.add_item(button)
def create_current_question(self) -> Embed:
"""Helper function to create the embed for the current question."""
@@ -53,30 +59,27 @@ class QuestionView(View):
color=Colours.python_yellow
)
for label, answer in zip(("A", "B", "C", "D"), self.current_question["answers"]):
- question_embed.add_field(name=label, value=answer, inline=False)
+ question_embed.add_field(name=f"Choice {label}", value=answer, inline=False)
- self.buttons = [QuestionButton(label) for label in ("A", "B", "C", "D")]
for button in self.buttons:
- self.add_item(button)
+ button.set_time()
+
return question_embed
def end_question(self) -> tuple[dict, Embed]:
"""Returns the dictionaries from the corresponding buttons for those who got it correct."""
labels = ("A", "B", "C", "D")
- label = labels[self.current_question["correct"].index(self.current_question["answers"])]
- return_dict = {}
+ label = labels[self.current_question["answers"].index(self.current_question["correct"])]
+ return_dict = {name: info for name, info in self.users_picked.items() if info[0] == label}
+ self.users_picked = {}
+
for button in self.buttons:
- return_dict.update(button.answer(label))
- self.remove_item(button)
+ button.users_picked = self.users_picked
answer_embed = Embed(
title=f"The correct answer for Question {self.current_question['number']} was",
- color=Colours.grass_green
- )
- answer_embed.add_field(
- name=label,
- value=self.current_question["correct"].index(self.current_question["answers"]),
- inline=False
+ description=self.current_question["correct"],
+ color=Colours.soft_green
)
return return_dict, answer_embed
@@ -87,7 +90,6 @@ class Questions:
def __init__(self, scoreboard: Scoreboard):
self.scoreboard = scoreboard
- self.view = QuestionView()
self.questions = []
self._ptr = -1
@@ -95,18 +97,26 @@ class Questions:
"""Setting `self.questions` dynamically via a function to set it."""
self.questions = questions
- def next_question(self) -> None:
- """Advances to the next question."""
- self._ptr += 1
- if self._ptr < len(self.questions):
- self.questions[self._ptr]["visited"] = True
- self.view.current_question = self.questions[self._ptr]
+ def next_question(self) -> Union[Embed, None]:
+ """Uses another, new question."""
+ if all("visited" in question.keys() for question in self.questions.values()):
+ 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))
+
+ self.questions[self._ptr]["visited"] = True
+ self.view.current_question = self.questions[self._ptr]
def current_question(self) -> tuple[Embed, QuestionView]:
"""Returns an embed entailing the current question as an embed with a view."""
return self.view.create_current_question(), self.view
- def end_question(self) -> None:
+ def end_question(self) -> Embed:
"""Terminates answering of the question and displays the correct answer."""
scores, answer_embed = self.view.end_question()
for user, score in scores.items():
diff --git a/bot/exts/events/trivianight/_scoreboard.py b/bot/exts/events/trivianight/_scoreboard.py
index 96ff5ced..cab0288f 100644
--- a/bot/exts/events/trivianight/_scoreboard.py
+++ b/bot/exts/events/trivianight/_scoreboard.py
@@ -12,32 +12,41 @@ class ScoreboardView(View):
"""View for the scoreboard."""
def __init__(self, bot: Bot):
+ super().__init__()
self.bot = bot
self.points = {}
self.speed = {}
- def create_main_leaderboard(self) -> Embed:
+ async def create_main_leaderboard(self) -> Embed:
"""Helper function that iterates through `self.points` to generate the main leaderboard embed."""
main_embed = Embed(
title="Winners of the Trivia Night",
description="See the leaderboard for who got the most points during the Trivia Night!",
color=Colours.python_blue,
)
- for user, points in list(self.points.items())[:10]:
- main_embed.add_field(name=self.bot.get_user(user), value=f"`{points}` pts", inline=False)
+
+ # Limit self.points.items() to 10 items at maximum (top 10 users) in the future
+ for user, points in list(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
+ )
return main_embed
- def _create_speed_embed(self) -> Embed:
+ async def _create_speed_embed(self) -> Embed:
"""Helper function that iterates through `self.speed` to generate a leaderboard embed."""
speed_embed = Embed(
title="Average Time Taken to Answer a Question",
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())[:10]:
+ for user, time_taken in list(self.speed.items()):
+ user = await self.bot.fetch_user(int(user))
speed_embed.add_field(
- name=self.bot.get_user(user),
+ name=f"{user.name}#{user.discriminator}",
value=f"`{(time_taken[1] / time_taken[0]):.3f}s` (on average)",
inline=False
)
@@ -47,15 +56,12 @@ class ScoreboardView(View):
@discord.ui.button(label="Scoreboard for Speed", style=ButtonStyle.green)
async def speed_leaderboard(self, button: Button, interaction: Interaction) -> None:
"""Send an ephemeral message with the speed leaderboard embed."""
- await interaction.response.send_message(embed=self._create_speed_embed(), ephemeral=True)
+ await interaction.response.send_message(embed=await self._create_speed_embed(), ephemeral=True)
class Scoreboard:
"""Class for the scoreboard for the trivianight event."""
- def __init__(self, bot: Bot):
- self.view = ScoreboardView(bot)
-
def __setitem__(self, key: str, value: int):
if key.startswith("points: "):
key = key.removeprefix("points: ")
@@ -76,6 +82,6 @@ class Scoreboard:
elif item.startswith("speed: "):
return self.view.speed[item.removeprefix("speed: ")]
- def display(self) -> Union[Embed, View]:
+ async def display(self) -> Union[Embed, View]:
"""Returns the embed of the main leaderboard along with the ScoreboardView."""
- return self.view.create_main_leaderboard(), self.view
+ return await self.view.create_main_leaderboard(), self.view
diff --git a/bot/exts/events/trivianight/trivianight.py b/bot/exts/events/trivianight/trivianight.py
index 66b2ae43..609f6651 100644
--- a/bot/exts/events/trivianight/trivianight.py
+++ b/bot/exts/events/trivianight/trivianight.py
@@ -1,3 +1,4 @@
+import logging
from json import loads
from random import choice
@@ -6,8 +7,8 @@ from discord.ext import commands
from bot.bot import Bot
from bot.constants import Colours, POSITIVE_REPLIES
-from ._questions import Questions
-from ._scoreboard import Scoreboard
+from ._questions import QuestionView, Questions
+from ._scoreboard import Scoreboard, ScoreboardView
class TriviaNight(commands.Cog):
@@ -15,7 +16,7 @@ class TriviaNight(commands.Cog):
def __init__(self, bot: Bot):
self.bot = bot
- self.scoreboard = Scoreboard(self.bot)
+ self.scoreboard = Scoreboard()
self.questions = Questions(self.scoreboard)
@commands.group()
@@ -28,6 +29,9 @@ class TriviaNight(commands.Cog):
"""Load the JSON file provided into the questions."""
json_text = (await ctx.message.attachments[0].read()).decode("utf8")
serialized_json = loads(json_text)
+ self.questions.view = QuestionView()
+ logging.getLogger(__name__).debug(self.questions.view)
+ self.scoreboard.view = ScoreboardView(self.bot)
self.questions.set_questions(serialized_json)
success_embed = Embed(
title=choice(POSITIVE_REPLIES),
@@ -36,6 +40,28 @@ class TriviaNight(commands.Cog):
)
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()
+ if isinstance(next_question, Embed):
+ await ctx.send(embed=next_question)
+ return
+
+ question_embed, question_view = self.questions.current_question()
+ await ctx.send(embed=question_embed, view=question_view)
+
+ @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())
+
+ @trivianight.command()
+ async def end(self, ctx: commands.Context) -> None:
+ """Ends the trivia night event and displays the scoreboard."""
+ scoreboard_embed, scoreboard_view = await self.scoreboard.display()
+ await ctx.send(embed=scoreboard_embed, view=scoreboard_view)
+
def setup(bot: Bot) -> None:
"""Load the TriviaNight cog."""