feat(user): support global rank & country rank
This commit is contained in:
87
app/service/calculate_all_user_rank.py
Normal file
87
app/service/calculate_all_user_rank.py
Normal file
@@ -0,0 +1,87 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import UTC, datetime, timedelta
|
||||
|
||||
from app.database import RankHistory, UserStatistics
|
||||
from app.database.rank_history import RankTop
|
||||
from app.dependencies.database import engine
|
||||
from app.dependencies.scheduler import get_scheduler
|
||||
from app.models.score import GameMode
|
||||
|
||||
from sqlmodel import col, exists, select, update
|
||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
|
||||
|
||||
@get_scheduler().scheduled_job(
|
||||
"cron", hour=0, minute=0, second=0, id="calculate_user_rank"
|
||||
)
|
||||
async def calculate_user_rank(is_today: bool = False):
|
||||
today = datetime.now(UTC).date()
|
||||
target_date = today if is_today else today - timedelta(days=1)
|
||||
async with AsyncSession(engine) as session:
|
||||
for gamemode in GameMode:
|
||||
users = await session.exec(
|
||||
select(UserStatistics)
|
||||
.where(
|
||||
UserStatistics.mode == gamemode,
|
||||
UserStatistics.pp > 0,
|
||||
col(UserStatistics.is_ranked).is_(True),
|
||||
)
|
||||
.order_by(
|
||||
col(UserStatistics.pp).desc(),
|
||||
col(UserStatistics.total_score).desc(),
|
||||
)
|
||||
)
|
||||
rank = 1
|
||||
for user in users:
|
||||
is_exist = (
|
||||
await session.exec(
|
||||
select(exists()).where(
|
||||
RankHistory.user_id == user.user_id,
|
||||
RankHistory.mode == gamemode,
|
||||
RankHistory.date == target_date,
|
||||
)
|
||||
)
|
||||
).first()
|
||||
if not is_exist:
|
||||
rank_history = RankHistory(
|
||||
user_id=user.user_id,
|
||||
mode=gamemode,
|
||||
rank=rank,
|
||||
date=today,
|
||||
)
|
||||
session.add(rank_history)
|
||||
else:
|
||||
await session.execute(
|
||||
update(RankHistory)
|
||||
.where(
|
||||
col(RankHistory.user_id) == user.user_id,
|
||||
col(RankHistory.mode) == gamemode,
|
||||
col(RankHistory.date) == target_date,
|
||||
)
|
||||
.values(rank=rank)
|
||||
)
|
||||
|
||||
rank_top = (
|
||||
await session.exec(
|
||||
select(RankTop).where(
|
||||
RankTop.user_id == user.user_id,
|
||||
RankTop.mode == gamemode,
|
||||
)
|
||||
)
|
||||
).first()
|
||||
if not rank_top:
|
||||
rank_top = RankTop(
|
||||
user_id=user.user_id,
|
||||
mode=gamemode,
|
||||
rank=rank,
|
||||
date=today,
|
||||
)
|
||||
session.add(rank_top)
|
||||
else:
|
||||
if rank_top.rank > rank:
|
||||
rank_top.rank = rank
|
||||
rank_top.date = today
|
||||
|
||||
rank += 1
|
||||
await session.commit()
|
||||
Reference in New Issue
Block a user