diff --git a/frontend/textbooks/physics_8_ch1.html b/frontend/textbooks/physics_8_ch1.html
index e53818e..99a9f86 100644
--- a/frontend/textbooks/physics_8_ch1.html
+++ b/frontend/textbooks/physics_8_ch1.html
@@ -267,7 +267,8 @@ const ACH_LABELS = {
p9_done:"Удельная теплота плавления и кристаллизации освоен!",
p10_done:"Испарение жидкостей. Факторы, влияющие на скорость испарения освоен!",
p11_done:"Кипение жидкостей. Удельная теплота парообразования освоен!",
- ch1_done:"Глава 1 пройдена!"
+ ch1_done:"Глава 1 пройдена!",
+ thermal_master:"Мастер теплоты — все боссы главы 1 повержены!"
};
const SIDEBARS = {
@@ -337,9 +338,24 @@ const SIDEBARS = {
["железо","$\\lambda = 2{,}7 \\cdot 10^5$"],
["Баланс","$Q_{нагр} + Q_{пл} + Q_{нагр.ж}$"]
]},
- p10:{title:"Шпаргалка § 10",rows:[["В разработке","Phase 1 Wave 5"]]},
- p11:{title:"Шпаргалка § 11",rows:[["В разработке","Phase 1 Wave 5"]]},
- final1:{title:"Шпаргалка ★",rows:[["В разработке","Phase 1 Wave 5"]]}
+ p10:{title:"Шпаргалка § 10",rows:[
+ ["Испарение","с поверхности при любой $T$"],
+ ["Скорость зависит от","$T$, $S$, ветра, рода жидкости"],
+ ["Жидкость","охлаждается (уходят быстрые)"],
+ ["Конденсация","пар $\\to$ жидкость, тепло выделяется"]
+ ]},
+ p11:{title:"Шпаргалка § 11",rows:[
+ ["Кипение","по всему объёму при $T = T_{кип}$"],
+ ["Формула","$Q = Lm$"],
+ ["$L$ для воды","$2{,}26 \\cdot 10^6$ Дж/кг"],
+ ["$T_{кип}$ воды","100 °C (при 1 атм)"],
+ ["Давление $\\downarrow$","$T_{кип} \\downarrow$ (на горе)"]
+ ]},
+ final1:{title:"Финал главы 1",rows:[
+ ["Формулы","$Q = cm\\Delta T$, $Q = qm$, $Q = \\lambda m$, $Q = Lm$"],
+ ["3 вида теплопередачи","проводность, конвекция, излучение"],
+ ["Награда","+50 XP + «Мастер теплоты»"]
+ ]}
};
const TIPS=[
@@ -352,9 +368,9 @@ const TIPS=[
{sec:'p7',html:"При сгорании 1 кг топлива выделяется $q$ Дж энергии. Полное выделение: $Q = q m$. У бензина $q$ в 4,5 раза больше, чем у дров, — поэтому литр бензина греет дольше, чем литр дров."},
{sec:'p8',html:"Пока лёд плавится, температура смеси «лёд + вода» сидит на 0 °C — даже если плита продолжает греть. На графике $T(t)$ это видно как горизонтальная площадка (плато)."},
{sec:'p9',html:"Чтобы расплавить 1 кг льда (без нагрева!), нужно $\\lambda = 334$ кДж. Это столько же, сколько на нагрев той же массы воды от 0 до 80 °C. Поэтому лёд — хороший «холодильник»."},
- {sec:'p10',html:"Параграф § 10 будет реализован в Phase 1 Wave 5. Используем хелперы из phys.js и optics.js."},
- {sec:'p11',html:"Параграф § 11 будет реализован в Phase 1 Wave 5. Используем хелперы из phys.js и optics.js."},
- {sec:'final1',html:"Параграф ★ будет реализован в Phase 1 Wave 5. Используем хелперы из phys.js и optics.js."}
+ {sec:'p10',html:"Лужа высыхает даже зимой — это испарение. Чем теплее и ветренее, тем быстрее. При этом сама жидкость остывает , потому что её покидают самые быстрые молекулы — вот почему мокрая рука зябнет."},
+ {sec:'p11',html:"При кипении пузырьки пара образуются внутри жидкости. Чтобы перевести 1 кг воды (100 °C) в пар, нужно $L = 2{,}26 \\cdot 10^6$ Дж — это в 5,4 раза больше, чем на нагрев той же воды от 0 до 100 °C."},
+ {sec:'final1',html:"Финал главы — синтез 11 параграфов. 7 интегрированных боссов на формулы $Q = cm\\Delta T$, $\\lambda m$, $Lm$, $qm$, баланс смешивания, КПД, цепные расчёты. За победу — +50 XP и ачивка «Мастер теплоты»."}
];
const BUILDERS = {
@@ -367,9 +383,9 @@ const BUILDERS = {
p7: ()=>{ build_p7(); },
p8: ()=>{ build_p8(); },
p9: ()=>{ build_p9(); },
- p10: ()=>{ const box=document.getElementById('p10-body'); box.innerHTML = buildStub('p10', 'Испарение жидкостей. Факторы, влияющие на скорость испарения', 'Phase 1 Wave 5') + secNavFor('p10') + readButton('p10'); renderMath(box); wireReadBtn('p10'); },
- p11: ()=>{ const box=document.getElementById('p11-body'); box.innerHTML = buildStub('p11', 'Кипение жидкостей. Удельная теплота парообразования', 'Phase 1 Wave 5') + secNavFor('p11') + readButton('p11'); renderMath(box); wireReadBtn('p11'); },
- final1: ()=>{ const box=document.getElementById('final1-body'); box.innerHTML = buildStub('final1', 'Финал главы', 'Phase 1 Wave 5') + secNavFor('final1') + readButton('final1'); renderMath(box); wireReadBtn('final1'); }
+ p10: ()=>{ build_p10(); },
+ p11: ()=>{ build_p11(); },
+ final1: ()=>{ build_final1(); }
};
function calcLevel(xp){ return Math.floor(Math.sqrt((xp||0)/100))+1; }
@@ -2968,6 +2984,592 @@ function _initP9_tasks(){
render();
}
+/* ======================================================================
+ PHASE 1 · WAVE 5 — §10, §11, FINAL 1
+ ====================================================================== */
+
+/* ======== §10 — Испарение жидкостей ======== */
+function build_p10(){
+ const box = document.getElementById('p10-body');
+ let h = '';
+
+ h += makeCard('theory', 'Что такое испарение', '§ 10.1',
+ '
Испарение — переход жидкости в пар с поверхности . Идёт при любой температуре (даже при 0 °C, даже зимой).
'
+ +'Механизм: молекулы у поверхности движутся хаотически. Самые быстрые из них преодолевают притяжение остальных и улетают в воздух — становятся паром.
'
+ +'Поэтому при испарении жидкость остывает — её покидают наиболее «горячие» молекулы, средняя $E_k$ оставшихся падает.
'
+ );
+ h += makeCard('rule', 'От чего зависит скорость испарения', '§ 10.2',
+ ''
+ +'Температура : чем выше $T$, тем больше быстрых молекул, испарение интенсивнее. '
+ +'Площадь свободной поверхности : чем больше $S$, тем больше «выходов». '
+ +'Движение воздуха (ветер): унося пар, ветер не даёт ему вернуться обратно. '
+ +'Род жидкости : эфир, спирт испаряются быстро; вода медленнее; ртуть — почти не испаряется. '
+ +' '
+ +'Обратный процесс — конденсация (пар $\\to$ жидкость), при ней теплота выделяется .
'
+ );
+ h += makeCard('example', 'Где встречается', '§ 10.3',
+ ''
+ +'Пот охлаждает тело — испаряясь, он уносит тепло. '
+ +'Мокрая рука или одежда зябнет на ветру. '
+ +'Лужа на ветреной площади сохнет быстрее, чем в безветренной комнате. '
+ +'Бельё сохнет быстрее на солнце и на ветру. '
+ +'Зимой бельё, вынесенное на мороз, тоже постепенно высыхает (возгонка). '
+ +' '
+ );
+
+ /* IV1 — симуляция «молекулы покидают поверхность» */
+ h += ''
+ +''
+ +'
Меняй температуру и ветер — наблюдай, как быстро молекулы покидают жидкость и уносятся в воздух.
'
+ +'
'
+ +'$T$, °C: 40 '
+ +'Ветер: умеренный '
+ +'
'
+ +'
'
+ +'
Испарилось молекул: 0 Скорость: средняя
'
+ +'
';
+
+ /* IV2 — викторина «лужа высохнет быстрее…» */
+ h += ''
+ +''
+ +'
Сравни две ситуации.
'
+ +'
'
+ +'
Следующий
'
+ +'
Раунд: 1 / 6 Правильно: 0
'
+ +'
';
+
+ /* IV3 — DnD факторы */
+ h += ''
+ +''
+ +'
Перетащи факторы в две колонки.
'
+ +'
'
+ +'
'
+ +'
Проверить Сброс
'
+ +'
'
+ +'
';
+
+ /* IV4 — MCQ */
+ h += ''
+ +''
+ +'
4+ правильных — +15 XP.
'
+ +'
'
+ +'
Вопрос: 1 / 6 Правильно: 0
'
+ +'
';
+
+ box.innerHTML = h + secNavFor('p10') + readButton('p10');
+ renderMath(box);
+ wireReadBtn('p10');
+
+ _initP10_sim();
+ _initP10_quiz();
+ _initP10_dnd();
+ _initP10_mcq();
+}
+
+function _initP10_sim(){
+ _killSim('p10sim');
+ const svg = document.getElementById('p10-sim'); if(!svg) return;
+ const W = 460, H = 220;
+ /* жидкость в нижней половине, частицы вылетают вверх */
+ const liqY = 130;
+ const N = 28;
+ const ps = [];
+ for(let i=0;i W + 10 || p.y < -10){
+ /* "вернуть" молекулу обратно */
+ p.x = 80 + Math.random()*300; p.y = liqY + 10 + Math.random()*70;
+ p.vx = 0; p.vy = 0; p.evap = false;
+ }
+ } else {
+ /* у поверхности (y близок к liqY) есть шанс испариться */
+ if(p.y < liqY + 14 && Math.random() < pEvap){
+ p.evap = true;
+ p.vy = -1.0 - Math.random()*0.6;
+ p.vx = (Math.random() - 0.4) * 0.5 + wind*0.2;
+ evapCount++;
+ } else {
+ /* небольшое броуновское движение */
+ p.x += (Math.random()-0.5)*0.6;
+ p.y += (Math.random()-0.5)*0.6;
+ if(p.x < 75) p.x = 75; if(p.x > 385) p.x = 385;
+ if(p.y < liqY + 6) p.y = liqY + 6;
+ if(p.y > 200) p.y = 200;
+ }
+ }
+ }
+ /* draw */
+ let s = '';
+ /* сосуд + жидкость */
+ s += ' ';
+ s += ' ';
+ /* небо */
+ s += ' ';
+ /* солнце-температура */
+ const tCol = window.PHYS.tempColor(T, 5, 90);
+ s += ' ';
+ s += ''+T+'° ';
+ /* ветер-стрелки */
+ if(wind > 0){
+ for(let i=0;i ';
+ }
+ svg.innerHTML = s;
+ _SIMS.p10sim.raf = requestAnimationFrame(tick);
+ }
+ _SIMS.p10sim = { raf: 0 };
+ _SIMS.p10sim.raf = requestAnimationFrame(tick);
+
+ function update(){
+ T = +document.getElementById('p10-t').value;
+ wind = +document.getElementById('p10-w').value;
+ document.getElementById('p10-tv').textContent = T;
+ document.getElementById('p10-wv').textContent = ['нет','слабый','умеренный','сильный'][wind];
+ const rate = T*0.4 + wind*5;
+ let rateLabel = 'низкая';
+ if(rate > 25) rateLabel = 'высокая';
+ else if(rate > 15) rateLabel = 'средняя';
+ document.getElementById('p10-rate').textContent = rateLabel;
+ document.getElementById('p10-evap').textContent = evapCount;
+ }
+ document.getElementById('p10-t').addEventListener('input', update);
+ document.getElementById('p10-w').addEventListener('input', update);
+ setInterval(()=>{ document.getElementById('p10-evap').textContent = evapCount; }, 500);
+ update();
+}
+
+function _initP10_quiz(){
+ const QS = [
+ {A:'лужа в безветренной комнате при 20 °C', B:'лужа на ветреной площади при 20 °C', ans:'B', why:'Ветер ускоряет испарение, унося пар.'},
+ {A:'вода в стакане', B:'та же вода, разлитая по тарелке', ans:'B', why:'Больше площадь свободной поверхности — быстрее испарение.'},
+ {A:'мокрая ткань на 20 °C', B:'та же ткань на 5 °C', ans:'A', why:'Выше $T$ — больше быстрых молекул.'},
+ {A:'вода', B:'эфир (при той же $T$)', ans:'B', why:'У эфира слабее связи между молекулами, он испаряется в десятки раз быстрее воды.'},
+ {A:'бельё в подвале', B:'бельё на солнце и ветру', ans:'B', why:'Солнечное излучение нагревает + ветер уносит пар.'},
+ {A:'мокрая рука на воздухе', B:'мокрая рука в воде', ans:'A', why:'В воде испарения почти нет — нет свободной поверхности «жидкость-воздух».'}
+ ];
+ let i = 0, ok = 0;
+ function render(){
+ const q = QS[i]; const wrap = document.getElementById('p10-quiz'); if(!wrap) return;
+ wrap.innerHTML =
+ ''
+ +'A. '+q.A+' '
+ +'B. '+q.B+' '
+ +'
'
+ +'
';
+ document.getElementById('p10-quiz-r').textContent = (i+1);
+ document.getElementById('p10-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('p10-quiz-fb');
+ if(btn.dataset.pick === q.ans){ ok++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(3,'p10-quiz'); bumpProgress('p10', 4); }
+ else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; }
+ document.getElementById('p10-quiz-ok').textContent = ok;
+ });
+ });
+ }
+ document.getElementById('p10-quiz-next').addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); });
+ render();
+}
+
+function _initP10_dnd(){
+ const items = [
+ {id:'up_t', cat:'up', html:'нагрев'},
+ {id:'up_s', cat:'up', html:'большая площадь'},
+ {id:'up_w', cat:'up', html:'ветер'},
+ {id:'up_e', cat:'up', html:'эфир вместо воды'},
+ {id:'dn_t', cat:'dn', html:'охлаждение'},
+ {id:'dn_s', cat:'dn', html:'узкое горлышко'},
+ {id:'dn_w', cat:'dn', html:'закрытая банка'},
+ {id:'dn_m', cat:'dn', html:'ртуть вместо воды'}
+ ];
+ const dnd = setupSorter({ poolId:'p10-dnd-pool', scopeSelector:'#sec-p10', cats:['up','dn'], items, columnLayout:false });
+ document.getElementById('p10-dnd-check').addEventListener('click', ()=>{
+ const fb = document.getElementById('p10-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. Четыре фактора: T, S, ветер, род жидкости.'; addXp(15,'p10-dnd'); bumpProgress('p10', 20); }
+ else { fb.className='feedback fail'; fb.innerHTML='✗ Ошибок: '+wrong+'. Подсказка: ртуть и закрытая банка — это блокирует испарение.'; }
+ });
+ document.getElementById('p10-dnd-reset').addEventListener('click', ()=>{ dnd.reset(); const fb=document.getElementById('p10-dnd-fb'); fb.style.display='none'; });
+}
+
+function _initP10_mcq(){
+ const QS = [
+ {q:'При испарении жидкость …', opts:['нагревается','остывает','не меняет $T$','становится твёрже'], ans:1, why:'Уходят самые быстрые молекулы — средняя $E_k$ остающихся падает.'},
+ {q:'При какой температуре идёт испарение?', opts:['только при $T_{кип}$','при любой $T$','только зимой','только под солнцем'], ans:1, why:'Испарение идёт всегда, даже у льда (возгонка).'},
+ {q:'Почему мокрая рука зябнет на ветру?', opts:['ветер холодный','вода уносит тепло','испарение охлаждает','оба B и C'], ans:3, why:'И вода уносит тепло, и испаряясь, охлаждает кожу.'},
+ {q:'Где жидкость испаряется быстрее?', opts:['в стакане','в тарелке','в бутылке','в пробирке'], ans:1, why:'В тарелке самая большая площадь свободной поверхности.'},
+ {q:'Что произойдёт, если над паром резко охладить?', opts:['он замёрзнет','он расширится','он конденсируется','ничего'], ans:2, why:'Конденсация — пар возвращается в жидкость, тепло выделяется.'},
+ {q:'Когда лужа высохнет быстрее?', opts:['ночью','днём','в тумане','в подвале'], ans:1, why:'Днём — больше тепла, обычно ветер.'}
+ ];
+ let i = 0, ok = 0, done = 0, awarded = false;
+ function render(){
+ const q = QS[i]; const wrap = document.getElementById('p10-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('p10-mcq-i').textContent = (i+1);
+ document.getElementById('p10-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('p10-mcq-fb');
+ if(k===q.ans){ ok++; done++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(2,'p10-mcq'); bumpProgress('p10', 3); }
+ else { done++; fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; }
+ document.getElementById('p10-mcq-ok').textContent = ok;
+ renderMath(wrap);
+ if(done >= QS.length && !awarded && ok >= 4){ awarded = true; setTimeout(()=>{ const wf=document.getElementById('p10-mcq-fb'); wf.className='feedback ok'; wf.innerHTML='✓ +15 XP — тренажёр пройден ('+ok+'/'+QS.length+').'; addXp(15,'p10-mcq-bonus'); bumpProgress('p10', 15); }, 600); }
+ });
+ });
+ const nb = document.getElementById('p10-mcq-next'); if(nb) nb.addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); });
+ renderMath(wrap);
+ }
+ render();
+}
+
+/* ======== §11 — Кипение, удельная теплота парообразования ======== */
+function build_p11(){
+ const box = document.getElementById('p11-body');
+ let h = '';
+
+ h += makeCard('theory', 'Что такое кипение', '§ 11.1',
+ 'Кипение — переход жидкости в пар по всему объёму при определённой температуре $T_{кип}$.
'
+ +'В жидкости всегда есть растворённый воздух с пузырьками пара. При $T = T_{кип}$ давление пара в пузырьках становится равно атмосферному, пузырьки растут, всплывают и лопаются — это и есть кипение.
'
+ +'Во время кипения температура жидкости не меняется , как и при плавлении.
'
+ );
+ h += makeCard('rule', '$Q = Lm$ — удельная теплота парообразования', '§ 11.2',
+ 'Чтобы перевести массу $m$ жидкости (при $T = T_{кип}$) в пар, нужно:
'
+ +'$$Q = L\\,m$$
'
+ +'$L$ — удельная теплота парообразования, Дж/кг. Для воды:
'
+ +'L = 2,26 · 106 Дж/кг = 2260 кДж/кг
'
+ +'Это огромная величина — поэтому ожог паром опаснее ожога кипятком (пар конденсируется на коже и выделяет $L$).
'
+ );
+ h += makeCard('example', '$T_{кип}$ зависит от давления', '§ 11.3',
+ ''
+ +'При нормальном давлении (1 атм $= 10^5$ Па) вода кипит при $100$ °C. '
+ +'На горе $T_{кип}$ ниже (давление меньше). На Эвересте — около $70$ °C. '
+ +'В скороварке давление выше — $T_{кип}$ выше ($120$ °C), еда варится быстрее. '
+ +'В вакууме вода кипит при комнатной температуре. '
+ +' '
+ );
+
+ /* IV1 — главный визуал: график «лёд → вода → пар» */
+ h += ''
+ +''
+ +'
Нагреваем 1 кг льда от -20 °C до пара при 100 °C. График $T(t)$ имеет два плато : плавление и кипение.
'
+ +'
'
+ +'
'
+ +'■ 1. Нагрев льда '
+ +'■ 2. Плавление при 0 °C ($\\lambda m$) '
+ +'■ 3. Нагрев воды '
+ +'■ 4. Кипение при 100 °C ($L m$) — самое длинное плато! '
+ +'■ 5. Нагрев пара '
+ +'
'
+ +'
';
+
+ /* IV2 — калькулятор Q = Lm */
+ h += ''
+ +''
+ +'
Сколько энергии нужно, чтобы перевести жидкость в пар при $T = T_{кип}$?
'
+ +'
'
+ +'Жидкость: '
+ +'вода ($L = 2{,}26 \\cdot 10^6$) '
+ +'спирт ($L = 9{,}0 \\cdot 10^5$) '
+ +'эфир ($L = 3{,}0 \\cdot 10^5$) '
+ +'ртуть ($L = 2{,}85 \\cdot 10^5$) '
+ +' '
+ +'$m$, кг: 1.0 '
+ +'
'
+ +'
'
+ +'$Q$ = 2.26 МДж = 0.63 кВт·ч '
+ +'Эквивалент: нагрев 6.7 кг воды от 20 до 100 °C. '
+ +'
'
+ +'
';
+
+ /* IV3 — DnD «фазовый переход» */
+ h += ''
+ +''
+ +'
Распредели процессы по типам.
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
Конденсация / кристаллизация
'
+ +'
'
+ +'
Проверить Сброс
'
+ +'
'
+ +'
';
+
+ /* IV4 — расчётные задачи */
+ h += ''
+ +''
+ +'
4+ верных — +15 XP.
'
+ +'
'
+ +'
Задача: 1 / 6 Правильно: 0
'
+ +'
';
+
+ box.innerHTML = h + secNavFor('p11') + readButton('p11');
+ renderMath(box);
+ wireReadBtn('p11');
+
+ _initP11_graph();
+ _initP11_calc();
+ _initP11_dnd();
+ _initP11_tasks();
+}
+
+function _initP11_graph(){
+ const svg = document.getElementById('p11-sim'); if(!svg) return;
+ /* строим график T(t) для 1 кг воды/льда/пара
+ сегменты по времени:
+ 1) -20→0 (лёд): t = m·c_ice·20 / P
+ 2) плавление: t = m·λ / P
+ 3) 0→100 (вода): t = m·c_w·100 / P
+ 4) кипение: t = m·L / P
+ 5) пар после 100, нагрев на 80 К (с pp = 2010 для пара)
+ Используем относительные времена. */
+ const m = 1;
+ const cIce=2100, lam=3.34e5, cW=4200, L=2.26e6, cSt=2010;
+ const t1 = m*cIce*20; /* 42 000 */
+ const t2 = m*lam; /* 334 000 */
+ const t3 = m*cW*100; /* 420 000 */
+ const t4 = m*L; /* 2 260 000 */
+ const t5 = m*cSt*80; /* 160 800 */
+ const T1 = 0, T2 = 100, T3 = 180;
+ const tot = t1+t2+t3+t4+t5; /* нормируем к 10 */
+ const sc = 10/tot;
+ /* points */
+ let cur = 0;
+ const segs = [
+ { tStart: cur, tEnd: (cur+=t1*sc)*1, Tstart: -20, Tend: 0, col: '#2563eb', label:'лёд' },
+ { tStart: (cur), tEnd: (cur+=t2*sc), Tstart: 0, Tend: 0, col: '#f59e0b', label:'плавление' },
+ { tStart: (cur), tEnd: (cur+=t3*sc), Tstart: 0, Tend: 100, col: '#dc2626', label:'вода' },
+ { tStart: (cur), tEnd: (cur+=t4*sc), Tstart: 100, Tend: 100, col: '#ef4444', label:'кипение' },
+ { tStart: (cur), tEnd: (cur+=t5*sc), Tstart: 100, Tend: 180, col: '#7c3aed', label:'пар' }
+ ];
+ const W=460, H=280, pad=36;
+ const r = window.PHYS.phaseGraphTT(W, H, pad, segs.map(s=>({tStart:s.tStart,tEnd:s.tEnd,Tstart:s.Tstart,Tend:s.Tend})), 10, -40, 200);
+ /* Раскрашиваем сегменты разными цветами поверх */
+ let extra = '';
+ /* Горизонталь 0 и 100 */
+ extra += ' ';
+ extra += ' ';
+ /* подписи 0 и 100 */
+ extra += '0 °C (плавление) ';
+ extra += '100 °C (кипение) ';
+ /* перерисовываем сегменты */
+ for(const s of segs){
+ extra += ' ';
+ }
+ svg.innerHTML = r.svg + extra;
+}
+
+function _initP11_calc(){
+ function update(){
+ const L = +document.getElementById('p11-liq').value;
+ const m = +document.getElementById('p11-m').value;
+ document.getElementById('p11-mv').textContent = m.toFixed(1);
+ const Q = L*m;
+ document.getElementById('p11-q').textContent = (Q/1e6).toFixed(2)+' МДж';
+ document.getElementById('p11-qkw').textContent = (Q/3.6e6).toFixed(2);
+ /* эквивалент: нагрев воды от 20 до 100 (ΔT=80, c=4200) */
+ document.getElementById('p11-eqkg').textContent = (Q/(4200*80)).toFixed(1);
+ }
+ document.getElementById('p11-liq').addEventListener('change', update);
+ document.getElementById('p11-m').addEventListener('input', update);
+ update();
+}
+
+function _initP11_dnd(){
+ const items = [
+ {id:'a', cat:'melt', html:'лёд тает в стакане'},
+ {id:'b', cat:'melt', html:'свинец становится жидким'},
+ {id:'c', cat:'evap', html:'лужа высыхает'},
+ {id:'d', cat:'evap', html:'кипящий чайник пускает пар'},
+ {id:'e', cat:'evap', html:'спирт испаряется с кожи'},
+ {id:'f', cat:'cond', html:'роса утром на траве'},
+ {id:'g', cat:'cond', html:'пар оседает на холодном стекле'},
+ {id:'h', cat:'cond', html:'жидкое золото застывает в слитки'}
+ ];
+ const dnd = setupSorter({ poolId:'p11-dnd-pool', scopeSelector:'#sec-p11', cats:['melt','evap','cond'], items, columnLayout:false });
+ document.getElementById('p11-dnd-check').addEventListener('click', ()=>{
+ const fb = document.getElementById('p11-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,'p11-dnd'); bumpProgress('p11', 20); }
+ else { fb.className='feedback fail'; fb.innerHTML='✗ Ошибок: '+wrong+'. Подсказка: роса — это пар → жидкость (конденсация).'; }
+ });
+ document.getElementById('p11-dnd-reset').addEventListener('click', ()=>{ dnd.reset(); const fb=document.getElementById('p11-dnd-fb'); fb.style.display='none'; });
+}
+
+function _initP11_tasks(){
+ const TASKS = [
+ {q:'Сколько энергии (в МДж) нужно, чтобы превратить 0,5 кг воды (100 °C) в пар? ($L = 2{,}26 \\cdot 10^6$)', ans: 1.13, tol: 0.04, why:'$Q = Lm = 2{,}26\\cdot10^6 \\cdot 0{,}5 = 1{,}13\\cdot10^6$ Дж = $1{,}13$ МДж.'},
+ {q:'Сколько кг воды можно превратить в пар, имея 11,3 МДж энергии?', ans: 5, tol: 0.1, why:'$m = Q/L = 1{,}13\\cdot10^7/(2{,}26\\cdot10^6) = 5$ кг.'},
+ {q:'$Q_1$ — нагрев 1 кг воды от 20 до 100 °C. $Q_2$ — испарение этой воды. Найди отношение $Q_2/Q_1$ (целое число).', ans: 7, tol: 0.5, why:'$Q_1 = 4200 \\cdot 80 = 336$ кДж. $Q_2 = 2260$ кДж. $Q_2/Q_1 \\approx 6{,}7 \\approx 7$.'},
+ {q:'Спирт массой 2 кг полностью испаряется. Сколько кДж нужно? ($L = 9 \\cdot 10^5$)', ans: 1800, tol: 30, why:'$Q = 9\\cdot10^5 \\cdot 2 = 1{,}8\\cdot10^6$ Дж = $1800$ кДж.'},
+ {q:'При конденсации 100 г пара (100 °C) сколько кДж выделится?', ans: 226, tol: 6, why:'$Q = Lm = 2{,}26\\cdot10^6 \\cdot 0{,}1 = 2{,}26\\cdot10^5$ Дж = $226$ кДж.'},
+ {q:'1 кг льда (-10 °C) превратить полностью в пар (100 °C). Сколько МДж нужно? ($c_л=2100$, $\\lambda=3{,}34\\cdot10^5$, $c_в=4200$, $L=2{,}26\\cdot10^6$)', ans: 3.04, tol: 0.06, why:'$Q_1=21\\,000$, $Q_2=334\\,000$, $Q_3=420\\,000$, $Q_4=2\\,260\\,000$. Итого $3{,}04$ МДж.'}
+ ];
+ let i = 0, ok = 0, done = 0, awarded = false;
+ function render(){
+ const t = TASKS[i]; const wrap = document.getElementById('p11-task'); if(!wrap) return;
+ wrap.innerHTML =
+ 'Задача '+(i+1)+'. '+t.q+'
'
+ +' '
+ +'Ответ '
+ +'Подсказка '
+ +'Следующая
'
+ +''+t.why+'
'
+ +'
';
+ document.getElementById('p11-task-i').textContent = (i+1);
+ document.getElementById('p11-task-ok').textContent = ok;
+ document.getElementById('p11-task-go').addEventListener('click', ()=>{
+ const v = parseFloat((document.getElementById('p11-task-inp').value || '').replace(',','.'));
+ const fb = document.getElementById('p11-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,'p11-task'); bumpProgress('p11', 6); }
+ else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. Правильный ответ: '+t.ans+'. '+t.why; }
+ document.getElementById('p11-task-ok').textContent = ok;
+ renderMath(wrap);
+ if(done >= TASKS.length && !awarded && ok >= 4){ awarded = true; setTimeout(()=>{ const wf=document.getElementById('p11-task-fb'); wf.className='feedback ok'; wf.innerHTML='✓ +15 XP — расчёты сданы ('+ok+'/'+TASKS.length+').'; addXp(15,'p11-task-bonus'); bumpProgress('p11', 15); }, 600); }
+ });
+ document.getElementById('p11-task-hint').addEventListener('click', ()=>{ document.getElementById('p11-task-hint-txt').classList.toggle('show'); });
+ document.getElementById('p11-task-next').addEventListener('click', ()=>{ i=(i+1)%TASKS.length; render(); });
+ renderMath(wrap);
+ }
+ render();
+}
+
+/* ======== ФИНАЛ ГЛАВЫ 1 ======== */
+function build_final1(){
+ const box = document.getElementById('final1-body');
+ let h = '';
+
+ /* Шпаргалка главы */
+ h += ''
+ +''
+ +'
'
+ +'
Тепло при изменении $T$: $Q = c m \\Delta T$c — Дж/(кг·К). У воды 4200.
'
+ +'
Тепло при сгорании: $Q = q m$q — Дж/кг. У бензина 4{,}6·10⁷.
'
+ +'
Тепло на плавление: $Q = \\lambda m$λ — Дж/кг. У льда 3{,}34·10⁵.
'
+ +'
Тепло на парообразование: $Q = L m$L — Дж/кг. У воды 2{,}26·10⁶.
'
+ +'
Баланс : $Q_{отд} = Q_{пол}$
'
+ +'
3 вида теплопередачи : проводность, конвекция, излучение
'
+ +'
';
+
+ /* 7 интегрированных боссов */
+ const BOSSES = [
+ {n:1, title:'Нагрев + расчёт', q:'На сколько градусов нагреется 2 кг алюминия при подведении 92 кДж? ($c = 920$)', hint:'$\\Delta T = Q/(cm) = 92\\,000/(920 \\cdot 2) = 50$ К.', ans:50, tol:1, step:'1'},
+ {n:2, title:'Смешивание воды', q:'Смешали 2 кг воды при $80$ °C и 3 кг воды при $20$ °C. Итоговая $T$ (°C)?', hint:'$T = (2\\cdot80 + 3\\cdot20)/5 = 220/5 = 44$ °C.', ans:44, tol:0.5, step:'1'},
+ {n:3, title:'Плавление', q:'Сколько кДж нужно, чтобы расплавить 3 кг льда при 0 °C? ($\\lambda = 3{,}34\\cdot10^5$)', hint:'$Q = \\lambda m = 3{,}34\\cdot10^5 \\cdot 3 = 1{,}002\\cdot10^6$ Дж = $1002$ кДж.', ans:1002, tol:10, step:'1'},
+ {n:4, title:'Кипение', q:'1 кг воды при 100 °C полностью испарили. Сколько МДж энергии затрачено? ($L = 2{,}26\\cdot10^6$)', hint:'$Q = Lm = 2{,}26$ МДж.', ans:2.26, tol:0.05, step:'0.01'},
+ {n:5, title:'Цепная задача', q:'1 кг льда при -10 °C довели до воды при 50 °C. Сколько кДж? ($c_л=2100$, $\\lambda=3{,}34\\cdot10^5$, $c_в=4200$)', hint:'$Q_1 = 21\\,000$, $Q_2 = 334\\,000$, $Q_3 = 210\\,000$, итого $565\\,000$ Дж = $565$ кДж.', ans:565, tol:12, step:'1'},
+ {n:6, title:'Топливо + КПД', q:'Котёл с $\\eta = 60\\%$ сжёг 5 кг дров. Какая полезная энергия в МДж? ($q = 10^7$)', hint:'$Q_{сгор} = 5\\cdot10^7 = 50$ МДж. $Q_{пол} = 0{,}6 \\cdot 50 = 30$ МДж.', ans:30, tol:0.5, step:'1'},
+ {n:7, title:'Полный цикл', q:'Сколько МДж нужно, чтобы 0,5 кг льда (0 °C) превратить в пар (100 °C)? ($\\lambda = 3{,}34\\cdot10^5$, $c_в = 4200$, $L = 2{,}26\\cdot10^6$). Округли до сотых.', hint:'$Q_{пл}=167\\,000$, $Q_{нагр}=210\\,000$, $Q_{исп}=1\\,130\\,000$. Итого $1{,}51$ МДж.', ans:1.51, tol:0.04, step:'0.01'}
+ ];
+
+ h += ''
+ +'
'
+ +'
Боссов побеждено: 0 / 7 '
+ +'
'
+ +'
'
+ +'
';
+
+ box.innerHTML = h + secNavFor('final1') + readButton('final1');
+ renderMath(box);
+ wireReadBtn('final1');
+
+ _initFinal1_bosses(BOSSES);
+}
+
+function _initFinal1_bosses(BOSSES){
+ const KEY = 'physics8_ch1_bosses';
+ function loadState(){ try { return JSON.parse(localStorage.getItem(KEY) || '{}') || {}; } catch(e){ return {}; } }
+ function saveState(s){ try { localStorage.setItem(KEY, JSON.stringify(s)); } catch(e){} }
+ function updateBar(){
+ const s = loadState();
+ let won = 0; for(const k in s) if(s[k]) won++;
+ document.getElementById('f1-won').textContent = won;
+ document.getElementById('f1-bar').style.width = Math.round(won*100/BOSSES.length)+'%';
+ if(won >= BOSSES.length && !STATE.achievements.has('thermal_master')){
+ addXp(50, 'thermal-master');
+ achievement('thermal_master');
+ }
+ return won;
+ }
+ function renderAll(){
+ const cont = document.getElementById('f1-bosses');
+ const state = loadState();
+ let html = '';
+ BOSSES.forEach(b=>{
+ const solved = state[b.n];
+ html += ''
+ +'
Босс '+b.n+' '+b.title+'
'
+ +'
'+b.q+'
'
+ +'
'
+ +' '
+ +'Атаковать '
+ +'Подсказка '
+ +'
'
+ +'
'+b.hint+'
'
+ +'
'+(solved?'✓ Победа! +10 XP. Босс повержен.':'')+'
'
+ +'
';
+ });
+ cont.innerHTML = html;
+ BOSSES.forEach(b=>{
+ const go = document.getElementById('f1-b'+b.n+'-go');
+ const inp = document.getElementById('f1-b'+b.n+'-inp');
+ const fb = document.getElementById('f1-b'+b.n+'-fb');
+ const ht = document.getElementById('f1-b'+b.n+'-ht');
+ const hintBtn = document.getElementById('f1-b'+b.n+'-hint');
+ if(hintBtn) hintBtn.addEventListener('click', ()=>{ ht.style.display = ht.style.display==='block'?'none':'block'; });
+ if(!go || go.disabled) return;
+ go.addEventListener('click', ()=>{
+ const v = parseFloat((inp.value || '').replace(',','.'));
+ if(isNaN(v)){ fb.style.display='block'; fb.className='feedback fail'; fb.innerHTML='Введите число.'; return; }
+ if(Math.abs(v - b.ans) < b.tol){
+ fb.style.display='block'; fb.className='feedback ok'; fb.innerHTML='✓ Победа! +10 XP. '+b.hint;
+ go.disabled = true; inp.disabled = true;
+ document.getElementById('f1-boss-'+b.n).classList.add('solved');
+ const s = loadState();
+ if(!s[b.n]){ s[b.n]=true; saveState(s); addXp(10,'f1-boss-'+b.n); bumpProgress('final1', 12); }
+ updateBar();
+ renderMath(fb);
+ } else {
+ fb.style.display='block'; fb.className='feedback fail'; fb.innerHTML='✗ Не то. Перепроверь и попробуй снова.';
+ }
+ });
+ inp.addEventListener('keydown', e=>{ if(e.key === 'Enter') go.click(); });
+ });
+ renderMath(cont);
+ updateBar();
+ }
+ renderAll();
+}
+
function init(){
loadProgress(); initTheme(); initSidebarToggle(); initSearch();
buildParaSelector(); refreshProgressUI(); loadServerReadState(); goTo(PARAS[0].id);