From 053c2ebfdda5d1d99f3cad3ccf2de1066dfea394 Mon Sep 17 00:00:00 2001 From: Maxim Dolgolyov Date: Fri, 29 May 2026 23:18:46 +0300 Subject: [PATCH] =?UTF-8?q?feat(phys8=20ch2):=20Phase=202=20Wave=202=20?= =?UTF-8?q?=E2=80=94=20=C2=A715=20=D1=8D=D0=BB=D0=B5=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D1=82=D0=B0=D1=80=D0=BD=D1=8B=D0=B9=20=D0=B7=D0=B0=D1=80=D1=8F?= =?UTF-8?q?=D0=B4=20+=20=C2=A716=20=D1=81=D1=82=D1=80=D0=BE=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=B0=D1=82=D0=BE=D0=BC=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit §15 Электрический заряд. Элементарный заряд: - 3 теории: e = 1.6·10⁻¹⁹ Кл, формула q = Ne, закон сохранения - IV-1: интерактивный калькулятор q ↔ N со slider в логарифм. шкале 10⁶..10¹⁸ электронов, выводит q в Кл и нКл - IV-2: 6 раундов «существует ли такой заряд?» (проверка кратности e) - IV-3: DnD 8 ситуаций «сохраняется / меняется» (заземление, рентген...) - IV-4: 5 расчётных задач с допусками и подсказками §16 Строение атома. Ионы: - 3 теории: планетарная модель, ионы, таблица атомов и ионов - IV-1: главный визуал — интерактивная модель атома: slider'ы Z и число электронов, электроны распределяются по 3 оболочкам (2/8/18), ядро с Z протонов, заряд иона рассчитывается автоматически - IV-2: 6 викторин по таблице ионов - IV-3: DnD 9 частиц на 3 категории (+/-/нейтр) - IV-4: 6 MCQ Глобальная константа E_CHARGE = 1.6e-19 на верхнем уровне. Co-Authored-By: Claude Opus 4.7 --- frontend/textbooks/physics_8_ch2.html | 449 +++++++++++++++++++++++++- 1 file changed, 443 insertions(+), 6 deletions(-) diff --git a/frontend/textbooks/physics_8_ch2.html b/frontend/textbooks/physics_8_ch2.html index 4137bf2..36f6eb7 100644 --- a/frontend/textbooks/physics_8_ch2.html +++ b/frontend/textbooks/physics_8_ch2.html @@ -327,8 +327,22 @@ const SIDEBARS = { ["Ближний конец","заряд противоположного знака"], ["Если разделить","на 2 заряженные части"] ]}, - p15:{title:"Шпаргалка § 15",rows:[["В разработке","Phase 2 Wave 2"]]}, - p16:{title:"Шпаргалка § 16",rows:[["В разработке","Phase 2 Wave 2"]]}, + p15:{title:"Шпаргалка § 15",rows:[ + ["Элементарный заряд","$e = 1{,}6 \\cdot 10^{-19}$ Кл"], + ["Формула","$q = N e$ ($N$ — число избыт. электронов)"], + ["Знак $-q$","избыток электронов"], + ["Знак $+q$","нехватка электронов"], + ["1 Кл","заряд $6{,}25 \\cdot 10^{18}$ электронов"], + ["Сохранение","$\\sum q = $ const"] + ]}, + p16:{title:"Шпаргалка § 16",rows:[ + ["Атом","ядро (+) + электроны (−)"], + ["Ядро","протоны + нейтроны"], + ["Нейтр. атом","$N_{электр} = Z$ (атомный номер)"], + ["Катион (+)","потерял электрон(ы)"], + ["Анион (−)","принял электрон(ы)"], + ["Электронные оболочки","K, L, M, …"] + ]}, p17:{title:"Шпаргалка § 17",rows:[["В разработке","Phase 2 Wave 3"]]}, p18:{title:"Шпаргалка § 18",rows:[["В разработке","Phase 2 Wave 3"]]}, p19:{title:"Шпаргалка § 19",rows:[["В разработке","Phase 3 Wave 1"]]}, @@ -351,8 +365,8 @@ const TIPS=[ {sec:'p12',html:"Потри расчёску о волосы — она начнёт притягивать клочки бумаги. Это электризация. При трении один предмет получает положительный заряд, другой — отрицательный. Одноимённые отталкиваются, разноимённые — притягиваются."}, {sec:'p13',html:"Металлы — отличные проводники: их электроны легко двигаются. Эбонит, стекло, пластик — диэлектрики: электроны связаны атомами. Поэтому ручка отвёртки из пластика — а сама отвёртка металлическая."}, {sec:'p14',html:"Поднеси заряженный шар к незаряженному металлическому шарику — он притянется. В нейтральном проводнике под действием внешнего заряда электроны перераспределяются, и ближний конец получает противоположный знак."}, - {sec:'p15',html:"Параграф § 15 будет реализован в Phase 2 Wave 2. Используем хелперы из phys.js и optics.js."}, - {sec:'p16',html:"Параграф § 16 будет реализован в Phase 2 Wave 2. Используем хелперы из phys.js и optics.js."}, + {sec:'p15',html:"Заряд не бывает «дробным» — все заряды кратны элементарному $e = 1{,}6 \\cdot 10^{-19}$ Кл. Если у тела «лишние» $N$ электронов, его заряд $q = -Ne$. 1 Кл — это очень много: примерно $6 \\cdot 10^{18}$ электронов."}, + {sec:'p16',html:"Атом — это плотное положительное ядро (протоны+нейтроны) и облако отрицательных электронов вокруг. В обычном атоме число электронов равно числу протонов — он нейтрален. Если потерять электрон → ион +, если получить → ион −."}, {sec:'p17',html:"Параграф § 17 будет реализован в Phase 2 Wave 3. Используем хелперы из phys.js и optics.js."}, {sec:'p18',html:"Параграф § 18 будет реализован в Phase 2 Wave 3. Используем хелперы из phys.js и optics.js."}, {sec:'p19',html:"Параграф § 19 будет реализован в Phase 3 Wave 1. Используем хелперы из phys.js и optics.js."}, @@ -375,8 +389,8 @@ const BUILDERS = { p12: ()=>{ build_p12(); }, p13: ()=>{ build_p13(); }, p14: ()=>{ build_p14(); }, - p15: ()=>{ const box=document.getElementById('p15-body'); box.innerHTML = buildStub('p15', 'Электрический заряд. Элементарный заряд', 'Phase 2 Wave 2') + secNavFor('p15') + readButton('p15'); renderMath(box); wireReadBtn('p15'); }, - p16: ()=>{ const box=document.getElementById('p16-body'); box.innerHTML = buildStub('p16', 'Строение атома. Ионы', 'Phase 2 Wave 2') + secNavFor('p16') + readButton('p16'); renderMath(box); wireReadBtn('p16'); }, + p15: ()=>{ build_p15(); }, + p16: ()=>{ build_p16(); }, p17: ()=>{ const box=document.getElementById('p17-body'); box.innerHTML = buildStub('p17', 'Электрическое поле. Электрическое напряжение', 'Phase 2 Wave 3') + secNavFor('p17') + readButton('p17'); renderMath(box); wireReadBtn('p17'); }, p18: ()=>{ const box=document.getElementById('p18-body'); box.innerHTML = buildStub('p18', 'Единица электрического напряжения. Расчёт работы в электрическом поле', 'Phase 2 Wave 3') + secNavFor('p18') + readButton('p18'); renderMath(box); wireReadBtn('p18'); }, p19: ()=>{ const box=document.getElementById('p19-body'); box.innerHTML = buildStub('p19', 'Электрический ток. Источники тока', 'Phase 3 Wave 1') + secNavFor('p19') + readButton('p19'); renderMath(box); wireReadBtn('p19'); }, @@ -1418,6 +1432,429 @@ function _initP14_mcq(){ render(); } +/* ====================================================================== + PHASE 2 · WAVE 2 — §15, §16 + ====================================================================== */ + +const E_CHARGE = 1.6e-19; + +/* ======== §15 — Электрический заряд. Элементарный заряд ======== */ +function build_p15(){ + const box = document.getElementById('p15-body'); + let h = ''; + + h += makeCard('theory', 'Элементарный заряд', '§ 15.1', + '

Эксперимент Милликена с масляными каплями показал: заряд тела всегда кратен наименьшей порции — элементарному заряду:

' + +'

$$e = 1{,}6 \\cdot 10^{-19} \\text{ Кл}$$

' + +'

Это заряд одного электрона (со знаком «−») и одного протона (со знаком «+»). Меньше — не бывает (это квантуется).

' + ); + h += makeCard('rule', 'Формула $q = N e$', '§ 15.2', + '

Если у тела «лишних» $N$ электронов, его заряд:

' + +'

$$q = N \\cdot e$$

' + +'' + +'

Сколько электронов в 1 Кл? $N = 1/e = 6{,}25 \\cdot 10^{18}$ — это огромное число.

' + ); + h += makeCard('example', 'Закон сохранения заряда', '§ 15.3', + '

В замкнутой системе сумма всех зарядов не меняется:

' + +'

$$\\sum q_i = \\text{const}$$

' + +'

Электризация трением — не «появление» заряда, а его перенос: было два нейтральных тела (всего 0), стало $+q$ и $-q$ (сумма всё ещё 0).

' + ); + + /* IV1 — калькулятор q ↔ N */ + h += '
' + +'
IV-1
Сколько электронов?
' + +'
Преобразуй между числом электронов $N$ и зарядом $q$ в нанокулонах.
' + +'
' + +'' + +'
' + +'
' + +'$N$ = 1 000 000 000' + +'$|q| = N e$ = 1.6×10-10 Кл = 0.16 нКл' + +'Это очень малый заряд — почти неощутим.' + +'
' + +'
'; + + /* IV2 — викторина квантования */ + h += '
' + +'
IV-2
Может ли существовать такой заряд?
' + +'
Проверь, кратен ли указанный заряд $e = 1{,}6 \\cdot 10^{-19}$ Кл.
' + +'
' + +'
' + +'
Раунд: 1 / 6Правильно: 0
' + +'
'; + + /* IV3 — DnD сохранение заряда */ + h += '
' + +'
IV-3
Сохраняется ли заряд?
' + +'
Распредели ситуации: где общий заряд изменился, а где остался прежним.
' + +'
' + +'
' + +'
Сохраняется
' + +'
Меняется (внеш. вмешат.)
' + +'
' + +'
' + +'' + +'
'; + + /* IV4 — числовые задачи */ + h += '
' + +'
IV-4
Тренажёр: 5 расчётных задач
' + +'
4+ правильных — +15 XP. $e = 1{,}6 \\cdot 10^{-19}$ Кл.
' + +'
' + +'
Задача: 1 / 5Правильно: 0
' + +'
'; + + box.innerHTML = h + secNavFor('p15') + readButton('p15'); + renderMath(box); + wireReadBtn('p15'); + + _initP15_calc(); + _initP15_quiz(); + _initP15_dnd(); + _initP15_tasks(); +} + +function _initP15_calc(){ + function update(){ + const exp = +document.getElementById('p15-n').value; + const N = Math.pow(10, exp); + document.getElementById('p15-nv').innerHTML = '10'+exp.toFixed(1)+''; + document.getElementById('p15-nval').textContent = N.toExponential(2).replace('+',''); + const q = N * E_CHARGE; + const qExp = Math.floor(Math.log10(q)); + const qMant = (q/Math.pow(10,qExp)).toFixed(2); + document.getElementById('p15-qval').innerHTML = qMant+'×10'+qExp+''; + document.getElementById('p15-qnc').textContent = (q*1e9).toExponential(2).replace('+',''); + } + document.getElementById('p15-n').addEventListener('input', update); + update(); +} + +function _initP15_quiz(){ + const QS = [ + {q:'$q = 3{,}2 \\cdot 10^{-19}$ Кл', ans:'Y', why:'$N = q/e = 2$ — кратно, существует.'}, + {q:'$q = 8 \\cdot 10^{-19}$ Кл', ans:'Y', why:'$N = 5$ — целое, существует.'}, + {q:'$q = 2{,}4 \\cdot 10^{-19}$ Кл', ans:'N', why:'$N = 1{,}5$ — не целое, не существует.'}, + {q:'$q = 1 \\cdot 10^{-19}$ Кл', ans:'N', why:'$N = 0{,}625$ — не целое.'}, + {q:'$q = 1{,}6 \\cdot 10^{-18}$ Кл', ans:'Y', why:'$N = 10$ — целое, существует.'}, + {q:'$q = 5 \\cdot 10^{-19}$ Кл', ans:'N', why:'$N = 3{,}125$ — не целое.'} + ]; + let i = 0, ok = 0; + function render(){ + const q = QS[i]; const wrap = document.getElementById('p15-quiz'); if(!wrap) return; + wrap.innerHTML = + '
'+q.q+'
' + +'
' + +'' + +'' + +'
' + +''; + document.getElementById('p15-quiz-r').textContent = (i+1); + document.getElementById('p15-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('p15-quiz-fb'); + if(btn.dataset.pick === q.ans){ ok++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(3,'p15-quiz'); bumpProgress('p15', 4); } + else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; } + document.getElementById('p15-quiz-ok').textContent = ok; + renderMath(wrap); + }); + }); + renderMath(wrap); + } + document.getElementById('p15-quiz-next').addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); }); + render(); +} + +function _initP15_dnd(){ + const items = [ + {id:'a', cat:'keep', html:'трение двух тел в изолированной системе'}, + {id:'b', cat:'keep', html:'переход электронов внутри проводника'}, + {id:'c', cat:'keep', html:'индукция в шарике'}, + {id:'d', cat:'keep', html:'два шара соприкоснулись и разъединились'}, + {id:'e', cat:'ext', html:'тело заземлили (заряд ушёл в землю)'}, + {id:'f', cat:'ext', html:'тело потёрли о внешний предмет, а потом убрали'}, + {id:'g', cat:'ext', html:'к телу поднесли «насос электронов»'}, + {id:'h', cat:'ext', html:'тело облучили рентгеном (выбил электроны)'} + ]; + const dnd = setupSorter({ poolId:'p15-dnd-pool', scopeSelector:'#sec-p15', cats:['keep','ext'], items, columnLayout:false }); + document.getElementById('p15-dnd-check').addEventListener('click', ()=>{ + const fb = document.getElementById('p15-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,'p15-dnd'); bumpProgress('p15', 20); } + else { fb.className='feedback fail'; fb.innerHTML='✗ Ошибок: '+wrong+'. Заземление и внешнее излучение — это внешнее вмешательство.'; } + }); + document.getElementById('p15-dnd-reset').addEventListener('click', ()=>{ dnd.reset(); const fb=document.getElementById('p15-dnd-fb'); fb.style.display='none'; }); +} + +function _initP15_tasks(){ + const TASKS = [ + {q:'Сколько электронов нужно собрать, чтобы получить заряд $q = -1$ нКл? ($e = 1{,}6 \\cdot 10^{-19}$ Кл) — Ответ в формате $N \\cdot 10^9$, введи $N$ с одним знаком после запятой.', ans:6.25, tol:0.1, why:'$N = q/e = 10^{-9}/(1{,}6\\cdot10^{-19}) = 6{,}25 \\cdot 10^9$. Ответ: $6{,}25$.'}, + {q:'У тела «лишних» $5 \\cdot 10^{10}$ электронов. Каков его заряд (в нКл, по модулю)?', ans:8, tol:0.2, why:'$q = Ne = 5\\cdot10^{10} \\cdot 1{,}6\\cdot10^{-19} = 8\\cdot10^{-9}$ Кл = $8$ нКл.'}, + {q:'У одного тела $q_1 = +3$ нКл, у другого $q_2 = -5$ нКл. После их соприкосновения и разделения сумма $q_1 + q_2$ равна (в нКл)?', ans:-2, tol:0.05, why:'Заряд сохраняется: $3 + (-5) = -2$ нКл (так и осталось после контакта).'}, + {q:'Какой заряд (в Кл, по модулю) получится при $N = 2 \\cdot 10^{19}$? Ответ в формате $a \\cdot 10^0$, введи $a$ (одно число).', ans:3.2, tol:0.05, why:'$q = 2\\cdot10^{19} \\cdot 1{,}6\\cdot10^{-19} = 3{,}2$ Кл — это очень много!'}, + {q:'Заряд $q = 4{,}8 \\cdot 10^{-19}$ Кл существует? Если да — сколько в нём электронов? Введи $N$.', ans:3, tol:0.1, why:'$N = q/e = 4{,}8/1{,}6 = 3$. Заряд существует, в нём 3 элементарных.'} + ]; + let i = 0, ok = 0, done = 0, awarded = false; + function render(){ + const t = TASKS[i]; const wrap = document.getElementById('p15-task'); if(!wrap) return; + wrap.innerHTML = + '
Задача '+(i+1)+'. '+t.q+'
' + +'
' + +'' + +'' + +'
' + +'
'+t.why+'
' + +''; + document.getElementById('p15-task-i').textContent = (i+1); + document.getElementById('p15-task-ok').textContent = ok; + document.getElementById('p15-task-go').addEventListener('click', ()=>{ + const v = parseFloat((document.getElementById('p15-task-inp').value || '').replace(',','.')); + const fb = document.getElementById('p15-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,'p15-task'); bumpProgress('p15', 6); } + else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. Правильный ответ: '+t.ans+'. '+t.why; } + document.getElementById('p15-task-ok').textContent = ok; + renderMath(wrap); + if(done >= TASKS.length && !awarded && ok >= 4){ awarded = true; setTimeout(()=>{ const wf=document.getElementById('p15-task-fb'); wf.className='feedback ok'; wf.innerHTML='✓ +15 XP — расчёты сданы ('+ok+'/'+TASKS.length+').'; addXp(15,'p15-task-bonus'); bumpProgress('p15', 15); }, 600); } + }); + document.getElementById('p15-task-hint').addEventListener('click', ()=>{ document.getElementById('p15-task-hint-txt').classList.toggle('show'); }); + document.getElementById('p15-task-next').addEventListener('click', ()=>{ i=(i+1)%TASKS.length; render(); }); + renderMath(wrap); + } + render(); +} + +/* ======== §16 — Строение атома. Ионы ======== */ +function build_p16(){ + const box = document.getElementById('p16-body'); + let h = ''; + + h += makeCard('theory', 'Планетарная модель атома', '§ 16.1', + '

Атом устроен как маленькая «солнечная система»:

' + +'' + +'

В нейтральном атоме число электронов = число протонов = атомный номер $Z$.

' + ); + h += makeCard('rule', 'Ионы', '§ 16.2', + '

Если атом потерял 1 или больше электронов — он становится положительным ионом (катионом): $\\text{Na} \\to \\text{Na}^+$.

' + +'

Если атом принял лишний электрон — он становится отрицательным ионом (анионом): $\\text{Cl} \\to \\text{Cl}^-$.

' + +'

Соли в растворах диссоциируют на ионы — поэтому растворы солей проводят ток.

' + ); + h += makeCard('example', 'Атомы и ионы', '§ 16.3', + '' + +'' + +'' + +'' + +'' + +'
Элемент$Z$Электр.Заряд иона
водород H11H+
натрий Na1111Na+
хлор Cl1717Cl
кальций Ca2020Ca2+
кислород O88O2−
' + ); + + /* IV1 — конструктор атома */ + h += '
' + +'
IV-1
Конструктор атома / иона
' + +'
Меняй число протонов и электронов — увидь, нейтрален ли атом и какой ион получится.
' + +'
' + +'' + +'' + +'
' + +'' + +'
' + +'Заряд: 0 (нейтрален)' + +'Состояние: нейтральный атом' + +'
' + +'
'; + + /* IV2 — викторина по таблице */ + h += '
' + +'
IV-2
Какой заряд у иона?
' + +'
Дан элемент и преобразование — назови заряд получившегося иона.
' + +'
' + +'
' + +'
Раунд: 1 / 6Правильно: 0
' + +'
'; + + /* IV3 — DnD сортировка частиц */ + h += '
' + +'
IV-3
Сортировка частиц
' + +'
Распредели частицы по знаку заряда.
' + +'
' + +'
' + +'
Положительные
' + +'
Отрицательные
' + +'
Нейтральные
' + +'
' + +'
' + +'' + +'
'; + + /* IV4 — MCQ */ + h += '
' + +'
IV-4
Тренажёр: 6 вопросов
' + +'
4+ правильных — +15 XP.
' + +'
' + +'
Вопрос: 1 / 6Правильно: 0
' + +'
'; + + box.innerHTML = h + secNavFor('p16') + readButton('p16'); + renderMath(box); + wireReadBtn('p16'); + + _initP16_atom(); + _initP16_quiz(); + _initP16_dnd(); + _initP16_mcq(); +} + +function _initP16_atom(){ + const svg = document.getElementById('p16-sim'); if(!svg) return; + function draw(){ + const Z = +document.getElementById('p16-z').value; + const N = +document.getElementById('p16-e').value; + document.getElementById('p16-zv').textContent = Z; + document.getElementById('p16-ev').textContent = N; + const delta = Z - N; + document.getElementById('p16-qbal').textContent = (delta > 0 ? '+'+delta : (delta < 0 ? delta : '0'))+' e'; + let state = ''; + if(delta === 0) state = 'нейтральный атом'; + else if(delta > 0) state = 'катион (+'+delta+')'; + else state = 'анион ('+delta+')'; + document.getElementById('p16-state').textContent = state; + /* draw */ + const cx = 230, cy = 120; + let s = ''; + /* электронные оболочки */ + const shellRs = [50, 80, 110]; + for(const r of shellRs) s += ''; + /* ядро */ + s += ''; + s += ''+Z+'p'; + /* электроны на оболочках: 2 на K (50), 8 на L (80), остальное на M (110) */ + let placed = 0; + const shellMax = [2, 8, 18]; + for(let sh = 0; sh < 3 && placed < N; sh++){ + const r = shellRs[sh]; + const count = Math.min(shellMax[sh], N - placed); + for(let i = 0; i < count; i++){ + const ang = 2 * Math.PI * i / count + sh * 0.3; + const ex = cx + r*Math.cos(ang); + const ey = cy + r*Math.sin(ang); + s += ''; + s += ''; + } + placed += count; + } + /* пометка заряда */ + if(delta !== 0){ + const sign = delta > 0 ? '+' : ''; + const col = delta > 0 ? '#dc2626' : '#2563eb'; + s += ''+sign+delta+''; + } + svg.innerHTML = s; + } + document.getElementById('p16-z').addEventListener('input', draw); + document.getElementById('p16-e').addEventListener('input', draw); + draw(); +} + +function _initP16_quiz(){ + const QS = [ + {q:'Na отдал 1 электрон. Какой ион?', opts:['Na+','Na','Na2+','Na'], ans:0, why:'Потерял 1 электрон → катион +1.'}, + {q:'Cl принял 1 электрон. Какой ион?', opts:['Cl+','Cl','Cl2−','Cl'], ans:1, why:'Принял 1 → анион −1.'}, + {q:'Ca отдал 2 электрона. Заряд иона?', opts:['+1','+2','−1','0'], ans:1, why:'2 потерянных электрона → +2.'}, + {q:'O принял 2 электрона. Заряд иона?', opts:['+2','−2','−1','0'], ans:1, why:'2 принятых электрона → −2.'}, + {q:'Сколько электронов у Na+? ($Z_{Na}$=11)', opts:['10','11','12','9'], ans:0, why:'Был 11, отдал 1, остался 10.'}, + {q:'Сколько электронов у Cl? ($Z_{Cl}$=17)', opts:['18','17','16','19'], ans:0, why:'Принял 1, стало 18.'} + ]; + let i = 0, ok = 0; + function render(){ + const q = QS[i]; const wrap = document.getElementById('p16-quiz'); if(!wrap) return; + let h = '
Вопрос '+(i+1)+'. '+q.q+'
'; + q.opts.forEach((opt,k)=>{ h += ''; }); + h += '
'; + wrap.innerHTML = h; + document.getElementById('p16-quiz-r').textContent = (i+1); + document.getElementById('p16-quiz-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('p16-quiz-fb'); + if(k===q.ans){ ok++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(3,'p16-quiz'); bumpProgress('p16', 4); } + else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; } + document.getElementById('p16-quiz-ok').textContent = ok; + }); + }); + } + document.getElementById('p16-quiz-next').addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); }); + render(); +} + +function _initP16_dnd(){ + const items = [ + {id:'p', cat:'pos', html:'протон'}, + {id:'na', cat:'pos', html:'ион Na+'}, + {id:'ca', cat:'pos', html:'ион Ca2+'}, + {id:'e', cat:'neg', html:'электрон'}, + {id:'cl', cat:'neg', html:'ион Cl'}, + {id:'o', cat:'neg', html:'ион O2−'}, + {id:'n', cat:'neu', html:'нейтрон'}, + {id:'aH', cat:'neu', html:'атом водорода H'}, + {id:'aHe',cat:'neu', html:'атом гелия He'} + ]; + const dnd = setupSorter({ poolId:'p16-dnd-pool', scopeSelector:'#sec-p16', cats:['pos','neg','neu'], items, columnLayout:false }); + document.getElementById('p16-dnd-check').addEventListener('click', ()=>{ + const fb = document.getElementById('p16-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,'p16-dnd'); bumpProgress('p16', 20); } + else { fb.className='feedback fail'; fb.innerHTML='✗ Ошибок: '+wrong+'. Подсказка: нейтрон и сами атомы — нейтральные, ионы — заряжены.'; } + }); + document.getElementById('p16-dnd-reset').addEventListener('click', ()=>{ dnd.reset(); const fb=document.getElementById('p16-dnd-fb'); fb.style.display='none'; }); +} + +function _initP16_mcq(){ + const QS = [ + {q:'Что находится в ядре атома?', opts:['электроны','протоны и нейтроны','только протоны','только нейтроны'], ans:1, why:'Ядро = протоны + нейтроны.'}, + {q:'Какой заряд у протона?', opts:['$-e$','$+e$','0','$+2e$'], ans:1, why:'Протон несёт элементарный + заряд.'}, + {q:'Какой заряд у нейтрона?', opts:['$-e$','$+e$','0','$+2e$'], ans:2, why:'Нейтрон нейтрален.'}, + {q:'В нейтральном атоме число электронов равно…', opts:['числу нейтронов','числу протонов','массовому числу','$Z+N$'], ans:1, why:'$Z$ электронов компенсируют $Z$ протонов.'}, + {q:'Какой ион получится, если атом отдаст 2 электрона?', opts:['−2','−1','+1','+2'], ans:3, why:'2 потерянных электрона → заряд +2.'}, + {q:'Что больше: атом или ядро?', opts:['ядро','атом','одинаково','зависит от элемента'], ans:1, why:'Атом примерно в 100 000 раз больше ядра.'} + ]; + let i = 0, ok = 0, done = 0, awarded = false; + function render(){ + const q = QS[i]; const wrap = document.getElementById('p16-mcq'); if(!wrap) return; + let h = '
Вопрос '+(i+1)+'. '+q.q+'
'; + q.opts.forEach((opt,k)=>{ h += ''; }); + h += '
'; + wrap.innerHTML = h; + document.getElementById('p16-mcq-i').textContent = (i+1); + document.getElementById('p16-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('p16-mcq-fb'); + if(k===q.ans){ ok++; done++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(2,'p16-mcq'); bumpProgress('p16', 3); } + else { done++; fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; } + document.getElementById('p16-mcq-ok').textContent = ok; + renderMath(wrap); + if(done >= QS.length && !awarded && ok >= 4){ awarded = true; setTimeout(()=>{ const wf=document.getElementById('p16-mcq-fb'); wf.className='feedback ok'; wf.innerHTML='✓ +15 XP — тренажёр пройден ('+ok+'/'+QS.length+').'; addXp(15,'p16-mcq-bonus'); bumpProgress('p16', 15); }, 600); } + }); + }); + const nb = document.getElementById('p16-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);