Enhance leaderboard display in Leaderboard cog by adding a warning about potential inaccuracies, modernizing embed titles and descriptions, and improving user stats presentation. Update footer details for clarity and adjust formatting for better user experience.
Some checks are pending
Run pre-commit / Run pre-commit (push) Waiting to run

This commit is contained in:
Valerie 2025-05-26 20:51:46 -04:00
parent d638772e80
commit 9c5924418d
2 changed files with 83 additions and 99 deletions

View file

@ -358,17 +358,17 @@ class Leaderboard(commands.Cog):
if not chunks:
return await ctx.send("No users have 10,000 or more credits!")
# Send warning message first
await ctx.send("⚠️ **Note:** The global leaderboard may be slightly inaccurate due to synchronization delays.")
embeds = []
for page_num, entries in enumerate(chunks, 1):
embed = discord.Embed(
title="Global Credits Leaderboard",
title="🏆 Global Credits Leaderboard",
description="*Only showing users with 10,000+ credits*",
color=await ctx.embed_color()
)
# Add server icon if available
if ctx.guild.icon:
embed.set_thumbnail(url=ctx.guild.icon.url)
description = []
start_pos = (page_num - 1) * items_per_page
@ -377,26 +377,12 @@ class Leaderboard(commands.Cog):
user_id = entry.get("userId", "0")
credits = entry.get("points", 0)
# Calculate percentage position
percentage = (i / len(leaderboard_data)) * 100
# Medal emojis for top 3
medal = "🥇" if i == 1 else "🥈" if i == 2 else "🥉" if i == 3 else ""
description.append(
f"`{i}.` {medal} <@{user_id}>\n"
f"┗ 💰 **{humanize_number(credits)}** credits • Top **{percentage:.1f}%**"
f"`{i}.` <@{user_id}> • **{humanize_number(credits)}** credits"
)
embed.description = "\n".join(description)
# Modern footer with stats
total_credits = sum(entry["points"] for entry in leaderboard_data)
embed.set_footer(
text=f"Page {page_num}/{len(chunks)}{len(leaderboard_data):,} Users • {humanize_number(total_credits)} Total Credits",
icon_url=self.bot.user.display_avatar.url
)
embed.timestamp = datetime.now(timezone.utc)
embed.description = embed.description + "\n\n" + "\n".join(description)
embed.set_footer(text=f"Page {page_num}/{len(chunks)} • Total Users: {len(leaderboard_data)}")
embeds.append(embed)
view = LeaderboardView(self, ctx, embeds)
@ -456,49 +442,30 @@ class Leaderboard(commands.Cog):
# Debug logging
log.info(f"Credits check for {member}: {credits} credits")
# Get user's rank and total users for percentage calculation
# Get user's rank
leaderboard_data = await self.get_all_balances()
total_users = len(leaderboard_data)
rank = next(
(i for i, entry in enumerate(leaderboard_data, 1)
if entry.get("userId") == str(member.id)),
None
)
# Calculate percentage (top x%)
percentage = (rank / total_users * 100) if rank and total_users > 0 else None
embed = discord.Embed(
title="", # Modern design: no title needed
title="🏆 Global Credits",
color=await ctx.embed_color()
)
if credits >= 10000:
# Modern stat display with emojis and clean formatting
stats = [
f"💰 **{humanize_number(credits)}** credits",
f"📊 Rank **#{humanize_number(rank)}**" if rank else "📊 Unranked",
f"🎯 Top **{percentage:.1f}%**" if percentage else "",
f"🆔 `{member.id}`"
]
embed.description = "\n".join(s for s in stats if s) # Only include non-empty stats
embed.description = (
f"**User:** {member.mention}\n"
f"**Credits:** {humanize_number(credits)}\n"
f"**Rank:** #{humanize_number(rank) if rank else 'Unranked'}\n"
f"**ID:** {member.id}"
)
else:
embed.description = f"💰 **{humanize_number(credits)}** credits\n❗ *Minimum 10,000 credits needed for ranking*"
embed.description = f"{member.mention} has less than 10,000 credits ({humanize_number(credits)} total)"
# Modern avatar display
embed.set_author(
name=member.display_name,
icon_url=member.display_avatar.url
)
# Add a subtle footer with timestamp
embed.set_footer(
text="Global Leaderboard Stats",
icon_url=ctx.guild.icon.url if ctx.guild.icon else None
)
embed.timestamp = datetime.now(timezone.utc)
embed.set_thumbnail(url=member.display_avatar.url)
await ctx.send(embed=embed)
@globalboard.command(name="resync")

View file

@ -217,19 +217,19 @@ def generate_default_profile(
# Create the stats layer with glass effect
stats_layer = Image.new("RGBA", desired_card_size, (0, 0, 0, 0))
# Create a semi-transparent background for stats with modern blur effect
# Create a modern glass morphism effect for stats
glass = Image.new("RGBA", desired_card_size, (0, 0, 0, 0))
glass_draw = ImageDraw.Draw(glass)
glass_draw.rounded_rectangle(stats_area, radius=20, fill=(0, 0, 0, 95))
glass_draw.rounded_rectangle(stats_area, radius=25, fill=(255, 255, 255, 25)) # Lighter, more modern glass
# Add a subtle gradient overlay for depth
gradient = Image.new("RGBA", desired_card_size, (0, 0, 0, 0))
gradient_draw = ImageDraw.Draw(gradient)
for i in range(30):
opacity = int(60 * (1 - i/30))
for i in range(40):
opacity = int(35 * (1 - i/40)) # Reduced opacity for subtler effect
gradient_draw.rounded_rectangle(
(stats_area[0], stats_area[1]+i, stats_area[2], stats_area[3]),
radius=20,
radius=25,
fill=(255, 255, 255, opacity)
)
@ -237,13 +237,13 @@ def generate_default_profile(
stats_layer = Image.alpha_composite(stats_layer, glass)
stats_layer = Image.alpha_composite(stats_layer, gradient)
# Add a subtle glow border
# Add a subtle border glow
border_draw = ImageDraw.Draw(stats_layer)
for i in range(3):
border_draw.rounded_rectangle(
(stats_area[0]-i, stats_area[1]-i, stats_area[2]+i, stats_area[3]+i),
radius=20,
outline=(155, 17, 30, 100-i*30),
radius=25,
outline=(255, 255, 255, 80-i*25), # Lighter border
width=1
)
@ -256,53 +256,58 @@ def generate_default_profile(
level_text = f"P{prestige}{level_text}"
# Use larger font for level display
level_font = ImageFont.truetype(str(font_path or imgtools.DEFAULT_FONT), 52) # Increased from 42
level_y = stats_area[1] + 10
level_font = ImageFont.truetype(str(font_path or imgtools.DEFAULT_FONT), 56) # Increased size
level_y = stats_area[1] + 15
# Add subtle text shadow for depth
shadow_offset = 2
draw.text(
(stats_area[0] + 15 + shadow_offset, level_y + shadow_offset),
(stats_area[0] + 20 + shadow_offset, level_y + shadow_offset),
level_text,
font=level_font,
fill=(0, 0, 0, 100)
fill=(0, 0, 0, 80) # Reduced shadow opacity
)
draw.text(
(stats_area[0] + 15, level_y),
(stats_area[0] + 20, level_y),
level_text,
font=level_font,
fill=user_color
)
# Stats section with improved layout and larger fonts
title_font_size = 26 # Increased from 20
value_font_size = 30 # Increased from 24
title_font_size = 28 # Increased from 26
value_font_size = 32 # Increased from 30
title_font = ImageFont.truetype(str(font_path or imgtools.DEFAULT_FONT), title_font_size)
value_font = ImageFont.truetype(str(font_path or imgtools.DEFAULT_FONT), value_font_size)
spacing = 42 # Increased from 35
spacing = 45 # Increased spacing
# Starting positions
start_x = stats_area[0] + 15
start_y = level_y + 65 # Adjusted for larger level font
start_x = stats_area[0] + 20
start_y = level_y + 75
# Helper function for stat rendering with improved spacing
def draw_stat(x_pos, y_pos, icon, title, value, color=stat_color):
# Draw icon
# Draw icon with glow effect
for offset in [(1,1), (-1,-1), (1,-1), (-1,1)]:
draw.text((x_pos + offset[0], y_pos + offset[1] + 2), icon, font=value_font, fill=(255, 255, 255, 30))
draw.text((x_pos, y_pos + 2), icon, font=value_font, fill=color)
# Draw title
title_x = x_pos + 35 # Increased spacing after icon
draw.text((title_x, y_pos), f"{title}:", font=title_font, fill=(200, 200, 200))
# Draw title with modern styling
title_x = x_pos + 40 # Increased spacing after icon
draw.text((title_x, y_pos), f"{title}:", font=title_font, fill=(220, 220, 220))
# Calculate value position
title_width = draw.textlength(f"{title}:", font=title_font)
# Draw value with shadow for depth
value_x = title_x + title_width + 8 # Increased spacing between title and value
draw.text((value_x + 1, y_pos + 1), value, font=value_font, fill=(0, 0, 0, 100))
value_x = title_x + title_width + 10 # Increased spacing
# Draw value with subtle shadow
draw.text((value_x + 1, y_pos + 1), value, font=value_font, fill=(0, 0, 0, 60))
draw.text((value_x, y_pos), value, font=value_font, fill=color)
return spacing
# Draw stats in two columns with better spacing
left_column_x = start_x
right_column_x = stats_area[0] + 320 # Adjusted for larger text
right_column_x = stats_area[0] + 340 # Adjusted for larger text
current_y = start_y
# Left column stats
@ -316,48 +321,48 @@ def generate_default_profile(
current_y += draw_stat(right_column_x, current_y, "💰", "Balance", f"{humanize_number(balance)} {currency_name}")
current_y += draw_stat(right_column_x, current_y, "🏆", "Rank", f"#{humanize_number(position)}")
# Progress bar with modern design - moved down
bar_width = stats_area[2] - stats_area[0] - 30
bar_height = 28 # Increased from 25
bar_y = stats_area[3] - 50 # Adjusted position
# Progress bar with modern design
bar_width = stats_area[2] - stats_area[0] - 40 # Slightly narrower
bar_height = 30 # Taller bar
bar_y = stats_area[3] - 65 # Moved up slightly
progress = (current_xp - previous_xp) / (next_xp - previous_xp)
# XP text above progress bar with larger font
xp_font = ImageFont.truetype(str(font_path or imgtools.DEFAULT_FONT), 24) # Increased from 20
# XP text above progress bar
xp_font = ImageFont.truetype(str(font_path or imgtools.DEFAULT_FONT), 26) # Increased size
xp_text = f"EXP: {humanize_number(current_xp)} / {humanize_number(next_xp)}"
xp_x = start_x + (bar_width - draw.textlength(xp_text, font=xp_font)) // 2
# Draw XP text with shadow
# Draw XP text with improved shadow
draw.text(
(xp_x + 1, bar_y - 28 + 1), # Adjusted for larger font
(xp_x + 1, bar_y - 30 + 1),
xp_text,
font=xp_font,
fill=(0, 0, 0, 100)
fill=(0, 0, 0, 60)
)
draw.text(
(xp_x, bar_y - 28), # Adjusted for larger font
(xp_x, bar_y - 30),
xp_text,
font=xp_font,
fill=(255, 255, 255)
)
# Create progress bar background with gradient
bar_bg = Image.new("RGBA", (bar_width, bar_height), (0, 0, 0, 100))
# Create progress bar with modern gradient
bar_bg = Image.new("RGBA", (bar_width, bar_height), (0, 0, 0, 40)) # More transparent background
progress_width = max(1, int(bar_width * progress))
bar_progress = Image.new("RGBA", (progress_width, bar_height), level_bar_color + (200,))
bar_progress = Image.new("RGBA", (progress_width, bar_height), level_bar_color + (230,))
# Add shine effect to progress bar
gradient = Image.new("RGBA", bar_progress.size, (0, 0, 0, 0))
gradient_draw = ImageDraw.Draw(gradient)
for i in range(bar_height):
opacity = int(150 * (1 - abs(i - bar_height/2)/(bar_height/2)))
opacity = int(120 * (1 - abs(i - bar_height/2)/(bar_height/2))) # Reduced shine intensity
gradient_draw.rectangle(
(0, i, bar_progress.width, i+1),
fill=(255, 255, 255, opacity)
)
bar_progress = Image.alpha_composite(bar_progress, gradient)
# Round the corners
# Round the corners more
bar_mask = Image.new("L", (bar_width, bar_height))
bar_mask_draw = ImageDraw.Draw(bar_mask)
bar_mask_draw.rounded_rectangle((0, 0, bar_width-1, bar_height-1), radius=bar_height//2, fill=255)
@ -372,16 +377,28 @@ def generate_default_profile(
stats_layer.paste(bar_bg, (start_x, bar_y), bar_bg)
stats_layer.paste(bar_progress_masked, (start_x, bar_y), bar_progress_masked)
# Progress percentage below bar
# Progress percentage with improved positioning and styling
percent_text = f"{int(progress * 100)}%"
percent_x = start_x + (bar_width - draw.textlength(percent_text, font=xp_font)) // 2
percent_font = ImageFont.truetype(str(font_path or imgtools.DEFAULT_FONT), 24) # Dedicated font size
percent_width = draw.textlength(percent_text, font=percent_font)
# Position percentage on the progress bar itself
percent_x = start_x + progress_width - (percent_width // 2)
percent_x = min(max(start_x + 10, percent_x), start_x + bar_width - percent_width - 10) # Keep within bar bounds
percent_y = bar_y + (bar_height - 24) // 2 # Center vertically in bar
# Draw percentage with improved visibility
draw.text(
(percent_x, bar_y + bar_height + 6), # Adjusted spacing
(percent_x + 1, percent_y + 1),
percent_text,
font=xp_font,
fill=stat_color,
stroke_width=1,
stroke_fill=(0, 0, 0)
font=percent_font,
fill=(0, 0, 0, 80)
)
draw.text(
(percent_x, percent_y),
percent_text,
font=percent_font,
fill=(255, 255, 255) # White text for better contrast
)
# Composite the layers