stepstead-backend/routers/leaderboard.py
jts ea049b8ccd İlk commit: Stepstead backend (FastAPI)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 11:30:24 +03:00

59 lines
1.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Liderlik tablosu — adım (lifetime), level ve gold sıralamaları.
GET /leaderboard?by=steps|level|gold → top 20 + kendi sıran.
"""
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
from sqlalchemy import select, text
from sqlalchemy.ext.asyncio import AsyncSession
from deps import get_current_user
from models import Character, User, get_db
router = APIRouter(prefix="/leaderboard", tags=["leaderboard"])
ORDER_COLS = {"steps": "step_lifetime", "level": "total_xp", "gold": "gold"}
class LeaderRow(BaseModel):
rank: int
name: str
level: int
value: int # sıralama kriterinin değeri
me: bool
class LeaderboardOut(BaseModel):
by: str
rows: list[LeaderRow]
my_rank: int
@router.get("", response_model=LeaderboardOut)
async def leaderboard(by: str = "steps",
user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db)):
if by not in ORDER_COLS:
raise HTTPException(400, "by: steps | level | gold")
col = ORDER_COLS[by]
char = (await db.execute(select(Character).where(Character.user_id == user.id))).scalar_one_or_none()
if not char:
raise HTTPException(404, "Karakter yok")
rows = (await db.execute(text(f"""
SELECT rank, name, level, val, id FROM (
SELECT id, name, level, {col} AS val,
RANK() OVER (ORDER BY {col} DESC, id) AS rank
FROM characters
) t WHERE rank <= 20 OR id = :me
ORDER BY rank
"""), {"me": char.id})).all()
my_rank = 0
out: list[LeaderRow] = []
for r in rows:
me = r[4] == char.id
if me:
my_rank = int(r[0])
if int(r[0]) <= 20:
out.append(LeaderRow(rank=int(r[0]), name=r[1], level=int(r[2]), value=int(r[3]), me=me))
return LeaderboardOut(by=by, rows=out, my_rank=my_rank)