Files
Learn_System/backend/scripts/inject_p8_ch23_tasks.cjs
Maxim Dolgolyov 15fbd73847 feat(p8 ch2-3): IV-5 расчётные задачи для всех MCQ-only параграфов
Завершение Physics 8 — IV-5 добавлен в оставшиеся 13 параграфов:

Ch2 (Электромагнитные явления, 11 параграфов):
- §12 Электризация: 5 (выравнивание зарядов, n=q/e)
- §13 Проводники/диэлектрики: 5 (плотность носителей, I=q/t)
- §14 Электростатическая индукция: 5 (заземление, угол отклонения)
- §16 Строение атома: 5 (q=ne, заряд ядра)
- §17 Электрическое поле: 5 (E=F/q, F=qE, A=qEd, плотность линий)
- §19 Источники тока: 5 (ЭДС = A/q, A = εIt)
- §21 Электрическая цепь: 5 (I = q/t, числ. электронов)
- §28 Постоянные магниты: 5 (полюса, северный/южный)
- §29 Магнитное поле тока: 5 (F = BIL, B ∝ I)
- §30 Опыт Эрстеда: 5 (правило буравчика, год открытия)
- §31 Электромагнит: 5 (B ∝ N, B ∝ I, сердечник)

Ch3 (Световые явления, 2 параграфа):
- §32 Источники света: 5 (c=3·10^8, время до Луны/Солнца)
- §39 Дисперсия/глаз: 5 (спектр, длины волн, D=1/F)

Итого: 65 новых задач с автопроверкой, подсказкой-решением (KaTeX),
+20 XP. Все Phys 8 параграфы теперь имеют числовой тренажёр.
2026-05-30 09:36:22 +03:00

228 lines
28 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Inject IV-5 «Расчётные задачи» into MCQ-only paragraphs of physics_8_ch2.html
// and physics_8_ch3.html — параграфы §12,13,14,16,17,19,21,28,29,30,31,32,39.
'use strict';
const fs = require('fs');
const path = require('path');
const TBOOKS = path.join(__dirname, '..', '..', 'frontend', 'textbooks');
// === Numeric tasks per paragraph ===
const TASKS = {
// === Ch2: Электромагнитные явления ===
p12: [ // Электризация
{ q: 'Два одинаковых шарика имели заряды $q_1 = +6$ мкКл и $q_2 = -2$ мкКл. После соприкосновения и разделения, какой заряд (мкКл) остался на каждом?', ans: 2, tol: 0.05, why: 'При контакте одинаковых шаров заряды выравниваются: $q = (q_1 + q_2)/2 = (+6 - 2)/2 = +2$ мкКл.' },
{ q: 'У эбонитовой палочки $-30$ нКл, у шерсти $+30$ нКл. Какой суммарный заряд (нКл) системы по закону сохранения заряда?', ans: 0, tol: 0.5, why: 'Заряд изолированной системы сохраняется. Если до трения было $0$ — и после $0$: $-30 + 30 = 0$.' },
{ q: 'У шарика заряд $q = +4$ мкКл. Сколько электронов нужно добавить, чтобы он стал нейтральным? ($e = 1{,}6 \\cdot 10^{-19}$ Кл). Ответ дайте в единицах $\\times 10^{13}$.', ans: 2.5, tol: 0.1, why: '$n = q/e = 4 \\cdot 10^{-6} / 1{,}6 \\cdot 10^{-19} = 2{,}5 \\cdot 10^{13}$ электронов.' },
{ q: 'Тело потеряло $n = 5 \\cdot 10^{12}$ электронов. Каков стал его заряд (мкКл)? ($e = 1{,}6 \\cdot 10^{-19}$ Кл)', ans: 0.8, tol: 0.02, why: '$q = n \\cdot e = 5 \\cdot 10^{12} \\cdot 1{,}6 \\cdot 10^{-19} = 8 \\cdot 10^{-7}$ Кл $= 0{,}8$ мкКл (положительный, т. к. потерял электроны).' },
{ q: 'Если соединить шары с зарядами $q_1 = +10$ нКл и $q_2 = +6$ нКл одинакового размера, какой заряд (нКл) будет на каждом после разделения?', ans: 8, tol: 0.2, why: '$q = (q_1 + q_2)/2 = 16/2 = 8$ нКл.' },
],
p13: [ // Проводники и диэлектрики
{ q: 'У проводника плотность свободных электронов $n = 10^{29}$ м⁻³, у диэлектрика $\\sim 10^{17}$ м⁻³. Во сколько раз больше носителей у проводника? (степень 10)', ans: 12, tol: 0.5, why: '$n_{пр}/n_{ди} = 10^{29}/10^{17} = 10^{12}$.' },
{ q: 'Стержень проводника $L = 10$ см заряжен. Если соединить с таким же незаряженным, какая часть (в %) заряда уйдёт на второй?', ans: 50, tol: 1, why: 'Заряды выравниваются, на каждом — половина исходного: $50\\,\\%$.' },
{ q: 'Какой материал лучший проводник: $1$ — стекло, $2$ — сухое дерево, $3$ — медь, $4$ — пластик? Введите номер.', ans: 3, tol: 0.1, why: 'Металлы (медь) — лучшие проводники из перечисленных.' },
{ q: 'У диэлектрика свободных зарядов нет, но связанные могут поляризоваться. Сколько свободных носителей в идеальном диэлектрике?', ans: 0, tol: 0.1, why: 'В идеальном диэлектрике $n_{своб} = 0$ — есть только связанные заряды атомов и молекул.' },
{ q: 'Через тело прошло за $t = 2$ с $q = 4$ Кл. Какова сила тока $I$ (А)?', ans: 2, tol: 0.05, why: '$I = q/t = 4/2 = 2$ А.' },
],
p14: [ // Электростатическая индукция
{ q: 'К незаряженному проводнику поднесли $+$-заряженный шар. Какой заряд индуцируется на ближнем конце проводника?', ans: -1, tol: 0.1, why: 'Свободные электроны притянутся к $+$ — на ближнем конце $-1$ (отрицательный заряд). Введите $-1$.' },
{ q: 'Шар с зарядом $q = +20$ нКл коснулся незаряженного такого же шара. Заряд (нКл) на одном шаре после разделения?', ans: 10, tol: 0.2, why: 'Заряды выравниваются: $q/2 = 10$ нКл.' },
{ q: 'Электроскоп заряжен зарядом $q = 5$ нКл. Что произойдёт с углом отклонения лепестков, если к нему поднести заряд того же знака? ($1$ — уменьшится, $2$ — увеличится, $3$ — не изменится)', ans: 2, tol: 0.1, why: 'Одноимённые заряды отталкиваются — лепестки разойдутся сильнее.' },
{ q: 'Если поднести $+$-заряд к нейтральному шару и заземлить его (отвести электроны), какой заряд останется на шаре после удаления $+$-заряда? ($1$ — положительный, $-1$ — отрицательный)', ans: -1, tol: 0.1, why: 'Электроны притянулись и не ушли — шар стал отрицательным. Ответ $-1$.' },
{ q: 'Заряженная палочка приближается к листку фольги. Лепесток отклоняется на угол $\\alpha$. Если палочку удалить, какой будет $\\alpha$?', ans: 0, tol: 0.1, why: 'Без внешнего поля индуцированные заряды перераспределяются обратно — отклонение $0$.' },
],
p16: [ // Строение атома
{ q: 'У атома водорода $1$ электрон. Каков заряд электронной оболочки (в единицах $e$)? Введите модуль.', ans: 1, tol: 0.1, why: 'Один электрон с зарядом $-e$. Модуль $|q| = e = 1$ в этих единицах.' },
{ q: 'Электрон имеет заряд $e = 1{,}6 \\cdot 10^{-19}$ Кл. Какой суммарный заряд (Кл) у $n = 10^{20}$ электронов? Дайте ответ в виде $\\times 10^{1}$ Кл.', ans: 16, tol: 0.5, why: '$q = ne = 10^{20} \\cdot 1{,}6 \\cdot 10^{-19} = 16$ Кл.' },
{ q: 'Какой заряд имеет атомное ядро углерода $^{12}_{6}$C (в единицах $e$)?', ans: 6, tol: 0.1, why: 'У углерода $Z = 6$ протонов, каждый с зарядом $+e$. Заряд ядра $= +6e$.' },
{ q: 'Атом нейтрален. Сколько электронов вокруг ядра кислорода $^{16}_{8}$O?', ans: 8, tol: 0.1, why: 'В нейтральном атоме число электронов равно числу протонов: $Z = 8$.' },
{ q: 'Сколько Кл составляет заряд $5$ протонов? ($e = 1{,}6 \\cdot 10^{-19}$ Кл). Ответ $\\times 10^{-19}$.', ans: 8, tol: 0.2, why: '$q = 5e = 5 \\cdot 1{,}6 \\cdot 10^{-19} = 8 \\cdot 10^{-19}$ Кл.' },
],
p17: [ // Электрическое поле
{ q: 'В точке поля на заряд $q = 2$ нКл действует сила $F = 4 \\cdot 10^{-5}$ Н. Найдите модуль напряжённости $E$ (В/м). $E = F/q$.', ans: 20000, tol: 500, why: '$E = F/q = 4 \\cdot 10^{-5} / 2 \\cdot 10^{-9} = 2 \\cdot 10^{4} = 20\\,000$ В/м.' },
{ q: 'Напряжённость поля $E = 1000$ В/м. Какая сила (мкН) действует на заряд $q = 5$ нКл?', ans: 5, tol: 0.2, why: '$F = qE = 5 \\cdot 10^{-9} \\cdot 1000 = 5 \\cdot 10^{-6}$ Н $= 5$ мкН.' },
{ q: 'Однородное поле напряжённостью $E = 200$ В/м. Какая работа поля (мкДж) при перемещении заряда $q = 1$ мкКл вдоль линии поля на $d = 10$ см?', ans: 20, tol: 1, why: '$A = qEd = 10^{-6} \\cdot 200 \\cdot 0{,}1 = 2 \\cdot 10^{-5}$ Дж $= 20$ мкДж.' },
{ q: 'На пробный заряд $q_0$ в поле действует сила $F$. Если заряд $q_0$ удвоить, во сколько раз изменится $E$ в этой точке?', ans: 1, tol: 0.05, why: '$E$ — характеристика поля, не зависит от пробного заряда: $E$ не меняется (коэффициент $= 1$).' },
{ q: 'Силовые линии однородного поля идут параллельно с плотностью $5$ линий/см. У сильного поля плотность $20$ линий/см. Во сколько раз больше $E$?', ans: 4, tol: 0.2, why: 'Густота линий пропорциональна $E$: $20/5 = 4$ раза.' },
],
p19: [ // Источники тока
{ q: 'Батарея делает работу $A = 12$ Дж по перемещению заряда $q = 4$ Кл. Найдите ЭДС $\\mathcal{E}$ (В). $\\mathcal{E} = A/q$.', ans: 3, tol: 0.05, why: '$\\mathcal{E} = A/q = 12/4 = 3$ В.' },
{ q: 'ЭДС источника $\\mathcal{E} = 9$ В. Какую работу (Дж) совершат сторонние силы по переносу заряда $q = 5$ Кл?', ans: 45, tol: 1, why: '$A = \\mathcal{E} \\cdot q = 9 \\cdot 5 = 45$ Дж.' },
{ q: 'Аккумулятор отдал заряд $q = 0{,}5$ Кл при ЭДС $\\mathcal{E} = 12$ В. Сколько Дж работы он совершил?', ans: 6, tol: 0.1, why: '$A = \\mathcal{E} q = 12 \\cdot 0{,}5 = 6$ Дж.' },
{ q: 'У батарейки ЭДС $1{,}5$ В. Сколько Кл нужно перенести, чтобы получить $3$ Дж?', ans: 2, tol: 0.05, why: '$q = A/\\mathcal{E} = 3/1{,}5 = 2$ Кл.' },
{ q: 'Гальванический элемент работает $t = 60$ с с током $I = 0{,}1$ А и ЭДС $\\mathcal{E} = 1{,}5$ В. Какую работу (Дж) он совершил? ($A = \\mathcal{E} I t$)', ans: 9, tol: 0.2, why: '$A = \\mathcal{E} \\cdot I \\cdot t = 1{,}5 \\cdot 0{,}1 \\cdot 60 = 9$ Дж.' },
],
p21: [ // Электрическая цепь
{ q: 'За $t = 2$ с через сечение проводника прошёл заряд $q = 6$ Кл. Найдите силу тока $I$ (А). $I = q/t$.', ans: 3, tol: 0.05, why: '$I = q/t = 6/2 = 3$ А.' },
{ q: 'В цепи течёт ток $I = 0{,}5$ А. Какой заряд (Кл) пройдёт за минуту?', ans: 30, tol: 0.5, why: '$q = It = 0{,}5 \\cdot 60 = 30$ Кл.' },
{ q: 'Через лампочку прошло $q = 60$ Кл за $t = 5$ мин. Найдите $I$ (мА). Внимание: переведите минуты в секунды.', ans: 200, tol: 5, why: '$t = 300$ с, $I = q/t = 60/300 = 0{,}2$ А $= 200$ мА.' },
{ q: 'В лампе сила тока $I = 0{,}3$ А. Сколько электронов проходит через сечение нити за $t = 1$ с? ($e = 1{,}6 \\cdot 10^{-19}$ Кл). Ответ $\\times 10^{18}$.', ans: 1.875, tol: 0.05, why: '$n = q/e = It/e = 0{,}3 / 1{,}6 \\cdot 10^{-19} \\approx 1{,}88 \\cdot 10^{18}$.' },
{ q: 'Какой ток (А) в цепи, где за $0{,}5$ часа прошло $q = 900$ Кл?', ans: 0.5, tol: 0.02, why: '$t = 1800$ с, $I = q/t = 900/1800 = 0{,}5$ А.' },
],
p28: [ // Постоянные магниты
{ q: 'Сколько полюсов у любого магнита?', ans: 2, tol: 0.1, why: 'У любого магнита всегда $2$ полюса: северный N и южный S. Магнитного «монополя» не существует.' },
{ q: 'Если разрезать магнит на $2$ части, сколько магнитов получится?', ans: 2, tol: 0.1, why: 'Каждая часть будет иметь свои $2$ полюса — получаем $2$ магнита.' },
{ q: 'Магнит разрезали на $5$ кусков. Сколько всего полюсов у всех кусков?', ans: 10, tol: 0.1, why: 'Каждый магнит имеет $2$ полюса. Всего: $5 \\cdot 2 = 10$.' },
{ q: 'У одного магнита N-полюс, у другого S-полюс. Они притягиваются или отталкиваются? ($1$ — притягиваются, $0$ — отталкиваются)', ans: 1, tol: 0.1, why: 'Разноимённые магнитные полюса притягиваются (как и разноимённые заряды).' },
{ q: 'Какой полюс у Земли находится около географического Северного полюса? ($1$ — северный магнитный, $2$ — южный магнитный)', ans: 2, tol: 0.1, why: 'Около географ. севера — южный магнитный полюс Земли (поэтому стрелка компаса N притягивается к нему).' },
],
p29: [ // Магнитное поле тока
{ q: 'Опыт Эрстеда: магнитная стрелка отклоняется при включении тока в проводнике. Это значит, что вокруг тока есть... ($1$ — электрическое поле, $2$ — магнитное поле, $3$ — гравитационное)', ans: 2, tol: 0.1, why: 'Вокруг любого тока существует магнитное поле — ключевое открытие Эрстеда (1820).' },
{ q: 'Линии магнитного поля прямого тока — это: ($1$ — прямые, $2$ — концентрические окружности вокруг проводника, $3$ — параболы)', ans: 2, tol: 0.1, why: 'Силовые линии магнитного поля прямого тока — концентрические окружности в плоскостях, перпендикулярных проводнику.' },
{ q: 'У одного провода ток $I_1 = 2$ А, у другого $I_2 = 8$ А. У какого индукция магнитного поля на одинаковом расстоянии больше во сколько раз? ($B \\propto I$)', ans: 4, tol: 0.1, why: '$B \\propto I$, поэтому $B_2/B_1 = I_2/I_1 = 8/2 = 4$ раза.' },
{ q: 'Сила, действующая на проводник с током в магнитном поле, при $I = 5$ А, $B = 0{,}2$ Тл, $L = 0{,}1$ м: $F = BIL$ (Н)?', ans: 0.1, tol: 0.005, why: '$F = BIL = 0{,}2 \\cdot 5 \\cdot 0{,}1 = 0{,}1$ Н.' },
{ q: 'Если ток в проводнике увеличить в $3$ раза, во сколько раз увеличится сила в магнитном поле?', ans: 3, tol: 0.1, why: '$F = BIL \\propto I$, поэтому $F$ увеличится в $3$ раза.' },
],
p30: [ // Опыт Эрстеда (в этом учебнике — продолжение)
{ q: 'В каком году Эрстед обнаружил магнитное действие тока?', ans: 1820, tol: 5, why: 'Х. Эрстед открыл связь электрического тока и магнетизма в 1820 году.' },
{ q: 'Стрелка компаса находится над проводником. Какой угол (в градусах) к проводнику она составит при отсутствии тока? ($1$ — $0°$, $2$ — $90°$)', ans: 1, tol: 0.1, why: 'Без тока стрелка направлена вдоль магнитного поля Земли. Над проводником, протянутым с севера на юг, стрелка $\\parallel$ проводнику ($0°$).' },
{ q: 'При включении тока стрелка отклоняется. Когда ток отключают, что произойдёт? ($1$ — останется, $2$ — вернётся в исходное положение)', ans: 2, tol: 0.1, why: 'Без тока магнитное поле проводника исчезает, на стрелку действует только поле Земли — она возвращается.' },
{ q: 'Правило буравчика: если ток течёт вверх, в каком направлении вращаются силовые линии магн. поля? ($1$ — по часовой при взгляде сверху, $2$ — против часовой при взгляде сверху)', ans: 2, tol: 0.1, why: 'Правило правой руки: большой палец — направление тока, согнутые пальцы показывают направление поля. При токе вверх — против часовой при взгляде сверху.' },
{ q: 'Сила тока удвоилась. Во сколько раз сильнее отклонится магнитная стрелка (приближённо)?', ans: 2, tol: 0.1, why: 'Магнитное поле $B \\propto I$, отклонение стрелки тоже растёт примерно линейно — в $2$ раза.' },
],
p31: [ // Электромагнит
{ q: 'У электромагнита было $N_1 = 100$ витков, его магнитное поле $B_1$. После добавления стало $N_2 = 500$ витков (тот же ток). Во сколько раз вырастет $B$?', ans: 5, tol: 0.2, why: '$B \\propto N$, поэтому $B_2/B_1 = N_2/N_1 = 5$.' },
{ q: 'Ток в катушке вырос с $I_1 = 0{,}2$ А до $I_2 = 1$ А. Во сколько раз увеличилось магнитное поле электромагнита?', ans: 5, tol: 0.2, why: '$B \\propto I$, поэтому $B_2/B_1 = I_2/I_1 = 5$.' },
{ q: 'Без сердечника поле электромагнита $B_0 = 1$ мТл. С железным сердечником стало $B = 1000$ мТл. Во сколько раз сердечник усилил поле?', ans: 1000, tol: 10, why: 'Железо имеет магнитную проницаемость $\\mu \\sim 1000$. $B/B_0 = 1000$.' },
{ q: 'Электромагнит подняет груз массой $m = 50$ кг с силой $F = 500$ Н. Какова перегрузка $F/(mg)$? ($g = 10$ м/с²)', ans: 1, tol: 0.05, why: '$F/(mg) = 500/(50 \\cdot 10) = 500/500 = 1$ — сила в точности уравновешивает вес.' },
{ q: 'Если ток отключить, что произойдёт с магн. полем электромагнита? ($1$ — останется, $0$ — исчезнет)', ans: 0, tol: 0.1, why: 'Магнитное поле электромагнита создаётся током. Нет тока — нет поля. (В отличие от постоянного магнита.)' },
],
// === Ch3: Световые явления ===
p32: [ // Источники света
{ q: 'Скорость света в вакууме $c = 3 \\cdot 10^{8}$ м/с. За какое время (мкс) свет пройдёт $L = 300$ км?', ans: 1000, tol: 10, why: '$t = L/c = 3 \\cdot 10^{5} / 3 \\cdot 10^{8} = 10^{-3}$ с $= 1000$ мкс.' },
{ q: 'Свет от Солнца достигает Земли за $t = 500$ с. Какое расстояние (в км)? Ответ $\\times 10^{8}$.', ans: 1.5, tol: 0.05, why: '$L = ct = 3 \\cdot 10^{8} \\cdot 500 = 1{,}5 \\cdot 10^{11}$ м $= 1{,}5 \\cdot 10^{8}$ км.' },
{ q: 'Сколько секунд лётит свет от Луны до Земли, если расстояние $L = 384\\,000$ км?', ans: 1.28, tol: 0.05, why: '$t = L/c = 3{,}84 \\cdot 10^{8} / 3 \\cdot 10^{8} = 1{,}28$ с.' },
{ q: 'Свет звезды доходит до нас за $4$ года. Сколько $4$ световых лет в км? Ответ $\\times 10^{13}$.', ans: 3.78, tol: 0.05, why: '$1$ год $\\approx 3{,}15 \\cdot 10^{7}$ с. $L = c \\cdot 4 \\cdot 3{,}15 \\cdot 10^{7} = 3{,}78 \\cdot 10^{16}$ м $= 3{,}78 \\cdot 10^{13}$ км.' },
{ q: 'Какой из источников света — точечный с практической точки зрения: ($1$ — Солнце на небе для нас, $2$ — лампа в комнате с метра, $3$ — звезда)?', ans: 3, tol: 0.1, why: 'Звёзды настолько далеки, что их можно считать точечными источниками света. Солнце и лампа — нет.' },
],
p39: [ // §39 в ch3 — обычно «Глаз / Дисперсия / Оптические приборы»
{ q: 'Из скольких основных цветов состоит спектр белого света (радуга)?', ans: 7, tol: 0.1, why: '$7$ цветов: красный, оранжевый, жёлтый, зелёный, голубой, синий, фиолетовый.' },
{ q: 'У какого цвета света наибольшая длина волны: ($1$ — красный, $2$ — синий, $3$ — фиолетовый, $4$ — зелёный)?', ans: 1, tol: 0.1, why: 'Красный свет имеет наибольшую длину волны ($\\sim 700$ нм) среди видимого спектра.' },
{ q: 'У какого цвета света наименьшая длина волны: ($1$ — красный, $2$ — жёлтый, $3$ — зелёный, $4$ — фиолетовый)?', ans: 4, tol: 0.1, why: 'Фиолетовый свет имеет наименьшую длину волны ($\\sim 400$ нм).' },
{ q: 'Линза с фокусом $F = 25$ см. Оптическая сила $D = 1/F$ (дптр). Найдите $D$ при $F$ в метрах.', ans: 4, tol: 0.1, why: '$F = 0{,}25$ м, $D = 1/F = 1/0{,}25 = 4$ дптр.' },
{ q: 'У близорукого человека очки $-2$ дптр. Найдите фокусное расстояние линзы $F$ в м.', ans: -0.5, tol: 0.02, why: '$F = 1/D = 1/(-2) = -0{,}5$ м (рассеивающая линза).' },
],
};
// === Generate IV-5 widget HTML + initializer function per pid ===
function makeIv5Widget(pid) {
return `
/* IV5 — Расчётные задачи (auto-injected) */
h += '<div class="wg">'
+'<div class="wg-header"><span class="wg-badge">IV-5</span><div class="wg-title">Тренажёр: ${TASKS[pid].length} расчётных задач</div></div>'
+'<div class="wg-help">Введи числовой ответ (точка как разделитель). Решено все верно — +20 XP.</div>'
+'<div id="${pid}-tasks5"></div>'
+'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="${pid}-tasks5-i">1</b> / ${TASKS[pid].length}</span><span>Правильно: <b id="${pid}-tasks5-ok">0</b></span></div>'
+'</div>';
`;
}
function makeIv5Init(pid) {
const tasksLit = JSON.stringify(TASKS[pid]);
return `
function _init${pid}_iv5(){
const TASKS = ${tasksLit};
let i = 0, ok = 0, awarded = false;
function render(){
const t = TASKS[i]; const wrap = document.getElementById('${pid}-tasks5'); if(!wrap) return;
wrap.innerHTML =
'<div style="padding:10px 14px;background:rgba(15,23,42,.04);border-radius:9px;margin-bottom:10px;font-size:.95rem;line-height:1.55"><b>Задача '+(i+1)+'.</b> '+t.q+'</div>'
+'<div class="actions"><input type="number" step="0.001" class="tinp" id="${pid}-iv5-inp" placeholder="число" style="width:140px">'
+'<button class="btn primary" id="${pid}-iv5-go">Ответ</button>'
+'<button class="btn" id="${pid}-iv5-hint">Подсказка</button>'
+'<button class="btn" id="${pid}-iv5-next">Следующая</button></div>'
+'<details class="spoiler" id="${pid}-iv5-why-wrap" style="margin-top:8px;display:none"><summary>Решение</summary><div class="spoiler-body">'+t.why+'</div></details>'
+'<div class="feedback" id="${pid}-iv5-fb"></div>';
if (window.renderMathInElement) try { renderMathInElement(wrap, {delimiters:[{left:'$',right:'$',display:false}],throwOnError:false}); } catch(e){}
document.getElementById('${pid}-iv5-go').onclick = () => {
const v = parseFloat(document.getElementById('${pid}-iv5-inp').value.replace(',','.'));
const fb = document.getElementById('${pid}-iv5-fb');
const wh = document.getElementById('${pid}-iv5-why-wrap');
if (Math.abs(v - t.ans) <= t.tol) {
fb.className = 'feedback ok'; fb.innerHTML = 'Верно!'; ok++;
document.getElementById('${pid}-tasks5-ok').textContent = ok;
wh.style.display = 'block';
} else {
fb.className = 'feedback fail'; fb.innerHTML = 'Не совсем. Ожидался $' + t.ans + '$. Загляни в подсказку.';
if (window.renderMathInElement) try { renderMathInElement(fb, {delimiters:[{left:'$',right:'$',display:false}],throwOnError:false}); } catch(e){}
}
};
document.getElementById('${pid}-iv5-hint').onclick = () => {
const wh = document.getElementById('${pid}-iv5-why-wrap');
wh.style.display = wh.style.display === 'block' ? 'none' : 'block';
};
document.getElementById('${pid}-iv5-next').onclick = () => {
i = (i + 1) % TASKS.length;
document.getElementById('${pid}-tasks5-i').textContent = i + 1;
render();
if (ok === TASKS.length && !awarded) { awarded = true; if (typeof addXp === 'function') addXp(20, '${pid}-iv5'); }
};
}
render();
}
`;
}
// === Patch chapter file ===
function patchChapter(fname, pids) {
const dst = path.join(TBOOKS, fname);
let h = fs.readFileSync(dst, 'utf8');
let patched = 0;
for (const pid of pids) {
if (!TASKS[pid]) { console.warn(` ${pid}: no task data`); continue; }
const widget = makeIv5Widget(pid);
const init = makeIv5Init(pid);
const insertWidgetBefore = `box.innerHTML = h + secNavFor('${pid}') + readButton('${pid}');`;
if (!h.includes(insertWidgetBefore)) {
console.warn(` ${pid}: insert marker not found`);
continue;
}
// Check if already injected
if (h.includes(`id="${pid}-tasks5"`)) {
console.log(` ${pid}: already injected, skip`);
continue;
}
h = h.replace(insertWidgetBefore, widget.trim() + '\n\n ' + insertWidgetBefore);
const wireMarker = `wireReadBtn('${pid}');`;
h = h.replace(wireMarker, wireMarker + `\n _init${pid}_iv5();`);
const fnStart = h.indexOf(`function build_${pid}()`);
const fnEnd = h.indexOf('\n}\n', fnStart);
const insertPos = fnEnd + 3;
h = h.slice(0, insertPos) + '\n' + init.trim() + '\n' + h.slice(insertPos);
patched++;
console.log(` ${pid}: patched (${TASKS[pid].length} tasks)`);
}
fs.writeFileSync(dst, h);
console.log(`${fname}: ${patched}/${pids.length} patched, ${h.length} bytes`);
// 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 ${fname}:`, e.message); process.exit(1); }
}
console.log(`${fname}: inline JS parses OK`);
}
console.log('=== physics_8_ch2.html ===');
patchChapter('physics_8_ch2.html', ['p12','p13','p14','p16','p17','p19','p21','p28','p29','p30','p31']);
console.log('=== physics_8_ch3.html ===');
patchChapter('physics_8_ch3.html', ['p32','p39']);