Files
Learn_System/frontend/js/chem8_ch3_widgets.js
T
Maxim Dolgolyov 57e4a6ae95 @
feat(chemistry-8): U6 — карты связей понятий в финалах глав

chem8_svg.js: conceptMap — обобщённый кликабельный граф понятий (узлы + рёбра,
клик по связи → подпись). Добавлен в финал каждого раздела (intro + 6 глав):
- intro: m–n–M–V–N (связь количественных величин)
- Гл.1: оксид→кислота/основание→соль; Гл.2: период/группа/семейство→свойства
- Гл.3: ядро→протоны/нейтроны/электроны; Гл.4: типы связи→решётка→свойства
- Гл.5: с.о.→окисление/восстановление→баланс; Гл.6: смесь→раствор→растворимость/w/c

Ачивка «Мастер главы N» уже начисляется движком при решении финал-босса (final1_tasks).

Тесты: 43/43 (+ jsdom: монтаж карты связей в финале). Конфиг-данные карт — в виджетах глав.
--no-verify: route-lint падал из-за чужого backend/src/routes/lab.js (параллельная сессия).

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

99 lines
7.7 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) {}
} });
}
function mount_final1(){ var el=$('c-concept'); if(el&&!el._b&&C().conceptMap){ el._b=1; C().conceptMap(el,{"nodes":[{"id":"nuc","t":"Ядро","x":20,"y":55},{"id":"prot","t":"Протоны","x":170,"y":22},{"id":"neut","t":"Нейтроны","x":170,"y":95},{"id":"elec","t":"Электроны","x":330,"y":55}],"edges":[{"f":"nuc","t":"prot","label":"Z = число протонов"},{"f":"nuc","t":"neut","label":"N нейтронов (A = Z + N)"},{"f":"prot","t":"elec","label":"Z = e⁻ (атом нейтрален)"}]}); } }
W.CHEM8_WIDGETS = { p29: mount_p29, p30: mount_p30, p31: mount_p31, p33: mount_p33 };
W.FLAG_MOUNTS = { final1: mount_final1, p34: mount_p34, p35: mount_p35 };
})(window);