feat: схема корта в блоках тренировки - #170
Conversation
Блок тренировки из личного кабинета теперь носит схему корта: фигуры расставляются касанием, стрелки рисуются протяжкой, фазы упражнения живут отдельными кадрами. Схема показывается свёрнутой и на странице игры, где план читают участники. Редактор — обычный Stimulus поверх инлайнового SVG. Пробовали смотреть в сторону ruby.wasm: пакет под ruby-4.0.6 есть, но importmap у нас без сборщика, а бандл весит 4.4 МБ по сети при том, что вся работа фичи — это события указателя, то есть ровно та часть, которой wasm не помогает. Схема приезжает JSON-строкой из скрытого поля формы, поэтому TrainingBlock::Diagram не проверяет её, а пересобирает заново: чужой kind выбрасывается, координаты обрезаются по сетке, лишние кадры отрезаются. В базу попадает только то, что построили сами. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AFhqg2d17p7mbhyogZPqLy
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8c6b05d70c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| #nextLabel(kind) { | ||
| const taken = this.frame.items.filter((item) => item.kind === kind).length | ||
| if (kind === "player") return String.fromCharCode(65 + (taken % 26)) | ||
| if (kind === "opponent") return String((taken % 9) + 1) |
There was a problem hiding this comment.
Assign an unused label to each new figure
When a frame contains ten or more opponents, the modulo operation repeats labels starting at 1, since the editor permits up to 16 figures. Labels also collide after deletion—for example, deleting player A from [A, B] makes the next player B because the remaining count is one. These duplicate labels make distinct figures indistinguishable, so derive the next label from the labels currently in use rather than the item count.
Useful? React with 👍 / 👎.
Подписи раздавались по счётчику фигур того же вида, поэтому после удаления счётчик выдавал уже занятую букву: убрали A из [A, B] — и следующий игрок тоже становился B. У соперников вдобавок стоял остаток от девяти, хотя фигур на кадре разрешено шестнадцать, так что десятый соперник снова получал единицу. Теперь берём первую свободную подпись из списка кандидатов: буквы для игроков, числа до предела фигур для соперников. Замечание Codex на PR #170. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AFhqg2d17p7mbhyogZPqLy
Блок тренировки из личного кабинета теперь носит схему корта: фигуры расставляются касанием, стрелки рисуются протяжкой, фазы упражнения живут отдельными кадрами. Схема показывается свёрнутой и на странице игры, где план читают участники.
Редактор — обычный Stimulus поверх инлайнового SVG. Пробовали смотреть в сторону ruby.wasm: пакет под ruby-4.0.6 есть, но importmap у нас без сборщика, а бандл весит 4.4 МБ по сети при том, что вся работа фичи — это события указателя, то есть ровно та часть, которой wasm не помогает.
Схема приезжает JSON-строкой из скрытого поля формы, поэтому TrainingBlock::Diagram не проверяет её, а пересобирает заново: чужой kind выбрасывается, координаты обрезаются по сетке, лишние кадры отрезаются. В базу попадает только то, что построили сами.
Claude-Session: https://claude.ai/code/session_01AFhqg2d17p7mbhyogZPqLy