Phase 5: Complete Core Game Engine implementation

- Added MTGOnlineGame, GamePlayer, GameHistory models
- Implemented full game CRUD endpoints (create, list, get, join, leave, start, end)
- Integrated WebSocket game server with database persistence
- Added Commander deck validation service (100-card min, color identity, ban list)
- Created Alembic migration 006 for new game tables
- All game endpoints now database-backed (no more stubs)
This commit is contained in:
2026-08-27 05:29:38 +00:00
parent 0e6506d97f
commit e9f5377e0a
9 changed files with 1057 additions and 102 deletions
+57 -8
View File
@@ -142,26 +142,75 @@ class FolderResponse(BaseModel):
class GameCreate(BaseModel):
"""Game creation request."""
room_id: int
game_type: Optional[str] = None
game_type: str = Field("Commander", pattern="^(Commander|Standard|Modern|Pauper)$")
max_players: int = Field(4, ge=2, le=10)
is_password_protected: bool = False
description: Optional[str] = None
password: Optional[str] = None
class GameUpdate(BaseModel):
"""Game update request."""
game_type: Optional[str] = Field(None, pattern="^(Commander|Standard|Modern|Pauper)$")
max_players: Optional[int] = Field(None, ge=2, le=10)
is_password_protected: Optional[bool] = None
class GamePlayerResponse(BaseModel):
"""Game player response."""
id: int
game_id: int
user_id: int
seat_number: Optional[int]
life_total: int
is_ready: bool
is_host: bool
joined_at: datetime
model_config = ConfigDict(from_attributes=True)
class GameResponse(BaseModel):
"""Game response payload."""
id: int
room_id: int
game_type: Optional[str]
description: Optional[str]
with_password: bool
host_id: int
game_type: str
state: str
is_password_protected: bool
max_players: int
player_count: int
started: bool
creation_date: datetime
current_players: int
created_at: datetime
started_at: Optional[datetime] = None
finished_at: Optional[datetime] = None
players: List[GamePlayerResponse] = []
model_config = ConfigDict(from_attributes=True)
class GameHistoryResponse(BaseModel):
"""Game history response."""
id: int
game_id: Optional[int] = None
room_id: Optional[int] = None
game_type: str
winner_id: Optional[int] = None
duration_seconds: Optional[int] = None
result_type: Optional[str] = None
replay_data: Optional[dict] = None
created_at: datetime
model_config = ConfigDict(from_attributes=True)
class GameJoinResponse(BaseModel):
"""Game join/leave response."""
message: str
game_id: int
player_id: int
current_players: int
max_players: int
# ===== Room Schemas =====
class RoomResponse(BaseModel):