@
feat(quantik-game): фаза 5 — авторинг игровых уровней в sim-builder + раздача Учитель собирает игровой уровень без кода: новая (аддитивная, сворачиваемая) панель в sim-builder задаёт блок goal (when/title/hint/hold/fail) + до 3 звёзд + game-мету (chapter/order/par_ms); выражения проверяются inline через SimExpr.compile (без eval). buildSpec/loadFromSim — round-trip без потерь (goal/game пишутся только при включённом слое; обычная sim не меняется). Кнопка «Играть» монтирует черновик в SimEngine-модалке (HUD цели из Ф0). QuantikLevels стал async: подмешивает custom_sims cat=game (свои+ published) в реестр (custom:<dbid>), offline-safe, строки без goal отбрасываются; deep-link /quantik?level=custom:<id> с серверной проверкой доступа (own|published → иначе 403/404), мимо геймплейного гейта unlockStars. Раздача классу — реюз share Ф6 (game-aware ссылка + durable pushNotif). Правки sim-builder строго аддитивны (параллельная сессия). npm test 259/8 baseline; quantik-authoring 6/6; lint:routes 0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> @
This commit is contained in:
+26
-6
@@ -521,17 +521,37 @@
|
||||
|
||||
backBtn.addEventListener('click', showMap);
|
||||
|
||||
// Подмешать авторённые уровни (custom_sims cat='game') до рендера карты (Ф5).
|
||||
function ensureCustomLevels() {
|
||||
if (window.QuantikLevels.ensureCustom) {
|
||||
return window.QuantikLevels.ensureCustom().catch(function () {});
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// Старт: если ?level=<id> в URL и уровень доступен — открыть его, иначе карта.
|
||||
loadProgress().then(function () {
|
||||
// Сначала грузим прогресс И авторённые уровни (параллельно), затем deep-link.
|
||||
Promise.all([loadProgress(), ensureCustomLevels()]).then(function () {
|
||||
map.render(progressMap);
|
||||
var params = new URLSearchParams(location.search);
|
||||
var wantId = params.get('level');
|
||||
if (wantId) {
|
||||
var lvl = window.QuantikLevels.get(wantId);
|
||||
if (lvl && window.QuantikProgress.isUnlocked(lvl, progressMap, window.QuantikLevels.list())) {
|
||||
openLevel(lvl);
|
||||
return;
|
||||
}
|
||||
// custom:<id> может быть свой draft (нет в списке) — резолвим асинхронно с
|
||||
// проверкой доступа на сервере (own|published|admin → иначе 404/403 → карта).
|
||||
var resolve = window.QuantikLevels.getAsync
|
||||
? window.QuantikLevels.getAsync(wantId)
|
||||
: Promise.resolve(window.QuantikLevels.get(wantId));
|
||||
resolve.then(function (lvl) {
|
||||
// Авторённый уровень (deep-link) — открываем без гейта unlockStars
|
||||
// (учитель/получатель ссылки заходит прямо в него). Встроенный — как раньше.
|
||||
var isCustom = /^custom:/.test(wantId);
|
||||
if (lvl && (isCustom || window.QuantikProgress.isUnlocked(lvl, progressMap, window.QuantikLevels.list()))) {
|
||||
openLevel(lvl);
|
||||
} else {
|
||||
showMapNoReload();
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
showMapNoReload();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user