diff options
| author | 2019-09-23 19:00:32 +0530 | |
|---|---|---|
| committer | 2019-09-23 19:00:32 +0530 | |
| commit | 207efa437e3b585250f7b36e66ab262a0acc3217 (patch) | |
| tree | 341e9ebb0733fc73ef210abda2379a97d2ef371b /bot/seasons/evergreen/trivia_quiz.py | |
| parent | using self.categories insted of list(self.categories.keys()) (diff) | |
Modified the code drastically for the quiz game:
- Using a while loop to run a game rather than bunch of the functions calling each other.
- using wait_for() to send hints, answers and to move to next questions.
Diffstat (limited to 'bot/seasons/evergreen/trivia_quiz.py')
| -rw-r--r-- | bot/seasons/evergreen/trivia_quiz.py | 266 |
1 files changed, 0 insertions, 266 deletions
diff --git a/bot/seasons/evergreen/trivia_quiz.py b/bot/seasons/evergreen/trivia_quiz.py deleted file mode 100644 index 433a021d..00000000 --- a/bot/seasons/evergreen/trivia_quiz.py +++ /dev/null @@ -1,266 +0,0 @@ -import asyncio -import json -import logging -import random -from dataclasses import dataclass -from pathlib import Path - -import discord -from discord.ext import commands -from fuzzywuzzy import fuzz - -from bot.constants import Roles - - -logger = logging.getLogger(__name__) - - -annoyed_expressions = ["-_-", "-.-"] - -wrong_ans_responses = [ - "No one gave the correct answer", - "Losers", - "You guys really need to learn" -] - - -@dataclass -class GameData: - """A dataclass for game data.""" - - owner: int - players = [] - points = [] - done_questions = [] - category: str - question: dict = None - hints = 0 - unanswered_questions = 0 - - -class TriviaQuiz(commands.Cog): - """A cog for all quiz commands.""" - - def __init__(self, bot): - self.bot = bot - self.questions = self.load_questions() - self.running_games = {} # channel as key and value as instance of dataclass GameData - self.categories = { - "retro": "Questions related to retro gaming." - } - self.inactivity_limit = 3 # Number of questions unanswered in a row after which quiz stops. - - @staticmethod - def load_questions(): - """Load the questions from json file.""" - p = Path("bot", "resources", "evergreen", "trivia_quiz.json") - with p.open() as json_data: - questions = json.load(json_data) - return questions - - @commands.group(name="tquiz", invoke_without_command=True) - async def tquiz(self, ctx): - """Trivia Quiz game for fun!""" - await ctx.send_help("tquiz") - - @tquiz.command(name="start") - async def start(self, ctx, category=None): - """ - Start a quiz! - - Questions for the quiz can be selected from the following categories: - - Retro : questions related to retro gaming. - """ - await ctx.send("Quiz triggered! Gonna start in a couple of seconds...") - await asyncio.sleep(1) - - # Checking if there is already a game running in that channel. - if ctx.channel.id in self.running_games: - return await ctx.send("Game already running in this channel!") - - if category is None: - category = random.choice(self.categories) - - else: - category = category.lower() - if category not in self.categories: - embed = self.category_embed() - return await ctx.send(f"Category {category} does not exist!", embed=embed) - - self.running_games[ctx.channel.id] = GameData( - owner=ctx.author.id, - category=category - ) - - await self.send_question(ctx.channel) - - def category_embed(self): - """A function which returns an embed showing all avilable categories""" - embed = discord.Embed(colour=discord.Colour.blue()) - embed.title = "The available question categories are:" - embed.description = "" - for cat, description in self.categories.items(): - embed.description += f"**- {cat.capitalize()}**\n{description.capitalize()}\n" - embed.set_footer(text="If not category is chosen, then a random one will be selected.") - return embed - - async def send_question(self, channel): - """This function is to be called whenever a question needs to be sent.""" - await asyncio.sleep(2) - game = self.running_games[channel.id] - if game.unanswered_questions == self.inactivity_limit: - del self.running_games[channel.id] - return await channel.send("Game stopped due to inactivity.") - - category = game.category - category_dict = self.questions[category] - question_dict = random.choice(category_dict) - - same_question = True - - # Making sure a question is not repeated. - while same_question is True: - question_dict = random.choice(category_dict) - if question_dict["id"] not in game.done_questions: - same_question = False - - # Initial points for a question. - question_dict["points"] = 100 - game.question = question_dict - game.hints = 0 - - embed = discord.Embed(colour=discord.Colour.dark_gold()) - - question = question_dict["question"] - question_id = question_dict["id"] - - game.done_questions.append(question_id) - question_number = len(game.done_questions) - - embed.title = f"#{question_number} Question" - embed.description = question - embed.set_footer(text="A hint will be provided after every 10s if no one gives the right answer.Max of 2 hints") - - await channel.send(embed=embed) - await self.send_hint(channel, question_dict) - - @commands.Cog.listener() - async def on_message(self, message): - """A function triggered when a message is sent.""" - channel = message.channel - if channel.id not in self.running_games: - return - if message.author.bot: - return - - game = self.running_games[message.channel.id] - question_data = game.question - answer = question_data["answer"].lower() - user_answer = message.content.lower() - ratio = fuzz.ratio(answer, user_answer) - if ratio > 84: - points = question_data["points"] - game.hints*25 - if message.author in game.players: - author_index = game.players.index(message.author) - game.points[author_index] = game.points[author_index] + points - else: - game.players.append(message.author) - game.points.append(points) - - await channel.send(f"{message.author.mention} got it right! Good job :tada:" - f"You got {points} points.") - await self.send_score(channel) - await self.send_question(channel) - elif ratio in range(75, 84): - await channel.send(f"Your close to the answer {message.author.mention}") - - async def send_hint(self, channel, question_dict): - """Function to be called whenever a hint has to be sent.""" - await asyncio.sleep(10) - try: - game = self.running_games[channel.id] - except KeyError: - return - - # Checking if the question is the same after 10 seconds. - if question_dict["id"] == game.question["id"]: - - # If the max number of hints is already reached, then send the answer. - if 2 - game.hints == 0: - return await self.send_answer(channel) - - hint_list = question_dict["hints"] - hint_index = game.hints - hint = hint_list[hint_index] - game.hints += 1 - message = f"**Hint {game.hints}**: {hint}\n*Number of hints remaining: {2-game.hints}*" - await channel.send(message) - await self.send_hint(channel, question_dict) - - async def send_answer(self, channel): - """A function to send the answer in the channel if no user have given the correct answer even after 2 hints.""" - game = self.running_games[channel.id] - answer = game.question["answer"] - response = random.choice(wrong_ans_responses) - expression = random.choice(annoyed_expressions) - await channel.send(f"{response} {expression}, the correct answer is **{answer}**.") - self.running_games[channel.id].unanswered_questions += 1 - await self.send_score(channel) - await self.send_question(channel) - - @tquiz.command(name="score") - async def show_score(self, ctx): - """Show scoreboard of the game running in this channel.""" - await self.send_score(ctx.channel) - - async def send_score(self, channel): - """Show score of each player in the quiz.""" - if channel.id not in self.running_games: - return await channel.send("There are no games running in this channel!") - game = self.running_games[channel.id] - players = game.players - if len(players) == 0: - return - points = game.points - embed = discord.Embed(color=discord.Colour.dark_gold()) - embed.title = "Scoreboard" - embed.description = "" - for player, score in zip(players, points): - embed.description += f"{player} - {score}\n" - await channel.send(embed=embed) - - @tquiz.command(name="stop") - async def stop_quiz(self, ctx): - """Stop the quiz.""" - if ctx.channel.id not in self.running_games: - return await ctx.send("No game running, nothing to stop here -.-") - game = self.running_games[ctx.channel.id] - owner = game.owner - mods = Roles.moderator - if ctx.author.id == owner or mods in [role.id for role in ctx.author.roles]: - await ctx.send("Game is not running anymore!") - await self.send_score(ctx.channel) - if game.players: - highest_points = max(game.points) - - # Check if more than 1 player has highest points. - - if game.points.count(highest_points) > 1: - pass - else: - author_index = game.points.index(highest_points) - winner = game.players[author_index] - await ctx.send( - f"Congratz {winner.mention} :tada: " - f"You have won this quiz game with a grand total of {highest_points} points!!" - ) - await asyncio.sleep(2) - del self.running_games[ctx.channel.id] - else: - await ctx.send("You are not authorised to close this game!") - - -def setup(bot): - """Loading the cog.""" - bot.add_cog(TriviaQuiz(bot)) - logger.debug("TriviaQuiz cog loaded!") |