feat(score): support download replay

This commit is contained in:
MingxuanGame
2025-08-11 08:19:05 +00:00
parent 680c7525b8
commit b9babb8f24
7 changed files with 198 additions and 17 deletions

View File

@@ -10,6 +10,11 @@ from .beatmapset import (
BeatmapsetResp as BeatmapsetResp,
)
from .best_score import BestScore
from .counts import (
CountResp,
MonthlyPlaycounts,
ReplayWatchedCount,
)
from .daily_challenge import DailyChallengeStats, DailyChallengeStatsResp
from .favourite_beatmapset import FavouriteBeatmapset
from .lazer_user import (
@@ -56,11 +61,13 @@ __all__ = [
"Beatmapset",
"BeatmapsetResp",
"BestScore",
"CountResp",
"DailyChallengeStats",
"DailyChallengeStatsResp",
"FavouriteBeatmapset",
"ItemAttemptsCount",
"ItemAttemptsResp",
"MonthlyPlaycounts",
"MultiplayerEvent",
"MultiplayerEventResp",
"MultiplayerScores",
@@ -73,6 +80,7 @@ __all__ = [
"Relationship",
"RelationshipResp",
"RelationshipType",
"ReplayWatchedCount",
"Room",
"RoomParticipatedUser",
"RoomResp",

View File

@@ -14,7 +14,13 @@ if TYPE_CHECKING:
from .lazer_user import User
class MonthlyPlaycounts(SQLModel, table=True):
class CountBase(SQLModel):
year: int = Field(index=True)
month: int = Field(index=True)
count: int = Field(default=0)
class MonthlyPlaycounts(CountBase, table=True):
__tablename__ = "monthly_playcounts" # pyright: ignore[reportAssignmentType]
id: int | None = Field(
@@ -24,20 +30,29 @@ class MonthlyPlaycounts(SQLModel, table=True):
user_id: int = Field(
sa_column=Column(BigInteger, ForeignKey("lazer_users.id"), index=True)
)
year: int = Field(index=True)
month: int = Field(index=True)
playcount: int = Field(default=0)
user: "User" = Relationship(back_populates="monthly_playcounts")
class MonthlyPlaycountsResp(SQLModel):
class ReplayWatchedCount(CountBase, table=True):
__tablename__ = "replays_watched_counts" # pyright: ignore[reportAssignmentType]
id: int | None = Field(
default=None,
sa_column=Column(BigInteger, primary_key=True, autoincrement=True),
)
user_id: int = Field(
sa_column=Column(BigInteger, ForeignKey("lazer_users.id"), index=True)
)
user: "User" = Relationship(back_populates="replays_watched_counts")
class CountResp(SQLModel):
start_date: date
count: int
@classmethod
def from_db(cls, db_model: MonthlyPlaycounts) -> "MonthlyPlaycountsResp":
def from_db(cls, db_model: CountBase) -> "CountResp":
return cls(
start_date=date(db_model.year, db_model.month, 1),
count=db_model.playcount,
count=db_model.count,
)

View File

@@ -7,8 +7,8 @@ from app.models.user import Country, Page, RankHistory
from .achievement import UserAchievement, UserAchievementResp
from .beatmap_playcounts import BeatmapPlaycounts
from .counts import CountResp, MonthlyPlaycounts, ReplayWatchedCount
from .daily_challenge import DailyChallengeStats, DailyChallengeStatsResp
from .monthly_playcounts import MonthlyPlaycounts, MonthlyPlaycountsResp
from .statistics import UserStatistics, UserStatisticsResp
from .team import Team, TeamMember
from .user_account_history import UserAccountHistory, UserAccountHistoryResp
@@ -76,7 +76,6 @@ class UserBase(UTCBaseModel, SQLModel):
username: str = Field(max_length=32, unique=True, index=True)
page: Page = Field(sa_column=Column(JSON), default=Page(html="", raw=""))
previous_usernames: list[str] = Field(default_factory=list, sa_column=Column(JSON))
# TODO: replays_watched_counts
support_level: int = 0
badges: list[Badge] = Field(default_factory=list, sa_column=Column(JSON))
@@ -146,6 +145,9 @@ class User(AsyncAttrs, UserBase, table=True):
back_populates="user"
)
monthly_playcounts: list[MonthlyPlaycounts] = Relationship(back_populates="user")
replays_watched_counts: list[ReplayWatchedCount] = Relationship(
back_populates="user"
)
favourite_beatmapsets: list["FavouriteBeatmapset"] = Relationship(
back_populates="user"
)
@@ -185,7 +187,8 @@ class UserResp(UserBase):
account_history: list[UserAccountHistoryResp] = []
active_tournament_banners: list[dict] = [] # TODO
kudosu: Kudosu = Field(default_factory=lambda: Kudosu(available=0, total=0)) # TODO
monthly_playcounts: list[MonthlyPlaycountsResp] = Field(default_factory=list)
monthly_playcounts: list[CountResp] = Field(default_factory=list)
replay_watched_counts: list[CountResp] = Field(default_factory=list)
unread_pm_count: int = 0 # TODO
rank_history: RankHistory | None = None # TODO
rank_highest: RankHighest | None = None # TODO
@@ -299,10 +302,16 @@ class UserResp(UserBase):
if "monthly_playcounts" in include:
u.monthly_playcounts = [
MonthlyPlaycountsResp.from_db(pc)
CountResp.from_db(pc)
for pc in await obj.awaitable_attrs.monthly_playcounts
]
if "replays_watched_counts" in include:
u.replay_watched_counts = [
CountResp.from_db(rwc)
for rwc in await obj.awaitable_attrs.replays_watched_counts
]
if "achievements" in include:
u.user_achievements = [
UserAchievementResp.from_db(ua)
@@ -373,6 +382,7 @@ ALL_INCLUDED = [
"statistics_rulesets",
"achievements",
"monthly_playcounts",
"replays_watched_counts",
]
@@ -383,6 +393,7 @@ SEARCH_INCLUDED = [
"statistics_rulesets",
"achievements",
"monthly_playcounts",
"replays_watched_counts",
]
BASE_INCLUDES = [

View File

@@ -37,8 +37,8 @@ from .beatmap import Beatmap, BeatmapResp
from .beatmap_playcounts import process_beatmap_playcount
from .beatmapset import BeatmapsetResp
from .best_score import BestScore
from .counts import MonthlyPlaycounts
from .lazer_user import User, UserResp
from .monthly_playcounts import MonthlyPlaycounts
from .pp_best_score import PPBestScore
from .relationship import (
Relationship as DBRelationship,
@@ -612,7 +612,7 @@ async def process_user(
)
)
statistics.play_count += 1
mouthly_playcount.playcount += 1
mouthly_playcount.count += 1
statistics.play_time += length
statistics.count_100 += score.n100 + score.nkatu
statistics.count_300 += score.n300 + score.ngeki