Implement /api/v1/leaderboard

This commit is contained in:
kittentm 2026-03-22 00:40:21 +01:00
commit 2456e2b4ec
No known key found for this signature in database
GPG key ID: AC43DFDBC1F44A91
3 changed files with 74 additions and 1 deletions

View file

@ -1,4 +1,4 @@
from sqlalchemy import create_engine, Column, String, Integer, Boolean, DateTime, ForeignKey, Text, BigInteger
from sqlalchemy import create_engine, Column, String, Integer, Boolean, DateTime, ForeignKey, Text, BigInteger, Float, func
from sqlalchemy.orm import declarative_base, sessionmaker
from sqlalchemy.exc import OperationalError
from config import settings
@ -45,6 +45,20 @@ class EquipmentLast(Base):
Rank = Column(Integer)
Udemae = Column(Integer)
class PlayerRank(Base):
__tablename__ = 'player_ranks'
PId = Column(BigInteger, primary_key=True, nullable=False)
GameMode = Column(Integer, primary_key=True, nullable=False)
MiiName = Column(String, nullable=True)
Rank = Column(Integer, default=0)
FesPower = Column(Float, default=0.0)
WinSum = Column(Integer, default=0)
LoseSum = Column(Integer, default=0)
RankingScore = Column(Float, default=0.0)
createdAt = Column(DateTime, server_default=func.now())
updatedAt = Column(DateTime, onupdate=func.now())
engine = create_engine(settings.db_url, pool_pre_ping=True)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

View file

@ -11,6 +11,7 @@ from routes import me
from routes.equipment import equipment_history
from routes.equipment import equipment
from services.boss_retrieval import process_boss_file
from routes import Ranking
from contextlib import asynccontextmanager
import asyncio
import subprocess
@ -119,6 +120,7 @@ app.include_router(boss.router, prefix="/api/v1")
app.include_router(me.router, prefix="/api/v1")
app.include_router(equipment_history.router, prefix="/api/v1")
app.include_router(equipment.router, prefix="/api/v1")
app.include_router(Ranking.router, prefix="/api/v1")
if __name__ == '__main__':
uvicorn.run("main:app", host="0.0.0.0", port=settings.port, reload=True)

57
routes/Ranking.py Normal file
View file

@ -0,0 +1,57 @@
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session as DBSession
from sqlalchemy import desc
from database import SessionLocal, PlayerRank
router = APIRouter()
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@router.get("/leaderboard")
async def get_leaderboard(db: DBSession = Depends(get_db)):
try:
top_100_query = (
db.query(PlayerRank.PId)
.order_by(desc(PlayerRank.FesPower))
.limit(100)
.all()
)
top_100_pids = {row for row in top_100_query}
modes = [0, 1, 2]
leaderboard = {}
for mode in modes:
top_players = (
db.query(PlayerRank)
.filter(PlayerRank.GameMode == mode)
.order_by(desc(PlayerRank.RankingScore))
.limit(9)
.all()
)
mode_results = []
for player in top_players:
mode_results.append({
"PId": player.PId,
"MiiName": player.MiiName,
"Rank": player.Rank,
"WinSum": player.WinSum,
"LoseSum": player.LoseSum,
"RankingScore": round(player.RankingScore, 2),
"FesPower": player.FesPower,
"is_top_100_fes": player.PId in top_100_pids
})
leaderboard[f"mode_{mode}"] = mode_results
return leaderboard
except Exception as e:
print(f"Error fetching leaderboard: {e}")
return {"error": str(e)}