diff --git a/app/router/v2/ranking.py b/app/router/v2/ranking.py index e0590fe..bd83cec 100644 --- a/app/router/v2/ranking.py +++ b/app/router/v2/ranking.py @@ -11,14 +11,74 @@ from app.models.score import GameMode from .router import router from fastapi import Depends, Path, Query, Security +from pydantic import BaseModel from sqlmodel import col, select from sqlmodel.ext.asyncio.session import AsyncSession +class CountryStatistics(BaseModel): + country_code: str + active_users: int + play_count: int + ranked_score: int + performance: int + + +class CountryResponse(BaseModel): + ranking: list[CountryStatistics] + + +@router.get( + "/rankings/{ruleset}/country", + response_model=CountryResponse, + name="获取地区排行榜", + description="获取在指定模式下的地区排行榜", + tags=["排行榜"], +) +async def get_country_ranking( + ruleset: GameMode = Path(..., description="指定 ruleset"), + page: int = Query(1, ge=1, description="页码"), # TODO + current_user: User = Security(get_current_user, scopes=["public"]), + session: AsyncSession = Depends(get_db), +): + response = CountryResponse(ranking=[]) + countries = (await session.exec(select(User.country_code).distinct())).all() + for country in countries: + statistics = ( + await session.exec( + select(UserStatistics).where( + UserStatistics.mode == ruleset, + col(UserStatistics.user).has(country_code=country), + ) + ) + ).all() + pp = 0 + country_stats = CountryStatistics( + country_code=country, + active_users=0, + play_count=0, + ranked_score=0, + performance=0, + ) + for stat in statistics: + country_stats.active_users += 1 + country_stats.play_count += stat.play_count + country_stats.ranked_score += stat.ranked_score + pp += stat.pp + country_stats.performance = round(pp) + response.ranking.append(country_stats) + response.ranking.sort(key=lambda x: x.performance, reverse=True) + return response + + +class TopUsersResponse(BaseModel): + ranking: list[UserStatisticsResp] + + @router.get( "/rankings/{ruleset}/{type}", - response_model=list[UserStatisticsResp], - name="获取排行榜", + response_model=TopUsersResponse, + name="获取用户排行榜", description="获取在指定模式下的用户排行榜", tags=["排行榜"], ) @@ -46,7 +106,9 @@ async def get_user_ranking( .limit(50) .offset(50 * (page - 1)) ) - return [ - await UserStatisticsResp.from_db(statistics, session, None) - for statistics in statistics_list - ] + return TopUsersResponse( + ranking=[ + await UserStatisticsResp.from_db(statistics, session, None) + for statistics in statistics_list + ] + )