Files
Learn_System/frontend/js/phys9_ch5_widgets.js
T
Maxim Dolgolyov 70aad6a423 feat(phys9 ch5): добавлены 12 виджетов Wave E — Лабораторный практикум
Новый модуль frontend/js/phys9_ch5_widgets.js — экспортирует
window.PHYS9_CH5_WIDGETS = { lr1..lr12: fn }.

Каждая ЛР содержит:
- 2-4 slider'а с параметрами измерений
- Автоматический расчёт результата
- Кнопка «Сдать работу (+30 XP)» с интеграцией в XP-систему

Виджеты:
- ЛР 1: средняя скорость на 2 участках
- ЛР 2: ускорение через 2 измерения s/t²
- ЛР 3: a_n по 10 оборотам шарика на нити
- ЛР 4: g через период математического маятника + погрешность
- ЛР 5: проекции силы на наклонной (F‖, F⊥)
- ЛР 6: g = 2h/t² свободное падение + погрешность
- ЛР 7: ЗСМЭ — сравнение Ep и Ek с расчётом потерь
- ЛР 8: F_A и V тела (вес в воздухе и в воде)
- ЛР 9: условие плавания — доля погружения, статус
- ЛР 10: равновесие рычага — l₂ для баланса
- ЛР 11: КПД наклонной — A_пол/A_зат
- ЛР 12: жёсткость пружины k через период

Подключено в physics_9_ch5.html через ensureBuilt hook.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 09:53:29 +03:00

430 lines
25 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.
// phys9_ch5_widgets.js — виджеты для Физики 9, Глава 5 (ЛР 1-12).
(function(){
'use strict';
function wgWrapper(secId, badge, title, help, body){
return '<div class="wg" id="'+secId+'"><div class="wg-header"><span class="wg-badge">'+badge+'</span><div class="wg-title">'+title+'</div></div><div class="wg-help">'+help+'</div>'+body+'</div>';
}
function appendTo(secId, html){
const box = document.getElementById(secId+'-body');
if(!box) return false;
if(box.querySelector('.wg-phys9-extra-'+secId)) return false;
const div = document.createElement('div'); div.className = 'wg-phys9-extra-'+secId; div.innerHTML = html;
box.appendChild(div);
try { if(window.renderMathInElement) window.renderMathInElement(box); } catch(e){}
return true;
}
function wireSubmit(id){
const btn = document.getElementById(id+'-sub'); if(!btn) return;
btn.addEventListener('click', ()=>{
const fb = document.getElementById(id+'-fb');
fb.className='feedback ok';
fb.innerHTML='&#10003; Работа сдана! +30 XP. Молодец, лаборант!';
btn.disabled = true; btn.style.opacity = 0.6;
try { if(window.addXp) window.addXp(30, id); } catch(e){}
});
}
/* === ЛР 1. Определение средней скорости === */
function add_lr1(){
const body = '<div class="sliders">'
+'<label>$s_1$ м: <b id="lr1w-s1">1.0</b><input type="range" id="lr1w-s1-r" min="0.2" max="3" step="0.1" value="1"></label>'
+'<label>$t_1$ с: <b id="lr1w-t1">2.0</b><input type="range" id="lr1w-t1-r" min="0.5" max="5" step="0.1" value="2"></label>'
+'<label>$s_2$ м: <b id="lr1w-s2">2.0</b><input type="range" id="lr1w-s2-r" min="0.2" max="5" step="0.1" value="2"></label>'
+'<label>$t_2$ с: <b id="lr1w-t2">3.0</b><input type="range" id="lr1w-t2-r" min="0.5" max="6" step="0.1" value="3"></label>'
+'</div>'
+'<div class="score-display" style="flex-direction:column;align-items:flex-start;gap:4px">'
+'<span>Полный путь $s$ = <b id="lr1w-s">3.0</b> м, время $t$ = <b id="lr1w-t">5.0</b> с</span>'
+'<span>$\\langle v\\rangle = s/t$ = <b id="lr1w-vv">0.60</b> м/с</span>'
+'</div>'
+'<div class="actions"><button class="btn primary" id="lr1-sub">Сдать работу (+30 XP)</button></div>'
+'<div class="feedback" id="lr1-fb"></div>';
if(appendTo('lr1', wgWrapper('lr1-extra', 'ЛР 1', 'Определение средней скорости', 'Засеки время на 2 участках, рассчитай среднюю скорость.', body))){
const upd = ()=>{
const s1 = +document.getElementById('lr1w-s1-r').value;
const t1 = +document.getElementById('lr1w-t1-r').value;
const s2 = +document.getElementById('lr1w-s2-r').value;
const t2 = +document.getElementById('lr1w-t2-r').value;
document.getElementById('lr1w-s1').textContent = s1.toFixed(2);
document.getElementById('lr1w-t1').textContent = t1.toFixed(2);
document.getElementById('lr1w-s2').textContent = s2.toFixed(2);
document.getElementById('lr1w-t2').textContent = t2.toFixed(2);
const s = s1+s2, t = t1+t2;
document.getElementById('lr1w-s').textContent = s.toFixed(2);
document.getElementById('lr1w-t').textContent = t.toFixed(2);
document.getElementById('lr1w-vv').textContent = (s/t).toFixed(2);
};
['lr1w-s1-r','lr1w-t1-r','lr1w-s2-r','lr1w-t2-r'].forEach(id=>document.getElementById(id).addEventListener('input', upd));
upd();
wireSubmit('lr1');
}
}
/* === ЛР 2. Изучение равноускоренного движения === */
function add_lr2(){
const body = '<div class="sliders">'
+'<label>Длина 1: $s_1$ м: <b id="lr2w-s1">0.5</b><input type="range" id="lr2w-s1-r" min="0.1" max="2" step="0.05" value="0.5"></label>'
+'<label>$t_1$ с: <b id="lr2w-t1">1.0</b><input type="range" id="lr2w-t1-r" min="0.2" max="3" step="0.05" value="1"></label>'
+'<label>Длина 2: $s_2$ м: <b id="lr2w-s2">2.0</b><input type="range" id="lr2w-s2-r" min="0.5" max="5" step="0.1" value="2"></label>'
+'<label>$t_2$ с: <b id="lr2w-t2">2.0</b><input type="range" id="lr2w-t2-r" min="0.5" max="5" step="0.05" value="2"></label>'
+'</div>'
+'<div class="score-display" style="flex-direction:column;align-items:flex-start;gap:4px">'
+'<span>$a = 2 s_1 / t_1^2$ = <b id="lr2w-a1">1.0</b> м/с² (по 1-му)</span>'
+'<span>$a = 2 s_2 / t_2^2$ = <b id="lr2w-a2">1.0</b> м/с² (по 2-му)</span>'
+'<span>Среднее: $a$ = <b id="lr2w-a">1.0</b> м/с²</span>'
+'</div>'
+'<div class="actions"><button class="btn primary" id="lr2-sub">Сдать работу (+30 XP)</button></div>'
+'<div class="feedback" id="lr2-fb"></div>';
if(appendTo('lr2', wgWrapper('lr2-extra', 'ЛР 2', 'Равноускоренное движение', 'Тележка скатывается с начала и проходит $s_1$ за $t_1$, потом $s_2$ за $t_2$ от старта. $a = 2s/t^2$.', body))){
const upd = ()=>{
const s1 = +document.getElementById('lr2w-s1-r').value;
const t1 = +document.getElementById('lr2w-t1-r').value;
const s2 = +document.getElementById('lr2w-s2-r').value;
const t2 = +document.getElementById('lr2w-t2-r').value;
document.getElementById('lr2w-s1').textContent = s1.toFixed(2);
document.getElementById('lr2w-t1').textContent = t1.toFixed(2);
document.getElementById('lr2w-s2').textContent = s2.toFixed(2);
document.getElementById('lr2w-t2').textContent = t2.toFixed(2);
const a1 = 2*s1/(t1*t1), a2 = 2*s2/(t2*t2);
document.getElementById('lr2w-a1').textContent = a1.toFixed(2);
document.getElementById('lr2w-a2').textContent = a2.toFixed(2);
document.getElementById('lr2w-a').textContent = ((a1+a2)/2).toFixed(2);
};
['lr2w-s1-r','lr2w-t1-r','lr2w-s2-r','lr2w-t2-r'].forEach(id=>document.getElementById(id).addEventListener('input', upd));
upd();
wireSubmit('lr2');
}
}
/* === ЛР 3. Движение по окружности === */
function add_lr3(){
const body = '<div class="sliders">'
+'<label>$R$ м: <b id="lr3w-R">0.3</b><input type="range" id="lr3w-R-r" min="0.05" max="2" step="0.05" value="0.3"></label>'
+'<label>10 оборотов за $t$ с: <b id="lr3w-t">5</b><input type="range" id="lr3w-t-r" min="1" max="30" step="0.5" value="5"></label>'
+'</div>'
+'<div class="score-display" style="flex-direction:column;align-items:flex-start;gap:4px">'
+'<span>$T$ = $t$/10 = <b id="lr3w-T">0.50</b> с</span>'
+'<span>$v$ = $2\\pi R/T$ = <b id="lr3w-v">3.77</b> м/с</span>'
+'<span>$a_n$ = $v^2/R$ = <b id="lr3w-an">47</b> м/с²</span>'
+'</div>'
+'<div class="actions"><button class="btn primary" id="lr3-sub">Сдать работу (+30 XP)</button></div>'
+'<div class="feedback" id="lr3-fb"></div>';
if(appendTo('lr3', wgWrapper('lr3-extra', 'ЛР 3', 'Движение по окружности', 'Измерь время 10 оборотов шарика на нити длиной $R$.', body))){
const upd = ()=>{
const R = +document.getElementById('lr3w-R-r').value;
const t = +document.getElementById('lr3w-t-r').value;
document.getElementById('lr3w-R').textContent = R.toFixed(2);
document.getElementById('lr3w-t').textContent = t.toFixed(2);
const T = t/10;
const v = 2*Math.PI*R/T;
const an = v*v/R;
document.getElementById('lr3w-T').textContent = T.toFixed(2);
document.getElementById('lr3w-v').textContent = v.toFixed(2);
document.getElementById('lr3w-an').textContent = an.toFixed(1);
};
document.getElementById('lr3w-R-r').addEventListener('input', upd);
document.getElementById('lr3w-t-r').addEventListener('input', upd);
upd();
wireSubmit('lr3');
}
}
/* === ЛР 4. Маятник, нахождение g === */
function add_lr4(){
const body = '<div class="sliders">'
+'<label>$l$ нить, м: <b id="lr4w-l">1.0</b><input type="range" id="lr4w-l-r" min="0.1" max="3" step="0.05" value="1"></label>'
+'<label>10 колебаний за $t$ с: <b id="lr4w-t">20.1</b><input type="range" id="lr4w-t-r" min="5" max="40" step="0.1" value="20.1"></label>'
+'</div>'
+'<div class="score-display" style="flex-direction:column;align-items:flex-start;gap:4px">'
+'<span>$T$ = $t/10$ = <b id="lr4w-T">2.01</b> с</span>'
+'<span>$g = 4\\pi^2 l / T^2$ = <b id="lr4w-g">9.77</b> м/с²</span>'
+'<span>Эталон: $9{,}81$ м/с². Погрешность: <b id="lr4w-err">0.4</b>%</span>'
+'</div>'
+'<div class="actions"><button class="btn primary" id="lr4-sub">Сдать работу (+30 XP)</button></div>'
+'<div class="feedback" id="lr4-fb"></div>';
if(appendTo('lr4', wgWrapper('lr4-extra', 'ЛР 4', 'Определение $g$ маятником', 'Засеки время 10 полных колебаний, рассчитай $g$.', body))){
const upd = ()=>{
const l = +document.getElementById('lr4w-l-r').value;
const t = +document.getElementById('lr4w-t-r').value;
document.getElementById('lr4w-l').textContent = l.toFixed(2);
document.getElementById('lr4w-t').textContent = t.toFixed(1);
const T = t/10;
const g = 4*Math.PI*Math.PI*l/(T*T);
const err = Math.abs(g - 9.81)/9.81*100;
document.getElementById('lr4w-T').textContent = T.toFixed(2);
document.getElementById('lr4w-g').textContent = g.toFixed(2);
document.getElementById('lr4w-err').textContent = err.toFixed(1);
};
document.getElementById('lr4w-l-r').addEventListener('input', upd);
document.getElementById('lr4w-t-r').addEventListener('input', upd);
upd();
wireSubmit('lr4');
}
}
/* === ЛР 5. Сила тяги на наклонной === */
function add_lr5(){
const body = '<div class="sliders">'
+'<label>$m$ груза, кг: <b id="lr5w-m">0.2</b><input type="range" id="lr5w-m-r" min="0.05" max="2" step="0.05" value="0.2"></label>'
+'<label>Угол $\\alpha$, &#176;: <b id="lr5w-a">30</b><input type="range" id="lr5w-a-r" min="10" max="60" step="1" value="30"></label>'
+'</div>'
+'<div class="score-display" style="flex-direction:column;align-items:flex-start;gap:4px">'
+'<span>Сила тяжести $P = mg$ = <b id="lr5w-P">1.96</b> Н</span>'
+'<span>Проекция вдоль накл.: $F_\\parallel = mg\\sin\\alpha$ = <b id="lr5w-Fp">0.98</b> Н</span>'
+'<span>Прижим: $F_\\perp = mg\\cos\\alpha$ = <b id="lr5w-Fn">1.70</b> Н</span>'
+'</div>'
+'<div class="actions"><button class="btn primary" id="lr5-sub">Сдать работу (+30 XP)</button></div>'
+'<div class="feedback" id="lr5-fb"></div>';
if(appendTo('lr5', wgWrapper('lr5-extra', 'ЛР 5', 'Силы на наклонной плоскости', 'Изменяй угол, наблюдай как меняются $F_\\parallel$ и $F_\\perp$.', body))){
const upd = ()=>{
const m = +document.getElementById('lr5w-m-r').value;
const a = +document.getElementById('lr5w-a-r').value;
document.getElementById('lr5w-m').textContent = m.toFixed(2);
document.getElementById('lr5w-a').textContent = a;
const g = 9.8;
const P = m*g;
const Fp = P*Math.sin(a*Math.PI/180);
const Fn = P*Math.cos(a*Math.PI/180);
document.getElementById('lr5w-P').textContent = P.toFixed(2);
document.getElementById('lr5w-Fp').textContent = Fp.toFixed(2);
document.getElementById('lr5w-Fn').textContent = Fn.toFixed(2);
};
document.getElementById('lr5w-m-r').addEventListener('input', upd);
document.getElementById('lr5w-a-r').addEventListener('input', upd);
upd();
wireSubmit('lr5');
}
}
/* === ЛР 6. Свободное падение g = 2h/t² === */
function add_lr6(){
const body = '<div class="sliders">'
+'<label>$h$ высота, м: <b id="lr6w-h">2.0</b><input type="range" id="lr6w-h-r" min="0.5" max="10" step="0.1" value="2"></label>'
+'<label>$t$ время, с: <b id="lr6w-t">0.64</b><input type="range" id="lr6w-t-r" min="0.2" max="2" step="0.01" value="0.64"></label>'
+'</div>'
+'<div class="score-display" style="flex-direction:column;align-items:flex-start;gap:4px">'
+'<span>$g = 2h/t^2$ = <b id="lr6w-g">9.77</b> м/с²</span>'
+'<span>Эталон: $9{,}81$. Погрешность: <b id="lr6w-err">0.4</b>%</span>'
+'</div>'
+'<div class="actions"><button class="btn primary" id="lr6-sub">Сдать работу (+30 XP)</button></div>'
+'<div class="feedback" id="lr6-fb"></div>';
if(appendTo('lr6', wgWrapper('lr6-extra', 'ЛР 6', 'Свободное падение', 'Сбрось предмет, засеки время. $g = 2h/t^2$.', body))){
const upd = ()=>{
const h = +document.getElementById('lr6w-h-r').value;
const t = +document.getElementById('lr6w-t-r').value;
document.getElementById('lr6w-h').textContent = h.toFixed(2);
document.getElementById('lr6w-t').textContent = t.toFixed(2);
const g = 2*h/(t*t);
const err = Math.abs(g-9.81)/9.81*100;
document.getElementById('lr6w-g').textContent = g.toFixed(2);
document.getElementById('lr6w-err').textContent = err.toFixed(1);
};
document.getElementById('lr6w-h-r').addEventListener('input', upd);
document.getElementById('lr6w-t-r').addEventListener('input', upd);
upd();
wireSubmit('lr6');
}
}
/* === ЛР 7. Закон сохранения механической энергии === */
function add_lr7(){
const body = '<div class="sliders">'
+'<label>$m$ кг: <b id="lr7w-m">0.1</b><input type="range" id="lr7w-m-r" min="0.05" max="2" step="0.05" value="0.1"></label>'
+'<label>$h$ м: <b id="lr7w-h">0.5</b><input type="range" id="lr7w-h-r" min="0.1" max="3" step="0.05" value="0.5"></label>'
+'<label>Измер. $v_{внизу}$: <b id="lr7w-v">3.0</b><input type="range" id="lr7w-v-r" min="0.5" max="10" step="0.05" value="3"></label>'
+'</div>'
+'<div class="score-display" style="flex-direction:column;align-items:flex-start;gap:4px">'
+'<span>$E_p^{старт} = mgh$ = <b id="lr7w-Ep">0.49</b> Дж</span>'
+'<span>$E_k^{внизу} = mv^2/2$ = <b id="lr7w-Ek">0.45</b> Дж</span>'
+'<span>Сохранение: <b id="lr7w-cons">8%</b> потерь</span>'
+'</div>'
+'<div class="actions"><button class="btn primary" id="lr7-sub">Сдать работу (+30 XP)</button></div>'
+'<div class="feedback" id="lr7-fb"></div>';
if(appendTo('lr7', wgWrapper('lr7-extra', 'ЛР 7', 'ЗСЭ на горке', 'Сравни $E_p$ вверху и $E_k$ внизу.', body))){
const upd = ()=>{
const m = +document.getElementById('lr7w-m-r').value;
const h = +document.getElementById('lr7w-h-r').value;
const v = +document.getElementById('lr7w-v-r').value;
document.getElementById('lr7w-m').textContent = m.toFixed(2);
document.getElementById('lr7w-h').textContent = h.toFixed(2);
document.getElementById('lr7w-v').textContent = v.toFixed(2);
const Ep = m*9.8*h;
const Ek = m*v*v/2;
document.getElementById('lr7w-Ep').textContent = Ep.toFixed(2);
document.getElementById('lr7w-Ek').textContent = Ek.toFixed(2);
const loss = Math.max(0, (Ep-Ek)/Ep*100);
document.getElementById('lr7w-cons').textContent = loss.toFixed(0)+'% потерь';
};
['lr7w-m-r','lr7w-h-r','lr7w-v-r'].forEach(id=>document.getElementById(id).addEventListener('input', upd));
upd();
wireSubmit('lr7');
}
}
/* === ЛР 8. Закон Архимеда === */
function add_lr8(){
const body = '<div class="sliders">'
+'<label>Вес в воздухе $P_1$, Н: <b id="lr8w-P1">2.0</b><input type="range" id="lr8w-P1-r" min="0.5" max="10" step="0.1" value="2"></label>'
+'<label>Вес в воде $P_2$, Н: <b id="lr8w-P2">1.5</b><input type="range" id="lr8w-P2-r" min="0.1" max="10" step="0.1" value="1.5"></label>'
+'</div>'
+'<div class="score-display" style="flex-direction:column;align-items:flex-start;gap:4px">'
+'<span>$F_A = P_1 - P_2$ = <b id="lr8w-Fa">0.50</b> Н</span>'
+'<span>$V = F_A/(\\rho g) = $ <b id="lr8w-V">51</b> см³</span>'
+'</div>'
+'<div class="actions"><button class="btn primary" id="lr8-sub">Сдать работу (+30 XP)</button></div>'
+'<div class="feedback" id="lr8-fb"></div>';
if(appendTo('lr8', wgWrapper('lr8-extra', 'ЛР 8', 'Закон Архимеда', 'Взвешиваем тело в воздухе и в воде, находим $F_A$ и $V$.', body))){
const upd = ()=>{
const P1 = +document.getElementById('lr8w-P1-r').value;
const P2 = +document.getElementById('lr8w-P2-r').value;
document.getElementById('lr8w-P1').textContent = P1.toFixed(2);
document.getElementById('lr8w-P2').textContent = P2.toFixed(2);
const Fa = Math.max(0, P1-P2);
const V_m3 = Fa/(1000*9.8);
document.getElementById('lr8w-Fa').textContent = Fa.toFixed(2);
document.getElementById('lr8w-V').textContent = (V_m3*1e6).toFixed(0);
};
document.getElementById('lr8w-P1-r').addEventListener('input', upd);
document.getElementById('lr8w-P2-r').addEventListener('input', upd);
upd();
wireSubmit('lr8');
}
}
/* === ЛР 9. Плавание тел === */
function add_lr9(){
const body = '<div class="sliders">'
+'<label>$\\rho_{тела}$, кг/м³: <b id="lr9w-rt">700</b><input type="range" id="lr9w-rt-r" min="100" max="15000" step="50" value="700"></label>'
+'<label>$\\rho_{жидк}$, кг/м³: <b id="lr9w-rl">1000</b><input type="range" id="lr9w-rl-r" min="500" max="14000" step="50" value="1000"></label>'
+'</div>'
+'<div class="score-display" style="flex-direction:column;align-items:flex-start;gap:4px">'
+'<span>Доля погружения: <b id="lr9w-h">70</b>%</span>'
+'<span><b id="lr9w-r" style="color:var(--ok)">ПЛАВАЕТ ↑</b></span>'
+'</div>'
+'<div class="actions"><button class="btn primary" id="lr9-sub">Сдать работу (+30 XP)</button></div>'
+'<div class="feedback" id="lr9-fb"></div>';
if(appendTo('lr9', wgWrapper('lr9-extra', 'ЛР 9', 'Условие плавания', '$h_{погр}/h_{тела} = \\rho_{тела}/\\rho_{жидк}$.', body))){
const upd = ()=>{
const rt = +document.getElementById('lr9w-rt-r').value;
const rl = +document.getElementById('lr9w-rl-r').value;
document.getElementById('lr9w-rt').textContent = rt;
document.getElementById('lr9w-rl').textContent = rl;
const h = (rt/rl)*100;
document.getElementById('lr9w-h').textContent = Math.min(100, h).toFixed(0);
const r = document.getElementById('lr9w-r');
if(rt < rl){ r.innerHTML='ПЛАВАЕТ ↑'; r.style.color='var(--ok,#10b981)'; }
else if(Math.abs(rt-rl) < 5){ r.innerHTML='ВЗВЕШЕНО →'; r.style.color='var(--muted)'; }
else { r.innerHTML='ТОНЕТ ↓'; r.style.color='var(--fail,#dc2626)'; }
};
document.getElementById('lr9w-rt-r').addEventListener('input', upd);
document.getElementById('lr9w-rl-r').addEventListener('input', upd);
upd();
wireSubmit('lr9');
}
}
/* === ЛР 10. Равновесие рычага === */
function add_lr10(){
const body = '<div class="sliders">'
+'<label>$F_1$ Н: <b id="lr10w-F1">2</b><input type="range" id="lr10w-F1-r" min="0.5" max="20" step="0.5" value="2"></label>'
+'<label>$l_1$ см: <b id="lr10w-l1">30</b><input type="range" id="lr10w-l1-r" min="5" max="100" step="1" value="30"></label>'
+'<label>$F_2$ Н: <b id="lr10w-F2">3</b><input type="range" id="lr10w-F2-r" min="0.5" max="20" step="0.5" value="3"></label>'
+'</div>'
+'<div class="score-display" style="flex-direction:column;align-items:flex-start;gap:4px">'
+'<span>Для равновесия: $l_2 = F_1 l_1 / F_2$ = <b id="lr10w-l2">20</b> см</span>'
+'<span>Проверка: $F_1 l_1$ = <b id="lr10w-M1">60</b>, $F_2 l_2$ = <b id="lr10w-M2">60</b> (Н·см)</span>'
+'</div>'
+'<div class="actions"><button class="btn primary" id="lr10-sub">Сдать работу (+30 XP)</button></div>'
+'<div class="feedback" id="lr10-fb"></div>';
if(appendTo('lr10', wgWrapper('lr10-extra', 'ЛР 10', 'Равновесие рычага', 'Подбери $l_2$ так чтобы $F_1 l_1 = F_2 l_2$.', body))){
const upd = ()=>{
const F1 = +document.getElementById('lr10w-F1-r').value;
const l1 = +document.getElementById('lr10w-l1-r').value;
const F2 = +document.getElementById('lr10w-F2-r').value;
document.getElementById('lr10w-F1').textContent = F1;
document.getElementById('lr10w-l1').textContent = l1;
document.getElementById('lr10w-F2').textContent = F2;
const l2 = F1*l1/F2;
document.getElementById('lr10w-l2').textContent = l2.toFixed(1);
document.getElementById('lr10w-M1').textContent = (F1*l1).toFixed(1);
document.getElementById('lr10w-M2').textContent = (F2*l2).toFixed(1);
};
['lr10w-F1-r','lr10w-l1-r','lr10w-F2-r'].forEach(id=>document.getElementById(id).addEventListener('input', upd));
upd();
wireSubmit('lr10');
}
}
/* === ЛР 11. КПД наклонной === */
function add_lr11(){
const body = '<div class="sliders">'
+'<label>$m$ кг: <b id="lr11w-m">0.2</b><input type="range" id="lr11w-m-r" min="0.05" max="2" step="0.05" value="0.2"></label>'
+'<label>$h$ м: <b id="lr11w-h">0.3</b><input type="range" id="lr11w-h-r" min="0.05" max="1.5" step="0.05" value="0.3"></label>'
+'<label>$l$ м (длина накл.): <b id="lr11w-l">0.6</b><input type="range" id="lr11w-l-r" min="0.1" max="3" step="0.05" value="0.6"></label>'
+'<label>Сила тяги $F$, Н: <b id="lr11w-F">1.2</b><input type="range" id="lr11w-F-r" min="0.05" max="5" step="0.05" value="1.2"></label>'
+'</div>'
+'<div class="score-display" style="flex-direction:column;align-items:flex-start;gap:4px">'
+'<span>$A_{пол} = mgh$ = <b id="lr11w-Ap">0.59</b> Дж</span>'
+'<span>$A_{зат} = Fl$ = <b id="lr11w-Az">0.72</b> Дж</span>'
+'<span>$\\eta = A_{пол}/A_{зат}$ = <b id="lr11w-eta">82</b>%</span>'
+'</div>'
+'<div class="actions"><button class="btn primary" id="lr11-sub">Сдать работу (+30 XP)</button></div>'
+'<div class="feedback" id="lr11-fb"></div>';
if(appendTo('lr11', wgWrapper('lr11-extra', 'ЛР 11', 'КПД наклонной плоскости', 'Измерь силу тяги динамометром и рассчитай КПД.', body))){
const upd = ()=>{
const m = +document.getElementById('lr11w-m-r').value;
const h = +document.getElementById('lr11w-h-r').value;
const l = +document.getElementById('lr11w-l-r').value;
const F = +document.getElementById('lr11w-F-r').value;
document.getElementById('lr11w-m').textContent = m.toFixed(2);
document.getElementById('lr11w-h').textContent = h.toFixed(2);
document.getElementById('lr11w-l').textContent = l.toFixed(2);
document.getElementById('lr11w-F').textContent = F.toFixed(2);
const Ap = m*9.8*h, Az = F*l;
document.getElementById('lr11w-Ap').textContent = Ap.toFixed(2);
document.getElementById('lr11w-Az').textContent = Az.toFixed(2);
document.getElementById('lr11w-eta').textContent = Az > 0 ? Math.min(100, Math.round(Ap/Az*100)) : 0;
};
['lr11w-m-r','lr11w-h-r','lr11w-l-r','lr11w-F-r'].forEach(id=>document.getElementById(id).addEventListener('input', upd));
upd();
wireSubmit('lr11');
}
}
/* === ЛР 12. Период пружинного маятника === */
function add_lr12(){
const body = '<div class="sliders">'
+'<label>$m$ груза, кг: <b id="lr12w-m">0.2</b><input type="range" id="lr12w-m-r" min="0.05" max="2" step="0.05" value="0.2"></label>'
+'<label>10 колебаний за $t$ с: <b id="lr12w-t">3.0</b><input type="range" id="lr12w-t-r" min="0.5" max="15" step="0.1" value="3"></label>'
+'</div>'
+'<div class="score-display" style="flex-direction:column;align-items:flex-start;gap:4px">'
+'<span>$T = t/10$ = <b id="lr12w-T">0.30</b> с</span>'
+'<span>$k = 4\\pi^2 m / T^2$ = <b id="lr12w-k">88</b> Н/м</span>'
+'</div>'
+'<div class="actions"><button class="btn primary" id="lr12-sub">Сдать работу (+30 XP)</button></div>'
+'<div class="feedback" id="lr12-fb"></div>';
if(appendTo('lr12', wgWrapper('lr12-extra', 'ЛР 12', 'Жёсткость пружины', 'Засеки время 10 колебаний и рассчитай $k$.', body))){
const upd = ()=>{
const m = +document.getElementById('lr12w-m-r').value;
const t = +document.getElementById('lr12w-t-r').value;
document.getElementById('lr12w-m').textContent = m.toFixed(2);
document.getElementById('lr12w-t').textContent = t.toFixed(2);
const T = t/10;
const k = 4*Math.PI*Math.PI*m/(T*T);
document.getElementById('lr12w-T').textContent = T.toFixed(2);
document.getElementById('lr12w-k').textContent = k.toFixed(0);
};
document.getElementById('lr12w-m-r').addEventListener('input', upd);
document.getElementById('lr12w-t-r').addEventListener('input', upd);
upd();
wireSubmit('lr12');
}
}
window.PHYS9_CH5_WIDGETS = {
lr1:add_lr1, lr2:add_lr2, lr3:add_lr3, lr4:add_lr4, lr5:add_lr5, lr6:add_lr6,
lr7:add_lr7, lr8:add_lr8, lr9:add_lr9, lr10:add_lr10, lr11:add_lr11, lr12:add_lr12
};
})();