fix(playlist): fix user attempts

This commit is contained in:
MingxuanGame
2025-08-09 04:53:20 +00:00
parent 3e3cf27acc
commit d7002374b6
5 changed files with 68 additions and 8 deletions

View File

@@ -16,7 +16,11 @@ from .lazer_user import (
UserResp,
)
from .multiplayer_event import MultiplayerEvent, MultiplayerEventResp
from .playlist_attempts import ItemAttemptsCount, ItemAttemptsResp
from .playlist_attempts import (
ItemAttemptsCount,
ItemAttemptsResp,
PlaylistAggregateScore,
)
from .playlist_best_score import PlaylistBestScore
from .playlists import Playlist, PlaylistResp
from .pp_best_score import PPBestScore
@@ -58,6 +62,7 @@ __all__ = [
"OAuthToken",
"PPBestScore",
"Playlist",
"PlaylistAggregateScore",
"PlaylistBestScore",
"PlaylistResp",
"Relationship",

View File

@@ -1,6 +1,7 @@
from .lazer_user import User, UserResp
from .playlist_best_score import PlaylistBestScore
from pydantic import BaseModel
from sqlmodel import (
BigInteger,
Column,
@@ -112,3 +113,39 @@ class ItemAttemptsResp(ItemAttemptsCountBase):
resp.position = await item_attempts.get_position(session)
# resp.accuracy *= 100
return resp
class ItemAttemptsCountForItem(BaseModel):
id: int
attempts: int
passed: bool
class PlaylistAggregateScore(BaseModel):
playlist_item_attempts: list[ItemAttemptsCountForItem] = Field(default_factory=list)
@classmethod
async def from_db(
cls,
room_id: int,
user_id: int,
session: AsyncSession,
) -> "PlaylistAggregateScore":
playlist_scores = (
await session.exec(
select(PlaylistBestScore).where(
PlaylistBestScore.room_id == room_id,
PlaylistBestScore.user_id == user_id,
)
)
).all()
playlist_item_attempts = []
for score in playlist_scores:
playlist_item_attempts.append(
ItemAttemptsCountForItem(
id=score.playlist_id,
attempts=score.attempts,
passed=score.score.passed,
)
)
return cls(playlist_item_attempts=playlist_item_attempts)

View File

@@ -62,20 +62,21 @@ async def process_playlist_best_score(
)
).first()
if previous is None:
score = PlaylistBestScore(
previous = PlaylistBestScore(
user_id=user_id,
score_id=score_id,
room_id=room_id,
playlist_id=playlist_id,
total_score=total_score,
)
session.add(score)
else:
session.add(previous)
elif not previous.score.passed or previous.total_score < total_score:
previous.score_id = score_id
previous.total_score = total_score
previous.attempts += 1
previous.attempts += 1
await session.commit()
await redis.decr(f"multiplayer:{room_id}:gameplay:players")
if await redis.exists(f"multiplayer:{room_id}:gameplay:players"):
await redis.decr(f"multiplayer:{room_id}:gameplay:players")
async def get_position(

View File

@@ -1,5 +1,6 @@
from datetime import UTC, datetime
from app.database.playlist_attempts import PlaylistAggregateScore
from app.models.model import UTCBaseModel
from app.models.multiplayer_hub import ServerMultiplayerRoom
from app.models.room import (
@@ -23,6 +24,7 @@ from sqlmodel import (
Relationship,
SQLModel,
)
from sqlmodel.ext.asyncio.session import AsyncSession
class RoomBase(SQLModel, UTCBaseModel):
@@ -77,9 +79,16 @@ class RoomResp(RoomBase):
playlist_item_stats: RoomPlaylistItemStats | None = None
difficulty_range: RoomDifficultyRange | None = None
current_playlist_item: PlaylistResp | None = None
current_user_score: PlaylistAggregateScore | None = None
@classmethod
async def from_db(cls, room: Room) -> "RoomResp":
async def from_db(
cls,
room: Room,
include: list[str] = [],
session: AsyncSession | None = None,
user: User | None = None,
) -> "RoomResp":
resp = cls.model_validate(room.model_dump())
stats = RoomPlaylistItemStats(count_active=0, count_total=0)
@@ -105,6 +114,10 @@ class RoomResp(RoomBase):
resp.difficulty_range = difficulty_range
resp.current_playlist_item = resp.playlist[-1] if resp.playlist else None
if "current_user_score" in include and user and session:
resp.current_user_score = await PlaylistAggregateScore.from_db(
room.id, user.id, session
)
return resp
@classmethod

View File

@@ -116,13 +116,17 @@ async def get_room(
room: int,
category: str = Query(default=""),
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
redis: Redis = Depends(get_redis),
):
# 直接从db获取信息毕竟都一样
db_room = (await db.exec(select(Room).where(Room.id == room))).first()
if db_room is None:
raise HTTPException(404, "Room not found")
return await RoomResp.from_db(db_room)
resp = await RoomResp.from_db(
db_room, include=["current_user_score"], session=db, user=current_user
)
return resp
@router.delete("/rooms/{room}", tags=["room"])