201e94ea81
Два 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>
110 lines
5.9 KiB
JavaScript
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'
|
|
};
|
|
})();
|