Skip to content

Commit

Permalink
Fixed leaderboard (for real this time) w/ other fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Ambratolm authored and Ambratolm committed Feb 26, 2025
1 parent 7a7a929 commit f2d59bc
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 52 deletions.
79 changes: 49 additions & 30 deletions bot/cogs/board.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

from discord import Color, Embed, Interaction, Member, User, app_commands
from discord.ext.commands import Cog
from humanize import naturaltime
from humanize import intcomma, naturaltime
from odmantic import query

from bot.main import ActBot
from db.actor import Actor
from humanize import intword, metric, ordinal


class Board(Cog, description="Allows players to view their data."):
Expand All @@ -22,7 +23,10 @@ async def profile(
):
await interaction.response.defer()
member = member or interaction.user
embed = Embed(title=f"👤 {member.display_name}", color=Color.blue())
embed = Embed(
title=f"👤 {member.display_name}",
color=Color.blue(),
)
if isinstance(member, Member):
embed.description = " ".join(
[
Expand All @@ -31,29 +35,33 @@ async def profile(
if role != member.guild.default_role
]
)
embed.set_thumbnail(url=member.display_avatar.url)
db = self.bot.get_db(interaction.guild)
actor = db.find_one(Actor, Actor.id == member.id) if db else None
if actor:
embed.add_field(name="", value="", inline=False)
embed.add_field(
name="Level",
value=f"🏅 **{actor.level}**\n{actor.level_bar}",
)
embed.add_field(
name="Experience",
value=f"⏫ **{actor.xp}** / {actor.next_level_xp}\n{actor.xp_bar}",
)
embed.add_field(name="", value="", inline=False)
embed.add_field(name="Gold", value=f"💰 **{actor.gold}**")
embed.add_field(name="Items", value=f"🎒 **{len(actor.items)}**")
embed.add_field(name="", value="", inline=False)

if not actor:
actor = self.bot.create_actor(member)
embed.add_field(name="", value="", inline=False)
embed.add_field(
name="Rank", value=f"🏆 **{actor.rank_name}**\n{actor.rank_bar}"
)
embed.add_field(
name="Level",
value=f"🏅 **{actor.level}**\n{actor.level_bar}",
)
embed.add_field(
name="Experience",
value=f"⏫ **{actor.xp}** / {actor.next_level_xp}\n{actor.xp_bar}",
)
embed.add_field(name="", value="", inline=False)
embed.add_field(name="Gold", value=f"💰 **{actor.gold}**")
embed.add_field(name="Items", value=f"🎒 **{len(actor.items)}**")
if isinstance(member, Member):
embed.add_field(
name="Joined",
value=f"⌚ {member.guild.name} **{naturaltime(member.joined_at or 0)}**\n-# ⌚ Discord **{naturaltime(member.created_at)}**",
)
embed.add_field(name="", value="", inline=False)
embed.set_footer(text=f"#️⃣{member.name} \n🆔{member.id}")
embed.set_thumbnail(url=member.display_avatar.url)
await interaction.followup.send(embed=embed)

@app_commands.guild_only()
Expand All @@ -71,6 +79,7 @@ async def leaderboard(self, interaction: Interaction):
db.find(
Actor,
sort=(
query.desc(Actor.rank),
query.desc(Actor.level),
query.desc(Actor.xp),
query.desc(Actor.gold),
Expand All @@ -90,18 +99,28 @@ async def leaderboard(self, interaction: Interaction):
)
return

# Create embed while fetching memebrs associated with actors
embed = Embed(title="🏆 Leaderboard", color=Color.blue())
# Create board table
top_actor: Actor
leaderboard_text = "```"
for i, actor in enumerate(actors):
separator = 10 * "‎ "
embed.add_field(name="", value="", inline=False)
embed.add_field(
name=f"# **{i + 1}** {separator} {actor.display_name}",
value=f"",
)
embed.add_field(name="", value="")
embed.add_field(
name=f"",
value=f"-# 🏅 {actor.level} {separator}{actor.xp} {separator} 💰 {actor.gold}",
if i == 0:
top_actor = actor
name = f"{actor.display_name} ({actor.name})"
rank = actor.rank_name
level = str(actor.level)
xp = intcomma(actor.xp)
gold = intcomma(actor.gold)
leaderboard_text += (
f"# {(i+1):<2} {name}\n\t 🏆{rank:<2} 🏅{level}{xp} 💰{gold}\n\n"
)
leaderboard_text += "```"

# Create embed
embed = Embed(title="🏆 Leaderboard", color=Color.blue())
top_member = guild.get_member(top_actor.id) or await guild.fetch_member(
top_actor.id
)
if top_member:
embed.set_thumbnail(url=top_member.display_avatar)
embed.add_field(name="", value=leaderboard_text, inline=False)
await interaction.followup.send(embed=embed)
47 changes: 33 additions & 14 deletions bot/cogs/farm.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,17 @@
import random
import re

from discord import Color, Embed, Member, Message, TextChannel, User, utils
from discord import (
Color,
Embed,
Member,
Message,
Permissions,
Role,
TextChannel,
User,
utils,
)
from discord.ext.commands import Bot, Cog

from bot.main import ActBot
Expand Down Expand Up @@ -48,24 +58,32 @@ async def on_message(self, message: Message):
gold_reward = random.randint(1, 500) * actor.level
actor.gold += gold_reward
embed = Embed(
title=f"🎉 Level Up",
title=f"🏅 Level Up",
description=f"{member.display_name} {member.mention} has reached a new level and has been rewarded.",
color=Color.green(),
)
embed.add_field(name="", value="", inline=False)
embed.add_field(name="Level", value=f"🏅 **{actor.level}**")
embed.add_field(name="Level", value=f"🏅 **{actor.level}**")
embed.add_field(name="Gold 🔼", value=f"💰 **+{gold_reward}**")
embed.set_thumbnail(url=member.display_avatar.url)
await message.channel.send(embed=embed)

# Try role-up
awarded_role = await self.award_role(member, actor.rank_name)
if awarded_role:
if actor.try_rank_up():
# awarded_role = await self.award_role(member, actor.rank_name)
# if awarded_role:
gold_reward = random.randint(1, 1000) * actor.level
actor.gold += gold_reward
await message.channel.send(
f"🎉 {member.mention}! You have been awarded **{awarded_role.name} Role** and earned **💰 {gold_reward} Gold**."
embed = Embed(
title=f"🏆 Rank Up",
description=f"{member.display_name} {member.mention} has reached a new rank and has been rewarded.",
color=Color.green(),
)
embed.add_field(name="", value="", inline=False)
embed.add_field(name="Rank ✨", value=f"🏆 **{actor.rank_name}**")
embed.add_field(name="Gold 🔼", value=f"💰 **+{gold_reward}**")
embed.set_thumbnail(url=member.display_avatar.url)
await message.channel.send(embed=embed)

# Save changes
db.save(actor)
Expand Down Expand Up @@ -95,10 +113,11 @@ def calculate_xp_reward(message: Message):
return random.randint(1, word_count)

@staticmethod
async def award_role(user: Member, role_name: str):
if role_name:
role = utils.get(user.guild.roles, name=role_name)
if role and role not in user.roles:
await user.add_roles(role)
return role
return None
async def try_award_role(member: Member, role_name: str) -> Role | None:
role = utils.get(member.guild.roles, name=role_name)
if role in member.roles:
return None
elif not role:
role = await member.guild.create_role(name=role_name)
await member.add_roles(role)
return role
12 changes: 8 additions & 4 deletions db/actor.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class Actor(Model):
RANK_BASE_LEVEL: ClassVar[int] = 30
RANK_EXPONENT: ClassVar[float] = 1
RANK_NAMES: ClassVar[list[str]] = [
"Unranked",
"?",
"Iron",
"Bronze",
"Silver",
Expand All @@ -51,7 +51,7 @@ class Actor(Model):
@property
def rank_name(self) -> str:
"""Get name of current rank."""
return self.RANK_NAMES[self.rank - 1]
return self.RANK_NAMES[self.rank]

# ----------------------------------------------------------------------------------------------------

Expand Down Expand Up @@ -86,15 +86,19 @@ def try_level_up(self) -> bool:
def try_rank_up(self) -> bool:
"""Check if player has enough level to rank up and increment rank if so."""
initial_rank = self.rank
if self.level >= self.next_rank_level and self.rank < self.MAX_RANKS:
while self.level >= self.next_rank_level and self.rank < self.MAX_RANKS:
self.rank += 1
return self.rank > initial_rank

# ----------------------------------------------------------------------------------------------------

@property
def rank_bar(self) -> str:
return text_progress_bar(self.rank, self.MAX_RANKS, 5, "⭐", "☆")

@property
def level_bar(self) -> str:
return text_progress_bar(self.level, self.next_rank_level, 5, "", "")
return text_progress_bar(self.level, self.next_rank_level, 5, "", "")

@property
def xp_bar(self) -> str:
Expand Down
5 changes: 1 addition & 4 deletions utils/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,7 @@ def text_progress_bar(
empty_char="░",
) -> str:
"""Render text progress bar using unicode characters."""
if max == 0:
max = current if current != 0 else 1
normalized_value = int((current / max) * length)
type(normalized_value)
normalized_value = min(int((current / (max or current or 1)) * length), length)
return (normalized_value * filled_char) + ((length - normalized_value) * empty_char)


Expand Down

0 comments on commit f2d59bc

Please sign in to comment.