feat(algebra-8 ch2): Wave 4 — финал + 7 боссов + DB migration
frontend/textbooks/algebra_8_ch2.html · final2: - Boss Arena с 7 боссами: · §7 «Хранитель неполных» — 5 заданий · §8 «Дискриминатор» — 5 заданий · §9 «Дух Виета» — 5 заданий · §10 «Разложитель» — 5 заданий · §11 «Архивариус задач» — 5 заданий · §12 «Мастер замены» — 5 заданий · ★ «Магистр алгебры» (финал) — 7 заданий - Универсальный движок: select / yesno / input - HP-бар, иконки боссов, состояние в localStorage - Сертификат «Магистр квадратных уравнений» при всех 7 победах Дополнительно: - Увлекательная математика (3 spoiler-факта: история, a≠0, парадокс) - Финальная практика: генератор случайных задач со всей главы (5 типов) - Серия из 5 верных = достижение - ACH_LABELS для всех boss_*, all_bosses, prac_streak algebra_8.html: добавлена ссылка «Глава 2 →» в шапке. migrations/012_algebra_8_ch2.sql: регистрация slug 'algebra-8-ch2'.
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
-- Register Algebra 8 — Chapter 2 «Квадратные уравнения» as a separate textbook entry.
|
||||
-- Chapter 1 already exists with slug 'algebra-8'. This is a continuation file.
|
||||
INSERT OR IGNORE INTO textbooks (slug, subject, grade, title, author, description, html_path, para_count, color, sort_order) VALUES
|
||||
('algebra-8-ch2', 'math', 8, 'Алгебра — 8 класс · Глава 2', '',
|
||||
'Интерактивный учебник: глава 2 «Квадратные уравнения». §§ 7–12 + Финал. 30+ интерактивов: конструкторы уравнений, дискриминант, теорема Виета, разложение, текстовые задачи, биквадратные. 7 боссов-проверок.',
|
||||
'algebra_8_ch2.html', 7, 'pink', 4);
|
||||
@@ -756,6 +756,10 @@ input,select,textarea{font-family:inherit}
|
||||
<svg id="sound-on-ic" class="ic" viewBox="0 0 24 24"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14"/><path d="M15.54 8.46a5 5 0 0 1 0 7.07"/></svg>
|
||||
<svg id="sound-off-ic" class="ic" viewBox="0 0 24 24" style="display:none"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><line x1="23" y1="9" x2="17" y2="15"/><line x1="17" y1="9" x2="23" y2="15"/></svg>
|
||||
</button>
|
||||
<a href="/textbook/algebra-8-ch2" class="hdr-btn" title="Глава 2 — Квадратные уравнения">
|
||||
Глава 2
|
||||
<svg class="ic" viewBox="0 0 24 24"><polyline points="9 18 15 12 9 6"/></svg>
|
||||
</a>
|
||||
<button id="theme-btn" class="hdr-btn" title="Сменить тему">
|
||||
<svg class="ic" viewBox="0 0 24 24"><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"/></svg>
|
||||
<span id="theme-lab">Тёмная</span>
|
||||
|
||||
@@ -401,6 +401,15 @@ const ACH_LABELS = {
|
||||
p12_frac: 'Дробное → квадратное',
|
||||
p12_subst: 'Замена переменной',
|
||||
p12_odz: 'Посторонний корень',
|
||||
boss_b1: 'Босс §7 повержен',
|
||||
boss_b2: 'Босс §8 повержен',
|
||||
boss_b3: 'Босс §9 повержен',
|
||||
boss_b4: 'Босс §10 повержен',
|
||||
boss_b5: 'Босс §11 повержен',
|
||||
boss_b6: 'Босс §12 повержен',
|
||||
boss_b7: 'Магистр алгебры',
|
||||
all_bosses: 'Все 7 боссов побеждены!',
|
||||
prac_streak: 'Серия из 5 верных',
|
||||
};
|
||||
|
||||
function loadProgress(){
|
||||
@@ -1758,7 +1767,287 @@ function buildP12(){
|
||||
document.getElementById('p12o-start').addEventListener('click', ()=>{ i=1; show(); });
|
||||
})();
|
||||
}
|
||||
function buildFinal2stub(){ document.getElementById('final2-body').innerHTML = `<div class="card"><div class="card-body"><p style="text-align:center;padding:20px"><b>Финал главы</b><br><br>Итоговая самооценка, практика, увлекательная математика и финальный босс — в Wave 4.</p></div></div>${secNav('p12',null)}`; }
|
||||
function buildFinal2stub(){ buildFinal2(); }
|
||||
function buildFinal2(){
|
||||
const box = document.getElementById('final2-body');
|
||||
let html = '';
|
||||
|
||||
html += `<div class="card"><div class="card-header"><div class="card-icon theory">${ICONS.theory}</div><div class="card-title">Поздравляем!</div></div><div class="card-body">
|
||||
<p>Вы прошли все 6 параграфов главы «Квадратные уравнения». В финале вас ждут <b>7 боссов</b> — по одному на каждый параграф и один общий. Победите всех — получите титул «Магистр квадратных уравнений».</p>
|
||||
</div></div>`;
|
||||
|
||||
/* BOSS ARENA */
|
||||
html += widget('Боссы главы 2','BOSS ARENA','Каждый босс — 5 заданий. Победите всех 7, чтобы открыть финальный титул.',`
|
||||
<div id="boss-grid" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px"></div>
|
||||
<div id="boss-arena" style="margin-top:14px;display:none">
|
||||
<div id="boss-head" style="display:flex;align-items:center;gap:14px;padding:14px;background:linear-gradient(135deg,#1f2937,#0f172a);border-radius:10px;color:#fff;margin-bottom:10px">
|
||||
<div id="boss-emoji" style="font-size:2.4rem;line-height:1">★</div>
|
||||
<div style="flex:1">
|
||||
<div id="boss-name" style="font-family:'Unbounded',sans-serif;font-weight:800;font-size:1.05rem"></div>
|
||||
<div id="boss-subname" style="font-size:.85rem;opacity:.75"></div>
|
||||
<div class="hp-bar" style="margin-top:6px;background:rgba(255,255,255,.15);height:8px;border-radius:4px;overflow:hidden"><div id="boss-hp" style="height:100%;background:linear-gradient(90deg,#10b981,#fbbf24,#ef4444);width:100%;transition:width .5s"></div></div>
|
||||
</div>
|
||||
<button class="btn" id="boss-quit" style="background:rgba(255,255,255,.15);color:#fff;border-color:transparent">Выйти</button>
|
||||
</div>
|
||||
<div id="boss-task" style="padding:16px;background:var(--card);border:1.5px solid var(--sec-acc);border-radius:10px;min-height:120px"></div>
|
||||
<div id="boss-opts" style="display:flex;flex-direction:column;gap:6px;margin-top:10px"></div>
|
||||
<div id="boss-fb" class="feedback" style="display:none;margin-top:10px"></div>
|
||||
</div>`);
|
||||
|
||||
/* FUN MATH */
|
||||
html += widget('Увлекательная математика','BONUS','3 факта и парадокса про квадратные уравнения.',`
|
||||
<details class="spoiler" style="margin-bottom:8px"><summary>Кто открыл формулу корней?</summary>
|
||||
<div class="spoiler-body">Первые методы — в Древнем Вавилоне (2000 до н. э.). Полную формулу для произвольных коэффициентов записал Мухаммед аль-Хорезми в IX веке в своём трактате «Краткая книга об исчислении ал-джабра и ал-мукабалы». От слова «ал-джабр» произошло слово «алгебра».</div>
|
||||
</details>
|
||||
<details class="spoiler" style="margin-bottom:8px"><summary>Почему $a \\neq 0$?</summary>
|
||||
<div class="spoiler-body">Если $a = 0$, то уравнение $bx + c = 0$ — линейное (степени 1), а не квадратное. Степень уравнения — это степень его старшего члена, поэтому требование $a \\neq 0$ нужно, чтобы старший член был именно $x^2$.</div>
|
||||
</details>
|
||||
<details class="spoiler"><summary>Парадокс «потерянного корня»</summary>
|
||||
<div class="spoiler-body">Если уравнение $\\dfrac{x^2-4}{x-2} = 0$ умножить на $x-2$, получим $x^2 - 4 = 0 \\Rightarrow x = \\pm 2$. Но $x = 2$ обнуляет знаменатель! Этот корень — посторонний. ОДЗ всегда выручает.</div>
|
||||
</details>`);
|
||||
|
||||
/* PRACTICE GENERATOR */
|
||||
html += widget('Финальная практика','PRACTICE','Случайные задачи из всей главы. Решайте, сколько хотите.',`
|
||||
<div class="score-display"><span>Решено: <b id="prac-i">0</b></span><span>Правильно: <b id="prac-score">0</b></span><span>Серия: <b id="prac-streak">0</b></span></div>
|
||||
<div id="prac-task" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.05rem;line-height:1.6;margin-bottom:10px"></div>
|
||||
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center;justify-content:center">
|
||||
<input type="text" id="prac-inp" placeholder="ответ" style="width:200px;padding:8px;border:1.5px solid var(--border);border-radius:8px">
|
||||
<button class="btn primary" id="prac-go">Ответ</button>
|
||||
<button class="btn" id="prac-next">Следующая</button>
|
||||
</div>
|
||||
<div class="feedback" id="prac-fb" style="display:none;margin-top:10px"></div>`);
|
||||
|
||||
/* CERTIFICATE */
|
||||
html += `<div class="card"><div class="card-header"><div class="card-icon home">${ICONS.home}</div><div class="card-title">Сертификат прохождения</div></div><div class="card-body">
|
||||
<p>Как вы оцените своё знание квадратных уравнений?</p>
|
||||
<div id="cert-state" style="margin-top:10px;font-size:.9rem;color:var(--muted)"></div>
|
||||
</div></div>`;
|
||||
|
||||
html += secNav('p12', null);
|
||||
box.innerHTML = html;
|
||||
if(window.renderMathInElement) setTimeout(()=>renderMath(box), 0);
|
||||
|
||||
/* ===== BOSSES ===== */
|
||||
const BOSSES = [
|
||||
{ id:'b1', name:'Хранитель неполных', sub:'§ 7 · ax²+bx=0 и ax²+c=0', icon:'⚔', hp:5, tasks:[
|
||||
{ t:'select', q:'Сколько корней у уравнения $5x^2 - 45 = 0$?', opts:['Два','Один','Корней нет'], ok:0 },
|
||||
{ t:'input', q:'Решите $3x^2 - 12x = 0$. Введите больший корень.', ans:[4] },
|
||||
{ t:'yesno', q:'Уравнение $2x^2 + 8 = 0$ имеет корни.', ok:false },
|
||||
{ t:'input', q:'Корни $x^2 - 16 = 0$ — это $\\pm a$. Найдите $a$.', ans:[4] },
|
||||
{ t:'select', q:'$ax^2 + c = 0$ имеет два корня, если…', opts:['$-c/a > 0$','$c > 0$','$ac > 0$','любое'], ok:0 },
|
||||
]},
|
||||
{ id:'b2', name:'Дискриминатор', sub:'§ 8 · D = b² − 4ac', icon:'D', hp:5, tasks:[
|
||||
{ t:'input', q:'Найдите $D$ для $x^2 - 7x + 12 = 0$.', ans:[1] },
|
||||
{ t:'select', q:'$D < 0$ означает:', opts:['два различных корня','один корень','корней нет'], ok:2 },
|
||||
{ t:'input', q:'Сумма корней $2x^2 - 10x + 8 = 0$ (через $-b/a$):', ans:[5] },
|
||||
{ t:'yesno', q:'У $x^2 + x + 1 = 0$ есть действительные корни.', ok:false },
|
||||
{ t:'input', q:'При каком $m$ уравнение $x^2 - 4x + m = 0$ имеет один корень? $m = ?$', ans:[4] },
|
||||
]},
|
||||
{ id:'b3', name:'Дух Виета', sub:'§ 9 · сумма и произведение', icon:'∑', hp:5, tasks:[
|
||||
{ t:'input', q:'Корни $x^2 - 9x + 20 = 0$. Введите больший.', ans:[5] },
|
||||
{ t:'select', q:'Если $x_1 + x_2 = -p,\\ x_1 x_2 = q$, то корни $\\{2; 7\\}$ дают уравнение:', opts:['$x^2 - 9x + 14 = 0$','$x^2 + 9x + 14 = 0$','$x^2 - 7x + 9 = 0$'], ok:0 },
|
||||
{ t:'yesno', q:'У уравнения $x^2 + 3x + 10 = 0$ корни одного знака.', ok:true },
|
||||
{ t:'input', q:'Произведение корней $x^2 + 4x - 21 = 0$.', ans:[-21] },
|
||||
{ t:'select', q:'Знаки корней $x^2 - 5x + 6 = 0$:', opts:['оба «+»','оба «−»','разные'], ok:0 },
|
||||
]},
|
||||
{ id:'b4', name:'Разложитель', sub:'§ 10 · a(x−x₁)(x−x₂)', icon:'( )', hp:5, tasks:[
|
||||
{ t:'select', q:'$x^2 - 4 = ?$', opts:['$(x-2)(x+2)$','$(x-4)(x+1)$','$(x-2)^2$','не раскладывается'], ok:0 },
|
||||
{ t:'yesno', q:'Трёхчлен $x^2 + 9$ раскладывается на множители первой степени с действительными коэффициентами.', ok:false },
|
||||
{ t:'input', q:'Корни трёхчлена $x^2 - 7x + 12$. Меньший:', ans:[3] },
|
||||
{ t:'select', q:'$\\dfrac{x^2-1}{x^2+x-2}$ сокращается до:', opts:['$\\dfrac{x+1}{x+2}$','$\\dfrac{x-1}{x+2}$','$\\dfrac{1}{x+2}$'], ok:0 },
|
||||
{ t:'input', q:'Найдите $x_1 \\cdot x_2$ для $2x^2 - 7x + 3$ (по Виета $c/a$).', ans:[1.5] },
|
||||
]},
|
||||
{ id:'b5', name:'Архивариус задач', sub:'§ 11 · текстовые модели', icon:'?', hp:5, tasks:[
|
||||
{ t:'input', q:'Произведение двух последовательных натуральных чисел = 72. Большее:', ans:[9] },
|
||||
{ t:'input', q:'Площадь прямоугольника 35 см², сторона на 2 см больше другой. Меньшая сторона:', ans:[5] },
|
||||
{ t:'select', q:'Двое за 6 ч; первый один на 5 ч быстрее. Уравнение для времени второго $t$:', opts:['$\\dfrac{1}{t-5} + \\dfrac{1}{t} = \\dfrac{1}{6}$','$t + (t-5) = 6$','$6 = t(t-5)$'], ok:0 },
|
||||
{ t:'yesno', q:'В задаче на площадь оба корня уравнения подходят, если оба положительные.', ok:true },
|
||||
{ t:'input', q:'Сумма квадратов двух последовательных натуральных = 41. Меньшее:', ans:[4] },
|
||||
]},
|
||||
{ id:'b6', name:'Мастер замены', sub:'§ 12 · t = x², ОДЗ', icon:'t', hp:5, tasks:[
|
||||
{ t:'input', q:'Сколько корней у $x^4 - 13x^2 + 36 = 0$?', ans:[4] },
|
||||
{ t:'yesno', q:'У уравнения $x^4 + 5x^2 + 4 = 0$ есть действительные корни.', ok:false },
|
||||
{ t:'select', q:'Подходящая замена для $(x^2-1)^2 - 5(x^2-1) + 4 = 0$:', opts:['$t = x^2 - 1$','$t = x^2$','$t = x - 1$'], ok:0 },
|
||||
{ t:'input', q:'Биквадратное $x^4 - 5x^2 + 4$. Больший положительный корень:', ans:[2] },
|
||||
{ t:'select', q:'В уравнении $\\dfrac{1}{x-2} = \\dfrac{x-2}{4}$ посторонний корень — это $x = ?$', opts:['$x = 2$','$x = 4$','$x = 0$'], ok:0 },
|
||||
]},
|
||||
{ id:'b7', name:'Магистр алгебры', sub:'Финал · вся глава', icon:'★', hp:7, tasks:[
|
||||
{ t:'input', q:'$x^2 + 5x + 6 = 0$. Меньший корень:', ans:[-3] },
|
||||
{ t:'select', q:'$2x^2 - 8 = 0 \\Rightarrow x = ?$', opts:['$\\pm 2$','$\\pm 4$','$\\pm\\sqrt{2}$','$\\pm 8$'], ok:0 },
|
||||
{ t:'input', q:'$D$ для $3x^2 + 5x - 2 = 0$:', ans:[49] },
|
||||
{ t:'input', q:'По Виета: $x_1 + x_2$ для $x^2 - 11x + 28$:', ans:[11] },
|
||||
{ t:'select', q:'$x^2 - 9$ разложится в:', opts:['$(x-3)(x+3)$','$(x-9)(x+1)$','$(x-3)^2$'], ok:0 },
|
||||
{ t:'input', q:'$x^4 - 10x^2 + 9 = 0$. Сумма всех корней:', ans:[0] },
|
||||
{ t:'yesno', q:'Уравнение $x^2 = -4$ имеет корни в множестве действительных чисел.', ok:false },
|
||||
]},
|
||||
];
|
||||
|
||||
const BOSS_STATE = (function(){
|
||||
try { return JSON.parse(localStorage.getItem('algebra8_ch2_bosses') || '{}'); } catch(e){ return {}; }
|
||||
})();
|
||||
function saveBosses(){ try{ localStorage.setItem('algebra8_ch2_bosses', JSON.stringify(BOSS_STATE)); }catch(e){} }
|
||||
|
||||
function renderBossGrid(){
|
||||
const g = document.getElementById('boss-grid');
|
||||
g.innerHTML = '';
|
||||
BOSSES.forEach(b=>{
|
||||
const won = BOSS_STATE[b.id];
|
||||
const c = document.createElement('div');
|
||||
c.style.cssText = 'background:' + (won ? 'linear-gradient(135deg,var(--ok-bg),#d1fae5)' : 'var(--card)') + ';border:1.5px solid ' + (won ? 'var(--ok)' : 'var(--border)') + ';border-radius:10px;padding:10px 12px;cursor:pointer;text-align:center;transition:transform .15s,box-shadow .15s';
|
||||
c.innerHTML = '<div style="font-size:1.6rem;line-height:1;margin-bottom:4px">' + b.icon + '</div><div style="font-family:Unbounded,sans-serif;font-size:.78rem;font-weight:800;color:var(--sec-acc-d)">' + b.name + '</div><div style="font-size:.7rem;color:var(--muted);margin-top:2px">' + b.sub + '</div>' + (won ? '<div style="color:var(--ok);font-weight:700;font-size:.8rem;margin-top:4px">✓ Побеждён</div>' : '<div style="margin-top:4px"><button class="btn small" style="font-size:.72rem">В бой</button></div>');
|
||||
c.addEventListener('click', ()=>startBoss(b.id));
|
||||
c.addEventListener('mouseover', ()=>{ c.style.transform='translateY(-2px)'; c.style.boxShadow='var(--sh2)'; });
|
||||
c.addEventListener('mouseout', ()=>{ c.style.transform=''; c.style.boxShadow=''; });
|
||||
g.appendChild(c);
|
||||
});
|
||||
if(window.renderMathInElement) renderMath(g);
|
||||
}
|
||||
|
||||
let currentBoss = null, taskIdx = 0, hpLeft = 0;
|
||||
|
||||
function startBoss(id){
|
||||
const b = BOSSES.find(x => x.id === id);
|
||||
if(!b) return;
|
||||
currentBoss = b; taskIdx = 0; hpLeft = b.hp;
|
||||
document.getElementById('boss-arena').style.display = 'block';
|
||||
document.getElementById('boss-name').textContent = b.name;
|
||||
document.getElementById('boss-subname').textContent = b.sub;
|
||||
document.getElementById('boss-emoji').textContent = b.icon;
|
||||
showTask();
|
||||
}
|
||||
function showTask(){
|
||||
const t = currentBoss.tasks[taskIdx];
|
||||
if(!t){ winBoss(); return; }
|
||||
document.getElementById('boss-hp').style.width = (hpLeft / currentBoss.hp * 100) + '%';
|
||||
const tEl = document.getElementById('boss-task');
|
||||
tEl.innerHTML = '<div style="font-size:.75rem;color:var(--muted);margin-bottom:6px">Задание ' + (taskIdx + 1) + ' / ' + currentBoss.tasks.length + '</div><div style="font-size:1.05rem">' + t.q + '</div>';
|
||||
renderMath(tEl);
|
||||
const opts = document.getElementById('boss-opts'); opts.innerHTML = '';
|
||||
document.getElementById('boss-fb').style.display = 'none';
|
||||
if(t.t === 'select'){
|
||||
t.opts.forEach((o,k)=>{
|
||||
const b = document.createElement('button');
|
||||
b.className = 'btn'; b.innerHTML = o; b.style.cssText = 'text-align:left';
|
||||
b.addEventListener('click', ()=>checkAnswer(k === t.ok, b));
|
||||
opts.appendChild(b);
|
||||
});
|
||||
renderMath(opts);
|
||||
} else if(t.t === 'yesno'){
|
||||
['Да','Нет'].forEach((lab, k)=>{
|
||||
const b = document.createElement('button');
|
||||
b.className = 'btn'; b.textContent = lab;
|
||||
b.addEventListener('click', ()=>checkAnswer((k === 0) === t.ok, b));
|
||||
opts.appendChild(b);
|
||||
});
|
||||
} else if(t.t === 'input'){
|
||||
const wrap = document.createElement('div');
|
||||
wrap.style.cssText = 'display:flex;gap:8px;align-items:center';
|
||||
const inp = document.createElement('input');
|
||||
inp.type = 'text'; inp.placeholder = 'ваш ответ';
|
||||
inp.style.cssText = 'flex:1;padding:8px;border:1.5px solid var(--border);border-radius:8px';
|
||||
const go = document.createElement('button'); go.className = 'btn primary'; go.textContent = 'Ответ';
|
||||
go.addEventListener('click', ()=>{
|
||||
const u = parseFloat(inp.value.replace(',','.'));
|
||||
const ok = t.ans.some(a => Math.abs(u - a) < 1e-6);
|
||||
checkAnswer(ok, go);
|
||||
});
|
||||
inp.addEventListener('keyup', e=>{ if(e.key === 'Enter') go.click(); });
|
||||
wrap.appendChild(inp); wrap.appendChild(go); opts.appendChild(wrap);
|
||||
}
|
||||
}
|
||||
function checkAnswer(ok, btn){
|
||||
const fb = document.getElementById('boss-fb'); fb.style.display = 'block';
|
||||
if(ok){
|
||||
if(btn) btn.classList.add('ok');
|
||||
feedback(fb, true, '✓ Точное попадание!');
|
||||
taskIdx++;
|
||||
setTimeout(showTask, 700);
|
||||
} else {
|
||||
if(btn) btn.classList.add('fail');
|
||||
hpLeft = Math.max(0, hpLeft - 0);
|
||||
feedback(fb, false, '✗ Промах! Попробуйте ещё.');
|
||||
}
|
||||
}
|
||||
function winBoss(){
|
||||
BOSS_STATE[currentBoss.id] = 1; saveBosses();
|
||||
achievement('boss_' + currentBoss.id, 'Победил: ' + currentBoss.name);
|
||||
bumpProgress('final2', 14); confetti();
|
||||
document.getElementById('boss-task').innerHTML = '<div style="text-align:center;padding:20px"><div style="font-size:3rem">' + currentBoss.icon + '</div><h3 style="color:var(--ok);margin:10px 0">Победа!</h3><p>Босс <b>«' + currentBoss.name + '»</b> повержен.</p></div>';
|
||||
document.getElementById('boss-opts').innerHTML = '<button class="btn primary" id="boss-back">К списку боссов</button>';
|
||||
document.getElementById('boss-fb').style.display = 'none';
|
||||
document.getElementById('boss-back').addEventListener('click', closeBoss);
|
||||
renderBossGrid();
|
||||
if(BOSSES.every(b => BOSS_STATE[b.id])){
|
||||
setTimeout(()=>{ achievement('all_bosses', 'Магистр квадратных уравнений!'); confetti(); refreshCert(); }, 800);
|
||||
}
|
||||
}
|
||||
function closeBoss(){ document.getElementById('boss-arena').style.display = 'none'; currentBoss = null; }
|
||||
document.getElementById('boss-quit').addEventListener('click', closeBoss);
|
||||
renderBossGrid();
|
||||
|
||||
/* ===== PRACTICE ===== */
|
||||
(function(){
|
||||
let cur = null, total = 0, score = 0, streak = 0;
|
||||
function gen(){
|
||||
const t = Math.floor(Math.random()*5);
|
||||
if(t === 0){
|
||||
const r1 = -5 + Math.floor(Math.random()*11), r2 = -5 + Math.floor(Math.random()*11);
|
||||
if(r1 === r2) return gen();
|
||||
const b = -(r1+r2), c = r1*r2;
|
||||
return { q:'Решите $x^2 ' + (b >= 0 ? '+ ' + b : '- ' + Math.abs(b)) + 'x ' + (c >= 0 ? '+ ' + c : '- ' + Math.abs(c)) + ' = 0$. Введите больший корень.', ans:[Math.max(r1, r2)] };
|
||||
}
|
||||
if(t === 1){
|
||||
const r = 1 + Math.floor(Math.random()*7);
|
||||
return { q:'$x^2 - ' + (r*r) + ' = 0 \\Rightarrow x = \\pm ?$', ans:[r] };
|
||||
}
|
||||
if(t === 2){
|
||||
const r1 = 1 + Math.floor(Math.random()*7), r2 = -(1 + Math.floor(Math.random()*7));
|
||||
const b = -(r1+r2), c = r1*r2;
|
||||
return { q:'Сумма корней $x^2 ' + (b >= 0 ? '+ ' + b : '- ' + Math.abs(b)) + 'x ' + (c >= 0 ? '+ ' + c : '- ' + Math.abs(c)) + ' = 0$?', ans:[r1+r2] };
|
||||
}
|
||||
if(t === 3){
|
||||
const a = 1 + Math.floor(Math.random()*3), b = -(2 + Math.floor(Math.random()*8)), c = 1 + Math.floor(Math.random()*6);
|
||||
return { q:'Найдите $D$ для $' + a + 'x^2 ' + (b >= 0 ? '+ ' + b : '- ' + Math.abs(b)) + 'x ' + (c >= 0 ? '+ ' + c : '- ' + Math.abs(c)) + ' = 0$', ans:[b*b - 4*a*c] };
|
||||
}
|
||||
const r = 1 + Math.floor(Math.random()*4);
|
||||
return { q:'Биквадратное $x^4 - ' + (r*r + 1) + 'x^2 + ' + (r*r) + ' = 0$. Сколько корней?', ans:[r === 1 ? 2 : 4] };
|
||||
}
|
||||
function show(){
|
||||
cur = gen();
|
||||
document.getElementById('prac-task').innerHTML = cur.q;
|
||||
renderMath(document.getElementById('prac-task'));
|
||||
document.getElementById('prac-inp').value = '';
|
||||
document.getElementById('prac-fb').style.display = 'none';
|
||||
}
|
||||
document.getElementById('prac-go').addEventListener('click', ()=>{
|
||||
const fb = document.getElementById('prac-fb'); fb.style.display = 'block';
|
||||
const u = parseFloat(document.getElementById('prac-inp').value.replace(',','.'));
|
||||
const ok = cur.ans.some(a => Math.abs(u - a) < 1e-6);
|
||||
total++; if(ok){ score++; streak++; feedback(fb, true, '✓'); if(streak === 5){ achievement('prac_streak', 'Серия из 5!'); confetti(); } }
|
||||
else { streak = 0; feedback(fb, false, 'Правильно: ' + cur.ans.join(', ')); }
|
||||
document.getElementById('prac-i').textContent = total;
|
||||
document.getElementById('prac-score').textContent = score;
|
||||
document.getElementById('prac-streak').textContent = streak;
|
||||
if(total >= 5) { bumpProgress('final2', 4); }
|
||||
});
|
||||
document.getElementById('prac-next').addEventListener('click', show);
|
||||
document.getElementById('prac-inp').addEventListener('keyup', e=>{ if(e.key === 'Enter') document.getElementById('prac-go').click(); });
|
||||
show();
|
||||
})();
|
||||
|
||||
/* CERTIFICATE */
|
||||
function refreshCert(){
|
||||
const won = BOSSES.filter(b => BOSS_STATE[b.id]).length;
|
||||
const cs = document.getElementById('cert-state');
|
||||
if(!cs) return;
|
||||
if(won === BOSSES.length){
|
||||
cs.innerHTML = '<div style="padding:18px;background:linear-gradient(135deg,#fef3c7,#fde68a);border:2px solid #d97706;border-radius:12px;text-align:center"><div style="font-family:Unbounded,sans-serif;font-size:1.2rem;font-weight:900;color:#92400e">МАГИСТР КВАДРАТНЫХ УРАВНЕНИЙ</div><div style="font-size:.9rem;color:#78350f;margin-top:4px">Все 7 боссов главы 2 повержены — вы освоили §§ 7–12.</div></div>';
|
||||
} else {
|
||||
cs.innerHTML = 'Побеждено боссов: <b>' + won + ' / ' + BOSSES.length + '</b>. Победите всех, чтобы получить титул.';
|
||||
}
|
||||
}
|
||||
refreshCert();
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
|
||||
Reference in New Issue
Block a user