LichessStatTgWeb/LichessWebServices/models.py
vrubelroman b031539f5e Добавлена поддержка классических игр в статистике
- Добавлен classical в модель GamesStats
- Добавлена обработка classical в методе _process_games_by_mode
- Теперь команды /today, /yesterday и /week выводят информацию по классическим играм
- Форматтер уже поддерживает classical (emoji ♟️)
2025-10-31 19:24:27 +03:00

238 lines
15 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
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)
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="Данные статистики решения задач")