237 lines
15 KiB
Python
237 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+ минут)
|
|||
|
|
"""
|
|||
|
|
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="Данные статистики решения задач")
|