feat(alg9 ch4 final): Финал Главы 4 «Прогрессии» (5 боссов + ачивка)
This commit is contained in:
@@ -2304,21 +2304,231 @@ function buildP19(){
|
||||
}
|
||||
|
||||
function buildFinal4(){
|
||||
const root = document.getElementById('final4-body');
|
||||
root.innerHTML = `
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<span class="card-icon theory">${ICONS.theory}</span>
|
||||
<span class="card-title">В разработке</span>
|
||||
<span class="card-num">★</span>
|
||||
const box = document.getElementById('final4-body');
|
||||
let html = '';
|
||||
|
||||
/* Часть А — Шпаргалка главы (6 mini-карточек) */
|
||||
html += `<div class="card">
|
||||
<div class="card-header">
|
||||
<span class="card-icon theory">${ICONS.theory}</span>
|
||||
<span class="card-title">Шпаргалка главы 4</span>
|
||||
<span class="card-num">Итог</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>Все ключевые формулы главы — в одном месте. Просмотри перед боссами!</p>
|
||||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:12px;margin-top:10px">
|
||||
<div style="padding:12px 14px;background:var(--sec-acc-soft);border-radius:11px;border-left:3px solid var(--pri)">
|
||||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="var(--pri2)" stroke-width="2" style="width:18px;height:18px"><circle cx="6" cy="12" r="2"/><circle cx="12" cy="12" r="2"/><circle cx="18" cy="12" r="2"/></svg>
|
||||
<div style="font-family:'Unbounded',sans-serif;font-weight:700;color:var(--pri2);font-size:.92rem">§ 14 · Последовательность</div>
|
||||
</div>
|
||||
<div style="font-size:.95rem">$a_n = f(n)$. Способы: формула, рекуррентно, таблица. Возрастает / убывает / ни то, ни другое.</div>
|
||||
</div>
|
||||
<div style="padding:12px 14px;background:var(--sec-acc-soft);border-radius:11px;border-left:3px solid var(--pri)">
|
||||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="var(--pri2)" stroke-width="2" style="width:18px;height:18px"><path d="M3 17l4-4 4 4 4-8 6 8"/></svg>
|
||||
<div style="font-family:'Unbounded',sans-serif;font-weight:700;color:var(--pri2);font-size:.92rem">§ 15 · Арифм. прогрессия</div>
|
||||
</div>
|
||||
<div style="font-size:.95rem">$a_n = a_1 + (n-1)d$. Разность $d = a_{n+1} - a_n$. Среднее: $a_n = \\dfrac{a_{n-1} + a_{n+1}}{2}$.</div>
|
||||
</div>
|
||||
<div style="padding:12px 14px;background:var(--sec-acc-soft);border-radius:11px;border-left:3px solid var(--pri)">
|
||||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="var(--pri2)" stroke-width="2" style="width:18px;height:18px"><path d="M4 20V8M10 20V4M16 20V12M22 20H2"/></svg>
|
||||
<div style="font-family:'Unbounded',sans-serif;font-weight:700;color:var(--pri2);font-size:.92rem">§ 16 · Сумма арифм.</div>
|
||||
</div>
|
||||
<div style="font-size:.95rem">$S_n = \\dfrac{a_1 + a_n}{2} \\cdot n = \\dfrac{2a_1 + (n-1)d}{2} \\cdot n$. <b>Идея Гаусса</b>: пары с одинаковой суммой.</div>
|
||||
</div>
|
||||
<div style="padding:12px 14px;background:var(--sec-acc-soft);border-radius:11px;border-left:3px solid var(--pri)">
|
||||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="var(--pri2)" stroke-width="2" style="width:18px;height:18px"><path d="M3 21c2-6 6-12 18-18"/></svg>
|
||||
<div style="font-family:'Unbounded',sans-serif;font-weight:700;color:var(--pri2);font-size:.92rem">§ 17 · Геом. прогрессия</div>
|
||||
</div>
|
||||
<div style="font-size:.95rem">$b_n = b_1 q^{n-1}$. Знаменатель $q = \\dfrac{b_{n+1}}{b_n}$. Среднее: $b_n^2 = b_{n-1} \\cdot b_{n+1}$.</div>
|
||||
</div>
|
||||
<div style="padding:12px 14px;background:var(--sec-acc-soft);border-radius:11px;border-left:3px solid var(--pri)">
|
||||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="var(--pri2)" stroke-width="2" style="width:18px;height:18px"><path d="M4 4h16M4 10h16M4 16h10"/></svg>
|
||||
<div style="font-family:'Unbounded',sans-serif;font-weight:700;color:var(--pri2);font-size:.92rem">§ 18 · Сумма геом.</div>
|
||||
</div>
|
||||
<div style="font-size:.95rem">$S_n = \\dfrac{b_1(q^n - 1)}{q - 1}$ при $q \\ne 1$. При $q = 1$: $S_n = n \\cdot b_1$.</div>
|
||||
</div>
|
||||
<div style="padding:12px 14px;background:var(--sec-acc-soft);border-radius:11px;border-left:3px solid var(--pri)">
|
||||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="var(--pri2)" stroke-width="2" style="width:18px;height:18px"><path d="M3 12c4-8 14-8 18 0M3 12c4 8 14 8 18 0"/></svg>
|
||||
<div style="font-family:'Unbounded',sans-serif;font-weight:700;color:var(--pri2);font-size:.92rem">§ 19 · Беск. убывающая</div>
|
||||
</div>
|
||||
<div style="font-size:.95rem">При $|q| < 1$: $S = \\dfrac{b_1}{1 - q}$. Превращает периодические дроби в обыкновенные!</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>Содержание финала главы <b>Финал главы — в разработке</b> будет добавлено в следующих обновлениях.</p>
|
||||
<p style="color:var(--muted);font-size:.9rem">Боссы и итоговые задания будут добавлены в Phase 1.</p>
|
||||
</div>
|
||||
</div>` + secNav('p19', null) + readButton('final4');
|
||||
renderMath(root);
|
||||
wireReadBtn('final4');
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
/* Часть Б — 5 боссов */
|
||||
html += `<div class="card">
|
||||
<div class="card-header">
|
||||
<span class="card-icon rule">${ICONS.rule}</span>
|
||||
<span class="card-title">Боссы главы 4</span>
|
||||
<span class="card-num">5</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>5 интегрированных задач. Каждая комбинирует несколько тем главы 4. За каждого побеждённого босса — <b>+10 XP</b>. Победишь всех — <b>+50 XP бонус</b> и ачивка «Магистр прогрессий»!</p>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
html += '<div id="ch4-bosses-container"></div>';
|
||||
|
||||
html += `<div style="margin-top:18px;padding:18px 20px;background:linear-gradient(135deg,var(--pri-soft),var(--sec-acc-soft));border-radius:14px;border:1.5px solid var(--pri);text-align:center" id="ch4-final-summary">
|
||||
<div style="font-family:'Unbounded',sans-serif;font-weight:800;color:var(--pri2);font-size:1.1rem;margin-bottom:6px">Прогресс по боссам</div>
|
||||
<div id="ch4-boss-overall" style="font-size:.95rem;color:var(--text);margin-bottom:10px">0 / 5 боссов побеждено</div>
|
||||
<div style="height:12px;background:var(--card);border-radius:8px;overflow:hidden;border:1px solid var(--border)">
|
||||
<div id="ch4-boss-overall-fill" style="height:100%;width:0%;background:linear-gradient(90deg,#7c3aed,#a78bfa);transition:width .35s"></div>
|
||||
</div>
|
||||
<div id="ch4-final-reward" style="margin-top:14px;display:none;padding:16px;background:var(--card);border-radius:11px;border:2px solid #f59e0b">
|
||||
<div style="font-family:'Unbounded',sans-serif;font-weight:800;color:#92400e;font-size:1.15rem;margin-bottom:6px">Магистр прогрессий</div>
|
||||
<div style="font-size:.95rem;margin-bottom:8px"><b>Алгебра 9 пройдена!</b> Все 4 главы изучены. Готовы к Геометрии 9!</div>
|
||||
<div style="font-size:.9rem;color:var(--muted);margin-bottom:12px">+50 XP бонус начислены.</div>
|
||||
<a class="btn primary" href="/textbook/algebra-9" style="text-decoration:none">К хабу Алгебры 9 <svg class="ic" viewBox="0 0 24 24"><polyline points="9 18 15 12 9 6"/></svg></a>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
html += secNav('p19', null);
|
||||
|
||||
box.innerHTML = html;
|
||||
renderMath(box);
|
||||
|
||||
/* Боссы */
|
||||
const BOSSES = [
|
||||
{
|
||||
n:1, color:'#10b981',
|
||||
title:'Гном Арифметики',
|
||||
tag:'§ 15 + § 16',
|
||||
q:'В арифметической прогрессии $a_1 = 3$, $d = 4$. Найди $S_{10}$.',
|
||||
ans:210,
|
||||
hint:'$a_{10} = a_1 + 9d = 3 + 9 \\cdot 4 = 39$. Тогда $S_{10} = \\dfrac{a_1 + a_{10}}{2} \\cdot 10 = \\dfrac{3 + 39}{2} \\cdot 10 = \\mathbf{210}$.'
|
||||
},
|
||||
{
|
||||
n:2, color:'#0891b2',
|
||||
title:'Эльф Геометрии',
|
||||
tag:'§ 17 + § 18',
|
||||
q:'В геометрической прогрессии $b_1 = 2$, $q = 3$. Найди $S_5$.',
|
||||
ans:242,
|
||||
hint:'$S_5 = \\dfrac{b_1(q^5 - 1)}{q - 1} = \\dfrac{2(243 - 1)}{3 - 1} = \\dfrac{2 \\cdot 242}{2} = \\mathbf{242}$.'
|
||||
},
|
||||
{
|
||||
n:3, color:'#7c3aed',
|
||||
title:'Орк Сходимости',
|
||||
tag:'§ 19 — синтез',
|
||||
q:'Преврати периодическую дробь $0{,}\\overline{18}$ в обыкновенную и введи <b>знаменатель</b> несократимой дроби.',
|
||||
ans:11,
|
||||
hint:'$0{,}\\overline{18} = \\dfrac{0{,}18}{1 - 0{,}01} = \\dfrac{18}{99} = \\dfrac{2}{11}$. Знаменатель: $\\mathbf{11}$.'
|
||||
},
|
||||
{
|
||||
n:4, color:'#dc2626',
|
||||
title:'Маг Двух Прогрессий',
|
||||
tag:'§ 15 + § 17',
|
||||
q:'Числа $x, y, z$ — арифм. прогрессия; числа $x, y-1, z$ — геом. прогрессия. Если $x + y + z = 12$, найди $y$.',
|
||||
ans:4,
|
||||
hint:'Из арифм.: $y = \\dfrac{x + z}{2} \\Rightarrow x + z = 2y$. Тогда $x + y + z = 3y = 12 \\Rightarrow y = \\mathbf{4}$. (Проверка геом.: $(y-1)^2 = xz$, т.е. $9 = xz$ с $x+z = 8$ — корни $t^2 - 8t + 9 = 0$, всё ок.)'
|
||||
},
|
||||
{
|
||||
n:5, color:'#f59e0b',
|
||||
title:'Архимаг Прогрессий',
|
||||
tag:'§§ 14–19 — синтез',
|
||||
q:'В геометрической прогрессии $b_1 = 16$, $q = \\dfrac{1}{2}$. Найди <b>сумму</b> бесконечно убывающей прогрессии.',
|
||||
ans:32,
|
||||
hint:'$|q| = \\dfrac{1}{2} < 1$ — формула работает. $S = \\dfrac{b_1}{1 - q} = \\dfrac{16}{1 - 1/2} = \\dfrac{16}{1/2} = \\mathbf{32}$.'
|
||||
},
|
||||
];
|
||||
|
||||
const cont = document.getElementById('ch4-bosses-container');
|
||||
const STATE_KEY = 'algebra9_ch4_bosses';
|
||||
const BOSS_STATE = (function(){
|
||||
try{ const s = localStorage.getItem(STATE_KEY); if(s) return JSON.parse(s); }catch(e){}
|
||||
return BOSSES.map(()=>({defeated:false}));
|
||||
})();
|
||||
function saveBosses(){ try{ localStorage.setItem(STATE_KEY, JSON.stringify(BOSS_STATE)); }catch(e){} }
|
||||
|
||||
cont.innerHTML = BOSSES.map((b, idx)=>{
|
||||
return '<div class="boss-card" id="boss4-'+b.n+'-card" style="padding:16px;background:var(--card);border-radius:12px;border:2px solid '+b.color+';margin-bottom:14px">'
|
||||
+'<div style="display:flex;align-items:center;gap:10px;margin-bottom:10px;flex-wrap:wrap">'
|
||||
+'<svg viewBox="0 0 24 24" fill="none" stroke="'+b.color+'" stroke-width="2.2" style="width:28px;height:28px;flex-shrink:0"><polygon points="12,2 22,20 2,20"/></svg>'
|
||||
+'<div style="font-family:\'Unbounded\',sans-serif;font-weight:800;color:'+b.color+';font-size:1.05rem">Босс '+b.n+': '+b.title+'</div>'
|
||||
+'<div style="margin-left:auto;font-size:.78rem;color:var(--muted);padding:3px 8px;background:var(--sec-acc-soft);border-radius:6px">'+b.tag+'</div>'
|
||||
+'</div>'
|
||||
+'<div id="boss4-'+b.n+'-q" style="padding:12px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:1rem;line-height:1.5;margin-bottom:10px">'+b.q+'</div>'
|
||||
+'<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap">'
|
||||
+'<span style="font-family:\'JetBrains Mono\',monospace;font-size:.92rem">ответ =</span>'
|
||||
+'<input type="number" id="boss4-'+b.n+'-ans" class="tinp" style="width:120px;text-align:center" placeholder="число">'
|
||||
+'<button class="btn primary" id="boss4-'+b.n+'-go" style="background:'+b.color+';border-color:'+b.color+'">Атаковать</button>'
|
||||
+'<button class="btn" id="boss4-'+b.n+'-hint">Подсказка</button>'
|
||||
+'</div>'
|
||||
+'<div class="feedback" id="boss4-'+b.n+'-fb"></div>'
|
||||
+'</div>';
|
||||
}).join('');
|
||||
renderMath(cont);
|
||||
|
||||
function refreshOverall(){
|
||||
const won = BOSS_STATE.filter(s => s.defeated).length;
|
||||
const txt = document.getElementById('ch4-boss-overall');
|
||||
const fill = document.getElementById('ch4-boss-overall-fill');
|
||||
if(txt) txt.textContent = won + ' / ' + BOSSES.length + ' боссов побеждено';
|
||||
if(fill) fill.style.width = (won * 100 / BOSSES.length) + '%';
|
||||
if(won >= BOSSES.length){
|
||||
const reward = document.getElementById('ch4-final-reward');
|
||||
if(reward && reward.style.display === 'none'){
|
||||
reward.style.display = 'block';
|
||||
if(!STATE.achievements.has('ch4_done')){
|
||||
achievement('ch4_done','Магистр прогрессий');
|
||||
addXp(50, 'ch4-bonus');
|
||||
bumpProgress('final4', 30);
|
||||
if(window.confetti){ try{ confetti(); }catch(e){} }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOSSES.forEach((b, idx)=>{
|
||||
const card = document.getElementById('boss4-'+b.n+'-card');
|
||||
const goBtn = document.getElementById('boss4-'+b.n+'-go');
|
||||
const hintBtn = document.getElementById('boss4-'+b.n+'-hint');
|
||||
const ansInp = document.getElementById('boss4-'+b.n+'-ans');
|
||||
if(BOSS_STATE[idx].defeated){
|
||||
card.style.background = 'linear-gradient(135deg,var(--sec-acc-soft),var(--pri-soft))';
|
||||
goBtn.disabled = true; goBtn.style.opacity = .55; goBtn.textContent = '✓ Повержен';
|
||||
ansInp.disabled = true;
|
||||
}
|
||||
goBtn.addEventListener('click', ()=>{
|
||||
if(BOSS_STATE[idx].defeated) return;
|
||||
const fb = document.getElementById('boss4-'+b.n+'-fb');
|
||||
const val = parseInt(ansInp.value, 10);
|
||||
if(isNaN(val)){ feedback(fb, false, '✗ Введи целое число.'); return; }
|
||||
if(val === b.ans){
|
||||
BOSS_STATE[idx].defeated = true; saveBosses();
|
||||
feedback(fb, true, '✓ Босс '+b.n+' повержен! +10 XP. '+b.hint);
|
||||
addXp(10, 'boss-ch4-'+b.n);
|
||||
bumpProgress('final4', 18);
|
||||
goBtn.disabled = true; goBtn.style.opacity = .55; goBtn.textContent = '✓ Повержен';
|
||||
ansInp.disabled = true;
|
||||
card.style.background = 'linear-gradient(135deg,var(--sec-acc-soft),var(--pri-soft))';
|
||||
refreshOverall();
|
||||
} else {
|
||||
feedback(fb, false, '✗ Промах. Попробуй ещё. Подсказка доступна.');
|
||||
}
|
||||
});
|
||||
hintBtn.addEventListener('click', ()=>{
|
||||
const fb = document.getElementById('boss4-'+b.n+'-fb');
|
||||
fb.className = 'feedback ok';
|
||||
fb.innerHTML = '<b>Подсказка:</b> '+b.hint;
|
||||
fb.style.display = 'block';
|
||||
fb.style.background = 'var(--warn-bg)';
|
||||
fb.style.color = '#92400e';
|
||||
fb.style.borderLeftColor = 'var(--warn)';
|
||||
renderMath(fb);
|
||||
});
|
||||
ansInp.addEventListener('keydown', e=>{ if(e.key === 'Enter') goBtn.click(); });
|
||||
});
|
||||
|
||||
refreshOverall();
|
||||
}
|
||||
|
||||
/* ===== Search ===== */
|
||||
|
||||
Reference in New Issue
Block a user