refactor: distribute lab-init.js into 34 engine files

lab-init.js: 4098 -> 543 lines (infrastructure + THEORY only)

Each sim's _open*() + UI helpers moved to its engine file:
graph.js, projectile.js, collision.js, magnetic.js, triangle.js,
geometry.js, trigcircle.js, gas.js (molphys), coulomb.js, circuit.js,
reactions.js (chemistry), newton.js (dynamics), chemsandbox.js,
celldivision.js, photosynthesis.js, angrybirds.js, quadratic.js,
normaldist.js, graphtransform.js, pendulum.js, equilibrium.js,
thinlens.js, mirror.js, isoprocess.js, titration.js, refraction.js,
probability.js, bohratom.js, electrolysis.js, waves.js,
crystal.js, orbitals.js, stereo.js, hydrostatics.js

All 34 engine files syntax-checked OK.
This commit is contained in:
Maxim Dolgolyov
2026-05-08 14:54:54 +03:00
parent d5f77bb648
commit ae31e4c4e8
35 changed files with 3657 additions and 3589 deletions
+92 -1
View File
@@ -1,4 +1,4 @@
'use strict';
'use strict';
/* ═══════════════════════════════════════════
WavesSim v2 — Волны и звук
Modes: transverse | longitudinal | superposition | standing
@@ -454,3 +454,94 @@ class WavesSim {
_emit() { if (this.onUpdate) this.onUpdate(this.info()); }
}
/* ─── lab UI init ─────────────────────────────────── */
function _openWaves() {
document.getElementById('sim-topbar-title').textContent = 'Волны и звук';
document.getElementById('ctrl-waves').style.display = '';
_simShow('sim-waves');
_registerSimState('waves', () => wavesSim?.getParams(),
st => { if (wavesSim) { if (st.mode) wavesSim.setMode(st.mode); wavesSim.setParams(st); } });
if (_embedMode) _startStateEmit('waves');
requestAnimationFrame(() => requestAnimationFrame(() => {
if (!wavesSim) {
wavesSim = new WavesSim(document.getElementById('waves-canvas'));
wavesSim.onUpdate = _wavesUpdateUI;
}
wavesSim.fit();
wavesSim.reset();
wavesSim.play();
_wavesUpdateUI(wavesSim.info());
}));
}
function wavesMode(mode, btn) {
document.querySelectorAll('.wave-mode-btn').forEach(b => b.classList.remove('active'));
if (btn) btn.classList.add('active');
document.getElementById('waves-w2-section').style.display = mode === 'superposition' ? '' : 'none';
document.getElementById('waves-n-section').style.display = mode === 'standing' ? '' : 'none';
if (wavesSim) wavesSim.setMode(mode);
}
function wavesParam(name, val) {
const v = parseFloat(val);
const el = (id, txt) => { const e = document.getElementById(id); if (e) e.textContent = txt; };
if (name === 'A1') el('waves-A1-val', v);
if (name === 'f1') el('waves-f1-val', v.toFixed(1) + ' Гц');
if (name === 'phi1') el('waves-phi1-val', v.toFixed(1));
if (name === 'A2') el('waves-A2-val', v);
if (name === 'f2') el('waves-f2-val', v.toFixed(1) + ' Гц');
if (name === 'phi2') el('waves-phi2-val', v.toFixed(1));
if (name === 'speed') el('waves-speed-val', '\u00d7' + v.toFixed(1));
if (wavesSim) wavesSim.setParams({ [name]: v });
}
function wavesN(n, btn) {
document.querySelectorAll('.wave-n-btn').forEach(b => b.classList.remove('active'));
if (btn) btn.classList.add('active');
if (wavesSim) wavesSim.setParams({ n });
}
function wavesPreset(name) {
const presets = {
constructive: { A1: 50, f1: 1.0, phi1: 0, A2: 50, f2: 1.0, phi2: 0 },
destructive: { A1: 50, f1: 1.0, phi1: 0, A2: 50, f2: 1.0, phi2: 3.14 },
beats: { A1: 50, f1: 1.0, phi1: 0, A2: 50, f2: 1.3, phi2: 0 },
};
const p = presets[name]; if (!p) return;
document.getElementById('sl-waves-A1').value = p.A1;
document.getElementById('sl-waves-f1').value = p.f1;
document.getElementById('sl-waves-phi1').value = p.phi1;
document.getElementById('sl-waves-A2').value = p.A2;
document.getElementById('sl-waves-f2').value = p.f2;
document.getElementById('sl-waves-phi2').value = p.phi2;
document.getElementById('waves-A1-val').textContent = p.A1;
document.getElementById('waves-f1-val').textContent = p.f1.toFixed(1) + ' Гц';
document.getElementById('waves-phi1-val').textContent = p.phi1.toFixed(1);
document.getElementById('waves-A2-val').textContent = p.A2;
document.getElementById('waves-f2-val').textContent = p.f2.toFixed(1) + ' Гц';
document.getElementById('waves-phi2-val').textContent = p.phi2.toFixed(1);
if (wavesSim) wavesSim.setParams({ A1: p.A1, f1: p.f1, phi1: p.phi1, A2: p.A2, f2: p.f2, phi2: p.phi2 });
}
function wavesPlayPause() {
if (!wavesSim) return;
const btn = document.getElementById('waves-play-btn');
if (wavesSim._paused) {
wavesSim.play();
btn.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/></svg>';
} else {
wavesSim.pause();
btn.innerHTML = '<svg viewBox="0 0 24 24" fill="currentColor"><polygon points="5 3 19 12 5 21 5 3"/></svg>';
}
}
function _wavesUpdateUI(info) {
const v = (id, val) => { const e = document.getElementById(id); if (e) e.textContent = val; };
v('wavesbar-T', info.T);
v('wavesbar-lam', info.lambda);
v('wavesbar-v', info.v);
v('wavesbar-f', (+info.f1).toFixed(1));
}
/* ── crystal lattice (3D) ── */