diff --git a/backend/scripts/inject_p8_ch23_tasks.cjs b/backend/scripts/inject_p8_ch23_tasks.cjs new file mode 100644 index 0000000..859e4d2 --- /dev/null +++ b/backend/scripts/inject_p8_ch23_tasks.cjs @@ -0,0 +1,227 @@ +// 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 += '
' + +'
IV-5
Тренажёр: ${TASKS[pid].length} расчётных задач
' + +'
Введи числовой ответ (точка как разделитель). Решено все верно — +20 XP.
' + +'
' + +'
Задача: 1 / ${TASKS[pid].length}Правильно: 0
' + +'
'; +`; +} + +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 = + '
Задача '+(i+1)+'. '+t.q+'
' + +'
' + +'' + +'' + +'
' + +'' + +'
'; + 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(/