7f045737d3
- Босс 1 Прямая ⊥ плоскость (4 этапа, +30 XP)
- Босс 2 Расстояния (4 этапа, +30 XP)
- Босс 3 Угол + ТТП (4 этапа, +35 XP, поддержка √2/2, 1/√3 и т.п.)
- Босс 4 ⊥-плоскости (4 этапа, +30 XP)
- Босс 5 Сборная (5 этапов, +45 XP — диагональ куба √3, sin угла 1/√3)
- Celebration: ачивка stereo10_r3_master + 130 XP бонус
- sec-nav: финал-таб разблокирован, refreshTabs учитывает {f1..f5}
- Состояние: STATE.bosses{f1..f5} + geometry10_achievements в localStorage
1714 lines
104 KiB
HTML
1714 lines
104 KiB
HTML
<!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 · Раздел 3 · Перпендикулярность</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:#fff1f2; --card:#fff; --card-2:#f1f5f9;
|
||
--text:#3f0a1c; --text-2:#7f1d1d; --muted:#475569;
|
||
--border:#fecdd3; --border-2:#e2e8f0;
|
||
--pri:#e11d48; --pri-d:#be123c; --pri-l:#fda4af;
|
||
--pri-soft:#fecdd3; --pri-soft-2:#ffe4e6;
|
||
--dark:#7f1d1d;
|
||
--accent:#7c3aed;
|
||
--good:#16a34a;
|
||
--warn:#d97706;
|
||
--sh:0 4px 16px rgba(225,29,72,.08);
|
||
--sh-h:0 12px 36px rgba(225,29,72,.18);
|
||
}
|
||
html.dark{
|
||
--bg:#1c0612; --card:#240a1c; --card-2:#2d1024;
|
||
--text:#fecdd3; --text-2:#fda4af; --muted:#94a3b8;
|
||
--border:#7f1d1d; --border-2:#1e293b;
|
||
--pri-soft:rgba(225,29,72,.18); --pri-soft-2:rgba(225,29,72,.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,#7c3aed);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(124,58,237,.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:240px;text-align:center}
|
||
.viz-cell-label{font-size:.78rem;color:var(--muted);font-weight:700;margin-top:6px}
|
||
|
||
.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:100px}
|
||
.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,#7f1d1d 0%,#9f1239 50%,#be123c 100%);color:#fff;border-radius:18px;padding:24px;margin-bottom:24px;position:relative;overflow:hidden;box-shadow:0 16px 48px rgba(190,18,60,.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:#fecdd3}
|
||
.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:#fda4af;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:110px}
|
||
.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:#fecdd3;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>Раздел 3. Перпендикулярность</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="7" href="#para-7"><span class="dot"></span>§7 Прямая ⊥ пл-сть</a>
|
||
<a class="sec-tab" data-tab="8" href="#para-8"><span class="dot"></span>§8 Расстояния</a>
|
||
<a class="sec-tab" data-tab="9" href="#para-9"><span class="dot"></span>§9 Угол</a>
|
||
<a class="sec-tab" data-tab="10" href="#para-10"><span class="dot"></span>§10 Пл-сти ⊥</a>
|
||
<a class="sec-tab" data-tab="final" href="#para-final"><span class="dot"></span>Финал</a>
|
||
</div>
|
||
</nav>
|
||
|
||
<main>
|
||
|
||
<!-- §7 -->
|
||
<section id="para-7" class="para">
|
||
<div class="para-head">
|
||
<div class="para-num">§ 7</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">ОПРЕДЕЛЕНИЕ</span> Прямая, перпендикулярная плоскости</div>
|
||
<div id="viz7-def" style="text-align:center"></div>
|
||
<div class="viz-cap">Прямая $l$ перпендикулярна плоскости $\alpha$, если она <b>перпендикулярна любой</b> прямой, лежащей в этой плоскости и проходящей через точку пересечения. Обозначение: $l \perp \alpha$.</div>
|
||
</div>
|
||
|
||
<div class="viz">
|
||
<div class="viz-title"><span class="badge">ПРИЗНАК</span> $l \perp m,\ l \perp n,\ m \cap n = O \Rightarrow l \perp \alpha$</div>
|
||
<div id="viz7-sign" style="text-align:center"></div>
|
||
<div class="viz-cap">Если прямая $l$ перпендикулярна <b>двум пересекающимся</b> прямым $m$ и $n$ в плоскости $\alpha$, то $l \perp \alpha$. Двух пересекающихся достаточно — необязательно проверять все прямые плоскости.</div>
|
||
</div>
|
||
|
||
<div class="theory">
|
||
<div class="t-card">
|
||
<span class="t-tag">7.1</span>
|
||
<div class="t-title">Определение</div>
|
||
<div class="t-body">
|
||
<p>Прямая $l$ называется <b>перпендикулярной плоскости</b> $\alpha$, если она перпендикулярна <b>каждой</b> прямой в $\alpha$, проходящей через точку их пересечения.</p>
|
||
<p>Обозначение: $l \perp \alpha$.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="t-card">
|
||
<span class="t-tag">7.2</span>
|
||
<div class="t-title">Признак перпендикулярности</div>
|
||
<div class="t-body">
|
||
<p>Если прямая $l$ перпендикулярна двум пересекающимся прямым $m$ и $n$ плоскости $\alpha$, то $l \perp \alpha$.</p>
|
||
<p>Это основной инструмент для доказательства перпендикулярности.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="t-card">
|
||
<span class="t-tag">7.3</span>
|
||
<div class="t-title">Свойство</div>
|
||
<div class="t-body">
|
||
<p>Если $l \perp \alpha$, то $l$ перпендикулярна <b>любой</b> прямой плоскости $\alpha$ (не только проходящей через точку пересечения, но и параллельной ей).</p>
|
||
<p>$l \perp \alpha,\ a \subset \alpha \Rightarrow l \perp a$.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="t-card">
|
||
<span class="t-tag">7.4</span>
|
||
<div class="t-title">Параллельность и перпендикулярность</div>
|
||
<div class="t-body">
|
||
<p>Если $l \perp \alpha$ и $l \parallel l'$, то $l' \perp \alpha$.</p>
|
||
<p>Если $l_1 \perp \alpha$ и $l_2 \perp \alpha$, то $l_1 \parallel l_2$.</p>
|
||
<p>Две прямые, перпендикулярные одной плоскости, всегда параллельны между собой.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="t-card">
|
||
<span class="t-tag">7.5</span>
|
||
<div class="t-title">Существование и единственность</div>
|
||
<div class="t-body">
|
||
<p>Через любую точку пространства проходит <b>единственная</b> прямая, перпендикулярная данной плоскости.</p>
|
||
<p>Через любую точку плоскости — единственная прямая, перпендикулярная этой плоскости.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="t-card">
|
||
<span class="t-tag">7.6</span>
|
||
<div class="t-title">Куб и перпендикулярность</div>
|
||
<div class="t-body">
|
||
<p>В кубе $ABCDA_1B_1C_1D_1$: ребро $AA_1$ перпендикулярно нижней грани $ABCD$, потому что $AA_1 \perp AB$ и $AA_1 \perp AD$ (две пересек. прямые в плоскости).</p>
|
||
<p>Аналогично — каждое боковое ребро перпендикулярно обоим основаниям.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="inter" data-inter="i7-perp">
|
||
<div class="inter-h">
|
||
<div class="inter-icon">1</div>
|
||
<div class="inter-title">Перпендикулярна ли прямая плоскости?</div>
|
||
<div class="inter-progress" id="i7-perp-prog">0 / 6</div>
|
||
</div>
|
||
<div class="quiz">
|
||
<div class="quiz-q" id="i7-perp-q"></div>
|
||
<div class="quiz-opts" id="i7-perp-opts"></div>
|
||
</div>
|
||
<div class="quiz-feedback" id="i7-perp-fb"></div>
|
||
</div>
|
||
|
||
<div class="inter" data-inter="i7-sign">
|
||
<div class="inter-h">
|
||
<div class="inter-icon">2</div>
|
||
<div class="inter-title">Применение признака</div>
|
||
<div class="inter-progress" id="i7-sign-prog">0 / 5</div>
|
||
</div>
|
||
<div class="quiz">
|
||
<div class="quiz-q" id="i7-sign-q"></div>
|
||
<div class="quiz-opts" id="i7-sign-opts"></div>
|
||
</div>
|
||
<div class="quiz-feedback" id="i7-sign-fb"></div>
|
||
</div>
|
||
|
||
<div class="inter" data-inter="i7-cube">
|
||
<div class="inter-h">
|
||
<div class="inter-icon">3</div>
|
||
<div class="inter-title">Перпендикулярность в кубе</div>
|
||
<div class="inter-progress" id="i7-cube-prog">0 / 5</div>
|
||
</div>
|
||
<div class="quiz">
|
||
<div class="quiz-q" id="i7-cube-q"></div>
|
||
<div class="quiz-opts" id="i7-cube-opts"></div>
|
||
</div>
|
||
<div class="quiz-feedback" id="i7-cube-fb"></div>
|
||
</div>
|
||
|
||
<div class="boss" id="boss-7"></div>
|
||
|
||
<div class="para-actions">
|
||
<button class="mark-btn" id="mark-7">
|
||
<svg class="ic" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg>
|
||
<span>Отметить §7 как изученный</span>
|
||
</button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- §8 -->
|
||
<section id="para-8" class="para">
|
||
<div class="para-head">
|
||
<div class="para-num">§ 8</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">4 ВИДА РАССТОЯНИЙ</span> Все через перпендикуляр</div>
|
||
<div class="viz-row">
|
||
<div class="viz-cell"><div id="viz8-pt-pl"></div><div class="viz-cell-label">Точка → плоскость</div></div>
|
||
<div class="viz-cell"><div id="viz8-ln-pl"></div><div class="viz-cell-label">Прямая ∥ плоскость</div></div>
|
||
<div class="viz-cell"><div id="viz8-pl-pl"></div><div class="viz-cell-label">Парал. плоскости</div></div>
|
||
<div class="viz-cell"><div id="viz8-skew"></div><div class="viz-cell-label">Скрещ. прямые</div></div>
|
||
</div>
|
||
<div class="viz-cap">Расстояние в стереометрии — всегда длина <b>перпендикуляра</b>. От точки до плоскости — это длина перпендикуляра, опущенного из точки.</div>
|
||
</div>
|
||
|
||
<div class="viz">
|
||
<div class="viz-title"><span class="badge">ТОЧКА И ПЛОСКОСТЬ</span> Расстояние $\rho(A, \alpha) = |AO|$</div>
|
||
<div id="viz8-detail" style="text-align:center"></div>
|
||
<div class="viz-cap">Точка $A$ вне плоскости $\alpha$. Опускаем перпендикуляр $AO$ ($O \in \alpha$). Длина $|AO|$ — расстояние от $A$ до $\alpha$. Любая <span style="color:#1e3a8a;font-weight:800">наклонная $AB$</span> всегда длиннее перпендикуляра.</div>
|
||
</div>
|
||
|
||
<div class="theory">
|
||
<div class="t-card">
|
||
<span class="t-tag">8.1</span>
|
||
<div class="t-title">Расстояние от точки до плоскости</div>
|
||
<div class="t-body">
|
||
<p>Длина перпендикуляра, опущенного из точки $A$ на плоскость $\alpha$.</p>
|
||
<p>Перпендикуляр короче любой наклонной из той же точки.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="t-card">
|
||
<span class="t-tag">8.2</span>
|
||
<div class="t-title">От прямой до параллельной плоскости</div>
|
||
<div class="t-body">
|
||
<p>Если $a \parallel \alpha$, то расстояние от $a$ до $\alpha$ — это расстояние от <b>любой точки</b> прямой $a$ до $\alpha$ (оно постоянно).</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="t-card">
|
||
<span class="t-tag">8.3</span>
|
||
<div class="t-title">Между параллельными плоскостями</div>
|
||
<div class="t-body">
|
||
<p>Длина общего перпендикуляра между $\alpha \parallel \beta$. Равна расстоянию от любой точки одной плоскости до другой.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="t-card">
|
||
<span class="t-tag">8.4</span>
|
||
<div class="t-title">Между скрещивающимися прямыми</div>
|
||
<div class="t-body">
|
||
<p>Длина <b>общего перпендикуляра</b> к двум скрещивающимся прямым.</p>
|
||
<p>Общий перпендикуляр существует, единствен и перпендикулярен обеим прямым.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="t-card">
|
||
<span class="t-tag">8.5</span>
|
||
<div class="t-title">Свойство перпендикуляра</div>
|
||
<div class="t-body">
|
||
<p>Перпендикуляр из точки на плоскость — это <b>кратчайший</b> отрезок от точки до плоскости.</p>
|
||
<p>Если из точки опущен перпендикуляр $AO$ и наклонная $AB$, то $|AO| \le |AB|$, причём равенство — только если $B = O$.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="t-card">
|
||
<span class="t-tag">8.6</span>
|
||
<div class="t-title">Куб: типовые расстояния</div>
|
||
<div class="t-body">
|
||
<p>В кубе с ребром $a$:</p>
|
||
<ul>
|
||
<li>Расстояние от $A$ до плоскости $A_1B_1C_1D_1$ равно $a$ (ребро $AA_1$).</li>
|
||
<li>Расстояние между рёбрами $AB$ и $C_1D_1$ равно $a\sqrt{2}$ (диагональ грани).</li>
|
||
<li>Расстояние между $AB$ и $CC_1$ равно $a$ (ребро $BC$).</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="inter" data-inter="i8-cube">
|
||
<div class="inter-h">
|
||
<div class="inter-icon">1</div>
|
||
<div class="inter-title">Расстояния в кубе (ребро $a = 1$)</div>
|
||
<div class="inter-progress" id="i8-cube-prog">0 / 6</div>
|
||
</div>
|
||
<div class="quiz">
|
||
<div class="quiz-q" id="i8-cube-q"></div>
|
||
<div class="quiz-input">
|
||
<input id="i8-cube-in" type="text" placeholder="ответ">
|
||
<button id="i8-cube-go">OK</button>
|
||
</div>
|
||
</div>
|
||
<div class="quiz-feedback" id="i8-cube-fb"></div>
|
||
</div>
|
||
|
||
<div class="inter" data-inter="i8-type">
|
||
<div class="inter-h">
|
||
<div class="inter-icon">2</div>
|
||
<div class="inter-title">Какое расстояние ищется?</div>
|
||
<div class="inter-progress" id="i8-type-prog">0 / 5</div>
|
||
</div>
|
||
<div class="quiz">
|
||
<div class="quiz-q" id="i8-type-q"></div>
|
||
<div class="quiz-opts" id="i8-type-opts"></div>
|
||
</div>
|
||
<div class="quiz-feedback" id="i8-type-fb"></div>
|
||
</div>
|
||
|
||
<div class="inter" data-inter="i8-true">
|
||
<div class="inter-h">
|
||
<div class="inter-icon">3</div>
|
||
<div class="inter-title">Верно или неверно</div>
|
||
<div class="inter-progress" id="i8-true-prog">0 / 5</div>
|
||
</div>
|
||
<div class="quiz">
|
||
<div class="quiz-q" id="i8-true-q"></div>
|
||
<div class="quiz-opts" id="i8-true-opts"></div>
|
||
</div>
|
||
<div class="quiz-feedback" id="i8-true-fb"></div>
|
||
</div>
|
||
|
||
<div class="boss" id="boss-8"></div>
|
||
|
||
<div class="para-actions">
|
||
<button class="mark-btn" id="mark-8">
|
||
<svg class="ic" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg>
|
||
<span>Отметить §8 как изученный</span>
|
||
</button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- §9 -->
|
||
<section id="para-9" class="para">
|
||
<div class="para-head">
|
||
<div class="para-num">§ 9</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">ОПРЕДЕЛЕНИЕ</span> Угол между наклонной и плоскостью</div>
|
||
<div id="viz9-angle" style="text-align:center"></div>
|
||
<div class="viz-cap">Точка $A$ вне плоскости $\alpha$. <span style="color:#dc2626;font-weight:800">$AH$ — перпендикуляр</span> ($H \in \alpha$). <span style="color:#1e3a8a;font-weight:800">$AB$ — наклонная</span> ($B \in \alpha, B \neq H$). <span style="color:#16a34a;font-weight:800">$HB$ — проекция наклонной</span>. <b>Углом</b> между $AB$ и $\alpha$ называется $\angle ABH$ — угол между наклонной и её проекцией.</div>
|
||
</div>
|
||
|
||
<div class="viz">
|
||
<div class="viz-title"><span class="badge">ТТП</span> Теорема о трёх перпендикулярах</div>
|
||
<div id="viz9-ttp" style="text-align:center"></div>
|
||
<div class="viz-cap">Если из основания $H$ перпендикуляра $AH$ к плоскости $\alpha$ провести в плоскости $\alpha$ прямую $BC \perp HB$, то и <b>наклонная</b> $AB \perp BC$. Обратное верно: $AB \perp BC \Rightarrow HB \perp BC$.</div>
|
||
</div>
|
||
|
||
<div class="theory">
|
||
<div class="t-card">
|
||
<span class="t-tag">9.1</span>
|
||
<div class="t-title">Наклонная и проекция</div>
|
||
<div class="t-body">
|
||
<p>Если $A \notin \alpha$, $AH \perp \alpha$ ($H \in \alpha$), а $AB$ — отрезок до $B \in \alpha, B \neq H$, то:</p>
|
||
<ul>
|
||
<li>$AH$ — <b>перпендикуляр</b> из $A$;</li>
|
||
<li>$AB$ — <b>наклонная</b>;</li>
|
||
<li>$HB$ — <b>проекция</b> наклонной $AB$.</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="t-card">
|
||
<span class="t-tag">9.2</span>
|
||
<div class="t-title">Угол между прямой и плоскостью</div>
|
||
<div class="t-body">
|
||
<p>Углом между <b>наклонной</b> и плоскостью называется <b>угол между наклонной и её проекцией</b> на эту плоскость: $\varphi = \angle ABH$.</p>
|
||
<p>Для перпендикулярной прямой угол с плоскостью равен $90°$.</p>
|
||
<p>Для прямой, лежащей в плоскости (или параллельной ей) — $0°$.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="t-card">
|
||
<span class="t-tag">9.3</span>
|
||
<div class="t-title">Теорема о трёх перпендикулярах</div>
|
||
<div class="t-body">
|
||
<p><b>Прямая теорема:</b> $AH \perp \alpha, BC \subset \alpha, HB \perp BC \Rightarrow AB \perp BC$.</p>
|
||
<p><b>Обратная теорема:</b> $AH \perp \alpha, BC \subset \alpha, AB \perp BC \Rightarrow HB \perp BC$.</p>
|
||
<p>Часто применяется в задачах с пирамидами и призмами.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="t-card">
|
||
<span class="t-tag">9.4</span>
|
||
<div class="t-title">Равные наклонные = равные проекции</div>
|
||
<div class="t-body">
|
||
<p>Из одной точки $A$ к плоскости $\alpha$ проведены наклонные $AB_1$ и $AB_2$. Тогда:</p>
|
||
<ul>
|
||
<li>$|AB_1| = |AB_2| \Leftrightarrow |HB_1| = |HB_2|$;</li>
|
||
<li>бóльшая наклонная даёт бóльшую проекцию.</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="t-card">
|
||
<span class="t-tag">9.5</span>
|
||
<div class="t-title">Формула угла</div>
|
||
<div class="t-body">
|
||
<p>Если $|AH| = h$ — перпендикуляр, $|HB| = p$ — проекция, $|AB| = \ell$ — наклонная, то:</p>
|
||
<p>$\tg \varphi = \dfrac{h}{p}, \quad \sin \varphi = \dfrac{h}{\ell}, \quad \cos \varphi = \dfrac{p}{\ell}$.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="t-card">
|
||
<span class="t-tag">9.6</span>
|
||
<div class="t-title">ТТП в кубе</div>
|
||
<div class="t-body">
|
||
<p>Куб $ABCDA_1B_1C_1D_1$. Диагональ $AC_1$ — наклонная к плоскости $ABCD$. Её проекция — диагональ $AC$ нижней грани.</p>
|
||
<p>$\tg \varphi = \dfrac{AA_1}{AC} = \dfrac{a}{a\sqrt{2}} = \dfrac{1}{\sqrt{2}}$, откуда $\varphi \approx 35{,}26°$.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="inter" data-inter="i9-elem">
|
||
<div class="inter-h">
|
||
<div class="inter-icon">1</div>
|
||
<div class="inter-title">Перпендикуляр, наклонная или проекция?</div>
|
||
<div class="inter-progress" id="i9-elem-prog">0 / 6</div>
|
||
</div>
|
||
<div class="quiz">
|
||
<div class="quiz-q" id="i9-elem-q"></div>
|
||
<div class="quiz-opts" id="i9-elem-opts"></div>
|
||
</div>
|
||
<div class="quiz-feedback" id="i9-elem-fb"></div>
|
||
</div>
|
||
|
||
<div class="inter" data-inter="i9-cube">
|
||
<div class="inter-h">
|
||
<div class="inter-icon">2</div>
|
||
<div class="inter-title">Углы наклонных в кубе (ребро $a = 1$)</div>
|
||
<div class="inter-progress" id="i9-cube-prog">0 / 5</div>
|
||
</div>
|
||
<div class="quiz">
|
||
<div class="quiz-q" id="i9-cube-q"></div>
|
||
<div class="quiz-input">
|
||
<input id="i9-cube-in" type="text" placeholder="ответ">
|
||
<button id="i9-cube-go">OK</button>
|
||
</div>
|
||
</div>
|
||
<div class="quiz-feedback" id="i9-cube-fb"></div>
|
||
</div>
|
||
|
||
<div class="inter" data-inter="i9-ttp">
|
||
<div class="inter-h">
|
||
<div class="inter-icon">3</div>
|
||
<div class="inter-title">Применима ли ТТП?</div>
|
||
<div class="inter-progress" id="i9-ttp-prog">0 / 5</div>
|
||
</div>
|
||
<div class="quiz">
|
||
<div class="quiz-q" id="i9-ttp-q"></div>
|
||
<div class="quiz-opts" id="i9-ttp-opts"></div>
|
||
</div>
|
||
<div class="quiz-feedback" id="i9-ttp-fb"></div>
|
||
</div>
|
||
|
||
<div class="boss" id="boss-9"></div>
|
||
|
||
<div class="para-actions">
|
||
<button class="mark-btn" id="mark-9">
|
||
<svg class="ic" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg>
|
||
<span>Отметить §9 как изученный</span>
|
||
</button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- §10 -->
|
||
<section id="para-10" class="para">
|
||
<div class="para-head">
|
||
<div class="para-num">§ 10</div>
|
||
<div class="para-h">
|
||
<h2>Перпендикулярность плоскостей</h2>
|
||
<div class="para-h-sub">Двугранный угол · линейный угол · признак $\alpha \perp \beta$</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="viz">
|
||
<div class="viz-title"><span class="badge">ДВУГРАННЫЙ УГОЛ</span> Полуплоскости с общим ребром</div>
|
||
<div id="viz10-dihedral" style="text-align:center"></div>
|
||
<div class="viz-cap">Двугранный угол — фигура из двух полуплоскостей с общим ребром $l$. Его величина измеряется <b>линейным углом</b>: из точки $M \in l$ в каждой полуплоскости проводят $MP \perp l$ и $MQ \perp l$. Тогда $\angle PMQ$ — линейный угол двугранного угла.</div>
|
||
</div>
|
||
|
||
<div class="viz">
|
||
<div class="viz-title"><span class="badge">ПРИЗНАК</span> $\alpha \perp \beta$, если $\alpha \supset l \perp \beta$</div>
|
||
<div id="viz10-sign" style="text-align:center"></div>
|
||
<div class="viz-cap">Если плоскость $\alpha$ содержит прямую $l$, <b>перпендикулярную</b> плоскости $\beta$, — то $\alpha \perp \beta$. Иначе: достаточно одной перпендикулярной к $\beta$ прямой в $\alpha$, чтобы плоскости были перпендикулярны.</div>
|
||
</div>
|
||
|
||
<div class="theory">
|
||
<div class="t-card">
|
||
<span class="t-tag">10.1</span>
|
||
<div class="t-title">Двугранный угол</div>
|
||
<div class="t-body">
|
||
<p><b>Двугранный угол</b> — фигура из двух полуплоскостей с общим ребром $l$ (граней двугранного угла).</p>
|
||
<p>Двугранный угол может быть острым, прямым, тупым или развёрнутым.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="t-card">
|
||
<span class="t-tag">10.2</span>
|
||
<div class="t-title">Линейный угол</div>
|
||
<div class="t-body">
|
||
<p>Возьмём $M \in l$. В каждой полуплоскости проведём луч $\perp l$ из $M$. Угол между этими лучами — <b>линейный угол</b>.</p>
|
||
<p>Линейный угол не зависит от выбора точки $M$ на ребре.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="t-card">
|
||
<span class="t-tag">10.3</span>
|
||
<div class="t-title">Перпендикулярные плоскости</div>
|
||
<div class="t-body">
|
||
<p>Две плоскости называются <b>перпендикулярными</b>, если их двугранный угол прямой ($90°$).</p>
|
||
<p>Обозначение: $\alpha \perp \beta$.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="t-card">
|
||
<span class="t-tag">10.4</span>
|
||
<div class="t-title">Признак $\alpha \perp \beta$</div>
|
||
<div class="t-body">
|
||
<p>Если плоскость $\alpha$ содержит прямую $l$, перпендикулярную плоскости $\beta$, то $\alpha \perp \beta$.</p>
|
||
<p>Достаточно <b>одной</b> такой прямой.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="t-card">
|
||
<span class="t-tag">10.5</span>
|
||
<div class="t-title">Свойство</div>
|
||
<div class="t-body">
|
||
<p>Если $\alpha \perp \beta$ и из точки $M \in \alpha$ опустить перпендикуляр $MK$ в плоскости $\alpha$ к линии пересечения $\alpha \cap \beta$, то $MK \perp \beta$.</p>
|
||
<p>Перпендикуляр к ребру двугранного угла в одной из полуплоскостей перпендикулярен другой плоскости.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="t-card">
|
||
<span class="t-tag">10.6</span>
|
||
<div class="t-title">⊥-плоскости в кубе</div>
|
||
<div class="t-body">
|
||
<p>В кубе все смежные грани перпендикулярны. Например, $ABCD \perp ABB_1A_1$, потому что ребро $AA_1 \subset ABB_1A_1$ и $AA_1 \perp ABCD$ — выполнен признак.</p>
|
||
<p>Каждая грань куба перпендикулярна 4 соседним и параллельна 1 противоположной.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="inter" data-inter="i10-dihedral">
|
||
<div class="inter-h">
|
||
<div class="inter-icon">1</div>
|
||
<div class="inter-title">Двугранный угол: понимаешь?</div>
|
||
<div class="inter-progress" id="i10-dihedral-prog">0 / 5</div>
|
||
</div>
|
||
<div class="quiz">
|
||
<div class="quiz-q" id="i10-dihedral-q"></div>
|
||
<div class="quiz-opts" id="i10-dihedral-opts"></div>
|
||
</div>
|
||
<div class="quiz-feedback" id="i10-dihedral-fb"></div>
|
||
</div>
|
||
|
||
<div class="inter" data-inter="i10-sign">
|
||
<div class="inter-h">
|
||
<div class="inter-icon">2</div>
|
||
<div class="inter-title">Признак перпендикулярности плоскостей</div>
|
||
<div class="inter-progress" id="i10-sign-prog">0 / 5</div>
|
||
</div>
|
||
<div class="quiz">
|
||
<div class="quiz-q" id="i10-sign-q"></div>
|
||
<div class="quiz-opts" id="i10-sign-opts"></div>
|
||
</div>
|
||
<div class="quiz-feedback" id="i10-sign-fb"></div>
|
||
</div>
|
||
|
||
<div class="inter" data-inter="i10-cube">
|
||
<div class="inter-h">
|
||
<div class="inter-icon">3</div>
|
||
<div class="inter-title">Перпендикулярность граней куба</div>
|
||
<div class="inter-progress" id="i10-cube-prog">0 / 5</div>
|
||
</div>
|
||
<div class="quiz">
|
||
<div class="quiz-q" id="i10-cube-q"></div>
|
||
<div class="quiz-opts" id="i10-cube-opts"></div>
|
||
</div>
|
||
<div class="quiz-feedback" id="i10-cube-fb"></div>
|
||
</div>
|
||
|
||
<div class="boss" id="boss-10"></div>
|
||
|
||
<div class="para-actions">
|
||
<button class="mark-btn" id="mark-10">
|
||
<svg class="ic" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg>
|
||
<span>Отметить §10 как изученный</span>
|
||
</button>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="para-final" class="para">
|
||
<div class="para-head">
|
||
<div class="para-num">★</div>
|
||
<div class="para-h">
|
||
<h2>Финал раздела 3</h2>
|
||
<div class="para-h-sub">5 интегральных боссов · ачивка «Перпендикулярность освоена»</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="viz" style="background:linear-gradient(135deg,var(--pri-soft),var(--pri-soft-2));border-color:var(--pri-l)">
|
||
<div class="viz-title" style="color:var(--pri-d)"><span class="badge">ФИНАЛЬНОЕ ИСПЫТАНИЕ</span> Победи 5 боссов подряд</div>
|
||
<div class="viz-cap" style="color:var(--text-2);margin-top:0">Каждый босс — на одну тему: <b>прямая⊥плоскость</b>, <b>расстояния</b>, <b>угол наклонной + ТТП</b>, <b>⊥-плоскости</b>, <b>сборная задача</b>. После победы над всеми — ачивка <code>stereo10_r3_master</code> и +130 XP бонусом.</div>
|
||
</div>
|
||
|
||
<div class="boss" id="boss-f1"></div>
|
||
<div class="boss" id="boss-f2"></div>
|
||
<div class="boss" id="boss-f3"></div>
|
||
<div class="boss" id="boss-f4"></div>
|
||
<div class="boss" id="boss-f5"></div>
|
||
|
||
<div id="celebration" style="display:none"></div>
|
||
</section>
|
||
|
||
</main>
|
||
|
||
<footer class="foot">
|
||
Геометрия — 10 класс · Раздел 3 · 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_r3_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-r3/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 === '7' || n === '8' || n === '9' || n === '10'){
|
||
if (STATE.read.indexOf(parseInt(n,10)) >= 0) t.classList.add('read');
|
||
else t.classList.remove('read');
|
||
} else if (n === 'final'){
|
||
var allBeat = ['f1','f2','f3','f4','f5'].every(function(k){
|
||
return STATE.bosses && STATE.bosses[k] && STATE.bosses[k].defeated;
|
||
});
|
||
if (allBeat) t.classList.add('read');
|
||
}
|
||
});
|
||
}
|
||
|
||
/* ========== SVG VIZ ========== */
|
||
function buildPerpDef(){
|
||
if (!window.STEREO3D) return setTimeout(buildPerpDef, 80);
|
||
var S = window.STEREO3D;
|
||
var sc = new S.Scene(420, 320, {view:'CABINET', scale:50});
|
||
sc.addPlane([0,0,0],[0,0,1],{size:2.2, label:'α'});
|
||
// Прямая l вертикально через O
|
||
sc.addEdge([0,0,-0.3],[0,0,1.8], {stroke:'#dc2626', width:3});
|
||
sc.addLabel('l', [0,0,1.8], {dx:12, dy:-4, color:'#dc2626', fontSize:16, anchor:'start'});
|
||
sc.addVertex([0,0,0], 'O', {dx:10, dy:14, color:'#0b1d33'});
|
||
// 4 прямые в плоскости через O (под разными углами)
|
||
var dirs = [
|
||
[1.5, 0, 0], // x
|
||
[0, 1.5, 0], // y
|
||
[1.2, 1.0, 0],
|
||
[-1.2, 1.0, 0]
|
||
];
|
||
for (var i = 0; i < dirs.length; i++){
|
||
sc.addEdge([-dirs[i][0], -dirs[i][1], 0], dirs[i], {stroke:'#1e3a8a', width:1.8});
|
||
// маркер прямого угла
|
||
sc.addRightAngleMark([0,0,0], [0,0,0.3], [dirs[i][0]*0.25, dirs[i][1]*0.25, 0], {color:'#7c3aed', width:1.5, size:0.18});
|
||
}
|
||
document.getElementById('viz7-def').innerHTML = sc.render();
|
||
}
|
||
|
||
function buildPerpSign(){
|
||
if (!window.STEREO3D) return setTimeout(buildPerpSign, 80);
|
||
var S = window.STEREO3D;
|
||
var sc = new S.Scene(420, 320, {view:'CABINET', scale:50});
|
||
sc.addPlane([0,0,0],[0,0,1],{size:2.2, label:'α'});
|
||
// l вертикально
|
||
sc.addEdge([0,0,-0.2],[0,0,1.8], {stroke:'#dc2626', width:3});
|
||
sc.addLabel('l', [0,0,1.8], {dx:12, dy:-4, color:'#dc2626', fontSize:16, anchor:'start'});
|
||
// m в плоскости α (вдоль x)
|
||
sc.addEdge([-1.6, 0, 0],[1.6, 0, 0], {stroke:'#16a34a', width:2.4});
|
||
sc.addLabel('m', [1.6, 0, 0], {dx:12, dy:-4, color:'#16a34a', fontSize:14, anchor:'start'});
|
||
// n в плоскости α (вдоль y)
|
||
sc.addEdge([0, -1.4, 0],[0, 1.4, 0], {stroke:'#0891b2', width:2.4});
|
||
sc.addLabel('n', [0, 1.4, 0], {dx:12, dy:-4, color:'#0891b2', fontSize:14, anchor:'start'});
|
||
// O — точка пересечения
|
||
sc.addVertex([0,0,0], 'O', {dx:-22, dy:14, color:'#0b1d33'});
|
||
// правый угол l-m и l-n
|
||
sc.addRightAngleMark([0,0,0], [0,0,0.3], [0.3, 0, 0], {color:'#7c3aed', width:1.5, size:0.20});
|
||
sc.addRightAngleMark([0,0,0], [0,0,0.3], [0, 0.3, 0], {color:'#7c3aed', width:1.5, size:0.20});
|
||
document.getElementById('viz7-sign').innerHTML = sc.render();
|
||
}
|
||
|
||
function buildDistanceCases(){
|
||
if (!window.STEREO3D) return setTimeout(buildDistanceCases, 80);
|
||
var S = window.STEREO3D;
|
||
// 1) Точка → плоскость
|
||
(function(){
|
||
var sc = new S.Scene(220, 200, {view:'CABINET', scale:40});
|
||
sc.addPlane([0,0,0],[0,0,1],{size:1.8, label:'α'});
|
||
sc.addVertex([0, 0, 1.2], 'A', {dx:10, dy:-6, color:'#dc2626'});
|
||
sc.addEdge([0, 0, 1.2],[0, 0, 0], {stroke:'#dc2626', width:2.6});
|
||
sc.addVertex([0, 0, 0], 'O', {dx:-14, dy:14, color:'#0b1d33'});
|
||
sc.addRightAngleMark([0,0,0], [0,0,0.3], [0.3, 0, 0], {color:'#7c3aed', width:1.5, size:0.20});
|
||
document.getElementById('viz8-pt-pl').innerHTML = sc.render();
|
||
})();
|
||
// 2) Прямая ∥ плоскость
|
||
(function(){
|
||
var sc = new S.Scene(220, 200, {view:'CABINET', scale:40});
|
||
sc.addPlane([0,0,0],[0,0,1],{size:1.8, label:'α'});
|
||
sc.addEdge([-1.4, -0.4, 0.9],[1.4, 0.4, 0.9], {stroke:'#16a34a', width:2.6});
|
||
sc.addLabel('a', [1.4, 0.4, 0.9], {dx:12, dy:-4, color:'#16a34a', fontSize:14, anchor:'start'});
|
||
sc.addEdge([0, 0, 0.9],[0, 0, 0], {stroke:'#dc2626', width:2.4, dash:'5 3'});
|
||
document.getElementById('viz8-ln-pl').innerHTML = sc.render();
|
||
})();
|
||
// 3) Параллельные плоскости
|
||
(function(){
|
||
var sc = new S.Scene(220, 200, {view:'CABINET', scale:40});
|
||
sc.addPlane([0,0,-0.4],[0,0,1],{size:1.5, label:'α'});
|
||
sc.addPlane([0,0,+0.6],[0,0,1],{size:1.5, label:'β', fill:'#86efac', opacity:0.32});
|
||
sc.addEdge([0, 0, 0.6],[0, 0, -0.4], {stroke:'#dc2626', width:2.6});
|
||
document.getElementById('viz8-pl-pl').innerHTML = sc.render();
|
||
})();
|
||
// 4) Скрещивающиеся прямые
|
||
(function(){
|
||
var sc = new S.Scene(220, 200, {view:'CABINET', scale:40});
|
||
sc.addEdge([-1.3, -0.5, 0],[1.3, 0.5, 0], {stroke:'#1e3a8a', width:2.4});
|
||
sc.addEdge([-1.3, 0.5, 1.1],[1.3, -0.5, 1.1], {stroke:'#0891b2', width:2.4});
|
||
// общий перпендикуляр
|
||
sc.addEdge([0,0,0],[0,0,1.1], {stroke:'#dc2626', width:2.6});
|
||
sc.addLabel('a', [1.3, 0.5, 0], {dx:10, dy:-4, color:'#1e3a8a', fontSize:13, anchor:'start'});
|
||
sc.addLabel('b', [1.3, -0.5, 1.1], {dx:10, dy:-4, color:'#0891b2', fontSize:13, anchor:'start'});
|
||
document.getElementById('viz8-skew').innerHTML = sc.render();
|
||
})();
|
||
}
|
||
|
||
function buildDistanceDetail(){
|
||
if (!window.STEREO3D) return setTimeout(buildDistanceDetail, 80);
|
||
var S = window.STEREO3D;
|
||
var sc = new S.Scene(440, 320, {view:'CABINET', scale:60});
|
||
sc.addPlane([0,0,0],[0,0,1],{size:2.2, label:'α'});
|
||
// Точка A над плоскостью
|
||
sc.addVertex([0.2, 0.3, 1.2], 'A', {dx:10, dy:-6, color:'#dc2626'});
|
||
// Перпендикуляр AO
|
||
sc.addEdge([0.2, 0.3, 1.2],[0.2, 0.3, 0], {stroke:'#dc2626', width:2.8});
|
||
sc.addVertex([0.2, 0.3, 0], 'O', {dx:-18, dy:14, color:'#0b1d33'});
|
||
// Наклонная AB
|
||
sc.addEdge([0.2, 0.3, 1.2],[-1.2, -0.7, 0], {stroke:'#1e3a8a', width:2.4, dash:'4 3'});
|
||
sc.addVertex([-1.2, -0.7, 0], 'B', {dx:-16, dy:14, color:'#1e3a8a'});
|
||
// Прямой угол при O
|
||
sc.addRightAngleMark([0.2,0.3,0], [0.2,0.3,0.3], [0.5, 0.3, 0], {color:'#7c3aed', width:1.5, size:0.18});
|
||
// Подписи длин
|
||
sc.addLabel('h', [0.2, 0.3, 0.6], {dx:14, dy:0, color:'#dc2626', fontSize:14, anchor:'start'});
|
||
document.getElementById('viz8-detail').innerHTML = sc.render();
|
||
}
|
||
|
||
/* ===== §9 SVGs ===== */
|
||
function buildAngleViz(){
|
||
if (!window.STEREO3D) return setTimeout(buildAngleViz, 80);
|
||
var S = window.STEREO3D;
|
||
var sc = new S.Scene(440, 320, {view:'CABINET', scale:60});
|
||
sc.addPlane([0,0,0],[0,0,1],{size:2.2, label:'α'});
|
||
// Точка A над плоскостью
|
||
var A = [0, 0, 1.4];
|
||
var H = [0, 0, 0];
|
||
var B = [1.3, 0.4, 0];
|
||
sc.addVertex(A, 'A', {dx:10, dy:-6, color:'#dc2626'});
|
||
sc.addVertex(H, 'H', {dx:-18, dy:14, color:'#7c3aed'});
|
||
sc.addVertex(B, 'B', {dx:12, dy:10, color:'#1e3a8a'});
|
||
// AH — перпендикуляр
|
||
sc.addEdge(A, H, {stroke:'#dc2626', width:2.8});
|
||
// AB — наклонная
|
||
sc.addEdge(A, B, {stroke:'#1e3a8a', width:2.6});
|
||
// HB — проекция
|
||
sc.addEdge(H, B, {stroke:'#16a34a', width:2.6});
|
||
// Прямой угол при H
|
||
sc.addRightAngleMark(H, [0,0,0.3], [0.3, 0.1, 0], {color:'#7c3aed', width:1.5, size:0.18});
|
||
// Угол φ при B
|
||
sc.addAngleMark(B, A, H, {r:0.45, color:'#d97706', width:1.6, label:'φ'});
|
||
document.getElementById('viz9-angle').innerHTML = sc.render();
|
||
}
|
||
|
||
function buildTTPViz(){
|
||
if (!window.STEREO3D) return setTimeout(buildTTPViz, 80);
|
||
var S = window.STEREO3D;
|
||
var sc = new S.Scene(440, 320, {view:'CABINET', scale:60});
|
||
sc.addPlane([0,0,0],[0,0,1],{size:2.2, label:'α'});
|
||
var A = [0, 0, 1.3];
|
||
var H = [0, 0, 0];
|
||
var B = [1.2, 0, 0];
|
||
var C = [1.2, 0.9, 0];
|
||
sc.addVertex(A, 'A', {dx:10, dy:-6, color:'#dc2626'});
|
||
sc.addVertex(H, 'H', {dx:-18, dy:14, color:'#7c3aed'});
|
||
sc.addVertex(B, 'B', {dx:6, dy:14, color:'#1e3a8a'});
|
||
sc.addVertex(C, 'C', {dx:12, dy:-4, color:'#16a34a'});
|
||
// AH перпендикуляр
|
||
sc.addEdge(A, H, {stroke:'#dc2626', width:2.8});
|
||
// HB проекция
|
||
sc.addEdge(H, B, {stroke:'#7c3aed', width:2.4});
|
||
// BC — прямая в α перпендикулярная HB
|
||
sc.addEdge(B, C, {stroke:'#16a34a', width:2.6});
|
||
// AB наклонная
|
||
sc.addEdge(A, B, {stroke:'#1e3a8a', width:2.6});
|
||
// Прямые углы: при H (AH ⊥ HB), при B (HB ⊥ BC), при B (AB ⊥ BC по выводу)
|
||
sc.addRightAngleMark(H, [0,0,0.3], [0.3, 0, 0], {color:'#7c3aed', width:1.5, size:0.18});
|
||
sc.addRightAngleMark(B, [0.9, 0, 0], [1.2, 0.3, 0], {color:'#7c3aed', width:1.5, size:0.18});
|
||
document.getElementById('viz9-ttp').innerHTML = sc.render();
|
||
}
|
||
|
||
/* ===== §10 SVGs ===== */
|
||
function buildDihedralViz(){
|
||
if (!window.STEREO3D) return setTimeout(buildDihedralViz, 80);
|
||
var S = window.STEREO3D;
|
||
var sc = new S.Scene(440, 320, {view:'CABINET', scale:60});
|
||
// Полуплоскость 1: горизонтальная (y >= 0)
|
||
// Полуплоскость 2: наклонена под 60° от первой
|
||
// Ребро l — ось x
|
||
// Рисуем как 2 параллелограмма
|
||
// Полуплоскость 1: точки (-1.4,0,0), (1.4,0,0), (1.4,1.2,0), (-1.4,1.2,0)
|
||
sc.addFace([[-1.4,0,0],[1.4,0,0],[1.4,1.2,0],[-1.4,1.2,0]], {fill:'#dbeafe', opacity:0.45, stroke:'#1e3a8a', strokeWidth:1.2});
|
||
// Полуплоскость 2: повёрнута на 60° вокруг x
|
||
var a = Math.PI / 3;
|
||
var ca = Math.cos(a), sa = Math.sin(a);
|
||
var rot60 = function(p){ return [p[0], p[1]*ca, p[1]*sa]; };
|
||
sc.addFace([
|
||
rot60([-1.4,0,0]),
|
||
rot60([1.4,0,0]),
|
||
rot60([1.4,1.2,0]),
|
||
rot60([-1.4,1.2,0])
|
||
], {fill:'#fef3c7', opacity:0.50, stroke:'#d97706', strokeWidth:1.2});
|
||
// Ребро l
|
||
sc.addEdge([-1.5, 0, 0],[1.5, 0, 0], {stroke:'#dc2626', width:3});
|
||
sc.addLabel('l', [1.5, 0, 0], {dx:12, dy:-4, color:'#dc2626', fontSize:15, anchor:'start'});
|
||
// Точка M на ребре
|
||
var M = [0.2, 0, 0];
|
||
sc.addVertex(M, 'M', {dx:0, dy:14, color:'#0b1d33'});
|
||
// MP в первой полуплоскости перпендикулярно l (вдоль y)
|
||
var P = [0.2, 0.9, 0];
|
||
sc.addEdge(M, P, {stroke:'#1e3a8a', width:2.4});
|
||
sc.addVertex(P, 'P', {dx:8, dy:-4, color:'#1e3a8a'});
|
||
// MQ во второй полуплоскости перпендикулярно l (под 60° от MP)
|
||
var Q = rot60([0.2, 0.9, 0]);
|
||
sc.addEdge(M, Q, {stroke:'#d97706', width:2.4});
|
||
sc.addVertex(Q, 'Q', {dx:8, dy:-4, color:'#d97706'});
|
||
// Угол PMQ
|
||
sc.addAngleMark(M, P, Q, {r:0.40, color:'#7c3aed', width:1.6, label:'φ'});
|
||
// Прямые углы при M
|
||
sc.addRightAngleMark(M, [0.45, 0, 0], [0.2, 0.25, 0], {color:'#16a34a', width:1.4, size:0.16});
|
||
document.getElementById('viz10-dihedral').innerHTML = sc.render();
|
||
}
|
||
|
||
function buildPlanePerpSign(){
|
||
if (!window.STEREO3D) return setTimeout(buildPlanePerpSign, 80);
|
||
var S = window.STEREO3D;
|
||
var sc = new S.Scene(440, 320, {view:'CABINET', scale:55});
|
||
// β — горизонтальная
|
||
sc.addPlane([0,0,0],[0,0,1],{size:2.2, label:'β'});
|
||
// α — вертикальная (yz-плоскость, нормаль вдоль x)
|
||
sc.addPlane([0,0,0.6],[1,0,0],{size:1.5, label:'α', fill:'#fde047', opacity:0.30});
|
||
// Прямая l в α (вертикальная) перпендикулярна β
|
||
sc.addEdge([0,0,-0.2],[0,0,1.8], {stroke:'#dc2626', width:3});
|
||
sc.addLabel('l', [0,0,1.8], {dx:12, dy:-4, color:'#dc2626', fontSize:16, anchor:'start'});
|
||
// Точка O пересечения l и β
|
||
sc.addVertex([0,0,0], 'O', {dx:8, dy:14, color:'#0b1d33'});
|
||
// Прямой угол при O между l и β
|
||
sc.addRightAngleMark([0,0,0], [0,0,0.3], [0.3, 0, 0], {color:'#7c3aed', width:1.5, size:0.18});
|
||
document.getElementById('viz10-sign').innerHTML = sc.render();
|
||
}
|
||
|
||
/* ========== Quiz Engine (shared) ========== */
|
||
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 normalizeAns(s){
|
||
return String(s||'').toLowerCase()
|
||
.replace(/\s+/g,'')
|
||
.replace(/°/g,'')
|
||
.replace(/sqrt/g,'√')
|
||
.replace(/корень/g,'√')
|
||
.replace(/,/g,'.');
|
||
}
|
||
|
||
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 = normalizeAns(inEl.value);
|
||
var answers = Array.isArray(item.answer) ? item.answer.map(normalizeAns) : [normalizeAns(item.answer)];
|
||
if (answers.indexOf(v) >= 0){
|
||
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();
|
||
}
|
||
|
||
/* ========== Quiz Items ========== */
|
||
var i7PerpItems = [
|
||
{ q:'Прямая $l$ перпендикулярна одной прямой $a \\subset \\alpha$. Достаточно для $l \\perp \\alpha$?', opts:['Да','Нет','Иногда'], correct:1, explain:'Нужны две пересекающиеся прямые в плоскости — одной мало.' },
|
||
{ q:'Прямая $l$ перпендикулярна двум параллельным прямым $a, b \\subset \\alpha$. Достаточно?', opts:['Да','Нет'], correct:1, explain:'Нужны именно две ПЕРЕСЕКАЮЩИЕСЯ. Параллельные мало.' },
|
||
{ q:'Прямая $l$ перпендикулярна двум пересекающимся $m, n \\subset \\alpha$. Тогда $l \\perp \\alpha$?', opts:['Да','Нет','Иногда'], correct:0, explain:'Это и есть признак перпендикулярности.' },
|
||
{ q:'Если $l \\perp \\alpha$ и $p \\subset \\alpha$, то…', opts:['$l \\perp p$','$l \\parallel p$','$l$ скрещ. с $p$'], correct:0, explain:'$l$ перпендикулярна любой прямой плоскости.' },
|
||
{ q:'Если $l_1 \\perp \\alpha$ и $l_2 \\perp \\alpha$, то $l_1$ и $l_2$…', opts:['Параллельны','Пересекаются','Перпендикулярны'], correct:0, explain:'Две прямые, перпендикулярные одной плоскости, всегда параллельны.' },
|
||
{ q:'Через точку проходит сколько прямых, перпендикулярных данной плоскости?', opts:['1','2','Бесконечно'], correct:0, explain:'Единственная.' }
|
||
];
|
||
|
||
var i7SignItems = [
|
||
{ q:'В кубе ребро $AA_1$ перпендикулярно $AB$ и $AD$. Каков вывод?', opts:['$AA_1 \\perp ABCD$','$AA_1 \\parallel ABCD$','Никакого'], correct:0, explain:'$AB$ и $AD$ пересекаются в $A$ — признак работает: $AA_1 \\perp$ плоскости $ABCD$.' },
|
||
{ q:'Прямая $l$ перпендикулярна двум прямым $a, b \\subset \\alpha$, но $a \\parallel b$. Можем ли утверждать $l \\perp \\alpha$?', opts:['Да','Нет','Иногда'], correct:1, explain:'Признак требует ПЕРЕСЕКАЮЩИЕСЯ прямые. Параллельных недостаточно.' },
|
||
{ q:'Доказано $l \\perp \\alpha$. Что можем заключить про любую прямую $p \\subset \\alpha$?', opts:['$l \\perp p$','$l \\parallel p$','Ничего'], correct:0, explain:'Свойство: $l \\perp$ каждой прямой плоскости.' },
|
||
{ q:'Если $l_1 \\perp \\alpha$ и $l_1 \\parallel l_2$, то $l_2$…', opts:['$\\perp \\alpha$','$\\parallel \\alpha$','Лежит в $\\alpha$'], correct:0, explain:'Если параллельна перпендикулярной — сама перпендикулярна.' },
|
||
{ q:'Прямая $l$ пересекает плоскость $\\alpha$ и образует с двумя пересек. прямыми $m, n \\subset \\alpha$ равные углы. Что нельзя заключить?', opts:['$l \\perp \\alpha$','$l$ наклонная','Угол с $\\alpha$ определён'], correct:0, explain:'Равные углы — недостаточно для перпендикулярности. Нужны прямые углы.' }
|
||
];
|
||
|
||
var i7CubeItems = [
|
||
{ q:'Куб: ребро $AA_1$ и плоскость $ABCD$ — это…', opts:['$\\perp$','$\\parallel$','Лежит'], correct:0, explain:'$AA_1 \\perp AB$ и $AA_1 \\perp AD$ ⇒ $AA_1 \\perp ABCD$.' },
|
||
{ q:'Куб: ребро $BB_1$ и плоскость $ABCD$ — это…', opts:['$\\perp$','$\\parallel$','Под углом 45°'], correct:0, explain:'Все боковые рёбра перпендикулярны основанию.' },
|
||
{ q:'Куб: ребро $AB$ и плоскость $ADD_1A_1$ (левая боковая) — это…', opts:['$\\perp$','$\\parallel$','Лежит'], correct:0, explain:'$AB \\perp AD$ и $AB \\perp AA_1$ ⇒ $AB \\perp$ плоскости $ADD_1A_1$.' },
|
||
{ q:'Куб: какая прямая перпендикулярна плоскости $BCC_1B_1$ (правая грань)?', opts:['$AB$','$BC$','$BB_1$','$AC$'], correct:0, explain:'$AB \\perp BC$ и $AB \\perp BB_1$ — обе в правой грани ⇒ $AB \\perp BCC_1B_1$.' },
|
||
{ q:'Куб: диагональ $AC$ нижней грани и ребро $AA_1$ — это…', opts:['$\\perp$','$\\parallel$','Под углом 45°'], correct:0, explain:'$AA_1 \\perp$ всей плоскости $ABCD$, значит $AA_1 \\perp AC$ (свойство).' }
|
||
];
|
||
|
||
var i8CubeItems = [
|
||
{ q:'Куб с ребром $1$. Расстояние от $A$ до плоскости $A_1B_1C_1D_1$?', answer:'1', explain:'Это длина бокового ребра $AA_1 = 1$.' },
|
||
{ q:'Куб с ребром $1$. Расстояние между параллельными гранями?', answer:'1', explain:'Расстояние = ребро куба = $1$.' },
|
||
{ q:'Куб с ребром $1$. Расстояние между скрещ. рёбрами $AB$ и $CC_1$?', answer:'1', explain:'Общий перпендикуляр — это $BC = 1$.' },
|
||
{ q:'Куб с ребром $1$. Расстояние между скрещ. рёбрами $AB$ и $C_1D_1$? (Запиши без $\\sqrt{}$: используй число или формулу типа sqrt(2)).', answer:['√2','sqrt(2)','sqrt2','корень2','1.41','1.414'], explain:'Это диагональ грани квадрата 1×1: $\\sqrt{2}$.' },
|
||
{ q:'Куб с ребром $1$. Расстояние между параллельными прямыми $AB$ и $D_1C_1$?', answer:['√2','sqrt(2)','sqrt2','1.41','1.414'], explain:'$AB$ и $D_1C_1$ лежат на противоположных гранях по диагонали; расстояние — диагональ квадрата 1×1 = $\\sqrt{2}$.' },
|
||
{ q:'Куб с ребром $2$. Расстояние от $A$ до плоскости $A_1B_1C_1D_1$?', answer:'2', explain:'Ребро куба = 2.' }
|
||
];
|
||
|
||
var i8TypeItems = [
|
||
{ q:'«Дан куб. Найди расстояние от $A$ до $B_1$.» Какой это тип задачи?', opts:['Точка → точка','Точка → плоскость','Точка → прямая','Скрещ. прямые'], correct:0, explain:'Просто длина отрезка — расстояние между двумя точками.' },
|
||
{ q:'«Дан куб. Найди расстояние от $A$ до плоскости $BB_1C_1C$.» Какой тип?', opts:['Точка → точка','Точка → плоскость','Точка → прямая','Скрещ. прямые'], correct:1, explain:'Точка до плоскости — длина перпендикуляра.' },
|
||
{ q:'«Найди расстояние между скрещ. рёбрами куба $AD$ и $BB_1$.»', opts:['Точка → точка','Точка → плоскость','Параллельные плоскости','Скрещ. прямые'], correct:3, explain:'Скрещ. прямые — общий перпендикуляр.' },
|
||
{ q:'«Между параллельными гранями куба.»', opts:['Точка → плоскость','Парал. плоскости','Парал. прямые','Скрещ. прямые'], correct:1, explain:'Параллельные плоскости — длина их общего перпендикуляра.' },
|
||
{ q:'«Дана прямая $a \\parallel \\alpha$. Найти $\\rho(a, \\alpha)$.»', opts:['Точка → точка','Прямая → парал. пл-ть','Парал. плоскости','Скрещ. прямые'], correct:1, explain:'От параллельной прямой до плоскости — расстояние от любой точки прямой.' }
|
||
];
|
||
|
||
var i8TrueItems = [
|
||
{ q:'Перпендикуляр из точки на плоскость — это кратчайший отрезок до неё.', opts:['Верно','Неверно'], correct:0, explain:'Любая наклонная длиннее перпендикуляра.' },
|
||
{ q:'Если из точки $A$ опущены перпендикуляр $AO$ и наклонная $AB$, то $|AO| \\ge |AB|$.', opts:['Верно','Неверно'], correct:1, explain:'Наоборот: $|AO| \\le |AB|$. Перпендикуляр — самый короткий.' },
|
||
{ q:'Расстояние между скрещ. прямыми — длина общего перпендикуляра.', opts:['Верно','Неверно'], correct:0, explain:'Общий перпендикуляр существует, единствен и реализует кратчайшее расстояние.' },
|
||
{ q:'Расстояние от прямой $a \\parallel \\alpha$ до плоскости $\\alpha$ зависит от выбора точки прямой.', opts:['Верно','Неверно'], correct:1, explain:'Не зависит — для любой точки расстояние одинаково.' },
|
||
{ q:'У двух параллельных плоскостей есть бесконечно много общих перпендикуляров одинаковой длины.', opts:['Верно','Неверно'], correct:0, explain:'Каждый перпендикуляр к плоскостям имеет одну и ту же длину — расстояние между ними.' }
|
||
];
|
||
|
||
var i9ElemItems = [
|
||
{ q:'Из точки $A$ к плоскости $\\alpha$: $AH \\perp \\alpha$, $H \\in \\alpha$. Чем называется $AH$?', opts:['Перпендикуляр','Наклонная','Проекция'], correct:0, explain:'Перпендикуляр.' },
|
||
{ q:'Из точки $A$ к плоскости проведён отрезок $AB$, $B \\in \\alpha, B \\neq H$. Это…', opts:['Перпендикуляр','Наклонная','Проекция'], correct:1, explain:'Наклонная.' },
|
||
{ q:'Отрезок $HB$ ($H$ — основание перпендикуляра, $B$ — конец наклонной) — это…', opts:['Перпендикуляр','Наклонная','Проекция'], correct:2, explain:'Проекция наклонной на плоскость.' },
|
||
{ q:'Угол между прямой и плоскостью — это угол между…', opts:['Прямой и любой прямой плоскости','Прямой и её проекцией','Прямой и перпендикуляром'], correct:1, explain:'Наклонная и её проекция.' },
|
||
{ q:'Чему равен угол между прямой и плоскостью, в которой она лежит?', opts:['$0°$','$45°$','$90°$'], correct:0, explain:'Прямая в плоскости даёт угол $0°$.' },
|
||
{ q:'Чему равен угол между перпендикулярной к плоскости прямой и самой плоскостью?', opts:['$0°$','$45°$','$90°$'], correct:2, explain:'Перпендикулярная — даёт $90°$.' }
|
||
];
|
||
|
||
var i9CubeItems = [
|
||
{ q:'Угол между ребром $AA_1$ и плоскостью $ABCD$ (нижняя грань)?', answer:'90', explain:'$AA_1 \\perp ABCD$ ⇒ угол $90°$.' },
|
||
{ q:'Угол между ребром $AB$ и плоскостью $ABCD$?', answer:'0', explain:'Ребро лежит в плоскости — угол $0°$.' },
|
||
{ q:'Угол между диагональю $AC$ и плоскостью $ABCD$?', answer:'0', explain:'Диагональ лежит в нижней плоскости.' },
|
||
{ q:'$\\tg$ угла между $AC_1$ и плоскостью $ABCD$? (Куб с ребром 1.)', answer:['1/√2','1/sqrt(2)','√2/2','sqrt(2)/2','0.707'], explain:'$\\tg \\varphi = \\frac{AA_1}{AC} = \\frac{1}{\\sqrt{2}} = \\frac{\\sqrt{2}}{2}$.' },
|
||
{ q:'Угол между диагональю $A_1C$ и плоскостью $A_1B_1C_1D_1$ — в градусах? (через $\\tg \\varphi = \\sqrt{2}$, ответ $\\approx$54.7°, округли до целого)', answer:['55','54','arctg(√2)','arctan(sqrt(2))'], explain:'Проекция $A_1C$ на верхнюю грань = $A_1C_1$ = $\\sqrt{2}$. $\\tg \\varphi = 1/\\sqrt{2}$... подожди. Перпендикуляр $CC_1 = 1$ (от $C$ до верх. грани). Проекция $C_1A_1 = \\sqrt{2}$. $\\tg \\varphi = 1/\\sqrt{2} \\approx 35°$. Округление: 35.' }
|
||
];
|
||
// Заметка: 5-я задача переформулирована — оставим ответ 35 (в градусах).
|
||
i9CubeItems[4] = { q:'Угол между диагональю $A_1C$ и плоскостью $A_1B_1C_1D_1$ — в градусах, целое (формула $\\tg\\varphi = 1/\\sqrt{2}$, $\\varphi \\approx ?$).', answer:'35', explain:'$\\tg \\varphi = \\frac{1}{\\sqrt{2}} \\approx 0.707 \\Rightarrow \\varphi \\approx 35°$.' };
|
||
|
||
var i9TtpItems = [
|
||
{ q:'$AH \\perp \\alpha$, $BC \\subset \\alpha$, $HB \\perp BC$. Вывод по ТТП?', opts:['$AB \\perp BC$','$AB \\parallel BC$','Ничего'], correct:0, explain:'Прямая ТТП: $AB \\perp BC$.' },
|
||
{ q:'$AH \\perp \\alpha$, $BC \\subset \\alpha$, $AB \\perp BC$. Вывод по обратной ТТП?', opts:['$HB \\perp BC$','$HB \\parallel BC$','Ничего'], correct:0, explain:'Обратная ТТП: $HB \\perp BC$.' },
|
||
{ q:'Если $BC \\not\\subset \\alpha$ (т.е. $BC$ не лежит в плоскости), применима ли ТТП?', opts:['Да','Нет'], correct:1, explain:'ТТП требует, чтобы $BC$ лежало в той же плоскости, что и проекция.' },
|
||
{ q:'Если $AH$ — не перпендикуляр, а наклонная, применима ли ТТП?', opts:['Да','Нет'], correct:1, explain:'ТТП требует именно перпендикуляр $AH$.' },
|
||
{ q:'В пирамиде высота $SO \\perp$ основание. Грань $SAB$. Перпендикулярна ли $SAB$ ребру $CD$ в основании? (При условии $OB \\perp CD$)', opts:['Да, по ТТП','Нет','Нужны дополнительные данные'], correct:0, explain:'$SO \\perp$ основание, $CD$ в основании, $OB \\perp CD$ ⇒ по ТТП $SB \\perp CD$.' }
|
||
];
|
||
|
||
var i10DihedralItems = [
|
||
{ q:'Двугранный угол — это…', opts:['Угол между прямыми','Фигура из 2 полуплоскостей с общим ребром','Угол наклонной','Угол между плоскостями (всегда острый)'], correct:1, explain:'2 полуплоскости с общим ребром.' },
|
||
{ q:'Линейный угол двугранного угла строится…', opts:['Произвольно','Перпендикуляром к ребру из точки $M \\in l$','Через диагональ','Через высоту'], correct:1, explain:'Лучи $\\perp l$ в каждой полуплоскости.' },
|
||
{ q:'Зависит ли линейный угол от выбора точки $M$ на ребре?', opts:['Да','Нет'], correct:1, explain:'Не зависит — все линейные углы двугранного угла равны.' },
|
||
{ q:'Две плоскости называются перпендикулярными, если…', opts:['Параллельны','Их двугранный угол равен $90°$','Они совпадают','Их пересекает прямая'], correct:1, explain:'Линейный угол $= 90°$.' },
|
||
{ q:'Чему равен линейный угол развёрнутого двугранного угла?', opts:['$0°$','$90°$','$180°$','$360°$'], correct:2, explain:'Развёрнутый — это $180°$.' }
|
||
];
|
||
|
||
var i10SignItems = [
|
||
{ q:'Прямая $l \\subset \\alpha$, $l \\perp \\beta$. Вывод?', opts:['$\\alpha \\parallel \\beta$','$\\alpha \\perp \\beta$','$\\alpha = \\beta$'], correct:1, explain:'Признак $\\alpha \\perp \\beta$.' },
|
||
{ q:'Достаточно ли $\\alpha$ содержать ОДНУ прямую, перпендикулярную $\\beta$, для перпендикулярности плоскостей?', opts:['Да','Нет, нужно две','Нужно три'], correct:0, explain:'Одной прямой достаточно — это и есть признак.' },
|
||
{ q:'Если плоскость $\\alpha$ содержит прямую, параллельную $\\beta$, можем ли мы заключить $\\alpha \\perp \\beta$?', opts:['Да','Нет'], correct:1, explain:'Параллельная прямая — это про параллельность плоскостей, а не перпендикулярность.' },
|
||
{ q:'$\\alpha \\perp \\beta$. Опускаем из $M \\in \\alpha$ перпендикуляр в $\\alpha$ к линии пересечения. Этот перпендикуляр…', opts:['$\\parallel \\beta$','$\\perp \\beta$','$\\subset \\beta$'], correct:1, explain:'Перпендикулярен второй плоскости (свойство).' },
|
||
{ q:'Если плоскость $\\alpha$ перпендикулярна плоскости $\\beta$, а $\\beta \\perp \\gamma$, то $\\alpha \\perp \\gamma$?', opts:['Всегда','Не обязательно','Никогда'], correct:1, explain:'Перпендикулярность плоскостей не транзитивна — могут быть и параллельны, и пересекаться под любым углом.' }
|
||
];
|
||
|
||
var i10CubeItems = [
|
||
{ q:'Куб: плоскости граней $ABCD$ и $ABB_1A_1$ — это…', opts:['Параллельны','Перпендикулярны','Пересекаются под $45°$'], correct:1, explain:'Смежные грани куба перпендикулярны: $AA_1 \\subset ABB_1A_1$ и $AA_1 \\perp ABCD$ — признак.' },
|
||
{ q:'Куб: плоскости $ABCD$ и $A_1B_1C_1D_1$ — это…', opts:['Параллельны','Перпендикулярны','Совпадают'], correct:0, explain:'Противоположные грани — параллельны.' },
|
||
{ q:'Сколько граней куба перпендикулярно одной заданной грани?', opts:['2','3','4','6'], correct:2, explain:'4 смежные грани перпендикулярны; 1 параллельна.' },
|
||
{ q:'Куб: плоскости $ABB_1A_1$ и $BCC_1B_1$ (две соседние боковые) — это…', opts:['Параллельны','Перпендикулярны','Пересекаются под $60°$'], correct:1, explain:'Соседние боковые грани куба перпендикулярны (общее ребро $BB_1$, линейный угол — между $BA$ и $BC$, равен $90°$).' },
|
||
{ q:'Куб: диагональная плоскость $ACC_1A_1$ и нижняя грань $ABCD$ — это…', opts:['Параллельны','Перпендикулярны','Под $45°$'], correct:1, explain:'$AA_1 \\subset ACC_1A_1$ и $AA_1 \\perp ABCD$ ⇒ $ACC_1A_1 \\perp ABCD$.' }
|
||
];
|
||
|
||
/* ========== Bosses ========== */
|
||
var BOSS_DEFS = {
|
||
7: {
|
||
title:'§7 — Перпендикулярность прямой и плоскости',
|
||
xp:70,
|
||
stages:[
|
||
{ q:'Достаточно ли $l$ перпендикулярна одной прямой плоскости, чтобы $l \\perp \\alpha$?', type:'mc', opts:['Да','Нет','Иногда'], correct:1, explain:'Нужны две ПЕРЕСЕКАЮЩИЕСЯ.' },
|
||
{ q:'$l \\perp m$, $l \\perp n$, $m \\cap n = O \\in \\alpha$. Вывод?', type:'mc', opts:['$l \\perp \\alpha$','$l \\parallel \\alpha$','Никакой'], correct:0, explain:'Признак перпендикулярности.' },
|
||
{ q:'Сколько прямых, перпендикулярных плоскости, можно провести через точку?', type:'input', a:'1', explain:'Единственная.' },
|
||
{ q:'Если $l_1 \\perp \\alpha$ и $l_2 \\perp \\alpha$, то $l_1$ и $l_2$…', type:'mc', opts:['$\\parallel$','$\\perp$','Скрещ.'], correct:0, explain:'Параллельны.' },
|
||
{ q:'Куб: ребро $CC_1$ перпендикулярно плоскости $ABCD$?', type:'mc', opts:['Да','Нет','Зависит от куба'], correct:0, explain:'Боковое ребро ⊥ основанию.' }
|
||
]
|
||
},
|
||
8: {
|
||
title:'§8 — Расстояния',
|
||
xp:70,
|
||
stages:[
|
||
{ q:'Куб с ребром $1$. Расстояние от $A_1$ до плоскости $ABCD$?', type:'input', a:'1', explain:'Длина $AA_1 = 1$.' },
|
||
{ q:'Куб с ребром $1$. Расстояние между $AA_1$ и $CC_1$? (форма ответа: число)', type:'input', a:['√2','sqrt(2)','sqrt2','1.41','1.414'], explain:'$AA_1 \\parallel CC_1$ (параллельные прямые); расстояние = диагональ $AC = \\sqrt{2}$.' },
|
||
{ q:'Перпендикуляр короче любой наклонной из той же точки?', type:'mc', opts:['Да','Нет','Иногда'], correct:0, explain:'Да — основное свойство.' },
|
||
{ q:'Куб с ребром $2$. Расстояние между параллельными гранями?', type:'input', a:'2', explain:'Расстояние = ребро = 2.' },
|
||
{ q:'Расстояние между скрещ. прямыми — это длина чего?', type:'mc', opts:['Любого отрезка','Общего перпендикуляра','Касательной','Биссектрисы'], correct:1, explain:'Общего перпендикуляра.' }
|
||
]
|
||
},
|
||
9: {
|
||
title:'§9 — Угол и ТТП',
|
||
xp:70,
|
||
stages:[
|
||
{ q:'Из точки $A$ к плоскости проведены $AH$ (перпендикуляр), $AB$ (наклонная). Что такое $HB$?', type:'mc', opts:['Перпендикуляр','Наклонная','Проекция'], correct:2, explain:'Проекция наклонной.' },
|
||
{ q:'Угол между наклонной и плоскостью — это угол между…', type:'mc', opts:['Наклонной и перпендикуляром','Наклонной и проекцией','Наклонной и любой прямой'], correct:1, explain:'Наклонная и её проекция.' },
|
||
{ q:'ТТП: $AH \\perp \\alpha, BC \\subset \\alpha, HB \\perp BC$. Вывод про $AB$ и $BC$?', type:'mc', opts:['$AB \\perp BC$','$AB \\parallel BC$','Ничего'], correct:0, explain:'$AB \\perp BC$ — прямая ТТП.' },
|
||
{ q:'Угол между диагональю куба $AC_1$ и плоскостью $ABCD$ ($\\tg \\varphi = 1/\\sqrt{2}$, $\\varphi \\approx ?°$, округли до целого)', type:'input', a:'35', explain:'$\\varphi \\approx 35{,}26°$.' },
|
||
{ q:'Чему равен угол между прямой $a \\subset \\alpha$ и плоскостью $\\alpha$?', type:'input', a:'0', explain:'$0°$ — прямая лежит в плоскости.' }
|
||
]
|
||
},
|
||
10: {
|
||
title:'§10 — Перпендикулярность плоскостей',
|
||
xp:75,
|
||
stages:[
|
||
{ q:'Двугранный угол — это…', type:'mc', opts:['Угол между плоскостями','2 полуплоскости с общим ребром','Угол между прямыми','Угол наклонной'], correct:1, explain:'2 полуплоскости + ребро.' },
|
||
{ q:'Линейный угол двугранного угла строится…', type:'mc', opts:['Произвольно','Перпендикулярами к ребру в каждой полуплоскости','Через высоту','Через диагональ'], correct:1, explain:'Перпендикуляры к ребру.' },
|
||
{ q:'Плоскость $\\alpha \\supset l \\perp \\beta$. Вывод?', type:'mc', opts:['$\\alpha \\parallel \\beta$','$\\alpha \\perp \\beta$','$\\alpha = \\beta$'], correct:1, explain:'Признак: $\\alpha \\perp \\beta$.' },
|
||
{ q:'Сколько граней куба перпендикулярно одной заданной грани?', type:'input', a:'4', explain:'4 смежные.' },
|
||
{ q:'Куб: плоскости $ABB_1A_1$ и $CDD_1C_1$ — это…', type:'mc', opts:['Параллельны','Перпендикулярны','Совпадают'], correct:0, explain:'Это противоположные боковые грани — параллельны.' },
|
||
{ q:'Линейный угол развёрнутого двугранного угла равен … градусов', type:'input', a:'180', explain:'$180°$ — развёрнутый угол.' }
|
||
]
|
||
}
|
||
};
|
||
|
||
var FINAL_BOSS_DEFS = {
|
||
f1: {
|
||
title:'Босс 1 · Прямая ⊥ плоскость',
|
||
xp:30,
|
||
stages:[
|
||
{ q:'Признак $l \\perp \\alpha$: $l$ перпендикулярна двум $?$ прямым в $\\alpha$.', type:'mc', opts:['Параллельным','Пересекающимся','Произвольным'], correct:1, explain:'Двум ПЕРЕСЕКАЮЩИМСЯ прямым.' },
|
||
{ q:'Через точку проходит сколько прямых, перпендикулярных данной плоскости?', type:'input', a:'1', explain:'Единственная.' },
|
||
{ q:'Если $l \\perp \\alpha$ и $a \\subset \\alpha$, то $l$ и $a$…', type:'mc', opts:['Параллельны','Перпендикулярны','Скрещиваются'], correct:1, explain:'$l$ перпендикулярна любой прямой плоскости.' },
|
||
{ q:'Куб: ребро $DD_1$ перпендикулярно плоскости $ABCD$?', type:'mc', opts:['Да','Нет','Зависит'], correct:0, explain:'Все боковые рёбра ⊥ основанию.' }
|
||
]
|
||
},
|
||
f2: {
|
||
title:'Босс 2 · Расстояния',
|
||
xp:30,
|
||
stages:[
|
||
{ q:'Куб с ребром $3$. Расстояние от $A$ до плоскости $A_1B_1C_1D_1$?', type:'input', a:'3', explain:'Длина $AA_1 = 3$.' },
|
||
{ q:'Куб с ребром $1$. Расстояние между скрещ. рёбрами $AB$ и $D_1C_1$?', type:'input', a:['√2','sqrt(2)','sqrt2','1.41','1.414'], explain:'Диагональ грани $\\sqrt{2}$.' },
|
||
{ q:'Расстояние между скрещ. прямыми реализуется на каком отрезке?', type:'mc', opts:['Любом','Общем перпендикуляре','Биссектрисе','Касательной'], correct:1, explain:'Общий перпендикуляр.' },
|
||
{ q:'Перпендикуляр из точки на плоскость … любой наклонной из той же точки.', type:'mc', opts:['Длиннее','Короче','Равен'], correct:1, explain:'Короче (кратчайший отрезок).' }
|
||
]
|
||
},
|
||
f3: {
|
||
title:'Босс 3 · Угол + ТТП',
|
||
xp:35,
|
||
stages:[
|
||
{ q:'Что такое проекция наклонной $AB$ на плоскость $\\alpha$ (где $AH \\perp \\alpha$, $H \\in \\alpha$)?', type:'mc', opts:['$AH$','$HB$','$AB$'], correct:1, explain:'Проекция — отрезок $HB$.' },
|
||
{ q:'Угол между прямой и плоскостью — это угол между прямой и…', type:'mc', opts:['Перпендикуляром','Проекцией','Любой прямой'], correct:1, explain:'Наклонная и её проекция.' },
|
||
{ q:'ТТП: $AH \\perp \\alpha, BC \\subset \\alpha, HB \\perp BC$. Что верно?', type:'mc', opts:['$AB \\perp BC$','$AB \\parallel BC$','Ничего'], correct:0, explain:'$AB \\perp BC$.' },
|
||
{ q:'Куб (ребро 1): $\\tg$ угла между диагональю $AC_1$ и плоскостью $ABCD$?', type:'input', a:['1/√2','1/sqrt(2)','√2/2','sqrt(2)/2','0.707'], explain:'$\\tg \\varphi = \\frac{1}{\\sqrt{2}}$.' }
|
||
]
|
||
},
|
||
f4: {
|
||
title:'Босс 4 · ⊥-плоскости',
|
||
xp:30,
|
||
stages:[
|
||
{ q:'Двугранный угол — это…', type:'mc', opts:['Угол наклонной','2 полуплоскости с общим ребром','Угол прямых'], correct:1, explain:'Полуплоскости + общее ребро.' },
|
||
{ q:'Признак $\\alpha \\perp \\beta$: $\\alpha$ содержит прямую, $?$ к $\\beta$.', type:'mc', opts:['Параллельную','Перпендикулярную','Произвольную'], correct:1, explain:'Перпендикулярную $\\beta$.' },
|
||
{ q:'Сколько граней куба перпендикулярно одной заданной грани?', type:'input', a:'4', explain:'4 смежные.' },
|
||
{ q:'Линейный угол двугранного угла зависит от выбора точки на ребре?', type:'mc', opts:['Да','Нет'], correct:1, explain:'Не зависит.' }
|
||
]
|
||
},
|
||
f5: {
|
||
title:'Босс 5 · Сборная',
|
||
xp:45,
|
||
stages:[
|
||
{ q:'Куб с ребром $1$. Расстояние от $A$ до $C_1$? (длина диагонали куба)', type:'input', a:['√3','sqrt(3)','sqrt3','1.73','1.732'], explain:'Диагональ куба $= a\\sqrt{3}$.' },
|
||
{ q:'Куб (ребро 1): $\\sin$ угла между $AC_1$ и плоскостью $ABCD$?', type:'input', a:['1/√3','1/sqrt(3)','√3/3','sqrt(3)/3','0.577'], explain:'$\\sin \\varphi = \\frac{AA_1}{AC_1} = \\frac{1}{\\sqrt{3}}$.' },
|
||
{ q:'Если $l_1 \\perp \\alpha$ и $l_2 \\perp \\alpha$, то $l_1$ и $l_2$ — …', type:'mc', opts:['$\\parallel$','$\\perp$','Скрещиваются'], correct:0, explain:'Параллельны.' },
|
||
{ q:'В пирамиде высота $SO \\perp$ основание. Применяем ТТП: $OB \\perp BC \\Rightarrow$ ?', type:'mc', opts:['$SB \\perp BC$','$SB \\parallel BC$','Ничего'], correct:0, explain:'По ТТП: $SB \\perp BC$.' },
|
||
{ q:'Куб: диагональная плоскость $BDD_1B_1$ и грань $ABCD$ — это…', type:'mc', opts:['Параллельны','Перпендикулярны','Под $45°$'], correct:1, explain:'$BB_1 \\subset BDD_1B_1$ и $BB_1 \\perp ABCD$ ⇒ перпендикулярны.' }
|
||
]
|
||
}
|
||
};
|
||
|
||
function renderFinalBoss(id){
|
||
var def = FINAL_BOSS_DEFS[id];
|
||
if (!def) return;
|
||
var el = document.getElementById('boss-' + id);
|
||
if (!el) return;
|
||
if (!STATE.bosses) STATE.bosses = {};
|
||
var st = STATE.bosses[id] || { stage:0, defeated:false };
|
||
STATE.bosses[id] = st;
|
||
if (st.defeated){
|
||
el.classList.add('victory');
|
||
el.innerHTML = '<div class="boss-defeated">'
|
||
+ '<div class="boss-defeated-title">' + def.title + ' побеждён!</div>'
|
||
+ '<span class="boss-defeated-xp">+' + def.xp + ' XP</span>'
|
||
+ '</div>';
|
||
checkFinalComplete();
|
||
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-' + id + '-in" inputmode="text" placeholder="ответ"><button id="boss-' + id + '-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>';
|
||
|
||
function normalizeAns(s){
|
||
return String(s||'').toLowerCase()
|
||
.replace(/\s+/g,'')
|
||
.replace(/°/g,'')
|
||
.replace(/sqrt/g,'√')
|
||
.replace(/корень/g,'√')
|
||
.replace(/,/g,'.');
|
||
}
|
||
|
||
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(){ advanceFinalBoss(id); }, 600);
|
||
} else {
|
||
btn.classList.add('wrong');
|
||
setTimeout(function(){ btn.classList.remove('wrong'); }, 600);
|
||
}
|
||
});
|
||
});
|
||
} else {
|
||
var inEl = document.getElementById('boss-' + id + '-in');
|
||
var goEl = document.getElementById('boss-' + id + '-go');
|
||
var box = inEl.parentNode;
|
||
function attack(){
|
||
var v = normalizeAns(inEl.value);
|
||
var answers = Array.isArray(stage.a) ? stage.a.map(normalizeAns) : [normalizeAns(stage.a)];
|
||
if (answers.indexOf(v) >= 0){
|
||
inEl.style.background = 'rgba(34,197,94,.25)';
|
||
setTimeout(function(){ advanceFinalBoss(id); }, 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 advanceFinalBoss(id){
|
||
var st = STATE.bosses[id];
|
||
var def = FINAL_BOSS_DEFS[id];
|
||
st.stage++;
|
||
if (st.stage >= def.stages.length){
|
||
st.defeated = true;
|
||
saveState();
|
||
addXp(def.xp, def.title);
|
||
} else {
|
||
saveState();
|
||
}
|
||
renderFinalBoss(id);
|
||
}
|
||
|
||
function checkFinalComplete(){
|
||
var allBeat = ['f1','f2','f3','f4','f5'].every(function(k){
|
||
return STATE.bosses[k] && STATE.bosses[k].defeated;
|
||
});
|
||
if (!allBeat) return;
|
||
var cel = document.getElementById('celebration');
|
||
if (!cel) return;
|
||
if (cel.dataset.shown === '1') return;
|
||
cel.dataset.shown = '1';
|
||
cel.style.display = 'block';
|
||
cel.innerHTML = '<div class="boss victory" style="text-align:center;padding:40px 24px">'
|
||
+ '<div style="font-family:Unbounded,sans-serif;font-size:1.8rem;font-weight:900;color:#fef3c7;letter-spacing:-.01em;margin-bottom:8px">★ Раздел 3 пройден! ★</div>'
|
||
+ '<div style="font-size:1rem;color:#dcfce7;margin-bottom:16px">Все 5 финальных боссов побеждены. Перпендикулярность — освоена.</div>'
|
||
+ '<span class="boss-defeated-xp" style="font-size:1rem;padding:10px 22px">+ 130 XP бонус + ачивка «stereo10_r3_master»</span>'
|
||
+ '</div>';
|
||
var achKey = 'geometry10_achievements';
|
||
var raw = localStorage.getItem(achKey);
|
||
var list = [];
|
||
try { list = raw ? JSON.parse(raw) : []; } catch(e){}
|
||
if (list.indexOf('stereo10_r3_master') < 0){
|
||
list.push('stereo10_r3_master');
|
||
localStorage.setItem(achKey, JSON.stringify(list));
|
||
addXp(130, 'ачивка: Перпендикулярность освоена');
|
||
}
|
||
}
|
||
|
||
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>';
|
||
|
||
function normalizeAns(s){
|
||
return String(s||'').toLowerCase()
|
||
.replace(/\s+/g,'')
|
||
.replace(/°/g,'')
|
||
.replace(/sqrt/g,'√')
|
||
.replace(/корень/g,'√')
|
||
.replace(/,/g,'.');
|
||
}
|
||
|
||
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 = normalizeAns(inEl.value);
|
||
var answers = Array.isArray(stage.a) ? stage.a.map(normalizeAns) : [normalizeAns(stage.a)];
|
||
if (answers.indexOf(v) >= 0){
|
||
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(){
|
||
buildPerpDef();
|
||
buildPerpSign();
|
||
buildDistanceCases();
|
||
buildDistanceDetail();
|
||
buildAngleViz();
|
||
buildTTPViz();
|
||
buildDihedralViz();
|
||
buildPlanePerpSign();
|
||
|
||
runQuizMC({ id:'i7-perp', items:i7PerpItems, xpPerAll:14, title:'перпендикулярность' });
|
||
runQuizMC({ id:'i7-sign', items:i7SignItems, xpPerAll:12, title:'признак' });
|
||
runQuizMC({ id:'i7-cube', items:i7CubeItems, xpPerAll:12, title:'⊥ в кубе' });
|
||
|
||
runQuizInput({ id:'i8-cube', items:i8CubeItems, xpPerAll:18, title:'расстояния в кубе' });
|
||
runQuizMC({ id:'i8-type', items:i8TypeItems, xpPerAll:12, title:'тип расстояния' });
|
||
runQuizMC({ id:'i8-true', items:i8TrueItems, xpPerAll:10, title:'верно/неверно' });
|
||
|
||
runQuizMC({ id:'i9-elem', items:i9ElemItems, xpPerAll:12, title:'элементы наклонной' });
|
||
runQuizInput({ id:'i9-cube', items:i9CubeItems, xpPerAll:16, title:'углы в кубе' });
|
||
runQuizMC({ id:'i9-ttp', items:i9TtpItems, xpPerAll:12, title:'ТТП' });
|
||
|
||
runQuizMC({ id:'i10-dihedral', items:i10DihedralItems, xpPerAll:12, title:'двугранный угол' });
|
||
runQuizMC({ id:'i10-sign', items:i10SignItems, xpPerAll:12, title:'признак ⊥ плоскостей' });
|
||
runQuizMC({ id:'i10-cube', items:i10CubeItems, xpPerAll:12, title:'⊥ грани куба' });
|
||
|
||
renderBoss(7);
|
||
renderBoss(8);
|
||
renderBoss(9);
|
||
renderBoss(10);
|
||
renderFinalBoss('f1');
|
||
renderFinalBoss('f2');
|
||
renderFinalBoss('f3');
|
||
renderFinalBoss('f4');
|
||
renderFinalBoss('f5');
|
||
checkFinalComplete();
|
||
|
||
document.getElementById('mark-7').addEventListener('click', function(){ markRead(7); });
|
||
document.getElementById('mark-8').addEventListener('click', function(){ markRead(8); });
|
||
document.getElementById('mark-9').addEventListener('click', function(){ markRead(9); });
|
||
document.getElementById('mark-10').addEventListener('click', function(){ markRead(10); });
|
||
refreshMarkBtn(7); refreshMarkBtn(8); refreshMarkBtn(9); refreshMarkBtn(10);
|
||
refreshTabs();
|
||
|
||
var tabs = document.querySelectorAll('.sec-tab[data-tab]');
|
||
var sections = ['para-7','para-8','para-9','para-10','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>
|