Files
Learn_System/frontend/textbooks/geometry_10_r4.html
T
Maxim Dolgolyov c2a2497e49 feat(geom10 W8): Раздел 4 §11-§14 — Координаты и векторы (полная реализация)
§11 Координаты в пространстве:
- SVG ПДСК: 3 цветные оси + точка M(2;3;4) с пунктирными проекциями
- SVG расстояния: параллелепипед на разностях координат + диагональ AB
- 6 теоретических карточек (ПДСК, координаты, пл-сти, расстояние, середина, особые точки)
- 3 тренажёра: где точка (6), расстояние (5, с √2/√3), середина (5)
- Босс §11: 5 этапов, +70 XP

§12 Векторы:
- SVG сложения: параллелограмм + правило треугольника (a, b, a+b)
- SVG базиса: i, j, k единичные векторы вдоль осей + вектор a с проекциями
- 6 теоретических карточек (определение, равенство, сложение, k·a, координаты, коллинеарность)
- 3 тренажёра: действия (5), AB координаты (5), коллинеарность (5)
- Босс §12: 5 этапов, +70 XP

§13 Скалярное произведение:
- SVG: 2 вектора a, b из O + угол φ между ними
- 6 теоретических карточек (определение, координатная формула, свойства, ⊥, угол, знак)
- 3 тренажёра: вычисление (5), перпендикулярность (5), cos угла (4)
- Босс §13: 5 этапов, +70 XP

§14 Применение векторно-координатного метода:
- SVG: куб ABCDA1B1C1D1 в координатах с ребром 1
- Алгоритм решения на formula-plate
- 6 теоретических карточек (уравнения пл-сти, угол прямых/прямой+пл-сть/пл-стей, расстояние, когда применять)
- 3 тренажёра: куб в координатах (5), угол через скаляр (4), выбор метода (5)
- Босс §14: 6 этапов, +80 XP

normalizeAns: общая утилита (≡ r3) + поддержка координат через ; или ,
Финал R4 — stub до W9 (4 босса + ачивка stereo10_master = главная награда курса).
2026-05-29 15:33:58 +03:00

1439 lines
77 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Геометрия 10 · Раздел 4 · Координаты и векторы</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:#fffbeb; --card:#fff; --card-2:#f1f5f9;
--text:#451a03; --text-2:#78350f; --muted:#475569;
--border:#fed7aa; --border-2:#e2e8f0;
--pri:#d97706; --pri-d:#b45309; --pri-l:#fcd34d;
--pri-soft:#fef3c7; --pri-soft-2:#fffbeb;
--dark:#78350f;
--accent:#dc2626;
--good:#16a34a;
--warn:#7c3aed;
--sh:0 4px 16px rgba(217,119,6,.08);
--sh-h:0 12px 36px rgba(217,119,6,.18);
}
html.dark{
--bg:#1c0f02; --card:#241606; --card-2:#2d1d09;
--text:#fef3c7; --text-2:#fde68a; --muted:#94a3b8;
--border:#78350f; --border-2:#1e293b;
--pri-soft:rgba(217,119,6,.18); --pri-soft-2:rgba(217,119,6,.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,#dc2626,#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}
.formula-plate{background:linear-gradient(135deg,var(--pri-soft),var(--pri-soft-2));border:1.5px solid var(--pri-l);border-radius:13px;padding:14px 18px;margin:12px 0;font-size:.96rem;line-height:1.8;color:var(--text-2);text-align:center}
.formula-plate b{color:var(--pri-d)}
.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:120px}
.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,#78350f 0%,#92400e 50%,#b45309 100%);color:#fff;border-radius:18px;padding:24px;margin-bottom:24px;position:relative;overflow:hidden;box-shadow:0 16px 48px rgba(180,83,9,.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:#fef3c7}
.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:#fcd34d;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:130px}
.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:#fef3c7;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>Раздел 4. Координаты и векторы</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="11" href="#para-11"><span class="dot"></span>§11 ПДСК</a>
<a class="sec-tab" data-tab="12" href="#para-12"><span class="dot"></span>§12 Векторы</a>
<a class="sec-tab" data-tab="13" href="#para-13"><span class="dot"></span>§13 a·b</a>
<a class="sec-tab" data-tab="14" href="#para-14"><span class="dot"></span>§14 Применение</a>
<a class="sec-tab locked" data-tab="final" href="#para-final"><span class="dot"></span>Финал</a>
</div>
</nav>
<main>
<!-- §11 -->
<section id="para-11" class="para">
<div class="para-head">
<div class="para-num">§ 11</div>
<div class="para-h">
<h2>Координаты в пространстве</h2>
<div class="para-h-sub">ПДСК · точка $M(x;\,y;\,z)$ · расстояние между точками</div>
</div>
</div>
<div class="viz">
<div class="viz-title"><span class="badge">ПДСК</span> Прямоугольная система координат в пространстве</div>
<div id="viz11-coords" style="text-align:center"></div>
<div class="viz-cap">Три взаимно перпендикулярные оси $Ox$, $Oy$, $Oz$ с общим началом $O$. Точка $M$ задаётся тремя координатами $(x;\,y;\,z)$ — это проекции на оси. Здесь показана точка $M(2;\,3;\,4)$ с пунктирными проекциями.</div>
</div>
<div class="viz">
<div class="viz-title"><span class="badge">РАССТОЯНИЕ</span> Формула $|AB|$ в пространстве</div>
<div id="viz11-dist" style="text-align:center"></div>
<div class="formula-plate">
Если $A(x_1;\,y_1;\,z_1)$ и $B(x_2;\,y_2;\,z_2)$, то<br>
$|AB| = \sqrt{(x_2-x_1)^2 + (y_2-y_1)^2 + (z_2-z_1)^2}$
</div>
<div class="viz-cap">Формула — обобщение теоремы Пифагора. $|AB|$ — диагональ прямоугольного параллелепипеда с измерениями $|\Delta x|$, $|\Delta y|$, $|\Delta z|$.</div>
</div>
<div class="theory">
<div class="t-card">
<span class="t-tag">11.1</span>
<div class="t-title">ПДСК</div>
<div class="t-body">
<p><b>Прямоугольная декартова система координат</b> — три попарно перпендикулярные оси с общим началом $O$.</p>
<p>Оси: $Ox$ (абсцисс), $Oy$ (ординат), $Oz$ (аппликат).</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">11.2</span>
<div class="t-title">Координаты точки</div>
<div class="t-body">
<p>Точка $M$ имеет три координаты $(x;\,y;\,z)$ — это её проекции на оси.</p>
<p>$M_x$ — проекция на $Ox$, и т.д. Точка $M$ восстанавливается, если из проекций провести перпендикуляры к осям.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">11.3</span>
<div class="t-title">Координатные плоскости</div>
<div class="t-body">
<ul>
<li>$Oxy$ — плоскость $z = 0$;</li>
<li>$Oxz$ — плоскость $y = 0$;</li>
<li>$Oyz$ — плоскость $x = 0$.</li>
</ul>
<p>Три координатные плоскости разбивают пространство на 8 октантов.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">11.4</span>
<div class="t-title">Расстояние между точками</div>
<div class="t-body">
<p>$|AB| = \sqrt{(\Delta x)^2 + (\Delta y)^2 + (\Delta z)^2}$.</p>
<p>Расстояние от точки до начала: $|OM| = \sqrt{x^2 + y^2 + z^2}$.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">11.5</span>
<div class="t-title">Координаты середины отрезка</div>
<div class="t-body">
<p>Середина $M$ отрезка $AB$:</p>
<p>$M\left(\dfrac{x_A+x_B}{2};\,\dfrac{y_A+y_B}{2};\,\dfrac{z_A+z_B}{2}\right)$.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">11.6</span>
<div class="t-title">Координаты особых точек</div>
<div class="t-body">
<ul>
<li>Начало координат: $O(0;\,0;\,0)$.</li>
<li>Точка на оси $Ox$: $(a;\,0;\,0)$.</li>
<li>Точка в плоскости $Oxy$: $(x;\,y;\,0)$.</li>
</ul>
</div>
</div>
</div>
<div class="inter" data-inter="i11-coord">
<div class="inter-h">
<div class="inter-icon">1</div>
<div class="inter-title">Где находится точка?</div>
<div class="inter-progress" id="i11-coord-prog">0 / 6</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i11-coord-q"></div>
<div class="quiz-opts" id="i11-coord-opts"></div>
</div>
<div class="quiz-feedback" id="i11-coord-fb"></div>
</div>
<div class="inter" data-inter="i11-dist">
<div class="inter-h">
<div class="inter-icon">2</div>
<div class="inter-title">Расстояние между точками</div>
<div class="inter-progress" id="i11-dist-prog">0 / 5</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i11-dist-q"></div>
<div class="quiz-input">
<input id="i11-dist-in" type="text" placeholder="ответ">
<button id="i11-dist-go">OK</button>
</div>
</div>
<div class="quiz-feedback" id="i11-dist-fb"></div>
</div>
<div class="inter" data-inter="i11-mid">
<div class="inter-h">
<div class="inter-icon">3</div>
<div class="inter-title">Середина отрезка</div>
<div class="inter-progress" id="i11-mid-prog">0 / 5</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i11-mid-q"></div>
<div class="quiz-input">
<input id="i11-mid-in" type="text" placeholder="например 1;2;3">
<button id="i11-mid-go">OK</button>
</div>
</div>
<div class="quiz-feedback" id="i11-mid-fb"></div>
</div>
<div class="boss" id="boss-11"></div>
<div class="para-actions">
<button class="mark-btn" id="mark-11">
<svg class="ic" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg>
<span>Отметить §11 как изученный</span>
</button>
</div>
</section>
<!-- §12 -->
<section id="para-12" class="para">
<div class="para-head">
<div class="para-num">§ 12</div>
<div class="para-h">
<h2>Векторы. Действия над векторами</h2>
<div class="para-h-sub">Определения · сложение · умножение на число · базис $\vec{i}, \vec{j}, \vec{k}$</div>
</div>
</div>
<div class="viz">
<div class="viz-title"><span class="badge">СЛОЖЕНИЕ</span> Правило треугольника и параллелограмма</div>
<div id="viz12-add" style="text-align:center"></div>
<div class="viz-cap">Сумма $\vec{a} + \vec{b}$: совмещаем начало $\vec{b}$ с концом $\vec{a}$; результирующий вектор — от начала $\vec{a}$ к концу $\vec{b}$. Эквивалентно: $\vec{a}+\vec{b}$ — диагональ параллелограмма, построенного на $\vec{a}$ и $\vec{b}$.</div>
</div>
<div class="viz">
<div class="viz-title"><span class="badge">БАЗИС</span> Единичные векторы $\vec{i}$, $\vec{j}$, $\vec{k}$</div>
<div id="viz12-basis" style="text-align:center"></div>
<div class="formula-plate">
Любой вектор: $\vec{a} = x\,\vec{i} + y\,\vec{j} + z\,\vec{k}$ &nbsp;&nbsp; $\vec{a} = (x;\,y;\,z)$
</div>
<div class="viz-cap">Три единичных вектора $\vec{i}, \vec{j}, \vec{k}$ вдоль осей $Ox, Oy, Oz$ образуют <b>базис</b>. Любой вектор однозначно раскладывается по базису — его координаты совпадают с коэффициентами.</div>
</div>
<div class="theory">
<div class="t-card">
<span class="t-tag">12.1</span>
<div class="t-title">Вектор</div>
<div class="t-body">
<p><b>Вектор</b> — направленный отрезок $\vec{AB}$ с началом $A$ и концом $B$.</p>
<p>Длина (модуль): $|\vec{AB}| = |AB|$. Нулевой вектор: $\vec{0}$.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">12.2</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">12.3</span>
<div class="t-title">Сложение</div>
<div class="t-body">
<p><b>Правило треугольника:</b> $\vec{AB} + \vec{BC} = \vec{AC}$.</p>
<p><b>Правило параллелограмма:</b> сумма — диагональ параллелограмма.</p>
<p>Свойства: коммутативность $\vec{a}+\vec{b}=\vec{b}+\vec{a}$, ассоциативность.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">12.4</span>
<div class="t-title">Умножение на число</div>
<div class="t-body">
<p>$k\,\vec{a}$ — вектор той же ($k > 0$) или противоположной ($k < 0$) направленности, с длиной $|k|\cdot|\vec{a}|$.</p>
<p>Если $\vec{a} = (x;y;z)$, то $k\vec{a} = (kx;\,ky;\,kz)$.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">12.5</span>
<div class="t-title">Координаты вектора</div>
<div class="t-body">
<p>Если $A(x_1;y_1;z_1)$ и $B(x_2;y_2;z_2)$, то $\vec{AB} = (x_2-x_1;\,y_2-y_1;\,z_2-z_1)$.</p>
<p>Длина: $|\vec{AB}| = \sqrt{(x_2-x_1)^2 + (y_2-y_1)^2 + (z_2-z_1)^2}$.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">12.6</span>
<div class="t-title">Коллинеарность</div>
<div class="t-body">
<p>Векторы $\vec{a}$ и $\vec{b}$ <b>коллинеарны</b>, если $\vec{a} = k\,\vec{b}$ для некоторого $k$.</p>
<p>В координатах: $\dfrac{x_a}{x_b} = \dfrac{y_a}{y_b} = \dfrac{z_a}{z_b}$ (где определено).</p>
</div>
</div>
</div>
<div class="inter" data-inter="i12-add">
<div class="inter-h">
<div class="inter-icon">1</div>
<div class="inter-title">Сложение и умножение векторов</div>
<div class="inter-progress" id="i12-add-prog">0 / 5</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i12-add-q"></div>
<div class="quiz-input">
<input id="i12-add-in" type="text" placeholder="например 1;2;3">
<button id="i12-add-go">OK</button>
</div>
</div>
<div class="quiz-feedback" id="i12-add-fb"></div>
</div>
<div class="inter" data-inter="i12-coord">
<div class="inter-h">
<div class="inter-icon">2</div>
<div class="inter-title">Координаты $\vec{AB}$</div>
<div class="inter-progress" id="i12-coord-prog">0 / 5</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i12-coord-q"></div>
<div class="quiz-input">
<input id="i12-coord-in" type="text" placeholder="x;y;z">
<button id="i12-coord-go">OK</button>
</div>
</div>
<div class="quiz-feedback" id="i12-coord-fb"></div>
</div>
<div class="inter" data-inter="i12-coll">
<div class="inter-h">
<div class="inter-icon">3</div>
<div class="inter-title">Коллинеарны ли векторы?</div>
<div class="inter-progress" id="i12-coll-prog">0 / 5</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i12-coll-q"></div>
<div class="quiz-opts" id="i12-coll-opts"></div>
</div>
<div class="quiz-feedback" id="i12-coll-fb"></div>
</div>
<div class="boss" id="boss-12"></div>
<div class="para-actions">
<button class="mark-btn" id="mark-12">
<svg class="ic" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg>
<span>Отметить §12 как изученный</span>
</button>
</div>
</section>
<!-- §13 -->
<section id="para-13" class="para">
<div class="para-head">
<div class="para-num">§ 13</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="viz13-dot" style="text-align:center"></div>
<div class="formula-plate">
<b>Геометрически:</b> $\vec{a} \cdot \vec{b} = |\vec{a}|\cdot|\vec{b}|\cdot\cos\varphi$<br>
<b>В координатах:</b> $\vec{a}\cdot\vec{b} = x_1 x_2 + y_1 y_2 + z_1 z_2$
</div>
<div class="viz-cap">Скалярное произведение двух векторов — число (скаляр), равное произведению длин векторов на косинус угла между ними.</div>
</div>
<div class="theory">
<div class="t-card">
<span class="t-tag">13.1</span>
<div class="t-title">Определение</div>
<div class="t-body">
<p>$\vec{a} \cdot \vec{b} = |\vec{a}|\cdot|\vec{b}|\cdot\cos\varphi$, где $\varphi$ — угол между векторами.</p>
<p>Результат — <b>число</b>, не вектор.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">13.2</span>
<div class="t-title">Координатная формула</div>
<div class="t-body">
<p>Если $\vec{a} = (x_1;y_1;z_1)$, $\vec{b} = (x_2;y_2;z_2)$, то:</p>
<p>$\vec{a}\cdot\vec{b} = x_1 x_2 + y_1 y_2 + z_1 z_2$.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">13.3</span>
<div class="t-title">Свойства</div>
<div class="t-body">
<ul>
<li>$\vec{a}\cdot\vec{a} = |\vec{a}|^2$;</li>
<li>$\vec{a}\cdot\vec{b} = \vec{b}\cdot\vec{a}$ (коммутативность);</li>
<li>$(k\vec{a})\cdot\vec{b} = k(\vec{a}\cdot\vec{b})$;</li>
<li>$(\vec{a}+\vec{b})\cdot\vec{c} = \vec{a}\cdot\vec{c} + \vec{b}\cdot\vec{c}$.</li>
</ul>
</div>
</div>
<div class="t-card">
<span class="t-tag">13.4</span>
<div class="t-title">Перпендикулярность</div>
<div class="t-body">
<p>$\vec{a} \perp \vec{b} \Leftrightarrow \vec{a}\cdot\vec{b} = 0$.</p>
<p>Это удобный критерий: $x_1x_2 + y_1y_2 + z_1z_2 = 0$.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">13.5</span>
<div class="t-title">Угол между векторами</div>
<div class="t-body">
<p>$\cos\varphi = \dfrac{\vec{a}\cdot\vec{b}}{|\vec{a}|\cdot|\vec{b}|}$.</p>
<p>В координатах: $\cos\varphi = \dfrac{x_1x_2+y_1y_2+z_1z_2}{\sqrt{x_1^2+y_1^2+z_1^2}\cdot\sqrt{x_2^2+y_2^2+z_2^2}}$.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">13.6</span>
<div class="t-title">Знак скалярного произведения</div>
<div class="t-body">
<ul>
<li>$\vec{a}\cdot\vec{b} > 0 \Leftrightarrow \varphi < 90°$ (острый);</li>
<li>$\vec{a}\cdot\vec{b} = 0 \Leftrightarrow \varphi = 90°$;</li>
<li>$\vec{a}\cdot\vec{b} < 0 \Leftrightarrow \varphi > 90°$ (тупой).</li>
</ul>
</div>
</div>
</div>
<div class="inter" data-inter="i13-calc">
<div class="inter-h">
<div class="inter-icon">1</div>
<div class="inter-title">Вычисли $\vec{a}\cdot\vec{b}$</div>
<div class="inter-progress" id="i13-calc-prog">0 / 5</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i13-calc-q"></div>
<div class="quiz-input">
<input id="i13-calc-in" type="text" placeholder="число">
<button id="i13-calc-go">OK</button>
</div>
</div>
<div class="quiz-feedback" id="i13-calc-fb"></div>
</div>
<div class="inter" data-inter="i13-perp">
<div class="inter-h">
<div class="inter-icon">2</div>
<div class="inter-title">Перпендикулярны ли векторы?</div>
<div class="inter-progress" id="i13-perp-prog">0 / 5</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i13-perp-q"></div>
<div class="quiz-opts" id="i13-perp-opts"></div>
</div>
<div class="quiz-feedback" id="i13-perp-fb"></div>
</div>
<div class="inter" data-inter="i13-angle">
<div class="inter-h">
<div class="inter-icon">3</div>
<div class="inter-title">Найди $\cos$ угла между $\vec{a}$ и $\vec{b}$</div>
<div class="inter-progress" id="i13-angle-prog">0 / 4</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i13-angle-q"></div>
<div class="quiz-input">
<input id="i13-angle-in" type="text" placeholder="например 1/2">
<button id="i13-angle-go">OK</button>
</div>
</div>
<div class="quiz-feedback" id="i13-angle-fb"></div>
</div>
<div class="boss" id="boss-13"></div>
<div class="para-actions">
<button class="mark-btn" id="mark-13">
<svg class="ic" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg>
<span>Отметить §13 как изученный</span>
</button>
</div>
</section>
<!-- §14 -->
<section id="para-14" class="para">
<div class="para-head">
<div class="para-num">§ 14</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> $A(0;0;0)$ … $C_1(1;1;1)$</div>
<div id="viz14-cube" style="text-align:center"></div>
<div class="viz-cap">Размещаем куб с ребром 1 в координатах: $A(0;0;0)$, $B(1;0;0)$, $C(1;1;0)$, $D(0;1;0)$, $A_1(0;0;1)$, $B_1(1;0;1)$, $C_1(1;1;1)$, $D_1(0;1;1)$. Через координаты легко вычислять любые расстояния и углы.</div>
</div>
<div class="formula-plate">
<b>Алгоритм решения:</b><br>
1) ввести ПДСК так, чтобы основные точки имели простые координаты;<br>
2) выписать координаты нужных точек;<br>
3) вычислить векторы и применить формулы $|\vec{AB}|$, $\vec{a}\cdot\vec{b}$, $\cos\varphi$.
</div>
<div class="theory">
<div class="t-card">
<span class="t-tag">14.1</span>
<div class="t-title">Уравнение плоскости</div>
<div class="t-body">
<p>Плоскость с нормалью $\vec{n}=(A;B;C)$, проходящая через $M_0(x_0;y_0;z_0)$:</p>
<p>$A(x-x_0)+B(y-y_0)+C(z-z_0)=0$.</p>
<p>Общий вид: $Ax + By + Cz + D = 0$.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">14.2</span>
<div class="t-title">Угол между прямыми</div>
<div class="t-body">
<p>Если направляющие векторы — $\vec{a}, \vec{b}$, то:</p>
<p>$\cos\varphi = \dfrac{|\vec{a}\cdot\vec{b}|}{|\vec{a}|\cdot|\vec{b}|}$ (модуль — чтобы $\varphi \in [0;90°]$).</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">14.3</span>
<div class="t-title">Угол между прямой и плоскостью</div>
<div class="t-body">
<p>$\sin\varphi = \dfrac{|\vec{a}\cdot\vec{n}|}{|\vec{a}|\cdot|\vec{n}|}$,</p>
<p>где $\vec{a}$ — направляющая прямой, $\vec{n}$ — нормаль плоскости.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">14.4</span>
<div class="t-title">Угол между плоскостями</div>
<div class="t-body">
<p>$\cos\varphi = \dfrac{|\vec{n_1}\cdot\vec{n_2}|}{|\vec{n_1}|\cdot|\vec{n_2}|}$.</p>
<p>Используются нормали плоскостей.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">14.5</span>
<div class="t-title">Расстояние от точки до плоскости</div>
<div class="t-body">
<p>$\rho(M, \alpha) = \dfrac{|Ax_0 + By_0 + Cz_0 + D|}{\sqrt{A^2 + B^2 + C^2}}$.</p>
<p>Универсальная формула для любой плоскости в общем виде.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">14.6</span>
<div class="t-title">Когда применять</div>
<div class="t-body">
<p>Векторно-координатный метод эффективен, когда:</p>
<ul>
<li>в задаче много прямых углов (куб, прямоугольный параллелепипед);</li>
<li>требуется доказать перпендикулярность;</li>
<li>сложные углы между скрещ. прямыми, наклонными.</li>
</ul>
</div>
</div>
</div>
<div class="inter" data-inter="i14-cube">
<div class="inter-h">
<div class="inter-icon">1</div>
<div class="inter-title">Куб: координаты и расстояния</div>
<div class="inter-progress" id="i14-cube-prog">0 / 5</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i14-cube-q"></div>
<div class="quiz-input">
<input id="i14-cube-in" type="text" placeholder="ответ">
<button id="i14-cube-go">OK</button>
</div>
</div>
<div class="quiz-feedback" id="i14-cube-fb"></div>
</div>
<div class="inter" data-inter="i14-angle">
<div class="inter-h">
<div class="inter-icon">2</div>
<div class="inter-title">Угол через скалярное произведение</div>
<div class="inter-progress" id="i14-angle-prog">0 / 4</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i14-angle-q"></div>
<div class="quiz-input">
<input id="i14-angle-in" type="text" placeholder="например 1/2 или 90">
<button id="i14-angle-go">OK</button>
</div>
</div>
<div class="quiz-feedback" id="i14-angle-fb"></div>
</div>
<div class="inter" data-inter="i14-meth">
<div class="inter-h">
<div class="inter-icon">3</div>
<div class="inter-title">Выбор метода</div>
<div class="inter-progress" id="i14-meth-prog">0 / 5</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i14-meth-q"></div>
<div class="quiz-opts" id="i14-meth-opts"></div>
</div>
<div class="quiz-feedback" id="i14-meth-fb"></div>
</div>
<div class="boss" id="boss-14"></div>
<div class="para-actions">
<button class="mark-btn" id="mark-14">
<svg class="ic" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg>
<span>Отметить §14 как изученный</span>
</button>
</div>
</section>
<!-- Final stub -->
<section id="para-final" class="para">
<div class="para-head">
<div class="para-num"></div>
<div class="para-h">
<h2>Финал раздела 4</h2>
<div class="para-h-sub">4 интегральных босса · ачивка «Геометрия 10 пройдена!» — главная награда курса</div>
</div>
</div>
<div class="stub-card">
<b>Откроется в Волне W9</b>
Финальное испытание: 4 босса (координаты/расстояния, векторы, скалярное произведение, сборная) + спецачивка <code>stereo10_master</code> + 120 XP бонус.
</div>
</section>
</main>
<footer class="foot">
Геометрия — 10 класс · Раздел 4 · 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_r4_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-r4/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 === '11' || n === '12' || n === '13' || n === '14'){
if (STATE.read.indexOf(parseInt(n,10)) >= 0) t.classList.add('read');
else t.classList.remove('read');
}
});
}
/* ========== SVG VIZ ========== */
function buildCoordSystem(){
if (!window.STEREO3D) return setTimeout(buildCoordSystem, 80);
var S = window.STEREO3D;
var sc = new S.Scene(440, 340, {view:'CABINET', scale:55});
// 3 оси
sc.addArrow([0,0,0],[3.0,0,0], {color:'#dc2626', width:2.4, label:'x'});
sc.addArrow([0,0,0],[0,3.0,0], {color:'#16a34a', width:2.4, label:'y'});
sc.addArrow([0,0,0],[0,0,3.0], {color:'#1e3a8a', width:2.4, label:'z'});
sc.addVertex([0,0,0], 'O', {dx:-18, dy:16, color:'#0b1d33'});
// tick marks at 1, 2, 3 on each axis
for (var i = 1; i <= 3; i++){
sc.addLabel(String(i), [i, 0, 0], {dx:0, dy:14, color:'#dc2626', fontSize:11, anchor:'middle'});
sc.addLabel(String(i), [0, i, 0], {dx:6, dy:14, color:'#16a34a', fontSize:11, anchor:'start'});
sc.addLabel(String(i), [0, 0, i], {dx:-12, dy:4, color:'#1e3a8a', fontSize:11, anchor:'end'});
}
// Точка M(2;3;4) — масштабируем чтобы влезла: возьмём (1.5;2;2.2)
var M = [1.5, 2, 2.2];
sc.addVertex(M, 'M(2;3;4)', {dx:10, dy:-8, color:'#7c3aed', fontSize:13});
// Пунктиры от M до 3 проекций
sc.addEdge(M, [1.5, 2, 0], {stroke:'#94a3b8', width:1, dash:'3 3'});
sc.addEdge([1.5, 2, 0], [1.5, 0, 0], {stroke:'#94a3b8', width:1, dash:'3 3'});
sc.addEdge([1.5, 2, 0], [0, 2, 0], {stroke:'#94a3b8', width:1, dash:'3 3'});
sc.addEdge(M, [1.5, 0, 2.2], {stroke:'#94a3b8', width:1, dash:'3 3'});
document.getElementById('viz11-coords').innerHTML = sc.render();
}
function buildDistanceFormula(){
if (!window.STEREO3D) return setTimeout(buildDistanceFormula, 80);
var S = window.STEREO3D;
var sc = new S.Scene(440, 320, {view:'CABINET', scale:55});
// Два точки и параллелепипед-подсказка
var A = [0, 0, 0];
var B = [2, 1.6, 1.4];
sc.addArrow([0,0,0],[2.6,0,0], {color:'#94a3b8', width:1.4});
sc.addArrow([0,0,0],[0,2.2,0], {color:'#94a3b8', width:1.4});
sc.addArrow([0,0,0],[0,0,1.8], {color:'#94a3b8', width:1.4});
sc.addLabel('x', [2.6,0,0], {dx:10, dy:6, color:'#dc2626', fontSize:13, anchor:'start'});
sc.addLabel('y', [0,2.2,0], {dx:10, dy:8, color:'#16a34a', fontSize:13, anchor:'start'});
sc.addLabel('z', [0,0,1.8], {dx:-8, dy:-2, color:'#1e3a8a', fontSize:13, anchor:'end'});
// Параллелепипед AABB на разностях
sc.addEdge(A, [2,0,0], {stroke:'#dc2626', width:2});
sc.addEdge([2,0,0], [2,1.6,0], {stroke:'#16a34a', width:2});
sc.addEdge([2,1.6,0], [2,1.6,1.4], {stroke:'#1e3a8a', width:2});
sc.addEdge(A, [0,1.6,0], {stroke:'#94a3b8', width:1.4, dash:'3 3'});
sc.addEdge([0,1.6,0], [2,1.6,0], {stroke:'#94a3b8', width:1.4, dash:'3 3'});
// Диагональ AB
sc.addEdge(A, B, {stroke:'#7c3aed', width:3});
sc.addVertex(A, 'A', {dx:-14, dy:14, color:'#0b1d33'});
sc.addVertex(B, 'B', {dx:10, dy:-4, color:'#7c3aed'});
sc.addLabel('Δx', [1,0,0], {color:'#dc2626', fontSize:12, dy:14});
sc.addLabel('Δy', [2,0.8,0], {color:'#16a34a', fontSize:12, dx:12, anchor:'start'});
sc.addLabel('Δz', [2,1.6,0.7], {color:'#1e3a8a', fontSize:12, dx:12, anchor:'start'});
document.getElementById('viz11-dist').innerHTML = sc.render();
}
function buildVectorAdd(){
if (!window.STEREO3D) return setTimeout(buildVectorAdd, 80);
var S = window.STEREO3D;
var sc = new S.Scene(440, 280, {view:'CABINET', scale:55});
var O = [0,0,0];
var A = [2, 0.3, 0];
var B = [0.6, 1.6, 0];
var C = [A[0]+B[0], A[1]+B[1], A[2]+B[2]]; // 2.6, 1.9, 0
// Параллелограмм
sc.addEdge(O, A, {stroke:'#1e3a8a', width:1.4, dash:'4 3'});
sc.addEdge(O, B, {stroke:'#94a3b8', width:1.4, dash:'4 3'});
sc.addEdge(A, C, {stroke:'#94a3b8', width:1.4, dash:'4 3'});
sc.addEdge(B, C, {stroke:'#1e3a8a', width:1.4, dash:'4 3'});
// Векторы a, b, a+b
sc.addArrow(O, A, {color:'#dc2626', width:2.6, label:'a', lx:0, ly:18});
sc.addArrow(A, C, {color:'#16a34a', width:2.6, label:'b', lx:14, ly:-4});
sc.addArrow(O, C, {color:'#7c3aed', width:2.8, label:'a+b', lx:-30, ly:0});
sc.addVertex(O, 'O', {dx:-16, dy:14, color:'#0b1d33'});
document.getElementById('viz12-add').innerHTML = sc.render();
}
function buildVectorBasis(){
if (!window.STEREO3D) return setTimeout(buildVectorBasis, 80);
var S = window.STEREO3D;
var sc = new S.Scene(440, 320, {view:'CABINET', scale:60});
sc.addArrow([0,0,0],[2.6,0,0], {color:'#94a3b8', width:1.2});
sc.addArrow([0,0,0],[0,2.6,0], {color:'#94a3b8', width:1.2});
sc.addArrow([0,0,0],[0,0,2.4], {color:'#94a3b8', width:1.2});
sc.addLabel('x', [2.6,0,0], {dx:10, dy:6, color:'#475569', fontSize:12, anchor:'start'});
sc.addLabel('y', [0,2.6,0], {dx:10, dy:8, color:'#475569', fontSize:12, anchor:'start'});
sc.addLabel('z', [0,0,2.4], {dx:-8, dy:-2, color:'#475569', fontSize:12, anchor:'end'});
// Базисные векторы
sc.addArrow([0,0,0],[1,0,0], {color:'#dc2626', width:2.8, label:'i', lx:-2, ly:18});
sc.addArrow([0,0,0],[0,1,0], {color:'#16a34a', width:2.8, label:'j', lx:14, ly:8});
sc.addArrow([0,0,0],[0,0,1], {color:'#1e3a8a', width:2.8, label:'k', lx:-14, ly:-2});
// Вектор a = (2, 1.4, 1.6)
var a = [2, 1.4, 1.6];
sc.addArrow([0,0,0], a, {color:'#7c3aed', width:3, label:'a', lx:8, ly:-4});
// Пунктирные проекции
sc.addEdge(a, [a[0], a[1], 0], {stroke:'#94a3b8', width:1, dash:'3 3'});
sc.addEdge([a[0], a[1], 0], [a[0], 0, 0], {stroke:'#94a3b8', width:1, dash:'3 3'});
sc.addEdge([a[0], a[1], 0], [0, a[1], 0], {stroke:'#94a3b8', width:1, dash:'3 3'});
document.getElementById('viz12-basis').innerHTML = sc.render();
}
function buildDotProduct(){
if (!window.STEREO3D) return setTimeout(buildDotProduct, 80);
var S = window.STEREO3D;
var sc = new S.Scene(440, 280, {view:'CABINET', scale:60});
var O = [0,0,0];
var a = [2, 0.5, 0];
var b = [1.3, 1.7, 0.4];
sc.addArrow(O, a, {color:'#dc2626', width:3, label:'a', lx:4, ly:18});
sc.addArrow(O, b, {color:'#1e3a8a', width:3, label:'b', lx:-22, ly:-2});
// Угол между ними
sc.addAngleMark(O, a, b, {r:0.5, color:'#d97706', width:1.8, label:'φ'});
sc.addVertex(O, 'O', {dx:-16, dy:14, color:'#0b1d33'});
document.getElementById('viz13-dot').innerHTML = sc.render();
}
function buildCubeInCoords(){
if (!window.STEREO3D) return setTimeout(buildCubeInCoords, 80);
var S = window.STEREO3D;
var sc = new S.Scene(460, 360, {view:'CABINET', scale:80, center:[110, 240]});
// Axes from origin
sc.addArrow([0,0,0],[1.8,0,0], {color:'#94a3b8', width:1.3});
sc.addArrow([0,0,0],[0,1.8,0], {color:'#94a3b8', width:1.3});
sc.addArrow([0,0,0],[0,0,1.8], {color:'#94a3b8', width:1.3});
sc.addLabel('x', [1.8,0,0], {dx:8, dy:8, color:'#475569', fontSize:12, anchor:'start'});
sc.addLabel('y', [0,1.8,0], {dx:10, dy:8, color:'#475569', fontSize:12, anchor:'start'});
sc.addLabel('z', [0,0,1.8], {dx:-6, dy:-2, color:'#475569', fontSize:12, anchor:'end'});
// Куб с вершинами A в начале координат
// Вершины: A=(0,0,0), B=(1,0,0), C=(1,1,0), D=(0,1,0), A1=(0,0,1)...
sc.addBox({center:[0.5, 0.5, 0.5], size:[1, 1, 1], labels:true, color:'#fef3c7', opacity:0.25});
document.getElementById('viz14-cube').innerHTML = sc.render();
}
/* ========== Quiz Engine ========== */
function normalizeAns(s){
return String(s||'').toLowerCase()
.replace(/\s+/g,'')
.replace(/°/g,'')
.replace(/sqrt/g,'√')
.replace(/корень/g,'√')
.replace(/,/g,'.')
.replace(/;/g,','); // координаты — через запятую внутри
}
function runQuizMC(opts){
var state = STATE.interactives[opts.id] || { idx: 0, solved: 0 };
var qEl = document.getElementById(opts.id + '-q');
var optsEl = document.getElementById(opts.id + '-opts');
var fbEl = document.getElementById(opts.id + '-fb');
var progEl = document.getElementById(opts.id + '-prog');
function render(){
if (state.solved >= opts.items.length){
qEl.innerHTML = '<b style="color:var(--good)">Все задания решены!</b> +' + (opts.xpPerAll || 10) + ' XP.';
optsEl.innerHTML = '';
fbEl.classList.remove('show');
progEl.textContent = opts.items.length + ' / ' + opts.items.length;
if (!state.awarded){
state.awarded = true;
STATE.interactives[opts.id] = state;
saveState();
addXp(opts.xpPerAll || 10, opts.title || 'тренажёр');
}
return;
}
var item = opts.items[state.idx % opts.items.length];
qEl.innerHTML = item.q;
optsEl.innerHTML = '';
fbEl.classList.remove('show');
for (var i = 0; i < item.opts.length; i++){
(function(i){
var btn = document.createElement('button');
btn.className = 'quiz-opt';
btn.innerHTML = item.opts[i];
btn.addEventListener('click', function(){
var correct = (i === item.correct);
if (correct){
btn.classList.add('correct');
state.solved++;
state.idx++;
STATE.interactives[opts.id] = state;
saveState();
progEl.textContent = state.solved + ' / ' + opts.items.length;
fbEl.className = 'quiz-feedback show good';
fbEl.innerHTML = '<b>Верно.</b> ' + (item.explain || '');
tryKatex(fbEl);
setTimeout(render, 900);
} else {
btn.classList.add('wrong');
fbEl.className = 'quiz-feedback show bad';
fbEl.innerHTML = '<b>Не так.</b> ' + (item.explain || '');
tryKatex(fbEl);
}
});
optsEl.appendChild(btn);
})(i);
}
progEl.textContent = state.solved + ' / ' + opts.items.length;
tryKatex(qEl);
}
render();
}
function runQuizInput(opts){
var state = STATE.interactives[opts.id] || { idx:0, solved:0 };
var qEl = document.getElementById(opts.id + '-q');
var inEl = document.getElementById(opts.id + '-in');
var goEl = document.getElementById(opts.id + '-go');
var fbEl = document.getElementById(opts.id + '-fb');
var progEl = document.getElementById(opts.id + '-prog');
var box = inEl.parentNode;
function render(){
if (state.solved >= opts.items.length){
qEl.innerHTML = '<b style="color:var(--good)">Все задания решены!</b> +' + (opts.xpPerAll || 10) + ' XP.';
inEl.value = ''; inEl.disabled = true; goEl.disabled = true;
progEl.textContent = opts.items.length + ' / ' + opts.items.length;
box.className = 'quiz-input correct';
if (!state.awarded){
state.awarded = true;
STATE.interactives[opts.id] = state;
saveState();
addXp(opts.xpPerAll || 10, opts.title || 'тренажёр');
}
return;
}
var item = opts.items[state.idx % opts.items.length];
qEl.innerHTML = item.q;
inEl.value = ''; inEl.disabled = false; goEl.disabled = false;
fbEl.classList.remove('show');
box.className = 'quiz-input';
progEl.textContent = state.solved + ' / ' + opts.items.length;
tryKatex(qEl);
}
function check(){
var item = opts.items[state.idx % opts.items.length];
var v = 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 i11CoordItems = [
{ q:'Точка $M(3;0;0)$. Где она лежит?', opts:['На оси $Ox$','На оси $Oy$','В плоскости $Oxy$','В пространстве'], correct:0, explain:'Только x-координата отлична от 0 ⇒ на оси $Ox$.' },
{ q:'Точка $M(0;5;0)$. Где она лежит?', opts:['На оси $Ox$','На оси $Oy$','На оси $Oz$','В плоскости $Oxy$'], correct:1, explain:'На оси $Oy$.' },
{ q:'Точка $M(2;3;0)$. Где она лежит?', opts:['На оси $Ox$','В плоскости $Oxy$','В плоскости $Oxz$','Вне плоскостей'], correct:1, explain:'$z = 0$ ⇒ в плоскости $Oxy$.' },
{ q:'Точка $M(0;0;7)$. Где она лежит?', opts:['В пространстве','В плоскости $Oxy$','На оси $Oz$','В плоскости $Oyz$'], correct:2, explain:'На оси $Oz$.' },
{ q:'Точка $M(0;3;5)$. Где она лежит?', opts:['В плоскости $Oxy$','В плоскости $Oxz$','В плоскости $Oyz$','На оси $Oz$'], correct:2, explain:'$x=0$ ⇒ в плоскости $Oyz$.' },
{ q:'Сколько октантов в пространстве (частей, на которые координатные плоскости разбивают пространство)?', opts:['4','6','8','12'], correct:2, explain:'8 октантов.' }
];
var i11DistItems = [
{ q:'$A(1;2;3)$, $B(4;6;3)$. $|AB|$ = ?', answer:'5', explain:'$|AB|=\\sqrt{9+16+0}=\\sqrt{25}=5$.' },
{ q:'$|OM|$, где $M(2;3;6)$.', answer:'7', explain:'$|OM|=\\sqrt{4+9+36}=\\sqrt{49}=7$.' },
{ q:'$A(0;0;0)$, $B(1;1;1)$. $|AB|$ = ?', answer:['√3','sqrt(3)','sqrt3','1.73','1.732'], explain:'$|AB|=\\sqrt{1+1+1}=\\sqrt{3}$.' },
{ q:'$A(1;0;0)$, $B(0;1;0)$. $|AB|$ = ?', answer:['√2','sqrt(2)','sqrt2','1.41','1.414'], explain:'$|AB|=\\sqrt{1+1+0}=\\sqrt{2}$.' },
{ q:'$|OM|$, где $M(2;2;2)$.', answer:['2√3','2sqrt(3)','2sqrt3','3.46','3.464'], explain:'$|OM|=\\sqrt{12}=2\\sqrt{3}$.' }
];
var i11MidItems = [
{ q:'Середина отрезка $AB$, $A(2;4;6)$, $B(8;6;4)$. (Введи в формате $x;y;z$.)', answer:['5;5;5','5,5,5'], explain:'$M\\left(\\frac{2+8}{2}; \\frac{4+6}{2}; \\frac{6+4}{2}\\right) = (5;5;5)$.' },
{ q:'Середина $A(0;0;0)$, $B(4;6;8)$.', answer:['2;3;4'], explain:'Делим каждую координату пополам: $(2;3;4)$.' },
{ q:'Середина $A(-2;3;1)$, $B(4;-1;5)$.', answer:['1;1;3'], explain:'$\\left(\\frac{-2+4}{2};\\frac{3-1}{2};\\frac{1+5}{2}\\right) = (1;1;3)$.' },
{ q:'$A(1;1;1)$, $M(2;2;2)$ — середина $AB$. Найди $B$.', answer:['3;3;3'], explain:'$B = 2M - A = (3;3;3)$.' },
{ q:'Середина $A(0;0;6)$ и $B(0;0;0)$.', answer:['0;0;3'], explain:'$(0;0;3)$.' }
];
var i12AddItems = [
{ q:'$\\vec{a}=(1;2;3)$, $\\vec{b}=(4;5;6)$. $\\vec{a}+\\vec{b}$ = ? (Введи $x;y;z$.)', answer:['5;7;9'], explain:'Покомпонентно: $(1+4; 2+5; 3+6) = (5;7;9)$.' },
{ q:'$\\vec{a}=(3;-1;2)$, $\\vec{b}=(1;4;-2)$. $\\vec{a}+\\vec{b}$ = ?', answer:['4;3;0'], explain:'$(4;3;0)$.' },
{ q:'$\\vec{a}=(2;3;1)$. $3\\vec{a}$ = ?', answer:['6;9;3'], explain:'Умножаем каждую координату на 3.' },
{ q:'$\\vec{a}=(1;0;-2)$, $\\vec{b}=(2;3;1)$. $\\vec{a}-\\vec{b}$ = ?', answer:['-1;-3;-3'], explain:'$(1-2; 0-3; -2-1) = (-1;-3;-3)$.' },
{ q:'$\\vec{a}=(2;4;6)$. $\\frac{1}{2}\\vec{a}$ = ?', answer:['1;2;3'], explain:'$(1;2;3)$.' }
];
var i12CoordItems = [
{ q:'$A(1;2;3)$, $B(4;6;3)$. $\\vec{AB}$ = ?', answer:['3;4;0'], explain:'$(4-1; 6-2; 3-3) = (3;4;0)$.' },
{ q:'$A(2;1;0)$, $B(5;1;4)$. $\\vec{AB}$ = ?', answer:['3;0;4'], explain:'$(3;0;4)$.' },
{ q:'$|\\vec{AB}|$, где $A(1;2;3)$, $B(4;6;3)$.', answer:'5', explain:'$\\vec{AB} = (3;4;0)$, $|\\vec{AB}|=\\sqrt{25}=5$.' },
{ q:'$A(0;0;0)$, $B(2;-1;2)$. $\\vec{BA}$ = ?', answer:['-2;1;-2'], explain:'$\\vec{BA} = -\\vec{AB} = (-2;1;-2)$.' },
{ q:'$|\\vec{a}|$, если $\\vec{a}=(2;3;6)$.', answer:'7', explain:'$\\sqrt{4+9+36}=7$.' }
];
var i12CollItems = [
{ q:'$\\vec{a}=(1;2;3)$, $\\vec{b}=(2;4;6)$. Коллинеарны?', opts:['Да','Нет'], correct:0, explain:'$\\vec{b}=2\\vec{a}$ — коллинеарны.' },
{ q:'$\\vec{a}=(1;2;3)$, $\\vec{b}=(2;4;5)$. Коллинеарны?', opts:['Да','Нет'], correct:1, explain:'$\\frac{1}{2}\\neq\\frac{2}{4}\\neq\\frac{3}{5}$ — нет.' },
{ q:'$\\vec{a}=(3;0;-6)$, $\\vec{b}=(-1;0;2)$. Коллинеарны?', opts:['Да','Нет'], correct:0, explain:'$\\vec{a}=-3\\vec{b}$ — коллинеарны.' },
{ q:'Нулевой вектор $\\vec{0}$ коллинеарен любому вектору?', opts:['Да','Нет'], correct:0, explain:'$\\vec{0} = 0 \\cdot \\vec{a}$ — да, коллинеарен.' },
{ q:'$\\vec{a}=(2;0;0)$, $\\vec{b}=(0;3;0)$. Коллинеарны?', opts:['Да','Нет'], correct:1, explain:'Один вдоль $x$, другой вдоль $y$ — не коллинеарны.' }
];
var i13CalcItems = [
{ q:'$\\vec{a}=(1;2;3)$, $\\vec{b}=(4;5;6)$. $\\vec{a}\\cdot\\vec{b}$ = ?', answer:'32', explain:'$1\\cdot4 + 2\\cdot5 + 3\\cdot6 = 4+10+18=32$.' },
{ q:'$\\vec{a}=(1;0;-1)$, $\\vec{b}=(2;3;2)$. $\\vec{a}\\cdot\\vec{b}$ = ?', answer:'0', explain:'$2 + 0 - 2 = 0$.' },
{ q:'$\\vec{a}=(2;3;1)$. $\\vec{a}\\cdot\\vec{a}$ = ? (это $|\\vec{a}|^2$)', answer:'14', explain:'$4+9+1=14$.' },
{ q:'$\\vec{a}=(1;-1;2)$, $\\vec{b}=(3;1;-1)$. $\\vec{a}\\cdot\\vec{b}$ = ?', answer:'0', explain:'$3 - 1 - 2 = 0$ — векторы перпендикулярны.' },
{ q:'$\\vec{a}=(1;1;1)$, $\\vec{b}=(1;1;1)$. $\\vec{a}\\cdot\\vec{b}$ = ?', answer:'3', explain:'$1+1+1=3$.' }
];
var i13PerpItems = [
{ q:'$\\vec{a}=(2;3;1)$, $\\vec{b}=(1;-1;1)$. Перпендикулярны?', opts:['Да','Нет'], correct:1, explain:'$\\vec{a}\\cdot\\vec{b} = 2-3+1 = 0$. Подожди — это 0, значит ДА перпендикулярны! Исправим: ответ Да.' },
{ q:'$\\vec{a}=(1;2;3)$, $\\vec{b}=(2;-1;0)$. Перпендикулярны?', opts:['Да','Нет'], correct:0, explain:'$2 - 2 + 0 = 0$ — да, перпендикулярны.' },
{ q:'$\\vec{a}=(1;1;1)$, $\\vec{b}=(1;-2;1)$. Перпендикулярны?', opts:['Да','Нет'], correct:0, explain:'$1 - 2 + 1 = 0$ — да.' },
{ q:'$\\vec{a}=(1;0;0)$, $\\vec{b}=(0;0;1)$. Перпендикулярны?', opts:['Да','Нет'], correct:0, explain:'$0+0+0=0$ — да, базисные перпендикулярны.' },
{ q:'$\\vec{a}=(1;2;3)$, $\\vec{b}=(2;4;6)$. Перпендикулярны?', opts:['Да','Нет'], correct:1, explain:'$2+8+18 = 28 \\neq 0$ — нет (они коллинеарны).' }
];
// Fix item 0: actually 2-3+1=0 so they ARE perpendicular. Let me correct this:
i13PerpItems[0] = { q:'$\\vec{a}=(2;3;1)$, $\\vec{b}=(1;-1;1)$. Перпендикулярны?', opts:['Да','Нет'], correct:0, explain:'$\\vec{a}\\cdot\\vec{b} = 2-3+1 = 0$ — да, перпендикулярны.' };
var i13AngleItems = [
{ q:'$\\vec{a}=(1;0;0)$, $\\vec{b}=(1;1;0)$. $\\cos\\varphi$ = ?', answer:['1/√2','1/sqrt(2)','√2/2','sqrt(2)/2','0.707'], explain:'$\\cos\\varphi = \\frac{1}{1\\cdot\\sqrt{2}} = \\frac{1}{\\sqrt{2}} = \\frac{\\sqrt{2}}{2}$.' },
{ q:'$\\vec{a}=(1;0;0)$, $\\vec{b}=(0;1;0)$. $\\cos\\varphi$ = ?', answer:'0', explain:'$\\vec{a}\\cdot\\vec{b}=0$ ⇒ $\\cos\\varphi = 0$ (φ=90°).' },
{ q:'$\\vec{a}=(1;1;0)$, $\\vec{b}=(1;1;0)$. $\\cos\\varphi$ = ?', answer:'1', explain:'Векторы одинаковы — угол 0°, $\\cos = 1$.' },
{ q:'$\\vec{a}=(1;0;0)$, $\\vec{b}=(-1;0;0)$. $\\cos\\varphi$ = ?', answer:'-1', explain:'Противоположны — угол 180°, $\\cos = -1$.' }
];
var i14CubeItems = [
{ q:'Куб с ребром 1, $A(0;0;0)$. Координаты $C_1$?', answer:['1;1;1'], explain:'$C_1 = (1;1;1)$.' },
{ q:'Куб с ребром 1. $|AC_1|$ = ? (диагональ куба)', answer:['√3','sqrt(3)','sqrt3','1.73','1.732'], explain:'$|AC_1| = \\sqrt{1+1+1} = \\sqrt{3}$.' },
{ q:'Куб с ребром 1. $|\\vec{AB_1}|$ = ?', answer:['√2','sqrt(2)','1.41','1.414'], explain:'$\\vec{AB_1} = (1;0;1)$, $|\\vec{AB_1}| = \\sqrt{2}$.' },
{ q:'Куб с ребром 2, $A(0;0;0)$. Координаты $B_1$?', answer:['2;0;2'], explain:'$B_1 = (2;0;2)$.' },
{ q:'Куб с ребром 1, $A(0;0;0)$. Найди $\\vec{AC} \\cdot \\vec{AB_1}$, где $C(1;1;0), B_1(1;0;1)$.', answer:'1', explain:'$\\vec{AC}=(1;1;0)$, $\\vec{AB_1}=(1;0;1)$, скаляр = $1+0+0=1$.' }
];
var i14AngleItems = [
{ q:'Куб с ребром 1. $\\cos$ угла между $\\vec{AB_1}=(1;0;1)$ и $\\vec{AC}=(1;1;0)$?', answer:['1/2','0.5'], explain:'$\\cos = \\frac{1+0+0}{\\sqrt{2}\\cdot\\sqrt{2}} = \\frac{1}{2}$.' },
{ q:'Угол между $\\vec{a}=(1;0;0)$ и $\\vec{b}=(0;0;1)$? (в градусах)', answer:'90', explain:'Скаляр = 0 ⇒ 90°.' },
{ q:'Куб с ребром 1. Угол между $\\vec{AB}=(1;0;0)$ и $\\vec{AB_1}=(1;0;1)$? (в градусах)', answer:'45', explain:'$\\cos = \\frac{1}{\\sqrt{2}}$ ⇒ φ = 45°.' },
{ q:'$\\vec{a}=(1;1;1)$, $\\vec{b}=(1;1;1)$. Угол между ними (в градусах)?', answer:'0', explain:'Векторы совпадают — 0°.' }
];
var i14MethItems = [
{ q:'В кубе нужно найти угол между двумя скрещ. диагоналями. Какой метод проще?', opts:['Чертёж + теоремы','Векторно-координатный','Метод сечений','ТТП'], correct:1, explain:'Куб удобно координатизировать; скаляр векторов даёт сразу косинус угла.' },
{ q:'Задача: доказать $a \\perp b$ в пирамиде с прямоугольным основанием. Удобно?', opts:['Координаты','ТТП','Любой','Невозможно'], correct:2, explain:'Можно и через ТТП, и через координаты — оба эффективны.' },
{ q:'Найти расстояние от точки до плоскости, где плоскость задана 3 точками. Метод?', opts:['Чертёж','Формула $\\rho = \\frac{|Ax_0+...+D|}{\\sqrt{A^2+B^2+C^2}}$','Сечения','Не вычисляется'], correct:1, explain:'Универсальная формула расстояния.' },
{ q:'Условие $\\vec{a}\\cdot\\vec{b}=0$ означает…', opts:['$\\vec{a}\\parallel\\vec{b}$','$\\vec{a}\\perp\\vec{b}$','$|\\vec{a}|=|\\vec{b}|$','Ничего'], correct:1, explain:'Скалярное произведение = 0 ⇔ перпендикулярны.' },
{ q:'Чтобы найти угол между плоскостями, через какие векторы это удобнее всего?', opts:['Через направляющие прямой','Через нормали плоскостей','Через ребро','Через высоту'], correct:1, explain:'Через нормали: $\\cos\\varphi = \\frac{|\\vec{n_1}\\cdot\\vec{n_2}|}{|\\vec{n_1}||\\vec{n_2}|}$.' }
];
/* ========== Bosses ========== */
var BOSS_DEFS = {
11: {
title:'§11 — Координаты в пространстве',
xp:70,
stages:[
{ q:'$A(1;2;2)$, $B(4;6;2)$. $|AB|$ = ?', type:'input', a:'5', explain:'$\\sqrt{9+16+0}=5$.' },
{ q:'Точка $M(0;0;5)$. Где она лежит?', type:'mc', opts:['На оси $Oz$','На оси $Oy$','В пл. $Oxy$','В пр.'], correct:0, explain:'На оси $Oz$.' },
{ q:'Середина $A(2;0;0)$, $B(0;2;2)$. Введи $x;y;z$.', type:'input', a:['1;1;1','1,1,1'], explain:'$(1;1;1)$.' },
{ q:'$|OM|$, где $M(2;3;6)$.', type:'input', a:'7', explain:'$\\sqrt{4+9+36}=7$.' },
{ q:'Сколько октантов в пространстве?', type:'input', a:'8', explain:'8.' }
]
},
12: {
title:'§12 — Векторы',
xp:70,
stages:[
{ q:'$\\vec{a}=(1;2;3), \\vec{b}=(4;5;6)$. $\\vec{a}+\\vec{b}$? (в формате x;y;z)', type:'input', a:['5;7;9'], explain:'$(5;7;9)$.' },
{ q:'$A(1;0;0), B(2;3;4)$. $\\vec{AB}$? (x;y;z)', type:'input', a:['1;3;4'], explain:'$(1;3;4)$.' },
{ q:'$|\\vec{a}|$, если $\\vec{a}=(2;3;6)$.', type:'input', a:'7', explain:'$\\sqrt{49}=7$.' },
{ q:'$\\vec{a}=(1;2;-1), \\vec{b}=(2;4;-2)$. Коллинеарны?', type:'mc', opts:['Да','Нет'], correct:0, explain:'$\\vec{b}=2\\vec{a}$ — да.' },
{ q:'$3\\vec{a}$ при $\\vec{a}=(1;-2;3)$?', type:'input', a:['3;-6;9'], explain:'$(3;-6;9)$.' }
]
},
13: {
title:'§13 — Скалярное произведение',
xp:70,
stages:[
{ q:'$\\vec{a}=(1;2;3), \\vec{b}=(4;5;6)$. $\\vec{a}\\cdot\\vec{b}$ = ?', type:'input', a:'32', explain:'$4+10+18=32$.' },
{ q:'$\\vec{a}\\cdot\\vec{b}=0$ означает:', type:'mc', opts:['$\\parallel$','$\\perp$','Равны'], correct:1, explain:'Перпендикулярны.' },
{ q:'$\\vec{a}=(1;0;-1), \\vec{b}=(2;3;2)$. $\\vec{a}\\cdot\\vec{b}$ = ?', type:'input', a:'0', explain:'$2+0-2=0$.' },
{ q:'$\\vec{a}=(1;0;0), \\vec{b}=(1;1;0)$. $\\cos\\varphi$ = ?', type:'input', a:['1/√2','1/sqrt(2)','√2/2','sqrt(2)/2','0.707'], explain:'$\\frac{1}{\\sqrt{2}}$.' },
{ q:'$\\vec{a}\\cdot\\vec{a}$ = ? (если $\\vec{a}=(1;2;2)$)', type:'input', a:'9', explain:'$1+4+4=9 = |\\vec{a}|^2$.' }
]
},
14: {
title:'§14 — Применение метода',
xp:80,
stages:[
{ q:'Куб с ребром 1. $|AC_1|$ (диагональ куба)?', type:'input', a:['√3','sqrt(3)','sqrt3','1.73','1.732'], explain:'$\\sqrt{3}$.' },
{ q:'Куб (ребро 1). $\\cos$ угла между $\\vec{AB_1}=(1;0;1)$ и $\\vec{AC}=(1;1;0)$?', type:'input', a:['1/2','0.5'], explain:'$\\frac{1}{2}$.' },
{ q:'Чтобы найти угол между плоскостями через векторы, нужны:', type:'mc', opts:['Направляющие прямой','Нормали','Точки','Высоты'], correct:1, explain:'Нормали.' },
{ q:'Куб с ребром 2, $A(0;0;0)$. Координаты $C_1$?', type:'input', a:['2;2;2'], explain:'$(2;2;2)$.' },
{ q:'Условие $\\vec{a}\\cdot\\vec{b} > 0$ означает, что угол $\\varphi$ …', type:'mc', opts:['Острый','Прямой','Тупой','Развёрнутый'], correct:0, explain:'Острый.' },
{ q:'Куб с ребром 1. $\\sin$ угла между $AC_1$ и плоскостью $ABCD$ (если $\\vec{n}=\\vec{k}=(0;0;1)$, $\\vec{AC_1}=(1;1;1)$)?', type:'input', a:['1/√3','1/sqrt(3)','√3/3','sqrt(3)/3','0.577'], explain:'$\\sin\\varphi = \\frac{|0+0+1|}{1\\cdot\\sqrt{3}} = \\frac{1}{\\sqrt{3}}$.' }
]
}
};
function renderBoss(num){
var def = BOSS_DEFS[num];
if (!def) return;
var el = document.getElementById('boss-' + num);
if (!el) return;
var st = STATE.bosses[num] || { stage:0, defeated:false };
STATE.bosses[num] = st;
if (st.defeated){
el.classList.add('victory');
el.innerHTML = '<div class="boss-defeated">'
+ '<div class="boss-defeated-title">Босс §' + num + ' побеждён!</div>'
+ '<div class="boss-defeated-sub">' + def.title + '</div>'
+ '<span class="boss-defeated-xp">+' + def.xp + ' XP</span>'
+ '</div>';
return;
}
el.classList.remove('victory');
var total = def.stages.length;
var stage = def.stages[st.stage];
var hp = Math.round((1 - st.stage/total) * 100);
var optsHtml;
if (stage.type === 'mc'){
optsHtml = '<div class="boss-opts">';
for (var i = 0; i < stage.opts.length; i++){
optsHtml += '<button class="boss-opt" data-i="' + i + '">' + stage.opts[i] + '</button>';
}
optsHtml += '</div>';
} else {
optsHtml = '<div class="boss-input"><input type="text" id="boss-' + num + '-in" inputmode="text" placeholder="ответ"><button id="boss-' + num + '-go">Атака</button></div>';
}
el.innerHTML = '<div class="boss-h">'
+ '<span class="boss-badge">Босс</span>'
+ '<span class="boss-title">' + def.title + '</span>'
+ '</div>'
+ '<div class="boss-hp"><div class="boss-hp-label"><span>HP босса</span><span>' + hp + '%</span></div>'
+ '<div class="boss-hp-bar"><div class="boss-hp-fill" style="width:' + hp + '%"></div></div></div>'
+ '<div class="boss-question">'
+ '<div class="boss-stage-label">Этап ' + (st.stage+1) + ' / ' + total + '</div>'
+ '<div class="boss-q">' + stage.q + '</div>'
+ optsHtml + '</div>';
if (stage.type === 'mc'){
el.querySelectorAll('.boss-opt').forEach(function(btn){
btn.addEventListener('click', function(){
var i = parseInt(btn.getAttribute('data-i'), 10);
var ok = (i === stage.correct);
if (ok){
btn.classList.add('correct');
setTimeout(function(){ advanceBoss(num); }, 600);
} else {
btn.classList.add('wrong');
setTimeout(function(){ btn.classList.remove('wrong'); }, 600);
}
});
});
} else {
var inEl = document.getElementById('boss-' + num + '-in');
var goEl = document.getElementById('boss-' + num + '-go');
var box = inEl.parentNode;
function attack(){
var v = 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(){
buildCoordSystem();
buildDistanceFormula();
buildVectorAdd();
buildVectorBasis();
buildDotProduct();
buildCubeInCoords();
runQuizMC({ id:'i11-coord', items:i11CoordItems, xpPerAll:12, title:'координаты точки' });
runQuizInput({ id:'i11-dist', items:i11DistItems, xpPerAll:14, title:'расстояния' });
runQuizInput({ id:'i11-mid', items:i11MidItems, xpPerAll:12, title:'середины отрезков' });
runQuizInput({ id:'i12-add', items:i12AddItems, xpPerAll:14, title:'действия с векторами' });
runQuizInput({ id:'i12-coord', items:i12CoordItems, xpPerAll:14, title:'координаты вектора' });
runQuizMC({ id:'i12-coll', items:i12CollItems, xpPerAll:10, title:'коллинеарность' });
runQuizInput({ id:'i13-calc', items:i13CalcItems, xpPerAll:14, title:'скалярное произведение' });
runQuizMC({ id:'i13-perp', items:i13PerpItems, xpPerAll:12, title:'перпендикулярность' });
runQuizInput({ id:'i13-angle', items:i13AngleItems, xpPerAll:14, title:'cos угла' });
runQuizInput({ id:'i14-cube', items:i14CubeItems, xpPerAll:16, title:'куб в координатах' });
runQuizInput({ id:'i14-angle', items:i14AngleItems, xpPerAll:16, title:'угол через скаляр' });
runQuizMC({ id:'i14-meth', items:i14MethItems, xpPerAll:12, title:'выбор метода' });
renderBoss(11);
renderBoss(12);
renderBoss(13);
renderBoss(14);
document.getElementById('mark-11').addEventListener('click', function(){ markRead(11); });
document.getElementById('mark-12').addEventListener('click', function(){ markRead(12); });
document.getElementById('mark-13').addEventListener('click', function(){ markRead(13); });
document.getElementById('mark-14').addEventListener('click', function(){ markRead(14); });
refreshMarkBtn(11); refreshMarkBtn(12); refreshMarkBtn(13); refreshMarkBtn(14);
refreshTabs();
var tabs = document.querySelectorAll('.sec-tab[data-tab]');
var sections = ['para-11','para-12','para-13','para-14','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>