Files
g0v0-server/app/service/calculate_all_user_rank.py
2025-08-22 08:21:52 +00:00

85 lines
3.1 KiB
Python

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 with_db
from app.dependencies.scheduler import get_scheduler
from app.models.score import GameMode
from sqlmodel import col, exists, select, update
@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 with_db() 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()