feat(user): support get the user's first scores
This commit is contained in:
@@ -2,6 +2,7 @@ from datetime import datetime, timedelta
|
|||||||
import json
|
import json
|
||||||
from typing import TYPE_CHECKING, NotRequired, TypedDict
|
from typing import TYPE_CHECKING, NotRequired, TypedDict
|
||||||
|
|
||||||
|
from app.config import settings
|
||||||
from app.models.model import UTCBaseModel
|
from app.models.model import UTCBaseModel
|
||||||
from app.models.score import GameMode
|
from app.models.score import GameMode
|
||||||
from app.models.user import Country, Page
|
from app.models.user import Country, Page
|
||||||
@@ -223,7 +224,7 @@ class UserResp(UserBase):
|
|||||||
follower_count: int = 0
|
follower_count: int = 0
|
||||||
friends: list["RelationshipResp"] | None = None
|
friends: list["RelationshipResp"] | None = None
|
||||||
scores_best_count: int = 0
|
scores_best_count: int = 0
|
||||||
scores_first_count: int = 0 # TODO
|
scores_first_count: int = 0
|
||||||
scores_recent_count: int = 0
|
scores_recent_count: int = 0
|
||||||
scores_pinned_count: int = 0
|
scores_pinned_count: int = 0
|
||||||
beatmap_playcounts_count: int = 0
|
beatmap_playcounts_count: int = 0
|
||||||
@@ -261,7 +262,7 @@ class UserResp(UserBase):
|
|||||||
from .favourite_beatmapset import FavouriteBeatmapset
|
from .favourite_beatmapset import FavouriteBeatmapset
|
||||||
from .pp_best_score import PPBestScore
|
from .pp_best_score import PPBestScore
|
||||||
from .relationship import Relationship, RelationshipResp, RelationshipType
|
from .relationship import Relationship, RelationshipResp, RelationshipType
|
||||||
from .score import Score
|
from .score import Score, get_user_first_score_count
|
||||||
|
|
||||||
ruleset = ruleset or obj.playmode
|
ruleset = ruleset or obj.playmode
|
||||||
|
|
||||||
@@ -409,6 +410,7 @@ class UserResp(UserBase):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
).one()
|
).one()
|
||||||
|
u.scores_first_count = await get_user_first_score_count(session, obj.id, ruleset)
|
||||||
u.beatmap_playcounts_count = (
|
u.beatmap_playcounts_count = (
|
||||||
await session.exec(
|
await session.exec(
|
||||||
select(func.count())
|
select(func.count())
|
||||||
@@ -421,7 +423,6 @@ class UserResp(UserBase):
|
|||||||
|
|
||||||
# 检查会话验证状态
|
# 检查会话验证状态
|
||||||
# 如果邮件验证功能被禁用,则始终设置 session_verified 为 true
|
# 如果邮件验证功能被禁用,则始终设置 session_verified 为 true
|
||||||
from app.config import settings
|
|
||||||
|
|
||||||
if not settings.enable_email_verification:
|
if not settings.enable_email_verification:
|
||||||
u.session_verified = True
|
u.session_verified = True
|
||||||
|
|||||||
@@ -570,6 +570,64 @@ async def get_user_best_score_with_mod_in_beatmap(
|
|||||||
).first()
|
).first()
|
||||||
|
|
||||||
|
|
||||||
|
async def get_user_first_scores(
|
||||||
|
session: AsyncSession, user_id: int, mode: GameMode, limit: int = 5, offset: int = 0
|
||||||
|
) -> list[BestScore]:
|
||||||
|
rownum = (
|
||||||
|
func.row_number()
|
||||||
|
.over(
|
||||||
|
partition_by=(col(BestScore.beatmap_id), col(BestScore.gamemode)),
|
||||||
|
order_by=col(BestScore.total_score).desc(),
|
||||||
|
)
|
||||||
|
.label("rn")
|
||||||
|
)
|
||||||
|
|
||||||
|
# Step 1: Fetch top score_ids in Python
|
||||||
|
subq = (
|
||||||
|
select(
|
||||||
|
col(BestScore.score_id).label("score_id"),
|
||||||
|
col(BestScore.user_id).label("user_id"),
|
||||||
|
rownum,
|
||||||
|
)
|
||||||
|
.where(col(BestScore.gamemode) == mode)
|
||||||
|
.subquery()
|
||||||
|
)
|
||||||
|
|
||||||
|
top_ids_stmt = select(subq.c.score_id).where(subq.c.rn == 1, subq.c.user_id == user_id).limit(limit).offset(offset)
|
||||||
|
|
||||||
|
top_ids = await session.exec(top_ids_stmt)
|
||||||
|
top_ids = list(top_ids)
|
||||||
|
|
||||||
|
stmt = select(BestScore).where(col(BestScore.score_id).in_(top_ids)).order_by(col(BestScore.total_score).desc())
|
||||||
|
|
||||||
|
result = await session.exec(stmt)
|
||||||
|
return list(result.all())
|
||||||
|
|
||||||
|
|
||||||
|
async def get_user_first_score_count(session: AsyncSession, user_id: int, mode: GameMode) -> int:
|
||||||
|
rownum = (
|
||||||
|
func.row_number()
|
||||||
|
.over(
|
||||||
|
partition_by=(col(BestScore.beatmap_id), col(BestScore.gamemode)),
|
||||||
|
order_by=col(BestScore.total_score).desc(),
|
||||||
|
)
|
||||||
|
.label("rn")
|
||||||
|
)
|
||||||
|
subq = (
|
||||||
|
select(
|
||||||
|
col(BestScore.score_id).label("score_id"),
|
||||||
|
col(BestScore.user_id).label("user_id"),
|
||||||
|
rownum,
|
||||||
|
)
|
||||||
|
.where(col(BestScore.gamemode) == mode)
|
||||||
|
.subquery()
|
||||||
|
)
|
||||||
|
count_stmt = select(func.count()).where(subq.c.rn == 1, subq.c.user_id == user_id)
|
||||||
|
|
||||||
|
result = await session.exec(count_stmt)
|
||||||
|
return result.one()
|
||||||
|
|
||||||
|
|
||||||
async def get_user_best_pp_in_beatmap(
|
async def get_user_best_pp_in_beatmap(
|
||||||
session: AsyncSession,
|
session: AsyncSession,
|
||||||
beatmap: int,
|
beatmap: int,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ from app.database import (
|
|||||||
from app.database.events import Event
|
from app.database.events import Event
|
||||||
from app.database.lazer_user import SEARCH_INCLUDED
|
from app.database.lazer_user import SEARCH_INCLUDED
|
||||||
from app.database.pp_best_score import PPBestScore
|
from app.database.pp_best_score import PPBestScore
|
||||||
from app.database.score import Score, ScoreResp
|
from app.database.score import Score, ScoreResp, get_user_first_scores
|
||||||
from app.dependencies.database import Database, get_redis
|
from app.dependencies.database import Database, get_redis
|
||||||
from app.dependencies.user import get_current_user
|
from app.dependencies.user import get_current_user
|
||||||
from app.log import logger
|
from app.log import logger
|
||||||
@@ -360,14 +360,17 @@ async def get_user_scores(
|
|||||||
where_clause &= Score.ended_at > utcnow() - timedelta(hours=24)
|
where_clause &= Score.ended_at > utcnow() - timedelta(hours=24)
|
||||||
order_by = col(Score.ended_at).desc()
|
order_by = col(Score.ended_at).desc()
|
||||||
elif type == "firsts":
|
elif type == "firsts":
|
||||||
# TODO
|
|
||||||
where_clause &= false()
|
where_clause &= false()
|
||||||
|
|
||||||
scores = (
|
if type != "firsts":
|
||||||
await session.exec(select(Score).where(where_clause).order_by(order_by).limit(limit).offset(offset))
|
scores = (
|
||||||
).all()
|
await session.exec(select(Score).where(where_clause).order_by(order_by).limit(limit).offset(offset))
|
||||||
if not scores:
|
).all()
|
||||||
return []
|
if not scores:
|
||||||
|
return []
|
||||||
|
else:
|
||||||
|
best_scores = await get_user_first_scores(session, db_user.id, gamemode, limit)
|
||||||
|
scores = [best_score.score for best_score in best_scores]
|
||||||
|
|
||||||
score_responses = [
|
score_responses = [
|
||||||
await ScoreResp.from_db(
|
await ScoreResp.from_db(
|
||||||
|
|||||||
Reference in New Issue
Block a user