feat(chemistry7): Phase 1 Волна 4 — Глава 1 завершена (§§10–12 + ЛО1 + финал)
§10 Физические и химические явления (детектор признаков реакции), ЛО1 Признаки реакций (опыты с признаками), §11 Закон сохранения массы (весы сохранения массы), §12 Составление уравнений (балансировщик через Chem8.equationBalancer), финал главы (6 интегрированных боссов + шпаргалка). Глава 1 «Первоначальные химические понятия» наполнена полностью (12§). Тесты: 10/10 chem7 pass; полный прогон 156/159 (3 — известный baseline Auth). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -298,10 +298,79 @@
|
||||
$('p9-a').addEventListener('change', upd); $('p9-b').addEventListener('change', upd); upd();
|
||||
}
|
||||
|
||||
/* ── Волна 4 ── */
|
||||
|
||||
/* §10 / ЛО1 — детектор признаков химической реакции */
|
||||
var DEMOS = [
|
||||
{ name: 'Нагревание малахита', signs: ['изменение цвета: зелёный → чёрный', 'выделение газа (водяной пар и углекислый газ)'] },
|
||||
{ name: 'Сливание растворов CuSO₄ и NaOH', signs: ['образование осадка (голубой)', 'изменение цвета раствора'] },
|
||||
{ name: 'Горение серы', signs: ['выделение света и тепла (пламя)', 'появление резкого запаха'] },
|
||||
{ name: 'Добавление соды в уксус', signs: ['выделение газа (пузырьки)'] }
|
||||
];
|
||||
function mount_signs(mountId) {
|
||||
var m = $(mountId); if (!m || m._built) return; m._built = 1;
|
||||
var idx = 0;
|
||||
function render() {
|
||||
m.innerHTML = '<div class="fld"><label>Опыт</label><select id="' + mountId + '-pick">'
|
||||
+ DEMOS.map(function (d, i) { return '<option value="' + i + '"' + (i === idx ? ' selected' : '') + '>' + esc(d.name) + '</option>'; }).join('') + '</select>'
|
||||
+ '<button class="btn primary" id="' + mountId + '-go">Провести опыт</button></div>'
|
||||
+ '<div class="out" id="' + mountId + '-out">Выбери опыт и нажми «Провести опыт».</div>';
|
||||
$(mountId + '-pick').addEventListener('change', function (e) { idx = +e.target.value; m._built = 0; render(); });
|
||||
$(mountId + '-go').addEventListener('click', function () {
|
||||
var d = DEMOS[idx], out = $(mountId + '-out'); out.className = 'out ok';
|
||||
out.innerHTML = '<b>Наблюдаемые признаки реакции:</b><div style="margin-top:6px">'
|
||||
+ d.signs.map(function (s) { return '<div style="padding:5px 10px;margin:3px 0;border-radius:8px;background:var(--pri-soft);font-weight:600">✓ ' + esc(s) + '</div>'; }).join('')
|
||||
+ '</div><div style="font-size:.84rem;color:var(--muted);margin-top:6px">Эти признаки указывают, что произошла <b>химическая реакция</b> — образовались новые вещества.</div>';
|
||||
});
|
||||
}
|
||||
render();
|
||||
}
|
||||
function mount_p10() { mount_signs('p10-signs'); }
|
||||
function mount_lo1() { mount_signs('lo1-signs'); }
|
||||
|
||||
/* §11 — весы сохранения массы */
|
||||
function mount_p11() {
|
||||
var m = $('p11-bal'); if (!m || m._built) return; m._built = 1;
|
||||
var mixed = false;
|
||||
function scale(level) {
|
||||
// level: 0 = равновесие
|
||||
return '<svg viewBox="0 0 320 130" width="100%" style="max-width:340px">'
|
||||
+ '<line x1="160" y1="14" x2="160" y2="40" stroke="var(--muted)" stroke-width="3"/>'
|
||||
+ '<line x1="60" y1="40" x2="260" y2="40" stroke="var(--muted)" stroke-width="3"/>'
|
||||
+ '<circle cx="160" cy="14" r="6" fill="var(--pri)"/>'
|
||||
+ '<rect x="30" y="55" width="80" height="34" rx="6" fill="var(--pri-soft)" stroke="var(--border)"/>'
|
||||
+ '<rect x="210" y="55" width="80" height="34" rx="6" fill="var(--pri-soft)" stroke="var(--border)"/>'
|
||||
+ '<line x1="60" y1="40" x2="70" y2="55" stroke="var(--muted)" stroke-width="2"/><line x1="110" y1="40" x2="100" y2="55" stroke="var(--muted)" stroke-width="2"/>'
|
||||
+ '<line x1="210" y1="40" x2="220" y2="55" stroke="var(--muted)" stroke-width="2"/><line x1="260" y1="40" x2="250" y2="55" stroke="var(--muted)" stroke-width="2"/>'
|
||||
+ '<text x="70" y="77" font-size="13" font-weight="700" fill="var(--text)">100 г</text>'
|
||||
+ '<text x="250" y="77" font-size="13" font-weight="700" fill="var(--text)">100 г</text>'
|
||||
+ '<text x="70" y="108" font-size="11" fill="var(--muted)">' + (mixed ? 'продукты' : 'реагенты') + '</text>'
|
||||
+ '<text x="225" y="108" font-size="11" fill="var(--muted)">' + (mixed ? 'продукты' : 'реагенты') + '</text>'
|
||||
+ '</svg>';
|
||||
}
|
||||
function render() {
|
||||
m.innerHTML = scale()
|
||||
+ '<div style="margin:6px 0;font-size:.92rem">' + (mixed
|
||||
? 'После реакции: <b>осадок Cu(OH)₂ + раствор Na₂SO₄</b>. Стрелка весов не сдвинулась — <b>масса сохранилась</b> (100 г = 100 г).'
|
||||
: 'До реакции: <b>раствор CuSO₄ + раствор NaOH</b>, общая масса 100 г.') + '</div>'
|
||||
+ '<button class="btn primary" id="p11-mix">' + (mixed ? 'Сбросить' : 'Смешать растворы') + '</button>';
|
||||
$('p11-mix').addEventListener('click', function () { mixed = !mixed; m._built = 0; render(); });
|
||||
}
|
||||
render();
|
||||
}
|
||||
|
||||
/* §12 — балансировщик уравнений (переиспользуем Chem8.equationBalancer) */
|
||||
function mount_p12() {
|
||||
var pick = $('p12-pick'), mount = $('p12-mount'); if (!pick || pick._built || !C().equationBalancer) return; pick._built = 1;
|
||||
function build() { var parts = pick.value.split('|'); C().equationBalancer(mount, { skeleton: parts[0], solution: parts[1].split(',').map(Number) }); }
|
||||
pick.addEventListener('change', build); build();
|
||||
}
|
||||
|
||||
W.CHEM8_WIDGETS = Object.assign(W.CHEM8_WIDGETS || {}, {
|
||||
p1: mount_p1, p2: mount_p2, pr1: mount_pr1, p3: mount_p3,
|
||||
p4: mount_p4, p5: mount_p5, p6: mount_p6,
|
||||
p7: mount_p7, p8: mount_p8, p9: mount_p9
|
||||
p7: mount_p7, p8: mount_p8, p9: mount_p9,
|
||||
p10: mount_p10, lo1: mount_lo1, p11: mount_p11
|
||||
});
|
||||
W.FLAG_MOUNTS = Object.assign(W.FLAG_MOUNTS || {}, {});
|
||||
W.FLAG_MOUNTS = Object.assign(W.FLAG_MOUNTS || {}, { p12: mount_p12 });
|
||||
})(window);
|
||||
|
||||
Reference in New Issue
Block a user