feat(phys8 ch2): Phase 2 Wave 2 — §15 элементарный заряд + §16 строение атома
§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 <noreply@anthropic.com>
This commit is contained in:
@@ -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:"Потри расчёску о волосы — она начнёт притягивать клочки бумаги. Это <b>электризация</b>. При трении один предмет получает <b>положительный</b> заряд, другой — <b>отрицательный</b>. Одноимённые отталкиваются, разноимённые — притягиваются."},
|
||||
{sec:'p13',html:"Металлы — отличные проводники: их электроны легко двигаются. Эбонит, стекло, пластик — диэлектрики: электроны связаны атомами. Поэтому ручка отвёртки из пластика — а сама отвёртка металлическая."},
|
||||
{sec:'p14',html:"Поднеси заряженный шар к незаряженному металлическому шарику — он притянется. В нейтральном проводнике под действием внешнего заряда электроны перераспределяются, и ближний конец получает противоположный знак."},
|
||||
{sec:'p15',html:"Параграф § 15 будет реализован в Phase 2 Wave 2. Используем хелперы из <code>phys.js</code> и <code>optics.js</code>."},
|
||||
{sec:'p16',html:"Параграф § 16 будет реализован в Phase 2 Wave 2. Используем хелперы из <code>phys.js</code> и <code>optics.js</code>."},
|
||||
{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. Используем хелперы из <code>phys.js</code> и <code>optics.js</code>."},
|
||||
{sec:'p18',html:"Параграф § 18 будет реализован в Phase 2 Wave 3. Используем хелперы из <code>phys.js</code> и <code>optics.js</code>."},
|
||||
{sec:'p19',html:"Параграф § 19 будет реализован в Phase 3 Wave 1. Используем хелперы из <code>phys.js</code> и <code>optics.js</code>."},
|
||||
@@ -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',
|
||||
'<p>Эксперимент Милликена с масляными каплями показал: <b>заряд тела всегда кратен</b> наименьшей порции — <b>элементарному заряду</b>:</p>'
|
||||
+'<p style="text-align:center;margin:8px 0">$$e = 1{,}6 \\cdot 10^{-19} \\text{ Кл}$$</p>'
|
||||
+'<p>Это заряд одного электрона (со знаком «−») и одного протона (со знаком «+»). Меньше — не бывает (это <b>квантуется</b>).</p>'
|
||||
);
|
||||
h += makeCard('rule', 'Формула $q = N e$', '§ 15.2',
|
||||
'<p>Если у тела «лишних» $N$ электронов, его заряд:</p>'
|
||||
+'<p style="text-align:center;margin:8px 0">$$q = N \\cdot e$$</p>'
|
||||
+'<ul style="padding-left:20px;margin:6px 0">'
|
||||
+'<li>$q < 0$ — избыток электронов;</li>'
|
||||
+'<li>$q > 0$ — нехватка электронов;</li>'
|
||||
+'<li>$q = 0$ — нейтральное тело (число +зарядов = число −зарядов).</li>'
|
||||
+'</ul>'
|
||||
+'<p>Сколько электронов в 1 Кл? $N = 1/e = 6{,}25 \\cdot 10^{18}$ — это огромное число.</p>'
|
||||
);
|
||||
h += makeCard('example', 'Закон сохранения заряда', '§ 15.3',
|
||||
'<p>В замкнутой системе сумма всех зарядов <b>не меняется</b>:</p>'
|
||||
+'<p style="text-align:center;margin:8px 0">$$\\sum q_i = \\text{const}$$</p>'
|
||||
+'<p>Электризация трением — не «появление» заряда, а его <b>перенос</b>: было два нейтральных тела (всего 0), стало $+q$ и $-q$ (сумма всё ещё 0).</p>'
|
||||
);
|
||||
|
||||
/* IV1 — калькулятор q ↔ N */
|
||||
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">Преобразуй между числом электронов $N$ и зарядом $q$ в нанокулонах.</div>'
|
||||
+'<div class="sliders" style="margin-bottom:10px">'
|
||||
+'<label>Число электронов $N$: <b id="p15-nv">10<sup>9</sup></b><input type="range" id="p15-n" min="6" max="18" step="0.5" value="9"></label>'
|
||||
+'</div>'
|
||||
+'<div class="score-display" style="margin-top:8px;flex-direction:column;align-items:flex-start;gap:4px">'
|
||||
+'<span>$N$ = <b id="p15-nval">1 000 000 000</b></span>'
|
||||
+'<span>$|q| = N e$ = <b id="p15-qval">1.6×10<sup>-10</sup></b> Кл = <b id="p15-qnc">0.16</b> нКл</span>'
|
||||
+'<span style="font-size:.84rem;color:var(--muted)">Это очень малый заряд — почти неощутим.</span>'
|
||||
+'</div>'
|
||||
+'</div>';
|
||||
|
||||
/* IV2 — викторина квантования */
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-2</span><div class="wg-title">Может ли существовать такой заряд?</div></div>'
|
||||
+'<div class="wg-help">Проверь, кратен ли указанный заряд $e = 1{,}6 \\cdot 10^{-19}$ Кл.</div>'
|
||||
+'<div id="p15-quiz"></div>'
|
||||
+'<div class="actions"><button class="btn" id="p15-quiz-next">Следующий</button></div>'
|
||||
+'<div class="score-display" style="margin-top:10px"><span>Раунд: <b id="p15-quiz-r">1</b> / 6</span><span>Правильно: <b id="p15-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="p15-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="keep"></div></div>'
|
||||
+'<div class="drop-box"><h5>Меняется (внеш. вмешат.)</h5><div class="drop-items" data-cat="ext"></div></div>'
|
||||
+'</div>'
|
||||
+'<div class="actions"><button class="btn primary" id="p15-dnd-check">Проверить</button><button class="btn" id="p15-dnd-reset">Сброс</button></div>'
|
||||
+'<div class="feedback" id="p15-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. $e = 1{,}6 \\cdot 10^{-19}$ Кл.</div>'
|
||||
+'<div id="p15-task"></div>'
|
||||
+'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="p15-task-i">1</b> / 5</span><span>Правильно: <b id="p15-task-ok">0</b></span></div>'
|
||||
+'</div>';
|
||||
|
||||
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<sup>'+exp.toFixed(1)+'</sup>';
|
||||
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<sup>'+qExp+'</sup>';
|
||||
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 =
|
||||
'<div style="padding:10px 14px;background:rgba(15,23,42,.04);border-radius:9px;margin:8px 0;line-height:1.5;font-size:1.05rem">'+q.q+'</div>'
|
||||
+'<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px">'
|
||||
+'<button class="btn" data-pick="Y" style="padding:14px"><b>Существует</b></button>'
|
||||
+'<button class="btn" data-pick="N" style="padding:14px"><b>Не существует</b></button>'
|
||||
+'</div>'
|
||||
+'<div class="feedback" id="p15-quiz-fb"></div>';
|
||||
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 =
|
||||
'<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="p15-task-inp" placeholder="число" style="width:140px">'
|
||||
+'<button class="btn primary" id="p15-task-go">Ответ</button>'
|
||||
+'<button class="btn" id="p15-task-hint">Подсказка</button>'
|
||||
+'<button class="btn" id="p15-task-next">Следующая</button></div>'
|
||||
+'<div class="boss-hint-txt" id="p15-task-hint-txt">'+t.why+'</div>'
|
||||
+'<div class="feedback" id="p15-task-fb"></div>';
|
||||
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',
|
||||
'<p>Атом устроен как маленькая «солнечная система»:</p>'
|
||||
+'<ul style="padding-left:20px;margin:6px 0">'
|
||||
+'<li><b>Ядро</b> в центре — очень маленькое (10<sup>-15</sup> м), но в нём почти вся масса. Состоит из <b>протонов</b> ($+e$) и <b>нейтронов</b> (нейтральные).</li>'
|
||||
+'<li><b>Электроны</b> ($-e$) движутся вокруг ядра по оболочкам.</li>'
|
||||
+'<li>Атом в целом размером $\\sim 10^{-10}$ м — ядро в 100 000 раз меньше всего атома.</li>'
|
||||
+'</ul>'
|
||||
+'<p>В <b>нейтральном</b> атоме число электронов = число протонов = <b>атомный номер</b> $Z$.</p>'
|
||||
);
|
||||
h += makeCard('rule', 'Ионы', '§ 16.2',
|
||||
'<p>Если атом <b>потерял</b> 1 или больше электронов — он становится <b>положительным ионом (катионом)</b>: $\\text{Na} \\to \\text{Na}^+$.</p>'
|
||||
+'<p>Если атом <b>принял</b> лишний электрон — он становится <b>отрицательным ионом (анионом)</b>: $\\text{Cl} \\to \\text{Cl}^-$.</p>'
|
||||
+'<p>Соли в растворах диссоциируют на ионы — поэтому растворы солей проводят ток.</p>'
|
||||
);
|
||||
h += makeCard('example', 'Атомы и ионы', '§ 16.3',
|
||||
'<table style="width:100%;border-collapse:collapse;font-size:.92rem"><thead><tr style="background:rgba(15,23,42,.04)"><th style="padding:6px">Элемент</th><th style="padding:6px;text-align:center">$Z$</th><th style="padding:6px;text-align:center">Электр.</th><th style="padding:6px;text-align:center">Заряд иона</th></tr></thead>'
|
||||
+'<tbody><tr><td style="padding:6px;border-bottom:1px dashed var(--border)">водород H</td><td style="padding:6px;border-bottom:1px dashed var(--border);text-align:center">1</td><td style="padding:6px;border-bottom:1px dashed var(--border);text-align:center">1</td><td style="padding:6px;border-bottom:1px dashed var(--border);text-align:center">H<sup>+</sup></td></tr>'
|
||||
+'<tr><td style="padding:6px;border-bottom:1px dashed var(--border)">натрий Na</td><td style="padding:6px;border-bottom:1px dashed var(--border);text-align:center">11</td><td style="padding:6px;border-bottom:1px dashed var(--border);text-align:center">11</td><td style="padding:6px;border-bottom:1px dashed var(--border);text-align:center">Na<sup>+</sup></td></tr>'
|
||||
+'<tr><td style="padding:6px;border-bottom:1px dashed var(--border)">хлор Cl</td><td style="padding:6px;border-bottom:1px dashed var(--border);text-align:center">17</td><td style="padding:6px;border-bottom:1px dashed var(--border);text-align:center">17</td><td style="padding:6px;border-bottom:1px dashed var(--border);text-align:center">Cl<sup>−</sup></td></tr>'
|
||||
+'<tr><td style="padding:6px;border-bottom:1px dashed var(--border)">кальций Ca</td><td style="padding:6px;border-bottom:1px dashed var(--border);text-align:center">20</td><td style="padding:6px;border-bottom:1px dashed var(--border);text-align:center">20</td><td style="padding:6px;border-bottom:1px dashed var(--border);text-align:center">Ca<sup>2+</sup></td></tr>'
|
||||
+'<tr><td style="padding:6px">кислород O</td><td style="padding:6px;text-align:center">8</td><td style="padding:6px;text-align:center">8</td><td style="padding:6px;text-align:center">O<sup>2−</sup></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">Меняй число протонов и электронов — увидь, нейтрален ли атом и какой ион получится.</div>'
|
||||
+'<div class="sliders" style="margin-bottom:10px">'
|
||||
+'<label>Протонов ($Z$): <b id="p16-zv">11</b><input type="range" id="p16-z" min="1" max="20" step="1" value="11"></label>'
|
||||
+'<label>Электронов: <b id="p16-ev">11</b><input type="range" id="p16-e" min="0" max="20" step="1" value="11"></label>'
|
||||
+'</div>'
|
||||
+'<svg id="p16-sim" viewBox="0 0 460 240" style="width:100%;height:auto;background:#f8fafc;border-radius:9px;border:1px solid var(--border)"></svg>'
|
||||
+'<div class="score-display" style="margin-top:10px;flex-direction:column;align-items:flex-start;gap:4px">'
|
||||
+'<span>Заряд: <b id="p16-qbal">0</b> (нейтрален)</span>'
|
||||
+'<span>Состояние: <b id="p16-state">нейтральный атом</b></span>'
|
||||
+'</div>'
|
||||
+'</div>';
|
||||
|
||||
/* IV2 — викторина по таблице */
|
||||
h += '<div class="wg">'
|
||||
+'<div class="wg-header"><span class="wg-badge">IV-2</span><div class="wg-title">Какой заряд у иона?</div></div>'
|
||||
+'<div class="wg-help">Дан элемент и преобразование — назови заряд получившегося иона.</div>'
|
||||
+'<div id="p16-quiz"></div>'
|
||||
+'<div class="actions"><button class="btn" id="p16-quiz-next">Следующий</button></div>'
|
||||
+'<div class="score-display" style="margin-top:10px"><span>Раунд: <b id="p16-quiz-r">1</b> / 6</span><span>Правильно: <b id="p16-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="p16-dnd-pool"></div>'
|
||||
+'<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px;margin-top:10px">'
|
||||
+'<div class="drop-box"><h5>Положительные</h5><div class="drop-items" data-cat="pos"></div></div>'
|
||||
+'<div class="drop-box"><h5>Отрицательные</h5><div class="drop-items" data-cat="neg"></div></div>'
|
||||
+'<div class="drop-box"><h5>Нейтральные</h5><div class="drop-items" data-cat="neu"></div></div>'
|
||||
+'</div>'
|
||||
+'<div class="actions"><button class="btn primary" id="p16-dnd-check">Проверить</button><button class="btn" id="p16-dnd-reset">Сброс</button></div>'
|
||||
+'<div class="feedback" id="p16-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="p16-mcq"></div>'
|
||||
+'<div class="score-display" style="margin-top:10px"><span>Вопрос: <b id="p16-mcq-i">1</b> / 6</span><span>Правильно: <b id="p16-mcq-ok">0</b></span></div>'
|
||||
+'</div>';
|
||||
|
||||
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 += '<circle cx="'+cx+'" cy="'+cy+'" r="'+r+'" fill="none" stroke="#cbd5e1" stroke-width="1" stroke-dasharray="3 3"/>';
|
||||
/* ядро */
|
||||
s += '<circle cx="'+cx+'" cy="'+cy+'" r="22" fill="#fef3c7" stroke="#dc2626" stroke-width="2"/>';
|
||||
s += '<text x="'+cx+'" y="'+(cy+5)+'" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="13" font-weight="800" fill="#dc2626">'+Z+'p</text>';
|
||||
/* электроны на оболочках: 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 += '<circle cx="'+ex.toFixed(1)+'" cy="'+ey.toFixed(1)+'" r="5" fill="#2563eb" stroke="#0f172a" stroke-width="0.8"/>';
|
||||
s += '<text x="'+ex.toFixed(1)+'" y="'+(ey+3).toFixed(1)+'" text-anchor="middle" font-family="Inter,sans-serif" font-size="9" font-weight="800" fill="#fff">−</text>';
|
||||
}
|
||||
placed += count;
|
||||
}
|
||||
/* пометка заряда */
|
||||
if(delta !== 0){
|
||||
const sign = delta > 0 ? '+' : '';
|
||||
const col = delta > 0 ? '#dc2626' : '#2563eb';
|
||||
s += '<text x="'+(cx+130)+'" y="'+(cy-90)+'" text-anchor="middle" font-family="Unbounded,sans-serif" font-size="20" font-weight="900" fill="'+col+'">'+sign+delta+'</text>';
|
||||
}
|
||||
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<sup>+</sup>','Na<sup>−</sup>','Na<sup>2+</sup>','Na'], ans:0, why:'Потерял 1 электрон → катион +1.'},
|
||||
{q:'Cl принял 1 электрон. Какой ион?', opts:['Cl<sup>+</sup>','Cl<sup>−</sup>','Cl<sup>2−</sup>','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<sup>+</sup>? ($Z_{Na}$=11)', opts:['10','11','12','9'], ans:0, why:'Был 11, отдал 1, остался 10.'},
|
||||
{q:'Сколько электронов у Cl<sup>−</sup>? ($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 = '<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 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="p16-quiz-fb"></div>';
|
||||
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<sup>+</sup>'},
|
||||
{id:'ca', cat:'pos', html:'ион Ca<sup>2+</sup>'},
|
||||
{id:'e', cat:'neg', html:'электрон'},
|
||||
{id:'cl', cat:'neg', html:'ион Cl<sup>−</sup>'},
|
||||
{id:'o', cat:'neg', html:'ион O<sup>2−</sup>'},
|
||||
{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 = '<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="p16-mcq-fb"></div><div class="actions"><button class="btn" id="p16-mcq-next">Следующий</button></div>';
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user