From f3cff6ad03d536d31e0a7604375c6ef1f962efc4 Mon Sep 17 00:00:00 2001 From: Maxim Dolgolyov Date: Fri, 29 May 2026 10:58:52 +0300 Subject: [PATCH] =?UTF-8?q?feat(alg10=20W2):=20=C2=A75-=C2=A77=20=D0=B3?= =?UTF-8?q?=D0=BB=D0=B0=D0=B2=D1=8B=201=20(=D0=B3=D1=80=D0=B0=D1=84=D0=B8?= =?UTF-8?q?=D0=BA=D0=B8=20sin/cos/tg/ctg=20+=20=D0=BE=D0=B1=D1=80=D0=B0?= =?UTF-8?q?=D1=82=D0=BD=D1=8B=D0=B5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Реализованы 3 параграфа главы 1: §5 y = sin x и y = cos x. Свойства и графики: - Большой график sin x на [-2π;2π] с отметками экстремумов (640x240, ALG10.func.canvas + plot) - График cos x с тем же оформлением - Совмещённый график sin/cos с легендой и точкой пересечения π/4 - Полные таблицы свойств (D, E, период, чётность, нули, монотонность) - Алгоритм преобразований y = A·sin(ωx+φ) + b - Интерактив 1: 4 ползунка (A/ω/φ/b) → real-time перерисовка графика с базовым sin пунктиром для сравнения - Интерактив 2: 7 заданий на свойства - Босс §5: 5 этапов §6 y = tg x и y = ctg x. Свойства и графики: - График tg x с авто-обрывами у асимптот (±12 порог) + красные вертикальные асимптоты - График ctg x аналогично - Таблицы свойств с подсветкой ключевых отличий (период π!) - Интерактив 1: 6 заданий на свойства - Интерактив 2: сравнение значений по графику (< / = / >) с использованием монотонности (tg возр., ctg убыв.) - Босс §6: 5 этапов §7 Арксинус, арккосинус, арктангенс, арккотангенс: - 4 маленьких графика 280x240 (arcsin/arccos/arctg/arcctg) с правильными областями значений [-π/2;π/2] / [0;π] - Таблицы главных значений для sin/cos - Подсветка: arccos и arcctg НЕ нечётные - Связки: arcsin a + arccos a = π/2 - Интерактив 1: 8 заданий на главные значения - Интерактив 2: arcsin(sin α) — тонкая разница, 5 заданий - Босс §7: 5 этапов (включая тонкий вопрос про arcsin(sin(5π/6))) Обновлены ACH_LABELS (+p5/p6/p7_done), bumpProgress, SIDEBARS (шпаргалки), TIPS (подсказки для каждого §). Файл вырос с 96 KB до 141 KB (1321 → 1888 строк). --- frontend/textbooks/algebra_10_ch1.html | 597 ++++++++++++++++++++++++- 1 file changed, 594 insertions(+), 3 deletions(-) diff --git a/frontend/textbooks/algebra_10_ch1.html b/frontend/textbooks/algebra_10_ch1.html index c78f144..b8ded8a 100644 --- a/frontend/textbooks/algebra_10_ch1.html +++ b/frontend/textbooks/algebra_10_ch1.html @@ -252,6 +252,9 @@ const ACH_LABELS = { p2_done:'sin α и cos α — на ладони!', p3_done:'tg α и ctg α — понимаешь!', p4_done:'Тождества — твои!', + p5_done:'Графики sin x и cos x — мастер!', + p6_done:'Графики tg x и ctg x — знаешь!', + p7_done:'Обратные тригонометрические — освоены!', ch1_done:'Глава 1 — Тригонометрия пройдена!', }; @@ -279,6 +282,9 @@ function bumpProgress(key, delta){ else if(key==='p2') achievement('p2_done'); else if(key==='p3') achievement('p3_done'); else if(key==='p4') achievement('p4_done'); + else if(key==='p5') achievement('p5_done'); + else if(key==='p6') achievement('p6_done'); + else if(key==='p7') achievement('p7_done'); else if(key==='final1') achievement('ch1_done'); } } @@ -355,9 +361,7 @@ function buildParaSelector(){ const BUILT=new Set(); const BUILDERS = { p1:()=>buildP1(), p2:()=>buildP2(), p3:()=>buildP3(), p4:()=>buildP4(), - p5:()=>buildStub('p5','§5 — Графики функций sin x и cos x'), - p6:()=>buildStub('p6','§6 — Графики функций tg x и ctg x'), - p7:()=>buildStub('p7','§7 — Арксинус, арккосинус, арктангенс, арккотангенс'), + p5:()=>buildP5(), p6:()=>buildP6(), p7:()=>buildP7(), p8:()=>buildStub('p8','§8 — Тригонометрические уравнения'), p9:()=>buildStub('p9','§9 — Формулы приведения'), p10:()=>buildStub('p10','§10 — Синус, косинус, тангенс суммы и разности'), @@ -411,6 +415,36 @@ const SIDEBARS = { ['Связь','$\\tg\\alpha \\cdot \\ctg\\alpha = 1$'], ['Знать одно','найти все 4'], ]}, + p5:{title:'Шпаргалка §5',rows:[ + ['Период','$T = 2\\pi$'], + ['$D(\\sin)$','$\\mathbb{R}$'], + ['$E(\\sin)$','$[-1;\\,1]$'], + ['sin — нечётная','$\\sin(-x) = -\\sin x$'], + ['cos — чётная','$\\cos(-x) = \\cos x$'], + ['Нули sin','$x = \\pi n$'], + ['Нули cos','$x = \\frac{\\pi}{2} + \\pi n$'], + ['Связь','$\\cos x = \\sin(x + \\frac{\\pi}{2})$'], + ]}, + p6:{title:'Шпаргалка §6',rows:[ + ['Период tg / ctg','$T = \\pi$'], + ['$D(\\tg)$','$x \\ne \\frac{\\pi}{2} + \\pi n$'], + ['$D(\\ctg)$','$x \\ne \\pi n$'], + ['$E(\\tg) = E(\\ctg)$','$\\mathbb{R}$'], + ['Асимптоты tg','$x = \\frac{\\pi}{2} + \\pi n$'], + ['Асимптоты ctg','$x = \\pi n$'], + ['tg — нечётная','$\\tg(-x) = -\\tg x$'], + ['ctg — нечётная','$\\ctg(-x) = -\\ctg x$'], + ]}, + p7:{title:'Шпаргалка §7',rows:[ + ['$\\arcsin a$','$\\in [-\\frac{\\pi}{2};\\,\\frac{\\pi}{2}]$, $a \\in [-1;1]$'], + ['$\\arccos a$','$\\in [0;\\,\\pi]$, $a \\in [-1;1]$'], + ['$\\arctg a$','$\\in (-\\frac{\\pi}{2};\\,\\frac{\\pi}{2})$, $a \\in \\mathbb{R}$'], + ['$\\arcctg a$','$\\in (0;\\,\\pi)$, $a \\in \\mathbb{R}$'], + ['Связь','$\\arcsin a + \\arccos a = \\frac{\\pi}{2}$'], + ['','$\\arctg a + \\arcctg a = \\frac{\\pi}{2}$'], + ['Нечётные','$\\arcsin(-a) = -\\arcsin a$, $\\arctg$'], + ['Не нечётные','$\\arccos(-a) = \\pi - \\arccos a$'], + ]}, }; const TIPS=[ @@ -418,6 +452,9 @@ const TIPS=[ {sec:'p2',html:'Запомни: sin = ордината (y), cos = абсцисса (x). Точка $P_\\alpha$ — это и есть пара $(\\cos\\alpha;\\,\\sin\\alpha)$.'}, {sec:'p3',html:'Ось тангенсов — касательная к окружности при $x=1$. Продолжение радиуса $OP_\\alpha$ упирается в эту ось — там и сидит значение tg α.'}, {sec:'p4',html:'Алгоритм «знаю одну → найду все»: 1) основное тождество даёт пару sin/cos; 2) знак выбираем по четверти; 3) tg = sin/cos; 4) ctg = 1/tg.'}, + {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$. Это всегда!'}, ]; function buildSidebar(id){ @@ -1338,6 +1375,560 @@ function buildP4(){ wireReadBtn('p4'); } +/* ============================================================ + § 5 — Функции y = sin x и y = cos x. Свойства и графики + ============================================================ */ +function buildP5(){ + const box = document.getElementById('p5-body'); + const A = window.ALG10; + let html = ''; + + /* === SVG 1: график y = sin x на [-2π; 2π] === */ + let svgSin = ''; + if(A){ + const f = A.func.canvas({id:'p5-sin', W:640, H:240, xRange:[-2*Math.PI, 2*Math.PI], yRange:[-1.6, 1.6], bg:'#fff'}); + let s = f.open + + f.grid({xStep:Math.PI/2, yStep:0.5, color:'#f1f5f9'}) + + f.axes({color:'#475569', + xTicks:[ + {val:-2*Math.PI, label:'-2π'},{val:-3*Math.PI/2, label:'-3π/2'}, + {val:-Math.PI, label:'-π'},{val:-Math.PI/2, label:'-π/2'}, + {val:Math.PI/2, label:'π/2'},{val:Math.PI, label:'π'}, + {val:3*Math.PI/2, label:'3π/2'},{val:2*Math.PI, label:'2π'} + ], + yTicks:[{val:-1, label:'-1'}, {val:1, label:'1'}] + }) + /* Полупрозрачные горизонтальные полоски области значений */ + + '' + + '' + + f.plot(x => Math.sin(x), {color:'#0d9488', width:2.8}) + /* Точки максимума и минимума */ + + f.pointXY(Math.PI/2, 1, {color:'#dc2626', r:3.5, label:'max', dx:6, dy:-8, fontSize:10}) + + f.pointXY(-Math.PI/2, -1, {color:'#dc2626', r:3.5, label:'min', dx:6, dy:14, fontSize:10}) + + f.pointXY(3*Math.PI/2, -1, {color:'#dc2626', r:3.5}) + + f.pointXY(-3*Math.PI/2, 1, {color:'#dc2626', r:3.5}) + + f.close; + svgSin = s; + } + + /* === SVG 2: график y = cos x === */ + let svgCos = ''; + if(A){ + const f = A.func.canvas({id:'p5-cos', W:640, H:240, xRange:[-2*Math.PI, 2*Math.PI], yRange:[-1.6, 1.6], bg:'#fff'}); + let s = f.open + + f.grid({xStep:Math.PI/2, yStep:0.5, color:'#f1f5f9'}) + + f.axes({color:'#475569', + xTicks:[ + {val:-2*Math.PI, label:'-2π'},{val:-Math.PI, label:'-π'}, + {val:Math.PI, label:'π'},{val:2*Math.PI, label:'2π'} + ], + yTicks:[{val:-1, label:'-1'}, {val:1, label:'1'}] + }) + + '' + + '' + + f.plot(x => Math.cos(x), {color:'#0891b2', width:2.8}) + + f.pointXY(0, 1, {color:'#dc2626', r:3.5, label:'max', dx:6, dy:-8, fontSize:10}) + + f.pointXY(Math.PI, -1, {color:'#dc2626', r:3.5, label:'min', dx:6, dy:14, fontSize:10}) + + f.pointXY(-Math.PI, -1, {color:'#dc2626', r:3.5}) + + f.pointXY(2*Math.PI, 1, {color:'#dc2626', r:3.5}) + + f.pointXY(-2*Math.PI, 1, {color:'#dc2626', r:3.5}) + + f.close; + svgCos = s; + } + + /* === SVG 3: совмещённые sin и cos === */ + let svgBoth = ''; + if(A){ + const f = A.func.canvas({id:'p5-both', W:640, H:240, xRange:[-2*Math.PI, 2*Math.PI], yRange:[-1.6, 1.6], bg:'#fff'}); + let s = f.open + + f.grid({xStep:Math.PI/2, yStep:0.5, color:'#f1f5f9'}) + + f.axes({color:'#475569', + xTicks:[{val:-Math.PI, label:'-π'},{val:Math.PI, label:'π'},{val:2*Math.PI, label:'2π'}], + yTicks:[{val:-1, label:'-1'}, {val:1, label:'1'}] + }) + + f.plot(x => Math.sin(x), {color:'#0d9488', width:2.5}) + + f.plot(x => Math.cos(x), {color:'#0891b2', width:2.5, dash:'5 4'}) + /* Точка пересечения при x = π/4: sin = cos = √2/2 */ + + f.pointXY(Math.PI/4, Math.sqrt(2)/2, {color:'#dc2626', r:4, label:'π/4', dx:6, dy:-6, fontSize:10}) + /* Легенда */ + + '' + + '' + + 'sin x' + + '' + + 'cos x' + + f.close; + svgBoth = s; + } + + html += makeCard('rule', 'Свойства функции y = sin x', '5.1', ` +

На каждом числе $x$ значение $\\sin x$ — это ордината точки $P_x$ единичной окружности.

+ + + + + + + + + + +
СвойствоЗначение
Область определения$D(\\sin) = \\mathbb{R}$
Область значений$E(\\sin) = [-1;\\,1]$
Период$T = 2\\pi$
ЧётностьНечётная: $\\sin(-x) = -\\sin x$
Нули$x = \\pi n$, $n \\in \\mathbb{Z}$
Возрастаетна $\\left[-\\frac{\\pi}{2} + 2\\pi n;\\,\\frac{\\pi}{2} + 2\\pi n\\right]$
max$1$ при $x = \\frac{\\pi}{2} + 2\\pi n$
min$-1$ при $x = -\\frac{\\pi}{2} + 2\\pi n$
`); + + html += makeCard('rule', 'График y = sin x', '5.2', ` +

График — синусоида. Повторяется каждые $2\\pi$.

+
${svgSin}
+

Красные точки — экстремумы. Кривая всегда лежит между $y = -1$ и $y = 1$.

`); + + html += makeCard('rule', 'Свойства y = cos x', '5.3', ` +

Свойства аналогичны синусу, но с двумя ключевыми отличиями:

+ + + + + + + + + +
СвойствоЗначение
Область определения$D(\\cos) = \\mathbb{R}$
Область значений$E(\\cos) = [-1;\\,1]$
Период$T = 2\\pi$
ЧётностьЧётная: $\\cos(-x) = \\cos x$
Нули$x = \\frac{\\pi}{2} + \\pi n$
max$1$ при $x = 2\\pi n$
min$-1$ при $x = \\pi + 2\\pi n$
`); + + html += makeCard('rule', 'График y = cos x', '5.4', ` +

График $y = \\cos x$ — та же синусоида, но сдвинутая на $\\dfrac{\\pi}{2}$ влево.

+
${svgCos}
+

Это значит: $\\cos x = \\sin\\left(x + \\dfrac{\\pi}{2}\\right)$.

+
${svgBoth}
+

На совмещённом графике видно: где у $\\sin x$ нули — у $\\cos x$ экстремумы, и наоборот.

`); + + html += makeCard('algo', 'Преобразования графиков', '5.5', ` +

Общий вид: $y = A \\sin(\\omega x + \\varphi) + b$, где:

+
    +
  • $A$амплитуда: растяжение по оси $y$. $E = [-|A| + b;\\,|A| + b]$.
  • +
  • $\\omega$частота: новый период $T = \\dfrac{2\\pi}{|\\omega|}$.
  • +
  • $\\varphi$начальная фаза: сдвиг по оси $x$ на $-\\dfrac{\\varphi}{\\omega}$.
  • +
  • $b$ — сдвиг по оси $y$ (вверх или вниз).
  • +
+

Поэкспериментируй с параметрами на следующем интерактиве!

`); + + /* === ИНТЕРАКТИВ 1: Slider-эксперимент === */ + html += '
' + +'
ИНТЕРАКТИВ 1
y = A · sin(ωx + φ) + b — крути параметры
' + +'
Двигай ползунки и смотри, как меняется график синусоиды.
' + +'
1.0
' + +'
1.00
' + +'
0.00
' + +'
0.0
' + +'
' + +'
' + +'
'; + + /* === ИНТЕРАКТИВ 2: Найди свойство === */ + html += '
' + +'
ИНТЕРАКТИВ 2
Свойства функций sin x и cos x
' + +'
Ответы — числа (период в виде «2pi», «pi/2» и т.д.), названия («чётная»/«нечётная»), или градусы.
' + +trainerHTML('p5-iv2', 7, 'ответ') + +'
'; + + /* === БОСС === */ + html += '

Босс §5 — Графики sin и cos

'; + html += makeBoss('p5', { + color:'#0d9488', + title:'Босс §5 — Графики sin и cos', + steps:[ + { q:'Период функции $y = \\sin 2x$ — введи как pi/n или 2pi/n.', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi'||s==='π';}, hint:'$T = 2\\pi / \\omega = 2\\pi / 2 = \\pi$.' }, + { q:'$y = \\cos x$ — чётная или нечётная? Введи слово.', verify:(v)=>String(v).trim().toLowerCase().startsWith('чёт')||String(v).trim().toLowerCase().startsWith('чет'), hint:'$\\cos(-x) = \\cos x$.' }, + { q:'На каком из промежутков $[0;\\,2\\pi]$ функция $\\sin x$ возрастает? Введи правую границу как градусы: $\\pi/2$ → 90.', verify:(v)=>+v===90, hint:'$\\sin x$ возрастает на $[0; \\pi/2]$.' }, + { q:'Чему равно $\\sin\\left(\\dfrac{\\pi}{2} + 4\\pi\\right)$? (используй период)', verify:(v)=>+v===1, hint:'$4\\pi = 2 \\cdot 2\\pi$ — два полных периода. Эквивалентно $\\sin\\frac{\\pi}{2} = 1$.' }, + { q:'Сколько корней у уравнения $\\sin x = 0$ на $[0;\\,2\\pi]$?', verify:(v)=>+v===3, hint:'$x = 0, \\pi, 2\\pi$.' }, + ] + }); + + html += secNav('p4', 'p6') + readButton('p5'); + box.innerHTML = html; renderMath(box); + + /* IV1: slider experiment */ + (function(){ + const A_in = document.getElementById('p5-A'); + const w_in = document.getElementById('p5-w'); + const ph_in = document.getElementById('p5-ph'); + const b_in = document.getElementById('p5-b'); + const Av = document.getElementById('p5-Av'); + const wv = document.getElementById('p5-wv'); + const phv = document.getElementById('p5-phv'); + const bv = document.getElementById('p5-bv'); + const formula = document.getElementById('p5-formula'); + const svgHost = document.getElementById('p5-iv1-svg'); + function redraw(){ + if(!A) return; + const Av0 = parseFloat(A_in.value); + const wv0 = parseFloat(w_in.value); + const phv0 = parseFloat(ph_in.value); + const bv0 = parseFloat(b_in.value); + Av.textContent = Av0.toFixed(1); + wv.textContent = wv0.toFixed(2); + phv.textContent = phv0.toFixed(2); + bv.textContent = bv0.toFixed(1); + formula.textContent = 'y = ' + Av0.toFixed(1) + ' · sin(' + wv0.toFixed(2) + 'x + ' + phv0.toFixed(2) + ') + ' + bv0.toFixed(1); + const f = A.func.canvas({id:'p5-iv1-c', W:640, H:240, xRange:[-2*Math.PI, 2*Math.PI], yRange:[-4.5, 4.5], bg:'#fff'}); + let svg = f.open + + f.grid({xStep:Math.PI/2, yStep:1, color:'#f1f5f9'}) + + f.axes({color:'#475569', + xTicks:[{val:-Math.PI, label:'-π'},{val:Math.PI, label:'π'},{val:2*Math.PI, label:'2π'}], + yTicks:[{val:-3, label:'-3'},{val:-1, label:'-1'},{val:1, label:'1'},{val:3, label:'3'}] + }) + /* Базовый sin x пунктиром */ + + f.plot(x => Math.sin(x), {color:'#cbd5e1', width:1.5, dash:'4 3'}) + /* Преобразованный график */ + + f.plot(x => Av0 * Math.sin(wv0 * x + phv0) + bv0, {color:'#0d9488', width:2.8}) + + f.close; + svgHost.innerHTML = svg; + } + [A_in, w_in, ph_in, b_in].forEach(el => el.addEventListener('input', redraw)); + redraw(); + })(); + + /* IV2: properties */ + makeTrainer({ + idPrefix:'p5-iv2', + parser:(v)=>v, + questions:[ + { q:'Чему равен период функции $y = \\sin x$? (введи как 2pi)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='2pi'||s==='2π';}, show:'$2\\pi$' }, + { q:'Период функции $y = \\cos 3x$? (введи как 2pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='2pi/3'||s==='2π/3';}, show:'$2\\pi/3$' }, + { q:'$y = \\sin x$ — чётная или нечётная? Введи слово.', a:(v)=>String(v).trim().toLowerCase().startsWith('нечёт')||String(v).trim().toLowerCase().startsWith('нечет'), show:'нечётная' }, + { q:'$y = \\cos x$ — чётная или нечётная? Введи слово.', a:(v)=>String(v).trim().toLowerCase().startsWith('чёт')||String(v).trim().toLowerCase().startsWith('чет'), show:'чётная' }, + { q:'Сколько нулей у $\\sin x$ на $[0;\\,2\\pi]$?', a:(v)=>+v===3, show:'3 (это $0, \\pi, 2\\pi$)' }, + { q:'Сколько нулей у $\\cos x$ на $[0;\\,2\\pi]$?', a:(v)=>+v===2, show:'2 (это $\\pi/2, 3\\pi/2$)' }, + { q:'Наибольшее значение $y = 3\\sin x + 1$? ', a:(v)=>+v===4, show:'4 (при sin = 1)' }, + ], + onComplete:(s,n)=>{ if(s===n){addXp(20,'p5-iv2');bumpProgress('p5',35);} else if(s>=4){addXp(10,'p5-iv2');bumpProgress('p5',16);} } + }); + + wireReadBtn('p5'); +} + +/* ============================================================ + § 6 — Функции y = tg x и y = ctg x + ============================================================ */ +function buildP6(){ + const box = document.getElementById('p6-body'); + const A = window.ALG10; + let html = ''; + + /* === SVG 1: график y = tg x === */ + let svgTg = ''; + if(A){ + const f = A.func.canvas({id:'p6-tg', W:640, H:280, xRange:[-2*Math.PI, 2*Math.PI], yRange:[-5, 5], bg:'#fff'}); + let s = f.open + + f.grid({xStep:Math.PI/2, yStep:1, color:'#f1f5f9'}) + /* Асимптоты */ + + f.asymptoteV(-3*Math.PI/2, {color:'#dc2626'}) + + f.asymptoteV(-Math.PI/2, {color:'#dc2626'}) + + f.asymptoteV(Math.PI/2, {color:'#dc2626'}) + + f.asymptoteV(3*Math.PI/2, {color:'#dc2626'}) + + f.axes({color:'#475569', + xTicks:[ + {val:-3*Math.PI/2, label:'-3π/2'}, + {val:-Math.PI, label:'-π'}, + {val:-Math.PI/2, label:'-π/2'}, + {val:Math.PI/2, label:'π/2'}, + {val:Math.PI, label:'π'}, + {val:3*Math.PI/2, label:'3π/2'} + ], + yTicks:[{val:-3, label:'-3'},{val:-1, label:'-1'},{val:1, label:'1'},{val:3, label:'3'}] + }) + /* Tg x с авто-разрывами */ + + f.plot(x => { + /* Избегаем точек слишком близко к асимптотам */ + const t = Math.tan(x); + if (Math.abs(t) > 12) return NaN; + return t; + }, {color:'#16a34a', width:2.8}) + + f.close; + svgTg = s; + } + + /* === SVG 2: график y = ctg x === */ + let svgCtg = ''; + if(A){ + const f = A.func.canvas({id:'p6-ctg', W:640, H:280, xRange:[-2*Math.PI, 2*Math.PI], yRange:[-5, 5], bg:'#fff'}); + let s = f.open + + f.grid({xStep:Math.PI/2, yStep:1, color:'#f1f5f9'}) + + f.asymptoteV(-2*Math.PI, {color:'#dc2626'}) + + f.asymptoteV(-Math.PI, {color:'#dc2626'}) + + f.asymptoteV(0, {color:'#dc2626'}) + + f.asymptoteV(Math.PI, {color:'#dc2626'}) + + f.asymptoteV(2*Math.PI, {color:'#dc2626'}) + + f.axes({color:'#475569', + xTicks:[ + {val:-3*Math.PI/2, label:'-3π/2'}, + {val:-Math.PI/2, label:'-π/2'}, + {val:Math.PI/2, label:'π/2'}, + {val:3*Math.PI/2, label:'3π/2'} + ], + yTicks:[{val:-3, label:'-3'},{val:-1, label:'-1'},{val:1, label:'1'},{val:3, label:'3'}] + }) + + f.plot(x => { + const c = 1 / Math.tan(x); + if (Math.abs(c) > 12) return NaN; + return c; + }, {color:'#7c3aed', width:2.8}) + + f.close; + svgCtg = s; + } + + html += makeCard('rule', 'Свойства y = tg x', '6.1', ` + + + + + + + + + +
СвойствоЗначение
$D(\\tg)$$x \\ne \\dfrac{\\pi}{2} + \\pi n$
$E(\\tg)$$\\mathbb{R}$ — все действительные числа
Период$T = \\pi$ (вдвое короче, чем у sin/cos!)
ЧётностьНечётная: $\\tg(-x) = -\\tg x$
Нули$x = \\pi n$
Асимптоты$x = \\dfrac{\\pi}{2} + \\pi n$ (вертикальные)
МонотонностьВозрастает на $\\left(-\\dfrac{\\pi}{2} + \\pi n;\\,\\dfrac{\\pi}{2} + \\pi n\\right)$
`); + + html += makeCard('rule', 'График y = tg x', '6.2', ` +

Тангенс не похож на синусоиду — это «ветви», разорванные вертикальными асимптотами.

+
${svgTg}
+

Красные пунктирные линии — асимптоты. На каждом промежутке между ними функция возрастает от $-\\infty$ до $+\\infty$.

`); + + html += makeCard('rule', 'Свойства y = ctg x', '6.3', ` + + + + + + + + + +
СвойствоЗначение
$D(\\ctg)$$x \\ne \\pi n$
$E(\\ctg)$$\\mathbb{R}$
Период$T = \\pi$
ЧётностьНечётная
Нули$x = \\dfrac{\\pi}{2} + \\pi n$
Асимптоты$x = \\pi n$
МонотонностьУбывает на $(\\pi n;\\,\\pi + \\pi n)$
`); + + html += makeCard('rule', 'График y = ctg x', '6.4', ` +

Котангенс — «зеркало» тангенса: те же ветви, но убывающие, и сдвинуты на $\\frac{\\pi}{2}$.

+
${svgCtg}
+

Связь: $\\ctg x = \\tg\\left(\\dfrac{\\pi}{2} - x\\right)$.

`); + + /* === ИНТЕРАКТИВ === */ + html += '
' + +'
ИНТЕРАКТИВ 1
Свойства tg x и ctg x
' + +'
Период обоих $= \\pi$. Асимптоты — там, где знаменатель = 0.
' + +trainerHTML('p6-iv1', 6, 'ответ') + +'
'; + + html += '
' + +'
ИНТЕРАКТИВ 2
Сравни значения по графику
' + +'
Используй монотонность: $\\tg$ возрастает, $\\ctg$ убывает на главном промежутке.
' + +'
Задача 1 / 5Очки: 0 / 5
' + +'
' + +'
' + +'
'; + + /* === БОСС === */ + html += '

Босс §6 — Графики tg и ctg

'; + html += makeBoss('p6', { + color:'#16a34a', + title:'Босс §6 — Графики tg и ctg', + steps:[ + { q:'Период функции $y = \\tg x$ — введи как pi/n или просто pi.', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi'||s==='π';}, hint:'$T = \\pi$.' }, + { q:'Период функции $y = \\tg 2x$? (введи pi/n)', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/2'||s==='π/2';}, hint:'$T = \\pi / 2$.' }, + { q:'Где у $\\tg x$ вертикальные асимптоты? Введи общую формулу в виде «pi/2+pi*n» (без пробелов).', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/2+pi*n'||s==='pi/2+pin'||s==='π/2+πn'||s==='π/2+π*n';}, hint:'Там, где $\\cos x = 0$.' }, + { q:'$\\tg x$ — возрастает или убывает на главном промежутке? Введи слово.', verify:(v)=>String(v).trim().toLowerCase().startsWith('возр'), hint:'От $-\\infty$ до $+\\infty$.' }, + { q:'$\\ctg x$ — возрастает или убывает? Введи слово.', verify:(v)=>String(v).trim().toLowerCase().startsWith('убыв'), hint:'От $+\\infty$ до $-\\infty$.' }, + ] + }); + + html += secNav('p5', 'p7') + readButton('p6'); + box.innerHTML = html; renderMath(box); + + /* IV1 */ + makeTrainer({ + idPrefix:'p6-iv1', + parser:(v)=>v, + questions:[ + { q:'Период $y = \\tg x$? (введи pi)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi'||s==='π';}, show:'$\\pi$' }, + { q:'Период $y = \\ctg 3x$? (введи pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/3'||s==='π/3';}, show:'$\\pi/3$' }, + { q:'$\\tg x$ — чётная или нечётная? Введи слово.', a:(v)=>String(v).trim().toLowerCase().startsWith('нечёт')||String(v).trim().toLowerCase().startsWith('нечет'), show:'нечётная' }, + { q:'Сколько нулей у $\\tg x$ на $[0;\\,2\\pi]$?', a:(v)=>+v===3, show:'3 (0, π, 2π)' }, + { q:'Сколько вертикальных асимптот у $\\tg x$ на $(0;\\,2\\pi)$?', a:(v)=>+v===2, show:'2 (π/2 и 3π/2)' }, + { q:'$\\tg 0 = ?$', a:(v)=>+v===0, show:'0' }, + ], + onComplete:(s,n)=>{ if(s===n){addXp(15,'p6-iv1');bumpProgress('p6',30);} else if(s>=4){addXp(8,'p6-iv1');bumpProgress('p6',14);} } + }); + + /* IV2: compare */ + (function(){ + const Q=[ + { e:'Сравни $\\tg 30°$ и $\\tg 45°$', ans:'lt' }, + { e:'Сравни $\\tg 60°$ и $\\tg 80°$', ans:'lt' }, + { e:'Сравни $\\ctg 30°$ и $\\ctg 60°$', ans:'gt' }, + { e:'Сравни $\\tg(-30°)$ и $\\tg 30°$', ans:'lt' }, + { e:'Сравни $\\tg 45°$ и $\\ctg 45°$', ans:'eq' }, + ]; + let i=0,score=0; + function show(){ + if(i>=Q.length){ document.getElementById('p6-iv2-q').innerHTML='Готово! '+score+' / '+Q.length; if(score===Q.length){addXp(15,'p6-iv2');bumpProgress('p6',25);} else if(score>=3){addXp(8,'p6-iv2');bumpProgress('p6',12);} return; } + document.getElementById('p6-iv2-i').textContent=(i+1); + document.getElementById('p6-iv2-s').textContent=score; + document.getElementById('p6-iv2-q').innerHTML=Q[i].e; + renderMath(document.getElementById('p6-iv2-q')); + document.getElementById('p6-iv2-fb').style.display='none'; + } + function ans(a){ + if(i>=Q.length) return; + const fb=document.getElementById('p6-iv2-fb'); + if(a===Q[i].ans){ score++; feedback(fb,true,'✓ Верно!'); } + else{ const lab={lt:'<',eq:'=',gt:'>'}; feedback(fb,false,'✗ Правильно: '+lab[Q[i].ans]+''); } + document.getElementById('p6-iv2-s').textContent=score; + i++; setTimeout(show,1200); + } + document.getElementById('p6-iv2-lt').addEventListener('click',()=>ans('lt')); + document.getElementById('p6-iv2-eq').addEventListener('click',()=>ans('eq')); + document.getElementById('p6-iv2-gt').addEventListener('click',()=>ans('gt')); + show(); + })(); + + wireReadBtn('p6'); +} + +/* ============================================================ + § 7 — Арксинус, арккосинус, арктангенс, арккотангенс + ============================================================ */ +function buildP7(){ + const box = document.getElementById('p7-body'); + const A = window.ALG10; + let html = ''; + + /* === SVG: 4 графика обратных функций === */ + function plotInverse(id, fn, xRange, yRange, color, title){ + if(!A) return ''; + const f = A.func.canvas({id, W:280, H:240, xRange, yRange, bg:'#fff'}); + let s = f.open + + f.grid({xStep:1, yStep:0.5, color:'#f1f5f9'}) + + f.axes({color:'#475569', + xTicks:[{val:-1, label:'-1'},{val:1, label:'1'}], + yTicks:[ + {val:-Math.PI/2, label:'-π/2'}, + {val:0, label:'0'}, + {val:Math.PI/2, label:'π/2'}, + {val:Math.PI, label:'π'} + ].filter(t => t.val >= yRange[0] && t.val <= yRange[1]) + }) + + f.plot(fn, {color, width:2.5, step:(xRange[1]-xRange[0])/200}) + + ''+title+'' + + f.close; + return s; + } + const svgAsin = plotInverse('p7-asin', Math.asin, [-1.05, 1.05], [-Math.PI/2 - 0.2, Math.PI/2 + 0.2], '#0d9488', 'y = arcsin x'); + const svgAcos = plotInverse('p7-acos', Math.acos, [-1.05, 1.05], [-0.2, Math.PI + 0.2], '#0891b2', 'y = arccos x'); + const svgAtg = plotInverse('p7-atg', Math.atan, [-4, 4], [-Math.PI/2 - 0.2, Math.PI/2 + 0.2], '#16a34a', 'y = arctg x'); + const svgActg = plotInverse('p7-actg', x => Math.PI/2 - Math.atan(x), [-4, 4], [-0.2, Math.PI + 0.2], '#7c3aed', 'y = arcctg x'); + + html += makeCard('theory', 'Зачем обратные функции', '7.1', ` +

Уравнение $\\sin x = \\dfrac{1}{2}$ имеет бесконечно много решений ($x = \\dfrac{\\pi}{6} + 2\\pi n$ и $x = \\pi - \\dfrac{\\pi}{6} + 2\\pi n$).

+

Если хочется записать одно «опорное» решение, мы выбираем главное значение — это и есть $\\arcsin\\dfrac{1}{2}$.

`); + + html += makeCard('rule', 'arcsin a', '7.2', ` +

Определение. $\\arcsin a$ — это такое число $\\alpha \\in \\left[-\\dfrac{\\pi}{2};\\,\\dfrac{\\pi}{2}\\right]$, что $\\sin\\alpha = a$.

+

Существует только при $a \\in [-1;\\,1]$. Главные значения:

+ + + +
$a$$0$$\\frac{1}{2}$$\\frac{\\sqrt{2}}{2}$$\\frac{\\sqrt{3}}{2}$$1$
$\\arcsin a$$0$$\\frac{\\pi}{6}$$\\frac{\\pi}{4}$$\\frac{\\pi}{3}$$\\frac{\\pi}{2}$
+

$\\arcsin$ — нечётная: $\\arcsin(-a) = -\\arcsin a$.

+
${svgAsin}
`); + + html += makeCard('rule', 'arccos a', '7.3', ` +

Определение. $\\arccos a$ — это такое число $\\alpha \\in [0;\\,\\pi]$, что $\\cos\\alpha = a$.

+

Существует только при $a \\in [-1;\\,1]$. Главные значения:

+ + + +
$a$$1$$\\frac{\\sqrt{3}}{2}$$\\frac{\\sqrt{2}}{2}$$\\frac{1}{2}$$0$$-1$
$\\arccos a$$0$$\\frac{\\pi}{6}$$\\frac{\\pi}{4}$$\\frac{\\pi}{3}$$\\frac{\\pi}{2}$$\\pi$
+

Важно: $\\arccos$ не является нечётной! $\\arccos(-a) = \\pi - \\arccos a$.

+
${svgAcos}
`); + + html += makeCard('rule', 'arctg a и arcctg a', '7.4', ` +

Определение.

+
    +
  • $\\arctg a$ — такое $\\alpha \\in \\left(-\\dfrac{\\pi}{2};\\,\\dfrac{\\pi}{2}\\right)$, что $\\tg\\alpha = a$. Определено для всех $a \\in \\mathbb{R}$.
  • +
  • $\\arcctg a$ — такое $\\alpha \\in (0;\\,\\pi)$, что $\\ctg\\alpha = a$. Определено для всех $a \\in \\mathbb{R}$.
  • +
+

Главные значения: $\\arctg 0 = 0$, $\\arctg 1 = \\dfrac{\\pi}{4}$, $\\arctg\\sqrt{3} = \\dfrac{\\pi}{3}$, $\\arctg\\dfrac{1}{\\sqrt{3}} = \\dfrac{\\pi}{6}$.

+

$\\arctg$ — нечётная: $\\arctg(-a) = -\\arctg a$. $\\arcctg$ — нет: $\\arcctg(-a) = \\pi - \\arcctg a$.

+
${svgAtg}${svgActg}
`); + + html += makeCard('rule', 'Полезные связки', '7.5', ` +

Эти две формулы стоит запомнить:

+

$\\arcsin a + \\arccos a = \\dfrac{\\pi}{2}$

+

$\\arctg a + \\arcctg a = \\dfrac{\\pi}{2}$

+

Например, $\\arccos\\dfrac{1}{2} = \\dfrac{\\pi}{2} - \\arcsin\\dfrac{1}{2} = \\dfrac{\\pi}{2} - \\dfrac{\\pi}{6} = \\dfrac{\\pi}{3}$.

`); + + /* === ИНТЕРАКТИВ 1: Главные значения === */ + html += '
' + +'
ИНТЕРАКТИВ 1
Найди главное значение
' + +'
Ответ — в виде дроби: pi/6, pi/3, -pi/4, или просто число (для нуля).
' + +trainerHTML('p7-iv1', 8, 'значение') + +'
'; + + /* === ИНТЕРАКТИВ 2: arc(sin(α)) vs α === */ + html += '
' + +'
ИНТЕРАКТИВ 2
arcsin(sin α) vs α
' + +'
$\\sin(\\arcsin a) = a$ всегда. Но $\\arcsin(\\sin\\alpha) = \\alpha$ только если $\\alpha \\in [-\\pi/2;\\,\\pi/2]$. Иначе нужно привести!
' + +trainerHTML('p7-iv2', 5, 'ответ') + +'
'; + + /* === БОСС === */ + html += '

Босс §7 — Обратные функции

'; + html += makeBoss('p7', { + color:'#7c3aed', + title:'Босс §7 — Обратные функции', + steps:[ + { q:'Чему равен $\\arcsin 0$?', verify:(v)=>+v===0, hint:'$\\sin 0 = 0$.' }, + { q:'$\\arcsin\\dfrac{1}{2} = ?$ (введи как pi/n)', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/6'||s==='π/6';}, hint:'$\\sin(\\pi/6) = 1/2$.' }, + { q:'$\\arccos(-1) = ?$ (введи как pi или 0)', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi'||s==='π';}, hint:'$\\cos\\pi = -1$.' }, + { q:'$\\arcsin\\dfrac{\\sqrt{3}}{2} + \\arccos\\dfrac{\\sqrt{3}}{2} = ?$ (введи pi/n)', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/2'||s==='π/2';}, hint:'Сумма всегда $= \\pi/2$.' }, + { q:'$\\arcsin\\left(\\sin\\dfrac{5\\pi}{6}\\right) = ?$ (внимание, $5\\pi/6$ вне $[-\\pi/2;\\,\\pi/2]$! Введи pi/n.)', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/6'||s==='π/6';}, hint:'$\\sin(5\\pi/6) = \\sin(\\pi - \\pi/6) = \\sin(\\pi/6) = 1/2$. arcsin(1/2) = $\\pi/6$.' }, + ] + }); + + html += secNav('p6', 'p8') + readButton('p7'); + box.innerHTML = html; renderMath(box); + + /* IV1: главные значения */ + makeTrainer({ + idPrefix:'p7-iv1', + parser:(v)=>v, + questions:[ + { q:'$\\arcsin 1 = ?$ (введи pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/2'||s==='π/2';}, show:'$\\pi/2$' }, + { q:'$\\arcsin(-1) = ?$ (введи -pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-pi/2'||s==='-π/2';}, show:'$-\\pi/2$' }, + { q:'$\\arccos 1 = ?$', a:(v)=>+v===0, show:'$0$' }, + { q:'$\\arccos 0 = ?$ (введи pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/2'||s==='π/2';}, show:'$\\pi/2$' }, + { q:'$\\arctg 1 = ?$ (введи pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/4'||s==='π/4';}, show:'$\\pi/4$' }, + { q:'$\\arctg(-1) = ?$ (введи -pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-pi/4'||s==='-π/4';}, show:'$-\\pi/4$' }, + { q:'$\\arccos\\dfrac{1}{2} = ?$ (введи pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/3'||s==='π/3';}, show:'$\\pi/3$' }, + { q:'$\\arccos\\left(-\\dfrac{1}{2}\\right) = ?$ (введи 2pi/3)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='2pi/3'||s==='2π/3';}, show:'$2\\pi/3$ ($\\pi - \\pi/3$)' }, + ], + onComplete:(s,n)=>{ if(s===n){addXp(20,'p7-iv1');bumpProgress('p7',32);} else if(s>=5){addXp(10,'p7-iv1');bumpProgress('p7',15);} } + }); + + /* IV2: arcsin(sin α) */ + makeTrainer({ + idPrefix:'p7-iv2', + parser:(v)=>v, + questions:[ + { q:'$\\sin(\\arcsin 0{,}5) = ?$', a:(v)=>+v===0.5, show:'$0{,}5$' }, + { q:'$\\arcsin\\left(\\sin\\dfrac{\\pi}{4}\\right) = ?$ (введи pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/4'||s==='π/4';}, show:'$\\pi/4$ — внутри $[-\\pi/2;\\pi/2]$' }, + { q:'$\\arcsin\\left(\\sin\\dfrac{3\\pi}{4}\\right) = ?$ (введи pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/4'||s==='π/4';}, show:'$\\pi/4$ ($\\sin(3\\pi/4) = \\sin(\\pi/4)$)' }, + { q:'$\\cos(\\arccos(-0{,}3)) = ?$', a:(v)=>+v===-0.3, show:'$-0{,}3$' }, + { q:'$\\arccos\\left(\\cos\\dfrac{5\\pi}{4}\\right) = ?$ (введи как 3pi/4)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='3pi/4'||s==='3π/4';}, show:'$3\\pi/4$ ($\\cos(5\\pi/4) = -\\frac{\\sqrt{2}}{2}$, $\\arccos = 3\\pi/4$)' }, + ], + onComplete:(s,n)=>{ if(s===n){addXp(18,'p7-iv2');bumpProgress('p7',28);} else if(s>=3){addXp(9,'p7-iv2');bumpProgress('p7',14);} } + }); + + wireReadBtn('p7'); +} +