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>
This commit is contained in:
Maxim Dolgolyov
2026-05-30 18:12:55 +03:00
parent 6c1e003340
commit 5381679c68
55 changed files with 10203 additions and 305 deletions
+73
View File
@@ -0,0 +1,73 @@
const fs = require('fs');
const path = require('path');
const dir = path.join(__dirname, '..', '..', 'frontend', 'textbooks');
const files = ['geometry_10_r1.html','geometry_10_r2.html','geometry_10_r3.html','geometry_10_r4.html'];
console.log('SECTION CONTENT STRUCTURE:');
for (const f of files) {
const txt = fs.readFileSync(path.join(dir, f), 'utf8');
// teor1/teor2/teor3 occurrences
const teor = (txt.match(/teor[123]/g) || []).length;
const int1234 = (txt.match(/int[1234]/g) || []).length;
// viz blocks
const viz = (txt.match(/viz[1234]|svg-/g) || []).length;
// readBtn / btnRead
const readBtn = (txt.match(/btnRead|readBtn|markRead|done-read|read-mark/g) || []).length;
const yaProch = (txt.match(/Я прочитал/g) || []).length;
// Sections in render
const renderSections = (txt.match(/renderSection|renderPart|sect\.id/g) || []).length;
console.log(' ' + f);
console.log(' teor1/2/3:', teor, ' int1-4:', int1234, ' viz:', viz);
console.log(' readBtn-related:', readBtn, ' "Я прочитал":', yaProch, ' renderSection:', renderSections);
}
// Final course in hub
console.log('\\nHUB - course final mention:');
const hub = fs.readFileSync(path.join(dir,'geometry_10_hub.html'),'utf8');
console.log(' "Финал курса":', (hub.match(/Финал курса/g)||[]).length);
console.log(' "финал" (any):', (hub.match(/финал/gi)||[]).length);
// Triangle/3D shape labels - look for projection helpers
console.log('\\n3D PROJECTION HELPERS in r1-r4:');
for (const f of files) {
const txt = fs.readFileSync(path.join(dir, f), 'utf8');
const hasProject = /function\s+project|proj\s*=\s*\(/.test(txt);
const has3DPoints = /\{x:[^}]+y:[^}]+z:/.test(txt) || /\[\s*[0-9.-]+\s*,\s*[0-9.-]+\s*,\s*[0-9.-]+\s*\]/.test(txt);
const hasIso = /isoP|isometric|axonom/.test(txt);
console.log(' ' + f + ' project()=' + hasProject + ' 3DPoints=' + has3DPoints + ' iso=' + hasIso);
}
// Check pixel literals in SVG text labels
console.log('\\nSVG <text> labels with px-like values:');
for (const f of files) {
const txt = fs.readFileSync(path.join(dir, f), 'utf8');
// crude pattern: text content like "R = 120" "a = 80" etc
const re = />([A-Za-zА-Яа-я]\s*=\s*\d{2,3})\s*</g;
let m, cnt=0;
while ((m = re.exec(txt)) !== null) {
cnt++;
if (cnt <= 6) {
const line = (txt.slice(0,m.index).match(/\n/g)||[]).length+1;
console.log(' ' + f + ' line '+line+': '+m[1]);
}
}
if (cnt) console.log(' -> total in ' + f + ': ' + cnt);
}
// Sample around final/interactive in r1 to see structure
console.log('\\n--- r1 sample around interactives ---');
const r1 = fs.readFileSync(path.join(dir,'geometry_10_r1.html'),'utf8');
// Find "3 эталонных" or "эталонных" labels mismatch
const ets = [...r1.matchAll(/(\d+)\s+эталонн/g)];
for (const e of ets) {
const line = (r1.slice(0,e.index).match(/\n/g)||[]).length+1;
console.log(' r1 line '+line+': "'+r1.slice(e.index, e.index+60).replace(/\n/g,' ')+'"');
}
for (const f of files) {
const txt = fs.readFileSync(path.join(dir, f), 'utf8');
const ets = [...txt.matchAll(/(\d+)\s+эталонн/g)];
for (const e of ets) {
const line = (txt.slice(0,e.index).match(/\n/g)||[]).length+1;
console.log(' ' + f + ' line '+line+': "'+txt.slice(e.index, e.index+60).replace(/\n/g,' ')+'"');
}
}