Модель — многопользовательский Elo: партия раскладывается на пары, ожидаемый исход считается из разницы рейтингов (треб. 3). Размер изменения масштабирует множитель отрыва:
темп победы относительно лимита раундов, с учётом хоумрула 9 раундов на 5–6 игроков (треб. 1);
отрыв по целям и мирам (треб. 4);
близость по типу победы (треб. 5);
вес размера стола — слабее, чем у темпа (треб. 2).
Шкала — классический Elo: старт 1500, D = 400, K новичка 64 → 16 у опытного. Пример «60 против 40» из задачи — это 1600 против 1400. Старая история пересчитывается по тем же формулам: у партий без новых полей признаки считаются нейтральными.
проверяет 15 пошаговых примеров документа через assert;
проверяет, что выбор шкалы не влияет на качество прогноза;
прогоняет синтетическую лигу в четырёх сценариях: сигнал, шум, клубы, рост.
Результат симуляции:
В сценариях, где отрыв связан с силой, предложенная система лучше текущего League Points и чистого Elo по всем метрикам качества. Например, ρ с истинной силой после 10 партий — 0.807 против 0.769, в «клубах» — 0.644 против 0.525.
В сценарии «шум» система уступает около 0.1 п.п. точности.
Поле дуэли 2×3 (6 тайлов, 6.6 мира на игрока) — в таблице правил, скрипте, примерах 2 и 4 и симуляции. Пересчёт сдвинул метрики на тысячные, выводы не изменились.
Шкала 1500 — во всех формулах, примерах, пределах изменений и таблицах. Скрипт проверяет, что при этом точность, Brier и ρ совпадают с прежней шкалой до 1e-9. Меняются только сами числа рейтинга.
правило last_standing ⇔ ровно один невыбывший: причина ставится автоматически и не выбирается вручную, сервер проверяет правило при завершении и правке;
бэкфилл истории для last_standing;
рейтинг показывается целым числом;
в общем топе убран столбец «Поб», «Очки» → «Рейтинг».
Раздел 9 «Открытые вопросы» стал «Решениями владельца»: все шесть пунктов и что из каждого следует.
Попутно: устаревший абзац про CLAUDE.md (которого нет в репозитории) заменён отсылкой к HelpPage.tsx, где формула продублирована; время прогонов в шапке исправлено на фактическое.
Коммиты
8f1518b Рейтинг: эталонная реализация и симуляция новой системы
648c10f Рейтинг: документ с предложением новой системы
af7d2b3 Рейтинг: поле 2×3 для дуэли и шкала 1500 в эталонной реализации
28846c5 Рейтинг: документ по решениям владельца
Проверки
python docs/rating/simulate.py — exit 0 (≈1.5 мин): «Все примеры совпадают с документом» и «Шкала 1500 и шкала 50 дают одинаковые точность, Brier и ρ». Таблицы 7.3 взяты из этого прогона; повторный прогон финальной версии дал тот же вывод (плюс строка проверки шкалы).
python docs/rating/simulate.py --grid --grid-seasons 40 — exit 0 (≈7 мин), таблицы 7.4 взяты из этого прогона.
Поиск остатков старой шкалы и поля (2×2, D = 40, старт 50, K 6.4/1.6, +3.2) — только в тексте раздела 9, где описано решение.
git diff --stat origin/dev...HEAD — изменены только docs/rating/ (2 файла). Код приложения не затронут, тесты бэкенда и сборка фронта не нужны.
Формулы — блоки ```math, Gitea 1.27.3 их поддерживает.
Отклонения от плана
Добавлены сценарии «клубы» и «рост»: без них сравнение нечестно в пользу текущей системы.
Поправка на автокорреляцию проверена и не включена: её эффект около 0.0001 Brier.
Веса темпа и целей заданы требованиями, а не вершиной перебора (разделы 7.4 и 7.5).
В доработке: проверка инвариантности шкалы встроена в simulate.py, чтобы утверждение документа «формулы от шкалы не зависят» воспроизводилось, а не держалось на слове.
На утверждение
Открытых вопросов не осталось. Мёрж PR = утверждение предложения. После мёржа документ будет выложен комментарием в #23.
## Что сделано
Документ [`docs/rating/rating-system.md`](https://gitea.arseniev.info/NotBigGhost/ForbiddenStarsApp/src/branch/issue-22-rating-proposal/docs/rating/rating-system.md) описывает новую рейтинговую систему.
**Модель** — многопользовательский Elo: партия раскладывается на пары, ожидаемый исход считается из разницы рейтингов (треб. 3). Размер изменения масштабирует множитель отрыва:
- темп победы относительно лимита раундов, с учётом хоумрула 9 раундов на 5–6 игроков (треб. 1);
- отрыв по целям и мирам (треб. 4);
- близость по типу победы (треб. 5);
- вес размера стола — слабее, чем у темпа (треб. 2).
**Шкала** — классический Elo: старт 1500, D = 400, K новичка 64 → 16 у опытного. Пример «60 против 40» из задачи — это 1600 против 1400. Старая история пересчитывается по тем же формулам: у партий без новых полей признаки считаются нейтральными.
**Скрипт** `docs/rating/simulate.py` (только stdlib) — эталонная реализация. Он:
- проверяет 15 пошаговых примеров документа через `assert`;
- проверяет, что выбор шкалы не влияет на качество прогноза;
- прогоняет синтетическую лигу в четырёх сценариях: сигнал, шум, клубы, рост.
**Результат симуляции:**
- В сценариях, где отрыв связан с силой, предложенная система лучше текущего League Points и чистого Elo по всем метрикам качества. Например, ρ с истинной силой после 10 партий — 0.807 против 0.769, в «клубах» — 0.644 против 0.525.
- В сценарии «шум» система уступает около 0.1 п.п. точности.
## Доработка по замечаниям владельца
Замечания: [уточнение в #22](https://gitea.arseniev.info/NotBigGhost/ForbiddenStarsApp/issues/22#issuecomment-3380) и [решения в этом PR](https://gitea.arseniev.info/NotBigGhost/ForbiddenStarsApp/pulls/65#issuecomment-3466).
- **Поле дуэли 2×3** (6 тайлов, 6.6 мира на игрока) — в таблице правил, скрипте, примерах 2 и 4 и симуляции. Пересчёт сдвинул метрики на тысячные, выводы не изменились.
- **Шкала 1500** — во всех формулах, примерах, пределах изменений и таблицах. Скрипт проверяет, что при этом точность, Brier и ρ совпадают с прежней шкалой до 1e-9. Меняются только сами числа рейтинга.
- **Раздел 8 (для #23):**
- правило `last_standing` ⇔ ровно один невыбывший: причина ставится автоматически и не выбирается вручную, сервер проверяет правило при завершении и правке;
- бэкфилл истории для `last_standing`;
- рейтинг показывается целым числом;
- в общем топе убран столбец «Поб», «Очки» → «Рейтинг».
- **Раздел 9** «Открытые вопросы» стал «Решениями владельца»: все шесть пунктов и что из каждого следует.
- Попутно: устаревший абзац про CLAUDE.md (которого нет в репозитории) заменён отсылкой к `HelpPage.tsx`, где формула продублирована; время прогонов в шапке исправлено на фактическое.
## Коммиты
- `8f1518b` Рейтинг: эталонная реализация и симуляция новой системы
- `648c10f` Рейтинг: документ с предложением новой системы
- `af7d2b3` Рейтинг: поле 2×3 для дуэли и шкала 1500 в эталонной реализации
- `28846c5` Рейтинг: документ по решениям владельца
## Проверки
- `python docs/rating/simulate.py` — exit 0 (≈1.5 мин): «Все примеры совпадают с документом» и «Шкала 1500 и шкала 50 дают одинаковые точность, Brier и ρ». Таблицы 7.3 взяты из этого прогона; повторный прогон финальной версии дал тот же вывод (плюс строка проверки шкалы).
- `python docs/rating/simulate.py --grid --grid-seasons 40` — exit 0 (≈7 мин), таблицы 7.4 взяты из этого прогона.
- Поиск остатков старой шкалы и поля (`2×2`, `D = 40`, `старт 50`, K 6.4/1.6, `+3.2`) — только в тексте раздела 9, где описано решение.
- `git diff --stat origin/dev...HEAD` — изменены только `docs/rating/` (2 файла). Код приложения не затронут, тесты бэкенда и сборка фронта не нужны.
- Формулы — блоки ` ```math `, Gitea 1.27.3 их поддерживает.
## Отклонения от плана
- Добавлены сценарии «клубы» и «рост»: без них сравнение нечестно в пользу текущей системы.
- Поправка на автокорреляцию проверена и **не включена**: её эффект около 0.0001 Brier.
- Веса темпа и целей заданы требованиями, а не вершиной перебора (разделы 7.4 и 7.5).
- В доработке: проверка инвариантности шкалы встроена в `simulate.py`, чтобы утверждение документа «формулы от шкалы не зависят» воспроизводилось, а не держалось на слове.
## На утверждение
Открытых вопросов не осталось. Мёрж PR = утверждение предложения. После мёржа документ будет выложен комментарием в #23.
Closes #22
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01LqSoRj99iwVEH5U5fnZgsd
docs/rating/simulate.py — только stdlib, фиксированные seed. Содержит
многопользовательский Elo с множителем отрыва (темп, цели, миры, тип победы,
размер стола, K новичка) и пошаговые примеры документа с assert. Синтетическая
лига в сценариях «сигнал», «шум», «клубы» и «рост» сравнивает текущий League
Points, чистый Elo и предложенную систему. Флаг --grid перебирает K и веса
на отдельных сезонах. #22
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XfTsytzT6TojfmprRDKiV6
docs/rating/rating-system.md:
- проблемы текущего League Points;
- правила игры как исходные данные: тай-брейки, хоумрул 9 раундов, миры;
- выбор модели среди альтернатив, формулы и коэффициенты;
- трассировка требований 1–5 и пошаговые примеры;
- результаты симуляции и анализ чувствительности;
- последствия для реализации: поля, миграция, пересчёт истории, что
ломается;
- открытые вопросы. #22
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XfTsytzT6TojfmprRDKiV6
Я налажал, когда расписывал количество систем, при игре вдвоём поле 2 на 3, а не 2 на 2.
Решение:
Шкала - 1500. При реализации в интерфейсе, чтобы рейтинг поместился в столбец общего рейтинга приложения, нужно будет убрать столбец "количество побед". Заодно можно будет переименовать столбец из "очки" в "рейтинг"
С коэффициентами типов побед согласен
Такую причину победы добавить, в интерфейсе её реализовать так: если в партии все игроки, кроме одного, отправляются в поле "выбыл", автоматически проставить эту причину победы без возможности её заменить, пока в невыбывших игроках не будет хотя бы двоих. При этом в список выбора типа победы (выпадающее меню) его не добавлять
ввод количества миров удобен, его оставляем
затухание не добавляем
минимум партий оставляем текущим (10)
Я налажал, когда расписывал количество систем, при игре вдвоём поле 2 на 3, а не 2 на 2.
Решение:
1) Шкала - 1500. При реализации в интерфейсе, чтобы рейтинг поместился в столбец общего рейтинга приложения, нужно будет убрать столбец "количество побед". Заодно можно будет переименовать столбец из "очки" в "рейтинг"
2) С коэффициентами типов побед согласен
3) Такую причину победы добавить, в интерфейсе её реализовать так: если в партии все игроки, кроме одного, отправляются в поле "выбыл", автоматически проставить эту причину победы без возможности её заменить, пока в невыбывших игроках не будет хотя бы двоих. При этом в список выбора типа победы (выпадающее меню) его не добавлять
4) ввод количества миров удобен, его оставляем
5) затухание не добавляем
6) минимум партий оставляем текущим (10)
Решения владельца по #22: у дуэли поле 2×3 (6 тайлов, 6.6 мира на игрока),
шкала — классический Elo (R0 = 1500, D = 400, K 64 → 16; чистый Elo — 96 → 16).
Примеры и assert переведены в новую шкалу, сетки K в --grid умножены на 10,
|ΔR| League Points в сравнении приводится к шкале 1500. Добавлена проверка,
что шкала не влияет на точность, Brier и ρ. #22
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LqSoRj99iwVEH5U5fnZgsd
Поле дуэли 2×3 в таблице правил и примерах; шкала 1500 в формулах, примерах
и пределах изменений; таблицы 7.3 и 7.4 — из новых прогонов simulate.py.
Раздел 8 для #23: правило last_standing (автоматически при одном невыбывшем,
проверка на сервере, бэкфилл истории), рейтинг целым числом, столбцы общего
топа; устаревший абзац про CLAUDE.md заменён отсылкой к HelpPage.tsx.
Раздел 9 «Открытые вопросы» стал «Решениями владельца». #22
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LqSoRj99iwVEH5U5fnZgsd
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Что сделано
Документ
docs/rating/rating-system.mdописывает новую рейтинговую систему.Модель — многопользовательский Elo: партия раскладывается на пары, ожидаемый исход считается из разницы рейтингов (треб. 3). Размер изменения масштабирует множитель отрыва:
Шкала — классический Elo: старт 1500, D = 400, K новичка 64 → 16 у опытного. Пример «60 против 40» из задачи — это 1600 против 1400. Старая история пересчитывается по тем же формулам: у партий без новых полей признаки считаются нейтральными.
Скрипт
docs/rating/simulate.py(только stdlib) — эталонная реализация. Он:assert;Результат симуляции:
Доработка по замечаниям владельца
Замечания: уточнение в #22 и решения в этом PR.
last_standing⇔ ровно один невыбывший: причина ставится автоматически и не выбирается вручную, сервер проверяет правило при завершении и правке;last_standing;HelpPage.tsx, где формула продублирована; время прогонов в шапке исправлено на фактическое.Коммиты
8f1518bРейтинг: эталонная реализация и симуляция новой системы648c10fРейтинг: документ с предложением новой системыaf7d2b3Рейтинг: поле 2×3 для дуэли и шкала 1500 в эталонной реализации28846c5Рейтинг: документ по решениям владельцаПроверки
python docs/rating/simulate.py— exit 0 (≈1.5 мин): «Все примеры совпадают с документом» и «Шкала 1500 и шкала 50 дают одинаковые точность, Brier и ρ». Таблицы 7.3 взяты из этого прогона; повторный прогон финальной версии дал тот же вывод (плюс строка проверки шкалы).python docs/rating/simulate.py --grid --grid-seasons 40— exit 0 (≈7 мин), таблицы 7.4 взяты из этого прогона.2×2,D = 40,старт 50, K 6.4/1.6,+3.2) — только в тексте раздела 9, где описано решение.git diff --stat origin/dev...HEAD— изменены толькоdocs/rating/(2 файла). Код приложения не затронут, тесты бэкенда и сборка фронта не нужны.```math, Gitea 1.27.3 их поддерживает.Отклонения от плана
simulate.py, чтобы утверждение документа «формулы от шкалы не зависят» воспроизводилось, а не держалось на слове.На утверждение
Открытых вопросов не осталось. Мёрж PR = утверждение предложения. После мёржа документ будет выложен комментарием в #23.
Closes #22
🤖 Generated with Claude Code
https://claude.ai/code/session_01LqSoRj99iwVEH5U5fnZgsd
Я налажал, когда расписывал количество систем, при игре вдвоём поле 2 на 3, а не 2 на 2.
Решение: