diff --git a/frontend/textbooks/algebra_10_ch1.html b/frontend/textbooks/algebra_10_ch1.html
index b8ded8a..d52eb01 100644
--- a/frontend/textbooks/algebra_10_ch1.html
+++ b/frontend/textbooks/algebra_10_ch1.html
@@ -255,6 +255,7 @@ const ACH_LABELS = {
p5_done:'Графики sin x и cos x — мастер!',
p6_done:'Графики tg x и ctg x — знаешь!',
p7_done:'Обратные тригонометрические — освоены!',
+ p8_done:'Тригонометрические уравнения — решаешь!',
ch1_done:'Глава 1 — Тригонометрия пройдена!',
};
@@ -285,6 +286,7 @@ function bumpProgress(key, delta){
else if(key==='p5') achievement('p5_done');
else if(key==='p6') achievement('p6_done');
else if(key==='p7') achievement('p7_done');
+ else if(key==='p8') achievement('p8_done');
else if(key==='final1') achievement('ch1_done');
}
}
@@ -361,8 +363,7 @@ function buildParaSelector(){
const BUILT=new Set();
const BUILDERS = { p1:()=>buildP1(), p2:()=>buildP2(), p3:()=>buildP3(), p4:()=>buildP4(),
- p5:()=>buildP5(), p6:()=>buildP6(), p7:()=>buildP7(),
- p8:()=>buildStub('p8','§8 — Тригонометрические уравнения'),
+ p5:()=>buildP5(), p6:()=>buildP6(), p7:()=>buildP7(), p8:()=>buildP8(),
p9:()=>buildStub('p9','§9 — Формулы приведения'),
p10:()=>buildStub('p10','§10 — Синус, косинус, тангенс суммы и разности'),
p11:()=>buildStub('p11','§11 — Формулы двойного аргумента'),
@@ -445,6 +446,18 @@ const SIDEBARS = {
['Нечётные','$\\arcsin(-a) = -\\arcsin a$, $\\arctg$'],
['Не нечётные','$\\arccos(-a) = \\pi - \\arccos a$'],
]},
+ p8:{title:'Шпаргалка §8',rows:[
+ ['$\\sin x = a$','$x = (-1)^n\\arcsin a + \\pi n$'],
+ ['','при $|a| > 1$ — нет корней'],
+ ['$\\cos x = a$','$x = \\pm\\arccos a + 2\\pi n$'],
+ ['','при $|a| > 1$ — нет корней'],
+ ['$\\tg x = a$','$x = \\arctg a + \\pi n$'],
+ ['$\\ctg x = a$','$x = \\arcctg a + \\pi n$'],
+ ['$\\sin x = 0$','$x = \\pi n$'],
+ ['$\\sin x = 1$','$x = \\frac{\\pi}{2} + 2\\pi n$'],
+ ['$\\cos x = 0$','$x = \\frac{\\pi}{2} + \\pi n$'],
+ ['$\\cos x = 1$','$x = 2\\pi n$'],
+ ]},
};
const TIPS=[
@@ -455,6 +468,7 @@ const TIPS=[
{sec:'p5',html:'$\\cos x$ — это $\\sin x$, сдвинутый влево на $\\frac{\\pi}{2}$. Графики выглядят одинаково, но смещены: где у sin ноль — у cos максимум, и наоборот.'},
{sec:'p6',html:'tg x имеет вертикальные асимптоты в $\\frac{\\pi}{2} + \\pi n$ (там, где $\\cos x = 0$). ctg x — в $\\pi n$ (там, где $\\sin x = 0$). Период $\\pi$, а не $2\\pi$ — это короче, чем у sin/cos.'},
{sec:'p7',html:'Главные значения: $\\arcsin$ и $\\arctg$ — от $-\\frac{\\pi}{2}$ до $\\frac{\\pi}{2}$; $\\arccos$ и $\\arcctg$ — от $0$ до $\\pi$. Это всегда!'},
+ {sec:'p8',html:'Перед формулой проверь: $|a| > 1$ для sin и cos — корней НЕТ. Если $a = 0, \\pm 1$ — используй особые случаи, они проще общих формул.'},
];
function buildSidebar(id){
@@ -1929,6 +1943,240 @@ function buildP7(){
wireReadBtn('p7');
}
+/* ============================================================
+ § 8 — Тригонометрические уравнения
+ ============================================================ */
+function buildP8(){
+ const box = document.getElementById('p8-body');
+ const A = window.ALG10;
+ let html = '';
+
+ /* === SVG 1: геометрия решения sin x = a === */
+ let svgSin = '';
+ if(A){
+ const c = A.tri.canvas({id:'p8-sin', W:320, H:320, R:120});
+ const a = 0.5; /* sin x = 0.5 */
+ const x1 = Math.asin(a); /* π/6 */
+ const x2 = Math.PI - x1; /* 5π/6 */
+ const yL = c.cy - a * c.R;
+ let s = c.open
+ + c.axes()
+ + c.circle({width:2})
+ /* Горизонтальная линия y = a */
+ + ''
+ + 'y = a'
+ /* Две точки пересечения */
+ + c.radius(x1, {color:'#0d9488'})
+ + c.point(x1, {color:'#0d9488', label:'P_{x_1}', labelOffset:18, fontSize:11})
+ + c.radius(x2, {color:'#7c3aed'})
+ + c.point(x2, {color:'#7c3aed', label:'P_{x_2}', labelOffset:18, fontSize:11})
+ + 'x_1 = arcsin a, x_2 = π − arcsin a'
+ + c.close;
+ svgSin = s;
+ }
+
+ /* === SVG 2: геометрия cos x = a === */
+ let svgCos = '';
+ if(A){
+ const c = A.tri.canvas({id:'p8-cos', W:320, H:320, R:120});
+ const a = 0.5; /* cos x = 0.5 */
+ const x1 = Math.acos(a);
+ const x2 = -x1;
+ const xL = c.cx + a * c.R;
+ let s = c.open
+ + c.axes()
+ + c.circle({width:2})
+ /* Вертикальная линия x = a */
+ + ''
+ + 'x = a'
+ + c.radius(x1, {color:'#0d9488'})
+ + c.point(x1, {color:'#0d9488', label:'P_{x_1}', labelOffset:18, fontSize:11})
+ + c.radius(x2, {color:'#7c3aed'})
+ + c.point(x2, {color:'#7c3aed', label:'P_{x_2}', labelOffset:18, fontSize:11})
+ + 'x_{1,2} = ±arccos a'
+ + c.close;
+ svgCos = s;
+ }
+
+ /* === SVG 3: геометрия tg x = a === */
+ let svgTg = '';
+ if(A){
+ const c = A.tri.canvas({id:'p8-tg', W:340, H:320, R:120});
+ const a = 0.6; /* tg x = 0.6 */
+ const x1 = Math.atan(a); /* arctg a */
+ const x2 = x1 + Math.PI; /* arctg a + π */
+ const xAx = c.cx + c.R;
+ const yA = c.cy - a * c.R;
+ let s = c.open
+ + c.axes({xExt:c.R+40})
+ + c.circle({width:2})
+ + c.tgAxis()
+ /* Метка точки A_a на оси тангенсов */
+ + ''
+ + 'A_a = (1; a)'
+ /* Линия от точки A через начало координат */
+ + ''
+ + c.point(x1, {color:'#0d9488', label:'P_{x_1}', labelOffset:14, fontSize:10})
+ + c.point(x2, {color:'#7c3aed', label:'P_{x_2}', labelOffset:14, fontSize:10})
+ + 'x = arctg a + πn (одна формула!)'
+ + c.close;
+ svgTg = s;
+ }
+
+ html += makeCard('theory', 'Зачем геометрия?', '8.1', `
+
Уравнение $\\sin x = a$ — это «на каких углах ордината точки $P_x$ равна $a$?». Геометрия даёт нам наглядный способ найти все решения.
+ В простейшем случае берём горизонтальную линию $y = a$ и находим точки её пересечения с единичной окружностью. От них уже получаем все остальные корни через периодичность.
`);
+
+ html += makeCard('rule', 'Уравнение sin x = a', '8.2', `
+ Горизонтальная прямая $y = a$ пересекает единичную окружность в двух точках (если $|a| < 1$).
+ ${svgSin}
+ Эти точки симметричны относительно оси $y$, поэтому:
+
+ - $x_1 = \\arcsin a + 2\\pi n$
+ - $x_2 = \\pi - \\arcsin a + 2\\pi n$
+
+ Эти две серии объединяются одной формулой:
+ $x = (-1)^n \\arcsin a + \\pi n, \\quad n \\in \\mathbb{Z}$
+ При $|a| > 1$ — корней нет.
`);
+
+ html += makeCard('rule', 'Уравнение cos x = a', '8.3', `
+ Вертикальная прямая $x = a$ пересекает окружность в двух точках, симметричных относительно оси $x$.
+ ${svgCos}
+ Поэтому формула короче:
+ $x = \\pm \\arccos a + 2\\pi n, \\quad n \\in \\mathbb{Z}$
+ При $|a| > 1$ — корней нет.
`);
+
+ html += makeCard('rule', 'Уравнение tg x = a', '8.4', `
+ На оси тангенсов отмечаем точку $A_a = (1;\\,a)$. Прямая через $O$ и $A_a$ пересекает окружность в двух точках, лежащих на одной прямой (симметрично относительно $O$).
+ ${svgTg}
+ А период tg равен $\\pi$ — поэтому формула одна:
+ $x = \\arctg a + \\pi n, \\quad n \\in \\mathbb{Z}$
+ Для $\\ctg x = a$ аналогично: $x = \\arcctg a + \\pi n$.
+ Здесь $a$ любое — ограничений нет.
`);
+
+ html += makeCard('algo', 'Особые случаи (запомнить!)', '8.5', `
+ Когда $a = 0, \\pm 1$ — лучше использовать частные формулы вместо общих:
+
+ | Уравнение | Решение |
+ | $\\sin x = 0$ | $x = \\pi n$ |
+ | $\\sin x = 1$ | $x = \\dfrac{\\pi}{2} + 2\\pi n$ |
+ | $\\sin x = -1$ | $x = -\\dfrac{\\pi}{2} + 2\\pi n$ |
+ | $\\cos x = 0$ | $x = \\dfrac{\\pi}{2} + \\pi n$ |
+ | $\\cos x = 1$ | $x = 2\\pi n$ |
+ | $\\cos x = -1$ | $x = \\pi + 2\\pi n$ |
+ | $\\tg x = 0$ | $x = \\pi n$ |
+ | $\\ctg x = 0$ | $x = \\dfrac{\\pi}{2} + \\pi n$ |
+
`);
+
+ html += makeCard('algo', 'Метод замены переменной', '8.6', `
+ Если в уравнении встречается одна тригонометрическая функция — обозначь её переменной $t$ и реши получившееся алгебраическое уравнение.
+ Пример. $2\\sin^2 x - 3\\sin x + 1 = 0$.
+ Пусть $t = \\sin x$, тогда $2t^2 - 3t + 1 = 0$. Корни: $t_1 = 1, t_2 = 0{,}5$.
+ Возвращаемся: $\\sin x = 1$ или $\\sin x = 0{,}5$.
+
+ - $\\sin x = 1$ ⇒ $x = \\dfrac{\\pi}{2} + 2\\pi n$.
+ - $\\sin x = 0{,}5$ ⇒ $x = (-1)^k \\dfrac{\\pi}{6} + \\pi k$.
+
`);
+
+ html += makeCard('algo', 'Метод разложения на множители', '8.7', `
+ Если уравнение приводится к виду $f_1(x) \\cdot f_2(x) = 0$ — оно распадается на два простейших.
+ Пример. $\\sqrt{3}\\sin x = \\cos^2 x \\sin x$.
+ Переносим всё в одну сторону: $\\sin x (\\sqrt{3} - \\cos^2 x) = 0$.
+ Либо $\\sin x = 0$ (тогда $x = \\pi n$), либо $\\cos^2 x = \\sqrt{3} > 1$ — корней нет.
+ Итого: $x = \\pi n$.
`);
+
+ html += makeCard('algo', 'Однородные уравнения', '8.8', `
+ Однородное 1-й степени $a\\sin x + b\\cos x = 0$ — делим на $\\cos x$ (при условии $\\cos x \\ne 0$, что проверяем): $a\\tg x + b = 0$ ⇒ $\\tg x = -\\dfrac{b}{a}$.
+ Однородное 2-й степени $a\\sin^2 x + b\\sin x \\cos x + c\\cos^2 x = 0$ — делим на $\\cos^2 x$: $a\\tg^2 x + b\\tg x + c = 0$. Замена $t = \\tg x$.
`);
+
+ /* === ИНТЕРАКТИВ 1: Простейшие === */
+ html += ''
+ +''
+ +'
Для серий с πn — введи один корень в $[0;\\,2\\pi)$. Если корней несколько в этом промежутке — введи наименьший положительный.
'
+ +trainerHTML('p8-iv1', 10, 'корень в [0;2π)')
+ +'
';
+
+ /* === ИНТЕРАКТИВ 2: Сколько корней в промежутке === */
+ html += ''
+ +''
+ +'
Найди серии корней, потом отсчитай, сколько из них попало в указанный промежуток.
'
+ +trainerHTML('p8-iv2', 6, 'число')
+ +'
';
+
+ /* === ИНТЕРАКТИВ 3: Замена/разложение === */
+ html += ''
+ +''
+ +'
Сделай замену $t = \\sin x$ или $\\cos x$ и реши квадратное.
'
+ +trainerHTML('p8-iv3', 5, 'число корней в [0;2π)')
+ +'
';
+
+ /* === БОСС §8 — 6 этапов === */
+ html += 'Босс §8 — Тригонометрические уравнения
';
+ html += makeBoss('p8', {
+ color:'#dc2626',
+ title:'Босс §8 — Тригонометрические уравнения',
+ steps:[
+ { q:'Уравнение $\\sin x = 2$ имеет корни? «да» или «нет»', verify:(v)=>String(v).trim().toLowerCase().startsWith('н'), hint:'$|2| > 1$, корней нет.' },
+ { q:'Сколько корней у $\\sin x = 0{,}5$ на промежутке $[0;\\,2\\pi]$?', verify:(v)=>+v===2, hint:'$x_1 = \\pi/6$ и $x_2 = 5\\pi/6$ — обе в промежутке.' },
+ { q:'Реши $\\cos x = -1$. Введи корень в $[0;\\,2\\pi]$ как pi (если ответ $\\pi$).', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi'||s==='π';}, hint:'$\\cos\\pi = -1$.' },
+ { q:'Реши $2\\cos^2 x + 3\\cos x + 1 = 0$. Сколько корней в $[0;\\,2\\pi)$?', verify:(v)=>+v===3, hint:'$t = \\cos x$: $2t^2+3t+1=0$, $t = -1$ или $t = -1/2$. cos=−1: x=π. cos=−1/2: x=2π/3, 4π/3. Итого 3.' },
+ { q:'Решает ли значение $x = \\dfrac{\\pi}{2}$ уравнение $\\sin x \\cos x = 0$? «да» или «нет»', verify:(v)=>String(v).trim().toLowerCase().startsWith('д'), hint:'$\\cos(\\pi/2) = 0$, произведение = 0 ✓.' },
+ { q:'Реши $\\tg x = 1$. Введи наименьший положительный корень как pi/n.', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/4'||s==='π/4';}, hint:'$\\arctg 1 = \\pi/4$, серия $x = \\pi/4 + \\pi n$.' },
+ ]
+ });
+
+ html += secNav('p7', 'p9') + readButton('p8');
+ box.innerHTML = html; renderMath(box);
+
+ /* IV1: простейшие */
+ makeTrainer({
+ idPrefix:'p8-iv1',
+ parser:(v)=>v,
+ questions:[
+ { q:'$\\sin x = 0$. Наименьший корень в $[0;\\,2\\pi)$?', a:(v)=>+v===0, show:'$0$' },
+ { q:'$\\sin x = 1$. Корень в $[0;\\,2\\pi)$? (введи pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/2'||s==='π/2';}, show:'$\\pi/2$' },
+ { q:'$\\cos x = 1$. Наименьший корень в $[0;\\,2\\pi)$?', a:(v)=>+v===0, show:'$0$' },
+ { q:'$\\cos x = -1$. Корень в $[0;\\,2\\pi)$?', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi'||s==='π';}, show:'$\\pi$' },
+ { q:'$\\sin x = 0{,}5$. Наименьший корень в $[0;\\,2\\pi)$? (pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/6'||s==='π/6';}, show:'$\\pi/6$' },
+ { q:'$\\cos x = 0{,}5$. Наименьший корень в $[0;\\,2\\pi)$? (pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/3'||s==='π/3';}, show:'$\\pi/3$' },
+ { q:'$\\sin x = -1$. Корень в $[0;\\,2\\pi)$? (введи 3pi/2)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='3pi/2'||s==='3π/2';}, show:'$3\\pi/2$' },
+ { q:'$\\tg x = 0$. Наименьший корень в $[0;\\,2\\pi)$?', a:(v)=>+v===0, show:'$0$' },
+ { q:'$\\tg x = \\sqrt{3}$. Наименьший корень в $[0;\\,2\\pi)$? (pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/3'||s==='π/3';}, show:'$\\pi/3$' },
+ { q:'$\\sin x = 3$. Сколько корней? (число)', a:(v)=>+v===0, show:'$0$ (нет, $|3|>1$)' },
+ ],
+ onComplete:(s,n)=>{ if(s===n){addXp(22,'p8-iv1');bumpProgress('p8',32);} else if(s>=6){addXp(11,'p8-iv1');bumpProgress('p8',16);} }
+ });
+
+ /* IV2: сколько корней */
+ makeTrainer({
+ idPrefix:'p8-iv2',
+ questions:[
+ { q:'Сколько корней у $\\sin x = 0$ на $[0;\\,2\\pi]$?', a:3, show:'3 ($0, \\pi, 2\\pi$)' },
+ { q:'Сколько корней у $\\sin x = 0{,}5$ на $[0;\\,2\\pi]$?', a:2, show:'2 ($\\pi/6$ и $5\\pi/6$)' },
+ { q:'Сколько корней у $\\cos x = 0$ на $[0;\\,2\\pi]$?', a:2, show:'2 ($\\pi/2$ и $3\\pi/2$)' },
+ { q:'Сколько корней у $\\cos x = 1$ на $[0;\\,2\\pi]$?', a:2, show:'2 ($0$ и $2\\pi$)' },
+ { q:'Сколько корней у $\\tg x = 1$ на $[0;\\,\\pi]$?', a:1, show:'1 ($\\pi/4$)' },
+ { q:'Сколько корней у $\\sin x = \\dfrac{\\sqrt{2}}{2}$ на $[0;\\,4\\pi]$?', a:4, show:'4 (на каждом периоде по 2)' },
+ ],
+ onComplete:(s,n)=>{ if(s===n){addXp(18,'p8-iv2');bumpProgress('p8',26);} else if(s>=4){addXp(9,'p8-iv2');bumpProgress('p8',12);} }
+ });
+
+ /* IV3: замена */
+ makeTrainer({
+ idPrefix:'p8-iv3',
+ questions:[
+ { q:'$2\\sin^2 x - \\sin x = 0$. Сколько корней в $[0;\\,2\\pi)$?', a:4, show:'4 ($\\sin x(2\\sin x - 1) = 0$: sin x = 0 ⇒ 0, π; sin x = 1/2 ⇒ π/6, 5π/6)' },
+ { q:'$\\cos^2 x = 1$. Сколько корней в $[0;\\,2\\pi)$?', a:2, show:'2 (cos x = ±1 ⇒ x = 0, π)' },
+ { q:'$2\\sin^2 x - 3\\sin x + 1 = 0$. Сколько корней в $[0;\\,2\\pi)$?', a:3, show:'3 (sin = 1: π/2; sin = 1/2: π/6, 5π/6)' },
+ { q:'$\\sin^2 x + \\sin x = 0$. Сколько корней в $[0;\\,2\\pi)$?', a:3, show:'3 (sin x = 0: 0, π; sin x = -1: 3π/2)' },
+ { q:'$\\tg^2 x - 1 = 0$. Сколько корней в $[0;\\,2\\pi)$?', a:4, show:'4 (tg = ±1, серии π/4 + πn/2)' },
+ ],
+ onComplete:(s,n)=>{ if(s===n){addXp(18,'p8-iv3');bumpProgress('p8',26);} else if(s>=2){addXp(9,'p8-iv3');bumpProgress('p8',12);} }
+ });
+
+ wireReadBtn('p8');
+}
+