refactor(task): move schedulers and startup/shutdown task into tasks directory
This commit is contained in:
100
app/tasks/calculate_all_user_rank.py
Normal file
100
app/tasks/calculate_all_user_rank.py
Normal file
@@ -0,0 +1,100 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import 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.log import logger
|
||||
from app.models.score import GameMode
|
||||
from app.utils import utcnow
|
||||
|
||||
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 = utcnow().date()
|
||||
target_date = today if is_today else today - timedelta(days=1)
|
||||
logger.info("Starting user rank calculation for {}", target_date)
|
||||
async with with_db() as session:
|
||||
for gamemode in GameMode:
|
||||
logger.info("Calculating ranks for {} on {}", gamemode.name, target_date)
|
||||
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
|
||||
processed_users = 0
|
||||
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
|
||||
processed_users += 1
|
||||
await session.commit()
|
||||
if processed_users > 0:
|
||||
logger.info(
|
||||
"Updated ranks for {} on {} ({} users)",
|
||||
gamemode.name,
|
||||
target_date,
|
||||
processed_users,
|
||||
)
|
||||
else:
|
||||
logger.info("No users found for {} on {}", gamemode.name, target_date)
|
||||
logger.success("User rank calculation completed for {}", target_date)
|
||||
Reference in New Issue
Block a user