239 lines
15 KiB
Python
239 lines
15 KiB
Python
"""
|
||
Lichess Statistics API - Модели данных
|
||
|
||
Этот модуль содержит все Pydantic модели для валидации и сериализации данных.
|
||
Модели используются для:
|
||
- Валидации входных параметров API
|
||
- Сериализации ответов API
|
||
- Документации в Swagger UI
|
||
- Типизации данных в коде
|
||
|
||
Автор: Lichess Web Services Team
|
||
Версия: 1.0.0
|
||
"""
|
||
|
||
from pydantic import BaseModel, Field
|
||
from typing import Dict, Optional, Any
|
||
|
||
# =============================================================================
|
||
# МОДЕЛИ СТАТИСТИКИ ЗАДАЧ (ПАЗЛОВ)
|
||
# =============================================================================
|
||
|
||
class TaskStats(BaseModel):
|
||
"""
|
||
Статистика решения задач (пазлов) пользователя.
|
||
|
||
Содержит информацию о том, сколько задач пользователь решил,
|
||
сколько решил правильно и сколько не решил или решил неправильно.
|
||
"""
|
||
total: int = Field(..., description="Общее количество решенных задач", example=15)
|
||
solved: int = Field(..., description="Количество правильно решенных задач", example=12)
|
||
unsolved: int = Field(..., description="Количество нерешенных или неправильно решенных задач", example=3)
|
||
|
||
# =============================================================================
|
||
# МОДЕЛИ СТАТИСТИКИ ИГР
|
||
# =============================================================================
|
||
|
||
class GameModeStats(BaseModel):
|
||
"""
|
||
Статистика игр для конкретного режима (Bullet, Blitz, Rapid и т.д.).
|
||
|
||
Содержит полную статистику по играм в определенном временном формате:
|
||
- Количество сыгранных игр
|
||
- Изменение рейтинга за период
|
||
- Текущий рейтинг
|
||
- Результаты игр (победы, поражения, ничьи)
|
||
"""
|
||
games_played: int = Field(..., description="Общее количество сыгранных игр", example=8)
|
||
rating_change: int = Field(..., description="Изменение рейтинга (может быть отрицательным)", example=15)
|
||
final_rating: int = Field(..., description="Текущий рейтинг игрока", example=2850)
|
||
wins: int = Field(..., description="Количество побед", example=5)
|
||
losses: int = Field(..., description="Количество поражений", example=2)
|
||
draws: int = Field(..., description="Количество ничьих", example=1)
|
||
|
||
class GamesStats(BaseModel):
|
||
"""
|
||
Статистика игр по всем режимам.
|
||
|
||
Агрегирует статистику игр по всем временным форматам:
|
||
- Bullet: быстрые игры (1-3 минуты)
|
||
- Blitz: блиц игры (3-10 минут)
|
||
- Rapid: рапид игры (10+ минут)
|
||
- Classical: классические игры (30+ минут)
|
||
"""
|
||
bullet: GameModeStats = Field(..., description="Статистика Bullet игр (1-3 минуты)")
|
||
blitz: GameModeStats = Field(..., description="Статистика Blitz игр (3-10 минут)")
|
||
rapid: GameModeStats = Field(..., description="Статистика Rapid игр (10+ минут)")
|
||
classical: GameModeStats = Field(..., description="Статистика Classical игр (30+ минут)")
|
||
|
||
class UserStats(BaseModel):
|
||
"""
|
||
Полная статистика пользователя.
|
||
|
||
Содержит всю доступную статистику по пользователю:
|
||
- Статистику решения задач (пазлов)
|
||
- Статистику игр по всем режимам
|
||
"""
|
||
username: str = Field(..., description="Имя пользователя на Lichess", example="magnus")
|
||
tasks: TaskStats = Field(..., description="Статистика решения задач")
|
||
games: GamesStats = Field(..., description="Статистика игр по всем режимам")
|
||
|
||
# =============================================================================
|
||
# МОДЕЛИ ОТВЕТОВ API
|
||
# =============================================================================
|
||
|
||
class ActivityResponse(BaseModel):
|
||
"""
|
||
Стандартный ответ API с результатами запроса статистики.
|
||
|
||
Используется для всех эндпоинтов статистики (сегодня, вчера, неделя).
|
||
Содержит сообщение о результате и данные статистики пользователя.
|
||
"""
|
||
message: str = Field(..., description="Сообщение о результате запроса", example="Статистика за сегодняшний день")
|
||
data: Optional[UserStats] = Field(None, description="Данные статистики пользователя (null если пользователь не найден или неактивен)")
|
||
|
||
class ErrorResponse(BaseModel):
|
||
"""
|
||
Модель для стандартизированных ошибок API.
|
||
|
||
Используется для возврата структурированных ошибок с дополнительной информацией.
|
||
"""
|
||
detail: str = Field(..., description="Описание ошибки", example="Пользователь не найден")
|
||
error_code: Optional[str] = Field(None, description="Код ошибки", example="USER_NOT_FOUND")
|
||
timestamp: Optional[str] = Field(None, description="Время возникновения ошибки", example="2024-01-15T10:30:00Z")
|
||
|
||
class HealthResponse(BaseModel):
|
||
"""
|
||
Ответ для health check эндпоинта.
|
||
|
||
Используется для мониторинга состояния сервиса и проверки его работоспособности.
|
||
"""
|
||
status: str = Field(..., description="Статус сервиса", example="healthy")
|
||
timestamp: str = Field(..., description="Время проверки", example="2024-01-15T10:30:00Z")
|
||
service: str = Field(..., description="Название сервиса", example="Lichess Statistics API")
|
||
|
||
# =============================================================================
|
||
# МОДЕЛИ ДЛЯ ЭНДПОИНТА СТАТИСТИКИ ИГР ЗА ПЕРИОД
|
||
# =============================================================================
|
||
|
||
class GamePlayer(BaseModel):
|
||
"""
|
||
Информация об игроке в партии.
|
||
|
||
Содержит данные о пользователе, его рейтинге и изменении рейтинга в конкретной игре.
|
||
"""
|
||
user: Optional[Dict[str, Any]] = Field(None, description="Информация о пользователе")
|
||
rating: Optional[int] = Field(None, description="Рейтинг игрока")
|
||
ratingDiff: Optional[int] = Field(None, description="Изменение рейтинга")
|
||
|
||
class Game(BaseModel):
|
||
"""
|
||
Модель игры из Lichess API.
|
||
|
||
Содержит полную информацию об игре, включая:
|
||
- Метаданные игры (ID, время создания, статус)
|
||
- Информацию об игроках и их рейтингах
|
||
- Результат игры и ходы в PGN формате
|
||
"""
|
||
id: str = Field(..., description="ID игры")
|
||
rated: bool = Field(..., description="Рейтинговая ли игра")
|
||
variant: str = Field(..., description="Вариант игры")
|
||
speed: str = Field(..., description="Скорость игры (bullet, blitz, rapid, classical, correspondence)")
|
||
perf: str = Field(..., description="Тип производительности")
|
||
createdAt: int = Field(..., description="Время создания игры (timestamp)")
|
||
lastMoveAt: int = Field(..., description="Время последнего хода (timestamp)")
|
||
status: str = Field(..., description="Статус игры")
|
||
players: Dict[str, GamePlayer] = Field(..., description="Игроки (white, black)")
|
||
winner: Optional[str] = Field(None, description="Победитель (white, black или null)")
|
||
moves: str = Field(..., description="Ходы игры в PGN формате")
|
||
|
||
class GameStats(BaseModel):
|
||
"""
|
||
Статистика игр по конкретному типу (Bullet, Blitz, Rapid и т.д.).
|
||
|
||
Содержит агрегированную статистику по играм определенного типа:
|
||
- Количество сыгранных игр
|
||
- Результаты игр (победы, поражения, ничьи)
|
||
- Общее изменение рейтинга
|
||
- Итоговый рейтинг после последней игры
|
||
"""
|
||
games_played: int = Field(..., description="Общее количество сыгранных игр", example=10)
|
||
wins: int = Field(..., description="Количество побед", example=6)
|
||
losses: int = Field(..., description="Количество поражений", example=3)
|
||
draws: int = Field(..., description="Количество ничьих", example=1)
|
||
rating_change: int = Field(..., description="Общее изменение рейтинга", example=15)
|
||
rating: Optional[int] = Field(None, description="Итоговый рейтинг после последней игры (только если games_played > 0)", example=2850)
|
||
|
||
class GamesOfPeriodStats(BaseModel):
|
||
"""
|
||
Статистика игр за период по всем типам.
|
||
|
||
Агрегирует статистику игр по всем временным форматам:
|
||
- Bullet, Blitz, Rapid, Classical, Correspondence
|
||
- Общая статистика по всем типам
|
||
"""
|
||
bullet: GameStats = Field(..., description="Статистика Bullet игр")
|
||
blitz: GameStats = Field(..., description="Статистика Blitz игр")
|
||
rapid: GameStats = Field(..., description="Статистика Rapid игр")
|
||
classical: GameStats = Field(..., description="Статистика Classical игр")
|
||
correspondence: GameStats = Field(..., description="Статистика Correspondence игр")
|
||
total: GameStats = Field(..., description="Общая статистика по всем типам")
|
||
|
||
class GamesOfPeriodResponse(BaseModel):
|
||
"""
|
||
Ответ API с результатами запроса статистики игр за период.
|
||
|
||
Содержит метаинформацию о запросе и агрегированную статистику игр.
|
||
"""
|
||
message: str = Field(..., description="Сообщение о результате запроса", example="Статистика игр за период")
|
||
username: str = Field(..., description="Имя пользователя", example="magnus")
|
||
period_start: int = Field(..., description="Начало периода (Unix timestamp)", example=1640995200)
|
||
period_end: int = Field(..., description="Конец периода (Unix timestamp)", example=1641081600)
|
||
games_count: int = Field(..., description="Общее количество игр", example=25)
|
||
earliest_game_ts: Optional[int] = Field(None, description="Время самой старой найденной партии (Unix timestamp, секунды)", example=1638316800)
|
||
data: Optional[GamesOfPeriodStats] = Field(None, description="Данные статистики игр")
|
||
|
||
# =============================================================================
|
||
# МОДЕЛИ ДЛЯ ЭНДПОИНТА СТАТИСТИКИ ЗАДАЧ ЗА ПЕРИОД
|
||
# =============================================================================
|
||
|
||
class PuzzleActivity(BaseModel):
|
||
"""
|
||
Активность по решению задачи (пазла) из Lichess API.
|
||
|
||
Содержит информацию о попытке решения задачи пользователем:
|
||
- ID задачи и время решения
|
||
- Результат решения (решена/не решена)
|
||
- Дополнительная информация о задаче
|
||
"""
|
||
id: str = Field(..., description="ID задачи", example="abc123")
|
||
createdAt: int = Field(..., description="Время создания активности (timestamp в миллисекундах)", example=1640995200000)
|
||
win: bool = Field(..., description="Решена ли задача правильно", example=True)
|
||
puzzle: Dict[str, Any] = Field(..., description="Информация о задаче")
|
||
|
||
class PuzzleStats(BaseModel):
|
||
"""
|
||
Агрегированная статистика решения задач за период.
|
||
|
||
Содержит сводную информацию о решении задач:
|
||
- Общее количество попыток
|
||
- Количество успешных и неуспешных решений
|
||
- Процент успешности
|
||
"""
|
||
total_attempts: int = Field(..., description="Общее количество попыток решения", example=25)
|
||
solved: int = Field(..., description="Количество решенных задач", example=18)
|
||
failed: int = Field(..., description="Количество нерешенных задач", example=7)
|
||
success_rate: float = Field(..., description="Процент успешных решений", example=72.0)
|
||
|
||
class PuzzleOfPeriodResponse(BaseModel):
|
||
"""
|
||
Ответ API с результатами запроса статистики решения задач за период.
|
||
|
||
Содержит метаинформацию о запросе и агрегированную статистику решения задач.
|
||
"""
|
||
message: str = Field(..., description="Сообщение о результате запроса", example="Статистика решения задач за период")
|
||
period_start: int = Field(..., description="Начало периода (Unix timestamp в миллисекундах)", example=1640995200000)
|
||
period_end: int = Field(..., description="Конец периода (Unix timestamp в миллисекундах)", example=1641081600000)
|
||
max_puzzles: int = Field(..., description="Максимальное количество задач для получения", example=50)
|
||
puzzles_in_period: int = Field(..., description="Количество задач в указанном периоде", example=15)
|
||
data: Optional[PuzzleStats] = Field(None, description="Данные статистики решения задач")
|