feat(phys8 ch2): Phase 3 Wave 1 — §19 источники тока + §20 I=q/t
§19 Электрический ток. Источники: - 3 теории: условие тока, типы источников, гальв. элемент Вольта - IV-1: круговая анимация работы батарейки — 14 электронов бегут по контуру против тока, лампа загорается - IV-2: 5 источников «химия/механика/свет/тепло» - IV-3: DnD «есть ли ток?» 8 ситуаций - IV-4: 6 MCQ §20 Сила тока I = q/t: - 3 теории: формула, направление тока vs электронов, таблица - IV-1: симуляция потока электронов через провод, slider I 0-3 А, лампа меняет яркость, счётчик «Кл и электронов в секунду» - IV-2: 5 числовых задач q/t/I - IV-3: DnD 5 устройств по возрастанию I (наушники → стартер) - IV-4: 5 расчётных задач с допусками Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -358,8 +358,20 @@ const SIDEBARS = {
|
||||
["Розетка","220 В"],
|
||||
["1 В","работа 1 Дж на 1 Кл"]
|
||||
]},
|
||||
p19:{title:"Шпаргалка § 19",rows:[["В разработке","Phase 3 Wave 1"]]},
|
||||
p20:{title:"Шпаргалка § 20",rows:[["В разработке","Phase 3 Wave 1"]]},
|
||||
p19:{title:"Шпаргалка § 19",rows:[
|
||||
["Ток","упорядоченное движение зарядов"],
|
||||
["Условие 1","свободные носители"],
|
||||
["Условие 2","эл. поле от источника"],
|
||||
["Источники","батарейки, аккумуляторы, генераторы"],
|
||||
["Внутри источника","сторонние силы $\\to$ ЭДС"]
|
||||
]},
|
||||
p20:{title:"Шпаргалка § 20",rows:[
|
||||
["Формула","$I = q/t$"],
|
||||
["Единица","[I] = А = Кл/с"],
|
||||
["1 А","заряд 1 Кл за 1 с"],
|
||||
["Направление тока","от + к − (исторически)"],
|
||||
["В металлах","электроны против тока"]
|
||||
]},
|
||||
p21:{title:"Шпаргалка § 21",rows:[["В разработке","Phase 3 Wave 2"]]},
|
||||
p22:{title:"Шпаргалка § 22",rows:[["В разработке","Phase 3 Wave 2"]]},
|
||||
p23:{title:"Шпаргалка § 23",rows:[["В разработке","Phase 3 Wave 3"]]},
|
||||
@@ -382,8 +394,8 @@ const TIPS=[
|
||||
{sec:'p16',html:"Атом — это плотное положительное ядро (протоны+нейтроны) и облако отрицательных электронов вокруг. В обычном атоме число электронов равно числу протонов — он нейтрален. Если потерять электрон → ион +, если получить → ион −."},
|
||||
{sec:'p17',html:"Заряд не «торкает» другие заряды напрямую — он создаёт вокруг себя <b>электрическое поле</b>, а уже оно действует силой на другие заряды. Линии поля идут от + к − и показывают направление силы на пробный +заряд."},
|
||||
{sec:'p18',html:"Напряжение $U$ — это работа поля по перемещению единичного заряда: $A = qU$. Единица — 1 Вольт. Розетка 220 В, батарейка 1,5 В. Чем больше $U$, тем «сильнее» поле толкает заряд."},
|
||||
{sec:'p19',html:"Параграф § 19 будет реализован в Phase 3 Wave 1. Используем хелперы из <code>phys.js</code> и <code>optics.js</code>."},
|
||||
{sec:'p20',html:"Параграф § 20 будет реализован в Phase 3 Wave 1. Используем хелперы из <code>phys.js</code> и <code>optics.js</code>."},
|
||||
{sec:'p19',html:"Ток — это упорядоченное движение свободных зарядов. Чтобы оно поддерживалось, нужен <b>источник тока</b> — батарейка, аккумулятор, генератор. Внутри источника <i>сторонние силы</i> переносят заряды против поля — это и есть «насос электричества»."},
|
||||
{sec:'p20',html:"$I = q/t$ — сколько Кулонов прошло через сечение провода за 1 секунду. Единица — <b>Ампер</b> ($1$ А = $1$ Кл/с). За направление тока приняли движение «+» зарядов — хотя в металлах реально двигаются электроны (против тока)."},
|
||||
{sec:'p21',html:"Параграф § 21 будет реализован в Phase 3 Wave 2. Используем хелперы из <code>phys.js</code> и <code>optics.js</code>."},
|
||||
{sec:'p22',html:"Параграф § 22 будет реализован в Phase 3 Wave 2. Используем хелперы из <code>phys.js</code> и <code>optics.js</code>."},
|
||||
{sec:'p23',html:"Параграф § 23 будет реализован в Phase 3 Wave 3. Используем хелперы из <code>phys.js</code> и <code>optics.js</code>."},
|
||||
@@ -406,8 +418,8 @@ const BUILDERS = {
|
||||
p16: ()=>{ build_p16(); },
|
||||
p17: ()=>{ build_p17(); },
|
||||
p18: ()=>{ build_p18(); },
|
||||
p19: ()=>{ const box=document.getElementById('p19-body'); box.innerHTML = buildStub('p19', 'Электрический ток. Источники тока', 'Phase 3 Wave 1') + secNavFor('p19') + readButton('p19'); renderMath(box); wireReadBtn('p19'); },
|
||||
p20: ()=>{ const box=document.getElementById('p20-body'); box.innerHTML = buildStub('p20', 'Сила и направление электрического тока', 'Phase 3 Wave 1') + secNavFor('p20') + readButton('p20'); renderMath(box); wireReadBtn('p20'); },
|
||||
p19: ()=>{ build_p19(); },
|
||||
p20: ()=>{ build_p20(); },
|
||||
p21: ()=>{ const box=document.getElementById('p21-body'); box.innerHTML = buildStub('p21', 'Электрическая цепь. Измерение силы тока и напряжения', 'Phase 3 Wave 2') + secNavFor('p21') + readButton('p21'); renderMath(box); wireReadBtn('p21'); },
|
||||
p22: ()=>{ const box=document.getElementById('p22-body'); box.innerHTML = buildStub('p22', 'Связь силы тока и напряжения. Закон Ома для участка электрической цепи', 'Phase 3 Wave 2') + secNavFor('p22') + readButton('p22'); renderMath(box); wireReadBtn('p22'); },
|
||||
p23: ()=>{ const box=document.getElementById('p23-body'); box.innerHTML = buildStub('p23', 'Единица сопротивления. Расчёт сопротивления', 'Phase 3 Wave 3') + secNavFor('p23') + readButton('p23'); renderMath(box); wireReadBtn('p23'); },
|
||||
@@ -2266,6 +2278,488 @@ function _initP18_tasks(){
|
||||
render();
|
||||
}
|
||||
|
||||
/* ======================================================================
|
||||
PHASE 3 · WAVE 1 — §19, §20
|
||||
====================================================================== */
|
||||
|
||||
/* ======== §19 — Электрический ток. Источники тока ======== */
|
||||
function build_p19(){
|
||||
const box = document.getElementById('p19-body');
|
||||
let h = '';
|
||||
|
||||
h += makeCard('theory', 'Что такое электрический ток', '§ 19.1',
|
||||
'<p><b>Электрический ток</b> — упорядоченное (направленное) движение свободных заряженных частиц.</p>'
|
||||
+'<p>В проводе у каждой точки много электронов, движущихся хаотически. Если приложить эл. поле — все они «сдвигаются» в одну сторону. Это и есть ток.</p>'
|
||||
+'<p>Для существования тока нужно:</p>'
|
||||
+'<ol style="padding-left:20px;margin:6px 0">'
|
||||
+'<li><b>свободные носители заряда</b> (электроны в металле, ионы в растворе);</li>'
|
||||
+'<li><b>электрическое поле</b>, заставляющее их двигаться упорядоченно.</li>'
|
||||
+'</ol>'
|
||||
);
|
||||
h += makeCard('rule', 'Источники тока', '§ 19.2',
|
||||
'<p><b>Источник тока</b> создаёт и поддерживает эл. поле в цепи. Внутри него «<b>сторонние силы</b>» (химические, механические, световые) переносят заряды против поля — от одного электрода к другому.</p>'
|
||||
+'<ul style="padding-left:20px;margin:6px 0">'
|
||||
+'<li><b>Гальванический элемент (батарейка)</b> — химическая энергия → электрическая.</li>'
|
||||
+'<li><b>Аккумулятор</b> — то же, но с обратимой реакцией (заряжается).</li>'
|
||||
+'<li><b>Генератор</b> — механическая → электрическая (на электростанции).</li>'
|
||||
+'<li><b>Фотоэлемент</b> — световая → электрическая.</li>'
|
||||
+'<li><b>Термоэлемент</b> — тепловая → электрическая.</li>'
|
||||
+'</ul>'
|
||||
);
|
||||
h += makeCard('example', 'Простейшая батарейка', '§ 19.3',
|
||||
'<p>Два разных металла (например, медь и цинк) опущенные в раствор кислоты, дают электрический ток. Цинк отдаёт электроны в раствор и становится «−». Медь принимает электроны и становится «+».</p>'
|
||||
+'<p>Так устроен <b>гальванический элемент</b> — изобретение Алессандро Вольта (1799 г.). Это была первая в истории батарейка!</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>'
|
||||
+'<svg id="p19-sim" viewBox="0 0 460 220" style="width:100%;height:auto;background:#f8fafc;border-radius:9px;border:1px solid var(--border)"></svg>'
|
||||
+'<div class="actions" style="margin-top:10px"><button class="btn primary" id="p19-on">Замкнуть цепь</button><button class="btn" id="p19-reset">Сброс</button></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="p19-quiz"></div>'
|
||||
+'<div class="actions"><button class="btn" id="p19-quiz-next">Следующий</button></div>'
|
||||
+'<div class="score-display" style="margin-top:10px"><span>Раунд: <b id="p19-quiz-r">1</b> / 5</span><span>Правильно: <b id="p19-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="p19-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="y"></div></div>'
|
||||
+'<div class="drop-box"><h5>Нет тока</h5><div class="drop-items" data-cat="n"></div></div>'
|
||||
+'</div>'
|
||||
+'<div class="actions"><button class="btn primary" id="p19-dnd-check">Проверить</button><button class="btn" id="p19-dnd-reset">Сброс</button></div>'
|
||||
+'<div class="feedback" id="p19-dnd-fb"></div>'
|
||||
+'</div>';
|
||||
|
||||
/* IV4 — MCQ */
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-4</span><div class="wg-title">Тренажёр: 6 вопросов</div></div>'
|
||||
+'<div class="wg-help">4+ — +15 XP.</div>'
|
||||
+'<div id="p19-mcq"></div>'
|
||||
+'<div class="score-display" style="margin-top:10px"><span>Вопрос: <b id="p19-mcq-i">1</b> / 6</span><span>Правильно: <b id="p19-mcq-ok">0</b></span></div>'
|
||||
+'</div>';
|
||||
|
||||
box.innerHTML = h + secNavFor('p19') + readButton('p19');
|
||||
renderMath(box);
|
||||
wireReadBtn('p19');
|
||||
|
||||
_initP19_sim();
|
||||
_initP19_quiz();
|
||||
_initP19_dnd();
|
||||
_initP19_mcq();
|
||||
}
|
||||
|
||||
function _initP19_sim(){
|
||||
_killSim('p19sim');
|
||||
const svg = document.getElementById('p19-sim'); if(!svg) return;
|
||||
let on = false;
|
||||
const N = 14;
|
||||
const electrons = [];
|
||||
/* Путь: батарея (40,110) → провод вверх → горизонталь → вниз → лампа → возврат */
|
||||
/* Замкнутый контур по часовой стрелке (электроны двигаются ПРОТИВ тока — против часовой) */
|
||||
/* Точки контура */
|
||||
const path = [
|
||||
{x:80, y:170}, /* − батареи (низ) */
|
||||
{x:80, y:60}, /* левый верхний угол */
|
||||
{x:200, y:60}, /* перед лампой */
|
||||
{x:230, y:90}, /* в лампу */
|
||||
{x:260, y:60}, /* выход лампы */
|
||||
{x:380, y:60}, /* правый верхний угол */
|
||||
{x:380, y:170}, /* + батареи (низ) */
|
||||
{x:80, y:170} /* возврат через батарею */
|
||||
];
|
||||
/* Длина пути */
|
||||
function pathLen(){
|
||||
let L = 0;
|
||||
for(let i=0;i<path.length-1;i++){ L += Math.hypot(path[i+1].x-path[i].x, path[i+1].y-path[i].y); }
|
||||
return L;
|
||||
}
|
||||
const totalLen = pathLen();
|
||||
for(let i = 0; i < N; i++) electrons.push({ t: i * (totalLen/N) });
|
||||
function posAt(t){
|
||||
let rem = ((t % totalLen) + totalLen) % totalLen;
|
||||
for(let i=0;i<path.length-1;i++){
|
||||
const seg = Math.hypot(path[i+1].x-path[i].x, path[i+1].y-path[i].y);
|
||||
if(rem <= seg){
|
||||
const k = rem/seg;
|
||||
return { x: path[i].x + (path[i+1].x-path[i].x)*k, y: path[i].y + (path[i+1].y-path[i].y)*k };
|
||||
}
|
||||
rem -= seg;
|
||||
}
|
||||
return path[0];
|
||||
}
|
||||
function tick(){
|
||||
if(!_isVisible('p19')){ _SIMS.p19sim.raf = requestAnimationFrame(tick); return; }
|
||||
if(on) for(const e of electrons) e.t += 1.4;
|
||||
let s = '';
|
||||
/* провода */
|
||||
for(let i=0;i<path.length-1;i++){
|
||||
s += '<line x1="'+path[i].x+'" y1="'+path[i].y+'" x2="'+path[i+1].x+'" y2="'+path[i+1].y+'" stroke="#374151" stroke-width="3"/>';
|
||||
}
|
||||
/* батарея слева */
|
||||
s += '<rect x="40" y="115" width="80" height="60" fill="#e0f2fe" stroke="#0f172a" stroke-width="2" rx="4"/>';
|
||||
s += '<text x="80" y="135" text-anchor="middle" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="#0f172a">источник</text>';
|
||||
s += '<text x="55" y="170" font-family="Inter,sans-serif" font-size="14" font-weight="800" fill="#dc2626">+</text>';
|
||||
s += '<text x="100" y="170" font-family="Inter,sans-serif" font-size="14" font-weight="800" fill="#2563eb">−</text>';
|
||||
/* стрелка тока I (внутри цепи) */
|
||||
if(on){
|
||||
s += '<text x="230" y="40" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="13" font-weight="700" fill="#d97706">I →</text>';
|
||||
}
|
||||
/* лампа в центре */
|
||||
s += window.PHYS.lightbulbSymbol(230, 90, 18);
|
||||
if(on){
|
||||
/* свечение */
|
||||
s += '<circle cx="230" cy="90" r="28" fill="#fde047" opacity="0.45"/>';
|
||||
s += '<circle cx="230" cy="90" r="40" fill="#fbbf24" opacity="0.18"/>';
|
||||
}
|
||||
/* электроны двигаются против тока — то есть против хода path */
|
||||
for(const e of electrons){
|
||||
const p = posAt(-e.t);
|
||||
s += '<circle cx="'+p.x.toFixed(1)+'" cy="'+p.y.toFixed(1)+'" r="4.5" fill="#2563eb" stroke="#0f172a" stroke-width="0.6"/>';
|
||||
s += '<text x="'+p.x.toFixed(1)+'" y="'+(p.y+3).toFixed(1)+'" text-anchor="middle" font-family="Inter,sans-serif" font-size="9" font-weight="800" fill="#fff">−</text>';
|
||||
}
|
||||
svg.innerHTML = s;
|
||||
_SIMS.p19sim.raf = requestAnimationFrame(tick);
|
||||
}
|
||||
_SIMS.p19sim = { raf: 0 };
|
||||
_SIMS.p19sim.raf = requestAnimationFrame(tick);
|
||||
document.getElementById('p19-on').addEventListener('click', ()=>{
|
||||
on = !on;
|
||||
document.getElementById('p19-on').textContent = on ? 'Разомкнуть' : 'Замкнуть цепь';
|
||||
});
|
||||
document.getElementById('p19-reset').addEventListener('click', ()=>{
|
||||
on = false; document.getElementById('p19-on').textContent = 'Замкнуть цепь';
|
||||
for(let i=0;i<N;i++) electrons[i].t = i * (totalLen/N);
|
||||
});
|
||||
}
|
||||
|
||||
function _initP19_quiz(){
|
||||
const QS = [
|
||||
{sit:'Гальванический элемент', ans:'C', why:'Химическая (реакция в электролите) → электрическая.'},
|
||||
{sit:'Гидроэлектростанция (плотина)', ans:'M', why:'Механическая (вращение турбины) → электрическая.'},
|
||||
{sit:'Солнечная батарея', ans:'L', why:'Световая (фотоны) → электрическая.'},
|
||||
{sit:'Термопара', ans:'T', why:'Тепловая → электрическая.'},
|
||||
{sit:'Аккумулятор автомобиля', ans:'C', why:'Химическая, как и батарейка.'}
|
||||
];
|
||||
let i = 0, ok = 0;
|
||||
function render(){
|
||||
const q = QS[i]; const wrap = document.getElementById('p19-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:6px">'
|
||||
+'<button class="btn" data-pick="C" style="padding:10px"><b>Химическая</b></button>'
|
||||
+'<button class="btn" data-pick="M" style="padding:10px"><b>Механическая</b></button>'
|
||||
+'<button class="btn" data-pick="L" style="padding:10px"><b>Световая</b></button>'
|
||||
+'<button class="btn" data-pick="T" style="padding:10px"><b>Тепловая</b></button>'
|
||||
+'</div>'
|
||||
+'<div class="feedback" id="p19-quiz-fb"></div>';
|
||||
document.getElementById('p19-quiz-r').textContent = (i+1);
|
||||
document.getElementById('p19-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('p19-quiz-fb');
|
||||
if(btn.dataset.pick === q.ans){ ok++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(3,'p19-quiz'); bumpProgress('p19', 4); }
|
||||
else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; }
|
||||
document.getElementById('p19-quiz-ok').textContent = ok;
|
||||
});
|
||||
});
|
||||
}
|
||||
document.getElementById('p19-quiz-next').addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); });
|
||||
render();
|
||||
}
|
||||
|
||||
function _initP19_dnd(){
|
||||
const items = [
|
||||
{id:'a', cat:'y', html:'медный провод + батарейка + лампа'},
|
||||
{id:'b', cat:'y', html:'раствор соли + 2 угольных электрода + батарейка'},
|
||||
{id:'c', cat:'y', html:'аккумулятор автомобиля при стартере'},
|
||||
{id:'d', cat:'y', html:'солнечная панель в светлый день'},
|
||||
{id:'e', cat:'n', html:'стеклянный стакан + батарейка'},
|
||||
{id:'f', cat:'n', html:'разомкнутый ключ + батарейка'},
|
||||
{id:'g', cat:'n', html:'сухое дерево + батарейка'},
|
||||
{id:'h', cat:'n', html:'медный провод без источника'}
|
||||
];
|
||||
const dnd = setupSorter({ poolId:'p19-dnd-pool', scopeSelector:'#sec-p19', cats:['y','n'], items, columnLayout:false });
|
||||
document.getElementById('p19-dnd-check').addEventListener('click', ()=>{
|
||||
const fb = document.getElementById('p19-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. Нужны: проводник + источник + замкнутая цепь.'; addXp(15,'p19-dnd'); bumpProgress('p19', 20); }
|
||||
else { fb.className='feedback fail'; fb.innerHTML='✗ Ошибок: '+wrong+'. Без источника или с разомкнутой цепью тока нет.'; }
|
||||
});
|
||||
document.getElementById('p19-dnd-reset').addEventListener('click', ()=>{ dnd.reset(); const fb=document.getElementById('p19-dnd-fb'); fb.style.display='none'; });
|
||||
}
|
||||
|
||||
function _initP19_mcq(){
|
||||
const QS = [
|
||||
{q:'Что такое электрический ток?', opts:['хаос. движение','упорядоченное движение зарядов','нагрев тела','сила поля'], ans:1, why:'Ток = направленное движение свободных зарядов.'},
|
||||
{q:'Что нужно для тока?', opts:['только поле','только проводник','свободные носители + поле','магнит'], ans:2, why:'Носители + поле.'},
|
||||
{q:'В батарейке энергия…', opts:['световая → эл.','химическая → эл.','механическая → эл.','тепловая → эл.'], ans:1, why:'Химическая реакция переносит заряды.'},
|
||||
{q:'Зачем нужен источник тока в цепи?', opts:['греть провод','создавать и поддерживать поле','охлаждать','тратить заряд'], ans:1, why:'Источник поддерживает разность потенциалов.'},
|
||||
{q:'Что переносит заряды внутри источника против поля?', opts:['внешние силы','сторонние силы','гравитация','магнетизм'], ans:1, why:'Это и есть «сторонние силы».'},
|
||||
{q:'Куда «бегут» свободные электроны в цепи (от куда к куда)?', opts:['от + к −','от − к +','туда-сюда','стоят на месте'], ans:1, why:'Электроны двигаются от − к + по внешней цепи (против тока).'}
|
||||
];
|
||||
let i = 0, ok = 0, done = 0, awarded = false;
|
||||
function render(){
|
||||
const q = QS[i]; const wrap = document.getElementById('p19-mcq'); if(!wrap) return;
|
||||
let h = '<div style="padding:10px 14px;background:rgba(15,23,42,.04);border-radius:9px;margin-bottom:10px;font-size:.95rem;line-height:1.5"><b>Вопрос '+(i+1)+'.</b> '+q.q+'</div><div style="display:grid;grid-template-columns:1fr;gap:6px">';
|
||||
q.opts.forEach((opt,k)=>{ h += '<button class="btn" data-k="'+k+'" style="text-align:left;padding:10px 14px">'+String.fromCharCode(65+k)+'. '+opt+'</button>'; });
|
||||
h += '</div><div class="feedback" id="p19-mcq-fb"></div><div class="actions"><button class="btn" id="p19-mcq-next">Следующий</button></div>';
|
||||
wrap.innerHTML = h;
|
||||
document.getElementById('p19-mcq-i').textContent = (i+1);
|
||||
document.getElementById('p19-mcq-ok').textContent = ok;
|
||||
wrap.querySelectorAll('[data-k]').forEach(btn=>{
|
||||
btn.addEventListener('click', ()=>{
|
||||
if(btn.disabled) return; wrap.querySelectorAll('[data-k]').forEach(b=>b.disabled=true);
|
||||
const k = +btn.dataset.k; const fb = document.getElementById('p19-mcq-fb');
|
||||
if(k===q.ans){ ok++; done++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(2,'p19-mcq'); bumpProgress('p19', 3); }
|
||||
else { done++; fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; }
|
||||
document.getElementById('p19-mcq-ok').textContent = ok;
|
||||
if(done >= QS.length && !awarded && ok >= 4){ awarded = true; setTimeout(()=>{ const wf=document.getElementById('p19-mcq-fb'); wf.className='feedback ok'; wf.innerHTML='✓ +15 XP — тренажёр пройден.'; addXp(15,'p19-mcq-bonus'); bumpProgress('p19', 15); }, 600); }
|
||||
});
|
||||
});
|
||||
const nb = document.getElementById('p19-mcq-next'); if(nb) nb.addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); });
|
||||
}
|
||||
render();
|
||||
}
|
||||
|
||||
/* ======== §20 — Сила и направление тока ======== */
|
||||
function build_p20(){
|
||||
const box = document.getElementById('p20-body');
|
||||
let h = '';
|
||||
|
||||
h += makeCard('theory', 'Сила тока', '§ 20.1',
|
||||
'<p><b>Сила тока</b> $I$ показывает, сколько заряда проходит через поперечное сечение проводника за единицу времени:</p>'
|
||||
+'<p style="text-align:center;margin:8px 0">$$I = \\dfrac{q}{t}$$</p>'
|
||||
+'<p>Единица измерения — <b>Ампер (А)</b>. <b>1 А</b> — это $1$ Кл, проходящий за $1$ с (это очень много электронов: $\\approx 6\\cdot 10^{18}$ за секунду!).</p>'
|
||||
+'<p>Названа в честь французского физика Андре-Мари Ампера.</p>'
|
||||
);
|
||||
h += makeCard('rule', 'Направление тока', '§ 20.2',
|
||||
'<p>Исторически за направление тока приняли направление движения <b>положительных зарядов</b> — от «+» к «−» во внешней цепи.</p>'
|
||||
+'<p>Однако в металлах реально двигаются <b>электроны</b> — от «−» к «+», то есть <b>против</b> направления тока.</p>'
|
||||
+'<p>Это «договорённость» — она сформировалась до открытия электрона. Менять её уже поздно.</p>'
|
||||
);
|
||||
h += makeCard('example', 'Типичные токи', '§ 20.3',
|
||||
'<table style="width:100%;border-collapse:collapse;font-size:.92rem"><tbody>'
|
||||
+'<tr><td style="padding:5px;border-bottom:1px dashed var(--border)">наушники</td><td style="padding:5px;text-align:right;border-bottom:1px dashed var(--border)"><code>~1 мА</code></td></tr>'
|
||||
+'<tr><td style="padding:5px;border-bottom:1px dashed var(--border)">светодиод</td><td style="padding:5px;text-align:right;border-bottom:1px dashed var(--border)"><code>~10 мА</code></td></tr>'
|
||||
+'<tr><td style="padding:5px;border-bottom:1px dashed var(--border)">лампочка карманного фонаря</td><td style="padding:5px;text-align:right;border-bottom:1px dashed var(--border)"><code>~0,3 А</code></td></tr>'
|
||||
+'<tr><td style="padding:5px;border-bottom:1px dashed var(--border)">лампа 60 Вт в розетке</td><td style="padding:5px;text-align:right;border-bottom:1px dashed var(--border)"><code>~0,27 А</code></td></tr>'
|
||||
+'<tr><td style="padding:5px;border-bottom:1px dashed var(--border)">чайник электрический</td><td style="padding:5px;text-align:right;border-bottom:1px dashed var(--border)"><code>~10 А</code></td></tr>'
|
||||
+'<tr><td style="padding:5px;border-bottom:1px dashed var(--border)">стартер автомобиля</td><td style="padding:5px;text-align:right;border-bottom:1px dashed var(--border)"><code>~200 А</code></td></tr>'
|
||||
+'<tr><td style="padding:5px">молния</td><td style="padding:5px;text-align:right"><code>$\\sim 10^4 - 10^5$ А</code></td></tr>'
|
||||
+'</tbody></table>'
|
||||
);
|
||||
|
||||
/* 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">Меняй $I$ — увидь, как меняется скорость потока электронов в проводе. Лампа загорается сильнее при большем токе.</div>'
|
||||
+'<div class="sliders" style="margin-bottom:10px">'
|
||||
+'<label>$I$, А: <b id="p20-iv">0.3</b><input type="range" id="p20-i" min="0" max="3" step="0.1" value="0.3"></label>'
|
||||
+'</div>'
|
||||
+'<svg id="p20-sim" viewBox="0 0 460 180" style="width:100%;height:auto;background:#f8fafc;border-radius:9px;border:1px solid var(--border)"></svg>'
|
||||
+'<div class="score-display" style="margin-top:10px"><span>За 1 с пройдёт <b id="p20-q1">0.3</b> Кл</span><span>Это <b id="p20-ne">1.9×10<sup>18</sup></b> электронов</span></div>'
|
||||
+'</div>';
|
||||
|
||||
/* IV2 — викторина «по формуле» */
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-2</span><div class="wg-title">Найди по формуле $I = q/t$</div></div>'
|
||||
+'<div class="wg-help">Числовые вопросы.</div>'
|
||||
+'<div id="p20-quiz"></div>'
|
||||
+'<div class="actions"><button class="btn" id="p20-quiz-next">Следующая</button></div>'
|
||||
+'<div class="score-display" style="margin-top:10px"><span>Раунд: <b id="p20-quiz-r">1</b> / 5</span><span>Правильно: <b id="p20-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="p20-dnd-pool"></div>'
|
||||
+'<div style="display:grid;grid-template-columns:repeat(5,1fr);gap:8px;margin-top:10px">'
|
||||
+'<div class="drop-box"><h5>1. Меньше</h5><div class="drop-items" data-cat="r1"></div></div>'
|
||||
+'<div class="drop-box"><h5>2</h5><div class="drop-items" data-cat="r2"></div></div>'
|
||||
+'<div class="drop-box"><h5>3</h5><div class="drop-items" data-cat="r3"></div></div>'
|
||||
+'<div class="drop-box"><h5>4</h5><div class="drop-items" data-cat="r4"></div></div>'
|
||||
+'<div class="drop-box"><h5>5. Больше</h5><div class="drop-items" data-cat="r5"></div></div>'
|
||||
+'</div>'
|
||||
+'<div class="actions"><button class="btn primary" id="p20-dnd-check">Проверить</button><button class="btn" id="p20-dnd-reset">Сброс</button></div>'
|
||||
+'<div class="feedback" id="p20-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="p20-task"></div>'
|
||||
+'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="p20-task-i">1</b> / 5</span><span>Правильно: <b id="p20-task-ok">0</b></span></div>'
|
||||
+'</div>';
|
||||
|
||||
box.innerHTML = h + secNavFor('p20') + readButton('p20');
|
||||
renderMath(box);
|
||||
wireReadBtn('p20');
|
||||
|
||||
_initP20_sim();
|
||||
_initP20_quiz();
|
||||
_initP20_dnd();
|
||||
_initP20_tasks();
|
||||
}
|
||||
|
||||
function _initP20_sim(){
|
||||
_killSim('p20sim');
|
||||
const svg = document.getElementById('p20-sim'); if(!svg) return;
|
||||
const N = 22;
|
||||
const electrons = [];
|
||||
for(let i=0;i<N;i++) electrons.push({ x: 60 + i*16, y: 90 });
|
||||
let I = 0.3;
|
||||
function tick(){
|
||||
if(!_isVisible('p20')){ _SIMS.p20sim.raf = requestAnimationFrame(tick); return; }
|
||||
/* скорость пропорциональна I */
|
||||
const v = I * 1.5;
|
||||
for(const e of electrons){
|
||||
e.x -= v; /* электроны двигаются справа налево (против тока, которое идёт слева направо) */
|
||||
if(e.x < 60) e.x += (400 - 60);
|
||||
}
|
||||
let s = '';
|
||||
/* провод */
|
||||
s += '<rect x="60" y="80" width="340" height="20" fill="#cbd5e1" stroke="#0f172a" stroke-width="2" rx="3"/>';
|
||||
/* стрелки тока I (направление + → −, слева направо для удобства) */
|
||||
if(I > 0){
|
||||
s += '<text x="230" y="60" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="13" font-weight="700" fill="#d97706">I →</text>';
|
||||
s += window.PHYS.drawArrow(190, 70, 270, 70, '#d97706', 2.2, 9);
|
||||
}
|
||||
/* электроны */
|
||||
for(const e of electrons){
|
||||
s += '<circle cx="'+e.x.toFixed(1)+'" cy="'+e.y+'" r="4" fill="#2563eb" stroke="#0f172a" stroke-width="0.5"/>';
|
||||
}
|
||||
/* подпись о направлении электронов */
|
||||
if(I > 0){
|
||||
s += '<text x="230" y="135" text-anchor="middle" font-family="Inter,sans-serif" font-size="11" fill="#2563eb">электроны ← (против тока)</text>';
|
||||
}
|
||||
/* лампа справа */
|
||||
s += window.PHYS.lightbulbSymbol(420, 90, 16);
|
||||
/* свечение зависит от I */
|
||||
if(I > 0){
|
||||
const glow = Math.min(1, I/2);
|
||||
s += '<circle cx="420" cy="90" r="'+(20+I*10).toFixed(0)+'" fill="#fde047" opacity="'+(glow*0.4).toFixed(2)+'"/>';
|
||||
s += '<circle cx="420" cy="90" r="'+(34+I*15).toFixed(0)+'" fill="#fbbf24" opacity="'+(glow*0.15).toFixed(2)+'"/>';
|
||||
}
|
||||
svg.innerHTML = s;
|
||||
_SIMS.p20sim.raf = requestAnimationFrame(tick);
|
||||
}
|
||||
_SIMS.p20sim = { raf: 0 };
|
||||
_SIMS.p20sim.raf = requestAnimationFrame(tick);
|
||||
function update(){
|
||||
I = +document.getElementById('p20-i').value;
|
||||
document.getElementById('p20-iv').textContent = I.toFixed(1);
|
||||
document.getElementById('p20-q1').textContent = I.toFixed(1);
|
||||
const Ne = I / E_CHARGE;
|
||||
document.getElementById('p20-ne').innerHTML = (Ne/1e18).toFixed(2)+'×10<sup>18</sup>';
|
||||
}
|
||||
document.getElementById('p20-i').addEventListener('input', update);
|
||||
update();
|
||||
}
|
||||
|
||||
function _initP20_quiz(){
|
||||
const QS = [
|
||||
{q:'$q = 6$ Кл прошло за $t = 2$ с. Найди $I$ (А).', ans:3, tol:0.05, why:'$I = 6/2 = 3$ А.'},
|
||||
{q:'$I = 0{,}5$ А, $t = 10$ с. Найди $q$ (Кл).', ans:5, tol:0.05, why:'$q = It = 0{,}5 \\cdot 10 = 5$ Кл.'},
|
||||
{q:'$q = 60$ Кл, $I = 2$ А. Найди $t$ (с).', ans:30, tol:0.5, why:'$t = q/I = 60/2 = 30$ с.'},
|
||||
{q:'За 1 минуту прошёл заряд $q = 30$ Кл. Найди $I$ (А).', ans:0.5, tol:0.05, why:'$I = 30/60 = 0{,}5$ А.'},
|
||||
{q:'$I = 0{,}1$ А течёт 5 мин. Какой заряд (Кл)?', ans:30, tol:0.5, why:'$t = 300$ с, $q = 0{,}1 \\cdot 300 = 30$ Кл.'}
|
||||
];
|
||||
let i = 0, ok = 0;
|
||||
function render(){
|
||||
const t = QS[i]; const wrap = document.getElementById('p20-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">'+t.q+'</div>'
|
||||
+'<div class="boss-row"><input type="number" step="0.01" class="tinp" id="p20-quiz-inp" placeholder="число" style="width:140px">'
|
||||
+'<button class="btn primary" id="p20-quiz-go">Ответ</button></div>'
|
||||
+'<div class="feedback" id="p20-quiz-fb"></div>';
|
||||
document.getElementById('p20-quiz-r').textContent = (i+1);
|
||||
document.getElementById('p20-quiz-ok').textContent = ok;
|
||||
document.getElementById('p20-quiz-go').addEventListener('click', ()=>{
|
||||
const v = parseFloat((document.getElementById('p20-quiz-inp').value || '').replace(',','.'));
|
||||
const fb = document.getElementById('p20-quiz-fb');
|
||||
if(isNaN(v)){ fb.className='feedback fail'; fb.innerHTML='Введи число.'; return; }
|
||||
if(Math.abs(v - t.ans) < t.tol){ ok++; fb.className='feedback ok'; fb.innerHTML='✓ Верно! '+t.why; addXp(3,'p20-quiz'); bumpProgress('p20', 4); }
|
||||
else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. Ответ: '+t.ans+'. '+t.why; }
|
||||
document.getElementById('p20-quiz-ok').textContent = ok;
|
||||
renderMath(wrap);
|
||||
});
|
||||
renderMath(wrap);
|
||||
}
|
||||
document.getElementById('p20-quiz-next').addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); });
|
||||
render();
|
||||
}
|
||||
|
||||
function _initP20_dnd(){
|
||||
const items = [
|
||||
{id:'h', cat:'r1', html:'наушники ($1$ мА)'},
|
||||
{id:'l', cat:'r2', html:'светодиод ($10$ мА)'},
|
||||
{id:'f', cat:'r3', html:'лампа в розетке ($0{,}3$ А)'},
|
||||
{id:'k', cat:'r4', html:'чайник ($10$ А)'},
|
||||
{id:'s', cat:'r5', html:'стартер ($200$ А)'}
|
||||
];
|
||||
const dnd = setupSorter({ poolId:'p20-dnd-pool', scopeSelector:'#sec-p20', cats:['r1','r2','r3','r4','r5'], items, columnLayout:false });
|
||||
document.getElementById('p20-dnd-check').addEventListener('click', ()=>{
|
||||
const fb = document.getElementById('p20-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. Бытовые токи — от миллиампер до 100+ А.'; addXp(15,'p20-dnd'); bumpProgress('p20', 20); }
|
||||
else { fb.className='feedback fail'; fb.innerHTML='✗ Ошибок: '+wrong+'.'; }
|
||||
});
|
||||
document.getElementById('p20-dnd-reset').addEventListener('click', ()=>{ dnd.reset(); const fb=document.getElementById('p20-dnd-fb'); fb.style.display='none'; });
|
||||
}
|
||||
|
||||
function _initP20_tasks(){
|
||||
const TASKS = [
|
||||
{q:'Через лампу за 0,5 с прошёл заряд 0,15 Кл. Найди ток (А).', ans:0.3, tol:0.02, why:'$I = q/t = 0{,}15/0{,}5 = 0{,}3$ А.'},
|
||||
{q:'$I = 2$ А течёт 10 минут. Сколько Кл пройдёт?', ans:1200, tol:10, why:'$t = 600$ с, $q = 2 \\cdot 600 = 1200$ Кл.'},
|
||||
{q:'Сколько электронов проходит через сечение провода за 1 с при $I = 1$ А? Ответ в формате $a \\cdot 10^{18}$, введи $a$.', ans:6.25, tol:0.05, why:'$N = I \\cdot 1/e = 1/(1{,}6\\cdot10^{-19}) = 6{,}25 \\cdot 10^{18}$.'},
|
||||
{q:'Через спираль чайника за 30 секунд прошло 300 Кл. Найди ток (А).', ans:10, tol:0.1, why:'$I = 300/30 = 10$ А.'},
|
||||
{q:'Светодиод работает на токе $I = 20$ мА = $0{,}02$ А. Сколько Кл пройдёт за час?', ans:72, tol:1, why:'$t = 3600$ с, $q = 0{,}02 \\cdot 3600 = 72$ Кл.'}
|
||||
];
|
||||
let i = 0, ok = 0, done = 0, awarded = false;
|
||||
function render(){
|
||||
const t = TASKS[i]; const wrap = document.getElementById('p20-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="p20-task-inp" placeholder="число" style="width:140px">'
|
||||
+'<button class="btn primary" id="p20-task-go">Ответ</button>'
|
||||
+'<button class="btn" id="p20-task-hint">Подсказка</button>'
|
||||
+'<button class="btn" id="p20-task-next">Следующая</button></div>'
|
||||
+'<div class="boss-hint-txt" id="p20-task-hint-txt">'+t.why+'</div>'
|
||||
+'<div class="feedback" id="p20-task-fb"></div>';
|
||||
document.getElementById('p20-task-i').textContent = (i+1);
|
||||
document.getElementById('p20-task-ok').textContent = ok;
|
||||
document.getElementById('p20-task-go').addEventListener('click', ()=>{
|
||||
const v = parseFloat((document.getElementById('p20-task-inp').value || '').replace(',','.'));
|
||||
const fb = document.getElementById('p20-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,'p20-task'); bumpProgress('p20', 6); }
|
||||
else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. Ответ: '+t.ans+'. '+t.why; }
|
||||
document.getElementById('p20-task-ok').textContent = ok;
|
||||
renderMath(wrap);
|
||||
if(done >= TASKS.length && !awarded && ok >= 4){ awarded = true; setTimeout(()=>{ const wf=document.getElementById('p20-task-fb'); wf.className='feedback ok'; wf.innerHTML='✓ +15 XP — расчёты сданы.'; addXp(15,'p20-task-bonus'); bumpProgress('p20', 15); }, 600); }
|
||||
});
|
||||
document.getElementById('p20-task-hint').addEventListener('click', ()=>{ document.getElementById('p20-task-hint-txt').classList.toggle('show'); });
|
||||
document.getElementById('p20-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