diff --git a/frontend/textbooks/physics_8_ch2.html b/frontend/textbooks/physics_8_ch2.html index 6e5568a..830d275 100644 --- a/frontend/textbooks/physics_8_ch2.html +++ b/frontend/textbooks/physics_8_ch2.html @@ -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:"Заряд не «торкает» другие заряды напрямую — он создаёт вокруг себя электрическое поле, а уже оно действует силой на другие заряды. Линии поля идут от + к − и показывают направление силы на пробный +заряд."}, {sec:'p18',html:"Напряжение $U$ — это работа поля по перемещению единичного заряда: $A = qU$. Единица — 1 Вольт. Розетка 220 В, батарейка 1,5 В. Чем больше $U$, тем «сильнее» поле толкает заряд."}, - {sec:'p19',html:"Параграф § 19 будет реализован в Phase 3 Wave 1. Используем хелперы из phys.js и optics.js."}, - {sec:'p20',html:"Параграф § 20 будет реализован в Phase 3 Wave 1. Используем хелперы из phys.js и optics.js."}, + {sec:'p19',html:"Ток — это упорядоченное движение свободных зарядов. Чтобы оно поддерживалось, нужен источник тока — батарейка, аккумулятор, генератор. Внутри источника сторонние силы переносят заряды против поля — это и есть «насос электричества»."}, + {sec:'p20',html:"$I = q/t$ — сколько Кулонов прошло через сечение провода за 1 секунду. Единица — Ампер ($1$ А = $1$ Кл/с). За направление тока приняли движение «+» зарядов — хотя в металлах реально двигаются электроны (против тока)."}, {sec:'p21',html:"Параграф § 21 будет реализован в Phase 3 Wave 2. Используем хелперы из phys.js и optics.js."}, {sec:'p22',html:"Параграф § 22 будет реализован в Phase 3 Wave 2. Используем хелперы из phys.js и optics.js."}, {sec:'p23',html:"Параграф § 23 будет реализован в Phase 3 Wave 3. Используем хелперы из phys.js и optics.js."}, @@ -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', + '

Электрический ток — упорядоченное (направленное) движение свободных заряженных частиц.

' + +'

В проводе у каждой точки много электронов, движущихся хаотически. Если приложить эл. поле — все они «сдвигаются» в одну сторону. Это и есть ток.

' + +'

Для существования тока нужно:

' + +'
    ' + +'
  1. свободные носители заряда (электроны в металле, ионы в растворе);
  2. ' + +'
  3. электрическое поле, заставляющее их двигаться упорядоченно.
  4. ' + +'
' + ); + h += makeCard('rule', 'Источники тока', '§ 19.2', + '

Источник тока создаёт и поддерживает эл. поле в цепи. Внутри него «сторонние силы» (химические, механические, световые) переносят заряды против поля — от одного электрода к другому.

' + +'' + ); + h += makeCard('example', 'Простейшая батарейка', '§ 19.3', + '

Два разных металла (например, медь и цинк) опущенные в раствор кислоты, дают электрический ток. Цинк отдаёт электроны в раствор и становится «−». Медь принимает электроны и становится «+».

' + +'

Так устроен гальванический элемент — изобретение Алессандро Вольта (1799 г.). Это была первая в истории батарейка!

' + ); + + /* IV1 — анимация работы батарейки */ + h += '
' + +'
IV-1
Как работает батарейка
' + +'
Включи цепь — увидь, как электроны «бегут» по проводу от $-$ к $+$, а внутри батарейки «насос» переносит их в обратную сторону.
' + +'' + +'
' + +'
'; + + /* IV2 — викторина источников */ + h += '
' + +'
IV-2
Какая энергия превращается в электрическую?
' + +'
Определи тип источника по принципу работы.
' + +'
' + +'
' + +'
Раунд: 1 / 5Правильно: 0
' + +'
'; + + /* IV3 — DnD «можно/нельзя получить ток» */ + h += '
' + +'
IV-3
Есть ли в этой системе ток?
' + +'
Распредели ситуации.
' + +'
' + +'
' + +'
Есть ток
' + +'
Нет тока
' + +'
' + +'
' + +'
' + +'
'; + + /* IV4 — MCQ */ + h += '
' + +'
IV-4
Тренажёр: 6 вопросов
' + +'
4+ — +15 XP.
' + +'
' + +'
Вопрос: 1 / 6Правильно: 0
' + +'
'; + + 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'; + } + /* батарея слева */ + s += ''; + s += 'источник'; + s += '+'; + s += ''; + /* стрелка тока I (внутри цепи) */ + if(on){ + s += 'I →'; + } + /* лампа в центре */ + s += window.PHYS.lightbulbSymbol(230, 90, 18); + if(on){ + /* свечение */ + s += ''; + s += ''; + } + /* электроны двигаются против тока — то есть против хода path */ + for(const e of electrons){ + const p = posAt(-e.t); + s += ''; + s += ''; + } + 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'+q.sit+'' + +'
' + +'' + +'' + +'' + +'' + +'
' + +''; + 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 = '
Вопрос '+(i+1)+'. '+q.q+'
'; + q.opts.forEach((opt,k)=>{ h += ''; }); + h += '
'; + 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', + '

Сила тока $I$ показывает, сколько заряда проходит через поперечное сечение проводника за единицу времени:

' + +'

$$I = \\dfrac{q}{t}$$

' + +'

Единица измерения — Ампер (А). 1 А — это $1$ Кл, проходящий за $1$ с (это очень много электронов: $\\approx 6\\cdot 10^{18}$ за секунду!).

' + +'

Названа в честь французского физика Андре-Мари Ампера.

' + ); + h += makeCard('rule', 'Направление тока', '§ 20.2', + '

Исторически за направление тока приняли направление движения положительных зарядов — от «+» к «−» во внешней цепи.

' + +'

Однако в металлах реально двигаются электроны — от «−» к «+», то есть против направления тока.

' + +'

Это «договорённость» — она сформировалась до открытия электрона. Менять её уже поздно.

' + ); + h += makeCard('example', 'Типичные токи', '§ 20.3', + '' + +'' + +'' + +'' + +'' + +'' + +'' + +'' + +'
наушники~1 мА
светодиод~10 мА
лампочка карманного фонаря~0,3 А
лампа 60 Вт в розетке~0,27 А
чайник электрический~10 А
стартер автомобиля~200 А
молния$\\sim 10^4 - 10^5$ А
' + ); + + /* IV1 — симуляция тока с регулировкой */ + h += '
' + +'
IV-1
Поток электронов в проводе
' + +'
Меняй $I$ — увидь, как меняется скорость потока электронов в проводе. Лампа загорается сильнее при большем токе.
' + +'
' + +'' + +'
' + +'' + +'
За 1 с пройдёт 0.3 КлЭто 1.9×1018 электронов
' + +'
'; + + /* IV2 — викторина «по формуле» */ + h += '
' + +'
IV-2
Найди по формуле $I = q/t$
' + +'
Числовые вопросы.
' + +'
' + +'
' + +'
Раунд: 1 / 5Правильно: 0
' + +'
'; + + /* IV3 — DnD «токи по возрастанию» */ + h += '
' + +'
IV-3
Расставь по возрастанию тока
' + +'
От самого слабого тока к самому большому.
' + +'
' + +'
' + +'
1. Меньше
' + +'
2
' + +'
3
' + +'
4
' + +'
5. Больше
' + +'
' + +'
' + +'' + +'
'; + + /* IV4 — расчётные задачи */ + h += '
' + +'
IV-4
Тренажёр: 5 задач
' + +'
4+ — +15 XP.
' + +'
' + +'
Задача: 1 / 5Правильно: 0
' + +'
'; + + 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 0){ + s += 'I →'; + s += window.PHYS.drawArrow(190, 70, 270, 70, '#d97706', 2.2, 9); + } + /* электроны */ + for(const e of electrons){ + s += ''; + } + /* подпись о направлении электронов */ + if(I > 0){ + s += 'электроны ← (против тока)'; + } + /* лампа справа */ + s += window.PHYS.lightbulbSymbol(420, 90, 16); + /* свечение зависит от I */ + if(I > 0){ + const glow = Math.min(1, I/2); + s += ''; + s += ''; + } + 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)+'×1018'; + } + 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 = + '
'+t.q+'
' + +'
' + +'
' + +''; + 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 = + '
Задача '+(i+1)+'. '+t.q+'
' + +'
' + +'' + +'' + +'
' + +'
'+t.why+'
' + +''; + 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);