fix(score): move db only fields to DB model

This commit is contained in:
MingxuanGame
2025-07-25 21:38:51 +08:00
parent 92f8a3a416
commit 2260d9265e
2 changed files with 24 additions and 17 deletions

View File

@@ -6,9 +6,8 @@ from typing import Literal
from app.models.score import Rank from app.models.score import Rank
from .beatmap import Beatmap from .beatmap import Beatmap, BeatmapResp
from .beatmapset import Beatmapset from .beatmapset import Beatmapset, BeatmapsetResp
from .user import User
from pydantic import BaseModel from pydantic import BaseModel
from sqlalchemy import Column, DateTime from sqlalchemy import Column, DateTime
@@ -18,7 +17,6 @@ from sqlmodel import BigInteger, Field, Relationship, SQLModel
class ScoreBase(SQLModel): class ScoreBase(SQLModel):
# 基本字段 # 基本字段
accuracy: float accuracy: float
beatmap_id: int = Field(index=True, foreign_key="_beatmap.id")
map_md5: str = Field(max_length=32, index=True) map_md5: str = Field(max_length=32, index=True)
best_id: int | None = Field(default=None) best_id: int | None = Field(default=None)
build_id: int | None = Field(default=None) build_id: int | None = Field(default=None)
@@ -39,23 +37,10 @@ class ScoreBase(SQLModel):
started_at: datetime = Field(sa_column=Column(DateTime)) started_at: datetime = Field(sa_column=Column(DateTime))
total_score: int = Field(default=0, sa_column=Column(BigInteger)) total_score: int = Field(default=0, sa_column=Column(BigInteger))
type: str type: str
user_id: int = Field(foreign_key="user.id", index=True)
# ScoreStatistics
n300: int = Field(default=0, exclude=True)
n100: int
n50: int
nmiss: int
ngeki: int
nkatu: int
nlarge_tick_miss: int | None = Field(default=None, exclude=True)
nslider_tail_hit: int | None = Field(default=None, exclude=True)
# optional # optional
beatmap: "Beatmap" = Relationship(back_populates="scores")
beatmapset: "Beatmapset" = Relationship(back_populates="scores")
# TODO: current_user_attributes # TODO: current_user_attributes
position: int | None = Field(default=None) # multiplayer position: int | None = Field(default=None) # multiplayer
user: "User" = Relationship(back_populates="scores")
class ScoreStatistics(BaseModel): class ScoreStatistics(BaseModel):
@@ -72,6 +57,22 @@ class ScoreStatistics(BaseModel):
class Score(ScoreBase, table=True): class Score(ScoreBase, table=True):
__tablename__ = "scores" # pyright: ignore[reportAssignmentType] __tablename__ = "scores" # pyright: ignore[reportAssignmentType]
id: int = Field(primary_key=True) id: int = Field(primary_key=True)
beatmap_id: int = Field(index=True, foreign_key="beatmap.id")
user_id: int = Field(foreign_key="user.id", index=True)
# ScoreStatistics
n300: int = Field(exclude=True)
n100: int = Field(exclude=True)
n50: int = Field(exclude=True)
nmiss: int = Field(exclude=True)
ngeki: int = Field(exclude=True)
nkatu: int = Field(exclude=True)
nlarge_tick_miss: int | None = Field(default=None, exclude=True)
nslider_tail_hit: int | None = Field(default=None, exclude=True)
# optional
beatmap: "Beatmap" = Relationship(back_populates="scores")
beatmapset: "Beatmapset" = Relationship(back_populates="scores")
# FIXME: user: "User" = Relationship(back_populates="scores")
class ScoreResp(ScoreBase): class ScoreResp(ScoreBase):
@@ -81,11 +82,16 @@ class ScoreResp(ScoreBase):
legacy_total_score: int = 0 # FIXME legacy_total_score: int = 0 # FIXME
processed: bool = False # solo_score processed: bool = False # solo_score
weight: float = 0.0 weight: float = 0.0
beatmap: BeatmapResp | None = None
beatmapset: BeatmapsetResp | None = None
# FIXME: user: APIUser | None = None
statistics: ScoreStatistics | None = None statistics: ScoreStatistics | None = None
@classmethod @classmethod
def from_db(cls, score: Score) -> "ScoreResp": def from_db(cls, score: Score) -> "ScoreResp":
s = cls.model_validate(score) s = cls.model_validate(score)
s.beatmap = BeatmapResp.from_db(score.beatmap)
s.beatmapset = BeatmapsetResp.from_db(score.beatmap.beatmapset)
s.is_perfect_combo = s.max_combo == s.beatmap.max_combo s.is_perfect_combo = s.max_combo == s.beatmap.max_combo
s.legacy_perfect = s.max_combo == s.beatmap.max_combo s.legacy_perfect = s.max_combo == s.beatmap.max_combo
if score.best_id: if score.best_id:

View File

@@ -19,6 +19,7 @@ MODE_TO_INT = {
GameMode.FRUITS: 2, GameMode.FRUITS: 2,
GameMode.MANIA: 3, GameMode.MANIA: 3,
} }
INT_TO_MODE = {v: k for k, v in MODE_TO_INT.items()}
class Rank(str, Enum): class Rank(str, Enum):