# Нормализованное хранение хоккейной статистики

Эта сборка сохраняет исходные XML/JSON Stat2TV как `raw_payload`, но дополнительно раскладывает основные данные по отдельным SQL-таблицам PostgreSQL.

## Новые таблицы

- `hockey_game_team_statistics` — командная статистика конкретного матча: итог + отдельная строка на каждый период для обеих команд.
- `hockey_player_season_statistics` — сезонная статистика игроков и вратарей по турниру.
- `hockey_tournament_standing_rows` — нормализованные строки общей таблицы, конференций и дивизионов.
- `hockey_tournament_statistic_rows` — нормализованные строки `powerplay` и `rank`.
- `hockey_team_season_statistics` — единая сезонная строка команды, собранная из standings + powerplay.

Расписание уже хранится нормализованно в `hockey_games` и продолжает обновляться прежним механизмом.

## Что происходит при запуске

`database.create_all()` создаёт отсутствующие таблицы без удаления существующих данных. После этого выполняется backfill: если новые нормализованные таблицы ещё пустые, уже сохранённые `raw_payload` разбираются локально и переносятся в новые таблицы без повторного обращения к Stat2TV.

## Автоматическая запись при новых sync

- sync карточки матча -> `hockey_game_team_statistics`;
- sync players -> `hockey_player_season_statistics`;
- sync standings -> `hockey_tournament_standing_rows` + пересборка `hockey_team_season_statistics`;
- sync powerplay/rank -> `hockey_tournament_statistic_rows` + пересборка сезонной строки команды для powerplay.

## Проверка базы

Общее состояние:

```text
GET /api/hockey/database/statistics-status
```

Только один турнир:

```text
GET /api/hockey/database/statistics-status?tournament_id=1369
```

Ответ показывает имя SQL-таблицы, количество строк и время последней синхронизации. Для `powerplay/rank` также возвращается количество строк по каждому `resource_type`.

## Ручной backfill

Администратор может повторно разложить сохранённые RAW-данные:

```text
POST /api/hockey/database/statistics-backfill
```

Запрос к Stat2TV для этой операции не нужен.

## Безопасность обновления

Существующие `raw_payload`, расписание, матчи, составы, события, mapping и vMix-настройки не удаляются. Новые таблицы добавляются поверх текущей схемы.


## Build 31 fix — 2026-08-18

- Исправлена дедупликация команд в `hockey_team_season_statistics`, когда один и тот же клуб повторяется в нескольких секциях `powerplay` XML.
- Поддержаны реальные ключи Stat2TV `pp`, `ppgf`, `pp_pct` вместе с прежними `ppo`, `ppg`.
- Перед пересборкой сезонной командной статистики удаляются и уже записанные, и pending ORM-строки текущего Session.
- В SQLAlchemy включён `hide_parameters=True`: большие XML/JSON payload больше не печатаются в traceback SQL-ошибок.
- В консоль добавлены только короткие сообщения об обновлении матчей, игроков, standings, powerplay/rank и backfill.
