from __future__ import annotations from typing import Any from pydantic import BaseModel, Field, field_validator from .models import ALLOWED_DIFFICULTIES, ALLOWED_PUZZLES class CreateSessionRequest(BaseModel): player_name: str = Field(min_length=1, max_length=80) puzzle_type: str difficulty: str puzzle_id: str | None = Field(default=None, min_length=1) @field_validator("puzzle_type") @classmethod def validate_puzzle_type(cls, value: str) -> str: if value not in ALLOWED_PUZZLES: raise ValueError(f"Unsupported puzzle type: {value}") return value @field_validator("difficulty") @classmethod def validate_difficulty(cls, value: str) -> str: if value not in ALLOWED_DIFFICULTIES: raise ValueError(f"Unsupported difficulty: {value}") return value class SubmitSessionRequest(BaseModel): board_ascii: str = Field(min_length=1) class SessionPayload(BaseModel): problem_ascii: str current_board_ascii: str image_base64: str | None = None class PuzzleOptionResponse(BaseModel): puzzle_id: str title: str sequence: int puzzle_type: str difficulty: str args: str class SessionResponse(BaseModel): session_id: str engine: str puzzle_type: str difficulty: str puzzle_id: str args: str status: str started_at: str | None = None payload: SessionPayload class SubmitResponse(BaseModel): solved: bool elapsed_ms: int | None status: str verification: dict[str, Any] class LLMResultsResponse(BaseModel): puzzle_id: str models_solved: list[str] models_failed: list[str] class LeaderboardEntry(BaseModel): player_name: str elapsed_ms: int | None submission_count: int solved: bool started_at: str | None submitted_at: str | None class LeaderboardResponse(BaseModel): puzzle_id: str entries: list[LeaderboardEntry]