Реализация новой рейтинговой системы #23

Closed
opened 2026-09-09 01:13:25 +03:00 by NotBigGhost · 3 comments
Owner

Реализация рейтинговой системы, разработанной и описанной в задаче #22.

Зависит от #22

Реализация рейтинговой системы, разработанной и описанной в задаче #22. Зависит от #22
NotBigGhost added this to the v1.5 — изменение системы подсчёта рейтинга milestone 2026-09-09 01:13:25 +03:00
NotBigGhost added the Kind/Enhancement label 2026-09-09 01:13:25 +03:00
Agent added the
Status
Blocked
1
label 2026-09-09 14:25:34 +03:00
Author
Owner

Документация новой рейтинговой системы

Документация новой рейтинговой системы
Agent removed the
Status
Blocked
1
label 2026-09-14 21:47:12 +03:00
Agent self-assigned this 2026-09-14 21:52:02 +03:00
Agent added the
Reviewed
Confirmed
1
label 2026-09-14 21:52:03 +03:00
Collaborator

План выполнения

Реализация по утверждённому docs/rating/rating-system.md (#22), эталон — docs/rating/simulate.py.

  1. Движок. scoring.py переписывается под парный Elo с множителем отрыва: шкала 1500/400, K 64→16 за 20 партий, G(N), темп/цели/миры, близость по типу победы, clamp [0.5, 2]. Функции — порт rate_match один в один.
  2. Данные.
    • Миграция 0014: groups.nine_rounds_rule, снимок matches.nine_rounds_rule, matches.end_round, match_participants.objectives/worlds, причина last_standing.
    • Бэкфилл last_standing у партий с одним невыбывшим.
    • Миграция идемпотентна и отказывается пересоздавать таблицу при PRAGMA foreign_keys=ON.
  3. Ввод и валидация.
    • Раунд окончания и цели/миры на участника в финише, правке и черновике.
    • На сервере: end_round ≤ R_max, у выбывшего 0 миров, «невыбывший ровно один ⇔ last_standing».
    • Галочка «9 раундов при 5–6 игроках» в настройках группы.
  4. Витрины.
    • Рейтинг пересчитывается проигрыванием завершённых партий (played_at, finished_at, id) вместо SQL-агрегата. Цепочки две: общая и групповая.
    • «Лучшая партия» определяется по ΔR, «лучшая/худшая фракция» — по среднему S − E.
  5. Фронтенд.
    • Поля ввода в PlaceEditor, MatchDetailPage, AdminMatchEdit.
    • Автоподстановка last_standing с блокировкой выбора и сбросом при возврате второго невыбывшего.
    • Предупреждения о несогласованном вводе (отправку не блокируют).
    • Топ: без столбца «Поб», «Очки» → «Рейтинг», целое число.
    • Справка переписана.
  6. Тесты.
    • 15 примеров документа с точными числами.
    • Перекрёстная проверка с simulate.py.
    • Валидация, миграция на копии dev-БД, пересчёт после правки, best_only.

Уведомления игрокам и пояснение на странице топа в эту задачу не входят: систему оповещений владелец делает отдельно, до релиза рейтинга.

Критерии готовности

  • Все 15 примеров раздела 6 дают ΔR из документа; реализация совпадает с simulate.py на сгенерированном сезоне.
  • Миграция 0014 идемпотентна, на копии dev-БД не теряет строки, CHECK/FK/индексы на месте.
  • Новые поля вводятся в форме завершения, правке и админке; last_standing проставляется автоматически; сервер отвергает противоречия.
  • Топ, профиль, группа и главная показывают рейтинг по новой системе; справка соответствует формулам.
  • pytest и npm run build зелёные.

Изменение ломающее: меняются числа и порядок топа, score становится целым с новым смыслом, появляется новое значение win_reason.

Ветка: issue-23-rating-system от dev

## План выполнения Реализация по утверждённому `docs/rating/rating-system.md` (#22), эталон — `docs/rating/simulate.py`. 1. **Движок.** `scoring.py` переписывается под парный Elo с множителем отрыва: шкала 1500/400, K 64→16 за 20 партий, `G(N)`, темп/цели/миры, близость по типу победы, clamp [0.5, 2]. Функции — порт `rate_match` один в один. 2. **Данные.** - Миграция `0014`: `groups.nine_rounds_rule`, снимок `matches.nine_rounds_rule`, `matches.end_round`, `match_participants.objectives/worlds`, причина `last_standing`. - Бэкфилл `last_standing` у партий с одним невыбывшим. - Миграция идемпотентна и отказывается пересоздавать таблицу при `PRAGMA foreign_keys=ON`. 3. **Ввод и валидация.** - Раунд окончания и цели/миры на участника в финише, правке и черновике. - На сервере: `end_round ≤ R_max`, у выбывшего 0 миров, «невыбывший ровно один ⇔ `last_standing`». - Галочка «9 раундов при 5–6 игроках» в настройках группы. 4. **Витрины.** - Рейтинг пересчитывается проигрыванием завершённых партий (`played_at`, `finished_at`, `id`) вместо SQL-агрегата. Цепочки две: общая и групповая. - «Лучшая партия» определяется по ΔR, «лучшая/худшая фракция» — по среднему `S − E`. 5. **Фронтенд.** - Поля ввода в `PlaceEditor`, `MatchDetailPage`, `AdminMatchEdit`. - Автоподстановка `last_standing` с блокировкой выбора и сбросом при возврате второго невыбывшего. - **Предупреждения о несогласованном вводе** (отправку не блокируют). - Топ: без столбца «Поб», «Очки» → «Рейтинг», целое число. - Справка переписана. 6. **Тесты.** - 15 примеров документа с точными числами. - Перекрёстная проверка с `simulate.py`. - Валидация, миграция на копии dev-БД, пересчёт после правки, `best_only`. Уведомления игрокам и пояснение на странице топа в эту задачу **не входят**: систему оповещений владелец делает отдельно, до релиза рейтинга. **Критерии готовности** - Все 15 примеров раздела 6 дают ΔR из документа; реализация совпадает с `simulate.py` на сгенерированном сезоне. - Миграция 0014 идемпотентна, на копии dev-БД не теряет строки, CHECK/FK/индексы на месте. - Новые поля вводятся в форме завершения, правке и админке; `last_standing` проставляется автоматически; сервер отвергает противоречия. - Топ, профиль, группа и главная показывают рейтинг по новой системе; справка соответствует формулам. - `pytest` и `npm run build` зелёные. **Изменение ломающее:** меняются числа и порядок топа, `score` становится целым с новым смыслом, появляется новое значение `win_reason`. **Ветка:** `issue-23-rating-system` от `dev`
Agent added the
Status
In Review
label 2026-09-14 22:51:33 +03:00
Collaborator

Работа выполнена, открыт PR: #75

Итог: рейтинг теперь считается Elo с множителем отрыва (шкала 1500) проигрыванием истории, в общей и групповой цепочке.

  • Появились ввод раунда, целей и миров, галочка «9 раундов» в группе, автоматическая причина last_standing и предупреждения о несогласованном вводе.
  • Топ и справка обновлены.
  • Миграция 0014 идемпотентна, данные не теряет.

Проверки:

  • pytest — 189 passed, в том числе 15 примеров документа и совпадение с simulate.py на целых сезонах;
  • npm run build — зелёный;
  • миграция 0014 проверена на копии dev-БД и на схеме origin/dev с CHECK (повтор и downgrade тоже);
  • сквозной HTTP-сценарий через vite-прокси пройден.

Ручной прогон интерфейса в браузере не выполнен: расширение Chrome было не подключено. Вёрстку новых полей стоит посмотреть при ревью.

Статус: Status/In Review
Осталось за вами: ревью и мёрж PR — задача закроется автоматически. Перед выпуском в main — система оповещений, как вы решили.

Работа выполнена, открыт PR: https://gitea.arseniev.info/NotBigGhost/ForbiddenStarsApp/pulls/75 **Итог:** рейтинг теперь считается Elo с множителем отрыва (шкала 1500) проигрыванием истории, в общей и групповой цепочке. - Появились ввод раунда, целей и миров, галочка «9 раундов» в группе, автоматическая причина `last_standing` и предупреждения о несогласованном вводе. - Топ и справка обновлены. - Миграция 0014 идемпотентна, данные не теряет. **Проверки:** - `pytest` — 189 passed, в том числе 15 примеров документа и совпадение с `simulate.py` на целых сезонах; - `npm run build` — зелёный; - миграция 0014 проверена на копии dev-БД и на схеме `origin/dev` с CHECK (повтор и `downgrade` тоже); - сквозной HTTP-сценарий через vite-прокси пройден. Ручной прогон интерфейса в браузере **не выполнен**: расширение Chrome было не подключено. Вёрстку новых полей стоит посмотреть при ревью. **Статус:** `Status/In Review` **Осталось за вами:** ревью и мёрж PR — задача закроется автоматически. Перед выпуском в `main` — система оповещений, как вы решили.
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Reference: NotBigGhost/ForbiddenStarsApp#23