Files
Learn_System/frontend/js/labs/_register-all.js
T
Maxim Dolgolyov 201e94ea81 fix(lab-content-engine): phase 3 - устранён блокер ревью (loader не был подключён)
Два edit'а Фазы 3 не применились в fc1139f (упали по отступу), запушив
сломанное состояние: lab.html убрал eager sim-скрипты, но open остался
синхронным -> ReferenceError при клике на любую симуляцию кроме graph.

ИСПРАВЛЕНО:
- _register-all.js: open-обёртка LabLoader.ensure(id).then(rawOpen) + sync-фолбэк
- lab-init.js openSim: обработка Promise от open() (.then -> lucide, .catch -> log)

E2E vm-harness: click->ensure->load->rawOpen после загрузки; pendulum/stereo:cube/
molphys(4 файла)/alias magnetic — ALL PASS; node --check OK.
Независимое ревью поймало этот блокер.

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

110 lines
5.9 KiB
JavaScript

'use strict';
/*
* Контент-движок, Фаза 1 — data-driven регистрация ВСЕХ симуляций в LabRegistry.
*
* Вместо ручного переписывания 40 манифестов модуль строит их из единых источников:
* - метаданные (id/cat/title/desc) и preview — из массива SIMS (lab-glue.js);
* - теория — из объекта THEORY (lab-init.js);
* - поведение open(ctx) — из карты OPEN ниже (обёртки над глобальными _openXxx).
* Это структурно гарантирует паритет с прежним каталогом и диспетчеризацией.
*
* Подключается ПОСЛЕДНИМ среди labs-скриптов (defer), поэтому SIMS, THEORY и все
* _openXxx уже определены. Останов/закрытие симуляций по-прежнему выполняет
* «дробовик» _pauseAllSims()/closeSim() (точный паритет) — поэтому stop/destroy
* в манифестах не задаются на этом этапе.
*
* После регистрации if-цепочка в openSim() становится мёртвой и удалена.
*
* В Фазе 1 заменил пилотный _pilots.js. SIMS/THEORY остаются источниками данных
* (SIMS → БД в Фазе 4, THEORY сворачивается в манифесты позже).
*/
(function () {
if (!window.LabRegistry) return;
if (typeof SIMS === 'undefined') return;
var R = window.LabRegistry;
var T = (typeof THEORY !== 'undefined') ? THEORY : {};
// id -> open(ctx). ctx.arg — параметр deep-link (после двоеточия): stereo:cube и т.п.
var OPEN = {
graph: function (c) { _openGraph(); },
projectile: function (c) { _openProjectile(); },
collision: function (c) { _openCollision(); },
triangle: function (c) { _openTriangle(); },
trigcircle: function (c) { _openTrigCircle(); },
emfield: function (c) { _openEMField(c.arg || 'E'); },
molphys: function (c) { _openMolPhys(c.arg); },
circuit: function (c) { _openCircuit(); },
chemistry: function (c) { _openChemistry(c.arg); },
dynamics: function (c) { _openDynamics(c.arg); },
crystal: function (c) { _openCrystal(); },
orbitals: function (c) { _openOrbitals(); },
stereo: function (c) { _openStereo(c.arg); },
chemsandbox: function (c) { _openChemSandbox(); },
celldivision: function (c) { _openCellDivision(); },
photosynthesis: function (c) { _openPhotosynthesis(); },
angrybirds: function (c) { _openAngryBirds(); },
quadratic: function (c) { _openQuadratic(); },
normaldist: function (c) { _openNormalDist(); },
graphtransform: function (c) { _openGraphTransform(); },
pendulum: function (c) { _openPendulum(); },
equilibrium: function (c) { _openEquilibrium(); },
opticsbench: function (c) { _openOpticsBench(c.arg || 'lens'); },
isoprocess: function (c) { _openIsoprocess(); },
titration: function (c) { _openTitration(); },
probability: function (c) { _openProbability(); },
bohratom: function (c) { _openBohrAtom(); },
electrolysis: function (c) { _openElectrolysis(); },
race: function (c) { _openRace(); },
waves: function (c) { _openWaves(); },
hydrostatics: function (c) { _openHydro(c.arg); },
radioactive: function (c) { _openRadioactive(); },
geometry: function (c) { _openGeometry(); },
logic: function (c) { _openLogic(); },
heatengine: function (c) { _openHeatEngine(); },
stoichiometry: function (c) { _openStoich(); },
qualanalysis: function (c) { _openQualAnalysis(); },
periodic: function (c) { _openPeriodic(); },
organic: function (c) { _openOrganic(); },
solutions: function (c) { _openSolutions(); }
};
SIMS.forEach(function (s) {
if (!s.id) return; // "Скоро" — карточка без id
var open = OPEN[s.id];
if (!open) { // подстраховка: незамапленный id оставляем legacy-пути
if (window.console) console.warn('[LabRegistry] нет open() для', s.id);
return;
}
R.register({
id: s.id,
cat: s.cat,
title: s.title,
desc: s.desc,
preview: s.preview, // уже готовая SVG-строка (P_* вычислены в SIMS)
theory: T[s.id] || null,
// Фаза 3: ленивая загрузка кода. LabLoader.ensure(id) подгружает файлы
// симуляции (+ three.js при необходимости), затем выполняется raw-open.
// Если LabLoader недоступен — открываем синхронно как раньше (фолбэк).
open: (function (rawOpen, simId) {
return function (c) {
if (window.LabLoader && window.LabLoader.ensure) {
return window.LabLoader.ensure(simId).then(function () { rawOpen(c); });
}
rawOpen(c);
};
})(open, s.id)
// stop/destroy: глобальный «дробовик» _pauseAllSims()/closeSim() — паритет
});
});
// Алиасы deep-link → канонический id[:arg]. Диспетчер openSim() нормализует их
// перед обращением к реестру (карточек у алиасов нет — только прямые ссылки).
window.LAB_SIM_ALIASES = {
magnetic: 'emfield:B',
coulomb: 'emfield:E',
thinlens: 'opticsbench:lens',
mirrors: 'opticsbench:mirror',
refraction: 'opticsbench:refraction'
};
})();