Files
Learn_System/plans/quantik-game/CONTEXT.md
T
Maxim Dolgolyov 0b1925fd3b @
feat(quantik-game): фаза 4 — квантовые способности + SR-комнаты

Глава-созвездие quantum (L12–L16) и фирменные механики — всё через
безопасную модель спеки, движок и бэкенд НЕ тронуты (engine touch = 0):
- Суперпозиция: два тела ball+ball2, goal.when требует ОБА (зеркальный
  закон). Туннелирование: forbidden-зона wall + fail wall.hit && tunnel<1;
  способность тратит энергию → setParam(tunnel,1). Коллапс/прицел: пунктир-
  plot предсказанной траектории на паузе.
- Энергия — клиентский ресурс (localStorage quantik-energy, QuantikEnergy).
- SR-комната: мини-сессия повторения флешкарт в модалке (НЕ iframe),
  LS.fcStudySession/fcReview; «Знаю/Легко» дают энергию; текст карт
  экранируется, картинки — по regex-вайтлисту.
Все 5 уровней проверены на реальном движке (2★ достижимы; суперпозиция
требует оба тела; туннель-гейт блокирует без заряда). npm test 253/8
baseline; lint:routes 0; цепочка разблокировки проходима.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@
2026-06-14 10:29:35 +03:00

14 KiB
Raw Blame History

Feature Context: Квантик — Законы Мира

Current State

  • Ветка feature/quantik-game ответвлена от feature/sim-builder (движок P1–P3 там, не в master).
  • При ответвлении унаследован чужой uncommitted WIP sim-builder: frontend/js/sim-builder.js, frontend/sim-builder.html, .claude/settings.json + множество untracked tmp_*/мусорных файлов. НЕ трогать и НЕ коммитить этот WIP — стейджить только свои файлы поимённо.
  • Phase 0 реализован (pending review): слой целей в движке _sim_engine.js (блок goal, компиляция when/fail/stars через SimExpr, состояние результата, HUD-оверлей, API onGoal/getResult/resetResult) + серверный гейт validateSpec пропускает goal/game. Изменены: frontend/js/labs/_sim_engine.js, backend/src/controllers/customSimController.js. Аддитивно: спека без goal ведёт себя ровно как раньше (HUD не создаётся, побед не считается). Смоук 40/40; npm test 238 pass / 8 baseline fail; lint:routes 0.
  • Phase 1 реализован (pending review): сквозной играбельный срез. Страница /quantik (frontend/quantik.html + frontend/js/game/quantik-game.js) монтирует уровень-спеку через SimEngine.mount; «игровой режим» = HUD из Ф0 (сам по наличию goal) + слайдеры params + play/reset. Уровень phys-artillery-1 — данные в frontend/js/game/levels.js (window.QuantikLevels): physics-гравитация + body-запуск под углом θ/скоростью v, портал-цель, бонус-звезда. На победу onGoalLS.gameProgressSubmit + DOM-оверлей успеха (звёзды/время/попытки). Прогресс: таблица game_progress (мигр.076), API /api/game/progress (GET/POST, gameController.js+routes/game.js, смонтировано в server.js после /api/custom-sims), клиент LS.gameProgressList/Submit. Сайдбар: /quantik (icon rocket) виден всем. Новые: 076_game_progress.sql, gameController.js, routes/game.js, quantik.html, js/game/levels.js, js/game/quantik-game.js, tests/game.test.js. Изменены: server.js, js/api.js, js/sidebar.js. npm test 251 pass / 8 baseline fail (game.test.js 13/13); lint:routes 0; миграция применяется чисто.
  • Phase 2 реализован (pending review): одиночный уровень превращён в играбельный мир. Карта-созвездие (frontend/js/game/map.js, window.QuantikMap) на звёздном фоне: 6 физ-уровней в 2 главах (Кинематика 1–3, Динамика 4–6), узлы-«звёзды» со статусом (locked/available/completed+ звёзды), линии-связи, поэтапное появление. Шапка: нарратор-Квантик (PetSprite), XP-бар + «уровень Квантика», всего звёзд, скин-пикер (8 скинов, часть за XP/звёзды). Контент уровней расширен в levels.js (метаданные chapter/order/par_ms/unlockStars, по 2 звезды: кристалл + норматив времени). Разблокировка/XP/группировка — ЧИСТЫЕ функции в новом frontend/js/game/progress-logic.js (window.QuantikProgress), покрыты тестом. Навигация: карта→интро(нарратор)→уровень→успех (нарратор по звёздам)→карта; «Дальше» активирована (nextPlayable); скин тинтует героя+нарратора (localStorage quantik-skin). Backend НЕ тронут — XP клиентская агрегация из game_progress. Новые: js/game/map.js, js/game/progress-logic.js. Изменены: quantik.html, js/game/levels.js, js/game/quantik-game.js. node --check все OK; смоуки (логика 16/16, рендер 7/7, winnability 6/6 на реальном движке) зелёные и удалены; npm test 259/251 pass / 8 baseline fail (без изменений); lint:routes 0.
  • Phase 3 реализован (pending review): новый ТИП уровня — Квантик едет по кривой y=f(x), которую СОБИРАЕТ игрок (слайдеры коэффициентов). Движок (_sim_engine.js, аддитивно): (1) «бегунок по кривой» — на plot поле runner:{duration,hold} кладёт в env <id>.runX/.runY/.runDone; герой = обычный point на curve.runX/runY (f компилируется 1 раз, питает И кривую, И бегунок — нет само-ссылки); (2) type:'zone' (rect/circle, kind forbidden/target/collect, track) → булево env-поле <zoneId>.hit (1/0); goal/fail/stars ссылаются на него. Предикаты в грамматику SimExpr НЕ добавлялись. Новая глава-созвездие functions в levels.js (5 уровней: луч/синус/парабола/модуль/экспонента, unlockStars 9..17 ≤ 18 макс физ-звёзд → нет дедлока); map.js НЕ тронут (рисует по метаданным). Сервер validateSpec принимает zone+runner (OBJECT_TYPES + поля). Изменены: _sim_engine.js, levels.js, customSimController.js, quantik.html (per-level бейдж темы). Новые тесты: custom-sims.test.js +2 (приём zone+runner, отказ unknown type) — 26/26. Headless vm-смоук (per-level solvability + logic 29/29) зелёный и удалён. npm test 261 / 253 pass / 8 baseline fail (без новых); lint:routes 0; все node --check OK.
  • Phase 4 реализован (pending review): фирменные квантовые способности + SR-связка, ВСЁ через безопасную модель (движок _sim_engine.js НЕ тронут). Новый frontend/js/game/quantik-abilities.js: window.QuantikEnergy (клиентский ресурс энергии, localStorage quantik-energy, 0..99; grant/spend/canSpend/rewardForQuality; TUNNEL_COST=3, GOOD=1/EASY=2) + window.QuantikAbilities (mountBar — HUD энергии + кнопки «Повторение/Туннель/Прицел» оверлеем на сцене; openRestRoom — мини-сессия повторения флешкарт в модалке, реюз LS.fcListDecks/fcStudySession/fcReview, НЕ iframe). Туннель = тратит энергию → inst.setParam('tunnel',1); барьер = forbidden-зона wall, fail:'wall.hit && tunnel<1' (tunnel — не слайдер, отсутствует в env → 0 → стена сплошная). Прицел = пауза-тоггл над пунктир-plot предсказанной траектории. Суперпозиция = чистый контент: 2 тела ball+ball2, goal.when с обоими. Глава quantum (L12L16) + CHAPTERS.quantum в levels.js; карта рисует автоматически (map.js не тронут). js/api.js +2 врапера (fcStudySession, fcReview). quantik.html +script-тег +CSS .qa-*. Backend НЕ тронут. Все node --check OK (вкл. инлайн quantik.html); headless vm-смоук (РЕАЛЬНЫЕ движки): энергия + суперпозиция-оба-тела + tunnel-flips-fail + per-level solvability sweep (5/5 выигрываемы, full-star достижим, L15/L16 без tunnel = 0 win) + регресс 11 существующих уровней — 48/48, удалён. Контент-фикс: монета L16 (5,6)r0.7 → (5,6.9)r0.85 (была несовместима со 2-й звездой k≥6.8). npm test 261 / 253 pass / 8 baseline fail (без новых); lint:routes 0.

Key Architecture Decisions

  • «Атом» = блок goal в спеке (булево SimExpr). Любой уровень = спека SimForge + goal. Движок вычисляет goal.when каждый кадр; победа → result + callback. Нет goal → no-op.
  • Уровни хранятся в custom_sims (cat='game'), а не в новой таблице. Реюз авторинга/шаринга/embed. Новые таблицы — только под ПРОГРЕСС игрока и лидерборд (мигр.).
    • Уточнение Ф1: для MVP уровни — ВСТРОЕННЫЕ ДАННЫЕ в frontend/js/game/levels.js (window.QuantikLevels, форма { id, title, subject?, hint?, spec }), а не записи custom_sims. custom_sims cat='game' остаётся целевым хранилищем для авторённых уровней (Ф5); реестр тогда станет асинхронным (загрузка опубликованных + слияние со встроенными той же формы записи).
  • Герой Квантик: в уровне = engine point с body + glow + trail (визуал P2). На карте/в диалогах = PetSprite.render(level, mood, accessories, colorKey, streak, pattern) (DOM SVG).
  • Управление = чинить закон, а не WASD: игрок крутит params-слайдеры движка (угол/скорость/ гравитация) или собирает f(x); затем «Запуск» — симуляция проигрывается к цели.
  • Безопасность: цвета — только в canvas-стоки; текст спеки — escape (& < >); выражения — только длина на сервере, исполняет безопасный SimExpr на клиенте.

Engine touch-points (Phase 0)

  • Спека v1 формат — в шапке _sim_engine.js. Добавить goal/game СЮДА (документировать).
  • rAF-цикл _renderFrame (вычисляет env). Добавить _evalGoal() после построения env.
  • mount() возвращает инстанс — добавить onGoal, getResult, resetResult.
  • HUD — DOM-оверлей _labelLayer/новый слой (как readout-бейджи). Без эмодзи, inline SVG.
  • Серверный гейт customSimController.validateSpec (:93) — разрешить goal/stars/hint/game.

Cross-Phase Dependencies

  • Phase 1+ зависят от goal/getResult/onGoal из Phase 0.
  • Phase 2 (XP/скины) зависит от прогресса Phase 1.
  • Phase 4 (туннелирование) зависит от флешкарт-SR API.
  • Phase 5 (авторинг) трогает sim-builder — к этому моменту чужой P4-WIP должен быть смержен в sim-builder; свериться перед стартом фазы (возможен мерж base-ветки).
  • Phase 6 (живая гонка) зависит от моста sim_state (Ф7 sim-builder) — он на base-ветке.

Temporary Workarounds

(пока нет)

Phase 0 — API/гочи (для следующих фаз)

  • Движковое API цели: inst.onGoal(cb) (1 раз при победе, cb получает getResult()), inst.getResult(){won,failed,timeMs,attempts,stars:{got,total}} (без goal → null), inst.resetResult() (сброс результата, НЕ считается попыткой). inst.reset() = полный перезапуск уровня + attempts++ (пользовательская попытка; первый авто-reset при mount НЕ считается).
  • HUD появляется автоматически при наличии goal в спеке (отдельного флага «game mode» нет).
  • timeMs = мировое время t от старта (max(1, round(t*1000))), детерминизм; не wallclock.
  • Env цели = весь env кадра + единственный доп.идентификатор tries (= attempts). Других не вводить.
  • Серверный validateSpec принимает goal{when,title,hint,hold,fail,stars≤3} и game{...} (резерв Ф1/5); выражения не исполняются (только длина ≤500), текст escape+обрезка.
  • Победа делает pause() в кадре; следующий queued-rAF выходит рано → onGoal не задвоится.

Open Questions / Notes

  • Категория cat='game' — проверить список CATS в customSimController.js, расширить при необходимости.
  • Ассеты: разрешены CC0/открытые из интернета (выбор пользователя) — фиксировать источник+лицензию в коммите/доке; визуальная база остаётся in-house (PetSprite/canvas/FLUX).
  • Маршрут страницы игры: clean URL /quantik (паттерн /sim-builder, /lab).