fix(textbooks): Физика 9 — escape § в num + phys9_legacy.js + финалы 5 глав

Багфиксы:
- gen_phys9_ch.js: убран двойной escape \u00a7 → литерал §
  (раньше карточка показывала '\u00a7 1' вместо '§ 1')
- phys9_legacy.js (262 КБ): извлечён весь JS монолита для глобальных onclick-
  обработчиков (startAnim1, lab11add/all/reset, checkNum, togglePend36 и пр.).
  Setup-код в конце обёрнут в try/catch — он рассчитан на DOM монолита.
- migrate_phys9_ch4.js + migrate_phys9_content.js: подключают phys9_legacy.js
  во все 5 ch-файлов перед закрытием <head>.

Финалы глав (write_phys9_finals.js):
- ch1: 5 задач (кинематика — поезд, разгон, окружность, лодка/река)
- ch2: 5 задач (динамика — трение, Гук, свободное падение, перегрузка)
- ch3: 5 задач (статика — рычаг, Архимед, блок, КПД накл. плоск., льдина)
- ch4: 5 задач (импульс — неупр. удар, ЗСЭ, мощность крана, пуля, бросок)
- ch5: 5 контрольных по практикуму (среднее, ЛР2, ЛР4, ЛР6, ЛР10)

Все задачи с автопроверкой через checkNum() (теперь работает из legacy.js).
This commit is contained in:
Maxim Dolgolyov
2026-05-30 08:55:00 +03:00
parent 0c6618fb38
commit dcdcde5b4e
10 changed files with 6625 additions and 62 deletions
+386
View File
@@ -0,0 +1,386 @@
// Заполняет final1..final5 в physics_9_ch1..ch5.html — итоги главы:
// шпаргалка ключевых формул + 4-5 интегрированных задач с автопроверкой.
// Использует существующую функцию checkNum() из phys9_legacy.js для автопроверки.
'use strict';
const fs = require('fs');
const path = require('path');
const TBOOKS = path.join(__dirname, '..', '..', 'frontend', 'textbooks');
// === Контент финалов ===
const FINALS = {
ch1: {
title: 'Финал главы 1',
num: '★',
body: `
<div class="formula-grid" style="margin-bottom:20px">
<div class="fcard highlight"><h3>Равномерное движение</h3>
<div class="main-f">$\\vec{v} = \\text{const}$</div>
<p>$\\Delta\\vec{r} = \\vec{v}\\,t$ · $x = x_0 + v_x t$ · $s = vt$</p>
</div>
<div class="fcard"><h3>Равноускоренное</h3>
<div class="main-f">$\\vec{v} = \\vec{v}_0 + \\vec{a}\\,t$</div>
<p>$\\Delta\\vec{r} = \\vec{v}_0 t + \\dfrac{\\vec{a} t^2}{2}$ · $v^2 - v_0^2 = 2a_x\\Delta x$</p>
</div>
<div class="fcard"><h3>По окружности</h3>
<div class="main-f">$a_n = \\dfrac{v^2}{R} = \\omega^2 R$</div>
<p>$\\omega = \\dfrac{2\\pi}{T} = 2\\pi\\nu$ · $v = \\omega R$</p>
</div>
</div>
<div class="section-title"><i class="fas fa-star"></i> Интегрированные задачи</div>
<div class="task-card">
<div class="task-num">Задача 1</div>
<div class="task-text">Автомобиль за $t_1 = 20$ с разгоняется до $v_1 = 20$ м/с, далее едет $t_2 = 60$ с с постоянной скоростью. Найдите средний модуль скорости за всё время движения. Начальная скорость $v_0 = 0$.</div>
<div class="task-hint">Сложите путь на каждом участке: $s_1 = v_1 t_1 / 2$, $s_2 = v_1 t_2$. Средняя $\\langle v\\rangle = (s_1 + s_2)/(t_1 + t_2)$.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin1-q1" step="any"><span class="unit-lbl">м/с</span>
<button class="btn btn-pri" onclick="checkNum('fin1-q1', 17.5, 'м/с', 0.5)">Проверить</button></div>
<div class="feedback" id="fb-fin1-q1"></div>
</div>
<div class="task-card">
<div class="task-num">Задача 2</div>
<div class="task-text">Тело движется с ускорением $a = 2$ м/с². Через $t = 5$ с его скорость стала $v = 14$ м/с. Найдите начальную скорость тела.</div>
<div class="task-hint">$v = v_0 + at$, откуда $v_0 = v - at$.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin1-q2" step="any"><span class="unit-lbl">м/с</span>
<button class="btn btn-pri" onclick="checkNum('fin1-q2', 4, 'м/с', 0.1)">Проверить</button></div>
<div class="feedback" id="fb-fin1-q2"></div>
</div>
<div class="task-card">
<div class="task-num">Задача 3</div>
<div class="task-text">Шарик движется по окружности радиуса $R = 0{,}5$ м с периодом $T = 2{,}0$ с. Найдите модуль центростремительного ускорения.</div>
<div class="task-hint">$a_n = \\dfrac{4\\pi^2 R}{T^2}$. Подставьте $\\pi \\approx 3{,}14$.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin1-q3" step="any"><span class="unit-lbl">м/с²</span>
<button class="btn btn-pri" onclick="checkNum('fin1-q3', 4.93, 'м/с²', 0.1)">Проверить</button></div>
<div class="feedback" id="fb-fin1-q3"></div>
</div>
<div class="task-card">
<div class="task-num">Задача 4</div>
<div class="task-text">Катер движется по реке со скоростью $v_к = 5$ м/с относительно воды. Скорость течения $v_р = 2$ м/с. Найдите модуль скорости катера относительно берега при движении против течения.</div>
<div class="task-hint">Против течения скорости вычитаются: $v = v_к - v_р$.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin1-q4" step="any"><span class="unit-lbl">м/с</span>
<button class="btn btn-pri" onclick="checkNum('fin1-q4', 3, 'м/с', 0.05)">Проверить</button></div>
<div class="feedback" id="fb-fin1-q4"></div>
</div>
<div class="task-card">
<div class="task-num">Задача 5 (повышенный уровень)</div>
<div class="task-text">Поезд проходит мимо пешехода за $t_1 = 8$ с, а мимо платформы длиной $L = 200$ м — за $t_2 = 18$ с. Найдите скорость поезда. Поезд движется равномерно.</div>
<div class="task-hint">За $t_1$ поезд проходит свою длину $\\ell$, за $t_2$$\\ell + L$. Имеем $\\ell = v t_1$ и $\\ell + L = v t_2$. Отсюда $v = L/(t_2 - t_1)$.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin1-q5" step="any"><span class="unit-lbl">м/с</span>
<button class="btn btn-pri" onclick="checkNum('fin1-q5', 20, 'м/с', 0.1)">Проверить</button></div>
<div class="feedback" id="fb-fin1-q5"></div>
</div>
`,
},
ch2: {
title: 'Финал главы 2',
num: '★',
body: `
<div class="formula-grid" style="margin-bottom:20px">
<div class="fcard highlight"><h3>Законы Ньютона</h3>
<div class="main-f">$\\vec{F} = m\\vec{a}$</div>
<p>1-й: ИСО; 2-й: $\\vec{a} = \\vec{F}/m$; 3-й: $\\vec{F}_{12} = -\\vec{F}_{21}$</p>
</div>
<div class="fcard"><h3>Силы</h3>
<div class="main-f">$F_{\\text{упр}} = -kx$, $F_{\\text{тр}} = \\mu N$</div>
<p>Тяжести: $mg$ · Гравит.: $F = G m_1 m_2/r^2$</p>
</div>
<div class="fcard"><h3>Вес</h3>
<div class="main-f">$P = m(g \\pm a)$</div>
<p>Свободное падение → $P = 0$ (невесомость)</p>
</div>
</div>
<div class="section-title"><i class="fas fa-star"></i> Интегрированные задачи</div>
<div class="task-card">
<div class="task-num">Задача 1</div>
<div class="task-text">На тело массой $m = 2$ кг действует сила $F = 10$ Н в горизонтальном направлении. Сила трения $F_{\\text{тр}} = 4$ Н. Найдите модуль ускорения тела.</div>
<div class="task-hint">Равнодействующая $F_{\\text{рез}} = F - F_{\\text{тр}}$, ускорение $a = F_{\\text{рез}}/m$.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin2-q1" step="any"><span class="unit-lbl">м/с²</span>
<button class="btn btn-pri" onclick="checkNum('fin2-q1', 3, 'м/с²', 0.05)">Проверить</button></div>
<div class="feedback" id="fb-fin2-q1"></div>
</div>
<div class="task-card">
<div class="task-num">Задача 2</div>
<div class="task-text">Под действием груза пружина с жёсткостью $k = 200$ Н/м растянулась на $x = 5$ см. Найдите массу груза. $g = 9{,}81$ м/с².</div>
<div class="task-hint">В равновесии $kx = mg$, отсюда $m = kx/g$.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin2-q2" step="any"><span class="unit-lbl">кг</span>
<button class="btn btn-pri" onclick="checkNum('fin2-q2', 1.02, 'кг', 0.05)">Проверить</button></div>
<div class="feedback" id="fb-fin2-q2"></div>
</div>
<div class="task-card">
<div class="task-num">Задача 3</div>
<div class="task-text">Брусок массой $m = 5$ кг скользит по горизонтальной поверхности с коэффициентом трения $\\mu = 0{,}3$. Найдите силу трения скольжения. $g = 10$ м/с².</div>
<div class="task-hint">$F_{\\text{тр}} = \\mu mg$.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin2-q3" step="any"><span class="unit-lbl">Н</span>
<button class="btn btn-pri" onclick="checkNum('fin2-q3', 15, 'Н', 0.1)">Проверить</button></div>
<div class="feedback" id="fb-fin2-q3"></div>
</div>
<div class="task-card">
<div class="task-num">Задача 4</div>
<div class="task-text">Тело свободно падает с высоты $h = 45$ м. Найдите время падения. $g = 10$ м/с².</div>
<div class="task-hint">$h = gt^2/2$, отсюда $t = \\sqrt{2h/g}$.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin2-q4" step="any"><span class="unit-lbl">с</span>
<button class="btn btn-pri" onclick="checkNum('fin2-q4', 3, 'с', 0.05)">Проверить</button></div>
<div class="feedback" id="fb-fin2-q4"></div>
</div>
<div class="task-card">
<div class="task-num">Задача 5 (повышенный уровень)</div>
<div class="task-text">Космонавт массой $m = 80$ кг стоит на полу лифта. Лифт движется вверх с ускорением $a = 2{,}0$ м/с². Найдите вес космонавта. $g = 10$ м/с².</div>
<div class="task-hint">$P = m(g + a)$ при движении вверх с положительным ускорением (перегрузка).</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin2-q5" step="any"><span class="unit-lbl">Н</span>
<button class="btn btn-pri" onclick="checkNum('fin2-q5', 960, 'Н', 5)">Проверить</button></div>
<div class="feedback" id="fb-fin2-q5"></div>
</div>
`,
},
ch3: {
title: 'Финал главы 3',
num: '★',
body: `
<div class="formula-grid" style="margin-bottom:20px">
<div class="fcard highlight"><h3>Равновесие</h3>
<div class="main-f">$\\sum\\vec{F} = 0$ и $\\sum M = 0$</div>
<p>Момент: $M = F \\cdot \\ell$ (плечо)</p>
</div>
<div class="fcard"><h3>Простые механизмы</h3>
<div class="main-f">$F_1 \\ell_1 = F_2 \\ell_2$</div>
<p>Рычаг · подв. блок (выигрыш в 2 раза) · накл. плоскость</p>
</div>
<div class="fcard"><h3>Архимед</h3>
<div class="main-f">$F_A = \\rho_ж g V_{\\text{погр}}$</div>
<p>КПД: $\\eta = A_{\\text{пол}}/A_{\\text{сов}} \\cdot 100\\%$</p>
</div>
</div>
<div class="section-title"><i class="fas fa-star"></i> Интегрированные задачи</div>
<div class="task-card">
<div class="task-num">Задача 1</div>
<div class="task-text">Рычаг в равновесии. На левое плечо длиной $\\ell_1 = 0{,}3$ м действует сила $F_1 = 60$ Н. Правое плечо длиной $\\ell_2 = 0{,}9$ м. Найдите силу $F_2$ на правом плече.</div>
<div class="task-hint">$F_1 \\ell_1 = F_2 \\ell_2$, отсюда $F_2 = F_1 \\ell_1 / \\ell_2$.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin3-q1" step="any"><span class="unit-lbl">Н</span>
<button class="btn btn-pri" onclick="checkNum('fin3-q1', 20, 'Н', 0.2)">Проверить</button></div>
<div class="feedback" id="fb-fin3-q1"></div>
</div>
<div class="task-card">
<div class="task-num">Задача 2</div>
<div class="task-text">Куб со стороной $a = 10$ см полностью погружён в воду. Плотность воды $\\rho = 1000$ кг/м³, $g = 10$ м/с². Найдите выталкивающую силу.</div>
<div class="task-hint">$V = a^3$, $F_A = \\rho g V$.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin3-q2" step="any"><span class="unit-lbl">Н</span>
<button class="btn btn-pri" onclick="checkNum('fin3-q2', 10, 'Н', 0.1)">Проверить</button></div>
<div class="feedback" id="fb-fin3-q2"></div>
</div>
<div class="task-card">
<div class="task-num">Задача 3</div>
<div class="task-text">Подвижный блок поднимает груз весом $P = 200$ Н на высоту $h_1 = 1$ м. Найдите силу тяги $F$, прикладываемую к нити (без учёта трения и веса блока).</div>
<div class="task-hint">Подвижный блок даёт выигрыш в силе в 2 раза: $F = P/2$.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin3-q3" step="any"><span class="unit-lbl">Н</span>
<button class="btn btn-pri" onclick="checkNum('fin3-q3', 100, 'Н', 1)">Проверить</button></div>
<div class="feedback" id="fb-fin3-q3"></div>
</div>
<div class="task-card">
<div class="task-num">Задача 4</div>
<div class="task-text">Тело весом $P = 50$ Н поднимают по наклонной плоскости длиной $\\ell = 3$ м на высоту $h = 1$ м. Сила тяги $F = 20$ Н. Найдите КПД наклонной плоскости.</div>
<div class="task-hint">$A_{\\text{пол}} = Ph$, $A_{\\text{сов}} = F\\ell$, $\\eta = A_{\\text{пол}}/A_{\\text{сов}} \\cdot 100\\%$.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin3-q4" step="any"><span class="unit-lbl">%</span>
<button class="btn btn-pri" onclick="checkNum('fin3-q4', 83.3, '%', 1)">Проверить</button></div>
<div class="feedback" id="fb-fin3-q4"></div>
</div>
<div class="task-card">
<div class="task-num">Задача 5 (повышенный уровень)</div>
<div class="task-text">Льдина имеет объём $V = 2{,}0$ м³ и плавает в пресной воде. Плотность льда $\\rho_л = 900$ кг/м³, воды $\\rho_в = 1000$ кг/м³. Какой объём льдины находится над водой?</div>
<div class="task-hint">Условие плавания: $mg = F_A$, откуда $\\rho_л V g = \\rho_в V_{\\text{погр}} g$. Объём над водой: $V - V_{\\text{погр}}$.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin3-q5" step="any"><span class="unit-lbl">м³</span>
<button class="btn btn-pri" onclick="checkNum('fin3-q5', 0.2, 'м³', 0.01)">Проверить</button></div>
<div class="feedback" id="fb-fin3-q5"></div>
</div>
`,
},
ch4: {
title: 'Финал главы 4',
num: '★',
body: `
<div class="formula-grid" style="margin-bottom:20px">
<div class="fcard highlight"><h3>Импульс</h3>
<div class="main-f">$\\vec{p} = m\\vec{v}$</div>
<p>ЗСИ: $\\sum\\vec{p}_{\\text{до}} = \\sum\\vec{p}_{\\text{после}}$</p>
</div>
<div class="fcard"><h3>Работа · мощность</h3>
<div class="main-f">$A = F\\Delta r\\cos\\alpha$</div>
<p>$P = A/\\Delta t$ · $E_к = mv^2/2$ · $E_п = mgh$</p>
</div>
<div class="fcard"><h3>ЗСЭ</h3>
<div class="main-f">$E_к + E_п = \\text{const}$</div>
<p>В замкнутой консерв. сист. полная мех. энергия сохраняется</p>
</div>
</div>
<div class="section-title"><i class="fas fa-star"></i> Интегрированные задачи</div>
<div class="task-card">
<div class="task-num">Задача 1</div>
<div class="task-text">Тележка массой $m_1 = 3$ кг движется со скоростью $v_1 = 4$ м/с и сталкивается с покоящейся тележкой массой $m_2 = 1$ кг. После сцепления они движутся вместе. Найдите их общую скорость.</div>
<div class="task-hint">ЗСИ: $m_1 v_1 = (m_1 + m_2) v$, отсюда $v = m_1 v_1 / (m_1 + m_2)$.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin4-q1" step="any"><span class="unit-lbl">м/с</span>
<button class="btn btn-pri" onclick="checkNum('fin4-q1', 3, 'м/с', 0.05)">Проверить</button></div>
<div class="feedback" id="fb-fin4-q1"></div>
</div>
<div class="task-card">
<div class="task-num">Задача 2</div>
<div class="task-text">Тело массой $m = 2$ кг падает с высоты $h = 5$ м без начальной скорости. Найдите кинетическую энергию тела в момент удара о землю (сопротивлением воздуха пренебречь). $g = 10$ м/с².</div>
<div class="task-hint">ЗСЭ: вся потенциальная энергия переходит в кинетическую. $E_к = mgh$.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin4-q2" step="any"><span class="unit-lbl">Дж</span>
<button class="btn btn-pri" onclick="checkNum('fin4-q2', 100, 'Дж', 1)">Проверить</button></div>
<div class="feedback" id="fb-fin4-q2"></div>
</div>
<div class="task-card">
<div class="task-num">Задача 3</div>
<div class="task-text">Подъёмный кран поднимает груз массой $m = 500$ кг на высоту $h = 12$ м за $t = 30$ с. Найдите среднюю мощность крана. $g = 10$ м/с².</div>
<div class="task-hint">$A = mgh$, $P = A/t$.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin4-q3" step="any"><span class="unit-lbl">Вт</span>
<button class="btn btn-pri" onclick="checkNum('fin4-q3', 2000, 'Вт', 10)">Проверить</button></div>
<div class="feedback" id="fb-fin4-q3"></div>
</div>
<div class="task-card">
<div class="task-num">Задача 4</div>
<div class="task-text">Пуля массой $m = 10$ г летит со скоростью $v = 400$ м/с. Найдите модуль её импульса.</div>
<div class="task-hint">$p = mv$. Не забудьте перевести массу в кг.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin4-q4" step="any"><span class="unit-lbl">кг·м/с</span>
<button class="btn btn-pri" onclick="checkNum('fin4-q4', 4, 'кг·м/с', 0.05)">Проверить</button></div>
<div class="feedback" id="fb-fin4-q4"></div>
</div>
<div class="task-card">
<div class="task-num">Задача 5 (повышенный уровень)</div>
<div class="task-text">Камень бросают вертикально вверх со скоростью $v_0 = 20$ м/с. На какой высоте $h$ кинетическая энергия камня станет в 3 раза меньше начальной? $g = 10$ м/с².</div>
<div class="task-hint">ЗСЭ: $\\dfrac{mv_0^2}{2} = \\dfrac{mv^2}{2} + mgh$. По условию $\\dfrac{mv^2}{2} = \\dfrac{1}{3}\\dfrac{mv_0^2}{2}$. Отсюда $mgh = \\dfrac{2}{3}\\dfrac{mv_0^2}{2}$, т. е. $h = \\dfrac{v_0^2}{3g}$.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin4-q5" step="any"><span class="unit-lbl">м</span>
<button class="btn btn-pri" onclick="checkNum('fin4-q5', 13.3, 'м', 0.3)">Проверить</button></div>
<div class="feedback" id="fb-fin4-q5"></div>
</div>
`,
},
ch5: {
title: 'Финал главы 5',
num: '★',
body: `
<div class="formula-grid" style="margin-bottom:20px">
<div class="fcard highlight"><h3>Погрешности</h3>
<div class="main-f">$\\Delta x = \\Delta x_{\\text{сист}} + \\Delta x_{\\text{случ}}$</div>
<p>$\\varepsilon_x = \\dfrac{\\Delta x}{\\langle x\\rangle}\\cdot 100\\%$ · итог: $x = \\langle x\\rangle \\pm \\Delta x$</p>
</div>
<div class="fcard"><h3>Ключевые формулы 12 ЛР</h3>
<div class="main-f">$a = \\dfrac{2l}{t^2}$, $\\mu = \\dfrac{F_{\\text{тр}}}{P}$, $F_A = F_1 - F_2$</div>
<p>$k = F/x$ · $\\eta = \\dfrac{A_{\\text{пол}}}{A_{\\text{сов}}}$ · $v_0 = l\\sqrt{g/(2h)}$</p>
</div>
<div class="fcard"><h3>Проверка законов</h3>
<div class="main-f">ЗСИ · ЗСЭ · условие равновесия</div>
<p>ЛР7: $F_1 \\ell_1 = F_2 \\ell_2$ · ЛР11: $m_1 l_1 = m_1 l_1' + m_2 l_2'$ · ЛР12: $F|x| = ml^2 g/(2h)$</p>
</div>
</div>
<div class="section-title"><i class="fas fa-star"></i> Контрольные вопросы по практикуму</div>
<div class="task-card">
<div class="task-num">Вопрос 1</div>
<div class="task-text">При пяти повторных измерениях времени получены значения: $4{,}8$ · $5{,}0$ · $5{,}2$ · $4{,}9$ · $5{,}1$ с. Найдите среднее значение $\\langle t\\rangle$.</div>
<div class="task-hint">$\\langle t\\rangle = (t_1 + t_2 + t_3 + t_4 + t_5)/5$.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin5-q1" step="any"><span class="unit-lbl">с</span>
<button class="btn btn-pri" onclick="checkNum('fin5-q1', 5.0, 'с', 0.02)">Проверить</button></div>
<div class="feedback" id="fb-fin5-q1"></div>
</div>
<div class="task-card">
<div class="task-num">Вопрос 2</div>
<div class="task-text">В ЛР2 шарик прошёл по жёлобу длину $l = 0{,}80$ м за $t = 1{,}0$ с. Найдите модуль ускорения шарика.</div>
<div class="task-hint">$a = 2l/t^2$.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin5-q2" step="any"><span class="unit-lbl">м/с²</span>
<button class="btn btn-pri" onclick="checkNum('fin5-q2', 1.6, 'м/с²', 0.05)">Проверить</button></div>
<div class="feedback" id="fb-fin5-q2"></div>
</div>
<div class="task-card">
<div class="task-num">Вопрос 3</div>
<div class="task-text">В ЛР4 при подвешивании груза массой $m = 0{,}2$ кг пружина растянулась на $x = 4$ см. Найдите жёсткость пружины. $g = 10$ м/с².</div>
<div class="task-hint">$k = mg/x$.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin5-q3" step="any"><span class="unit-lbl">Н/м</span>
<button class="btn btn-pri" onclick="checkNum('fin5-q3', 50, 'Н/м', 0.5)">Проверить</button></div>
<div class="feedback" id="fb-fin5-q3"></div>
</div>
<div class="task-card">
<div class="task-num">Вопрос 4</div>
<div class="task-text">В ЛР6 шарик упал на пол с высоты $h = 0{,}8$ м, пройдя по горизонтали $l = 1{,}6$ м. Найдите начальную горизонтальную скорость шарика. $g = 10$ м/с².</div>
<div class="task-hint">$v_0 = l\\sqrt{g/(2h)}$. Подставьте численно.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin5-q4" step="any"><span class="unit-lbl">м/с</span>
<button class="btn btn-pri" onclick="checkNum('fin5-q4', 4, 'м/с', 0.1)">Проверить</button></div>
<div class="feedback" id="fb-fin5-q4"></div>
</div>
<div class="task-card">
<div class="task-num">Вопрос 5</div>
<div class="task-text">В ЛР10 цилиндр в воздухе весил $F_1 = 1{,}0$ Н, а полностью погружённый в воду — $F_2 = 0{,}6$ Н. Найдите модуль выталкивающей силы.</div>
<div class="task-hint">$F_A = F_1 - F_2$.</div>
<div class="ans-row"><input type="number" class="ans-inp" id="fin5-q5" step="any"><span class="unit-lbl">Н</span>
<button class="btn btn-pri" onclick="checkNum('fin5-q5', 0.4, 'Н', 0.02)">Проверить</button></div>
<div class="feedback" id="fb-fin5-q5"></div>
</div>
`,
},
};
// === Замена STUB в ch-файле ===
for (const [chKey, fin] of Object.entries(FINALS)) {
const chN = parseInt(chKey.slice(2));
const finId = 'final' + chN;
const dstPath = path.join(TBOOKS, `physics_9_${chKey}.html`);
let h = fs.readFileSync(dstPath, 'utf8');
const before = h.length;
// STUB builder для finalN использует makeCard('theory', 'Финал главы N', '★', `...`)
const stubRegex = new RegExp(
`makeCard\\('theory', "Финал главы ${chN}", "\\u2605", \`[\\s\\S]*?\`\\);`
);
const match = h.match(stubRegex);
if (!match) {
console.error(`Final STUB not found for ${chKey} (looking for 'Финал главы ${chN}')`);
continue;
}
// Экранируем для template literal
const esc = fin.body.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$\{/g, '\\${');
const replacement = `makeCard('theory', "Финал главы ${chN}", "★", \`\n${esc}\n \`);`;
h = h.replace(stubRegex, () => replacement);
fs.writeFileSync(dstPath, h);
console.log(`${chKey} final: ${before}${h.length} bytes (+${h.length - before})`);
// Sanity parse
const scripts = [...h.matchAll(/<script>([\s\S]*?)<\/script>/g)];
for (const m of scripts) {
try { new Function(m[1]); }
catch(e) { console.error(`JS PARSE FAIL in ${chKey}:`, e.message); process.exit(1); }
}
}
console.log('Finals written.');