From fe93b27eb5f3d65b15caf91825dd271d0629c8fe Mon Sep 17 00:00:00 2001 From: iiLarsH Date: Wed, 12 Aug 2026 11:10:35 +0200 Subject: [PATCH] Changes to LB and Profile commands Leaderboard updates: - Hopefully sped up the loading - Added perfect games lb - Added Monthly, Yearly and Alltime Profile updates: - Added Perfect games --- Commands/leaderboard.py | 191 +++++++++++++++++++++++++++------------- Commands/profile.py | 9 ++ 2 files changed, 137 insertions(+), 63 deletions(-) diff --git a/Commands/leaderboard.py b/Commands/leaderboard.py index bc92220..657ec75 100755 --- a/Commands/leaderboard.py +++ b/Commands/leaderboard.py @@ -7,79 +7,144 @@ class Leaderboard(commands.Cog): def __init__(self, bot): self.bot = bot + @app_commands.choices( + leaderboard_type=[ + app_commands.Choice(name="Accuracy", value="accuracy"), + app_commands.Choice(name="Perfect Games", value="perfect") + ], + period=[ + app_commands.Choice(name="Monthly", value="monthly"), + app_commands.Choice(name="Yearly", value="yearly"), + app_commands.Choice(name="All Time", value="alltime") + ] + ) @app_commands.command( name="leaderboard", - description="Best players by accuracy" + description="Show a leaderboard" ) - async def leaderboard(self, interaction: discord.Interaction): - conn = sqlite3.connect("Goonerdle.db") - cursor = conn.cursor() - + async def leaderboard( + self, + interaction: discord.Interaction, + leaderboard_type: str, + period: str + ): try: - cursor.execute(""" - SELECT - User_ID, - COUNT(*) as games_played, - SUM(Result) as total_correct - FROM Result - GROUP BY User_ID - """) + if leaderboard_type == "accuracy": + msg = get_accuracy_leaderboard( + period, + interaction.guild + ) - rows = cursor.fetchall() - - if not rows: - await interaction.response.send_message("No data available.") - return - - leaderboard_data = [] - - # Calculate accuracy - for user_id, games_played, total_correct in rows: - total_possible = games_played * 10 - accuracy = (total_correct / total_possible) * 100 - - leaderboard_data.append((user_id, accuracy, games_played)) - - # Sort by accuracy descending - leaderboard_data.sort(key=lambda x: x[1], reverse=True) - - # Build leaderboard text - lines = [] - position = 1 - - for user_id, accuracy, games_played in leaderboard_data[:10]: - # Try cache first - user = self.bot.get_user(user_id) - - # Fetch if not cached - if user is None: - try: - user = await self.bot.fetch_user(user_id) - except e: - user = None - - # NO PINGS → use display name or username - if user: - name = user.display_name if hasattr(user, "display_name") else user.name - else: - name = f"User {user_id}" - - line = f"{position}. {name} — **{accuracy:.2f}%** ({games_played} games)" - lines.append(line) - - position += 1 - - msg = "🏆 **Accuracy Leaderboard** 🏆\n\n" + "\n".join(lines) + elif leaderboard_type == "perfect": + msg = get_perfect_score_leaderboard( + period, + interaction.guild + ) await interaction.response.send_message(msg) except Exception as e: print("Leaderboard error:", e) - await interaction.response.send_message("Error loading leaderboard.") - - finally: - conn.close() - + await interaction.response.send_message( + "Error loading leaderboard." + ) async def setup(bot): await bot.add_cog(Leaderboard(bot)) + +def get_accuracy_leaderboard(period, guild): + conn = sqlite3.connect("Goonerdle.db") + cursor = conn.cursor() + + cursor.execute(""" + SELECT + User_ID, + COUNT(*) AS games_played, + ROUND( + (SUM(Result) * 100.0) / + (COUNT(*) * 10), + 2 + ) AS accuracy + FROM Result + WHERE + ? = 'alltime' + OR ( + ? = 'monthly' + AND DateScore >= date('now', 'start of month') + ) + OR ( + ? = 'yearly' + AND DateScore >= date('now', 'start of year') + ) + GROUP BY User_ID + HAVING COUNT(*) >= 5 + ORDER BY accuracy DESC + LIMIT 10 + """, (period, period, period)) + + rows = cursor.fetchall() + conn.close() + + lines = [] + + for position, (user_id, games_played, accuracy) in enumerate(rows, start=1): + + member = guild.get_member(user_id) + + if member: + name = member.display_name + else: + name = f"User {user_id}" + + lines.append( + f"{position}. {name} — **{accuracy:.2f}%** ({games_played} games)" + ) + + return "🏆 **Accuracy Leaderboard** 🏆\n\n" + "\n".join(lines) + +def get_perfect_score_leaderboard(period, guild): + conn = sqlite3.connect("Goonerdle.db") + cursor = conn.cursor() + + cursor.execute(""" + SELECT + User_ID, + COUNT(*) AS perfect_games + FROM Result + WHERE + Result = 10 + AND ( + ? = 'alltime' + OR ( + ? = 'monthly' + AND DateScore >= date('now', 'start of month') + ) + OR ( + ? = 'yearly' + AND DateScore >= date('now', 'start of year') + ) + ) + GROUP BY User_ID + ORDER BY perfect_games DESC + LIMIT 10 + """, (period, period, period)) + + rows = cursor.fetchall() + conn.close() + + lines = [] + + for position, (user_id, perfect_games) in enumerate(rows, start=1): + + member = guild.get_member(user_id) + + if member: + name = member.display_name + else: + name = f"User {user_id}" + + lines.append( + f"{position}. {name} — **{perfect_games}** perfect games" + ) + + return "🏆 **Perfect Game Leaderboard** 🏆\n\n" + "\n".join(lines) \ No newline at end of file diff --git a/Commands/profile.py b/Commands/profile.py index ae6b04e..34fde26 100755 --- a/Commands/profile.py +++ b/Commands/profile.py @@ -29,6 +29,14 @@ class Profile(commands.Cog): times_played = row[0] total_correct = row[1] + cursor.execute("""SELECT COUNT(*) + FROM Result + WHERE User_ID = ? AND Result = 10 + """, (user_id,)) + + row = cursor.fetchone() + perfect_games = row[0] + if times_played == 0: await interaction.response.send_message( f"{user.mention} has not played yet!" @@ -43,6 +51,7 @@ class Profile(commands.Cog): msg = ( f"**{user.name}'s Profile**\n\n" f"Games Played: **{times_played}**\n" + f"Perfect Games Played: **{perfect_games}**\n" f"Correct: **{total_correct}**\n" f"Incorrect: **{total_incorrect}**\n" f"Accuracy: **{percentage:.2f}%**"