from __future__ import annotations import datetime as dt from typing import Any, Dict, List, Optional from pydantic import BaseModel, Field class ActionSchema(BaseModel): type: str payload: Dict[str, Any] = Field(default_factory=dict) class ActionLogSchema(BaseModel): idx: int ts: dt.datetime actor: str action: ActionSchema applied: bool = True meta: Dict[str, Any] = Field(default_factory=dict) class TradeOfferSchema(BaseModel): id: str from_player: str to_player: Optional[str] = None offer: Dict[str, int] request: Dict[str, int] status: str created_at: dt.datetime class GameSlotSchema(BaseModel): slot_id: int name: Optional[str] = None user_id: Optional[int] = None is_ai: bool = False ai_kind: Optional[str] = None ai_model: Optional[str] = None ready: bool = False color: Optional[str] = None class GameSummarySchema(BaseModel): id: str name: str status: str max_players: int created_by: str created_at: dt.datetime players: List[GameSlotSchema] class GameStateSchema(BaseModel): id: str name: str status: str max_players: int created_by: str created_at: dt.datetime players: List[GameSlotSchema] game: Optional[Dict[str, Any]] = None board: Optional[Dict[str, Any]] = None legal_actions: List[ActionSchema] = Field(default_factory=list) pending_trades: List[TradeOfferSchema] = Field(default_factory=list) history: List[ActionLogSchema] = Field(default_factory=list) class CreateGameRequest(BaseModel): name: str max_players: int created_by: Optional[str] = None class JoinGameRequest(BaseModel): username: str user_id: int class AddAIRequest(BaseModel): ai_type: str model_name: Optional[str] = None class TradeOfferRequest(BaseModel): from_player: str to_player: Optional[str] = None offer: Dict[str, int] request: Dict[str, int] class TradeRespondRequest(BaseModel): player: str accept: bool class ActionRequest(BaseModel): actor: str action: ActionSchema class AIRequest(BaseModel): observation: Dict[str, Any] legal_actions: List[ActionSchema] agent: Dict[str, Any] debug: bool = False class AIResponse(BaseModel): action: ActionSchema debug: Dict[str, Any] = Field(default_factory=dict) class ReplayMeta(BaseModel): id: str created_at: dt.datetime players: List[str] winner: Optional[str] = None total_actions: int class ReplayDetail(ReplayMeta): seed: int actions: List[ActionLogSchema] class ReplayArchive(BaseModel): version: int = 1 id: str created_at: dt.datetime seed: int players: List[str] winner: Optional[str] = None slots: List[GameSlotSchema] actions: List[ActionLogSchema]