diff --git a/frontend/textbooks/physics_8_ch2.html b/frontend/textbooks/physics_8_ch2.html
index bf5563e..250fc9e 100644
--- a/frontend/textbooks/physics_8_ch2.html
+++ b/frontend/textbooks/physics_8_ch2.html
@@ -408,8 +408,21 @@ const SIDEBARS = {
["Два равных","$R_{общ} = R/2$"],
["Поломка одного","остальные работают"]
]},
- p26:{title:"Шпаргалка § 26",rows:[["В разработке","Phase 3 Wave 4"]]},
- p27:{title:"Шпаргалка § 27",rows:[["В разработке","Phase 3 Wave 4"]]},
+ p26:{title:"Шпаргалка § 26",rows:[
+ ["Работа тока","$A = U I t$"],
+ ["Мощность","$P = U I = A/t$"],
+ ["Также","$P = U^2/R = I^2 R$"],
+ ["Джоуль-Ленц","$Q = I^2 R t$"],
+ ["[P]","Вт"],
+ ["1 кВт·ч","$3{,}6 \\cdot 10^6$ Дж"]
+ ]},
+ p27:{title:"Шпаргалка § 27",rows:[
+ ["Энергия","$W = P \\tau$ (кВт·ч)"],
+ ["Стоимость","$\\text{руб} = W \\cdot \\text{тариф}$"],
+ ["1-фазная розетка","220 В, 16 А max"],
+ ["ТБ","не голыми руками!"],
+ ["Заземление","для защиты"]
+ ]},
p28:{title:"Шпаргалка § 28",rows:[["В разработке","Phase 4 Wave 1"]]},
p29:{title:"Шпаргалка § 29",rows:[["В разработке","Phase 4 Wave 1"]]},
p30:{title:"Шпаргалка § 30",rows:[["В разработке","Phase 4 Wave 2"]]},
@@ -432,8 +445,8 @@ const TIPS=[
{sec:'p23',html:"Сопротивление провода зависит от трёх вещей: материала ($\\rho$), длины ($l$) и толщины ($S$). Длинный тонкий нихром — большое $R$ (спираль чайника), короткий толстый медный — маленькое $R$ (провод)."},
{sec:'p24',html:"При последовательном соединении ток течёт через все элементы один и тот же. Напряжения складываются. Сопротивления складываются. Реостат — переменный резистор, при сдвиге движка меняется длина включённой проволоки."},
{sec:'p25',html:"При параллельном соединении на каждой ветви одно и то же напряжение. Токи складываются. Сопротивление считается по особой формуле — в итоге $R_{общ}$ меньше любого из $R_1$, $R_2$."},
- {sec:'p26',html:"Параграф § 26 будет реализован в Phase 3 Wave 4. Используем хелперы из phys.js и optics.js."},
- {sec:'p27',html:"Параграф § 27 будет реализован в Phase 3 Wave 4. Используем хелперы из phys.js и optics.js."},
+ {sec:'p26',html:"$A = UIt$ — энергия, которую ток отдаёт прибору. $P = UI$ — это мощность (Дж/с = Вт). В резисторе вся эта энергия превращается в тепло — это закон Джоуля-Ленца : $Q = I^2 R t$."},
+ {sec:'p27',html:"Счётчик в квартире меряет энергию в кВт·ч : 1 кВт·ч — это работа за 1 час мощностью 1 кВт. Стоимость = энергия × тариф. ТБ: розетка под 220 В может ударить смертельным током."},
{sec:'p28',html:"Параграф § 28 будет реализован в Phase 4 Wave 1. Используем хелперы из phys.js и optics.js."},
{sec:'p29',html:"Параграф § 29 будет реализован в Phase 4 Wave 1. Используем хелперы из phys.js и optics.js."},
{sec:'p30',html:"Параграф § 30 будет реализован в Phase 4 Wave 2. Используем хелперы из phys.js и optics.js."},
@@ -456,8 +469,8 @@ const BUILDERS = {
p23: ()=>{ build_p23(); },
p24: ()=>{ build_p24(); },
p25: ()=>{ build_p25(); },
- p26: ()=>{ const box=document.getElementById('p26-body'); box.innerHTML = buildStub('p26', 'Работа и мощность электрического тока. Закон Джоуля — Ленца', 'Phase 3 Wave 4') + secNavFor('p26') + readButton('p26'); renderMath(box); wireReadBtn('p26'); },
- p27: ()=>{ const box=document.getElementById('p27-body'); box.innerHTML = buildStub('p27', 'Использование и экономия электроэнергии. Безопасность', 'Phase 3 Wave 4') + secNavFor('p27') + readButton('p27'); renderMath(box); wireReadBtn('p27'); },
+ p26: ()=>{ build_p26(); },
+ p27: ()=>{ build_p27(); },
p28: ()=>{ const box=document.getElementById('p28-body'); box.innerHTML = buildStub('p28', 'Постоянные магниты', 'Phase 4 Wave 1') + secNavFor('p28') + readButton('p28'); renderMath(box); wireReadBtn('p28'); },
p29: ()=>{ const box=document.getElementById('p29-body'); box.innerHTML = buildStub('p29', 'Магнитное поле', 'Phase 4 Wave 1') + secNavFor('p29') + readButton('p29'); renderMath(box); wireReadBtn('p29'); },
p30: ()=>{ const box=document.getElementById('p30-body'); box.innerHTML = buildStub('p30', 'Магнитное поле тока', 'Phase 4 Wave 2') + secNavFor('p30') + readButton('p30'); renderMath(box); wireReadBtn('p30'); },
@@ -3893,6 +3906,437 @@ function _initP25_tasks(){
render();
}
+/* ======================================================================
+ PHASE 3 · WAVE 4 — §26, §27
+ ====================================================================== */
+
+/* ======== §26 — Работа и мощность тока. Джоуль-Ленц ======== */
+function build_p26(){
+ const box = document.getElementById('p26-body');
+ let h = '';
+
+ h += makeCard('theory', 'Работа тока', '§ 26.1',
+ '
Электрическое поле, прогоняя заряд через проводник, совершает работу. За время $t$ через сечение проходит заряд $q = It$. На каждый кулон поле совершает работу $U$ Джоулей. Значит:
'
+ +'$$A = U I t$$
'
+ +'Это работа электрического тока — энергия, которую ток отдаёт прибору. Она превращается в тепло, свет, движение, звук — в зависимости от прибора.
'
+ );
+ h += makeCard('rule', 'Мощность тока', '§ 26.2',
+ 'Мощность $P$ — работа за единицу времени:
'
+ +'$$P = \\dfrac{A}{t} = U I$$
'
+ +'Эквиваленты (используя закон Ома):
'
+ +'$$P = U I = I^2 R = \\dfrac{U^2}{R}$$
'
+ +'Единица: 1 Ватт (Вт) — это 1 Дж/с. Названа в честь Джеймса Уатта.
'
+ );
+ h += makeCard('example', 'Закон Джоуля — Ленца', '§ 26.3',
+ 'В резисторе вся электрическая энергия превращается в тепло :
'
+ +'$$Q = I^2 R t$$
'
+ +'Это закон Джоуля-Ленца . Поэтому работают спирали чайника, утюга, кипятильника. Чем больше $I$ или $R$, тем больше тепла.
'
+ +'В лампе накаливания нить нагревается до $\\sim 2500$ °C и светится. КПД у такой лампы низкий — 5%; остальное тепло.
'
+ );
+
+ /* IV1 — калькулятор P+анимация нагрева */
+ h += ''
+ +''
+ +'
Меняй $U$ и $R$ — увидь мощность и как нагревается резистор.
'
+ +'
'
+ +'$U$, В: 220 '
+ +'$R$, Ом: 100 '
+ +'
'
+ +'
'
+ +'
'
+ +'$I = U/R$ = 2.2 А '
+ +'$P = UI$ = 484 Вт '
+ +'$Q$ за 1 минуту = 29.0 кДж '
+ +'
'
+ +'
';
+
+ /* IV2 — выбор формулы */
+ h += ''
+ +''
+ +'
Даны величины — выбери удобную формулу для $P$.
'
+ +'
'
+ +'
Следующий
'
+ +'
Раунд: 1 / 5 Правильно: 0
'
+ +'
';
+
+ /* IV3 — DnD мощности приборов */
+ h += ''
+ +''
+ +'
От самого «слабого» к самому «мощному».
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
Проверить Сброс
'
+ +'
'
+ +'
';
+
+ /* IV4 — задачи */
+ h += ''
+ +''
+ +'
4+ — +15 XP.
'
+ +'
'
+ +'
Задача: 1 / 6 Правильно: 0
'
+ +'
';
+
+ box.innerHTML = h + secNavFor('p26') + readButton('p26');
+ renderMath(box);
+ wireReadBtn('p26');
+
+ _initP26_sim();
+ _initP26_quiz();
+ _initP26_dnd();
+ _initP26_tasks();
+}
+
+function _initP26_sim(){
+ const svg = document.getElementById('p26-sim'); if(!svg) return;
+ function update(){
+ const U = +document.getElementById('p26-u').value;
+ const R = +document.getElementById('p26-r').value;
+ document.getElementById('p26-uv').textContent = U;
+ document.getElementById('p26-rv').textContent = R;
+ const I = U/R;
+ const P = U*I;
+ const Q1 = P * 60; /* за 1 мин */
+ document.getElementById('p26-ic').textContent = I.toFixed(2);
+ document.getElementById('p26-pc').textContent = P.toFixed(0);
+ document.getElementById('p26-q1').textContent = (Q1/1000).toFixed(1);
+ /* SVG: резистор + цвет нагрева */
+ let s = '';
+ s += window.PHYS.batteryEMF(60, 70, U+' В', 'h');
+ s += window.PHYS.wire(60, 52, 60, 30);
+ s += window.PHYS.wire(60, 30, 200, 30);
+ /* резистор */
+ const tCol = window.PHYS.tempColor(Math.min(150, P/8), 20, 150);
+ s += ' ';
+ s += 'R = '+R+' Ом ';
+ /* glow при высокой мощности */
+ if(P > 100){
+ const glow = Math.min(1, P/2000);
+ s += ' ';
+ }
+ s += window.PHYS.wire(280, 30, 400, 30);
+ s += window.PHYS.wire(400, 30, 400, 70);
+ s += window.PHYS.wire(80, 70, 400, 70);
+ /* подпись P */
+ s += 'P = '+P.toFixed(0)+' Вт ';
+ s += 'за 1 мин: Q = '+(Q1/1000).toFixed(1)+' кДж ';
+ s += ''+(P<60 ? 'слабый разогрев' : P<500 ? 'тёплый' : P<1500 ? 'горячо' : 'опасно — может оплавиться')+' ';
+ svg.innerHTML = s;
+ }
+ document.getElementById('p26-u').addEventListener('input', update);
+ document.getElementById('p26-r').addEventListener('input', update);
+ update();
+}
+
+function _initP26_quiz(){
+ const QS = [
+ {sit:'Дано $U = 220$ В, $I = 5$ А. Какая формула?', opts:['$P = UI$','$P = I^2R$','$P = U^2/R$','любая'], ans:0, why:'Когда дано $U$ и $I$ — прямой подсчёт через $UI$.'},
+ {sit:'Дано $I = 3$ А, $R = 50$ Ом. Какая?', opts:['$P = UI$','$P = I^2R$','$P = U^2/R$','нельзя'], ans:1, why:'Когда дано $I$ и $R$ — $I^2R$.'},
+ {sit:'Дано $U = 220$ В, $R = 100$ Ом. Какая?', opts:['$P = UI$','$P = I^2R$','$P = U^2/R$','нельзя'], ans:2, why:'$U^2/R$ удобнее.'},
+ {sit:'$P$ нагревательного прибора 1500 Вт при $U = 220$ В. Какой ток?', opts:['$I = P/U \\approx 6{,}8$ А','$I = U/R$','$I = UP$','нельзя'], ans:0, why:'$I = P/U = 1500/220 \\approx 6{,}82$ А.'},
+ {sit:'$Q$ за 10 с в резисторе $R$ при токе $I$. Какая формула?', opts:['$Q = It$','$Q = UI/t$','$Q = I^2 R t$','$Q = U^2/R$'], ans:2, why:'Закон Джоуля-Ленца.'}
+ ];
+ let i = 0, ok = 0;
+ function render(){
+ const q = QS[i]; const wrap = document.getElementById('p26-quiz'); if(!wrap) return;
+ let html = 'Вопрос '+(i+1)+'. '+q.sit+'
';
+ q.opts.forEach((opt,k)=>{ html += ''+String.fromCharCode(65+k)+'. '+opt+' '; });
+ html += '
';
+ wrap.innerHTML = html;
+ document.getElementById('p26-quiz-r').textContent = (i+1);
+ document.getElementById('p26-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('p26-quiz-fb');
+ if(k===q.ans){ ok++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(3,'p26-quiz'); bumpProgress('p26', 4); }
+ else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; }
+ document.getElementById('p26-quiz-ok').textContent = ok;
+ renderMath(wrap);
+ });
+ });
+ renderMath(wrap);
+ }
+ document.getElementById('p26-quiz-next').addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); });
+ render();
+}
+
+function _initP26_dnd(){
+ const items = [
+ {id:'led', cat:'r1', html:'светодиод (~0,1 Вт)'},
+ {id:'ph', cat:'r2', html:'телефон-зарядка (~5 Вт)'},
+ {id:'lamp',cat:'r3', html:'лампа накаливания (60 Вт)'},
+ {id:'ket', cat:'r4', html:'чайник (2000 Вт)'},
+ {id:'car', cat:'r5', html:'электромобиль (10 000 Вт)'}
+ ];
+ const dnd = setupSorter({ poolId:'p26-dnd-pool', scopeSelector:'#sec-p26', cats:['r1','r2','r3','r4','r5'], items, columnLayout:false });
+ document.getElementById('p26-dnd-check').addEventListener('click', ()=>{
+ const fb = document.getElementById('p26-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,'p26-dnd'); bumpProgress('p26', 20); }
+ else { fb.className='feedback fail'; fb.innerHTML='✗ Ошибок: '+wrong+'.'; }
+ });
+ document.getElementById('p26-dnd-reset').addEventListener('click', ()=>{ dnd.reset(); const fb=document.getElementById('p26-dnd-fb'); fb.style.display='none'; });
+}
+
+function _initP26_tasks(){
+ const TASKS = [
+ {q:'$U = 220$ В, $I = 0{,}5$ А. Найди $P$ (Вт).', ans:110, tol:1, why:'$P = UI = 220 \\cdot 0{,}5 = 110$ Вт.'},
+ {q:'Лампа 60 Вт работает 5 часов. Какая работа $A$ (Дж)?', ans:1080000, tol:5000, why:'$A = Pt = 60 \\cdot 18\\,000 = 1{,}08 \\cdot 10^6$ Дж.'},
+ {q:'$I = 2$ А, $R = 50$ Ом, $t = 60$ с. Сколько $Q$ выделится (кДж)?', ans:12, tol:0.3, why:'$Q = I^2 R t = 4 \\cdot 50 \\cdot 60 = 12\\,000$ Дж = $12$ кДж.'},
+ {q:'$P = 2000$ Вт работают 30 мин. Сколько $A$ в кВт·ч?', ans:1, tol:0.05, why:'$A = 2 \\cdot 0{,}5 = 1$ кВт·ч.'},
+ {q:'Чайник 1500 Вт, $U = 220$ В. Какой ток (А, до сотых)?', ans:6.82, tol:0.1, why:'$I = P/U = 1500/220 \\approx 6{,}82$ А.'},
+ {q:'$P = 100$ Вт, $R = 484$ Ом. Найди $U$ (В).', ans:220, tol:3, why:'$U = \\sqrt{PR} = \\sqrt{48\\,400} = 220$ В.'}
+ ];
+ let i = 0, ok = 0, done = 0, awarded = false;
+ function render(){
+ const t = TASKS[i]; const wrap = document.getElementById('p26-task'); if(!wrap) return;
+ wrap.innerHTML =
+ 'Задача '+(i+1)+'. '+t.q+'
'
+ +' '
+ +'Ответ '
+ +'Подсказка '
+ +'Следующая
'
+ +''+t.why+'
'
+ +'
';
+ document.getElementById('p26-task-i').textContent = (i+1);
+ document.getElementById('p26-task-ok').textContent = ok;
+ document.getElementById('p26-task-go').addEventListener('click', ()=>{
+ const v = parseFloat((document.getElementById('p26-task-inp').value || '').replace(',','.'));
+ const fb = document.getElementById('p26-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,'p26-task'); bumpProgress('p26', 6); }
+ else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. Ответ: '+t.ans+'. '+t.why; }
+ document.getElementById('p26-task-ok').textContent = ok;
+ renderMath(wrap);
+ if(done >= TASKS.length && !awarded && ok >= 4){ awarded = true; setTimeout(()=>{ const wf=document.getElementById('p26-task-fb'); wf.className='feedback ok'; wf.innerHTML='✓ +15 XP — расчёты сданы.'; addXp(15,'p26-task-bonus'); bumpProgress('p26', 15); }, 600); }
+ });
+ document.getElementById('p26-task-hint').addEventListener('click', ()=>{ document.getElementById('p26-task-hint-txt').classList.toggle('show'); });
+ document.getElementById('p26-task-next').addEventListener('click', ()=>{ i=(i+1)%TASKS.length; render(); });
+ renderMath(wrap);
+ }
+ render();
+}
+
+/* ======== §27 — Электроэнергия. Безопасность ======== */
+function build_p27(){
+ const box = document.getElementById('p27-body');
+ let h = '';
+
+ h += makeCard('theory', 'Энергия в быту: кВт·ч', '§ 27.1',
+ 'В квартире электросчётчик измеряет потреблённую энергию в киловатт-часах (кВт·ч) .
'
+ +'$1$ кВт·ч — работа за 1 час прибором мощностью 1 кВт = 1000 Вт.
'
+ +'$$1 \\text{ кВт·ч} = 3{,}6 \\cdot 10^6 \\text{ Дж}$$
'
+ +'Стоимость:
'
+ +'$$\\text{руб} = W (\\text{кВт·ч}) \\times \\text{тариф (руб/кВт·ч)}$$
'
+ );
+ h += makeCard('rule', 'Как сэкономить', '§ 27.2',
+ ''
+ +'Светодиоды вместо ламп накаливания (60 Вт → 8 Вт при том же свете). '
+ +'Выключать приборы из розетки (не оставлять в режиме standby). '
+ +'Энергосберегающие чайники, мультиварки. '
+ +'Утеплять дом (меньше работает обогреватель). '
+ +' '
+ );
+ h += makeCard('example', 'Безопасность при работе с током', '§ 27.3',
+ ''
+ +'Не трогать оголённые провода и розетки голыми руками. '
+ +'Не использовать электроприборы в ванной без УЗО. '
+ +'При коротком замыкании срабатывает предохранитель или автомат — отключает цепь. '
+ +'Заземление отводит ток на землю при пробое корпуса прибора. '
+ +'Опасно для жизни: ток > $50$ мА (это $\\sim 12$ В через мокрую кожу). '
+ +' '
+ );
+
+ /* IV1 — счётчик электроэнергии за месяц */
+ h += '';
+
+ /* IV2 — викторина «безопасно ли это?» */
+ h += ''
+ +''
+ +'
Оцени ситуацию с точки зрения электробезопасности.
'
+ +'
'
+ +'
Следующий
'
+ +'
Раунд: 1 / 6 Правильно: 0
'
+ +'
';
+
+ /* IV3 — DnD энергосбережение */
+ h += ''
+ +''
+ +'
'
+ +'
'
+ +'
Проверить Сброс
'
+ +'
'
+ +'
';
+
+ /* IV4 — задачи */
+ h += ''
+ +''
+ +'
4+ — +15 XP.
'
+ +'
'
+ +'
Задача: 1 / 5 Правильно: 0
'
+ +'
';
+
+ box.innerHTML = h + secNavFor('p27') + readButton('p27');
+ renderMath(box);
+ wireReadBtn('p27');
+
+ _initP27_meter();
+ _initP27_quiz();
+ _initP27_dnd();
+ _initP27_tasks();
+}
+
+function _initP27_meter(){
+ function update(){
+ const h1 = +document.getElementById('p27-h1r').value;
+ const h2 = +document.getElementById('p27-h2r').value;
+ const h3 = +document.getElementById('p27-h3r').value;
+ const h4 = +document.getElementById('p27-h4r').value;
+ const tar = +document.getElementById('p27-tarr').value;
+ document.getElementById('p27-h1').textContent = h1.toFixed(1);
+ document.getElementById('p27-h2').textContent = h2.toFixed(1);
+ document.getElementById('p27-h3').textContent = h3.toFixed(0);
+ document.getElementById('p27-h4').textContent = h4.toFixed(0);
+ document.getElementById('p27-tar').textContent = tar.toFixed(2);
+ /* кВт·ч за день */
+ const w1 = 0.060 * h1;
+ const w2 = 0.100 * h2;
+ const w3 = 2.000 * (h3/60);
+ const w4 = 0.150 * h4;
+ const wDay = w1+w2+w3+w4;
+ const wMon = wDay * 30;
+ const cost = wMon * tar;
+ document.getElementById('p27-w').textContent = wMon.toFixed(1);
+ document.getElementById('p27-cost').textContent = cost.toFixed(2);
+ const all = [['лампа',w1],['ТВ',w2],['чайник',w3],['холодильник',w4]];
+ all.sort((a,b)=>b[1]-a[1]);
+ document.getElementById('p27-top').textContent = all[0][0];
+ }
+ ['p27-h1r','p27-h2r','p27-h3r','p27-h4r','p27-tarr'].forEach(id => document.getElementById(id).addEventListener('input', update));
+ update();
+}
+
+function _initP27_quiz(){
+ const QS = [
+ {sit:'Менять лампочку в горячей люстре, не отключив выключатель.', ans:'N', why:'Опасно — можно получить удар током. Сначала выключить.'},
+ {sit:'Использовать электрочайник с заземлённой розеткой.', ans:'Y', why:'Заземление защищает в случае пробоя корпуса.'},
+ {sit:'Сушить волосы феном, стоя в ванной с водой.', ans:'N', why:'Очень опасно — вода резко увеличивает риск удара.'},
+ {sit:'Удлинитель с предохранителем для розеток.', ans:'Y', why:'Предохранитель сработает при перегрузке.'},
+ {sit:'Сэкономить — обмотать оголённый провод изолентой.', ans:'N', why:'Временный «костыль». Нужно заменить провод.'},
+ {sit:'Светодиодная лампа вместо лампы накаливания.', ans:'Y', why:'Безопаснее (меньше тепла) и экономичнее.'}
+ ];
+ let i = 0, ok = 0;
+ function render(){
+ const q = QS[i]; const wrap = document.getElementById('p27-quiz'); if(!wrap) return;
+ wrap.innerHTML =
+ ''+q.sit+'
'
+ +''
+ +'Безопасно '
+ +'Опасно '
+ +'
'
+ +'
';
+ document.getElementById('p27-quiz-r').textContent = (i+1);
+ document.getElementById('p27-quiz-ok').textContent = ok;
+ wrap.querySelectorAll('[data-pick]').forEach(btn=>{
+ btn.addEventListener('click', ()=>{
+ if(btn.disabled) return; wrap.querySelectorAll('[data-pick]').forEach(b=>b.disabled=true);
+ const fb = document.getElementById('p27-quiz-fb');
+ if(btn.dataset.pick === q.ans){ ok++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(3,'p27-quiz'); bumpProgress('p27', 4); }
+ else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; }
+ document.getElementById('p27-quiz-ok').textContent = ok;
+ });
+ });
+ }
+ document.getElementById('p27-quiz-next').addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); });
+ render();
+}
+
+function _initP27_dnd(){
+ const items = [
+ {id:'a', cat:'save', html:'светодиодная лампа'},
+ {id:'b', cat:'save', html:'утеплитель на окнах'},
+ {id:'c', cat:'save', html:'выключать ТВ из розетки'},
+ {id:'d', cat:'save', html:'натуральный свет днём'},
+ {id:'e', cat:'waste', html:'лампа накаливания 100 Вт'},
+ {id:'f', cat:'waste', html:'оставлять зарядки в розетке'},
+ {id:'g', cat:'waste', html:'кипятить полный чайник для 1 чашки'},
+ {id:'h', cat:'waste', html:'обогреватель при открытой двери'}
+ ];
+ const dnd = setupSorter({ poolId:'p27-dnd-pool', scopeSelector:'#sec-p27', cats:['save','waste'], items, columnLayout:false });
+ document.getElementById('p27-dnd-check').addEventListener('click', ()=>{
+ const fb = document.getElementById('p27-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,'p27-dnd'); bumpProgress('p27', 20); }
+ else { fb.className='feedback fail'; fb.innerHTML='✗ Ошибок: '+wrong+'.'; }
+ });
+ document.getElementById('p27-dnd-reset').addEventListener('click', ()=>{ dnd.reset(); const fb=document.getElementById('p27-dnd-fb'); fb.style.display='none'; });
+}
+
+function _initP27_tasks(){
+ const TASKS = [
+ {q:'Чайник $P = 2$ кВт работает 30 мин. Сколько кВт·ч?', ans:1, tol:0.05, why:'$W = P \\tau = 2 \\cdot 0{,}5 = 1$ кВт·ч.'},
+ {q:'Лампа $60$ Вт горит 5 часов. Сколько кВт·ч?', ans:0.3, tol:0.02, why:'$W = 0{,}06 \\cdot 5 = 0{,}3$ кВт·ч.'},
+ {q:'Тариф $0{,}25$ руб/(кВт·ч). За месяц израсходовали 200 кВт·ч. Стоимость (руб)?', ans:50, tol:1, why:'$200 \\cdot 0{,}25 = 50$ руб.'},
+ {q:'Холодильник $150$ Вт работает 24 ч/день. Сколько кВт·ч за месяц (30 дней)?', ans:108, tol:2, why:'$W = 0{,}15 \\cdot 24 \\cdot 30 = 108$ кВт·ч.'},
+ {q:'Электрообогреватель 2 кВт работает 8 ч/день, тариф $0{,}3$ руб. Сколько за месяц (руб)?', ans:144, tol:3, why:'$W = 2 \\cdot 8 \\cdot 30 = 480$ кВт·ч, $480 \\cdot 0{,}3 = 144$ руб.'}
+ ];
+ let i = 0, ok = 0, done = 0, awarded = false;
+ function render(){
+ const t = TASKS[i]; const wrap = document.getElementById('p27-task'); if(!wrap) return;
+ wrap.innerHTML =
+ 'Задача '+(i+1)+'. '+t.q+'
'
+ +' '
+ +'Ответ '
+ +'Подсказка '
+ +'Следующая
'
+ +''+t.why+'
'
+ +'
';
+ document.getElementById('p27-task-i').textContent = (i+1);
+ document.getElementById('p27-task-ok').textContent = ok;
+ document.getElementById('p27-task-go').addEventListener('click', ()=>{
+ const v = parseFloat((document.getElementById('p27-task-inp').value || '').replace(',','.'));
+ const fb = document.getElementById('p27-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,'p27-task'); bumpProgress('p27', 6); }
+ else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. Ответ: '+t.ans+'. '+t.why; }
+ document.getElementById('p27-task-ok').textContent = ok;
+ renderMath(wrap);
+ if(done >= TASKS.length && !awarded && ok >= 4){ awarded = true; setTimeout(()=>{ const wf=document.getElementById('p27-task-fb'); wf.className='feedback ok'; wf.innerHTML='✓ +15 XP — расчёты сданы.'; addXp(15,'p27-task-bonus'); bumpProgress('p27', 15); }, 600); }
+ });
+ document.getElementById('p27-task-hint').addEventListener('click', ()=>{ document.getElementById('p27-task-hint-txt').classList.toggle('show'); });
+ document.getElementById('p27-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);