From 5ed21e4d2e69ccdc7f26a39ee7190038e8789e9a Mon Sep 17 00:00:00 2001 From: Maxim Dolgolyov Date: Fri, 29 May 2026 08:56:30 +0300 Subject: [PATCH] =?UTF-8?q?feat(alg9=20ch4=20wave2):=20=C2=A716=20=C2=AB?= =?UTF-8?q?=D0=A1=D1=83=D0=BC=D0=BC=D0=B0=20=D0=B0=D1=80=D0=B8=D1=84=D0=BC?= =?UTF-8?q?.=C2=BB=20+=20=C2=A717=20=C2=AB=D0=93=D0=B5=D0=BE=D0=BC.=20?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D0=B3=D1=80=D0=B5=D1=81=D1=81=D0=B8=D1=8F?= =?UTF-8?q?=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/textbooks/algebra_9_ch4.html | 612 ++++++++++++++++++++++++-- 1 file changed, 587 insertions(+), 25 deletions(-) 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 = ` -
-
- ${ICONS.theory} - В разработке - § 16 + const box = document.getElementById('p16-body'); + let html = ''; + + html += makeCard('theory', 'Формула суммы (через крайние члены)', '16.1', ` +

Сумма $n$ первых членов арифметической прогрессии равна полусумме первого и последнего члена, умноженной на число членов:

+

$$S_n = \\dfrac{a_1 + a_n}{2} \\cdot n.$$

+

Удобно применять, когда известны $a_1$, $a_n$ и $n$ (или их легко найти).

`); + + html += makeCard('rule', 'Формула суммы (через $a_1$ и $d$)', '16.2', ` +

Подставив $a_n = a_1 + (n - 1) d$ в первую формулу, получим:

+

$$S_n = \\dfrac{2 a_1 + (n - 1) d}{2} \\cdot n.$$

+

Эта формула удобна, когда заданы $a_1$, $d$ и $n$. Обе формулы эквивалентны и дают один и тот же результат.

`); + + html += makeCard('example', 'Идея вывода (Гаусс) и примеры', '16.3', ` +

Идея вывода. Пусть $S = 1 + 2 + 3 + \\ldots + 100$. Сложим пары крайних членов: + $(1 + 100) + (2 + 99) + \\ldots + (50 + 51)$. Каждая пара даёт $101$, пар $50$, поэтому + $S = 50 \\cdot 101 = \\mathbf{5050}$.

+

Аналогично для арифм. прогрессии: пар $n/2$, каждая равна $a_1 + a_n$, итого $S_n = \\dfrac{(a_1 + a_n) \\cdot n}{2}$.

+

а) Сумма первых $20$ членов прогрессии $3, 7, 11, \\ldots$: $a_1 = 3$, $d = 4$, $a_{20} = 3 + 19 \\cdot 4 = 79$. Тогда $S_{20} = \\dfrac{3 + 79}{2} \\cdot 20 = \\mathbf{820}.$

+

б) Сумма первых $100$ натуральных чисел: $S = \\dfrac{1 + 100}{2} \\cdot 100 = \\mathbf{5050}.$

`); + + /* INTERACTIVE 1 — конструктор суммы (Гаусс-пары) */ + html += `
+
ИНТЕРАКТИВ 1
Конструктор суммы (приём Гаусса)
+
Двигай ползунки $a_1$, $d$, $n$. Будут показаны все $n$ членов и подсвечены пары крайних — каждая пара даёт одно и то же число $a_1 + a_n$.
+
+ + + +
+
+
+
+
`; + + /* INTERACTIVE 2 — калькулятор суммы */ + html += `
+
ИНТЕРАКТИВ 2
Калькулятор суммы $S_n$
+
Введи $a_1$, $d$, $n$ — получишь $a_n$ и $S_n$ с подстановкой.
+
+
+ $a_1$ = + $d$ = + $n$ =
-
-

Содержание параграфа «Сумма арифм. прогрессии» будет добавлено в следующих обновлениях.

-

Раздел Phase 1.

-
-
` + secNav('p15', 'p17') + readButton('p16'); - renderMath(root); + +
+
+
`; + + /* INTERACTIVE 3 — найди ошибку в формуле */ + html += `
+
ИНТЕРАКТИВ 3
Найди ошибку в формуле
+
Перед тобой — утверждение. Если оно верное, жми «Верно»; если есть ошибка — «Ошибка».
+
Задача: 1 / 6 · Очки: 0
+
+
+ + +
+ +
`; + + /* INTERACTIVE 4 — тренажёр сумм */ + html += `
+
ИНТЕРАКТИВ 4
Тренажёр сумм
+
Применяй $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 = ` -
-
- ${ICONS.theory} - В разработке - § 17 + const box = document.getElementById('p17-body'); + let html = ''; + + html += makeCard('theory', 'Определение и формула $n$-го члена', '17.1', ` +

Геометрическая прогрессия — числовая последовательность, в которой каждый следующий член равен предыдущему, умноженному на одно и то же число $q \\ne 0$ — знаменатель прогрессии.

+

$$b_{n+1} = b_n \\cdot q,\\quad b_1 \\ne 0.$$

+

Формула $n$-го члена:

+

$$b_n = b_1 \\cdot q^{n - 1}.$$

+

Пример. $2, 6, 18, 54, \\ldots$ — геометрическая прогрессия с $b_1 = 2$, $q = 3$. Тогда $b_5 = 2 \\cdot 3^4 = 162$.

`); + + html += makeCard('rule', 'Характеристическое свойство', '17.2', ` +

В геометрической прогрессии с положительными членами (или с одним знаком) средний член — это среднее геометрическое своих соседей:

+

$$b_n^2 = b_{n-1} \\cdot b_{n+1}\\quad (n \\ge 2),$$

+

то есть $|b_n| = \\sqrt{b_{n-1} \\cdot b_{n+1}}$.

+

Пример. Между $2$ и $8$ в геом. прогрессии стоит $\\sqrt{2 \\cdot 8} = \\sqrt{16} = 4$.

`); + + html += makeCard('example', 'Применение формулы и поведение', '17.3', ` +

а) $b_1 = 3$, $q = 2$: $b_5 = 3 \\cdot 2^4 = 3 \\cdot 16 = \\mathbf{48}.$

+

б) $b_1 = 64$, $q = \\dfrac{1}{2}$: $b_5 = 64 \\cdot \\left(\\dfrac{1}{2}\\right)^4 = 64 \\cdot \\dfrac{1}{16} = \\mathbf{4}.$ Прогрессия убывает по модулю.

+

Поведение в зависимости от $q$:

+
    +
  • $|q| > 1$ — модули членов растут;
  • +
  • $|q| < 1$ — модули убывают к $0$;
  • +
  • $|q| = 1$ — все члены равны по модулю;
  • +
  • $q < 0$ — знаки членов чередуются.
  • +
`); + + /* INTERACTIVE 1 — конструктор геометрической */ + html += `
+
ИНТЕРАКТИВ 1
Конструктор геом. прогрессии
+
Двигай ползунки $b_1$ и $q$. Точки $(n; b_n)$ показывают, как ведёт себя прогрессия: рост / убывание / чередование знаков.
+
+ + +
+
+
+ +
+
+
+
`; + + /* INTERACTIVE 2 — калькулятор b_n и q */ + html += `
+
ИНТЕРАКТИВ 2
Калькулятор $b_n$ и $q$
+
Две формы. Слева — найди $b_n$ по $b_1$, $q$, $n$. Справа — найди $q$ по $b_1$, $b_n$, $n$.
+
+
+
Найти $b_n$
+
+ $b_1$ = + $q$ = + $n$ = +
+ +
-
-

Содержание параграфа «Геометрическая прогрессия» будет добавлено в следующих обновлениях.

-

Раздел Phase 1.

+
+
Найти $q$
+
+ $b_1$ = + $b_n$ = + $n$ = +
+ +
-
` + secNav('p16', 'p18') + readButton('p17'); - renderMath(root); +
+
`; + + /* INTERACTIVE 3 — геометрическая или нет */ + html += `
+
ИНТЕРАКТИВ 3
Является ли геометрической?
+
Даны первые члены последовательности. Если отношение $b_{n+1}/b_n$ постоянно — это геометрическая прогрессия.
+
Задача: 1 / 6 · Очки: 0
+
+
+ + +
+ +
`; + + /* INTERACTIVE 4 — тренажёр */ + html += `
+
ИНТЕРАКТИВ 4
Тренажёр геом. прогрессии
+
Применяй $b_n = b_1 \\cdot q^{n - 1}$ и характеристическое свойство $b_n^2 = b_{n-1} \\cdot b_{n+1}$. Ответ — целое число.
+
Задача: 1 / 6 · Очки: 0
+
+
+ Ответ: + + +
+ +
`; + + box.innerHTML = html + secNav('p16', 'p18') + readButton('p17'); + renderMath(box); + + /* ===== IV1 wiring ===== */ + (function(){ + const svg = document.getElementById('p17-iv1-svg'); + const b1Sl = document.getElementById('p17-iv1-b1'); + const qSl = document.getElementById('p17-iv1-q'); + const bv = document.getElementById('p17-iv1-bv'); + const qv = document.getElementById('p17-iv1-qv'); + const formula = document.getElementById('p17-iv1-formula'); + const out = document.getElementById('p17-iv1-out'); + const desc = document.getElementById('p17-iv1-desc'); + let bumped = false; + + function fmtQ(q){ + // 1/2, 1/4 — для красоты + if (Math.abs(q - 0.5) < 1e-9) return '\\dfrac{1}{2}'; + if (Math.abs(q + 0.5) < 1e-9) return '-\\dfrac{1}{2}'; + if (Math.abs(q - 0.25) < 1e-9) return '\\dfrac{1}{4}'; + if (Math.abs(q + 0.25) < 1e-9) return '-\\dfrac{1}{4}'; + if (Math.abs(q - 0.75) < 1e-9) return '\\dfrac{3}{4}'; + if (Math.abs(q + 0.75) < 1e-9) return '-\\dfrac{3}{4}'; + if (Math.abs(q - 1.5) < 1e-9) return '\\dfrac{3}{2}'; + if (Math.abs(q + 1.5) < 1e-9) return '-\\dfrac{3}{2}'; + return fmt(q); + } + + function redraw(){ + const b1 = +b1Sl.value; + const q = +qSl.value; + bv.textContent = b1; qv.textContent = q; + + const N = 10; + const pts = []; + for (let n=1;n<=N;n++) pts.push([n, b1 * Math.pow(q, n-1)]); + + // обрезаем чрезмерные значения для оси Y + const ABS_LIMIT = 200; + const ys = pts.map(p=>p[1]).filter(v=>Math.abs(v)<=ABS_LIMIT*5); + let ymin = Math.min(...ys, 0), ymax = Math.max(...ys, 0); + if (!isFinite(ymin) || !isFinite(ymax) || ymax === ymin){ ymin = -1; ymax = 1; } + const pad = Math.max(2, (ymax - ymin) * 0.15); + ymin = Math.floor(ymin - pad); + ymax = Math.ceil(ymax + pad); + + const ax = axes2D(460, 300, 34, 0, N+1, ymin, ymax); + let g = ax.content; + + // соединяющая ломаная (без хвостов вне зоны) + let path = ''; + let prevIn = false; + pts.forEach(p=>{ + const inZone = (p[1] >= ymin && p[1] <= ymax); + if (inZone){ + path += (prevIn ? ' L' : ' M') + ax.toX(p[0]).toFixed(1) + ',' + ax.toY(p[1]).toFixed(1); + } + prevIn = inZone; + }); + g += ''; + + // точки + pts.forEach(p=>{ + if (p[1] < ymin || p[1] > ymax) return; + const x = ax.toX(p[0]); const y = ax.toY(p[1]); + const color = (p[1] >= 0) ? '#0891b2' : '#ef4444'; + g += ''; + }); + svg.innerHTML = g; + + // формула + formula.innerHTML = '$b_n = ' + b1 + ' \\cdot (' + fmtQ(q) + ')^{n - 1}$'; + + // первые 6 членов + const first6 = pts.slice(0,6).map(p=>fmt(+p[1].toFixed(4))).join(',\\ '); + out.innerHTML = 'Первые 6 членов: $' + first6 + ',\\ \\ldots$'; + + // описание поведения + let txt = ''; + const aq = Math.abs(q); + if (q === 0){ txt = 'При $q = 0$ прогрессия не определена (со 2-го члена все нули).'; } + else if (aq > 1) txt = 'Модули растут (|q| > 1). '; + else if (aq < 1) txt = 'Модули убывают к 0 (|q| < 1). '; + else txt = 'Все члены по модулю равны $|b_1|$ (|q| = 1). '; + if (q < 0) txt += 'Знаки чередуются (q < 0).'; + else if (q > 0) txt += 'Все члены одного знака (q > 0).'; + desc.textContent = txt; + + renderMath(formula); renderMath(out); + if (!bumped){ bumped = true; bumpProgress('p17', 15); addXp(10,'p17-iv1'); } + } + b1Sl.addEventListener('input', redraw); + qSl.addEventListener('input', redraw); + redraw(); + })(); + + /* ===== IV2 wiring ===== */ + (function(){ + // Найти b_n + const outA = document.getElementById('p17-iv2a-out'); + let bumpedA = false; + document.getElementById('p17-iv2a-go').addEventListener('click', ()=>{ + const b1 = +document.getElementById('p17-iv2a-b1').value; + const q = +document.getElementById('p17-iv2a-q').value; + const n = +document.getElementById('p17-iv2a-n').value; + if (!Number.isInteger(n) || n < 1){ outA.innerHTML = 'Номер $n$ должен быть натуральным.'; renderMath(outA); return; } + if (q === 0){ outA.innerHTML = 'Знаменатель $q$ должен быть $\\ne 0$.'; renderMath(outA); return; } + const bn = b1 * Math.pow(q, n - 1); + outA.innerHTML = '$b_{'+n+'} = '+b1+' \\cdot ('+fmt(q)+')^{'+n+' - 1} = '+b1+' \\cdot ('+fmt(q)+')^{'+(n-1)+'} = \\mathbf{'+fmt(+bn.toFixed(6))+'}$'; + renderMath(outA); + if (!bumpedA){ bumpedA = true; bumpProgress('p17', 8); addXp(5,'p17-iv2a'); } + }); + // Найти q + const outB = document.getElementById('p17-iv2b-out'); + let bumpedB = false; + document.getElementById('p17-iv2b-go').addEventListener('click', ()=>{ + const b1 = +document.getElementById('p17-iv2b-b1').value; + const bn = +document.getElementById('p17-iv2b-bn').value; + const n = +document.getElementById('p17-iv2b-n').value; + if (!Number.isInteger(n) || n < 2){ outB.innerHTML = '$n$ должно быть целым и $\\ge 2$.'; renderMath(outB); return; } + if (b1 === 0){ outB.innerHTML = 'Должно быть $b_1 \\ne 0$.'; renderMath(outB); return; } + const ratio = bn / b1; + const k = n - 1; + // действительный корень (положительный) + let qPos; + if (ratio >= 0) qPos = Math.pow(ratio, 1/k); + else if (k % 2 === 1) qPos = -Math.pow(-ratio, 1/k); + else qPos = NaN; + if (!isFinite(qPos) || isNaN(qPos)){ + outB.innerHTML = '$\\dfrac{b_n}{b_1} = '+fmt(ratio)+' < 0$, а степень $n - 1 = '+k+'$ чётная — действительного $q$ нет.'; + renderMath(outB); return; + } + outB.innerHTML = '$q^{'+k+'} = \\dfrac{b_n}{b_1} = \\dfrac{'+bn+'}{'+b1+'} = '+fmt(ratio)+'$   $\\Rightarrow$   $q = \\sqrt['+k+']{'+fmt(ratio)+'} = \\mathbf{'+fmt(+qPos.toFixed(6))+'}$'; + renderMath(outB); + if (!bumpedB){ bumpedB = true; bumpProgress('p17', 7); addXp(5,'p17-iv2b'); } + }); + })(); + + /* ===== IV3 wiring ===== */ + (function(){ + const items = [ + { q:'$1,\\ 2,\\ 4,\\ 8,\\ \\ldots$', ans:true, hint:'Отношение $q = 2$ постоянно.' }, + { q:'$3,\\ 6,\\ 9,\\ 12,\\ \\ldots$', ans:false, hint:'Отношения $2, 1.5, \\tfrac{4}{3}$ — разные. Это арифметическая ($d = 3$).' }, + { q:'$5,\\ 5,\\ 5,\\ 5,\\ \\ldots$', ans:true, hint:'Это геом. прогрессия с $q = 1$ (и одновременно арифм. с $d = 0$).' }, + { q:'$81,\\ -27,\\ 9,\\ -3,\\ \\ldots$', ans:true, hint:'$q = -\\dfrac{1}{3}$ постоянна — знаки чередуются.' }, + { q:'$2,\\ 4,\\ 6,\\ 8,\\ \\ldots$', ans:false, hint:'Отношения $2, 1.5, \\tfrac{4}{3}$ — не равны. Это арифм. с $d = 2$.' }, + { q:'$1,\\ \\dfrac{1}{2},\\ \\dfrac{1}{4},\\ \\dfrac{1}{8},\\ \\ldots$', ans:true, hint:'$q = \\dfrac{1}{2}$ постоянна.' } + ]; + let i = 0, sc = 0; + const idxEl = document.getElementById('p17-iv3-idx'); + const scEl = document.getElementById('p17-iv3-sc'); + const qEl = document.getElementById('p17-iv3-q'); + const fb = document.getElementById('p17-iv3-fb'); + const yBtn = document.getElementById('p17-iv3-y'); + const nBtn = document.getElementById('p17-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('p17', 25); addXp(15,'p17-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:'$b_1 = 2,\\ q = 3$. Найти $b_4$.', ans: 54 }, + { q:'$b_1 = 64,\\ q = \\dfrac{1}{2}$. Найти $b_5$.', ans: 4 }, + { q:'$b_1 = 5,\\ b_3 = 45$. Найти $q$ (положительный).', ans: 3 }, + { q:'$b_2 = 6,\\ b_4 = 24$. Найти $q$ (положительный).', ans: 2 }, + { q:'Найти среднее геометрическое чисел $2$ и $8$ (положительное).', ans: 4 }, + { q:'$b_1 = 3,\\ q = -2$. Найти $b_4$.', ans: -24 } + ]; + let i = 0, sc = 0; + const idxEl = document.getElementById('p17-iv4-idx'); + const scEl = document.getElementById('p17-iv4-sc'); + const qEl = document.getElementById('p17-iv4-q'); + const inp = document.getElementById('p17-iv4-ans'); + const btn = document.getElementById('p17-iv4-go'); + const fb = document.getElementById('p17-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('p17', 25); addXp(15,'p17-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('p17'); }