feat(phys8 ch1): Phase 1 Wave 4 — §8 плавление + §9 удельная теплота плавления
§8 Плавление и кристаллизация: - 3 теории: плавление, плато на графике T(t), примеры (включая аморф.) - IV-1: график T(t) через PHYS.phaseGraphTT с цветной подсветкой 3 участков (твёрдое/плавление/жидкость) + горизонтальная линия T_пл, выбор из 7 веществ (ртуть → железо) - IV-2: 6 ситуационных вопросов (лёд+вода, плавление железа, аморфные) - IV-3: DnD ранжирование 5 веществ по T_пл - IV-4: MCQ-тренажёр §9 Q = λm: - 3 теории: формула λm, таблица, цепочка «лёд → вода» - IV-1: калькулятор Q=λm с анимацией «кубик → лужица» - IV-2: «цепной» калькулятор Q1+Q2+Q3 для нагрева льда → воды - IV-3: DnD ранжирование 5 веществ по возрастанию λ - IV-4: 6 числовых задач (включая цепные и кристаллизацию) Добавлена константа MAT_MELT. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -320,8 +320,23 @@ const SIDEBARS = {
|
||||
["природ. газ","$q = 4{,}4 \\cdot 10^7$"],
|
||||
["КПД котла","$\\eta = Q_{пол}/(q m)$"]
|
||||
]},
|
||||
p8:{title:"Шпаргалка § 8",rows:[["В разработке","Phase 1 Wave 4"]]},
|
||||
p9:{title:"Шпаргалка § 9",rows:[["В разработке","Phase 1 Wave 4"]]},
|
||||
p8:{title:"Шпаргалка § 8",rows:[
|
||||
["Плавление","$T = T_{пл} = $ const"],
|
||||
["Кристаллизация","$T = T_{кр} = T_{пл}$"],
|
||||
["На графике","горизонт. плато"],
|
||||
["Энергия идёт на","разрушение / построение решётки"],
|
||||
["лёд","$T_{пл} = 0$ °C"],
|
||||
["алюминий","$T_{пл} = 660$ °C"],
|
||||
["железо","$T_{пл} = 1539$ °C"]
|
||||
]},
|
||||
p9:{title:"Шпаргалка § 9",rows:[
|
||||
["Формула","$Q = \\lambda m$"],
|
||||
["$\\lambda$","удельная теплота плавления, Дж/кг"],
|
||||
["лёд","$\\lambda = 3{,}34 \\cdot 10^5$"],
|
||||
["свинец","$\\lambda = 2{,}5 \\cdot 10^4$"],
|
||||
["железо","$\\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"]]}
|
||||
@@ -335,8 +350,8 @@ const TIPS=[
|
||||
{sec:'p5',html:"Солнце греет Землю через космический вакуум — теплопроводность и конвекция тут невозможны. Это <b>излучение</b> электромагнитными волнами. Чёрная футболка в жаркий день нагревается сильнее белой."},
|
||||
{sec:'p6',html:"Чтобы нагреть тело массой $m$ на $\\Delta T$ градусов, нужно $Q = c m \\Delta T$. Здесь $c$ — это «сколько энергии съедает 1 кг этого вещества на 1 градус». У воды $c$ самое большое — поэтому вода долго греется и долго остывает."},
|
||||
{sec:'p7',html:"При сгорании 1 кг топлива выделяется $q$ Дж энергии. Полное выделение: $Q = q m$. У бензина $q$ в 4,5 раза больше, чем у дров, — поэтому литр бензина греет дольше, чем литр дров."},
|
||||
{sec:'p8',html:"Параграф § 8 будет реализован в Phase 1 Wave 4. Используем хелперы из <code>phys.js</code> и <code>optics.js</code>."},
|
||||
{sec:'p9',html:"Параграф § 9 будет реализован в Phase 1 Wave 4. Используем хелперы из <code>phys.js</code> и <code>optics.js</code>."},
|
||||
{sec:'p8',html:"Пока лёд плавится, температура смеси «лёд + вода» сидит на 0 °C — даже если плита продолжает греть. На графике $T(t)$ это видно как горизонтальная площадка (плато)."},
|
||||
{sec:'p9',html:"Чтобы расплавить 1 кг льда (без нагрева!), нужно $\\lambda = 334$ кДж. Это столько же, сколько на нагрев той же массы воды от 0 до 80 °C. Поэтому лёд — хороший «холодильник»."},
|
||||
{sec:'p10',html:"Параграф § 10 будет реализован в Phase 1 Wave 5. Используем хелперы из <code>phys.js</code> и <code>optics.js</code>."},
|
||||
{sec:'p11',html:"Параграф § 11 будет реализован в Phase 1 Wave 5. Используем хелперы из <code>phys.js</code> и <code>optics.js</code>."},
|
||||
{sec:'final1',html:"Параграф ★ будет реализован в Phase 1 Wave 5. Используем хелперы из <code>phys.js</code> и <code>optics.js</code>."}
|
||||
@@ -350,8 +365,8 @@ const BUILDERS = {
|
||||
p5: ()=>{ build_p5(); },
|
||||
p6: ()=>{ build_p6(); },
|
||||
p7: ()=>{ build_p7(); },
|
||||
p8: ()=>{ const box=document.getElementById('p8-body'); box.innerHTML = buildStub('p8', 'Плавление и кристаллизация', 'Phase 1 Wave 4') + secNavFor('p8') + readButton('p8'); renderMath(box); wireReadBtn('p8'); },
|
||||
p9: ()=>{ const box=document.getElementById('p9-body'); box.innerHTML = buildStub('p9', 'Удельная теплота плавления и кристаллизации', 'Phase 1 Wave 4') + secNavFor('p9') + readButton('p9'); renderMath(box); wireReadBtn('p9'); },
|
||||
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'); }
|
||||
@@ -2509,6 +2524,450 @@ function _initP7_tasks(){
|
||||
render();
|
||||
}
|
||||
|
||||
/* ======================================================================
|
||||
PHASE 1 · WAVE 4 — §8, §9
|
||||
====================================================================== */
|
||||
|
||||
/* Таблица температур плавления и λ */
|
||||
const MAT_MELT = [
|
||||
{key:'mercury',name:'ртуть', Tm:-39, lam:1.18e4},
|
||||
{key:'ice', name:'лёд', Tm:0, lam:3.34e5},
|
||||
{key:'lead', name:'свинец', Tm:327, lam:2.5e4},
|
||||
{key:'zinc', name:'цинк', Tm:420, lam:1.12e5},
|
||||
{key:'al', name:'алюминий', Tm:660, lam:3.9e5},
|
||||
{key:'cu', name:'медь', Tm:1085, lam:2.1e5},
|
||||
{key:'fe', name:'железо', Tm:1539, lam:2.7e5}
|
||||
];
|
||||
|
||||
/* ======== §8 — Плавление и кристаллизация ======== */
|
||||
function build_p8(){
|
||||
const box = document.getElementById('p8-body');
|
||||
let h = '';
|
||||
|
||||
h += makeCard('theory', 'Плавление', '§ 8.1',
|
||||
'<p><b>Плавление</b> — переход вещества из твёрдого состояния в жидкое.</p>'
|
||||
+'<p>У каждого <b>кристаллического</b> вещества есть своя <b>температура плавления</b> $T_{пл}$ — она одинакова и для плавления, и для обратного процесса — кристаллизации.</p>'
|
||||
+'<p>Во время плавления температура смеси «твёрдое + жидкое» <b>не меняется</b>, пока всё не расплавится. Подведённая теплота тратится на разрушение кристаллической решётки.</p>'
|
||||
);
|
||||
h += makeCard('rule', 'График фазового перехода', '§ 8.2',
|
||||
'<p>Если нагревать твёрдое тело и записывать температуру со временем, получится характерный график с <b>плато</b>:</p>'
|
||||
+'<ol style="padding-left:20px;margin:6px 0">'
|
||||
+'<li>нагрев твёрдого ($T$ растёт);</li>'
|
||||
+'<li>плавление ($T = T_{пл} = $ const, идёт время);</li>'
|
||||
+'<li>нагрев жидкости ($T$ снова растёт).</li>'
|
||||
+'</ol>'
|
||||
+'<p>При охлаждении — зеркальный процесс: $T$ падает $\\to$ плато кристаллизации $\\to$ $T$ продолжает падать.</p>'
|
||||
);
|
||||
h += makeCard('example', 'Примеры', '§ 8.3',
|
||||
'<ul style="padding-left:20px;margin:6px 0">'
|
||||
+'<li>Лёд в стакане воды держит $T = 0$ °C, пока не растает весь.</li>'
|
||||
+'<li>Снег зимой переносит много энергии при таянии — поэтому весной долго холодно.</li>'
|
||||
+'<li>Расплавленный металл (магма, чугун) застывает в кристаллы при остывании.</li>'
|
||||
+'<li>Аморфные тела (стекло, смола) <b>не имеют</b> чёткой $T_{пл}$ — они плавятся плавно.</li>'
|
||||
+'</ul>'
|
||||
);
|
||||
|
||||
/* IV1 — главный визуал: график T(t) с плато */
|
||||
let optsT = '';
|
||||
MAT_MELT.forEach(m=>{ optsT += '<option value="'+m.Tm+'">'+m.name+' ($T_{пл}='+m.Tm+'$ °C)</option>'; });
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-1</span><div class="wg-title">График плавления $T(t)$</div></div>'
|
||||
+'<div class="wg-help">Выбери вещество — увидь характерный «ступенчатый» график. Время плато ∝ массе и удельной теплоте плавления.</div>'
|
||||
+'<div class="sliders" style="margin-bottom:10px">'
|
||||
+'<label>Вещество: <select id="p8-mat" class="tinp" style="width:auto;padding:6px 10px;font-size:.92rem">'+optsT+'</select></label>'
|
||||
+'<label>Длительность плато: <b id="p8-pv">средняя</b><input type="range" id="p8-p" min="1" max="5" step="1" value="3"></label>'
|
||||
+'</div>'
|
||||
+'<svg id="p8-sim" viewBox="0 0 460 280" style="width:100%;height:auto;background:#f8fafc;border-radius:9px;border:1px solid var(--border)"></svg>'
|
||||
+'<div class="score-display" style="margin-top:8px;flex-direction:column;align-items:flex-start;gap:3px">'
|
||||
+'<span><span style="color:#dc2626">■</span> участок 1 — нагрев твёрдого</span>'
|
||||
+'<span><span style="color:#f59e0b">■</span> участок 2 — плавление ($T = T_{пл}$)</span>'
|
||||
+'<span><span style="color:#2563eb">■</span> участок 3 — нагрев жидкости</span>'
|
||||
+'</div>'
|
||||
+'</div>';
|
||||
|
||||
/* IV2 — квикфайр «температура смеси лёд+вода» */
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-2</span><div class="wg-title">Сколько градусов в смеси?</div></div>'
|
||||
+'<div class="wg-help">В стакане плавающий лёд и вода. Какая температура смеси?</div>'
|
||||
+'<div id="p8-quiz"></div>'
|
||||
+'<div class="actions"><button class="btn" id="p8-quiz-next">Следующий</button></div>'
|
||||
+'<div class="score-display" style="margin-top:10px"><span>Раунд: <b id="p8-quiz-r">1</b> / 6</span><span>Правильно: <b id="p8-quiz-ok">0</b></span></div>'
|
||||
+'</div>';
|
||||
|
||||
/* IV3 — DnD веществ по T_пл */
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-3</span><div class="wg-title">Расставь по $T_{пл}$ (по возрастанию)</div></div>'
|
||||
+'<div class="wg-help">От самого «мягкого» (плавится при низкой $T$) до самого тугоплавкого.</div>'
|
||||
+'<div id="p8-dnd-pool"></div>'
|
||||
+'<div style="display:grid;grid-template-columns:repeat(5,1fr);gap:8px;margin-top:10px">'
|
||||
+'<div class="drop-box"><h5>1. Меньше</h5><div class="drop-items" data-cat="r1"></div></div>'
|
||||
+'<div class="drop-box"><h5>2</h5><div class="drop-items" data-cat="r2"></div></div>'
|
||||
+'<div class="drop-box"><h5>3</h5><div class="drop-items" data-cat="r3"></div></div>'
|
||||
+'<div class="drop-box"><h5>4</h5><div class="drop-items" data-cat="r4"></div></div>'
|
||||
+'<div class="drop-box"><h5>5. Больше</h5><div class="drop-items" data-cat="r5"></div></div>'
|
||||
+'</div>'
|
||||
+'<div class="actions"><button class="btn primary" id="p8-dnd-check">Проверить</button><button class="btn" id="p8-dnd-reset">Сброс</button></div>'
|
||||
+'<div class="feedback" id="p8-dnd-fb"></div>'
|
||||
+'</div>';
|
||||
|
||||
/* IV4 — MCQ тренажёр */
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-4</span><div class="wg-title">Тренажёр: 6 вопросов</div></div>'
|
||||
+'<div class="wg-help">4+ правильных — +15 XP.</div>'
|
||||
+'<div id="p8-mcq"></div>'
|
||||
+'<div class="score-display" style="margin-top:10px"><span>Вопрос: <b id="p8-mcq-i">1</b> / 6</span><span>Правильно: <b id="p8-mcq-ok">0</b></span></div>'
|
||||
+'</div>';
|
||||
|
||||
box.innerHTML = h + secNavFor('p8') + readButton('p8');
|
||||
renderMath(box);
|
||||
wireReadBtn('p8');
|
||||
|
||||
_initP8_graph();
|
||||
_initP8_quiz();
|
||||
_initP8_dnd();
|
||||
_initP8_mcq();
|
||||
}
|
||||
|
||||
function _initP8_graph(){
|
||||
const svg = document.getElementById('p8-sim'); if(!svg) return;
|
||||
function draw(){
|
||||
const Tm = +document.getElementById('p8-mat').value;
|
||||
const p = +document.getElementById('p8-p').value;
|
||||
document.getElementById('p8-pv').textContent = ['очень кратк.','краткая','средняя','длинная','очень длин.'][p-1];
|
||||
const W = 460, H = 280, pad = 36;
|
||||
/* Сегменты графика T(t).
|
||||
Подбор: ось T от (Tm - 60) до (Tm + 80), ось t от 0 до 10. */
|
||||
const Tmin = Math.min(Tm - 60, -50);
|
||||
const Tmax = Math.max(Tm + 100, 50);
|
||||
const tStart = Tm - 50;
|
||||
const plateauW = p * 0.8; /* 0.8..4 единиц времени */
|
||||
const segs = [
|
||||
{ tStart: 0, tEnd: 2, Tstart: tStart, Tend: Tm, label: 'твёрдое' },
|
||||
{ tStart: 2, tEnd: 2+plateauW, Tstart: Tm, Tend: Tm, label: 'плавление' },
|
||||
{ tStart: 2+plateauW,tEnd: 10, Tstart: Tm, Tend: Tm + 60, label: 'жидкость' }
|
||||
];
|
||||
const r = window.PHYS.phaseGraphTT(W, H, pad, segs, 10, Tmin, Tmax);
|
||||
/* Подсветка плато */
|
||||
const x1 = r.toX(2), x2 = r.toX(2+plateauW), yp = r.toY(Tm);
|
||||
let extra = '<rect x="'+x1+'" y="'+(yp-10)+'" width="'+(x2-x1)+'" height="20" fill="#fef3c7" opacity="0.6"/>';
|
||||
/* Подпись T_пл */
|
||||
extra += '<line x1="'+pad+'" y1="'+yp+'" x2="'+(W-pad)+'" y2="'+yp+'" stroke="#f59e0b" stroke-width="1.2" stroke-dasharray="4 3" opacity="0.7"/>';
|
||||
extra += '<text x="'+(pad+4)+'" y="'+(yp-4)+'" font-family="JetBrains Mono,monospace" font-size="11" font-weight="700" fill="#92400e">T_пл = '+Tm+' °C</text>';
|
||||
/* Перекрашиваем сегменты разными цветами */
|
||||
let seg1 = '<line x1="'+r.toX(0)+'" y1="'+r.toY(tStart)+'" x2="'+r.toX(2)+'" y2="'+r.toY(Tm)+'" stroke="#dc2626" stroke-width="3"/>';
|
||||
let seg2 = '<line x1="'+r.toX(2)+'" y1="'+yp+'" x2="'+r.toX(2+plateauW)+'" y2="'+yp+'" stroke="#f59e0b" stroke-width="3"/>';
|
||||
let seg3 = '<line x1="'+r.toX(2+plateauW)+'" y1="'+yp+'" x2="'+r.toX(10)+'" y2="'+r.toY(Tm+60)+'" stroke="#2563eb" stroke-width="3"/>';
|
||||
/* собираем: оси из r.svg, нужно вырезать только path и оставить оси/подписи */
|
||||
/* r.svg уже содержит оси и красный path; мы его перерисуем поверх */
|
||||
svg.innerHTML = r.svg + extra + seg1 + seg2 + seg3;
|
||||
}
|
||||
document.getElementById('p8-mat').addEventListener('change', draw);
|
||||
document.getElementById('p8-p').addEventListener('input', draw);
|
||||
draw();
|
||||
}
|
||||
|
||||
function _initP8_quiz(){
|
||||
const QS = [
|
||||
{sit:'В стакане плавающие кусочки льда + вода. Какая температура смеси?', opts:['-5 °C','0 °C','+5 °C','+10 °C'], ans:1, why:'Лёд и вода в равновесии — это точка плавления, $T = 0$ °C.'},
|
||||
{sit:'Нагреваем железо. Температура 1539 °C, на плите плато. Что происходит?', opts:['Греется как обычно','Плавится','Остывает','Кипит'], ans:1, why:'1539 °C — это $T_{пл}$ железа.'},
|
||||
{sit:'У стекла НЕТ чёткой температуры плавления. Что это значит?', opts:['Оно никогда не плавится','Это аморфное вещество','Оно газ','Оно ядовито'], ans:1, why:'Стекло — аморфное тело, нет дальнего порядка, плавится плавно.'},
|
||||
{sit:'Свинец плавится при 327 °C. При 320 °C он …', opts:['твёрдый','плавится','жидкий','газ'], ans:0, why:'320 < 327, значит ещё твёрдый.'},
|
||||
{sit:'Жидкая ртуть остывает с 0 °C до -50 °C. Где плато на графике?', opts:['нет плато','на -50','на -39','на 0'], ans:2, why:'$T_{пл}$ ртути $= -39$ °C — там плато кристаллизации.'},
|
||||
{sit:'Куда уходит подведённая теплота во время плавления?', opts:['На нагрев','На разрушение связей в кристалле','На испарение','На сжатие'], ans:1, why:'Энергия рвёт кристаллическую решётку, $T$ не меняется.'}
|
||||
];
|
||||
let i = 0, ok = 0;
|
||||
function render(){
|
||||
const q = QS[i]; const wrap = document.getElementById('p8-quiz'); if(!wrap) return;
|
||||
let html = '<div style="padding:10px 14px;background:rgba(15,23,42,.04);border-radius:9px;margin:8px 0;line-height:1.5">'+q.sit+'</div><div style="display:grid;grid-template-columns:1fr 1fr;gap:6px">';
|
||||
q.opts.forEach((opt,k)=>{ html += '<button class="btn" data-k="'+k+'" style="padding:10px 14px;text-align:left">'+String.fromCharCode(65+k)+'. '+opt+'</button>'; });
|
||||
html += '</div><div class="feedback" id="p8-quiz-fb"></div>';
|
||||
wrap.innerHTML = html;
|
||||
document.getElementById('p8-quiz-r').textContent = (i+1);
|
||||
document.getElementById('p8-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('p8-quiz-fb');
|
||||
if(k===q.ans){ ok++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(3,'p8-quiz'); bumpProgress('p8', 4); }
|
||||
else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; }
|
||||
document.getElementById('p8-quiz-ok').textContent = ok;
|
||||
});
|
||||
});
|
||||
}
|
||||
document.getElementById('p8-quiz-next').addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); });
|
||||
render();
|
||||
}
|
||||
|
||||
function _initP8_dnd(){
|
||||
/* 5 веществ по возрастанию T_пл: ртуть(-39) → лёд(0) → свинец(327) → алюминий(660) → железо(1539) */
|
||||
const items = [
|
||||
{id:'hg', cat:'r1', html:'ртуть (-39)'},
|
||||
{id:'ic', cat:'r2', html:'лёд (0)'},
|
||||
{id:'pb', cat:'r3', html:'свинец (327)'},
|
||||
{id:'al', cat:'r4', html:'алюминий (660)'},
|
||||
{id:'fe', cat:'r5', html:'железо (1539)'}
|
||||
];
|
||||
const dnd = setupSorter({ poolId:'p8-dnd-pool', scopeSelector:'#sec-p8', cats:['r1','r2','r3','r4','r5'], items, columnLayout:false });
|
||||
document.getElementById('p8-dnd-check').addEventListener('click', ()=>{
|
||||
const fb = document.getElementById('p8-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_{пл}$.'; addXp(15,'p8-dnd'); bumpProgress('p8', 20); renderMath(fb); }
|
||||
else { fb.className='feedback fail'; fb.innerHTML='✗ Ошибок: '+wrong+'. У ртути минимум, у железа максимум.'; }
|
||||
});
|
||||
document.getElementById('p8-dnd-reset').addEventListener('click', ()=>{ dnd.reset(); const fb=document.getElementById('p8-dnd-fb'); fb.style.display='none'; });
|
||||
}
|
||||
|
||||
function _initP8_mcq(){
|
||||
const QS = [
|
||||
{q:'Что происходит во время плавления?', opts:['$T$ растёт','$T$ не меняется','$T$ падает','зависит от вещества'], ans:1, why:'Энергия идёт на разрушение решётки, $T$ постоянна.'},
|
||||
{q:'Какой график соответствует нагреву и плавлению?', opts:['прямая линия','зигзаг','рост, плато, рост','падение, плато, падение'], ans:2, why:'Плато плавления разделяет две прямые роста.'},
|
||||
{q:'Аморфные тела (стекло, смола) …', opts:['не плавятся','имеют резкую $T_{пл}$','плавятся плавно без плато','состоят из жидкости'], ans:2, why:'Нет кристаллической решётки $\\Rightarrow$ нет резкого перехода.'},
|
||||
{q:'Когда лёд тает в воде, температура смеси…', opts:['опускается','растёт','равна 0 °C, пока тает весь лёд','зависит от количества'], ans:2, why:'Это точка плавления льда.'},
|
||||
{q:'Что происходит при кристаллизации?', opts:['тепло поглощается','тепло выделяется','$T$ растёт','$T$ падает резко'], ans:1, why:'Молекулы выстраиваются в решётку и отдают связанную энергию.'},
|
||||
{q:'$T_{пл}$ и $T_{кр}$ одного вещества…', opts:['$T_{пл} > T_{кр}$','$T_{пл} < T_{кр}$','равны','зависит от давления'], ans:2, why:'Это одна и та же температура — точка фазового равновесия.'}
|
||||
];
|
||||
let i = 0, ok = 0, done = 0, awarded = false;
|
||||
function render(){
|
||||
const q = QS[i]; const wrap = document.getElementById('p8-mcq'); if(!wrap) return;
|
||||
let h = '<div style="padding:10px 14px;background:rgba(15,23,42,.04);border-radius:9px;margin-bottom:10px;font-size:.95rem;line-height:1.5"><b>Вопрос '+(i+1)+'.</b> '+q.q+'</div><div style="display:grid;grid-template-columns:1fr;gap:6px">';
|
||||
q.opts.forEach((opt,k)=>{ h += '<button class="btn" data-k="'+k+'" style="text-align:left;padding:10px 14px">'+String.fromCharCode(65+k)+'. '+opt+'</button>'; });
|
||||
h += '</div><div class="feedback" id="p8-mcq-fb"></div><div class="actions"><button class="btn" id="p8-mcq-next">Следующий</button></div>';
|
||||
wrap.innerHTML = h;
|
||||
document.getElementById('p8-mcq-i').textContent = (i+1);
|
||||
document.getElementById('p8-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('p8-mcq-fb');
|
||||
if(k===q.ans){ ok++; done++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(2,'p8-mcq'); bumpProgress('p8', 3); }
|
||||
else { done++; fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; }
|
||||
document.getElementById('p8-mcq-ok').textContent = ok;
|
||||
renderMath(wrap);
|
||||
if(done >= QS.length && !awarded && ok >= 4){ awarded = true; setTimeout(()=>{ const wf=document.getElementById('p8-mcq-fb'); wf.className='feedback ok'; wf.innerHTML='✓ +15 XP — тренажёр пройден ('+ok+'/'+QS.length+').'; addXp(15,'p8-mcq-bonus'); bumpProgress('p8', 15); }, 600); }
|
||||
});
|
||||
});
|
||||
const nb = document.getElementById('p8-mcq-next'); if(nb) nb.addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); });
|
||||
renderMath(wrap);
|
||||
}
|
||||
render();
|
||||
}
|
||||
|
||||
/* ======== §9 — Q = λm ======== */
|
||||
function build_p9(){
|
||||
const box = document.getElementById('p9-body');
|
||||
let h = '';
|
||||
|
||||
h += makeCard('theory', 'Удельная теплота плавления', '§ 9.1',
|
||||
'<p>Чтобы расплавить массу $m$ кристаллического вещества при $T = T_{пл}$, нужно подвести количество теплоты:</p>'
|
||||
+'<p style="text-align:center;margin:8px 0">$$Q = \\lambda\\,m$$</p>'
|
||||
+'<p>$\\lambda$ (лямбда) — <b>удельная теплота плавления</b>, Дж/кг.</p>'
|
||||
+'<p>Это «цена входа» в жидкое состояние: сколько энергии нужно потратить, чтобы расплавить 1 кг. При кристаллизации та же $Q$ возвращается в окружающую среду.</p>'
|
||||
);
|
||||
h += makeCard('rule', 'Таблица $\\lambda$', '§ 9.2',
|
||||
'<table style="width:100%;border-collapse:collapse;font-size:.92rem"><thead><tr style="background:rgba(15,23,42,.04)"><th style="padding:6px;text-align:left">Вещество</th><th style="padding:6px;text-align:right">$T_{пл}$, °C</th><th style="padding:6px;text-align:right">$\\lambda$, $\\dfrac{\\text{Дж}}{\\text{кг}}$</th></tr></thead><tbody>'
|
||||
+ MAT_MELT.map(m=>'<tr><td style="padding:6px;border-bottom:1px dashed var(--border)">'+m.name+'</td><td style="padding:6px;text-align:right;border-bottom:1px dashed var(--border)">'+m.Tm+'</td><td style="padding:6px;text-align:right;border-bottom:1px dashed var(--border)"><code>'+m.lam.toExponential(2).replace('+','')+'</code></td></tr>').join('')
|
||||
+'</tbody></table>'
|
||||
+'<p style="margin-top:8px">У льда $\\lambda$ велика — поэтому весной снег тает медленно, поглощая много энергии.</p>'
|
||||
);
|
||||
h += makeCard('example', 'Сложная задача: «лёд → вода → пар»', '§ 9.3',
|
||||
'<p>Если у нас есть кусок льда при -10 °C и мы хотим довести его до 50 °C, нужно три порции теплоты:</p>'
|
||||
+'<ol style="padding-left:20px;margin:6px 0">'
|
||||
+'<li>$Q_1 = c_{льда} \\cdot m \\cdot (0 - (-10))$ — нагрев льда до 0 °C;</li>'
|
||||
+'<li>$Q_2 = \\lambda \\cdot m$ — плавление льда при 0 °C;</li>'
|
||||
+'<li>$Q_3 = c_{воды} \\cdot m \\cdot (50 - 0)$ — нагрев воды до 50 °C.</li>'
|
||||
+'</ol>'
|
||||
+'<p>Всего: $Q = Q_1 + Q_2 + Q_3$.</p>'
|
||||
);
|
||||
|
||||
/* IV1 — калькулятор Q = λm с визуалом */
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-1</span><div class="wg-title">Калькулятор $Q = \\lambda m$</div></div>'
|
||||
+'<div class="wg-help">Выбери вещество и массу — увидь, сколько теплоты нужно для плавления.</div>'
|
||||
+'<div class="sliders" style="margin-bottom:10px">'
|
||||
+'<label>Вещество: <select id="p9-mat" class="tinp" style="width:auto;padding:6px 10px;font-size:.92rem">'
|
||||
+ MAT_MELT.map(m=>'<option value="'+m.lam+'" data-name="'+m.name+'" data-tm="'+m.Tm+'">'+m.name+' ($\\lambda='+m.lam.toExponential(1).replace('+','')+'$)</option>').join('')
|
||||
+'</select></label>'
|
||||
+'<label>$m$, кг: <b id="p9-mv">1.0</b><input type="range" id="p9-m" min="0.1" max="10" step="0.1" value="1"></label>'
|
||||
+'</div>'
|
||||
+'<svg id="p9-sim" viewBox="0 0 460 140" style="width:100%;height:auto;background:#f8fafc;border-radius:9px;border:1px solid var(--border)"></svg>'
|
||||
+'<div class="score-display" style="margin-top:10px;flex-direction:column;align-items:flex-start;gap:4px">'
|
||||
+'<span>$\\lambda$ = <b id="p9-lv">3.34×10<sup>5</sup></b> Дж/кг</span>'
|
||||
+'<span>$Q$ = <b id="p9-q">334 кДж</b></span>'
|
||||
+'<span style="font-size:.84rem;color:var(--muted)">Это столько же, сколько на нагрев <b id="p9-eq">80</b> кг воды на 1 К.</span>'
|
||||
+'</div>'
|
||||
+'</div>';
|
||||
|
||||
/* IV2 — тренажёр «лёд → вода → пар» */
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-2</span><div class="wg-title">Лёд → вода: расчёт по этапам</div></div>'
|
||||
+'<div class="wg-help">У нас $m$ кг льда при $T_1$ °C. Сколько энергии нужно, чтобы довести его до $T_2$ °C (жидкой воды)?</div>'
|
||||
+'<div class="sliders" style="margin-bottom:10px">'
|
||||
+'<label>$m$, кг: <b id="p9-ymv">1.0</b><input type="range" id="p9-ym" min="0.1" max="5" step="0.1" value="1"></label>'
|
||||
+'<label>$T_1$, °C: <b id="p9-y1v">-20</b><input type="range" id="p9-y1" min="-40" max="0" step="5" value="-20"></label>'
|
||||
+'<label>$T_2$, °C: <b id="p9-y2v">40</b><input type="range" id="p9-y2" min="10" max="100" step="5" value="40"></label>'
|
||||
+'</div>'
|
||||
+'<div class="score-display" style="margin-top:8px;flex-direction:column;align-items:flex-start;gap:4px">'
|
||||
+'<span>1. Нагрев льда: $Q_1 = c_{л} m (0 - T_1)$ = <b id="p9-q1">42</b> кДж</span>'
|
||||
+'<span>2. Плавление: $Q_2 = \\lambda m$ = <b id="p9-q2">334</b> кДж</span>'
|
||||
+'<span>3. Нагрев воды: $Q_3 = c_{в} m (T_2 - 0)$ = <b id="p9-q3">168</b> кДж</span>'
|
||||
+'<span style="margin-top:4px;font-weight:800">Итого: $Q$ = <b id="p9-qall">544</b> кДж</span>'
|
||||
+'</div>'
|
||||
+'</div>';
|
||||
|
||||
/* IV3 — DnD ранжирование λ */
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-3</span><div class="wg-title">Расставь $\\lambda$ по возрастанию</div></div>'
|
||||
+'<div class="wg-help">От самого «лёгкого в плавке» к самому «энергоёмкому».</div>'
|
||||
+'<div id="p9-dnd-pool"></div>'
|
||||
+'<div style="display:grid;grid-template-columns:repeat(5,1fr);gap:8px;margin-top:10px">'
|
||||
+'<div class="drop-box"><h5>1. Меньше</h5><div class="drop-items" data-cat="r1"></div></div>'
|
||||
+'<div class="drop-box"><h5>2</h5><div class="drop-items" data-cat="r2"></div></div>'
|
||||
+'<div class="drop-box"><h5>3</h5><div class="drop-items" data-cat="r3"></div></div>'
|
||||
+'<div class="drop-box"><h5>4</h5><div class="drop-items" data-cat="r4"></div></div>'
|
||||
+'<div class="drop-box"><h5>5. Больше</h5><div class="drop-items" data-cat="r5"></div></div>'
|
||||
+'</div>'
|
||||
+'<div class="actions"><button class="btn primary" id="p9-dnd-check">Проверить</button><button class="btn" id="p9-dnd-reset">Сброс</button></div>'
|
||||
+'<div class="feedback" id="p9-dnd-fb"></div>'
|
||||
+'</div>';
|
||||
|
||||
/* IV4 — расчётные задачи */
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-4</span><div class="wg-title">Тренажёр: 6 расчётных задач</div></div>'
|
||||
+'<div class="wg-help">4+ верных — +15 XP. Допуск ±3 %.</div>'
|
||||
+'<div id="p9-task"></div>'
|
||||
+'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="p9-task-i">1</b> / 6</span><span>Правильно: <b id="p9-task-ok">0</b></span></div>'
|
||||
+'</div>';
|
||||
|
||||
box.innerHTML = h + secNavFor('p9') + readButton('p9');
|
||||
renderMath(box);
|
||||
wireReadBtn('p9');
|
||||
|
||||
_initP9_calc();
|
||||
_initP9_chain();
|
||||
_initP9_dnd();
|
||||
_initP9_tasks();
|
||||
}
|
||||
|
||||
function _initP9_calc(){
|
||||
const svg = document.getElementById('p9-sim'); if(!svg) return;
|
||||
function update(){
|
||||
const sel = document.getElementById('p9-mat');
|
||||
const opt = sel.options[sel.selectedIndex];
|
||||
const lam = +sel.value;
|
||||
const m = +document.getElementById('p9-m').value;
|
||||
const name = opt.getAttribute('data-name');
|
||||
const Tm = opt.getAttribute('data-tm');
|
||||
document.getElementById('p9-mv').textContent = m.toFixed(1);
|
||||
document.getElementById('p9-lv').innerHTML = lam.toExponential(2).replace('+','').replace('e','×10<sup>')+'</sup>';
|
||||
const Q = lam * m;
|
||||
const QkJ = Q / 1000;
|
||||
document.getElementById('p9-q').textContent = QkJ.toFixed(0)+' кДж';
|
||||
/* эквивалент в "кг воды на 1 K" */
|
||||
const eqkg = Q / 4200;
|
||||
document.getElementById('p9-eq').textContent = eqkg.toFixed(1);
|
||||
/* SVG */
|
||||
let s = '';
|
||||
/* куб льда / металла, превращается в лужицу */
|
||||
s += '<rect x="50" y="40" width="80" height="60" fill="#bfdbfe" stroke="#0f172a" stroke-width="1.8" rx="4"/>';
|
||||
s += '<text x="90" y="74" text-anchor="middle" font-family="Inter,sans-serif" font-size="13" font-weight="700" fill="#0f172a">'+name+'</text>';
|
||||
s += '<text x="90" y="118" text-anchor="middle" font-family="Inter,sans-serif" font-size="11" fill="#475569">m = '+m.toFixed(1)+' кг, T = '+Tm+' °C</text>';
|
||||
/* arrow */
|
||||
s += window.PHYS.drawArrow(140, 70, 220, 70, '#f59e0b', 2.4, 10);
|
||||
s += '<text x="180" y="58" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="12" fill="#0f172a">Q = λm</text>';
|
||||
/* жидкость */
|
||||
s += '<path d="M 240 90 Q 270 65 305 65 Q 340 65 370 90 L 370 110 L 240 110 Z" fill="#60a5fa" stroke="#0f172a" stroke-width="1.6"/>';
|
||||
s += '<text x="305" y="100" text-anchor="middle" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="#fff">расплав '+name+'</text>';
|
||||
/* подпись Q */
|
||||
s += '<text x="305" y="130" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="13" font-weight="800" fill="#dc2626">Q = '+QkJ.toFixed(0)+' кДж</text>';
|
||||
svg.innerHTML = s;
|
||||
}
|
||||
document.getElementById('p9-mat').addEventListener('change', update);
|
||||
document.getElementById('p9-m').addEventListener('input', update);
|
||||
update();
|
||||
}
|
||||
|
||||
function _initP9_chain(){
|
||||
function update(){
|
||||
const m = +document.getElementById('p9-ym').value;
|
||||
const T1 = +document.getElementById('p9-y1').value;
|
||||
const T2 = +document.getElementById('p9-y2').value;
|
||||
document.getElementById('p9-ymv').textContent = m.toFixed(1);
|
||||
document.getElementById('p9-y1v').textContent = T1;
|
||||
document.getElementById('p9-y2v').textContent = T2;
|
||||
const cIce = 2100, lam = 3.34e5, cW = 4200;
|
||||
const Q1 = cIce * m * (0 - T1);
|
||||
const Q2 = lam * m;
|
||||
const Q3 = cW * m * (T2 - 0);
|
||||
document.getElementById('p9-q1').textContent = (Q1/1000).toFixed(0);
|
||||
document.getElementById('p9-q2').textContent = (Q2/1000).toFixed(0);
|
||||
document.getElementById('p9-q3').textContent = (Q3/1000).toFixed(0);
|
||||
document.getElementById('p9-qall').textContent = ((Q1+Q2+Q3)/1000).toFixed(0);
|
||||
}
|
||||
['p9-ym','p9-y1','p9-y2'].forEach(id => document.getElementById(id).addEventListener('input', update));
|
||||
update();
|
||||
}
|
||||
|
||||
function _initP9_dnd(){
|
||||
/* 5 веществ по возрастанию λ:
|
||||
ртуть(1.18e4) → свинец(2.5e4) → цинк(1.12e5) → железо(2.7e5) → лёд(3.34e5)
|
||||
(алюминий 3.9e5 не используем) */
|
||||
const items = [
|
||||
{id:'hg', cat:'r1', html:'ртуть ($1{,}2\\cdot10^4$)'},
|
||||
{id:'pb', cat:'r2', html:'свинец ($2{,}5\\cdot10^4$)'},
|
||||
{id:'zn', cat:'r3', html:'цинк ($1{,}1\\cdot10^5$)'},
|
||||
{id:'fe', cat:'r4', html:'железо ($2{,}7\\cdot10^5$)'},
|
||||
{id:'ic', cat:'r5', html:'лёд ($3{,}3\\cdot10^5$)'}
|
||||
];
|
||||
const dnd = setupSorter({ poolId:'p9-dnd-pool', scopeSelector:'#sec-p9', cats:['r1','r2','r3','r4','r5'], items, columnLayout:false });
|
||||
document.getElementById('p9-dnd-check').addEventListener('click', ()=>{
|
||||
const fb = document.getElementById('p9-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. У льда $\\lambda$ велика — поэтому снег тает медленно.'; addXp(15,'p9-dnd'); bumpProgress('p9', 20); renderMath(fb); }
|
||||
else { fb.className='feedback fail'; fb.innerHTML='✗ Ошибок: '+wrong+'. Подсказка: у льда $\\lambda$ больше всех в этом списке.'; renderMath(fb); }
|
||||
});
|
||||
document.getElementById('p9-dnd-reset').addEventListener('click', ()=>{ dnd.reset(); const fb=document.getElementById('p9-dnd-fb'); fb.style.display='none'; });
|
||||
}
|
||||
|
||||
function _initP9_tasks(){
|
||||
const TASKS = [
|
||||
{q:'Сколько энергии (в кДж) нужно, чтобы расплавить 0,5 кг льда при 0 °C? ($\\lambda = 3{,}34 \\cdot 10^5$)', ans: 167, tol: 3, why:'$Q = \\lambda m = 3{,}34\\cdot10^5 \\cdot 0{,}5 = 1{,}67\\cdot10^5$ Дж = $167$ кДж.'},
|
||||
{q:'Сколько кг свинца можно расплавить при $T_{пл}$, имея 25 кДж? ($\\lambda = 2{,}5 \\cdot 10^4$)', ans: 1, tol: 0.05, why:'$m = Q/\\lambda = 25\\,000 / 2{,}5\\cdot10^4 = 1$ кг.'},
|
||||
{q:'Лёд массой 2 кг при -10 °C довести до воды при 0 °C. Сколько кДж нужно? ($c_{л}=2100$, $\\lambda=3{,}34\\cdot10^5$)', ans: 710, tol: 14, why:'$Q_1 = 2100 \\cdot 2 \\cdot 10 = 42\\,000$, $Q_2 = 3{,}34\\cdot10^5 \\cdot 2 = 668\\,000$, итого $710\\,000$ Дж $= 710$ кДж.'},
|
||||
{q:'У какого вещества $\\lambda$ выше: у воды (лёд → жидкость) или у железа? Запиши 1 — если у льда, 2 — если у железа.', ans: 1, tol: 0.1, why:'$\\lambda_{льда} = 3{,}3\\cdot10^5$ > $\\lambda_{железа} = 2{,}7\\cdot10^5$.'},
|
||||
{q:'Сколько кДж выделится при кристаллизации 1,5 кг олова? ($\\lambda \\approx 5{,}9 \\cdot 10^4$)', ans: 88.5, tol: 2, why:'$Q = \\lambda m = 5{,}9\\cdot10^4 \\cdot 1{,}5 = 88\\,500$ Дж = $88{,}5$ кДж.'},
|
||||
{q:'Кубик льда 200 г (0 °C) положили в стакан с водой и он расплавился. Сколько кДж теплоты он отнял у воды?', ans: 66.8, tol: 2, why:'$Q = \\lambda m = 3{,}34\\cdot10^5 \\cdot 0{,}2 = 66\\,800$ Дж = $66{,}8$ кДж.'}
|
||||
];
|
||||
let i = 0, ok = 0, done = 0, awarded = false;
|
||||
function render(){
|
||||
const t = TASKS[i]; const wrap = document.getElementById('p9-task'); if(!wrap) return;
|
||||
wrap.innerHTML =
|
||||
'<div style="padding:10px 14px;background:rgba(15,23,42,.04);border-radius:9px;margin-bottom:10px;font-size:.95rem;line-height:1.5"><b>Задача '+(i+1)+'.</b> '+t.q+'</div>'
|
||||
+'<div class="boss-row"><input type="number" step="0.01" class="tinp" id="p9-task-inp" placeholder="число" style="width:140px">'
|
||||
+'<button class="btn primary" id="p9-task-go">Ответ</button>'
|
||||
+'<button class="btn" id="p9-task-hint">Подсказка</button>'
|
||||
+'<button class="btn" id="p9-task-next">Следующая</button></div>'
|
||||
+'<div class="boss-hint-txt" id="p9-task-hint-txt">'+t.why+'</div>'
|
||||
+'<div class="feedback" id="p9-task-fb"></div>';
|
||||
document.getElementById('p9-task-i').textContent = (i+1);
|
||||
document.getElementById('p9-task-ok').textContent = ok;
|
||||
document.getElementById('p9-task-go').addEventListener('click', ()=>{
|
||||
const v = parseFloat((document.getElementById('p9-task-inp').value || '').replace(',','.'));
|
||||
const fb = document.getElementById('p9-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,'p9-task'); bumpProgress('p9', 6); }
|
||||
else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. Правильный ответ: '+t.ans+'. '+t.why; }
|
||||
document.getElementById('p9-task-ok').textContent = ok;
|
||||
renderMath(wrap);
|
||||
if(done >= TASKS.length && !awarded && ok >= 4){ awarded = true; setTimeout(()=>{ const wf=document.getElementById('p9-task-fb'); wf.className='feedback ok'; wf.innerHTML='✓ +15 XP — расчёты сданы ('+ok+'/'+TASKS.length+').'; addXp(15,'p9-task-bonus'); bumpProgress('p9', 15); }, 600); }
|
||||
});
|
||||
document.getElementById('p9-task-hint').addEventListener('click', ()=>{ document.getElementById('p9-task-hint-txt').classList.toggle('show'); });
|
||||
document.getElementById('p9-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);
|
||||
|
||||
Reference in New Issue
Block a user