Files
Learn_System/frontend/js/phys7_ch5_widgets.js
T
Maxim Dolgolyov f471463911 feat(phys7 ch5): Phase 6 — Работа/Мощность/Энергия §§36-42 + финал «Энергетик»
Глава 5 «Работа. Мощность. Энергия» закрыта целиком. Файл phys7_ch5_widgets.js
(1275 строк, 8 экспортов: p36..p42 + final5). Палитра emerald.

§36 Механическая работа A=Fs:
- 3 карточки (определение / знак работы +/-/0 / толкаем ящик)
- IV-1 СИМ: SVG-сцена с бруском, стрелками F и s, slider F=0..200/s=0..20
- IV-2 КАЛЬК A=Fs
- IV-3 DnD 6→3 (положит/отрицат/нулевая)
- IV-4 ТРН 5

§37 Полезная и совершённая работа. КПД:
- 3 карточки + таблица КПД устройств (5..95%)
- IV-1 КАЛЬК с warning при η>100% и расчётом потерь
- IV-2 СИМ: наклонная плоскость, slider угла → расчёт КПД с трением
- DnD 6→3 (низкий/средний/высокий КПД) / ТРН 5

§38 Мощность P=A/t:
- 3 карточки + таблица 8 объектов (лампа..атомная станция)
- IV-1 КАЛЬК P=A/t с автоопределением уровня (телефон..МВт)
- IV-2 СИМ: 2 спортсмена с одинаковой A но разным t → определение мощнейшего
- DnD 6→3 / ТРН 5

§39 Кинетическая энергия Eк=mv²/2:
- 3 карточки (формула / квадратичная зависимость / автомобиль)
- IV-1 КАЛЬК с автосравнением (мяч..грузовик)
- IV-2 СИМ: интерактивный график Eк(v) с парабалой и красной точкой
- DnD 6→3 (Дж/кДж/сотни кДж) / ТРН 5

§40 Потенциальная энергия (введение):
- 3 карточки (запас работы / гравит и упругая / ГЭС-пружина-лук)
- IV-1 СИМ: подъём груза с шкалой высоты и индикатором Eп
- DnD 6→3 (Eк/Eп.грав/Eп.упр) / квиз 4 / ТРН 4

§41 Eп=mgh:
- 3 карточки + IV-1 КАЛЬК с большим диапазоном
- IV-2 СИМ: 2 тела на разных высотах (slider mA/hA/mB/hB) — кто запасает больше
- DnD 6→3 / ТРН 5

§42 ЗАКОН СОХРАНЕНИЯ — ГЛАВНЫЙ ВИЗУАЛ КУРСА:
- 3 карточки (E=Eк+Eп=const / как меняется при движении / свободное падение)
- IV-1 СИМ ГЛАВНЫЙ: тележка скатывается с горки через PHYS.HillSlideSim,
  slider h0/m/friction, кнопки «Запустить/Сброс», 3 цветных progress-bar'а
  для Eк/Eп/Eполн с текущими значениями в реальном времени
- IV-2 СИМ: маятник через PHYS.PendulumSim, slider начального угла,
  Etot сохраняется автоматически
- КВИЗ 4 / ТРН 5

ФИНАЛ ГЛАВЫ 5 (7 боссов + ачивка «Энергетик» +50 XP):
1. A=Fs (960 Дж)
2. КПД 80%
3. P=A/t (300 Вт)
4. Eк (25 Дж)
5. Eп=mgh (240 Дж)
6. Закон сохранения: v=√(2gh) при падении (20 м/с)
7. Энергетик: потери на трение на горке (8 Дж)

Parse OK, smoke (8 экспортов) OK.
2026-05-30 11:47:06 +03:00

1276 lines
96 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Физика 7 · Глава 5 «Работа. Мощность. Энергия» · §§36–42 + финал.
// Палитра emerald. Главный визуал курса — §42 (закон сохранения через HillSlideSim/PendulumSim из phys.js).
(function(){
'use strict';
const ACCENT = '#10b981';
const ACCENT_D = '#047857';
const ACCENT_SOFT = '#d1fae5';
function renderMath(root){
if(window.renderMathInElement){
try{
window.renderMathInElement(root, {
delimiters: [{left:'$$',right:'$$',display:true},{left:'$',right:'$',display:false}],
throwOnError: false
});
}catch(e){}
}
}
function makeCard(kind, title, badge, body){
const colorByKind = { theory:ACCENT, rule:'#0284c7', example:'#d97706' };
const labelByKind = { theory:'Теория', rule:'Правило', example:'Пример' };
const c = colorByKind[kind] || ACCENT;
return '<div style="background:#fff;border:1.5px solid ' + ACCENT_SOFT + ';border-left:5px solid ' + c + ';border-radius:11px;padding:14px 16px;margin-bottom:14px;box-shadow:0 2px 8px rgba(0,0,0,.05)">'
+ '<div style="display:flex;align-items:center;gap:10px;margin-bottom:8px;flex-wrap:wrap">'
+ '<span style="background:' + c + ';color:#fff;padding:3px 10px;border-radius:99px;font-size:.7rem;font-weight:800;text-transform:uppercase;letter-spacing:.05em">' + labelByKind[kind] + '</span>'
+ '<span style="font-size:.72rem;font-weight:700;color:#64748b;letter-spacing:.04em">' + (badge||'') + '</span>'
+ '<span style="font-family:Unbounded,sans-serif;font-weight:800;font-size:.96rem;color:#0f172a;flex:1;min-width:0">' + title + '</span>'
+ '</div>'
+ '<div style="font-size:.94rem;line-height:1.6;color:#0f172a">' + body + '</div>'
+ '</div>';
}
function wgWrap(id, badge, title, hint, body){
return '<div id="' + id + '" style="background:#fff;border:1.5px solid ' + ACCENT_SOFT + ';border-radius:12px;padding:14px 16px;margin-bottom:14px;box-shadow:0 2px 8px rgba(0,0,0,.05)">'
+ '<div style="display:flex;align-items:center;gap:10px;margin-bottom:8px;flex-wrap:wrap">'
+ '<span style="background:' + ACCENT + ';color:#fff;padding:3px 10px;border-radius:99px;font-size:.7rem;font-weight:800;letter-spacing:.05em">' + badge + '</span>'
+ '<span style="font-family:Unbounded,sans-serif;font-weight:800;font-size:.92rem;color:#0f172a">' + title + '</span>'
+ '</div>'
+ (hint ? '<div style="font-size:.84rem;color:#64748b;background:' + ACCENT_SOFT + ';border-left:3px solid ' + ACCENT + ';border-radius:6px;padding:8px 12px;margin-bottom:10px;line-height:1.5">' + hint + '</div>' : '')
+ body
+ '</div>';
}
function readButton(pid){
return '<div style="text-align:center;margin-top:18px"><button class="ph7-read-btn" data-pid="' + pid + '" '
+ 'style="background:linear-gradient(135deg,#0284c7,#0c4a6e);color:#fff;border:none;padding:11px 22px;border-radius:11px;font-weight:700;font-size:.92rem;cursor:pointer;font-family:inherit;display:inline-flex;align-items:center;gap:8px;box-shadow:0 4px 14px rgba(2,132,199,.32)">'
+ '<svg viewBox="0 0 24 24" style="width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round"><polyline points="20 6 9 17 4 12"/></svg>'
+ 'Я прочитал § &nbsp;<span style="opacity:.85;font-size:.86rem">+10 XP</span>'
+ '</button></div>';
}
function wireReadBtn(pid){
const btn = document.querySelector('.ph7-read-btn[data-pid="' + pid + '"]');
if(!btn) return;
const KEY = 'physics7_ch5_read_' + pid;
if(localStorage.getItem(KEY) === '1'){
btn.innerHTML = '<svg viewBox="0 0 24 24" style="width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round"><polyline points="20 6 9 17 4 12"/></svg> Прочитано';
btn.disabled = true; btn.style.background = '#94a3b8'; btn.style.cursor = 'default';
return;
}
btn.addEventListener('click', function(){
if(localStorage.getItem(KEY) === '1') return;
localStorage.setItem(KEY, '1');
if(typeof window.bumpProgress === 'function') window.bumpProgress(pid, 30);
if(typeof window.addXp === 'function') window.addXp(10, 'read-' + pid);
btn.innerHTML = '<svg viewBox="0 0 24 24" style="width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round"><polyline points="20 6 9 17 4 12"/></svg> Прочитано';
btn.disabled = true; btn.style.background = '#94a3b8'; btn.style.cursor = 'default';
});
}
function wireDnd(host, items){
const root = document.getElementById(host);
if(!root) return;
const checkBtn = root.querySelector('.dnd-check');
const fb = root.querySelector('.dnd-fb');
let placed = {}, armed = null;
root.querySelectorAll('.dnd-chip').forEach(chip => chip.addEventListener('click', () => {
if(armed === chip){ armed.classList.remove('armed'); armed.style.boxShadow = ''; armed = null; return; }
if(armed){ armed.classList.remove('armed'); armed.style.boxShadow = ''; }
armed = chip;
chip.classList.add('armed');
chip.style.boxShadow = '0 0 0 3px rgba(16,185,129,.3)';
}));
root.querySelectorAll('.drop-box').forEach(box => box.addEventListener('click', () => {
if(!armed) return;
const cat = box.dataset.cat;
const id = armed.dataset.id;
placed[id] = cat;
const clone = armed.cloneNode(true);
clone.classList.remove('armed'); clone.classList.add('placed');
clone.style.background = ACCENT_SOFT; clone.style.borderColor = ACCENT; clone.style.boxShadow = '';
clone.addEventListener('click', e => {
e.stopPropagation();
delete placed[id];
clone.remove();
armed = null;
const orig = root.querySelector('.dnd-chip[data-id="' + id + '"]:not(.placed)');
if(orig) orig.style.display = '';
});
box.querySelector('.drop-items').appendChild(clone);
armed.style.display = 'none';
armed.classList.remove('armed'); armed.style.boxShadow = '';
armed = null;
}));
if(checkBtn) checkBtn.addEventListener('click', () => {
const total = items.length;
let correct = 0;
items.forEach(it => { if(placed[it.id] === it.cat) correct++; });
fb.style.display = 'block';
if(correct === total){
fb.style.background = '#d1fae5'; fb.style.color = '#065f46'; fb.style.borderLeft = '4px solid #10b981';
fb.innerHTML = '&#10003; Идеально! ' + total + '/' + total + '.';
if(typeof window.addXp === 'function') window.addXp(15, 'dnd-' + host);
} else {
fb.style.background = '#fee2e2'; fb.style.color = '#7f1d1d'; fb.style.borderLeft = '4px solid #dc2626';
fb.innerHTML = '&#10007; Правильно: ' + correct + '/' + total + '. Попробуй ещё раз.';
}
});
}
function dndPool(host, items, cats){
const chips = items.map(it => '<button class="dnd-chip" data-id="' + it.id + '" type="button" style="background:#fff;border:1.5px solid ' + ACCENT_SOFT + ';border-radius:10px;padding:7px 13px;cursor:pointer;font-size:.9rem;font-family:inherit;transition:all .15s">' + it.html + '</button>').join('');
const boxes = cats.map(c => '<div class="drop-box" data-cat="' + c.cat + '" style="background:#fff;border:1.5px dashed ' + ACCENT_SOFT + ';border-radius:10px;padding:10px;min-height:80px"><h5 style="font-family:Unbounded,sans-serif;font-size:.76rem;color:' + ACCENT_D + ';margin-bottom:8px;text-transform:uppercase;letter-spacing:.04em">' + c.label + '</h5><div class="drop-items" style="display:flex;flex-wrap:wrap;gap:6px;min-height:32px"></div></div>').join('');
return '<div id="' + host + '" class="dnd-host">'
+ '<div style="font-size:.86rem;color:#475569;margin-bottom:10px">Кликни по карточке, потом по корзине. Чтобы вернуть — кликни в корзине.</div>'
+ '<div style="display:flex;flex-wrap:wrap;gap:8px;margin-bottom:14px;padding:10px;border:1.5px dashed ' + ACCENT_SOFT + ';border-radius:10px;background:#ecfdf5">' + chips + '</div>'
+ '<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:10px;margin-bottom:12px">' + boxes + '</div>'
+ '<div style="display:flex;gap:8px"><button class="dnd-check" type="button" style="background:linear-gradient(135deg,' + ACCENT + ',' + ACCENT_D + ');color:#fff;border:none;padding:9px 18px;border-radius:9px;font-weight:700;font-size:.86rem;cursor:pointer;font-family:inherit">Проверить</button></div>'
+ '<div class="dnd-fb" style="padding:10px 14px;border-radius:9px;font-weight:600;font-size:.88rem;margin-top:8px;display:none;line-height:1.45"></div>'
+ '</div>';
}
function quizQuestion(host, idx, q, opts, correctIdx, explain){
const optsHtml = opts.map((o,i) => '<button class="qz-opt" data-i="' + i + '" type="button" style="background:#fff;border:1.5px solid ' + ACCENT_SOFT + ';border-radius:9px;padding:9px 14px;cursor:pointer;font-size:.92rem;font-family:inherit;text-align:left;width:100%;margin-bottom:6px">' + o + '</button>').join('');
return '<div class="qz-q" data-idx="' + idx + '" style="background:' + ACCENT_SOFT + ';border:1.5px solid ' + ACCENT_SOFT + ';border-radius:10px;padding:12px 14px;margin-bottom:10px">'
+ '<div style="font-weight:700;margin-bottom:8px;font-size:.94rem">' + (idx+1) + '. ' + q + '</div>'
+ '<div class="qz-opts" data-correct="' + correctIdx + '" data-explain="' + (explain||'').replace(/"/g,'&quot;') + '">' + optsHtml + '</div>'
+ '<div class="qz-fb" style="padding:9px 12px;border-radius:8px;font-size:.86rem;margin-top:6px;display:none;line-height:1.45"></div>'
+ '</div>';
}
function wireQuiz(host, onAllCorrect){
const root = document.getElementById(host);
if(!root) return;
const all = root.querySelectorAll('.qz-q');
const done = new Set();
all.forEach(qDiv => {
const opts = qDiv.querySelectorAll('.qz-opt');
const correct = +qDiv.querySelector('.qz-opts').dataset.correct;
const explain = qDiv.querySelector('.qz-opts').dataset.explain;
const fb = qDiv.querySelector('.qz-fb');
opts.forEach(o => o.addEventListener('click', () => {
if(done.has(qDiv)) return;
const i = +o.dataset.i;
opts.forEach(x => x.disabled = true);
if(i === correct){
o.style.background = '#d1fae5'; o.style.borderColor = '#10b981'; o.style.color = '#065f46';
fb.style.display = 'block'; fb.style.background = '#d1fae5'; fb.style.color = '#065f46'; fb.style.borderLeft = '4px solid #10b981';
fb.innerHTML = '&#10003; Верно!' + (explain ? ' ' + explain : '');
done.add(qDiv);
if(done.size === all.length && typeof onAllCorrect === 'function') onAllCorrect();
} else {
o.style.background = '#fee2e2'; o.style.borderColor = '#dc2626'; o.style.color = '#7f1d1d';
opts[correct].style.background = '#d1fae5'; opts[correct].style.borderColor = '#10b981'; opts[correct].style.color = '#065f46';
fb.style.display = 'block'; fb.style.background = '#fee2e2'; fb.style.color = '#7f1d1d'; fb.style.borderLeft = '4px solid #dc2626';
fb.innerHTML = '&#10007; Неверно. Правильно: «' + opts[correct].textContent + '».' + (explain ? ' ' + explain : '');
done.add(qDiv);
}
}));
});
}
/* ========================================================== */
/* §36 — Механическая работа */
/* ========================================================== */
function add_p36(){
const body = document.getElementById('p36-body');
if(!body) return;
let h = '';
h += makeCard('theory', 'Что такое работа', '§ 36.1',
'<b>Механическая работа</b> $A$ совершается силой, когда тело перемещается под её действием.<br><br>'
+ 'Когда направление силы $\\vec F$ совпадает с направлением перемещения $\\vec s$:<br>'
+ '$$A = F \\cdot s$$<br>'
+ '$[A] = $ Дж (джоуль). $1$ Дж $= 1$ Н $\\cdot$ $1$ м.');
h += makeCard('rule', 'Знак работы', '§ 36.2',
'Работа может быть:'
+ '<ul style="padding-left:20px;margin:5px 0">'
+ '<li><b>Положительной</b> ($A > 0$) — сила в направлении движения. Тело набирает энергию.</li>'
+ '<li><b>Отрицательной</b> ($A < 0$) — сила против движения (например, трение). Тело теряет энергию.</li>'
+ '<li><b>Нулевой</b> ($A = 0$) — если $F = 0$, или $s = 0$, или сила перпендикулярна перемещению (например, тяжесть при горизонтальном движении).</li>'
+ '</ul>');
h += makeCard('example', 'Толкаем ящик', '§ 36.3',
'Грузчик толкает ящик с силой $F = 50$ Н по горизонтали на расстояние $s = 4$ м.<br>'
+ '<b>Работа грузчика:</b> $A_F = F \\cdot s = 50 \\cdot 4 = 200$ Дж (положительная).<br>'
+ 'Если есть трение $F_{тр} = 20$ Н, то <b>работа трения:</b> $A_{тр} = -F_{тр} \\cdot s = -80$ Дж (отрицательная — против движения).<br>'
+ 'Работа силы тяжести $A_g = 0$ — сила вертикальна, перемещение горизонтально.');
/* IV-1 СИМ */
h += wgWrap('p36-iv1', 'СИМ', 'Работа силы при движении', 'Меняй силу и путь — увидь работу.',
'<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">'
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Сила $F$, Н: <b id="p36-F" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">50</b><input type="range" id="p36-F-r" min="0" max="200" step="5" value="50" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Путь $s$, м: <b id="p36-s" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">4</b><input type="range" id="p36-s-r" min="0" max="20" step="0.5" value="4" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
+ '</div>'
+ '<svg id="p36-svg" viewBox="0 0 380 130" width="100%" style="max-width:600px;display:block;margin:0 auto;background:#ecfdf5;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>'
+ '<div id="p36-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:10px 14px;margin-top:8px;font-size:.94rem;text-align:center"></div>');
/* IV-2 КАЛЬК */
h += wgWrap('p36-iv2', 'КАЛЬК', 'Калькулятор $A = F s$', '',
'<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">'
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$F$, Н: <b id="p36c-F" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">100</b><input type="range" id="p36c-F-r" min="1" max="1000" step="1" value="100" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$s$, м: <b id="p36c-s" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">5</b><input type="range" id="p36c-s-r" min="0.1" max="100" step="0.1" value="5" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
+ '</div>'
+ '<div style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:12px 14px;font-size:.94rem">$A = Fs = $ <b id="p36c-A" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">500</b> Дж $= $ <b id="p36c-Akj" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">0.5</b> кДж</div>');
/* IV-3 DnD */
h += wgWrap('p36-iv3', 'DnD', 'Знак работы', '',
dndPool('p36-dnd', [
{ id:'a1', cat:'pos', html:'Толкаем тележку вперёд' },
{ id:'a2', cat:'pos', html:'Кран поднимает груз' },
{ id:'a3', cat:'neg', html:'Сила трения при качении мяча' },
{ id:'a4', cat:'neg', html:'Тормозим машину' },
{ id:'a5', cat:'zero', html:'Стол держит книгу (нет перемещения)' },
{ id:'a6', cat:'zero', html:'Сила тяжести при горизонтальной езде' }
], [
{ cat:'pos', label:'$A > 0$' },
{ cat:'neg', label:'$A < 0$' },
{ cat:'zero', label:'$A = 0$' }
]));
/* IV-4 ТРН */
h += wgWrap('p36-iv4', 'ТРН', 'Тренажёр §36', '',
'<div id="p36-tr-host">'
+ quizQuestion('p36-tr', 0, '$F = 200$ Н, $s = 3$ м. Работа?', ['200 Дж','300 Дж','600 Дж','1000 Дж'], 2, '$A = 200 \\cdot 3 = 600$ Дж.')
+ quizQuestion('p36-tr', 1, 'Сила трения $F_{тр} = 15$ Н, перемещение $s = 8$ м. Работа трения?', ['+120 Дж','120 Дж','0','+1200 Дж'], 1, 'Трение против движения, $A_{тр} = -15 \\cdot 8 = -120$ Дж.')
+ quizQuestion('p36-tr', 2, 'Шкафу применили силу $F = 80$ Н, но он не сдвинулся. Работа?', ['80 Дж','40 Дж','0','Зависит от времени'], 2, 'Если $s = 0$, то $A = F \\cdot 0 = 0$.')
+ quizQuestion('p36-tr', 3, 'Поднимаем груз $m = 5$ кг на $h = 2$ м (g=10). Какова минимальная работа?', ['10 Дж','50 Дж','100 Дж','500 Дж'], 2, '$A = mg h = 50 \\cdot 2 = 100$ Дж.')
+ quizQuestion('p36-tr', 4, '$1$ кДж $= ?$ Дж', ['10','100','1 000','10 000'], 2)
+ '</div>');
h += readButton('p36');
body.innerHTML = h;
function draw36(){
const F = +document.getElementById('p36-F-r').value;
const s = +document.getElementById('p36-s-r').value;
document.getElementById('p36-F').textContent = F;
document.getElementById('p36-s').textContent = s;
const A = F * s;
const W = 380, H = 130, baseY = 100;
let svg = '';
svg += '<rect x="0" y="' + baseY + '" width="' + W + '" height="20" fill="#94a3b8"/>';
for(let i = 0; i < 18; i++) svg += '<line x1="' + (i*22+5) + '" y1="' + baseY + '" x2="' + (i*22+15) + '" y2="' + (baseY+8) + '" stroke="#374151" stroke-width="0.6"/>';
const bx = 30, bw = 50;
svg += '<rect x="' + bx + '" y="' + (baseY-30) + '" width="' + bw + '" height="30" fill="' + ACCENT + '" stroke="' + ACCENT_D + '" stroke-width="1.5" rx="3"/>';
// Стрелка пути
const sPx = Math.min(280, s * 14);
svg += '<line x1="' + (bx + bw + 5) + '" y1="' + (baseY - 15) + '" x2="' + (bx + bw + 5 + sPx) + '" y2="' + (baseY - 15) + '" stroke="#0c4a6e" stroke-width="1.5" stroke-dasharray="3 2"/>';
svg += '<polygon points="' + (bx + bw + 5 + sPx) + ',' + (baseY - 15) + ' ' + (bx + bw + 5 + sPx - 7) + ',' + (baseY - 19) + ' ' + (bx + bw + 5 + sPx - 7) + ',' + (baseY - 11) + '" fill="#0c4a6e"/>';
svg += '<text x="' + (bx + bw + 5 + sPx/2) + '" y="' + (baseY - 22) + '" text-anchor="middle" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="#0c4a6e">s = ' + s + ' м</text>';
// Стрелка силы F
const fLen = Math.min(60, F * 0.5);
if(fLen > 2){
svg += '<line x1="' + (bx - 10) + '" y1="' + (baseY - 15) + '" x2="' + (bx - 10 - fLen) + '" y2="' + (baseY - 15) + '" stroke="' + ACCENT_D + '" stroke-width="3"/>';
svg += '<polygon points="' + (bx - 10 - fLen) + ',' + (baseY - 15) + ' ' + (bx - 10 - fLen + 8) + ',' + (baseY - 20) + ' ' + (bx - 10 - fLen + 8) + ',' + (baseY - 10) + '" fill="' + ACCENT_D + '"/>';
}
// Подпись F направо
svg += '<text x="20" y="30" font-family="Inter,sans-serif" font-size="12" font-weight="700" fill="' + ACCENT_D + '">F = ' + F + ' Н →</text>';
svg += '<text x="' + (W - 10) + '" y="30" text-anchor="end" font-family="Inter,sans-serif" font-size="14" font-weight="800" fill="' + ACCENT_D + '">A = ' + A + ' Дж</text>';
document.getElementById('p36-svg').innerHTML = svg;
document.getElementById('p36-info').innerHTML = '$A = F \\cdot s = ' + F + ' \\cdot ' + s + ' = $ <b>' + A + '</b> Дж';
renderMath(document.getElementById('p36-info'));
}
['p36-F-r','p36-s-r'].forEach(id => document.getElementById(id).addEventListener('input', draw36));
draw36();
const upd36c = () => {
const F = +document.getElementById('p36c-F-r').value;
const s = +document.getElementById('p36c-s-r').value;
document.getElementById('p36c-F').textContent = F;
document.getElementById('p36c-s').textContent = s.toFixed(1);
const A = F * s;
document.getElementById('p36c-A').textContent = A.toFixed(0);
document.getElementById('p36c-Akj').textContent = (A / 1000).toFixed(2);
};
['p36c-F-r','p36c-s-r'].forEach(id => document.getElementById(id).addEventListener('input', upd36c));
upd36c();
wireDnd('p36-dnd', [
{ id:'a1', cat:'pos' },{ id:'a2', cat:'pos' },{ id:'a3', cat:'neg' },
{ id:'a4', cat:'neg' },{ id:'a5', cat:'zero' },{ id:'a6', cat:'zero' }
]);
wireQuiz('p36-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p36'); });
wireReadBtn('p36');
renderMath(body);
}
/* ========================================================== */
/* §37 — Полезная и совершённая работа. КПД */
/* ========================================================== */
function add_p37(){
const body = document.getElementById('p37-body');
if(!body) return;
let h = '';
h += makeCard('theory', 'Полезная и полная работа', '§ 37.1',
'Когда мы используем устройство (рычаг, наклонную плоскость, блок), часть энергии тратится '
+ '«не на дело» — на трение, нагрев, преодоление веса самого механизма.<br><br>'
+ '<b>$A_{полез}$</b> — то, что мы хотели сделать (поднять груз и т.п.).<br>'
+ '<b>$A_{полн}$</b> — всё, что пришлось затратить.<br>'
+ 'Всегда $A_{полез} \\le A_{полн}$.');
h += makeCard('rule', 'Коэффициент полезного действия', '§ 37.2',
'$$\\eta = \\dfrac{A_{полез}}{A_{полн}} \\cdot 100\\%$$<br>'
+ 'У <b>идеальной</b> машины $\\eta = 100\\%$. В жизни всегда меньше:'
+ '<ul style="padding-left:20px;margin:5px 0">'
+ '<li>Двигатель внутреннего сгорания: $\\eta \\approx 25..40$ %.</li>'
+ '<li>Электродвигатель: $\\eta \\approx 80..95$ %.</li>'
+ '<li>Лампа накаливания: $\\eta \\approx 5$ % (остальное — тепло).</li>'
+ '<li>Светодиодная лампа: $\\eta \\approx 40$ %.</li>'
+ '</ul>');
h += makeCard('example', 'Наклонная плоскость', '§ 37.3',
'Поднимаем груз $m = 50$ кг по наклону длиной $l = 4$ м на высоту $h = 1$ м, сила тяги $F = 150$ Н ($g = 10$).<br>'
+ '$A_{полез} = mgh = 500$ Дж (то, что мы хотели — поднять на $h$).<br>'
+ '$A_{полн} = F l = 600$ Дж (то, что приложили).<br>'
+ '$\\eta = 500/600 \\cdot 100\\% \\approx 83$ %.<br>'
+ 'Потеря $100$ Дж ушла на трение по наклону.');
/* IV-1 КАЛЬК */
h += wgWrap('p37-iv1', 'КАЛЬК', 'Калькулятор КПД', '',
'<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">'
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$A_{полез}$, Дж: <b id="p37-Ap" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">500</b><input type="range" id="p37-Ap-r" min="1" max="1000" step="1" value="500" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$A_{полн}$, Дж: <b id="p37-At" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">600</b><input type="range" id="p37-At-r" min="1" max="2000" step="1" value="600" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
+ '</div>'
+ '<div style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:12px 14px;font-size:.94rem;line-height:1.7">$\\eta = A_{полез}/A_{полн} \\cdot 100\\% = $ <b id="p37-eta" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">83.3</b> % <span id="p37-warn" style="font-size:.82rem;color:#dc2626;margin-left:8px"></span><div id="p37-loss" style="font-size:.84rem;color:#475569;margin-top:5px"></div></div>');
/* IV-2 СИМ */
h += wgWrap('p37-iv2', 'СИМ', 'Наклонная плоскость', 'Меняй угол — как меняется потребная сила и КПД.',
'<div style="margin-bottom:10px"><label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Угол наклона, °: <b id="p37s-a" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">30</b><input type="range" id="p37s-a-r" min="10" max="80" step="1" value="30" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label></div>'
+ '<svg id="p37s-svg" viewBox="0 0 360 200" width="100%" style="max-width:500px;display:block;margin:0 auto;background:#ecfdf5;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>'
+ '<div id="p37s-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:10px 14px;margin-top:8px;font-size:.92rem;line-height:1.6"></div>');
/* IV-3 DnD */
h += wgWrap('p37-iv3', 'DnD', 'Сопоставь КПД с устройством', '',
dndPool('p37-dnd', [
{ id:'a1', cat:'low', html:'Лампа накаливания' },
{ id:'a2', cat:'low', html:'Двигатель внутр. сгорания авто' },
{ id:'a3', cat:'mid', html:'Светодиодная лампа' },
{ id:'a4', cat:'mid', html:'Простой блок с трением' },
{ id:'a5', cat:'high', html:'Электродвигатель' },
{ id:'a6', cat:'high', html:'Гидравлический пресс' }
], [
{ cat:'low', label:'Низкий КПД (5..30 %)' },
{ cat:'mid', label:'Средний (40..60 %)' },
{ cat:'high', label:'Высокий (80..95 %)' }
]));
/* IV-4 ТРН */
h += wgWrap('p37-iv4', 'ТРН', 'Тренажёр §37', '',
'<div id="p37-tr-host">'
+ quizQuestion('p37-tr', 0, '$A_{полез} = 300$ Дж, $A_{полн} = 400$ Дж. КПД?', ['25 %','50 %','75 %','100 %'], 2, '$300/400 = 0{,}75 = 75\\%$.')
+ quizQuestion('p37-tr', 1, 'КПД $= 80\\%$, $A_{полн} = 500$ Дж. $A_{полез}$?', ['100 Дж','200 Дж','400 Дж','600 Дж'], 2, '$A_{полез} = 0{,}8 \\cdot 500 = 400$ Дж.')
+ quizQuestion('p37-tr', 2, 'Может ли КПД быть $> 100\\%$?', ['Да','Нет, никогда','Иногда','Только в идеале'], 1, 'Нельзя получить больше работы, чем затрачено.')
+ quizQuestion('p37-tr', 3, 'Куда уходят $100\\% - \\eta$?', ['Возвращаются','В трение, нагрев, шум, деформации','Исчезают','В электричество'], 1)
+ quizQuestion('p37-tr', 4, 'Поднимаем $m = 20$ кг на $h = 3$ м с $\\eta = 60\\%$ ($g = 10$). $A_{полн}$?', ['600 Дж','800 Дж','1000 Дж','1200 Дж'], 2, '$A_{полез} = 600$ Дж. $A_{полн} = 600/0{,}6 = 1000$ Дж.')
+ '</div>');
h += readButton('p37');
body.innerHTML = h;
const upd37 = () => {
const Ap = +document.getElementById('p37-Ap-r').value;
const At = +document.getElementById('p37-At-r').value;
document.getElementById('p37-Ap').textContent = Ap;
document.getElementById('p37-At').textContent = At;
const eta = (Ap / At) * 100;
document.getElementById('p37-eta').textContent = eta.toFixed(1);
const warn = document.getElementById('p37-warn');
if(eta > 100){
warn.textContent = '(невозможно! Ap > At — ошибка ввода)';
} else {
warn.textContent = '';
}
document.getElementById('p37-loss').textContent = 'Потери: ' + (At - Ap).toFixed(0) + ' Дж (' + (100 - Math.min(100, eta)).toFixed(1) + ' %)';
};
['p37-Ap-r','p37-At-r'].forEach(id => document.getElementById(id).addEventListener('input', upd37));
upd37();
// §37 IV-2 наклонная
function draw37s(){
const ang = +document.getElementById('p37s-a-r').value;
document.getElementById('p37s-a').textContent = ang;
const W = 360, H = 200;
const m = 10, g = 10, mu = 0.1; // фиксированные параметры
const a = ang * Math.PI / 180;
// SVG: треугольник
const baseY = 170;
const len = 200; // px длина наклона
const x1 = 60, y1 = baseY;
const x2 = x1 + len * Math.cos(a);
const y2 = baseY - len * Math.sin(a);
let s = '';
// Земля
s += '<line x1="0" y1="' + baseY + '" x2="' + W + '" y2="' + baseY + '" stroke="#0f172a" stroke-width="1.5"/>';
s += '<polygon points="' + x1 + ',' + y1 + ' ' + (x1 + len * Math.cos(a)) + ',' + y1 + ' ' + x2 + ',' + y2 + '" fill="' + ACCENT_SOFT + '" stroke="' + ACCENT_D + '" stroke-width="1.5"/>';
// Брусок
const bx = (x1 + x2)/2 - 12;
const by = (y1 + y2)/2 - 24;
s += '<g transform="rotate(' + (-ang) + ' ' + ((x1+x2)/2) + ' ' + ((y1+y2)/2) + ')">';
s += '<rect x="' + bx + '" y="' + by + '" width="24" height="20" fill="' + ACCENT + '" stroke="' + ACCENT_D + '" stroke-width="1.5" rx="2"/>';
s += '</g>';
// Подпись угла
s += '<text x="' + (x1 + 30) + '" y="' + (baseY - 5) + '" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="' + ACCENT_D + '">α = ' + ang + '°</text>';
// Подпись h
const hSim = len * Math.sin(a);
s += '<line x1="' + (x2 + 8) + '" y1="' + y2 + '" x2="' + (x2 + 8) + '" y2="' + baseY + '" stroke="#dc2626" stroke-width="1" stroke-dasharray="3 2"/>';
s += '<text x="' + (x2 + 12) + '" y="' + ((y2 + baseY)/2) + '" font-family="Inter,sans-serif" font-size="10" font-weight="700" fill="#dc2626">h = ' + (hSim/20).toFixed(1) + ' м</text>';
document.getElementById('p37s-svg').innerHTML = s;
// Расчёт КПД для наклонной плоскости с трением:
const hReal = 1; // 1 м для пример
const lReal = hReal / Math.sin(a);
const Apolez = m * g * hReal;
const FtrShift = mu * m * g * Math.cos(a);
const Ftyga = m * g * Math.sin(a) + FtrShift;
const Apolnoy = Ftyga * lReal;
const eta = (Apolez / Apolnoy) * 100;
document.getElementById('p37s-info').innerHTML = 'Поднимаем $m = 10$ кг на $h = 1$ м (μ = 0,1): '
+ '$A_{полез} = mgh = 100$ Дж, '
+ '$F_{тяги} = ' + Ftyga.toFixed(1) + '$ Н, '
+ '$A_{полн} = F l = ' + Apolnoy.toFixed(1) + '$ Дж, '
+ '$\\eta = ' + eta.toFixed(1) + '$ %.<br><span style="font-size:.84rem;color:#475569">Большие углы → меньше трения → выше КПД, но требуется большая сила.</span>';
renderMath(document.getElementById('p37s-info'));
}
document.getElementById('p37s-a-r').addEventListener('input', draw37s);
draw37s();
wireDnd('p37-dnd', [
{ id:'a1', cat:'low' },{ id:'a2', cat:'low' },{ id:'a3', cat:'mid' },
{ id:'a4', cat:'mid' },{ id:'a5', cat:'high' },{ id:'a6', cat:'high' }
]);
wireQuiz('p37-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p37'); });
wireReadBtn('p37');
renderMath(body);
}
/* ========================================================== */
/* §38 — Мощность */
/* ========================================================== */
function add_p38(){
const body = document.getElementById('p38-body');
if(!body) return;
let h = '';
h += makeCard('theory', 'Мощность — это скорость работы', '§ 38.1',
'<b>Мощность</b> $P$ — это работа, совершаемая за единицу времени:<br>'
+ '$$P = \\dfrac{A}{t}$$<br>'
+ '$[P] = $ Вт (ватт). $1$ Вт $= 1$ Дж/с.');
h += makeCard('rule', 'Кратные единицы', '§ 38.2',
'<ul style="padding-left:20px;margin:5px 0">'
+ '<li>$1$ кВт $= 1000$ Вт</li>'
+ '<li>$1$ МВт $= 10^6$ Вт</li>'
+ '<li>$1$ ГВт $= 10^9$ Вт (мощность крупной электростанции)</li>'
+ '<li>$1$ л. с. (лошадиная сила) $= 736$ Вт $\\approx 0{,}74$ кВт</li>'
+ '</ul>');
h += makeCard('example', 'Таблица мощностей', '§ 38.3',
'<table style="width:100%;border-collapse:collapse;font-size:.92rem">'
+ '<tr style="background:' + ACCENT_SOFT + '"><th style="padding:6px 10px;text-align:left;border-bottom:2px solid ' + ACCENT + '">Объект</th><th style="padding:6px 10px;text-align:right;border-bottom:2px solid ' + ACCENT + '">P</th></tr>'
+ [['Светодиодная лампа','5..10 Вт'],['Человек (физический труд)','~100 Вт'],['Лампа накаливания','60 Вт'],['Лошадь','~700 Вт (1 л.с.)'],['Чайник электрический','2 кВт'],['Легковой автомобиль','50..150 кВт'],['Поезд (локомотив)','~5 МВт'],['Атомная электростанция (1 блок)','~1 ГВт']].map(r =>
'<tr><td style="padding:5px 10px;border-bottom:1px solid ' + ACCENT_SOFT + '">' + r[0] + '</td><td style="padding:5px 10px;text-align:right;border-bottom:1px solid ' + ACCENT_SOFT + ';font-family:JetBrains Mono,monospace;font-weight:700">' + r[1] + '</td></tr>').join('')
+ '</table>');
/* IV-1 КАЛЬК */
h += wgWrap('p38-iv1', 'КАЛЬК', 'Калькулятор $P = A/t$', '',
'<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">'
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$A$, Дж: <b id="p38-A" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">600</b><input type="range" id="p38-A-r" min="1" max="100000" step="1" value="600" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$t$, с: <b id="p38-t" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">10</b><input type="range" id="p38-t-r" min="0.1" max="3600" step="0.1" value="10" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
+ '</div>'
+ '<div style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:12px 14px;font-size:.94rem;line-height:1.7">'
+ '$P = A/t = $ <b id="p38-P" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">60</b> Вт $= $ <b id="p38-Pkw" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">0.06</b> кВт $\\approx $ <b id="p38-Pls" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">0.08</b> л. с.'
+ '<div id="p38-cmp" style="font-size:.84rem;color:#475569;margin-top:5px"></div>'
+ '</div>');
/* IV-2 СИМ */
h += wgWrap('p38-iv2', 'СИМ', 'Два силача с одинаковой работой', 'Кто мощнее — тот, кто быстрее.',
'<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">'
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Спортсмен А: $t_A$, с: <b id="p38s-tA" style="color:#dc2626;font-family:JetBrains Mono,monospace">5</b><input type="range" id="p38s-tA-r" min="1" max="30" step="1" value="5" style="display:block;width:100%;margin-top:6px;accent-color:#dc2626"></label>'
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Спортсмен Б: $t_Б$, с: <b id="p38s-tB" style="color:#0284c7;font-family:JetBrains Mono,monospace">10</b><input type="range" id="p38s-tB-r" min="1" max="30" step="1" value="10" style="display:block;width:100%;margin-top:6px;accent-color:#0284c7"></label>'
+ '</div>'
+ '<div id="p38s-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:12px 14px;font-size:.94rem;line-height:1.7"></div>');
/* IV-3 DnD */
h += wgWrap('p38-iv3', 'DnD', 'Мощности по порядку', '',
dndPool('p38-dnd', [
{ id:'a1', cat:'low', html:'Светодиодная лампа (~10 Вт)' },
{ id:'a2', cat:'low', html:'Зарядка телефона (~5 Вт)' },
{ id:'a3', cat:'mid', html:'Утюг (~2 кВт)' },
{ id:'a4', cat:'mid', html:'Микроволновка (~1 кВт)' },
{ id:'a5', cat:'high', html:'Легковой автомобиль (~100 кВт)' },
{ id:'a6', cat:'high', html:'Локомотив (~5 МВт)' }
], [
{ cat:'low', label:'Малая (Вт)' },
{ cat:'mid', label:'Средняя (кВт)' },
{ cat:'high', label:'Большая (десятки кВт..МВт)' }
]));
/* IV-4 ТРН */
h += wgWrap('p38-iv4', 'ТРН', 'Тренажёр §38', '',
'<div id="p38-tr-host">'
+ quizQuestion('p38-tr', 0, '$A = 600$ Дж за $t = 30$ с. $P$?', ['10 Вт','20 Вт','30 Вт','60 Вт'], 1, '$P = 600/30 = 20$ Вт.')
+ quizQuestion('p38-tr', 1, 'Двигатель $P = 3$ кВт работал $t = 5$ мин. $A$?', ['600 Дж','9 кДж','15 кДж','900 кДж'], 3, '$t = 300$ с, $A = Pt = 3000 \\cdot 300 = 900\\,000$ Дж $= 900$ кДж.')
+ quizQuestion('p38-tr', 2, 'Один человек поднял груз за $10$ с, другой — за $20$ с. У кого мощность больше?', ['У первого','У второго','Одинакова','Нельзя сказать'], 0)
+ quizQuestion('p38-tr', 3, '$2$ кВт $= ?$ Вт', ['200','2 000','20 000','200 000'], 1)
+ quizQuestion('p38-tr', 4, '$1$ л. с. в Вт (округли):', ['100','500','736','1000'], 2)
+ '</div>');
h += readButton('p38');
body.innerHTML = h;
const upd38 = () => {
const A = +document.getElementById('p38-A-r').value;
const t = +document.getElementById('p38-t-r').value;
document.getElementById('p38-A').textContent = A;
document.getElementById('p38-t').textContent = t.toFixed(1);
const P = A / t;
document.getElementById('p38-P').textContent = P.toFixed(1);
document.getElementById('p38-Pkw').textContent = (P/1000).toFixed(3);
document.getElementById('p38-Pls').textContent = (P/736).toFixed(2);
let cmp;
if(P < 30) cmp = 'Уровень зарядки телефона.';
else if(P < 200) cmp = 'Уровень бытовой лампы / человека.';
else if(P < 3000) cmp = 'Чайник / утюг.';
else if(P < 200000) cmp = 'Автомобиль.';
else if(P < 10000000) cmp = 'Локомотив.';
else cmp = 'Электростанция (МВт-ГВт уровень).';
document.getElementById('p38-cmp').textContent = cmp;
};
['p38-A-r','p38-t-r'].forEach(id => document.getElementById(id).addEventListener('input', upd38));
upd38();
const upd38s = () => {
const tA = +document.getElementById('p38s-tA-r').value;
const tB = +document.getElementById('p38s-tB-r').value;
document.getElementById('p38s-tA').textContent = tA;
document.getElementById('p38s-tB').textContent = tB;
const A = 1000; // фикс. работа 1000 Дж
const PA = A / tA;
const PB = A / tB;
const winner = PA > PB ? 'А' : (PB > PA ? 'Б' : 'равны');
document.getElementById('p38s-info').innerHTML = 'Каждый совершил работу $A = ' + A + '$ Дж (одинаковую).<br>'
+ '<span style="color:#dc2626;font-weight:700">$P_А = ' + A + '/' + tA + ' = ' + PA.toFixed(0) + '$ Вт</span><br>'
+ '<span style="color:#0284c7;font-weight:700">$P_Б = ' + A + '/' + tB + ' = ' + PB.toFixed(0) + '$ Вт</span><br>'
+ '<b>Мощнее: ' + winner + '</b> (он сделал ту же работу быстрее).';
renderMath(document.getElementById('p38s-info'));
};
['p38s-tA-r','p38s-tB-r'].forEach(id => document.getElementById(id).addEventListener('input', upd38s));
upd38s();
wireDnd('p38-dnd', [
{ id:'a1', cat:'low' },{ id:'a2', cat:'low' },{ id:'a3', cat:'mid' },
{ id:'a4', cat:'mid' },{ id:'a5', cat:'high' },{ id:'a6', cat:'high' }
]);
wireQuiz('p38-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p38'); });
wireReadBtn('p38');
renderMath(body);
}
/* ========================================================== */
/* §39 — Кинетическая энергия */
/* ========================================================== */
function add_p39(){
const body = document.getElementById('p39-body');
if(!body) return;
let h = '';
h += makeCard('theory', 'Энергия движения', '§ 39.1',
'<b>Кинетическая энергия</b> $E_к$ — это энергия, которой обладает <b>движущееся</b> тело.<br><br>'
+ '$$E_к = \\dfrac{m v^2}{2}$$<br>'
+ '$[E] = $ Дж. У покоящегося тела ($v = 0$) кинетическая энергия равна нулю.');
h += makeCard('rule', 'Квадратичная зависимость от $v$', '§ 39.2',
'Из формулы видно: при удвоении скорости энергия растёт <b>в 4 раза</b>; при увеличении в 3 раза — <b>в 9 раз</b>.<br><br>'
+ 'Поэтому тормозной путь автомобиля при удвоении скорости — в 4 раза длиннее.');
h += makeCard('example', 'Сколько энергии у машины?', '§ 39.3',
'Автомобиль $m = 1000$ кг едет $v = 20$ м/с (72 км/ч).<br>'
+ '$E_к = mv^2/2 = 1000 \\cdot 400/2 = 200\\,000$ Дж $= 200$ кДж.<br><br>'
+ 'При $v = 40$ м/с (144 км/ч): $E_к = 1000 \\cdot 1600/2 = 800$ кДж — в 4 раза больше! '
+ 'Эту энергию тормоза должны рассеять как тепло.');
/* IV-1 КАЛЬК */
h += wgWrap('p39-iv1', 'КАЛЬК', 'Калькулятор $E_к = mv^2/2$', '',
'<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">'
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$m$, кг: <b id="p39-m" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">1000</b><input type="range" id="p39-m-r" min="0.1" max="2000" step="0.1" value="1000" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$v$, м/с: <b id="p39-v" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">20</b><input type="range" id="p39-v-r" min="0" max="100" step="0.5" value="20" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
+ '</div>'
+ '<div style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:12px 14px;font-size:.94rem;line-height:1.7">'
+ '$E_к = mv^2/2 = $ <b id="p39-Ek" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">200 000</b> Дж $= $ <b id="p39-Ekkj" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">200</b> кДж'
+ '<div id="p39-cmp" style="font-size:.84rem;color:#475569;margin-top:4px"></div>'
+ '</div>');
/* IV-2 СИМ: тело движется + индикатор Ek */
h += wgWrap('p39-iv2', 'СИМ', 'E_к растёт квадратично', 'Двигай v — увидь, как энергия растёт по параболе.',
'<div style="margin-bottom:10px"><label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Скорость $v$, м/с (при $m = 1$ кг): <b id="p39s-v" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">5</b><input type="range" id="p39s-v-r" min="0" max="20" step="0.5" value="5" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label></div>'
+ '<svg id="p39s-svg" viewBox="0 0 360 200" width="100%" style="max-width:500px;display:block;margin:0 auto;background:#ecfdf5;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>'
+ '<div id="p39s-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:10px 14px;margin-top:8px;font-size:.92rem;text-align:center"></div>');
/* IV-3 DnD */
h += wgWrap('p39-iv3', 'DnD', 'У кого больше $E_к$?', '',
dndPool('p39-dnd', [
{ id:'a1', cat:'small', html:'Шарик $m = 0{,}1$ кг при $v = 1$ м/с (0,05 Дж)' },
{ id:'a2', cat:'small', html:'Снежинка падает (~0,001 Дж)' },
{ id:'a3', cat:'mid', html:'Бегун $m = 70$ кг, $v = 6$ м/с (1260 Дж)' },
{ id:'a4', cat:'mid', html:'Велосипедист $m = 80$ кг, $v = 5$ м/с (1000 Дж)' },
{ id:'a5', cat:'big', html:'Машина $m = 1000$ кг, $v = 20$ м/с (200 кДж)' },
{ id:'a6', cat:'big', html:'Грузовик $m = 5000$ кг, $v = 15$ м/с (562 кДж)' }
], [
{ cat:'small', label:'Малая (Дж)' },
{ cat:'mid', label:'Средняя (кДж)' },
{ cat:'big', label:'Большая (десятки..сотни кДж)' }
]));
/* IV-4 ТРН */
h += wgWrap('p39-iv4', 'ТРН', 'Тренажёр §39', '',
'<div id="p39-tr-host">'
+ quizQuestion('p39-tr', 0, '$m = 2$ кг, $v = 3$ м/с. $E_к$?', ['3 Дж','6 Дж','9 Дж','18 Дж'], 2, '$E_к = 2 \\cdot 9/2 = 9$ Дж.')
+ quizQuestion('p39-tr', 1, 'Тело $m = 0{,}5$ кг с $v = 10$ м/с. $E_к$?', ['12,5 Дж','25 Дж','50 Дж','100 Дж'], 1, '$E_к = 0{,}5 \\cdot 100/2 = 25$ Дж.')
+ quizQuestion('p39-tr', 2, 'При удвоении $v$ кинетическая энергия:', ['Удваивается','Утраивается','В 4 раза больше','Не меняется'], 2)
+ quizQuestion('p39-tr', 3, 'Машина едет $36$ км/ч ($= 10$ м/с), $m = 1500$ кг. $E_к$?', ['7,5 кДж','15 кДж','75 кДж','150 кДж'], 2, '$E_к = 1500 \\cdot 100/2 = 75\\,000$ Дж.')
+ quizQuestion('p39-tr', 4, 'Машина с $E_к = 100$ кДж и $m = 800$ кг. Какова $v$?', ['10 м/с','12,5 м/с','15,8 м/с','20 м/с'], 2, '$v = \\sqrt{2E_к/m} = \\sqrt{250} \\approx 15{,}8$ м/с.')
+ '</div>');
h += readButton('p39');
body.innerHTML = h;
const upd39 = () => {
const m = +document.getElementById('p39-m-r').value;
const v = +document.getElementById('p39-v-r').value;
document.getElementById('p39-m').textContent = m.toFixed(1);
document.getElementById('p39-v').textContent = v.toFixed(1);
const Ek = m * v * v / 2;
document.getElementById('p39-Ek').textContent = Ek.toLocaleString('ru-RU', { maximumFractionDigits: 0 });
document.getElementById('p39-Ekkj').textContent = (Ek/1000).toFixed(2);
let cmp;
if(Ek < 10) cmp = 'Меньше энергии летящего камня.';
else if(Ek < 1000) cmp = 'Уровень бегуна или мяча.';
else if(Ek < 100000) cmp = 'Уровень велосипедиста / лёгкой машины.';
else if(Ek < 1e6) cmp = 'Уровень автомобиля на шоссе.';
else cmp = 'Огромная — грузовик или поезд.';
document.getElementById('p39-cmp').textContent = cmp;
};
['p39-m-r','p39-v-r'].forEach(id => document.getElementById(id).addEventListener('input', upd39));
upd39();
// §39 IV-2 — parabola
function draw39s(){
const v = +document.getElementById('p39s-v-r').value;
document.getElementById('p39s-v').textContent = v.toFixed(1);
const W = 360, H = 200, pad = 30;
const vMax = 20, EkMax = vMax * vMax / 2; // m=1
function toX(vv){ return pad + (W - 2*pad) * vv / vMax; }
function toY(ek){ return H - pad - (H - 2*pad) * ek / EkMax; }
let s = '';
// Оси
s += '<line x1="' + pad + '" y1="' + (H - pad) + '" x2="' + (W - pad + 4) + '" y2="' + (H - pad) + '" stroke="#0f172a" stroke-width="1.5"/>';
s += '<line x1="' + pad + '" y1="' + (pad - 4) + '" x2="' + pad + '" y2="' + (H - pad) + '" stroke="#0f172a" stroke-width="1.5"/>';
s += '<text x="' + (W - pad + 8) + '" y="' + (H - pad + 4) + '" font-family="Inter,sans-serif" font-size="11" fill="#0f172a">v, м/с</text>';
s += '<text x="' + (pad - 4) + '" y="' + (pad - 6) + '" text-anchor="end" font-family="Inter,sans-serif" font-size="11" fill="#0f172a">E_к, Дж</text>';
// Ticks
for(let vv = 0; vv <= vMax; vv += 5){
const x = toX(vv);
s += '<line x1="' + x + '" y1="' + (H - pad) + '" x2="' + x + '" y2="' + (H - pad + 3) + '" stroke="#0f172a" stroke-width="1"/>';
if(vv > 0) s += '<text x="' + x + '" y="' + (H - pad + 14) + '" text-anchor="middle" font-family="Inter,sans-serif" font-size="9" fill="#0f172a">' + vv + '</text>';
}
for(let ek = 0; ek <= EkMax; ek += 50){
const y = toY(ek);
s += '<line x1="' + pad + '" y1="' + y + '" x2="' + (pad - 3) + '" y2="' + y + '" stroke="#0f172a" stroke-width="1"/>';
if(ek > 0) s += '<text x="' + (pad - 5) + '" y="' + (y + 3) + '" text-anchor="end" font-family="Inter,sans-serif" font-size="9" fill="#0f172a">' + ek + '</text>';
}
// Парабола
let path = '';
for(let i = 0; i <= 60; i++){
const vv = vMax * i / 60;
const ek = vv * vv / 2;
path += (i === 0 ? 'M' : 'L') + toX(vv).toFixed(1) + ' ' + toY(ek).toFixed(1) + ' ';
}
s += '<path d="' + path + '" fill="none" stroke="' + ACCENT + '" stroke-width="2.5"/>';
// Текущая точка
const Ek = v * v / 2;
const cx = toX(v), cy = toY(Ek);
s += '<line x1="' + cx + '" y1="' + (H - pad) + '" x2="' + cx + '" y2="' + cy + '" stroke="#dc2626" stroke-width="1" stroke-dasharray="2 2"/>';
s += '<line x1="' + pad + '" y1="' + cy + '" x2="' + cx + '" y2="' + cy + '" stroke="#dc2626" stroke-width="1" stroke-dasharray="2 2"/>';
s += '<circle cx="' + cx + '" cy="' + cy + '" r="6" fill="#dc2626" stroke="#fff" stroke-width="2"/>';
document.getElementById('p39s-svg').innerHTML = s;
document.getElementById('p39s-info').innerHTML = '$v = ' + v.toFixed(1) + '$ м/с &middot; $E_к = v^2/2 = $ <b>' + Ek.toFixed(1) + '</b> Дж';
renderMath(document.getElementById('p39s-info'));
}
document.getElementById('p39s-v-r').addEventListener('input', draw39s);
draw39s();
wireDnd('p39-dnd', [
{ id:'a1', cat:'small' },{ id:'a2', cat:'small' },{ id:'a3', cat:'mid' },
{ id:'a4', cat:'mid' },{ id:'a5', cat:'big' },{ id:'a6', cat:'big' }
]);
wireQuiz('p39-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p39'); });
wireReadBtn('p39');
renderMath(body);
}
/* ========================================================== */
/* §40 — Потенциальная энергия (введение) */
/* ========================================================== */
function add_p40(){
const body = document.getElementById('p40-body');
if(!body) return;
let h = '';
h += makeCard('theory', 'Потенциальная энергия', '§ 40.1',
'<b>Потенциальная энергия</b> $E_п$ — это «запас» работы, который сила (тяжести, упругости) сможет совершить над телом.<br><br>'
+ 'Камень, поднятый на гору, ничего не делает — но если его столкнуть, он покатится вниз, разгонится и сможет сдвинуть препятствие. '
+ 'Запас энергии у камня — потенциальная.');
h += makeCard('rule', 'Два вида $E_п$', '§ 40.2',
'<ul style="padding-left:20px;margin:6px 0">'
+ '<li><b>Гравитационная</b> — у тела, поднятого над землёй (или над любым выбранным уровнем). $E_п = mgh$.</li>'
+ '<li><b>Упругая</b> — у деформированного тела (пружины, лука). У школьной пружины: $E_п \\sim \\Delta l^2$ (растёт быстро с растяжением).</li>'
+ '</ul>'
+ 'Чем выше тело — тем больше гравит. потенциальная. Чем сильнее сжата пружина — тем больше упругой.');
h += makeCard('example', 'Запас работы', '§ 40.3',
'<ul style="padding-left:20px;margin:6px 0">'
+ '<li><b>Вода в водохранилище</b> — гравитационная $E_п$. Запускают вниз через турбину — генерирует электричество (ГЭС).</li>'
+ '<li><b>Сжатая пружина в часах</b> — упругая $E_п$. Расправляется — крутит стрелки.</li>'
+ '<li><b>Тетива лука</b> — упругая. Распрямляется — толкает стрелу.</li>'
+ '</ul>');
/* IV-1 СИМ: подъём груза */
h += wgWrap('p40-iv1', 'СИМ', 'Поднимем груз — увеличим запас', 'Меняй высоту — увидь рост $E_п$.',
'<div style="margin-bottom:10px"><label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Высота $h$, м: <b id="p40-h" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">5</b><input type="range" id="p40-h-r" min="0" max="20" step="0.5" value="5" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label></div>'
+ '<svg id="p40-svg" viewBox="0 0 320 220" width="100%" style="max-width:400px;display:block;margin:0 auto;background:#ecfdf5;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>'
+ '<div id="p40-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:10px 14px;margin-top:8px;font-size:.92rem;text-align:center"></div>');
/* IV-2 КВИЗ */
h += wgWrap('p40-iv2', 'КВИЗ', 'Что такое потенц. энергия', '',
'<div id="p40-q-host">'
+ quizQuestion('p40-q', 0, 'Что обладает потенциальной энергией?', ['Любое движущееся тело','Тело в поле силы (например, поднятый камень)','Только электрические заряды','Только пружины'], 1)
+ quizQuestion('p40-q', 1, 'Какие два главных вида $E_п$ в механике?', ['Тепловая и магнитная','Гравитационная и упругая','Постоянная и переменная','Открытая и закрытая'], 1)
+ quizQuestion('p40-q', 2, 'У камня, висящего на потолке, $E_п$:', ['Нулевая','Существует — он может упасть и совершить работу','Отрицательная','Только если он движется'], 1)
+ quizQuestion('p40-q', 3, 'Сжатая пружина обладает:', ['Кинетической','Упругой потенциальной','Гравитационной','Никакой'], 1)
+ '</div>');
/* IV-3 DnD */
h += wgWrap('p40-iv3', 'DnD', 'Какой вид энергии?', '',
dndPool('p40-dnd', [
{ id:'a1', cat:'k', html:'Летящий мяч' },
{ id:'a2', cat:'k', html:'Едущий автомобиль' },
{ id:'a3', cat:'pg', html:'Камень на вершине утёса' },
{ id:'a4', cat:'pg', html:'Вода в водохранилище' },
{ id:'a5', cat:'pe', html:'Сжатая пружина' },
{ id:'a6', cat:'pe', html:'Натянутая тетива лука' }
], [
{ cat:'k', label:'Кинетическая' },
{ cat:'pg', label:'$E_п$ гравитационная' },
{ cat:'pe', label:'$E_п$ упругая' }
]));
/* IV-4 ТРН */
h += wgWrap('p40-iv4', 'ТРН', 'Тренажёр §40', '',
'<div id="p40-tr-host">'
+ quizQuestion('p40-tr', 0, 'Когда $E_п$ гравитационная больше: на $1$ м или на $10$ м (для того же тела)?', ['На 1 м','На 10 м','Одинаково','Зависит от массы'], 1)
+ quizQuestion('p40-tr', 1, 'Можно ли $E_п$ превратить в $E_к$?', ['Нет','Да, например при падении','Только в особых условиях','Только с помощью двигателя'], 1)
+ quizQuestion('p40-tr', 2, 'Что является источником энергии ГЭС?', ['$E_к$ ветра','$E_п$ воды на высоте','$E_к$ молекул','Магнетизм'], 1)
+ quizQuestion('p40-tr', 3, 'Тело с $E_п = 100$ Дж может совершить работу не больше…', ['10 Дж','100 Дж','1000 Дж','Сколько угодно'], 1)
+ '</div>');
h += readButton('p40');
body.innerHTML = h;
function draw40(){
const hVal = +document.getElementById('p40-h-r').value;
document.getElementById('p40-h').textContent = hVal;
const W = 320, H = 220, baseY = 200;
let s = '';
s += '<line x1="0" y1="' + baseY + '" x2="' + W + '" y2="' + baseY + '" stroke="#0f172a" stroke-width="1.5"/>';
for(let i = 0; i < 14; i++) s += '<line x1="' + (i*22+5) + '" y1="' + baseY + '" x2="' + (i*22+1) + '" y2="' + (baseY+10) + '" stroke="#374151" stroke-width="0.8"/>';
// Шкала высоты
for(let hh = 0; hh <= 20; hh += 5){
const y = baseY - hh * 8;
s += '<line x1="20" y1="' + y + '" x2="25" y2="' + y + '" stroke="#0f172a" stroke-width="1"/>';
s += '<text x="28" y="' + (y + 3) + '" font-family="Inter,sans-serif" font-size="9" fill="#0f172a">' + hh + ' м</text>';
}
s += '<line x1="20" y1="' + baseY + '" x2="20" y2="' + (baseY - 160) + '" stroke="#0f172a" stroke-width="1"/>';
// Тело
const y = baseY - hVal * 8 - 14;
s += '<rect x="160" y="' + y + '" width="36" height="22" fill="' + ACCENT + '" stroke="' + ACCENT_D + '" stroke-width="1.5" rx="3"/>';
s += '<text x="178" y="' + (y + 14) + '" text-anchor="middle" font-family="Inter,sans-serif" font-size="10" font-weight="700" fill="#fff">1 кг</text>';
// Линия высоты
if(hVal > 0){
s += '<line x1="40" y1="' + baseY + '" x2="40" y2="' + (baseY - hVal*8) + '" stroke="#dc2626" stroke-width="2"/>';
s += '<polygon points="40,' + (baseY - hVal*8 + 7) + ' 35,' + (baseY - hVal*8 + 14) + ' 45,' + (baseY - hVal*8 + 14) + '" fill="#dc2626"/>';
s += '<text x="50" y="' + (baseY - hVal*4) + '" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="#dc2626">h = ' + hVal + ' м</text>';
}
// Подпись Ep
const Ep = 1 * 10 * hVal; // m=1, g=10
s += '<text x="220" y="40" font-family="Unbounded,sans-serif" font-size="14" font-weight="800" fill="' + ACCENT_D + '">E_п = ' + Ep + ' Дж</text>';
document.getElementById('p40-svg').innerHTML = s;
document.getElementById('p40-info').innerHTML = 'Тело $m = 1$ кг на высоте $h = ' + hVal + '$ м: $E_п = mgh = 1 \\cdot 10 \\cdot ' + hVal + ' = $ <b>' + Ep + '</b> Дж.';
renderMath(document.getElementById('p40-info'));
}
document.getElementById('p40-h-r').addEventListener('input', draw40);
draw40();
wireDnd('p40-dnd', [
{ id:'a1', cat:'k' },{ id:'a2', cat:'k' },{ id:'a3', cat:'pg' },
{ id:'a4', cat:'pg' },{ id:'a5', cat:'pe' },{ id:'a6', cat:'pe' }
]);
wireQuiz('p40-q-host', () => { if(window.addXp) window.addXp(10, 'q-p40'); });
wireQuiz('p40-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p40'); });
wireReadBtn('p40');
renderMath(body);
}
/* ========================================================== */
/* §41 — Расчёт потенциальной энергии $E_п = mgh$ */
/* ========================================================== */
function add_p41(){
const body = document.getElementById('p41-body');
if(!body) return;
let h = '';
h += makeCard('theory', 'Формула гравитационной $E_п$', '§ 41.1',
'$$E_п = m g h$$<br>'
+ '$m$ — масса тела (кг), $g \\approx 9{,}8$ Н/кг, $h$ — высота над выбранным уровнем (м).<br>'
+ '$[E_п] = $ Дж.<br><br>'
+ 'Чем тяжелее тело и чем выше — тем больше его запас энергии.');
h += makeCard('rule', 'Высота от чего?', '§ 41.2',
'<b>$E_п$ зависит от выбора нулевого уровня</b>. Например, лампа на потолке: '
+ 'относительно пола высота $h_1 = 3$ м, относительно стола $h_2 = 2$ м, относительно стула $h_3 = 2{,}5$ м.<br><br>'
+ 'Обычно за «ноль» берут поверхность Земли (землю) — но это <b>условность</b>. '
+ 'Главное — <b>разность</b> $E_п$ при перемещении тела всегда определена однозначно: $\\Delta E_п = mg\\Delta h$.');
h += makeCard('example', 'Подъём яблока', '§ 41.3',
'Яблоко $m = 0{,}15$ кг поднимаем на стол высотой $h = 0{,}8$ м.<br>'
+ '$E_п = mgh = 0{,}15 \\cdot 10 \\cdot 0{,}8 = 1{,}2$ Дж.<br>'
+ 'Чтобы его поднять, нам понадобилось совершить работу $\\ge 1{,}2$ Дж (без учёта трения о воздух).');
/* IV-1 КАЛЬК */
h += wgWrap('p41-iv1', 'КАЛЬК', 'Калькулятор $E_п = mgh$', '',
'<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">'
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$m$, кг: <b id="p41-m" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">2</b><input type="range" id="p41-m-r" min="0.01" max="1000" step="0.01" value="2" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$h$, м: <b id="p41-h" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">5</b><input type="range" id="p41-h-r" min="0" max="100" step="0.1" value="5" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
+ '</div>'
+ '<div style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:12px 14px;font-size:.94rem">$E_п = mgh = $ <b id="p41-Ep" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">100</b> Дж $= $ <b id="p41-Epkj" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">0.1</b> кДж <span style="font-size:.84rem;color:#475569;margin-left:8px">($g = 10$ Н/кг)</span></div>');
/* IV-2 СИМ: 2 тела на разной высоте */
h += wgWrap('p41-iv2', 'СИМ', 'Сравни два тела', 'У какого тела запас энергии больше?',
'<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">'
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:7px 11px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">A: $m$, кг: <b id="p41s-mA" style="color:#dc2626;font-family:JetBrains Mono,monospace">5</b><input type="range" id="p41s-mA-r" min="0.5" max="20" step="0.5" value="5" style="display:block;width:100%;margin-top:5px;accent-color:#dc2626"></label>'
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:7px 11px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">A: $h$, м: <b id="p41s-hA" style="color:#dc2626;font-family:JetBrains Mono,monospace">3</b><input type="range" id="p41s-hA-r" min="0" max="15" step="0.5" value="3" style="display:block;width:100%;margin-top:5px;accent-color:#dc2626"></label>'
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:7px 11px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Б: $m$, кг: <b id="p41s-mB" style="color:#0284c7;font-family:JetBrains Mono,monospace">2</b><input type="range" id="p41s-mB-r" min="0.5" max="20" step="0.5" value="2" style="display:block;width:100%;margin-top:5px;accent-color:#0284c7"></label>'
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:7px 11px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Б: $h$, м: <b id="p41s-hB" style="color:#0284c7;font-family:JetBrains Mono,monospace">10</b><input type="range" id="p41s-hB-r" min="0" max="15" step="0.5" value="10" style="display:block;width:100%;margin-top:5px;accent-color:#0284c7"></label>'
+ '</div>'
+ '<svg id="p41s-svg" viewBox="0 0 360 200" width="100%" style="max-width:500px;display:block;margin:0 auto;background:#ecfdf5;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>'
+ '<div id="p41s-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:10px 14px;margin-top:8px;font-size:.94rem;line-height:1.6"></div>');
/* IV-3 DnD */
h += wgWrap('p41-iv3', 'DnD', 'Кто запасает больше $E_п$?', '',
dndPool('p41-dnd', [
{ id:'a1', cat:'small', html:'Карандаш ($m = 0{,}01$ кг) на столе ($h = 1$ м)' },
{ id:'a2', cat:'small', html:'Книга ($m = 0{,}5$ кг) на полке ($h = 2$ м)' },
{ id:'a3', cat:'mid', html:'Человек ($m = 60$ кг) на 5-м этаже ($h = 15$ м)' },
{ id:'a4', cat:'mid', html:'Машина ($m = 1500$ кг) на холме ($h = 5$ м)' },
{ id:'a5', cat:'big', html:'Вода в озере ($V = 1$ млн м³) на $h = 100$ м' },
{ id:'a6', cat:'big', html:'Поезд ($m = 10^6$ кг) на горном перевале ($h = 1000$ м)' }
], [
{ cat:'small', label:'Малая (Дж)' },
{ cat:'mid', label:'Средняя (кДж)' },
{ cat:'big', label:'Огромная (МДж..ГДж)' }
]));
/* IV-4 ТРН */
h += wgWrap('p41-iv4', 'ТРН', 'Тренажёр §41', '',
'<div id="p41-tr-host">'
+ quizQuestion('p41-tr', 0, '$m = 5$ кг, $h = 8$ м ($g = 10$). $E_п$?', ['200 Дж','300 Дж','400 Дж','500 Дж'], 2, '$E_п = 5 \\cdot 10 \\cdot 8 = 400$ Дж.')
+ quizQuestion('p41-tr', 1, 'Птица $m = 0{,}3$ кг летит на высоте $h = 20$ м. $E_п$?', ['6 Дж','30 Дж','60 Дж','600 Дж'], 2)
+ quizQuestion('p41-tr', 2, '$E_п = 200$ Дж, $h = 4$ м. Найди $m$ (g=10).', ['2 кг','4 кг','5 кг','10 кг'], 2, '$m = E_п/(gh) = 200/40 = 5$ кг.')
+ quizQuestion('p41-tr', 3, 'Камень $m = 0{,}5$ кг на $h_1 = 2$ м поднимаем до $h_2 = 5$ м. $\\Delta E_п$?', ['10 Дж','15 Дж','25 Дж','35 Дж'], 1, '$\\Delta E_п = mg \\Delta h = 0{,}5 \\cdot 10 \\cdot 3 = 15$ Дж.')
+ quizQuestion('p41-tr', 4, 'Зависит ли $E_п$ тела на столе от выбора нулевого уровня?', ['Нет','Да — само значение зависит','Только от массы','Только от $g$'], 1)
+ '</div>');
h += readButton('p41');
body.innerHTML = h;
const upd41 = () => {
const m = +document.getElementById('p41-m-r').value;
const hv = +document.getElementById('p41-h-r').value;
document.getElementById('p41-m').textContent = m.toFixed(2);
document.getElementById('p41-h').textContent = hv.toFixed(1);
const Ep = m * 10 * hv;
document.getElementById('p41-Ep').textContent = Ep.toLocaleString('ru-RU', { maximumFractionDigits: 1 });
document.getElementById('p41-Epkj').textContent = (Ep/1000).toFixed(3);
};
['p41-m-r','p41-h-r'].forEach(id => document.getElementById(id).addEventListener('input', upd41));
upd41();
function draw41s(){
const mA = +document.getElementById('p41s-mA-r').value;
const hA = +document.getElementById('p41s-hA-r').value;
const mB = +document.getElementById('p41s-mB-r').value;
const hB = +document.getElementById('p41s-hB-r').value;
document.getElementById('p41s-mA').textContent = mA;
document.getElementById('p41s-hA').textContent = hA;
document.getElementById('p41s-mB').textContent = mB;
document.getElementById('p41s-hB').textContent = hB;
const EpA = mA * 10 * hA, EpB = mB * 10 * hB;
const W = 360, H = 200, baseY = 180;
const pxPerM = 10;
let s = '';
s += '<line x1="0" y1="' + baseY + '" x2="' + W + '" y2="' + baseY + '" stroke="#0f172a" stroke-width="1.5"/>';
for(let i = 0; i < 18; i++) s += '<line x1="' + (i*22+5) + '" y1="' + baseY + '" x2="' + (i*22+1) + '" y2="' + (baseY+10) + '" stroke="#374151" stroke-width="0.8"/>';
// A слева
const yA = baseY - hA * pxPerM - 18;
s += '<rect x="80" y="' + yA + '" width="40" height="20" fill="#dc2626" stroke="#7f1d1d" stroke-width="1.5" rx="3"/>';
s += '<text x="100" y="' + (yA + 13) + '" text-anchor="middle" font-family="Inter,sans-serif" font-size="10" font-weight="700" fill="#fff">' + mA + ' кг</text>';
s += '<line x1="60" y1="' + baseY + '" x2="60" y2="' + (baseY - hA * pxPerM) + '" stroke="#dc2626" stroke-width="1.5"/>';
s += '<text x="40" y="' + (baseY - hA * pxPerM/2) + '" text-anchor="middle" font-family="Inter,sans-serif" font-size="10" font-weight="700" fill="#dc2626">' + hA + ' м</text>';
// B справа
const yB = baseY - hB * pxPerM - 18;
s += '<rect x="240" y="' + yB + '" width="40" height="20" fill="#0284c7" stroke="#0c4a6e" stroke-width="1.5" rx="3"/>';
s += '<text x="260" y="' + (yB + 13) + '" text-anchor="middle" font-family="Inter,sans-serif" font-size="10" font-weight="700" fill="#fff">' + mB + ' кг</text>';
s += '<line x1="220" y1="' + baseY + '" x2="220" y2="' + (baseY - hB * pxPerM) + '" stroke="#0284c7" stroke-width="1.5"/>';
s += '<text x="205" y="' + (baseY - hB * pxPerM/2) + '" text-anchor="middle" font-family="Inter,sans-serif" font-size="10" font-weight="700" fill="#0284c7">' + hB + ' м</text>';
document.getElementById('p41s-svg').innerHTML = s;
const winner = EpA > EpB ? 'A' : (EpB > EpA ? 'Б' : 'равны');
document.getElementById('p41s-info').innerHTML = '<span style="color:#dc2626;font-weight:700">$E_{пA} = ' + mA + ' \\cdot 10 \\cdot ' + hA + ' = ' + EpA + '$ Дж</span><br>'
+ '<span style="color:#0284c7;font-weight:700">$E_{пБ} = ' + mB + ' \\cdot 10 \\cdot ' + hB + ' = ' + EpB + '$ Дж</span><br>'
+ '<b>Больше у: ' + winner + '</b>';
renderMath(document.getElementById('p41s-info'));
}
['p41s-mA-r','p41s-hA-r','p41s-mB-r','p41s-hB-r'].forEach(id => document.getElementById(id).addEventListener('input', draw41s));
draw41s();
wireDnd('p41-dnd', [
{ id:'a1', cat:'small' },{ id:'a2', cat:'small' },{ id:'a3', cat:'mid' },
{ id:'a4', cat:'mid' },{ id:'a5', cat:'big' },{ id:'a6', cat:'big' }
]);
wireQuiz('p41-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p41'); });
wireReadBtn('p41');
renderMath(body);
}
/* ========================================================== */
/* §42 — ЗАКОН СОХРАНЕНИЯ МЕХАНИЧЕСКОЙ ЭНЕРГИИ */
/* ГЛАВНЫЙ ВИЗУАЛ КУРСА: HillSlideSim + PendulumSim */
/* ========================================================== */
function add_p42(){
const body = document.getElementById('p42-body');
if(!body) return;
let h = '';
h += makeCard('theory', 'Полная механическая энергия', '§ 42.1',
'<b>Полная механическая энергия</b> тела — сумма кинетической и потенциальной:<br>'
+ '$$E = E_к + E_п = \\dfrac{mv^2}{2} + mgh$$<br>'
+ '<b>Закон сохранения механической энергии:</b><br>'
+ 'Если на тело действуют <b>только консервативные силы</b> (тяжесть, упругость), то его полная механическая энергия <b>сохраняется</b>:<br>'
+ '$$E = E_к + E_п = \\text{const}$$');
h += makeCard('rule', 'Что происходит при движении', '§ 42.2',
'<ul style="padding-left:20px;margin:6px 0">'
+ '<li>Тело <b>падает</b>: $h \\downarrow \\Rightarrow E_п \\downarrow$, но $v \\uparrow \\Rightarrow E_к \\uparrow$. Сумма $E$ не меняется!</li>'
+ '<li>Тело <b>подбрасывают</b>: $v \\downarrow \\Rightarrow E_к \\downarrow$, $h \\uparrow \\Rightarrow E_п \\uparrow$.</li>'
+ '<li>В <b>верхней точке</b> траектории $v = 0 \\Rightarrow E_к = 0$, вся энергия — потенциальная.</li>'
+ '<li>В <b>самой низкой точке</b> траектории $h = 0 \\Rightarrow E_п = 0$, вся энергия — кинетическая.</li>'
+ '</ul>');
h += makeCard('example', 'Свободное падение', '§ 42.3',
'Камень $m = 0{,}5$ кг падает с высоты $h_0 = 10$ м без сопротивления воздуха.<br>'
+ 'В начале: $E_п = mgh_0 = 50$ Дж, $E_к = 0$. Полная $E = 50$ Дж.<br>'
+ 'У земли ($h = 0$): $E_п = 0$, $E_к = 50$ Дж.<br>'
+ '$\\dfrac{mv^2}{2} = 50 \\Rightarrow v = \\sqrt{2 \\cdot 50/0{,}5} = \\sqrt{200} \\approx 14{,}1$ м/с.<br><br>'
+ '<b>В присутствии трения</b> часть энергии превращается в тепло. Тогда $E_к + E_п < E_0$.');
/* IV-1 ГЛАВНЫЙ ВИЗУАЛ — горка с тележкой */
h += wgWrap('p42-iv1', 'СИМ', 'Главный визуал курса: тележка скатывается с горки', 'Запусти симуляцию и наблюдай, как $E_п$ превращается в $E_к$. С трением — часть переходит в тепло.',
'<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:8px;margin-bottom:10px">'
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:7px 11px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Высота $h_0$, м: <b id="p42-h" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">5</b><input type="range" id="p42-h-r" min="1" max="10" step="0.5" value="5" style="display:block;width:100%;margin-top:5px;accent-color:' + ACCENT + '"></label>'
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:7px 11px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Масса $m$, кг: <b id="p42-m" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">1</b><input type="range" id="p42-m-r" min="0.5" max="5" step="0.5" value="1" style="display:block;width:100%;margin-top:5px;accent-color:' + ACCENT + '"></label>'
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:7px 11px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Трение: <b id="p42-fr" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">0</b><input type="range" id="p42-fr-r" min="0" max="50" step="5" value="0" style="display:block;width:100%;margin-top:5px;accent-color:' + ACCENT + '"></label>'
+ '<div style="display:flex;gap:6px;align-items:end"><button id="p42-go" type="button" style="background:linear-gradient(135deg,' + ACCENT + ',' + ACCENT_D + ');color:#fff;border:none;padding:8px 18px;border-radius:9px;cursor:pointer;font-weight:700;font-family:inherit;font-size:.88rem">Запустить</button><button id="p42-reset" type="button" style="background:#fff;border:1.5px solid ' + ACCENT_SOFT + ';padding:8px 14px;border-radius:9px;cursor:pointer;font-family:inherit;font-weight:600;font-size:.84rem">Сброс</button></div>'
+ '</div>'
+ '<svg id="p42-svg" viewBox="0 0 380 240" width="100%" style="max-width:600px;display:block;margin:0 auto;background:#ecfdf5;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>'
+ '<div id="p42-bars" style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:6px;margin-top:8px">'
+ '<div style="text-align:center"><div style="font-size:.8rem;color:#dc2626;font-weight:700">$E_к$</div><div style="height:14px;background:#fee2e2;border-radius:4px;overflow:hidden;margin-top:2px"><div id="p42-bar-Ek" style="height:100%;width:0;background:#dc2626;transition:width .2s"></div></div><div id="p42-Ek-val" style="font-size:.78rem;color:#7f1d1d;margin-top:2px;font-family:JetBrains Mono,monospace">0 Дж</div></div>'
+ '<div style="text-align:center"><div style="font-size:.8rem;color:#7c3aed;font-weight:700">$E_п$</div><div style="height:14px;background:#ede9fe;border-radius:4px;overflow:hidden;margin-top:2px"><div id="p42-bar-Ep" style="height:100%;width:100%;background:#7c3aed;transition:width .2s"></div></div><div id="p42-Ep-val" style="font-size:.78rem;color:#5b21b6;margin-top:2px;font-family:JetBrains Mono,monospace">0 Дж</div></div>'
+ '<div style="text-align:center"><div style="font-size:.8rem;color:#10b981;font-weight:700">$E_к + E_п$</div><div style="height:14px;background:#d1fae5;border-radius:4px;overflow:hidden;margin-top:2px"><div id="p42-bar-Et" style="height:100%;width:100%;background:#10b981;transition:width .2s"></div></div><div id="p42-Et-val" style="font-size:.78rem;color:#047857;margin-top:2px;font-family:JetBrains Mono,monospace">0 Дж</div></div>'
+ '</div>');
/* IV-2 СИМ маятник */
h += wgWrap('p42-iv2', 'СИМ', 'Маятник: вечный обмен энергиями', 'В крайних точках вся энергия потенциальная; в нижней — вся кинетическая.',
'<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">'
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:7px 11px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Угол отклонения, °: <b id="p42p-a" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">25</b><input type="range" id="p42p-a-r" min="5" max="45" step="1" value="25" style="display:block;width:100%;margin-top:5px;accent-color:' + ACCENT + '"></label>'
+ '<div style="display:flex;gap:6px;align-items:end"><button id="p42p-go" type="button" style="background:linear-gradient(135deg,' + ACCENT + ',' + ACCENT_D + ');color:#fff;border:none;padding:8px 18px;border-radius:9px;cursor:pointer;font-weight:700;font-family:inherit;font-size:.88rem">Старт / Сброс</button></div>'
+ '</div>'
+ '<svg id="p42p-svg" viewBox="0 0 320 200" width="100%" style="max-width:400px;display:block;margin:0 auto;background:#ecfdf5;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>'
+ '<div id="p42p-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:10px 14px;margin-top:8px;font-size:.92rem;text-align:center"></div>');
/* IV-3 квиз/DnD */
h += wgWrap('p42-iv3', 'КВИЗ', 'Закон сохранения', '',
'<div id="p42-q-host">'
+ quizQuestion('p42-q', 0, 'Камень падает (без сопротивления). $E_к$ и $E_п$ изменяются как?', ['Обе растут','$E_к$ растёт, $E_п$ падает','Обе падают','$E_к$ падает, $E_п$ растёт'], 1)
+ quizQuestion('p42-q', 1, 'В нижней точке маятника:', ['Вся энергия потенциальная','Вся энергия кинетическая','Равно поровну','Нулевая'], 1)
+ quizQuestion('p42-q', 2, 'При наличии трения $E_к + E_п$:', ['Растёт','Сохраняется','Уменьшается (уходит в тепло)','Становится нулевой'], 2)
+ quizQuestion('p42-q', 3, 'Камень брошен вверх со скоростью $v$. На какой высоте $E_к = 0$?', ['На земле','На максимальной высоте','В любой точке','Нигде'], 1, 'В верхней точке $v = 0$, вся энергия — потенциальная.')
+ '</div>');
/* IV-4 ТРН */
h += wgWrap('p42-iv4', 'ТРН', 'Тренажёр §42', '',
'<div id="p42-tr-host">'
+ quizQuestion('p42-tr', 0, 'Камень $m = 1$ кг падает с $h = 5$ м (g=10, нет трения). $v$ у земли?', ['5 м/с','10 м/с','15 м/с','20 м/с'], 1, '$mgh = mv^2/2$, $v = \\sqrt{2gh} = \\sqrt{100} = 10$ м/с.')
+ quizQuestion('p42-tr', 1, 'Бросили мяч вверх с $v_0 = 20$ м/с (g=10). Макс. высота?', ['10 м','15 м','20 м','40 м'], 2, '$v_0^2/2 = gh$, $h = v_0^2/(2g) = 400/20 = 20$ м.')
+ quizQuestion('p42-tr', 2, 'Шар на верху горки $E_п = 100$ Дж, $E_к = 0$. В середине $E_к = 40$ Дж. $E_п$ в этом месте?', ['40 Дж','60 Дж','100 Дж','140 Дж'], 1, '$E_к + E_п = 100 \\Rightarrow E_п = 60$ Дж (без потерь).')
+ quizQuestion('p42-tr', 3, 'То же, но с трением: $E_к = 30$ Дж в середине, $E_п = 50$ Дж. Сколько ушло в трение?', ['10 Дж','20 Дж','30 Дж','40 Дж'], 1, '$100 - (30+50) = 20$ Дж.')
+ quizQuestion('p42-tr', 4, 'Тело $m = 0{,}2$ кг с $h = 10$ м. $v$ у земли (без трения, g=10)?', ['10 м/с','14,1 м/с','20 м/с','100 м/с'], 1, '$v = \\sqrt{2gh} = \\sqrt{200} \\approx 14{,}1$ м/с (не зависит от $m$).')
+ '</div>');
h += readButton('p42');
body.innerHTML = h;
// §42 IV-1 — Hill sim
let hill = null, hillRaf = 0, hillRunning = false;
function initHill(){
if(!window.PHYS || !window.PHYS.HillSlideSim) return;
const h0 = +document.getElementById('p42-h-r').value;
const m = +document.getElementById('p42-m-r').value;
const fr = +document.getElementById('p42-fr-r').value / 100;
hill = new window.PHYS.HillSlideSim({ x0: 30, y0: 200, hStart: h0, mass: m, friction: fr, g: 10, scale: 22 });
drawHill();
}
function drawHill(){
const svg = document.getElementById('p42-svg');
if(!svg || !hill) return;
svg.innerHTML = hill.renderProfile();
const E = hill.getEnergies();
const Etot0 = hill.m * hill.g * hill.hStart;
const ratio = (v) => Math.max(0, Math.min(100, v / Etot0 * 100));
document.getElementById('p42-bar-Ek').style.width = ratio(E.Ek) + '%';
document.getElementById('p42-bar-Ep').style.width = ratio(E.Ep) + '%';
document.getElementById('p42-bar-Et').style.width = ratio(E.Etot) + '%';
document.getElementById('p42-Ek-val').textContent = E.Ek.toFixed(1) + ' Дж';
document.getElementById('p42-Ep-val').textContent = E.Ep.toFixed(1) + ' Дж';
document.getElementById('p42-Et-val').textContent = E.Etot.toFixed(1) + ' Дж';
}
function hillLoop(){
if(!hill || !hillRunning){ return; }
hill.step(0.05);
drawHill();
if(hill.h > 0.01){
hillRaf = requestAnimationFrame(hillLoop);
} else {
hillRunning = false;
}
}
['p42-h-r','p42-m-r','p42-fr-r'].forEach(id => document.getElementById(id).addEventListener('input', () => {
document.getElementById('p42-h').textContent = document.getElementById('p42-h-r').value;
document.getElementById('p42-m').textContent = document.getElementById('p42-m-r').value;
document.getElementById('p42-fr').textContent = document.getElementById('p42-fr-r').value;
if(!hillRunning) initHill();
}));
document.getElementById('p42-go').addEventListener('click', () => {
if(hillRunning) return;
if(!hill || hill.h < 0.01) initHill();
hillRunning = true;
if(hillRaf) cancelAnimationFrame(hillRaf);
hillLoop();
});
document.getElementById('p42-reset').addEventListener('click', () => {
hillRunning = false;
if(hillRaf) cancelAnimationFrame(hillRaf);
initHill();
});
initHill();
// §42 IV-2 — Pendulum
let pend = null, pendRaf = 0, pendRunning = false;
function initPend(){
if(!window.PHYS || !window.PHYS.PendulumSim) return;
const ang = +document.getElementById('p42p-a-r').value;
pend = new window.PHYS.PendulumSim({ cx: 160, cy: 30, length: 1.5, mass: 0.5, angleDeg: ang, g: 10, scale: 90 });
drawPend();
}
function drawPend(){
const svg = document.getElementById('p42p-svg');
if(!svg || !pend) return;
svg.innerHTML = pend.render();
const E = pend.getEnergies();
document.getElementById('p42p-info').innerHTML = '$E_к = ' + E.Ek.toFixed(2) + '$ Дж &middot; $E_п = ' + E.Ep.toFixed(2) + '$ Дж &middot; <b>$E_{полн} = ' + E.Etot.toFixed(2) + '$ Дж</b> (сохраняется!)';
renderMath(document.getElementById('p42p-info'));
}
function pendLoop(){
if(!pend || !pendRunning) return;
for(let i = 0; i < 3; i++) pend.step(0.02);
drawPend();
pendRaf = requestAnimationFrame(pendLoop);
}
document.getElementById('p42p-go').addEventListener('click', () => {
pendRunning = false;
if(pendRaf) cancelAnimationFrame(pendRaf);
initPend();
pendRunning = true;
pendLoop();
});
document.getElementById('p42p-a-r').addEventListener('input', () => {
document.getElementById('p42p-a').textContent = document.getElementById('p42p-a-r').value;
if(!pendRunning) initPend();
});
initPend();
wireQuiz('p42-q-host', () => { if(window.addXp) window.addXp(10, 'q-p42'); });
wireQuiz('p42-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p42'); });
wireReadBtn('p42');
renderMath(body);
}
/* ========================================================== */
/* Финал главы 5 — 7 боссов + ачивка «Энергетик» */
/* ========================================================== */
function add_final5(){
const body = document.getElementById('final5-body');
if(!body) return;
let h = '';
h += '<div style="background:linear-gradient(135deg,' + ACCENT_SOFT + ',#ecfccb);border:1.5px solid ' + ACCENT + ';border-radius:14px;padding:16px;margin-bottom:14px;text-align:center">'
+ '<div style="font-family:Unbounded,sans-serif;font-weight:800;font-size:1.12rem;color:' + ACCENT_D + '">Финал главы 5: победи 7 боссов</div>'
+ '<div style="font-size:.88rem;color:#475569;margin-top:5px">Реши все 7 задач — получишь ачивку «Энергетик» и +50 XP.</div>'
+ '<div style="height:10px;background:#fff;border-radius:6px;overflow:hidden;margin-top:12px;border:1px solid ' + ACCENT_SOFT + '"><div id="ch5-fin-fill" style="height:100%;background:linear-gradient(90deg,' + ACCENT + ',' + ACCENT_D + ');width:0%;transition:width .4s"></div></div>'
+ '<div id="ch5-fin-lab" style="font-size:.84rem;color:#475569;margin-top:6px">Побеждено: 0 / 7</div>'
+ '</div>';
const bosses = [
{ n:1, tag:'§36', title:'Работа',
q:'$F = 120$ Н, $s = 8$ м. Работа $A$ в Дж?',
hint:'$A = F s = 120 \\cdot 8 = 960$ Дж.',
ans:960, tol:5, step:'1' },
{ n:2, tag:'§37', title:'КПД',
q:'$A_{полез} = 240$ Дж, $A_{полн} = 300$ Дж. КПД в %?',
hint:'$\\eta = 240/300 \\cdot 100 = 80$ %.',
ans:80, tol:1, step:'1' },
{ n:3, tag:'§38', title:'Мощность',
q:'$A = 9000$ Дж за $t = 30$ с. Мощность $P$ в Вт?',
hint:'$P = A/t = 9000/30 = 300$ Вт.',
ans:300, tol:3, step:'1' },
{ n:4, tag:'§39', title:'Кинетическая энергия',
q:'$m = 2$ кг, $v = 5$ м/с. $E_к$ в Дж?',
hint:'$E_к = mv^2/2 = 2 \\cdot 25/2 = 25$ Дж.',
ans:25, tol:0.5, step:'0.5' },
{ n:5, tag:'§41', title:'Потенциальная энергия',
q:'$m = 4$ кг, $h = 6$ м, $g = 10$. $E_п$ в Дж?',
hint:'$E_п = mgh = 4 \\cdot 10 \\cdot 6 = 240$ Дж.',
ans:240, tol:2, step:'1' },
{ n:6, tag:'§42', title:'Закон сохранения',
q:'Камень $m = 0{,}5$ кг падает с $h = 20$ м без сопротивления ($g = 10$). Скорость $v$ у земли в м/с?',
hint:'$mgh = mv^2/2 \\Rightarrow v = \\sqrt{2gh} = \\sqrt{400} = 20$ м/с.',
ans:20, tol:0.3, step:'0.1' },
{ n:7, tag:'синтез', title:'Энергетик',
q:'Тележка $m = 1$ кг скатывается с горки высотой $h_0 = 4$ м (g=10). На дне измерено $v = 8$ м/с. Сколько энергии в Дж потеряно на трение?',
hint:'$E_0 = mgh_0 = 40$ Дж. На дне $E_к = mv^2/2 = 32$ Дж. Потеряно: $40 - 32 = 8$ Дж.',
ans:8, tol:0.2, step:'0.1' }
];
const STATE_KEY = 'physics7_ch5_final_bosses';
let solved = {};
try{ solved = JSON.parse(localStorage.getItem(STATE_KEY) || '{}') || {}; }catch(e){}
bosses.forEach(b => {
const isSolved = !!solved[b.n];
h += '<div data-boss="' + b.n + '" style="background:#fff;border:2px solid ' + (isSolved ? '#10b981' : ACCENT_SOFT) + ';border-radius:12px;padding:14px 16px;margin-bottom:12px;box-shadow:' + (isSolved ? '0 0 0 3px rgba(16,185,129,.16)' : '0 2px 8px rgba(0,0,0,.05)') + '">'
+ '<div style="display:flex;align-items:center;gap:10px;margin-bottom:8px;flex-wrap:wrap">'
+ '<span style="background:' + ACCENT + ';color:#fff;padding:3px 10px;border-radius:99px;font-size:.7rem;font-weight:800;letter-spacing:.04em">' + b.tag + '</span>'
+ '<span style="font-family:Unbounded,sans-serif;font-weight:800;font-size:.96rem;color:#0f172a">Босс ' + b.n + '. ' + b.title + '</span>'
+ '</div>'
+ '<div style="padding:10px 12px;background:' + ACCENT_SOFT + ';border-radius:8px;margin-bottom:10px;font-size:.94rem;line-height:1.55">' + b.q + '</div>'
+ '<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center">'
+ '<input type="number" step="' + b.step + '" class="boss-inp" data-n="' + b.n + '" placeholder="число" style="padding:8px 12px;border:1.5px solid ' + ACCENT_SOFT + ';border-radius:8px;width:140px;text-align:center;font-family:JetBrains Mono,monospace;font-size:.95rem"' + (isSolved ? ' value="' + b.ans + '" disabled' : '') + '>'
+ '<button class="boss-go" data-n="' + b.n + '" type="button" style="background:linear-gradient(135deg,' + ACCENT + ',' + ACCENT_D + ');color:#fff;border:none;padding:8px 16px;border-radius:9px;font-weight:700;font-size:.88rem;cursor:pointer;font-family:inherit"' + (isSolved ? ' disabled' : '') + '>Атаковать</button>'
+ '<button class="boss-hint" data-n="' + b.n + '" type="button" style="background:#fff;color:#475569;border:1.5px solid ' + ACCENT_SOFT + ';padding:8px 14px;border-radius:9px;font-weight:600;font-size:.86rem;cursor:pointer;font-family:inherit">Подсказка</button>'
+ '</div>'
+ '<div class="boss-hint-txt" data-n="' + b.n + '" style="margin-top:8px;padding:9px 13px;background:#fef3c7;border-left:3px solid #f59e0b;border-radius:6px;font-size:.86rem;line-height:1.5;display:none">' + b.hint + '</div>'
+ '<div class="boss-fb" data-n="' + b.n + '" style="margin-top:8px;padding:9px 13px;border-radius:8px;font-weight:600;font-size:.88rem;line-height:1.45;' + (isSolved ? 'background:#d1fae5;color:#065f46;border-left:4px solid #10b981' : 'display:none') + '">' + (isSolved ? '&#10003; Босс повержен! +20 XP.' : '') + '</div>'
+ '</div>';
});
h += '<div id="ch5-mastered" style="margin-top:14px;padding:14px 18px;border-radius:12px;background:linear-gradient(135deg,#fef3c7,#fde68a);border:1.5px solid #f59e0b;display:none;align-items:center;gap:12px"><svg style="width:32px;height:32px;stroke:#92400e;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round" viewBox="0 0 24 24"><polygon points="12,2 15,9 22,9.3 17,14 18.5,21 12,17 5.5,21 7,14 2,9.3 9,9"/></svg><div style="flex:1"><div style="font-weight:800;color:#92400e;font-family:Unbounded,sans-serif">Ачивка «Энергетик» получена!</div><div style="font-size:.86rem;color:#78350f;margin-top:2px">+50 XP &middot; Глава 5 полностью пройдена.</div></div></div>';
body.innerHTML = h;
renderMath(body);
function updateBar(){
const cnt = bosses.filter(b => solved[b.n]).length;
document.getElementById('ch5-fin-fill').style.width = (cnt * 100 / bosses.length) + '%';
document.getElementById('ch5-fin-lab').textContent = 'Побеждено: ' + cnt + ' / ' + bosses.length;
if(cnt === bosses.length){
document.getElementById('ch5-mastered').style.display = 'flex';
const ACH_KEY = 'physics7_ch5_master';
if(localStorage.getItem(ACH_KEY) !== '1'){
localStorage.setItem(ACH_KEY, '1');
if(window.addXp) window.addXp(50, 'ach-ch5-master');
if(window.achievement) window.achievement('ch_done', 'Энергетик');
}
}
}
updateBar();
body.querySelectorAll('.boss-hint').forEach(btn => btn.addEventListener('click', () => {
const n = btn.dataset.n;
const txt = body.querySelector('.boss-hint-txt[data-n="' + n + '"]');
if(txt) txt.style.display = txt.style.display === 'none' ? 'block' : 'none';
}));
body.querySelectorAll('.boss-go').forEach(btn => btn.addEventListener('click', () => {
const n = +btn.dataset.n;
const b = bosses.find(x => x.n === n);
const inp = body.querySelector('.boss-inp[data-n="' + n + '"]');
const fb = body.querySelector('.boss-fb[data-n="' + n + '"]');
const card = body.querySelector('[data-boss="' + n + '"]');
const v = parseFloat((inp.value || '').replace(',', '.'));
if(isNaN(v)){
fb.style.display = 'block';
fb.style.background = '#fee2e2'; fb.style.color = '#7f1d1d'; fb.style.borderLeft = '4px solid #dc2626';
fb.textContent = 'Введи число.';
return;
}
if(Math.abs(v - b.ans) < b.tol){
fb.style.display = 'block';
fb.style.background = '#d1fae5'; fb.style.color = '#065f46'; fb.style.borderLeft = '4px solid #10b981';
fb.innerHTML = '&#10003; Босс повержен! +20 XP.';
card.style.border = '2px solid #10b981';
card.style.boxShadow = '0 0 0 3px rgba(16,185,129,.16)';
btn.disabled = true; inp.disabled = true;
if(!solved[n]){
solved[n] = true;
try{ localStorage.setItem(STATE_KEY, JSON.stringify(solved)); }catch(e){}
if(window.addXp) window.addXp(20, 'boss-ch5-' + n);
updateBar();
}
} else {
fb.style.display = 'block';
fb.style.background = '#fee2e2'; fb.style.color = '#7f1d1d'; fb.style.borderLeft = '4px solid #dc2626';
fb.textContent = 'Не то. Перепроверь решение.';
}
}));
body.querySelectorAll('.boss-inp').forEach(inp => inp.addEventListener('keydown', e => {
if(e.key === 'Enter'){ e.preventDefault(); body.querySelector('.boss-go[data-n="' + inp.dataset.n + '"]').click(); }
}));
}
window.PHYS7_CH5_WIDGETS = {
p36: add_p36,
p37: add_p37,
p38: add_p38,
p39: add_p39,
p40: add_p40,
p41: add_p41,
p42: add_p42,
final5: add_final5
};
})();