feat(phys10 ch2 wave2): §13 «Количество теплоты» + §14 «Первый закон ТД»
Наполнены параграфы §13 и §14 (build_p13, build_p14) — теория, формулы, 4 интерактива каждый. §13: - 3 теоретические карточки (Q=cmΔT, фазовые переходы, баланс) - ИНТ1: универсальный калькулятор Q (4 режима: нагрев/плавл/исп/сгор) - ИНТ2: SVG-график нагревания льда → воды → пара (4 сегмента) - ИНТ3: DnD-сортер 6 явлений → 4 типа процессов - ИНТ4: тренажёр 6 задач §14: - 3 теоретические карточки (формулировка, изопроцессы, адиабата) - ИНТ1: визуализатор первого закона с бар-чартом Q, ΔU, A для 4 процессов - ИНТ2: калькулятор Q = ΔU + A (3 режима поиска) - ИНТ3: квикфайр 'что неизменно' (T/V/p/Q) - ИНТ4: тренажёр 5 задач Файл: 1537 → 2325 строк. KaTeX-делимитеры, renderMath, secNav, wireReadBtn.
This commit is contained in:
@@ -1334,34 +1334,822 @@ function build_p12(){
|
||||
function build_p13(){
|
||||
const box = document.getElementById('p13-body');
|
||||
let html = '';
|
||||
html += makeCard('theory', "Количество теплоты", "§13", `
|
||||
<p><b>Количество теплоты</b> — этот параграф в разработке (Phase 1+).</p>
|
||||
<p>Здесь появятся: теория, формулы, разобранные примеры и 3–4 интерактива в стиле «алгебры 11» — таблицы, симуляции, ползунки, drag-and-drop и автопроверяемые тренажёры.</p>
|
||||
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.92rem">
|
||||
<b>Phase 0:</b> создан скелет учебника. <b>Phase 2+:</b> наполнение этого § содержанием по учебнику «Физика 10» (Беларусь, 2019).
|
||||
</p>
|
||||
|
||||
/* THEORY 1 — Количество теплоты и удельная теплоёмкость */
|
||||
html += makeCard('theory', "Количество теплоты и удельная теплоёмкость", "§13", `
|
||||
<p><b>Количество теплоты</b> $Q$ — энергия, передаваемая телу при теплообмене (без совершения работы). Единица — джоуль (Дж).</p>
|
||||
<p style="margin-top:8px">Для <b>нагревания или охлаждения</b> (без фазового перехода):</p>
|
||||
<p style="text-align:center;margin:10px 0">$$Q = c\\,m\\,\\Delta T$$</p>
|
||||
<ul style="margin:6px 0 8px 22px;line-height:1.75">
|
||||
<li>$c$ — <b>удельная теплоёмкость</b>, Дж/(кг·К);</li>
|
||||
<li>$m$ — масса тела, кг;</li>
|
||||
<li>$\\Delta T = T_{кон} - T_{нач}$ — разность температур (К или °C, числовое значение совпадает).</li>
|
||||
</ul>
|
||||
<p><b>Удельная теплоёмкость</b> — это $Q$, нужное, чтобы нагреть 1 кг вещества на 1 К. Характеристика вещества:</p>
|
||||
<table style="width:100%;border-collapse:collapse;margin:10px 0;font-size:.92rem">
|
||||
<thead><tr style="background:var(--sec-acc-soft)"><th style="padding:8px;border:1px solid var(--border);text-align:left">Вещество</th><th style="padding:8px;border:1px solid var(--border)">$c$, Дж/(кг·К)</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td style="padding:8px;border:1px solid var(--border)"><b style="color:#2563eb">Вода</b></td><td style="padding:8px;border:1px solid var(--border);text-align:center">4200</td></tr>
|
||||
<tr><td style="padding:8px;border:1px solid var(--border)">Воздух</td><td style="padding:8px;border:1px solid var(--border);text-align:center">1000</td></tr>
|
||||
<tr><td style="padding:8px;border:1px solid var(--border)">Алюминий</td><td style="padding:8px;border:1px solid var(--border);text-align:center">920</td></tr>
|
||||
<tr><td style="padding:8px;border:1px solid var(--border)">Железо</td><td style="padding:8px;border:1px solid var(--border);text-align:center">460</td></tr>
|
||||
<tr><td style="padding:8px;border:1px solid var(--border)">Медь</td><td style="padding:8px;border:1px solid var(--border);text-align:center">390</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p style="padding:10px 14px;background:var(--warn-bg,#fef3c7);border-left:4px solid var(--warn,#f59e0b);border-radius:9px"><b>Вода имеет аномально большую $c$:</b> поэтому моря медленно нагреваются и медленно остывают — именно так формируется морской климат.</p>
|
||||
`);
|
||||
|
||||
/* THEORY 2 — Фазовые переходы */
|
||||
html += makeCard('rule', "Фазовые переходы: плавление и парообразование", "§13", `
|
||||
<p><b>Плавление и кристаллизация</b> (температура не меняется):</p>
|
||||
<p style="text-align:center;margin:10px 0">$$Q = \\lambda\\,m$$</p>
|
||||
<ul style="margin:6px 0 8px 22px;line-height:1.75">
|
||||
<li>$\\lambda$ — <b>удельная теплота плавления</b>, Дж/кг;</li>
|
||||
<li>лёд: $\\lambda = 3{,}3 \\cdot 10^5$ Дж/кг ($= 330$ кДж/кг);</li>
|
||||
<li>при плавлении $Q > 0$ (поглощается), при кристаллизации $Q < 0$ (выделяется).</li>
|
||||
</ul>
|
||||
<p><b>Парообразование и конденсация</b>:</p>
|
||||
<p style="text-align:center;margin:10px 0">$$Q = r\\,m$$</p>
|
||||
<ul style="margin:6px 0 8px 22px;line-height:1.75">
|
||||
<li>$r$ — <b>удельная теплота парообразования</b>, Дж/кг;</li>
|
||||
<li>вода: $r = 2{,}26 \\cdot 10^6$ Дж/кг ($= 2260$ кДж/кг).</li>
|
||||
</ul>
|
||||
<p style="padding:10px 14px;background:var(--warn-bg,#fef3c7);border-left:4px solid var(--warn,#f59e0b);border-radius:9px"><b>Важно:</b> $r > \\lambda$ — испарение требует значительно больше энергии, чем плавление. Поэтому ожог паром гораздо опаснее ожога кипятком.</p>
|
||||
`);
|
||||
|
||||
/* THEORY 3 — Сгорание топлива и тепловой баланс */
|
||||
html += makeCard('example', "Сгорание топлива. Уравнение теплового баланса", "§13", `
|
||||
<p><b>Сгорание топлива</b>:</p>
|
||||
<p style="text-align:center;margin:10px 0">$$Q = q\\,m$$</p>
|
||||
<ul style="margin:6px 0 8px 22px;line-height:1.75">
|
||||
<li>$q$ — <b>удельная теплота сгорания</b>, Дж/кг;</li>
|
||||
<li>бензин: $q = 4{,}4 \\cdot 10^7$ Дж/кг;</li>
|
||||
<li>уголь: $q \\approx 2{,}9 \\cdot 10^7$ Дж/кг;</li>
|
||||
<li>дрова сухие: $q \\approx 1{,}3 \\cdot 10^7$ Дж/кг.</li>
|
||||
</ul>
|
||||
<p><b>Уравнение теплового баланса</b> для изолированной системы (нет теплообмена с окружением):</p>
|
||||
<p style="text-align:center;margin:10px 0">$$\\sum Q_i = 0$$</p>
|
||||
<p>Теплота, отданная горячими телами, равна теплоте, полученной холодными:</p>
|
||||
<p style="text-align:center;margin:10px 0">$$Q_{отд} = Q_{пол}$$</p>
|
||||
<p><b>Пример.</b> В калориметр наливают холодную воду и опускают горячий кусок металла. Установится общая температура $T$, при которой</p>
|
||||
<p style="text-align:center;margin:10px 0">$$c_1 m_1 (T - T_1) = c_2 m_2 (T_2 - T)$$</p>
|
||||
<p>отсюда:</p>
|
||||
<p style="text-align:center;margin:10px 0">$$T = \\dfrac{c_1 m_1 T_1 + c_2 m_2 T_2}{c_1 m_1 + c_2 m_2}$$</p>
|
||||
`);
|
||||
|
||||
/* INTERACTIVE 1 — Универсальный калькулятор Q */
|
||||
html += `<div class="wg" id="p13-iv1">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Калькулятор количества теплоты $Q$</div></div>
|
||||
<div class="wg-help">Выбери тип процесса — введи параметры — получи формулу и значение в Дж и кДж.</div>
|
||||
<div style="display:flex;gap:10px;flex-wrap:wrap;justify-content:center;margin-bottom:10px" id="p13-iv1-tabs">
|
||||
<button class="btn primary" data-mode="heat">Нагревание $Q = cm\\Delta T$</button>
|
||||
<button class="btn" data-mode="melt">Плавление $Q = \\lambda m$</button>
|
||||
<button class="btn" data-mode="evap">Испарение $Q = rm$</button>
|
||||
<button class="btn" data-mode="burn">Сгорание $Q = qm$</button>
|
||||
</div>
|
||||
<div id="p13-iv1-inputs" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:10px;margin-bottom:10px"></div>
|
||||
<div class="actions" style="justify-content:center"><button class="btn primary" id="p13-iv1-go">Вычислить $Q$</button></div>
|
||||
<div id="p13-iv1-out" style="margin-top:10px;padding:12px 14px;background:var(--card);border-radius:9px;font-size:.94rem;min-height:60px;line-height:1.85"></div>
|
||||
<div class="feedback" id="p13-iv1-fb"></div>
|
||||
</div>`;
|
||||
|
||||
/* INTERACTIVE 2 — График нагревания и плавления льда */
|
||||
html += `<div class="wg" id="p13-iv2">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">График нагревания льда → воды → пара</div></div>
|
||||
<div class="wg-help">Меняй массу — четыре сегмента ломаной: нагрев льда, плавление, нагрев воды, испарение.</div>
|
||||
<div class="sliders">
|
||||
<label>Масса $m$: <b id="p13-iv2-mL">1.0</b> кг <input type="range" id="p13-iv2-m" min="0.5" max="2" value="1.0" step="0.1"></label>
|
||||
</div>
|
||||
<div style="display:flex;gap:12px;flex-wrap:wrap;justify-content:center;margin-bottom:8px;font-size:.84rem">
|
||||
<span style="display:inline-flex;align-items:center;gap:6px"><span style="width:18px;height:3px;background:#0ea5e9;border-radius:2px"></span> Лёд</span>
|
||||
<span style="display:inline-flex;align-items:center;gap:6px"><span style="width:18px;height:0;border-top:3px dashed #2563eb"></span> Плавление</span>
|
||||
<span style="display:inline-flex;align-items:center;gap:6px"><span style="width:18px;height:3px;background:#ea580c;border-radius:2px"></span> Вода</span>
|
||||
<span style="display:inline-flex;align-items:center;gap:6px"><span style="width:18px;height:0;border-top:3px dashed #dc2626"></span> Испарение</span>
|
||||
</div>
|
||||
<div style="background:var(--card);border:1px solid var(--border);border-radius:9px;padding:8px">
|
||||
<svg id="p13-iv2-svg" viewBox="0 0 420 280" width="100%" style="height:auto"></svg>
|
||||
</div>
|
||||
<div id="p13-iv2-info" style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.92rem;line-height:1.75"></div>
|
||||
</div>`;
|
||||
|
||||
/* INTERACTIVE 3 — DnD сортер */
|
||||
html += `<div class="wg" id="p13-iv3">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 3</span><div class="wg-title">Какой это тепловой процесс?</div></div>
|
||||
<div class="wg-help">6 явлений — 4 типа процессов.</div>
|
||||
<div class="dnd-hint"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 11V6a3 3 0 0 1 6 0v5"/><path d="M9 11h6v8a4 4 0 0 1-8 0z"/></svg> 6 ситуаций — 4 ящика</div>
|
||||
<div id="p13-iv3-pool"></div>
|
||||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:10px;margin-top:8px">
|
||||
<div class="drop-box"><h5 data-cat="heat">Нагревание/охлаждение</h5><div class="drop-items" data-cat="heat"></div></div>
|
||||
<div class="drop-box"><h5 data-cat="melt">Плавление/кристаллизация</h5><div class="drop-items" data-cat="melt"></div></div>
|
||||
<div class="drop-box"><h5 data-cat="evap">Парообразование/конденсация</h5><div class="drop-items" data-cat="evap"></div></div>
|
||||
<div class="drop-box"><h5 data-cat="burn">Сгорание топлива</h5><div class="drop-items" data-cat="burn"></div></div>
|
||||
</div>
|
||||
<div class="actions"><button class="btn primary" id="p13-iv3-check">Проверить</button><button class="btn" id="p13-iv3-reset">Сначала</button></div>
|
||||
<div class="feedback" id="p13-iv3-fb"></div>
|
||||
</div>`;
|
||||
|
||||
/* INTERACTIVE 4 — Тренажёр теплоты */
|
||||
html += `<div class="wg" id="p13-iv4">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 4</span><div class="wg-title">Тренажёр теплоты</div></div>
|
||||
<div class="wg-help">6 задач. $c_{воды} = 4200$, $\\lambda_{льда} = 3{,}3 \\cdot 10^5$, $r_{воды} = 2{,}26 \\cdot 10^6$, $q_{бенз} = 4{,}4 \\cdot 10^7$ (СИ). Допуск $\\pm 5\\%$.</div>
|
||||
<div class="score-display"><span>Задача <b id="p13-iv4-i">1</b> / 6</span><span>Очки: <b id="p13-iv4-s">0</b> / 6</span></div>
|
||||
<div id="p13-iv4-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.02rem;margin-bottom:10px;text-align:center;min-height:54px"></div>
|
||||
<div style="display:flex;gap:10px;align-items:center;flex-wrap:wrap;justify-content:center">
|
||||
<span style="font-family:'JetBrains Mono',monospace">ответ =</span>
|
||||
<input type="number" id="p13-iv4-ans" class="tinp" style="width:140px;text-align:center" step="any">
|
||||
<button class="btn primary" id="p13-iv4-go">Проверить</button>
|
||||
<button class="btn" id="p13-iv4-start">Заново</button>
|
||||
</div>
|
||||
<div class="feedback" id="p13-iv4-fb"></div>
|
||||
</div>`;
|
||||
|
||||
html += secNav('p12', 'p14');
|
||||
html += readButton('p13');
|
||||
|
||||
box.innerHTML = html;
|
||||
renderMath(box);
|
||||
|
||||
/* IV1 — Универсальный калькулятор Q */
|
||||
(function(){
|
||||
const tabs = document.getElementById('p13-iv1-tabs');
|
||||
const inpsBox = document.getElementById('p13-iv1-inputs');
|
||||
const out = document.getElementById('p13-iv1-out');
|
||||
const fb = document.getElementById('p13-iv1-fb');
|
||||
const used = new Set(); let _done = false;
|
||||
let mode = 'heat';
|
||||
const C_MAP = { water:4200, air:1000, alum:920, iron:460, copper:390 };
|
||||
const C_LBL = { water:'Вода', air:'Воздух', alum:'Алюминий', iron:'Железо', copper:'Медь' };
|
||||
const L_MAP = { ice:330000, lead:25000, iron:270000 };
|
||||
const L_LBL = { ice:'Лёд (330 кДж/кг)', lead:'Свинец (25 кДж/кг)', iron:'Железо (270 кДж/кг)' };
|
||||
const R_MAP = { water:2260000, eth:360000, alc:850000 };
|
||||
const R_LBL = { water:'Вода (2260 кДж/кг)', eth:'Эфир (360 кДж/кг)', alc:'Спирт (850 кДж/кг)' };
|
||||
const Q_MAP = { gas:4.4e7, coal:2.9e7, wood:1.3e7 };
|
||||
const Q_LBL = { gas:'Бензин (44 МДж/кг)', coal:'Уголь (29 МДж/кг)', wood:'Дрова (13 МДж/кг)' };
|
||||
|
||||
function selectHTML(id, map, lblMap){
|
||||
let h = '<select id="'+id+'" class="tinp" style="width:100%;margin-top:6px;padding:6px 8px">';
|
||||
Object.keys(map).forEach(k => { h += '<option value="'+k+'">'+lblMap[k]+'</option>'; });
|
||||
h += '</select>';
|
||||
return h;
|
||||
}
|
||||
function field(id, label, val){
|
||||
return '<label style="display:block;font-size:.9rem;color:var(--muted);background:var(--card);padding:8px 12px;border-radius:8px;border:1px solid var(--border)">'+label+' <input type="number" id="'+id+'" class="tinp" style="width:100%;margin-top:6px" value="'+val+'" step="any"></label>';
|
||||
}
|
||||
function pickField(id, label, mapHtml){
|
||||
return '<label style="display:block;font-size:.9rem;color:var(--muted);background:var(--card);padding:8px 12px;border-radius:8px;border:1px solid var(--border)">'+label+mapHtml+'</label>';
|
||||
}
|
||||
function build(){
|
||||
let h = '';
|
||||
if(mode === 'heat'){
|
||||
h += pickField('p13-iv1-sub','Вещество',selectHTML('p13-iv1-c', C_MAP, C_LBL));
|
||||
h += field('p13-iv1-m','$m$, кг','1');
|
||||
h += field('p13-iv1-dt','$\\Delta T$, К','50');
|
||||
} else if(mode === 'melt'){
|
||||
h += pickField('p13-iv1-sub','Вещество',selectHTML('p13-iv1-lam', L_MAP, L_LBL));
|
||||
h += field('p13-iv1-m','$m$, кг','1');
|
||||
} else if(mode === 'evap'){
|
||||
h += pickField('p13-iv1-sub','Вещество',selectHTML('p13-iv1-r', R_MAP, R_LBL));
|
||||
h += field('p13-iv1-m','$m$, кг','1');
|
||||
} else {
|
||||
h += pickField('p13-iv1-sub','Топливо',selectHTML('p13-iv1-q', Q_MAP, Q_LBL));
|
||||
h += field('p13-iv1-m','$m$, кг','1');
|
||||
}
|
||||
inpsBox.innerHTML = h;
|
||||
renderMath(inpsBox);
|
||||
out.innerHTML = '';
|
||||
fb.style.display = 'none';
|
||||
}
|
||||
function num(id){ const el = document.getElementById(id); return el ? parseFloat((el.value||'').replace(',','.')) : NaN; }
|
||||
function fmtJ(v){ const k = v/1000, M = v/1e6; if(Math.abs(v) >= 1e6) return v.toExponential(2)+' Дж ($\\approx '+M.toFixed(2)+'$ МДж)'; if(Math.abs(v) >= 1000) return v.toFixed(0)+' Дж ($= '+k.toFixed(1)+'$ кДж)'; return v.toFixed(1)+' Дж'; }
|
||||
function calc(){
|
||||
let Q = 0, res = '';
|
||||
const m = num('p13-iv1-m');
|
||||
if(!isFinite(m) || m <= 0){ feedback(fb,false,'✗ Масса должна быть положительной.'); return; }
|
||||
if(mode === 'heat'){
|
||||
const sel = document.getElementById('p13-iv1-c').value;
|
||||
const c = C_MAP[sel];
|
||||
const dT = num('p13-iv1-dt');
|
||||
if(!isFinite(dT)){ feedback(fb,false,'✗ Введи $\\Delta T$.'); return; }
|
||||
Q = c * m * dT;
|
||||
res = '$Q = c\\,m\\,\\Delta T = '+c+' \\cdot '+m+' \\cdot '+dT+' = '+Q.toFixed(0)+'$ Дж';
|
||||
} else if(mode === 'melt'){
|
||||
const sel = document.getElementById('p13-iv1-lam').value;
|
||||
const lam = L_MAP[sel];
|
||||
Q = lam * m;
|
||||
res = '$Q = \\lambda\\,m = '+lam.toExponential(2)+' \\cdot '+m+' = '+Q.toFixed(0)+'$ Дж';
|
||||
} else if(mode === 'evap'){
|
||||
const sel = document.getElementById('p13-iv1-r').value;
|
||||
const r = R_MAP[sel];
|
||||
Q = r * m;
|
||||
res = '$Q = r\\,m = '+r.toExponential(2)+' \\cdot '+m+' = '+Q.toFixed(0)+'$ Дж';
|
||||
} else {
|
||||
const sel = document.getElementById('p13-iv1-q').value;
|
||||
const q = Q_MAP[sel];
|
||||
Q = q * m;
|
||||
res = '$Q = q\\,m = '+q.toExponential(2)+' \\cdot '+m+' = '+Q.toFixed(0)+'$ Дж';
|
||||
}
|
||||
out.innerHTML = '<div style="margin-bottom:8px">'+res+'</div>'
|
||||
+ '<div><b>Ответ:</b> <span style="font-weight:700;color:var(--pri2)">'+fmtJ(Q)+'</span></div>';
|
||||
renderMath(out);
|
||||
feedback(fb, true, '✓ Вычислено.');
|
||||
used.add(mode);
|
||||
if(!_done && used.size === 4){ _done = true; addXp(10,'p13-iv1'); bumpProgress('p13', 15); }
|
||||
}
|
||||
tabs.querySelectorAll('button').forEach(b => {
|
||||
b.addEventListener('click', () => {
|
||||
mode = b.dataset.mode;
|
||||
tabs.querySelectorAll('button').forEach(x => { x.className = 'btn'; });
|
||||
b.className = 'btn primary';
|
||||
build();
|
||||
});
|
||||
});
|
||||
document.getElementById('p13-iv1-go').addEventListener('click', calc);
|
||||
build();
|
||||
})();
|
||||
|
||||
/* IV2 — График нагревания льда */
|
||||
(function(){
|
||||
const svg = document.getElementById('p13-iv2-svg');
|
||||
const mIn = document.getElementById('p13-iv2-m');
|
||||
const mL = document.getElementById('p13-iv2-mL');
|
||||
const info = document.getElementById('p13-iv2-info');
|
||||
const seen = new Set(); let _done = false;
|
||||
const C_ICE = 2100, C_WATER = 4200, LAMBDA = 330000, R_VAP = 2260000;
|
||||
|
||||
function render(){
|
||||
const m = +mIn.value;
|
||||
mL.textContent = m.toFixed(1);
|
||||
// Q-сегменты в Дж
|
||||
const Q1 = C_ICE * m * 20; // -20 → 0
|
||||
const Q2 = LAMBDA * m; // плавление
|
||||
const Q3 = C_WATER * m * 100; // 0 → 100
|
||||
const Q4 = R_VAP * m; // испарение
|
||||
// в кДж для оси X
|
||||
const q1 = Q1/1000, q2 = Q2/1000, q3 = Q3/1000, q4 = Q4/1000;
|
||||
const Qtotal_kJ = q1 + q2 + q3 + q4;
|
||||
// оси: X 0..6000 кДж × Y -20..120 °C
|
||||
const W=420, H=280, pad=44;
|
||||
// расширяем X-предел чтобы Q4 поместилось
|
||||
const xMax = Math.ceil((Qtotal_kJ + 200) / 500) * 500;
|
||||
// axes2D рисует целые тики; используем напрямую координатную сетку
|
||||
// Зайдём в систему: вычислим toX/toY вручную
|
||||
const xmin = 0, xmax = xMax, ymin = -20, ymax = 120;
|
||||
const ux = (W - 2*pad) / (xmax - xmin);
|
||||
const uy = (H - 2*pad) / (ymax - ymin);
|
||||
const toX = v => pad + (v - xmin) * ux;
|
||||
const toY = v => H - pad - (v - ymin) * uy;
|
||||
let g = '';
|
||||
g += '<rect x="'+pad+'" y="'+pad+'" width="'+(W-2*pad)+'" height="'+(H-2*pad)+'" fill="none" stroke="#e5e7eb"/>';
|
||||
// сетка X
|
||||
g += '<g stroke="#e5e7eb" stroke-width="1">';
|
||||
const xStep = xMax / 10;
|
||||
for(let xv = 0; xv <= xMax; xv += xStep){
|
||||
g += '<line x1="'+toX(xv)+'" y1="'+pad+'" x2="'+toX(xv)+'" y2="'+(H-pad)+'"/>';
|
||||
}
|
||||
for(let yv = -20; yv <= 120; yv += 20){
|
||||
g += '<line x1="'+pad+'" y1="'+toY(yv)+'" x2="'+(W-pad)+'" y2="'+toY(yv)+'"/>';
|
||||
}
|
||||
g += '</g>';
|
||||
// оси (Y=0 линия)
|
||||
g += '<line x1="'+pad+'" y1="'+toY(0)+'" x2="'+(W-pad)+'" y2="'+toY(0)+'" stroke="#0f172a" stroke-width="1.5"/>';
|
||||
g += '<line x1="'+pad+'" y1="'+pad+'" x2="'+pad+'" y2="'+(H-pad)+'" stroke="#0f172a" stroke-width="1.5"/>';
|
||||
// подписи осей
|
||||
g += '<text x="'+(W-pad+2)+'" y="'+(H-pad+14)+'" font-size="10" fill="#0f172a">Q, кДж</text>';
|
||||
g += '<text x="'+(pad-26)+'" y="'+(pad-6)+'" font-size="10" fill="#0f172a">T, °C</text>';
|
||||
// тики X
|
||||
g += '<g font-size="9" fill="#64748b">';
|
||||
for(let xv = 0; xv <= xMax; xv += xStep){
|
||||
g += '<text x="'+(toX(xv)-8)+'" y="'+(H-pad+11)+'">'+Math.round(xv)+'</text>';
|
||||
}
|
||||
for(let yv = -20; yv <= 120; yv += 20){
|
||||
g += '<text x="'+(pad-26)+'" y="'+(toY(yv)+3)+'">'+yv+'</text>';
|
||||
}
|
||||
g += '</g>';
|
||||
|
||||
// Сегменты ломаной
|
||||
let xCur = 0;
|
||||
// 1) лёд -20 → 0 (голубой)
|
||||
g += '<line x1="'+toX(xCur)+'" y1="'+toY(-20)+'" x2="'+toX(xCur+q1)+'" y2="'+toY(0)+'" stroke="#0ea5e9" stroke-width="3" stroke-linecap="round"/>';
|
||||
xCur += q1;
|
||||
// 2) плавление 0 → 0 (синий пунктир)
|
||||
g += '<line x1="'+toX(xCur)+'" y1="'+toY(0)+'" x2="'+toX(xCur+q2)+'" y2="'+toY(0)+'" stroke="#2563eb" stroke-width="3" stroke-dasharray="6 4" stroke-linecap="round"/>';
|
||||
xCur += q2;
|
||||
// 3) вода 0 → 100 (оранжевый)
|
||||
g += '<line x1="'+toX(xCur)+'" y1="'+toY(0)+'" x2="'+toX(xCur+q3)+'" y2="'+toY(100)+'" stroke="#ea580c" stroke-width="3" stroke-linecap="round"/>';
|
||||
xCur += q3;
|
||||
// 4) испарение 100 → 100 (красный пунктир)
|
||||
g += '<line x1="'+toX(xCur)+'" y1="'+toY(100)+'" x2="'+toX(xCur+q4)+'" y2="'+toY(100)+'" stroke="#dc2626" stroke-width="3" stroke-dasharray="6 4" stroke-linecap="round"/>';
|
||||
xCur += q4;
|
||||
// точки переходов
|
||||
let xMark = 0;
|
||||
const marks = [
|
||||
{x:xMark, y:-20, color:'#0ea5e9'},
|
||||
{x:(xMark+=q1), y:0, color:'#2563eb'},
|
||||
{x:(xMark+=q2), y:0, color:'#ea580c'},
|
||||
{x:(xMark+=q3), y:100, color:'#dc2626'},
|
||||
{x:(xMark+=q4), y:100, color:'#7c2d12'},
|
||||
];
|
||||
marks.forEach(p => { g += '<circle cx="'+toX(p.x)+'" cy="'+toY(p.y)+'" r="3.5" fill="'+p.color+'"/>'; });
|
||||
|
||||
svg.innerHTML = g;
|
||||
|
||||
const totalMJ = Qtotal_kJ/1000;
|
||||
info.innerHTML = '<div style="margin-bottom:6px"><b>Масса:</b> $m = '+m.toFixed(1)+'$ кг.</div>'
|
||||
+ '<div style="margin-bottom:4px">$Q_1 = c_{льда}\\,m\\,\\Delta T = 2100 \\cdot '+m.toFixed(1)+' \\cdot 20 = '+Q1.toFixed(0)+'$ Дж $\\approx '+q1.toFixed(0)+'$ кДж</div>'
|
||||
+ '<div style="margin-bottom:4px">$Q_2 = \\lambda\\,m = '+LAMBDA+' \\cdot '+m.toFixed(1)+' = '+Q2.toFixed(0)+'$ Дж $\\approx '+q2.toFixed(0)+'$ кДж</div>'
|
||||
+ '<div style="margin-bottom:4px">$Q_3 = c_{воды}\\,m \\cdot 100 = 4200 \\cdot '+m.toFixed(1)+' \\cdot 100 = '+Q3.toFixed(0)+'$ Дж $\\approx '+q3.toFixed(0)+'$ кДж</div>'
|
||||
+ '<div style="margin-bottom:6px">$Q_4 = r\\,m = '+R_VAP+' \\cdot '+m.toFixed(1)+' = '+Q4.toFixed(0)+'$ Дж $\\approx '+q4.toFixed(0)+'$ кДж</div>'
|
||||
+ '<div><b>Итого:</b> $Q_{общ} = Q_1+Q_2+Q_3+Q_4 \\approx '+totalMJ.toFixed(2)+'$ МДж</div>';
|
||||
renderMath(info);
|
||||
|
||||
seen.add(Math.round(m*10));
|
||||
if(!_done && seen.size >= 4){ _done = true; addXp(10,'p13-iv2'); bumpProgress('p13', 15); }
|
||||
}
|
||||
mIn.addEventListener('input', render);
|
||||
render();
|
||||
})();
|
||||
|
||||
/* IV3 — DnD сортер: тип процесса */
|
||||
(function(){
|
||||
const items = [
|
||||
{ id:'b1', cat:'heat', html:'Нагрев кастрюли с водой на плите' },
|
||||
{ id:'b2', cat:'melt', html:'Тает лёд в стакане чая' },
|
||||
{ id:'b3', cat:'evap', html:'Кипит чайник на огне' },
|
||||
{ id:'b4', cat:'burn', html:'Сжигание бензина в двигателе' },
|
||||
{ id:'b5', cat:'heat', html:'Чашка кофе постепенно остывает' },
|
||||
{ id:'b6', cat:'melt', html:'Замерзает вода в формочке' },
|
||||
];
|
||||
const sorter = setupSorter({
|
||||
poolId:'p13-iv3-pool',
|
||||
scopeSelector:'#p13-iv3',
|
||||
items: items,
|
||||
cats:['heat','melt','evap','burn'],
|
||||
columnLayout:false,
|
||||
});
|
||||
document.getElementById('p13-iv3-check').addEventListener('click', () => {
|
||||
const fb = document.getElementById('p13-iv3-fb');
|
||||
const placedCount = items.filter(it => sorter.placed[it.id]).length;
|
||||
const correct = items.filter(it => sorter.placed[it.id] === it.cat).length;
|
||||
if(placedCount < items.length){ feedback(fb, false, '✗ Размести все 6 явлений.'); return; }
|
||||
if(correct === items.length){ feedback(fb, true, '✓ Все 6 верно! +10 XP'); addXp(10,'p13-iv3'); bumpProgress('p13', 15); }
|
||||
else feedback(fb, false, '✗ Правильно ' + correct + ' из 6. Попробуй ещё.');
|
||||
});
|
||||
document.getElementById('p13-iv3-reset').addEventListener('click', () => { sorter.reset(); document.getElementById('p13-iv3-fb').style.display = 'none'; });
|
||||
})();
|
||||
|
||||
/* IV4 — Тренажёр теплоты */
|
||||
(function(){
|
||||
const Q = [
|
||||
{ q:'Нагреть 2 кг воды от 20°C до 80°C. $Q$ в кДж?', ans:504, tol:10, hint:'$Q = c m \\Delta T = 4200 \\cdot 2 \\cdot 60 = 504000$ Дж = 504 кДж' },
|
||||
{ q:'Растопить 0{,}5 кг льда при 0°C. $Q$ в кДж?', ans:165, tol:5, hint:'$Q = \\lambda m = 330000 \\cdot 0{,}5 = 165$ кДж' },
|
||||
{ q:'Испарить 1 кг воды при 100°C. $Q$ в кДж?', ans:2260, tol:50, hint:'$Q = r m = 2{,}26 \\cdot 10^6 \\cdot 1 = 2260$ кДж' },
|
||||
{ q:'Сжечь 0{,}5 кг бензина ($q = 4{,}4 \\cdot 10^7$ Дж/кг). $Q$ в МДж?', ans:22, tol:1, hint:'$Q = q m = 4{,}4 \\cdot 10^7 \\cdot 0{,}5 = 2{,}2 \\cdot 10^7$ Дж = 22 МДж' },
|
||||
{ q:'В калориметр налили 100 г воды при 20°C и опустили 200 г меди при 100°C ($c_{Cu} = 390$). Конечная $T$ в °C?', ans:33, tol:1.5, hint:'$4200 \\cdot 0{,}1 \\cdot (T-20) = 390 \\cdot 0{,}2 \\cdot (100-T)$ → $T \\approx 32{,}5$°C' },
|
||||
{ q:'Нагреть 1 кг алюминия ($c = 920$) от 20°C до 100°C. $Q$ в кДж?', ans:73.6, tol:2, hint:'$Q = 920 \\cdot 1 \\cdot 80 = 73600$ Дж = 73{,}6 кДж' },
|
||||
];
|
||||
let i = 0, score = 0;
|
||||
function show(){
|
||||
if(i >= Q.length){
|
||||
document.getElementById('p13-iv4-q').innerHTML = '<b>Готово!</b> Результат: ' + score + ' / ' + Q.length;
|
||||
if(score === Q.length){ addXp(15, 'p13-iv4'); bumpProgress('p13', 25); }
|
||||
else if(score >= 4){ addXp(8, 'p13-iv4'); bumpProgress('p13', 15); }
|
||||
return;
|
||||
}
|
||||
document.getElementById('p13-iv4-i').textContent = (i+1);
|
||||
document.getElementById('p13-iv4-s').textContent = score;
|
||||
document.getElementById('p13-iv4-q').innerHTML = Q[i].q;
|
||||
document.getElementById('p13-iv4-ans').value = '';
|
||||
renderMath(document.getElementById('p13-iv4-q'));
|
||||
document.getElementById('p13-iv4-fb').style.display = 'none';
|
||||
}
|
||||
function go(){
|
||||
if(i >= Q.length) return;
|
||||
const fb = document.getElementById('p13-iv4-fb');
|
||||
const raw = document.getElementById('p13-iv4-ans').value.replace(',', '.');
|
||||
const ans = parseFloat(raw);
|
||||
if(isNaN(ans)){ feedback(fb, false, '✗ Введи число.'); return; }
|
||||
if(Math.abs(ans - Q[i].ans) <= Q[i].tol + 0.001){ score++; feedback(fb, true, '✓ Верно! '+Q[i].hint+'. Дальше ▶'); }
|
||||
else feedback(fb, false, '✗ Неверно. Ответ: $'+Q[i].ans+'$. '+Q[i].hint+'. Дальше ▶');
|
||||
document.getElementById('p13-iv4-s').textContent = score;
|
||||
i++;
|
||||
setTimeout(show, 1800);
|
||||
}
|
||||
document.getElementById('p13-iv4-go').addEventListener('click', go);
|
||||
document.getElementById('p13-iv4-ans').addEventListener('keydown', e => { if(e.key === 'Enter') go(); });
|
||||
document.getElementById('p13-iv4-start').addEventListener('click', () => { i = 0; score = 0; show(); });
|
||||
show();
|
||||
})();
|
||||
|
||||
wireReadBtn('p13');
|
||||
}
|
||||
|
||||
function build_p14(){
|
||||
const box = document.getElementById('p14-body');
|
||||
let html = '';
|
||||
html += makeCard('theory', "Первый закон термодинамики", "§14", `
|
||||
<p><b>Первый закон термодинамики</b> — этот параграф в разработке (Phase 1+).</p>
|
||||
<p>Здесь появятся: теория, формулы, разобранные примеры и 3–4 интерактива в стиле «алгебры 11» — таблицы, симуляции, ползунки, drag-and-drop и автопроверяемые тренажёры.</p>
|
||||
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.92rem">
|
||||
<b>Phase 0:</b> создан скелет учебника. <b>Phase 2+:</b> наполнение этого § содержанием по учебнику «Физика 10» (Беларусь, 2019).
|
||||
</p>
|
||||
|
||||
/* THEORY 1 — Формулировка первого закона ТД */
|
||||
html += makeCard('theory', "Формулировка первого закона термодинамики", "§14", `
|
||||
<p><b>Первый закон термодинамики</b> — закон сохранения энергии для термодинамической системы:</p>
|
||||
<p style="text-align:center;margin:10px 0">$$\\Delta U = Q + A_{внеш}$$</p>
|
||||
<ul style="margin:6px 0 8px 22px;line-height:1.75">
|
||||
<li>$\\Delta U$ — изменение внутренней энергии системы;</li>
|
||||
<li>$Q$ — количество теплоты, переданное системе ($Q > 0$, если получено);</li>
|
||||
<li>$A_{внеш}$ — работа внешних сил над системой.</li>
|
||||
</ul>
|
||||
<p>Через работу газа (учитывая $A_{внеш} = -A_{газ}$):</p>
|
||||
<p style="text-align:center;margin:10px 0">$$Q = \\Delta U + A_{газ}$$</p>
|
||||
<p style="padding:10px 14px;background:var(--warn-bg,#fef3c7);border-left:4px solid var(--warn,#f59e0b);border-radius:9px"><b>Словами:</b> теплота, полученная газом, расходуется на изменение его внутренней энергии и на совершение работы газом.</p>
|
||||
<p>Правила знаков:</p>
|
||||
<table style="width:100%;border-collapse:collapse;margin:10px 0;font-size:.92rem">
|
||||
<thead><tr style="background:var(--sec-acc-soft)"><th style="padding:8px;border:1px solid var(--border);text-align:left">Величина</th><th style="padding:8px;border:1px solid var(--border)">$> 0$</th><th style="padding:8px;border:1px solid var(--border)">$< 0$</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td style="padding:8px;border:1px solid var(--border)"><b>$Q$</b></td><td style="padding:8px;border:1px solid var(--border);text-align:center">газ получает</td><td style="padding:8px;border:1px solid var(--border);text-align:center">газ отдаёт</td></tr>
|
||||
<tr><td style="padding:8px;border:1px solid var(--border)"><b>$A_{газ}$</b></td><td style="padding:8px;border:1px solid var(--border);text-align:center">расширение</td><td style="padding:8px;border:1px solid var(--border);text-align:center">сжатие</td></tr>
|
||||
<tr><td style="padding:8px;border:1px solid var(--border)"><b>$\\Delta U$</b></td><td style="padding:8px;border:1px solid var(--border);text-align:center">$T$ растёт</td><td style="padding:8px;border:1px solid var(--border);text-align:center">$T$ падает</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
`);
|
||||
|
||||
/* THEORY 2 — Применение к изопроцессам */
|
||||
html += makeCard('rule', "Применение к изопроцессам", "§14", `
|
||||
<p>Первый закон $Q = \\Delta U + A_{газ}$ принимает простой вид для каждого изопроцесса.</p>
|
||||
<p style="margin-top:8px"><b>1) Изотермический</b> ($T = \\text{const}$, для идеального газа $\\Delta U = 0$):</p>
|
||||
<p style="text-align:center;margin:8px 0">$$Q = A_{газ}$$</p>
|
||||
<p>Вся подведённая теплота превращается в работу газа.</p>
|
||||
<p style="margin-top:8px"><b>2) Изохорный</b> ($V = \\text{const}$, $A_{газ} = 0$):</p>
|
||||
<p style="text-align:center;margin:8px 0">$$Q = \\Delta U = \\dfrac{3}{2}\\,\\nu R\\,\\Delta T$$</p>
|
||||
<p>Вся теплота идёт на увеличение внутренней энергии.</p>
|
||||
<p style="margin-top:8px"><b>3) Изобарный</b> ($p = \\text{const}$):</p>
|
||||
<p style="text-align:center;margin:8px 0">$$Q = \\Delta U + p\\,\\Delta V$$</p>
|
||||
<p>Часть теплоты — на $\\Delta U$, часть — на работу.</p>
|
||||
<p style="margin-top:8px"><b>4) Адиабатный</b> ($Q = 0$, нет теплообмена):</p>
|
||||
<p style="text-align:center;margin:8px 0">$$\\Delta U = -A_{газ}$$</p>
|
||||
<p>Работа совершается за счёт внутренней энергии: расширение → охлаждение, сжатие → нагрев.</p>
|
||||
`);
|
||||
|
||||
/* THEORY 3 — Адиабатный процесс и примеры */
|
||||
html += makeCard('example', "Адиабатный процесс и примеры", "§14", `
|
||||
<p><b>Адиабатный процесс</b> — без теплообмена ($Q = 0$). Реализуется:</p>
|
||||
<ul style="margin:6px 0 8px 22px;line-height:1.75">
|
||||
<li>в теплоизолированных сосудах;</li>
|
||||
<li>при <b>быстрых</b> процессах — теплообмен не успевает произойти.</li>
|
||||
</ul>
|
||||
<p><b>Примеры:</b></p>
|
||||
<ul style="margin:6px 0 8px 22px;line-height:1.75">
|
||||
<li><b>Дизельный двигатель.</b> Быстрое сжатие воздуха разогревает его до $\\sim 700°$C — этого достаточно для самовоспламенения солярки (без свечи зажигания).</li>
|
||||
<li><b>Образование облаков.</b> Тёплый влажный воздух поднимается, адиабатно расширяется, охлаждается — водяной пар конденсируется в капли.</li>
|
||||
<li><b>Холодильник.</b> Рабочее тело расширяется через дроссель — охлаждается; затем сжимается компрессором — нагревается.</li>
|
||||
<li><b>Велонасос.</b> При быстром сжатии воздух заметно нагревается — это адиабатный процесс.</li>
|
||||
</ul>
|
||||
<p style="padding:10px 14px;background:var(--warn-bg,#fef3c7);border-left:4px solid var(--warn,#f59e0b);border-radius:9px"><b>Уравнение Пуассона</b> для адиабаты: $pV^{\\gamma} = \\text{const}$, где $\\gamma = c_p/c_v$ — показатель адиабаты. Для одноатомного газа $\\gamma = 5/3$, для двухатомного $\\gamma = 7/5$.</p>
|
||||
`);
|
||||
|
||||
/* INTERACTIVE 1 — Первый закон в действии (бар-чарт по 4 процессам) */
|
||||
html += `<div class="wg" id="p14-iv1">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Первый закон в действии</div></div>
|
||||
<div class="wg-help">Выбери процесс и сдвигай параметр — смотри бар-чарт $Q$, $\\Delta U$, $A_{газ}$.</div>
|
||||
<div style="display:flex;gap:14px;flex-wrap:wrap;justify-content:center;margin-bottom:10px">
|
||||
<label style="display:inline-flex;align-items:center;gap:6px;font-size:.92rem"><input type="radio" name="p14-iv1-proc" value="iso" checked> <span style="color:#ea580c;font-weight:700">Изотермический</span></label>
|
||||
<label style="display:inline-flex;align-items:center;gap:6px;font-size:.92rem"><input type="radio" name="p14-iv1-proc" value="hor"> <span style="color:#10b981;font-weight:700">Изохорный</span></label>
|
||||
<label style="display:inline-flex;align-items:center;gap:6px;font-size:.92rem"><input type="radio" name="p14-iv1-proc" value="bar"> <span style="color:#2563eb;font-weight:700">Изобарный</span></label>
|
||||
<label style="display:inline-flex;align-items:center;gap:6px;font-size:.92rem"><input type="radio" name="p14-iv1-proc" value="adi"> <span style="color:#7c3aed;font-weight:700">Адиабатный</span></label>
|
||||
</div>
|
||||
<div class="sliders" id="p14-iv1-sliders"></div>
|
||||
<div style="background:var(--card);border:1px solid var(--border);border-radius:9px;padding:8px">
|
||||
<svg id="p14-iv1-svg" viewBox="0 0 420 240" width="100%" style="height:auto"></svg>
|
||||
</div>
|
||||
<div id="p14-iv1-info" style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.92rem;line-height:1.85"></div>
|
||||
</div>`;
|
||||
|
||||
/* INTERACTIVE 2 — Калькулятор первого закона */
|
||||
html += `<div class="wg" id="p14-iv2">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Калькулятор первого закона</div></div>
|
||||
<div class="wg-help">Введи две величины — получи третью по формуле $Q = \\Delta U + A_{газ}$.</div>
|
||||
<div style="display:flex;gap:10px;flex-wrap:wrap;justify-content:center;margin-bottom:10px" id="p14-iv2-tabs">
|
||||
<button class="btn primary" data-find="dU">Найти $\\Delta U$</button>
|
||||
<button class="btn" data-find="Q">Найти $Q$</button>
|
||||
<button class="btn" data-find="A">Найти $A_{газ}$</button>
|
||||
</div>
|
||||
<div id="p14-iv2-inputs" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:10px;margin-bottom:10px"></div>
|
||||
<div class="actions" style="justify-content:center"><button class="btn primary" id="p14-iv2-go">Вычислить</button></div>
|
||||
<div id="p14-iv2-out" style="margin-top:10px;padding:12px 14px;background:var(--card);border-radius:9px;font-size:.94rem;min-height:60px;line-height:1.85"></div>
|
||||
<div class="feedback" id="p14-iv2-fb"></div>
|
||||
</div>`;
|
||||
|
||||
/* INTERACTIVE 3 — Что неизменно? (квикфайр) */
|
||||
html += `<div class="wg" id="p14-iv3">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 3</span><div class="wg-title">Что неизменно в этом процессе?</div></div>
|
||||
<div class="wg-help">6 ситуаций. Выбери постоянную величину.</div>
|
||||
<div class="score-display"><span>Задание <b id="p14-iv3-i">1</b> / 6</span><span>Очки: <b id="p14-iv3-s">0</b> / 6</span></div>
|
||||
<div id="p14-iv3-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.02rem;margin-bottom:10px;text-align:center;min-height:54px"></div>
|
||||
<div style="display:flex;gap:8px;justify-content:center;flex-wrap:wrap">
|
||||
<button class="btn primary" data-ans="T">$T = \\text{const}$</button>
|
||||
<button class="btn primary" data-ans="V">$V = \\text{const}$</button>
|
||||
<button class="btn primary" data-ans="p">$p = \\text{const}$</button>
|
||||
<button class="btn primary" data-ans="Q">$Q = 0$</button>
|
||||
</div>
|
||||
<div class="feedback" id="p14-iv3-fb"></div>
|
||||
</div>`;
|
||||
|
||||
/* INTERACTIVE 4 — Тренажёр первого закона */
|
||||
html += `<div class="wg" id="p14-iv4">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 4</span><div class="wg-title">Тренажёр первого закона</div></div>
|
||||
<div class="wg-help">5 задач. $R = 8{,}3$ Дж/(моль·К). Допуск $\\pm 5\\%$.</div>
|
||||
<div class="score-display"><span>Задача <b id="p14-iv4-i">1</b> / 5</span><span>Очки: <b id="p14-iv4-s">0</b> / 5</span></div>
|
||||
<div id="p14-iv4-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.02rem;margin-bottom:10px;text-align:center;min-height:54px"></div>
|
||||
<div style="display:flex;gap:10px;align-items:center;flex-wrap:wrap;justify-content:center">
|
||||
<span style="font-family:'JetBrains Mono',monospace">ответ =</span>
|
||||
<input type="number" id="p14-iv4-ans" class="tinp" style="width:140px;text-align:center" step="any">
|
||||
<button class="btn primary" id="p14-iv4-go">Проверить</button>
|
||||
<button class="btn" id="p14-iv4-start">Заново</button>
|
||||
</div>
|
||||
<div class="feedback" id="p14-iv4-fb"></div>
|
||||
</div>`;
|
||||
|
||||
html += secNav('p13', 'p15');
|
||||
html += readButton('p14');
|
||||
|
||||
box.innerHTML = html;
|
||||
renderMath(box);
|
||||
|
||||
/* IV1 — Первый закон в действии: бар-чарт */
|
||||
(function(){
|
||||
const R = 8.314;
|
||||
const slBox = document.getElementById('p14-iv1-sliders');
|
||||
const svg = document.getElementById('p14-iv1-svg');
|
||||
const info = document.getElementById('p14-iv1-info');
|
||||
const COL = { iso:'#ea580c', hor:'#10b981', bar:'#2563eb', adi:'#7c3aed' };
|
||||
const seen = new Set(); let _done = false;
|
||||
|
||||
function getMode(){ const r = document.querySelector('input[name="p14-iv1-proc"]:checked'); return r ? r.value : 'iso'; }
|
||||
|
||||
function buildSliders(){
|
||||
const m = getMode();
|
||||
let h = '';
|
||||
if(m === 'iso'){
|
||||
h += '<label>$T$: <b id="p14-iv1-tL">300</b> К <input type="range" id="p14-iv1-t" min="200" max="500" value="300" step="10"></label>';
|
||||
h += '<label>Отношение $V_2/V_1$: <b id="p14-iv1-rL">2.0</b> <input type="range" id="p14-iv1-r" min="0.5" max="4" value="2.0" step="0.1"></label>';
|
||||
} else if(m === 'hor'){
|
||||
h += '<label>$\\Delta T$: <b id="p14-iv1-dtL">+50</b> К <input type="range" id="p14-iv1-dt" min="-100" max="200" value="50" step="10"></label>';
|
||||
} else if(m === 'bar'){
|
||||
h += '<label>$\\Delta T$: <b id="p14-iv1-dtL">+50</b> К <input type="range" id="p14-iv1-dt" min="-100" max="200" value="50" step="10"></label>';
|
||||
} else {
|
||||
h += '<label>$A_{газ}$: <b id="p14-iv1-aL">+400</b> Дж <input type="range" id="p14-iv1-a" min="-800" max="800" value="400" step="20"></label>';
|
||||
}
|
||||
slBox.innerHTML = h;
|
||||
renderMath(slBox);
|
||||
slBox.querySelectorAll('input[type=range]').forEach(i => i.addEventListener('input', render));
|
||||
}
|
||||
|
||||
function drawBars(Q, dU, A, mode){
|
||||
const W=420, H=240, pad=44;
|
||||
const innerW = W - 2*pad, innerH = H - 2*pad;
|
||||
const maxAbs = Math.max(Math.abs(Q), Math.abs(dU), Math.abs(A), 100);
|
||||
const ySc = innerH / (2 * maxAbs * 1.15);
|
||||
const y0 = H/2; // ось 0
|
||||
const barW = innerW / 4;
|
||||
const labels = ['Q', 'ΔU', 'A_{газ}'];
|
||||
const vals = [Q, dU, A];
|
||||
const cols = [COL[mode], '#0ea5e9', '#f59e0b'];
|
||||
let g = '';
|
||||
// фон
|
||||
g += '<rect x="'+pad+'" y="'+pad+'" width="'+innerW+'" height="'+innerH+'" fill="#fafbfc" stroke="#e5e7eb"/>';
|
||||
// ось 0
|
||||
g += '<line x1="'+pad+'" y1="'+y0+'" x2="'+(W-pad)+'" y2="'+y0+'" stroke="#0f172a" stroke-width="1.5"/>';
|
||||
g += '<text x="'+(pad-30)+'" y="'+(y0+4)+'" font-size="10" fill="#0f172a">0</text>';
|
||||
// подсказки уровней
|
||||
for(const lv of [-maxAbs, -maxAbs/2, maxAbs/2, maxAbs]){
|
||||
const y = y0 - lv * ySc;
|
||||
if(y > pad && y < H - pad){
|
||||
g += '<line x1="'+pad+'" y1="'+y+'" x2="'+(W-pad)+'" y2="'+y+'" stroke="#e5e7eb" stroke-dasharray="3 3"/>';
|
||||
g += '<text x="'+(pad-36)+'" y="'+(y+3)+'" font-size="9" fill="#64748b">'+lv.toFixed(0)+'</text>';
|
||||
}
|
||||
}
|
||||
// бары
|
||||
vals.forEach((v, i) => {
|
||||
const cx = pad + innerW * (i+0.5) / 3;
|
||||
const bx = cx - barW/2;
|
||||
const h = Math.abs(v) * ySc;
|
||||
const by = v >= 0 ? y0 - h : y0;
|
||||
g += '<rect x="'+bx+'" y="'+by+'" width="'+barW+'" height="'+h+'" fill="'+cols[i]+'" opacity="0.85" stroke="'+cols[i]+'" stroke-width="2"/>';
|
||||
g += '<text x="'+cx+'" y="'+(H-pad+18)+'" font-size="12" font-weight="700" text-anchor="middle" fill="#0f172a">'+labels[i]+'</text>';
|
||||
const labY = v >= 0 ? by - 6 : by + h + 14;
|
||||
g += '<text x="'+cx+'" y="'+labY+'" font-size="11" font-weight="700" text-anchor="middle" fill="'+cols[i]+'">'+v.toFixed(0)+' Дж</text>';
|
||||
});
|
||||
svg.innerHTML = g;
|
||||
}
|
||||
|
||||
function render(){
|
||||
const m = getMode();
|
||||
let Q = 0, dU = 0, A = 0, descr = '', formula = '';
|
||||
const NU = 1;
|
||||
if(m === 'iso'){
|
||||
const T = +document.getElementById('p14-iv1-t').value;
|
||||
const r = +document.getElementById('p14-iv1-r').value;
|
||||
document.getElementById('p14-iv1-tL').textContent = T;
|
||||
document.getElementById('p14-iv1-rL').textContent = r.toFixed(1);
|
||||
dU = 0;
|
||||
A = NU * R * T * Math.log(r);
|
||||
Q = A;
|
||||
descr = 'Изотермический процесс: $T = \\text{const}$, $\\Delta U = 0$.';
|
||||
formula = '$Q = A_{газ} = \\nu RT\\ln(V_2/V_1) = '+A.toFixed(0)+'$ Дж';
|
||||
} else if(m === 'hor'){
|
||||
const dT = +document.getElementById('p14-iv1-dt').value;
|
||||
document.getElementById('p14-iv1-dtL').textContent = (dT >= 0 ? '+' : '') + dT;
|
||||
A = 0;
|
||||
dU = 1.5 * NU * R * dT;
|
||||
Q = dU;
|
||||
descr = 'Изохорный процесс: $V = \\text{const}$, $A_{газ} = 0$.';
|
||||
formula = '$Q = \\Delta U = \\tfrac{3}{2}\\nu R \\Delta T = '+dU.toFixed(0)+'$ Дж';
|
||||
} else if(m === 'bar'){
|
||||
const dT = +document.getElementById('p14-iv1-dt').value;
|
||||
document.getElementById('p14-iv1-dtL').textContent = (dT >= 0 ? '+' : '') + dT;
|
||||
dU = 1.5 * NU * R * dT;
|
||||
A = NU * R * dT; // p ΔV = νR ΔT
|
||||
Q = dU + A;
|
||||
descr = 'Изобарный процесс: $p = \\text{const}$. Часть теплоты — на $\\Delta U$, часть — на работу.';
|
||||
formula = '$Q = \\Delta U + p\\Delta V = '+dU.toFixed(0)+' + '+A.toFixed(0)+' = '+Q.toFixed(0)+'$ Дж';
|
||||
} else {
|
||||
const av = +document.getElementById('p14-iv1-a').value;
|
||||
document.getElementById('p14-iv1-aL').textContent = (av >= 0 ? '+' : '') + av;
|
||||
Q = 0;
|
||||
A = av;
|
||||
dU = -A;
|
||||
descr = 'Адиабатный процесс: $Q = 0$, $\\Delta U = -A_{газ}$.';
|
||||
formula = '$\\Delta U = -A_{газ} = '+dU.toFixed(0)+'$ Дж'+(A > 0 ? ' (расширение → охлаждение)' : (A < 0 ? ' (сжатие → нагрев)' : ''));
|
||||
}
|
||||
drawBars(Q, dU, A, m);
|
||||
info.innerHTML = '<div style="margin-bottom:6px">'+descr+'</div>'
|
||||
+ '<div style="margin-bottom:6px">'+formula+'</div>'
|
||||
+ '<div><b>Проверка $Q = \\Delta U + A_{газ}$:</b> '+Q.toFixed(0)+' = '+dU.toFixed(0)+' + '+A.toFixed(0)+' ✓</div>';
|
||||
renderMath(info);
|
||||
seen.add(m);
|
||||
if(!_done && seen.size === 4){ _done = true; addXp(10,'p14-iv1'); bumpProgress('p14', 15); }
|
||||
}
|
||||
document.querySelectorAll('input[name="p14-iv1-proc"]').forEach(r => r.addEventListener('change', () => { buildSliders(); render(); }));
|
||||
buildSliders();
|
||||
render();
|
||||
})();
|
||||
|
||||
/* IV2 — Калькулятор первого закона */
|
||||
(function(){
|
||||
const tabs = document.getElementById('p14-iv2-tabs');
|
||||
const inpsBox = document.getElementById('p14-iv2-inputs');
|
||||
const out = document.getElementById('p14-iv2-out');
|
||||
const fb = document.getElementById('p14-iv2-fb');
|
||||
const used = new Set(); let _done = false;
|
||||
let mode = 'dU';
|
||||
|
||||
function field(id, label, val){
|
||||
return '<label style="display:block;font-size:.9rem;color:var(--muted);background:var(--card);padding:8px 12px;border-radius:8px;border:1px solid var(--border)">'+label+' <input type="number" id="'+id+'" class="tinp" style="width:100%;margin-top:6px" value="'+val+'" step="any"></label>';
|
||||
}
|
||||
function build(){
|
||||
let h = '';
|
||||
if(mode === 'dU'){
|
||||
h += field('p14-iv2-Q','$Q$, Дж','500');
|
||||
h += field('p14-iv2-A','$A_{газ}$, Дж','300');
|
||||
} else if(mode === 'Q'){
|
||||
h += field('p14-iv2-dU','$\\Delta U$, Дж','400');
|
||||
h += field('p14-iv2-A','$A_{газ}$, Дж','300');
|
||||
} else {
|
||||
h += field('p14-iv2-Q','$Q$, Дж','500');
|
||||
h += field('p14-iv2-dU','$\\Delta U$, Дж','200');
|
||||
}
|
||||
inpsBox.innerHTML = h;
|
||||
renderMath(inpsBox);
|
||||
out.innerHTML = '';
|
||||
fb.style.display = 'none';
|
||||
}
|
||||
function num(id){ const el = document.getElementById(id); return el ? parseFloat((el.value||'').replace(',','.')) : NaN; }
|
||||
function calc(){
|
||||
let res = '', val = 0;
|
||||
if(mode === 'dU'){
|
||||
const Q = num('p14-iv2-Q'), A = num('p14-iv2-A');
|
||||
if(![Q,A].every(isFinite)){ feedback(fb,false,'✗ Введи оба числа.'); return; }
|
||||
val = Q - A;
|
||||
res = '$\\Delta U = Q - A_{газ} = '+Q+' - ('+A+') = '+val.toFixed(0)+'$ Дж';
|
||||
} else if(mode === 'Q'){
|
||||
const dU = num('p14-iv2-dU'), A = num('p14-iv2-A');
|
||||
if(![dU,A].every(isFinite)){ feedback(fb,false,'✗ Введи оба числа.'); return; }
|
||||
val = dU + A;
|
||||
res = '$Q = \\Delta U + A_{газ} = '+dU+' + ('+A+') = '+val.toFixed(0)+'$ Дж';
|
||||
} else {
|
||||
const Q = num('p14-iv2-Q'), dU = num('p14-iv2-dU');
|
||||
if(![Q,dU].every(isFinite)){ feedback(fb,false,'✗ Введи оба числа.'); return; }
|
||||
val = Q - dU;
|
||||
res = '$A_{газ} = Q - \\Delta U = '+Q+' - ('+dU+') = '+val.toFixed(0)+'$ Дж';
|
||||
}
|
||||
const labels = { dU:'\\Delta U', Q:'Q', A:'A_{газ}' };
|
||||
out.innerHTML = '<div style="margin-bottom:8px">'+res+'</div>'
|
||||
+ '<div><b>Ответ:</b> <span style="font-weight:700;color:var(--pri2)">$'+labels[mode]+' = '+val.toFixed(0)+'$ Дж</span></div>';
|
||||
renderMath(out);
|
||||
feedback(fb, true, '✓ Вычислено.');
|
||||
used.add(mode);
|
||||
if(!_done && used.size === 3){ _done = true; addXp(10,'p14-iv2'); bumpProgress('p14', 15); }
|
||||
}
|
||||
tabs.querySelectorAll('button').forEach(b => {
|
||||
b.addEventListener('click', () => {
|
||||
mode = b.dataset.find;
|
||||
tabs.querySelectorAll('button').forEach(x => { x.className = 'btn'; });
|
||||
b.className = 'btn primary';
|
||||
build();
|
||||
});
|
||||
});
|
||||
document.getElementById('p14-iv2-go').addEventListener('click', calc);
|
||||
build();
|
||||
})();
|
||||
|
||||
/* IV3 — Что неизменно? */
|
||||
(function(){
|
||||
const Q = [
|
||||
{ q:'Изотермический процесс — что постоянно?', ans:'T' },
|
||||
{ q:'Изохорный процесс — что постоянно?', ans:'V' },
|
||||
{ q:'Изобарный процесс — что постоянно?', ans:'p' },
|
||||
{ q:'Адиабатный процесс — какая величина равна нулю?', ans:'Q' },
|
||||
{ q:'Вода кипит при $T = 100°$C — какой параметр постоянен?', ans:'T' },
|
||||
{ q:'Газ в герметичном баллоне греют. Что неизменно?', ans:'V' },
|
||||
];
|
||||
let i = 0, score = 0; let _done = false;
|
||||
const box = document.getElementById('p14-iv3');
|
||||
function show(){
|
||||
const qEl = document.getElementById('p14-iv3-q');
|
||||
const fb = document.getElementById('p14-iv3-fb');
|
||||
if(i >= Q.length){
|
||||
qEl.innerHTML = '<b>Готово!</b> Результат: ' + score + ' / ' + Q.length;
|
||||
renderMath(qEl);
|
||||
if(!_done){
|
||||
_done = true;
|
||||
if(score === Q.length){ addXp(15,'p14-iv3'); bumpProgress('p14', 25); }
|
||||
else if(score >= 4){ addXp(8,'p14-iv3'); bumpProgress('p14', 15); }
|
||||
}
|
||||
return;
|
||||
}
|
||||
document.getElementById('p14-iv3-i').textContent = (i+1);
|
||||
document.getElementById('p14-iv3-s').textContent = score;
|
||||
qEl.innerHTML = Q[i].q;
|
||||
renderMath(qEl);
|
||||
fb.style.display = 'none';
|
||||
}
|
||||
box.querySelectorAll('button[data-ans]').forEach(b => {
|
||||
b.addEventListener('click', () => {
|
||||
if(i >= Q.length) return;
|
||||
const fb = document.getElementById('p14-iv3-fb');
|
||||
const ans = b.dataset.ans;
|
||||
if(ans === Q[i].ans){ score++; feedback(fb, true, '✓ Верно! Дальше ▶'); }
|
||||
else {
|
||||
const labels = {T:'$T = \\text{const}$', V:'$V = \\text{const}$', p:'$p = \\text{const}$', Q:'$Q = 0$'};
|
||||
feedback(fb, false, '✗ Неверно. Правильно: '+labels[Q[i].ans]+'. Дальше ▶');
|
||||
}
|
||||
document.getElementById('p14-iv3-s').textContent = score;
|
||||
i++;
|
||||
setTimeout(show, 1500);
|
||||
});
|
||||
});
|
||||
show();
|
||||
})();
|
||||
|
||||
/* IV4 — Тренажёр первого закона */
|
||||
(function(){
|
||||
const Q = [
|
||||
{ q:'Газ получил $Q = 500$ Дж тепла и совершил работу $A_{газ} = 300$ Дж. Найди $\\Delta U$ в Дж.', ans:200, tol:5, hint:'$\\Delta U = Q - A = 500 - 300 = 200$' },
|
||||
{ q:'Изохорно нагрели 1 моль газа на $\\Delta T = 50$ К. $\\Delta U$ в Дж?', ans:622, tol:30, hint:'$\\Delta U = \\tfrac{3}{2}\\nu R\\Delta T = 1{,}5 \\cdot 1 \\cdot 8{,}3 \\cdot 50 \\approx 622$' },
|
||||
{ q:'Изотермически 1 моль газа при $T = 300$ К расширили вдвое ($V_2 = 2V_1$). $Q$ в Дж?', ans:1726, tol:50, hint:'$Q = A = \\nu RT\\ln 2 = 8{,}3 \\cdot 300 \\cdot 0{,}693 \\approx 1726$' },
|
||||
{ q:'В адиабатном процессе газ совершил $A_{газ} = 400$ Дж. $\\Delta U$ в Дж (со знаком)?', ans:-400, tol:5, hint:'$Q = 0 \\Rightarrow \\Delta U = -A = -400$' },
|
||||
{ q:'Газ изобарно расширился, при этом $\\Delta U = 600$ Дж, $A_{газ} = 400$ Дж. $Q$ в Дж?', ans:1000, tol:20, hint:'$Q = \\Delta U + A = 600 + 400 = 1000$' },
|
||||
];
|
||||
let i = 0, score = 0;
|
||||
function show(){
|
||||
if(i >= Q.length){
|
||||
document.getElementById('p14-iv4-q').innerHTML = '<b>Готово!</b> Результат: ' + score + ' / ' + Q.length;
|
||||
if(score === Q.length){ addXp(15, 'p14-iv4'); bumpProgress('p14', 25); }
|
||||
else if(score >= 3){ addXp(8, 'p14-iv4'); bumpProgress('p14', 15); }
|
||||
return;
|
||||
}
|
||||
document.getElementById('p14-iv4-i').textContent = (i+1);
|
||||
document.getElementById('p14-iv4-s').textContent = score;
|
||||
document.getElementById('p14-iv4-q').innerHTML = Q[i].q;
|
||||
document.getElementById('p14-iv4-ans').value = '';
|
||||
renderMath(document.getElementById('p14-iv4-q'));
|
||||
document.getElementById('p14-iv4-fb').style.display = 'none';
|
||||
}
|
||||
function go(){
|
||||
if(i >= Q.length) return;
|
||||
const fb = document.getElementById('p14-iv4-fb');
|
||||
const raw = document.getElementById('p14-iv4-ans').value.replace(',', '.');
|
||||
const ans = parseFloat(raw);
|
||||
if(isNaN(ans)){ feedback(fb, false, '✗ Введи число.'); return; }
|
||||
if(Math.abs(ans - Q[i].ans) <= Q[i].tol + 0.001){ score++; feedback(fb, true, '✓ Верно! '+Q[i].hint+'. Дальше ▶'); }
|
||||
else feedback(fb, false, '✗ Неверно. Ответ: $'+Q[i].ans+'$. '+Q[i].hint+'. Дальше ▶');
|
||||
document.getElementById('p14-iv4-s').textContent = score;
|
||||
i++;
|
||||
setTimeout(show, 1800);
|
||||
}
|
||||
document.getElementById('p14-iv4-go').addEventListener('click', go);
|
||||
document.getElementById('p14-iv4-ans').addEventListener('keydown', e => { if(e.key === 'Enter') go(); });
|
||||
document.getElementById('p14-iv4-start').addEventListener('click', () => { i = 0; score = 0; show(); });
|
||||
show();
|
||||
})();
|
||||
|
||||
wireReadBtn('p14');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user