feat(ranking): support country leaderboard
This commit is contained in:
@@ -11,14 +11,74 @@ from app.models.score import GameMode
|
|||||||
from .router import router
|
from .router import router
|
||||||
|
|
||||||
from fastapi import Depends, Path, Query, Security
|
from fastapi import Depends, Path, Query, Security
|
||||||
|
from pydantic import BaseModel
|
||||||
from sqlmodel import col, select
|
from sqlmodel import col, select
|
||||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
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(
|
@router.get(
|
||||||
"/rankings/{ruleset}/{type}",
|
"/rankings/{ruleset}/{type}",
|
||||||
response_model=list[UserStatisticsResp],
|
response_model=TopUsersResponse,
|
||||||
name="获取排行榜",
|
name="获取用户排行榜",
|
||||||
description="获取在指定模式下的用户排行榜",
|
description="获取在指定模式下的用户排行榜",
|
||||||
tags=["排行榜"],
|
tags=["排行榜"],
|
||||||
)
|
)
|
||||||
@@ -46,7 +106,9 @@ async def get_user_ranking(
|
|||||||
.limit(50)
|
.limit(50)
|
||||||
.offset(50 * (page - 1))
|
.offset(50 * (page - 1))
|
||||||
)
|
)
|
||||||
return [
|
return TopUsersResponse(
|
||||||
await UserStatisticsResp.from_db(statistics, session, None)
|
ranking=[
|
||||||
for statistics in statistics_list
|
await UserStatisticsResp.from_db(statistics, session, None)
|
||||||
]
|
for statistics in statistics_list
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user