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
Some checks are pending
Run pre-commit / Run pre-commit (push) Waiting to run
This commit is contained in:
parent
d638772e80
commit
9c5924418d
2 changed files with 83 additions and 99 deletions
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue