"""Pydantic models for API requests and responses.""" from __future__ import annotations from enum import Enum from typing import Any from pydantic import BaseModel, Field class GameStatus(str, Enum): """Game status.""" IN_PROGRESS = "in_progress" WHITE_WINS = "white_wins" BLACK_WINS = "black_wins" DRAW = "draw" ABORTED = "aborted" class Color(str, Enum): """Chess colors.""" WHITE = "white" BLACK = "black" class GameMode(str, Enum): """Game modes.""" SINGLEPLAYER = "singleplayer" LOCAL_MULTIPLAYER = "local_multiplayer" ONLINE_MULTIPLAYER = "online_multiplayer" class DifficultyLevel(str, Enum): """Engine difficulty levels.""" BEGINNER_1 = "beginner_1" BEGINNER_2 = "beginner_2" INTERMEDIATE = "intermediate" ADVANCED = "advanced" MASTER = "master" class MoveClassification(str, Enum): """Move quality classification.""" BEST = "best" GREAT = "great" GOOD = "good" INACCURACY = "inaccuracy" MISTAKE = "mistake" BLUNDER = "blunder" BOOK = "book" BRILLIANT = "brilliant" class NewGameRequest(BaseModel): """Request to create a new game.""" player_color: Color = Field(default=Color.WHITE, description="Player's color") difficulty: DifficultyLevel = Field( default=DifficultyLevel.INTERMEDIATE, description="Engine difficulty level" ) mode: GameMode = Field( default=GameMode.SINGLEPLAYER, description="Game mode" ) class NewGameResponse(BaseModel): """Response for new game creation.""" game_id: str status: GameStatus player_color: Color engine_color: Color | None difficulty: DifficultyLevel mode: GameMode fen: str board_state: dict[str, Any] is_player_turn: bool class MakeMoveRequest(BaseModel): """Request to make a move.""" move: str = Field(..., description="Move in UCI format (e.g., 'e2e4')") class MakeMoveResponse(BaseModel): """Response for making a move.""" game_id: str status: GameStatus fen: str board_state: dict[str, Any] is_player_turn: bool is_check: bool is_checkmate: bool is_stalemate: bool is_game_over: bool engine_move: str | None = None move_count: int class GameResponse(BaseModel): """Response for game state.""" game_id: str status: GameStatus player_color: Color engine_color: Color | None difficulty: DifficultyLevel mode: GameMode fen: str board_state: dict[str, Any] is_player_turn: bool is_check: bool is_checkmate: bool is_stalemate: bool is_game_over: bool move_count: int opening_name: str | None = None result: str | None = None class AnalyzeGameRequest(BaseModel): """Request to analyze a game.""" depth: int = Field(default=15, ge=1, le=30, description="Analysis depth") class MoveEvaluation(BaseModel): """Move evaluation result.""" move: str san: str | None = None move_number: int turn: Color classification: MoveClassification color: str centipawn_loss: float evaluation_before: dict[str, Any] evaluation_after: dict[str, Any] | None = None best_move: str | None = None class GameAnalysisResponse(BaseModel): """Response for game analysis.""" game_id: str analysis_date: str total_moves: int player_color: Color evaluations: list[MoveEvaluation] summary: dict[str, Any] player_summary: dict[str, Any] critical_moments: list[dict[str, Any]] best_moves: list[dict[str, Any]] accuracy: float player_accuracy: float average_centipawn_loss: float player_average_loss: float evaluation_graph: list[dict[str, Any]] phase_analysis: dict[str, Any] class ProfileResponse(BaseModel): """Response for player profile.""" profile_id: str games_played: int wins: int losses: int draws: int win_rate: float total_moves: int accuracy: float average_centipawn_loss: float opening_accuracy: float middlegame_accuracy: float endgame_accuracy: float opening_performance: dict[str, Any] strengths: list[str] weaknesses: list[str] recommendations: list[str] rating_estimate: int last_updated: str | None = None class GameHistoryResponse(BaseModel): """Response for game history.""" games: list[dict[str, Any]] total: int statistics: dict[str, Any] class ErrorResponse(BaseModel): """Error response.""" error: str detail: str | None = None class Theme(str, Enum): """Board themes.""" WOODEN = "wooden" SIMPLE = "simple" class BoardThemeResponse(BaseModel): """Response for board theme.""" theme: Theme colors: dict[str, str] class PositionAnalysisRequest(BaseModel): """Request to analyze a position.""" fen: str depth: int = Field(default=15, ge=1, le=30) class PositionAnalysisResponse(BaseModel): """Response for position analysis.""" fen: str best_move: str | None evaluation: dict[str, Any] top_moves: list[dict[str, Any]] depth: int