feat(math6): обогащение всех глав — хук, разбор по шагам, факты в каждом §

Каждый содержательный параграф 6 глав дополнен (Sonnet, по главе):
- карточка «Где это в жизни» (реальный контекст темы);
- «Разбор по шагам» (нумерованный алгоритм решения);
- «А знаешь ли ты?» (интересный факт/история);
- доведено до ≥2 рабочих интерактивов (где было меньше — добавлены).
Движок/общие файлы не трогались; структура M6/порядок init сохранены.
Проверено: тесты math6 18/18, честный рендер 4 глав — контент появляется,
рантайм-ошибок нет (только jsdom scrollTo-заглушка).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-06-02 21:14:56 +03:00
parent fe378371bd
commit 85c516e811
7 changed files with 813 additions and 12 deletions
+80 -1
View File
@@ -102,12 +102,22 @@ function _union(A,B){ var u=A.slice(); B.forEach(function(x){ if(u.indexOf(x)<0)
/* ===================== § 1. МНОЖЕСТВО. ЭЛЕМЕНТЫ. ПУСТОЕ МНОЖЕСТВО ===================== */
function buildP1(){
var box=document.getElementById('p1-body'); var h='';
h+=makeCard('oral','Где это в жизни','1.0',
'<p>Множества — это буквально всё вокруг нас. Список покупок в магазине — множество товаров. Состав футбольной команды — множество игроков. Коллекция марок, набор инструментов, список друзей — везде одна и та же идея: несколько разных объектов, собранных вместе. В программировании массивы и коллекции данных — прямые родственники математических множеств.</p>');
h+=makeCard('theory','Множество и его элементы','1.1',
'<p><b>Множество</b> — это набор различных объектов, объединённых общим признаком. Объекты множества — его <b>элементы</b>. Множества обозначают большими буквами, элементы перечисляют в фигурных скобках: $A=\\{2;4;6;8\\}$.</p>'
+'<p>Запись $3\\in A$ читается «$3$ принадлежит $A$», $5\\notin A$ — «$5$ не принадлежит $A$».</p>');
h+=makeCard('rule','Пустое множество','1.2',
h+=makeCard('example','Разбор по шагам','1.2',
'<p>Дано: $A=\\{1;3;5;7;9\\}$. Принадлежит ли $5$ множеству $A$? А $4$?</p>'
+'<ol><li>Смотрим на элементы $A$: $1, 3, 5, 7, 9$.</li>'
+'<li>Ищем $5$ в списке: $5$ есть — значит $5\\in A$.</li>'
+'<li>Ищем $4$ в списке: $4$ нет — значит $4\\notin A$.</li>'
+'<li>Сколько элементов? Считаем: $1, 2, 3, 4, 5$ — итого $|A|=5$.</li></ol>');
h+=makeCard('rule','Пустое множество','1.3',
'<p><b>Пустое множество</b> $\\varnothing$ не содержит ни одного элемента (например, множество натуральных решений уравнения $x+1=0$).</p>'
+'<p>Множества <b>равны</b>, если состоят из одних и тех же элементов; порядок и повторы не важны: $\\{1;2;3\\}=\\{3;1;2\\}$.</p>');
h+=makeCard('theory','А знаешь ли ты?','1.4',
'<p>Теорию множеств создал немецкий математик Георг Кантор в конце XIX века. Поначалу его идеи казались настолько странными, что коллеги не принимали их всерьёз. Сегодня теория множеств — фундамент всей современной математики: на ней строятся числа, функции и вся высшая математика.</p>');
h+='<div class="wg" id="p1-iv1"><div class="wg-header"><span class="wg-badge">Интерактив 1</span><div class="wg-title">Принадлежит или нет?</div></div>'
+'<div class="wg-help">Определи, принадлежит ли элемент данному множеству.</div>'
+'<div class="score-display"><span>Вопрос <b id="p1-i">1</b> / 6</span><span>Очки: <b id="p1-s">0</b> / 6</span></div>'
@@ -120,6 +130,12 @@ function buildP1(){
+'<div id="p1-cq" class="qbox"></div>'
+'<div style="display:flex;gap:10px;justify-content:center;align-items:center;flex-wrap:wrap"><input type="number" id="p1-ca" class="tinp" style="width:80px;text-align:center"><button class="btn primary" id="p1-cgo">Проверить</button></div>'
+'<div class="feedback" id="p1-cfb"></div></div>';
h+='<div class="wg" id="p1-iv3"><div class="wg-header"><span class="wg-badge">Интерактив 3</span><div class="wg-title">Составь множество</div></div>'
+'<div class="wg-help">Выбери все числа, которые принадлежат описанному множеству. Нажми нужные и проверь.</div>'
+'<div id="p1-sv3-q" class="qbox"></div>'
+'<div id="p1-sv3-chips" style="display:flex;gap:8px;justify-content:center;flex-wrap:wrap;margin:10px 0"></div>'
+'<div style="display:flex;gap:10px;justify-content:center"><button class="btn primary" id="p1-sv3-go">Проверить</button><button class="btn" id="p1-sv3-next">Следующее</button></div>'
+'<div class="feedback" id="p1-sv3-fb"></div></div>';
h+=secNav(null,'p2')+readBtn('p1');
box.innerHTML=h; renderMath(box);
@@ -148,14 +164,57 @@ function buildP1(){
document.getElementById('p1-cgo').addEventListener('click',go);
document.getElementById('p1-ca').addEventListener('keydown',function(e){ if(e.key==='Enter')go(); }); show();
})();
(function(){
var TASKS=[
{desc:'чётные числа от 1 до 10', nums:[1,2,3,4,5,6,7,8,9,10], correct:[2,4,6,8,10]},
{desc:'делители числа 8', nums:[1,2,3,4,5,6,7,8], correct:[1,2,4,8]},
{desc:'однозначные нечётные числа', nums:[1,2,3,4,5,6,7,8,9,10], correct:[1,3,5,7,9]},
{desc:'числа, кратные 4, до 20', nums:[2,4,6,8,10,12,14,16,18,20], correct:[4,8,12,16,20]}
];
var ti=0, sel=[];
function render(){
var t=TASKS[ti];
document.getElementById('p1-sv3-q').innerHTML='Выбери все числа: <b>'+t.desc+'</b>';
var chips=''; t.nums.forEach(function(n){ chips+='<button class="btn sv3-chip" data-n="'+n+'">'+n+'</button>'; });
document.getElementById('p1-sv3-chips').innerHTML=chips;
sel=[]; document.getElementById('p1-sv3-fb').style.display='none';
document.querySelectorAll('#p1-iv3 .sv3-chip').forEach(function(b){
b.addEventListener('click',function(){
var n=+b.getAttribute('data-n'), idx=sel.indexOf(n);
if(idx>=0){ sel.splice(idx,1); b.classList.remove('primary'); } else { sel.push(n); b.classList.add('primary'); }
});
});
}
document.getElementById('p1-sv3-go').addEventListener('click',function(){
var t=TASKS[ti], fb=document.getElementById('p1-sv3-fb');
var ok=t.correct.slice().sort().join(',')===[].concat(sel).sort().join(',');
if(ok){ feedback(fb,true,'Верно! Множество: {'+t.correct.join('; ')+'}'); addXp(10,'p1-iv3'); bumpProgress('p1',20); }
else { feedback(fb,false,'Не совсем. Правильный ответ: {'+t.correct.join('; ')+'}'); }
});
document.getElementById('p1-sv3-next').addEventListener('click',function(){
ti=(ti+1)%TASKS.length; render();
});
render();
})();
}
/* ===================== § 2. СПОСОБЫ ЗАДАНИЯ МНОЖЕСТВ ===================== */
function buildP2(){
var box=document.getElementById('p2-body'); var h='';
h+=makeCard('oral','Где это в жизни','2.0',
'<p>Когда составляют расписание уроков, можно написать список предметов — это перечисление. А можно написать правило: «предметы, которые идут в понедельник» — это задание свойством. В базах данных программисты постоянно используют оба способа: хранят конкретные списки и создают запросы-условия. Правильно выбрать способ задания множества — значит сэкономить время и избежать ошибок.</p>');
h+=makeCard('theory','Два способа задания','2.1',
'<p><b>Перечислением</b> — выписывают все элементы: $A=\\{2;4;6;8\\}$.</p>'
+'<p><b>Характеристическим свойством</b> — указывают признак: $A=\\{x \\mid x$ — чётное, $0<x<10\\}$ (читается «множество всех $x$ таких, что …»).</p>');
h+=makeCard('example','Разбор по шагам','2.2',
'<p>Задано свойство: $B=\\{x\\mid x$ — делитель числа $12\\}$. Запишем $B$ перечислением.</p>'
+'<ol><li>Находим все делители $12$: числа, на которые $12$ делится без остатка.</li>'
+'<li>Проверяем по очереди: $1, 2, 3, 4, 6, 12$ — все делят $12$ нацело.</li>'
+'<li>Числа $5, 7, 8, 9, 10, 11$ — не делители: остаток не ноль.</li>'
+'<li>Итог: $B=\\{1;2;3;4;6;12\\}$.</li></ol>');
h+=makeCard('theory','А знаешь ли ты?','2.3',
'<p>Запись $\\{x\\mid\\ldots\\}$ придумали, чтобы задавать бесконечные множества. Например, множество всех чётных чисел $\\{x\\mid x$ кратно $2\\}$ нельзя задать перечислением — элементов бесконечно много. А свойством — одна строчка!</p>');
h+='<div class="wg" id="p2-iv1"><div class="wg-header"><span class="wg-badge">Интерактив 1</span><div class="wg-title">Свойство → множество</div></div>'
+'<div class="wg-help">Выбери множество, заданное перечислением, которое соответствует описанию.</div>'
+'<div class="score-display"><span>Вопрос <b id="p2-i">1</b> / 5</span><span>Очки: <b id="p2-s">0</b> / 5</span></div>'
@@ -216,10 +275,19 @@ function buildP2(){
/* ===================== § 3. ОПЕРАЦИИ НАД МНОЖЕСТВАМИ ===================== */
function buildP3(){
var box=document.getElementById('p3-body'); var h='';
h+=makeCard('oral','Где это в жизни','3.0',
'<p>Представь: $A$ — ученики, которые занимаются футболом, $B$ — те, кто ходит на плавание. Пересечение $A\\cap B$ — те, кто занимается обоими видами спорта. Объединение $A\\cup B$ — все, кто занимается хотя бы одним. Такие операции каждый день используют составители расписаний, маркетологи («покупатели, которые брали и A, и B») и врачи, анализируя симптомы.</p>');
h+=makeCard('theory','Пересечение и объединение','3.1',
'<p><b>Пересечение</b> $A\\cap B$ — множество элементов, принадлежащих <b>обоим</b> множествам сразу.</p>'
+'<p><b>Объединение</b> $A\\cup B$ — множество элементов, принадлежащих <b>хотя бы одному</b> из множеств.</p>'
+'<p>$A=\\{1;2;3;4\\}$, $B=\\{3;4;5;6\\}$: $A\\cap B=\\{3;4\\}$, $A\\cup B=\\{1;2;3;4;5;6\\}$.</p>');
h+=makeCard('example','Разбор по шагам','3.2',
'<p>Найти $A\\cap B$ и $A\\cup B$, если $A=\\{2;4;6;8\\}$, $B=\\{4;6;10;12\\}$.</p>'
+'<ol><li>Для <b>пересечения</b> берём только общие элементы: смотрим, что есть и в $A$, и в $B$. Это $4$ и $6$. Значит, $A\\cap B=\\{4;6\\}$.</li>'
+'<li>Для <b>объединения</b> берём все элементы из обоих: $2, 4, 6, 8$ из $A$, добавляем новые из $B$ — $10$ и $12$. Повторы ($4$ и $6$) пишем один раз.</li>'
+'<li>Итог: $A\\cup B=\\{2;4;6;8;10;12\\}$.</li></ol>');
h+=makeCard('theory','А знаешь ли ты?','3.3',
'<p>Символы $\\cap$ (пересечение) и $\\cup$ (объединение) ввёл итальянский математик Джузеппе Пеано в 1888 году. Символ $\\cup$ напоминает букву U — от слова <i>union</i> (союз, объединение по-английски). Сегодня эти символы используют во всём мире в математике, логике и программировании.</p>');
h+='<div class="wg" id="p3-iv1"><div class="wg-header"><span class="wg-badge">Интерактив 1</span><div class="wg-title">Операции наглядно</div></div>'
+'<div class="wg-help">Нажми операцию — увидишь закрашенную область и результат для $A=\\{1;2;3;4\\}$, $B=\\{3;4;5;6\\}$.</div>'
+'<div style="display:flex;gap:8px;justify-content:center;flex-wrap:wrap;margin-bottom:8px"><button class="btn primary" data-op="inter">$A\\cap B$</button><button class="btn" data-op="union">$A\\cup B$</button></div>'
@@ -264,8 +332,19 @@ function buildP3(){
/* ===================== § 4. КРУГИ ЭЙЛЕРА ===================== */
function buildP4(){
var box=document.getElementById('p4-body'); var h='';
h+=makeCard('oral','Где это в жизни','4.0',
'<p>Круги Эйлера — не просто красивые картинки. Врачи рисуют их, чтобы понять, у скольких пациентов сочетаются два симптома. Маркетологи — чтобы узнать, кто смотрит и кино, и сериалы. Задача «в классе 30 учеников, 18 занимаются музыкой, 14 — танцами, 5 — и тем и тем; сколько не занимаются ничем?» — классический круг Эйлера. Один рисунок заменяет три уравнения.</p>');
h+=makeCard('theory','Круги Эйлера','4.1',
'<p>Множества удобно изображать кругами (круги Эйлера). Пересекающиеся круги показывают общую часть. Если в $A$ — $a$ элементов, в $B$ — $b$, а в пересечении — $c$, то в объединении: $|A\\cup B| = a + b - c$ (общие посчитаны дважды — вычитаем один раз).</p>');
h+=makeCard('example','Разбор по шагам','4.2',
'<p>В классе 30 учеников. Математику любят 18, физику — 14, оба предмета — 6. Сколько не любят ни то, ни другое?</p>'
+'<ol><li>Рисуем два пересекающихся круга: «Математика» и «Физика».</li>'
+'<li>В центр (пересечение) пишем $6$ — те, кто любит оба.</li>'
+'<li>Только математику: $18-6=12$. Только физику: $14-6=8$.</li>'
+'<li>Любят хотя бы один предмет: $12+6+8=26$.</li>'
+'<li>Не любят ни один: $30-26=4$.</li></ol>');
h+=makeCard('theory','А знаешь ли ты?','4.3',
'<p>Круги Эйлера придумал швейцарский математик Леонард Эйлер в XVIII веке — один из самых плодовитых математиков в истории. Он опубликовал более 800 работ и продолжал трудиться, даже ослепнув на оба глаза. Его именем названы и формула $e^{i\\pi}+1=0$, и данный метод наглядного изображения множеств.</p>');
h+='<div class="wg" id="p4-iv1"><div class="wg-header"><span class="wg-badge">Интерактив 1</span><div class="wg-title">Задача с кругами Эйлера</div></div>'
+'<div class="wg-help">Разнеси данные по кругам и ответь на вопрос.</div>'
+'<div class="score-display"><span>Задача <b id="p4-i">1</b> / 5</span><span>Очки: <b id="p4-s">0</b> / 5</span></div>'