[F8-06] Калькулятор: шаги, замочки, пол tech, баг speed-lock #49
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Подзадача полировки UI (этап F8), родительский #43.
Цель: Калькулятор: корректные шаги числовых инпутов, унификация замочков, нижняя граница по текущему tech, фикс бага speed-lock.
Пункты из #43:
Заметка. п.9 и п.12 — баги; п.10 — зарезервированное место под замочки + единый идиом «число + замок → input» (как lock-замочки секцией ниже), включая MAT планеты; п.11 — нижняя граница уровней tech = текущий уровень технологий игрока на этом ходе.
Порядок обработки: F8-06 из 12. Создано в рамках #43; зонтичный issue остаётся открытым до закрытия всех подзадач.
Working log (issue-agent) — click to expand
State: done
Updated: 2026-05-26T17:24Z
Branch / PR: PR #61 merged (merge commit
b03993f) · feature branch auto-deletedConfirmed:
b01a60e(stale=false, comments_count=0) at 17:20Z.b01a60eare conclusion=success (395 go-unit, 396 integration, 397 ui-test). The combined commit-status readsfailureonly because of run 394 (ui-test/push) — auto-cancelled when the matching ui-test/pull_request run started; this is the documented phantom-failure pattern.Open question: —
Decisions:
default_merge_style: merge); feature branch deleted viadelete_branch_after_merge: true.Closes #49; terminal label flipped working → done through the exclusiveclaude/*scope.Next: —
@owner — готово к ревью: PR #61 (
feature/issue-49-calculator-polish→development). Все четыре пункта одной правкой; CI зелёный (go-unit,ui-test,integration).Коротко по пунктам:
(0, 1)), дальше шаг ±0.1; ArrowDown на 1 схлопывает на 0. Нативный спиннер на этих инпутах спрятан (он бы воспроизвёл проблему с 0.01). Armament оставлен с нативным шагом 1.pkg/calc/solve.goDriveForSpeed: приrestMass == 0(корабль D=1, остальные 0) достижимая скорость ровно одна — потолок20 × driveTech, поэтому solver больше не помечает её как недостижимую. Fake-core зеркало обновлено, добавлены параллельные unit-тесты.Если в каком-то месте моя интерпретация разошлась с задумкой — скажи, поправлю. По умолчанию мерж пойдёт через merge-gate после твоего APPROVED-ревью на текущий head.
Спасибо! Мелкие шероховатости:
@owner — поправил все четыре пункта, новый head
cbf7f65в PR #61.Ceil3-форматтер, что и результаты в отчёте: 3 знака после запятой, tabular-nums, выравнивание по правому краю — формат и шрифтовая ширина те же, что в derived results. То же касается read-only клетки goal-seek (когда блок back-solved). Если под «fixed-шрифтом» ты имел в виду именно монопространственный font-family, а не tabular-nums как в отчёте — скажи, переведу наmonospace.computeCalculatorтеперь валидирует back-solved блок против того же правила DWSC (0или≥ 1), что и обычный ввод. Если solver попадает в (0, 1) — например attack 0.5 при weaponsTech 1.5 = weapons 0.333… — lock помечается infeasible (красная рамка + тултип), а в read-only клетке остаётся то, что ввёл пользователь руками. Силуэт корабля больше не уезжает молча ниже единицы при прокрутке спиннера. Сама прокрутка теперь идёт стрелочками с шагом 0.001 (см. п.9), так что сжать в (0, 1) случайным колесом мыши тоже сложнее.changeнаinputс проверкойInputEvent.inputType: datalist-replacement даёт"insertReplacementText"в Chromium/WebKit иundefinedв Firefox, обычная печатка несёт"insertText"/"deleteContent…". То есть клик по опции грузит класс сразу, без второго клика. Перед загрузкой сравниваю текущие блоки с ранее загруженным классом (или с дефолтными нулями, если ничего не было загружено); если есть ручные изменения — спрашиваюСбросить несохранённые изменения и загрузить класс «…»?через нативныйwindow.confirm(отдельной модалки у нас в калькуляторе нет, native-confirm — минимальный шаг). При «нет» возвращаю имя в поле к предыдущему загруженному (или к пустому) и оставляю design нетронутым.Покрыто шестью новыми кейсами в
calculator-tab.test.tsиcalc-model.test.ts(Arrow-step для armament, форматтер на tech-/MAT-лейблах, infeasible-lock на attack→weapons и emptyMass→cargo, ArrowKey-шаг на lock-инпуте, иммедиат-загрузка из datalist + confirm-блокирует + confirm-пропускает). Все 779 vitest зелёные,go test ./pkg/calc/...зелёный,svelte-checkчист. Жду твоего ревью на новом head; мерж пойдёт через merge-gate после APPROVED.Всё ещё остались некоторые "проблемки".
Если описанная выше логика не ложится на код - приходи обсуждать, приноси предложения.
По остальным пунктам посмотрел - всё в норме, спасибо!
@owner — поправил всё из последнего комментария, новый head
cc4727aв PR #61. CI зелёный по всем трём workflows (go-unit,ui-test,integration).fmtокруглял ceil-ом до 3 знаков, но печатал черезmaximumFractionDigits: 3, поэтому целые значения шли как"1". Теперь иmin, иmax= 3, иuseGrouping: false. Это разом подтянуло все лейблы, которые ты перечислил: tech, mass, speed, attack, defence, bombing, cargo capacity, MAT, ships per turn, modernization cost, full capacity, read-only клетка goal-seek блока.20→20.000,1→1.000,1.2→1.200. Группировку тысяч убрал, потому что та же строка теперь embed-ится в<input type="number">(read-only клетка back-solved блока) и"1,234.000"туда не парсится.--font-mono(тот же стек, что вreport—ui-monospace, SF Mono, Cascadia Code, Menlo, Consolas, monospace) ко всем числовым лейблам и инпутам калькулятора:.cell .val,.cell input,.tech-val,.mat-val,.full-capacity,.custom-load,.planet-stats dd, плюс блок ship-design-area.tabular-nums+text-align: rightсохранены, поэтому колонки выстраиваются строго в столбик.capDecimals(event, apply): наinput-событии, если в текстовом значении больше трёх знаков после точки — отрезает четвёртый+ символ и явно перезаписывает связанное состояние черезapply. Явная перезапись важна, потому что у Sveltebind:valueсвой обработчикinput, и он уже прочитал «перепрецизионное» число до нас; безapplyследующий реактивный флэш вернул бы длинную строку обратно в DOM. Применил ко всем числовым инпутам калькулятора: DWSC-блоки, tech, MAT, custom load, lock value, target tech модернизации.resolvedCeilуже прогоняет back-solved блок черезcore.ceil3, иfmtповторно ceil-ит при выводе (идемпотентно), так что после смены формата лейбла back-solved клетка тоже стабильно показывает 3 знака. Сам внутренний числовой стейт оставил «как пришёл от солвера» — лгать про точность в инпуте не хочется, а отображение уже корректное.Покрыто пятью новыми тестами в
calculator-tab.test.ts: 3-decimal padding на tech-лейбле, на MAT-лейбле и на derived результате (целое empty mass), плюс кап на каждом классе инпутов (MAT / custom-load, tech + target tech, lock value, ship-block). Все 32 кейса в файле зелёные, общий vitest набор — 784 passed / 16 skipped (3 wasm-core теста требуютmake wasmлокально и проходят в CI).pnpm run checkчист.Если формат / шрифт где-то ещё надо подтянуть — скажи, поправлю. По умолчанию мерж пойдёт через merge-gate после твоего APPROVED-ревью на
cc4727a.Выглядит очень классно, спасибо! Парочка финальных мелких моментов:
@owner — поправил оба пункта, новый head
b01a60eв PR #61. CI зелёный по всем трём workflows (go-unit,ui-test,integration).delete <ship_class_name>ушла из калькулятора. Снёс её разом с обвязкой:canDelete-derived,deleteClass-функцию, CSS-правило.delete, i18n-ключgame.calculator.action.delete(он нигде больше не использовался — у других удалений свои namespace'ы). СамremoveShipClass-флоу остался жив вlib/active-view/table-ship-classes.svelte(и у дизайнера); калькулятор просто перестал быть его второй точкой входа. Под #53 ты, как договаривались, перепилишь его уже там..cell { justify-content: flex-end }: в локабельных строках справа стоит кнопка-замочек, и значение прижимается к ней, а у bombing / cargo capacity замочка нет — значение упиралось прямо в правый край ячейки, наlock-width + gapправее. Положил в эти две ячейки скрытый плейсхолдер<span class="lock-slot" aria-hidden="true">🔓</span>соflex: none; font-size: 0.7rem; line-height: 1; visibility: hidden. Та же ширина, что у видимой кнопки-замочка, не в табстопе, не озвучивается скринридерами. Колонка теперь строго в столбик от mass до cargo capacity.Документация: в
ui/docs/calculator-ux.mdсекциюCreate / load / deleteпереименовал вCreate / load, оставил указатель, что delete-class живёт в ship-classes-таблице, и добавил строку про зарезервированный lock-slot.Покрыто двумя новыми vitest-кейсами в
calculator-tab.test.ts: после загрузки классаqueryByTestId("calculator-delete")возвращаетnull; в ячейках bombing и cargo capacity присутствует.lock-slot. Все 34 кейса калькулятора зелёные, общийpnpm test— 786 passed / 16 skipped (3 wasm-core теста требуютmake wasmлокально и проходят в CI).pnpm run checkчист.Мерж по-прежнему пойдёт через merge-gate после твоего APPROVED-ревью на
b01a60e.