diff --git a/app/database/statistics.py b/app/database/statistics.py index 54aa3bb..47d0824 100644 --- a/app/database/statistics.py +++ b/app/database/statistics.py @@ -86,7 +86,7 @@ class UserStatisticsResp(UserStatisticsBase): @classmethod async def from_db( - cls, obj: UserStatistics, session: AsyncSession, user_country: str + cls, obj: UserStatistics, session: AsyncSession, user_country: str | None = None ) -> "UserStatisticsResp": s = cls.model_validate(obj) s.grade_counts = { diff --git a/app/router/v2/__init__.py b/app/router/v2/__init__.py index 7f981ee..1cd8d16 100644 --- a/app/router/v2/__init__.py +++ b/app/router/v2/__init__.py @@ -5,6 +5,7 @@ from . import ( # pyright: ignore[reportUnusedImport] # noqa: F401 beatmapset, me, misc, + ranking, relationship, room, score, diff --git a/app/router/v2/ranking.py b/app/router/v2/ranking.py new file mode 100644 index 0000000..1e3c914 --- /dev/null +++ b/app/router/v2/ranking.py @@ -0,0 +1,52 @@ +from __future__ import annotations + +from typing import Literal + +from app.database import User +from app.database.statistics import UserStatistics, UserStatisticsResp +from app.dependencies import get_current_user +from app.dependencies.database import get_db +from app.models.score import GameMode + +from .router import router + +from fastapi import Depends, Path, Query, Security +from sqlmodel import col, select +from sqlmodel.ext.asyncio.session import AsyncSession + + +@router.get( + "/{ruleset}/{type}", + response_model=list[UserStatisticsResp], + name="获取排行榜", + description="获取在指定模式下的用户排行榜", + tags=["排行榜"], +) +async def get_user_ranking( + ruleset: GameMode = Path(..., description="指定 ruleset"), + type: Literal["performance", "score"] = Path( + ..., description="排名类型:performance 表现分 / score 计分成绩总分" + ), + country: str | None = Query(None, description="国家代码"), + page: int = Query(1, ge=1, description="页码"), + current_user: User = Security(get_current_user, scopes=["public"]), + session: AsyncSession = Depends(get_db), +): + wheres = [col(UserStatistics.mode) == ruleset] + if type == "performance": + order_by = col(UserStatistics.pp).desc() + else: + order_by = col(UserStatistics.ranked_score).desc() + if country: + wheres.append(col(UserStatistics.user).has(country_code=country.upper())) + statistics_list = await session.exec( + select(UserStatistics) + .where(*wheres) + .order_by(order_by) + .limit(50) + .offset(50 * (page - 1)) + ) + return [ + await UserStatisticsResp.from_db(statistics, session, None) + for statistics in statistics_list + ]