diff --git a/frontend/textbooks/physics_8_ch2.html b/frontend/textbooks/physics_8_ch2.html
index 830d275..252e1af 100644
--- a/frontend/textbooks/physics_8_ch2.html
+++ b/frontend/textbooks/physics_8_ch2.html
@@ -372,8 +372,20 @@ const SIDEBARS = {
["Направление тока","от + к − (исторически)"],
["В металлах","электроны против тока"]
]},
- p21:{title:"Шпаргалка § 21",rows:[["В разработке","Phase 3 Wave 2"]]},
- p22:{title:"Шпаргалка § 22",rows:[["В разработке","Phase 3 Wave 2"]]},
+ p21:{title:"Шпаргалка § 21",rows:[
+ ["Цепь","источник, проводник, потребитель, ключ"],
+ ["Амперметр","ПОСЛЕДОВАТЕЛЬНО, малое $R$"],
+ ["Вольтметр","ПАРАЛЛЕЛЬНО, большое $R$"],
+ ["Шкала А","А, мА, мкА"],
+ ["Шкала В","В, мВ, кВ"]
+ ]},
+ p22:{title:"Шпаргалка § 22",rows:[
+ ["Закон Ома","$I = U / R$"],
+ ["$R$","сопротивление, Ом"],
+ ["ВАХ металла","прямая через 0"],
+ ["Больше $U$","больше $I$ (пропорц.)"],
+ ["Больше $R$","меньше $I$"]
+ ]},
p23:{title:"Шпаргалка § 23",rows:[["В разработке","Phase 3 Wave 3"]]},
p24:{title:"Шпаргалка § 24",rows:[["В разработке","Phase 3 Wave 3"]]},
p25:{title:"Шпаргалка § 25",rows:[["В разработке","Phase 3 Wave 3"]]},
@@ -396,8 +408,8 @@ const TIPS=[
{sec:'p18',html:"Напряжение $U$ — это работа поля по перемещению единичного заряда: $A = qU$. Единица — 1 Вольт. Розетка 220 В, батарейка 1,5 В. Чем больше $U$, тем «сильнее» поле толкает заряд."},
{sec:'p19',html:"Ток — это упорядоченное движение свободных зарядов. Чтобы оно поддерживалось, нужен источник тока — батарейка, аккумулятор, генератор. Внутри источника сторонние силы переносят заряды против поля — это и есть «насос электричества»."},
{sec:'p20',html:"$I = q/t$ — сколько Кулонов прошло через сечение провода за 1 секунду. Единица — Ампер ($1$ А = $1$ Кл/с). За направление тока приняли движение «+» зарядов — хотя в металлах реально двигаются электроны (против тока)."},
- {sec:'p21',html:"Параграф § 21 будет реализован в Phase 3 Wave 2. Используем хелперы из phys.js и optics.js."},
- {sec:'p22',html:"Параграф § 22 будет реализован в Phase 3 Wave 2. Используем хелперы из phys.js и optics.js."},
+ {sec:'p21',html:"Простейшая цепь: батарея, лампа, ключ, провода. Чтобы измерить ток через лампу — амперметр включают последовательно с лампой. Чтобы измерить напряжение на лампе — вольтметр включают параллельно."},
+ {sec:'p22',html:"Закон Ома для участка цепи: $I = U/R$. Увеличил напряжение в 2 раза — ток вырос в 2 раза. Поставил резистор побольше — ток упал. Прямая зависимость для металлов."},
{sec:'p23',html:"Параграф § 23 будет реализован в Phase 3 Wave 3. Используем хелперы из phys.js и optics.js."},
{sec:'p24',html:"Параграф § 24 будет реализован в Phase 3 Wave 3. Используем хелперы из phys.js и optics.js."},
{sec:'p25',html:"Параграф § 25 будет реализован в Phase 3 Wave 3. Используем хелперы из phys.js и optics.js."},
@@ -420,8 +432,8 @@ const BUILDERS = {
p18: ()=>{ build_p18(); },
p19: ()=>{ build_p19(); },
p20: ()=>{ build_p20(); },
- p21: ()=>{ const box=document.getElementById('p21-body'); box.innerHTML = buildStub('p21', 'Электрическая цепь. Измерение силы тока и напряжения', 'Phase 3 Wave 2') + secNavFor('p21') + readButton('p21'); renderMath(box); wireReadBtn('p21'); },
- p22: ()=>{ const box=document.getElementById('p22-body'); box.innerHTML = buildStub('p22', 'Связь силы тока и напряжения. Закон Ома для участка электрической цепи', 'Phase 3 Wave 2') + secNavFor('p22') + readButton('p22'); renderMath(box); wireReadBtn('p22'); },
+ p21: ()=>{ build_p21(); },
+ p22: ()=>{ build_p22(); },
p23: ()=>{ const box=document.getElementById('p23-body'); box.innerHTML = buildStub('p23', 'Единица сопротивления. Расчёт сопротивления', 'Phase 3 Wave 3') + secNavFor('p23') + readButton('p23'); renderMath(box); wireReadBtn('p23'); },
p24: ()=>{ const box=document.getElementById('p24-body'); box.innerHTML = buildStub('p24', 'Последовательное соединение проводников. Реостат', 'Phase 3 Wave 3') + secNavFor('p24') + readButton('p24'); renderMath(box); wireReadBtn('p24'); },
p25: ()=>{ const box=document.getElementById('p25-body'); box.innerHTML = buildStub('p25', 'Параллельное соединение проводников', 'Phase 3 Wave 3') + secNavFor('p25') + readButton('p25'); renderMath(box); wireReadBtn('p25'); },
@@ -2760,6 +2772,434 @@ function _initP20_tasks(){
render();
}
+/* ======================================================================
+ PHASE 3 · WAVE 2 — §21, §22
+ ====================================================================== */
+
+/* ======== §21 — Эл. цепь. Амперметр и вольтметр ======== */
+function build_p21(){
+ const box = document.getElementById('p21-body');
+ let h = '';
+
+ h += makeCard('theory', 'Элементы цепи', '§ 21.1',
+ '
Простейшая электрическая цепь состоит из:
'
+ +''
+ +'- источника тока (батарея, генератор);
'
+ +'- потребителя (лампа, нагреватель, мотор);
'
+ +'- соединительных проводов;
'
+ +'- ключа (выключателя), который замыкает/размыкает цепь.
'
+ +'
'
+ +'На схемах элементы рисуют условными значками — это принципиальная схема.
'
+ );
+ h += makeCard('rule', 'Амперметр и вольтметр', '§ 21.2',
+ 'Амперметр измеряет силу тока. Подключается последовательно с измеряемым участком — чтобы весь ток шёл через него.
'
+ +''
+ +'- Имеет очень маленькое сопротивление, чтобы почти не «съедать» напряжение.
'
+ +'- Нельзя включать параллельно — сгорит!
'
+ +'
'
+ +'Вольтметр измеряет напряжение. Подключается параллельно участку — чтобы измерить разность потенциалов на его концах.
'
+ +''
+ +'- Имеет очень большое сопротивление, чтобы почти не отбирать ток.
'
+ +'
'
+ );
+ h += makeCard('example', 'Простейшая принципиальная схема', '§ 21.3',
+ 'Батарея $\\varepsilon$ — лампа $L$ — амперметр $A$ — ключ $K$ — обратно к батарее. Это всё в одной «петле» — последовательная цепь.
'
+ +'Параллельно лампе подключён вольтметр $V$ — он измеряет напряжение именно на ней.
'
+ );
+
+ /* IV1 — конструктор цепи */
+ h += ''
+ +''
+ +'
Включи ключ — увидь, как через лампу пошёл ток. Амперметр и вольтметр показывают свои значения.
'
+ +'
'
+ +'
'
+ +'
Амперметр: 0 АВольтметр: 0 В
'
+ +'
';
+
+ /* IV2 — викторина «куда включать прибор?» */
+ h += ''
+ +''
+ +'
Определи правильное подключение.
'
+ +'
'
+ +'
'
+ +'
Раунд: 1 / 6Правильно: 0
'
+ +'
';
+
+ /* IV3 — DnD «правильно/неправильно» */
+ h += ''
+ +''
+ +'
Распредели утверждения.
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
';
+
+ /* IV4 — MCQ */
+ h += ''
+ +''
+ +'
4+ — +15 XP.
'
+ +'
'
+ +'
Вопрос: 1 / 6Правильно: 0
'
+ +'
';
+
+ box.innerHTML = h + secNavFor('p21') + readButton('p21');
+ renderMath(box);
+ wireReadBtn('p21');
+
+ _initP21_sim();
+ _initP21_quiz();
+ _initP21_dnd();
+ _initP21_mcq();
+}
+
+function _initP21_sim(){
+ const svg = document.getElementById('p21-sim'); if(!svg) return;
+ let closed = false;
+ function draw(){
+ let s = '';
+ /* схема: батарея слева внизу, по проводам идём: справа от батареи вверх → амперметр → вправо → лампа → вниз → обратно к батарее. Вольтметр параллельно лампе. */
+ /* батарея */
+ s += window.PHYS.batteryEMF(80, 200, '4,5 В', 'h');
+ /* провода */
+ s += window.PHYS.wire(80, 180, 80, 80); /* левый верт. */
+ s += window.PHYS.wire(80, 80, 180, 80); /* верх к ам-ру */
+ s += window.PHYS.wire(220, 80, 280, 80); /* ам-р к лампе */
+ s += window.PHYS.wire(310, 80, 380, 80); /* после лампы */
+ s += window.PHYS.wire(380, 80, 380, 200); /* правый верт. */
+ s += window.PHYS.wire(380, 200, 80, 200);/* низ (через батарею) */
+ /* амперметр (последовательно) */
+ s += window.PHYS.ammeterSymbol(200, 80, 18);
+ /* лампа */
+ s += window.PHYS.lightbulbSymbol(295, 80, 18);
+ if(closed){
+ s += '';
+ s += '';
+ }
+ /* вольтметр (параллельно лампе) */
+ s += window.PHYS.wire(295, 100, 295, 140);
+ s += window.PHYS.wire(295, 140, 250, 140);
+ s += window.PHYS.wire(250, 140, 250, 170);
+ s += window.PHYS.wire(340, 140, 340, 170);
+ s += window.PHYS.wire(295, 140, 340, 140);
+ s += window.PHYS.voltmeterSymbol(295, 155, 18);
+ /* ключ */
+ s += '';
+ s += '';
+ s += '';
+ if(closed){
+ s += '';
+ } else {
+ s += '';
+ }
+ s += 'ключ';
+ svg.innerHTML = s;
+ document.getElementById('p21-amp').textContent = closed ? '0,5 А' : '0 А';
+ document.getElementById('p21-volt').textContent = closed ? '4,5 В' : '0 В';
+ }
+ document.getElementById('p21-key').addEventListener('click', ()=>{ closed = !closed; document.getElementById('p21-key').textContent = closed ? 'Разомкнуть' : 'Замкнуть ключ'; draw(); });
+ document.getElementById('p21-reset').addEventListener('click', ()=>{ closed = false; document.getElementById('p21-key').textContent = 'Замкнуть ключ'; draw(); });
+ draw();
+}
+
+function _initP21_quiz(){
+ const QS = [
+ {q:'Как включить амперметр для измерения тока через лампу?', opts:['параллельно лампе','последовательно с лампой','между + и − батареи напрямую','произвольно'], ans:1, why:'Амперметр включается в разрыв цепи (последовательно).'},
+ {q:'Как включить вольтметр для измерения напряжения на лампе?', opts:['параллельно лампе','последовательно с лампой','до батареи','после ключа'], ans:0, why:'Вольтметр меряет разность потенциалов — параллельно.'},
+ {q:'У амперметра сопротивление…', opts:['очень малое','очень большое','среднее','равно лампе'], ans:0, why:'Чтобы почти не влиять на ток.'},
+ {q:'У вольтметра сопротивление…', opts:['очень малое','очень большое','среднее','нулевое'], ans:1, why:'Чтобы не отбирать ток у цепи.'},
+ {q:'Если подключить амперметр параллельно лампе…', opts:['прибор покажет ток','прибор сгорит — короткое замыкание','напряжение увеличится','ничего не изменится'], ans:1, why:'Через малое R амперметра потечёт огромный ток.'},
+ {q:'Если подключить вольтметр последовательно с лампой…', opts:['ток будет нормальным','ток будет почти нулевой, лампа не загорится','прибор сгорит','лампа станет ярче'], ans:1, why:'Большое R вольтметра ограничит ток до неощутимого.'}
+ ];
+ let i = 0, ok = 0;
+ function render(){
+ const q = QS[i]; const wrap = document.getElementById('p21-quiz'); if(!wrap) return;
+ let html = 'Вопрос '+(i+1)+'. '+q.q+'
';
+ q.opts.forEach((opt,k)=>{ html += ''; });
+ html += '
';
+ wrap.innerHTML = html;
+ document.getElementById('p21-quiz-r').textContent = (i+1);
+ document.getElementById('p21-quiz-ok').textContent = ok;
+ wrap.querySelectorAll('[data-k]').forEach(btn=>{
+ btn.addEventListener('click', ()=>{
+ if(btn.disabled) return; wrap.querySelectorAll('[data-k]').forEach(b=>b.disabled=true);
+ const k = +btn.dataset.k; const fb = document.getElementById('p21-quiz-fb');
+ if(k===q.ans){ ok++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(3,'p21-quiz'); bumpProgress('p21', 4); }
+ else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; }
+ document.getElementById('p21-quiz-ok').textContent = ok;
+ });
+ });
+ }
+ document.getElementById('p21-quiz-next').addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); });
+ render();
+}
+
+function _initP21_dnd(){
+ const items = [
+ {id:'a', cat:'t', html:'амперметр последовательно с лампой'},
+ {id:'b', cat:'t', html:'вольтметр параллельно лампе'},
+ {id:'c', cat:'t', html:'амперметр имеет малое $R$'},
+ {id:'d', cat:'t', html:'вольтметр имеет большое $R$'},
+ {id:'e', cat:'f', html:'амперметр параллельно батарее'},
+ {id:'f', cat:'f', html:'вольтметр в разрыв цепи'},
+ {id:'g', cat:'f', html:'амперметр имеет большое $R$'},
+ {id:'h', cat:'f', html:'вольтметр меряет силу тока'}
+ ];
+ const dnd = setupSorter({ poolId:'p21-dnd-pool', scopeSelector:'#sec-p21', cats:['t','f'], items, columnLayout:false });
+ document.getElementById('p21-dnd-check').addEventListener('click', ()=>{
+ const fb = document.getElementById('p21-dnd-fb');
+ let wrong = 0; items.forEach(it=>{ if(dnd.placed[it.id] !== it.cat) wrong++; });
+ if(wrong===0){ fb.className='feedback ok'; fb.innerHTML='✓ Идеально! +15 XP. A последовательно (мал. R), V параллельно (бол. R).'; addXp(15,'p21-dnd'); bumpProgress('p21', 20); }
+ else { fb.className='feedback fail'; fb.innerHTML='✗ Ошибок: '+wrong+'.'; }
+ });
+ document.getElementById('p21-dnd-reset').addEventListener('click', ()=>{ dnd.reset(); const fb=document.getElementById('p21-dnd-fb'); fb.style.display='none'; });
+}
+
+function _initP21_mcq(){
+ const QS = [
+ {q:'Что такое замкнутая цепь?', opts:['разрыв провода','круговое соединение элементов','один провод','лампа без батареи'], ans:1, why:'Цепь — петля, по которой может пройти ток.'},
+ {q:'Что произойдёт, если разомкнуть ключ?', opts:['ток усилится','ток исчезнет','напряжение упадёт','ток пойдёт по новому пути'], ans:1, why:'Цепь разорвана — тока нет.'},
+ {q:'Какой элемент схемы рисуется как круг с буквой A?', opts:['батарея','амперметр','вольтметр','резистор'], ans:1, why:'A — амперметр.'},
+ {q:'А с буквой V?', opts:['батарея','вольтметр','лампа','ключ'], ans:1, why:'V — вольтметр.'},
+ {q:'Все потребители в одной «петле» — это…', opts:['последовательное соединение','параллельное','смешанное','короткое замыкание'], ans:0, why:'В одной петле — последовательно.'},
+ {q:'Почему амперметр НЕ имеет большого $R$?', opts:['чтобы не сгореть','чтобы не уменьшать ток в цепи','чтобы было дёшево','чтобы измерять напряжение'], ans:1, why:'Большое R снизило бы ток, измерение было бы неточным.'}
+ ];
+ let i = 0, ok = 0, done = 0, awarded = false;
+ function render(){
+ const q = QS[i]; const wrap = document.getElementById('p21-mcq'); if(!wrap) return;
+ let h = 'Вопрос '+(i+1)+'. '+q.q+'
';
+ q.opts.forEach((opt,k)=>{ h += ''; });
+ h += '
';
+ wrap.innerHTML = h;
+ document.getElementById('p21-mcq-i').textContent = (i+1);
+ document.getElementById('p21-mcq-ok').textContent = ok;
+ wrap.querySelectorAll('[data-k]').forEach(btn=>{
+ btn.addEventListener('click', ()=>{
+ if(btn.disabled) return; wrap.querySelectorAll('[data-k]').forEach(b=>b.disabled=true);
+ const k = +btn.dataset.k; const fb = document.getElementById('p21-mcq-fb');
+ if(k===q.ans){ ok++; done++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(2,'p21-mcq'); bumpProgress('p21', 3); }
+ else { done++; fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; }
+ document.getElementById('p21-mcq-ok').textContent = ok;
+ if(done >= QS.length && !awarded && ok >= 4){ awarded = true; setTimeout(()=>{ const wf=document.getElementById('p21-mcq-fb'); wf.className='feedback ok'; wf.innerHTML='✓ +15 XP — тренажёр пройден.'; addXp(15,'p21-mcq-bonus'); bumpProgress('p21', 15); }, 600); }
+ });
+ });
+ const nb = document.getElementById('p21-mcq-next'); if(nb) nb.addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); });
+ }
+ render();
+}
+
+/* ======== §22 — Закон Ома I = U/R ======== */
+function build_p22(){
+ const box = document.getElementById('p22-body');
+ let h = '';
+
+ h += makeCard('theory', 'Связь $I$ и $U$', '§ 22.1',
+ 'Опыт: подключаем резистор к источнику и меняем напряжение. Что будет с током?
'
+ +'Ток пропорционален напряжению: увеличили $U$ в 2 раза — $I$ тоже в 2 раза. Это и есть закон Ома:
'
+ +'$$I = \\dfrac{U}{R}$$
'
+ +'$R$ — сопротивление участка, измеряется в Омах (Ом). Закон открыт немецким физиком Георгом Симоном Омом в 1826 г.
'
+ );
+ h += makeCard('rule', 'Из закона Ома', '§ 22.2',
+ 'Закон можно «перевернуть» тремя способами:
'
+ +'$$I = \\dfrac{U}{R}, \\quad U = IR, \\quad R = \\dfrac{U}{I}$$
'
+ +'Эта связка — основа всей электротехники. Зная любые две величины — найдём третью.
'
+ +'1 Ом — это сопротивление участка, на котором при напряжении 1 В идёт ток 1 А.
'
+ );
+ h += makeCard('example', 'ВАХ — вольт-амперная характеристика', '§ 22.3',
+ 'Если на графике отложить $U$ по горизонтали, а $I$ по вертикали, получится ВАХ:
'
+ +''
+ +'- для металла — прямая через 0;
'
+ +'- наклон прямой определяет $R$: круче — меньше $R$;
'
+ +'- для лампы с раскалённой нитью ВАХ слегка изогнута (нить нагревается, $R$ растёт).
'
+ +'
'
+ );
+
+ /* IV1 — ВАХ-плоттер */
+ h += ''
+ +''
+ +'
Меняй $R$ — увидь, как меняется наклон прямой $I(U)$. Чем меньше $R$, тем круче растёт ток.
'
+ +'
'
+ +''
+ +'
'
+ +'
'
+ +'
';
+
+ /* IV2 — калькулятор */
+ h += ''
+ +''
+ +'
Введи две величины — узнай третью.
'
+ +'
'
+ +''
+ +''
+ +'
'
+ +'
'
+ +'$I = U/R$ = 1,2 А'
+ +'Для $U = 220$ В и $R = 100$ Ом ток будет 2,2 А — это средняя лампа накаливания.'
+ +'
'
+ +'
';
+
+ /* IV3 — викторина по графику */
+ h += ''
+ +''
+ +'
По наклону ВАХ оцени сопротивление.
'
+ +'
'
+ +'
'
+ +'
Раунд: 1 / 5Правильно: 0
'
+ +'
';
+
+ /* IV4 — задачи */
+ h += ''
+ +''
+ +'
4+ — +15 XP.
'
+ +'
'
+ +'
Задача: 1 / 6Правильно: 0
'
+ +'
';
+
+ box.innerHTML = h + secNavFor('p22') + readButton('p22');
+ renderMath(box);
+ wireReadBtn('p22');
+
+ _initP22_vah();
+ _initP22_calc();
+ _initP22_quiz();
+ _initP22_tasks();
+}
+
+function _initP22_vah(){
+ const svg = document.getElementById('p22-sim'); if(!svg) return;
+ function draw(){
+ const R = +document.getElementById('p22-r').value;
+ document.getElementById('p22-rv').textContent = R;
+ const W = 460, H = 240, pad = 38;
+ const Umax = 12, Imax = 2;
+ const toX = u => pad + (W-2*pad) * u / Umax;
+ const toY = i => H - pad - (H-2*pad) * i / Imax;
+ let s = '';
+ /* оси */
+ s += '';
+ s += '';
+ /* сетка */
+ for(let u = 2; u <= 10; u+=2){
+ s += '';
+ s += ''+u+'';
+ }
+ for(let i = 0.5; i <= 1.5; i+=0.5){
+ s += '';
+ s += ''+i+'';
+ }
+ /* подписи осей */
+ s += 'U, В';
+ s += 'I, А';
+ /* прямая I = U/R */
+ const x0 = toX(0), y0 = toY(0);
+ const uMaxVisible = Math.min(Umax, Imax * R);
+ const x1 = toX(uMaxVisible);
+ const y1 = toY(uMaxVisible / R);
+ s += '';
+ /* подпись наклона */
+ s += 'I = U / '+R+' Ом';
+ svg.innerHTML = s;
+ }
+ document.getElementById('p22-r').addEventListener('input', draw);
+ draw();
+}
+
+function _initP22_calc(){
+ function update(){
+ const U = +document.getElementById('p22-u').value;
+ const R = +document.getElementById('p22-r2').value;
+ document.getElementById('p22-uv').textContent = U;
+ document.getElementById('p22-rv2').textContent = R;
+ const I = U/R;
+ document.getElementById('p22-icur').textContent = I.toFixed(2);
+ let analogy = 'мало';
+ if(I > 5) analogy = 'мощный нагреватель';
+ else if(I > 1) analogy = 'средняя лампа накаливания';
+ else if(I > 0.2) analogy = 'светодиодная лампа';
+ else analogy = 'светодиод';
+ document.getElementById('p22-bulb').textContent = analogy;
+ }
+ document.getElementById('p22-u').addEventListener('input', update);
+ document.getElementById('p22-r2').addEventListener('input', update);
+ update();
+}
+
+function _initP22_quiz(){
+ const QS = [
+ {q:'У какого резистора $R$ больше: ВАХ круче или ВАХ положе?', opts:['круче','положе','одинаково','зависит от U'], ans:1, why:'$R$ = $U/I$, при том же $U$ положая прямая даёт меньший $I$ → больше $R$.'},
+ {q:'Если $U$ постоянно, а $R$ удвоить, что станет с $I$?', opts:['удвоится','уменьшится в 2 раза','не изменится','исчезнет'], ans:1, why:'$I = U/R$, $R$ ↑ → $I$ ↓.'},
+ {q:'Если $R$ постоянно, а $U$ утроить, что с $I$?', opts:['удвоится','утроится','уменьшится в 3 раза','не изменится'], ans:1, why:'Прямая пропорция.'},
+ {q:'При $U = 6$ В через резистор течёт $I = 0{,}5$ А. Чему равно $R$?', opts:['3 Ом','12 Ом','6 Ом','0,5 Ом'], ans:1, why:'$R = U/I = 6/0{,}5 = 12$ Ом.'},
+ {q:'Закон Ома справедлив для…', opts:['только газов','любых веществ','металлических проводников','только сверхпроводников'], ans:2, why:'Для металлов точно, для других — с оговорками.'}
+ ];
+ let i = 0, ok = 0;
+ function render(){
+ const q = QS[i]; const wrap = document.getElementById('p22-quiz'); if(!wrap) return;
+ let html = 'Вопрос '+(i+1)+'. '+q.q+'
';
+ q.opts.forEach((opt,k)=>{ html += ''; });
+ html += '
';
+ wrap.innerHTML = html;
+ document.getElementById('p22-quiz-r').textContent = (i+1);
+ document.getElementById('p22-quiz-ok').textContent = ok;
+ wrap.querySelectorAll('[data-k]').forEach(btn=>{
+ btn.addEventListener('click', ()=>{
+ if(btn.disabled) return; wrap.querySelectorAll('[data-k]').forEach(b=>b.disabled=true);
+ const k = +btn.dataset.k; const fb = document.getElementById('p22-quiz-fb');
+ if(k===q.ans){ ok++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(3,'p22-quiz'); bumpProgress('p22', 4); }
+ else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; }
+ document.getElementById('p22-quiz-ok').textContent = ok;
+ renderMath(wrap);
+ });
+ });
+ renderMath(wrap);
+ }
+ document.getElementById('p22-quiz-next').addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); });
+ render();
+}
+
+function _initP22_tasks(){
+ const TASKS = [
+ {q:'$U = 12$ В, $R = 4$ Ом. Найди $I$ (А).', ans:3, tol:0.05, why:'$I = 12/4 = 3$ А.'},
+ {q:'$I = 0{,}5$ А, $R = 220$ Ом. Найди $U$ (В).', ans:110, tol:1, why:'$U = IR = 0{,}5 \\cdot 220 = 110$ В.'},
+ {q:'$U = 220$ В, $I = 2$ А. Найди $R$ (Ом).', ans:110, tol:1, why:'$R = 220/2 = 110$ Ом.'},
+ {q:'Лампа $R = 240$ Ом подключена к 220 В. Какой ток (А, до сотых)?', ans:0.92, tol:0.02, why:'$I = 220/240 \\approx 0{,}917$ А.'},
+ {q:'$U$ возросло с 5 до 15 В на том же $R$. Во сколько раз возрос ток?', ans:3, tol:0.05, why:'$I$ пропорционально $U$.'},
+ {q:'При $U = 1{,}5$ В через светодиод течёт 20 мА. Найди $R$ (Ом).', ans:75, tol:1, why:'$R = 1{,}5/0{,}02 = 75$ Ом.'}
+ ];
+ let i = 0, ok = 0, done = 0, awarded = false;
+ function render(){
+ const t = TASKS[i]; const wrap = document.getElementById('p22-task'); if(!wrap) return;
+ wrap.innerHTML =
+ 'Задача '+(i+1)+'. '+t.q+'
'
+ +''
+ +''
+ +''
+ +'
'
+ +''+t.why+'
'
+ +'';
+ document.getElementById('p22-task-i').textContent = (i+1);
+ document.getElementById('p22-task-ok').textContent = ok;
+ document.getElementById('p22-task-go').addEventListener('click', ()=>{
+ const v = parseFloat((document.getElementById('p22-task-inp').value || '').replace(',','.'));
+ const fb = document.getElementById('p22-task-fb');
+ if(isNaN(v)){ fb.className='feedback fail'; fb.innerHTML='Введи число.'; return; }
+ done++;
+ if(Math.abs(v - t.ans) < t.tol){ ok++; fb.className='feedback ok'; fb.innerHTML='✓ Верно! '+t.why; addXp(4,'p22-task'); bumpProgress('p22', 6); }
+ else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. Ответ: '+t.ans+'. '+t.why; }
+ document.getElementById('p22-task-ok').textContent = ok;
+ renderMath(wrap);
+ if(done >= TASKS.length && !awarded && ok >= 4){ awarded = true; setTimeout(()=>{ const wf=document.getElementById('p22-task-fb'); wf.className='feedback ok'; wf.innerHTML='✓ +15 XP — расчёты сданы.'; addXp(15,'p22-task-bonus'); bumpProgress('p22', 15); }, 600); }
+ });
+ document.getElementById('p22-task-hint').addEventListener('click', ()=>{ document.getElementById('p22-task-hint-txt').classList.toggle('show'); });
+ document.getElementById('p22-task-next').addEventListener('click', ()=>{ i=(i+1)%TASKS.length; render(); });
+ renderMath(wrap);
+ }
+ render();
+}
+
function init(){
loadProgress(); initTheme(); initSidebarToggle(); initSearch();
buildParaSelector(); refreshProgressUI(); loadServerReadState(); goTo(PARAS[0].id);