diff --git a/frontend/textbooks/geometry_9_ch1.html b/frontend/textbooks/geometry_9_ch1.html index 9d51763..1797a27 100644 --- a/frontend/textbooks/geometry_9_ch1.html +++ b/frontend/textbooks/geometry_9_ch1.html @@ -1175,8 +1175,640 @@ function buildP2(){ wireReadBtn('p2'); } -function buildP3(){ _stubBuilder('p3', '§3', 'Тригонометрические формулы', 'p2', 'p4'); } -function buildP4(){ _stubBuilder('p4', '§4', 'sin, cos, tg, ctg тупого угла', 'p3', 'p5'); } +/* ===== §3 Тригонометрические формулы ===== */ +function buildP3(){ + const box = document.getElementById('p3-body'); + let html = ''; + + html += makeCard('theory', 'Основное тригонометрическое тождество', '3.1', ` +

Возьмём прямоугольный треугольник с острым углом $\\alpha$, противолежащим катетом $a$, прилежащим катетом $b$ и гипотенузой $c$. По определению $\\sin \\alpha = a/c$, $\\cos \\alpha = b/c$.

+

По теореме Пифагора $a^2 + b^2 = c^2$. Поделим обе части на $c^2$:

+

$\\dfrac{a^2}{c^2} + \\dfrac{b^2}{c^2} = 1 \\;\\Rightarrow\\; \\left(\\dfrac{a}{c}\\right)^2 + \\left(\\dfrac{b}{c}\\right)^2 = 1.$

+

$\\sin^2 \\alpha + \\cos^2 \\alpha = 1$

+

Следствия (для острого $\\alpha$):

+ +
Зачем это нужно?
+ Если известно одно из значений ($\\sin \\alpha$ или $\\cos \\alpha$), второе мгновенно вычисляется без чертежа треугольника. Это первое настоящее тригонометрическое тождество — равенство, верное для любого допустимого угла. +
`); + + html += makeCard('rule', 'Связь tg и ctg с sin и cos', '3.2', ` +

Из определений $\\tan \\alpha = \\dfrac{a}{b}$ и $\\sin \\alpha / \\cos \\alpha = \\dfrac{a/c}{b/c} = \\dfrac{a}{b}$ получаем:

+ +

Поделим основное тождество $\\sin^2 \\alpha + \\cos^2 \\alpha = 1$ на $\\cos^2 \\alpha$:

+

$\\dfrac{\\sin^2 \\alpha}{\\cos^2 \\alpha} + 1 = \\dfrac{1}{\\cos^2 \\alpha} \\;\\Rightarrow\\; \\boxed{\\,1 + \\tan^2 \\alpha = \\dfrac{1}{\\cos^2 \\alpha}\\,}$

+

Аналогично, поделив на $\\sin^2 \\alpha$:

+

$\\boxed{\\,1 + \\cot^2 \\alpha = \\dfrac{1}{\\sin^2 \\alpha}\\,}$

`); + + html += makeCard('example', 'Откуда берутся 30°, 45°, 60°', '3.3', ` +

1) Треугольник 45°-45°-90° — равнобедренный прямоугольный. Возьмём оба катета равными $1$. Тогда гипотенуза $\\sqrt{1^2 + 1^2} = \\sqrt{2}$. Значит:

+

$\\sin 45^\\circ = \\cos 45^\\circ = \\dfrac{1}{\\sqrt{2}} = \\dfrac{\\sqrt{2}}{2},\\quad \\tan 45^\\circ = \\cot 45^\\circ = 1.$

+

2) Треугольник 30°-60°-90° — половина равностороннего. У равностороннего треугольника со стороной $2$ все углы $60^\\circ$. Высота делит его на два прямоугольных треугольника с катетами $1$ (половина основания) и $\\sqrt{2^2 - 1^2} = \\sqrt{3}$, гипотенузой $2$. Углы: $30^\\circ$ (при вершине) и $60^\\circ$ (у основания). Получаем:

+

$\\sin 30^\\circ = \\dfrac{1}{2},\\; \\cos 30^\\circ = \\dfrac{\\sqrt{3}}{2},\\; \\tan 30^\\circ = \\dfrac{1}{\\sqrt{3}}.$

+

$\\sin 60^\\circ = \\dfrac{\\sqrt{3}}{2},\\; \\cos 60^\\circ = \\dfrac{1}{2},\\; \\tan 60^\\circ = \\sqrt{3}.$

+
+ + + + + + + + + + + + + +
Угол$\\sin$$\\cos$$\\tan$$\\cot$
30°$\\tfrac{1}{2}$$\\tfrac{\\sqrt{3}}{2}$$\\tfrac{1}{\\sqrt{3}}$$\\sqrt{3}$
45°$\\tfrac{\\sqrt{2}}{2}$$\\tfrac{\\sqrt{2}}{2}$$1$$1$
60°$\\tfrac{\\sqrt{3}}{2}$$\\tfrac{1}{2}$$\\sqrt{3}$$\\tfrac{1}{\\sqrt{3}}$
+
`); + + /* IV1 — Три эталонных треугольника */ + html += `
+
ИНТЕРАКТИВ 1
Три эталонных треугольника
+
Слева — треугольник $30^\\circ\\text{-}60^\\circ\\text{-}90^\\circ$ (катеты $1$ и $\\sqrt{3}$, гипотенуза $2$). Справа — равнобедренный $45^\\circ\\text{-}45^\\circ\\text{-}90^\\circ$ (катеты $1$, гипотенуза $\\sqrt{2}$).
+
+ +
+
+ + + + + + + + + + + + + +
Угол$\\sin$$\\cos$$\\tan$$\\cot$
30°$\\tfrac{1}{2}$$\\tfrac{\\sqrt{3}}{2}$$\\tfrac{1}{\\sqrt{3}}$$\\sqrt{3}$
45°$\\tfrac{\\sqrt{2}}{2}$$\\tfrac{\\sqrt{2}}{2}$$1$$1$
60°$\\tfrac{\\sqrt{3}}{2}$$\\tfrac{1}{2}$$\\sqrt{3}$$\\tfrac{1}{\\sqrt{3}}$
+
+
`; + + /* IV2 — Калькулятор тождеств */ + html += `
+
ИНТЕРАКТИВ 2
Калькулятор тождеств
+
Введи $\\sin \\alpha$ (значение от $0{,}01$ до $0{,}99$). Получишь $\\cos \\alpha$, $\\tan \\alpha$, $\\cot \\alpha$ и сам угол $\\alpha$ в градусах.
+
+ $\\sin \\alpha$ = + + + +
+
+
+
`; + + /* IV3 — Quickfire «Какое значение?» */ + html += `
+
ИНТЕРАКТИВ 3
Какое значение?
+
Дано тригонометрическое выражение — выбери его точное значение из 4 вариантов.
+
Задача 1 / 8Очки: 0 / 8
+
+
+ + + + +
+
+
`; + + /* IV4 — Применение тождеств */ + html += `
+
ИНТЕРАКТИВ 4
Применение тождеств
+
Реши задачу и введи число (целое или десятичную дробь до 3 знаков).
+
Задача 1 / 6Очки: 0 / 6
+
+
+ ответ = + + + +
+
+
`; + + html += secNav('p2', 'p4'); + html += readButton('p3'); + + box.innerHTML = html; + renderMath(box); + + /* IV1 — рисуем три эталонных треугольника */ + (function(){ + const svg = document.getElementById('p3-iv1-svg'); + if(!svg) return; + let s = ''; + // Треугольник 30-60-90: катеты 1 и sqrt(3), гипотенуза 2. Используем масштаб 60 px = 1 ед. + // Левый: BC = sqrt(3) (горизонт., прилежащий 30°), AB = 1 (вертикальный, противолежащий 30°) + // Вершины: A слева внизу, B слева вверху (прямой угол), C справа внизу. + // Угол 30° при C, угол 60° при A. + (function(){ + const u = 60; + const Ax = 40, Ay = 180; + const A = {x: Ax, y: Ay}; + const B = {x: Ax, y: Ay - u}; // катет AB = 1 + const C = {x: Ax + Math.sqrt(3)*u, y: Ay}; // катет BC = sqrt(3) + const uBA = unitVec(B, A); + const uBC = unitVec(B, C); + const uCA = unitVec(C, A); + const uCB = unitVec(C, B); + const uAB = unitVec(A, B); + const uAC = unitVec(A, C); + s += ''; + s += ''; + s += ''; + s += ''; + // подписи углов + s += '30°'; + s += '60°'; + // вершины и подписи + ['A','B','C'].forEach((nm,i)=>{ const P=[A,B,C][i]; s+=''; }); + s += 'A'; + s += 'B'; + s += 'C'; + // длины сторон + s += '1'; + s += '√3'; + const midAC={x:(A.x+C.x)/2, y:(A.y+C.y)/2}; + const nAC={x:-(C.y-A.y), y:(C.x-A.x)}; + const nL=Math.sqrt(nAC.x*nAC.x+nAC.y*nAC.y)||1; + const labP={x: midAC.x + 16*nAC.x/nL, y: midAC.y + 16*nAC.y/nL}; + s += '2'; + // заголовок + s += '30\xb0-60\xb0-90\xb0'; + })(); + // Треугольник 45-45-90: оба катета 1, гипотенуза sqrt(2). Масштаб тот же. + (function(){ + const u = 90; // покрупнее + const Ax = 360, Ay = 180; + const A = {x: Ax, y: Ay}; + const B = {x: Ax, y: Ay - u}; + const C = {x: Ax + u, y: Ay}; + const uBA = unitVec(B, A); + const uBC = unitVec(B, C); + const uCA = unitVec(C, A); + const uCB = unitVec(C, B); + const uAB = unitVec(A, B); + const uAC = unitVec(A, C); + s += ''; + s += ''; + s += ''; + s += ''; + s += '45°'; + s += '45°'; + ['A','B','C'].forEach((nm,i)=>{ const P=[A,B,C][i]; s+=''; }); + s += 'A'; + s += 'B'; + s += 'C'; + s += '1'; + s += '1'; + const midAC={x:(A.x+C.x)/2, y:(A.y+C.y)/2}; + const nAC={x:-(C.y-A.y), y:(C.x-A.x)}; + const nL=Math.sqrt(nAC.x*nAC.x+nAC.y*nAC.y)||1; + const labP={x: midAC.x + 16*nAC.x/nL, y: midAC.y + 16*nAC.y/nL}; + s += '√2'; + s += '45\xb0-45\xb0-90\xb0'; + })(); + svg.innerHTML = s; + addXp(10,'p3-iv1'); bumpProgress('p3', 15); + })(); + + /* IV2 — Калькулятор тождеств */ + (function(){ + const sl = document.getElementById('p3-iv2-s'); + const inp = document.getElementById('p3-iv2-sn'); + const go = document.getElementById('p3-iv2-go'); + const out = document.getElementById('p3-iv2-out'); + const fb = document.getElementById('p3-iv2-fb'); + let solved = 0; + function sync(from){ + if(from==='range') inp.value = sl.value; + else { const v = Math.max(0.01, Math.min(0.99, parseFloat(inp.value)||0.5)); sl.value = v; inp.value = v; } + } + function calc(){ + const sn = parseFloat(sl.value); + if(isNaN(sn) || sn<=0 || sn>=1){ feedback(fb, false, '✗ $\\sin \\alpha$ должен быть в (0; 1).'); return; } + const cs = Math.sqrt(1 - sn*sn); + const tn = sn / cs; + const ct = cs / sn; + const aDeg = Math.asin(sn) * 180 / Math.PI; + out.innerHTML = '$\\sin \\alpha = '+sn.toFixed(3)+'$  ·  $\\cos \\alpha = \\sqrt{1 - \\sin^2 \\alpha} \\approx '+cs.toFixed(3)+'$
' + + '$\\tan \\alpha \\approx '+tn.toFixed(3)+'$  ·  $\\cot \\alpha \\approx '+ct.toFixed(3)+'$
' + + '$\\alpha \\approx '+aDeg.toFixed(2)+'^\\circ$'; + renderMath(out); + feedback(fb, true, '✓ Все значения вычислены через основное тождество.'); + solved++; + if(solved === 1){ addXp(10,'p3-iv2'); bumpProgress('p3', 15); } + } + sl.addEventListener('input', ()=>{ sync('range'); calc(); }); + inp.addEventListener('input', ()=>{ sync('input'); }); + go.addEventListener('click', calc); + calc(); + })(); + + /* IV3 — Какое значение? */ + (function(){ + const Q = [ + { expr:'$\\sin 30^\\circ$', ans:'half', why:'эталон: $\\sin 30^\\circ = 1/2$' }, + { expr:'$\\cos 60^\\circ$', ans:'half', why:'эталон: $\\cos 60^\\circ = 1/2$' }, + { expr:'$\\sin 45^\\circ$', ans:'s2', why:'эталон: $\\sin 45^\\circ = \\sqrt{2}/2$' }, + { expr:'$\\cos 45^\\circ$', ans:'s2', why:'эталон: $\\cos 45^\\circ = \\sqrt{2}/2$' }, + { expr:'$\\sin 60^\\circ$', ans:'s3', why:'эталон: $\\sin 60^\\circ = \\sqrt{3}/2$' }, + { expr:'$\\cos 30^\\circ$', ans:'s3', why:'эталон: $\\cos 30^\\circ = \\sqrt{3}/2$' }, + { expr:'$\\sin^2 30^\\circ + \\cos^2 30^\\circ$', ans:'one', why:'основное тождество: $\\sin^2 + \\cos^2 = 1$' }, + { expr:'$\\tan 45^\\circ$', ans:'one', why:'эталон: $\\tan 45^\\circ = 1$' }, + ]; + let i = 0, score = 0; + function show(){ + if(i >= Q.length){ + document.getElementById('p3-iv3-q').innerHTML = 'Готово! Результат: ' + score + ' / ' + Q.length; + if(score === Q.length){ addXp(15,'p3-iv3'); bumpProgress('p3', 25); } + else if(score >= Q.length - 2){ addXp(8,'p3-iv3'); bumpProgress('p3', 15); } + return; + } + document.getElementById('p3-iv3-i').textContent = (i+1); + document.getElementById('p3-iv3-s').textContent = score; + document.getElementById('p3-iv3-q').innerHTML = Q[i].expr; + renderMath(document.getElementById('p3-iv3-q')); + document.getElementById('p3-iv3-fb').style.display = 'none'; + } + function answer(a){ + if(i >= Q.length) return; + const fb = document.getElementById('p3-iv3-fb'); + if(a === Q[i].ans){ score++; feedback(fb, true, '✓ Верно! '+Q[i].why+'. Дальше ▶'); } + else feedback(fb, false, '✗ Нет. '+Q[i].why+'. Дальше ▶'); + document.getElementById('p3-iv3-s').textContent = score; + i++; + setTimeout(show, 1100); + } + ['half','s2','s3','one'].forEach(k=>{ + const b = document.getElementById('p3-iv3-'+k); if(b) b.addEventListener('click', ()=>answer(k)); + }); + show(); + })(); + + /* IV4 — Применение тождеств */ + (function(){ + const Q = [ + { q:'Если $\\sin \\alpha = 0{,}6$ и $\\alpha$ — острый, найди $\\cos \\alpha$.', ans:0.8, tol:0.02, hint:'$\\cos \\alpha = \\sqrt{1 - 0{,}36} = \\sqrt{0{,}64} = 0{,}8$' }, + { q:'$\\sin^2 70^\\circ + \\cos^2 70^\\circ = ?$', ans:1, tol:0.01, hint:'основное тождество' }, + { q:'Если $\\cos \\alpha = 0{,}5$ и $\\alpha$ — острый, найди $\\sin \\alpha$.', ans:0.866, tol:0.01, hint:'$\\sin \\alpha = \\sqrt{1 - 0{,}25} = \\sqrt{0{,}75} = \\sqrt{3}/2 \\approx 0{,}866$' }, + { q:'$\\tan 60^\\circ \\cdot \\cot 60^\\circ = ?$', ans:1, tol:0.01, hint:'$\\tan \\alpha \\cdot \\cot \\alpha = 1$' }, + { q:'Если $\\tan \\alpha = 1$, то $\\alpha = ?$ (в градусах).', ans:45, tol:0.5, hint:'$\\tan 45^\\circ = 1$' }, + { q:'$\\sin 30^\\circ + \\cos 60^\\circ = ?$', ans:1, tol:0.01, hint:'$\\tfrac{1}{2} + \\tfrac{1}{2} = 1$' }, + ]; + let i = 0, score = 0; + function show(){ + if(i >= Q.length){ + document.getElementById('p3-iv4-q').innerHTML = 'Готово! Результат: ' + score + ' / ' + Q.length; + if(score === Q.length){ addXp(15,'p3-iv4'); bumpProgress('p3', 25); } + else if(score >= 4){ addXp(8,'p3-iv4'); bumpProgress('p3', 15); } + return; + } + document.getElementById('p3-iv4-i').textContent = (i+1); + document.getElementById('p3-iv4-s').textContent = score; + document.getElementById('p3-iv4-q').innerHTML = Q[i].q; + document.getElementById('p3-iv4-ans').value = ''; + renderMath(document.getElementById('p3-iv4-q')); + document.getElementById('p3-iv4-fb').style.display = 'none'; + } + function go(){ + if(i >= Q.length) return; + const fb = document.getElementById('p3-iv4-fb'); + const ans = parseFloat(document.getElementById('p3-iv4-ans').value); + if(isNaN(ans)){ feedback(fb, false, '✗ Введи число.'); return; } + if(Math.abs(ans - Q[i].ans) <= Q[i].tol){ score++; feedback(fb, true, '✓ Верно! '+Q[i].hint+'. Дальше ▶'); } + else feedback(fb, false, '✗ Неверно. Ответ: '+Q[i].ans+' ('+Q[i].hint+'). Дальше ▶'); + document.getElementById('p3-iv4-s').textContent = score; + i++; + setTimeout(show, 1400); + } + document.getElementById('p3-iv4-go').addEventListener('click', go); + document.getElementById('p3-iv4-ans').addEventListener('keydown', e=>{ if(e.key==='Enter') go(); }); + document.getElementById('p3-iv4-start').addEventListener('click', ()=>{ i=0; score=0; show(); }); + show(); + })(); + + wireReadBtn('p3'); +} + +/* ===== §4 sin, cos, tg, ctg тупого угла ===== */ +function buildP4(){ + const box = document.getElementById('p4-body'); + let html = ''; + + html += makeCard('theory', 'Единичная окружность', '4.1', ` +

Введём координатную плоскость. Единичная окружность — окружность радиуса $1$ с центром в начале координат $O$.

+

Для острого угла $\\alpha$ отложим его от положительного направления оси $Ox$ против часовой стрелки. Точку пересечения подвижного луча с единичной окружностью обозначим $P$. Тогда:

+
    +
  • $\\cos \\alpha$ — это $x$-координата точки $P$
  • +
  • $\\sin \\alpha$ — это $y$-координата точки $P$
  • +
+

Это обобщение старых определений: для острых углов оно совпадает с привычным «отношение катета к гипотенузе» (можно построить прямоугольный треугольник с гипотенузой $OP = 1$). Но теперь определение работает для любого угла от $0^\\circ$ до $180^\\circ$ — даже когда привычного прямоугольного треугольника нет.

+
Почему именно так?
+ Если $OP = 1$, то $\\cos \\alpha = \\dfrac{\\text{прилежащий катет}}{\\text{гипотенуза}} = \\dfrac{x_P}{1} = x_P$. Аналогично для синуса. Единичная окружность позволяет «продолжить» функции на углы $> 90^\\circ$. +
`); + + html += makeCard('rule', 'Тупой угол: знаки и формулы приведения', '4.2', ` +

Для тупого угла $\\alpha$ (где $90^\\circ < \\alpha < 180^\\circ$) точка $P$ оказывается во второй четверти: выше оси $Ox$ и левее оси $Oy$. Значит:

+
    +
  • $\\sin \\alpha = y_P > 0$ — синус положителен
  • +
  • $\\cos \\alpha = x_P < 0$ — косинус отрицателен
  • +
  • $\\tan \\alpha = \\dfrac{\\sin \\alpha}{\\cos \\alpha} < 0$ — тангенс отрицателен
  • +
  • $\\cot \\alpha < 0$ — котангенс отрицателен
  • +
+

Формулы приведения (главные для этого параграфа):

+

$\\boxed{\\,\\sin(180^\\circ - \\alpha) = \\sin \\alpha,\\qquad \\cos(180^\\circ - \\alpha) = -\\cos \\alpha\\,}$

+

Здесь $\\alpha$ — острый угол, а $180^\\circ - \\alpha$ — соответствующий ему тупой. Идея проста: точки $P(\\alpha)$ и $P(180^\\circ - \\alpha)$ симметричны относительно оси $Oy$ — у них одинаковая $y$-координата (синус), но противоположные $x$-координаты (косинус).

`); + + html += makeCard('example', 'Эталонные тупые углы', '4.3', ` +

Считаем через формулы приведения, сводя всё к острым углам $30^\\circ$, $45^\\circ$, $60^\\circ$:

+
    +
  • $\\sin 120^\\circ = \\sin(180^\\circ - 60^\\circ) = \\sin 60^\\circ = \\dfrac{\\sqrt{3}}{2}$
  • +
  • $\\cos 120^\\circ = -\\cos 60^\\circ = -\\dfrac{1}{2}$
  • +
  • $\\sin 135^\\circ = \\sin 45^\\circ = \\dfrac{\\sqrt{2}}{2}$
  • +
  • $\\cos 135^\\circ = -\\cos 45^\\circ = -\\dfrac{\\sqrt{2}}{2}$
  • +
  • $\\sin 150^\\circ = \\sin 30^\\circ = \\dfrac{1}{2}$
  • +
  • $\\cos 150^\\circ = -\\cos 30^\\circ = -\\dfrac{\\sqrt{3}}{2}$
  • +
+

Граничные случаи:

+
    +
  • $\\sin 90^\\circ = 1$, $\\cos 90^\\circ = 0$ (точка $P = (0, 1)$)
  • +
  • $\\sin 180^\\circ = 0$, $\\cos 180^\\circ = -1$ (точка $P = (-1, 0)$)
  • +
  • $\\sin 0^\\circ = 0$, $\\cos 0^\\circ = 1$ (точка $P = (1, 0)$)
  • +
`); + + /* IV1 — Единичная окружность */ + html += `
+
ИНТЕРАКТИВ 1
Единичная окружность
+
Двигай ползунок угла $\\alpha$ от $0^\\circ$ до $180^\\circ$. Смотри, как точка $P$ движется по окружности и как меняются $\\sin \\alpha$ (по $y$) и $\\cos \\alpha$ (по $x$). При $\\alpha > 90^\\circ$ — тупой угол, $\\cos \\alpha < 0$.
+
+ +
+
+ +
+
+
+
`; + + /* IV2 — Формула приведения */ + html += `
+
ИНТЕРАКТИВ 2
Формула приведения
+
Выбери тупой угол $\\alpha$ — увидишь, как формула приведения сводит $\\sin \\alpha$ и $\\cos \\alpha$ к острому углу $180^\\circ - \\alpha$.
+
+ $\\alpha$ = + + +
+
+ +
`; + + /* IV3 — Знак значения */ + html += `
+
ИНТЕРАКТИВ 3
Знак значения
+
Каким будет знак данного тригонометрического значения: положительным, отрицательным или равным нулю?
+
Задача 1 / 8Очки: 0 / 8
+
+
+ + + +
+ +
`; + + /* IV4 — Тренажёр тупого угла */ + html += `
+
ИНТЕРАКТИВ 4
Тренажёр тупого угла
+
Реши задачу и введи число (целое или десятичная дробь до 3 знаков; не забудь знак для отрицательных значений).
+
Задача 1 / 6Очки: 0 / 6
+
+
+ ответ = + + + +
+ +
`; + + html += secNav('p3', 'p5'); + html += readButton('p4'); + + box.innerHTML = html; + renderMath(box); + + /* IV1 — Единичная окружность */ + (function(){ + const sl = document.getElementById('p4-iv1-a'); + const lab = document.getElementById('p4-iv1-aval'); + const svg = document.getElementById('p4-iv1-svg'); + const out = document.getElementById('p4-iv1-out'); + const tag = document.getElementById('p4-iv1-tag'); + const seen = new Set(); + const cx = 200, cy = 200, R = 150; + function draw(){ + const aDeg = +sl.value; + lab.textContent = aDeg; + const aRad = deg2rad(aDeg); + const Px = cx + R*Math.cos(aRad); + const Py = cy - R*Math.sin(aRad); // y инвертирован + let s = ''; + // Сетка + s += ''; + // Координатные оси + s += ''; + s += ''; + // Стрелки на осях + s += ''; + s += ''; + s += 'x'; + s += 'y'; + // Единичная окружность + s += ''; + // Отметки 1, -1 + s += ''; + s += '1'; + s += ''; + s += '−1'; + s += ''; + s += '1'; + // Проекции — пунктиром + s += ''; + s += ''; + // Радиус OP + s += ''; + // Дуга угла alpha + if(aDeg > 0){ + const uOx = {x:1, y:0}; + const uOP = {x: Math.cos(aRad), y: -Math.sin(aRad)}; + s += ''; + // Подпись α + const aHalf = aRad/2; + const tx = cx + 54*Math.cos(aHalf); + const ty = cy - 54*Math.sin(aHalf); + s += 'α'; + } + // Точка P + s += ''; + s += 'P'; + // Подписи проекций + s += 'cos α'; + s += 'sin α'; + // Подпись радиуса + s += 'r=1'; + svg.innerHTML = s; + const sn = Math.sin(aRad), cs = Math.cos(aRad); + const tn = (Math.abs(cs) < 1e-9) ? null : sn/cs; + out.innerHTML = '$\\sin '+aDeg+'^\\circ \\approx '+sn.toFixed(3)+'$  ·  $\\cos '+aDeg+'^\\circ \\approx '+cs.toFixed(3)+'$
' + + (tn===null ? '$\\tan '+aDeg+'^\\circ$ — не определён' : '$\\tan '+aDeg+'^\\circ \\approx '+tn.toFixed(3)+'$'); + renderMath(out); + if(aDeg > 90 && aDeg < 180){ + tag.innerHTML = '⚠ Тупой угол! $\\cos \\alpha < 0$.'; + renderMath(tag); + } else if(aDeg === 90){ + tag.innerHTML = 'Прямой угол.'; + } else if(aDeg === 180 || aDeg === 0){ + tag.innerHTML = 'Развёрнутый/нулевой угол.'; + } else { + tag.innerHTML = 'Острый угол. Обе функции положительны.'; + } + seen.add(aDeg); + if(seen.size >= 6 && !seen.has('done')){ addXp(10,'p4-iv1'); bumpProgress('p4', 15); seen.add('done'); } + } + sl.addEventListener('input', draw); + draw(); + })(); + + /* IV2 — Формула приведения */ + (function(){ + const sel = document.getElementById('p4-iv2-a'); + const go = document.getElementById('p4-iv2-go'); + const out = document.getElementById('p4-iv2-out'); + const fb = document.getElementById('p4-iv2-fb'); + let solved = 0; + function apply(){ + const aDeg = parseInt(sel.value, 10); + const beta = 180 - aDeg; + const r = deg2rad(aDeg); + const sn = Math.sin(r), cs = Math.cos(r); + out.innerHTML = 'Формула приведения для $\\alpha = '+aDeg+'^\\circ$:
' + + '$\\sin '+aDeg+'^\\circ = \\sin(180^\\circ - '+aDeg+'^\\circ) = \\sin '+beta+'^\\circ \\approx '+sn.toFixed(3)+'$
' + + '$\\cos '+aDeg+'^\\circ = -\\cos(180^\\circ - '+aDeg+'^\\circ) = -\\cos '+beta+'^\\circ \\approx '+cs.toFixed(3)+'$
' + + 'Заметь: синус сохранил знак, косинус — поменял.'; + renderMath(out); + feedback(fb, true, '✓ Сведено к острому углу '+beta+'°.'); + solved++; + if(solved === 1){ addXp(10,'p4-iv2'); bumpProgress('p4', 15); } + } + go.addEventListener('click', apply); + apply(); + })(); + + /* IV3 — Знак значения */ + (function(){ + const Q = [ + { expr:'$\\sin 120^\\circ$', ans:'pos', why:'тупой угол: $\\sin > 0$' }, + { expr:'$\\cos 120^\\circ$', ans:'neg', why:'тупой угол: $\\cos < 0$' }, + { expr:'$\\sin 90^\\circ$', ans:'pos', why:'$\\sin 90^\\circ = 1 > 0$' }, + { expr:'$\\cos 90^\\circ$', ans:'zero', why:'$\\cos 90^\\circ = 0$' }, + { expr:'$\\sin 180^\\circ$', ans:'zero', why:'$\\sin 180^\\circ = 0$' }, + { expr:'$\\cos 180^\\circ$', ans:'neg', why:'$\\cos 180^\\circ = -1 < 0$' }, + { expr:'$\\sin 60^\\circ$', ans:'pos', why:'острый угол: $\\sin > 0$' }, + { expr:'$\\cos 150^\\circ$', ans:'neg', why:'тупой угол: $\\cos < 0$' }, + ]; + let i = 0, score = 0; + function show(){ + if(i >= Q.length){ + document.getElementById('p4-iv3-q').innerHTML = 'Готово! Результат: ' + score + ' / ' + Q.length; + if(score === Q.length){ addXp(15,'p4-iv3'); bumpProgress('p4', 25); } + else if(score >= Q.length - 2){ addXp(8,'p4-iv3'); bumpProgress('p4', 15); } + return; + } + document.getElementById('p4-iv3-i').textContent = (i+1); + document.getElementById('p4-iv3-s').textContent = score; + document.getElementById('p4-iv3-q').innerHTML = Q[i].expr; + renderMath(document.getElementById('p4-iv3-q')); + document.getElementById('p4-iv3-fb').style.display = 'none'; + } + function answer(a){ + if(i >= Q.length) return; + const fb = document.getElementById('p4-iv3-fb'); + if(a === Q[i].ans){ score++; feedback(fb, true, '✓ Верно! '+Q[i].why+'. Дальше ▶'); } + else feedback(fb, false, '✗ Нет. '+Q[i].why+'. Дальше ▶'); + document.getElementById('p4-iv3-s').textContent = score; + i++; + setTimeout(show, 1100); + } + ['pos','neg','zero'].forEach(k=>{ + const b = document.getElementById('p4-iv3-'+k); if(b) b.addEventListener('click', ()=>answer(k)); + }); + show(); + })(); + + /* IV4 — Тренажёр тупого угла */ + (function(){ + const Q = [ + { q:'$\\sin 120^\\circ = ?$', ans:0.866, tol:0.01, hint:'$\\sin 120^\\circ = \\sin 60^\\circ = \\sqrt{3}/2 \\approx 0{,}866$' }, + { q:'$\\cos 120^\\circ = ?$', ans:-0.5, tol:0.02, hint:'$\\cos 120^\\circ = -\\cos 60^\\circ = -1/2$' }, + { q:'$\\sin 150^\\circ = ?$', ans:0.5, tol:0.02, hint:'$\\sin 150^\\circ = \\sin 30^\\circ = 1/2$' }, + { q:'$\\cos 150^\\circ = ?$', ans:-0.866, tol:0.01, hint:'$\\cos 150^\\circ = -\\cos 30^\\circ = -\\sqrt{3}/2$' }, + { q:'$\\cos 90^\\circ = ?$', ans:0, tol:0.01, hint:'$\\cos 90^\\circ = 0$' }, + { q:'$\\sin 180^\\circ + \\cos 180^\\circ = ?$', ans:-1, tol:0.02, hint:'$0 + (-1) = -1$' }, + ]; + let i = 0, score = 0; + function show(){ + if(i >= Q.length){ + document.getElementById('p4-iv4-q').innerHTML = 'Готово! Результат: ' + score + ' / ' + Q.length; + if(score === Q.length){ addXp(15,'p4-iv4'); bumpProgress('p4', 25); } + else if(score >= 4){ addXp(8,'p4-iv4'); bumpProgress('p4', 15); } + return; + } + document.getElementById('p4-iv4-i').textContent = (i+1); + document.getElementById('p4-iv4-s').textContent = score; + document.getElementById('p4-iv4-q').innerHTML = Q[i].q; + document.getElementById('p4-iv4-ans').value = ''; + renderMath(document.getElementById('p4-iv4-q')); + document.getElementById('p4-iv4-fb').style.display = 'none'; + } + function go(){ + if(i >= Q.length) return; + const fb = document.getElementById('p4-iv4-fb'); + const ans = parseFloat(document.getElementById('p4-iv4-ans').value); + if(isNaN(ans)){ feedback(fb, false, '✗ Введи число.'); return; } + if(Math.abs(ans - Q[i].ans) <= Q[i].tol){ score++; feedback(fb, true, '✓ Верно! '+Q[i].hint+'. Дальше ▶'); } + else feedback(fb, false, '✗ Неверно. Ответ: '+Q[i].ans+' ('+Q[i].hint+'). Дальше ▶'); + document.getElementById('p4-iv4-s').textContent = score; + i++; + setTimeout(show, 1400); + } + document.getElementById('p4-iv4-go').addEventListener('click', go); + document.getElementById('p4-iv4-ans').addEventListener('keydown', e=>{ if(e.key==='Enter') go(); }); + document.getElementById('p4-iv4-start').addEventListener('click', ()=>{ i=0; score=0; show(); }); + show(); + })(); + + wireReadBtn('p4'); +} function buildP5(){ _stubBuilder('p5', '§5', 'Формулы площади', 'p4', 'p6'); } function buildP6(){ _stubBuilder('p6', '§6', 'Среднее геометрическое', 'p5', 'final1'); }