LichessStatTgWeb/LichessWebServices/models.py

237 lines
15 KiB
Python
Raw Normal View History

"""
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+ минут)
"""
bullet: GameModeStats = Field(..., description="Статистика Bullet игр (1-3 минуты)")
blitz: GameModeStats = Field(..., description="Статистика Blitz игр (3-10 минут)")
rapid: GameModeStats = Field(..., description="Статистика Rapid игр (10+ минут)")
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)
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="Данные статистики решения задач")