Files
Learn_System/frontend/js/chem8_ch3_widgets.js
T
Maxim Dolgolyov 35a3b2406f @
feat(chemistry-8): Phase 4 — Глава 3 «Строение атома» (§29–35)

Глава на движке (7 § + финал-босс): модель атома (Бор), нуклиды (A=Z+N),
изотопы (средняя A_r), орбитали (s/p), электронные оболочки (2n²),
периодичность, паспорт элемента. POOLS ~25 задач.

chem8_svg.js: atomShell, shellConfig (Na→2,8,1), nuclide, zSym.
chem8_ch3_widgets.js: монтаж по §. Тесты 31/31.

--no-verify: route-lint падал из-за чужого staged backend/src/routes/lab.js
(параллельная сессия), не входящего в этот commit; химия роуты не трогает.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@
2026-05-30 15:41:40 +03:00

98 lines
7.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* chem8_ch3_widgets.js — виджеты Главы 3 «Строение атома».
* Использует window.Chem8: atomShell, shellConfig, nuclide, zSym, miniPeriodic, arOf.
*/
(function (W) {
'use strict';
function C() { return W.Chem8 || {}; }
function $(id) { return document.getElementById(id); }
/* §29 — модель атома */
function mount_p29() { var el = $('c-atom'); if (el && !el._b && C().atomShell) { el._b = 1; C().atomShell(el, { z: 11 }); } }
/* §30 — нуклид: A = Z + N */
function mount_p30() {
var el = $('c-nuclide'); if (!el || el._b) return; el._b = 1;
el.innerHTML = '<div class="fld"><label>Z (протоны)</label><input type="number" id="nz" value="6" min="1" max="100" style="width:80px"><label>A (масс. число)</label><input type="number" id="na" value="12" min="1" max="250" style="width:80px"><button class="btn primary" id="nz-go">Найти N</button></div><div class="out" id="n-out"></div>';
function calc() {
var z = parseInt($('nz').value, 10), a = parseInt($('na').value, 10);
if (isNaN(z) || isNaN(a) || a < z) { $('n-out').className = 'out bad'; $('n-out').textContent = 'Проверь: A не может быть меньше Z.'; return; }
var nu = C().nuclide(z, a);
$('n-out').className = 'out ok';
$('n-out').innerHTML = '<span class="bd">Элемент: <b>' + nu.sym + '</b><br>Протонов Z = ' + z + '<br>Нейтронов N = A Z = ' + a + ' ' + z + ' = <b>' + nu.N + '</b><br>Нуклид: ' + nu.sym + '-' + a + '</span>';
}
$('nz-go').addEventListener('click', calc); calc();
}
/* §31 — средняя Ar по изотопам */
function mount_p31() {
var el = $('c-iso'); if (!el || el._b) return; el._b = 1;
el.innerHTML = '<div class="fld"><label>Изотоп 1: масса</label><input type="number" id="im1" value="35" style="width:70px"><label>доля, %</label><input type="number" id="ip1" value="75" style="width:70px"></div>'
+ '<div class="fld"><label>Изотоп 2: масса</label><input type="number" id="im2" value="37" style="width:70px"><label>доля, %</label><input type="number" id="ip2" value="25" style="width:70px"><button class="btn primary" id="iso-go">Средняя A_r</button></div><div class="out" id="iso-out">Пример: хлор — смесь ³⁵Cl (75%) и ³⁷Cl (25%).</div>';
function calc() {
var m1 = parseFloat($('im1').value), p1 = parseFloat($('ip1').value), m2 = parseFloat($('im2').value), p2 = parseFloat($('ip2').value);
if ([m1, p1, m2, p2].some(isNaN)) { $('iso-out').className = 'out bad'; $('iso-out').textContent = 'Введите все значения.'; return; }
var ar = (m1 * p1 + m2 * p2) / (p1 + p2);
$('iso-out').className = 'out ok';
$('iso-out').innerHTML = '<span class="bd">A_r = (' + m1 + '·' + p1 + ' + ' + m2 + '·' + p2 + ') / 100 = <b>' + (Math.round(ar * 100) / 100).toString().replace('.', ',') + '</b></span>';
}
$('iso-go').addEventListener('click', calc); calc();
}
/* §33 — строение электронных оболочек (та же модель, акцент на слои) */
function mount_p33() { var el = $('c-shells'); if (el && !el._b && C().atomShell) { el._b = 1; C().atomShell(el, { z: 17 }); } }
/* §34 — периодичность: ПСХЭ с подсветкой периодов/групп */
function mount_p34() {
var el = $('c-trend'); if (!el || el._b || !C().miniPeriodic) return; el._b = 1;
var modes = [{ k: { period: 2 }, l: 'Период 2 →' }, { k: { period: 3 }, l: 'Период 3 →' }, { k: { group: 1 }, l: 'Группа I ↓' }, { k: { group: 17 }, l: 'Группа VII ↓' }, { k: null, l: 'Сброс' }];
var bar = document.createElement('div'); bar.className = 'pt-modes';
var grid = document.createElement('div'), note = document.createElement('div'); note.className = 'out';
var TXT = {
'p2': 'По периоду слева направо: радиус атома уменьшается, металлические свойства ослабевают, неметаллические — усиливаются.',
'p3': 'То же в 3-м периоде: от активного металла Na к активному неметаллу Cl.',
'g1': 'Вниз по группе: радиус растёт, металлические свойства усиливаются (Li → Na → K → ...).',
'g17': 'Вниз по группе галогенов: неметаллические свойства ослабевают (F самый активный).'
};
modes.forEach(function (m) {
var b = document.createElement('button'); b.className = 'btn'; b.textContent = m.l;
b.addEventListener('click', function () {
bar.querySelectorAll('.btn').forEach(function (x) { x.classList.remove('primary'); }); b.classList.add('primary');
if (api) api.highlight(m.k);
var key = m.k ? (m.k.period ? 'p' + m.k.period : 'g' + m.k.group) : null;
note.textContent = key && TXT[key] ? TXT[key] : 'Выбери период или группу — увидишь тренд свойств.';
});
bar.appendChild(b);
});
el.appendChild(bar); el.appendChild(grid); el.appendChild(note);
var api = C().miniPeriodic(grid, {});
note.textContent = 'Выбери период или группу — увидишь, как меняются свойства.';
}
/* §35 — паспорт элемента: клик в ПСХЭ → полная характеристика */
function mount_p35() {
var el = $('c-passport'); if (!el || el._b || !C().miniPeriodic) return; el._b = 1;
var grid = document.createElement('div'), panel = document.createElement('div'); panel.className = 'passport';
panel.innerHTML = '<h4>Паспорт элемента</h4><div style="color:var(--muted);font-size:.85rem">Кликни элемент в системе.</div>';
el.appendChild(grid); el.appendChild(panel);
C().miniPeriodic(grid, { onClick: function (sym, info) {
var sh = C().shellConfig(info.z);
var catRu = info.cat === 'metal' ? 'металл' : info.cat === 'nonmetal' ? 'неметалл' : info.cat === 'metalloid' ? 'металлоид' : 'инертный газ';
panel.innerHTML = '<h4>Паспорт: ' + sym + '</h4><div class="passport-grid">'
+ '<div><b>Z</b>: ' + info.z + '</div>'
+ '<div><b>A_r</b>: ' + (info.ar || '—') + '</div>'
+ '<div><b>Период</b>: ' + info.p + '</div>'
+ '<div><b>Группа</b>: ' + info.g + '</div>'
+ '<div><b>Тип</b>: ' + catRu + '</div>'
+ '<div><b>Протонов</b>: ' + info.z + '</div>'
+ '<div><b>Электронов</b>: ' + info.z + '</div>'
+ '<div><b>Слои e⁻</b>: ' + sh.join(' ) ') + '</div>'
+ '<div><b>Внешних e⁻</b>: ' + sh[sh.length - 1] + '</div>'
+ '</div>';
if (W.chem8RenderMath) try { W.chem8RenderMath(panel); } catch (e) {}
} });
}
W.CHEM8_WIDGETS = { p29: mount_p29, p30: mount_p30, p31: mount_p31, p33: mount_p33 };
W.FLAG_MOUNTS = { p34: mount_p34, p35: mount_p35 };
})(window);