fix(playlist): fix user attempts
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"])
|
||||
|
||||
Reference in New Issue
Block a user