Files
Learn_System/backend/scripts/patch_interfsim2.js
T
Maxim Dolgolyov 5381679c68 chore: консолидация незакоммиченной работы (биохимия + System Health + lab/textbooks)
Зафиксирована накопленная незакоммиченная работа рабочего дерева, КРОМЕ файлов
учебника «Химия 7» (migration 046, chemistry_7_*.html, chem7_svg.js, тест —
оставлены незакоммиченными по запросу).

Включает: модуль биохимии (ядро BIO, 3D VSEPR, химдвижок, баланс, challenges,
пути из БД), System Health Level 1 (вердикт/мониторинг), а также frontend-
страницы и lab/textbooks-правки параллельной сессии.

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

236 lines
11 KiB
JavaScript

'use strict';
const fs = require('fs');
const path = require('path');
const targetFile = path.join(__dirname, '../../frontend/js/labs/opticsbench.js');
let src = fs.readFileSync(targetFile, 'utf-8');
// --- 1. Add ifSim variable declaration after freeSim ---
if (src.indexOf('var ifSim') < 0) {
src = src.replace(
'var freeSim = null; /* multi-lens free-build (Agent OB-A3) */',
'var freeSim = null; /* multi-lens free-build (Agent OB-A3) */\r\nvar ifSim = null; /* interference/polarization (Agent C) */'
);
console.log('Added ifSim declaration');
} else {
console.log('ifSim declaration already exists');
}
// --- 2. Add 'interf' to tab array in obSwitchMode ---
const tabArrOld = "['lens', 'mirror', 'refraction', 'prism', 'freebuild', 'waves'].forEach(m => {";
const tabArrNew = "['lens', 'mirror', 'refraction', 'prism', 'freebuild', 'waves', 'interf'].forEach(m => {";
if (src.indexOf(tabArrNew) < 0) {
if (src.indexOf(tabArrOld) >= 0) {
src = src.replace(tabArrOld, tabArrNew);
console.log('Updated tab array');
} else {
console.log('WARN: tab array old pattern not found');
}
} else {
console.log('Tab array already updated');
}
// --- 3. Add 'ob-ctrl-interf' to control panels array ---
const ctrlArrOld = "['ob-ctrl-lens', 'ob-ctrl-mirror', 'ob-ctrl-refraction', 'ob-ctrl-prism', 'ob-ctrl-freebuild', 'ob-ctrl-waves'].forEach(id => {";
const ctrlArrNew = "['ob-ctrl-lens', 'ob-ctrl-mirror', 'ob-ctrl-refraction', 'ob-ctrl-prism', 'ob-ctrl-freebuild', 'ob-ctrl-waves', 'ob-ctrl-interf'].forEach(id => {";
if (src.indexOf(ctrlArrNew) < 0) {
if (src.indexOf(ctrlArrOld) >= 0) {
src = src.replace(ctrlArrOld, ctrlArrNew);
console.log('Updated ctrl panel array');
} else {
console.log('WARN: ctrl panel array old pattern not found');
}
} else {
console.log('Ctrl panel array already updated');
}
// --- 4. Add 'ob-stats-interf' to stats array ---
const statsArrOld = "['ob-stats-lens', 'ob-stats-mirror', 'ob-stats-refr', 'ob-stats-prism', 'ob-stats-freebuild', 'ob-stats-waves'].forEach(id => {";
const statsArrNew = "['ob-stats-lens', 'ob-stats-mirror', 'ob-stats-refr', 'ob-stats-prism', 'ob-stats-freebuild', 'ob-stats-waves', 'ob-stats-interf'].forEach(id => {";
if (src.indexOf(statsArrNew) < 0) {
if (src.indexOf(statsArrOld) >= 0) {
src = src.replace(statsArrOld, statsArrNew);
console.log('Updated stats array');
} else {
console.log('WARN: stats array old pattern not found');
}
} else {
console.log('Stats array already updated');
}
// --- 5. Add 'ob-interf-canvas' to canvas arrays ---
const canvasIdsOld = "const canvasIds = ['ob-lens-canvas', 'ob-mirror-canvas', 'ob-refr-canvas', 'ob-prism-canvas', 'ob-free-canvas', 'ob-waves-canvas'];";
const canvasIdsNew = "const canvasIds = ['ob-lens-canvas', 'ob-mirror-canvas', 'ob-refr-canvas', 'ob-prism-canvas', 'ob-free-canvas', 'ob-waves-canvas', 'ob-interf-canvas'];";
if (src.indexOf(canvasIdsNew) < 0) {
if (src.indexOf(canvasIdsOld) >= 0) {
src = src.replace(canvasIdsOld, canvasIdsNew);
console.log('Updated canvasIds');
} else {
console.log('WARN: canvasIds old pattern not found');
}
} else {
console.log('canvasIds already updated');
}
const modeCanvasOld = "const modeCanvas = { lens: 'ob-lens-canvas', mirror: 'ob-mirror-canvas', refraction: 'ob-refr-canvas', prism: 'ob-prism-canvas', freebuild: 'ob-free-canvas', waves: 'ob-waves-canvas' };";
const modeCanvasNew = "const modeCanvas = { lens: 'ob-lens-canvas', mirror: 'ob-mirror-canvas', refraction: 'ob-refr-canvas', prism: 'ob-prism-canvas', freebuild: 'ob-free-canvas', waves: 'ob-waves-canvas', interf: 'ob-interf-canvas' };";
if (src.indexOf(modeCanvasNew) < 0) {
if (src.indexOf(modeCanvasOld) >= 0) {
src = src.replace(modeCanvasOld, modeCanvasNew);
console.log('Updated modeCanvas');
} else {
console.log('WARN: modeCanvas old pattern not found');
}
} else {
console.log('modeCanvas already updated');
}
// --- 6. Add 'interf' case in obSwitchMode, before closing brace ---
const interfCaseStr = ` } else if (mode === 'interf') { /* Agent C — interference / polarization */\r\n if (!ifSim) {\r\n const cv = document.getElementById('ob-interf-canvas');\r\n if (cv) { ifSim = new InterferenceSim(cv); ifSim.onUpdate = _ifUpdateUI; }\r\n }\r\n if (ifSim) { ifSim.fit(); ifSim.draw(); }\r\n _ifUpdateUI();\r\n }\r\n}`;
const oldModeEnd = ` } else if (mode === 'waves') { /* Agent B1 — diffraction & interference */\r\n if (!diffrSim) {\r\n const cv = document.getElementById('ob-waves-canvas');\r\n if (cv) diffrSim = new DiffractionSim(cv);\r\n }\r\n if (diffrSim) {\r\n diffrSim.fit();\r\n diffrSim.draw();\r\n diffrSim._updateHUD();\r\n }\r\n }\r\n}`;
const newModeEnd = ` } else if (mode === 'waves') { /* Agent B1 — diffraction & interference */\r\n if (!diffrSim) {\r\n const cv = document.getElementById('ob-waves-canvas');\r\n if (cv) diffrSim = new DiffractionSim(cv);\r\n }\r\n if (diffrSim) {\r\n diffrSim.fit();\r\n diffrSim.draw();\r\n diffrSim._updateHUD();\r\n }\r\n } else if (mode === 'interf') { /* Agent C — interference / polarization */\r\n if (!ifSim) {\r\n const cv = document.getElementById('ob-interf-canvas');\r\n if (cv) { ifSim = new InterferenceSim(cv); ifSim.onUpdate = _ifUpdateUI; }\r\n }\r\n if (ifSim) { ifSim.fit(); ifSim.draw(); }\r\n _ifUpdateUI();\r\n }\r\n}`;
if (src.indexOf('else if (mode === \'interf\')') < 0) {
if (src.indexOf(oldModeEnd) >= 0) {
src = src.replace(oldModeEnd, newModeEnd);
console.log('Added interf case in obSwitchMode');
} else {
// Try with LF only
const oldLF = oldModeEnd.replace(/\r\n/g, '\n');
const newLF = newModeEnd.replace(/\r\n/g, '\n');
if (src.indexOf(oldLF) >= 0) {
src = src.replace(oldLF, newLF);
console.log('Added interf case (LF variant)');
} else {
console.log('WARN: waves mode end pattern not found - trying fallback');
// Fallback: find closing brace of obSwitchMode after diffrSim block
const marker2 = "diffrSim._updateHUD();\n }\n }\n}";
const marker2cr = "diffrSim._updateHUD();\r\n }\r\n }\r\n}";
const repl2 = "diffrSim._updateHUD();\n }\n } else if (mode === 'interf') {\n if (!ifSim) {\n const cv = document.getElementById('ob-interf-canvas');\n if (cv) { ifSim = new InterferenceSim(cv); ifSim.onUpdate = _ifUpdateUI; }\n }\n if (ifSim) { ifSim.fit(); ifSim.draw(); }\n _ifUpdateUI();\n }\n}";
const repl2cr = "diffrSim._updateHUD();\r\n }\r\n } else if (mode === 'interf') {\r\n if (!ifSim) {\r\n const cv = document.getElementById('ob-interf-canvas');\r\n if (cv) { ifSim = new InterferenceSim(cv); ifSim.onUpdate = _ifUpdateUI; }\r\n }\r\n if (ifSim) { ifSim.fit(); ifSim.draw(); }\r\n _ifUpdateUI();\r\n }\r\n}";
if (src.indexOf(marker2) >= 0) {
src = src.replace(marker2, repl2);
console.log('Added interf case (fallback LF)');
} else if (src.indexOf(marker2cr) >= 0) {
src = src.replace(marker2cr, repl2cr);
console.log('Added interf case (fallback CRLF)');
} else {
console.log('WARN: all fallbacks failed for interf case');
}
}
}
} else {
console.log('interf case already exists');
}
// --- 7. Add _ifUpdateUI function and control functions ---
const ifUICode = `
/* ── Interference mode UI callbacks (Agent C) ── */
function _ifUpdateUI() {
if (!ifSim) return;
const subMode = ifSim.subMode;
['if-ctrl-newton', 'if-ctrl-thinfilm', 'if-ctrl-polarization'].forEach(id => {
const el = document.getElementById(id);
if (el) el.style.display = 'none';
});
const active = document.getElementById('if-ctrl-' + subMode);
if (active) active.style.display = '';
['if-sub-newton', 'if-sub-thinfilm', 'if-sub-polarization'].forEach(id => {
const el = document.getElementById(id);
if (el) el.classList.toggle('active', id === 'if-sub-' + subMode);
});
}
function ifSwitchSub(sub) {
if (window.LabFX) LabFX.sound.play('chime');
if (!ifSim) return;
ifSim.setSubMode(sub);
_ifUpdateUI();
}
function ifNewtParam(key, val) {
if (!ifSim) return;
const v = parseFloat(val);
if (key === 'R') { ifSim.nR = v; document.getElementById('if-newton-r-val').textContent = v; }
else if (key === 'nmax') { ifSim.nNmax = Math.round(v); document.getElementById('if-newton-n-val').textContent = Math.round(v); }
ifSim.draw();
}
function ifThinFilmParam(key, val) {
if (!ifSim) return;
const v = parseFloat(val);
if (key === 't') { ifSim.tfT = v; document.getElementById('if-tf-t-val').textContent = v; }
else if (key === 'n') { ifSim.tfN = v; document.getElementById('if-tf-n-val').textContent = v.toFixed(2); }
else if (key === 'theta') { ifSim.tfTheta = v; document.getElementById('if-tf-th-val').textContent = v; }
ifSim.draw();
}
function ifThinFilmPreset(name) {
if (!ifSim) return;
const presets = {
soap: { n: 1.33, label: 'Мыльная плёнка' },
oil: { n: 1.50, label: 'Масло на воде' },
coating: { n: 1.38, label: 'Антибликовое покрытие' },
};
const p = presets[name];
if (!p) return;
ifSim.tfN = p.n;
ifSim.tfPreset = name;
const slN = document.getElementById('sl-if-tf-n');
if (slN) slN.value = p.n;
const lbN = document.getElementById('if-tf-n-val');
if (lbN) lbN.textContent = p.n.toFixed(2);
ifSim.draw();
if (window.LabFX) LabFX.sound.play('chime');
}
function ifPolParam(key, val) {
if (!ifSim) return;
const v = parseFloat(val);
if (key === 'theta') { ifSim.polTheta = v; document.getElementById('if-pol-th-val').textContent = v; }
ifSim.draw();
}
function ifPolSrc(val) {
if (!ifSim) return;
ifSim.polSrc = val;
ifSim.draw();
}
`;
if (src.indexOf('function _ifUpdateUI') < 0) {
// Insert before the closing of the file or before _obRedraw
const insertBefore = 'function _obRedraw()';
const insertIdx = src.indexOf(insertBefore);
if (insertIdx >= 0) {
src = src.slice(0, insertIdx) + ifUICode + '\r\n' + src.slice(insertIdx);
console.log('Added _ifUpdateUI and control functions');
} else {
src = src + '\r\n' + ifUICode;
console.log('Appended _ifUpdateUI at end');
}
} else {
console.log('_ifUpdateUI already exists');
}
// --- 8. Make _obRedraw also redraw ifSim if active ---
const redrawOld = 'function _obRedraw() {';
const redrawNew = 'function _obRedraw() {';
// Find _obRedraw body and add ifSim redraw
if (src.indexOf('if (ifSim && _obMode') < 0) {
const marker3 = "if (prismSim && _obMode === 'prism')";
const repl3 = "if (ifSim && _obMode === 'interf') { ifSim.draw(); }\r\n if (prismSim && _obMode === 'prism')";
const marker3lf = "if (prismSim && _obMode === 'prism')";
if (src.indexOf(marker3) >= 0) {
src = src.replace(marker3, repl3);
console.log('Added ifSim redraw to _obRedraw');
} else {
console.log('WARN: could not find _obRedraw prism marker');
}
}
fs.writeFileSync(targetFile, src, 'utf-8');
console.log('Done. New size:', src.length);