feat(alg10 W5): Финал главы 1 — 6 интегрированных боссов + ачивка
Глава 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 § + Финал.
This commit is contained in:
@@ -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:'Запомнить помогает мнемоника: <b>знаки повторяются в sin</b> (sin·cos + cos·sin) и <b>чередуются в cos</b> (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:'<b>6 интегрированных боссов</b> проверяют синтез знаний всей главы. После победы над всеми — ачивка <b>«Магистр тригонометрии»</b> и +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$ <b>и</b> $\\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:'Сколько <b>различных</b> точек $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 += '<div style="background:linear-gradient(135deg,#0d9488,#7c3aed);color:#fff;border-radius:18px;padding:24px 22px;margin-bottom:24px;box-shadow:0 8px 28px rgba(13,148,136,.25);position:relative;overflow:hidden">'
|
||||
+'<div style="position:absolute;right:-20px;top:-30px;font-size:8rem;font-weight:900;color:rgba(255,255,255,.1);font-family:Unbounded,sans-serif;line-height:1;pointer-events:none">★</div>'
|
||||
+'<div style="position:relative;z-index:1">'
|
||||
+'<div style="font-size:.78rem;font-weight:800;letter-spacing:.1em;text-transform:uppercase;opacity:.85;margin-bottom:6px">ФИНАЛ ГЛАВЫ 1</div>'
|
||||
+'<h2 style="font-family:Unbounded,sans-serif;font-size:1.55rem;font-weight:800;margin-bottom:8px">6 интегрированных боссов</h2>'
|
||||
+'<p style="font-size:.95rem;opacity:.92;margin-bottom:14px;max-width:580px">Каждый босс проверяет синтез нескольких параграфов главы. Победи всех — получи ачивку <b>«Магистр тригонометрии»</b> и +150 XP.</p>'
|
||||
+'<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center">'
|
||||
+'<div style="padding:8px 14px;background:rgba(255,255,255,.18);border-radius:99px;font-size:.82rem;font-weight:700">★ 6 боссов</div>'
|
||||
+'<div style="padding:8px 14px;background:rgba(255,255,255,.18);border-radius:99px;font-size:.82rem;font-weight:700">+ до 300 XP</div>'
|
||||
+'<div style="padding:8px 14px;background:rgba(255,255,255,.18);border-radius:99px;font-size:.82rem;font-weight:700">★ Финальная ачивка</div>'
|
||||
+'</div></div></div>';
|
||||
|
||||
/* === Overall progress === */
|
||||
html += '<div style="background:var(--card);border:1.5px solid var(--border);border-radius:14px;padding:16px 20px;margin-bottom:20px">'
|
||||
+'<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:10px">'
|
||||
+'<div style="font-family:Unbounded,sans-serif;font-size:.85rem;font-weight:800;color:var(--text);letter-spacing:.06em;text-transform:uppercase">Прогресс по боссам</div>'
|
||||
+'<div id="final1-overall" style="font-size:.95rem;font-weight:700;color:var(--pri2)">0 / 6 побеждено</div>'
|
||||
+'</div>'
|
||||
+'<div style="height:12px;background:rgba(13,148,136,.12);border-radius:8px;overflow:hidden">'
|
||||
+'<div id="final1-overall-fill" style="height:100%;width:0%;background:linear-gradient(90deg,#0d9488,#7c3aed);transition:width .6s cubic-bezier(.16,1,.3,1)"></div>'
|
||||
+'</div></div>';
|
||||
|
||||
/* === Bosses container === */
|
||||
html += '<div id="final1-bosses"></div>';
|
||||
|
||||
/* === Celebration === */
|
||||
html += '<div id="final1-cel" style="display:none;margin:24px 0;padding:24px 22px;background:linear-gradient(135deg,#fef3c7,#fde68a);border:2px solid #f59e0b;border-radius:18px;text-align:center;box-shadow:0 6px 22px rgba(245,158,11,.25)">'
|
||||
+'<div style="font-size:3rem;margin-bottom:6px">★</div>'
|
||||
+'<div style="font-family:Unbounded,sans-serif;font-size:1.4rem;font-weight:900;color:#92400e;margin-bottom:6px">МАГИСТР ТРИГОНОМЕТРИИ!</div>'
|
||||
+'<div style="font-size:.95rem;color:#78350f;margin-bottom:14px">Ты победил всех 6 боссов главы 1 и освоил тригонометрию.<br>Получено: <b>+150 XP</b> и финальная ачивка.</div>'
|
||||
+'<a href="/textbook/algebra-10" style="display:inline-flex;align-items:center;gap:8px;padding:11px 22px;background:linear-gradient(135deg,#0d9488,#7c3aed);color:#fff;border-radius:11px;font-weight:700;text-decoration:none">Вернуться к Алгебре 10 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" style="width:16px;height:16px"><polyline points="9 18 15 12 9 6"/></svg></a>'
|
||||
+'</div>';
|
||||
|
||||
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 '<div class="boss-card" id="bb-'+b.n+'-card" style="border-color:'+b.color+'">'
|
||||
+'<div class="boss-head" style="flex-wrap:wrap">'
|
||||
+'<svg viewBox="0 0 24 24" fill="none" stroke="'+b.color+'" stroke-width="2.2" style="width:28px;height:28px"><polygon points="12,2 22,20 2,20"/></svg>'
|
||||
+'<div style="padding:3px 10px;background:'+b.color+'22;color:'+b.color+';border-radius:99px;font-family:Unbounded,sans-serif;font-size:.7rem;font-weight:800;letter-spacing:.06em;text-transform:uppercase">'+b.tag+'</div>'
|
||||
+'<div class="boss-title" style="color:'+b.color+';flex:1;min-width:0">Босс '+b.n+'. '+b.title+'</div>'
|
||||
+'<div class="boss-stage" id="bb-'+b.n+'-stage">Этап 1 / '+b.steps.length+'</div>'
|
||||
+'</div>'
|
||||
+'<div class="hp-boss" style="border-color:'+b.color+'66;background:'+b.color+'1a"><div class="hp-boss-fill" id="bb-'+b.n+'-fill" style="width:0%;background:linear-gradient(90deg,'+b.color+',#f59e0b)"></div></div>'
|
||||
+'<div class="boss-q" id="bb-'+b.n+'-q" style="border-color:'+b.color+'"></div>'
|
||||
+'<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap">'
|
||||
+'<input type="text" id="bb-'+b.n+'-input" class="tinp" placeholder="Ответ" style="width:160px;text-align:center">'
|
||||
+'<button class="btn primary" id="bb-'+b.n+'-go" style="background:'+b.color+';border-color:'+b.color+'">Атака</button>'
|
||||
+'<button class="btn" id="bb-'+b.n+'-hint">Подсказка</button>'
|
||||
+'<button class="btn" id="bb-'+b.n+'-restart">↻</button>'
|
||||
+'</div>'
|
||||
+'<div class="feedback" id="bb-'+b.n+'-fb"></div>'
|
||||
+'</div>';
|
||||
}).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='<b style="color:'+b.color+'">Босс повержен!</b>';
|
||||
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='<span style="color:#92400e">\u{1F4A1} Подсказка:</span> '+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');
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user