Files
Learn_System/frontend/textbooks/geometry_10_r1.html
T
Maxim Dolgolyov bfa7c46ef5 feat(geom10 W1): Раздел 1 §1 + §2 — Введение в стереометрию
§1 Пространственные фигуры:
- 5 hero-тел (призма/пирамида/цилиндр/конус/шар) через stereo3d
- Куб ABCDA1B1C1D1 с подсветкой диагонали AC1 и грани ABB1A1
- Прямая vs наклонная призма (side-by-side)
- 6 теоретических карточек (грани/рёбра, призма, пирамида, тела вращения, Эйлер, проекция)
- 3 тренажёра: узнавание тел (6 заданий), счёт элементов (6, формула Эйлера), 3D-крутилка куба (slider rotX/rotY)
- Босс §1: 5 этапов, +60 XP

§2 Прямые и плоскости:
- 3 SVG аксиом A1/A2/A3 + 3 SVG следствий
- 6 теоретических карточек (3 аксиомы + следствия + 4 способа задать плоскость + обозначения)
- 3 тренажёра: какая аксиома (6), можно ли задать плоскость (5), сколько плоскостей (5)
- Босс §2: 5 этапов, +65 XP

§3 + Финал — stub до Волны W2.
2026-05-29 14:48:30 +03:00

1101 lines
62 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Геометрия 10 · Раздел 1 · Введение в стереометрию</title>
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700;800;900&family=Inter:wght@400;500;600;700&family=Unbounded:wght@400;700;800;900&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css">
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js"></script>
<script src="/js/api.js" defer></script>
<script src="/js/xp.js" defer></script>
<script src="/js/stereo3d.js?v=1"></script>
<style>
:root{
--bg:#f8fafc; --card:#fff; --card-2:#f1f5f9;
--text:#0b1d33; --text-2:#1e293b; --muted:#475569;
--border:#dbeafe; --border-2:#e2e8f0;
--pri:#2563eb; --pri-d:#1d4ed8; --pri-l:#93c5fd;
--pri-soft:#dbeafe; --pri-soft-2:#eff6ff;
--dark:#1e3a8a;
--accent:#dc2626;
--good:#16a34a;
--warn:#d97706;
--sh:0 4px 16px rgba(37,99,235,.08);
--sh-h:0 12px 36px rgba(37,99,235,.18);
}
html.dark{
--bg:#020617; --card:#0a1929; --card-2:#0f1f33;
--text:#dbeafe; --text-2:#bfdbfe; --muted:#94a3b8;
--border:#1e3a5f; --border-2:#1e293b;
--pri-soft:rgba(37,99,235,.18); --pri-soft-2:rgba(37,99,235,.10);
}
*{margin:0;padding:0;box-sizing:border-box}
html,body{min-height:100vh}
body{font-family:'Inter',system-ui,sans-serif;background:var(--bg);color:var(--text);line-height:1.6;transition:background .25s,color .25s}
.hdr{position:relative;background:linear-gradient(110deg,var(--dark) 0%,var(--pri) 55%,var(--pri-l) 100%);color:#fff;padding:32px 24px 28px;overflow:hidden}
.hdr::before{content:'△';position:absolute;right:8px;top:-18%;font-family:'Outfit',sans-serif;font-size:clamp(8rem,22vw,18rem);font-weight:900;color:rgba(255,255,255,.10);line-height:1;pointer-events:none;user-select:none}
.hdr-inner{position:relative;z-index:1;max-width:1100px;margin:0 auto;display:flex;align-items:center;gap:18px;flex-wrap:wrap}
.hdr-back{display:inline-flex;align-items:center;gap:8px;padding:8px 14px;background:rgba(255,255,255,.14);border-radius:9px;color:#fff;text-decoration:none;font-size:.85rem;font-weight:600;transition:background .15s}
.hdr-back:hover{background:rgba(255,255,255,.24)}
.hdr h1{font-family:'Outfit',sans-serif;font-size:1.7rem;font-weight:900;letter-spacing:-.01em}
.hdr-sub{font-size:.92rem;opacity:.88;margin-top:4px}
.hdr-side{margin-left:auto;display:flex;gap:8px;align-items:center}
.hdr-btn{padding:8px 12px;background:rgba(255,255,255,.14);border:none;color:#fff;border-radius:9px;cursor:pointer;font-weight:600;font-size:.82rem;display:inline-flex;align-items:center;gap:6px;transition:background .15s;font-family:inherit}
.hdr-btn:hover{background:rgba(255,255,255,.24)}
.hdr-xp{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;background:linear-gradient(135deg,#f59e0b,#dc2626);border-radius:99px;font-family:'Unbounded',sans-serif;font-size:.78rem;font-weight:800;letter-spacing:.04em;color:#fff;box-shadow:0 4px 12px rgba(220,38,38,.32)}
.ic{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.sec-nav{position:sticky;top:0;z-index:30;background:var(--bg);border-bottom:1px solid var(--border-2);padding:10px 16px;overflow-x:auto;white-space:nowrap;box-shadow:0 2px 8px rgba(0,0,0,.04)}
.sec-nav-inner{display:inline-flex;gap:6px;max-width:1100px;margin:0 auto}
.sec-tab{display:inline-flex;align-items:center;gap:6px;padding:7px 14px;background:var(--card-2);border:1px solid var(--border-2);border-radius:10px;font-size:.82rem;font-weight:700;color:var(--muted);cursor:pointer;transition:all .15s;text-decoration:none;font-family:inherit}
.sec-tab:hover{background:var(--pri-soft);color:var(--pri-d);border-color:var(--pri-l)}
.sec-tab.active{background:var(--pri);color:#fff;border-color:var(--pri-d)}
.sec-tab .dot{width:8px;height:8px;border-radius:50%;background:rgba(0,0,0,.15);transition:background .25s}
.sec-tab.read .dot{background:var(--good)}
.sec-tab.active .dot{background:#fff}
.sec-tab.locked{opacity:.55}
main{max-width:1100px;margin:0 auto;padding:32px 24px 80px}
.para{margin-bottom:48px;scroll-margin-top:72px}
.para-head{display:flex;align-items:flex-start;gap:16px;margin-bottom:18px}
.para-num{font-family:'Outfit',sans-serif;font-size:1.6rem;font-weight:900;color:#fff;background:linear-gradient(135deg,var(--pri),var(--pri-d));padding:10px 16px;border-radius:11px;letter-spacing:-.02em;flex-shrink:0;box-shadow:var(--sh)}
.para-h{flex:1;min-width:0}
.para-h h2{font-family:'Outfit',sans-serif;font-size:1.6rem;font-weight:800;letter-spacing:-.01em;line-height:1.2;margin-bottom:4px}
.para-h-sub{color:var(--muted);font-size:.95rem}
.theory{display:grid;grid-template-columns:1fr;gap:14px;margin-bottom:24px}
@media(min-width:760px){.theory{grid-template-columns:repeat(2,1fr)}}
.t-card{background:var(--card);border:1.5px solid var(--border-2);border-radius:13px;padding:16px 18px;box-shadow:var(--sh);transition:border-color .15s}
.t-card:hover{border-color:var(--pri-l)}
.t-tag{display:inline-block;padding:3px 9px;background:var(--pri-soft);color:var(--pri-d);border-radius:6px;font-size:.7rem;font-weight:800;letter-spacing:.06em;text-transform:uppercase;margin-bottom:8px}
.t-title{font-family:'Outfit',sans-serif;font-size:1.02rem;font-weight:800;margin-bottom:6px;color:var(--text)}
.t-body{font-size:.92rem;color:var(--text);opacity:.9;line-height:1.6}
.t-body p{margin-bottom:8px}
.t-body ul{margin:6px 0 6px 20px}
.t-body li{margin-bottom:4px}
.t-body code{background:var(--card-2);padding:2px 6px;border-radius:5px;font-family:'JetBrains Mono',monospace;font-size:.86em}
.viz{background:var(--card);border:1.5px solid var(--border-2);border-radius:14px;padding:18px;margin-bottom:18px;box-shadow:var(--sh)}
.viz-title{font-family:'Outfit',sans-serif;font-size:.94rem;font-weight:800;color:var(--text);margin-bottom:10px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.viz-title .badge{padding:2px 8px;background:var(--pri-soft);color:var(--pri-d);border-radius:5px;font-size:.7rem;letter-spacing:.04em}
.viz-cap{font-size:.84rem;color:var(--muted);margin-top:8px;line-height:1.55}
.viz-row{display:flex;gap:12px;flex-wrap:wrap;justify-content:center}
.viz-cell{flex:1 1 200px;max-width:230px;text-align:center}
.viz-cell-label{font-size:.78rem;color:var(--muted);font-weight:700;margin-top:6px}
.rot-row{display:flex;gap:14px;flex-wrap:wrap;justify-content:center;margin-top:10px;font-size:.84rem;color:var(--muted)}
.rot-row label{display:inline-flex;align-items:center;gap:6px;font-weight:600}
.inter{background:var(--card);border:1.5px solid var(--border-2);border-radius:14px;padding:18px;margin-bottom:18px;box-shadow:var(--sh)}
.inter-h{display:flex;align-items:center;gap:10px;margin-bottom:12px}
.inter-icon{width:34px;height:34px;border-radius:9px;background:var(--pri-soft);color:var(--pri-d);display:flex;align-items:center;justify-content:center;flex-shrink:0;font-family:'Outfit',sans-serif;font-weight:900;font-size:.96rem}
.inter-title{font-family:'Outfit',sans-serif;font-size:1rem;font-weight:800;flex:1}
.inter-progress{font-size:.78rem;color:var(--muted);font-weight:700;font-family:'JetBrains Mono',monospace}
.quiz{display:flex;gap:14px;align-items:center;flex-wrap:wrap}
.quiz-q{flex:1;min-width:200px;font-size:.95rem;font-weight:600;line-height:1.55}
.quiz-opts{display:flex;gap:8px;flex-wrap:wrap}
.quiz-opt{padding:8px 14px;background:var(--card-2);border:1.5px solid var(--border-2);border-radius:9px;font-weight:700;font-size:.88rem;cursor:pointer;color:var(--text);font-family:inherit;transition:all .15s}
.quiz-opt:hover{background:var(--pri-soft);border-color:var(--pri-l)}
.quiz-opt.correct{background:linear-gradient(135deg,#dcfce7,#bbf7d0);border-color:#16a34a;color:#166534;animation:pop .35s}
.quiz-opt.wrong{background:linear-gradient(135deg,#fee2e2,#fecaca);border-color:#dc2626;color:#991b1b;animation:shake .35s}
@keyframes pop{0%{transform:scale(1)}50%{transform:scale(1.07)}100%{transform:scale(1)}}
@keyframes shake{0%,100%{transform:translateX(0)}25%{transform:translateX(-4px)}75%{transform:translateX(4px)}}
.quiz-input{display:inline-flex;align-items:center;gap:8px;background:var(--card-2);border:1.5px solid var(--border-2);border-radius:9px;padding:4px 6px;transition:border-color .15s}
.quiz-input.correct{border-color:#16a34a;background:linear-gradient(135deg,#dcfce7,#bbf7d0)}
.quiz-input.wrong{border-color:#dc2626;background:linear-gradient(135deg,#fee2e2,#fecaca)}
.quiz-input input{background:transparent;border:none;outline:none;padding:6px 8px;font-family:'JetBrains Mono',monospace;font-size:.92rem;font-weight:700;color:var(--text);width:90px}
.quiz-input button{background:var(--pri);border:none;color:#fff;padding:6px 10px;border-radius:6px;cursor:pointer;font-weight:700;font-size:.82rem;font-family:inherit}
.quiz-input button:hover{filter:brightness(1.08)}
.quiz-feedback{margin-top:10px;padding:10px 14px;background:var(--card-2);border-radius:9px;font-size:.88rem;color:var(--muted);display:none}
.quiz-feedback.show{display:block}
.quiz-feedback.good{background:linear-gradient(135deg,#dcfce7,#f0fdf4);color:#166534;border-left:3px solid #16a34a}
.quiz-feedback.bad{background:linear-gradient(135deg,#fee2e2,#fef2f2);color:#991b1b;border-left:3px solid #dc2626}
.boss{background:linear-gradient(135deg,#1e1b4b 0%,#312e81 50%,#4338ca 100%);color:#fff;border-radius:18px;padding:24px;margin-bottom:24px;position:relative;overflow:hidden;box-shadow:0 16px 48px rgba(67,56,202,.30)}
.boss::before{content:'';position:absolute;inset:0;background:radial-gradient(circle at 20% 30%,rgba(255,255,255,.10),transparent 50%);pointer-events:none}
.boss-h{display:flex;align-items:center;gap:12px;margin-bottom:14px;position:relative;z-index:1;flex-wrap:wrap}
.boss-badge{padding:5px 12px;background:rgba(245,158,11,.32);border:1px solid rgba(251,191,36,.5);border-radius:99px;font-family:'Unbounded',sans-serif;font-size:.72rem;font-weight:800;letter-spacing:.06em;color:#fde68a;text-transform:uppercase}
.boss-title{font-family:'Outfit',sans-serif;font-size:1.2rem;font-weight:800;flex:1}
.boss-hp{margin-bottom:14px;position:relative;z-index:1}
.boss-hp-label{display:flex;justify-content:space-between;font-size:.78rem;font-weight:700;margin-bottom:5px;color:#e0e7ff}
.boss-hp-bar{height:12px;background:rgba(255,255,255,.10);border-radius:7px;overflow:hidden;border:1px solid rgba(255,255,255,.18)}
.boss-hp-fill{height:100%;background:linear-gradient(90deg,#f59e0b,#ef4444);transition:width .5s ease-out}
.boss-question{background:rgba(0,0,0,.32);border-radius:12px;padding:16px;margin-bottom:14px;position:relative;z-index:1;border:1px solid rgba(255,255,255,.10)}
.boss-stage-label{font-size:.74rem;color:#a5b4fc;font-weight:700;letter-spacing:.08em;text-transform:uppercase;margin-bottom:6px}
.boss-q{font-size:1.02rem;font-weight:700;margin-bottom:14px;line-height:1.55}
.boss-opts{display:flex;gap:8px;flex-wrap:wrap}
.boss-opt{padding:10px 16px;background:rgba(255,255,255,.10);border:1.5px solid rgba(255,255,255,.20);border-radius:9px;color:#fff;font-weight:700;font-size:.92rem;cursor:pointer;font-family:inherit;transition:all .15s}
.boss-opt:hover{background:rgba(255,255,255,.18);border-color:rgba(255,255,255,.4)}
.boss-opt.correct{background:linear-gradient(135deg,#16a34a,#22c55e);border-color:#86efac;animation:pop .35s}
.boss-opt.wrong{background:linear-gradient(135deg,#dc2626,#ef4444);border-color:#fca5a5;animation:shake .35s}
.boss-input{display:inline-flex;align-items:center;gap:6px;background:rgba(0,0,0,.36);border:1.5px solid rgba(255,255,255,.20);border-radius:9px;padding:4px 6px}
.boss-input.wrong{border-color:#fca5a5;animation:shake .35s}
.boss-input input{background:transparent;border:none;outline:none;color:#fff;font-family:'JetBrains Mono',monospace;font-size:.95rem;font-weight:700;padding:6px 8px;width:100px}
.boss-input button{background:#f59e0b;border:none;color:#fff;padding:6px 12px;border-radius:6px;cursor:pointer;font-weight:800;font-size:.82rem;font-family:inherit}
.boss-defeated{text-align:center;padding:16px;position:relative;z-index:1}
.boss-defeated-title{font-family:'Outfit',sans-serif;font-size:1.3rem;font-weight:900;color:#fde68a;margin-bottom:8px;letter-spacing:-.01em}
.boss-defeated-sub{font-size:.92rem;color:#c7d2fe;margin-bottom:14px}
.boss-defeated-xp{display:inline-flex;align-items:center;gap:6px;padding:8px 16px;background:linear-gradient(135deg,#f59e0b,#dc2626);border-radius:99px;font-family:'Unbounded',sans-serif;font-weight:800;font-size:.86rem;letter-spacing:.06em;box-shadow:0 6px 20px rgba(245,158,11,.4)}
.boss.victory{background:linear-gradient(135deg,#15803d,#22c55e 50%,#86efac)}
.boss.victory::before{background:radial-gradient(circle at 50% 50%,rgba(254,240,138,.20),transparent 70%)}
.para-actions{display:flex;justify-content:center;margin-top:18px;gap:10px}
.mark-btn{padding:11px 22px;background:var(--pri);color:#fff;border:none;border-radius:11px;font-weight:800;font-size:.92rem;cursor:pointer;font-family:'Inter',sans-serif;display:inline-flex;align-items:center;gap:8px;transition:filter .15s,transform .15s;box-shadow:var(--sh)}
.mark-btn:hover{filter:brightness(1.10);transform:translateY(-1px)}
.mark-btn.done{background:linear-gradient(135deg,var(--good),#22c55e)}
.stub-card{background:linear-gradient(135deg,var(--pri-soft),transparent);border:1px dashed var(--pri-l);border-radius:14px;padding:24px;text-align:center;color:var(--pri-d);margin-bottom:24px}
.stub-card b{font-family:'Outfit',sans-serif;font-size:1.1rem;display:block;margin-bottom:4px}
.stub-card small{display:block;margin-top:6px;color:var(--muted);font-size:.84rem}
.foot{text-align:center;padding:24px 16px;color:var(--muted);font-size:.78rem;border-top:1px solid var(--border-2);margin-top:30px}
@media (max-width:560px){
.hdr h1{font-size:1.35rem}
.hdr-sub{font-size:.85rem}
.para-num{font-size:1.3rem;padding:8px 12px}
.para-h h2{font-size:1.3rem}
.quiz{flex-direction:column;align-items:flex-start}
}
</style>
</head>
<body>
<header class="hdr">
<div class="hdr-inner">
<div>
<a href="/textbook/geometry-10" class="hdr-back">
<svg class="ic" viewBox="0 0 24 24"><polyline points="15 18 9 12 15 6"/></svg>
К курсу
</a>
</div>
<div>
<h1>Раздел 1. Введение в стереометрию</h1>
<div class="hdr-sub">Пространственные фигуры · Аксиомы · Сечения</div>
</div>
<div class="hdr-side">
<span class="hdr-xp" id="hdr-xp">0 XP</span>
<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>
</button>
</div>
</div>
</header>
<nav class="sec-nav">
<div class="sec-nav-inner">
<a class="sec-tab active" data-tab="1" href="#para-1"><span class="dot"></span>§1 Фигуры</a>
<a class="sec-tab" data-tab="2" href="#para-2"><span class="dot"></span>§2 Аксиомы</a>
<a class="sec-tab locked" data-tab="3" href="#para-3"><span class="dot"></span>§3 Сечения</a>
<a class="sec-tab locked" data-tab="final" href="#para-final"><span class="dot"></span>Финал</a>
</div>
</nav>
<main>
<section id="para-1" class="para">
<div class="para-head">
<div class="para-num">§ 1</div>
<div class="para-h">
<h2>Пространственные фигуры</h2>
<div class="para-h-sub">Многогранники и тела вращения · грани, рёбра, вершины · формула Эйлера</div>
</div>
</div>
<div class="viz">
<div class="viz-title"><span class="badge">5 ОСНОВНЫХ ТЕЛ</span> Знакомство со стереометрией</div>
<div class="viz-row" id="viz1-solids"></div>
<div class="viz-cap">Стереометрия изучает фигуры в трёхмерном пространстве. Слева направо: <b>призма</b>, <b>пирамида</b>, <b>цилиндр</b>, <b>конус</b>, <b>шар</b>. Первые две — <b>многогранники</b> (все грани плоские), три остальные — <b>тела вращения</b>.</div>
</div>
<div class="theory">
<div class="t-card">
<span class="t-tag">1.1</span>
<div class="t-title">Многогранник: грани, рёбра, вершины</div>
<div class="t-body">
<p><b>Многогранник</b> — тело, ограниченное конечным числом плоских многоугольников.</p>
<ul>
<li><b>Грань</b> — каждый из этих многоугольников.</li>
<li><b>Ребро</b> — общая сторона двух соседних граней.</li>
<li><b>Вершина</b> — общая точка трёх или более рёбер.</li>
<li><b>Диагональ</b> — отрезок, соединяющий две вершины, не лежащие на одной грани.</li>
</ul>
</div>
</div>
<div class="t-card">
<span class="t-tag">1.2</span>
<div class="t-title">Призма</div>
<div class="t-body">
<p><b>Призма</b> — многогранник, у которого две грани (<b>основания</b>) — равные многоугольники в параллельных плоскостях, а остальные грани (<b>боковые</b>) — параллелограммы.</p>
<p><b>Виды:</b> прямая (боковые рёбра ⊥ основанию) или наклонная; правильная — прямая с основанием в виде правильного $n$-угольника.</p>
<p>Параллелепипед — частный случай призмы (основание — параллелограмм).</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">1.3</span>
<div class="t-title">Пирамида</div>
<div class="t-body">
<p><b>Пирамида</b> — многогранник с одним основанием-многоугольником и боковыми гранями-треугольниками с общей <b>вершиной пирамиды</b>.</p>
<p>Правильная пирамида: основание — правильный $n$-угольник, вершина проектируется в его центр.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">1.4</span>
<div class="t-title">Тела вращения</div>
<div class="t-body">
<p><b>Цилиндр</b> — вращение прямоугольника вокруг одной из его сторон.</p>
<p><b>Конус</b> — вращение прямоугольного треугольника вокруг катета.</p>
<p><b>Шар</b> — вращение полукруга вокруг диаметра.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">1.5</span>
<div class="t-title">Формула Эйлера</div>
<div class="t-body">
<p>Для любого <b>выпуклого многогранника</b>:</p>
<p style="text-align:center;font-size:1.05rem;margin:8px 0">$$ В - Р + Г = 2 $$</p>
<p>где В — число вершин, Р — рёбер, Г — граней. Куб: $В=8, Р=12, Г=6 \Rightarrow 8-12+6=2$. ✓</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">1.6</span>
<div class="t-title">Изображение на плоскости</div>
<div class="t-body">
<p>Пространственные фигуры изображают на плоскости в параллельной проекции (чаще — <b>кабинетной</b>).</p>
<p>Видимые рёбра — <b>сплошной</b> линией, невидимые — <b>штриховой</b>.</p>
<p>Параллельные отрезки остаются параллельными, но длины и углы искажаются.</p>
</div>
</div>
</div>
<div class="viz">
<div class="viz-title"><span class="badge">КУБ</span> Грани · рёбра · вершины · диагональ</div>
<div id="viz1-cube"></div>
<div class="viz-cap">Куб $ABCDA_1B_1C_1D_1$. Видимые рёбра — сплошные, невидимые — штриховые. Подсвечена <span style="color:#dc2626;font-weight:800">пространственная диагональ $AC_1$</span> и одна <span style="color:#7c3aed;font-weight:800">боковая грань $ABB_1A_1$</span>.</div>
</div>
<div class="viz">
<div class="viz-title"><span class="badge">ПРИЗМЫ</span> Прямая и наклонная</div>
<div class="viz-row">
<div class="viz-cell"><div id="viz1-prism-direct"></div><div class="viz-cell-label">Прямая (правильная)</div></div>
<div class="viz-cell"><div id="viz1-prism-oblique"></div><div class="viz-cell-label">Наклонная</div></div>
</div>
<div class="viz-cap">У прямой призмы боковые рёбра перпендикулярны основанию; у наклонной — нет. Правильная — прямая с правильным $n$-угольником в основании.</div>
</div>
<div class="inter" data-inter="i1-solid">
<div class="inter-h">
<div class="inter-icon">1</div>
<div class="inter-title">Узнай тело по описанию</div>
<div class="inter-progress" id="i1-solid-prog">0 / 6</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i1-solid-q"></div>
<div class="quiz-opts" id="i1-solid-opts"></div>
</div>
<div class="quiz-feedback" id="i1-solid-fb"></div>
</div>
<div class="inter" data-inter="i1-count">
<div class="inter-h">
<div class="inter-icon">2</div>
<div class="inter-title">Сосчитай элементы</div>
<div class="inter-progress" id="i1-count-prog">0 / 6</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i1-count-q"></div>
<div class="quiz-input">
<input id="i1-count-in" type="text" inputmode="numeric" placeholder="?">
<button id="i1-count-go">OK</button>
</div>
</div>
<div class="quiz-feedback" id="i1-count-fb"></div>
</div>
<div class="inter" data-inter="i1-rot">
<div class="inter-h">
<div class="inter-icon">3</div>
<div class="inter-title">Куб с разных сторон</div>
<div class="inter-progress" id="i1-rot-prog">смотри 3D</div>
</div>
<div id="i1-rot-viz" style="text-align:center"></div>
<div class="rot-row">
<label>Поворот X <input id="i1-rot-x" type="range" min="-60" max="60" value="0" step="1"> <span id="i1-rot-xv" style="font-family:JetBrains Mono,monospace;color:var(--pri-d)"></span></label>
<label>Поворот Y <input id="i1-rot-y" type="range" min="-60" max="60" value="0" step="1"> <span id="i1-rot-yv" style="font-family:JetBrains Mono,monospace;color:var(--pri-d)"></span></label>
</div>
<div class="viz-cap">Покрути куб — видимые рёбра останутся сплошными, невидимые — пунктирными. Это «кабинетная» проекция: $y$-ось уходит вглубь под $30°$ со сжатием $\tfrac{1}{2}$.</div>
</div>
<div class="boss" id="boss-1"></div>
<div class="para-actions">
<button class="mark-btn" id="mark-1">
<svg class="ic" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg>
<span>Отметить §1 как изученный</span>
</button>
</div>
</section>
<section id="para-2" class="para">
<div class="para-head">
<div class="para-num">§ 2</div>
<div class="para-h">
<h2>Прямые и плоскости в пространстве</h2>
<div class="para-h-sub">Три аксиомы стереометрии и их следствия · 4 способа задания плоскости</div>
</div>
</div>
<div class="viz">
<div class="viz-title"><span class="badge">АКСИОМЫ A1A3</span> Основа стереометрии</div>
<div class="viz-row">
<div class="viz-cell"><div id="viz2-a1"></div><div class="viz-cell-label">A1: три точки</div></div>
<div class="viz-cell"><div id="viz2-a2"></div><div class="viz-cell-label">A2: прямая в плоскости</div></div>
<div class="viz-cell"><div id="viz2-a3"></div><div class="viz-cell-label">A3: пересечение</div></div>
</div>
<div class="viz-cap">Три аксиомы стереометрии: через 3 точки — единственная плоскость; прямая лежит в плоскости, если 2 её точки в ней; две плоскости пересекаются по прямой.</div>
</div>
<div class="theory">
<div class="t-card">
<span class="t-tag">A1</span>
<div class="t-title">Через три точки</div>
<div class="t-body">
<p>Через любые три точки, <b>не лежащие на одной прямой</b>, проходит <b>единственная</b> плоскость.</p>
<p>Если же точки коллинеарны — плоскостей бесконечно много (можно «вращать» вокруг прямой).</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">A2</span>
<div class="t-title">Прямая в плоскости</div>
<div class="t-body">
<p>Если две точки прямой лежат в плоскости, то и <b>вся прямая</b> лежит в этой плоскости.</p>
<p>Обозначение: $a \subset \alpha$ — «прямая $a$ лежит в плоскости $\alpha$».</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">A3</span>
<div class="t-title">Пересечение плоскостей</div>
<div class="t-body">
<p>Если две плоскости имеют общую точку, то они имеют <b>общую прямую</b>, на которой лежат все их общие точки.</p>
<p>Эту прямую называют <b>линией пересечения</b> плоскостей: $\alpha \cap \beta = l$.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">2.4</span>
<div class="t-title">Следствия из аксиом</div>
<div class="t-body">
<ul>
<li>Через <b>прямую и точку</b> вне её — единственная плоскость.</li>
<li>Через <b>две пересекающиеся</b> прямые — единственная плоскость.</li>
<li>Через <b>две параллельные</b> прямые — единственная плоскость.</li>
</ul>
</div>
</div>
<div class="t-card">
<span class="t-tag">2.5</span>
<div class="t-title">4 способа задать плоскость</div>
<div class="t-body">
<ul>
<li>3 точки, не лежащие на одной прямой;</li>
<li>прямая и точка вне её;</li>
<li>две пересекающиеся прямые;</li>
<li>две параллельные прямые.</li>
</ul>
<p>Все эти способы — переформулировки аксиомы A1.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">2.6</span>
<div class="t-title">Обозначения</div>
<div class="t-body">
<ul>
<li>$A \in \alpha$ — точка $A$ принадлежит плоскости $\alpha$;</li>
<li>$a \subset \alpha$ — прямая $a$ лежит в $\alpha$;</li>
<li>$\alpha \cap \beta = c$ — плоскости пересекаются по прямой $c$;</li>
<li>$a \parallel b$ — прямые параллельны.</li>
</ul>
</div>
</div>
</div>
<div class="viz">
<div class="viz-title"><span class="badge">СЛЕДСТВИЯ</span> 3 способа однозначно задать плоскость</div>
<div class="viz-row">
<div class="viz-cell"><div id="viz2-c1"></div><div class="viz-cell-label">Прямая + точка</div></div>
<div class="viz-cell"><div id="viz2-c2"></div><div class="viz-cell-label">Пересекающиеся прямые</div></div>
<div class="viz-cell"><div id="viz2-c3"></div><div class="viz-cell-label">Параллельные прямые</div></div>
</div>
</div>
<div class="inter" data-inter="i2-axiom">
<div class="inter-h">
<div class="inter-icon">1</div>
<div class="inter-title">Какая аксиома или следствие?</div>
<div class="inter-progress" id="i2-axiom-prog">0 / 6</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i2-axiom-q"></div>
<div class="quiz-opts" id="i2-axiom-opts"></div>
</div>
<div class="quiz-feedback" id="i2-axiom-fb"></div>
</div>
<div class="inter" data-inter="i2-plane">
<div class="inter-h">
<div class="inter-icon">2</div>
<div class="inter-title">Можно ли задать плоскость?</div>
<div class="inter-progress" id="i2-plane-prog">0 / 5</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i2-plane-q"></div>
<div class="quiz-opts" id="i2-plane-opts"></div>
</div>
<div class="quiz-feedback" id="i2-plane-fb"></div>
</div>
<div class="inter" data-inter="i2-count">
<div class="inter-h">
<div class="inter-icon">3</div>
<div class="inter-title">Сколько плоскостей?</div>
<div class="inter-progress" id="i2-count-prog">0 / 5</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i2-count-q"></div>
<div class="quiz-opts" id="i2-count-opts"></div>
</div>
<div class="quiz-feedback" id="i2-count-fb"></div>
</div>
<div class="boss" id="boss-2"></div>
<div class="para-actions">
<button class="mark-btn" id="mark-2">
<svg class="ic" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg>
<span>Отметить §2 как изученный</span>
</button>
</div>
</section>
<section id="para-3" class="para">
<div class="para-head">
<div class="para-num">§ 3</div>
<div class="para-h">
<h2>Построения сечений</h2>
<div class="para-h-sub">Метод следов · сечения куба, призмы, пирамиды</div>
</div>
</div>
<div class="stub-card">
<b>В разработке (Волна W2)</b>
Параграф появится в следующей волне: сложная анимированная визуализация построения сечений многогранников.
<small>Сейчас сосредоточься на §1 и §2 — они дают контекст для §3.</small>
</div>
</section>
<section id="para-final" class="para">
<div class="para-head">
<div class="para-num"></div>
<div class="para-h">
<h2>Финал раздела 1</h2>
<div class="para-h-sub">4 интегральных босса · ачивка «Введение в стереометрию пройдено!»</div>
</div>
</div>
<div class="stub-card">
<b>Откроется после §3 (Волна W2)</b>
Финал содержит 4 босса (элементы тел, аксиомы, сечения, сборная задача) и спецачивку.
<small>До этого момента — побеждай боссов §1 и §2, чтобы заработать XP.</small>
</div>
</section>
</main>
<footer class="foot">
Геометрия — 10 класс · Раздел 1 · LearnSpace
</footer>
<script>
'use strict';
(function(){
var saved = localStorage.getItem('geometry10_theme') || localStorage.getItem('theme') || 'light';
if (saved === 'dark') document.documentElement.classList.add('dark');
var lab = document.getElementById('theme-lab');
if (lab) lab.textContent = saved === 'dark' ? 'Светлая' : 'Тёмная';
document.getElementById('theme-btn').addEventListener('click', function(){
document.documentElement.classList.toggle('dark');
var dark = document.documentElement.classList.contains('dark');
localStorage.setItem('geometry10_theme', dark ? 'dark' : 'light');
localStorage.setItem('theme', dark ? 'dark' : 'light');
if (lab) lab.textContent = dark ? 'Светлая' : 'Тёмная';
});
})();
var STATE_KEY = 'geometry10_r1_state';
var STATE = (function(){
try { var raw = localStorage.getItem(STATE_KEY); if (raw) return JSON.parse(raw); } catch(e){}
return { read:[], bosses:{}, interactives:{} };
})();
function saveState(){ try { localStorage.setItem(STATE_KEY, JSON.stringify(STATE)); } catch(e){} }
function addXp(amount, reason){
var cur = parseInt(localStorage.getItem('geometry10_xp') || '0', 10) || 0;
cur += amount;
localStorage.setItem('geometry10_xp', String(cur));
updateXpBadge();
if (window.LS && window.LS.xp && typeof window.LS.xp.toast === 'function'){
window.LS.xp.toast('+' + amount + ' XP — ' + (reason || ''));
}
}
function updateXpBadge(){
var el = document.getElementById('hdr-xp');
if (el) el.textContent = (parseInt(localStorage.getItem('geometry10_xp')||'0',10)||0) + ' XP';
}
updateXpBadge();
var syncTimer = null;
function syncProgress(){
if (syncTimer) clearTimeout(syncTimer);
syncTimer = setTimeout(function(){
if (!window.LS || typeof window.LS.api !== 'function') return;
window.LS.api('/api/textbooks/geometry-10-r1/progress', {
method:'POST',
body: JSON.stringify({ read: STATE.read })
}).catch(function(){});
}, 600);
}
function markRead(paraNum){
if (STATE.read.indexOf(paraNum) < 0){
STATE.read.push(paraNum);
saveState();
syncProgress();
}
refreshTabs();
refreshMarkBtn(paraNum);
}
function refreshMarkBtn(n){
var btn = document.getElementById('mark-' + n);
if (!btn) return;
if (STATE.read.indexOf(n) >= 0){
btn.classList.add('done');
btn.querySelector('span').textContent = '§' + n + ' изучен';
}
}
function refreshTabs(){
document.querySelectorAll('.sec-tab').forEach(function(t){
var n = t.getAttribute('data-tab');
if (n === '1' || n === '2'){
if (STATE.read.indexOf(parseInt(n,10)) >= 0) t.classList.add('read');
else t.classList.remove('read');
}
});
}
function buildHeroSolids(){
if (!window.STEREO3D) return setTimeout(buildHeroSolids, 80);
var S = window.STEREO3D;
var defs = [
{ label:'Призма (6-уг)', fn:function(sc){sc.addPrism({n:6,baseRadius:1.1,height:1.8,color:'#dbeafe'});} },
{ label:'Пирамида (4-уг)', fn:function(sc){sc.addPyramid({n:4,baseRadius:1.2,height:1.9,color:'#fee2e2'});} },
{ label:'Цилиндр', fn:function(sc){sc.addCylinder({segments:28,baseRadius:1.0,height:1.9,color:'#d1fae5'});} },
{ label:'Конус', fn:function(sc){sc.addCone({segments:28,baseRadius:1.1,height:2.0,color:'#fef3c7'});} },
{ label:'Шар', fn:function(sc){sc.addSphere({center:[0,0,0],radius:1.2,color:'#ede9fe'});} }
];
var row = document.getElementById('viz1-solids');
if (!row) return;
row.innerHTML = '';
for (var i = 0; i < defs.length; i++){
var sc = new S.Scene(180, 170, {view:'CABINET', scale:34, bg:'transparent', border:'none'});
defs[i].fn(sc);
var cell = document.createElement('div');
cell.className = 'viz-cell';
cell.innerHTML = sc.render() + '<div class="viz-cell-label">' + defs[i].label + '</div>';
row.appendChild(cell);
}
}
function buildAnnotatedCube(){
if (!window.STEREO3D) return setTimeout(buildAnnotatedCube, 80);
var S = window.STEREO3D;
var sc = new S.Scene(420, 320, {view:'CABINET', scale:55});
sc.addCube({center:[0,0,0], size:2.0, labels:true});
sc.addEdge([-1,-1,-1],[+1,+1,+1], {stroke:'#dc2626', width:3, dash:'5 3'});
sc.addFace([[-1,-1,-1],[1,-1,-1],[1,-1,1],[-1,-1,1]], {fill:'#a78bfa', opacity:0.30, stroke:'none'});
document.getElementById('viz1-cube').innerHTML = sc.render();
}
function buildPrismDirect(){
if (!window.STEREO3D) return setTimeout(buildPrismDirect, 80);
var S = window.STEREO3D;
var sc = new S.Scene(220, 220, {view:'CABINET', scale:36});
sc.addPrism({n:6, baseRadius:1.2, height:2.0, color:'#dbeafe'});
document.getElementById('viz1-prism-direct').innerHTML = sc.render();
}
function buildPrismOblique(){
if (!window.STEREO3D) return setTimeout(buildPrismOblique, 80);
var S = window.STEREO3D;
var sc = new S.Scene(220, 220, {view:'CABINET', scale:36});
var n = 6, r = 1.2, h = 2.0, shift = 0.7;
var bottom = [], top = [];
for (var i = 0; i < n; i++){
var a = 2 * Math.PI * i / n - Math.PI/2;
bottom.push([r*Math.cos(a), r*Math.sin(a), -h/2]);
top.push([r*Math.cos(a) + shift, r*Math.sin(a), +h/2]);
}
var verts = bottom.concat(top);
var faces = [];
var bi = []; for (var k = 0; k < n; k++) bi.push(k);
var ti = []; for (var k2 = 0; k2 < n; k2++) ti.push(k2 + n);
faces.push(bi); faces.push(ti.slice().reverse());
for (var j = 0; j < n; j++){
var jj = (j+1) % n;
faces.push([j, jj, jj+n, j+n]);
}
var edges = [];
for (var e = 0; e < n; e++){
var ee = (e+1) % n;
edges.push([e, ee]);
edges.push([e+n, ee+n]);
edges.push([e, e+n]);
}
sc._addPolyhedron(verts, faces, edges, [], {color:'#fef3c7', opacity:0.4});
document.getElementById('viz1-prism-oblique').innerHTML = sc.render();
}
function buildRotCube(){
if (!window.STEREO3D) return setTimeout(buildRotCube, 80);
var S = window.STEREO3D;
var holder = document.getElementById('i1-rot-viz');
var rx = document.getElementById('i1-rot-x');
var ry = document.getElementById('i1-rot-y');
var rxv = document.getElementById('i1-rot-xv');
var ryv = document.getElementById('i1-rot-yv');
function draw(){
var ax = parseFloat(rx.value) * Math.PI / 180;
var ay = parseFloat(ry.value) * Math.PI / 180;
rxv.textContent = rx.value + '°';
ryv.textContent = ry.value + '°';
var sc = new S.Scene(360, 280, {view:'CABINET', scale:56, rotX:ax, rotY:ay});
sc.addCube({center:[0,0,0], size:2.0, labels:true, color:'#dbeafe'});
holder.innerHTML = sc.render();
}
rx.addEventListener('input', draw);
ry.addEventListener('input', draw);
draw();
}
function buildAxiomVizes(){
if (!window.STEREO3D) return setTimeout(buildAxiomVizes, 80);
var S = window.STEREO3D;
(function(){
var sc = new S.Scene(220, 200, {view:'CABINET', scale:42});
sc.addPlane([0,0,0], [0,0,1], {size:2.0, label:'α'});
sc.addVertex([-1.0, -0.6, 0], 'A', {dx:-14, dy:-8, color:'#dc2626'});
sc.addVertex([+1.0, -0.4, 0], 'B', {dx:8, dy:-8, color:'#dc2626'});
sc.addVertex([+0.2, +1.0, 0], 'C', {dx:8, dy:-8, color:'#dc2626'});
document.getElementById('viz2-a1').innerHTML = sc.render();
})();
(function(){
var sc = new S.Scene(220, 200, {view:'CABINET', scale:42});
sc.addPlane([0,0,0], [0,0,1], {size:2.0, label:'α'});
sc.addEdge([-1.5, -0.8, 0], [+1.5, +0.8, 0], {stroke:'#dc2626', width:2.6});
sc.addLabel('a', [+1.5, +0.8, 0], {dx:14, dy:-4, color:'#dc2626', fontSize:15, anchor:'start'});
sc.addVertex([-1.0, -0.5, 0], 'M', {dx:-16, dy:-8, color:'#1e3a8a'});
sc.addVertex([+1.0, +0.5, 0], 'N', {dx:8, dy:-8, color:'#1e3a8a'});
document.getElementById('viz2-a2').innerHTML = sc.render();
})();
(function(){
var sc = new S.Scene(220, 200, {view:'CABINET', scale:42});
sc.addPlane([0,0,0], [0,0,1], {size:1.6, label:'α', opacity:0.20});
sc.addPlane([0,0,0], [Math.cos(Math.PI/4),0,Math.sin(Math.PI/4)], {size:1.6, label:'β', opacity:0.22, fill:'#fde047'});
sc.addEdge([-1.4, 0, 0], [+1.4, 0, 0], {stroke:'#dc2626', width:2.8});
sc.addLabel('l', [+1.4, 0, 0], {dx:14, dy:-4, color:'#dc2626', fontSize:15, anchor:'start'});
document.getElementById('viz2-a3').innerHTML = sc.render();
})();
(function(){
var sc = new S.Scene(220, 200, {view:'CABINET', scale:42});
sc.addPlane([0,0,0], [0,0,1], {size:2.0, label:'α'});
sc.addEdge([-1.5, -0.4, 0], [+1.5, +0.4, 0], {stroke:'#1e3a8a', width:2.4});
sc.addLabel('a', [+1.5, +0.4, 0], {dx:14, dy:-4, color:'#1e3a8a', fontSize:14, anchor:'start'});
sc.addVertex([+0.4, -0.9, 0], 'M', {dx:8, dy:-8, color:'#dc2626'});
document.getElementById('viz2-c1').innerHTML = sc.render();
})();
(function(){
var sc = new S.Scene(220, 200, {view:'CABINET', scale:42});
sc.addPlane([0,0,0], [0,0,1], {size:2.0, label:'α'});
sc.addEdge([-1.5, -0.8, 0], [+1.5, +0.8, 0], {stroke:'#1e3a8a', width:2.4});
sc.addEdge([-1.0, +0.9, 0], [+1.1, -1.0, 0], {stroke:'#dc2626', width:2.4});
sc.addVertex([+0.05, 0.04, 0], 'O', {dx:8, dy:-10, color:'#0b1d33'});
sc.addLabel('a', [+1.5, +0.8, 0], {dx:12, dy:-4, color:'#1e3a8a', fontSize:14, anchor:'start'});
sc.addLabel('b', [+1.1, -1.0, 0], {dx:12, dy:-4, color:'#dc2626', fontSize:14, anchor:'start'});
document.getElementById('viz2-c2').innerHTML = sc.render();
})();
(function(){
var sc = new S.Scene(220, 200, {view:'CABINET', scale:42});
sc.addPlane([0,0,0], [0,0,1], {size:2.0, label:'α'});
sc.addEdge([-1.5, -0.6, 0], [+1.5, -0.6, 0], {stroke:'#1e3a8a', width:2.4});
sc.addEdge([-1.5, +0.6, 0], [+1.5, +0.6, 0], {stroke:'#dc2626', width:2.4});
sc.addLabel('a', [+1.5, -0.6, 0], {dx:12, dy:-4, color:'#1e3a8a', fontSize:14, anchor:'start'});
sc.addLabel('b', [+1.5, +0.6, 0], {dx:12, dy:-4, color:'#dc2626', fontSize:14, anchor:'start'});
document.getElementById('viz2-c3').innerHTML = sc.render();
})();
}
function runQuizMC(opts){
var state = STATE.interactives[opts.id] || { idx: 0, solved: 0 };
var qEl = document.getElementById(opts.id + '-q');
var optsEl = document.getElementById(opts.id + '-opts');
var fbEl = document.getElementById(opts.id + '-fb');
var progEl = document.getElementById(opts.id + '-prog');
function render(){
if (state.solved >= opts.items.length){
qEl.innerHTML = '<b style="color:var(--good)">Все задания решены!</b> +' + (opts.xpPerAll || 10) + ' XP.';
optsEl.innerHTML = '';
fbEl.classList.remove('show');
progEl.textContent = opts.items.length + ' / ' + opts.items.length;
if (!state.awarded){
state.awarded = true;
STATE.interactives[opts.id] = state;
saveState();
addXp(opts.xpPerAll || 10, opts.title || 'тренажёр');
}
return;
}
var item = opts.items[state.idx % opts.items.length];
qEl.innerHTML = item.q;
optsEl.innerHTML = '';
fbEl.classList.remove('show');
for (var i = 0; i < item.opts.length; i++){
(function(i){
var btn = document.createElement('button');
btn.className = 'quiz-opt';
btn.innerHTML = item.opts[i];
btn.addEventListener('click', function(){
var correct = (i === item.correct);
if (correct){
btn.classList.add('correct');
state.solved++;
state.idx++;
STATE.interactives[opts.id] = state;
saveState();
progEl.textContent = state.solved + ' / ' + opts.items.length;
fbEl.className = 'quiz-feedback show good';
fbEl.innerHTML = '<b>Верно.</b> ' + (item.explain || '');
tryKatex(fbEl);
setTimeout(render, 900);
} else {
btn.classList.add('wrong');
fbEl.className = 'quiz-feedback show bad';
fbEl.innerHTML = '<b>Не так.</b> ' + (item.explain || '');
tryKatex(fbEl);
}
});
optsEl.appendChild(btn);
})(i);
}
progEl.textContent = state.solved + ' / ' + opts.items.length;
tryKatex(qEl);
}
render();
}
function runQuizInput(opts){
var state = STATE.interactives[opts.id] || { idx:0, solved:0 };
var qEl = document.getElementById(opts.id + '-q');
var inEl = document.getElementById(opts.id + '-in');
var goEl = document.getElementById(opts.id + '-go');
var fbEl = document.getElementById(opts.id + '-fb');
var progEl = document.getElementById(opts.id + '-prog');
var box = inEl.parentNode;
function render(){
if (state.solved >= opts.items.length){
qEl.innerHTML = '<b style="color:var(--good)">Все задания решены!</b> +' + (opts.xpPerAll || 10) + ' XP.';
inEl.value = ''; inEl.disabled = true; goEl.disabled = true;
progEl.textContent = opts.items.length + ' / ' + opts.items.length;
box.className = 'quiz-input correct';
if (!state.awarded){
state.awarded = true;
STATE.interactives[opts.id] = state;
saveState();
addXp(opts.xpPerAll || 10, opts.title || 'тренажёр');
}
return;
}
var item = opts.items[state.idx % opts.items.length];
qEl.innerHTML = item.q;
inEl.value = ''; inEl.disabled = false; goEl.disabled = false;
fbEl.classList.remove('show');
box.className = 'quiz-input';
progEl.textContent = state.solved + ' / ' + opts.items.length;
tryKatex(qEl);
}
function check(){
var item = opts.items[state.idx % opts.items.length];
var v = (inEl.value || '').trim().toLowerCase().replace(/\s+/g,'');
var ans = String(item.answer).toLowerCase().replace(/\s+/g,'');
if (v === ans){
box.className = 'quiz-input correct';
state.solved++;
state.idx++;
STATE.interactives[opts.id] = state;
saveState();
fbEl.className = 'quiz-feedback show good';
fbEl.innerHTML = '<b>Верно.</b> ' + (item.explain || '');
tryKatex(fbEl);
setTimeout(render, 900);
} else {
box.className = 'quiz-input wrong';
fbEl.className = 'quiz-feedback show bad';
fbEl.innerHTML = '<b>Не так.</b> ' + (item.explain || '');
tryKatex(fbEl);
}
}
goEl.addEventListener('click', check);
inEl.addEventListener('keydown', function(e){ if (e.key === 'Enter') check(); });
render();
}
var i1SolidItems = [
{ q:'Тело с двумя равными $n$-угольными гранями в параллельных плоскостях и $n$ параллелограммами по бокам.', opts:['Призма','Пирамида','Цилиндр','Конус'], correct:0, explain:'Это определение призмы.' },
{ q:'Тело с одной многоугольной гранью и треугольными боковыми гранями с общей вершиной.', opts:['Призма','Пирамида','Цилиндр','Конус'], correct:1, explain:'Пирамида: одно основание + треугольные боковые.' },
{ q:'Тело, полученное вращением прямоугольника вокруг одной из его сторон.', opts:['Шар','Цилиндр','Конус','Призма'], correct:1, explain:'Цилиндр — тело вращения прямоугольника.' },
{ q:'Тело, полученное вращением прямоугольного треугольника вокруг катета.', opts:['Конус','Цилиндр','Шар','Пирамида'], correct:0, explain:'Конус — вращение прямоугольного треугольника вокруг катета.' },
{ q:'Тело, полученное вращением полукруга вокруг диаметра.', opts:['Цилиндр','Конус','Шар','Тор'], correct:2, explain:'Шар — вращение полукруга вокруг диаметра.' },
{ q:'Многогранник, у которого все 4 грани — равные правильные треугольники.', opts:['Куб','Тетраэдр','Октаэдр','Икосаэдр'], correct:1, explain:'Правильный тетраэдр: 4 равносторонних треугольника.' }
];
var i1CountItems = [
{ q:'Сколько рёбер у шестиугольной призмы?', answer:'18', explain:'У $n$-угольной призмы $3n$ рёбер. При $n=6$: $3 \\cdot 6 = 18$.' },
{ q:'Сколько граней у пятиугольной пирамиды?', answer:'6', explain:'$n+1$ грань: $5+1=6$.' },
{ q:'Сколько вершин у куба?', answer:'8', explain:'У куба 8 вершин (по 4 на каждом из двух квадратных оснований).' },
{ q:'Сколько пространственных диагоналей у параллелепипеда?', answer:'4', explain:'4 диагонали — каждая соединяет противоположные вершины.' },
{ q:'Многогранник: $В=6, Г=8$. Найди $Р$ по формуле Эйлера.', answer:'12', explain:'$6 - Р + 8 = 2 \\Rightarrow Р = 12$. Это октаэдр.' },
{ q:'Сколько рёбер у 7-угольной пирамиды? (формула $2n$)', answer:'14', explain:'$2 \\cdot 7 = 14$ рёбер.' }
];
var i2AxiomItems = [
{ q:'«Через три точки $A, B, C$, не лежащие на одной прямой, проведена плоскость.»', opts:['A1','A2','A3','Следствие'], correct:0, explain:'Это формулировка A1.' },
{ q:'«Точки $M, N \\in \\alpha$, значит и вся прямая $MN \\subset \\alpha$.»', opts:['A1','A2','A3','Следствие'], correct:1, explain:'Аксиома A2.' },
{ q:'«Плоскости $\\alpha$ и $\\beta$ имеют общую точку $P$ — у них есть прямая пересечения.»', opts:['A1','A2','A3','Следствие'], correct:2, explain:'Аксиома A3.' },
{ q:'«Через прямую $a$ и точку $M \\notin a$ проходит единственная плоскость.»', opts:['A1','A2','A3','Следствие'], correct:3, explain:'Следствие из A1.' },
{ q:'«Через две пересекающиеся прямые проходит единственная плоскость.»', opts:['A1','A2','A3','Следствие'], correct:3, explain:'Следствие из A1.' },
{ q:'«Если две точки прямой лежат в плоскости — прямая лежит в плоскости.»', opts:['A1','A2','A3','Следствие'], correct:1, explain:'Точная формулировка A2.' }
];
var i2PlaneItems = [
{ q:'Даны 3 точки, не лежащие на одной прямой. Можно задать плоскость?', opts:['Да, единственную','Да, бесконечно','Нельзя'], correct:0, explain:'A1: 3 неколлинеарные точки задают единственную плоскость.' },
{ q:'Даны 3 точки на одной прямой. Сколько плоскостей через них?', opts:['Одна','Бесконечно','Ни одной'], correct:1, explain:'Плоскостей бесконечно много (вращаются вокруг прямой).' },
{ q:'Через 2 пересекающиеся прямые проходит:', opts:['Одна плоскость','Две','Бесконечно'], correct:0, explain:'Следствие: единственная.' },
{ q:'Даны 2 скрещивающиеся прямые. Можно ли провести через них одну плоскость?', opts:['Да','Нет','Иногда'], correct:1, explain:'Скрещивающиеся не лежат в одной плоскости — это и есть определение.' },
{ q:'Через прямую и точку вне её проходит:', opts:['Одна плоскость','Две','Бесконечно'], correct:0, explain:'Следствие: единственная.' }
];
var i2CountItems = [
{ q:'Сколько плоскостей через 4 точки общего положения (никакие 3 — не на одной прямой, не все в одной плоскости)?', opts:['1','3','4','6'], correct:2, explain:'Каждые 3 из 4 определяют плоскость: $C_4^3 = 4$.' },
{ q:'Через 2 параллельные прямые проходит:', opts:['1 плоскость','2','Бесконечно'], correct:0, explain:'Единственная плоскость.' },
{ q:'Через сколько точек, не лежащих на одной прямой, проходит не более 1 плоскости?', opts:['2','3','4','5'], correct:1, explain:'3 точки задают плоскость однозначно.' },
{ q:'Сколько общих точек у двух различных пересекающихся плоскостей?', opts:['Одна','Конечное число','Бесконечно (по прямой)'], correct:2, explain:'A3: пересечение по прямой ⇒ бесконечно точек.' },
{ q:'Сколько плоскостей содержат данную прямую $l$?', opts:['Одна','Две','Бесконечно'], correct:2, explain:'Через прямую — бесконечно плоскостей.' }
];
var BOSS_DEFS = {
1: {
title:'§1 — Пространственные фигуры',
xp:60,
stages:[
{ q:'Сколько рёбер у пятиугольной призмы?', type:'input', a:'15', explain:'$3n = 3 \\cdot 5 = 15$ рёбер.' },
{ q:'Сколько вершин у $n$-угольной пирамиды при $n=8$?', type:'input', a:'9', explain:'$n+1 = 9$ вершин.' },
{ q:'Какое тело получится при вращении прямоугольника вокруг стороны?', type:'mc', opts:['Шар','Цилиндр','Конус','Призма'], correct:1, explain:'Цилиндр.' },
{ q:'Сколько пространственных диагоналей у куба?', type:'input', a:'4', explain:'Куб имеет 4 пространственные диагонали.' },
{ q:'У многогранника $В=12$, $Р=30$. Сколько граней по Эйлеру?', type:'input', a:'20', explain:'$12 - 30 + Г = 2 \\Rightarrow Г = 20$. Икосаэдр.' }
]
},
2: {
title:'§2 — Прямые и плоскости',
xp:65,
stages:[
{ q:'Через сколько плоскостей проходит прямая?', type:'mc', opts:['1','2','3','Бесконечно'], correct:3, explain:'Через прямую — бесконечно плоскостей.' },
{ q:'Через 3 точки на одной прямой — сколько плоскостей?', type:'mc', opts:['1','2','3','Бесконечно'], correct:3, explain:'Точки коллинеарны ⇒ бесконечно плоскостей.' },
{ q:'Если две плоскости имеют общую точку — они пересекаются по…', type:'mc', opts:['Точке','Прямой','Плоскости','Не пересекаются'], correct:1, explain:'A3: пересечение — прямая.' },
{ q:'Сколько способов однозначно задать плоскость?', type:'mc', opts:['2','3','4','5'], correct:2, explain:'4 способа: 3 точки, прямая + точка, 2 пересек., 2 парал.' },
{ q:'Сколько плоскостей задают 4 точки общего положения?', type:'input', a:'4', explain:'$C_4^3 = 4$ тройки точек.' }
]
}
};
function renderBoss(num){
var def = BOSS_DEFS[num];
if (!def) return;
var el = document.getElementById('boss-' + num);
if (!el) return;
var st = STATE.bosses[num] || { stage:0, defeated:false };
STATE.bosses[num] = st;
if (st.defeated){
el.classList.add('victory');
el.innerHTML = '<div class="boss-defeated">'
+ '<div class="boss-defeated-title">Босс §' + num + ' побеждён!</div>'
+ '<div class="boss-defeated-sub">' + def.title + '</div>'
+ '<span class="boss-defeated-xp">+' + def.xp + ' XP</span>'
+ '</div>';
return;
}
el.classList.remove('victory');
var total = def.stages.length;
var stage = def.stages[st.stage];
var hp = Math.round((1 - st.stage/total) * 100);
var optsHtml;
if (stage.type === 'mc'){
optsHtml = '<div class="boss-opts">';
for (var i = 0; i < stage.opts.length; i++){
optsHtml += '<button class="boss-opt" data-i="' + i + '">' + stage.opts[i] + '</button>';
}
optsHtml += '</div>';
} else {
optsHtml = '<div class="boss-input"><input type="text" id="boss-' + num + '-in" inputmode="text" placeholder="ответ"><button id="boss-' + num + '-go">Атака</button></div>';
}
el.innerHTML = '<div class="boss-h">'
+ '<span class="boss-badge">Босс</span>'
+ '<span class="boss-title">' + def.title + '</span>'
+ '</div>'
+ '<div class="boss-hp"><div class="boss-hp-label"><span>HP босса</span><span>' + hp + '%</span></div>'
+ '<div class="boss-hp-bar"><div class="boss-hp-fill" style="width:' + hp + '%"></div></div></div>'
+ '<div class="boss-question">'
+ '<div class="boss-stage-label">Этап ' + (st.stage+1) + ' / ' + total + '</div>'
+ '<div class="boss-q">' + stage.q + '</div>'
+ optsHtml + '</div>';
if (stage.type === 'mc'){
el.querySelectorAll('.boss-opt').forEach(function(btn){
btn.addEventListener('click', function(){
var i = parseInt(btn.getAttribute('data-i'), 10);
var ok = (i === stage.correct);
if (ok){
btn.classList.add('correct');
setTimeout(function(){ advanceBoss(num); }, 600);
} else {
btn.classList.add('wrong');
setTimeout(function(){ btn.classList.remove('wrong'); }, 600);
}
});
});
} else {
var inEl = document.getElementById('boss-' + num + '-in');
var goEl = document.getElementById('boss-' + num + '-go');
var box = inEl.parentNode;
function attack(){
var v = (inEl.value || '').trim().toLowerCase().replace(/\s+/g,'');
var a = String(stage.a).toLowerCase().replace(/\s+/g,'');
if (v === a){
box.classList.remove('wrong');
inEl.style.background = 'rgba(34,197,94,.25)';
setTimeout(function(){ advanceBoss(num); }, 500);
} else {
box.classList.add('wrong');
inEl.style.background = 'rgba(220,38,38,.25)';
setTimeout(function(){ box.classList.remove('wrong'); inEl.style.background=''; }, 600);
}
}
goEl.addEventListener('click', attack);
inEl.addEventListener('keydown', function(e){ if (e.key === 'Enter') attack(); });
}
tryKatex(el);
}
function advanceBoss(num){
var st = STATE.bosses[num];
var def = BOSS_DEFS[num];
st.stage++;
if (st.stage >= def.stages.length){
st.defeated = true;
saveState();
addXp(def.xp, 'босс §' + num);
} else {
saveState();
}
renderBoss(num);
}
function tryKatex(scope){
if (!window.renderMathInElement) return;
try {
window.renderMathInElement(scope || document.body, {
delimiters: [
{left:'$$', right:'$$', display:true},
{left:'$', right:'$', display:false},
{left:'\\(', right:'\\)', display:false},
{left:'\\[', right:'\\]', display:true}
],
throwOnError: false
});
} catch(e){}
}
function start(){
buildHeroSolids();
buildAnnotatedCube();
buildPrismDirect();
buildPrismOblique();
buildRotCube();
buildAxiomVizes();
runQuizMC({ id:'i1-solid', items:i1SolidItems, xpPerAll:12, title:'узнавание тел' });
runQuizInput({ id:'i1-count', items:i1CountItems, xpPerAll:15, title:'счёт элементов' });
runQuizMC({ id:'i2-axiom', items:i2AxiomItems, xpPerAll:12, title:'аксиомы' });
runQuizMC({ id:'i2-plane', items:i2PlaneItems, xpPerAll:10, title:'задание плоскости' });
runQuizMC({ id:'i2-count', items:i2CountItems, xpPerAll:10, title:'счёт плоскостей' });
renderBoss(1);
renderBoss(2);
document.getElementById('mark-1').addEventListener('click', function(){ markRead(1); });
document.getElementById('mark-2').addEventListener('click', function(){ markRead(2); });
refreshMarkBtn(1); refreshMarkBtn(2);
refreshTabs();
var tabs = document.querySelectorAll('.sec-tab[data-tab]');
var sections = ['para-1','para-2','para-3','para-final'];
function onScroll(){
var y = window.scrollY + 100;
var active = 0;
for (var i = 0; i < sections.length; i++){
var el = document.getElementById(sections[i]);
if (!el) continue;
if (el.offsetTop <= y) active = i;
}
tabs.forEach(function(t,j){ if (j === active) t.classList.add('active'); else t.classList.remove('active'); });
}
window.addEventListener('scroll', onScroll, {passive:true});
setTimeout(function(){ tryKatex(document.body); }, 50);
}
if (document.readyState === 'loading'){
document.addEventListener('DOMContentLoaded', start);
} else {
start();
}
</script>
</body>
</html>