feat(phys8 ch2): Phase 3 Wave 3 — §23 R=ρl/S + §24 последов./реостат + §25 паралл.
§23 R = ρl/S: - 3 теории: формула, таблица ρ (6 материалов), применение - IV-1: калькулятор с визуализацией провода (длина и толщина меняются на SVG) - IV-2: 6 пар «у какого больше R?» - IV-3: DnD 8 факторов «R растёт/падает» - IV-4: 5 расчётных задач §24 Последовательное соединение. Реостат: - 3 теории: правила, реостат, ёлочная гирлянда - IV-1: ГЛАВНЫЙ ВИЗУАЛ — реостат-симулятор: slider положения движка, яркость лампы меняется с током - IV-2: 3-slider калькулятор послед. цепи (U, R₁, R₂) — I, U₁, U₂ - IV-3: DnD 8 утверждений «верно/неверно» - IV-4: 5 задач (включая «реостат при I=0.2 А») §25 Параллельное соединение: - 3 теории: правила, R = R₁R₂/(R₁+R₂), розетки дома - IV-1: визуальная схема 2 параллельных ветвей с резисторами, токи и общий R рассчитываются - IV-2: 6 раундов «послед. или паралл.?» - IV-3: DnD 8 формул на 2 типа соединения - IV-4: 6 задач (включая утюг+лампа в розетке 220 В) Добавлена константа MAT_RHO (6 материалов). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -386,9 +386,28 @@ const SIDEBARS = {
|
||||
["Больше $U$","больше $I$ (пропорц.)"],
|
||||
["Больше $R$","меньше $I$"]
|
||||
]},
|
||||
p23:{title:"Шпаргалка § 23",rows:[["В разработке","Phase 3 Wave 3"]]},
|
||||
p24:{title:"Шпаргалка § 24",rows:[["В разработке","Phase 3 Wave 3"]]},
|
||||
p25:{title:"Шпаргалка § 25",rows:[["В разработке","Phase 3 Wave 3"]]},
|
||||
p23:{title:"Шпаргалка § 23",rows:[
|
||||
["Формула","$R = \\rho \\, l / S$"],
|
||||
["$\\rho$","удельное сопр., Ом·мм²/м"],
|
||||
["медь","$\\rho = 0{,}017$"],
|
||||
["алюминий","$\\rho = 0{,}028$"],
|
||||
["нихром","$\\rho = 1{,}1$"],
|
||||
["1 Ом","$U=1$ В $\\to I=1$ А"]
|
||||
]},
|
||||
p24:{title:"Шпаргалка § 24",rows:[
|
||||
["Послед. соед.","$I = $ const"],
|
||||
["Напряжение","$U = U_1 + U_2$"],
|
||||
["Сопротивл.","$R = R_1 + R_2$"],
|
||||
["Реостат","переменный резистор"],
|
||||
["Поломка одного","вся цепь обесточена"]
|
||||
]},
|
||||
p25:{title:"Шпаргалка § 25",rows:[
|
||||
["Паралл. соед.","$U = $ const"],
|
||||
["Ток","$I = I_1 + I_2$"],
|
||||
["Сопротивл.","$1/R = 1/R_1 + 1/R_2$"],
|
||||
["Два равных","$R_{общ} = R/2$"],
|
||||
["Поломка одного","остальные работают"]
|
||||
]},
|
||||
p26:{title:"Шпаргалка § 26",rows:[["В разработке","Phase 3 Wave 4"]]},
|
||||
p27:{title:"Шпаргалка § 27",rows:[["В разработке","Phase 3 Wave 4"]]},
|
||||
p28:{title:"Шпаргалка § 28",rows:[["В разработке","Phase 4 Wave 1"]]},
|
||||
@@ -410,9 +429,9 @@ const TIPS=[
|
||||
{sec:'p20',html:"$I = q/t$ — сколько Кулонов прошло через сечение провода за 1 секунду. Единица — <b>Ампер</b> ($1$ А = $1$ Кл/с). За направление тока приняли движение «+» зарядов — хотя в металлах реально двигаются электроны (против тока)."},
|
||||
{sec:'p21',html:"Простейшая цепь: батарея, лампа, ключ, провода. Чтобы измерить ток через лампу — амперметр включают <b>последовательно</b> с лампой. Чтобы измерить напряжение на лампе — вольтметр включают <b>параллельно</b>."},
|
||||
{sec:'p22',html:"Закон Ома для участка цепи: $I = U/R$. Увеличил напряжение в 2 раза — ток вырос в 2 раза. Поставил резистор побольше — ток упал. Прямая зависимость для металлов."},
|
||||
{sec:'p23',html:"Параграф § 23 будет реализован в Phase 3 Wave 3. Используем хелперы из <code>phys.js</code> и <code>optics.js</code>."},
|
||||
{sec:'p24',html:"Параграф § 24 будет реализован в Phase 3 Wave 3. Используем хелперы из <code>phys.js</code> и <code>optics.js</code>."},
|
||||
{sec:'p25',html:"Параграф § 25 будет реализован в Phase 3 Wave 3. Используем хелперы из <code>phys.js</code> и <code>optics.js</code>."},
|
||||
{sec:'p23',html:"Сопротивление провода зависит от трёх вещей: <b>материала</b> ($\\rho$), <b>длины</b> ($l$) и <b>толщины</b> ($S$). Длинный тонкий нихром — большое $R$ (спираль чайника), короткий толстый медный — маленькое $R$ (провод)."},
|
||||
{sec:'p24',html:"При последовательном соединении ток течёт через все элементы один и тот же. Напряжения складываются. Сопротивления складываются. Реостат — переменный резистор, при сдвиге движка меняется длина включённой проволоки."},
|
||||
{sec:'p25',html:"При параллельном соединении на каждой ветви одно и то же напряжение. Токи складываются. Сопротивление считается по особой формуле — в итоге $R_{общ}$ <b>меньше</b> любого из $R_1$, $R_2$."},
|
||||
{sec:'p26',html:"Параграф § 26 будет реализован в Phase 3 Wave 4. Используем хелперы из <code>phys.js</code> и <code>optics.js</code>."},
|
||||
{sec:'p27',html:"Параграф § 27 будет реализован в Phase 3 Wave 4. Используем хелперы из <code>phys.js</code> и <code>optics.js</code>."},
|
||||
{sec:'p28',html:"Параграф § 28 будет реализован в Phase 4 Wave 1. Используем хелперы из <code>phys.js</code> и <code>optics.js</code>."},
|
||||
@@ -434,9 +453,9 @@ const BUILDERS = {
|
||||
p20: ()=>{ build_p20(); },
|
||||
p21: ()=>{ build_p21(); },
|
||||
p22: ()=>{ build_p22(); },
|
||||
p23: ()=>{ const box=document.getElementById('p23-body'); box.innerHTML = buildStub('p23', 'Единица сопротивления. Расчёт сопротивления', 'Phase 3 Wave 3') + secNavFor('p23') + readButton('p23'); renderMath(box); wireReadBtn('p23'); },
|
||||
p24: ()=>{ const box=document.getElementById('p24-body'); box.innerHTML = buildStub('p24', 'Последовательное соединение проводников. Реостат', 'Phase 3 Wave 3') + secNavFor('p24') + readButton('p24'); renderMath(box); wireReadBtn('p24'); },
|
||||
p25: ()=>{ const box=document.getElementById('p25-body'); box.innerHTML = buildStub('p25', 'Параллельное соединение проводников', 'Phase 3 Wave 3') + secNavFor('p25') + readButton('p25'); renderMath(box); wireReadBtn('p25'); },
|
||||
p23: ()=>{ build_p23(); },
|
||||
p24: ()=>{ build_p24(); },
|
||||
p25: ()=>{ build_p25(); },
|
||||
p26: ()=>{ const box=document.getElementById('p26-body'); box.innerHTML = buildStub('p26', 'Работа и мощность электрического тока. Закон Джоуля — Ленца', 'Phase 3 Wave 4') + secNavFor('p26') + readButton('p26'); renderMath(box); wireReadBtn('p26'); },
|
||||
p27: ()=>{ const box=document.getElementById('p27-body'); box.innerHTML = buildStub('p27', 'Использование и экономия электроэнергии. Безопасность', 'Phase 3 Wave 4') + secNavFor('p27') + readButton('p27'); renderMath(box); wireReadBtn('p27'); },
|
||||
p28: ()=>{ const box=document.getElementById('p28-body'); box.innerHTML = buildStub('p28', 'Постоянные магниты', 'Phase 4 Wave 1') + secNavFor('p28') + readButton('p28'); renderMath(box); wireReadBtn('p28'); },
|
||||
@@ -3200,6 +3219,680 @@ function _initP22_tasks(){
|
||||
render();
|
||||
}
|
||||
|
||||
/* ======================================================================
|
||||
PHASE 3 · WAVE 3 — §23, §24, §25
|
||||
====================================================================== */
|
||||
|
||||
const MAT_RHO = [
|
||||
{name:'серебро', rho:0.016},
|
||||
{name:'медь', rho:0.017},
|
||||
{name:'алюминий',rho:0.028},
|
||||
{name:'железо', rho:0.10},
|
||||
{name:'нихром', rho:1.1},
|
||||
{name:'константан', rho:0.5}
|
||||
];
|
||||
|
||||
/* ======== §23 — R = ρl/S ======== */
|
||||
function build_p23(){
|
||||
const box = document.getElementById('p23-body');
|
||||
let h = '';
|
||||
|
||||
h += makeCard('theory', 'Формула сопротивления', '§ 23.1',
|
||||
'<p>Сопротивление проводника зависит от трёх параметров:</p>'
|
||||
+'<p style="text-align:center;margin:8px 0">$$R = \\dfrac{\\rho \\, l}{S}$$</p>'
|
||||
+'<ul style="padding-left:20px;margin:6px 0">'
|
||||
+'<li>$\\rho$ — <b>удельное сопротивление</b>, Ом·мм²/м. Свойство материала.</li>'
|
||||
+'<li>$l$ — длина проводника, м.</li>'
|
||||
+'<li>$S$ — площадь поперечного сечения, мм².</li>'
|
||||
+'</ul>'
|
||||
+'<p>Чем длиннее — тем больше $R$. Чем толще (больше $S$) — тем меньше $R$. Чем «хуже» материал — тем больше $\\rho$.</p>'
|
||||
);
|
||||
h += makeCard('rule', 'Таблица $\\rho$', '§ 23.2',
|
||||
'<table style="width:100%;border-collapse:collapse;font-size:.92rem"><thead><tr style="background:rgba(15,23,42,.04)"><th style="padding:6px;text-align:left">Материал</th><th style="padding:6px;text-align:right">$\\rho$, $\\dfrac{\\text{Ом}\\cdot\\text{мм}^2}{\\text{м}}$</th></tr></thead><tbody>'
|
||||
+ MAT_RHO.map(m=>'<tr><td style="padding:6px;border-bottom:1px dashed var(--border)">'+m.name+'</td><td style="padding:6px;text-align:right;border-bottom:1px dashed var(--border)"><code>'+m.rho+'</code></td></tr>').join('')
|
||||
+'</tbody></table>'
|
||||
+'<p style="margin-top:8px">Для проводов берут медь или алюминий (малое $\\rho$). Для нагревательных спиралей — нихром (большое $\\rho$ → много тепла при том же токе).</p>'
|
||||
);
|
||||
h += makeCard('example', 'Где это применяется', '§ 23.3',
|
||||
'<ul style="padding-left:20px;margin:6px 0">'
|
||||
+'<li>Электропровода — медные, толстые → малое $R$ → малые потери.</li>'
|
||||
+'<li>Нагревательная спираль чайника — длинная и тонкая из нихрома.</li>'
|
||||
+'<li>Линии электропередачи — толстые алюминиевые провода (медь была бы дороже).</li>'
|
||||
+'<li>Удлинители — чем длиннее, тем больше $R$ → больше потерь.</li>'
|
||||
+'</ul>'
|
||||
);
|
||||
|
||||
/* IV1 — калькулятор R = ρl/S */
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-1</span><div class="wg-title">Калькулятор $R = \\rho l / S$</div></div>'
|
||||
+'<div class="wg-help">Выбери материал, длину и сечение — увидь $R$.</div>'
|
||||
+'<div class="sliders" style="margin-bottom:10px">'
|
||||
+'<label>Материал: <select id="p23-mat" class="tinp" style="width:auto;padding:6px 10px;font-size:.92rem">'
|
||||
+ MAT_RHO.map(m=>'<option value="'+m.rho+'">'+m.name+' ($\\rho='+m.rho+'$)</option>').join('')
|
||||
+'</select></label>'
|
||||
+'<label>$l$, м: <b id="p23-lv">10</b><input type="range" id="p23-l" min="0.1" max="100" step="0.5" value="10"></label>'
|
||||
+'<label>$S$, мм²: <b id="p23-sv">1.0</b><input type="range" id="p23-s" min="0.1" max="10" step="0.1" value="1"></label>'
|
||||
+'</div>'
|
||||
+'<svg id="p23-sim" viewBox="0 0 460 140" style="width:100%;height:auto;background:#f8fafc;border-radius:9px;border:1px solid var(--border)"></svg>'
|
||||
+'<div class="score-display" style="margin-top:10px;flex-direction:column;align-items:flex-start;gap:4px">'
|
||||
+'<span>$R = \\rho l / S$ = <b id="p23-rv2">0.17</b> Ом</span>'
|
||||
+'<span style="font-size:.84rem;color:var(--muted)">При $U = 12$ В: $I = U/R = $ <b id="p23-i12">71</b> А.</span>'
|
||||
+'</div>'
|
||||
+'</div>';
|
||||
|
||||
/* IV2 — «больше/меньше R?» */
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-2</span><div class="wg-title">У какого провода $R$ больше?</div></div>'
|
||||
+'<div class="wg-help">Сравни два варианта.</div>'
|
||||
+'<div id="p23-quiz"></div>'
|
||||
+'<div class="actions"><button class="btn" id="p23-quiz-next">Следующий</button></div>'
|
||||
+'<div class="score-display" style="margin-top:10px"><span>Раунд: <b id="p23-quiz-r">1</b> / 6</span><span>Правильно: <b id="p23-quiz-ok">0</b></span></div>'
|
||||
+'</div>';
|
||||
|
||||
/* IV3 — DnD «как изменится R» */
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-3</span><div class="wg-title">Как изменится $R$?</div></div>'
|
||||
+'<div class="wg-help">При изменении параметра.</div>'
|
||||
+'<div id="p23-dnd-pool"></div>'
|
||||
+'<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:10px">'
|
||||
+'<div class="drop-box"><h5>$R$ растёт</h5><div class="drop-items" data-cat="up"></div></div>'
|
||||
+'<div class="drop-box"><h5>$R$ падает</h5><div class="drop-items" data-cat="dn"></div></div>'
|
||||
+'</div>'
|
||||
+'<div class="actions"><button class="btn primary" id="p23-dnd-check">Проверить</button><button class="btn" id="p23-dnd-reset">Сброс</button></div>'
|
||||
+'<div class="feedback" id="p23-dnd-fb"></div>'
|
||||
+'</div>';
|
||||
|
||||
/* IV4 — задачи */
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-4</span><div class="wg-title">Тренажёр: 5 задач</div></div>'
|
||||
+'<div class="wg-help">4+ — +15 XP.</div>'
|
||||
+'<div id="p23-task"></div>'
|
||||
+'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="p23-task-i">1</b> / 5</span><span>Правильно: <b id="p23-task-ok">0</b></span></div>'
|
||||
+'</div>';
|
||||
|
||||
box.innerHTML = h + secNavFor('p23') + readButton('p23');
|
||||
renderMath(box);
|
||||
wireReadBtn('p23');
|
||||
|
||||
_initP23_calc();
|
||||
_initP23_quiz();
|
||||
_initP23_dnd();
|
||||
_initP23_tasks();
|
||||
}
|
||||
|
||||
function _initP23_calc(){
|
||||
const svg = document.getElementById('p23-sim'); if(!svg) return;
|
||||
function update(){
|
||||
const rho = +document.getElementById('p23-mat').value;
|
||||
const l = +document.getElementById('p23-l').value;
|
||||
const S = +document.getElementById('p23-s').value;
|
||||
document.getElementById('p23-lv').textContent = l.toFixed(1);
|
||||
document.getElementById('p23-sv').textContent = S.toFixed(1);
|
||||
const R = rho * l / S;
|
||||
document.getElementById('p23-rv2').textContent = R.toFixed(2);
|
||||
document.getElementById('p23-i12').textContent = (12/R).toFixed(1);
|
||||
/* SVG: провод */
|
||||
let s = '';
|
||||
const lenPx = 60 + Math.min(330, l*3);
|
||||
const wPx = 6 + Math.min(40, S*4);
|
||||
const cy = 70;
|
||||
const xS = 30;
|
||||
s += '<rect x="'+xS+'" y="'+(cy-wPx/2)+'" width="'+lenPx+'" height="'+wPx+'" fill="#cbd5e1" stroke="#0f172a" stroke-width="1.6" rx="3"/>';
|
||||
/* подписи */
|
||||
s += '<text x="'+(xS+lenPx/2)+'" y="'+(cy+wPx/2+18)+'" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="11" fill="#475569">l = '+l.toFixed(1)+' м</text>';
|
||||
s += '<text x="'+(xS+lenPx+12)+'" y="'+(cy+4)+'" font-family="JetBrains Mono,monospace" font-size="11" fill="#475569">S = '+S.toFixed(1)+' мм²</text>';
|
||||
/* формула */
|
||||
s += '<text x="'+(xS)+'" y="120" font-family="JetBrains Mono,monospace" font-size="13" font-weight="700" fill="#0f172a">R = '+rho+' · '+l.toFixed(1)+' / '+S.toFixed(1)+' = '+R.toFixed(2)+' Ом</text>';
|
||||
svg.innerHTML = s;
|
||||
}
|
||||
document.getElementById('p23-mat').addEventListener('change', update);
|
||||
document.getElementById('p23-l').addEventListener('input', update);
|
||||
document.getElementById('p23-s').addEventListener('input', update);
|
||||
update();
|
||||
}
|
||||
|
||||
function _initP23_quiz(){
|
||||
const QS = [
|
||||
{A:'медный провод 10 м', B:'медный провод 20 м', ans:'B', why:'Длиннее — больше $R$.'},
|
||||
{A:'медный провод $S = 1$ мм²', B:'медный провод $S = 2$ мм²', ans:'A', why:'Толще — меньше $R$.'},
|
||||
{A:'нихромовый провод 1 м', B:'медный провод 1 м', ans:'A', why:'Нихром в 65 раз хуже меди по $\\rho$.'},
|
||||
{A:'железный провод', B:'медный провод (тот же)', ans:'A', why:'Железо хуже меди.'},
|
||||
{A:'алюминиевый провод 50 м', B:'медный провод 50 м', ans:'A', why:'У алюминия $\\rho$ больше.'},
|
||||
{A:'тонкий нихром', B:'толстая медь', ans:'A', why:'Тонкий и нихром — двойное «увеличение R».'}
|
||||
];
|
||||
let i = 0, ok = 0;
|
||||
function render(){
|
||||
const q = QS[i]; const wrap = document.getElementById('p23-quiz'); if(!wrap) return;
|
||||
wrap.innerHTML =
|
||||
'<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:8px">'
|
||||
+'<button class="btn" data-pick="A" style="padding:14px;text-align:left"><b>A.</b> '+q.A+'</button>'
|
||||
+'<button class="btn" data-pick="B" style="padding:14px;text-align:left"><b>B.</b> '+q.B+'</button>'
|
||||
+'</div>'
|
||||
+'<div class="feedback" id="p23-quiz-fb"></div>';
|
||||
document.getElementById('p23-quiz-r').textContent = (i+1);
|
||||
document.getElementById('p23-quiz-ok').textContent = ok;
|
||||
wrap.querySelectorAll('[data-pick]').forEach(btn=>{
|
||||
btn.addEventListener('click', ()=>{
|
||||
if(btn.disabled) return; wrap.querySelectorAll('[data-pick]').forEach(b=>b.disabled=true);
|
||||
const fb = document.getElementById('p23-quiz-fb');
|
||||
if(btn.dataset.pick === q.ans){ ok++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(3,'p23-quiz'); bumpProgress('p23', 4); }
|
||||
else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; }
|
||||
document.getElementById('p23-quiz-ok').textContent = ok;
|
||||
});
|
||||
});
|
||||
}
|
||||
document.getElementById('p23-quiz-next').addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); });
|
||||
render();
|
||||
}
|
||||
|
||||
function _initP23_dnd(){
|
||||
const items = [
|
||||
{id:'lup', cat:'up', html:'увеличили длину $l$'},
|
||||
{id:'sdn', cat:'up', html:'уменьшили сечение $S$'},
|
||||
{id:'mb', cat:'up', html:'заменили медь на нихром'},
|
||||
{id:'cd', cat:'up', html:'заменили серебро на железо'},
|
||||
{id:'ldn', cat:'dn', html:'укоротили провод'},
|
||||
{id:'sup', cat:'dn', html:'утолстили провод'},
|
||||
{id:'mw', cat:'dn', html:'заменили нихром на медь'},
|
||||
{id:'cs', cat:'dn', html:'заменили железо на серебро'}
|
||||
];
|
||||
const dnd = setupSorter({ poolId:'p23-dnd-pool', scopeSelector:'#sec-p23', cats:['up','dn'], items, columnLayout:false });
|
||||
document.getElementById('p23-dnd-check').addEventListener('click', ()=>{
|
||||
const fb = document.getElementById('p23-dnd-fb');
|
||||
let wrong = 0; items.forEach(it=>{ if(dnd.placed[it.id] !== it.cat) wrong++; });
|
||||
if(wrong===0){ fb.className='feedback ok'; fb.innerHTML='✓ Идеально! +15 XP. $R$ пропорционально $\\rho l$ и обратно $S$.'; addXp(15,'p23-dnd'); bumpProgress('p23', 20); renderMath(fb); }
|
||||
else { fb.className='feedback fail'; fb.innerHTML='✗ Ошибок: '+wrong+'.'; }
|
||||
});
|
||||
document.getElementById('p23-dnd-reset').addEventListener('click', ()=>{ dnd.reset(); const fb=document.getElementById('p23-dnd-fb'); fb.style.display='none'; });
|
||||
}
|
||||
|
||||
function _initP23_tasks(){
|
||||
const TASKS = [
|
||||
{q:'Медь, $l = 100$ м, $S = 1$ мм². Найди $R$ (Ом).', ans:1.7, tol:0.05, why:'$R = 0{,}017 \\cdot 100 / 1 = 1{,}7$ Ом.'},
|
||||
{q:'Нихромовая спираль, $l = 5$ м, $S = 0{,}5$ мм². Найди $R$ (Ом).', ans:11, tol:0.3, why:'$R = 1{,}1 \\cdot 5 / 0{,}5 = 11$ Ом.'},
|
||||
{q:'$R = 4$ Ом, $\\rho = 0{,}4$, $l = 2$ м. Найди $S$ (мм²).', ans:0.2, tol:0.02, why:'$S = \\rho l / R = 0{,}4 \\cdot 2 / 4 = 0{,}2$ мм².'},
|
||||
{q:'Два медных провода: один длиннее в 3 раза, тоньше в 2 раза. Во сколько раз $R$ больше?', ans:6, tol:0.1, why:'$R$ ∝ $l/S$: $3 \\cdot 2 = 6$ раз.'},
|
||||
{q:'Алюминиевый провод, $l = 20$ м, $S = 4$ мм². Найди $R$ (Ом).', ans:0.14, tol:0.01, why:'$R = 0{,}028 \\cdot 20 / 4 = 0{,}14$ Ом.'}
|
||||
];
|
||||
let i = 0, ok = 0, done = 0, awarded = false;
|
||||
function render(){
|
||||
const t = TASKS[i]; const wrap = document.getElementById('p23-task'); if(!wrap) return;
|
||||
wrap.innerHTML =
|
||||
'<div style="padding:10px 14px;background:rgba(15,23,42,.04);border-radius:9px;margin-bottom:10px;font-size:.95rem;line-height:1.5"><b>Задача '+(i+1)+'.</b> '+t.q+'</div>'
|
||||
+'<div class="boss-row"><input type="number" step="0.01" class="tinp" id="p23-task-inp" placeholder="число" style="width:140px">'
|
||||
+'<button class="btn primary" id="p23-task-go">Ответ</button>'
|
||||
+'<button class="btn" id="p23-task-hint">Подсказка</button>'
|
||||
+'<button class="btn" id="p23-task-next">Следующая</button></div>'
|
||||
+'<div class="boss-hint-txt" id="p23-task-hint-txt">'+t.why+'</div>'
|
||||
+'<div class="feedback" id="p23-task-fb"></div>';
|
||||
document.getElementById('p23-task-i').textContent = (i+1);
|
||||
document.getElementById('p23-task-ok').textContent = ok;
|
||||
document.getElementById('p23-task-go').addEventListener('click', ()=>{
|
||||
const v = parseFloat((document.getElementById('p23-task-inp').value || '').replace(',','.'));
|
||||
const fb = document.getElementById('p23-task-fb');
|
||||
if(isNaN(v)){ fb.className='feedback fail'; fb.innerHTML='Введи число.'; return; }
|
||||
done++;
|
||||
if(Math.abs(v - t.ans) < t.tol){ ok++; fb.className='feedback ok'; fb.innerHTML='✓ Верно! '+t.why; addXp(4,'p23-task'); bumpProgress('p23', 6); }
|
||||
else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. Ответ: '+t.ans+'. '+t.why; }
|
||||
document.getElementById('p23-task-ok').textContent = ok;
|
||||
renderMath(wrap);
|
||||
if(done >= TASKS.length && !awarded && ok >= 4){ awarded = true; setTimeout(()=>{ const wf=document.getElementById('p23-task-fb'); wf.className='feedback ok'; wf.innerHTML='✓ +15 XP — расчёты сданы.'; addXp(15,'p23-task-bonus'); bumpProgress('p23', 15); }, 600); }
|
||||
});
|
||||
document.getElementById('p23-task-hint').addEventListener('click', ()=>{ document.getElementById('p23-task-hint-txt').classList.toggle('show'); });
|
||||
document.getElementById('p23-task-next').addEventListener('click', ()=>{ i=(i+1)%TASKS.length; render(); });
|
||||
renderMath(wrap);
|
||||
}
|
||||
render();
|
||||
}
|
||||
|
||||
/* ======== §24 — Последовательное соединение. Реостат ======== */
|
||||
function build_p24(){
|
||||
const box = document.getElementById('p24-body');
|
||||
let h = '';
|
||||
|
||||
h += makeCard('theory', 'Правила последовательного соединения', '§ 24.1',
|
||||
'<p>Если резисторы соединены <b>один за другим</b> (в одну «петлю»), это <b>последовательное</b> соединение.</p>'
|
||||
+'<ul style="padding-left:20px;margin:6px 0">'
|
||||
+'<li>Ток одинаков: $I = I_1 = I_2$ (одна и та же река через все «пороги»).</li>'
|
||||
+'<li>Напряжения складываются: $U = U_1 + U_2$.</li>'
|
||||
+'<li>Сопротивления складываются: $R = R_1 + R_2$.</li>'
|
||||
+'</ul>'
|
||||
+'<p>Если один из резисторов вышел из строя — <b>вся цепь обесточена</b>.</p>'
|
||||
);
|
||||
h += makeCard('rule', 'Реостат', '§ 24.2',
|
||||
'<p><b>Реостат</b> — переменный резистор. Состоит из проволочного резистивного элемента и подвижного контакта (движка).</p>'
|
||||
+'<p>Сдвигая движок, мы изменяем длину $l$ включённой части провода. Так как $R = \\rho l/S$, меняется и сопротивление.</p>'
|
||||
+'<p>Реостат используют для:</p>'
|
||||
+'<ul style="padding-left:20px;margin:6px 0">'
|
||||
+'<li>регулировки силы тока (например, яркости лампы);</li>'
|
||||
+'<li>защиты от перегрузки (последовательно с прибором);</li>'
|
||||
+'<li>«старой» школы — регуляторов громкости в радиоприёмниках.</li>'
|
||||
+'</ul>'
|
||||
);
|
||||
h += makeCard('example', 'Гирлянда — последовательная цепь', '§ 24.3',
|
||||
'<p>В старых ёлочных гирляндах все лампочки соединены последовательно. Каждой достаётся $220/N$ Вольт, где $N$ — число лампочек.</p>'
|
||||
+'<p>Минус: если перегорит одна — погаснут все! Поэтому современные гирлянды чаще делают по секциям с шунтирующими элементами.</p>'
|
||||
);
|
||||
|
||||
/* IV1 — реостат-симулятор */
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-1</span><div class="wg-title">Реостат регулирует яркость</div></div>'
|
||||
+'<div class="wg-help">Двигай движок реостата — увидь, как меняется ток и яркость лампы. Это последовательная цепь.</div>'
|
||||
+'<div class="sliders" style="margin-bottom:10px">'
|
||||
+'<label>Положение движка (доля включённой проволоки): <b id="p24-pv">50%</b><input type="range" id="p24-p" min="0" max="100" step="5" value="50"></label>'
|
||||
+'</div>'
|
||||
+'<svg id="p24-sim" viewBox="0 0 460 220" style="width:100%;height:auto;background:#f8fafc;border-radius:9px;border:1px solid var(--border)"></svg>'
|
||||
+'<div class="score-display" style="margin-top:10px;flex-direction:column;align-items:flex-start;gap:4px">'
|
||||
+'<span>$R_{реост}$ = <b id="p24-rr">10</b> Ом, $R_{лампы} = 12$ Ом, $R_{общ}$ = <b id="p24-rt">22</b> Ом</span>'
|
||||
+'<span>$I = U/R$ при $U = 12$ В: <b id="p24-it">0.55</b> А</span>'
|
||||
+'</div>'
|
||||
+'</div>';
|
||||
|
||||
/* IV2 — калькулятор */
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-2</span><div class="wg-title">Калькулятор последовательной цепи</div></div>'
|
||||
+'<div class="wg-help">Подбирай $R_1$, $R_2$ и $U$ — найди ток и напряжения на каждом.</div>'
|
||||
+'<div class="sliders" style="margin-bottom:10px">'
|
||||
+'<label>$U$, В: <b id="p24-uv">12</b><input type="range" id="p24-u" min="1" max="100" step="1" value="12"></label>'
|
||||
+'<label>$R_1$, Ом: <b id="p24-r1v">4</b><input type="range" id="p24-r1" min="1" max="50" step="1" value="4"></label>'
|
||||
+'<label>$R_2$, Ом: <b id="p24-r2v">8</b><input type="range" id="p24-r2" min="1" max="50" step="1" value="8"></label>'
|
||||
+'</div>'
|
||||
+'<div class="score-display" style="margin-top:8px;flex-direction:column;align-items:flex-start;gap:3px">'
|
||||
+'<span>$R$ = $R_1+R_2$ = <b id="p24-rs">12</b> Ом</span>'
|
||||
+'<span>$I = U/R$ = <b id="p24-is">1</b> А</span>'
|
||||
+'<span>$U_1 = I R_1$ = <b id="p24-u1">4</b> В</span>'
|
||||
+'<span>$U_2 = I R_2$ = <b id="p24-u2">8</b> В</span>'
|
||||
+'<span style="font-size:.84rem;color:var(--muted)">Проверка: $U_1+U_2$ = <b id="p24-check">12</b> В</span>'
|
||||
+'</div>'
|
||||
+'</div>';
|
||||
|
||||
/* IV3 — DnD «верно/неверно» */
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-3</span><div class="wg-title">Правила послед. соединения</div></div>'
|
||||
+'<div id="p24-dnd-pool"></div>'
|
||||
+'<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:10px">'
|
||||
+'<div class="drop-box"><h5>Верно</h5><div class="drop-items" data-cat="t"></div></div>'
|
||||
+'<div class="drop-box"><h5>Неверно</h5><div class="drop-items" data-cat="f"></div></div>'
|
||||
+'</div>'
|
||||
+'<div class="actions"><button class="btn primary" id="p24-dnd-check">Проверить</button><button class="btn" id="p24-dnd-reset">Сброс</button></div>'
|
||||
+'<div class="feedback" id="p24-dnd-fb"></div>'
|
||||
+'</div>';
|
||||
|
||||
/* IV4 — задачи */
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-4</span><div class="wg-title">Тренажёр: 5 задач</div></div>'
|
||||
+'<div class="wg-help">4+ — +15 XP.</div>'
|
||||
+'<div id="p24-task"></div>'
|
||||
+'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="p24-task-i">1</b> / 5</span><span>Правильно: <b id="p24-task-ok">0</b></span></div>'
|
||||
+'</div>';
|
||||
|
||||
box.innerHTML = h + secNavFor('p24') + readButton('p24');
|
||||
renderMath(box);
|
||||
wireReadBtn('p24');
|
||||
|
||||
_initP24_rheostat();
|
||||
_initP24_calc();
|
||||
_initP24_dnd();
|
||||
_initP24_tasks();
|
||||
}
|
||||
|
||||
function _initP24_rheostat(){
|
||||
const svg = document.getElementById('p24-sim'); if(!svg) return;
|
||||
function draw(){
|
||||
const p = +document.getElementById('p24-p').value;
|
||||
document.getElementById('p24-pv').textContent = p+'%';
|
||||
const Rrh = 20 * p / 100; /* 0..20 Ом */
|
||||
const Rlamp = 12;
|
||||
const Rtot = Rrh + Rlamp;
|
||||
const I = 12 / Rtot;
|
||||
document.getElementById('p24-rr').textContent = Rrh.toFixed(0);
|
||||
document.getElementById('p24-rt').textContent = Rtot.toFixed(0);
|
||||
document.getElementById('p24-it').textContent = I.toFixed(2);
|
||||
/* SVG */
|
||||
let s = '';
|
||||
/* батарея */
|
||||
s += window.PHYS.batteryEMF(60, 170, '12 В', 'h');
|
||||
/* провод снизу */
|
||||
s += window.PHYS.wire(60, 150, 60, 70);
|
||||
s += window.PHYS.wire(60, 70, 130, 70);
|
||||
/* реостат — длинная зигзаг полоска */
|
||||
s += '<rect x="130" y="60" width="180" height="20" fill="#fde68a" stroke="#0f172a" stroke-width="1.5" rx="3"/>';
|
||||
/* зона до движка (включена) — затемнить */
|
||||
s += '<rect x="130" y="60" width="'+(p*1.8)+'" height="20" fill="#d97706" opacity="0.4"/>';
|
||||
/* движок */
|
||||
s += '<line x1="'+(130+p*1.8)+'" y1="50" x2="'+(130+p*1.8)+'" y2="80" stroke="#0f172a" stroke-width="3"/>';
|
||||
s += '<polygon points="'+(130+p*1.8-6)+',50 '+(130+p*1.8+6)+',50 '+(130+p*1.8)+',58" fill="#0f172a"/>';
|
||||
s += '<text x="220" y="100" text-anchor="middle" font-family="Inter,sans-serif" font-size="11" fill="#475569">реостат '+Rrh.toFixed(0)+' Ом</text>';
|
||||
/* провод к лампе */
|
||||
s += window.PHYS.wire(310, 70, 360, 70);
|
||||
/* лампа */
|
||||
s += window.PHYS.lightbulbSymbol(380, 70, 18);
|
||||
/* яркость зависит от тока */
|
||||
const glow = Math.min(1, I / 1.2);
|
||||
s += '<circle cx="380" cy="70" r="'+(24+I*12).toFixed(0)+'" fill="#fde047" opacity="'+(glow*0.5).toFixed(2)+'"/>';
|
||||
s += '<circle cx="380" cy="70" r="'+(36+I*18).toFixed(0)+'" fill="#fbbf24" opacity="'+(glow*0.18).toFixed(2)+'"/>';
|
||||
/* провод вниз и обратно */
|
||||
s += window.PHYS.wire(380, 90, 380, 170);
|
||||
s += window.PHYS.wire(380, 170, 100, 170);
|
||||
/* I-метка */
|
||||
s += '<text x="220" y="195" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="13" font-weight="700" fill="#d97706">I = '+I.toFixed(2)+' А</text>';
|
||||
svg.innerHTML = s;
|
||||
}
|
||||
document.getElementById('p24-p').addEventListener('input', draw);
|
||||
draw();
|
||||
}
|
||||
|
||||
function _initP24_calc(){
|
||||
function update(){
|
||||
const U = +document.getElementById('p24-u').value;
|
||||
const R1 = +document.getElementById('p24-r1').value;
|
||||
const R2 = +document.getElementById('p24-r2').value;
|
||||
document.getElementById('p24-uv').textContent = U;
|
||||
document.getElementById('p24-r1v').textContent = R1;
|
||||
document.getElementById('p24-r2v').textContent = R2;
|
||||
const R = R1+R2;
|
||||
const I = U/R;
|
||||
const U1 = I*R1;
|
||||
const U2 = I*R2;
|
||||
document.getElementById('p24-rs').textContent = R;
|
||||
document.getElementById('p24-is').textContent = I.toFixed(2);
|
||||
document.getElementById('p24-u1').textContent = U1.toFixed(2);
|
||||
document.getElementById('p24-u2').textContent = U2.toFixed(2);
|
||||
document.getElementById('p24-check').textContent = (U1+U2).toFixed(2);
|
||||
}
|
||||
['p24-u','p24-r1','p24-r2'].forEach(id => document.getElementById(id).addEventListener('input', update));
|
||||
update();
|
||||
}
|
||||
|
||||
function _initP24_dnd(){
|
||||
const items = [
|
||||
{id:'a', cat:'t', html:'$I = I_1 = I_2$'},
|
||||
{id:'b', cat:'t', html:'$U = U_1 + U_2$'},
|
||||
{id:'c', cat:'t', html:'$R = R_1 + R_2$'},
|
||||
{id:'d', cat:'t', html:'обрыв одного $\\to$ нет тока во всей цепи'},
|
||||
{id:'e', cat:'f', html:'$U = U_1 = U_2$'},
|
||||
{id:'f', cat:'f', html:'$I = I_1 + I_2$'},
|
||||
{id:'g', cat:'f', html:'$1/R = 1/R_1 + 1/R_2$'},
|
||||
{id:'h', cat:'f', html:'обрыв одного $\\to$ ток продолжает идти'}
|
||||
];
|
||||
const dnd = setupSorter({ poolId:'p24-dnd-pool', scopeSelector:'#sec-p24', cats:['t','f'], items, columnLayout:false });
|
||||
document.getElementById('p24-dnd-check').addEventListener('click', ()=>{
|
||||
const fb = document.getElementById('p24-dnd-fb');
|
||||
let wrong = 0; items.forEach(it=>{ if(dnd.placed[it.id] !== it.cat) wrong++; });
|
||||
if(wrong===0){ fb.className='feedback ok'; fb.innerHTML='✓ Идеально! +15 XP. Послед.: одно $I$, складываются $U$ и $R$.'; addXp(15,'p24-dnd'); bumpProgress('p24', 20); renderMath(fb); }
|
||||
else { fb.className='feedback fail'; fb.innerHTML='✗ Ошибок: '+wrong+'. Эти правила — для параллельного соединения.'; renderMath(fb); }
|
||||
});
|
||||
document.getElementById('p24-dnd-reset').addEventListener('click', ()=>{ dnd.reset(); const fb=document.getElementById('p24-dnd-fb'); fb.style.display='none'; });
|
||||
}
|
||||
|
||||
function _initP24_tasks(){
|
||||
const TASKS = [
|
||||
{q:'$R_1 = 4$, $R_2 = 6$ Ом последовательно, $U = 20$ В. Найди $I$ (А).', ans:2, tol:0.05, why:'$R = 10$, $I = 20/10 = 2$ А.'},
|
||||
{q:'$R_1 = 3$, $R_2 = 5$ Ом, $I = 2$ А. Найди $U_2$ (В).', ans:10, tol:0.5, why:'$U_2 = I R_2 = 2 \\cdot 5 = 10$ В.'},
|
||||
{q:'Три одинаковых лампы $R = 50$ Ом каждая, последовательно, $U = 90$ В. Найди $I$ (А).', ans:0.6, tol:0.02, why:'$R = 150$, $I = 90/150 = 0{,}6$ А.'},
|
||||
{q:'$R_1 = 5$, $R_2 = ?$ последовательно. $U = 30$ В, $I = 2$ А. Найди $R_2$ (Ом).', ans:10, tol:0.5, why:'$R = 30/2 = 15$, $R_2 = 15 - 5 = 10$ Ом.'},
|
||||
{q:'Реостат $R = 0..50$ Ом + лампа $R_л = 10$ Ом, $U = 12$ В. При каком положении реостата (Ом) ток будет $0{,}2$ А?', ans:50, tol:1, why:'$R_{общ} = U/I = 60$, $R_{реост} = 60 - 10 = 50$ Ом.'}
|
||||
];
|
||||
let i = 0, ok = 0, done = 0, awarded = false;
|
||||
function render(){
|
||||
const t = TASKS[i]; const wrap = document.getElementById('p24-task'); if(!wrap) return;
|
||||
wrap.innerHTML =
|
||||
'<div style="padding:10px 14px;background:rgba(15,23,42,.04);border-radius:9px;margin-bottom:10px;font-size:.95rem;line-height:1.5"><b>Задача '+(i+1)+'.</b> '+t.q+'</div>'
|
||||
+'<div class="boss-row"><input type="number" step="0.01" class="tinp" id="p24-task-inp" placeholder="число" style="width:140px">'
|
||||
+'<button class="btn primary" id="p24-task-go">Ответ</button>'
|
||||
+'<button class="btn" id="p24-task-hint">Подсказка</button>'
|
||||
+'<button class="btn" id="p24-task-next">Следующая</button></div>'
|
||||
+'<div class="boss-hint-txt" id="p24-task-hint-txt">'+t.why+'</div>'
|
||||
+'<div class="feedback" id="p24-task-fb"></div>';
|
||||
document.getElementById('p24-task-i').textContent = (i+1);
|
||||
document.getElementById('p24-task-ok').textContent = ok;
|
||||
document.getElementById('p24-task-go').addEventListener('click', ()=>{
|
||||
const v = parseFloat((document.getElementById('p24-task-inp').value || '').replace(',','.'));
|
||||
const fb = document.getElementById('p24-task-fb');
|
||||
if(isNaN(v)){ fb.className='feedback fail'; fb.innerHTML='Введи число.'; return; }
|
||||
done++;
|
||||
if(Math.abs(v - t.ans) < t.tol){ ok++; fb.className='feedback ok'; fb.innerHTML='✓ Верно! '+t.why; addXp(4,'p24-task'); bumpProgress('p24', 6); }
|
||||
else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. Ответ: '+t.ans+'. '+t.why; }
|
||||
document.getElementById('p24-task-ok').textContent = ok;
|
||||
renderMath(wrap);
|
||||
if(done >= TASKS.length && !awarded && ok >= 4){ awarded = true; setTimeout(()=>{ const wf=document.getElementById('p24-task-fb'); wf.className='feedback ok'; wf.innerHTML='✓ +15 XP — расчёты сданы.'; addXp(15,'p24-task-bonus'); bumpProgress('p24', 15); }, 600); }
|
||||
});
|
||||
document.getElementById('p24-task-hint').addEventListener('click', ()=>{ document.getElementById('p24-task-hint-txt').classList.toggle('show'); });
|
||||
document.getElementById('p24-task-next').addEventListener('click', ()=>{ i=(i+1)%TASKS.length; render(); });
|
||||
renderMath(wrap);
|
||||
}
|
||||
render();
|
||||
}
|
||||
|
||||
/* ======== §25 — Параллельное соединение ======== */
|
||||
function build_p25(){
|
||||
const box = document.getElementById('p25-body');
|
||||
let h = '';
|
||||
|
||||
h += makeCard('theory', 'Правила параллельного соединения', '§ 25.1',
|
||||
'<p>Если резисторы соединены <b>«бок о бок»</b>, между двумя одинаковыми узлами — это <b>параллельное</b> соединение.</p>'
|
||||
+'<ul style="padding-left:20px;margin:6px 0">'
|
||||
+'<li>Напряжение одинаковое: $U = U_1 = U_2$ (один и тот же «перепад высоты» на всех ветках).</li>'
|
||||
+'<li>Токи складываются: $I = I_1 + I_2$.</li>'
|
||||
+'<li>Сопротивления через обратные величины: $\\dfrac{1}{R} = \\dfrac{1}{R_1} + \\dfrac{1}{R_2}$.</li>'
|
||||
+'</ul>'
|
||||
+'<p>Поломка одного резистора <b>не отключает</b> остальные.</p>'
|
||||
);
|
||||
h += makeCard('rule', 'Полезные формулы', '§ 25.2',
|
||||
'<p>Для двух резисторов:</p>'
|
||||
+'<p style="text-align:center;margin:8px 0">$$R = \\dfrac{R_1 R_2}{R_1 + R_2}$$</p>'
|
||||
+'<p>Для $N$ <b>одинаковых</b> резисторов по $R$:</p>'
|
||||
+'<p style="text-align:center;margin:8px 0">$$R_{общ} = \\dfrac{R}{N}$$</p>'
|
||||
+'<p>Общее $R$ <b>меньше</b> любого из частных. Это потому, что параллельные «ветви» дают много путей току.</p>'
|
||||
);
|
||||
h += makeCard('example', 'Где встречается', '§ 25.3',
|
||||
'<ul style="padding-left:20px;margin:6px 0">'
|
||||
+'<li>В розетках дома: все приборы (свет, ТВ, чайник) подключены параллельно. Поэтому каждый получает 220 В.</li>'
|
||||
+'<li>Поломка лампы не выключает остальные.</li>'
|
||||
+'<li>В машине фары, магнитола, освещение салона — все параллельно через аккумулятор.</li>'
|
||||
+'</ul>'
|
||||
);
|
||||
|
||||
/* IV1 — конструктор параллельной цепи */
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-1</span><div class="wg-title">Параллельная цепь — 2 ветви</div></div>'
|
||||
+'<div class="wg-help">Меняй $R_1$ и $R_2$ — увидь токи в каждой ветви и общий $R$.</div>'
|
||||
+'<div class="sliders" style="margin-bottom:10px">'
|
||||
+'<label>$R_1$, Ом: <b id="p25-r1v">6</b><input type="range" id="p25-r1" min="1" max="40" step="1" value="6"></label>'
|
||||
+'<label>$R_2$, Ом: <b id="p25-r2v">12</b><input type="range" id="p25-r2" min="1" max="40" step="1" value="12"></label>'
|
||||
+'</div>'
|
||||
+'<svg id="p25-sim" viewBox="0 0 460 220" style="width:100%;height:auto;background:#f8fafc;border-radius:9px;border:1px solid var(--border)"></svg>'
|
||||
+'<div class="score-display" style="margin-top:10px;flex-direction:column;align-items:flex-start;gap:3px">'
|
||||
+'<span>$R_{общ} = R_1 R_2 / (R_1+R_2)$ = <b id="p25-rt">4</b> Ом</span>'
|
||||
+'<span>При $U = 12$ В: $I_1 = U/R_1 = $ <b id="p25-i1">2</b> А</span>'
|
||||
+'<span>$I_2 = U/R_2 = $ <b id="p25-i2">1</b> А</span>'
|
||||
+'<span>Общий ток $I = I_1 + I_2$ = <b id="p25-it2">3</b> А</span>'
|
||||
+'</div>'
|
||||
+'</div>';
|
||||
|
||||
/* IV2 — викторина «послед. или паралл.» */
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-2</span><div class="wg-title">Какое соединение?</div></div>'
|
||||
+'<div class="wg-help">По описанию определи тип соединения.</div>'
|
||||
+'<div id="p25-quiz"></div>'
|
||||
+'<div class="actions"><button class="btn" id="p25-quiz-next">Следующий</button></div>'
|
||||
+'<div class="score-display" style="margin-top:10px"><span>Раунд: <b id="p25-quiz-r">1</b> / 6</span><span>Правильно: <b id="p25-quiz-ok">0</b></span></div>'
|
||||
+'</div>';
|
||||
|
||||
/* IV3 — DnD формулы */
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-3</span><div class="wg-title">К какому соединению относится?</div></div>'
|
||||
+'<div class="wg-help">Распредели формулы.</div>'
|
||||
+'<div id="p25-dnd-pool"></div>'
|
||||
+'<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:10px">'
|
||||
+'<div class="drop-box"><h5>Последовательно</h5><div class="drop-items" data-cat="ser"></div></div>'
|
||||
+'<div class="drop-box"><h5>Параллельно</h5><div class="drop-items" data-cat="par"></div></div>'
|
||||
+'</div>'
|
||||
+'<div class="actions"><button class="btn primary" id="p25-dnd-check">Проверить</button><button class="btn" id="p25-dnd-reset">Сброс</button></div>'
|
||||
+'<div class="feedback" id="p25-dnd-fb"></div>'
|
||||
+'</div>';
|
||||
|
||||
/* IV4 — задачи */
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-4</span><div class="wg-title">Тренажёр: 6 задач</div></div>'
|
||||
+'<div class="wg-help">4+ — +15 XP.</div>'
|
||||
+'<div id="p25-task"></div>'
|
||||
+'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="p25-task-i">1</b> / 6</span><span>Правильно: <b id="p25-task-ok">0</b></span></div>'
|
||||
+'</div>';
|
||||
|
||||
box.innerHTML = h + secNavFor('p25') + readButton('p25');
|
||||
renderMath(box);
|
||||
wireReadBtn('p25');
|
||||
|
||||
_initP25_calc();
|
||||
_initP25_quiz();
|
||||
_initP25_dnd();
|
||||
_initP25_tasks();
|
||||
}
|
||||
|
||||
function _initP25_calc(){
|
||||
const svg = document.getElementById('p25-sim'); if(!svg) return;
|
||||
function update(){
|
||||
const R1 = +document.getElementById('p25-r1').value;
|
||||
const R2 = +document.getElementById('p25-r2').value;
|
||||
document.getElementById('p25-r1v').textContent = R1;
|
||||
document.getElementById('p25-r2v').textContent = R2;
|
||||
const Rt = (R1*R2)/(R1+R2);
|
||||
const U = 12;
|
||||
const I1 = U/R1;
|
||||
const I2 = U/R2;
|
||||
document.getElementById('p25-rt').textContent = Rt.toFixed(2);
|
||||
document.getElementById('p25-i1').textContent = I1.toFixed(2);
|
||||
document.getElementById('p25-i2').textContent = I2.toFixed(2);
|
||||
document.getElementById('p25-it2').textContent = (I1+I2).toFixed(2);
|
||||
/* SVG */
|
||||
let s = '';
|
||||
/* батарея слева */
|
||||
s += window.PHYS.batteryEMF(60, 110, '12 В', 'h');
|
||||
/* провод вверх */
|
||||
s += window.PHYS.wire(60, 92, 60, 60);
|
||||
s += window.PHYS.wire(60, 60, 380, 60);
|
||||
/* провод вниз */
|
||||
s += window.PHYS.wire(60, 130, 60, 170);
|
||||
s += window.PHYS.wire(60, 170, 380, 170);
|
||||
/* развилка верх */
|
||||
s += window.PHYS.wire(150, 60, 150, 80);
|
||||
s += window.PHYS.wire(270, 60, 270, 80);
|
||||
/* верхняя ветвь */
|
||||
s += window.PHYS.resistor(190, 80, R1, 'h');
|
||||
/* нижняя ветвь */
|
||||
s += window.PHYS.wire(150, 130, 150, 150);
|
||||
s += window.PHYS.wire(270, 130, 270, 150);
|
||||
s += window.PHYS.resistor(190, 130, R2, 'h');
|
||||
/* подписи токов */
|
||||
s += '<text x="180" y="65" font-family="JetBrains Mono,monospace" font-size="11" fill="#d97706">I₁ = '+I1.toFixed(2)+' А</text>';
|
||||
s += '<text x="180" y="170" font-family="JetBrains Mono,monospace" font-size="11" fill="#d97706">I₂ = '+I2.toFixed(2)+' А</text>';
|
||||
/* провода к развилке снизу */
|
||||
s += window.PHYS.wire(150, 100, 270, 100);
|
||||
s += window.PHYS.wire(150, 150, 270, 150);
|
||||
svg.innerHTML = s;
|
||||
}
|
||||
document.getElementById('p25-r1').addEventListener('input', update);
|
||||
document.getElementById('p25-r2').addEventListener('input', update);
|
||||
update();
|
||||
}
|
||||
|
||||
function _initP25_quiz(){
|
||||
const QS = [
|
||||
{sit:'Все лампы в гирлянде гаснут при поломке одной', ans:'S', why:'Это последовательное соединение.'},
|
||||
{sit:'В розетке: ТВ и чайник работают независимо', ans:'P', why:'Параллельно — оба под 220 В.'},
|
||||
{sit:'Лампа, амперметр, батарея — в одной петле', ans:'S', why:'Последовательно.'},
|
||||
{sit:'Два резистора имеют одно и то же напряжение', ans:'P', why:'Параллельно — общее $U$.'},
|
||||
{sit:'Через два резистора течёт один и тот же ток', ans:'S', why:'Последовательно — общее $I$.'},
|
||||
{sit:'Общее $R$ меньше любого из $R_1$, $R_2$', ans:'P', why:'Параллельное соединение.'}
|
||||
];
|
||||
let i = 0, ok = 0;
|
||||
function render(){
|
||||
const q = QS[i]; const wrap = document.getElementById('p25-quiz'); if(!wrap) return;
|
||||
wrap.innerHTML =
|
||||
'<div style="padding:10px 14px;background:rgba(15,23,42,.04);border-radius:9px;margin:8px 0;line-height:1.5">'+q.sit+'</div>'
|
||||
+'<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px">'
|
||||
+'<button class="btn" data-pick="S" style="padding:14px"><b>Последовательно</b></button>'
|
||||
+'<button class="btn" data-pick="P" style="padding:14px"><b>Параллельно</b></button>'
|
||||
+'</div>'
|
||||
+'<div class="feedback" id="p25-quiz-fb"></div>';
|
||||
document.getElementById('p25-quiz-r').textContent = (i+1);
|
||||
document.getElementById('p25-quiz-ok').textContent = ok;
|
||||
wrap.querySelectorAll('[data-pick]').forEach(btn=>{
|
||||
btn.addEventListener('click', ()=>{
|
||||
if(btn.disabled) return; wrap.querySelectorAll('[data-pick]').forEach(b=>b.disabled=true);
|
||||
const fb = document.getElementById('p25-quiz-fb');
|
||||
if(btn.dataset.pick === q.ans){ ok++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(3,'p25-quiz'); bumpProgress('p25', 4); }
|
||||
else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; }
|
||||
document.getElementById('p25-quiz-ok').textContent = ok;
|
||||
});
|
||||
});
|
||||
}
|
||||
document.getElementById('p25-quiz-next').addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); });
|
||||
render();
|
||||
}
|
||||
|
||||
function _initP25_dnd(){
|
||||
const items = [
|
||||
{id:'a', cat:'ser', html:'$I = I_1 = I_2$'},
|
||||
{id:'b', cat:'ser', html:'$U = U_1 + U_2$'},
|
||||
{id:'c', cat:'ser', html:'$R = R_1 + R_2$'},
|
||||
{id:'d', cat:'ser', html:'обрыв $\\to$ ничего не работает'},
|
||||
{id:'e', cat:'par', html:'$U = U_1 = U_2$'},
|
||||
{id:'f', cat:'par', html:'$I = I_1 + I_2$'},
|
||||
{id:'g', cat:'par', html:'$1/R = 1/R_1 + 1/R_2$'},
|
||||
{id:'h', cat:'par', html:'обрыв $\\to$ остальные работают'}
|
||||
];
|
||||
const dnd = setupSorter({ poolId:'p25-dnd-pool', scopeSelector:'#sec-p25', cats:['ser','par'], items, columnLayout:false });
|
||||
document.getElementById('p25-dnd-check').addEventListener('click', ()=>{
|
||||
const fb = document.getElementById('p25-dnd-fb');
|
||||
let wrong = 0; items.forEach(it=>{ if(dnd.placed[it.id] !== it.cat) wrong++; });
|
||||
if(wrong===0){ fb.className='feedback ok'; fb.innerHTML='✓ Идеально! +15 XP. Главное отличие: послед.→общий I, паралл.→общее U.'; addXp(15,'p25-dnd'); bumpProgress('p25', 20); renderMath(fb); }
|
||||
else { fb.className='feedback fail'; fb.innerHTML='✗ Ошибок: '+wrong+'.'; renderMath(fb); }
|
||||
});
|
||||
document.getElementById('p25-dnd-reset').addEventListener('click', ()=>{ dnd.reset(); const fb=document.getElementById('p25-dnd-fb'); fb.style.display='none'; });
|
||||
}
|
||||
|
||||
function _initP25_tasks(){
|
||||
const TASKS = [
|
||||
{q:'$R_1 = 6$, $R_2 = 12$ Ом параллельно. Найди $R_{общ}$ (Ом).', ans:4, tol:0.1, why:'$R = 6\\cdot12/(6+12) = 72/18 = 4$ Ом.'},
|
||||
{q:'Два резистора по $R = 10$ Ом параллельно. $R_{общ}$ (Ом)?', ans:5, tol:0.1, why:'$R/2 = 5$ Ом.'},
|
||||
{q:'$R_1 = R_2 = R_3 = 9$ Ом, все параллельно. $R_{общ}$ (Ом)?', ans:3, tol:0.1, why:'$R/N = 9/3 = 3$ Ом.'},
|
||||
{q:'Параллельно $R_1 = 4$, $R_2 = 4$ Ом, $U = 12$ В. Найди ток в одной ветви (А).', ans:3, tol:0.1, why:'$I_1 = U/R_1 = 12/4 = 3$ А.'},
|
||||
{q:'$R_1 = 6$, $R_2 = ?$ параллельно, $R_{общ} = 4$ Ом. Найди $R_2$.', ans:12, tol:0.3, why:'$1/4 = 1/6 + 1/R_2 \\Rightarrow 1/R_2 = 1/12 \\Rightarrow R_2 = 12$ Ом.'},
|
||||
{q:'Параллельно к 220 В подключены утюг ($R = 44$ Ом) и лампа ($R = 220$ Ом). Какой общий ток (А)?', ans:6, tol:0.2, why:'$I_1 = 220/44 = 5$, $I_2 = 220/220 = 1$, $I = 6$ А.'}
|
||||
];
|
||||
let i = 0, ok = 0, done = 0, awarded = false;
|
||||
function render(){
|
||||
const t = TASKS[i]; const wrap = document.getElementById('p25-task'); if(!wrap) return;
|
||||
wrap.innerHTML =
|
||||
'<div style="padding:10px 14px;background:rgba(15,23,42,.04);border-radius:9px;margin-bottom:10px;font-size:.95rem;line-height:1.5"><b>Задача '+(i+1)+'.</b> '+t.q+'</div>'
|
||||
+'<div class="boss-row"><input type="number" step="0.01" class="tinp" id="p25-task-inp" placeholder="число" style="width:140px">'
|
||||
+'<button class="btn primary" id="p25-task-go">Ответ</button>'
|
||||
+'<button class="btn" id="p25-task-hint">Подсказка</button>'
|
||||
+'<button class="btn" id="p25-task-next">Следующая</button></div>'
|
||||
+'<div class="boss-hint-txt" id="p25-task-hint-txt">'+t.why+'</div>'
|
||||
+'<div class="feedback" id="p25-task-fb"></div>';
|
||||
document.getElementById('p25-task-i').textContent = (i+1);
|
||||
document.getElementById('p25-task-ok').textContent = ok;
|
||||
document.getElementById('p25-task-go').addEventListener('click', ()=>{
|
||||
const v = parseFloat((document.getElementById('p25-task-inp').value || '').replace(',','.'));
|
||||
const fb = document.getElementById('p25-task-fb');
|
||||
if(isNaN(v)){ fb.className='feedback fail'; fb.innerHTML='Введи число.'; return; }
|
||||
done++;
|
||||
if(Math.abs(v - t.ans) < t.tol){ ok++; fb.className='feedback ok'; fb.innerHTML='✓ Верно! '+t.why; addXp(4,'p25-task'); bumpProgress('p25', 6); }
|
||||
else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. Ответ: '+t.ans+'. '+t.why; }
|
||||
document.getElementById('p25-task-ok').textContent = ok;
|
||||
renderMath(wrap);
|
||||
if(done >= TASKS.length && !awarded && ok >= 4){ awarded = true; setTimeout(()=>{ const wf=document.getElementById('p25-task-fb'); wf.className='feedback ok'; wf.innerHTML='✓ +15 XP — расчёты сданы.'; addXp(15,'p25-task-bonus'); bumpProgress('p25', 15); }, 600); }
|
||||
});
|
||||
document.getElementById('p25-task-hint').addEventListener('click', ()=>{ document.getElementById('p25-task-hint-txt').classList.toggle('show'); });
|
||||
document.getElementById('p25-task-next').addEventListener('click', ()=>{ i=(i+1)%TASKS.length; render(); });
|
||||
renderMath(wrap);
|
||||
}
|
||||
render();
|
||||
}
|
||||
|
||||
function init(){
|
||||
loadProgress(); initTheme(); initSidebarToggle(); initSearch();
|
||||
buildParaSelector(); refreshProgressUI(); loadServerReadState(); goTo(PARAS[0].id);
|
||||
|
||||
Reference in New Issue
Block a user