diff --git a/frontend/textbooks/physics_8_ch2.html b/frontend/textbooks/physics_8_ch2.html
index 36f6eb7..6e5568a 100644
--- a/frontend/textbooks/physics_8_ch2.html
+++ b/frontend/textbooks/physics_8_ch2.html
@@ -343,8 +343,21 @@ const SIDEBARS = {
["Анион (−)","принял электрон(ы)"],
["Электронные оболочки","K, L, M, …"]
]},
- p17:{title:"Шпаргалка § 17",rows:[["В разработке","Phase 2 Wave 3"]]},
- p18:{title:"Шпаргалка § 18",rows:[["В разработке","Phase 2 Wave 3"]]},
+ p17:{title:"Шпаргалка § 17",rows:[
+ ["Эл. поле","материя вокруг заряда"],
+ ["Действует","силой на другие заряды"],
+ ["Линии поля","от + к −"],
+ ["Напряжение $U$","энергет. характеристика"],
+ ["$U_{AB}$","разность потенциалов между A и B"]
+ ]},
+ p18:{title:"Шпаргалка § 18",rows:[
+ ["Формула","$A = q U$"],
+ ["Единица","[U] = В = Дж/Кл"],
+ ["Батарейка","1,5 В"],
+ ["Аккумулятор","12 В"],
+ ["Розетка","220 В"],
+ ["1 В","работа 1 Дж на 1 Кл"]
+ ]},
p19:{title:"Шпаргалка § 19",rows:[["В разработке","Phase 3 Wave 1"]]},
p20:{title:"Шпаргалка § 20",rows:[["В разработке","Phase 3 Wave 1"]]},
p21:{title:"Шпаргалка § 21",rows:[["В разработке","Phase 3 Wave 2"]]},
@@ -367,8 +380,8 @@ const TIPS=[
{sec:'p14',html:"Поднеси заряженный шар к незаряженному металлическому шарику — он притянется. В нейтральном проводнике под действием внешнего заряда электроны перераспределяются, и ближний конец получает противоположный знак."},
{sec:'p15',html:"Заряд не бывает «дробным» — все заряды кратны элементарному $e = 1{,}6 \\cdot 10^{-19}$ Кл. Если у тела «лишние» $N$ электронов, его заряд $q = -Ne$. 1 Кл — это очень много: примерно $6 \\cdot 10^{18}$ электронов."},
{sec:'p16',html:"Атом — это плотное положительное ядро (протоны+нейтроны) и облако отрицательных электронов вокруг. В обычном атоме число электронов равно числу протонов — он нейтрален. Если потерять электрон → ион +, если получить → ион −."},
- {sec:'p17',html:"Параграф § 17 будет реализован в Phase 2 Wave 3. Используем хелперы из phys.js и optics.js."},
- {sec:'p18',html:"Параграф § 18 будет реализован в Phase 2 Wave 3. Используем хелперы из phys.js и optics.js."},
+ {sec:'p17',html:"Заряд не «торкает» другие заряды напрямую — он создаёт вокруг себя электрическое поле , а уже оно действует силой на другие заряды. Линии поля идут от + к − и показывают направление силы на пробный +заряд."},
+ {sec:'p18',html:"Напряжение $U$ — это работа поля по перемещению единичного заряда: $A = qU$. Единица — 1 Вольт. Розетка 220 В, батарейка 1,5 В. Чем больше $U$, тем «сильнее» поле толкает заряд."},
{sec:'p19',html:"Параграф § 19 будет реализован в Phase 3 Wave 1. Используем хелперы из phys.js и optics.js."},
{sec:'p20',html:"Параграф § 20 будет реализован в Phase 3 Wave 1. Используем хелперы из phys.js и optics.js."},
{sec:'p21',html:"Параграф § 21 будет реализован в Phase 3 Wave 2. Используем хелперы из phys.js и optics.js."},
@@ -391,8 +404,8 @@ const BUILDERS = {
p14: ()=>{ build_p14(); },
p15: ()=>{ build_p15(); },
p16: ()=>{ build_p16(); },
- p17: ()=>{ const box=document.getElementById('p17-body'); box.innerHTML = buildStub('p17', 'Электрическое поле. Электрическое напряжение', 'Phase 2 Wave 3') + secNavFor('p17') + readButton('p17'); renderMath(box); wireReadBtn('p17'); },
- p18: ()=>{ const box=document.getElementById('p18-body'); box.innerHTML = buildStub('p18', 'Единица электрического напряжения. Расчёт работы в электрическом поле', 'Phase 2 Wave 3') + secNavFor('p18') + readButton('p18'); renderMath(box); wireReadBtn('p18'); },
+ p17: ()=>{ build_p17(); },
+ p18: ()=>{ build_p18(); },
p19: ()=>{ const box=document.getElementById('p19-body'); box.innerHTML = buildStub('p19', 'Электрический ток. Источники тока', 'Phase 3 Wave 1') + secNavFor('p19') + readButton('p19'); renderMath(box); wireReadBtn('p19'); },
p20: ()=>{ const box=document.getElementById('p20-body'); box.innerHTML = buildStub('p20', 'Сила и направление электрического тока', 'Phase 3 Wave 1') + secNavFor('p20') + readButton('p20'); renderMath(box); wireReadBtn('p20'); },
p21: ()=>{ const box=document.getElementById('p21-body'); box.innerHTML = buildStub('p21', 'Электрическая цепь. Измерение силы тока и напряжения', 'Phase 3 Wave 2') + secNavFor('p21') + readButton('p21'); renderMath(box); wireReadBtn('p21'); },
@@ -1855,6 +1868,404 @@ function _initP16_mcq(){
render();
}
+/* ======================================================================
+ PHASE 2 · WAVE 3 — §17, §18
+ ====================================================================== */
+
+/* ======== §17 — Электрическое поле. Напряжение ======== */
+function build_p17(){
+ const box = document.getElementById('p17-body');
+ let h = '';
+
+ h += makeCard('theory', 'Что такое электрическое поле', '§ 17.1',
+ '
Заряды действуют друг на друга на расстоянии , без прямого контакта. Как же передаётся это взаимодействие?
'
+ +'Ответ: вокруг каждого заряда существует электрическое поле — особый вид материи. Поле — посредник.
'
+ +'Когда мы помещаем в это поле другой заряд, поле действует на него с некоторой силой :
'
+ +''
+ +'от $+q$ поле «отталкивает» другие $+q$ и «притягивает» $-q$; '
+ +'от $-q$ — наоборот. '
+ +' '
+ );
+ h += makeCard('rule', 'Линии электрического поля', '§ 17.2',
+ 'Поле наглядно изображают линиями со стрелками. Они показывают направление силы, которая действовала бы на пробный положительный заряд.
'
+ +''
+ +'Линии выходят из $+q$ и входят в $-q$ . '
+ +'Не пересекаются. '
+ +'Чем гуще линии — тем сильнее поле. '
+ +' '
+ );
+ h += makeCard('example', 'Напряжение', '§ 17.3',
+ 'Чтобы переместить заряд $q$ внутри поля, поле совершает (или над ним совершают) работу . Эта работа зависит от того, между какими двумя точками идёт перемещение.
'
+ +'Электрическое напряжение $U$ между точками A и B — это работа поля по переносу единичного $+q$ из A в B:
'
+ +'$$U_{AB} = \\dfrac{A}{q}$$
'
+ +'Подробно — в § 18.
'
+ );
+
+ /* IV1 — линии поля точечного заряда */
+ h += ''
+ +''
+ +'
Выбери знак заряда — увидь, как направлены линии поля.
'
+ +'
'
+ +'Знак заряда: $+q$ (отталкивает) $-q$ (притягивает) '
+ +'Сила поля: средняя '
+ +'
'
+ +'
'
+ +'
';
+
+ /* IV2 — викторина «линии поля» */
+ h += ''
+ +''
+ +'
Свойства линий поля.
'
+ +'
'
+ +'
Следующий
'
+ +'
Раунд: 1 / 5 Правильно: 0
'
+ +'
';
+
+ /* IV3 — DnD факты */
+ h += ''
+ +''
+ +'
Утверждения о поле и напряжении.
'
+ +'
'
+ +'
'
+ +'
Проверить Сброс
'
+ +'
'
+ +'
';
+
+ /* IV4 — MCQ */
+ h += ''
+ +''
+ +'
4+ правильных — +15 XP.
'
+ +'
'
+ +'
Вопрос: 1 / 6 Правильно: 0
'
+ +'
';
+
+ box.innerHTML = h + secNavFor('p17') + readButton('p17');
+ renderMath(box);
+ wireReadBtn('p17');
+
+ _initP17_field();
+ _initP17_quiz();
+ _initP17_dnd();
+ _initP17_mcq();
+}
+
+function _initP17_field(){
+ const svg = document.getElementById('p17-sim'); if(!svg) return;
+ function draw(){
+ const sig = +document.getElementById('p17-sig').value;
+ const scale = +document.getElementById('p17-s').value;
+ document.getElementById('p17-sv').textContent = scale < 60 ? 'слабая' : scale < 100 ? 'средняя' : 'сильная';
+ const cx = 230, cy = 120;
+ let s = '';
+ s += window.PHYS.fieldLinesPointCharge(cx, cy, sig, scale, 14);
+ s += window.PHYS.chargeMark(cx, cy, sig, 22, sig > 0 ? '+q' : '−q');
+ svg.innerHTML = s;
+ }
+ document.getElementById('p17-sig').addEventListener('change', draw);
+ document.getElementById('p17-s').addEventListener('input', draw);
+ draw();
+}
+
+function _initP17_quiz(){
+ const QS = [
+ {sit:'Линии поля около +q идут…', opts:['наружу','внутрь','параллельно','по кругу'], ans:0, why:'От + наружу.'},
+ {sit:'Линии поля около −q идут…', opts:['наружу','внутрь','параллельно','по кругу'], ans:1, why:'К − внутрь.'},
+ {sit:'Чем гуще линии, тем поле…', opts:['слабее','сильнее','не меняется','исчезает'], ans:1, why:'Густота показывает силу поля.'},
+ {sit:'Линии поля могут пересекаться?', opts:['да','нет','только в вакууме','только у проводников'], ans:1, why:'В каждой точке поле имеет одно направление.'},
+ {sit:'Поле двух одинаковых +q посередине между ними…', opts:['большое','нулевое','перпендикулярное','непрерывное'], ans:1, why:'Силы от двух зарядов равны и противоположны — компенсируются.'}
+ ];
+ let i = 0, ok = 0;
+ function render(){
+ const q = QS[i]; const wrap = document.getElementById('p17-quiz'); if(!wrap) return;
+ let html = ''+q.sit+'
';
+ q.opts.forEach((opt,k)=>{ html += ''+String.fromCharCode(65+k)+'. '+opt+' '; });
+ html += '
';
+ wrap.innerHTML = html;
+ document.getElementById('p17-quiz-r').textContent = (i+1);
+ document.getElementById('p17-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('p17-quiz-fb');
+ if(k===q.ans){ ok++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(3,'p17-quiz'); bumpProgress('p17', 4); }
+ else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; }
+ document.getElementById('p17-quiz-ok').textContent = ok;
+ });
+ });
+ }
+ document.getElementById('p17-quiz-next').addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); });
+ render();
+}
+
+function _initP17_dnd(){
+ const items = [
+ {id:'a', cat:'t', html:'Электрическое поле — особый вид материи'},
+ {id:'b', cat:'t', html:'Поле существует вокруг любого заряда'},
+ {id:'c', cat:'t', html:'$U_{AB} = A/q$ — определение напряжения'},
+ {id:'d', cat:'t', html:'Линии поля начинаются на + и кончаются на −'},
+ {id:'e', cat:'f', html:'Поле — это вакуум вокруг заряда'},
+ {id:'f', cat:'f', html:'Линии поля могут пересекаться'},
+ {id:'g', cat:'f', html:'Напряжение — это сила, действующая на заряд'},
+ {id:'h', cat:'f', html:'Поле существует только в вакууме'}
+ ];
+ const dnd = setupSorter({ poolId:'p17-dnd-pool', scopeSelector:'#sec-p17', cats:['t','f'], items, columnLayout:false });
+ document.getElementById('p17-dnd-check').addEventListener('click', ()=>{
+ const fb = document.getElementById('p17-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. Поле — материя; напряжение — работа на ед. заряда.'; addXp(15,'p17-dnd'); bumpProgress('p17', 20); }
+ else { fb.className='feedback fail'; fb.innerHTML='✗ Ошибок: '+wrong+'.'; }
+ });
+ document.getElementById('p17-dnd-reset').addEventListener('click', ()=>{ dnd.reset(); const fb=document.getElementById('p17-dnd-fb'); fb.style.display='none'; });
+}
+
+function _initP17_mcq(){
+ const QS = [
+ {q:'Через что заряды взаимодействуют?', opts:['напрямую','через эл. поле','через гравитацию','через воздух'], ans:1, why:'Поле — посредник взаимодействия.'},
+ {q:'Откуда выходят линии поля?', opts:['из −','из +','из любого','ниоткуда'], ans:1, why:'Линии начинаются на +.'},
+ {q:'Что показывают линии поля?', opts:['массу','направление силы на +q','скорость','температуру'], ans:1, why:'Линии — направление силы на пробный +.'},
+ {q:'Куда направлена сила на $-q$ в поле, идущем направо?', opts:['направо','налево','вверх','никуда'], ans:1, why:'На −q сила направлена против поля.'},
+ {q:'$U_{AB}$ — это…', opts:['сила поля','энергия заряда','работа поля на ед. заряд','скорость заряда'], ans:2, why:'$U = A/q$ — определение.'},
+ {q:'Если убрать заряд-источник, поле…', opts:['останется','исчезнет','инвертируется','усилится'], ans:1, why:'Поле существует только пока есть его источник.'}
+ ];
+ let i = 0, ok = 0, done = 0, awarded = false;
+ function render(){
+ const q = QS[i]; const wrap = document.getElementById('p17-mcq'); if(!wrap) return;
+ let h = 'Вопрос '+(i+1)+'. '+q.q+'
';
+ q.opts.forEach((opt,k)=>{ h += ''+String.fromCharCode(65+k)+'. '+opt+' '; });
+ h += '
Следующий
';
+ wrap.innerHTML = h;
+ document.getElementById('p17-mcq-i').textContent = (i+1);
+ document.getElementById('p17-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('p17-mcq-fb');
+ if(k===q.ans){ ok++; done++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(2,'p17-mcq'); bumpProgress('p17', 3); }
+ else { done++; fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; }
+ document.getElementById('p17-mcq-ok').textContent = ok;
+ if(done >= QS.length && !awarded && ok >= 4){ awarded = true; setTimeout(()=>{ const wf=document.getElementById('p17-mcq-fb'); wf.className='feedback ok'; wf.innerHTML='✓ +15 XP — тренажёр пройден.'; addXp(15,'p17-mcq-bonus'); bumpProgress('p17', 15); }, 600); }
+ });
+ });
+ const nb = document.getElementById('p17-mcq-next'); if(nb) nb.addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); });
+ }
+ render();
+}
+
+/* ======== §18 — A = qU ======== */
+function build_p18(){
+ const box = document.getElementById('p18-body');
+ let h = '';
+
+ h += makeCard('theory', 'Формула $A = qU$', '§ 18.1',
+ 'Если перенести заряд $q$ через разность потенциалов $U$, поле совершит работу:
'
+ +'$$A = q \\, U$$
'
+ +''
+ +'$A$ — работа, Дж; '
+ +'$q$ — заряд, Кл; '
+ +'$U$ — напряжение, В. '
+ +' '
+ +'Если $A > 0$ — поле «помогает» движению заряда; $A < 0$ — заряд движется «против» поля.
'
+ );
+ h += makeCard('rule', 'Что такое 1 Вольт', '§ 18.2',
+ '1 Вольт — это такое напряжение, при котором поле совершает работу 1 Джоуль на каждый 1 Кулон переносимого заряда:
'
+ +'$$1 \\text{ В} = \\dfrac{1 \\text{ Дж}}{1 \\text{ Кл}}$$
'
+ +'Один из величайших физиков Алессандро Вольта изобрёл первый источник тока — гальванический элемент. В его честь и названа единица.
'
+ );
+ h += makeCard('example', 'Напряжения в быту', '§ 18.3',
+ ''
+ +'Батарейка 1{,}5 В '
+ +'Крона 9 В '
+ +'Автомобильный аккумулятор 12 В '
+ +'Зарядка для телефона 5 В '
+ +'Розетка 220 В '
+ +'ЛЭП высокого напряжения 10 000 — 750 000 В '
+ +'Молния $10^8$ В '
+ +'
'
+ );
+
+ /* IV1 — калькулятор A=qU */
+ h += ''
+ +''
+ +'
Меняй $q$ и $U$ — увидь работу поля.
'
+ +'
'
+ +'$q$, мКл (10−3 Кл): 1.0 '
+ +'$U$, В: 220 '
+ +'
'
+ +'
'
+ +'
'
+ +'$A = q U$ = 0.22 Дж '
+ +'Этой энергии хватит, чтобы поднять груз 22 г на 1 м . '
+ +'
'
+ +'
';
+
+ /* IV2 — викторина «дано / найди» */
+ h += ''
+ +''
+ +'
По формуле $A = qU$ найди недостающую величину.
'
+ +'
'
+ +'
Следующий
'
+ +'
Раунд: 1 / 5 Правильно: 0
'
+ +'
';
+
+ /* IV3 — DnD «напряжения по возрастанию» */
+ h += ''
+ +''
+ +'
От самого маленького к самому большому.
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
Проверить Сброс
'
+ +'
'
+ +'
';
+
+ /* IV4 — расчётные задачи */
+ h += ''
+ +''
+ +'
4+ правильных — +15 XP.
'
+ +'
'
+ +'
Задача: 1 / 5 Правильно: 0
'
+ +'
';
+
+ box.innerHTML = h + secNavFor('p18') + readButton('p18');
+ renderMath(box);
+ wireReadBtn('p18');
+
+ _initP18_calc();
+ _initP18_quiz();
+ _initP18_dnd();
+ _initP18_tasks();
+}
+
+function _initP18_calc(){
+ const svg = document.getElementById('p18-sim'); if(!svg) return;
+ function update(){
+ const qmC = +document.getElementById('p18-q').value;
+ const U = +document.getElementById('p18-u').value;
+ const q = qmC * 1e-3; /* мКл → Кл */
+ const A = q * U;
+ document.getElementById('p18-qv').textContent = qmC.toFixed(1);
+ document.getElementById('p18-uv').textContent = U;
+ document.getElementById('p18-a').textContent = A.toFixed(3);
+ /* аналогия: поднять груз на 1 м, m = A/(g*1) */
+ const g = 9.8;
+ const massG = (A/g) * 1000;
+ document.getElementById('p18-anal').textContent = 'поднять груз '+massG.toFixed(0)+' г на 1 м';
+ /* sim */
+ let s = '';
+ /* батарея */
+ s += window.PHYS.batteryEMF(80, 70, U+' В', 'h');
+ /* стрелка переноса заряда */
+ s += 'q = '+qmC.toFixed(1)+' мКл ';
+ s += window.PHYS.drawArrow(180, 100, 320, 100, '#10b981', 2.5, 11);
+ s += 'A = qU = '+A.toFixed(3)+' Дж ';
+ /* итог "лампа" */
+ s += window.PHYS.lightbulbSymbol(360, 80, 22);
+ s += 'энергия ';
+ svg.innerHTML = s;
+ }
+ document.getElementById('p18-q').addEventListener('input', update);
+ document.getElementById('p18-u').addEventListener('input', update);
+ update();
+}
+
+function _initP18_quiz(){
+ const QS = [
+ {q:'Заряд $q = 2$ Кл прошёл напряжение $U = 5$ В. Найди $A$ (Дж).', ans:10, tol:0.1, why:'$A = qU = 2 \\cdot 5 = 10$ Дж.'},
+ {q:'$A = 240$ Дж, $U = 12$ В. Какой заряд прошёл (Кл)?', ans:20, tol:0.5, why:'$q = A/U = 240/12 = 20$ Кл.'},
+ {q:'$A = 6$ Дж, $q = 30$ мКл $= 0{,}03$ Кл. Найди $U$ (В).', ans:200, tol:2, why:'$U = A/q = 6/0{,}03 = 200$ В.'},
+ {q:'Поле перенесло $q = 0{,}5$ Кл через $U = 220$ В. Найди $A$ (Дж).', ans:110, tol:1, why:'$A = 0{,}5 \\cdot 220 = 110$ Дж.'},
+ {q:'$A = 4{,}5$ Дж, $q = 3$ Кл. Найди $U$ (В).', ans:1.5, tol:0.05, why:'$U = 4{,}5/3 = 1{,}5$ В — это батарейка.'}
+ ];
+ let i = 0, ok = 0;
+ function render(){
+ const t = QS[i]; const wrap = document.getElementById('p18-quiz'); if(!wrap) return;
+ wrap.innerHTML =
+ ''+t.q+'
'
+ +' '
+ +'Ответ
'
+ +'
';
+ document.getElementById('p18-quiz-r').textContent = (i+1);
+ document.getElementById('p18-quiz-ok').textContent = ok;
+ document.getElementById('p18-quiz-go').addEventListener('click', ()=>{
+ const v = parseFloat((document.getElementById('p18-quiz-inp').value || '').replace(',','.'));
+ const fb = document.getElementById('p18-quiz-fb');
+ if(isNaN(v)){ fb.className='feedback fail'; fb.innerHTML='Введи число.'; return; }
+ if(Math.abs(v - t.ans) < t.tol){ ok++; fb.className='feedback ok'; fb.innerHTML='✓ Верно! '+t.why; addXp(3,'p18-quiz'); bumpProgress('p18', 4); }
+ else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. Ответ: '+t.ans+'. '+t.why; }
+ document.getElementById('p18-quiz-ok').textContent = ok;
+ renderMath(wrap);
+ });
+ renderMath(wrap);
+ }
+ document.getElementById('p18-quiz-next').addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); });
+ render();
+}
+
+function _initP18_dnd(){
+ const items = [
+ {id:'bat', cat:'r1', html:'батарейка ($1{,}5$ В)'},
+ {id:'kr', cat:'r2', html:'аккумулятор авто ($12$ В)'},
+ {id:'sock',cat:'r3', html:'розетка ($220$ В)'},
+ {id:'lep', cat:'r4', html:'ЛЭП ($10^5$ В)'},
+ {id:'lit', cat:'r5', html:'молния ($10^8$ В)'}
+ ];
+ const dnd = setupSorter({ poolId:'p18-dnd-pool', scopeSelector:'#sec-p18', cats:['r1','r2','r3','r4','r5'], items, columnLayout:false });
+ document.getElementById('p18-dnd-check').addEventListener('click', ()=>{
+ const fb = document.getElementById('p18-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. Диапазон напряжений в природе огромен — от вольта до миллиардов.'; addXp(15,'p18-dnd'); bumpProgress('p18', 20); }
+ else { fb.className='feedback fail'; fb.innerHTML='✗ Ошибок: '+wrong+'.'; }
+ });
+ document.getElementById('p18-dnd-reset').addEventListener('click', ()=>{ dnd.reset(); const fb=document.getElementById('p18-dnd-fb'); fb.style.display='none'; });
+}
+
+function _initP18_tasks(){
+ const TASKS = [
+ {q:'Электрон ($q = 1{,}6 \\cdot 10^{-19}$ Кл) прошёл $U = 1$ В. Найди $A$ в эВ (это и есть 1 эВ). Введи в Джоулях, в формате $a \\cdot 10^{-19}$, введи $a$.', ans:1.6, tol:0.05, why:'$A = qU = 1{,}6\\cdot10^{-19} \\cdot 1 = 1{,}6\\cdot10^{-19}$ Дж = 1 эВ.'},
+ {q:'$U = 220$ В, $q = 5$ Кл. Сколько Дж энергии передало поле?', ans:1100, tol:5, why:'$A = 5 \\cdot 220 = 1100$ Дж.'},
+ {q:'В лампе работа $A = 60$ Дж за 1 с при $U = 220$ В. Какой заряд прошёл (в Кл, округли до сотых)?', ans:0.27, tol:0.02, why:'$q = A/U = 60/220 \\approx 0{,}273$ Кл.'},
+ {q:'Заряд $q = 2$ мКл переместился через $U = 100$ В. Найди $A$ в мДж.', ans:200, tol:5, why:'$A = qU = 2\\cdot10^{-3} \\cdot 100 = 0{,}2$ Дж = $200$ мДж.'},
+ {q:'$A = 1$ Дж, $q = 1$ Кл. Найди $U$.', ans:1, tol:0.05, why:'$U = A/q = 1/1 = 1$ В — определение единицы.'}
+ ];
+ let i = 0, ok = 0, done = 0, awarded = false;
+ function render(){
+ const t = TASKS[i]; const wrap = document.getElementById('p18-task'); if(!wrap) return;
+ wrap.innerHTML =
+ 'Задача '+(i+1)+'. '+t.q+'
'
+ +' '
+ +'Ответ '
+ +'Подсказка '
+ +'Следующая
'
+ +''+t.why+'
'
+ +'
';
+ document.getElementById('p18-task-i').textContent = (i+1);
+ document.getElementById('p18-task-ok').textContent = ok;
+ document.getElementById('p18-task-go').addEventListener('click', ()=>{
+ const v = parseFloat((document.getElementById('p18-task-inp').value || '').replace(',','.'));
+ const fb = document.getElementById('p18-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,'p18-task'); bumpProgress('p18', 6); }
+ else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. Ответ: '+t.ans+'. '+t.why; }
+ document.getElementById('p18-task-ok').textContent = ok;
+ renderMath(wrap);
+ if(done >= TASKS.length && !awarded && ok >= 4){ awarded = true; setTimeout(()=>{ const wf=document.getElementById('p18-task-fb'); wf.className='feedback ok'; wf.innerHTML='✓ +15 XP — расчёты сданы ('+ok+'/'+TASKS.length+').'; addXp(15,'p18-task-bonus'); bumpProgress('p18', 15); }, 600); }
+ });
+ document.getElementById('p18-task-hint').addEventListener('click', ()=>{ document.getElementById('p18-task-hint-txt').classList.toggle('show'); });
+ document.getElementById('p18-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);