aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--minecrafttrivia/game.py40
-rw-r--r--minecrafttrivia/trivia_interface_cog.py44
3 files changed, 74 insertions, 12 deletions
diff --git a/README.md b/README.md
index a916cdc..5e3e735 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,8 @@ Guess minecraft crafting recipes the fastest.
[p]minecrafttrivia high - Show highscores
[p]minecrafttrivia config - Set timeouts / round counts. (ADMIN)
[p]minecrafttrivia lead - Show total score leaderboard
+[p]minecrafttrivia winstreak - Show current winstreaks
+[p]minecrafttrivia startnow - Skip the join timer and start a game now
```
## Legal Notice
diff --git a/minecrafttrivia/game.py b/minecrafttrivia/game.py
index e2373e6..e43b5fa 100644
--- a/minecrafttrivia/game.py
+++ b/minecrafttrivia/game.py
@@ -26,6 +26,7 @@ class OngoingGame(ABC):
channel: discord.TextChannel
phase: GamePhase
signup_message: discord.Message
+ signup_embed: discord.Embed
def __init__(self, bot: Red, config: Config, channel: discord.TextChannel):
self.participants = []
@@ -37,23 +38,33 @@ class OngoingGame(ABC):
async def start_signup(self):
self.phase = GamePhase.SIGNUP
join_timeout = await self.config.join_timeout()
- embed = discord.Embed(
+ self.signup_embed = discord.Embed(
title="Signups opened for new game of Minecraft trivia",
description=f"React to this message in order to join. You have {join_timeout} seconds to signup.",
)
- embed.timestamp = datetime.now()
- self.signup_message = await self.channel.send(embed=embed)
+ self.signup_embed.timestamp = datetime.now()
+ self.signup_message = await self.channel.send(embed=self.signup_embed)
await self.signup_message.add_reaction(constants.POSITIVE_REACTION)
await asyncio.sleep(join_timeout)
- embed.description = "Signups are now closed. Wait for the game to finish to start a new one."
- await self.signup_message.edit(embed=embed)
- self.participants = await utils.get_participants((await self.channel.fetch_message(self.signup_message.id)).reactions)
- await self.start_game()
+ if self.phase == GamePhase.SIGNUP:
+ await self.start_game()
async def start_game(self):
self.phase = GamePhase.RUNNING
+ self.signup_embed.description = "Signups are now closed. Wait for the game to finish to start a new one."
+ self.participants = await utils.get_participants((await self.channel.fetch_message(self.signup_message.id)).reactions)
+ if len(self.participants) < await self.config.min_players():
+ self.signup_embed.description = "Too few players to start game."
+ await self.signup_message.edit(embed=self.signup_embed)
+ self.phase = GamePhase.FINISHED
+ return
+ await self.signup_message.edit(embed=self.signup_embed)
+ await self.starting_game()
await self.gameloop()
+ async def starting_game(self):
+ pass
+
async def conclude_game(self):
self.phase = GamePhase.FINISHED
embed = discord.Embed(
@@ -128,16 +139,27 @@ class PointBasedGame(OngoingGame, ABC):
high_scores[uid] = points
else:
high_scores[uid] = max(high_scores[uid], points)
+ async with self.config.current_winstreak() as current_winstreak:
+ sup = list(reversed(sorted(self.points.items(), key=lambda x: x[1])))
+ winner_id = str(sup[0][0].id)
+ if winner_id in current_winstreak:
+ current_winstreak[winner_id] += 1
+ else:
+ current_winstreak[winner_id] = 1
+ for user, points in sup[1:]:
+ uid = str(user.id)
+ current_winstreak[uid] = 0
return await super().conclude_game()
@property
def ranks(self) -> typing.List[typing.Tuple[int, typing.Tuple[discord.User, int]]]:
return utils.create_leaderboard(self.points)
- async def start_game(self):
+ async def starting_game(self):
for u in self.participants:
self.points[u] = 0
- return await super().start_game()
+
+ await super().starting_game()
def leaderboard(self) -> str:
return utils.format_leaderboard(self.ranks)
diff --git a/minecrafttrivia/trivia_interface_cog.py b/minecrafttrivia/trivia_interface_cog.py
index 405a64a..e65869a 100644
--- a/minecrafttrivia/trivia_interface_cog.py
+++ b/minecrafttrivia/trivia_interface_cog.py
@@ -9,7 +9,8 @@ from . import utils
from .game import OngoingGame, CraftingGame, GamePhase
-class TriviaInterfaceCog(commands.Cog):
+class TriviaInterfaceCog(commands.Cog, name="MinecraftTrivia"):
+
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.config = Config.get_conf(self, identifier=262200644)
@@ -18,8 +19,10 @@ class TriviaInterfaceCog(commands.Cog):
join_timeout=30,
guess_timeout=60,
round_count=10,
+ min_players=2,
total_scores={},
high_scores={},
+ current_winstreak={},
)
self.active_games_per_channel: typing.Dict[int, OngoingGame] = {}
@@ -35,19 +38,31 @@ class TriviaInterfaceCog(commands.Cog):
@commands.group(aliases=["mctrivia", "mct"], invoke_without_command=True)
@guild_only()
- async def minecrafttrivia(self, ctx: commands.GuildContext):
+ async def minecrafttrivia(self, ctx: commands.GuildContext, *, extra=""):
"""Starts a game of minecraft trivia"""
+ if extra:
+ await ctx.send("Invalid subcommand.")
game = self.get_game(ctx.channel)
if game:
return await ctx.send("Game already started.")
game = self.create_game(ctx.bot, ctx.channel)
await game.start_signup()
+ @minecrafttrivia.command(aliases=["now"])
+ @guild_only()
+ @checks.mod()
+ async def startnow(self, ctx: commands.GuildContext):
+ game = self.get_game(ctx.channel)
+ if not game:
+ return await ctx.send("No game running")
+ await game.start_game()
+
@minecrafttrivia.group(aliases=["config"], invoke_without_command=True)
@guild_only()
@checks.admin()
async def set(self, ctx: commands.GuildContext):
- await ctx.send("Available config options: join_timeout guess_timeout round_count")
+ """Sets config options. execute without arguments to see all options"""
+ await ctx.send("Available config options: join_timeout guess_timeout round_count min_players")
@set.command(aliases=["join"])
@guild_only()
@@ -60,6 +75,17 @@ class TriviaInterfaceCog(commands.Cog):
else:
await ctx.send(f"`join_timeout` is `{await c.join_timeout()}`")
+ @set.command(aliases=["players"])
+ @guild_only()
+ @checks.admin()
+ async def min_players(self, ctx: commands.GuildContext, to: int = None):
+ c = self.config.guild(ctx.guild)
+ if to:
+ await c.min_players.set(to)
+ await ctx.send(f"Set `min_players` to `{to}`")
+ else:
+ await ctx.send(f"`min_players` is `{await c.min_players()}`")
+
@set.command(aliases=["guess"])
@guild_only()
@checks.admin()
@@ -85,6 +111,7 @@ class TriviaInterfaceCog(commands.Cog):
@minecrafttrivia.command(aliases=["high"])
@guild_only()
async def highscore(self, ctx: commands.GuildContext):
+ """Show single-round highscore leaderboard"""
high_scores = await self.config.guild(ctx.guild).high_scores()
await ctx.send(embed=discord.Embed(
title=f"MC Trivia Highscores for {ctx.guild.name}",
@@ -93,14 +120,25 @@ class TriviaInterfaceCog(commands.Cog):
@minecrafttrivia.command(aliases=["lead", "total"])
@guild_only()
async def leaderboard(self, ctx: commands.GuildContext):
+ """Show total summed up highscore leaderboard"""
total_scores = await self.config.guild(ctx.guild).total_scores()
await ctx.send(embed=discord.Embed(
title=f"MC Trivia Leaderboard for {ctx.guild.name}",
description=utils.format_leaderboard(utils.create_leaderboard(total_scores))
))
+ @minecrafttrivia.command(aliases=["win"])
+ @guild_only()
+ async def winstreak(self, ctx: commands.GuildContext):
+ winstreaks = await self.config.guild(ctx.guild).current_winstreak()
+ await ctx.send(embed=discord.Embed(
+ title=f"MC Trivia Current Winstreaks in {ctx.guild.name}",
+ description=utils.format_leaderboard(utils.create_leaderboard(winstreaks))
+ ))
+
@minecrafttrivia.command()
async def info(self, ctx: commands.Context):
+ """Show info about this cog"""
embed = discord.Embed(
title="MC Trivia Cog by romangraef89",
description="This cog allows you to compete against your friends in a race to guess minecraft crafting recipes the fastest"