Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions src/tgbot/handlers/treasury/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from src.tgbot.handlers.payments.purchase import PURCHASE_TOKEN_CALLBACK_DATA_PATTERN
from src.tgbot.handlers.treasury.constants import PAYOUTS, TrxType
from src.tgbot.handlers.treasury.service import (
LEADERBOARD_WINDOW_DAYS,
get_leaderboard,
get_token_supply,
get_user_balance,
Expand Down Expand Up @@ -102,27 +103,30 @@ async def handle_show_leaderbaord(update: Update, context: ContextTypes.DEFAULT_
emoji = get_random_emoji()
leaderboard = await get_leaderboard()

LEADERBOARD_TEXT = f"{emoji} Leaderboard {emoji}\n\n"
LEADERBOARD_TEXT = (
f"{emoji} Leaderboard (last {LEADERBOARD_WINDOW_DAYS} days) {emoji}\n\n"
)
for i, user in enumerate(leaderboard):
icon = "🏆" if i == 0 else "🥈" if i == 1 else "🥉" if i == 2 else "🏅"
nick = user["nickname"] or get_random_emoji() * 3
LEADERBOARD_TEXT += f"{icon} - {nick} - {user['balance']} 🍔\n"
weekly_earned = user.get("weekly_earned", 0)
LEADERBOARD_TEXT += f"{icon} - {nick} - {weekly_earned} 🍔\n"

tokens = await get_token_supply()
LEADERBOARD_TEXT += f"\nTotal supply: {tokens} 🍔"

user_lb_data = await get_user_place_in_leaderboard(update.effective_user.id)
if user_lb_data:
place, nickname, balance = (
place, nickname, weekly_earned = (
user_lb_data["place"],
user_lb_data["nickname"],
user_lb_data["balance"],
user_lb_data.get("weekly_earned", 0),
)
if nickname:
LEADERBOARD_TEXT += f"""

You:
#{place} - {nickname} - {balance} 🍔
#{place} - {nickname} - {weekly_earned} 🍔

/kitchen /uploads /chat
"""
Expand Down
66 changes: 49 additions & 17 deletions src/tgbot/handlers/treasury/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
from src.tgbot.handlers.treasury.constants import TrxType


LEADERBOARD_WINDOW_DAYS = 7


async def calculate_user_balance(user_id: int):
select_statement = select(func.sum(treasury_trx.c.amount)).where(
treasury_trx.c.user_id == user_id
Expand All @@ -27,8 +30,31 @@ async def get_user_balance(user_id: int) -> int:
return user_balance or 0


def _recent_earnings_subquery():
window_start = func.now() - text(f"INTERVAL '{LEADERBOARD_WINDOW_DAYS} days'")

return (
select(
treasury_trx.c.user_id.label("user_id"),
func.sum(treasury_trx.c.amount).label("weekly_earned"),
)
.where(treasury_trx.c.created_at >= window_start)
.where(treasury_trx.c.amount > 0)
.group_by(treasury_trx.c.user_id)
.subquery()
)


async def get_leaderboard(limit=10) -> list[dict[str, Any]]:
select_statement = select(user).order_by(user.c.balance.desc()).limit(limit)
recent_earnings = _recent_earnings_subquery()

select_statement = (
select(user, recent_earnings.c.weekly_earned)
.join(recent_earnings, recent_earnings.c.user_id == user.c.id)
.order_by(recent_earnings.c.weekly_earned.desc(), user.c.id.asc())
.limit(limit)
)

return await fetch_all(select_statement)


Expand All @@ -39,25 +65,31 @@ async def get_token_supply() -> int:


async def get_user_place_in_leaderboard(user_id: int) -> int:
return await fetch_one(
text(
f"""
SELECT
id, nickname, place, balance
FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY balance DESC) place,
id,
nickname,
balance
FROM
"user"
) with_row_number
WHERE id = {user_id}
"""
recent_earnings = _recent_earnings_subquery()

ranked_users = (
select(
user.c.id.label("id"),
user.c.nickname.label("nickname"),
user.c.balance.label("balance"),
recent_earnings.c.weekly_earned.label("weekly_earned"),
func.row_number()
.over(
order_by=(
recent_earnings.c.weekly_earned.desc(),
user.c.id.asc(),
)
)
.label("place"),
)
.join(recent_earnings, recent_earnings.c.user_id == user.c.id)
.subquery()
)

select_statement = select(ranked_users).where(ranked_users.c.id == user_id)

return await fetch_one(select_statement)


async def create_treasury_trx(
user_id: int,
Expand Down