@
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:
@@ -454,17 +454,24 @@ function share(req, res) {
|
||||
}
|
||||
|
||||
const teacherName = (db.prepare('SELECT name FROM users WHERE id = ?').get(req.user.id) || {}).name || 'Учитель';
|
||||
const simTitle = row.title || 'симуляция';
|
||||
const link = '/lab?sim=custom:' + row.id;
|
||||
const isGame = row.cat === 'game';
|
||||
const simTitle = row.title || (isGame ? 'игровой уровень' : 'симуляция');
|
||||
// Игровой уровень открывается в «Квантике» (/quantik?level=custom:<id>),
|
||||
// обычная симуляция — в лаборатории (/lab?sim=custom:<id>). Фаза 5/6.
|
||||
const link = (isGame ? '/quantik?level=custom:' : '/lab?sim=custom:') + row.id;
|
||||
const notifType = isGame ? 'game_level_shared' : 'sim_shared';
|
||||
const notifMsg = isGame
|
||||
? `Новый игровой уровень от ${teacherName}: «${simTitle}»`
|
||||
: `Новая симуляция от ${teacherName}: «${simTitle}»`;
|
||||
const recipients = db.prepare('SELECT user_id FROM class_members WHERE class_id = ?').all(classId).map(r => r.user_id);
|
||||
|
||||
let sent = 0;
|
||||
for (const uid of recipients) {
|
||||
if (!uid || uid === req.user.id) continue;
|
||||
pushNotif(uid, 'sim_shared', `Новая симуляция от ${teacherName}: «${simTitle}»`, link);
|
||||
pushNotif(uid, notifType, notifMsg, link);
|
||||
sent++;
|
||||
}
|
||||
res.json({ ok: true, sent, status: 'published' });
|
||||
res.json({ ok: true, sent, status: 'published', link });
|
||||
}
|
||||
|
||||
/* POST /api/custom-sims/:id/clone — копия спеки текущему пользователю как draft.
|
||||
|
||||
Reference in New Issue
Block a user