diff --git a/.claude/settings.json b/.claude/settings.json index 2d45084..c151850 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -178,7 +178,21 @@ "Bash(cmd /c \"taskkill /PID 60564 /F\")", "Bash(cmd /c \"taskkill /F /PID 60564 2>&1\")", "Bash(kill -9 60564)", - "Bash(kill -9 9313)" + "Bash(kill -9 9313)", + "Read(//f/!Рабочие/ЦТ/Математика/**)", + "Read(//f/!Рабочие/ЦТ/Физика/**)", + "Read(//f/!����稥/��/��⥬�⨪�/**)", + "PowerShell(Get-ChildItem \"F:\\\\!Рабочие\\\\ЦТ\\\\Математика\\\\Математика\\\\ЦТ-ЦЭ\" | Select-Object Name, @{N='MB';E={[math]::Round\\($_.Length/1MB,1\\)}} | Format-Table -AutoSize)", + "Read(//f/!����稥/��/**)", + "PowerShell(Get-ChildItem \"F:\\\\!Рабочие\\\\ЦТ\\\\Физика\\\\Сборники ЦЭ,ЦТ-20260116T125835Z-3-001\" | Select-Object Name, @{N='MB';E={[math]::Round\\($_.Length/1MB,1\\)}} | Format-Table -AutoSize)", + "PowerShell(Get-ChildItem \"F:\\\\!Рабочие\\\\ЦТ\\\\Физика\\\\Сборники ЦТ-20260116T130104Z-3-001\" | Select-Object Name, @{N='MB';E={[math]::Round\\($_.Length/1MB,1\\)}} | Format-Table -AutoSize)", + "PowerShell(Get-ChildItem \"F:\\\\!Рабочие\\\\ЦТ\\\\Физика\\\\Сборники ЦЭ,ЦТ-20260116T125835Z-3-001\\\\Сборники ЦЭ,ЦТ\" | Select-Object Name, @{N='MB';E={[math]::Round\\($_.Length/1MB,1\\)}} | Format-Table -AutoSize)", + "PowerShell(Get-ChildItem \"F:\\\\!Рабочие\\\\ЦТ\\\\Физика\\\\Сборники ЦТ-20260116T130104Z-3-001\\\\Сборники ЦТ\" | Select-Object Name, @{N='MB';E={[math]::Round\\($_.Length/1MB,1\\)}} | Format-Table -AutoSize)", + "Bash(git commit -m ' *)", + "Bash(git push *)", + "Bash(curl -s http://localhost:3000/api/subjects)", + "PowerShell(\\(Get-Content \"g:\\\\Dev\\\\Тесты\\\\BQ-System\\\\frontend\\\\question-bank.html\"\\).Count)", + "Bash(curl -s \"http://localhost:3000/api/subjects/math/topics\" -H \"Authorization: Bearer test\")" ], "additionalDirectories": [ "\\tmp" diff --git a/backend/scripts/audit_chem8.js b/backend/scripts/audit_chem8.js new file mode 100644 index 0000000..8b40bff --- /dev/null +++ b/backend/scripts/audit_chem8.js @@ -0,0 +1,110 @@ +/* audit_chem8.js — аудит KaTeX и оформления учебника «Химия 8». + * Загружает каждую страницу в jsdom (renderMathInElement застаблен → $…$ остаются + * литералами с уже раскрытыми JS-эскейпами), строит все §, извлекает формулы и + * проверяет: баланс $, баланс {}, отсутствие управляющих символов (следы \t/\n), + * пустые формулы, «сырые» $…$ вне рендера. Запуск: node backend/scripts/audit_chem8.js + */ +'use strict'; +const fs = require('fs'); +const path = require('path'); +const { JSDOM, VirtualConsole } = require('jsdom'); + +const ROOT = path.join(__dirname, '..', '..'); +const readF = p => fs.readFileSync(path.join(ROOT, p), 'utf8'); +const wait = ms => new Promise(r => setTimeout(r, ms)); + +const PAGES = [ + ['chemistry_8_intro.html', 'chem8_intro_widgets'], + ['chemistry_8_ch1.html', 'chem8_ch1_widgets'], + ['chemistry_8_ch2.html', 'chem8_ch2_widgets'], + ['chemistry_8_ch3.html', 'chem8_ch3_widgets'], + ['chemistry_8_ch4.html', 'chem8_ch4_widgets'], + ['chemistry_8_ch5.html', 'chem8_ch5_widgets'], + ['chemistry_8_ch6.html', 'chem8_ch6_widgets'] +]; + +function buildPage(file, widgets) { + let html = readF('frontend/textbooks/' + file); + const inl = { + '/js/biochem-core.js': readF('frontend/js/biochem-core.js'), + '/js/chem8_svg.js': readF('frontend/js/chem8_svg.js'), + '/js/chem8_mol.js': readF('frontend/js/chem8_mol.js'), + ['/js/' + widgets + '.js']: readF('frontend/js/' + widgets + '.js'), + '/js/chem8_engine.js': readF('frontend/js/chem8_engine.js') + }; + html = html + .replace(/') + .replace(/'); + }); + return html; +} + +function extractMath(s) { + const out = []; + // $$...$$ затем $...$ + let re = /\$\$([\s\S]+?)\$\$/g, m; + let masked = s; + while ((m = re.exec(s)) !== null) out.push({ disp: true, body: m[1] }); + masked = s.replace(/\$\$[\s\S]+?\$\$/g, ''); + re = /\$([^$]*)\$/g; + while ((m = re.exec(masked)) !== null) out.push({ disp: false, body: m[1] }); + return out; +} + +function checkBraces(b) { let d = 0; for (const c of b) { if (c === '{') d++; else if (c === '}') d--; if (d < 0) return false; } return d === 0; } +function hasCtrl(b) { return /[\t\n\r\f\v\b]/.test(b); } + +async function auditPage(file, widgets) { + const issues = []; + const vc = new VirtualConsole(); const errs = []; + vc.on('jsdomError', e => errs.push(e.message)); + const dom = new JSDOM(buildPage(file, widgets), { + runScripts: 'dangerously', pretendToBeVisual: true, virtualConsole: vc, url: 'http://localhost/', + beforeParse(w) { w.scrollTo = function () {}; } + }); + await wait(120); + const doc = dom.window.document; + const paras = (dom.window.PARAS || []).map(p => p.id); + for (const id of paras) { try { dom.window.goTo(id); } catch (e) {} } + await wait(120); + + if (errs.length) issues.push('script errors: ' + errs.join(' | ')); + + // собрать все § тела + sidebar + let html = ''; + doc.querySelectorAll('[id$="-body"]').forEach(el => { html += el.innerHTML + '\n'; }); + const sidebar = doc.getElementById('sidebar-content'); if (sidebar) html += sidebar.innerHTML; + + // баланс $ (нечётное число одиночных $ вне $$) + const noDisp = html.replace(/\$\$[\s\S]+?\$\$/g, ''); + const singles = (noDisp.match(/\$/g) || []).length; + if (singles % 2 !== 0) issues.push('нечётное число одиночных $ (' + singles + ')'); + + const maths = extractMath(html); + let bad = 0; + for (const m of maths) { + const b = m.body; + if (!b.trim()) { issues.push('пустая формула $' + (m.disp ? '$' : '') + '$'); bad++; continue; } + if (!checkBraces(b)) { issues.push('несбалансированные {} в: ' + b.slice(0, 50)); bad++; } + if (hasCtrl(b)) { issues.push('управляющий символ (след \\t/\\n?) в: ' + JSON.stringify(b.slice(0, 50))); bad++; } + // одиночный backslash перед буквой, не часть известной команды? — грубая эвристика: \ в конце + if (/\\$/.test(b)) { issues.push('формула заканчивается на \\: ' + b.slice(-20)); bad++; } + } + return { file, mathCount: maths.length, badCount: bad, issues }; +} + +(async () => { + let total = 0, totalBad = 0; + for (const [file, w] of PAGES) { + const r = await auditPage(file, w); + total += r.mathCount; totalBad += r.badCount; + console.log('\n=== ' + file + ' — формул: ' + r.mathCount + ', проблем: ' + r.issues.length + ' ==='); + if (r.issues.length) r.issues.slice(0, 25).forEach(i => console.log(' ! ' + i)); + else console.log(' OK'); + } + console.log('\nИТОГО формул: ' + total + ', проблемных: ' + totalBad); + process.exit(0); +})(); diff --git a/backend/scripts/biochem_pathways_data.js b/backend/scripts/biochem_pathways_data.js new file mode 100644 index 0000000..576b8c5 --- /dev/null +++ b/backend/scripts/biochem_pathways_data.js @@ -0,0 +1,1290 @@ +'use strict'; +// Данные метаболических путей (источник для seed_biochem_pathways.js). +// Извлечены из инлайн-объекта PATHWAYS biochem-pathways.html — теперь самодостаточный источник. +module.exports = { + "glycolysis": { + "name": "Гликолиз", + "color": "#f59e0b", + "colorRgb": "245,158,11", + "desc": "10 реакций расщепления глюкозы до пирувата. Происходит в цитоплазме. Выход: 2 АТФ (нетто), 2 НАДН, 2 пируват.", + "stats": [ + { + "label": "−2 АТФ +4 АТФ", + "cls": "atp" + }, + { + "label": "2 НАДН", + "cls": "nadh" + } + ], + "legend": [ + { + "color": "#f59e0b", + "type": "circle", + "label": "Метаболит" + }, + { + "color": "#f59e0b", + "type": "line", + "label": "Реакция" + }, + { + "color": "#f59e0b88", + "type": "circle-sm", + "label": "Кофактор (АТФ/НАД)" + } + ], + "nodes": [ + { + "id": "glc", + "label": "Глюкоза", + "formula": "C₆H₁₂O₆", + "x": 400, + "y": 60, + "role": "substrate", + "desc": "Исходный субстрат гликолиза. 6-углеродный сахар, главный источник энергии клетки.", + "props": [] + }, + { + "id": "g6p", + "label": "Глюкозо-6-Ф", + "formula": "C₆H₁₃O₉P", + "x": 400, + "y": 145, + "role": "inter", + "desc": "Глюкозо-6-фосфат. Образуется при фосфорилировании глюкозы за счёт АТФ. Удерживает молекулу в клетке.", + "props": [ + "−1 АТФ" + ] + }, + { + "id": "f6p", + "label": "Фруктозо-6-Ф", + "formula": "C₆H₁₃O₉P", + "x": 400, + "y": 225, + "role": "inter", + "desc": "Изомер глюкозо-6-фосфата. Образуется при изомеризации ферментом фосфоглюкоизомеразой.", + "props": [] + }, + { + "id": "f16bp", + "label": "Фруктозо-1,6-бФ", + "formula": "C₆H₁₄O₁₂P₂", + "x": 400, + "y": 310, + "role": "key", + "desc": "Фруктозо-1,6-бисфосфат — ключевой регуляторный метаболит. Образование катализирует фосфофруктокиназа-1 (ФФК-1).", + "props": [ + "−1 АТФ", + "Контроль скорости" + ] + }, + { + "id": "dhap", + "label": "ДГАФ", + "formula": "C₃H₇O₆P", + "x": 260, + "y": 395, + "role": "inter", + "desc": "Дигидроксиацетонфосфат — один из двух триозофосфатов при расщеплении фруктозо-1,6-бисфосфата. Быстро конвертируется в ГАФ.", + "props": [] + }, + { + "id": "gap", + "label": "ГАФ", + "formula": "C₃H₇O₆P", + "x": 540, + "y": 395, + "role": "inter", + "desc": "Глицеральдегид-3-фосфат (ГАФ) — непосредственный субстрат следующих реакций. Оба триозофосфата канализируются через ГАФ.", + "props": [] + }, + { + "id": "bpg", + "label": "1,3-бФГ", + "formula": "C₃H₈O₁₀P₂", + "x": 540, + "y": 480, + "role": "inter", + "desc": "1,3-бисфосфоглицерат. Образуется при окислении ГАФ, сопряжённом с восстановлением НАД⁺ в НАДН.", + "props": [ + "2 НАДН" + ] + }, + { + "id": "pg3", + "label": "3-ФГК", + "formula": "C₃H₇O₇P", + "x": 540, + "y": 560, + "role": "inter", + "desc": "3-фосфоглицерат. Образуется при субстратном фосфорилировании АДФ АТФ ферментом фосфоглицераткиназой.", + "props": [ + "+2 АТФ" + ] + }, + { + "id": "pg2", + "label": "2-ФГК", + "formula": "C₃H₇O₇P", + "x": 540, + "y": 635, + "role": "inter", + "desc": "2-фосфоглицерат. Образуется при перемещении фосфатной группы с 3 на 2 положение.", + "props": [] + }, + { + "id": "pep", + "label": "ФЕП", + "formula": "C₃H₅O₆P", + "x": 540, + "y": 710, + "role": "inter", + "desc": "Фосфоенолпируват (ФЕП) — высокоэнергетический промежуточный продукт. Образуется при дегидратации 2-ФГК.", + "props": [] + }, + { + "id": "pyr", + "label": "Пируват", + "formula": "C₃H₄O₃", + "x": 400, + "y": 795, + "role": "product", + "desc": "Конечный продукт гликолиза. В аэробных условиях переходит в ацетил-КоА (цикл Кребса). В анаэробных лактат или этанол.", + "props": [ + "+2 АТФ", + "2 молекулы" + ] + } + ], + "edges": [ + { + "from": "glc", + "to": "g6p", + "enzyme": "Гексокиназа", + "co": "-АТФ", + "curveX": 0 + }, + { + "from": "g6p", + "to": "f6p", + "enzyme": "ФГИ", + "curveX": 0 + }, + { + "from": "f6p", + "to": "f16bp", + "enzyme": "ФФК-1", + "co": "-АТФ", + "curveX": 0 + }, + { + "from": "f16bp", + "to": "dhap", + "enzyme": "Альдолаза", + "curveX": 0 + }, + { + "from": "f16bp", + "to": "gap", + "enzyme": "Альдолаза", + "curveX": 0 + }, + { + "from": "dhap", + "to": "gap", + "enzyme": "ТФИ", + "curveX": 0 + }, + { + "from": "gap", + "to": "bpg", + "enzyme": "ГАФДГ", + "co": "+НАДН", + "curveX": 0 + }, + { + "from": "bpg", + "to": "pg3", + "enzyme": "ФГК", + "co": "+АТФ", + "curveX": 0 + }, + { + "from": "pg3", + "to": "pg2", + "enzyme": "Фосфоглицератмутаза", + "curveX": 0 + }, + { + "from": "pg2", + "to": "pep", + "enzyme": "Енолаза", + "curveX": 0 + }, + { + "from": "pep", + "to": "pyr", + "enzyme": "Пируваткиназа", + "co": "+АТФ", + "curveX": 0 + } + ], + "steps": [ + { + "title": "Фосфорилирование глюкозы", + "mol": "g6p", + "desc": "Гексокиназа катализирует перенос фосфатной группы с АТФ на глюкозу, образуя глюкозо-6-фосфат (Г6Ф). Реакция необратима и «ловит» глюкозу в клетке.", + "energy": [ + { + "label": "-1 АТФ", + "cls": "atp-used" + } + ], + "quiz": { + "q": "Зачем глюкозу фосфорилируют в первой реакции?", + "opts": [ + "Для выхода из клетки", + "Чтобы удержать глюкозу в клетке", + "Для образования НАДН", + "Для расщепления кольца" + ], + "ans": 1 + } + }, + { + "title": "Изомеризация", + "mol": "f6p", + "desc": "Фосфоглюкоизомераза превращает Г6Ф в фруктозо-6-фосфат (Ф6Ф). Реакция обратима и перестраивает альдозный сахар в кетозный.", + "energy": [], + "quiz": { + "q": "Какой фермент катализирует изомеризацию Г6Ф Ф6Ф?", + "opts": [ + "Гексокиназа", + "Альдолаза", + "Фосфоглюкоизомераза", + "Пируваткиназа" + ], + "ans": 2 + } + }, + { + "title": "Ключевой контрольный шаг", + "mol": "f16bp", + "desc": "Фосфофруктокиназа-1 (ФФК-1) фосфорилирует Ф6Ф фруктозо-1,6-бисфосфат. Это необратимая реакция — главный регуляторный пункт гликолиза. АТФ ингибирует, АМФ/АДФ активирует.", + "energy": [ + { + "label": "-1 АТФ", + "cls": "atp-used" + } + ], + "quiz": { + "q": "Что является главным аллостерическим активатором ФФК-1?", + "opts": [ + "АТФ", + "АМФ", + "НАДН", + "Пируват" + ], + "ans": 1 + } + }, + { + "title": "Расщепление на триозы", + "mol": "gap", + "desc": "Альдолаза расщепляет фруктозо-1,6-бисфосфат на два триозофосфата: ДГАФ и ГАФ (глицеральдегид-3-фосфат). Триозофосфатизомераза быстро конвертирует ДГАФ ГАФ.", + "energy": [], + "quiz": { + "q": "Сколько молекул ГАФ образуется из одной глюкозы?", + "opts": [ + "1", + "2", + "3", + "4" + ], + "ans": 1 + } + }, + { + "title": "Окислительное фосфорилирование", + "mol": "bpg", + "desc": "ГАФДГ окисляет ГАФ и присоединяет неорганический фосфат 1,3-бисфосфоглицерат. Сопряжено с восстановлением НАД⁺ НАДН. Реакция субстратного фосфорилирования.", + "energy": [ + { + "label": "+2 НАДН", + "cls": "nadh" + } + ], + "quiz": { + "q": "Чем восстанавливается НАД⁺ в этой реакции?", + "opts": [ + "ГАФ", + "Пируват", + "ДГАФ", + "АТФ" + ], + "ans": 0 + } + }, + { + "title": "Первая выработка АТФ", + "mol": "pg3", + "desc": "Фосфоглицераткиназа переносит фосфат с 1,3-бФГ на АДФ АТФ. Это субстратное фосфорилирование — первый синтез АТФ в гликолизе. С каждой глюкозы получаем 2 АТФ.", + "energy": [ + { + "label": "+2 АТФ", + "cls": "atp-prod" + } + ], + "quiz": { + "q": "Как называется тип синтеза АТФ в этой реакции?", + "opts": [ + "Окислительное фосфорилирование", + "Субстратное фосфорилирование", + "Фотофосфорилирование", + "Трансфосфорилирование" + ], + "ans": 1 + } + }, + { + "title": "Мутация фосфатной группы", + "mol": "pg2", + "desc": "Фосфоглицератмутаза перемещает фосфатную группу с 3-го на 2-е углеродное положение, подготавливая молекулу к дегидратации.", + "energy": [], + "quiz": { + "q": "Какой продукт образуется из 3-ФГК под действием мутазы?", + "opts": [ + "ФЕП", + "2-ФГК", + "Пируват", + "1,3-бФГ" + ], + "ans": 1 + } + }, + { + "title": "Образование ФЕП", + "mol": "pep", + "desc": "Енолаза катализирует дегидратацию 2-фосфоглицерата фосфоенолпируват (ФЕП). ФЕП — высокоэнергетический соединение с большой отрицательной ΔG° гидролиза фосфата.", + "energy": [], + "quiz": { + "q": "Почему ФЕП называют «высокоэнергетическим»?", + "opts": [ + "Содержит много атомов С", + "Большая ΔG° гидролиза фосфатной связи", + "Растворяется в жирах", + "Содержит двойную связь" + ], + "ans": 1 + } + }, + { + "title": "Финальная реакция — пируват", + "mol": "pyr", + "desc": "Пируваткиназа переносит фосфат с ФЕП на АДФ АТФ + пируват. Необратимая реакция. Итог: из 1 глюкозы 2 пирувата, 2 НАДН, +2 АТФ нетто.", + "energy": [ + { + "label": "+2 АТФ", + "cls": "atp-prod" + }, + { + "label": "2 пируват", + "cls": "co2" + } + ], + "quiz": { + "q": "Каков нетто-выход АТФ на 1 молекулу глюкозы в гликолизе?", + "opts": [ + "1", + "2", + "4", + "36" + ], + "ans": 1 + } + } + ] + }, + "krebs": { + "name": "Цикл Кребса", + "color": "#06b6d4", + "colorRgb": "6,182,212", + "desc": "8 реакций окисления ацетил-КоА. Происходит в матриксе митохондрий. Выход на 1 оборот: 3 НАДН, 1 ФАДН₂, 1 ГТФ, 2 СО₂.", + "stats": [ + { + "label": "3 НАДН / оборот", + "cls": "nadh" + }, + { + "label": "2 CO₂", + "cls": "co2" + }, + { + "label": "1 ГТФ", + "cls": "atp" + } + ], + "legend": [ + { + "color": "#06b6d4", + "type": "circle", + "label": "Промежуточный метаболит" + }, + { + "color": "#06b6d4", + "type": "line", + "label": "Реакция цикла" + } + ], + "nodes": [ + { + "id": "acetcoa", + "label": "Ацетил-КоА", + "formula": "CH₃CO-SCoA", + "x": 440, + "y": 80, + "role": "substrate", + "desc": "Активированный ацетат. Образуется из пирувата (гликолиз), жирных кислот (β-окисление) и аминокислот.", + "props": [ + "Входит в цикл" + ] + }, + { + "id": "oaa", + "label": "ОАА", + "formula": "C₄H₄O₅", + "x": 260, + "y": 140, + "role": "key", + "desc": "Оксалоацетат — акцептор ацетил-КоА. Регенерируется в каждом обороте цикла. Ключевой анаплеротический метаболит.", + "props": [ + "Акцептор" + ] + }, + { + "id": "cit", + "label": "Цитрат", + "formula": "C₆H₈O₇", + "x": 160, + "y": 260, + "role": "inter", + "desc": "Цитрат — первый продукт цикла. Синтезируется цитратсинтазой из ацетил-КоА и ОАА.", + "props": [] + }, + { + "id": "isocit", + "label": "Изоцитрат", + "formula": "C₆H₈O₇", + "x": 120, + "y": 390, + "role": "inter", + "desc": "Изоцитрат — изомер цитрата. Субстрат изоцитратдегидрогеназы — ключевого регуляторного фермента.", + "props": [] + }, + { + "id": "akg", + "label": "α-КГ", + "formula": "C₅H₆O₅", + "x": 160, + "y": 520, + "role": "inter", + "desc": "α-кетоглутарат (α-КГ). Образуется при окислительном декарбоксилировании изоцитрата. Выделяется CO₂.", + "props": [ + "−CO₂", + "+НАДН" + ] + }, + { + "id": "succoa", + "label": "Сукцинил-КоА", + "formula": "C₅H₆O₃S", + "x": 300, + "y": 620, + "role": "inter", + "desc": "Сукцинил-КоА — высокоэнергетический тиоэфир. Образуется при окислительном декарбоксилировании α-КГ.", + "props": [ + "+НАДН", + "+ГТФ", + "-CO₂" + ] + }, + { + "id": "succ", + "label": "Сукцинат", + "formula": "C₄H₆O₄", + "x": 480, + "y": 620, + "role": "inter", + "desc": "Сукцинат. Окисляется сукцинатдегидрогеназой (СДГ) — единственным мембранным ферментом цикла.", + "props": [ + "+ФАДН₂" + ] + }, + { + "id": "fum", + "label": "Фумарат", + "formula": "C₄H₄O₄", + "x": 620, + "y": 520, + "role": "inter", + "desc": "Фумарат — транс-изомер. Образуется при окислении сукцината. Гидратируется фумаразой.", + "props": [] + }, + { + "id": "mal", + "label": "Малат", + "formula": "C₄H₆O₅", + "x": 660, + "y": 390, + "role": "inter", + "desc": "Малат (яблочная кислота). Образуется при гидратации фумарата. Окисляется малатдегидрогеназой.", + "props": [ + "+НАДН" + ] + } + ], + "edges": [ + { + "from": "acetcoa", + "to": "cit", + "enzyme": "Цитратсинтаза", + "co": "+ОАА", + "curveX": 0 + }, + { + "from": "oaa", + "to": "cit", + "enzyme": "", + "curveX": 0 + }, + { + "from": "cit", + "to": "isocit", + "enzyme": "Аконитаза", + "curveX": 0 + }, + { + "from": "isocit", + "to": "akg", + "enzyme": "ИзоцитратДГ", + "co": "+НАДН,-CO₂", + "curveX": 0 + }, + { + "from": "akg", + "to": "succoa", + "enzyme": "α-КГДГ-комплекс", + "co": "+НАДН,-CO₂", + "curveX": 0 + }, + { + "from": "succoa", + "to": "succ", + "enzyme": "Сукцинил-КоА-синтетаза", + "co": "+ГТФ", + "curveX": 0 + }, + { + "from": "succ", + "to": "fum", + "enzyme": "Сукцинатдегидрогеназа", + "co": "+ФАДН₂", + "curveX": 0 + }, + { + "from": "fum", + "to": "mal", + "enzyme": "Фумараза", + "curveX": 0 + }, + { + "from": "mal", + "to": "oaa", + "enzyme": "МалатДГ", + "co": "+НАДН", + "curveX": 0 + } + ], + "steps": [ + { + "title": "Конденсация с ОАА", + "mol": "cit", + "desc": "Цитратсинтаза присоединяет ацетил-КоА (2C) к оксалоацетату (4C) цитрат (6C). Это необратимая реакция, запускающая цикл.", + "energy": [], + "quiz": { + "q": "Сколько углеродов в цитрате?", + "opts": [ + "2", + "4", + "6", + "8" + ], + "ans": 2 + } + }, + { + "title": "Изомеризация цитрата", + "mol": "isocit", + "desc": "Аконитаза через промежуточный цис-аконитат превращает цитрат в изоцитрат. Реакция обратима, равновесие сдвинуто в сторону цитрата.", + "energy": [], + "quiz": { + "q": "Какой фермент изомеризует цитрат?", + "opts": [ + "Фумараза", + "Аконитаза", + "Малатдегидрогеназа", + "Цитратсинтаза" + ], + "ans": 1 + } + }, + { + "title": "Первое окислительное декарбоксилирование", + "mol": "akg", + "desc": "Изоцитратдегидрогеназа окисляет изоцитрат α-кетоглутарат с выделением CO₂ и НАДН. Ключевой регуляторный шаг — активируется изоцитратом, ингибируется НАДН.", + "energy": [ + { + "label": "+НАДН", + "cls": "nadh" + }, + { + "label": "-CO₂", + "cls": "co2" + } + ], + "quiz": { + "q": "Сколько углеродов в α-кетоглутарате?", + "opts": [ + "2", + "4", + "5", + "6" + ], + "ans": 2 + } + }, + { + "title": "Второе окислительное декарбоксилирование", + "mol": "succoa", + "desc": "α-кетоглутаратдегидрогеназный комплекс (аналог ПДК) окисляет α-КГ сукцинил-КоА. Выделяется ещё одна CO₂ и НАДН.", + "energy": [ + { + "label": "+НАДН", + "cls": "nadh" + }, + { + "label": "-CO₂", + "cls": "co2" + } + ], + "quiz": { + "q": "Чем структурно похож α-КГДК на пируватдегидрогеназный комплекс?", + "opts": [ + "Использует ФАДН₂", + "Механизм окислительного декарбоксилирования с КоА", + "Находится в цитоплазме", + "Требует витамин К" + ], + "ans": 1 + } + }, + { + "title": "Субстратное фосфорилирование", + "mol": "succ", + "desc": "Сукцинил-КоА-синтетаза расщепляет тиоэфирную связь сукцинил-КоА, сопрягая это с синтезом ГТФ (или АТФ). Единственная реакция субстратного фосфорилирования в цикле.", + "energy": [ + { + "label": "+ГТФ", + "cls": "atp-prod" + } + ], + "quiz": { + "q": "Что синтезируется при реакции сукцинил-КоА-синтетазы?", + "opts": [ + "НАДН", + "ФАДН₂", + "ГТФ", + "CO₂" + ], + "ans": 2 + } + }, + { + "title": "Окисление сукцината", + "mol": "fum", + "desc": "Сукцинатдегидрогеназа (комплекс II дыхательной цепи) окисляет сукцинат фумарат, восстанавливая ФАД ФАДН₂.", + "energy": [ + { + "label": "+ФАДН₂", + "cls": "fadh2" + } + ], + "quiz": { + "q": "К какому комплексу дыхательной цепи относится СДГ?", + "opts": [ + "Комплекс I", + "Комплекс II", + "Комплекс III", + "АТФ-синтаза" + ], + "ans": 1 + } + }, + { + "title": "Гидратация фумарата", + "mol": "mal", + "desc": "Фумараза присоединяет воду к фумарату L-малат. Реакция стереоспецифична — образуется только L-изомер.", + "energy": [], + "quiz": { + "q": "Что присоединяется к фумарату в этой реакции?", + "opts": [ + "CO₂", + "АТФ", + "H₂O", + "НАДН" + ], + "ans": 2 + } + }, + { + "title": "Регенерация ОАА", + "mol": "oaa", + "desc": "Малатдегидрогеназа окисляет малат оксалоацетат с образованием НАДН. Регенерируется акцептор для следующего оборота цикла.", + "energy": [ + { + "label": "+НАДН", + "cls": "nadh" + } + ], + "quiz": { + "q": "Сколько оборотов цикла Кребса нужно на 1 молекулу глюкозы?", + "opts": [ + "1", + "2", + "4", + "10" + ], + "ans": 1 + } + } + ] + }, + "oxidation": { + "name": "β-Окисление", + "color": "#fb923c", + "colorRgb": "251,146,60", + "desc": "Повторяющиеся циклы окисления жирных кислот в митохондриях. Каждый цикл отщепляет 2C в виде ацетил-КоА и выделяет 1 НАДН + 1 ФАДН₂.", + "stats": [ + { + "label": "+НАДН / цикл", + "cls": "nadh" + }, + { + "label": "+ФАДН₂", + "cls": "nadh" + }, + { + "label": "+Ацетил-КоА", + "cls": "atp" + } + ], + "legend": [ + { + "color": "#fb923c", + "type": "circle", + "label": "Промежуточный продукт" + }, + { + "color": "#fb923c", + "type": "line", + "label": "Реакция β-окисления" + } + ], + "nodes": [ + { + "id": "fac", + "label": "Жирная к-та", + "formula": "R-COOH", + "x": 400, + "y": 60, + "role": "substrate", + "desc": "Свободная жирная кислота (напр. пальмитиновая C₁₆). Активируется в ацил-КоА перед входом в митохондрии.", + "props": [] + }, + { + "id": "acylcoa", + "label": "Ацил-КоА", + "formula": "R-CO-SCoA", + "x": 400, + "y": 150, + "role": "key", + "desc": "Активированная жирная кислота. Образуется при участии ацил-КоА-синтетазы за счёт АТФ (АМФ+PPi). Не проходит через мембрану — транспортируется как карнитиновый эфир.", + "props": [ + "-АТФ (АМФ)" + ] + }, + { + "id": "enoylcoa", + "label": "Транс-еноил-КоА", + "formula": "R-CH=CH-CO-SCoA", + "x": 400, + "y": 250, + "role": "inter", + "desc": "Транс-Δ²-еноил-КоА. Образуется при ФАД-зависимом окислении ацил-КоА ацил-КоА-дегидрогеназой.", + "props": [ + "+ФАДН₂" + ] + }, + { + "id": "hydroxy", + "label": "L-β-гидрокси-КоА", + "formula": "R-CHOH-CH₂-CO-SCoA", + "x": 400, + "y": 345, + "role": "inter", + "desc": "L-β-гидроксиацил-КоА. Образуется при гидратации двойной связи еноил-КоА гидратазой.", + "props": [] + }, + { + "id": "ketoacoa", + "label": "β-кето-КоА", + "formula": "R-CO-CH₂-CO-SCoA", + "x": 400, + "y": 440, + "role": "inter", + "desc": "β-кетоацил-КоА. Образуется при НАД⁺-зависимом окислении L-β-гидроксиацил-КоА.", + "props": [ + "+НАДН" + ] + }, + { + "id": "newacyl", + "label": "Ацил-КоА (−2C)", + "formula": "R'—CO-SCoA", + "x": 240, + "y": 540, + "role": "inter", + "desc": "Укороченный на 2 углерода ацил-КоА. Возвращается на начало цикла β-окисления.", + "props": [ + "Следующий цикл" + ] + }, + { + "id": "acetcoa2", + "label": "Ацетил-КоА", + "formula": "CH₃CO-SCoA", + "x": 560, + "y": 540, + "role": "product", + "desc": "Ацетил-КоА — входит в цикл Кребса. Из пальмитиновой кислоты (C₁₆) образуется 8 ацетил-КоА за 7 циклов β-окисления.", + "props": [ + " Цикл Кребса" + ] + } + ], + "edges": [ + { + "from": "fac", + "to": "acylcoa", + "enzyme": "Ацил-КоА-синтетаза", + "co": "-АТФ", + "curveX": 0 + }, + { + "from": "acylcoa", + "to": "enoylcoa", + "enzyme": "Ацил-КоА-ДГ", + "co": "+ФАДН₂", + "curveX": 0 + }, + { + "from": "enoylcoa", + "to": "hydroxy", + "enzyme": "Еноил-КоА-гидратаза", + "curveX": 0 + }, + { + "from": "hydroxy", + "to": "ketoacoa", + "enzyme": "L-3-гидроксиацил-КоА-ДГ", + "co": "+НАДН", + "curveX": 0 + }, + { + "from": "ketoacoa", + "to": "newacyl", + "enzyme": "Тиолаза", + "curveX": 0 + }, + { + "from": "ketoacoa", + "to": "acetcoa2", + "enzyme": "Тиолаза", + "curveX": 0 + }, + { + "from": "newacyl", + "to": "acylcoa", + "enzyme": "Повтор цикла", + "curveX": -60 + } + ], + "steps": [ + { + "title": "Активация жирной кислоты", + "mol": "acylcoa", + "desc": "Ацил-КоА-синтетаза присоединяет КоА к жирной кислоте, образуя ацил-КоА. Расходуется АТФ (АМФ+PPi, что эквивалентно 2 АТФ). Это происходит в цитоплазме.", + "energy": [ + { + "label": "-2 АТФ", + "cls": "atp-used" + } + ], + "quiz": { + "q": "Где происходит активация жирной кислоты в ацил-КоА?", + "opts": [ + "В митохондриях", + "В ядре", + "В цитоплазме", + "В рибосомах" + ], + "ans": 2 + } + }, + { + "title": "ФАД-зависимое окисление", + "mol": "enoylcoa", + "desc": "Ацил-КоА-дегидрогеназа окисляет ацил-КоА, вводя двойную связь между α и β углеродами транс-Δ²-еноил-КоА. ФАД восстанавливается до ФАДН₂.", + "energy": [ + { + "label": "+ФАДН₂", + "cls": "fadh2" + } + ], + "quiz": { + "q": "Какой кофактор восстанавливается в первой реакции β-окисления?", + "opts": [ + "НАД⁺", + "ФАД", + "ГТФ", + "КоА" + ], + "ans": 1 + } + }, + { + "title": "Гидратация двойной связи", + "mol": "hydroxy", + "desc": "Еноил-КоА-гидратаза присоединяет воду по двойной связи L-β-гидроксиацил-КоА. Реакция стереоспецифична.", + "energy": [], + "quiz": { + "q": "Что присоединяется в реакции гидратации еноил-КоА?", + "opts": [ + "CO₂", + "O₂", + "H₂O", + "НАД⁺" + ], + "ans": 2 + } + }, + { + "title": "НАД⁺-зависимое окисление", + "mol": "ketoacoa", + "desc": "L-3-гидроксиацил-КоА-дегидрогеназа окисляет гидроксильную группу кетогруппу, восстанавливая НАД⁺ НАДН.", + "energy": [ + { + "label": "+НАДН", + "cls": "nadh" + } + ], + "quiz": { + "q": "Какая группа окисляется в этой реакции?", + "opts": [ + "Карбоксильная", + "Аминогруппа", + "Гидроксильная", + "Метильная" + ], + "ans": 2 + } + }, + { + "title": "Тиолитическое расщепление", + "mol": "acetcoa2", + "desc": "Тиолаза расщепляет β-кетоацил-КоА присоединением КоА ацетил-КоА (2C) + укороченный ацил-КоА. Цикл повторяется.", + "energy": [ + { + "label": "+Ацетил-КоА", + "cls": "atp-prod" + } + ], + "quiz": { + "q": "Сколько ацетил-КоА образуется из пальмитиновой кислоты (C16)?", + "opts": [ + "4", + "6", + "7", + "8" + ], + "ans": 3 + } + } + ] + }, + "synthesis": { + "name": "Синтез белка", + "color": "#a78bfa", + "colorRgb": "167,139,250", + "desc": "Трансляция — считывание мРНК рибосомой и полимеризация аминокислот в полипептидную цепь.", + "stats": [ + { + "label": "~2 ГТФ / аминокислота", + "cls": "atp" + }, + { + "label": "мРНК белок", + "cls": "nadh" + } + ], + "legend": [ + { + "color": "#a78bfa", + "type": "circle", + "label": "Участник трансляции" + }, + { + "color": "#a78bfa", + "type": "line", + "label": "Этап синтеза" + } + ], + "nodes": [ + { + "id": "mrna", + "label": "мРНК", + "formula": "5′-AUG…-3′", + "x": 400, + "y": 60, + "role": "substrate", + "desc": "Матричная РНК — несёт генетическую информацию от ДНК к рибосоме в виде кодонов (триплетов нуклеотидов).", + "props": [ + "Матрица" + ] + }, + { + "id": "ribosome", + "label": "Рибосома", + "formula": "60S+40S", + "x": 400, + "y": 160, + "role": "key", + "desc": "Эукариотическая рибосома (80S). Состоит из малой (40S) и большой (60S) субъединиц. Имеет 3 сайта: A (аминоацильный), P (пептидильный), E (выход).", + "props": [ + "A-P-E сайты" + ] + }, + { + "id": "trna", + "label": "аминоацил-тРНК", + "formula": "aa-tRNA", + "x": 230, + "y": 260, + "role": "inter", + "desc": "тРНК с присоединённой аминокислотой. Распознаёт кодон мРНК через антикодон. Доставляется в A-сайт в комплексе с EF-Tu·ГТФ.", + "props": [ + "-2 ГТФ" + ] + }, + { + "id": "peptide", + "label": "Растущая цепь", + "formula": "...aa-aa-aa", + "x": 560, + "y": 260, + "role": "inter", + "desc": "Нарастающая полипептидная цепь в P-сайте. Пептидилтрансфераза (23S rRNA) катализирует образование пептидной связи.", + "props": [ + "P-сайт" + ] + }, + { + "id": "peptbond", + "label": "Пептидная связь", + "formula": "—CO—NH—", + "x": 400, + "y": 360, + "role": "inter", + "desc": "Образование пептидной связи катализируется рибозимом (23S rRNA) — пептидилтрансферазой. Выделяется тРНК из P-сайта.", + "props": [] + }, + { + "id": "translo", + "label": "Транслокация", + "formula": "EF-G·ГТФ", + "x": 400, + "y": 460, + "role": "inter", + "desc": "Фактор EF-G (с ГТФ) сдвигает рибосому на 1 кодон (3 нт) в направлении 5′3′. Освобождается Е-сайт. Расходуется ГТФ.", + "props": [ + "-1 ГТФ" + ] + }, + { + "id": "protein", + "label": "Белок", + "formula": "[полипептид]", + "x": 400, + "y": 560, + "role": "product", + "desc": "Готовый полипептид. Освобождается при встрече со стоп-кодоном (UAA, UAG, UGA) при участии факторов высвобождения RF1/RF2.", + "props": [ + "Готовый продукт" + ] + } + ], + "edges": [ + { + "from": "mrna", + "to": "ribosome", + "enzyme": "Инициация (eIF)", + "curveX": 0 + }, + { + "from": "ribosome", + "to": "trna", + "enzyme": "Декодирование", + "curveX": 0 + }, + { + "from": "trna", + "to": "peptbond", + "enzyme": "Пептидилтрансфераза", + "curveX": 0 + }, + { + "from": "peptide", + "to": "peptbond", + "enzyme": "", + "curveX": 0 + }, + { + "from": "peptbond", + "to": "translo", + "enzyme": "EF-G·ГТФ", + "curveX": 0 + }, + { + "from": "translo", + "to": "protein", + "enzyme": "Терминация (RF)", + "curveX": 0 + }, + { + "from": "translo", + "to": "ribosome", + "enzyme": "Следующий кодон", + "curveX": -70 + } + ], + "steps": [ + { + "title": "Инициация", + "mol": "ribosome", + "desc": "Малая субъединица рибосомы распознаёт 5′-кэп мРНК при помощи факторов инициации (eIF4E/4G). Инициаторная Met-тРНК занимает P-сайт. Присоединяется большая субъединица.", + "energy": [ + { + "label": "-3 ГТФ", + "cls": "atp-used" + } + ], + "quiz": { + "q": "Какой сайт занимает инициаторная Met-тРНК?", + "opts": [ + "A-сайт", + "P-сайт", + "E-сайт", + "Все три" + ], + "ans": 1 + } + }, + { + "title": "Элонгация — доставка аа-тРНК", + "mol": "trna", + "desc": "EF-Tu·ГТФ доставляет аминоацил-тРНК в A-сайт. При правильном спаривании кодон–антикодон ГТФ гидролизуется, EF-Tu·ГДФ уходит.", + "energy": [ + { + "label": "-1 ГТФ", + "cls": "atp-used" + } + ], + "quiz": { + "q": "Какой фактор доставляет аа-тРНК в А-сайт?", + "opts": [ + "EF-G", + "EF-Tu", + "eIF2", + "RF1" + ], + "ans": 1 + } + }, + { + "title": "Пептидная связь", + "mol": "peptbond", + "desc": "Пептидилтрансфераза переносит пептидильную группу с P-сайта на аминогруппу в A-сайте, образуя пептидную связь. Энергия — из гидролиза аминоацильной связи тРНК.", + "energy": [], + "quiz": { + "q": "Что катализирует образование пептидной связи?", + "opts": [ + "Белковый фермент", + "23S rRNA (рибозим)", + "ДНК-полимераза", + "АТФ-синтаза" + ], + "ans": 1 + } + }, + { + "title": "Транслокация", + "mol": "translo", + "desc": "EF-G·ГТФ сдвигает рибосому на 3 нуклеотида по мРНК. Цепь с тРНК перемещается из A P, пустая тРНК из P E и уходит. Расходуется ГТФ.", + "energy": [ + { + "label": "-1 ГТФ", + "cls": "atp-used" + } + ], + "quiz": { + "q": "На сколько нуклеотидов сдвигается рибосома при транслокации?", + "opts": [ + "1", + "2", + "3", + "4" + ], + "ans": 2 + } + }, + { + "title": "Терминация и высвобождение", + "mol": "protein", + "desc": "Стоп-кодон (UAA/UAG/UGA) распознаётся факторами высвобождения RF1/RF2. Пептидилтрансфераза гидролизует связь пептид-тРНК белок освобождается. Рибосома диссоциирует.", + "energy": [], + "quiz": { + "q": "Сколько стоп-кодонов существует?", + "opts": [ + "1", + "2", + "3", + "4" + ], + "ans": 2 + } + } + ] + } +}; diff --git a/backend/scripts/gen_phys10_ch.js b/backend/scripts/gen_phys10_ch.js new file mode 100644 index 0000000..026feb6 --- /dev/null +++ b/backend/scripts/gen_phys10_ch.js @@ -0,0 +1,1128 @@ +// Генератор physics_10_ch{1..6}.html — Phase 0 skeleton со STUB-builder'ами. +// Берём алгебру 11 ch1 как базу, заменяем только инфраструктуру: +// - title, theme keys, slug, hero, sec-nav names, PARAS list +// - STUB-builder для каждого § (37) + final{1..6} +// - SIDEBARS / TIPS / ACH_LABELS +// CSS POLISH + ICONS + 2D-хелперы оставляем 1:1 (нужны Phase 1+). +'use strict'; +const fs = require('fs'); +const path = require('path'); + +const TBOOKS = path.join(__dirname, '..', '..', 'frontend', 'textbooks'); +const SRC = path.join(TBOOKS, 'algebra_11_ch1.html'); + +// === Данные глав === +const PARA_NAMES = { + p1:'Основные положения МКТ', + p2:'Масса и размеры молекул. Количество вещества', + p3:'Идеальный газ. Основное уравнение МКТ', + p4:'Температура. Тепловое равновесие', + p5:'Уравнение состояния идеального газа', + p6:'Изопроцессы', + p7:'Строение и свойства твёрдых тел', + p8:'Строение и свойства жидкостей', + p9:'Испарение и конденсация. Насыщенный пар', + p10:'Влажность воздуха', + p11:'Внутренняя энергия', + p12:'Работа в термодинамике', + p13:'Количество теплоты', + p14:'Первый закон термодинамики', + p15:'Тепловые двигатели. Цикл Карно', + p16:'Электрический заряд', + p17:'Закон Кулона', + p18:'Электростатическое поле', + p19:'Напряжённость поля. Принцип суперпозиции', + p20:'Линии напряжённости', + p21:'Работа поля. Потенциал', + p22:'Разность потенциалов. Напряжение', + p23:'Конденсаторы', + p24:'Энергия поля конденсатора', + p25:'ЭДС источника тока', + p26:'Закон Ома для полной цепи', + p27:'Магнитное поле тока', + p28:'Индукция магнитного поля', + p29:'Сила Ампера', + p30:'Сила Лоренца', + p31:'Магнитный поток. Электромагнитная индукция', + p32:'Правило Ленца. Закон Фарадея', + p33:'Самоиндукция', + p34:'Ток в металлах. Сверхпроводимость', + p35:'Ток в электролитах', + p36:'Ток в газах. Плазма', + p37:'Ток в полупроводниках', +}; + +// Sub-формулы (с двойным backslash для JS string literals) +const PARA_SUBS = { + p1:'Положения МКТ', + p2:'$N_A = 6{,}022 \\\\cdot 10^{23}$', + p3:'$p = \\\\dfrac{1}{3}nm\\\\overline{v^2}$', + p4:'$\\\\overline{E_k} = \\\\dfrac{3}{2}kT$', + p5:'$pV = \\\\nu RT$', + p6:'$pV/T = \\\\text{const}$', + p7:'Кристаллы', + p8:'Поверхностное натяжение', + p9:'Насыщенный пар', + p10:'$\\\\varphi = p/p_н$', + p11:'$U = \\\\dfrac{3}{2}\\\\nu RT$', + p12:'$A = p\\\\Delta V$', + p13:'$Q = cm\\\\Delta T$', + p14:'$Q = \\\\Delta U + A$', + p15:'$\\\\eta = (T_1-T_2)/T_1$', + p16:'$q = ne$', + p17:'$F = k\\\\dfrac{q_1 q_2}{r^2}$', + p18:'$\\\\vec{E}$', + p19:'$\\\\vec{E} = \\\\sum \\\\vec{E_i}$', + p20:'Силовые линии', + p21:'$A = qU$', + p22:'$U = E \\\\cdot d$', + p23:'$C = q/U$', + p24:'$W = CU^2/2$', + p25:'$\\\\mathcal{E}$', + p26:'$I = \\\\mathcal{E}/(R+r)$', + p27:'Опыт Эрстеда', + p28:'$\\\\vec{B}$', + p29:'$F = BIL\\\\sin\\\\alpha$', + p30:'$F = qvB$', + p31:'$\\\\Phi = BS\\\\cos\\\\alpha$', + p32:'$\\\\mathcal{E}_i = -d\\\\Phi/dt$', + p33:'$L$, $W_L = LI^2/2$', + p34:'$\\\\rho(T)$', + p35:'$m = kIt$', + p36:'Виды разрядов', + p37:'n-/p-тип', +}; + +// Watermarks для секций (короткие) +const PARA_WM = { + p1:'МКТ', p2:'N_A', p3:'pV', p4:'T', p5:'pV=νRT', p6:'iso', p7:'cryst', p8:'σ', p9:'пар', p10:'φ', + p11:'U', p12:'A', p13:'Q', p14:'1-й', p15:'Карно', + p16:'q', p17:'Кулон', p18:'&vec;E', p19:'E', p20:'→', p21:'A=qU', p22:'U', p23:'C', p24:'CU²', + p25:'ε', p26:'Ом', + p27:'Эрстед', p28:'B', p29:'Ампер', p30:'Лоренц', p31:'Φ', p32:'Фарадей', p33:'L', + p34:'ρ(T)', p35:'m=kIt', p36:'plasma', p37:'n/p', + final1:'★', final2:'★', final3:'★', final4:'★', final5:'★', final6:'★', +}; + +const CHAPTERS = { + ch1: { + paras: ['p1','p2','p3','p4','p5','p6','p7','p8','p9','p10'], final: 'final1', + title: 'Основы МКТ', + headerSub: 'Молекулярно-кинетическая теория · идеальный газ · изопроцессы · влажность', + hero: { h:'Молекулярная физика — почему вещество ведёт себя так', p:'Молекулярно-кинетическая теория объясняет свойства вещества движением и взаимодействием молекул. Изучаем газы, твёрдые тела, жидкости, температуру, давление и влажность.' }, + pri:'#2563eb', priD:'#1d4ed8', priSoft:'#dbeafe', priLight:'#60a5fa', + headerGrad:'linear-gradient(110deg,#1e3a8a 0%,#2563eb 55%,#60a5fa 100%)', + chNum:1, watermarkHero:'T', + }, + ch2: { + paras: ['p11','p12','p13','p14','p15'], final: 'final2', + title: 'Термодинамика', + headerSub: 'Внутренняя энергия · работа · теплота · 1-й закон · тепловые двигатели', + hero: { h:'Термодинамика — превращения энергии', p:'Термодинамика — наука о превращении энергии. Внутренняя энергия, работа газа, количество теплоты, первый закон и тепловые двигатели.' }, + pri:'#059669', priD:'#047857', priSoft:'#d1fae5', priLight:'#34d399', + headerGrad:'linear-gradient(110deg,#064e3b 0%,#059669 55%,#34d399 100%)', + chNum:2, watermarkHero:'ΔU', + }, + ch3: { + paras: ['p16','p17','p18','p19','p20','p21','p22','p23','p24'], final: 'final3', + title: 'Электростатика', + headerSub: 'Заряд · Кулон · поле · потенциал · напряжение · конденсаторы', + hero: { h:'Электростатика — поле неподвижных зарядов', p:'Электрический заряд создаёт поле. Изучаем закон Кулона, напряжённость и потенциал поля, конденсаторы и их энергию.' }, + pri:'#7c3aed', priD:'#6d28d9', priSoft:'#ede9fe', priLight:'#a78bfa', + headerGrad:'linear-gradient(110deg,#3b0764 0%,#7c3aed 55%,#a78bfa 100%)', + chNum:3, watermarkHero:'+q', + }, + ch4: { + paras: ['p25','p26'], final: 'final4', + title: 'Постоянный ток', + headerSub: 'ЭДС источника · закон Ома для полной цепи · КПД', + hero: { h:'Постоянный ток в полной цепи', p:'Постоянный ток в полной цепи: ЭДС источника, закон Ома, КПД источника.' }, + pri:'#db2777', priD:'#be185d', priSoft:'#fce7f3', priLight:'#f472b6', + headerGrad:'linear-gradient(110deg,#831843 0%,#db2777 55%,#f472b6 100%)', + chNum:4, watermarkHero:'I', + }, + ch5: { + paras: ['p27','p28','p29','p30','p31','p32','p33'], final: 'final5', + title: 'Магнитное поле и ЭМИ', + headerSub: 'Магнитное поле · Ампер · Лоренц · поток · индукция · Ленц · Фарадей · самоиндукция', + hero: { h:'Магнитное поле и электромагнитная индукция', p:'Магнитное поле тока, сила Ампера, сила Лоренца, явление электромагнитной индукции и закон Фарадея.' }, + pri:'#0891b2', priD:'#0e7490', priSoft:'#cffafe', priLight:'#22d3ee', + headerGrad:'linear-gradient(110deg,#164e63 0%,#0891b2 55%,#22d3ee 100%)', + chNum:5, watermarkHero:'B', + }, + ch6: { + paras: ['p34','p35','p36','p37'], final: 'final6', + title: 'Ток в различных средах', + headerSub: 'Металлы · сверхпроводимость · электролиз · газы · плазма · полупроводники', + hero: { h:'Электрический ток в разных средах', p:'Электрический ток ведёт себя по-разному в металлах, электролитах, газах и полупроводниках. Сверхпроводимость, электролиз, плазма, p-n переход.' }, + pri:'#10b981', priD:'#059669', priSoft:'#d1fae5', priLight:'#6ee7b7', + headerGrad:'linear-gradient(110deg,#064e3b 0%,#10b981 55%,#6ee7b7 100%)', + chNum:6, watermarkHero:'n/p', + }, +}; + +// === Sidebar rows: краткие подсказки для каждого § === +const SIDEBAR_ROWS = { + p1: [['Положения','3 положения МКТ: все вещества из частиц, частицы движутся, взаимодействуют'],['Опыты','Броуновское движение, диффузия'],['Размер','$d \\\\sim 10^{-10}$ м']], + p2: [['Авогадро','$N_A = 6{,}022 \\\\cdot 10^{23}$ 1/моль'],['Количество в-ва','$\\\\nu = N/N_A = m/M$'],['Молярная масса','$M$ — кг/моль']], + p3: [['Идеальный газ','точечные частицы, упругие столкновения'],['Осн. ур-ие МКТ','$p = \\\\tfrac{1}{3}nm\\\\overline{v^2}$'],['Концентрация','$n = N/V$']], + p4: [['Темпер.','$T$ — мера ср. кин. энергии'],['$\\\\overline{E_k}$','$\\\\overline{E_k} = \\\\tfrac{3}{2}kT$'],['Шкалы','$T_K = t + 273{,}15$']], + p5: [['Менделеев-Клапейрон','$pV = \\\\nu RT$'],['Клапейрон','$\\\\frac{pV}{T} = \\\\text{const}$'],['$R$','$R = 8{,}314$ Дж/(моль·К)']], + p6: [['Изотерма','$T = \\\\text{const}$: $pV = \\\\text{const}$ (Бойль-Мариотт)'],['Изобара','$p = \\\\text{const}$: $V/T = \\\\text{const}$ (Гей-Люссак)'],['Изохора','$V = \\\\text{const}$: $p/T = \\\\text{const}$ (Шарль)']], + p7: [['Крист.','дальний порядок'],['Аморф.','ближний порядок, нет $T_{пл}$'],['Деформ.','упругая, пластическая']], + p8: [['Жидкость','ближний порядок, текучесть'],['Поверх. натяж.','$\\\\sigma$ — Н/м'],['Капилляр','смачивание']], + p9: [['Испар.','с поверхности'],['Кипение','$p_{нас} = p_{внеш}$'],['Нас. пар','динам. равновесие']], + p10: [['Абс. вл.','$\\\\rho_{пара}$ — кг/м³'],['Отн. вл.','$\\\\varphi = p/p_{нас} \\\\cdot 100\\\\%$'],['Точка росы','$T$, при которой $\\\\varphi = 100\\\\%$']], + p11: [['$U$','$U = \\\\tfrac{3}{2}\\\\nu RT$ — для одноат. идеал. газа'],['$\\\\Delta U$','зависит только от $T$ для идеал. газа'],['Способы','теплопередача, работа']], + p12: [['$A_{газ}$','$A = p\\\\Delta V$ при $p = \\\\text{const}$'],['Геометрия','площадь под графиком $p(V)$'],['Знак','газ расш. — $A > 0$']], + p13: [['$Q = cm\\\\Delta T$','нагрев/охлаждение'],['$Q = \\\\lambda m$','плавление'],['$Q = rm$','парообразование'],['$Q = qm$','сгорание']], + p14: [['1-й закон','$Q = \\\\Delta U + A$'],['Изопроц.','частные случаи'],['Адиабат.','$Q = 0 \\\\Rightarrow A = -\\\\Delta U$']], + p15: [['КПД','$\\\\eta = A_{пол}/Q_1$'],['Карно','$\\\\eta_{max} = (T_1 - T_2)/T_1$'],['Циклы','Отто, Дизель']], + p16: [['Заряд','$q$ — Кл'],['Электрон','$e = 1{,}6 \\\\cdot 10^{-19}$ Кл'],['Закон сохр.','$\\\\sum q = \\\\text{const}$ в замкн. системе'],['$q = ne$','дискретность']], + p17: [['Закон','$F = k\\\\dfrac{|q_1 q_2|}{r^2}$'],['$k$','$k = 9 \\\\cdot 10^9$ Н·м²/Кл²'],['$\\\\varepsilon_0$','$\\\\varepsilon_0 = 8{,}85 \\\\cdot 10^{-12}$ Ф/м']], + p18: [['Поле','посредник взаимодействия'],['Свойства','действует на заряд силой $\\\\vec{F}$'],['Источник','$+q$ или $-q$']], + p19: [['$\\\\vec{E}$','$\\\\vec{E} = \\\\vec{F}/q_0$'],['Точ. заряд','$E = k|q|/r^2$'],['Суперпоз.','$\\\\vec{E} = \\\\sum \\\\vec{E_i}$']], + p20: [['Линии','касат. — $\\\\vec{E}$'],['Густота','$E$ велико — линии чаще'],['$+ \\\\to -$','начало на $+$, конец на $-$ или $\\\\infty$']], + p21: [['Работа поля','$A_{поля} = qU$ — не зависит от пути'],['Потенц.','$\\\\varphi = W_p/q$'],['Знак','от $+$ к $-$ ток. зар. — $A > 0$']], + p22: [['Разность','$U = \\\\varphi_1 - \\\\varphi_2$'],['Однор. поле','$U = Ed$'],['Эквипот.','$\\\\bot$ линиям $\\\\vec{E}$']], + p23: [['$C = q/U$','Ф (фарад)'],['Плоский','$C = \\\\varepsilon\\\\varepsilon_0 S/d$'],['Парал.','$C = \\\\sum C_i$'],['Послед.','$1/C = \\\\sum 1/C_i$']], + p24: [['Энергия','$W = \\\\tfrac{CU^2}{2} = \\\\tfrac{q^2}{2C} = \\\\tfrac{qU}{2}$'],['Плотн.','$w = \\\\tfrac{\\\\varepsilon\\\\varepsilon_0 E^2}{2}$']], + p25: [['$\\\\mathcal{E}$','ЭДС — В'],['Сторон. силы','внутри источника'],['$\\\\mathcal{E} = A_{стор}/q$','']], + p26: [['$I = \\\\mathcal{E}/(R+r)$','полная цепь'],['КЗ','$I_{кз} = \\\\mathcal{E}/r$'],['КПД','$\\\\eta = R/(R+r)$'],['$U = \\\\mathcal{E} - Ir$','напр. на полюсах']], + p27: [['Эрстед','ток отклоняет стрелку'],['Поле тока','вихревое, $\\\\vec{B}$'],['Правая рука','для проводника']], + p28: [['$\\\\vec{B}$','индукция магн. поля — Тл'],['Линии','замкнутые, без начала/конца'],['Опр.','$B = F_{max}/(IL)$']], + p29: [['$F_A = BIL\\\\sin\\\\alpha$','сила Ампера'],['Левая рука','для напр-я силы'],['$F_A \\\\bot \\\\vec{B}, \\\\vec{I}$','']], + p30: [['$F_л = qvB\\\\sin\\\\alpha$','сила Лоренца'],['Радиус','$r = mv/(qB)$'],['$F_л \\\\bot \\\\vec{v}$','траектория — окружность/спираль']], + p31: [['$\\\\Phi = BS\\\\cos\\\\alpha$','магн. поток — Вб'],['ЭМИ','при $\\\\Delta\\\\Phi \\\\ne 0$ возникает $\\\\mathcal{E}_i$'],['Опыт Фарадея','']], + p32: [['Ленц','$I_{инд}$ противодействует причине'],['$\\\\mathcal{E}_i = -d\\\\Phi/dt$','закон Фарадея'],['Знак','определяет Ленц']], + p33: [['$\\\\mathcal{E}_{si} = -L\\\\dfrac{dI}{dt}$','самоиндукция'],['$L$','индуктивность — Гн'],['$W_L = LI^2/2$','энергия магн. поля']], + p34: [['Носители','свободные электроны'],['$\\\\rho(T) = \\\\rho_0(1 + \\\\alpha t)$','зависимость от $T$'],['Сверхпров.','$T < T_c$, $\\\\rho = 0$']], + p35: [['Электролит','раствор/расплав ионных в-в'],['$m = kIt$','1-й закон Фарадея'],['$k = M/(zF)$','эл.-хим. эквивалент'],['$F$','$F = 96485$ Кл/моль']], + p36: [['Несам.','требует ионизатора'],['Самост.','тлеющий, искровой, дуговой, коронный'],['Плазма','газ из ионов и электронов']], + p37: [['n-тип','примесь-донор, носители — электроны'],['p-тип','примесь-акцептор, носители — дырки'],['p-n','одностор. проводимость, диод']], +}; + +// Tips на каждый параграф — краткая подсказка +const TIPS_HTML = { + p1: 'Положения МКТ: все вещества из частиц, частицы движутся, взаимодействуют. Доказательства — диффузия, броуновское движение.', + p2: '$N_A = 6{,}022 \\\\cdot 10^{23}$ — число частиц в 1 моле. $\\\\nu = m/M = N/N_A$.', + p3: 'Идеальный газ: точечные молекулы, упругие столкновения. Основное ур-ие МКТ: $p = \\\\tfrac{1}{3}nm\\\\overline{v^2}$.', + p4: '$T$ — мера ср. кин. энергии: $\\\\overline{E_k} = \\\\tfrac{3}{2}kT$. Абс. ноль $T = 0$ К $= -273{,}15$°C.', + p5: 'Уравнение Менделеева-Клапейрона: $pV = \\\\nu RT$, где $R = 8{,}314$ Дж/(моль·К).', + p6: 'Изопроцессы: при фиксации одного параметра ($T$, $p$ или $V$). Бойль-Мариотт, Гей-Люссак, Шарль.', + p7: 'Кристалл — дальний порядок, $T_{пл}$ определена. Аморфные — ближний порядок, плавятся плавно.', + p8: 'Жидкость имеет $V$, но не имеет форму. Поверхностное натяжение $\\\\sigma$ создаёт «плёнку» на поверхности.', + p9: 'Насыщенный пар — пар в динамическом равновесии с жидкостью. $p_{нас}$ зависит только от $T$.', + p10: 'Отн. влажность: $\\\\varphi = p_{пара}/p_{нас} \\\\cdot 100\\\\%$. При $\\\\varphi = 100\\\\%$ — точка росы.', + p11: 'Внутр. энергия идеал. одноат. газа: $U = \\\\tfrac{3}{2}\\\\nu RT$. Зависит только от $T$.', + p12: 'Работа газа: $A = p\\\\Delta V$ при $p = \\\\text{const}$. Геометрически — площадь под графиком $p(V)$.', + p13: '$Q = cm\\\\Delta T$ — нагрев. $Q = \\\\lambda m$ — плавление. $Q = rm$ — парообразование. $Q = qm$ — сгорание.', + p14: '1-й закон термодинамики: $Q = \\\\Delta U + A$ — теплота идёт на изменение внутр. энергии и работу газа.', + p15: 'КПД цикла Карно: $\\\\eta_{max} = (T_1 - T_2)/T_1$ — максимально возможный при данных $T_1, T_2$.', + p16: 'Заряд квантуется: $q = ne$, где $e = 1{,}6 \\\\cdot 10^{-19}$ Кл. Закон сохранения заряда — фундаментальный.', + p17: '$F = k\\\\dfrac{|q_1 q_2|}{r^2}$, $k = 9 \\\\cdot 10^9$ Н·м²/Кл². Аналог закона всемирного тяготения.', + p18: 'Поле — посредник взаимодействия. Действует на заряд силой $\\\\vec{F} = q\\\\vec{E}$.', + p19: '$\\\\vec{E} = \\\\vec{F}/q_0$ — векторная характеристика поля. Принцип суперпозиции: $\\\\vec{E} = \\\\sum \\\\vec{E_i}$.', + p20: 'Линии напряжённости — касательные к $\\\\vec{E}$. Начинаются на «+» зарядах, заканчиваются на «−» или в $\\\\infty$.', + p21: 'Работа поля не зависит от пути: $A_{поля} = qU = q(\\\\varphi_1 - \\\\varphi_2)$. Поле потенциально.', + p22: 'В однородном поле: $U = E \\\\cdot d$. Эквипотенциальные поверхности перпендикулярны линиям $\\\\vec{E}$.', + p23: '$C = q/U$ — Ф. Плоский: $C = \\\\dfrac{\\\\varepsilon\\\\varepsilon_0 S}{d}$. Параллельно — $C_\\\\Sigma = \\\\sum C_i$.', + p24: '$W = \\\\dfrac{CU^2}{2} = \\\\dfrac{q^2}{2C} = \\\\dfrac{qU}{2}$ — три эквивалентные формулы.', + p25: 'ЭДС — работа сторонних сил по перемещению единичного заряда: $\\\\mathcal{E} = A_{стор}/q$. Измер. в В.', + p26: 'Закон Ома для полной цепи: $I = \\\\dfrac{\\\\mathcal{E}}{R + r}$. КПД источника: $\\\\eta = R/(R + r)$.', + p27: 'Опыт Эрстеда показал: ток создаёт магн. поле. Линии $\\\\vec{B}$ вокруг тока — концентр. окружности.', + p28: '$\\\\vec{B}$ — индукция магн. поля, измер. в Тл. Линии замкнуты (магн. поле — вихревое).', + p29: 'Сила Ампера: $F_A = BIL\\\\sin\\\\alpha$. Направление — по правилу левой руки.', + p30: 'Сила Лоренца: $F_л = qvB\\\\sin\\\\alpha$. Заряд движется по окружности с $r = mv/(qB)$.', + p31: 'Магн. поток: $\\\\Phi = BS\\\\cos\\\\alpha$. Измеряется в Вб. ЭМИ возникает при $\\\\Delta\\\\Phi \\\\ne 0$.', + p32: 'Закон Фарадея: $\\\\mathcal{E}_i = -\\\\dfrac{d\\\\Phi}{dt}$. Правило Ленца: $I_{инд}$ противодействует $\\\\Delta\\\\Phi$.', + p33: 'Самоиндукция: $\\\\mathcal{E}_{si} = -L\\\\dfrac{dI}{dt}$. Энергия магн. поля катушки: $W_L = LI^2/2$.', + p34: 'В металлах носители — свободные электроны. $\\\\rho(T) = \\\\rho_0(1 + \\\\alpha t)$. Сверхпров.: $\\\\rho = 0$.', + p35: 'Электролиз: $m = kIt$ — 1-й закон Фарадея. $k = M/(zF)$, $F = 96485$ Кл/моль.', + p36: 'Самостоятельный разряд: тлеющий, искровой, дуговой, коронный. Плазма — ионизованный газ.', + p37: 'Полупроводники: n-тип (донор, электроны) и p-тип (акцептор, дырки). p-n переход — диод.', + final1: 'Финал главы 1 — интегрированные задачи по §§1–10. В разработке (Phase 1+).', + final2: 'Финал главы 2 — интегрированные задачи по §§11–15. В разработке (Phase 2+).', + final3: 'Финал главы 3 — интегрированные задачи по §§16–24. В разработке (Phase 3+).', + final4: 'Финал главы 4 — интегрированные задачи по §§25–26. В разработке (Phase 4+).', + final5: 'Финал главы 5 — интегрированные задачи по §§27–33. В разработке (Phase 5+).', + final6: 'Финал главы 6 — интегрированные задачи по §§34–37. В разработке (Phase 6+).', +}; + +// === Билд одного ch === +function buildCh(chKey) { + const C = CHAPTERS[chKey]; + const slug = 'physics-10-' + chKey; + const lsPrefix = 'physics10_' + chKey; + const xpKey = 'physics10_xp'; + const allParas = [...C.paras, C.final]; + const paraNum = (pid) => { + if (pid.startsWith('final')) return '★'; + return '§\xa0' + pid.slice(1); + }; + // PARAS JS literal + const parasArr = allParas.map(pid => { + if (pid.startsWith('final')) { + return ` { id:'${pid}', num:'\\u2605', name:'Финал главы', sub:'Итоги \\u00b7 боссы главы ${C.chNum}', final:true }`; + } + const sub = PARA_SUBS[pid] || ''; + return ` { id:'${pid}', num:'\\u00a7 ${pid.slice(1)}', name:${JSON.stringify(PARA_NAMES[pid])}, sub:'${sub}' }`; + }).join(',\n'); + + // TOTAL_PARAS + const total = allParas.length; + + // ACH_LABELS — мини + const achLabels = [ + ` start:"Начало главы ${C.chNum}!"`, + ...C.paras.map(pid => ` ${pid}_done:${JSON.stringify(PARA_NAMES[pid] + ' освоен!')}`), + ` ${chKey}_done:"Глава ${C.chNum} пройдена!"`, + ].join(',\n'); + + // SIDEBARS JS — для каждой п в главе + final + const sidebarObj = allParas.map(pid => { + const rows = pid.startsWith('final') + ? [[`§§${C.paras[0].slice(1)}–${C.paras[C.paras.length-1].slice(1)}`, `теория главы ${C.chNum}`],['Награда','+50 XP']] + : (SIDEBAR_ROWS[pid] || [['В разработке',`шпаргалка ${pid}`]]); + const titleStr = pid.startsWith('final') ? `Финал главы ${C.chNum}` : `Шпаргалка ${pid.startsWith('p') ? '§' + pid.slice(1) : pid}`; + const rowsLit = rows.map(([k,v]) => `["${k}","${v}"]`).join(','); + return ` ${pid}:{title:"${titleStr}",rows:[${rowsLit}]}`; + }).join(',\n'); + + // TIPS JS + const tipsArr = allParas.map(pid => { + const html = TIPS_HTML[pid] || `Подсказка к ${pid} — в разработке.`; + return ` {sec:'${pid}',html:"${html.replace(/"/g, '\\"')}"}`; + }).join(',\n'); + + // STUB-builder для каждого п + const builders = allParas.map(pid => { + const isFinal = pid.startsWith('final'); + const name = isFinal ? `Финал главы ${C.chNum}` : PARA_NAMES[pid]; + const num = isFinal ? '★' : '§' + pid.slice(1); + const next = (() => { + const idx = allParas.indexOf(pid); + return idx < allParas.length - 1 ? allParas[idx+1] : null; + })(); + const prev = (() => { + const idx = allParas.indexOf(pid); + return idx > 0 ? allParas[idx-1] : null; + })(); + const prevStr = prev ? `'${prev}'` : 'null'; + const nextStr = next ? `'${next}'` : 'null'; + + return `function build_${pid}(){ + const box = document.getElementById('${pid}-body'); + let html = ''; + html += makeCard('theory', ${JSON.stringify(name)}, ${JSON.stringify(num)}, \` +

${name} — этот параграф в разработке (Phase 1+).

+

Здесь появятся: теория, формулы, разобранные примеры и 3–4 интерактива в стиле «алгебры 11» — таблицы, симуляции, ползунки, drag-and-drop и автопроверяемые тренажёры.

+

+ Phase 0: создан скелет учебника. Phase ${C.chNum}+: наполнение этого § содержанием по учебнику «Физика 10» (Беларусь, 2019). +

+ \`); + html += secNav(${prevStr}, ${nextStr}); + html += readButton('${pid}'); + box.innerHTML = html; + renderMath(box); + wireReadBtn('${pid}'); +}`; + }).join('\n\n'); + + // BUILDERS map + const buildersMap = allParas.map(pid => `${pid}:()=>build_${pid}()`).join(', '); + + // sec node HTML + const secNodes = allParas.map(pid => { + const isFinal = pid.startsWith('final'); + const num = isFinal ? '★' : '§ ' + pid.slice(1); + const titleHtml = isFinal ? 'Финал главы' : PARA_NAMES[pid]; + const wm = PARA_WM[pid] || '?'; + const numHtml = isFinal + ? `` + : `${num}`; + return `
${numHtml}

${titleHtml}

`; + }).join('\n'); + + // sec accent CSS — все секции одного цвета главы + const secCss = allParas.map(pid => + `.sec[id="sec-${pid}"]{ --sec-acc:${C.pri}; --sec-acc-d:${C.priD}; --sec-acc-soft:${C.priSoft}; }` + ).join('\n'); + + // Search NAMES map for secNav titles + const namesObj = allParas.map(pid => { + const v = pid.startsWith('final') ? 'Финал' : '\\xA7' + pid.slice(1); + return `${pid}:'${v}'`; + }).join(','); + + // === Финальный HTML === + const html = ` + + + + + + +Физика 10 · Глава ${C.chNum} · «${C.title}» + + + + + + + + + + + + + +
+
+
+

Физика 10 · Глава ${C.chNum}

+
${C.headerSub}
+
+
+ К физике 10 + + + +
+
+
+ +
+
+ +
+

${C.hero.h}

+

${C.hero.p}

+
+ +
+ Прогресс по главе +
+ 0% +
+
+
+
+ +
+
Параграфы главы
+
+
+ +${secNodes} + +
+ +
+
+ + + +
Достижение!
+ + + + + + +`; + + return html; +} + +// === Run === +for (const chKey of ['ch1','ch2','ch3','ch4','ch5','ch6']) { + const dst = path.join(TBOOKS, `physics_10_${chKey}.html`); + const html = buildCh(chKey); + fs.writeFileSync(dst, html); + + // Parse-check the inline