feat(user): support view recent & best scores
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
from datetime import UTC, datetime
|
||||
from datetime import UTC, datetime, timedelta
|
||||
from typing import TYPE_CHECKING, NotRequired, TypedDict
|
||||
|
||||
from app.models.model import UTCBaseModel
|
||||
@@ -6,6 +6,7 @@ from app.models.score import GameMode
|
||||
from app.models.user import Country, Page, RankHistory
|
||||
|
||||
from .achievement import UserAchievement, UserAchievementResp
|
||||
from .beatmap_playcounts import BeatmapPlaycounts
|
||||
from .daily_challenge import DailyChallengeStats, DailyChallengeStatsResp
|
||||
from .monthly_playcounts import MonthlyPlaycounts, MonthlyPlaycountsResp
|
||||
from .statistics import UserStatistics, UserStatisticsResp
|
||||
@@ -21,6 +22,7 @@ from sqlmodel import (
|
||||
Field,
|
||||
Relationship,
|
||||
SQLModel,
|
||||
col,
|
||||
func,
|
||||
select,
|
||||
)
|
||||
@@ -164,7 +166,7 @@ class UserResp(UserBase):
|
||||
is_online: bool = False
|
||||
groups: list = [] # TODO
|
||||
country: Country = Field(default_factory=lambda: Country(code="CN", name="China"))
|
||||
favourite_beatmapset_count: int = 0 # TODO
|
||||
favourite_beatmapset_count: int = 0
|
||||
graveyard_beatmapset_count: int = 0 # TODO
|
||||
guest_beatmapset_count: int = 0 # TODO
|
||||
loved_beatmapset_count: int = 0 # TODO
|
||||
@@ -176,9 +178,10 @@ class UserResp(UserBase):
|
||||
follower_count: int = 0
|
||||
friends: list["RelationshipResp"] | None = None
|
||||
scores_best_count: int = 0
|
||||
scores_first_count: int = 0
|
||||
scores_first_count: int = 0 # TODO
|
||||
scores_recent_count: int = 0
|
||||
scores_pinned_count: int = 0
|
||||
beatmap_playcounts_count: int = 0
|
||||
account_history: list[UserAccountHistoryResp] = []
|
||||
active_tournament_banners: list[dict] = [] # TODO
|
||||
kudosu: Kudosu = Field(default_factory=lambda: Kudosu(available=0, total=0)) # TODO
|
||||
@@ -207,7 +210,11 @@ class UserResp(UserBase):
|
||||
from app.dependencies.database import get_redis
|
||||
|
||||
from .best_score import BestScore
|
||||
from .favourite_beatmapset import FavouriteBeatmapset
|
||||
from .relationship import Relationship, RelationshipResp, RelationshipType
|
||||
from .score import Score
|
||||
|
||||
ruleset = ruleset or obj.playmode
|
||||
|
||||
u = cls.model_validate(obj.model_dump())
|
||||
u.id = obj.id
|
||||
@@ -275,7 +282,7 @@ class UserResp(UserBase):
|
||||
if "statistics" in include:
|
||||
current_stattistics = None
|
||||
for i in await obj.awaitable_attrs.statistics:
|
||||
if i.mode == (ruleset or obj.playmode):
|
||||
if i.mode == ruleset:
|
||||
current_stattistics = i
|
||||
break
|
||||
u.statistics = (
|
||||
@@ -302,6 +309,58 @@ class UserResp(UserBase):
|
||||
for ua in await obj.awaitable_attrs.achievement
|
||||
]
|
||||
|
||||
u.favourite_beatmapset_count = (
|
||||
await session.exec(
|
||||
select(func.count())
|
||||
.select_from(FavouriteBeatmapset)
|
||||
.where(FavouriteBeatmapset.user_id == obj.id)
|
||||
)
|
||||
).one()
|
||||
u.scores_pinned_count = (
|
||||
await session.exec(
|
||||
select(func.count())
|
||||
.select_from(Score)
|
||||
.where(
|
||||
Score.user_id == obj.id,
|
||||
Score.pinned_order > 0,
|
||||
Score.gamemode == ruleset,
|
||||
col(Score.passed).is_(True),
|
||||
)
|
||||
)
|
||||
).one()
|
||||
u.scores_best_count = (
|
||||
await session.exec(
|
||||
select(func.count())
|
||||
.select_from(BestScore)
|
||||
.where(
|
||||
BestScore.user_id == obj.id,
|
||||
BestScore.gamemode == ruleset,
|
||||
)
|
||||
.limit(200)
|
||||
)
|
||||
).one()
|
||||
u.scores_recent_count = (
|
||||
await session.exec(
|
||||
select(func.count())
|
||||
.select_from(Score)
|
||||
.where(
|
||||
Score.user_id == obj.id,
|
||||
Score.gamemode == ruleset,
|
||||
col(Score.passed).is_(True),
|
||||
Score.ended_at > datetime.now(UTC) - timedelta(hours=24),
|
||||
)
|
||||
)
|
||||
).one()
|
||||
u.beatmap_playcounts_count = (
|
||||
await session.exec(
|
||||
select(func.count())
|
||||
.select_from(BeatmapPlaycounts)
|
||||
.where(
|
||||
BeatmapPlaycounts.user_id == obj.id,
|
||||
)
|
||||
)
|
||||
).one()
|
||||
|
||||
return u
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import UTC, datetime, timedelta
|
||||
from typing import Literal
|
||||
|
||||
from app.database import (
|
||||
@@ -10,6 +11,7 @@ from app.database import (
|
||||
UserResp,
|
||||
)
|
||||
from app.database.lazer_user import SEARCH_INCLUDED
|
||||
from app.database.pp_best_score import PPBestScore
|
||||
from app.database.score import Score, ScoreResp
|
||||
from app.dependencies.database import get_db
|
||||
from app.dependencies.user import get_current_user
|
||||
@@ -20,7 +22,7 @@ from .api_router import router
|
||||
|
||||
from fastapi import Depends, HTTPException, Query
|
||||
from pydantic import BaseModel
|
||||
from sqlmodel import false, select
|
||||
from sqlmodel import exists, false, select
|
||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
from sqlmodel.sql.expression import col
|
||||
|
||||
@@ -152,15 +154,19 @@ async def get_user_scores(
|
||||
|
||||
gamemode = mode or db_user.playmode
|
||||
order_by = None
|
||||
where_clause = (
|
||||
(col(Score.user_id) == db_user.id)
|
||||
& (col(Score.gamemode) == gamemode)
|
||||
& (col(Score.passed).is_(True))
|
||||
where_clause = (col(Score.user_id) == db_user.id) & (
|
||||
col(Score.gamemode) == gamemode
|
||||
)
|
||||
if not include_fails:
|
||||
where_clause &= col(Score.passed).is_(True)
|
||||
if type == "pinned":
|
||||
where_clause &= Score.pinned_order > 0
|
||||
order_by = col(Score.pinned_order).asc()
|
||||
else:
|
||||
elif type == "best":
|
||||
where_clause &= exists().where(col(PPBestScore.score_id) == Score.id)
|
||||
elif type == "recent":
|
||||
where_clause &= Score.ended_at > datetime.now(UTC) - timedelta(hours=24)
|
||||
elif type == "firsts":
|
||||
# TODO
|
||||
where_clause &= false()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user