Files
Learn_System/plans/quantik-game/phase-1-shell-first-level.md
T
Maxim Dolgolyov 4b5c8077d3 @
feat(quantik-game): фаза 0 — слой целей в движке (goal/HUD/result)

Декларативный блок goal в спеке SimForge (булево SimExpr-условие победы),
вычисляемый каждый кадр: фиксация результата (победа/время/попытки/звёзды),
callback onGoal, HUD-оверлей (цель/звёзды/подсказка/баннер, inline SVG).
API инстанса: onGoal/getResult/resetResult. Серверный validateSpec
пропускает goal/game (длина выражений + escape текста, без исполнения).
Аддитивно: спека без goal ведёт себя как раньше. Смоук 40/40; npm test
238 pass/8 baseline; lint:routes 0. План фичи (7 фаз) + CONTEXT.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@
2026-06-13 15:13:02 +03:00

5.6 KiB
Raw Blame History

Phase 1: Оболочка игры + 1 физ-уровень + прогресс (MVP)

Status: Not Started Parent plan: PLAN.md Domain: fullstack

Objective

Сквозной играбельный срез: страница /quantik грузит уровень-спеку, монтирует движок в «игровом режиме» (управление = слайдеры закона + кнопка «Запуск»), на победу шлёт результат на сервер, показывает экран успеха со звёздами/временем. Прогресс сохраняется в БД. Первый уровень — «Артиллерия Квантика»: угол+скорость, попасть в портал, собрать звезду.

Tasks

  • Task 1: Миграция (следующий свободный номер) game_progress: id, user_id, level_id TEXT, best_time_ms INTEGER, best_stars INTEGER, attempts INTEGER, completed_at. Индекс по (user_id, level_id) UNIQUE.
  • Task 2: Контроллер gameController.js + роутер game.js, смонтировать в server.js (после /api/custom-sims). Эндпоинты: GET /api/game/progress (свой прогресс по всем уровням), POST /api/game/progress {level_id, time_ms, stars} (upsert: пишем лучший результат — min time / max stars; attempts++). auth-only; валидация входа.
  • Task 3: Клиент LS.gameProgressList() / LS.gameProgressSubmit(levelId, {time_ms, stars}) в js/api.js.
  • Task 4: Уровень как ДАННЫЕ: модуль frontend/js/game/levels.js (или сид в custom_sims). Для MVP — встроенная спека уровня phys-artillery-1 (physics + goal + 1 star + portal/star объекты). Решение источника уровней зафиксировать в CONTEXT.md (встроенные данные сейчас; custom_sims в Ф5).
  • Task 5: Страница frontend/quantik.html + frontend/js/game/quantik-game.js: доступ всем авторизованным (LS.initPage()); подключает _sim_expr.js+_sim_engine.js тем же путём, что lab.html/sim-builder.html. Монтирует уровень, ставит onGoal → submit + экран успеха.
  • Task 6: «Игровой режим» движка/обёртки: цель видна (HUD из Ф0), управление = существующие слайдеры params; кнопки «Запуск»(play)/«Сброс»(reset). Без редакторских панелей.
  • Task 7: Экран успеха (DOM-оверлей страницы): звёзды, время, попытки, кнопки «Ещё раз»/«Дальше» (для MVP «Дальше» неактивна/возврат). Inline SVG, без эмодзи.
  • Task 8: Пункт в сайдбаре js/sidebar.js/quantik в группе practice (по примеру /sim-builder), видимость по роли (доступно ученикам — это игра). isActive('/quantik') подсветка.
  • Task 9: Тест бэкенда backend/tests/game.test.js (паттерн lab-links.test.js: свой app.use нового роутера, getToken/inject): submit пишет лучший результат, не ухудшает, attempts++, требует auth, валидирует вход. Headless-смоук страницы по возможности (vm + стаб), иначе ручная проверка логики.

Files to Modify/Create

  • backend/src/db/migrations/0NN_game_progress.sql — таблица прогресса.
  • backend/src/controllers/gameController.js, backend/src/routes/game.js — API.
  • backend/src/server.js — монтаж роутера.
  • frontend/quantik.html, frontend/js/game/quantik-game.js, frontend/js/game/levels.js — клиент+уровень.
  • frontend/js/api.jsLS.gameProgress*.
  • frontend/js/sidebar.js — пункт меню.
  • backend/tests/game.test.js — тест.

Acceptance Criteria

  • /quantik грузится, монтирует уровень, цель видна; «Запуск» проигрывает физику.
  • Попадание в портал (+звезда) → экран успеха с временем/звёздами; результат записан в game_progress.
  • Повторный худший результат не перезаписывает лучший; attempts растёт.
  • npm run migrate применяет миграцию; npm test зелёный (+ новый тест); lint:routes baseline 0.

Notes

  • Маршрутизация /js/game/*: помнить гочу sim-builder — /js мапится на корневой js/, а файлы лежат во frontend/js/game/ → отдаются через express.static(frontendDir). Не трогать server.js static.
  • Роуты :id прикрыть authMiddleware на уровне роутера (lint:routes baseline 0).
  • Время — из getResult().timeMs (Ф0).

Review Checklist

  • Все задачи; конвенции (ownership/auth как studentMaterials/customSim); без эмодзи/eval
  • Миграция применяется; API безопасен; тест зелёный; lint baseline 0; existing тесты не сломаны

Handoff to Next Phase