# Результаты и аудит

Источник: https://docs.novapoker.ru/dev/results/
Дорожка: разработка
Сверено с кодом: Mon Aug 24
Код: repos/poker-api/apps/server/src/live/results.service.ts, repos/poker-api/packages/rating/src/index.ts

---

`src/live/results.service.ts` плюс пакет `packages/rating`. Всё начисление —
**одна транзакция**, а статус `running → finished` служит гейтом от второго
нажатия.

## Порядок мест

Не выбывший — место 1, дальше по убыванию времени вылета. Тай-брейки по
`createdAt` и `id`, чтобы порядок был детерминирован даже при совпадении меток.

`N` — число чек-инувшихся. **Неявки в размер поля не входят**, и это заметно
влияет на очки: формула зависит от `√N`.

## Что пишется

| Куда | Что |
|---|---|
| `Result` | место, очки сезона, xp, `skillBefore` и `skillAfter` |
| `PlayerProfile` | `xp`, пересчитанный `level`, новая `skill`, счётчики игр и побед |
| `AuditLog` | запись о подтверждении |
| пуш | `tournament.results` каждому участнику с аккаунтом |
| WS `/live` | рассылка нового состояния |

Формулы — в [пакете rating](https://docs.novapoker.ru/dev/rating.md), здесь только момент их применения.

## Гости

У записи гостя есть `guestPlayerId` и нет профиля. Такой участник получает
**только строку `Result`** — начислять некуда. Рейтинг подтянется при клейме
аккаунта, см. [аутентификацию](https://docs.novapoker.ru/dev/auth.md).

## Защита от второго нажатия

Гейт подтверждения атомарный: конкурентный второй вызов получает
`409 RESULTS_ALREADY_CONFIRMED` **до** начисления. Это важнее, чем кажется:
без такого порядка два нажатия в зале дали бы двойные очки.

## Пересчёт

`POST /admin/tournaments/{id}/recount`, только для `finished`, только у платформы.

Переиспользует то же начисление, но:

- удаляет и пересоздаёт `Result`, **сохраняя исходные `createdAt`**;
- учитывает уже заклеймленных гостей;
- полностью пересобирает профили всех задетых игроков по хронологии.

Сохранение `createdAt` обязательно потому, что сила — экспоненциальное
сглаживание и зависит от порядка турниров. Пересчёт не последнего турнира без
этого сдвинул бы его в конец истории игрока и дал бы дрейф силы.

По той же причине профиль **пересобирается**, а не правится дельтой.

## Аудит

В `AuditLog` пишется каждая операция ТД: старт, вылет, отмена вылета, пересадка,
подтверждение результатов. Это же источник для ленты событий турнира.

## Что рядом

- [Результаты и итоги вечера](https://docs.novapoker.ru/product/results.md) — то же словами продукта.
- [Live-цикл и реалтайм](https://docs.novapoker.ru/dev/live.md) — что происходит до подтверждения.
- [Рейтинг: пакет формул](https://docs.novapoker.ru/dev/rating.md) — сами формулы.
