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
This commit was merged in pull request #1.
This commit is contained in:
2026-08-12 11:10:35 +02:00
parent 36c8231b67
commit fe93b27eb5
2 changed files with 137 additions and 63 deletions
+128 -63
View File
@@ -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)