diff --git a/frontend/textbooks/physics_8_ch2.html b/frontend/textbooks/physics_8_ch2.html index 250fc9e..4fbee97 100644 --- a/frontend/textbooks/physics_8_ch2.html +++ b/frontend/textbooks/physics_8_ch2.html @@ -423,8 +423,19 @@ const SIDEBARS = { ["ТБ","не голыми руками!"], ["Заземление","для защиты"] ]}, - p28:{title:"Шпаргалка § 28",rows:[["В разработке","Phase 4 Wave 1"]]}, - p29:{title:"Шпаргалка § 29",rows:[["В разработке","Phase 4 Wave 1"]]}, + p28:{title:"Шпаргалка § 28",rows:[ + ["Полюсы","N (север), S (юг)"], + ["Одноим.","отталкиваются"], + ["Разноим.","притягиваются"], + ["Разрез магнита","2 новых магнита (нет монополя)"], + ["Магн. поле Земли","ось $\\approx$ географ."] + ]}, + p29:{title:"Шпаргалка § 29",rows:[ + ["$\\vec B$","магнитная индукция, Тл"], + ["Линии $\\vec B$","выходят из N, входят в S"], + ["Линии замкнуты","нет источника / стока"], + ["Опилки","показывают линии $\\vec B$"] + ]}, p30:{title:"Шпаргалка § 30",rows:[["В разработке","Phase 4 Wave 2"]]}, p31:{title:"Шпаргалка § 31",rows:[["В разработке","Phase 4 Wave 2"]]}, final2:{title:"Шпаргалка ★",rows:[["В разработке","Phase 4 Wave 2"]]} @@ -447,8 +458,8 @@ const TIPS=[ {sec:'p25',html:"При параллельном соединении на каждой ветви одно и то же напряжение. Токи складываются. Сопротивление считается по особой формуле — в итоге $R_{общ}$ меньше любого из $R_1$, $R_2$."}, {sec:'p26',html:"$A = UIt$ — энергия, которую ток отдаёт прибору. $P = UI$ — это мощность (Дж/с = Вт). В резисторе вся эта энергия превращается в тепло — это закон Джоуля-Ленца: $Q = I^2 R t$."}, {sec:'p27',html:"Счётчик в квартире меряет энергию в кВт·ч: 1 кВт·ч — это работа за 1 час мощностью 1 кВт. Стоимость = энергия × тариф. ТБ: розетка под 220 В может ударить смертельным током."}, - {sec:'p28',html:"Параграф § 28 будет реализован в Phase 4 Wave 1. Используем хелперы из phys.js и optics.js."}, - {sec:'p29',html:"Параграф § 29 будет реализован в Phase 4 Wave 1. Используем хелперы из phys.js и optics.js."}, + {sec:'p28',html:"Два полюса магнита: N (север) и S (юг). Как и заряды: одноимённые отталкиваются, разноимённые притягиваются. Но в отличие от зарядов, разрезать магнит и получить «только N» нельзя — выскочат новые два полюса."}, + {sec:'p29',html:"Вокруг магнита есть магнитное поле — оно действует на железные предметы и магнитные стрелки. Линии поля выходят из N и входят в S, и они замкнуты (в отличие от линий эл. поля). Опилки на бумаге над магнитом красиво «рисуют» эти линии."}, {sec:'p30',html:"Параграф § 30 будет реализован в Phase 4 Wave 2. Используем хелперы из phys.js и optics.js."}, {sec:'p31',html:"Параграф § 31 будет реализован в Phase 4 Wave 2. Используем хелперы из phys.js и optics.js."}, {sec:'final2',html:"Параграф ★ будет реализован в Phase 4 Wave 2. Используем хелперы из phys.js и optics.js."} @@ -471,8 +482,8 @@ const BUILDERS = { p25: ()=>{ build_p25(); }, p26: ()=>{ build_p26(); }, p27: ()=>{ build_p27(); }, - p28: ()=>{ const box=document.getElementById('p28-body'); box.innerHTML = buildStub('p28', 'Постоянные магниты', 'Phase 4 Wave 1') + secNavFor('p28') + readButton('p28'); renderMath(box); wireReadBtn('p28'); }, - p29: ()=>{ const box=document.getElementById('p29-body'); box.innerHTML = buildStub('p29', 'Магнитное поле', 'Phase 4 Wave 1') + secNavFor('p29') + readButton('p29'); renderMath(box); wireReadBtn('p29'); }, + p28: ()=>{ build_p28(); }, + p29: ()=>{ build_p29(); }, p30: ()=>{ const box=document.getElementById('p30-body'); box.innerHTML = buildStub('p30', 'Магнитное поле тока', 'Phase 4 Wave 2') + secNavFor('p30') + readButton('p30'); renderMath(box); wireReadBtn('p30'); }, p31: ()=>{ const box=document.getElementById('p31-body'); box.innerHTML = buildStub('p31', 'Магнитное поле прямого проводника и катушки с током. Электромагнит', 'Phase 4 Wave 2') + secNavFor('p31') + readButton('p31'); renderMath(box); wireReadBtn('p31'); }, final2: ()=>{ const box=document.getElementById('final2-body'); box.innerHTML = buildStub('final2', 'Финал главы', 'Phase 4 Wave 2') + secNavFor('final2') + readButton('final2'); renderMath(box); wireReadBtn('final2'); } @@ -4337,6 +4348,429 @@ function _initP27_tasks(){ render(); } +/* ====================================================================== + PHASE 4 · WAVE 1 — §28, §29 + ====================================================================== */ + +/* Хелпер: рисует магнитную полосу N-S */ +function _drawMagnet(x, y, w, hMag, flipped){ + const halfW = w/2; + const nCol = '#dc2626', sCol = '#2563eb'; + const left = flipped ? sCol : nCol; + const right = flipped ? nCol : sCol; + const leftLab = flipped ? 'S' : 'N'; + const rightLab = flipped ? 'N' : 'S'; + let s = ''; + s += ''; + s += ''; + s += ''+leftLab+''; + s += ''+rightLab+''; + return s; +} + +/* ======== §28 — Постоянные магниты ======== */ +function build_p28(){ + const box = document.getElementById('p28-body'); + let h = ''; + + h += makeCard('theory', 'Что такое магнит', '§ 28.1', + '

Постоянный магнит — тело, обладающее магнитными свойствами длительное время. Чаще всего из железа, никеля, кобальта или сплавов (например, «магнитное железо» — ферриты).

' + +'

У любого магнита есть два полюса: северный (N) и южный (S). Они расположены на противоположных концах.

' + +'

Сила взаимодействия сосредоточена у полюсов — там магнит «прилипает» к железу сильнее всего.

' + ); + h += makeCard('rule', 'Закон взаимодействия полюсов', '§ 28.2', + '

По аналогии с зарядами:

' + +'' + +'

В отличие от электрических зарядов, нельзя получить магнит только с одним полюсом. Если разрезать магнит пополам — получатся два новых магнита, у каждого свои N и S.

' + ); + h += makeCard('example', 'Магнитное поле Земли', '§ 28.3', + '

Земля — гигантский магнит. Её магнитные полюсы расположены вблизи географических (но не точно на них).

' + +'

Важно: «северный географический» близок к южному магнитному полюсу Земли. Поэтому северный конец стрелки компаса (он же N) притягивается к географическому северу.

' + +'

Магнитное поле Земли защищает нас от космических лучей и помогает ориентироваться компасу. Полюсы со временем «дрейфуют».

' + ); + + /* 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('p28') + readButton('p28'); + renderMath(box); + wireReadBtn('p28'); + + _initP28_two(); + _initP28_quiz(); + _initP28_dnd(); + _initP28_mcq(); +} + +function _initP28_two(){ + const svg = document.getElementById('p28-sim'); if(!svg) return; + function draw(){ + const flipped = +document.getElementById('p28-flip').value === 1; + let s = ''; + /* левый магнит — фиксирован */ + s += _drawMagnet(80, 70, 120, 60, false); /* N(left) S(right) */ + /* правый магнит */ + s += _drawMagnet(260, 70, 120, 60, flipped); /* зависит от флага */ + /* Между магнитами: соседствуют правая половина левого (S) и левая половина правого */ + /* левая половина правого: flipped ? N : S */ + const rightInner = flipped ? 'N' : 'S'; + /* левый внутр (правая половина левого) = S */ + const leftInner = 'S'; + const attract = leftInner !== rightInner; + /* стрелки силы */ + if(attract){ + /* притяжение — стрелки идут навстречу */ + s += window.PHYS.drawArrow(190, 100, 230, 100, '#10b981', 2.5, 10); + s += window.PHYS.drawArrow(270, 100, 230, 100, '#10b981', 2.5, 10); + s += 'ПРИТЯГИВАЮТСЯ'; + } else { + /* отталкивание — стрелки расходятся */ + s += window.PHYS.drawArrow(220, 100, 190, 100, '#dc2626', 2.5, 10); + s += window.PHYS.drawArrow(240, 100, 270, 100, '#dc2626', 2.5, 10); + s += 'ОТТАЛКИВАЮТСЯ'; + } + svg.innerHTML = s; + document.getElementById('p28-act').textContent = attract ? 'притягиваются' : 'отталкиваются'; + } + document.getElementById('p28-flip').addEventListener('change', draw); + draw(); +} + +function _initP28_quiz(){ + const QS = [ + {sit:'N подносим к N', ans:'R', why:'Одноимённые → отталкивание.'}, + {sit:'N подносим к S', ans:'A', why:'Разноимённые → притяжение.'}, + {sit:'S подносим к S', ans:'R', why:'Одноимённые → отталкивание.'}, + {sit:'S подносим к N', ans:'A', why:'Разноимённые → притяжение.'}, + {sit:'Полосовой магнит к стрелке компаса (северный конец)', ans:'A', why:'Северный конец стрелки притягивается к S полюсу магнита, отталкивается от N.'} + ]; + let i = 0, ok = 0; + function render(){ + const q = QS[i]; const wrap = document.getElementById('p28-quiz'); if(!wrap) return; + wrap.innerHTML = + '
'+q.sit+'
' + +'
' + +'' + +'' + +'
' + +''; + document.getElementById('p28-quiz-r').textContent = (i+1); + document.getElementById('p28-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('p28-quiz-fb'); + if(btn.dataset.pick === q.ans){ ok++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(3,'p28-quiz'); bumpProgress('p28', 4); } + else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; } + document.getElementById('p28-quiz-ok').textContent = ok; + }); + }); + } + document.getElementById('p28-quiz-next').addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); }); + render(); +} + +function _initP28_dnd(){ + const items = [ + {id:'a', cat:'t', html:'у магнита 2 полюса: N и S'}, + {id:'b', cat:'t', html:'N–S притягиваются'}, + {id:'c', cat:'t', html:'разрезать магнит → 2 магнита'}, + {id:'d', cat:'t', html:'Земля — гигантский магнит'}, + {id:'e', cat:'f', html:'можно получить один полюс'}, + {id:'f', cat:'f', html:'N–N притягиваются'}, + {id:'g', cat:'f', html:'магнит работает только при подключении'}, + {id:'h', cat:'f', html:'дерево — магнитный материал'} + ]; + const dnd = setupSorter({ poolId:'p28-dnd-pool', scopeSelector:'#sec-p28', cats:['t','f'], items, columnLayout:false }); + document.getElementById('p28-dnd-check').addEventListener('click', ()=>{ + const fb = document.getElementById('p28-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,'p28-dnd'); bumpProgress('p28', 20); } + else { fb.className='feedback fail'; fb.innerHTML='✗ Ошибок: '+wrong+'.'; } + }); + document.getElementById('p28-dnd-reset').addEventListener('click', ()=>{ dnd.reset(); const fb=document.getElementById('p28-dnd-fb'); fb.style.display='none'; }); +} + +function _initP28_mcq(){ + const QS = [ + {q:'Сколько полюсов у магнита?', opts:['1','2','3','много'], ans:1, why:'У любого магнита всегда 2 полюса.'}, + {q:'Какие материалы притягиваются магнитом?', opts:['все','железо, никель, кобальт','медь','стекло'], ans:1, why:'Ферромагнетики.'}, + {q:'Что произойдёт при разрезании магнита?', opts:['станет 2 разных магнита N и S','станет ничего','станут 2 полноценных магнита','полюса исчезнут'], ans:2, why:'Каждый «огрызок» снова имеет 2 полюса.'}, + {q:'Северный географический полюс Земли — это магнитный…', opts:['северный','южный','никакой','нейтральный'], ans:1, why:'Север географический ≈ южный магнитный (так задумано в физике).'}, + {q:'Что показывает северный конец компаса?', opts:['на N магнита','на N полюс магнита','на географический север','куда хочешь'], ans:2, why:'Стрелка компаса север «как бы» указывает на северный географический полюс.'}, + {q:'Какая сила действует между магнитами?', opts:['гравитационная','электрическая','магнитная','ядерная'], ans:2, why:'Магнитная.'} + ]; + let i = 0, ok = 0, done = 0, awarded = false; + function render(){ + const q = QS[i]; const wrap = document.getElementById('p28-mcq'); if(!wrap) return; + let h = '
Вопрос '+(i+1)+'. '+q.q+'
'; + q.opts.forEach((opt,k)=>{ h += ''; }); + h += '
'; + wrap.innerHTML = h; + document.getElementById('p28-mcq-i').textContent = (i+1); + document.getElementById('p28-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('p28-mcq-fb'); + if(k===q.ans){ ok++; done++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(2,'p28-mcq'); bumpProgress('p28', 3); } + else { done++; fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; } + document.getElementById('p28-mcq-ok').textContent = ok; + if(done >= QS.length && !awarded && ok >= 4){ awarded = true; setTimeout(()=>{ const wf=document.getElementById('p28-mcq-fb'); wf.className='feedback ok'; wf.innerHTML='✓ +15 XP — тренажёр пройден.'; addXp(15,'p28-mcq-bonus'); bumpProgress('p28', 15); }, 600); } + }); + }); + const nb = document.getElementById('p28-mcq-next'); if(nb) nb.addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); }); + } + render(); +} + +/* ======== §29 — Магнитное поле ======== */ +function build_p29(){ + const box = document.getElementById('p29-body'); + let h = ''; + + h += makeCard('theory', 'Что такое магнитное поле', '§ 29.1', + '

Подобно тому как заряды создают электрическое поле, магниты создают вокруг себя магнитное поле.

' + +'

Силовая характеристика поля — магнитная индукция $\\vec B$. Единица измерения — Тесла (Тл), в честь Никола Тесла.

' + +'

Магнитное поле обнаруживается по силе, действующей на:

' + +'' + ); + h += makeCard('rule', 'Линии магнитной индукции', '§ 29.2', + '

Магнитное поле наглядно изображают линиями магнитной индукции:

' + +'' + +'

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

' + ); + h += makeCard('example', 'Опыт с железными опилками', '§ 29.3', + '

Если на стекло над магнитом насыпать железные опилки, они выстраиваются вдоль линий магнитной индукции. Получается «фотография» магнитного поля.

' + +'

Сейчас увидим, как это выглядит.

' + ); + + /* IV1 — линии магн. индукции */ + h += '
' + +'
IV-1
Линии магнитного поля полосового магнита
' + +'
Линии выходят из N и входят в S — снаружи. Внутри магнита идут от S к N, замыкая контур.
' + +'' + +'
'; + + /* IV2 — викторина «где северный полюс» */ + h += '
' + +'
IV-2
Знаешь линии поля?
' + +'
Правда или ложь о линиях $\\vec B$.
' + +'
' + +'
' + +'
Раунд: 1 / 5Правильно: 0
' + +'
'; + + /* IV3 — DnD сравнение полей */ + h += '
' + +'
IV-3
Электрическое vs магнитное поле
' + +'
К какому полю относится свойство?
' + +'
' + +'
' + +'
Электрическое
' + +'
Магнитное
' + +'
' + +'
' + +'' + +'
'; + + /* IV4 — MCQ */ + h += '
' + +'
IV-4
Тренажёр: 6 вопросов
' + +'
4+ — +15 XP.
' + +'
' + +'
Вопрос: 1 / 6Правильно: 0
' + +'
'; + + box.innerHTML = h + secNavFor('p29') + readButton('p29'); + renderMath(box); + wireReadBtn('p29'); + + _initP29_lines(); + _initP29_quiz(); + _initP29_dnd(); + _initP29_mcq(); +} + +function _initP29_lines(){ + const svg = document.getElementById('p29-sim'); if(!svg) return; + /* Полосовой магнит N(слева) S(справа), линии поля изгибаются. + Параметрически: серия эллиптических дуг разного размера, выходящих из N. */ + const cx = 230, cy = 140; + const magW = 160, magH = 40; + let s = ''; + /* нарисуем магнит */ + s += _drawMagnet(cx - magW/2, cy - magH/2, magW, magH, false); /* N(left), S(right) */ + /* линии: эллипсы между N(150,140) и S(310,140), радиус растёт */ + for(let k = 0; k < 7; k++){ + const ry = 30 + k*25; + /* нарисуем верхнюю и нижнюю половину эллипса как path */ + const xN = cx - magW/2; + const xS = cx + magW/2; + /* верхняя половина: дуга от xN,cy через (cx,cy-ry) до xS,cy */ + const cx1 = (xN+xS)/2; + /* стрелка на верхушке */ + s += ''; + s += ''; + /* стрелка направления — посередине верхней дуги, направлена вправо */ + if(k < 5){ + s += window.PHYS.drawArrow(cx-6, cy - ry + 2, cx+6, cy - ry + 2, '#7c3aed', 1.5, 7); + s += window.PHYS.drawArrow(cx-6, cy + ry - 2, cx+6, cy + ry - 2, '#7c3aed', 1.5, 7); + } + } + /* пара прямых линий близко к оси (горизонтально между полюсами) */ + s += ''; + s += ''; + /* подписи */ + s += 'линии магнитной индукции $\\vec B$'; + s += 'снаружи: N → S'; + s += 'внутри: S → N (замыкают)'; + svg.innerHTML = s; +} + +function _initP29_quiz(){ + const QS = [ + {st:'Линии магнитного поля выходят из S и входят в N.', ans:'F', why:'Наоборот: из N в S.'}, + {st:'Линии магнитного поля замкнуты.', ans:'T', why:'Внутри магнита они идут от S к N, замыкая контур.'}, + {st:'Линии магнитного поля могут пересекаться.', ans:'F', why:'В каждой точке вектор $\\vec B$ имеет одно направление.'}, + {st:'Чем гуще линии, тем сильнее поле.', ans:'T', why:'Густота показывает $|B|$.'}, + {st:'Магнитное поле действует на неподвижный заряд.', ans:'F', why:'Только на движущийся заряд и на ток!'} + ]; + let i = 0, ok = 0; + function render(){ + const q = QS[i]; const wrap = document.getElementById('p29-quiz'); if(!wrap) return; + wrap.innerHTML = + '
"'+q.st+'"
' + +'
' + +'' + +'' + +'
' + +''; + document.getElementById('p29-quiz-r').textContent = (i+1); + document.getElementById('p29-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('p29-quiz-fb'); + if(btn.dataset.pick === q.ans){ ok++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(3,'p29-quiz'); bumpProgress('p29', 4); } + else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; } + document.getElementById('p29-quiz-ok').textContent = ok; + renderMath(wrap); + }); + }); + renderMath(wrap); + } + document.getElementById('p29-quiz-next').addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); }); + render(); +} + +function _initP29_dnd(){ + const items = [ + {id:'a', cat:'e', html:'линии начинаются на +, кончаются на −'}, + {id:'b', cat:'e', html:'действует на любой заряд'}, + {id:'c', cat:'e', html:'источники — заряды'}, + {id:'d', cat:'e', html:'$U = A/q$'}, + {id:'e', cat:'m', html:'линии замкнуты (без начала и конца)'}, + {id:'f', cat:'m', html:'действует на движ. заряды и ток'}, + {id:'g', cat:'m', html:'источники — магниты и токи'}, + {id:'h', cat:'m', html:'$\\vec B$ — индукция, [Тл]'} + ]; + const dnd = setupSorter({ poolId:'p29-dnd-pool', scopeSelector:'#sec-p29', cats:['e','m'], items, columnLayout:false }); + document.getElementById('p29-dnd-check').addEventListener('click', ()=>{ + const fb = document.getElementById('p29-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,'p29-dnd'); bumpProgress('p29', 20); renderMath(fb); } + else { fb.className='feedback fail'; fb.innerHTML='✗ Ошибок: '+wrong+'.'; renderMath(fb); } + }); + document.getElementById('p29-dnd-reset').addEventListener('click', ()=>{ dnd.reset(); const fb=document.getElementById('p29-dnd-fb'); fb.style.display='none'; }); +} + +function _initP29_mcq(){ + const QS = [ + {q:'Что обозначают $\\vec B$?', opts:['напряжённость','индукцию','потенциал','работу'], ans:1, why:'Магнитная индукция.'}, + {q:'Единица измерения $|B|$?', opts:['Вольт','Ампер','Тесла','Ом'], ans:2, why:'Тесла (Тл).'}, + {q:'Куда направлены линии вне магнита?', opts:['от N к S','от S к N','внутри по кругу','хаос'], ans:0, why:'Снаружи — от N к S.'}, + {q:'Линии $\\vec B$ обладают свойством…', opts:['открытости','замкнутости','пересечения','исчезновения'], ans:1, why:'Магнитное поле — соленоидальное.'}, + {q:'Что отклоняет стрелку компаса?', opts:['заряд','свет','магнитное поле Земли','гравитация'], ans:2, why:'Земля — гигантский магнит.'}, + {q:'Как «увидеть» магнитное поле?', opts:['опилками','спиртом','краской','углём'], ans:0, why:'Железные опилки выстраиваются вдоль линий.'} + ]; + let i = 0, ok = 0, done = 0, awarded = false; + function render(){ + const q = QS[i]; const wrap = document.getElementById('p29-mcq'); if(!wrap) return; + let h = '
Вопрос '+(i+1)+'. '+q.q+'
'; + q.opts.forEach((opt,k)=>{ h += ''; }); + h += '
'; + wrap.innerHTML = h; + document.getElementById('p29-mcq-i').textContent = (i+1); + document.getElementById('p29-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('p29-mcq-fb'); + if(k===q.ans){ ok++; done++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(2,'p29-mcq'); bumpProgress('p29', 3); } + else { done++; fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; } + document.getElementById('p29-mcq-ok').textContent = ok; + renderMath(wrap); + if(done >= QS.length && !awarded && ok >= 4){ awarded = true; setTimeout(()=>{ const wf=document.getElementById('p29-mcq-fb'); wf.className='feedback ok'; wf.innerHTML='✓ +15 XP — тренажёр пройден.'; addXp(15,'p29-mcq-bonus'); bumpProgress('p29', 15); }, 600); } + }); + }); + const nb = document.getElementById('p29-mcq-next'); if(nb) nb.addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); }); + renderMath(wrap); + } + render(); +} + function init(){ loadProgress(); initTheme(); initSidebarToggle(); initSearch(); buildParaSelector(); refreshProgressUI(); loadServerReadState(); goTo(PARAS[0].id);