From 77bfdb4331db206ca87745e02268782c155d1449 Mon Sep 17 00:00:00 2001 From: Maxim Dolgolyov Date: Fri, 29 May 2026 11:30:24 +0300 Subject: [PATCH] =?UTF-8?q?feat(alg10=20W5):=20=D0=A4=D0=B8=D0=BD=D0=B0?= =?UTF-8?q?=D0=BB=20=D0=B3=D0=BB=D0=B0=D0=B2=D1=8B=201=20=E2=80=94=206=20?= =?UTF-8?q?=D0=B8=D0=BD=D1=82=D0=B5=D0=B3=D1=80=D0=B8=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=B1=D0=BE=D1=81=D1=81=D0=BE?= =?UTF-8?q?=D0=B2=20+=20=D0=B0=D1=87=D0=B8=D0=B2=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Глава 1 'Тригонометрия' полностью завершена. buildFinal1(): - Hero card с градиентом teal→violet, водяной знак ★ и 3 плашки-метки (★ 6 боссов / + до 300 XP / ★ Финальная ачивка) - Общий прогресс-бар 'X / 6 побеждено' с градиентной заливкой - 6 boss-card по теме отдельных параграфов - Celebration-card 'МАГИСТР ТРИГОНОМЕТРИИ' (скрыта пока не все 6 боссов повержены) с ачивкой, кнопкой возврата на хаб - Своё состояние в localStorage (algebra10_ch1_final1_state) 6 боссов (5 этапов каждый, 30 вопросов всего): - Босс 1 (teal, §1-§4): окружность, sin/cos/tg/ctg, тождества - Босс 2 (cyan, §5-§7): графики, обратные функции - Босс 3 (red, §8): уравнения (метод интервалов, замена, разложение) - Босс 4 (dark teal, §9): формулы приведения (правило двух шагов) - Босс 5 (deep teal, §10-§11): сложение, разность, двойной аргумент - Босс 6 (violet, §12+): синтез — сумма→произведение, проверка на отождествление углов отличающихся на 2πn XP: - 5 XP за каждый правильный этап (30 правильных = 150 XP) - 25 XP за победу над каждым боссом (6 × 25 = 150 XP) - Бонус +150 XP за финальную ачивку 'trig_master' - Итого до 450 XP за финал Добавлены: - ACH_LABELS.trig_master: 'Магистр тригонометрии! +150 XP' - SIDEBARS.final1 + TIPS.final1 - BUILDERS.final1 теперь buildFinal1() (вместо stub) Файл вырос с 221 KB до 240 KB (2998 → 3252 строки). Глава 1 готова на 100% — 12 § + Финал. --- frontend/textbooks/algebra_10_ch1.html | 255 ++++++++++++++++++++++++- 1 file changed, 254 insertions(+), 1 deletion(-) diff --git a/frontend/textbooks/algebra_10_ch1.html b/frontend/textbooks/algebra_10_ch1.html index 2fa340b..3bd3443 100644 --- a/frontend/textbooks/algebra_10_ch1.html +++ b/frontend/textbooks/algebra_10_ch1.html @@ -290,6 +290,7 @@ const ACH_LABELS = { p11_done:'Двойной аргумент — лёгкость!', p12_done:'Преобразование суммы — освоено!', ch1_done:'Глава 1 — Тригонометрия пройдена!', + trig_master:'Магистр тригонометрии! +150 XP', }; function loadProgress(){ @@ -402,7 +403,7 @@ const BUILT=new Set(); const BUILDERS = { p1:()=>buildP1(), p2:()=>buildP2(), p3:()=>buildP3(), p4:()=>buildP4(), p5:()=>buildP5(), p6:()=>buildP6(), p7:()=>buildP7(), p8:()=>buildP8(), p9:()=>buildP9(), p10:()=>buildP10(), p11:()=>buildP11(), p12:()=>buildP12(), - final1:()=>buildStub('final1','Финал главы 1 — 6 боссов') + final1:()=>buildFinal1() }; function ensureBuilt(id){ if(BUILT.has(id)) return; const fn=BUILDERS[id]; if(fn){ fn(); BUILT.add(id); } } function goTo(id){ @@ -529,6 +530,16 @@ const SIDEBARS = { ['Польза','решение уравнений'], ['Пример','$\\sin 3x + \\sin x$ → произведение'], ]}, + final1:{title:'Финал главы 1',rows:[ + ['Боссов','6 — все темы главы'], + ['Босс 1','§1-§4 окружность, sin/cos/tg/ctg'], + ['Босс 2','§5-§7 графики, обратные'], + ['Босс 3','§8 уравнения'], + ['Босс 4','§9 приведение'], + ['Босс 5','§10-§11 сложение и двойной'], + ['Босс 6','§12+ синтез всех тем'], + ['Награда','+150 XP + «Магистр тригонометрии»'], + ]}, }; const TIPS=[ @@ -544,6 +555,7 @@ const TIPS=[ {sec:'p10',html:'Запомнить помогает мнемоника: знаки повторяются в sin (sin·cos + cos·sin) и чередуются в cos (cos·cos − sin·sin). Для разности — наоборот.'}, {sec:'p11',html:'Три формы $\\cos 2\\alpha$ нужны для разных задач: $\\cos^2 - \\sin^2$ — для упрощения; $1 - 2\\sin^2$ — когда задан $\\sin\\alpha$; $2\\cos^2 - 1$ — когда задан $\\cos\\alpha$.'}, {sec:'p12',html:'4 формулы — все имеют вид «2 · функция полусуммы · функция полуразности». Знаки и тип функции в правой части смотри по таблице (или по правилу для каждой формулы).'}, + {sec:'final1',html:'6 интегрированных боссов проверяют синтез знаний всей главы. После победы над всеми — ачивка «Магистр тригонометрии» и +150 XP. Не торопись, используй шпаргалки.'}, ]; function buildSidebar(id){ @@ -2862,6 +2874,247 @@ function buildP12(){ wireReadBtn('p12'); } +/* ============================================================ + ФИНАЛ ГЛАВЫ 1 — 6 интегрированных боссов + ============================================================ */ +const FINAL1_BOSSES = [ + { + n:1, tag:'§ 1–4', + title:'Окружность, sin/cos, tg/ctg, тождества', + color:'#0d9488', + steps:[ + { q:'Преобразуй $240°$ в радианы. Введи как 4pi/3.', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='4pi/3'||s==='4π/3';}, hint:'$240 \\cdot \\pi / 180 = 4\\pi/3$.' }, + { q:'Найди $\\sin\\dfrac{\\pi}{4} \\cdot \\cos\\dfrac{\\pi}{4}$. Введи как 1/2.', verify:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='1/2'||+v===0.5;}, hint:'$(\\sqrt{2}/2)^2 = 1/2$.' }, + { q:'В какой четверти $\\tg\\alpha > 0$ и $\\cos\\alpha < 0$? (1/2/3/4)', verify:(v)=>+v===3, hint:'tg > 0: I или III; cos < 0: II или III. Пересечение — III.' }, + { q:'$\\sin^2 30° + \\cos^2 60° = ?$ Введи 1/2.', verify:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='1/2'||+v===0.5;}, hint:'$(1/2)^2 + (1/2)^2 = 1/4 + 1/4$.' }, + { q:'$\\sin\\alpha = -3/5$, $\\alpha \\in (\\pi;\\,3\\pi/2)$. Найди $\\tg\\alpha$ (введи 3/4).', verify:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='3/4'||+v===0.75;}, hint:'cos = -4/5 (III четв.), tg = sin/cos = (-3/5)/(-4/5) = 3/4.' }, + ] + }, + { + n:2, tag:'§ 5–7', + title:'Графики, обратные функции', + color:'#0891b2', + steps:[ + { q:'Период функции $y = \\sin 3x$. Введи как 2pi/n.', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='2pi/3'||s==='2π/3';}, hint:'$T = 2\\pi / 3$.' }, + { q:'$y = \\cos x$ — чётная или нечётная? Введи слово.', verify:(v)=>String(v).trim().toLowerCase().startsWith('чёт')||String(v).trim().toLowerCase().startsWith('чет'), hint:'$\\cos(-x) = \\cos x$.' }, + { q:'Наибольшее значение функции $y = 3\\sin x - 1$?', verify:(v)=>+v===2, hint:'При $\\sin x = 1$: $3 - 1 = 2$.' }, + { q:'$\\arcsin(-1) = ?$ Введи как -pi/2.', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-pi/2'||s==='-π/2';}, hint:'$\\sin(-\\pi/2) = -1$.' }, + { q:'$\\arccos\\dfrac{\\sqrt{2}}{2} = ?$ Введи pi/4.', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/4'||s==='π/4';}, hint:'$\\cos(\\pi/4) = \\sqrt{2}/2$.' }, + ] + }, + { + n:3, tag:'§ 8', + title:'Тригонометрические уравнения', + color:'#dc2626', + steps:[ + { q:'Сколько корней у $\\sin x = 0{,}5$ на $[0;\\,2\\pi]$?', verify:(v)=>+v===2, hint:'$\\pi/6$ и $5\\pi/6$.' }, + { q:'Реши $\\cos x = -1$. Корень в $[0;\\,2\\pi]$? Введи pi.', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi'||s==='π';}, hint:'$\\cos\\pi = -1$.' }, + { q:'$2\\sin^2 x - \\sin x - 1 = 0$. Сколько корней в $[0;\\,2\\pi)$?', verify:(v)=>+v===3, hint:'$t = \\sin x$: $2t^2 - t - 1 = 0$, $t = 1$ или $t = -1/2$. sin = 1: π/2 (1 корень). sin = -1/2: 7π/6, 11π/6 (2 корня). Итого 3.' }, + { q:'$\\tg x = \\sqrt{3}$. Наименьший положительный корень? Введи pi/n.', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/3'||s==='π/3';}, hint:'$\\arctg\\sqrt{3} = \\pi/3$.' }, + { q:'$\\sin x \\cdot \\cos x = 0$. Сколько корней в $[0;\\,2\\pi)$?', verify:(v)=>+v===4, hint:'$\\sin x = 0$: 0, π. $\\cos x = 0$: π/2, 3π/2. Все различны — 4.' }, + ] + }, + { + n:4, tag:'§ 9', + title:'Формулы приведения', + color:'#0e7490', + steps:[ + { q:'$\\sin(\\pi - \\alpha) = ?$ Введи: «sin a» или «-sin a».', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='sina'||s==='sin(a)'||s==='sinα';}, hint:'II четв., sin > 0; имя не меняется.' }, + { q:'$\\cos\\left(\\dfrac{\\pi}{2} + \\alpha\\right) = ?$ Введи «-sin a».', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-sina'||s==='-sin(a)'||s==='-sinα';}, hint:'II четв., cos < 0; имя меняется cos → sin.' }, + { q:'Вычисли $\\sin 150°$. Введи 1/2.', verify:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='1/2'||+v===0.5;}, hint:'$\\sin(180° - 30°) = \\sin 30° = 1/2$.' }, + { q:'Вычисли $\\cos 210°$. Введи -sqrt3/2.', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-sqrt3/2'||s==='-√3/2'||Math.abs(+v - (-Math.sqrt(3)/2))<0.02;}, hint:'$\\cos(180° + 30°) = -\\cos 30°$.' }, + { q:'$\\tg\\left(\\dfrac{3\\pi}{2} - \\alpha\\right) = ?$ Введи «ctg a», «-ctg a» или «tg a».', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='ctga'||s==='ctg(a)'||s==='ctgα';}, hint:'III четв., tg > 0; имя меняется tg → ctg.' }, + ] + }, + { + n:5, tag:'§ 10–11', + title:'Сумма, разность, двойной аргумент', + color:'#0f766e', + steps:[ + { q:'$\\sin 75° = \\dfrac{\\sqrt{6} + \\sqrt{2}}{?}$ — введи знаменатель.', verify:(v)=>+v===4, hint:'$\\sin(45° + 30°) = \\sin 45 \\cos 30 + \\cos 45 \\sin 30$.' }, + { q:'$\\sin\\alpha = 3/5$, $\\alpha$ в I четв. Найди $\\sin 2\\alpha$ (введи 24/25).', verify:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='24/25'||+v===0.96;}, hint:'$\\cos\\alpha = 4/5$, $\\sin 2\\alpha = 2 \\cdot 3/5 \\cdot 4/5 = 24/25$.' }, + { q:'$\\cos^2 30° - \\sin^2 30° = ?$ Введи 1/2.', verify:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='1/2'||+v===0.5;}, hint:'Это $\\cos 60° = 1/2$.' }, + { q:'$\\tg(45° + 45°) = ?$ Введи 9999 (это $\\infty$).', verify:(v)=>+v===9999, hint:'$\\tg 90°$ не существует.' }, + { q:'$\\sin^2 22{,}5° = \\dfrac{1 - \\cos 45°}{?}$ — введи знаменатель.', verify:(v)=>+v===2, hint:'Формула понижения степени.' }, + ] + }, + { + n:6, tag:'§ 12+', + title:'Финальный — синтез всех тем', + color:'#7c3aed', + steps:[ + { q:'$\\sin 3x + \\sin x = 2\\sin ?x \\cos x$. Введи коэф.', verify:(v)=>+v===2, hint:'$\\frac{3x+x}{2} = 2x$.' }, + { q:'$\\dfrac{\\sin 5x - \\sin x}{\\cos 5x + \\cos x} = \\tg ?x$. Введи коэф.', verify:(v)=>+v===2, hint:'Числитель: $2\\sin 2x \\cos 3x$. Знаменатель: $2\\cos 3x \\cos 2x$. Сокращаем — $\\tg 2x$.' }, + { q:'Сколько корней у $\\cos x = 0{,}5$ на $[-2\\pi;\\,2\\pi]$?', verify:(v)=>+v===4, hint:'$x = \\pm\\pi/3 + 2\\pi n$: $-5\\pi/3, -\\pi/3, \\pi/3, 5\\pi/3$ — 4 корня.' }, + { q:'$\\sin\\alpha = 0{,}6$, $\\alpha$ в I четв. Найди $\\cos 2\\alpha$ (введи 0.28).', verify:(v)=>Math.abs(+v - 0.28)<0.01, hint:'$\\cos 2\\alpha = 1 - 2 \\cdot 0{,}36 = 0{,}28$.' }, + { q:'Сколько различных точек $P_\\alpha$ на окружности при $\\alpha = \\dfrac{\\pi}{4}, \\dfrac{9\\pi}{4}, -\\dfrac{7\\pi}{4}, \\dfrac{17\\pi}{4}$?', verify:(v)=>+v===1, hint:'Все отличаются на $2\\pi k$, значит совпадают.' }, + ] + }, +]; + +function buildFinal1(){ + const box = document.getElementById('final1-body'); + let html = ''; + + /* === Hero card === */ + html += '
' + +'
' + +'
' + +'
ФИНАЛ ГЛАВЫ 1
' + +'

6 интегрированных боссов

' + +'

Каждый босс проверяет синтез нескольких параграфов главы. Победи всех — получи ачивку «Магистр тригонометрии» и +150 XP.

' + +'
' + +'
★ 6 боссов
' + +'
+ до 300 XP
' + +'
★ Финальная ачивка
' + +'
'; + + /* === Overall progress === */ + html += '
' + +'
' + +'
Прогресс по боссам
' + +'
0 / 6 побеждено
' + +'
' + +'
' + +'
' + +'
'; + + /* === Bosses container === */ + html += '
'; + + /* === Celebration === */ + html += ''; + + html += secNav('p12', null) + readButton('final1'); + box.innerHTML = html; renderMath(box); + + /* === State === */ + const SKEY = 'algebra10_ch1_final1_state'; + let state = {}; + try{ const s=localStorage.getItem(SKEY); if(s) state = JSON.parse(s); }catch(e){} + /* инициализация */ + FINAL1_BOSSES.forEach(b => { + if(!state['b'+b.n]) state['b'+b.n] = {stage:0, defeated:false}; + }); + function save(){ try{ localStorage.setItem(SKEY, JSON.stringify(state)); }catch(e){} } + function refreshOverall(){ + let won = 0; + FINAL1_BOSSES.forEach(b => { if(state['b'+b.n].defeated) won++; }); + document.getElementById('final1-overall').textContent = won + ' / 6 побеждено'; + document.getElementById('final1-overall-fill').style.width = (won*100/6) + '%'; + if(won >= 6){ + document.getElementById('final1-cel').style.display = 'block'; + if(STATE.progress.final1 < 100){ + bumpProgress('final1', 100); + } + if(!STATE.achievements.has('trig_master')){ + achievement('trig_master'); + /* Бонус 150 XP */ + addXp(150, 'trig-master'); + } + } + } + + /* === Build boss cards === */ + const cont = document.getElementById('final1-bosses'); + cont.innerHTML = FINAL1_BOSSES.map(b => { + return '
' + +'
' + +'' + +'
'+b.tag+'
' + +'
Босс '+b.n+'. '+b.title+'
' + +'
Этап 1 / '+b.steps.length+'
' + +'
' + +'
' + +'
' + +'
' + +'' + +'' + +'' + +'' + +'
' + +'' + +'
'; + }).join(''); + if(window.renderMathInElement) try{ renderMath(cont); }catch(e){} + + /* === Bind handlers === */ + FINAL1_BOSSES.forEach(b => { + const stKey = 'b' + b.n; + function show(){ + const st = state[stKey]; + const stageEl=document.getElementById('bb-'+b.n+'-stage'); + const fill=document.getElementById('bb-'+b.n+'-fill'); + const q=document.getElementById('bb-'+b.n+'-q'); + const fb=document.getElementById('bb-'+b.n+'-fb'); + if(st.defeated){ + stageEl.textContent='✓ Побеждён'; + fill.style.width='100%'; + q.innerHTML='Босс повержен!'; + document.getElementById('bb-'+b.n+'-go').disabled=true; + document.getElementById('bb-'+b.n+'-go').style.opacity=.5; + return; + } + stageEl.textContent='Этап '+(st.stage+1)+' / '+b.steps.length; + fill.style.width=(st.stage*100/b.steps.length)+'%'; + q.innerHTML=b.steps[st.stage].q; + document.getElementById('bb-'+b.n+'-input').value=''; + fb.style.display='none'; + renderMath(q); + } + document.getElementById('bb-'+b.n+'-go').addEventListener('click', ()=>{ + const st = state[stKey]; + if(st.defeated) return; + const step=b.steps[st.stage]; + const val=document.getElementById('bb-'+b.n+'-input').value; + const fb=document.getElementById('bb-'+b.n+'-fb'); + if(!val.trim()){ feedback(fb,false,'✗ Введи ответ.'); return; } + if(step.verify(val)){ + st.stage++; + if(st.stage>=b.steps.length){ + st.defeated=true; save(); + feedback(fb,true,'✓ Босс '+b.n+' повержен! +25 XP'); + addXp(25,'final1-b'+b.n); + refreshOverall(); + setTimeout(show, 1400); + } else { + save(); + feedback(fb,true,'✓ Верно! +5 XP'); + addXp(5,'final1-b'+b.n+'-step'); + setTimeout(show, 1100); + } + } else { + feedback(fb,false,'✗ Промах. Подумай ещё.'); + } + }); + document.getElementById('bb-'+b.n+'-hint').addEventListener('click', ()=>{ + const st = state[stKey]; + if(st.defeated) return; + const fb=document.getElementById('bb-'+b.n+'-fb'); + fb.className='feedback ok'; + fb.innerHTML='\u{1F4A1} Подсказка: '+b.steps[st.stage].hint; + fb.style.display='block'; + fb.style.background='var(--warn-bg)'; fb.style.color='#92400e'; fb.style.borderLeftColor='var(--warn)'; + renderMath(fb); + }); + document.getElementById('bb-'+b.n+'-restart').addEventListener('click', ()=>{ + state[stKey] = {stage:0, defeated:false}; save(); + document.getElementById('bb-'+b.n+'-go').disabled=false; + document.getElementById('bb-'+b.n+'-go').style.opacity=1; + show(); refreshOverall(); + }); + show(); + }); + + refreshOverall(); + wireReadBtn('final1'); +} +