diff --git a/backend/tests/chemistry7-page.test.js b/backend/tests/chemistry7-page.test.js index c2ead93..955788b 100644 --- a/backend/tests/chemistry7-page.test.js +++ b/backend/tests/chemistry7-page.test.js @@ -95,6 +95,19 @@ test('ch1 Волна 2: интерактивы §4–§6 монтируются assert.deepEqual(errors, [], 'нет ошибок: ' + errors.join(' | ')); }); +test('ch1 Волна 3: интерактивы §7–§9 монтируются и считают', async () => { + const { doc, errors } = await loadDom('chemistry_7_ch1.html'); + doc.defaultView.goTo('p7'); await wait(100); + assert.ok(doc.querySelector('#p7-out'), 'парсер формулы §7'); + assert.match(doc.querySelector('#p7-out').textContent, /4/, 'H2SO4 → 4 атома O в разборе'); + doc.defaultView.goTo('p8'); await wait(100); + assert.match(doc.querySelector('#p8-out').textContent, /100/, 'M_r(CaCO3)=100'); + doc.defaultView.goTo('p9'); await wait(100); + assert.ok(doc.querySelector('#p9-bld #p9-a'), 'конструктор валентности §9'); + assert.match(doc.querySelector('#p9-bout').textContent, /Al/, 'формула по валентности построена'); + assert.deepEqual(errors, [], 'нет ошибок: ' + errors.join(' | ')); +}); + test('ch1: переход к §9 и финалу строит заглушку без ошибок', async () => { const { doc, errors } = await loadDom('chemistry_7_ch1.html'); doc.defaultView.goTo('p9'); await wait(80); diff --git a/frontend/js/chem7_ch1_widgets.js b/frontend/js/chem7_ch1_widgets.js index 3fdcf6a..ef6b5e6 100644 --- a/frontend/js/chem7_ch1_widgets.js +++ b/frontend/js/chem7_ch1_widgets.js @@ -235,9 +235,73 @@ } } + /* ── Волна 3 ── */ + + /* §7 — разбор химической формулы на состав */ + function mount_p7() { + var inp = $('p7-in'), out = $('p7-out'), go = $('p7-go'); if (!inp || inp._built) return; inp._built = 1; + function calc() { + var f = inp.value.trim(), cnt = C().elementCounts ? C().elementCounts(f) : null; + if (!cnt || !Object.keys(cnt).length) { out.className = 'out bad'; out.textContent = 'Не удалось разобрать формулу. Проверь символы элементов (например, H2SO4).'; return; } + var els = Object.keys(cnt), tot = els.reduce(function (s, e) { return s + cnt[e]; }, 0); + out.className = 'out ok'; + out.innerHTML = '' + (C().formula ? C().formula(f) : f) + '
' + + 'Элементов: ' + els.length + ' (' + (els.length === 1 ? 'простое' : 'сложное') + ' вещество)
' + + els.map(function (e) { return e + ': ' + cnt[e] + ' ' + (cnt[e] === 1 ? 'атом' : 'атома(ов)'); }).join('
') + + '
Всего атомов в формуле: ' + tot + '
'; + } + go.addEventListener('click', calc); + inp.addEventListener('keydown', function (e) { if (e.key === 'Enter') calc(); }); + document.querySelectorAll('.p7-ex').forEach(function (b) { b.addEventListener('click', function () { inp.value = b.dataset.f; calc(); }); }); + calc(); + } + + /* §8 — калькулятор относительной молекулярной массы M_r */ + function mount_p8() { + var inp = $('p8-in'), out = $('p8-out'), go = $('p8-go'); if (!inp || inp._built) return; inp._built = 1; + function calc() { + var f = inp.value.trim(), cnt = C().elementCounts ? C().elementCounts(f) : null, mr = C().molarMass ? C().molarMass(f) : NaN; + if (!cnt || isNaN(mr)) { out.className = 'out bad'; out.textContent = 'Не удалось разобрать формулу.'; return; } + out.className = 'out ok'; + out.innerHTML = 'M_r(' + f + ') = ' + C().fmt(mr) + '
' + + Object.keys(cnt).map(function (e) { return e + ': A_r=' + (C().arOf ? C().arOf(e) : '?') + ' × ' + cnt[e]; }).join('  |  ') + + '
Σ = ' + Object.keys(cnt).map(function (e) { return (C().arOf ? C().arOf(e) : '?') + '·' + cnt[e]; }).join(' + ') + ' = ' + C().fmt(mr) + '
'; + } + go.addEventListener('click', calc); + inp.addEventListener('keydown', function (e) { if (e.key === 'Enter') calc(); }); + document.querySelectorAll('.p8-ex').forEach(function (b) { b.addEventListener('click', function () { inp.value = b.dataset.f; calc(); }); }); + calc(); + } + + /* §9 — конструктор формулы по валентности (НОК индексов) */ + function gcd(a, b) { return b ? gcd(b, a % b) : a; } + var VA = [ ['Na', 1], ['K', 1], ['H', 1], ['Mg', 2], ['Ca', 2], ['Zn', 2], ['Cu', 2], ['Al', 3], ['C', 4] ]; + var VB = [ ['O', 2], ['Cl', 1], ['S', 2] ]; + function mount_p9() { + var m = $('p9-bld'); if (!m || m._built) return; m._built = 1; + function optA(){ return VA.map(function(e,i){ return ''; }).join(''); } + function optB(){ return VB.map(function(e,i){ return ''; }).join(''); } + m.innerHTML = '
' + +'
'; + function upd() { + var a = VA[+$('p9-a').value], b = VB[+$('p9-b').value]; + var lcm = a[1] * b[1] / gcd(a[1], b[1]); + var ia = lcm / a[1], ib = lcm / b[1]; + var raw = a[0] + (ia > 1 ? ia : '') + b[0] + (ib > 1 ? ib : ''); + var out = $('p9-bout'); out.className = 'out ok'; + out.innerHTML = 'Валентности: ' + a[0] + ' = ' + 'I'.repeat(a[1]).replace('IIII','IV') + ', ' + b[0] + ' = ' + 'I'.repeat(b[1]) + '
' + + 'Наименьшее общее кратное валентностей = ' + lcm + '
' + + 'Индексы: ' + a[0] + ' → ' + ia + ', ' + b[0] + ' → ' + ib + '
' + + 'Формула: ' + (C().formula ? C().formula(raw) : raw) + '
' + + 'Проверка: ' + ia + '·' + a[1] + ' = ' + ib + '·' + b[1] + ' = ' + lcm + ' единиц валентности — совпало.
'; + } + $('p9-a').addEventListener('change', upd); $('p9-b').addEventListener('change', upd); upd(); + } + 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 + p4: mount_p4, p5: mount_p5, p6: mount_p6, + p7: mount_p7, p8: mount_p8, p9: mount_p9 }); W.FLAG_MOUNTS = Object.assign(W.FLAG_MOUNTS || {}, {}); })(window); diff --git a/frontend/textbooks/chemistry_7_ch1.html b/frontend/textbooks/chemistry_7_ch1.html index 1e48637..07caf6d 100644 --- a/frontend/textbooks/chemistry_7_ch1.html +++ b/frontend/textbooks/chemistry_7_ch1.html @@ -105,7 +105,8 @@ window.PARAS = [ window.ACH_LABELS = { start:'Начало главы 1!', p1_done:'§1 изучен!', p2_done:'§2 изучен!', pr1_done:'Практическая работа 1 выполнена!', p3_done:'§3 изучен!', - p4_done:'§4 изучен!', p5_done:'§5 изучен!', p6_done:'§6 изучен!', final1_tasks:'Глава 1 пройдена!' }; + p4_done:'§4 изучен!', p5_done:'§5 изучен!', p6_done:'§6 изучен!', + p7_done:'§7 изучен!', p8_done:'§8 изучен!', p9_done:'§9 изучен!', final1_tasks:'Глава 1 пройдена!' }; window.SIDEBARS = { p1:{ title:'Шпаргалка §1', rows:[['Вещество','то, из чего состоит тело'],['Тело','предмет из вещества'],['Свойства','цвет, запах, плотность, $t_{пл}$…']] }, p2:{ title:'Шпаргалка §2', rows:[['Чистое','постоянный состав'],['Смесь','2+ вещества'],['Разделение','по различию свойств']] }, @@ -113,7 +114,10 @@ window.SIDEBARS = { p3:{ title:'Шпаргалка §3', rows:[['Атом','мельчайшая частица'],['Элемент','атомы с одинаковым $Z$'],['Символ','H, O, Fe, Cu…']] }, p4:{ title:'Шпаргалка §4', rows:[['$A_r$','во сколько раз тяжелее'],['Эталон','$1/12$ массы $^{12}$C'],['Пример','$A_r(\\text{O})=16$']] }, p5:{ title:'Шпаргалка §5', rows:[['Молекула','частица из атомов'],['Простое','1 элемент: $O_2$, $H_2$'],['Атомность','$O_2$, $O_3$']] }, - p6:{ title:'Шпаргалка §6', rows:[['Сложное','разные элементы'],['Примеры','$H_2O$, $CO_2$, $NH_3$'],['Состав','можно разложить']] } + p6:{ title:'Шпаргалка §6', rows:[['Сложное','разные элементы'],['Примеры','$H_2O$, $CO_2$, $NH_3$'],['Состав','можно разложить']] }, + p7:{ title:'Шпаргалка §7', rows:[['Индекс','число атомов'],['Коэффициент','число молекул'],['Состав','качеств. + количеств.']] }, + p8:{ title:'Шпаргалка §8', rows:[['$M_r$','$=\\sum A_r$'],['$M_r(H_2O)$','18'],['$M_r(H_2SO_4)$','98']] }, + p9:{ title:'Шпаргалка §9', rows:[['Валентность','число связей'],['H — I, O — II',''],['Формула','по НОК валентностей']] } }; window.TIPS = [ { sec:'p1', html:'Тело — это предмет (гвоздь, стакан), а вещество — то, из чего он сделан (железо, стекло). Из одного вещества можно сделать много тел.' }, @@ -122,7 +126,10 @@ window.TIPS = [ { sec:'p3', html:'Химический элемент определяется зарядом ядра (числом протонов) — это и есть порядковый номер $Z$.' }, { sec:'p4', html:'$A_r$ показывает, во сколько раз масса атома больше $1/12$ массы атома углерода-12. $A_r(\\text{H})=1$, $A_r(\\text{O})=16$, $A_r(\\text{Fe})=56$.' }, { sec:'p5', html:'Простое вещество — атомы одного элемента ($O_2$, $Fe$). Кислород $O_2$ и озон $O_3$ — разные простые вещества одного и того же элемента.' }, - { sec:'p6', html:'Сложное вещество образовано атомами разных элементов ($H_2O$ — водород и кислород) и может быть разложено на простые.' } + { sec:'p6', html:'Сложное вещество образовано атомами разных элементов ($H_2O$ — водород и кислород) и может быть разложено на простые.' }, + { sec:'p7', html:'Индекс относится к атому/группе слева от него. В $H_2SO_4$: 2 атома H, 1 атом S, 4 атома O. Коэффициент (число перед формулой) — это число молекул.' }, + { sec:'p8', html:'$M_r$ — сумма $A_r$ всех атомов формулы. $M_r(\\text{CO}_2)=12+2\\cdot16=44$.' }, + { sec:'p9', html:'Кислород в соединениях имеет валентность II, водород — I. Зная их, можно определить валентность другого элемента и составить формулу по НОК.' } ]; /* ── задачи (тренажёр) ── */ @@ -162,6 +169,24 @@ window.POOLS = { {q:'Сложное вещество образовано…',opts:['Атомами одного элемента','Атомами разных элементов','Только смесью','Одним атомом'],a:1,ex:'Сложное — разные элементы.'}, {q:'Какое из веществ — простое?',opts:['$\\text{H}_2\\text{O}$','$\\text{CO}_2$','$\\text{N}_2$','$\\text{NH}_3$'],a:2,ex:'$N_2$ — один элемент (азот).'}, {q:'Сколько разных химических элементов в молекуле метана $\\text{CH}_4$?',hint:'углерод и водород',unit:'',a:2,ex:'C и H — два элемента.'} + ], + p7:[ + {q:'Что показывает индекс в химической формуле?',opts:['Число молекул','Число атомов элемента','Массу вещества','Заряд'],a:1,ex:'Индекс — число атомов элемента (или группы) в формуле.'}, + {q:'Сколько атомов кислорода в формуле $\\text{H}_2\\text{SO}_4$?',hint:'индекс при O',unit:'',a:4,ex:'4 атома кислорода.'}, + {q:'Сколько всего атомов в молекуле воды $\\text{H}_2\\text{O}$?',hint:'2 H + 1 O',unit:'',a:3,ex:'2 + 1 = 3 атома.'}, + {q:'Число, стоящее перед формулой (коэффициент), показывает…',opts:['Число атомов','Число молекул','Валентность','Массу'],a:1,ex:'Коэффициент — число молекул вещества.'} + ], + p8:[ + {q:'Чему равна $M_r(\\text{H}_2\\text{O})$?',hint:'$2\\cdot1+16$',unit:'',a:18,ex:'$M_r=18$.'}, + {q:'Чему равна $M_r(\\text{CO}_2)$?',hint:'$12+2\\cdot16$',unit:'',a:44,ex:'$12+32=44$.'}, + {q:'Чему равна $M_r(\\text{H}_2\\text{SO}_4)$?',hint:'$2+32+4\\cdot16$',unit:'',a:98,ex:'$2+32+64=98$.'}, + {q:'Чему равна $M_r(\\text{CaCO}_3)$?',hint:'$40+12+3\\cdot16$',unit:'',a:100,ex:'$40+12+48=100$.'} + ], + p9:[ + {q:'За единицу валентности принята валентность атома…',opts:['кислорода','водорода','углерода','железа'],a:1,ex:'Единица валентности — валентность водорода (I).'}, + {q:'Какова валентность кислорода в соединениях?',hint:'постоянная',unit:'',a:2,ex:'Кислород почти всегда двухвалентен (II).'}, + {q:'Какова валентность хлора в молекуле $\\text{HCl}$?',hint:'равна числу атомов H',unit:'',a:1,ex:'Хлор соединён с 1 атомом H → валентность I.'}, + {q:'Какова формула оксида алюминия (Al — III, O — II)?',opts:['AlO','Al₂O₃','AlO₂','Al₃O₂'],a:1,ex:'НОК(3,2)=6 → индексы 2 и 3 → Al₂O₃.'} ] }; @@ -290,6 +315,58 @@ function build_p6(){ wireReadBtn('p6'); } +function build_p7(){ + document.getElementById('p7-body').innerHTML = + '
§ 7 · Химия 7

Химическая формула

' + +'
$\\text{H}_2\\text{O}$
' + +'
Как с помощью формулы записывают, из каких атомов и в каком числе состоит вещество.
' + +'
индекскоэффициентсостав
' + +makeCard('theory','Что показывает формула','§7','

Химическая формула показывает состав вещества: качественный (из каких элементов) и количественный (сколько атомов каждого элемента).

' + +'
Индекс — маленькое число справа внизу: показывает число атомов элемента ($\\text{H}_2\\text{O}$ — 2 атома H, 1 атом O). Коэффициент — число перед формулой: показывает число молекул ($2\\text{H}_2\\text{O}$ — две молекулы воды).
') + +makeCard('example','Чтение формул',null,'

$\\text{H}_2\\text{O}$ читают «аш-два-о», $\\text{H}_2\\text{SO}_4$ — «аш-два-эс-о-четыре», $\\text{CH}_4$ — «цэ-аш-четыре».

') + +wgt('Разбор формулы на состав','
' + +'
' + +'
Введи формулу и нажми «Разобрать».
') + +rememberBox(['Индекс — число атомов; стоит справа внизу.','Коэффициент — число молекул; стоит перед формулой.','Скобки: индекс умножает всё внутри — Ca(OH)₂ = 1 Ca, 2 O, 2 H.']) + +qList(['Чем индекс отличается от коэффициента?','Сколько атомов каждого элемента в $\\text{H}_3\\text{PO}_4$?','Что означает запись $3\\text{H}_2\\text{O}$?']) + +secNav('p6','p8')+readButton('p7'); + wireReadBtn('p7'); +} + +function build_p8(){ + document.getElementById('p8-body').innerHTML = + '
§ 8 · Химия 7

Относительная молекулярная масса

' + +'
$M_r=\\sum A_r$
' + +'
Как по формуле рассчитать, во сколько раз молекула тяжелее эталона.
' + +'
$M_r$$\\sum A_r$
' + +makeCard('rule','Относительная молекулярная масса','§8','
Относительная молекулярная масса $M_r$ равна сумме относительных атомных масс всех атомов в формуле. Это безразмерная величина: она показывает, во сколько раз молекула тяжелее $\\tfrac{1}{12}$ массы атома углерода-12.
') + +makeCard('example','Расчёт $M_r$',null,'

$M_r(\\text{H}_2\\text{O})=2\\cdot A_r(\\text{H})+A_r(\\text{O})=2\\cdot1+16=18$.

$M_r(\\text{H}_2\\text{SO}_4)=2\\cdot1+32+4\\cdot16=98$.
') + +wgt('Калькулятор $M_r$ по формуле','
' + +'
' + +'
Введи формулу и нажми «Вычислить».
') + +rememberBox(['$M_r$ — сумма $A_r$ всех атомов формулы.','$M_r$ безразмерна.','Индекс умножает $A_r$ соответствующего элемента.']) + +qList(['Вычисли $M_r(\\text{Na}_2\\text{CO}_3)$.','Во сколько раз молекула воды тяжелее $\\tfrac{1}{12}$ атома углерода-12?','Вычисли $M_r(\\text{Fe}_2\\text{O}_3)$.']) + +secNav('p7','p9')+readButton('p8'); + wireReadBtn('p8'); +} + +function build_p9(){ + document.getElementById('p9-body').innerHTML = + '
§ 9 · Химия 7

Валентность

' + +'
H — I, O — II
' + +'
Сколько связей образует атом и как по валентности составить формулу вещества.
' + +'
валентностьНОК
' + +makeCard('theory','Что такое валентность','§9','

Валентность — способность атома соединяться с определённым числом атомов других элементов. За единицу валентности принята валентность атома водорода (I). В $\\text{HCl}$ хлор одновалентен, в $\\text{H}_2\\text{O}$ кислород двухвалентен, в $\\text{NH}_3$ азот трёхвалентен, в $\\text{CH}_4$ углерод четырёхвалентен.

') + +makeCard('rule','Составление формул по валентности','§9','

Кислород в соединениях обычно имеет валентность II, водород — I. Зная валентности, формулу составляют так, чтобы суммарное число единиц валентности обоих элементов совпало (по наименьшему общему кратному).

' + +'
Постоянные валентности: H — I; O — II; Na, K — I; Mg, Ca, Zn — II; Al — III.
') + +makeCard('example','Оксид алюминия',null,'

Al — III, O — II. НОК(3, 2) = 6. Индексы: Al → 6/3 = 2, O → 6/2 = 3.

Формула: $\\text{Al}_2\\text{O}_3$.
') + +wgt('Конструктор формулы по валентности','
') + +rememberBox(['Валентность — число связей атома; единица — валентность водорода.','Кислород — II, водород — I (постоянные).','Формулу составляют по НОК валентностей.']) + +qList(['Определи валентность серы в $\\text{SO}_2$ (O — II).','Составь формулу соединения кальция (II) с кислородом.','Чему равна валентность азота в $\\text{NH}_3$?']) + +secNav('p8','p10')+readButton('p9'); + wireReadBtn('p9'); +} + /* заглушки для ещё не наполненных § (фазы — следующие волны) */ (function(){ var P = window.PARAS, B = {}; @@ -319,6 +396,9 @@ window.BUILDERS.p3 = build_p3; window.BUILDERS.p4 = build_p4; window.BUILDERS.p5 = build_p5; window.BUILDERS.p6 = build_p6; +window.BUILDERS.p7 = build_p7; +window.BUILDERS.p8 = build_p8; +window.BUILDERS.p9 = build_p9;