'use strict'; const fs = require('fs'); const path = require('path'); const OUT_DIR = path.join(__dirname, '..', '..', 'frontend', 'textbooks'); const SPECS = { ch2: { n: 2, title: 'Окружности', subtitle: 'Описанная · вписанная · четырёхугольники', heroH: 'Вписанные и описанные окружности', heroP: 'Здесь мы изучаем описанную и вписанную окружности треугольника, специальные формулы для прямоугольного треугольника $R = c/2$ и $r = (a+b-c)/2$, а также критерии вписанных и описанных четырёхугольников: $\\alpha + \\gamma = 180^\\circ$ и $a+c = b+d$.', heroWm: '○', headerWmName: 'ГЛАВА 2', paras: [ { id: 'p7', num: '§ 7', name: 'Описанная и вписанная окружности треугольника', sub: 'центр $O$, радиус $R$, $r$', watermark: '○' }, { id: 'p8', num: '§ 8', name: 'Окружности прямоугольного треугольника', sub: '$R = c/2$, $r = (a+b-c)/2$', watermark: '⊥' }, { id: 'p9', num: '§ 9', name: 'Вписанные и описанные четырёхугольники', sub: '$\\alpha + \\gamma = 180^\\circ$', watermark: '◇' }, { id: 'final2', num: '★', name: 'Финал главы', sub: 'Итоги главы 2', final: true, watermark: '★' } ], palette: { pri: '#059669', pri2: '#047857', priSoft: '#d1fae5', acc: '#34d399', acc2: '#059669', accSoft: '#ecfdf5', darkBg: '#08201b', darkCard: '#0a2b22', darkCardSoft: '#0d3329', darkText: '#d1fae5', darkMuted: '#7aa89a', darkBorder: '#1c463a', hdrGrad: 'linear-gradient(110deg,#064e3b 0%,#059669 55%,#34d399 100%)', hdrStroke: 'rgba(209,250,229,.12)', hdrUnderline: 'rgba(209,250,229,.2)' }, sidebars: { p7: { rows: [['Описанная','через все вершины'],['Центр','пересечение серединных перпендикуляров'],['Вписанная','касается всех сторон'],['Центр_in','пересечение биссектрис']] }, p8: { rows: [['Описанная','$R = \\tfrac{c}{2}$ — половина гипотенузы'],['Центр','середина гипотенузы'],['Вписанная','$r = \\tfrac{a+b-c}{2}$']] }, p9: { rows: [['Вписанный','$\\alpha + \\gamma = 180^\\circ$'],['Описанный','$a+c = b+d$']] }, final2: { rows: [['§§7–9','теория главы 2'],['Дальше','глава 3 — теоремы синусов и косинусов']] } }, tips: { p7: 'Центр описанной окружности — точка пересечения серединных перпендикуляров. Центр вписанной — точка пересечения биссектрис.', p8: 'В прямоугольном треугольнике гипотенуза — диаметр описанной окружности, отсюда $R = \\tfrac{c}{2}$.', p9: 'Четырёхугольник вписан в окружность ⟺ суммы противоположных углов равны $180^\\circ$. Четырёхугольник описан ⟺ суммы противоположных сторон равны.', final2: 'Главные результаты главы 2: формулы радиусов окружностей треугольника и критерии вписанных и описанных четырёхугольников.' }, achLabels: { start: 'Начало главы 2!', p7_done: 'Описанная и вписанная окружности освоены!', p8_done: 'Окружности прямоугольного треугольника освоены!', p9_done: 'Вписанные и описанные четырёхугольники освоены!', ch2_done: 'Глава 2 пройдена! Окружности — финал!' } }, ch3: { n: 3, title: 'Теоремы синусов и косинусов', subtitle: 'Произвольный треугольник · формула Герона', heroH: 'Теоремы синусов и косинусов', heroP: 'Здесь мы выводим теорему синусов $\\tfrac{a}{\\sin A} = 2R$, теорему косинусов $a^2 = b^2 + c^2 - 2bc\\cos A$ и формулу Герона $S = \\sqrt{p(p-a)(p-b)(p-c)}$. С их помощью решается любой треугольник.', heroWm: '∠', headerWmName: 'ГЛАВА 3', paras: [ { id: 'p10', num: '§ 10', name: 'Теорема синусов', sub: '$\\tfrac{a}{\\sin A} = 2R$', watermark: 'sin' }, { id: 'p11', num: '§ 11', name: 'Теорема косинусов', sub: '$a^2 = b^2 + c^2 - 2bc\\cos A$', watermark: 'cos' }, { id: 'p12', num: '§ 12', name: 'Формула Герона. Решение треугольников', sub: '$S = \\sqrt{p(p-a)(p-b)(p-c)}$', watermark: '√' }, { id: 'final3', num: '★', name: 'Финал главы', sub: 'Итоги главы 3', final: true, watermark: '★' } ], palette: { pri: '#7c3aed', pri2: '#6d28d9', priSoft: '#ede9fe', acc: '#a78bfa', acc2: '#7c3aed', accSoft: '#f5f3ff', darkBg: '#160b29', darkCard: '#1d1238', darkCardSoft: '#241646', darkText: '#ede9fe', darkMuted: '#a08fbf', darkBorder: '#352160', hdrGrad: 'linear-gradient(110deg,#3b0764 0%,#7c3aed 55%,#a78bfa 100%)', hdrStroke: 'rgba(237,233,254,.12)', hdrUnderline: 'rgba(237,233,254,.2)' }, sidebars: { p10: { rows: [['Теорема','$\\tfrac{a}{\\sin A} = \\tfrac{b}{\\sin B} = \\tfrac{c}{\\sin C} = 2R$'],['Применение','две стороны и угол напротив']] }, p11: { rows: [['Теорема','$a^2 = b^2 + c^2 - 2bc\\cos A$'],['Применение','три стороны или две стороны и угол']] }, p12: { rows: [['Полупериметр','$p = \\tfrac{a+b+c}{2}$'],['Площадь','$S = \\sqrt{p(p-a)(p-b)(p-c)}$']] }, final3: { rows: [['§§10–12','теория главы 3'],['Дальше','глава 4 — правильные многоугольники']] } }, tips: { p10: 'Теорема синусов: $\\dfrac{a}{\\sin A} = 2R$, где $R$ — радиус описанной окружности.', p11: 'Теорема косинусов обобщает теорему Пифагора: при $A = 90^\\circ$ получаем $a^2 = b^2 + c^2$.', p12: 'Формула Герона позволяет найти площадь треугольника, зная только три его стороны.', final3: 'Главные результаты главы 3: теоремы синусов и косинусов, формула Герона.' }, achLabels: { start: 'Начало главы 3!', p10_done: 'Теорема синусов освоена!', p11_done: 'Теорема косинусов освоена!', p12_done: 'Формула Герона освоена!', ch3_done: 'Глава 3 пройдена! Теоремы синусов и косинусов — финал!' } }, ch4: { n: 4, title: 'Правильные многоугольники', subtitle: 'Угол · радиусы · длина окружности · площадь круга', heroH: 'Правильные многоугольники', heroP: 'Здесь мы изучаем правильные многоугольники, формулу внутреннего угла $\\beta = \\tfrac{180^\\circ(n-2)}{n}$, связи стороны и радиуса описанной окружности, частные случаи (треугольник, квадрат, шестиугольник) и формулы $C = 2\\pi R$, $S = \\pi R^2$.', heroWm: '⬢', headerWmName: 'ГЛАВА 4', paras: [ { id: 'p13', num: '§ 13', name: 'Правильные многоугольники', sub: '$\\beta = \\tfrac{180^\\circ(n-2)}{n}$', watermark: '⬢' }, { id: 'p14', num: '§ 14', name: 'Формулы радиусов', sub: '$\\tfrac{a}{2} = R\\sin\\tfrac{180^\\circ}{n}$', watermark: 'R' }, { id: 'p15', num: '§ 15', name: 'Треугольник, квадрат, шестиугольник', sub: '$a = R\\sqrt{3}, R\\sqrt{2}, R$', watermark: '△□⬡' }, { id: 'p16', num: '§ 16', name: 'Длина окружности и площадь круга', sub: '$C = 2\\pi R$, $S = \\pi R^2$', watermark: '⊙' }, { id: 'final4', num: '★', name: 'Финал главы', sub: 'Итоги главы 4 · Геометрия 9 пройдена!', final: true, watermark: '★' } ], palette: { pri: '#0891b2', pri2: '#0e7490', priSoft: '#cffafe', acc: '#22d3ee', acc2: '#0891b2', accSoft: '#ecfeff', darkBg: '#04141a', darkCard: '#0a1b22', darkCardSoft: '#0d2229', darkText: '#e0fcff', darkMuted: '#7aa8b3', darkBorder: '#163842', hdrGrad: 'linear-gradient(110deg,#164e63 0%,#0891b2 55%,#22d3ee 100%)', hdrStroke: 'rgba(209,250,255,.12)', hdrUnderline: 'rgba(165,243,252,.2)' }, sidebars: { p13: { rows: [['Внутренний угол','$\\beta = \\tfrac{180^\\circ(n-2)}{n}$'],['Центральный угол','$\\tfrac{360^\\circ}{n}$']] }, p14: { rows: [['Сторона','$a = 2R\\sin\\tfrac{180^\\circ}{n}$'],['Радиус вписанной','$r = R\\cos\\tfrac{180^\\circ}{n}$']] }, p15: { rows: [['Треугольник','$a = R\\sqrt{3}$'],['Квадрат','$a = R\\sqrt{2}$'],['Шестиугольник','$a = R$']] }, p16: { rows: [['Длина','$C = 2\\pi R$'],['Площадь','$S = \\pi R^2$'],['Сектор','$S = \\tfrac{\\pi R^2 \\alpha}{360^\\circ}$']] }, final4: { rows: [['§§13–16','теория главы 4'],['Геометрия 9','полностью пройдена!']] } }, tips: { p13: 'В правильном $n$-угольнике все стороны и углы равны. Внутренний угол $\\beta = \\dfrac{180^\\circ(n-2)}{n}$.', p14: '$\\dfrac{a}{2} = R\\sin\\dfrac{180^\\circ}{n}$ — половина стороны через радиус описанной окружности.', p15: 'Запомни: в правильном треугольнике $a = R\\sqrt{3}$, в квадрате $a = R\\sqrt{2}$, в шестиугольнике $a = R$.', p16: '$C = 2\\pi R$ — длина окружности; $S = \\pi R^2$ — площадь круга.', final4: 'Главные результаты главы 4: формулы правильных многоугольников и круга. Вся Геометрия 9 в твоём арсенале!' }, achLabels: { start: 'Начало главы 4!', p13_done: 'Правильные многоугольники освоены!', p15_done: 'Треугольник, квадрат, шестиугольник освоены!', p16_done: 'Длина окружности и площадь круга освоены!', ch4_done: 'Глава 4 пройдена! Геометрия 9 — финал!' } } }; function jsStr(s){ return s.replace(/\\/g, '\\\\').replace(/'/g, "\\'"); } function cap(s){ return s[0].toUpperCase() + s.slice(1); } function buildChapter(spec){ const N = spec.n; const paras = spec.paras; const total = paras.length; const firstP = paras[0].id; const finalId = paras[paras.length-1].id; const lastNonFinal = paras[paras.length-2].id; const p = spec.palette; const sectionsHtml = paras.map(par => { const cls = par.final ? ' style="background:linear-gradient(135deg,'+p.pri+','+p.acc+')"' : ''; const heading = par.final ? ('Итоги главы '+N) : par.name; return `
${par.num}

${heading}

`; }).join('\n'); const parasJs = paras.map(par => { return ` { id:'${par.id}', num:'${par.num}', name:'${jsStr(par.name)}', sub:'${jsStr(par.sub||'')}'${par.final?', final:true':''} }`; }).join(',\n'); const buildersJs = paras.map(par => `${par.id}:()=>build${cap(par.id)}()`).join(', '); const sidebarsJs = paras.map(par => { const sb = spec.sidebars[par.id] || { rows: [] }; const rowsJs = sb.rows.map(([k,v]) => `['${jsStr(k.replace(/_in$/,''))}','${jsStr(v)}']`).join(','); const title = par.final ? 'Финал главы' : ('Шпаргалка \\xA7'+par.num.replace(/§\s*/,'')); return ` ${par.id}:{title:'${title}',rows:[${rowsJs}]}`; }).join(',\n'); const tipsJs = paras.map(par => ` {sec:'${par.id}',html:'${jsStr(spec.tips[par.id]||'')}'}`).join(',\n'); const achJs = Object.entries(spec.achLabels).map(([k,v]) => ` ${k}:'${jsStr(v)}'`).join(',\n'); const namesJs = paras.map(par => { return par.final ? `${par.id}:'Финал'` : `${par.id}:'\\xA7${par.num.replace(/§\s*/,'')}'`; }).join(','); const stubsJs = paras.filter(par => !par.final).map((par, i) => { const idx = paras.indexOf(par); const prev = idx === 0 ? 'null' : `'${paras[idx-1].id}'`; const next = `'${paras[idx+1].id}'`; return `function build${cap(par.id)}(){ _stubBuilder('${par.id}', '${par.num.replace(/§\s*/,'§')}', '${jsStr(par.name)}', ${prev}, ${next}); }`; }).join('\n'); const finalBuilderJs = `function build${cap(finalId)}(){ const body = document.getElementById('${finalId}-body'); let html = ''; html += makeCard('theory', 'Финал главы ${N}', '★', \`

Итоговый раздел главы «${spec.title}» будет добавлен в следующих обновлениях.

Раздел Phase 7.

\`); html += readButton('${finalId}'); html += secNav('${lastNonFinal}', null); body.innerHTML = html; wireReadBtn('${finalId}'); if(window.renderMathInElement) renderMath(body); }`; const progressInit = paras.map(par => `${par.id}:0`).join(','); return ` Геометрия 9 · Глава ${N} · ${spec.title}

Геометрия 9 · Глава ${N}

${spec.subtitle}
К геометрии 9

${spec.heroH}

${spec.heroP}

Прогресс по главе
0%
Параграфы главы
${sectionsHtml}
Достижение!
`; } ['ch2','ch3','ch4'].forEach(k => { const content = buildChapter(SPECS[k]); const outPath = path.join(OUT_DIR, 'geometry_9_' + k + '.html'); fs.writeFileSync(outPath, content, 'utf8'); console.log('Wrote', outPath, content.length, 'bytes'); });