diff --git a/frontend/textbooks/algebra_9_ch4.html b/frontend/textbooks/algebra_9_ch4.html
index 76df4ec..8f2fb18 100644
--- a/frontend/textbooks/algebra_9_ch4.html
+++ b/frontend/textbooks/algebra_9_ch4.html
@@ -1120,38 +1120,600 @@ function buildP15(){
}
function buildP16(){
- const root = document.getElementById('p16-body');
- root.innerHTML = `
-
- `;
+
+ /* INTERACTIVE 3 — найди ошибку в формуле */
+ html += `
+
+
Перед тобой — утверждение. Если оно верное, жми «Верно»; если есть ошибка — «Ошибка».
+
Задача: 1 / 6 · Очки: 0
+
+
+ Верно
+ Ошибка
+
+
+
`;
+
+ /* INTERACTIVE 4 — тренажёр сумм */
+ html += `
+
+
Применяй $S_n = \\dfrac{a_1 + a_n}{2} \\cdot n$ или $S_n = \\dfrac{2 a_1 + (n - 1) d}{2} \\cdot n$. Ответ — целое число.
+
Задача: 1 / 6 · Очки: 0
+
+
+ Ответ:
+
+ Проверить
+
+
+
`;
+
+ box.innerHTML = html + secNav('p15', 'p17') + readButton('p16');
+ renderMath(box);
+
+ /* ===== IV1 wiring ===== */
+ (function(){
+ const a1Sl = document.getElementById('p16-iv1-a1');
+ const dSl = document.getElementById('p16-iv1-d');
+ const nSl = document.getElementById('p16-iv1-n');
+ const av = document.getElementById('p16-iv1-av');
+ const dv = document.getElementById('p16-iv1-dv');
+ const nv = document.getElementById('p16-iv1-nv');
+ const termsEl = document.getElementById('p16-iv1-terms');
+ const pairsEl = document.getElementById('p16-iv1-pairs');
+ const formEl = document.getElementById('p16-iv1-formula');
+ const PAIR_COLORS = ['#ef4444','#0891b2','#16a34a','#a855f7','#f59e0b','#ec4899','#6366f1','#14b8a6','#f97316','#84cc16'];
+ let bumped = false;
+
+ function redraw(){
+ const a1 = +a1Sl.value, d = +dSl.value, n = +nSl.value;
+ av.textContent = a1; dv.textContent = d; nv.textContent = n;
+
+ // массив членов
+ const arr = [];
+ for (let i=0;i
''+v+' ');
+ termsEl.innerHTML = parts.join(' ');
+
+ // описание пар
+ const pairSum = a1 + an;
+ let pairsTxt = '';
+ if (halfPairs > 0){
+ const pairsList = [];
+ for (let p=0;p 3) pairsList.push('\\ldots');
+ pairsTxt = 'Пары: $' + pairsList.join('\\, +\\, ') + ' = ' + halfPairs + ' \\cdot ' + pairSum + ' = ' + (halfPairs*pairSum) + '$';
+ if (n % 2 === 1){
+ const mid = arr[(n-1)/2];
+ pairsTxt += ' + средний $' + mid + '$ ';
+ }
+ } else {
+ pairsTxt = 'n = 1 : $S_1 = a_1 = ' + a1 + '$';
+ }
+ pairsEl.innerHTML = pairsTxt;
+
+ // итог
+ const Sn = (a1 + an) * n / 2;
+ const dPart = (d>=0 ? '+ ' + d : '- ' + (-d));
+ formEl.innerHTML = '$a_{'+n+'} = '+a1+' '+dPart+' \\cdot ('+n+' - 1) = '+an+'$ '+
+ '$S_{'+n+'} = \\dfrac{'+a1+' + '+an+'}{2} \\cdot '+n+' = \\mathbf{'+Sn+'}$';
+
+ renderMath(pairsEl); renderMath(formEl);
+ if (!bumped){ bumped = true; bumpProgress('p16', 15); addXp(10,'p16-iv1'); }
+ }
+ a1Sl.addEventListener('input', redraw);
+ dSl.addEventListener('input', redraw);
+ nSl.addEventListener('input', redraw);
+ redraw();
+ })();
+
+ /* ===== IV2 wiring ===== */
+ (function(){
+ const out = document.getElementById('p16-iv2-out');
+ let bumped = false;
+ document.getElementById('p16-iv2-go').addEventListener('click', ()=>{
+ const a1 = +document.getElementById('p16-iv2-a1').value;
+ const d = +document.getElementById('p16-iv2-d').value;
+ const n = +document.getElementById('p16-iv2-n').value;
+ if (!Number.isInteger(n) || n < 1){ out.innerHTML = 'Номер $n$ должен быть натуральным.'; renderMath(out); return; }
+ const an = a1 + (n - 1) * d;
+ const Sn = (a1 + an) * n / 2;
+ const dPart = (d>=0 ? '+ ' + d : '- ' + (-d));
+ out.innerHTML =
+ '$a_{'+n+'} = '+a1+' '+dPart+' \\cdot ('+n+' - 1) = '+fmt(an)+'$ '+
+ '$S_{'+n+'} = \\dfrac{'+a1+' + '+fmt(an)+'}{2} \\cdot '+n+' = \\mathbf{'+fmt(Sn)+'}$';
+ renderMath(out);
+ if (!bumped){ bumped = true; bumpProgress('p16', 15); addXp(10,'p16-iv2'); }
+ });
+ })();
+
+ /* ===== IV3 wiring ===== */
+ (function(){
+ const items = [
+ { q:'Для прогрессии $1, 3, 5, 7, 9$: $S_5 = \\dfrac{1 + 9}{2} \\cdot 5 = 25$.', ans:true, hint:'$\\dfrac{10}{2} \\cdot 5 = 25$.' },
+ { q:'$S_n = a_1 + (n - 1) d$.', ans:false, hint:'Это формула $a_n$, а не суммы. У суммы есть множитель $n/2$.' },
+ { q:'$S_n = \\dfrac{a_1 + a_n}{2} \\cdot n$.', ans:true, hint:'Классическая формула суммы через крайние члены.' },
+ { q:'Для $1, 3, 5, \\ldots, 19$ (10 членов): $S_{10} = \\dfrac{1 + 19}{2} \\cdot 10 = 100$.', ans:true, hint:'$\\dfrac{20}{2} \\cdot 10 = 100$.' },
+ { q:'$S_n = n \\cdot a_1 + d$.', ans:false, hint:'Слагаемых с $d$ должно быть много, а здесь только одно. Это не сумма.' },
+ { q:'Сумма первых $50$ натуральных чисел: $\\dfrac{50 \\cdot 51}{2} = 1275$.', ans:true, hint:'$S = \\dfrac{1 + 50}{2} \\cdot 50 = 1275$.' }
+ ];
+ let i = 0, sc = 0;
+ const idxEl = document.getElementById('p16-iv3-idx');
+ const scEl = document.getElementById('p16-iv3-sc');
+ const qEl = document.getElementById('p16-iv3-q');
+ const fb = document.getElementById('p16-iv3-fb');
+ const yBtn = document.getElementById('p16-iv3-y');
+ const nBtn = document.getElementById('p16-iv3-n');
+ let bumped = false;
+ function render(){
+ idxEl.textContent = Math.min(i+1, items.length);
+ scEl.textContent = sc;
+ if (i >= items.length){
+ qEl.innerHTML = 'Готово! Результат: ' + sc + ' / ' + items.length;
+ yBtn.disabled = true; nBtn.disabled = true;
+ yBtn.style.opacity = .5; nBtn.style.opacity = .5;
+ if (!bumped){ bumped = true; bumpProgress('p16', 25); addXp(15,'p16-iv3'); }
+ return;
+ }
+ qEl.innerHTML = items[i].q;
+ fb.style.display = 'none';
+ renderMath(qEl);
+ }
+ function answer(v){
+ if (i >= items.length) return;
+ const it = items[i];
+ const ok = (v === it.ans);
+ if (ok) sc++;
+ feedback(fb, ok, (ok?'✓ Верно. ':'✗ Неверно. ') + it.hint);
+ i++;
+ setTimeout(render, 1100);
+ }
+ yBtn.addEventListener('click', ()=>answer(true));
+ nBtn.addEventListener('click', ()=>answer(false));
+ render();
+ })();
+
+ /* ===== IV4 wiring ===== */
+ (function(){
+ const items = [
+ { q:'Сумма первых 10 нечётных чисел: $1 + 3 + 5 + \\ldots + 19 = ?$', ans: 100 },
+ { q:'$a_1 = 5,\\ d = 2,\\ n = 6$. Найти $S_6$.', ans: 60 },
+ { q:'$a_1 = -3,\\ d = 4,\\ n = 10$. Найти $S_{10}$.', ans: 150 },
+ { q:'Сумма первых $100$ натуральных чисел.', ans: 5050 },
+ { q:'$a_1 = 2,\\ a_{20} = 40$. Найти $S_{20}$.', ans: 420 },
+ { q:'Прогрессия $7, 11, 15, \\ldots, 47$. Найти сумму всех её членов.', ans: 297 }
+ ];
+ let i = 0, sc = 0;
+ const idxEl = document.getElementById('p16-iv4-idx');
+ const scEl = document.getElementById('p16-iv4-sc');
+ const qEl = document.getElementById('p16-iv4-q');
+ const inp = document.getElementById('p16-iv4-ans');
+ const btn = document.getElementById('p16-iv4-go');
+ const fb = document.getElementById('p16-iv4-fb');
+ let bumped = false;
+ function render(){
+ idxEl.textContent = Math.min(i+1, items.length);
+ scEl.textContent = sc;
+ if (i >= items.length){
+ qEl.innerHTML = 'Готово! Результат: ' + sc + ' / ' + items.length;
+ inp.disabled = true; btn.disabled = true;
+ inp.style.opacity = .5; btn.style.opacity = .5;
+ if (!bumped){ bumped = true; bumpProgress('p16', 25); addXp(15,'p16-iv4'); }
+ return;
+ }
+ qEl.innerHTML = items[i].q;
+ inp.value = ''; fb.style.display = 'none';
+ renderMath(qEl);
+ }
+ btn.addEventListener('click', ()=>{
+ if (i >= items.length) return;
+ const v = +inp.value;
+ const it = items[i];
+ const ok = (v === it.ans);
+ if (ok) sc++;
+ feedback(fb, ok, ok ? '✓ Верно: $'+it.ans+'$' : '✗ Неверно. Правильный ответ: $'+it.ans+'$');
+ i++;
+ setTimeout(render, 1100);
+ });
+ inp.addEventListener('keydown', e=>{ if(e.key==='Enter'){ e.preventDefault(); btn.click(); } });
+ render();
+ })();
+
wireReadBtn('p16');
}
function buildP17(){
- const root = document.getElementById('p17-body');
- root.innerHTML = `
-
-