История игр в профиле игрока (#1) #21

Merged
NotBigGhost merged 2 commits from issue-1-profile-match-history into dev 2026-09-08 22:49:52 +03:00
Collaborator

Что сделано

В профиле появился список партий, которого там не было вовсе. Выборки партий по игроку в бэкенде тоже не существовало — только по группе, поэтому добавлен stats_service.user_match_list: завершённые партии игрока, свежие сверху. Сборку элементов списка вынес из group_match_list в общий _match_items и переиспользовал в обеих функциях, чтобы не держать её в двух копиях.

Витрину профиля задают две колонки в users (миграция 0011): history_mode (all / best) и history_detail (compact / full). Режим применяется на бэкенде, а не на клиенте — это витрина владельца, и в том же виде профиль видят гости. GET /api/users/{user_id}/matches отдаёт список вместе с mode и detail, так что гостю хватает одного запроса, чтобы отрисовать историю как задумал владелец.

На фронте — блок «История игр» с двумя тумблерами в «Аккаунте» и новый компонент MatchHistory: подробный режим переиспользует MatchListView (тот же список, что у группы, со всеми участниками), компактный рисует строку с результатом самого игрока — место, фракция, дата, длительность. Публичный профиль показывает ту же историю без контролов: страница намеренно read-only.

Уточнения ТЗ

В задаче не было критериев готовности, поэтому они были согласованы отдельно и зафиксированы планом в комментарии к #1: настройки хранятся в БД, «подробность» — это два режима карточки, «лучшая партия» выбирается по League Points, история видна и гостям.

Одна деталь всплыла при написании тестов и стоит упоминания: первое место даёт 1.0 очка независимо от размера стола, так что «победа на четверых весомее победы на двоих» — неверно. Разница возникает на непризовых местах: второе из четырёх — это (4-2)/3 ≈ 0.67, второе из двух — (2-2)/1 = 0. Тест на режим best построен именно на этом и проверяет, что берётся партия с лучшими очками, а не самая свежая.

Коммиты

  • be80891 Профиль: история партий игрока и настройки её витрины
  • 9dda7de Профиль: блок истории игр с переключателями режима и подробности

Проверки

  • alembic upgrade head — 0011 накатилась поверх 0010, цепочка миграций линейна
  • pytest — 74 passed (было 69). Добавлено пять тестов: в историю идут только завершённые партии игрока; чужая партия внутри его же группы не попадает; режим best берёт партию с максимальными очками, а не свежую; настройки сохраняются, мусорное значение отклоняется и не сбивает сохранённое; гость видит историю в режиме владельца
  • npm run gen:api + npm run build (tsc --noEmit && vite build) — зелёные
  • Визуальная проверка на dev-стенде — не выполнена: расширение Claude in Chrome к сессии не подключено

Отклонения от плана

Нет, план выполнен как есть.

Осознанно не сделано

Отдельного выключателя «скрыть историю целиком» задача не просит — режимы ограничены all / best. Если понадобится, это третье значение history_mode, а не новая колонка.

Closes #1

🤖 Generated with Claude Code

## Что сделано В профиле появился список партий, которого там не было вовсе. Выборки партий по игроку в бэкенде тоже не существовало — только по группе, поэтому добавлен `stats_service.user_match_list`: завершённые партии игрока, свежие сверху. Сборку элементов списка вынес из `group_match_list` в общий `_match_items` и переиспользовал в обеих функциях, чтобы не держать её в двух копиях. Витрину профиля задают две колонки в `users` (миграция `0011`): `history_mode` (`all` / `best`) и `history_detail` (`compact` / `full`). Режим применяется **на бэкенде, а не на клиенте** — это витрина владельца, и в том же виде профиль видят гости. `GET /api/users/{user_id}/matches` отдаёт список вместе с `mode` и `detail`, так что гостю хватает одного запроса, чтобы отрисовать историю как задумал владелец. На фронте — блок «История игр» с двумя тумблерами в «Аккаунте» и новый компонент `MatchHistory`: подробный режим переиспользует `MatchListView` (тот же список, что у группы, со всеми участниками), компактный рисует строку с результатом самого игрока — место, фракция, дата, длительность. Публичный профиль показывает ту же историю без контролов: страница намеренно read-only. ## Уточнения ТЗ В задаче не было критериев готовности, поэтому они были согласованы отдельно и зафиксированы планом в комментарии к #1: настройки хранятся в БД, «подробность» — это два режима карточки, «лучшая партия» выбирается по League Points, история видна и гостям. Одна деталь всплыла при написании тестов и стоит упоминания: **первое место даёт 1.0 очка независимо от размера стола**, так что «победа на четверых весомее победы на двоих» — неверно. Разница возникает на непризовых местах: второе из четырёх — это `(4-2)/3 ≈ 0.67`, второе из двух — `(2-2)/1 = 0`. Тест на режим `best` построен именно на этом и проверяет, что берётся партия с лучшими очками, а не самая свежая. ## Коммиты - `be80891` Профиль: история партий игрока и настройки её витрины - `9dda7de` Профиль: блок истории игр с переключателями режима и подробности ## Проверки - `alembic upgrade head` — `0011` накатилась поверх `0010`, цепочка миграций линейна - `pytest` — **74 passed** (было 69). Добавлено пять тестов: в историю идут только завершённые партии игрока; чужая партия внутри его же группы не попадает; режим `best` берёт партию с максимальными очками, а не свежую; настройки сохраняются, мусорное значение отклоняется и не сбивает сохранённое; гость видит историю в режиме владельца - `npm run gen:api` + `npm run build` (`tsc --noEmit && vite build`) — зелёные - Визуальная проверка на dev-стенде — **не выполнена**: расширение Claude in Chrome к сессии не подключено ## Отклонения от плана Нет, план выполнен как есть. ## Осознанно не сделано Отдельного выключателя «скрыть историю целиком» задача не просит — режимы ограничены `all` / `best`. Если понадобится, это третье значение `history_mode`, а не новая колонка. Closes #1 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Agent added 2 commits 2026-09-07 19:56:42 +03:00
Выборки партий по игроку в бэкенде не было — только по группе. Добавлен
stats_service.user_match_list: завершённые партии игрока, свежие сверху;
сборка элементов вынесена из group_match_list в общий _match_items, чтобы
не дублировать её в двух местах.

Витрина профиля задаётся двумя колонками в users (миграция 0011):
history_mode (all/best) и history_detail (compact/full). Режим применяется
на бэкенде, а не на клиенте: это витрина владельца, и в том же виде
профиль видят гости. В режиме best берётся партия с максимальными League
Points из SCORED_CTE (при равных очках — более свежая).

GET /api/users/{user_id}/matches отдаёт список вместе с mode и detail —
гостю хватает одного запроса, чтобы отрисовать историю как задумал владелец.

#1

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
В «Аккаунте» появился блок «История игр» с двумя тумблерами — «Только
лучшая партия» и «Подробные карточки»; выбор уходит в профиль, поэтому
переживает перезаход и другое устройство.

Новый компонент MatchHistory: подробный режим переиспользует список партий
группы (MatchListView со всеми участниками), компактный рисует строку с
результатом самого игрока — место, фракция, дата и длительность.

Публичный профиль показывает ту же историю в режиме владельца и без
контролов: страница намеренно read-only.

schema.d.ts пересобран с живого бэкенда (npm run gen:api).

#1

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
NotBigGhost merged commit f031bd5e89 into dev 2026-09-08 22:49:52 +03:00
NotBigGhost deleted branch issue-1-profile-match-history 2026-09-08 22:49:52 +03:00
Sign in to join this conversation.