feat(geom8): Wave 5 — финал Главы 2 (шпаргалка, карта связей, 7 боссов)

Часть 1 — Итоговая шпаргалка: 15 mini-cards с SVG-иконкой и формулой
в KaTeX для каждого § (от S=a² до пифагоровых троек).

Часть 2 — Карта связей (интерактивная SVG 620×340):
кликабельные узлы 'Площадь' → 'Прямоуг. фигуры' / 'Параллелограммы' /
'Треугольники' → конкретные фигуры. Клик показывает формулу площади.

Часть 3 — 7 боссов (по 10 XP):
  Босс 1: прямоугольный 9-12 → c=15, h_c=7.2, S=54
  Босс 2: параллелограмм 14×8 с углом 30° → h=4, S=56
  Босс 3: трапеция 18/12/5 → m=15, S=75
  Босс 4: ромб d₁=16 d₂=12 → S=96, a=10, P=40
  Босс 5: медиана и центроид (S=36) → S/6=6, S/2=18
  Босс 6: равносторонний a=10 → h, S, расстояние от центроида
  Босс 7: пифагорова тройка 5-12-13 (P=30, c=13) → катеты, S=30

Часть 4 — Финальная плашка: confetti + achievement
'Мастер площадей Главы 2' + 50 XP бонус + кнопка перехода к Главе 3.

File: 6519 → 7133 LOC. ГЛАВА 2 ПОЛНОСТЬЮ ЗАВЕРШЕНА.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-05-28 13:40:25 +03:00
parent e424bc231c
commit 1d39a1c7ea
+616 -2
View File
@@ -376,7 +376,7 @@ 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(),p13:()=>buildP13(),p14:()=>buildP14(),p15:()=>buildP15(),
final2:()=>buildFinal2stub(),
final2:()=>buildFinal2(),
};
function ensureBuilt(id){ if(BUILT.has(id))return;const fn=BUILDERS[id];if(fn){fn();BUILT.add(id);} }
function goTo(id){
@@ -6513,7 +6513,621 @@ function buildP15(){
if(window.renderMathInElement) renderMath(bossBox);
})();
}
function buildFinal2stub(){ document.getElementById('final2-body').innerHTML='<div class="card"><div class="card-body"><p><b>Финал главы 2 — Волна 1</b>: боссы и итоги появятся в следующем обновлении.</p></div></div>'+secNav('p15',null); }
function buildFinal2(){
const box = document.getElementById('final2-body');
let html = '';
/* === ЧАСТЬ 1: Итоговая шпаргалка === */
html += `<div class="card" style="border-color:var(--sec-acc,var(--pri));background:linear-gradient(135deg,var(--card),var(--sec-acc-soft,var(--pri-soft)))">
<div class="card-header">
<div class="card-icon theory">
<svg class="ic" viewBox="0 0 24 24"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>
</div>
<div class="card-title">Итоговая шпаргалка · Вся Глава 2 «Площади»</div>
</div>
<div class="card-body">
<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:10px">
<div style="background:var(--card);border:1.5px solid var(--border);border-radius:11px;padding:12px">
<div style="font-family:'Unbounded',sans-serif;font-size:.65rem;font-weight:800;color:var(--sec-acc-d,var(--pri2));text-transform:uppercase;letter-spacing:.07em;margin-bottom:7px">§1 Квадрат</div>
<div style="display:flex;align-items:center;gap:10px">
<svg viewBox="0 0 64 60" style="width:64px;height:60px;flex-shrink:0"><rect x="10" y="8" width="44" height="44" fill="rgba(5,150,105,.12)" stroke="#059669" stroke-width="2"/><text x="32" y="32" text-anchor="middle" dominant-baseline="middle" font-size="9" fill="#047857" font-family="JetBrains Mono,monospace">a</text><text x="32" y="56" text-anchor="middle" font-size="8" fill="#059669" font-family="JetBrains Mono,monospace">a</text></svg>
<div>
<p style="font-size:.9rem;margin-bottom:4px">$S = a^2$</p>
<p style="font-size:.78rem;color:var(--muted)">$P = 4a$</p>
</div>
</div>
</div>
<div style="background:var(--card);border:1.5px solid var(--border);border-radius:11px;padding:12px">
<div style="font-family:'Unbounded',sans-serif;font-size:.65rem;font-weight:800;color:var(--sec-acc-d,var(--pri2));text-transform:uppercase;letter-spacing:.07em;margin-bottom:7px">§2 Прямоугольник</div>
<div style="display:flex;align-items:center;gap:10px">
<svg viewBox="0 0 64 60" style="width:64px;height:60px;flex-shrink:0"><rect x="6" y="14" width="52" height="32" fill="rgba(8,145,178,.12)" stroke="#0891b2" stroke-width="2"/><text x="32" y="10" text-anchor="middle" font-size="8" fill="#0891b2" font-family="JetBrains Mono,monospace">a</text><text x="62" y="32" font-size="8" fill="#0891b2" font-family="JetBrains Mono,monospace">b</text></svg>
<div>
<p style="font-size:.9rem;margin-bottom:4px">$S = a \cdot b$</p>
<p style="font-size:.78rem;color:var(--muted)">$P = 2(a+b)$</p>
</div>
</div>
</div>
<div style="background:var(--card);border:1.5px solid var(--border);border-radius:11px;padding:12px">
<div style="font-family:'Unbounded',sans-serif;font-size:.65rem;font-weight:800;color:var(--sec-acc-d,var(--pri2));text-transform:uppercase;letter-spacing:.07em;margin-bottom:7px">§3 Параллелограмм</div>
<div style="display:flex;align-items:center;gap:10px">
<svg viewBox="0 0 64 60" style="width:64px;height:60px;flex-shrink:0"><polygon points="14,52 54,52 50,12 10,12" fill="rgba(139,92,246,.12)" stroke="#8b5cf6" stroke-width="2"/><line x1="14" y1="12" x2="14" y2="52" stroke="#8b5cf6" stroke-width="1.5" stroke-dasharray="3 2"/><text x="32" y="58" text-anchor="middle" font-size="8" fill="#8b5cf6" font-family="JetBrains Mono,monospace">a</text><text x="6" y="34" font-size="8" fill="#6d28d9" font-family="JetBrains Mono,monospace">h</text></svg>
<div>
<p style="font-size:.9rem;margin-bottom:4px">$S = a \cdot h$</p>
<p style="font-size:.78rem;color:var(--muted)">$h$ — высота</p>
</div>
</div>
</div>
<div style="background:var(--card);border:1.5px solid var(--border);border-radius:11px;padding:12px">
<div style="font-family:'Unbounded',sans-serif;font-size:.65rem;font-weight:800;color:var(--sec-acc-d,var(--pri2));text-transform:uppercase;letter-spacing:.07em;margin-bottom:7px">§4 Треугольник</div>
<div style="display:flex;align-items:center;gap:10px">
<svg viewBox="0 0 64 60" style="width:64px;height:60px;flex-shrink:0"><polygon points="32,6 8,54 56,54" fill="rgba(217,119,6,.12)" stroke="#d97706" stroke-width="2"/><line x1="32" y1="6" x2="32" y2="54" stroke="#d97706" stroke-width="1.5" stroke-dasharray="3 2"/><path d="M32,54 L32,46 L40,46" fill="none" stroke="#d97706" stroke-width="1.5"/><text x="36" y="36" font-size="8" fill="#b45309" font-family="JetBrains Mono,monospace">h</text><text x="32" y="60" text-anchor="middle" font-size="8" fill="#b45309" font-family="JetBrains Mono,monospace">a</text></svg>
<div>
<p style="font-size:.9rem;margin-bottom:4px">$S = \\dfrac{1}{2}ah$</p>
<p style="font-size:.78rem;color:var(--muted)">$a$ — основание</p>
</div>
</div>
</div>
<div style="background:var(--card);border:1.5px solid var(--border);border-radius:11px;padding:12px">
<div style="font-family:'Unbounded',sans-serif;font-size:.65rem;font-weight:800;color:var(--sec-acc-d,var(--pri2));text-transform:uppercase;letter-spacing:.07em;margin-bottom:7px">§5 Трапеция</div>
<div style="display:flex;align-items:center;gap:10px">
<svg viewBox="0 0 64 60" style="width:64px;height:60px;flex-shrink:0"><polygon points="10,52 54,52 46,12 18,12" fill="rgba(20,184,166,.12)" stroke="#14b8a6" stroke-width="2"/><text x="32" y="10" text-anchor="middle" font-size="7" fill="#0f766e" font-family="JetBrains Mono,monospace">b</text><text x="32" y="58" text-anchor="middle" font-size="7" fill="#0f766e" font-family="JetBrains Mono,monospace">a</text></svg>
<div>
<p style="font-size:.9rem;margin-bottom:4px">$S = \\dfrac{(a+b)}{2} h$</p>
<p style="font-size:.78rem;color:var(--muted)">$a,b$ — основания</p>
</div>
</div>
</div>
<div style="background:var(--card);border:1.5px solid var(--border);border-radius:11px;padding:12px">
<div style="font-family:'Unbounded',sans-serif;font-size:.65rem;font-weight:800;color:var(--sec-acc-d,var(--pri2));text-transform:uppercase;letter-spacing:.07em;margin-bottom:7px">§6 Ромб</div>
<div style="display:flex;align-items:center;gap:10px">
<svg viewBox="0 0 64 60" style="width:64px;height:60px;flex-shrink:0"><polygon points="32,4 60,30 32,56 4,30" fill="rgba(236,72,153,.12)" stroke="#ec4899" stroke-width="2"/><line x1="4" y1="30" x2="60" y2="30" stroke="#ec4899" stroke-width="1.2" stroke-dasharray="3 2"/><line x1="32" y1="4" x2="32" y2="56" stroke="#ec4899" stroke-width="1.2" stroke-dasharray="3 2"/><text x="36" y="28" font-size="7" fill="#be185d" font-family="JetBrains Mono,monospace">d₁</text><text x="33" y="22" font-size="7" fill="#be185d" font-family="JetBrains Mono,monospace">d₂</text></svg>
<div>
<p style="font-size:.9rem;margin-bottom:4px">$S = \\dfrac{d_1 d_2}{2}$</p>
<p style="font-size:.78rem;color:var(--muted)">$= ah = a^2 \\sin\\alpha$</p>
</div>
</div>
</div>
<div style="background:var(--card);border:1.5px solid var(--border);border-radius:11px;padding:12px">
<div style="font-family:'Unbounded',sans-serif;font-size:.65rem;font-weight:800;color:var(--sec-acc-d,var(--pri2));text-transform:uppercase;letter-spacing:.07em;margin-bottom:7px">§7 Прям. треугольник</div>
<div style="display:flex;align-items:center;gap:10px">
<svg viewBox="0 0 64 60" style="width:64px;height:60px;flex-shrink:0"><polygon points="10,50 10,10 50,50" fill="rgba(16,185,129,.12)" stroke="#10b981" stroke-width="2"/><path d="M10,50 L10,42 L18,42" fill="none" stroke="#10b981" stroke-width="1.5"/><text x="4" y="32" font-size="8" fill="#047857" font-family="JetBrains Mono,monospace">a</text><text x="28" y="56" font-size="8" fill="#047857" font-family="JetBrains Mono,monospace">b</text></svg>
<div>
<p style="font-size:.9rem;margin-bottom:4px">$S = \\dfrac{1}{2}ab$</p>
<p style="font-size:.78rem;color:var(--muted)">$a,b$ — катеты</p>
</div>
</div>
</div>
<div style="background:var(--card);border:1.5px solid var(--border);border-radius:11px;padding:12px">
<div style="font-family:'Unbounded',sans-serif;font-size:.65rem;font-weight:800;color:var(--sec-acc-d,var(--pri2));text-transform:uppercase;letter-spacing:.07em;margin-bottom:7px">§8 Высота к гипотенузе</div>
<div style="display:flex;align-items:center;gap:10px">
<svg viewBox="0 0 64 60" style="width:64px;height:60px;flex-shrink:0"><polygon points="8,52 56,52 8,8" fill="rgba(245,158,11,.12)" stroke="#f59e0b" stroke-width="2"/><path d="M8,8 L30,52" fill="none" stroke="#f59e0b" stroke-width="1.5" stroke-dasharray="3 2"/><line x1="8" y1="8" x2="30" y2="52" stroke="#f59e0b" stroke-width="1.5" stroke-dasharray="3 2"/><path d="M8,52 L8,44 L16,44" fill="none" stroke="#f59e0b" stroke-width="1.5"/><text x="20" y="46" font-size="7" fill="#b45309" font-family="JetBrains Mono,monospace">h_c</text></svg>
<div>
<p style="font-size:.9rem;margin-bottom:4px">$h_c = \\dfrac{ab}{c}$</p>
<p style="font-size:.78rem;color:var(--muted)">$c$ — гипотенуза</p>
</div>
</div>
</div>
<div style="background:var(--card);border:1.5px solid var(--border);border-radius:11px;padding:12px">
<div style="font-family:'Unbounded',sans-serif;font-size:.65rem;font-weight:800;color:var(--sec-acc-d,var(--pri2));text-transform:uppercase;letter-spacing:.07em;margin-bottom:7px">§9 Общая высота</div>
<div>
<p style="font-size:.9rem;margin-bottom:4px">$\\dfrac{S_1}{S_2} = \\dfrac{a_1}{a_2}$</p>
<p style="font-size:.78rem;color:var(--muted)">Треугольники с общей высотой</p>
</div>
</div>
<div style="background:var(--card);border:1.5px solid var(--border);border-radius:11px;padding:12px">
<div style="font-family:'Unbounded',sans-serif;font-size:.65rem;font-weight:800;color:var(--sec-acc-d,var(--pri2));text-transform:uppercase;letter-spacing:.07em;margin-bottom:7px">§10 Медиана</div>
<div>
<p style="font-size:.9rem;margin-bottom:4px">$S_{\\text{под}} = \\dfrac{S}{2}$ (медиана)</p>
<p style="font-size:.86rem;margin-bottom:4px">$S_{\\text{части}} = \\dfrac{S}{6}$ (центроид)</p>
<p style="font-size:.78rem;color:var(--muted)">3 медианы → 6 равных</p>
</div>
</div>
<div style="background:var(--card);border:1.5px solid var(--border);border-radius:11px;padding:12px">
<div style="font-family:'Unbounded',sans-serif;font-size:.65rem;font-weight:800;color:var(--sec-acc-d,var(--pri2));text-transform:uppercase;letter-spacing:.07em;margin-bottom:7px">§11 Теорема Пифагора</div>
<div style="display:flex;align-items:center;gap:10px">
<svg viewBox="0 0 64 60" style="width:64px;height:60px;flex-shrink:0"><polygon points="8,52 8,12 48,52" fill="rgba(99,102,241,.12)" stroke="#6366f1" stroke-width="2"/><path d="M8,52 L8,44 L16,44" fill="none" stroke="#6366f1" stroke-width="1.5"/><text x="1" y="32" font-size="8" fill="#4f46e5" font-family="JetBrains Mono,monospace">a</text><text x="24" y="58" font-size="8" fill="#4f46e5" font-family="JetBrains Mono,monospace">b</text><text x="28" y="30" font-size="8" fill="#4f46e5" font-family="JetBrains Mono,monospace">c</text></svg>
<div>
<p style="font-size:.9rem;margin-bottom:4px">$c^2 = a^2 + b^2$</p>
<p style="font-size:.78rem;color:var(--muted)">$c$ — гипотенуза</p>
</div>
</div>
</div>
<div style="background:var(--card);border:1.5px solid var(--border);border-radius:11px;padding:12px">
<div style="font-family:'Unbounded',sans-serif;font-size:.65rem;font-weight:800;color:var(--sec-acc-d,var(--pri2));text-transform:uppercase;letter-spacing:.07em;margin-bottom:7px">§12 Равносторонний</div>
<div>
<p style="font-size:.9rem;margin-bottom:4px">$h = \\dfrac{a\\sqrt{3}}{2}$</p>
<p style="font-size:.86rem;margin-bottom:0">$S = \\dfrac{a^2\\sqrt{3}}{4}$</p>
</div>
</div>
<div style="background:var(--card);border:1.5px solid var(--border);border-radius:11px;padding:12px">
<div style="font-family:'Unbounded',sans-serif;font-size:.65rem;font-weight:800;color:var(--sec-acc-d,var(--pri2));text-transform:uppercase;letter-spacing:.07em;margin-bottom:7px">§13 Диагональ квадрата</div>
<div>
<p style="font-size:.9rem;margin-bottom:4px">$d = a\\sqrt{2}$</p>
<p style="font-size:.78rem;color:var(--muted)">из теор. Пифагора</p>
</div>
</div>
<div style="background:var(--card);border:1.5px solid var(--border);border-radius:11px;padding:12px">
<div style="font-family:'Unbounded',sans-serif;font-size:.65rem;font-weight:800;color:var(--sec-acc-d,var(--pri2));text-transform:uppercase;letter-spacing:.07em;margin-bottom:7px">§14 Обратная теорема</div>
<div>
<p style="font-size:.9rem;margin-bottom:4px">$a^2+b^2=c^2$</p>
<p style="font-size:.78rem;color:var(--muted)">$\\Rightarrow$ угол при $c$ прямой</p>
</div>
</div>
<div style="background:var(--card);border:1.5px solid var(--border);border-radius:11px;padding:12px">
<div style="font-family:'Unbounded',sans-serif;font-size:.65rem;font-weight:800;color:var(--sec-acc-d,var(--pri2));text-transform:uppercase;letter-spacing:.07em;margin-bottom:7px">§15 Пифагоровы тройки</div>
<div>
<p style="font-size:.9rem;margin-bottom:4px">(3, 4, 5)</p>
<p style="font-size:.86rem;margin-bottom:4px">(5, 12, 13)</p>
<p style="font-size:.86rem;margin-bottom:0">(8, 15, 17), (7, 24, 25)</p>
</div>
</div>
</div>
</div>
</div>`;
/* === ЧАСТЬ 2: Карта связей фигур === */
html += `<div class="wg" id="final2-hier-wrap">
<div class="wg-header"><span class="wg-badge">КАРТА СВЯЗЕЙ</span><div class="wg-title">Фигуры и их формулы площади</div></div>
<div class="wg-help">Нажми на фигуру, чтобы увидеть формулу площади и ключевые свойства.</div>
<div id="final2-hier-svg" style="display:flex;justify-content:center;overflow-x:auto"></div>
<div id="final2-hier-info" style="min-height:56px;padding:12px 16px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;margin-top:10px;font-size:.9rem;line-height:1.65;color:var(--text)">Нажми на фигуру в схеме выше</div>
</div>`;
/* === ЧАСТЬ 3: 7 боссов === */
html += `<div class="wg" style="border-color:#059669;background:linear-gradient(135deg,var(--card),#d1fae5)">
<div class="wg-header">
<span class="wg-badge" style="background:#059669">7 БОССОВ ГЛАВЫ 2</span>
<div class="wg-title">Интегрированные задачи</div>
</div>
<div class="wg-help">Каждая задача объединяет 2–3 темы главы. +10 XP за каждого побеждённого босса. Победи всех семерых — получишь +50 XP и достижение «Мастер площадей»!</div>
<div id="final2-bosses"></div>
</div>`;
/* === ЧАСТЬ 4: Финальная плашка === */
html += `<div id="final2-finish" style="display:none;margin-top:20px;padding:24px;background:linear-gradient(135deg,#d1fae5,#ecfdf5);border:2px solid var(--ok,#10b981);border-radius:16px;text-align:center">
<div style="font-family:'Unbounded',sans-serif;font-size:1.2rem;font-weight:900;color:#065f46;margin-bottom:10px">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="width:28px;height:28px;vertical-align:middle;margin-right:6px"><polygon points="12,2 15.09,8.26 22,9.27 17,14.14 18.18,21.02 12,17.77 5.82,21.02 7,14.14 2,9.27 8.91,8.26"/></svg>
Мастер площадей Главы 2!
</div>
<p style="color:#065f46;font-size:.95rem;margin-bottom:16px">Ты победил всех 7 боссов и освоил всю Главу 2 «Площади». Отличная работа!</p>
<a href="/textbook/geometry-8-ch3" class="btn primary" style="font-size:.98rem;padding:12px 28px">
<svg class="ic" viewBox="0 0 24 24"><polyline points="9 18 15 12 9 6"/></svg>
Перейти к Главе 3
</a>
</div>`;
html += `<div style="margin-top:18px;display:flex;justify-content:center">
<button class="btn primary" id="final2-read-btn" onclick="addXp(10,'final2-read');bumpProgress('final2',40);this.textContent='Прочитано!';this.disabled=true;">
<svg class="ic" viewBox="0 0 24 24"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>
Я изучил Главу 2 (+10 XP)
</button>
</div>`;
html += secNav('p15', null);
box.innerHTML = html;
/* === JS: Карта связей SVG === */
(function(){
const W = 620, H = 340;
const nodes = [
{ id:'area', x:310, y:28, rx:58, label:'Площадь',
props:'Площадь — мера части плоскости, занятой фигурой. Выражается в кв. единицах.' },
{ id:'rect', x:100, y:120, rx:54, label:'Прямоуг. фигуры',
props:'Квадрат: $S=a^2$. Прямоугольник: $S=ab$. Прямоугольный треугольник: $S=\\frac{1}{2}ab$ (катеты).' },
{ id:'para', x:310, y:120, rx:56, label:'Параллелограммы',
props:'Параллелограмм: $S=ah$. Ромб: $S=\\frac{d_1 d_2}{2}$. Прямоугольник: $S=ab$. Квадрат: $S=a^2$.' },
{ id:'tri', x:510, y:120, rx:48, label:'Треугольники',
props:'Произвольный: $S=\\frac{1}{2}ah$. Прямоугольный: $S=\\frac{1}{2}ab$. Равносторонний: $S=\\frac{a^2\\sqrt{3}}{4}$.' },
{ id:'sq', x:60, y:230, rx:40, label:'Квадрат',
props:'$S=a^2$, $P=4a$, диагональ $d=a\\sqrt{2}$. Частный случай прямоугольника и ромба.' },
{ id:'recta', x:160, y:230, rx:44, label:'Прямоугольник',
props:'$S=ab$, $P=2(a+b)$, $d=\\sqrt{a^2+b^2}$.' },
{ id:'rhomb', x:280, y:230, rx:42, label:'Ромб',
props:'$S=\\frac{d_1 d_2}{2}=ah=a^2\\sin\\alpha$. Диагонали перпендикулярны.' },
{ id:'trap', x:400, y:230, rx:42, label:'Трапеция',
props:'$S=\\frac{(a+b)}{2}h$. Средняя линия $m=\\frac{a+b}{2}$.' },
{ id:'eqtri', x:520, y:230, rx:44, label:'Равносторонний',
props:'$h=\\frac{a\\sqrt{3}}{2}$, $S=\\frac{a^2\\sqrt{3}}{4}$. Все углы $60°$.' },
{ id:'pytri', x:560, y:310, rx:44, label:'Прям. треугольник',
props:'$S=\\frac{1}{2}ab$ (катеты). Теорема Пифагора: $c^2=a^2+b^2$. Высота: $h_c=\\frac{ab}{c}$.' },
];
const edges = [
['area','rect'],['area','para'],['area','tri'],
['rect','sq'],['rect','recta'],
['para','sq'],['para','recta'],['para','rhomb'],
['tri','eqtri'],['tri','pytri'],['para','trap'],
];
let sel = null;
function draw(selId){
const colors = { area:'#059669', rect:'#0891b2', para:'#8b5cf6', tri:'#d97706', sq:'#14b8a6', recta:'#2563eb', rhomb:'#ec4899', trap:'#f97316', eqtri:'#e11d48', pytri:'#16a34a' };
let s = `<svg viewBox="0 0 ${W} ${H}" style="width:100%;max-width:640px;background:var(--card);border:1.5px solid var(--border);border-radius:14px;cursor:pointer">`;
s += `<defs><marker id="f2-arr" markerWidth="7" markerHeight="7" refX="6" refY="3.5" orient="auto"><polygon points="0 0,7 3.5,0 7" fill="#94a3b8"/></marker></defs>`;
edges.forEach(([a,b])=>{
const na=nodes.find(n=>n.id===a), nb=nodes.find(n=>n.id===b);
if(!na||!nb) return;
const dx=nb.x-na.x, dy=nb.y-na.y, len=Math.sqrt(dx*dx+dy*dy);
if(len<1) return;
const sy_r=na.rx*0.52;
const sx=na.x+dx/len*na.rx, sy2=na.y+dy/len*sy_r;
const ex=nb.x-dx/len*(nb.rx+7), ey=nb.y-dy/len*(nb.rx*0.52+7);
const isAct = selId===a||selId===b;
s += `<line x1="${sx.toFixed(1)}" y1="${sy2.toFixed(1)}" x2="${ex.toFixed(1)}" y2="${ey.toFixed(1)}" stroke="${isAct?'#059669':'#94a3b8'}" stroke-width="${isAct?2.5:1.5}" marker-end="url(#f2-arr)"/>`;
});
nodes.forEach(n=>{
const isS = selId===n.id;
const col = colors[n.id] || '#059669';
const ry = n.rx * 0.52;
s += `<ellipse cx="${n.x}" cy="${n.y}" rx="${n.rx}" ry="${ry}" fill="${isS?col:'var(--card)'}" stroke="${col}" stroke-width="${isS?3:2}" data-nid="${n.id}" style="cursor:pointer"/>`;
const words = n.label.split(' ');
const line1 = words.slice(0,2).join(' '), line2 = words.slice(2).join(' ');
const tc = isS ? '#fff' : col;
if(line2){
s += `<text x="${n.x}" y="${n.y-5}" text-anchor="middle" font-size="8" font-weight="800" font-family="Unbounded,sans-serif" fill="${tc}" style="pointer-events:none">${line1}</text>`;
s += `<text x="${n.x}" y="${n.y+7}" text-anchor="middle" font-size="8" font-weight="800" font-family="Unbounded,sans-serif" fill="${tc}" style="pointer-events:none">${line2}</text>`;
} else {
s += `<text x="${n.x}" y="${n.y+4}" text-anchor="middle" font-size="8" font-weight="800" font-family="Unbounded,sans-serif" fill="${tc}" style="pointer-events:none">${line1}</text>`;
}
});
s += '</svg>';
document.getElementById('final2-hier-svg').innerHTML = s;
document.getElementById('final2-hier-svg').querySelector('svg').addEventListener('click', function(e){
const el = e.target.closest('[data-nid]');
if(!el) return;
const nid = el.dataset.nid;
sel = (sel===nid) ? null : nid;
const nd = nodes.find(n=>n.id===nid);
if(sel && nd){ document.getElementById('final2-hier-info').innerHTML = '<b>' + nd.label + '</b>: ' + nd.props; renderMath(document.getElementById('final2-hier-info')); }
else document.getElementById('final2-hier-info').textContent = 'Нажми на фигуру в схеме выше';
draw(sel);
});
}
draw(null);
})();
/* === JS: 7 боссов === */
(function(){
const bosses = [
{
n: 1,
title: 'Прямоугольный треугольник: Пифагор + высота',
color: '#059669',
svg: `<svg viewBox="0 0 260 180" style="width:100%;max-width:280px;background:var(--card);border:1px solid var(--border);border-radius:10px;display:block;margin:10px auto">
<!-- Right triangle A(20,155) B(200,155) C(20,20) -->
<polygon points="20,155 200,155 20,20" fill="rgba(5,150,105,.10)" stroke="#059669" stroke-width="2"/>
<!-- right angle at A -->
<path d="M20,155 L20,145 L30,145" fill="none" stroke="#059669" stroke-width="1.8"/>
<!-- height from C to hypotenuse CB foot H -->
<!-- H on line BC: parametric. B=(200,155) C=(20,20). direction=(180,135). len=225. foot from A=(20,155): t=((20-200)*(180)+(155-155)*(135))/(180^2+135^2)=-32400/56025=-0.5784 => H=(200-0.5784*180, 155-0.5784*135)=(95.9,77.4) -->
<line x1="20" y1="155" x2="96" y2="77" stroke="#8b5cf6" stroke-width="1.5" stroke-dasharray="4 2"/>
<!-- right angle mark at H on hypotenuse: u = unit along BC = (180/225, 135/225)=(0.8, 0.6); w = perpendicular = (-0.6, 0.8); mark = H+8u, H+8u+8w, H+8w -->
<path d="M102,83 L96,89 L90,83" fill="none" stroke="#8b5cf6" stroke-width="1.5"/>
<circle cx="96" cy="77" r="3.5" fill="#8b5cf6" stroke="#fff" stroke-width="1.5"/>
<!-- vertex dots -->
<circle cx="20" cy="155" r="4" fill="#059669" stroke="#fff" stroke-width="1.5"/>
<circle cx="200" cy="155" r="4" fill="#059669" stroke="#fff" stroke-width="1.5"/>
<circle cx="20" cy="20" r="4" fill="#059669" stroke="#fff" stroke-width="1.5"/>
<!-- labels -->
<text x="6" y="152" font-size="11" font-weight="700" fill="#065f46" font-family="Unbounded,sans-serif">A</text>
<text x="204" y="163" font-size="11" font-weight="700" fill="#065f46" font-family="Unbounded,sans-serif">B</text>
<text x="6" y="18" font-size="11" font-weight="700" fill="#065f46" font-family="Unbounded,sans-serif">C</text>
<text x="98" y="68" font-size="10" font-weight="700" fill="#6d28d9" font-family="Unbounded,sans-serif">H</text>
<!-- side labels -->
<text x="4" y="92" font-size="10" fill="#047857" font-family="JetBrains Mono,monospace">a=9</text>
<text x="100" y="170" font-size="10" fill="#047857" font-family="JetBrains Mono,monospace">b=12</text>
<text x="108" y="88" font-size="9" fill="#6d28d9" font-family="JetBrains Mono,monospace">h_c</text>
</svg>`,
cond: 'В прямоугольном треугольнике $ABC$ с прямым углом $A$ катеты $a = AC = 9$ и $b = AB = 12$.',
parts: [
{ label: 'Найди гипотенузу $c = BC$.', ans: 15, hint: '$c=\\sqrt{9^2+12^2}=\\sqrt{81+144}=\\sqrt{225}=15$' },
{ label: 'Найди высоту $h_c$ к гипотенузе (десятичный ответ допустим).', ans: 7.2, tol: 0.05, hint: '$h_c=\\dfrac{ab}{c}=\\dfrac{9\\cdot12}{15}=\\dfrac{108}{15}=7.2$' },
{ label: 'Найди площадь треугольника $ABC$.', ans: 54, hint: '$S=\\dfrac{1}{2}\\cdot9\\cdot12=54$' },
],
},
{
n: 2,
title: 'Параллелограмм через угол',
color: '#8b5cf6',
svg: `<svg viewBox="0 0 260 160" style="width:100%;max-width:280px;background:var(--card);border:1px solid var(--border);border-radius:10px;display:block;margin:10px auto">
<!-- Parallelogram A(30,130) B(220,130) C(200,30) D(10,30) -->
<polygon points="30,130 220,130 200,30 10,30" fill="rgba(139,92,246,.10)" stroke="#8b5cf6" stroke-width="2"/>
<!-- height from D(10,30) down to base AB at x=10, y=130 -->
<line x1="10" y1="30" x2="10" y2="130" stroke="#8b5cf6" stroke-width="1.5" stroke-dasharray="4 2"/>
<path d="M10,130 L10,122 L18,122" fill="none" stroke="#8b5cf6" stroke-width="1.5"/>
<!-- angle arc at A -->
<path d="M50,130 A22,22 0 0,1 36,112" stroke="#d97706" stroke-width="2" fill="rgba(217,119,6,.15)"/>
<text x="56" y="124" font-size="9" fill="#b45309" font-weight="700" font-family="JetBrains Mono,monospace">30°</text>
<!-- vertex dots and labels -->
<circle cx="30" cy="130" r="4" fill="#8b5cf6" stroke="#fff" stroke-width="1.5"/>
<circle cx="220" cy="130" r="4" fill="#8b5cf6" stroke="#fff" stroke-width="1.5"/>
<circle cx="200" cy="30" r="4" fill="#8b5cf6" stroke="#fff" stroke-width="1.5"/>
<circle cx="10" cy="30" r="4" fill="#8b5cf6" stroke="#fff" stroke-width="1.5"/>
<text x="16" y="147" font-size="11" font-weight="700" fill="#6d28d9" font-family="Unbounded,sans-serif">A</text>
<text x="224" y="147" font-size="11" font-weight="700" fill="#6d28d9" font-family="Unbounded,sans-serif">B</text>
<text x="204" y="24" font-size="11" font-weight="700" fill="#6d28d9" font-family="Unbounded,sans-serif">C</text>
<text x="0" y="24" font-size="11" font-weight="700" fill="#6d28d9" font-family="Unbounded,sans-serif">D</text>
<!-- side labels -->
<text x="116" y="148" text-anchor="middle" font-size="10" fill="#6d28d9" font-family="JetBrains Mono,monospace">14 см</text>
<text x="0" y="84" font-size="9" fill="#6d28d9" font-family="JetBrains Mono,monospace">8 см</text>
<text x="2" y="116" font-size="9" fill="#6d28d9" font-family="JetBrains Mono,monospace">h</text>
</svg>`,
cond: 'В параллелограмме $ABCD$ сторона $AB = 14$ см, смежная сторона $AD = 8$ см, угол при вершине $A$ равен $30°$.',
parts: [
{ label: 'Найди высоту $h$ параллелограмма ($h = AD \\cdot \\sin 30°$, в сантиметрах).', ans: 4, hint: '$h = AD \\cdot \\sin 30° = 8 \\cdot 0.5 = 4$ см' },
{ label: 'Найди площадь параллелограмма $S$ (кв. см).', ans: 56, hint: '$S = AB \\cdot h = 14 \\cdot 4 = 56$ кв. см' },
],
},
{
n: 3,
title: 'Трапеция и средняя линия',
color: '#f97316',
svg: `<svg viewBox="0 0 260 170" style="width:100%;max-width:280px;background:var(--card);border:1px solid var(--border);border-radius:10px;display:block;margin:10px auto">
<!-- Trapezoid A(20,145) B(240,145) C(200,50) D(60,50) -->
<polygon points="20,145 240,145 200,50 60,50" fill="rgba(249,115,22,.10)" stroke="#f97316" stroke-width="2"/>
<!-- height from D to AB -->
<line x1="60" y1="50" x2="60" y2="145" stroke="#f97316" stroke-width="1.5" stroke-dasharray="4 2"/>
<path d="M60,145 L60,137 L68,137" fill="none" stroke="#f97316" stroke-width="1.5"/>
<!-- midline MN -->
<line x1="40" y1="97" x2="220" y2="97" stroke="#d97706" stroke-width="2.5"/>
<circle cx="40" cy="97" r="4" fill="#d97706" stroke="#fff" stroke-width="1.5"/>
<circle cx="220" cy="97" r="4" fill="#d97706" stroke="#fff" stroke-width="1.5"/>
<text x="28" y="93" font-size="9" font-weight="700" fill="#b45309" font-family="Unbounded,sans-serif">M</text>
<text x="224" y="93" font-size="9" font-weight="700" fill="#b45309" font-family="Unbounded,sans-serif">N</text>
<!-- vertex dots -->
<circle cx="20" cy="145" r="4" fill="#f97316" stroke="#fff" stroke-width="1.5"/>
<circle cx="240" cy="145" r="4" fill="#f97316" stroke="#fff" stroke-width="1.5"/>
<circle cx="200" cy="50" r="4" fill="#f97316" stroke="#fff" stroke-width="1.5"/>
<circle cx="60" cy="50" r="4" fill="#f97316" stroke="#fff" stroke-width="1.5"/>
<text x="6" y="158" font-size="11" font-weight="700" fill="#c2410c" font-family="Unbounded,sans-serif">A</text>
<text x="244" y="158" font-size="11" font-weight="700" fill="#c2410c" font-family="Unbounded,sans-serif">B</text>
<text x="204" y="44" font-size="11" font-weight="700" fill="#c2410c" font-family="Unbounded,sans-serif">C</text>
<text x="46" y="44" font-size="11" font-weight="700" fill="#c2410c" font-family="Unbounded,sans-serif">D</text>
<!-- labels -->
<text x="130" y="164" text-anchor="middle" font-size="10" fill="#c2410c" font-family="JetBrains Mono,monospace">a=18</text>
<text x="130" y="44" text-anchor="middle" font-size="10" fill="#c2410c" font-family="JetBrains Mono,monospace">b=12</text>
<text x="46" y="102" font-size="9" fill="#b45309" font-family="JetBrains Mono,monospace">h=5</text>
<text x="116" y="91" text-anchor="middle" font-size="9" fill="#b45309" font-family="JetBrains Mono,monospace">m=?</text>
</svg>`,
cond: 'В трапеции основания $a = 18$ см и $b = 12$ см, высота $h = 5$ см.',
parts: [
{ label: 'Найди среднюю линию $m$ трапеции (см).', ans: 15, hint: '$m = \\dfrac{a+b}{2} = \\dfrac{18+12}{2} = 15$ см' },
{ label: 'Найди площадь трапеции $S$ (кв. см).', ans: 75, hint: '$S = \\dfrac{(a+b)}{2} \\cdot h = 15 \\cdot 5 = 75$ кв. см' },
],
},
{
n: 4,
title: 'Ромб: диагонали, сторона, площадь',
color: '#ec4899',
svg: `<svg viewBox="0 0 260 185" style="width:100%;max-width:280px;background:var(--card);border:1px solid var(--border);border-radius:10px;display:block;margin:10px auto">
<!-- Rhombus center (130,92). d1=16 horizontal, d2=12 vertical. Vertices: A(130,32) B(198,92) C(130,152) D(62,92) -->
<polygon points="130,32 198,92 130,152 62,92" fill="rgba(236,72,153,.10)" stroke="#ec4899" stroke-width="2"/>
<!-- diagonals -->
<line x1="62" y1="92" x2="198" y2="92" stroke="#ec4899" stroke-width="1.5" stroke-dasharray="4 2"/>
<line x1="130" y1="32" x2="130" y2="152" stroke="#ec4899" stroke-width="1.5" stroke-dasharray="4 2"/>
<!-- right angle at center -->
<path d="M130,92 L130,82 L140,82" fill="none" stroke="#ec4899" stroke-width="1.5"/>
<!-- vertex dots -->
<circle cx="130" cy="32" r="4" fill="#ec4899" stroke="#fff" stroke-width="1.5"/>
<circle cx="198" cy="92" r="4" fill="#ec4899" stroke="#fff" stroke-width="1.5"/>
<circle cx="130" cy="152" r="4" fill="#ec4899" stroke="#fff" stroke-width="1.5"/>
<circle cx="62" cy="92" r="4" fill="#ec4899" stroke="#fff" stroke-width="1.5"/>
<text x="116" y="26" font-size="11" font-weight="700" fill="#be185d" font-family="Unbounded,sans-serif">A</text>
<text x="202" y="100" font-size="11" font-weight="700" fill="#be185d" font-family="Unbounded,sans-serif">B</text>
<text x="116" y="170" font-size="11" font-weight="700" fill="#be185d" font-family="Unbounded,sans-serif">C</text>
<text x="46" y="100" font-size="11" font-weight="700" fill="#be185d" font-family="Unbounded,sans-serif">D</text>
<!-- diagonal labels -->
<text x="130" y="84" text-anchor="middle" font-size="9" fill="#be185d" font-family="JetBrains Mono,monospace">d₁=16</text>
<text x="146" y="68" font-size="9" fill="#be185d" font-family="JetBrains Mono,monospace">d₂=12</text>
</svg>`,
cond: 'В ромбе $ABCD$ диагонали $d_1 = 16$ см и $d_2 = 12$ см.',
parts: [
{ label: 'Найди площадь ромба $S$ (кв. см).', ans: 96, hint: '$S = \\dfrac{d_1 d_2}{2} = \\dfrac{16 \\cdot 12}{2} = 96$ кв. см' },
{ label: 'Найди сторону ромба $a$ (полудиагонали: $8$ и $6$, теорема Пифагора).', ans: 10, hint: '$a = \\sqrt{8^2 + 6^2} = \\sqrt{64+36} = \\sqrt{100} = 10$ см' },
{ label: 'Найди периметр ромба $P$ (см).', ans: 40, hint: '$P = 4a = 4 \\cdot 10 = 40$ см' },
],
},
{
n: 5,
title: 'Медиана и центроид',
color: '#2563eb',
svg: `<svg viewBox="0 0 260 185" style="width:100%;max-width:280px;background:var(--card);border:1px solid var(--border);border-radius:10px;display:block;margin:10px auto">
<!-- Triangle A(130,15) B(20,165) C(240,165). Midpoints: Ma=(B+C)/2=(130,165), Mb=(A+C)/2=(185,90), Mc=(A+B)/2=(75,90) -->
<polygon points="130,15 20,165 240,165" fill="rgba(37,99,235,.10)" stroke="#2563eb" stroke-width="2"/>
<!-- 3 medians -->
<line x1="130" y1="15" x2="130" y2="165" stroke="#2563eb" stroke-width="1.5" stroke-dasharray="5 3"/>
<line x1="20" y1="165" x2="185" y2="90" stroke="#2563eb" stroke-width="1.5" stroke-dasharray="5 3"/>
<line x1="240" y1="165" x2="75" y2="90" stroke="#2563eb" stroke-width="1.5" stroke-dasharray="5 3"/>
<!-- centroid G = ((130+20+240)/3, (15+165+165)/3) = (130, 115) -->
<circle cx="130" cy="115" r="6" fill="#2563eb" stroke="#fff" stroke-width="2"/>
<text x="136" y="114" font-size="11" font-weight="700" fill="#1d4ed8" font-family="Unbounded,sans-serif">G</text>
<!-- midpoints -->
<circle cx="130" cy="165" r="3.5" fill="#60a5fa" stroke="#fff" stroke-width="1.5"/>
<circle cx="185" cy="90" r="3.5" fill="#60a5fa" stroke="#fff" stroke-width="1.5"/>
<circle cx="75" cy="90" r="3.5" fill="#60a5fa" stroke="#fff" stroke-width="1.5"/>
<!-- vertex dots -->
<circle cx="130" cy="15" r="4" fill="#2563eb" stroke="#fff" stroke-width="1.5"/>
<circle cx="20" cy="165" r="4" fill="#2563eb" stroke="#fff" stroke-width="1.5"/>
<circle cx="240" cy="165" r="4" fill="#2563eb" stroke="#fff" stroke-width="1.5"/>
<text x="116" y="10" font-size="11" font-weight="700" fill="#1d4ed8" font-family="Unbounded,sans-serif">A</text>
<text x="4" y="178" font-size="11" font-weight="700" fill="#1d4ed8" font-family="Unbounded,sans-serif">B</text>
<text x="244" y="178" font-size="11" font-weight="700" fill="#1d4ed8" font-family="Unbounded,sans-serif">C</text>
<text x="116" y="182" font-size="9" fill="#1d4ed8" font-family="JetBrains Mono,monospace">S=36</text>
</svg>`,
cond: 'Площадь треугольника $ABC = 36$ кв. см. Точка $G$ — центроид (пересечение медиан).',
parts: [
{ label: 'Найди площадь треугольника, образованного центроидом $G$ и двумя вершинами (например, $\\triangle ABG$).', ans: 12, hint: 'Медиана делит треугольник на 2 равные части: $S/2=18$. Все 6 малых треугольников равны: $S_6 = 36/6 = 12$ кв. см' },
{ label: 'Одна медиана делит треугольник на 2 треугольника. Какова площадь каждого из них?', ans: 18, hint: 'Медиана делит треугольник на 2 равновеликих: $S/2 = 36/2 = 18$ кв. см' },
],
},
{
n: 6,
title: 'Равносторонний треугольник и центроид',
color: '#e11d48',
svg: `<svg viewBox="0 0 260 195" style="width:100%;max-width:280px;background:var(--card);border:1px solid var(--border);border-radius:10px;display:block;margin:10px auto">
<!-- Equilateral triangle: side 10. A(130,15) B(32,183) C(228,183) -->
<polygon points="130,15 32,183 228,183" fill="rgba(225,29,72,.10)" stroke="#e11d48" stroke-width="2"/>
<!-- height from A to BC -->
<line x1="130" y1="15" x2="130" y2="183" stroke="#e11d48" stroke-width="1.5" stroke-dasharray="4 2"/>
<path d="M130,183 L130,175 L138,175" fill="none" stroke="#e11d48" stroke-width="1.5"/>
<text x="136" y="140" font-size="10" fill="#be123c" font-weight="700" font-family="JetBrains Mono,monospace">h=?</text>
<!-- centroid G at (130, 127) = (1/3)(15+183+183) = 127 -->
<circle cx="130" cy="127" r="5" fill="#e11d48" stroke="#fff" stroke-width="2"/>
<text x="136" y="130" font-size="10" font-weight="700" fill="#be123c" font-family="Unbounded,sans-serif">G</text>
<!-- line from G to base midpoint (130,183) — centroid to foot -->
<line x1="130" y1="127" x2="130" y2="183" stroke="#f87171" stroke-width="1.2" stroke-dasharray="3 2"/>
<!-- vertex dots -->
<circle cx="130" cy="15" r="4" fill="#e11d48" stroke="#fff" stroke-width="1.5"/>
<circle cx="32" cy="183" r="4" fill="#e11d48" stroke="#fff" stroke-width="1.5"/>
<circle cx="228" cy="183" r="4" fill="#e11d48" stroke="#fff" stroke-width="1.5"/>
<text x="116" y="10" font-size="11" font-weight="700" fill="#be123c" font-family="Unbounded,sans-serif">A</text>
<text x="14" y="193" font-size="11" font-weight="700" fill="#be123c" font-family="Unbounded,sans-serif">B</text>
<text x="232" y="193" font-size="11" font-weight="700" fill="#be123c" font-family="Unbounded,sans-serif">C</text>
<text x="130" y="198" text-anchor="middle" font-size="10" fill="#be123c" font-family="JetBrains Mono,monospace">a=10</text>
</svg>`,
cond: 'В равностороннем треугольнике $ABC$ сторона $a = 10$ см. Точка $G$ — центроид.',
parts: [
{ label: 'Найди высоту $h$ равностороннего треугольника (введи значение, умноженное на 10, как целое: $h \\cdot 10 = ?$)', ans: 87, hint: '$h = \\dfrac{10\\sqrt{3}}{2} \\approx \\dfrac{10 \\cdot 1.732}{2} = 8.66$, умноженное на 10 = 86.6 \\approx 87', tol: 1 },
{ label: 'Найди площадь треугольника (введи значение, умноженное на 10, как целое: $S \\cdot 10 = ?$)', ans: 433, hint: '$S = \\dfrac{a^2\\sqrt{3}}{4} = \\dfrac{100\\sqrt{3}}{4} \\approx 43.3$, умноженное на 10 = 433', tol: 2 },
{ label: 'Найди расстояние от центроида $G$ до основания $BC$ (центроид делит высоту в отношении $2:1$, введи значение в целых мм: расстояние $\\cdot 10$)', ans: 29, hint: 'Расстояние = $h/3 = 8.66/3 \\approx 2.89$, умноженное на 10 = 28.9 \\approx 29', tol: 1 },
],
},
{
n: 7,
title: 'Пифагоровы тройки в задаче',
color: '#7c3aed',
svg: `<svg viewBox="0 0 260 185" style="width:100%;max-width:280px;background:var(--card);border:1px solid var(--border);border-radius:10px;display:block;margin:10px auto">
<!-- Right triangle with 5-12-13 triple. Scale: *10 for visual. A(20,165) B(20,25) C(150,165) -->
<polygon points="20,165 20,25 150,165" fill="rgba(124,58,237,.10)" stroke="#7c3aed" stroke-width="2"/>
<path d="M20,165 L20,153 L32,153" fill="none" stroke="#7c3aed" stroke-width="1.8"/>
<!-- vertex dots -->
<circle cx="20" cy="165" r="4" fill="#7c3aed" stroke="#fff" stroke-width="1.5"/>
<circle cx="20" cy="25" r="4" fill="#7c3aed" stroke="#fff" stroke-width="1.5"/>
<circle cx="150" cy="165" r="4" fill="#7c3aed" stroke="#fff" stroke-width="1.5"/>
<text x="2" y="162" font-size="11" font-weight="700" fill="#5b21b6" font-family="Unbounded,sans-serif">A</text>
<text x="2" y="22" font-size="11" font-weight="700" fill="#5b21b6" font-family="Unbounded,sans-serif">B</text>
<text x="154" y="178" font-size="11" font-weight="700" fill="#5b21b6" font-family="Unbounded,sans-serif">C</text>
<!-- side labels -->
<text x="0" y="102" font-size="10" fill="#5b21b6" font-family="JetBrains Mono,monospace">a=?</text>
<text x="72" y="180" font-size="10" fill="#5b21b6" font-family="JetBrains Mono,monospace">b=?</text>
<text x="84" y="88" font-size="10" fill="#5b21b6" font-family="JetBrains Mono,monospace">c=13</text>
<!-- perimeter label -->
<text x="130" y="20" font-size="9" fill="#7c3aed" font-family="JetBrains Mono,monospace">P=30</text>
</svg>`,
cond: 'Прямоугольный треугольник имеет периметр $P = 30$ см и гипотенузу $c = 13$ см. Используй пифагорову тройку $(5, 12, 13)$.',
parts: [
{ label: 'Найди сумму катетов $a + b$ (см).', ans: 17, hint: '$a + b = P - c = 30 - 13 = 17$ см' },
{ label: 'Используя тройку $(5, 12, 13)$: найди меньший катет $a$ (см).', ans: 5, hint: 'Тройка $(5, 12, 13)$: катеты $5$ и $12$, $5+12=17$. Меньший катет $a = 5$ см' },
{ label: 'Найди площадь треугольника $S$ (кв. см).', ans: 30, hint: '$S = \\dfrac{1}{2} \\cdot 5 \\cdot 12 = 30$ кв. см' },
],
},
];
window.final2BossSolved = new Set();
const bossBox = document.getElementById('final2-bosses');
bossBox.innerHTML = bosses.map(b => {
const partsHtml = b.parts.map((p,pi) => {
const labelText = p._label_fix || p.label;
return `<div style="padding:10px 0;border-top:1px dashed var(--border)">
<div style="font-size:.9rem;margin-bottom:7px">${labelText}</div>
<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap">
<input type="number" step="any" class="tinp final2-boss-inp" data-b="${b.n-1}" data-p="${pi}" placeholder="Ответ" style="width:120px">
<button class="btn primary final2-boss-check" data-b="${b.n-1}" data-p="${pi}" style="background:${b.color};border-color:${b.color}">Проверить</button>
<span class="final2-boss-ok" data-b="${b.n-1}" data-p="${pi}" style="display:none;color:var(--ok);font-weight:700">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" style="width:16px;height:16px;vertical-align:middle"><polyline points="20 6 9 17 4 12"/></svg>
</span>
</div>
<div class="feedback final2-boss-fb" data-b="${b.n-1}" data-p="${pi}" style="display:none;margin-top:6px"></div>
</div>`;
}).join('');
const svgHtml = b.svg ? `<div style="display:flex;justify-content:center;margin:10px 0">${b.svg}</div>` : '';
return `<div style="padding:16px;background:var(--card);border-radius:12px;border:2px solid ${b.color};margin-bottom:14px" id="final2-boss-card-${b.n-1}">
<div style="display:flex;align-items:center;gap:10px;margin-bottom:12px;flex-wrap:wrap">
<span style="background:${b.color};color:#fff;padding:4px 10px;border-radius:6px;font-family:'Unbounded',sans-serif;font-size:.7rem;font-weight:800">БОСС ${b.n}</span>
<span style="font-family:'Unbounded',sans-serif;font-size:.88rem;font-weight:800;color:${b.color}">${b.title}</span>
<span id="final2-boss-xp-${b.n-1}" style="margin-left:auto;display:none;background:var(--ok-bg);color:#065f46;padding:3px 10px;border-radius:99px;font-size:.78rem;font-weight:800">+10 XP</span>
</div>
<div style="padding:10px 14px;background:linear-gradient(135deg,#d1fae5,#fff);border-left:4px solid ${b.color};border-radius:9px;font-size:.92rem;line-height:1.6;margin-bottom:4px">${b.cond}</div>
${svgHtml}
${partsHtml}
</div>`;
}).join('');
function checkPart(bi, pi){
const boss = bosses[bi];
const part = boss.parts[pi];
const inp = bossBox.querySelector(`.final2-boss-inp[data-b="${bi}"][data-p="${pi}"]`);
const fb = bossBox.querySelector(`.final2-boss-fb[data-b="${bi}"][data-p="${pi}"]`);
const ok = bossBox.querySelector(`.final2-boss-ok[data-b="${bi}"][data-p="${pi}"]`);
if(!inp) return;
const val = parseFloat(inp.value);
const useExact = part._override && part._ans_exact !== undefined;
const ansCheck = useExact ? part._ans_exact : part.ans;
const tolCheck = useExact ? part._tol_exact : (part.tol !== undefined ? part.tol : 0);
const hintText = useExact ? part._hint_fix : part.hint;
if(Math.abs(val - ansCheck) <= tolCheck){
feedback(fb, true, 'Верно! ' + (hintText ? '<br><span style="font-size:.82rem;opacity:.85">' + hintText + '</span>' : ''));
inp.disabled = true;
const btn = bossBox.querySelector(`.final2-boss-check[data-b="${bi}"][data-p="${pi}"]`);
if(btn) btn.disabled = true;
if(ok) ok.style.display = 'inline';
const allDone = boss.parts.every((_,pj) => {
const el = bossBox.querySelector(`.final2-boss-inp[data-b="${bi}"][data-p="${pj}"]`);
return el && el.disabled;
});
if(allDone && !window.final2BossSolved.has(bi)){
window.final2BossSolved.add(bi);
addXp(10, 'final2-boss-' + (bi+1));
const xpBadge = document.getElementById('final2-boss-xp-' + bi);
if(xpBadge) xpBadge.style.display = 'inline';
bumpProgress('final2', 8);
if(window.final2BossSolved.size === bosses.length){
setTimeout(()=>{
confetti();
if(!STATE.achievements.has('final2-master')){
STATE.achievements.set('final2-master', 'Мастер площадей Главы 2');
saveProgress();
const pop = document.getElementById('ach-popup');
if(pop){ document.getElementById('ach-text').textContent = 'Мастер площадей Главы 2!'; pop.classList.add('show'); setTimeout(()=>pop.classList.remove('show'), 4000); }
}
addXp(50, 'final2-all-bosses');
bumpProgress('final2', 20);
const fin = document.getElementById('final2-finish');
if(fin) fin.style.display = 'block';
}, 500);
}
}
} else {
feedback(fb, false, 'Неверно. Подсказка: ' + (hintText || part.hint));
}
}
bossBox.querySelectorAll('.final2-boss-check').forEach(btn=>{
btn.addEventListener('click', ()=>{ checkPart(+btn.dataset.b, +btn.dataset.p); });
});
bossBox.querySelectorAll('.final2-boss-inp').forEach(inp=>{
inp.addEventListener('keydown', e=>{ if(e.key==='Enter'){ const btn=bossBox.querySelector(`.final2-boss-check[data-b="${inp.dataset.b}"][data-p="${inp.dataset.p}"]`); if(btn)btn.click(); } });
});
})();
renderMath(box);
}
</script>
</body>
</html>