Files
Learn_System/frontend/textbooks/algebra_10_ch1.html
T
Maxim Dolgolyov 9d5a2959e1 fix(textbooks): кнопка «Шпаргалка» не открывала контент на desktop
На десктопе (>980px) .col-side уже видна как sticky-колонка справа в grid 1fr 280px.
Клик по кнопке #sidebar-btn добавлял .col-side-backdrop.show — backdrop с
z-index:9990 затемнял всю страницу, перекрывая sticky-aside. Со стороны
выглядело как «ничего не открылось» — на самом деле появлялась чёрная вуаль.

Фикс: @media(min-width:981px) скрывает #sidebar-btn и подавляет показ backdrop.
На мобайле (≤980px) кнопка и overlay работают как раньше.

Применено в 51 файле: physics 8/9/10 chN, algebra 7/9/10/11 chN + 8 ch2-3,
geometry 7/8/9/11 chN, geometry_10 r1-4.
2026-05-30 09:51:04 +03:00

3134 lines
236 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 http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<title>Алгебра 10 · Глава 1 · Тригонометрия</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<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"
onload="renderMathInElement(document.body,{delimiters:[{left:'$$',right:'$$',display:true},{left:'$',right:'$',display:false},{left:'\\[',right:'\\]',display:true},{left:'\\(',right:'\\)',display:false}],throwOnError:false})"></script>
<script src="/js/api.js" defer></script>
<script src="/js/xp.js" defer></script>
<script src="/js/alg10_svg.js?v=1" defer></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Manrope:wght@600;700;800;900&family=Unbounded:wght@700;800;900&family=JetBrains+Mono:wght@500;700&display=swap" rel="stylesheet">
<style>
:root{
--bg:#ecfeff; --card:#fff; --card-soft:#f0fdfa; --text:#0f1a1f; --muted:#4b6671;
--border:#cffafe; --sh:0 1px 3px rgba(0,0,0,.06); --sh2:0 4px 14px rgba(0,0,0,.08);
--pri:#0d9488; --pri2:#0f766e; --pri-soft:#ccfbf1;
--acc:#14b8a6; --acc2:#0d9488; --acc-soft:#99f6e4;
--ok:#10b981; --ok-bg:#d1fae5; --warn:#f59e0b; --warn-bg:#fef3c7;
--bad:#ef4444; --fail:#dc2626; --fail-bg:#fee2e2;
}
.dark{--bg:#04181c; --card:#0a2329; --card-soft:#0e2c32; --text:#e0fbf9; --muted:#88aab1; --border:#1d4248}
*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{font-family:'Inter',system-ui,sans-serif;background:var(--bg);color:var(--text);line-height:1.55;font-size:15px}
button,input,select,textarea{font-family:inherit;font-size:inherit}
button{cursor:pointer;border:0;background:transparent;color:inherit}
a{color:inherit;text-decoration:none}
.ic{width:16px;height:16px;display:inline-block;flex-shrink:0;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;vertical-align:middle}
.hdr{position:relative;background:linear-gradient(110deg,#134e4a 0%,#0d9488 55%,#5eead4 100%);color:#fff;padding:46px 22px 30px;overflow:hidden;border-bottom:2px solid rgba(204,251,241,.2);min-height:130px}
.hdr::before{content:'ГЛАВА 1';position:absolute;right:-12px;top:50%;transform:translateY(-50%);font-family:'Unbounded',sans-serif;font-size:clamp(5rem,15vw,11rem);font-weight:900;letter-spacing:-.04em;color:transparent;-webkit-text-stroke:1.5px rgba(220,250,250,.12);line-height:1;pointer-events:none;z-index:0}
.hdr-row{position:relative;z-index:1;display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.hdr h1{font-family:'Unbounded',sans-serif;font-size:1.5rem;font-weight:900;letter-spacing:-.01em;line-height:1.3;padding-top:4px}
.hdr-sub{font-size:.85rem;opacity:.88;margin-top:6px;font-weight:500;line-height:1.4}
.hdr-side{margin-left:auto;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.hdr-btn{padding:7px 12px;border-radius:9px;background:rgba(255,255,255,.14);color:#fff;font-weight:600;font-size:.82rem;display:inline-flex;align-items:center;gap:6px;transition:background .15s;text-decoration:none}
.hdr-btn:hover{background:rgba(255,255,255,.24)}
.main{max-width:1240px;margin:0 auto;padding:22px;width:100%;display:grid;grid-template-columns:1fr 280px;gap:24px}
@media(max-width:980px){.main{grid-template-columns:1fr;padding:14px}}
.col-main{min-width:0}
.hero{background:linear-gradient(135deg,var(--pri-soft) 0%,var(--acc-soft) 50%,var(--pri-soft) 100%);background-size:200% 200%;animation:heroShift 12s ease-in-out infinite;border:1px solid var(--border);border-radius:18px;padding:24px 22px;margin-bottom:24px;position:relative;overflow:hidden}
@keyframes heroShift{0%,100%{background-position:0% 50%}50%{background-position:100% 50%}}
.hero::before{content:'sin α';position:absolute;right:-10px;top:-20px;font-size:clamp(2rem,8vw,5.5rem);font-weight:900;color:var(--pri);opacity:.10;line-height:1;pointer-events:none;font-family:'Unbounded',sans-serif}
.hero h2{font-family:'Unbounded',sans-serif;font-size:1.55rem;font-weight:800;color:var(--pri2);margin-bottom:10px}
.hero p{font-size:.95rem;color:var(--text);opacity:.88;margin-bottom:14px;max-width:640px}
.hero-row{display:flex;gap:14px;flex-wrap:wrap;align-items:center}
.btn-primary{padding:11px 22px;background:linear-gradient(135deg,var(--pri),var(--pri2));color:#fff;border-radius:11px;font-weight:700;font-size:.92rem;display:inline-flex;align-items:center;gap:8px;box-shadow:var(--sh2)}
.btn-primary:hover{transform:translateY(-1px);box-shadow:0 8px 28px rgba(13,148,136,.32)}
.hero-progress{flex:1;min-width:200px;max-width:280px}
.hp-label{font-size:.74rem;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;display:block;margin-bottom:5px}
.hp-bar{height:8px;background:rgba(13,148,136,.18);border-radius:5px;overflow:hidden}
.hp-fill{height:100%;background:linear-gradient(90deg,var(--pri),var(--acc));border-radius:5px;width:0%;transition:width .6s cubic-bezier(.16,1,.3,1)}
.hp-text{font-size:.78rem;color:var(--muted);font-weight:700;margin-top:4px;display:block}
.hero-xp-badge{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;background:linear-gradient(135deg,var(--warn,#f59e0b),var(--pri));color:#fff;border-radius:99px;font-size:.82rem;font-weight:800;font-family:'Unbounded',sans-serif}
.psel{margin-bottom:24px}
.psel-title{font-size:.72rem;font-weight:800;color:var(--muted);text-transform:uppercase;letter-spacing:.08em;margin-bottom:10px}
.psel-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px}
.psel-card{background:var(--card);border:1.5px solid var(--border);border-radius:13px;padding:12px;cursor:pointer;transition:transform .2s,box-shadow .2s,border-color .2s;text-align:left;position:relative}
.psel-card:hover{transform:translateY(-3px);box-shadow:var(--sh2);border-color:var(--pri)}
.psel-card.active{border-color:var(--pri);background:linear-gradient(135deg,var(--pri-soft),var(--card));box-shadow:var(--sh2)}
.psel-card.active::after{content:'';position:absolute;top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,var(--pri),var(--acc));border-radius:13px 13px 0 0}
.psel-num{font-family:'Unbounded',sans-serif;font-size:.72rem;font-weight:800;color:var(--pri);text-transform:uppercase;letter-spacing:.08em;margin-bottom:4px}
.psel-name{font-size:.82rem;font-weight:700;color:var(--text);line-height:1.3;margin-bottom:6px}
.psel-prog{height:4px;background:rgba(13,148,136,.10);border-radius:3px;overflow:hidden}
.psel-prog-fill{height:100%;background:var(--pri);width:0%;transition:width .4s}
.psel-card.final{background:linear-gradient(135deg,#fff5e1,#fef3c7)}
.sec[id="sec-p1"] { --sec-acc:#0d9488; --sec-acc-d:#0f766e; --sec-acc-soft:#ccfbf1; }
.sec[id="sec-p2"] { --sec-acc:#0891b2; --sec-acc-d:#0e7490; --sec-acc-soft:#cffafe; }
.sec[id="sec-p3"] { --sec-acc:#16a34a; --sec-acc-d:#15803d; --sec-acc-soft:#dcfce7; }
.sec[id="sec-p4"] { --sec-acc:#7c3aed; --sec-acc-d:#6d28d9; --sec-acc-soft:#ede9fe; }
.sec[id="sec-p5"], .sec[id="sec-p6"], .sec[id="sec-p7"], .sec[id="sec-p8"],
.sec[id="sec-p9"], .sec[id="sec-p10"], .sec[id="sec-p11"], .sec[id="sec-p12"],
.sec[id="sec-final1"]{ --sec-acc:#0d9488; --sec-acc-d:#0f766e; --sec-acc-soft:#ccfbf1; }
.sec{display:none;position:relative;animation:fadeIn .35s ease}
.sec.active{display:block}
@keyframes fadeIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
.sec::before{content:attr(data-watermark);position:absolute;right:-20px;top:10%;font-family:'Unbounded',sans-serif;font-size:clamp(6rem,18vw,14rem);font-weight:900;color:transparent;-webkit-text-stroke:1.5px var(--sec-acc-soft,var(--pri-soft));line-height:1;pointer-events:none;z-index:0;opacity:.35}
.sec-header{margin-bottom:22px;padding-bottom:14px;border-bottom:2px solid var(--sec-acc-soft,var(--pri-soft));position:relative;z-index:1}
.sec-num{display:inline-block;padding:4px 10px;background:linear-gradient(135deg,var(--sec-acc,var(--pri)),var(--sec-acc-d,var(--pri2)));color:#fff;border-radius:7px;font-family:'Unbounded',sans-serif;font-size:.78rem;font-weight:800;letter-spacing:.04em;margin-bottom:8px}
.sec-h{font-family:'Unbounded',sans-serif;font-size:1.5rem;font-weight:800;color:var(--sec-acc-d,var(--pri2));line-height:1.25}
.card{background:var(--card);border:1px solid var(--border);border-radius:14px;padding:18px 20px;margin-bottom:16px;box-shadow:0 1px 3px rgba(0,0,0,.04),0 8px 24px rgba(13,148,136,.06);position:relative;z-index:1}
.card-header{display:flex;align-items:center;gap:10px;margin-bottom:12px;padding-bottom:10px;border-bottom:1px dashed var(--border)}
.card-icon{width:32px;height:32px;border-radius:9px;display:flex;align-items:center;justify-content:center;flex-shrink:0;color:#fff}
.card-icon.theory{background:#8b5cf6}.card-icon.rule{background:#ec4899}.card-icon.algo{background:#f59e0b}.card-icon.example{background:#10b981}
.card-icon .ic{width:18px;height:18px}
.card-title{font-family:'Unbounded',sans-serif;font-size:.82rem;font-weight:800;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);flex:1}
.card-num{font-size:.74rem;font-weight:700;color:var(--muted);background:var(--sec-acc-soft,var(--pri-soft));padding:3px 7px;border-radius:5px}
.card-body{font-size:.94rem;line-height:1.65}
.card-body p{margin-bottom:8px}
.wg{background:linear-gradient(135deg,var(--card),var(--sec-acc-soft,var(--pri-soft)));border:1.5px solid var(--sec-acc,var(--pri));border-radius:14px;padding:18px 20px;margin-bottom:18px;box-shadow:var(--sh2);position:relative;z-index:1}
.wg-header{display:flex;align-items:center;gap:8px;margin-bottom:14px}
.wg-badge{padding:4px 9px;background:var(--sec-acc,var(--pri));color:#fff;border-radius:6px;font-family:'Unbounded',sans-serif;font-size:.68rem;font-weight:800;text-transform:uppercase;letter-spacing:.06em}
.wg-title{font-family:'Unbounded',sans-serif;font-size:1.05rem;font-weight:800;color:var(--sec-acc-d,var(--pri2));flex:1}
.wg-help{font-size:.88rem;color:var(--text);margin-bottom:12px;line-height:1.55;background:linear-gradient(135deg,var(--warn-bg,#fef3c7),var(--sec-acc-soft,var(--pri-soft)));border-left:4px solid var(--warn,#f59e0b);padding:9px 14px;border-radius:9px}
.btn{padding:8px 16px;border-radius:8px;background:var(--card);color:var(--text);border:1.5px solid var(--border);font-weight:600;font-size:.88rem;transition:background .15s,border-color .15s}
.btn:hover{background:var(--sec-acc-soft,var(--pri-soft));border-color:var(--sec-acc,var(--pri))}
.btn.primary{background:var(--sec-acc,var(--pri));color:#fff;border-color:var(--sec-acc,var(--pri))}
.btn.primary:hover{background:var(--sec-acc-d,var(--pri2));border-color:var(--sec-acc-d,var(--pri2))}
.tinp{padding:8px 12px;border:1.5px solid var(--border);border-radius:8px;background:var(--card);color:var(--text);font-family:'JetBrains Mono',monospace}
.tinp:focus{outline:0;border-color:var(--sec-acc,var(--pri));box-shadow:0 0 0 3px var(--sec-acc-soft,var(--pri-soft))}
.feedback{padding:10px 14px;border-radius:9px;font-weight:600;font-size:.88rem;margin-top:8px;display:none}
.feedback.ok{display:block;background:var(--ok-bg);color:#065f46;border-left:4px solid var(--ok)}
.feedback.fail{display:block;background:var(--fail-bg);color:#7f1d1d;border-left:4px solid var(--fail)}
.col-side{position:sticky;top:14px;align-self:start;height:fit-content;max-height:calc(100vh - 28px);overflow-y:auto}
.sidecard{background:var(--card);border:1px solid var(--border);border-radius:14px;padding:16px;margin-bottom:14px;box-shadow:var(--sh)}
.sidecard h4{font-family:'Unbounded',sans-serif;font-size:.74rem;font-weight:800;color:var(--pri2);text-transform:uppercase;letter-spacing:.07em;margin-bottom:10px;padding-bottom:8px;border-bottom:1px solid var(--border)}
.sidecard-row{margin-bottom:8px;font-size:.86rem;line-height:1.6}
.sidecard-row b{color:var(--pri);font-weight:700}
@media(max-width:980px){.col-side{position:static;max-height:none}}
.xp-card{background:linear-gradient(135deg,var(--acc-soft),var(--pri-soft));border:1.5px solid var(--acc);border-radius:12px;padding:14px;margin-bottom:14px}
.xp-card-title{font-size:.68rem;font-weight:800;color:var(--acc2);text-transform:uppercase;letter-spacing:.07em;margin-bottom:8px;display:flex;align-items:center;justify-content:space-between}
.xp-level{font-size:1.1rem;font-weight:900;color:var(--acc2);font-family:'Unbounded',sans-serif}
.xp-bar{height:9px;background:rgba(13,148,136,.18);border-radius:6px;overflow:hidden;margin:7px 0}
.xp-fill{height:100%;background:linear-gradient(90deg,var(--acc),var(--pri));border-radius:6px;transition:width .5s cubic-bezier(.4,0,.2,1)}
.xp-nums{font-size:.74rem;color:var(--muted);display:flex;justify-content:space-between}
.spoiler{border:1px solid var(--border);border-radius:10px;background:var(--card);margin:10px 0;overflow:hidden}
.spoiler summary{padding:8px 14px;background:var(--sec-acc-soft,var(--pri-soft));font-weight:700;cursor:pointer;font-size:.88rem;color:var(--sec-acc-d,var(--pri2));list-style:none;display:flex;align-items:center;gap:8px}
.spoiler summary::-webkit-details-marker{display:none}
.spoiler summary::before{content:'+';font-size:1.2rem;font-weight:900;color:var(--sec-acc,var(--pri));width:18px}
.spoiler[open] summary::before{content:'\2212'}
.spoiler-body{padding:10px 14px;font-size:.92rem;line-height:1.6}
.sec-nav{display:flex;gap:10px;margin-top:24px;padding-top:20px;border-top:1px solid var(--border);justify-content:space-between;flex-wrap:wrap}
.foot{text-align:center;padding:30px 16px;color:var(--muted);font-size:.78rem;border-top:1px solid var(--border);margin-top:30px}
.ach-popup{position:fixed;top:80px;right:18px;background:linear-gradient(135deg,#0d9488,#14b8a6);color:#fff;padding:12px 18px;border-radius:11px;font-weight:700;font-size:.9rem;box-shadow:0 8px 28px rgba(13,148,136,.45);z-index:1002;display:none;align-items:center;gap:8px;max-width:340px}
.ach-popup.show{display:flex}
.score-display{display:flex;gap:14px;flex-wrap:wrap;align-items:center;padding:10px 14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;margin-bottom:12px}
.score-display b{color:var(--sec-acc-d,var(--pri2));font-size:1.15rem}
.hp-boss{height:14px;background:rgba(220,38,38,.12);border-radius:9px;overflow:hidden;border:1px solid #fecaca;margin:8px 0}
.hp-boss-fill{height:100%;background:linear-gradient(90deg,#dc2626,#f59e0b);border-radius:9px;transition:width .5s cubic-bezier(.4,0,.2,1)}
.col-side-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.42);z-index:9990;display:none}
.col-side-backdrop.show{display:block}
@media(min-width:981px){#sidebar-btn{display:none}.col-side-backdrop.show{display:none}}
@media(max-width:980px){
.col-side{position:fixed;top:0;right:0;height:100vh;width:300px;max-width:88vw;background:var(--bg);box-shadow:-12px 0 24px rgba(0,0,0,.18);padding:18px 16px;overflow-y:auto;transform:translateX(100%);transition:transform .25s ease;z-index:9991;max-height:none}
.col-side.open{transform:none}
}
.boss-card{padding:16px;background:var(--card);border-radius:12px;border:2px solid var(--bad,#dc2626);margin-bottom:14px}
.boss-head{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.boss-title{font-family:'Unbounded',sans-serif;font-weight:800;color:#7f1d1d;font-size:1.04rem;flex:1}
.boss-stage{font-size:.85rem;color:var(--muted)}
.boss-q{font-size:1rem;line-height:1.55;padding:11px 13px;background:var(--card-soft);border-radius:8px;margin-bottom:9px;border-left:3px solid var(--bad,#dc2626)}
.svg-host{display:flex;justify-content:center;margin:12px 0}
.svg-host-row{display:flex;gap:8px;flex-wrap:wrap;justify-content:center;margin:12px 0}
/* Slider control for interactives */
.slider-ctrl{display:flex;align-items:center;gap:10px;background:var(--card);padding:10px 14px;border-radius:10px;border:1px solid var(--border);margin-bottom:12px;flex-wrap:wrap}
.slider-ctrl label{font-size:.86rem;font-weight:700;color:var(--text);min-width:88px}
.slider-ctrl input[type=range]{flex:1;min-width:180px;accent-color:var(--pri)}
.slider-ctrl .val{font-family:'JetBrains Mono',monospace;font-weight:700;color:var(--pri);min-width:80px;text-align:right}
.stub-soon{padding:30px 22px;text-align:center;background:linear-gradient(135deg,var(--pri-soft),var(--acc-soft));border:1.5px dashed var(--pri);border-radius:14px;color:var(--text)}
.stub-soon h3{font-family:'Unbounded',sans-serif;font-size:1.15rem;color:var(--pri2);margin-bottom:8px}
.stub-soon p{font-size:.92rem;color:var(--muted);max-width:520px;margin:0 auto}
/* Formula plates — стильные плакаты с формулами + KaTeX внутри */
.formula-plate{margin:16px 0;border-radius:14px;overflow:hidden;border:1.5px solid var(--border);box-shadow:0 4px 16px rgba(0,0,0,.04);background:var(--card)}
.formula-plate-head{padding:14px 18px;text-align:center;border-bottom:1px solid var(--border)}
.formula-plate-head.teal {background:linear-gradient(180deg,rgba(13,148,136,.12),rgba(13,148,136,.06))}
.formula-plate-head.cyan {background:linear-gradient(180deg,rgba(8,145,178,.12),rgba(8,145,178,.06))}
.formula-plate-head.violet {background:linear-gradient(180deg,rgba(124,58,237,.12),rgba(124,58,237,.06))}
.formula-plate-head.green {background:linear-gradient(180deg,rgba(22,163,74,.12),rgba(22,163,74,.06))}
.formula-plate-head.amber {background:linear-gradient(180deg,rgba(245,158,11,.14),rgba(245,158,11,.06))}
.formula-plate-title{font-family:'Unbounded',sans-serif;font-size:1.02rem;font-weight:800;letter-spacing:.04em;margin-bottom:4px;text-transform:uppercase}
.formula-plate-head.teal .formula-plate-title{color:#0f766e}
.formula-plate-head.cyan .formula-plate-title{color:#0e7490}
.formula-plate-head.violet .formula-plate-title{color:#6d28d9}
.formula-plate-head.green .formula-plate-title{color:#15803d}
.formula-plate-head.amber .formula-plate-title{color:#92400e}
.formula-plate-sub{font-size:.84rem;font-style:italic;color:var(--muted);line-height:1.4}
.formula-plate-body{padding:14px 22px}
.formula-row{padding:9px 4px;font-size:1.08rem;text-align:center;line-height:1.5;border-bottom:1px dashed rgba(0,0,0,.05)}
.formula-row:last-child{border-bottom:0}
.formula-row.alt{color:#7c3aed}
.formula-row.alt2{color:#0891b2}
.formula-row.danger{color:#dc2626}
.formula-section{margin:0 16px 16px;padding:12px 16px;border-radius:10px;background:rgba(245,158,11,.10);border:1.5px solid rgba(245,158,11,.6)}
.formula-section-title{font-family:'Unbounded',sans-serif;font-size:.74rem;font-weight:800;text-align:center;letter-spacing:.08em;color:#92400e;margin-bottom:8px;text-transform:uppercase}
.formula-section .formula-row{color:#92400e;border-bottom:1px dashed rgba(146,64,14,.18)}
.formula-mnem{margin:0 16px 16px;padding:12px 18px;border-radius:10px;background:rgba(124,58,237,.08);border:1.5px solid rgba(124,58,237,.4)}
.formula-mnem-title{font-family:'Unbounded',sans-serif;font-size:.74rem;font-weight:800;text-align:center;letter-spacing:.08em;color:#6d28d9;margin-bottom:8px;text-transform:uppercase}
.formula-mnem ul{margin:0;padding-left:18px;line-height:1.75;font-size:.93rem;color:var(--text)}
.formula-mnem li{margin-bottom:4px}
</style>
</head>
<body>
<header class="hdr">
<div class="hdr-row">
<div>
<h1>Алгебра 10 · Глава 1</h1>
<div class="hdr-sub">Тригонометрия · единичная окружность · функции · уравнения</div>
</div>
<div class="hdr-side">
<a href="/textbook/algebra-10" class="hdr-btn"><svg class="ic" viewBox="0 0 24 24"><polyline points="15 18 9 12 15 6"/></svg> К Алгебре 10</a>
<button id="sidebar-btn" class="hdr-btn"><svg class="ic" viewBox="0 0 24 24"><line x1="4" y1="6" x2="20" y2="6"/><line x1="4" y1="12" x2="20" y2="12"/><line x1="4" y1="18" x2="14" y2="18"/></svg> Шпаргалка</button>
<button id="theme-btn" class="hdr-btn"><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>
<main class="main">
<div class="col-main">
<section class="hero">
<h2>Тригонометрия начинается с одной окружности</h2>
<p>Единичная окружность с центром в начале координат — фундамент всей тригонометрии. На ней живут <b>sin α</b> и <b>cos α</b> (координаты точки), <b>tg α</b> и <b>ctg α</b> (точки на касательных). Из них вырастают <b>графики</b>, <b>уравнения</b>, <b>формулы</b>.</p>
<div class="hero-row">
<button class="btn-primary" onclick="goTo('p1')"><svg class="ic" viewBox="0 0 24 24"><polygon points="6 4 20 12 6 20 6 4" fill="currentColor" stroke="none"/></svg> Начать § 1</button>
<div class="hero-progress">
<span class="hp-label">Прогресс по главе</span>
<div class="hp-bar"><div id="hero-hp-fill" class="hp-fill"></div></div>
<span id="hero-hp-text" class="hp-text">0%</span>
</div>
<div id="hero-xp-badge" class="hero-xp-badge" data-gamified></div>
</div>
</section>
<section class="psel">
<div class="psel-title">Параграфы главы</div>
<div id="psel-grid" class="psel-grid"></div>
</section>
<section id="sec-p1" class="sec" data-watermark="P_α"><div class="sec-header"><span class="sec-num">§ 1</span><h2 class="sec-h">Единичная окружность. Градусная и радианная мера</h2></div><div id="p1-body"></div></section>
<section id="sec-p2" class="sec" data-watermark="sin"><div class="sec-header"><span class="sec-num">§ 2</span><h2 class="sec-h">Синус и косинус произвольного угла</h2></div><div id="p2-body"></div></section>
<section id="sec-p3" class="sec" data-watermark="tg"><div class="sec-header"><span class="sec-num">§ 3</span><h2 class="sec-h">Тангенс и котангенс произвольного угла</h2></div><div id="p3-body"></div></section>
<section id="sec-p4" class="sec" data-watermark="≡"><div class="sec-header"><span class="sec-num">§ 4</span><h2 class="sec-h">Тригонометрические тождества</h2></div><div id="p4-body"></div></section>
<section id="sec-p5" class="sec" data-watermark="∿"><div class="sec-header"><span class="sec-num">§ 5</span><h2 class="sec-h">Функции y = sin x и y = cos x</h2></div><div id="p5-body"></div></section>
<section id="sec-p6" class="sec" data-watermark="∿"><div class="sec-header"><span class="sec-num">§ 6</span><h2 class="sec-h">Функции y = tg x и y = ctg x</h2></div><div id="p6-body"></div></section>
<section id="sec-p7" class="sec" data-watermark="arc"><div class="sec-header"><span class="sec-num">§ 7</span><h2 class="sec-h">Арксинус, арккосинус, арктангенс, арккотангенс</h2></div><div id="p7-body"></div></section>
<section id="sec-p8" class="sec" data-watermark="="><div class="sec-header"><span class="sec-num">§ 8</span><h2 class="sec-h">Тригонометрические уравнения</h2></div><div id="p8-body"></div></section>
<section id="sec-p9" class="sec" data-watermark="↺"><div class="sec-header"><span class="sec-num">§ 9</span><h2 class="sec-h">Формулы приведения</h2></div><div id="p9-body"></div></section>
<section id="sec-p10" class="sec" data-watermark="±"><div class="sec-header"><span class="sec-num">§ 10</span><h2 class="sec-h">Синус, косинус, тангенс суммы и разности</h2></div><div id="p10-body"></div></section>
<section id="sec-p11" class="sec" data-watermark="2α"><div class="sec-header"><span class="sec-num">§ 11</span><h2 class="sec-h">Формулы двойного аргумента</h2></div><div id="p11-body"></div></section>
<section id="sec-p12" class="sec" data-watermark="·"><div class="sec-header"><span class="sec-num">§ 12</span><h2 class="sec-h">Преобразование суммы в произведение</h2></div><div id="p12-body"></div></section>
<section id="sec-final1" class="sec" data-watermark="&#9733;"><div class="sec-header"><span class="sec-num" style="background:linear-gradient(135deg,#0d9488,#5eead4)">Финал главы</span><h2 class="sec-h">Итоги. 6 боссов главы 1</h2></div><div id="final1-body"></div></section>
</div>
<aside class="col-side" id="col-side"><div id="sidebar-content"></div></aside>
<div class="col-side-backdrop" id="col-side-backdrop"></div>
</main>
<footer class="foot">Интерактивный учебник «Алгебра — 10 класс» · Глава 1 · Тригонометрия · LearnSpace</footer>
<div id="ach-popup" class="ach-popup"><svg class="ic" viewBox="0 0 24 24" style="width:22px;height:22px"><polygon points="12,2 22,20 2,20"/></svg><span id="ach-text">Достижение!</span></div>
<script>
'use strict';
const STATE = { current:'p1', progress:{p1:0,p2:0,p3:0,p4:0,p5:0,p6:0,p7:0,p8:0,p9:0,p10:0,p11:0,p12:0,final1:0}, achievements:new Map(), xp:0, level:1 };
const TOTAL_PARAS = 13;
const _TB_SLUG = 'algebra-10-ch1';
function calcLevel(xp){ return Math.floor(Math.sqrt((xp||0)/100))+1; }
function _xpForLevel(lv){ return (lv-1)*(lv-1)*100; }
const ACH_LABELS = {
start:'Начало главы 1!',
p1_done:'Окружность и углы — освоены!',
p2_done:'sin α и cos α — на ладони!',
p3_done:'tg α и ctg α — понимаешь!',
p4_done:'Тождества — твои!',
p5_done:'Графики sin x и cos x — мастер!',
p6_done:'Графики tg x и ctg x — знаешь!',
p7_done:'Обратные тригонометрические — освоены!',
p8_done:'Тригонометрические уравнения — решаешь!',
p9_done:'Формулы приведения — мастер!',
p10_done:'Сумма и разность — твои!',
p11_done:'Двойной аргумент — лёгкость!',
p12_done:'Преобразование суммы — освоено!',
ch1_done:'Глава 1 — Тригонометрия пройдена!',
trig_master:'Магистр тригонометрии! +150 XP',
};
function loadProgress(){
try{
const s=localStorage.getItem('algebra10_ch1_progress'); if(s) Object.assign(STATE.progress, JSON.parse(s));
const a=localStorage.getItem('algebra10_ch1_achievements');
if(a){ const p=JSON.parse(a); if(Array.isArray(p)) p.forEach(id=>STATE.achievements.set(id, ACH_LABELS[id]||id)); else if(p&&typeof p==='object'){ for(const[id,t] of Object.entries(p)) STATE.achievements.set(id,(t&&t!==id)?t:(ACH_LABELS[id]||id)); } }
STATE.xp=+(localStorage.getItem('algebra10_xp')||0); STATE.level=calcLevel(STATE.xp);
}catch(e){}
}
function saveProgress(){
try{
localStorage.setItem('algebra10_ch1_progress', JSON.stringify(STATE.progress));
localStorage.setItem('algebra10_ch1_achievements', JSON.stringify(Object.fromEntries(STATE.achievements)));
localStorage.setItem('algebra10_xp', String(STATE.xp));
}catch(e){}
}
function bumpProgress(key, delta){
STATE.progress[key]=Math.max(0,Math.min(100,(STATE.progress[key]||0)+delta));
saveProgress(); refreshProgressUI();
if(STATE.progress[key]>=50) markParaRead(key);
if(STATE.progress[key]>=100){
if(key==='p1') achievement('p1_done');
else if(key==='p2') achievement('p2_done');
else if(key==='p3') achievement('p3_done');
else if(key==='p4') achievement('p4_done');
else if(key==='p5') achievement('p5_done');
else if(key==='p6') achievement('p6_done');
else if(key==='p7') achievement('p7_done');
else if(key==='p8') achievement('p8_done');
else if(key==='p9') achievement('p9_done');
else if(key==='p10') achievement('p10_done');
else if(key==='p11') achievement('p11_done');
else if(key==='p12') achievement('p12_done');
else if(key==='final1') achievement('ch1_done');
}
}
const _markedRead=new Set();
let _pendingProgressBody=null, _progressTimer=null;
function _flushProgress(){
const body=_pendingProgressBody; _pendingProgressBody=null; if(!body) return;
const tok=(window.LS&&LS.getToken)?LS.getToken():''; if(!tok) return;
fetch('/api/textbooks/'+_TB_SLUG+'/progress',{method:'POST',headers:{'Content-Type':'application/json','Authorization':'Bearer '+tok},body:JSON.stringify(body),keepalive:true}).catch(()=>{});
}
function _queueProgress(patch){ _pendingProgressBody=Object.assign(_pendingProgressBody||{},patch); if(_progressTimer) clearTimeout(_progressTimer); _progressTimer=setTimeout(_flushProgress, 600); }
function markLastPara(id){ _queueProgress({last_para:id}); }
function markParaRead(id){ if(_markedRead.has(id)) return; _markedRead.add(id); _queueProgress({mark_read:id}); }
window.addEventListener('beforeunload', _flushProgress);
function addXp(n,src){
if(!n) return;
const prev=STATE.level; STATE.xp=Math.max(0,(STATE.xp||0)+n); STATE.level=calcLevel(STATE.xp);
saveProgress(); refreshProgressUI();
if(window.LS&&window.LS.xp) window.LS.xp.add(n,'algebra10-ch1-'+(src||'misc'));
if(STATE.level>prev){
const pop=document.getElementById('ach-popup');
if(pop){ document.getElementById('ach-text').textContent='Уровень '+STATE.level+'!'; pop.classList.add('show'); setTimeout(()=>pop.classList.remove('show'),2600); }
}
}
function refreshProgressUI(){
const total=Math.round(Object.values(STATE.progress).reduce((a,b)=>a+b,0)/TOTAL_PARAS);
const f=document.getElementById('hero-hp-fill'); if(f) f.style.width=total+'%';
const t=document.getElementById('hero-hp-text'); if(t) t.textContent=total+'% пройдено';
document.querySelectorAll('[data-prog-card]').forEach(el=>{ const k=el.dataset.progCard; const fl=el.querySelector('.psel-prog-fill'); if(fl) fl.style.width=(STATE.progress[k]||0)+'%'; });
const xpBadge=document.getElementById('hero-xp-badge');
if(xpBadge){ xpBadge.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="width:13px;height:13px"><polygon points="12 2 22 20 2 20"/></svg> Ур. '+STATE.level+' \xb7 '+(STATE.xp||0)+' XP'; }
if(STATE.current && document.getElementById('sidebar-content')){ try{ buildSidebar(STATE.current); }catch(e){} }
}
function achievement(id,text){
if(STATE.achievements.has(id)) return;
STATE.achievements.set(id, text||ACH_LABELS[id]||id); saveProgress();
const pop=document.getElementById('ach-popup');
if(pop){ document.getElementById('ach-text').textContent=text||ACH_LABELS[id]||id; pop.classList.add('show'); setTimeout(()=>pop.classList.remove('show'),3300); }
addXp(20,'ach-'+id);
}
const PARAS = [
{ id:'p1', num:'§ 1', name:'Единичная окружность', sub:'град ↔ рад' },
{ id:'p2', num:'§ 2', name:'sin и cos', sub:'координаты P_α' },
{ id:'p3', num:'§ 3', name:'tg и ctg', sub:'оси тангенсов' },
{ id:'p4', num:'§ 4', name:'Тождества', sub:'sin² + cos² = 1' },
{ id:'p5', num:'§ 5', name:'y = sin x / cos x', sub:'графики' },
{ id:'p6', num:'§ 6', name:'y = tg x / ctg x', sub:'графики' },
{ id:'p7', num:'§ 7', name:'arcsin, arccos, arctg, arcctg', sub:'обратные' },
{ id:'p8', num:'§ 8', name:'Уравнения', sub:'sin x = a и др.' },
{ id:'p9', num:'§ 9', name:'Формулы приведения', sub:'π/2 ± α и др.' },
{ id:'p10',num:'§ 10', name:'Сумма и разность', sub:'sin(α±β)' },
{ id:'p11',num:'§ 11', name:'Двойной аргумент', sub:'sin 2α' },
{ id:'p12',num:'§ 12', name:'Сумма → произведение', sub:'sin α + sin β' },
{ id:'final1', num:'&#9733;', name:'Финал главы', sub:'6 боссов', final:true },
];
function buildParaSelector(){
const g=document.getElementById('psel-grid'); g.innerHTML='';
PARAS.forEach(p=>{
const card=document.createElement('div');
card.className='psel-card'+(p.final?' final':'');
card.dataset.id=p.id; card.dataset.progCard=p.id;
card.innerHTML='<div class="psel-num">'+p.num+'</div><div class="psel-name">'+p.name+'</div><div class="psel-prog"><div class="psel-prog-fill"></div></div>';
card.addEventListener('click', ()=>goTo(p.id));
g.appendChild(card);
});
if(window.renderMathInElement) try{ renderMath(g); }catch(e){}
}
const BUILT=new Set();
const BUILDERS = { p1:()=>buildP1(), p2:()=>buildP2(), p3:()=>buildP3(), p4:()=>buildP4(),
p5:()=>buildP5(), p6:()=>buildP6(), p7:()=>buildP7(), p8:()=>buildP8(),
p9:()=>buildP9(), p10:()=>buildP10(), p11:()=>buildP11(), p12:()=>buildP12(),
final1:()=>buildFinal1()
};
function ensureBuilt(id){ if(BUILT.has(id)) return; const fn=BUILDERS[id]; if(fn){ fn(); BUILT.add(id); } }
function goTo(id){
STATE.current=id; ensureBuilt(id);
document.querySelectorAll('.sec').forEach(s=>s.classList.remove('active'));
const el=document.getElementById('sec-'+id); if(el) el.classList.add('active');
document.querySelectorAll('.psel-card').forEach(c=>c.classList.toggle('active', c.dataset.id===id));
buildSidebar(id);
window.scrollTo({top:0,behavior:'smooth'});
if((STATE.progress[id]||0)<10) bumpProgress(id, 10);
if(window.renderMathInElement) setTimeout(()=>renderMath(el), 0);
markLastPara(id);
}
const SIDEBARS = {
p1:{title:'Шпаргалка §1',rows:[
['Единичная окружн.','центр $(0;0)$, радиус $1$'],
['$P_\\alpha$','поворот $P_0(1;0)$ на $\\alpha$'],
['1 рад','$\\approx 57°$'],
['Перевод','град $\\cdot \\frac{\\pi}{180}$ → рад'],
['Перевод','рад $\\cdot \\frac{180}{\\pi}$ → град'],
['Полный оборот','$360° = 2\\pi$ рад'],
]},
p2:{title:'Шпаргалка §2',rows:[
['Опр.','$\\sin\\alpha = y_\\alpha$, $\\cos\\alpha = x_\\alpha$'],
['Область знач.','$-1 \\le \\sin\\alpha \\le 1$'],
['','$-1 \\le \\cos\\alpha \\le 1$'],
['I четверть','sin $+$, cos $+$'],
['II четверть','sin $+$, cos $-$'],
['III четверть','sin $-$, cos $-$'],
['IV четверть','sin $-$, cos $+$'],
]},
p3:{title:'Шпаргалка §3',rows:[
['Опр.','$\\tg\\alpha = \\frac{\\sin\\alpha}{\\cos\\alpha}$'],
['Опр.','$\\ctg\\alpha = \\frac{\\cos\\alpha}{\\sin\\alpha}$'],
['ОДЗ tg','$\\alpha \\ne \\frac{\\pi}{2} + \\pi n$'],
['ОДЗ ctg','$\\alpha \\ne \\pi n$'],
['Знаки','I: $+$, II: $-$, III: $+$, IV: $-$'],
['Произведение','$\\tg\\alpha \\cdot \\ctg\\alpha = 1$'],
]},
p4:{title:'Шпаргалка §4',rows:[
['Основное','$\\sin^2\\alpha + \\cos^2\\alpha = 1$'],
['Через tg','$1 + \\tg^2\\alpha = \\frac{1}{\\cos^2\\alpha}$'],
['Через ctg','$1 + \\ctg^2\\alpha = \\frac{1}{\\sin^2\\alpha}$'],
['Связь','$\\tg\\alpha \\cdot \\ctg\\alpha = 1$'],
['Знать одно','найти все 4'],
]},
p5:{title:'Шпаргалка §5',rows:[
['Период','$T = 2\\pi$'],
['$D(\\sin)$','$\\mathbb{R}$'],
['$E(\\sin)$','$[-1;\\,1]$'],
['sin — нечётная','$\\sin(-x) = -\\sin x$'],
['cos — чётная','$\\cos(-x) = \\cos x$'],
['Нули sin','$x = \\pi n$'],
['Нули cos','$x = \\frac{\\pi}{2} + \\pi n$'],
['Связь','$\\cos x = \\sin(x + \\frac{\\pi}{2})$'],
]},
p6:{title:'Шпаргалка §6',rows:[
['Период tg / ctg','$T = \\pi$'],
['$D(\\tg)$','$x \\ne \\frac{\\pi}{2} + \\pi n$'],
['$D(\\ctg)$','$x \\ne \\pi n$'],
['$E(\\tg) = E(\\ctg)$','$\\mathbb{R}$'],
['Асимптоты tg','$x = \\frac{\\pi}{2} + \\pi n$'],
['Асимптоты ctg','$x = \\pi n$'],
['tg — нечётная','$\\tg(-x) = -\\tg x$'],
['ctg — нечётная','$\\ctg(-x) = -\\ctg x$'],
]},
p7:{title:'Шпаргалка §7',rows:[
['$\\arcsin a$','$\\in [-\\frac{\\pi}{2};\\,\\frac{\\pi}{2}]$, $a \\in [-1;1]$'],
['$\\arccos a$','$\\in [0;\\,\\pi]$, $a \\in [-1;1]$'],
['$\\arctg a$','$\\in (-\\frac{\\pi}{2};\\,\\frac{\\pi}{2})$, $a \\in \\mathbb{R}$'],
['$\\arcctg a$','$\\in (0;\\,\\pi)$, $a \\in \\mathbb{R}$'],
['Связь','$\\arcsin a + \\arccos a = \\frac{\\pi}{2}$'],
['','$\\arctg a + \\arcctg a = \\frac{\\pi}{2}$'],
['Нечётные','$\\arcsin(-a) = -\\arcsin a$, $\\arctg$'],
['Не нечётные','$\\arccos(-a) = \\pi - \\arccos a$'],
]},
p8:{title:'Шпаргалка §8',rows:[
['$\\sin x = a$','$x = (-1)^n\\arcsin a + \\pi n$'],
['','при $|a| > 1$ — нет корней'],
['$\\cos x = a$','$x = \\pm\\arccos a + 2\\pi n$'],
['','при $|a| > 1$ — нет корней'],
['$\\tg x = a$','$x = \\arctg a + \\pi n$'],
['$\\ctg x = a$','$x = \\arcctg a + \\pi n$'],
['$\\sin x = 0$','$x = \\pi n$'],
['$\\sin x = 1$','$x = \\frac{\\pi}{2} + 2\\pi n$'],
['$\\cos x = 0$','$x = \\frac{\\pi}{2} + \\pi n$'],
['$\\cos x = 1$','$x = 2\\pi n$'],
]},
p9:{title:'Шпаргалка §9',rows:[
['Шаг 1','Знак — по четверти исх. функции'],
['Шаг 2','Имя меняется при $\\frac{\\pi}{2} \\pm \\alpha$, $\\frac{3\\pi}{2} \\pm \\alpha$'],
['','Не меняется при $\\pi \\pm \\alpha$, $2\\pi \\pm \\alpha$'],
['$\\sin(\\frac{\\pi}{2} - \\alpha)$','$= \\cos\\alpha$'],
['$\\cos(\\frac{\\pi}{2} - \\alpha)$','$= \\sin\\alpha$'],
['$\\sin(\\pi - \\alpha)$','$= \\sin\\alpha$'],
['$\\cos(\\pi - \\alpha)$','$= -\\cos\\alpha$'],
['$\\sin(\\pi + \\alpha)$','$= -\\sin\\alpha$'],
['$\\cos(\\pi + \\alpha)$','$= -\\cos\\alpha$'],
]},
p10:{title:'Шпаргалка §10',rows:[
['$\\sin(\\alpha + \\beta)$','$= \\sin\\alpha\\cos\\beta + \\cos\\alpha\\sin\\beta$'],
['$\\sin(\\alpha - \\beta)$','$= \\sin\\alpha\\cos\\beta - \\cos\\alpha\\sin\\beta$'],
['$\\cos(\\alpha + \\beta)$','$= \\cos\\alpha\\cos\\beta - \\sin\\alpha\\sin\\beta$'],
['$\\cos(\\alpha - \\beta)$','$= \\cos\\alpha\\cos\\beta + \\sin\\alpha\\sin\\beta$'],
['$\\tg(\\alpha + \\beta)$','$= \\frac{\\tg\\alpha + \\tg\\beta}{1 - \\tg\\alpha\\tg\\beta}$'],
['$\\tg(\\alpha - \\beta)$','$= \\frac{\\tg\\alpha - \\tg\\beta}{1 + \\tg\\alpha\\tg\\beta}$'],
['Пример','$\\sin 75° = \\sin(45° + 30°)$'],
]},
p11:{title:'Шпаргалка §11',rows:[
['$\\sin 2\\alpha$','$= 2\\sin\\alpha\\cos\\alpha$'],
['$\\cos 2\\alpha$','$= \\cos^2\\alpha - \\sin^2\\alpha$'],
['','$= 1 - 2\\sin^2\\alpha$'],
['','$= 2\\cos^2\\alpha - 1$'],
['$\\tg 2\\alpha$','$= \\frac{2\\tg\\alpha}{1 - \\tg^2\\alpha}$'],
['$\\sin^2\\alpha$','$= \\frac{1 - \\cos 2\\alpha}{2}$'],
['$\\cos^2\\alpha$','$= \\frac{1 + \\cos 2\\alpha}{2}$'],
]},
p12:{title:'Шпаргалка §12',rows:[
['$\\sin\\alpha + \\sin\\beta$','$= 2\\sin\\frac{\\alpha+\\beta}{2}\\cos\\frac{\\alpha-\\beta}{2}$'],
['$\\sin\\alpha - \\sin\\beta$','$= 2\\sin\\frac{\\alpha-\\beta}{2}\\cos\\frac{\\alpha+\\beta}{2}$'],
['$\\cos\\alpha + \\cos\\beta$','$= 2\\cos\\frac{\\alpha+\\beta}{2}\\cos\\frac{\\alpha-\\beta}{2}$'],
['$\\cos\\alpha - \\cos\\beta$','$= -2\\sin\\frac{\\alpha+\\beta}{2}\\sin\\frac{\\alpha-\\beta}{2}$'],
['Польза','решение уравнений'],
['Пример','$\\sin 3x + \\sin x$ → произведение'],
]},
final1:{title:'Финал главы 1',rows:[
['Боссов','6 — все темы главы'],
['Босс 1','§1-§4 окружность, sin/cos/tg/ctg'],
['Босс 2','§5-§7 графики, обратные'],
['Босс 3','§8 уравнения'],
['Босс 4','§9 приведение'],
['Босс 5','§10-§11 сложение и двойной'],
['Босс 6','§12+ синтез всех тем'],
['Награда','+150 XP + «Магистр тригонометрии»'],
]},
};
const TIPS=[
{sec:'p1',html:'Положительное направление — <b>против часовой</b>. $P_{450°}$ совпадает с $P_{90°}$ — лишний полный оборот.'},
{sec:'p2',html:'Запомни: <b>sin = ордината (y)</b>, <b>cos = абсцисса (x)</b>. Точка $P_\\alpha$ — это и есть пара $(\\cos\\alpha;\\,\\sin\\alpha)$.'},
{sec:'p3',html:'<b>Ось тангенсов</b> — касательная к окружности при $x=1$. Продолжение радиуса $OP_\\alpha$ упирается в эту ось — там и сидит значение tg α.'},
{sec:'p4',html:'Алгоритм «знаю одну → найду все»: 1) основное тождество даёт пару sin/cos; 2) знак выбираем по четверти; 3) tg = sin/cos; 4) ctg = 1/tg.'},
{sec:'p5',html:'$\\cos x$ — это $\\sin x$, сдвинутый <b>влево на $\\frac{\\pi}{2}$</b>. Графики выглядят одинаково, но смещены: где у sin ноль — у cos максимум, и наоборот.'},
{sec:'p6',html:'<b>tg x</b> имеет вертикальные асимптоты в $\\frac{\\pi}{2} + \\pi n$ (там, где $\\cos x = 0$). <b>ctg x</b> — в $\\pi n$ (там, где $\\sin x = 0$). Период <b>$\\pi$</b>, а не $2\\pi$ — это короче, чем у sin/cos.'},
{sec:'p7',html:'Главные значения: $\\arcsin$ и $\\arctg$ — <b>от $-\\frac{\\pi}{2}$ до $\\frac{\\pi}{2}$</b>; $\\arccos$ и $\\arcctg$ — <b>от $0$ до $\\pi$</b>. Это всегда!'},
{sec:'p8',html:'Перед формулой проверь: <b>$|a| > 1$ для sin и cos — корней НЕТ</b>. Если $a = 0, \\pm 1$ — используй <b>особые случаи</b>, они проще общих формул.'},
{sec:'p9',html:'Шаг 1: <b>знак</b> в правой части — по знаку исходной функции в той четверти, куда попадает аргумент при <b>остром $\\alpha$</b>. Шаг 2: <b>имя</b> меняется при $\\frac{\\pi}{2} \\pm \\alpha$ и $\\frac{3\\pi}{2} \\pm \\alpha$, не меняется при $\\pi \\pm \\alpha$ и $2\\pi \\pm \\alpha$.'},
{sec:'p10',html:'Запомнить помогает мнемоника: <b>знаки повторяются в sin</b> (sin·cos + cos·sin) и <b>чередуются в cos</b> (cos·cos sin·sin). Для разности — наоборот.'},
{sec:'p11',html:'Три формы $\\cos 2\\alpha$ нужны для разных задач: $\\cos^2 - \\sin^2$ — для упрощения; $1 - 2\\sin^2$ — когда задан $\\sin\\alpha$; $2\\cos^2 - 1$ — когда задан $\\cos\\alpha$.'},
{sec:'p12',html:'4 формулы — все имеют вид «2 · функция полусуммы · функция полуразности». Знаки и тип функции в правой части смотри по таблице (или по правилу для каждой формулы).'},
{sec:'final1',html:'<b>6 интегрированных боссов</b> проверяют синтез знаний всей главы. После победы над всеми — ачивка <b>«Магистр тригонометрии»</b> и +150 XP. Не торопись, используй шпаргалки.'},
];
function buildSidebar(id){
const box=document.getElementById('sidebar-content');
const sb=SIDEBARS[id]||SIDEBARS.p1;
let html='';
const xpForLv=_xpForLevel(STATE.level), xpNext=_xpForLevel(STATE.level+1);
const xpInLv=STATE.xp-xpForLv, xpRange=xpNext-xpForLv;
const xpPct=xpRange>0?Math.round(xpInLv/xpRange*100):100;
html+='<div class="xp-card" data-gamified><div class="xp-card-title" data-gamified><span>XP-прогресс</span><span class="xp-level">Ур. '+STATE.level+'</span></div><div class="xp-bar"><div class="xp-fill" style="width:'+xpPct+'%"></div></div><div class="xp-nums"><span>'+STATE.xp+' XP</span><span>'+xpNext+' XP</span></div></div>';
html+='<div class="sidecard"><h4>'+sb.title+'</h4>';
sb.rows.forEach(([k,v])=>{ html+='<div class="sidecard-row"><b>'+k+'</b>'+(v?' — '+v:'')+'</div>'; });
html+='</div>';
const tip=TIPS.find(t=>t.sec===id)||TIPS[0];
html+='<div class="sidecard" style="background:linear-gradient(135deg,var(--warn-bg,#fef3c7),var(--pri-soft));border-color:var(--warn,#f59e0b)"><h4 style="color:#92400e">Подсказка</h4><div class="sidecard-row" style="font-size:.84rem;line-height:1.55">'+tip.html+'</div></div>';
if(STATE.achievements.size>0){
html+='<div class="sidecard"><h4>Достижения</h4>';
[...STATE.achievements.values()].slice(-4).forEach(text=>{ html+='<div class="sidecard-row" style="font-size:.78rem;color:var(--ok)">&#10003; '+text+'</div>'; });
html+='</div>';
}
box.innerHTML=html;
if(window.renderMathInElement) try{ renderMath(box); }catch(e){}
}
function initTheme(){
const t=localStorage.getItem('algebra10_ch1_theme')||'light';
if(t==='dark') document.documentElement.classList.add('dark');
document.getElementById('theme-lab').textContent=t==='dark'?'Светлая':'Тёмная';
document.getElementById('theme-btn').addEventListener('click', ()=>{
document.documentElement.classList.toggle('dark');
const dark=document.documentElement.classList.contains('dark');
localStorage.setItem('algebra10_ch1_theme', dark?'dark':'light');
document.getElementById('theme-lab').textContent=dark?'Светлая':'Тёмная';
});
}
function renderMath(root){ if(window.renderMathInElement){ try{ renderMathInElement(root, {delimiters:[{left:'$$',right:'$$',display:true},{left:'$',right:'$',display:false},{left:'\\[',right:'\\]',display:true},{left:'\\(',right:'\\)',display:false}],throwOnError:false}); }catch(e){} } }
function feedback(elm, ok, text){ if(!elm) return; elm.className='feedback '+(ok?'ok':'fail'); elm.innerHTML=text||(ok?'&#10003; Верно!':'&#10007; Неверно'); elm.style.display='block'; try{renderMath(elm);}catch(e){} }
const ICONS = {
theory:'<svg class="ic" viewBox="0 0 24 24"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>',
algo:'<svg class="ic" viewBox="0 0 24 24"><polyline points="17 11 21 7 17 3"/><line x1="21" y1="7" x2="9" y2="7"/><polyline points="7 13 3 17 7 21"/><line x1="3" y1="17" x2="15" y2="17"/></svg>',
rule:'<svg class="ic" viewBox="0 0 24 24"><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/></svg>',
example:'<svg class="ic" viewBox="0 0 24 24"><path d="M9 18h6"/><path d="M10 22h4"/><path d="M12 2a7 7 0 0 0-4 13c1 1 2 2 2 4h4c0-2 1-3 2-4a7 7 0 0 0-4-13z"/></svg>',
};
function makeCard(kind, title, num, body){
const labels={theory:'Теория',algo:'Алгоритм',rule:'Правило',example:'Пример'};
return '<div class="card"><div class="card-header"><div class="card-icon '+kind+'">'+ICONS[kind]+'</div><div class="card-title">'+(labels[kind]||'')+(title&&title!==labels[kind]?' \xb7 '+title:'')+'</div>'+(num?'<div class="card-num">'+num+'</div>':'')+'</div><div class="card-body">'+body+'</div></div>';
}
function secNav(prev, next){
const NAMES={p1:'§1',p2:'§2',p3:'§3',p4:'§4',p5:'§5',p6:'§6',p7:'§7',p8:'§8',p9:'§9',p10:'§10',p11:'§11',p12:'§12',final1:'Финал'};
let h='<div class="sec-nav">';
h+=prev?'<button class="btn" onclick="goTo(\''+prev+'\')"><svg class="ic" viewBox="0 0 24 24"><polyline points="15 18 9 12 15 6"/></svg> '+NAMES[prev]+'</button>':'<span></span>';
h+=next?'<button class="btn primary" onclick="goTo(\''+next+'\')">'+NAMES[next]+' <svg class="ic" viewBox="0 0 24 24"><polyline points="9 18 15 12 9 6"/></svg></button>':'<span></span>';
h+='</div>'; return h;
}
function makeTrainer(opts){
let i=0, score=0;
const Q=opts.questions;
const parser = opts.parser || (v => parseFloat(String(v).replace(',','.')));
function show(){
if(i >= Q.length){
document.getElementById(opts.idPrefix+'-q').innerHTML = '<b>Готово!</b> Результат: '+score+' / '+Q.length;
if(opts.onComplete) opts.onComplete(score, Q.length);
return;
}
document.getElementById(opts.idPrefix+'-i').textContent = (i+1);
document.getElementById(opts.idPrefix+'-s').textContent = score;
document.getElementById(opts.idPrefix+'-q').innerHTML = Q[i].q;
document.getElementById(opts.idPrefix+'-ans').value = '';
renderMath(document.getElementById(opts.idPrefix+'-q'));
document.getElementById(opts.idPrefix+'-fb').style.display = 'none';
}
function go(){
if(i >= Q.length) return;
const fb = document.getElementById(opts.idPrefix+'-fb');
const raw = document.getElementById(opts.idPrefix+'-ans').value.trim();
if(raw === ''){ feedback(fb, false, '&#10007; Введи ответ.'); return; }
const expected = Q[i].a;
let ok = false;
if(typeof expected === 'function') ok = expected(raw);
else { const got = parser(raw); ok = !isNaN(got) && Math.abs(got - expected) < 1e-6; }
if(ok){ score++; feedback(fb, true, '&#10003; Верно! Дальше ▶'); }
else feedback(fb, false, '&#10007; Неверно. Правильно: <b>'+(Q[i].show||expected)+'</b>. Дальше ▶');
document.getElementById(opts.idPrefix+'-s').textContent = score;
i++; setTimeout(show, 1100);
}
document.getElementById(opts.idPrefix+'-go').addEventListener('click', go);
document.getElementById(opts.idPrefix+'-ans').addEventListener('keydown', e=>{ if(e.key==='Enter') go(); });
const restart = document.getElementById(opts.idPrefix+'-start');
if(restart) restart.addEventListener('click', ()=>{ i=0; score=0; show(); });
show();
}
function trainerHTML(idPrefix, total, placeholder){
return '<div class="score-display"><span>Задача <b id="'+idPrefix+'-i">1</b> / '+total+'</span><span>Очки: <b id="'+idPrefix+'-s">0</b> / '+total+'</span></div>'
+'<div id="'+idPrefix+'-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.05rem;margin-bottom:10px;text-align:center"></div>'
+'<div style="display:flex;gap:10px;align-items:center;flex-wrap:wrap;justify-content:center">'
+'<input type="text" id="'+idPrefix+'-ans" class="tinp" placeholder="'+(placeholder||'Ответ')+'" style="width:140px;text-align:center">'
+'<button class="btn primary" id="'+idPrefix+'-go">Проверить</button>'
+'<button class="btn" id="'+idPrefix+'-start">Заново</button>'
+'</div><div class="feedback" id="'+idPrefix+'-fb"></div>';
}
function makeBoss(paraId, bossDef){
/* bossDef: { color, title, steps:[{q, verify, hint}] } */
const idP = paraId+'-boss';
const SKEY = 'algebra10_ch1_'+paraId+'_boss';
let st = {stage:0, defeated:false};
try{ const s=localStorage.getItem(SKEY); if(s) st=JSON.parse(s); }catch(e){}
const html = '<div class="boss-card" style="border-color:'+bossDef.color+'">'
+'<div class="boss-head">'
+'<svg viewBox="0 0 24 24" fill="none" stroke="'+bossDef.color+'" stroke-width="2.2" style="width:28px;height:28px"><polygon points="12,2 22,20 2,20"/></svg>'
+'<div class="boss-title" style="color:'+bossDef.color+'">'+bossDef.title+'</div>'
+'<div class="boss-stage" id="'+idP+'-stage">Этап 1 / '+bossDef.steps.length+'</div>'
+'</div>'
+'<div class="hp-boss" style="border-color:'+bossDef.color+'66;background:'+bossDef.color+'1a"><div class="hp-boss-fill" id="'+idP+'-fill" style="width:0%;background:linear-gradient(90deg,'+bossDef.color+',#f59e0b)"></div></div>'
+'<div class="boss-q" id="'+idP+'-q" style="border-color:'+bossDef.color+'"></div>'
+'<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap">'
+'<input type="text" id="'+idP+'-input" class="tinp" placeholder="Ответ" style="width:160px;text-align:center">'
+'<button class="btn primary" id="'+idP+'-go" style="background:'+bossDef.color+';border-color:'+bossDef.color+'">Атака</button>'
+'<button class="btn" id="'+idP+'-hint">Подсказка</button>'
+'<button class="btn" id="'+idP+'-restart">↻</button>'
+'</div>'
+'<div class="feedback" id="'+idP+'-fb"></div>'
+'</div>';
setTimeout(()=>{
function save(){ try{ localStorage.setItem(SKEY, JSON.stringify(st)); }catch(e){} }
function show(){
const stageEl=document.getElementById(idP+'-stage');
const fill=document.getElementById(idP+'-fill');
const q=document.getElementById(idP+'-q');
const fb=document.getElementById(idP+'-fb');
if(st.defeated){
stageEl.innerHTML='&#10003; Побеждён'; fill.style.width='100%';
q.innerHTML='<b style="color:'+bossDef.color+'">Босс повержен!</b>';
document.getElementById(idP+'-go').disabled=true;
document.getElementById(idP+'-go').style.opacity=.5;
return;
}
stageEl.textContent='Этап '+(st.stage+1)+' / '+bossDef.steps.length;
fill.style.width=(st.stage*100/bossDef.steps.length)+'%';
q.innerHTML=bossDef.steps[st.stage].q;
document.getElementById(idP+'-input').value='';
fb.style.display='none';
renderMath(q);
}
document.getElementById(idP+'-go').addEventListener('click',()=>{
if(st.defeated) return;
const step=bossDef.steps[st.stage];
const val=document.getElementById(idP+'-input').value;
const fb=document.getElementById(idP+'-fb');
if(!val.trim()){ feedback(fb,false,'&#10007; Введи ответ.'); return; }
if(step.verify(val)){
st.stage++;
if(st.stage>=bossDef.steps.length){
st.defeated=true; save();
feedback(fb,true,'&#10003; Босс повержен! +20 XP');
addXp(20,paraId+'-boss'); bumpProgress(paraId, 30);
setTimeout(show,1400);
}else{
save(); feedback(fb,true,'&#10003; Верно! +3 XP'); addXp(3,paraId+'-boss-step'); setTimeout(show,1100);
}
}else{ feedback(fb,false,'&#10007; Промах.'); }
});
document.getElementById(idP+'-hint').addEventListener('click',()=>{
if(st.defeated) return;
const fb=document.getElementById(idP+'-fb');
fb.className='feedback ok';
fb.innerHTML='<span style="color:#92400e">\u{1F4A1} Подсказка:</span> '+bossDef.steps[st.stage].hint;
fb.style.display='block';
fb.style.background='var(--warn-bg)'; fb.style.color='#92400e'; fb.style.borderLeftColor='var(--warn)';
renderMath(fb);
});
document.getElementById(idP+'-restart').addEventListener('click',()=>{
st={stage:0,defeated:false}; save();
document.getElementById(idP+'-go').disabled=false;
document.getElementById(idP+'-go').style.opacity=1;
show();
});
show();
}, 0);
return html;
}
function readButton(paraId){
return '<div style="margin-top:18px;display:flex;justify-content:center">'
+'<button class="btn primary" id="'+paraId+'-read-btn">'
+'<svg class="ic" viewBox="0 0 24 24"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>'
+' Я прочитал §'+paraId.replace('p','').replace('final','финал ')+' (+10 XP)'
+'</button></div>';
}
function wireReadBtn(paraId){
document.getElementById(paraId+'-read-btn').addEventListener('click', ()=>{
addXp(10, paraId+'-read'); bumpProgress(paraId, 30);
const b=document.getElementById(paraId+'-read-btn'); b.textContent='Прочитано! +10 XP'; b.disabled=true; b.style.opacity=.6;
});
}
function initSidebarToggle(){
const side=document.getElementById('col-side'),back=document.getElementById('col-side-backdrop'),btn=document.getElementById('sidebar-btn');
if(!side||!btn) return;
function open(){ side.classList.add('open'); back.classList.add('show'); }
function close(){ side.classList.remove('open'); back.classList.remove('show'); }
btn.addEventListener('click',()=>{ if(side.classList.contains('open')) close(); else open(); });
back.addEventListener('click',close);
document.addEventListener('keydown',e=>{ if(e.key==='Escape') close(); });
}
function init(){
loadProgress(); initTheme(); initSidebarToggle();
buildParaSelector(); refreshProgressUI(); goTo('p1');
setTimeout(()=>achievement('start','Начало главы 1!'), 600);
}
document.addEventListener('DOMContentLoaded', init);
/* ============================================================
Заглушка для §5-§12 и финала
============================================================ */
function buildStub(paraId, title){
const box = document.getElementById(paraId+'-body');
box.innerHTML = '<div class="stub-soon">'
+'<h3>'+title+'</h3>'
+'<p>Этот параграф появится в одной из ближайших волн реализации. Сейчас доступны §1–§4 — базовый блок «единичная окружность + sin/cos + tg/ctg + тождества».</p>'
+'</div>'
+ secNav(paraId==='p5'?'p4':(paraId==='final1'?'p12':PARAS[PARAS.findIndex(p=>p.id===paraId)-1].id),
paraId==='final1'?null:PARAS[PARAS.findIndex(p=>p.id===paraId)+1].id);
}
/* ============================================================
§ 1 — Единичная окружность. Градусная и радианная мера
============================================================ */
function buildP1(){
const box = document.getElementById('p1-body');
const A = window.ALG10;
let html = '';
/* === Главный SVG: единичная окружность с делениями === */
let svgBase = '';
if(A){
const c = A.tri.canvas({id:'p1-base', W:340, H:340, R:130, bg:'#fff'});
let s = c.open
+ c.axes()
+ c.circle({width:2.5})
+ c.degreeMark(0) + c.degreeMark(30) + c.degreeMark(60) + c.degreeMark(90)
+ c.degreeMark(120)+ c.degreeMark(150) + c.degreeMark(180) + c.degreeMark(210)
+ c.degreeMark(240)+ c.degreeMark(270) + c.degreeMark(300) + c.degreeMark(330)
+ c.point(0, {label:'P_0', color:'#1e293b', labelOffset:18, fontSize:11})
+ c.point(Math.PI/3, {label:'P_{60°}', color:'#dc2626', labelOffset:18, fontSize:11})
+ c.radius(Math.PI/3, {color:'#dc2626'})
+ c.rotationArrow(Math.PI/3, {color:'#16a34a', r:35})
+ c.close;
svgBase = s;
}
/* === Slider-эксперимент: точка P_α на окружности === */
let svgSlider = '';
if(A){
const c = A.tri.canvas({id:'p1-sl', W:340, H:340, R:130, bg:'#fff'});
/* Заглушка — отрисует с углом 60°, динамика добавится при инициализации */
let s = c.open
+ c.axes()
+ c.circle({width:2})
+ c.point(0, {label:'P_0', color:'#94a3b8', labelOffset:18, fontSize:11})
+ '<g id="p1-sl-dyn"></g>'
+ c.close;
svgSlider = s;
}
html += makeCard('theory', 'Единичная окружность', '1.1', `
<p><b>Единичной (тригонометрической) окружностью</b> называется окружность с центром в начале координат и радиусом $R = 1$.</p>
<p>Начало отсчёта — точка $P_0(1;\\,0)$. <b>Положительное направление</b> движения по окружности — против часовой стрелки.</p>
<div class="svg-host">${svgBase}</div>
<p>Точка $P_\\alpha$ получается поворотом точки $P_0$ вокруг начала координат на угол $\\alpha$ — это базовая операция тригонометрии.</p>`);
html += makeCard('rule', 'Углы любой величины', '1.2', `
<p>В отличие от планиметрии, здесь угол может быть <b>любым действительным числом</b>:</p>
<ul style="padding-left:22px;line-height:1.85">
<li><b>$\\alpha > 0$</b> — поворот <b>против часовой</b>;</li>
<li><b>$\\alpha < 0$</b> — поворот <b>по часовой</b>;</li>
<li><b>$|\\alpha| > 360°$</b> — несколько полных оборотов плюс остаток.</li>
</ul>
<p>Например, $P_{450°} = P_{360° + 90°} = P_{90°}$ — лишний полный оборот не изменяет положения.</p>
<p>Общая формула: $P_\\alpha = P_{\\alpha + 360° \\cdot n}$ для любого целого $n$.</p>`);
html += makeCard('rule', 'Радианная мера', '1.3', `
<p>На единичной окружности длина дуги <b>равна</b> радианной мере соответствующего угла.</p>
<p>$1$ радиан — центральный угол, опирающийся на дугу длиной $1$ (то есть равную радиусу).</p>
<p style="background:var(--sec-acc-soft);padding:10px 14px;border-radius:8px"><b>$2\\pi$ рад $= 360°$</b>, поэтому <b>$1$ рад $= \\frac{180°}{\\pi} \\approx 57°$</b>.</p>
<p><b>Перевод:</b></p>
<ul style="padding-left:22px;line-height:1.9">
<li>град $\\to$ рад: <b>умножить на $\\dfrac{\\pi}{180}$</b>;</li>
<li>рад $\\to$ град: <b>умножить на $\\dfrac{180}{\\pi}$</b>.</li>
</ul>
<p>Примеры: $30° = \\dfrac{\\pi}{6}$, $45° = \\dfrac{\\pi}{4}$, $60° = \\dfrac{\\pi}{3}$, $90° = \\dfrac{\\pi}{2}$.</p>`);
html += makeCard('algo', 'Четверть угла', '1.4', `
<p>Чтобы определить, в какой четверти лежит угол $\\alpha$:</p>
<ol style="padding-left:22px;line-height:1.9">
<li>Если $\\alpha$ в радианах — переведи в градусы (по желанию).</li>
<li>Приведи к промежутку $[0°;\\,360°)$, отнимая или прибавляя нужное число оборотов.</li>
<li>Сравни:
<ul style="padding-left:18px;line-height:1.75">
<li>$[0°;\\,90°)$ — <b>I</b>;</li>
<li>$[90°;\\,180°)$ — <b>II</b>;</li>
<li>$[180°;\\,270°)$ — <b>III</b>;</li>
<li>$[270°;\\,360°)$ — <b>IV</b>.</li>
</ul>
</li>
</ol>
<p><b>Пример.</b> $\\alpha = 1300°$ → $1300° - 3 \\cdot 360° = 220°$ → III четверть.</p>`);
/* === ИНТЕРАКТИВ 1: Slider угла === */
html += '<div class="wg" id="p1-iv1">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Точка $P_\\alpha$ — крути угол</div></div>'
+'<div class="wg-help">Двигай ползунок угла от <b>-720°</b> до <b>+720°</b> и наблюдай, как точка $P_\\alpha$ перемещается по окружности.</div>'
+'<div class="slider-ctrl"><label>Угол α:</label><input type="range" id="p1-iv1-r" min="-720" max="720" step="5" value="60"><span class="val" id="p1-iv1-v">60°</span></div>'
+'<div class="svg-host">'+svgSlider+'</div>'
+'<div style="font-size:.86rem;color:var(--muted);text-align:center">Эквивалент в $[0°;\\,360°)$: <b id="p1-iv1-eq" style="color:var(--pri)">60°</b></div>'
+'</div>';
/* === ИНТЕРАКТИВ 2: Перевод град ↔ рад === */
html += '<div class="wg" id="p1-iv2">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Градусы ↔ радианы</div></div>'
+'<div class="wg-help">Введи ответ в виде дроби (например <b>5pi/6</b>) или числа (для градусов — без °).</div>'
+trainerHTML('p1-iv2', 8, 'ответ')
+'</div>';
/* === ИНТЕРАКТИВ 3: Четверть угла === */
html += '<div class="wg" id="p1-iv3">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 3</span><div class="wg-title">В какой четверти?</div></div>'
+'<div class="wg-help">Определи номер четверти (1, 2, 3, 4), в которой лежит угол.</div>'
+trainerHTML('p1-iv3', 6, 'номер')
+'</div>';
/* === БОСС === */
html += '<h3 style="font-family:Unbounded,sans-serif;font-size:1.05rem;color:var(--pri2);margin:20px 0 12px">Босс §1 — Окружность и углы</h3>';
html += makeBoss('p1', {
color:'#0d9488',
title:'Босс §1 — Окружность и углы',
steps:[
{ q:'Сколько градусов в $\\pi$ радиан?', verify:(v)=>+v===180, hint:'$\\pi$ рад $= 180°$.' },
{ q:'Преобразуй $240°$ в радианы (введи как <b>4pi/3</b>).', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='4pi/3' || s==='4π/3';}, hint:'$240° \\cdot \\dfrac{\\pi}{180} = \\dfrac{4\\pi}{3}$.' },
{ q:'В какой четверти лежит угол $1300°$?', verify:(v)=>+v===3, hint:'$1300° - 3 \\cdot 360° = 220°$ — III четверть.' },
{ q:'Сколько различных точек $P_\\alpha$ дадут углы $\\frac{\\pi}{3}$, $-\\frac{\\pi}{3}$, $\\frac{7\\pi}{3}$, $-\\frac{5\\pi}{3}$?', verify:(v)=>+v===2, hint:'$\\frac{\\pi}{3} = \\frac{7\\pi}{3}$ (отличие $2\\pi$) и $-\\frac{\\pi}{3} = -\\frac{5\\pi}{3} + \\frac{2\\pi} \\cdot? $ — на самом деле $-\\frac{5\\pi}{3} = \\frac{\\pi}{3}$. Итого 2.' },
{ q:'Радианная мера двух углов треугольника — $\\frac{2\\pi}{5}$ и $\\frac{3\\pi}{10}$. Найди третий угол в градусах.', verify:(v)=>+v===54, hint:'Сумма $= \\pi$, третий $= \\pi - \\frac{2\\pi}{5} - \\frac{3\\pi}{10} = \\frac{3\\pi}{10}$ — это $54°$.' },
]
});
html += secNav(null, 'p2') + readButton('p1');
box.innerHTML = html; renderMath(box);
/* === Логика интерактивов === */
/* IV1: slider угла */
(function(){
const r = document.getElementById('p1-iv1-r');
const v = document.getElementById('p1-iv1-v');
const eq = document.getElementById('p1-iv1-eq');
const dyn = document.getElementById('p1-sl-dyn');
function redraw(deg){
v.textContent = deg + '°';
let mod = ((deg % 360) + 360) % 360;
eq.textContent = mod + '°';
if(!A || !dyn) return;
const c = A.tri.canvas({id:'p1-sl-h', W:340, H:340, R:130});
const rad = deg * Math.PI / 180;
dyn.innerHTML = c.radius(rad, {color:'#dc2626'})
+ c.point(rad, {label:'P_α', color:'#dc2626', labelOffset:18, fontSize:11})
+ c.rotationArrow(rad, {r:30});
}
r.addEventListener('input', e=>redraw(+e.target.value));
redraw(60);
})();
/* IV2: тренажёр перевода */
makeTrainer({
idPrefix:'p1-iv2',
parser:(v)=>v,
questions:[
{ q:'Преобразуй $30°$ в радианы. Введи как pi/n.', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/6'||s==='π/6';}, show:'$\\pi/6$' },
{ q:'Преобразуй $90°$ в радианы.', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/2'||s==='π/2';}, show:'$\\pi/2$' },
{ q:'Преобразуй $150°$ в радианы.', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='5pi/6'||s==='5π/6';}, show:'$5\\pi/6$' },
{ q:'Преобразуй $\\dfrac{\\pi}{4}$ в градусы.', a:(v)=>+v===45, show:'$45°$' },
{ q:'Преобразуй $\\dfrac{2\\pi}{3}$ в градусы.', a:(v)=>+v===120, show:'$120°$' },
{ q:'Преобразуй $\\dfrac{7\\pi}{6}$ в градусы.', a:(v)=>+v===210, show:'$210°$' },
{ q:'Преобразуй $-80°$ в радианы. Введи как -np/m.', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-4pi/9'||s==='-4π/9';}, show:'$-4\\pi/9$' },
{ q:'Сколько градусов в $4$ радианах? (округли)', a:(v)=>+v===229, show:'$\\approx 229°$' },
],
onComplete:(s,n)=>{ if(s===n){addXp(18,'p1-iv2');bumpProgress('p1',30);} else if(s>=5){addXp(8,'p1-iv2');bumpProgress('p1',15);} }
});
/* IV3: четверть угла */
makeTrainer({
idPrefix:'p1-iv3',
questions:[
{ q:'$\\alpha = 126°$. Какая четверть?', a:2 },
{ q:'$\\alpha = 220°$. Какая четверть?', a:3 },
{ q:'$\\alpha = 7\\pi/10$. Какая четверть?', a:2 },
{ q:'$\\alpha = -\\pi/3$. Какая четверть?', a:4 },
{ q:'$\\alpha = 722°$. Какая четверть?', a:1 },
{ q:'$\\alpha = -189°$. Какая четверть?', a:2 },
],
onComplete:(s,n)=>{ if(s===n){addXp(15,'p1-iv3');bumpProgress('p1',25);} else if(s>=4){addXp(8,'p1-iv3');bumpProgress('p1',12);} }
});
wireReadBtn('p1');
}
/* ============================================================
§ 2 — Синус и косинус произвольного угла
============================================================ */
function buildP2(){
const box = document.getElementById('p2-body');
const A = window.ALG10;
let html = '';
/* === SVG 1: определение через координаты P_α === */
let svgDef = '';
if(A){
const c = A.tri.canvas({id:'p2-def', W:320, H:320, R:120});
const angle = 60 * Math.PI / 180;
let s = c.open
+ c.axes()
+ c.circle({width:2})
+ c.radius(angle, {color:'#dc2626'})
+ c.sinSegment(angle, {color:'#dc2626', label:'sin α', dash:'0', width:2.5})
+ c.cosSegment(angle, {color:'#2563eb', label:'cos α', dash:'0', width:2.5})
+ c.point(angle, {label:'P_α (cos α; sin α)', color:'#dc2626', labelOffset:20, fontSize:10})
+ c.close;
svgDef = s;
}
/* === SVG 2: знаки по четвертям === */
let svgSigns = '';
if(A){
const c = A.tri.canvas({id:'p2-signs', W:320, H:320, R:120});
let s = c.open
+ c.quadrant(1, {fill:'rgba(16,185,129,.15)'})
+ c.quadrant(2, {fill:'rgba(245,158,11,.15)'})
+ c.quadrant(3, {fill:'rgba(239,68,68,.15)'})
+ c.quadrant(4, {fill:'rgba(124,58,237,.15)'})
+ c.axes()
+ c.circle({width:2})
+ c.quadrantLabels({color:'#1e293b'})
/* Подписи знаков */
+ '<text x="220" y="115" text-anchor="middle" font-size="13" font-weight="800" fill="#065f46">sin +</text>'
+ '<text x="220" y="135" text-anchor="middle" font-size="13" font-weight="800" fill="#065f46">cos +</text>'
+ '<text x="100" y="115" text-anchor="middle" font-size="13" font-weight="800" fill="#92400e">sin +</text>'
+ '<text x="100" y="135" text-anchor="middle" font-size="13" font-weight="800" fill="#dc2626">cos </text>'
+ '<text x="100" y="225" text-anchor="middle" font-size="13" font-weight="800" fill="#dc2626">sin </text>'
+ '<text x="100" y="245" text-anchor="middle" font-size="13" font-weight="800" fill="#dc2626">cos </text>'
+ '<text x="220" y="225" text-anchor="middle" font-size="13" font-weight="800" fill="#dc2626">sin </text>'
+ '<text x="220" y="245" text-anchor="middle" font-size="13" font-weight="800" fill="#065f46">cos +</text>'
+ c.close;
svgSigns = s;
}
/* === SVG 3: точные значения для главных углов === */
let svgTable = '';
if(A){
const c = A.tri.canvas({id:'p2-tbl', W:340, H:340, R:130});
let s = c.open + c.axes() + c.circle({width:2});
const marks = [
{a:Math.PI/6, lab:'π/6', c:'#dc2626'},
{a:Math.PI/4, lab:'π/4', c:'#16a34a'},
{a:Math.PI/3, lab:'π/3', c:'#2563eb'},
{a:Math.PI/2, lab:'π/2', c:'#7c3aed'},
];
for(const m of marks){
s += c.radius(m.a, {color:m.c, width:1.8});
s += c.point(m.a, {color:m.c, label:m.lab, labelOffset:18, fontSize:11, r:3.5});
}
s += c.close;
svgTable = s;
}
html += makeCard('theory', 'Определение sin и cos', '2.1', `
<p>В планиметрии $\\sin\\alpha$ и $\\cos\\alpha$ были определены только для острого угла прямоугольного треугольника. Теперь обобщаем на любой угол.</p>
<p style="background:var(--sec-acc-soft);padding:10px 14px;border-radius:8px"><b>Определение.</b> Для любого угла $\\alpha$ точка $P_\\alpha$ единичной окружности имеет координаты $(\\cos\\alpha;\\,\\sin\\alpha)$:</p>
<p style="text-align:center;font-size:1.1rem;margin:10px 0">$\\sin\\alpha = y_\\alpha, \\quad \\cos\\alpha = x_\\alpha$</p>
<div class="svg-host">${svgDef}</div>
<p>Запомни: <b>sin — ордината (y)</b>, <b>cos — абсцисса (x)</b>.</p>`);
html += makeCard('rule', 'Область значений', '2.2', `
<p>Координаты любой точки единичной окружности лежат в $[-1;\\,1]$, поэтому:</p>
<p style="text-align:center;font-size:1.1rem;margin:10px 0">$-1 \\le \\sin\\alpha \\le 1, \\quad -1 \\le \\cos\\alpha \\le 1$</p>
<p>Значения, которые <b>не могут</b> быть синусами или косинусами: $\\sqrt{3}$, $-2$, $1{,}5$ — они вне отрезка $[-1;\\,1]$.</p>`);
html += makeCard('rule', 'Знаки sin/cos по четвертям', '2.3', `
<p>Знак $\\sin\\alpha$ совпадает со знаком ординаты точки $P_\\alpha$, а $\\cos\\alpha$ — со знаком абсциссы.</p>
<div class="svg-host">${svgSigns}</div>
<p><b>Мнемоника</b> для $\\sin\\alpha$: «положителен сверху от оси x» — то есть в I и II четвертях.</p>
<p><b>Для $\\cos\\alpha$:</b> «положителен справа от оси y» — I и IV четверти.</p>`);
html += makeCard('example', 'Значения для главных углов', '2.4', `
<p>Запомнить нужно только эти три:</p>
<table style="width:100%;border-collapse:collapse;margin:10px 0;font-size:.94rem">
<tr style="background:var(--sec-acc-soft)"><th style="padding:8px;border:1px solid var(--border)">α</th><th style="padding:8px;border:1px solid var(--border)">$\\pi/6$ ($30°$)</th><th style="padding:8px;border:1px solid var(--border)">$\\pi/4$ ($45°$)</th><th style="padding:8px;border:1px solid var(--border)">$\\pi/3$ ($60°$)</th></tr>
<tr><td style="padding:8px;border:1px solid var(--border);text-align:center"><b>sin α</b></td><td style="padding:8px;border:1px solid var(--border);text-align:center">$\\frac{1}{2}$</td><td style="padding:8px;border:1px solid var(--border);text-align:center">$\\frac{\\sqrt{2}}{2}$</td><td style="padding:8px;border:1px solid var(--border);text-align:center">$\\frac{\\sqrt{3}}{2}$</td></tr>
<tr><td style="padding:8px;border:1px solid var(--border);text-align:center"><b>cos α</b></td><td style="padding:8px;border:1px solid var(--border);text-align:center">$\\frac{\\sqrt{3}}{2}$</td><td style="padding:8px;border:1px solid var(--border);text-align:center">$\\frac{\\sqrt{2}}{2}$</td><td style="padding:8px;border:1px solid var(--border);text-align:center">$\\frac{1}{2}$</td></tr>
</table>
<p>Остальные значения находим через симметрии:</p>
<ul style="padding-left:22px;line-height:1.85">
<li>Через ось $x$: $\\sin(-\\alpha) = -\\sin\\alpha$, $\\cos(-\\alpha) = \\cos\\alpha$.</li>
<li>Через ось $y$: $\\sin(\\pi - \\alpha) = \\sin\\alpha$, $\\cos(\\pi - \\alpha) = -\\cos\\alpha$.</li>
<li>Через начало: $\\sin(\\alpha + \\pi) = -\\sin\\alpha$, $\\cos(\\alpha + \\pi) = -\\cos\\alpha$.</li>
</ul>
<div class="svg-host">${svgTable}</div>`);
/* === ИНТЕРАКТИВ 1: Знак sin/cos === */
html += '<div class="wg" id="p2-iv1">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Знаки sin и cos</div></div>'
+'<div class="wg-help">Введи знак: <b>+</b>, <b>-</b> (или <b>0</b> если значение равно нулю).</div>'
+trainerHTML('p2-iv1', 8, '+ или -')
+'</div>';
/* === ИНТЕРАКТИВ 2: Значение === */
html += '<div class="wg" id="p2-iv2">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Точные значения</div></div>'
+'<div class="wg-help">Введи ответ в виде дроби: <b>1/2</b>, <b>sqrt2/2</b>, <b>sqrt3/2</b>, <b>-1/2</b> и т.п. Знак минус — впереди.</div>'
+trainerHTML('p2-iv2', 6, 'значение')
+'</div>';
/* === ИНТЕРАКТИВ 3: Возможно ли? === */
html += '<div class="wg" id="p2-iv3">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 3</span><div class="wg-title">Может ли так быть?</div></div>'
+'<div class="wg-help">Проверяй: $-1 \\le \\sin\\alpha \\le 1$ и $-1 \\le \\cos\\alpha \\le 1$. И $\\sin^2 + \\cos^2 = 1$.</div>'
+'<div class="score-display"><span>Задача <b id="p2-iv3-i">1</b> / 6</span><span>Очки: <b id="p2-iv3-s">0</b> / 6</span></div>'
+'<div id="p2-iv3-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1rem;text-align:center;margin-bottom:10px"></div>'
+'<div style="display:flex;gap:8px;justify-content:center"><button class="btn primary" id="p2-iv3-y" style="background:#10b981;border-color:#10b981">Да</button><button class="btn primary" id="p2-iv3-n" style="background:#dc2626;border-color:#dc2626">Нет</button></div>'
+'<div class="feedback" id="p2-iv3-fb"></div></div>';
/* === БОСС === */
html += '<h3 style="font-family:Unbounded,sans-serif;font-size:1.05rem;color:var(--pri2);margin:20px 0 12px">Босс §2 — sin и cos</h3>';
html += makeBoss('p2', {
color:'#0891b2',
title:'Босс §2 — sin и cos',
steps:[
{ q:'$\\sin\\dfrac{\\pi}{2} = ?$', verify:(v)=>+v===1, hint:'Точка $P_{\\pi/2} = (0;1)$, ордината $= 1$.' },
{ q:'$\\cos 180° = ?$', verify:(v)=>+v===-1, hint:'Точка $P_\\pi = (-1;0)$, абсцисса $= -1$.' },
{ q:'Точка $P_\\alpha = (3/5;\\,-4/5)$. Найди $\\sin\\alpha$ как дробь (введи -4/5).', verify:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='-4/5'||+v===-0.8;}, hint:'sin = ордината.' },
{ q:'В каких четвертях $\\sin\\alpha > 0$? Введи через запятую: 1,2 или 3,4.', verify:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='1,2'||s==='2,1';}, hint:'Ордината положительна сверху от оси x.' },
{ q:'Может ли $\\sin\\alpha = \\sqrt{3}$? «да» или «нет»', verify:(v)=>String(v).trim().toLowerCase().startsWith('н'), hint:'$\\sqrt{3} \\approx 1{,}73 > 1$, а $\\sin\\alpha \\le 1$.' },
]
});
html += secNav('p1', 'p3') + readButton('p2');
box.innerHTML = html; renderMath(box);
/* IV1: знаки */
makeTrainer({
idPrefix:'p2-iv1',
parser:(v)=>v,
questions:[
{ q:'$\\sin 130°$ — какой знак?', a:(v)=>String(v).trim().startsWith('+'), show:'+ (II четв.)' },
{ q:'$\\cos 258°$ — какой знак?', a:(v)=>String(v).trim().startsWith('-')||String(v).trim()==='', show:' (III четв.)' },
{ q:'$\\sin(-150°)$ — какой знак?', a:(v)=>String(v).trim().startsWith('-')||String(v).trim()==='', show:' (III четв.)' },
{ q:'$\\cos(-340°)$ — какой знак?', a:(v)=>String(v).trim().startsWith('+'), show:'+ (I четв.)' },
{ q:'$\\sin 90°$ — какой знак?', a:(v)=>String(v).trim().startsWith('+'), show:'+ (равно 1)' },
{ q:'$\\cos 180°$ — какой знак?', a:(v)=>String(v).trim().startsWith('-')||String(v).trim()==='', show:' (равно 1)' },
{ q:'$\\sin\\pi$ — какой знак?', a:(v)=>+v===0||String(v).trim()==='0', show:'0' },
{ q:'$\\cos\\dfrac{3\\pi}{2}$ — какой знак?', a:(v)=>+v===0||String(v).trim()==='0', show:'0' },
],
onComplete:(s,n)=>{ if(s===n){addXp(15,'p2-iv1');bumpProgress('p2',25);} else if(s>=5){addXp(8,'p2-iv1');bumpProgress('p2',12);} }
});
/* IV2: точные значения */
makeTrainer({
idPrefix:'p2-iv2',
parser:(v)=>v,
questions:[
{ q:'$\\sin\\dfrac{\\pi}{6} = ?$', a:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='1/2'||+v===0.5;}, show:'$\\frac{1}{2}$' },
{ q:'$\\cos\\dfrac{\\pi}{3} = ?$', a:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='1/2'||+v===0.5;}, show:'$\\frac{1}{2}$' },
{ q:'$\\sin 90° = ?$', a:(v)=>+v===1, show:'1' },
{ q:'$\\cos 180° = ?$', a:(v)=>+v===-1, show:'$-1$' },
{ q:'$\\sin(-60°) = ?$ (введи -sqrt3/2 как ответ)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-sqrt3/2'||s==='-√3/2';}, show:'$-\\frac{\\sqrt{3}}{2}$' },
{ q:'$\\cos 120° = ?$ (введи -1/2)', a:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='-1/2'||+v===-0.5;}, show:'$-\\frac{1}{2}$' },
],
onComplete:(s,n)=>{ if(s===n){addXp(18,'p2-iv2');bumpProgress('p2',30);} else if(s>=3){addXp(9,'p2-iv2');bumpProgress('p2',15);} }
});
/* IV3: возможно ли */
(function(){
const Q=[
{ e:'$\\sin\\alpha = 5/13$ и $\\cos\\alpha = 12/13$ одновременно', ok:true, why:'$(5/13)^2 + (12/13)^2 = 169/169 = 1$ &#10003;' },
{ e:'$\\sin\\alpha = -0{,}3$ и $\\cos\\alpha = 0{,}4$ одновременно', ok:false, why:'$0{,}09 + 0{,}16 = 0{,}25 \\ne 1$.' },
{ e:'$\\sin\\alpha = 0{,}8$ и $\\cos\\alpha = 0{,}6$ одновременно', ok:true, why:'$0{,}64 + 0{,}36 = 1$ &#10003;' },
{ e:'$\\sin\\alpha = \\sqrt{3}$', ok:false, why:'$\\sqrt{3} \\approx 1{,}73 > 1$.' },
{ e:'$\\cos\\alpha = -1$', ok:true, why:'$\\cos\\pi = -1$.' },
{ e:'$\\sin\\alpha = 2$', ok:false, why:'$|\\sin\\alpha| \\le 1$.' },
];
let i=0,score=0;
function show(){
if(i>=Q.length){
document.getElementById('p2-iv3-q').innerHTML='<b>Готово!</b> '+score+' / '+Q.length;
if(score===Q.length){addXp(15,'p2-iv3');bumpProgress('p2',25);} else if(score>=4){addXp(8,'p2-iv3');bumpProgress('p2',12);}
return;
}
document.getElementById('p2-iv3-i').textContent=(i+1);
document.getElementById('p2-iv3-s').textContent=score;
document.getElementById('p2-iv3-q').innerHTML=Q[i].e;
renderMath(document.getElementById('p2-iv3-q'));
document.getElementById('p2-iv3-fb').style.display='none';
}
function ans(yes){
if(i>=Q.length) return;
const fb=document.getElementById('p2-iv3-fb');
if(yes===Q[i].ok){ score++; feedback(fb,true,'&#10003; Верно! '+Q[i].why); }
else feedback(fb,false,'&#10007; '+(Q[i].ok?'Да: ':'Нет: ')+Q[i].why);
document.getElementById('p2-iv3-s').textContent=score;
i++; setTimeout(show,1400);
}
document.getElementById('p2-iv3-y').addEventListener('click',()=>ans(true));
document.getElementById('p2-iv3-n').addEventListener('click',()=>ans(false));
show();
})();
wireReadBtn('p2');
}
/* ============================================================
§ 3 — Тангенс и котангенс произвольного угла
============================================================ */
function buildP3(){
const box = document.getElementById('p3-body');
const A = window.ALG10;
let html = '';
/* === SVG 1: ось тангенсов === */
let svgTg = '';
if(A){
const c = A.tri.canvas({id:'p3-tg', W:340, H:340, R:120});
const angle = 30 * Math.PI / 180;
let s = c.open
+ c.axes({xExt:c.R+40})
+ c.circle({width:2})
+ c.tgAxis()
+ c.radius(angle, {color:'#dc2626'})
+ c.point(angle, {label:'P_α', color:'#dc2626', labelOffset:14, fontSize:11})
+ c.tgValue(angle, {color:'#16a34a'})
+ c.close;
svgTg = s;
}
/* === SVG 2: ось котангенсов === */
let svgCtg = '';
if(A){
const c = A.tri.canvas({id:'p3-ctg', W:340, H:340, R:120});
const angle = 60 * Math.PI / 180;
let s = c.open
+ c.axes({yExt:c.R+40})
+ c.circle({width:2})
+ c.ctgAxis()
+ c.radius(angle, {color:'#dc2626'})
+ c.point(angle, {label:'P_α', color:'#dc2626', labelOffset:14, fontSize:11})
+ c.ctgValue(angle, {color:'#7c3aed'})
+ c.close;
svgCtg = s;
}
html += makeCard('theory', 'Определения', '3.1', `
<p style="background:var(--sec-acc-soft);padding:10px 14px;border-radius:8px"><b>Определение.</b> Тангенс и котангенс угла $\\alpha$:</p>
<p style="text-align:center;font-size:1.1rem;margin:10px 0">$\\tg\\alpha = \\dfrac{\\sin\\alpha}{\\cos\\alpha}, \\quad \\ctg\\alpha = \\dfrac{\\cos\\alpha}{\\sin\\alpha}$</p>
<p><b>ОДЗ:</b></p>
<ul style="padding-left:22px;line-height:1.85">
<li>$\\tg\\alpha$ существует, если $\\cos\\alpha \\ne 0$, то есть $\\alpha \\ne \\dfrac{\\pi}{2} + \\pi n$, $n \\in \\mathbb{Z}$.</li>
<li>$\\ctg\\alpha$ существует, если $\\sin\\alpha \\ne 0$, то есть $\\alpha \\ne \\pi n$, $n \\in \\mathbb{Z}$.</li>
</ul>
<p>Между ними простая связь: $\\tg\\alpha \\cdot \\ctg\\alpha = 1$ (если оба определены).</p>`);
html += makeCard('rule', 'Ось тангенсов', '3.2', `
<p>Геометрически tg α можно «увидеть»: проведём <b>касательную к окружности в точке $P_0(1;\\,0)$</b> — это прямая $x = 1$. Назовём её <b>осью тангенсов</b>.</p>
<p>Прямая $OP_\\alpha$ (или её продолжение) пересекает ось тангенсов в точке $A_\\alpha$. Координата $y$ этой точки и есть $\\tg\\alpha$.</p>
<div class="svg-host">${svgTg}</div>
<p>Если $P_\\alpha$ в I или IV четверти — $A_\\alpha$ строится через продолжение радиуса прямо; если во II или III — через продолжение радиуса в противоположную сторону.</p>`);
html += makeCard('rule', 'Ось котангенсов', '3.3', `
<p>Аналогично: касательная в точке $P_{\\pi/2}(0;\\,1)$ — это прямая $y = 1$. На ней «живёт» $\\ctg\\alpha$.</p>
<div class="svg-host">${svgCtg}</div>
<p>Координата $x$ точки пересечения — это $\\ctg\\alpha$.</p>`);
html += makeCard('algo', 'Знаки tg и ctg по четвертям', '3.4', `
<p>Так как $\\tg\\alpha = \\dfrac{\\sin\\alpha}{\\cos\\alpha}$, знак — произведение знаков sin и cos:</p>
<table style="width:100%;border-collapse:collapse;margin:10px 0;font-size:.94rem">
<tr style="background:var(--sec-acc-soft)"><th style="padding:8px;border:1px solid var(--border)">Четверть</th><th style="padding:8px;border:1px solid var(--border)">I</th><th style="padding:8px;border:1px solid var(--border)">II</th><th style="padding:8px;border:1px solid var(--border)">III</th><th style="padding:8px;border:1px solid var(--border)">IV</th></tr>
<tr><td style="padding:8px;border:1px solid var(--border);text-align:center"><b>sin</b></td><td style="padding:8px;border:1px solid var(--border);text-align:center;color:#065f46">+</td><td style="padding:8px;border:1px solid var(--border);text-align:center;color:#065f46">+</td><td style="padding:8px;border:1px solid var(--border);text-align:center;color:#dc2626"></td><td style="padding:8px;border:1px solid var(--border);text-align:center;color:#dc2626"></td></tr>
<tr><td style="padding:8px;border:1px solid var(--border);text-align:center"><b>cos</b></td><td style="padding:8px;border:1px solid var(--border);text-align:center;color:#065f46">+</td><td style="padding:8px;border:1px solid var(--border);text-align:center;color:#dc2626"></td><td style="padding:8px;border:1px solid var(--border);text-align:center;color:#dc2626"></td><td style="padding:8px;border:1px solid var(--border);text-align:center;color:#065f46">+</td></tr>
<tr style="background:var(--sec-acc-soft)"><td style="padding:8px;border:1px solid var(--border);text-align:center"><b>tg, ctg</b></td><td style="padding:8px;border:1px solid var(--border);text-align:center;color:#065f46">+</td><td style="padding:8px;border:1px solid var(--border);text-align:center;color:#dc2626"></td><td style="padding:8px;border:1px solid var(--border);text-align:center;color:#065f46">+</td><td style="padding:8px;border:1px solid var(--border);text-align:center;color:#dc2626"></td></tr>
</table>
<p><b>Запоминалка:</b> tg/ctg положительны в I и III четвертях, отрицательны во II и IV.</p>`);
/* === ИНТЕРАКТИВ 1: Существует ли? === */
html += '<div class="wg" id="p3-iv1">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Существует ли?</div></div>'
+'<div class="wg-help">tg α не существует, если cos α = 0 (то есть α = π/2 + πn). ctg α не существует, если sin α = 0 (α = πn).</div>'
+'<div class="score-display"><span>Задача <b id="p3-iv1-i">1</b> / 6</span><span>Очки: <b id="p3-iv1-s">0</b> / 6</span></div>'
+'<div id="p3-iv1-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1rem;text-align:center;margin-bottom:10px"></div>'
+'<div style="display:flex;gap:8px;justify-content:center"><button class="btn primary" id="p3-iv1-y" style="background:#10b981;border-color:#10b981">Существует</button><button class="btn primary" id="p3-iv1-n" style="background:#dc2626;border-color:#dc2626">Не существует</button></div>'
+'<div class="feedback" id="p3-iv1-fb"></div></div>';
/* === ИНТЕРАКТИВ 2: Знак tg/ctg === */
html += '<div class="wg" id="p3-iv2">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Знак tg / ctg</div></div>'
+'<div class="wg-help">Введи знак: <b>+</b> или <b>-</b>.</div>'
+trainerHTML('p3-iv2', 6, '+ или -')
+'</div>';
/* === БОСС === */
html += '<h3 style="font-family:Unbounded,sans-serif;font-size:1.05rem;color:var(--pri2);margin:20px 0 12px">Босс §3 — tg и ctg</h3>';
html += makeBoss('p3', {
color:'#16a34a',
title:'Босс §3 — tg и ctg',
steps:[
{ q:'$\\tg\\pi = ?$', verify:(v)=>+v===0, hint:'$\\sin\\pi = 0$, $\\cos\\pi = -1$, $0/(-1) = 0$.' },
{ q:'Существует ли $\\tg\\dfrac{\\pi}{2}$? «да» или «нет»', verify:(v)=>String(v).trim().toLowerCase().startsWith('н'), hint:'$\\cos\\frac{\\pi}{2} = 0$, делить нельзя.' },
{ q:'$\\ctg\\dfrac{\\pi}{4} = ?$', verify:(v)=>+v===1, hint:'$\\cos\\frac{\\pi}{4} / \\sin\\frac{\\pi}{4} = 1$.' },
{ q:'Точка $P_\\alpha = (5/13;\\,-12/13)$. Найди $\\tg\\alpha$ (введи в виде десятичной дроби, например -2.4).', verify:(v)=>Math.abs(+v - (-12/5)) < 0.05, hint:'$\\tg\\alpha = -12/5 = -2{,}4$.' },
{ q:'В каких четвертях $\\tg\\alpha > 0$? Введи: 1,2 / 1,3 / 2,4 / 2,3.', verify:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='1,3'||s==='3,1';}, hint:'sin и cos одного знака — I и III.' },
]
});
html += secNav('p2', 'p4') + readButton('p3');
box.innerHTML = html; renderMath(box);
/* IV1: существует ли */
(function(){
const Q=[
{ e:'$\\tg 0$', ok:true, why:'$\\sin 0 / \\cos 0 = 0/1 = 0$.' },
{ e:'$\\tg \\dfrac{\\pi}{2}$', ok:false, why:'$\\cos\\frac{\\pi}{2} = 0$.' },
{ e:'$\\ctg 0$', ok:false, why:'$\\sin 0 = 0$.' },
{ e:'$\\ctg 2\\pi$', ok:false, why:'$\\sin 2\\pi = 0$.' },
{ e:'$\\tg\\left(-\\dfrac{5\\pi}{2}\\right)$', ok:false, why:'$-5\\pi/2 = -2\\pi - \\pi/2$, эквивалентен $-\\pi/2$, $\\cos = 0$.' },
{ e:'$\\ctg(-3\\pi)$', ok:false, why:'$-3\\pi = -2\\pi - \\pi$, эквивалентен $\\pi$, $\\sin\\pi = 0$.' },
];
let i=0,score=0;
function show(){
if(i>=Q.length){ document.getElementById('p3-iv1-q').innerHTML='<b>Готово!</b> '+score+' / '+Q.length; if(score===Q.length){addXp(15,'p3-iv1');bumpProgress('p3',25);} else if(score>=4){addXp(8,'p3-iv1');bumpProgress('p3',12);} return; }
document.getElementById('p3-iv1-i').textContent=(i+1);
document.getElementById('p3-iv1-s').textContent=score;
document.getElementById('p3-iv1-q').innerHTML=Q[i].e;
renderMath(document.getElementById('p3-iv1-q'));
document.getElementById('p3-iv1-fb').style.display='none';
}
function ans(yes){
if(i>=Q.length) return;
const fb=document.getElementById('p3-iv1-fb');
if(yes===Q[i].ok){ score++; feedback(fb,true,'&#10003; Верно! '+Q[i].why); }
else feedback(fb,false,'&#10007; '+(Q[i].ok?'Существует: ':'Не существует: ')+Q[i].why);
document.getElementById('p3-iv1-s').textContent=score;
i++; setTimeout(show,1500);
}
document.getElementById('p3-iv1-y').addEventListener('click',()=>ans(true));
document.getElementById('p3-iv1-n').addEventListener('click',()=>ans(false));
show();
})();
/* IV2: знаки tg/ctg */
makeTrainer({
idPrefix:'p3-iv2',
parser:(v)=>v,
questions:[
{ q:'$\\tg 118°$ — какой знак?', a:(v)=>String(v).trim().startsWith('-')||String(v).trim()==='', show:' (II четв.)' },
{ q:'$\\ctg 200°$ — какой знак?', a:(v)=>String(v).trim().startsWith('+'), show:'+ (III четв.)' },
{ q:'$\\tg(-50°)$ — какой знак?', a:(v)=>String(v).trim().startsWith('-')||String(v).trim()==='', show:' (IV четв.)' },
{ q:'$\\ctg 330°$ — какой знак?', a:(v)=>String(v).trim().startsWith('-')||String(v).trim()==='', show:' (IV четв.)' },
{ q:'$\\tg 240°$ — какой знак?', a:(v)=>String(v).trim().startsWith('+'), show:'+ (III четв.)' },
{ q:'$\\ctg(-100°)$ — какой знак?', a:(v)=>String(v).trim().startsWith('+'), show:'+ (III четв., $-100°+360° = 260°$)' },
],
onComplete:(s,n)=>{ if(s===n){addXp(15,'p3-iv2');bumpProgress('p3',25);} else if(s>=4){addXp(8,'p3-iv2');bumpProgress('p3',12);} }
});
wireReadBtn('p3');
}
/* ============================================================
§ 4 — Тригонометрические тождества
============================================================ */
function buildP4(){
const box = document.getElementById('p4-body');
const A = window.ALG10;
let html = '';
/* === SVG 1: теорема Пифагора → основное тождество === */
let svgMain = '';
if(A){
const c = A.tri.canvas({id:'p4-main', W:320, H:320, R:120});
const angle = 50 * Math.PI / 180;
let s = c.open
+ c.axes()
+ c.circle({width:2})
+ c.radius(angle, {color:'#dc2626'})
+ c.sinSegment(angle, {color:'#dc2626', dash:'0', width:2.5})
+ c.cosSegment(angle, {color:'#2563eb', dash:'0', width:2.5})
+ c.point(angle, {color:'#dc2626', label:'P_α(x; y)', labelOffset:18, fontSize:10})
/* Подпись внизу */
+ '<text x="160" y="305" text-anchor="middle" font-size="12" font-family="JetBrains Mono,monospace" font-weight="700" fill="#0d9488">x² + y² = 1 ⇒ cos²α + sin²α = 1</text>'
+ c.close;
svgMain = s;
}
html += makeCard('rule', 'Основное тригонометрическое тождество', '4.1', `
<p style="background:var(--sec-acc-soft);padding:10px 14px;border-radius:8px"><b>Теорема.</b> Для любого угла $\\alpha$:</p>
<p style="text-align:center;font-size:1.2rem;margin:10px 0">$\\sin^2\\alpha + \\cos^2\\alpha = 1$</p>
<div class="svg-host">${svgMain}</div>
<p><b>Доказательство.</b> Точка $P_\\alpha = (\\cos\\alpha;\\,\\sin\\alpha)$ лежит на единичной окружности, заданной уравнением $x^2 + y^2 = 1$. Подставляем $x = \\cos\\alpha$, $y = \\sin\\alpha$ — получаем тождество. ■</p>`);
html += makeCard('rule', 'Производные тождества', '4.2', `
<p>Из основного тождества выводим ещё три:</p>
<p style="background:var(--sec-acc-soft);padding:10px 14px;border-radius:8px;text-align:center">$\\tg\\alpha \\cdot \\ctg\\alpha = 1$ (если оба определены)</p>
<p style="background:var(--sec-acc-soft);padding:10px 14px;border-radius:8px;text-align:center">$1 + \\tg^2\\alpha = \\dfrac{1}{\\cos^2\\alpha}$ (при $\\cos\\alpha \\ne 0$)</p>
<p style="background:var(--sec-acc-soft);padding:10px 14px;border-radius:8px;text-align:center">$1 + \\ctg^2\\alpha = \\dfrac{1}{\\sin^2\\alpha}$ (при $\\sin\\alpha \\ne 0$)</p>
<details class="spoiler"><summary>Доказательство для $1 + \\tg^2 = 1/\\cos^2$</summary>
<div class="spoiler-body">
<p>Разделим основное тождество $\\sin^2\\alpha + \\cos^2\\alpha = 1$ на $\\cos^2\\alpha$:</p>
<p>$\\dfrac{\\sin^2\\alpha}{\\cos^2\\alpha} + 1 = \\dfrac{1}{\\cos^2\\alpha}$ ⇒ $\\tg^2\\alpha + 1 = \\dfrac{1}{\\cos^2\\alpha}$. ■</p>
</div></details>`);
html += makeCard('algo', 'Алгоритм «знаю одну → найду все»', '4.3', `
<p>Если известно одно тригонометрическое значение угла $\\alpha$ и четверть, в которой он лежит, найди остальные три.</p>
<ol style="padding-left:22px;line-height:1.95">
<li>Из основного тождества вырази недостающее (sin или cos).</li>
<li>Знак выбери по четверти.</li>
<li>$\\tg\\alpha = \\dfrac{\\sin\\alpha}{\\cos\\alpha}$.</li>
<li>$\\ctg\\alpha = \\dfrac{1}{\\tg\\alpha}$ (или $\\dfrac{\\cos\\alpha}{\\sin\\alpha}$).</li>
</ol>`);
html += makeCard('example', 'Пример', '4.4', `
<p><b>Задача.</b> $\\sin\\alpha = \\dfrac{3}{5}$, $\\alpha \\in \\left(\\dfrac{\\pi}{2};\\,\\pi\\right)$. Найди $\\cos\\alpha$, $\\tg\\alpha$, $\\ctg\\alpha$.</p>
<p><b>Решение.</b></p>
<ol style="padding-left:22px;line-height:1.95">
<li>$\\cos^2\\alpha = 1 - \\sin^2\\alpha = 1 - \\dfrac{9}{25} = \\dfrac{16}{25}$ ⇒ $\\cos\\alpha = \\pm \\dfrac{4}{5}$.</li>
<li>$\\alpha \\in (\\pi/2;\\pi)$ — II четверть, $\\cos\\alpha < 0$, значит $\\cos\\alpha = -\\dfrac{4}{5}$.</li>
<li>$\\tg\\alpha = \\dfrac{3/5}{-4/5} = -\\dfrac{3}{4}$.</li>
<li>$\\ctg\\alpha = -\\dfrac{4}{3}$.</li>
</ol>`);
/* === ИНТЕРАКТИВ 1: Найди недостающее === */
html += '<div class="wg" id="p4-iv1">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Найди cos α</div></div>'
+'<div class="wg-help">Известны sin α и четверть. Найди cos α как дробь или с десятичной точкой.</div>'
+trainerHTML('p4-iv1', 5, 'значение')
+'</div>';
/* === ИНТЕРАКТИВ 2: Упрости === */
html += '<div class="wg" id="p4-iv2">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Упрости выражение</div></div>'
+'<div class="wg-help">Используй $\\sin^2 + \\cos^2 = 1$ и $\\tg \\cdot \\ctg = 1$. Введи итоговое значение или выражение.</div>'
+trainerHTML('p4-iv2', 5, 'итог')
+'</div>';
/* === ИНТЕРАКТИВ 3: Найди tg, ctg === */
html += '<div class="wg" id="p4-iv3">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 3</span><div class="wg-title">Найди tg α или ctg α</div></div>'
+'<div class="wg-help">$\\tg\\alpha = \\sin\\alpha / \\cos\\alpha$, $\\ctg\\alpha = 1 / \\tg\\alpha$.</div>'
+trainerHTML('p4-iv3', 5, 'значение')
+'</div>';
/* === БОСС === */
html += '<h3 style="font-family:Unbounded,sans-serif;font-size:1.05rem;color:var(--pri2);margin:20px 0 12px">Босс §4 — Тождества</h3>';
html += makeBoss('p4', {
color:'#7c3aed',
title:'Босс §4 — Тождества',
steps:[
{ q:'Чему равно $\\sin^2 30° + \\cos^2 30°$?', verify:(v)=>+v===1, hint:'Основное тождество, всегда равно 1.' },
{ q:'$\\sin\\alpha = 5/13$ и $\\cos\\alpha = 12/13$. Возможно? «да»/«нет»', verify:(v)=>String(v).trim().toLowerCase().startsWith('д'), hint:'$25/169 + 144/169 = 1$ &#10003;.' },
{ q:'$\\sin\\alpha = -3/5$, $\\alpha \\in (\\pi; 3\\pi/2)$. Найди $\\cos\\alpha$ как дробь (введи -4/5).', verify:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='-4/5'||+v===-0.8;}, hint:'$\\cos^2 = 16/25$, в III четверти $\\cos < 0$.' },
{ q:'Если $\\tg\\alpha = 0{,}75$, то $\\ctg\\alpha = ?$ (введи в виде десятичной дроби).', verify:(v)=>Math.abs(+v - 4/3) < 0.01, hint:'$\\ctg = 1/\\tg = 1/0{,}75 = 4/3 \\approx 1{,}33$.' },
{ q:'Упрости: $(1 + \\tg^2\\alpha) \\cdot \\cos^2\\alpha$. Чему равно?', verify:(v)=>+v===1, hint:'$1 + \\tg^2 = 1/\\cos^2$, значит произведение $= 1$.' },
]
});
html += secNav('p3', 'p5') + readButton('p4');
box.innerHTML = html; renderMath(box);
/* IV1: Найди cos α */
makeTrainer({
idPrefix:'p4-iv1',
parser:(v)=>v,
questions:[
{ q:'$\\sin\\alpha = 3/5$, $\\alpha \\in (0;\\pi/2)$. Найди $\\cos\\alpha$ (введи 4/5 или 0.8).', a:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='4/5'||+v===0.8;}, show:'$4/5 = 0{,}8$' },
{ q:'$\\sin\\alpha = 3/5$, $\\alpha \\in (\\pi/2;\\pi)$. Найди $\\cos\\alpha$.', a:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='-4/5'||+v===-0.8;}, show:'$-4/5$' },
{ q:'$\\sin\\alpha = -5/13$, $\\alpha \\in (3\\pi/2;\\,2\\pi)$. Найди $\\cos\\alpha$.', a:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='12/13'||Math.abs(+v - 12/13)<0.01;}, show:'$12/13$' },
{ q:'$\\cos\\alpha = -4/5$, $\\alpha \\in (\\pi;3\\pi/2)$. Найди $\\sin\\alpha$.', a:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='-3/5'||+v===-0.6;}, show:'$-3/5$' },
{ q:'$\\sin\\alpha = 0{,}8$, $\\alpha$ во II четв. Найди $\\cos\\alpha$.', a:(v)=>Math.abs(+v - (-0.6))<0.01, show:'$-0{,}6$' },
],
onComplete:(s,n)=>{ if(s===n){addXp(18,'p4-iv1');bumpProgress('p4',30);} else if(s>=3){addXp(9,'p4-iv1');bumpProgress('p4',15);} }
});
/* IV2: Упрости */
makeTrainer({
idPrefix:'p4-iv2',
parser:(v)=>v,
questions:[
{ q:'$3 - \\sin^2\\alpha - \\cos^2\\alpha = ?$', a:(v)=>+v===2, show:'2' },
{ q:'$\\cos^2\\alpha + \\sin^2\\alpha - 7 = ?$', a:(v)=>+v===-6, show:'$-6$' },
{ q:'$\\sin\\alpha \\cdot \\ctg\\alpha + \\cos\\alpha = ?$ (умножь на 1, выр-же $= 2\\cos\\alpha$, введи коэф-т)', a:(v)=>+v===2, show:'$2\\cos\\alpha$, коэф 2' },
{ q:'$(\\tg\\alpha + \\ctg\\alpha)^2 - (\\tg\\alpha - \\ctg\\alpha)^2 = ?$', a:(v)=>+v===4, show:'4' },
{ q:'$(1+\\ctg^2\\alpha)\\sin^2\\alpha = ?$', a:(v)=>+v===1, show:'1' },
],
onComplete:(s,n)=>{ if(s===n){addXp(18,'p4-iv2');bumpProgress('p4',30);} else if(s>=3){addXp(9,'p4-iv2');bumpProgress('p4',14);} }
});
/* IV3: tg, ctg */
makeTrainer({
idPrefix:'p4-iv3',
parser:(v)=>v,
questions:[
{ q:'$\\sin\\alpha = 3/5$, $\\cos\\alpha = -4/5$. Найди $\\tg\\alpha$ (как дробь).', a:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='-3/4'||+v===-0.75;}, show:'$-3/4$' },
{ q:'$\\tg\\alpha = 2$. Найди $\\ctg\\alpha$.', a:(v)=>+v===0.5, show:'$0{,}5$' },
{ q:'$\\sin\\alpha = 1/2$, $\\cos\\alpha = -\\sqrt{3}/2$. Найди $\\ctg\\alpha$ (введи как -sqrt3 или -1.73).', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-sqrt3'||s==='-√3'||Math.abs(+v - (-Math.sqrt(3)))<0.05;}, show:'$-\\sqrt{3}$' },
{ q:'$\\tg\\alpha = 5$. Найди $\\dfrac{3\\sin\\alpha - \\cos\\alpha}{\\sin\\alpha + 2\\cos\\alpha}$.', a:(v)=>+v===2, show:'2 (разделить числитель и знаменатель на $\\cos\\alpha$)' },
{ q:'$\\ctg\\alpha = 1/2$. Найди $\\tg\\alpha$.', a:(v)=>+v===2, show:'2' },
],
onComplete:(s,n)=>{ if(s===n){addXp(18,'p4-iv3');bumpProgress('p4',30);} else if(s>=3){addXp(9,'p4-iv3');bumpProgress('p4',14);} }
});
wireReadBtn('p4');
}
/* ============================================================
§ 5 — Функции y = sin x и y = cos x. Свойства и графики
============================================================ */
function buildP5(){
const box = document.getElementById('p5-body');
const A = window.ALG10;
let html = '';
/* === SVG 1: график y = sin x на [-2π; 2π] === */
let svgSin = '';
if(A){
const f = A.func.canvas({id:'p5-sin', W:640, H:240, xRange:[-2*Math.PI, 2*Math.PI], yRange:[-1.6, 1.6], bg:'#fff'});
let s = f.open
+ f.grid({xStep:Math.PI/2, yStep:0.5, color:'#f1f5f9'})
+ f.axes({color:'#475569',
xTicks:[
{val:-2*Math.PI, label:'-2π'},{val:-3*Math.PI/2, label:'-3π/2'},
{val:-Math.PI, label:'-π'},{val:-Math.PI/2, label:'-π/2'},
{val:Math.PI/2, label:'π/2'},{val:Math.PI, label:'π'},
{val:3*Math.PI/2, label:'3π/2'},{val:2*Math.PI, label:'2π'}
],
yTicks:[{val:-1, label:'-1'}, {val:1, label:'1'}]
})
/* Полупрозрачные горизонтальные полоски области значений */
+ '<line x1="0" y1="'+f.pxY(1)+'" x2="'+f.W+'" y2="'+f.pxY(1)+'" stroke="#cbd5e1" stroke-width="1" stroke-dasharray="3 3"/>'
+ '<line x1="0" y1="'+f.pxY(-1)+'" x2="'+f.W+'" y2="'+f.pxY(-1)+'" stroke="#cbd5e1" stroke-width="1" stroke-dasharray="3 3"/>'
+ f.plot(x => Math.sin(x), {color:'#0d9488', width:2.8})
/* Точки максимума и минимума */
+ f.pointXY(Math.PI/2, 1, {color:'#dc2626', r:3.5, label:'max', dx:6, dy:-8, fontSize:10})
+ f.pointXY(-Math.PI/2, -1, {color:'#dc2626', r:3.5, label:'min', dx:6, dy:14, fontSize:10})
+ f.pointXY(3*Math.PI/2, -1, {color:'#dc2626', r:3.5})
+ f.pointXY(-3*Math.PI/2, 1, {color:'#dc2626', r:3.5})
+ f.close;
svgSin = s;
}
/* === SVG 2: график y = cos x === */
let svgCos = '';
if(A){
const f = A.func.canvas({id:'p5-cos', W:640, H:240, xRange:[-2*Math.PI, 2*Math.PI], yRange:[-1.6, 1.6], bg:'#fff'});
let s = f.open
+ f.grid({xStep:Math.PI/2, yStep:0.5, color:'#f1f5f9'})
+ f.axes({color:'#475569',
xTicks:[
{val:-2*Math.PI, label:'-2π'},{val:-Math.PI, label:'-π'},
{val:Math.PI, label:'π'},{val:2*Math.PI, label:'2π'}
],
yTicks:[{val:-1, label:'-1'}, {val:1, label:'1'}]
})
+ '<line x1="0" y1="'+f.pxY(1)+'" x2="'+f.W+'" y2="'+f.pxY(1)+'" stroke="#cbd5e1" stroke-width="1" stroke-dasharray="3 3"/>'
+ '<line x1="0" y1="'+f.pxY(-1)+'" x2="'+f.W+'" y2="'+f.pxY(-1)+'" stroke="#cbd5e1" stroke-width="1" stroke-dasharray="3 3"/>'
+ f.plot(x => Math.cos(x), {color:'#0891b2', width:2.8})
+ f.pointXY(0, 1, {color:'#dc2626', r:3.5, label:'max', dx:6, dy:-8, fontSize:10})
+ f.pointXY(Math.PI, -1, {color:'#dc2626', r:3.5, label:'min', dx:6, dy:14, fontSize:10})
+ f.pointXY(-Math.PI, -1, {color:'#dc2626', r:3.5})
+ f.pointXY(2*Math.PI, 1, {color:'#dc2626', r:3.5})
+ f.pointXY(-2*Math.PI, 1, {color:'#dc2626', r:3.5})
+ f.close;
svgCos = s;
}
/* === SVG 3: совмещённые sin и cos === */
let svgBoth = '';
if(A){
const f = A.func.canvas({id:'p5-both', W:640, H:240, xRange:[-2*Math.PI, 2*Math.PI], yRange:[-1.6, 1.6], bg:'#fff'});
let s = f.open
+ f.grid({xStep:Math.PI/2, yStep:0.5, color:'#f1f5f9'})
+ f.axes({color:'#475569',
xTicks:[{val:-Math.PI, label:'-π'},{val:Math.PI, label:'π'},{val:2*Math.PI, label:'2π'}],
yTicks:[{val:-1, label:'-1'}, {val:1, label:'1'}]
})
+ f.plot(x => Math.sin(x), {color:'#0d9488', width:2.5})
+ f.plot(x => Math.cos(x), {color:'#0891b2', width:2.5, dash:'5 4'})
/* Точка пересечения при x = π/4: sin = cos = √2/2 */
+ f.pointXY(Math.PI/4, Math.sqrt(2)/2, {color:'#dc2626', r:4, label:'π/4', dx:6, dy:-6, fontSize:10})
/* Легенда */
+ '<rect x="'+(f.W-130)+'" y="10" width="120" height="46" rx="6" fill="#fff" stroke="#cbd5e1" stroke-width="1"/>'
+ '<line x1="'+(f.W-120)+'" y1="25" x2="'+(f.W-100)+'" y2="25" stroke="#0d9488" stroke-width="2.5"/>'
+ '<text x="'+(f.W-94)+'" y="29" font-size="12" font-family="JetBrains Mono,monospace" fill="#0d9488" font-weight="700">sin x</text>'
+ '<line x1="'+(f.W-120)+'" y1="45" x2="'+(f.W-100)+'" y2="45" stroke="#0891b2" stroke-width="2.5" stroke-dasharray="5 4"/>'
+ '<text x="'+(f.W-94)+'" y="49" font-size="12" font-family="JetBrains Mono,monospace" fill="#0891b2" font-weight="700">cos x</text>'
+ f.close;
svgBoth = s;
}
html += makeCard('rule', 'Свойства функции y = sin x', '5.1', `
<p>На каждом числе $x$ значение $\\sin x$ — это ордината точки $P_x$ единичной окружности.</p>
<table style="width:100%;border-collapse:collapse;margin:8px 0;font-size:.92rem">
<tr style="background:var(--sec-acc-soft)"><th style="padding:6px;border:1px solid var(--border);text-align:left">Свойство</th><th style="padding:6px;border:1px solid var(--border);text-align:left">Значение</th></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>Область определения</b></td><td style="padding:6px;border:1px solid var(--border)">$D(\\sin) = \\mathbb{R}$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>Область значений</b></td><td style="padding:6px;border:1px solid var(--border)">$E(\\sin) = [-1;\\,1]$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>Период</b></td><td style="padding:6px;border:1px solid var(--border)">$T = 2\\pi$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>Чётность</b></td><td style="padding:6px;border:1px solid var(--border)">Нечётная: $\\sin(-x) = -\\sin x$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>Нули</b></td><td style="padding:6px;border:1px solid var(--border)">$x = \\pi n$, $n \\in \\mathbb{Z}$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>Возрастает</b></td><td style="padding:6px;border:1px solid var(--border)">на $\\left[-\\frac{\\pi}{2} + 2\\pi n;\\,\\frac{\\pi}{2} + 2\\pi n\\right]$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>max</b></td><td style="padding:6px;border:1px solid var(--border)">$1$ при $x = \\frac{\\pi}{2} + 2\\pi n$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>min</b></td><td style="padding:6px;border:1px solid var(--border)">$-1$ при $x = -\\frac{\\pi}{2} + 2\\pi n$</td></tr>
</table>`);
html += makeCard('rule', 'График y = sin x', '5.2', `
<p>График — <b>синусоида</b>. Повторяется каждые $2\\pi$.</p>
<div class="svg-host">${svgSin}</div>
<p>Красные точки — экстремумы. Кривая всегда лежит между $y = -1$ и $y = 1$.</p>`);
html += makeCard('rule', 'Свойства y = cos x', '5.3', `
<p>Свойства аналогичны синусу, но с двумя ключевыми отличиями:</p>
<table style="width:100%;border-collapse:collapse;margin:8px 0;font-size:.92rem">
<tr style="background:var(--sec-acc-soft)"><th style="padding:6px;border:1px solid var(--border);text-align:left">Свойство</th><th style="padding:6px;border:1px solid var(--border);text-align:left">Значение</th></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>Область определения</b></td><td style="padding:6px;border:1px solid var(--border)">$D(\\cos) = \\mathbb{R}$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>Область значений</b></td><td style="padding:6px;border:1px solid var(--border)">$E(\\cos) = [-1;\\,1]$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>Период</b></td><td style="padding:6px;border:1px solid var(--border)">$T = 2\\pi$</td></tr>
<tr style="background:var(--warn-bg)"><td style="padding:6px;border:1px solid var(--border)"><b>Чётность</b></td><td style="padding:6px;border:1px solid var(--border)"><b>Чётная: $\\cos(-x) = \\cos x$</b></td></tr>
<tr style="background:var(--warn-bg)"><td style="padding:6px;border:1px solid var(--border)"><b>Нули</b></td><td style="padding:6px;border:1px solid var(--border)">$x = \\frac{\\pi}{2} + \\pi n$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>max</b></td><td style="padding:6px;border:1px solid var(--border)">$1$ при $x = 2\\pi n$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>min</b></td><td style="padding:6px;border:1px solid var(--border)">$-1$ при $x = \\pi + 2\\pi n$</td></tr>
</table>`);
html += makeCard('rule', 'График y = cos x', '5.4', `
<p>График $y = \\cos x$ — та же синусоида, но <b>сдвинутая на $\\dfrac{\\pi}{2}$ влево</b>.</p>
<div class="svg-host">${svgCos}</div>
<p>Это значит: $\\cos x = \\sin\\left(x + \\dfrac{\\pi}{2}\\right)$.</p>
<div class="svg-host">${svgBoth}</div>
<p>На совмещённом графике видно: где у $\\sin x$ нули — у $\\cos x$ экстремумы, и наоборот.</p>`);
html += makeCard('algo', 'Преобразования графиков', '5.5', `
<p>Общий вид: $y = A \\sin(\\omega x + \\varphi) + b$, где:</p>
<ul style="padding-left:22px;line-height:1.85">
<li><b>$A$</b> — <b>амплитуда</b>: растяжение по оси $y$. $E = [-|A| + b;\\,|A| + b]$.</li>
<li><b>$\\omega$</b> — <b>частота</b>: новый период $T = \\dfrac{2\\pi}{|\\omega|}$.</li>
<li><b>$\\varphi$</b> — <b>начальная фаза</b>: сдвиг по оси $x$ на $-\\dfrac{\\varphi}{\\omega}$.</li>
<li><b>$b$</b> — сдвиг по оси $y$ (вверх или вниз).</li>
</ul>
<p>Поэкспериментируй с параметрами на следующем интерактиве!</p>`);
/* === ИНТЕРАКТИВ 1: Slider-эксперимент === */
html += '<div class="wg" id="p5-iv1">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">y = A · sin(ωx + φ) + b — крути параметры</div></div>'
+'<div class="wg-help">Двигай ползунки и смотри, как меняется график синусоиды.</div>'
+'<div class="slider-ctrl"><label>A (амплитуда):</label><input type="range" id="p5-A" min="-3" max="3" step="0.1" value="1"><span class="val" id="p5-Av">1.0</span></div>'
+'<div class="slider-ctrl"><label>ω (частота):</label><input type="range" id="p5-w" min="0.25" max="3" step="0.05" value="1"><span class="val" id="p5-wv">1.00</span></div>'
+'<div class="slider-ctrl"><label>φ (фаза):</label><input type="range" id="p5-ph" min="-3.14" max="3.14" step="0.05" value="0"><span class="val" id="p5-phv">0.00</span></div>'
+'<div class="slider-ctrl"><label>b (сдвиг):</label><input type="range" id="p5-b" min="-2" max="2" step="0.1" value="0"><span class="val" id="p5-bv">0.0</span></div>'
+'<div id="p5-formula" style="text-align:center;font-family:JetBrains Mono,monospace;font-size:1rem;color:var(--pri2);margin:10px 0;padding:8px;background:var(--sec-acc-soft);border-radius:8px"></div>'
+'<div class="svg-host" id="p5-iv1-svg"></div>'
+'</div>';
/* === ИНТЕРАКТИВ 2: Найди свойство === */
html += '<div class="wg" id="p5-iv2">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Свойства функций sin x и cos x</div></div>'
+'<div class="wg-help">Ответы — числа (период в виде «2pi», «pi/2» и т.д.), названия («чётная»/«нечётная»), или градусы.</div>'
+trainerHTML('p5-iv2', 7, 'ответ')
+'</div>';
/* === БОСС === */
html += '<h3 style="font-family:Unbounded,sans-serif;font-size:1.05rem;color:var(--pri2);margin:20px 0 12px">Босс §5 — Графики sin и cos</h3>';
html += makeBoss('p5', {
color:'#0d9488',
title:'Босс §5 — Графики sin и cos',
steps:[
{ q:'Период функции $y = \\sin 2x$ — введи как pi/n или 2pi/n.', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi'||s==='π';}, hint:'$T = 2\\pi / \\omega = 2\\pi / 2 = \\pi$.' },
{ q:'$y = \\cos x$ — чётная или нечётная? Введи слово.', verify:(v)=>String(v).trim().toLowerCase().startsWith('чёт')||String(v).trim().toLowerCase().startsWith('чет'), hint:'$\\cos(-x) = \\cos x$.' },
{ q:'На каком из промежутков $[0;\\,2\\pi]$ функция $\\sin x$ <b>возрастает</b>? Введи правую границу как градусы: $\\pi/2$ → 90.', verify:(v)=>+v===90, hint:'$\\sin x$ возрастает на $[0; \\pi/2]$.' },
{ q:'Чему равно $\\sin\\left(\\dfrac{\\pi}{2} + 4\\pi\\right)$? (используй период)', verify:(v)=>+v===1, hint:'$4\\pi = 2 \\cdot 2\\pi$ — два полных периода. Эквивалентно $\\sin\\frac{\\pi}{2} = 1$.' },
{ q:'Сколько корней у уравнения $\\sin x = 0$ на $[0;\\,2\\pi]$?', verify:(v)=>+v===3, hint:'$x = 0, \\pi, 2\\pi$.' },
]
});
html += secNav('p4', 'p6') + readButton('p5');
box.innerHTML = html; renderMath(box);
/* IV1: slider experiment */
(function(){
const A_in = document.getElementById('p5-A');
const w_in = document.getElementById('p5-w');
const ph_in = document.getElementById('p5-ph');
const b_in = document.getElementById('p5-b');
const Av = document.getElementById('p5-Av');
const wv = document.getElementById('p5-wv');
const phv = document.getElementById('p5-phv');
const bv = document.getElementById('p5-bv');
const formula = document.getElementById('p5-formula');
const svgHost = document.getElementById('p5-iv1-svg');
function redraw(){
if(!A) return;
const Av0 = parseFloat(A_in.value);
const wv0 = parseFloat(w_in.value);
const phv0 = parseFloat(ph_in.value);
const bv0 = parseFloat(b_in.value);
Av.textContent = Av0.toFixed(1);
wv.textContent = wv0.toFixed(2);
phv.textContent = phv0.toFixed(2);
bv.textContent = bv0.toFixed(1);
formula.textContent = 'y = ' + Av0.toFixed(1) + ' · sin(' + wv0.toFixed(2) + 'x + ' + phv0.toFixed(2) + ') + ' + bv0.toFixed(1);
const f = A.func.canvas({id:'p5-iv1-c', W:640, H:240, xRange:[-2*Math.PI, 2*Math.PI], yRange:[-4.5, 4.5], bg:'#fff'});
let svg = f.open
+ f.grid({xStep:Math.PI/2, yStep:1, color:'#f1f5f9'})
+ f.axes({color:'#475569',
xTicks:[{val:-Math.PI, label:'-π'},{val:Math.PI, label:'π'},{val:2*Math.PI, label:'2π'}],
yTicks:[{val:-3, label:'-3'},{val:-1, label:'-1'},{val:1, label:'1'},{val:3, label:'3'}]
})
/* Базовый sin x пунктиром */
+ f.plot(x => Math.sin(x), {color:'#cbd5e1', width:1.5, dash:'4 3'})
/* Преобразованный график */
+ f.plot(x => Av0 * Math.sin(wv0 * x + phv0) + bv0, {color:'#0d9488', width:2.8})
+ f.close;
svgHost.innerHTML = svg;
}
[A_in, w_in, ph_in, b_in].forEach(el => el.addEventListener('input', redraw));
redraw();
})();
/* IV2: properties */
makeTrainer({
idPrefix:'p5-iv2',
parser:(v)=>v,
questions:[
{ q:'Чему равен период функции $y = \\sin x$? (введи как 2pi)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='2pi'||s==='2π';}, show:'$2\\pi$' },
{ q:'Период функции $y = \\cos 3x$? (введи как 2pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='2pi/3'||s==='2π/3';}, show:'$2\\pi/3$' },
{ q:'$y = \\sin x$ — чётная или нечётная? Введи слово.', a:(v)=>String(v).trim().toLowerCase().startsWith('нечёт')||String(v).trim().toLowerCase().startsWith('нечет'), show:'нечётная' },
{ q:'$y = \\cos x$ — чётная или нечётная? Введи слово.', a:(v)=>String(v).trim().toLowerCase().startsWith('чёт')||String(v).trim().toLowerCase().startsWith('чет'), show:'чётная' },
{ q:'Сколько нулей у $\\sin x$ на $[0;\\,2\\pi]$?', a:(v)=>+v===3, show:'3 (это $0, \\pi, 2\\pi$)' },
{ q:'Сколько нулей у $\\cos x$ на $[0;\\,2\\pi]$?', a:(v)=>+v===2, show:'2 (это $\\pi/2, 3\\pi/2$)' },
{ q:'Наибольшее значение $y = 3\\sin x + 1$? ', a:(v)=>+v===4, show:'4 (при sin = 1)' },
],
onComplete:(s,n)=>{ if(s===n){addXp(20,'p5-iv2');bumpProgress('p5',35);} else if(s>=4){addXp(10,'p5-iv2');bumpProgress('p5',16);} }
});
wireReadBtn('p5');
}
/* ============================================================
§ 6 — Функции y = tg x и y = ctg x
============================================================ */
function buildP6(){
const box = document.getElementById('p6-body');
const A = window.ALG10;
let html = '';
/* === SVG 1: график y = tg x === */
let svgTg = '';
if(A){
const f = A.func.canvas({id:'p6-tg', W:640, H:280, xRange:[-2*Math.PI, 2*Math.PI], yRange:[-5, 5], bg:'#fff'});
let s = f.open
+ f.grid({xStep:Math.PI/2, yStep:1, color:'#f1f5f9'})
/* Асимптоты */
+ f.asymptoteV(-3*Math.PI/2, {color:'#dc2626'})
+ f.asymptoteV(-Math.PI/2, {color:'#dc2626'})
+ f.asymptoteV(Math.PI/2, {color:'#dc2626'})
+ f.asymptoteV(3*Math.PI/2, {color:'#dc2626'})
+ f.axes({color:'#475569',
xTicks:[
{val:-3*Math.PI/2, label:'-3π/2'},
{val:-Math.PI, label:'-π'},
{val:-Math.PI/2, label:'-π/2'},
{val:Math.PI/2, label:'π/2'},
{val:Math.PI, label:'π'},
{val:3*Math.PI/2, label:'3π/2'}
],
yTicks:[{val:-3, label:'-3'},{val:-1, label:'-1'},{val:1, label:'1'},{val:3, label:'3'}]
})
/* Tg x с авто-разрывами */
+ f.plot(x => {
/* Избегаем точек слишком близко к асимптотам */
const t = Math.tan(x);
if (Math.abs(t) > 12) return NaN;
return t;
}, {color:'#16a34a', width:2.8})
+ f.close;
svgTg = s;
}
/* === SVG 2: график y = ctg x === */
let svgCtg = '';
if(A){
const f = A.func.canvas({id:'p6-ctg', W:640, H:280, xRange:[-2*Math.PI, 2*Math.PI], yRange:[-5, 5], bg:'#fff'});
let s = f.open
+ f.grid({xStep:Math.PI/2, yStep:1, color:'#f1f5f9'})
+ f.asymptoteV(-2*Math.PI, {color:'#dc2626'})
+ f.asymptoteV(-Math.PI, {color:'#dc2626'})
+ f.asymptoteV(0, {color:'#dc2626'})
+ f.asymptoteV(Math.PI, {color:'#dc2626'})
+ f.asymptoteV(2*Math.PI, {color:'#dc2626'})
+ f.axes({color:'#475569',
xTicks:[
{val:-3*Math.PI/2, label:'-3π/2'},
{val:-Math.PI/2, label:'-π/2'},
{val:Math.PI/2, label:'π/2'},
{val:3*Math.PI/2, label:'3π/2'}
],
yTicks:[{val:-3, label:'-3'},{val:-1, label:'-1'},{val:1, label:'1'},{val:3, label:'3'}]
})
+ f.plot(x => {
const c = 1 / Math.tan(x);
if (Math.abs(c) > 12) return NaN;
return c;
}, {color:'#7c3aed', width:2.8})
+ f.close;
svgCtg = s;
}
html += makeCard('rule', 'Свойства y = tg x', '6.1', `
<table style="width:100%;border-collapse:collapse;margin:8px 0;font-size:.92rem">
<tr style="background:var(--sec-acc-soft)"><th style="padding:6px;border:1px solid var(--border);text-align:left">Свойство</th><th style="padding:6px;border:1px solid var(--border);text-align:left">Значение</th></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>$D(\\tg)$</b></td><td style="padding:6px;border:1px solid var(--border)">$x \\ne \\dfrac{\\pi}{2} + \\pi n$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>$E(\\tg)$</b></td><td style="padding:6px;border:1px solid var(--border)">$\\mathbb{R}$ — все действительные числа</td></tr>
<tr style="background:var(--warn-bg)"><td style="padding:6px;border:1px solid var(--border)"><b>Период</b></td><td style="padding:6px;border:1px solid var(--border)"><b>$T = \\pi$</b> (вдвое короче, чем у sin/cos!)</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>Чётность</b></td><td style="padding:6px;border:1px solid var(--border)">Нечётная: $\\tg(-x) = -\\tg x$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>Нули</b></td><td style="padding:6px;border:1px solid var(--border)">$x = \\pi n$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>Асимптоты</b></td><td style="padding:6px;border:1px solid var(--border)">$x = \\dfrac{\\pi}{2} + \\pi n$ (вертикальные)</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>Монотонность</b></td><td style="padding:6px;border:1px solid var(--border)">Возрастает на $\\left(-\\dfrac{\\pi}{2} + \\pi n;\\,\\dfrac{\\pi}{2} + \\pi n\\right)$</td></tr>
</table>`);
html += makeCard('rule', 'График y = tg x', '6.2', `
<p>Тангенс не похож на синусоиду — это <b>«ветви»</b>, разорванные вертикальными асимптотами.</p>
<div class="svg-host">${svgTg}</div>
<p>Красные пунктирные линии — асимптоты. На каждом промежутке между ними функция возрастает от $-\\infty$ до $+\\infty$.</p>`);
html += makeCard('rule', 'Свойства y = ctg x', '6.3', `
<table style="width:100%;border-collapse:collapse;margin:8px 0;font-size:.92rem">
<tr style="background:var(--sec-acc-soft)"><th style="padding:6px;border:1px solid var(--border);text-align:left">Свойство</th><th style="padding:6px;border:1px solid var(--border);text-align:left">Значение</th></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>$D(\\ctg)$</b></td><td style="padding:6px;border:1px solid var(--border)">$x \\ne \\pi n$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>$E(\\ctg)$</b></td><td style="padding:6px;border:1px solid var(--border)">$\\mathbb{R}$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>Период</b></td><td style="padding:6px;border:1px solid var(--border)">$T = \\pi$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>Чётность</b></td><td style="padding:6px;border:1px solid var(--border)">Нечётная</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>Нули</b></td><td style="padding:6px;border:1px solid var(--border)">$x = \\dfrac{\\pi}{2} + \\pi n$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>Асимптоты</b></td><td style="padding:6px;border:1px solid var(--border)">$x = \\pi n$</td></tr>
<tr style="background:var(--warn-bg)"><td style="padding:6px;border:1px solid var(--border)"><b>Монотонность</b></td><td style="padding:6px;border:1px solid var(--border)"><b>Убывает</b> на $(\\pi n;\\,\\pi + \\pi n)$</td></tr>
</table>`);
html += makeCard('rule', 'График y = ctg x', '6.4', `
<p>Котангенс — «зеркало» тангенса: те же ветви, но <b>убывающие</b>, и сдвинуты на $\\frac{\\pi}{2}$.</p>
<div class="svg-host">${svgCtg}</div>
<p>Связь: $\\ctg x = \\tg\\left(\\dfrac{\\pi}{2} - x\\right)$.</p>`);
/* === ИНТЕРАКТИВ === */
html += '<div class="wg" id="p6-iv1">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Свойства tg x и ctg x</div></div>'
+'<div class="wg-help">Период обоих $= \\pi$. Асимптоты — там, где знаменатель = 0.</div>'
+trainerHTML('p6-iv1', 6, 'ответ')
+'</div>';
html += '<div class="wg" id="p6-iv2">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Сравни значения по графику</div></div>'
+'<div class="wg-help">Используй монотонность: $\\tg$ <b>возрастает</b>, $\\ctg$ <b>убывает</b> на главном промежутке.</div>'
+'<div class="score-display"><span>Задача <b id="p6-iv2-i">1</b> / 5</span><span>Очки: <b id="p6-iv2-s">0</b> / 5</span></div>'
+'<div id="p6-iv2-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1rem;text-align:center;margin-bottom:10px"></div>'
+'<div style="display:flex;gap:8px;justify-content:center"><button class="btn primary" id="p6-iv2-lt" style="background:#10b981;border-color:#10b981">&lt;</button><button class="btn primary" id="p6-iv2-eq" style="background:#f59e0b;border-color:#f59e0b">=</button><button class="btn primary" id="p6-iv2-gt" style="background:#dc2626;border-color:#dc2626">&gt;</button></div>'
+'<div class="feedback" id="p6-iv2-fb"></div></div>';
/* === БОСС === */
html += '<h3 style="font-family:Unbounded,sans-serif;font-size:1.05rem;color:var(--pri2);margin:20px 0 12px">Босс §6 — Графики tg и ctg</h3>';
html += makeBoss('p6', {
color:'#16a34a',
title:'Босс §6 — Графики tg и ctg',
steps:[
{ q:'Период функции $y = \\tg x$ — введи как pi/n или просто pi.', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi'||s==='π';}, hint:'$T = \\pi$.' },
{ q:'Период функции $y = \\tg 2x$? (введи pi/n)', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/2'||s==='π/2';}, hint:'$T = \\pi / 2$.' },
{ q:'Где у $\\tg x$ вертикальные асимптоты? Введи общую формулу в виде «pi/2+pi*n» (без пробелов).', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/2+pi*n'||s==='pi/2+pin'||s==='π/2+πn'||s==='π/2+π*n';}, hint:'Там, где $\\cos x = 0$.' },
{ q:'$\\tg x$ — возрастает или убывает на главном промежутке? Введи слово.', verify:(v)=>String(v).trim().toLowerCase().startsWith('возр'), hint:'От $-\\infty$ до $+\\infty$.' },
{ q:'$\\ctg x$ — возрастает или убывает? Введи слово.', verify:(v)=>String(v).trim().toLowerCase().startsWith('убыв'), hint:'От $+\\infty$ до $-\\infty$.' },
]
});
html += secNav('p5', 'p7') + readButton('p6');
box.innerHTML = html; renderMath(box);
/* IV1 */
makeTrainer({
idPrefix:'p6-iv1',
parser:(v)=>v,
questions:[
{ q:'Период $y = \\tg x$? (введи pi)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi'||s==='π';}, show:'$\\pi$' },
{ q:'Период $y = \\ctg 3x$? (введи pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/3'||s==='π/3';}, show:'$\\pi/3$' },
{ q:'$\\tg x$ — чётная или нечётная? Введи слово.', a:(v)=>String(v).trim().toLowerCase().startsWith('нечёт')||String(v).trim().toLowerCase().startsWith('нечет'), show:'нечётная' },
{ q:'Сколько нулей у $\\tg x$ на $[0;\\,2\\pi]$?', a:(v)=>+v===3, show:'3 (0, π, 2π)' },
{ q:'Сколько вертикальных асимптот у $\\tg x$ на $(0;\\,2\\pi)$?', a:(v)=>+v===2, show:'2 (π/2 и 3π/2)' },
{ q:'$\\tg 0 = ?$', a:(v)=>+v===0, show:'0' },
],
onComplete:(s,n)=>{ if(s===n){addXp(15,'p6-iv1');bumpProgress('p6',30);} else if(s>=4){addXp(8,'p6-iv1');bumpProgress('p6',14);} }
});
/* IV2: compare */
(function(){
const Q=[
{ e:'Сравни $\\tg 30°$ и $\\tg 45°$', ans:'lt' },
{ e:'Сравни $\\tg 60°$ и $\\tg 80°$', ans:'lt' },
{ e:'Сравни $\\ctg 30°$ и $\\ctg 60°$', ans:'gt' },
{ e:'Сравни $\\tg(-30°)$ и $\\tg 30°$', ans:'lt' },
{ e:'Сравни $\\tg 45°$ и $\\ctg 45°$', ans:'eq' },
];
let i=0,score=0;
function show(){
if(i>=Q.length){ document.getElementById('p6-iv2-q').innerHTML='<b>Готово!</b> '+score+' / '+Q.length; if(score===Q.length){addXp(15,'p6-iv2');bumpProgress('p6',25);} else if(score>=3){addXp(8,'p6-iv2');bumpProgress('p6',12);} return; }
document.getElementById('p6-iv2-i').textContent=(i+1);
document.getElementById('p6-iv2-s').textContent=score;
document.getElementById('p6-iv2-q').innerHTML=Q[i].e;
renderMath(document.getElementById('p6-iv2-q'));
document.getElementById('p6-iv2-fb').style.display='none';
}
function ans(a){
if(i>=Q.length) return;
const fb=document.getElementById('p6-iv2-fb');
if(a===Q[i].ans){ score++; feedback(fb,true,'&#10003; Верно!'); }
else{ const lab={lt:'<',eq:'=',gt:'>'}; feedback(fb,false,'&#10007; Правильно: <b>'+lab[Q[i].ans]+'</b>'); }
document.getElementById('p6-iv2-s').textContent=score;
i++; setTimeout(show,1200);
}
document.getElementById('p6-iv2-lt').addEventListener('click',()=>ans('lt'));
document.getElementById('p6-iv2-eq').addEventListener('click',()=>ans('eq'));
document.getElementById('p6-iv2-gt').addEventListener('click',()=>ans('gt'));
show();
})();
wireReadBtn('p6');
}
/* ============================================================
§ 7 — Арксинус, арккосинус, арктангенс, арккотангенс
============================================================ */
function buildP7(){
const box = document.getElementById('p7-body');
const A = window.ALG10;
let html = '';
/* === SVG: 4 графика обратных функций === */
function plotInverse(id, fn, xRange, yRange, color, title){
if(!A) return '';
const f = A.func.canvas({id, W:280, H:240, xRange, yRange, bg:'#fff'});
let s = f.open
+ f.grid({xStep:1, yStep:0.5, color:'#f1f5f9'})
+ f.axes({color:'#475569',
xTicks:[{val:-1, label:'-1'},{val:1, label:'1'}],
yTicks:[
{val:-Math.PI/2, label:'-π/2'},
{val:0, label:'0'},
{val:Math.PI/2, label:'π/2'},
{val:Math.PI, label:'π'}
].filter(t => t.val >= yRange[0] && t.val <= yRange[1])
})
+ f.plot(fn, {color, width:2.5, step:(xRange[1]-xRange[0])/200})
+ '<text x="140" y="22" text-anchor="middle" font-size="13" font-family="Unbounded,Inter,sans-serif" font-weight="800" fill="'+color+'">'+title+'</text>'
+ f.close;
return s;
}
const svgAsin = plotInverse('p7-asin', Math.asin, [-1.05, 1.05], [-Math.PI/2 - 0.2, Math.PI/2 + 0.2], '#0d9488', 'y = arcsin x');
const svgAcos = plotInverse('p7-acos', Math.acos, [-1.05, 1.05], [-0.2, Math.PI + 0.2], '#0891b2', 'y = arccos x');
const svgAtg = plotInverse('p7-atg', Math.atan, [-4, 4], [-Math.PI/2 - 0.2, Math.PI/2 + 0.2], '#16a34a', 'y = arctg x');
const svgActg = plotInverse('p7-actg', x => Math.PI/2 - Math.atan(x), [-4, 4], [-0.2, Math.PI + 0.2], '#7c3aed', 'y = arcctg x');
html += makeCard('theory', 'Зачем обратные функции', '7.1', `
<p>Уравнение $\\sin x = \\dfrac{1}{2}$ имеет бесконечно много решений ($x = \\dfrac{\\pi}{6} + 2\\pi n$ и $x = \\pi - \\dfrac{\\pi}{6} + 2\\pi n$).</p>
<p>Если хочется записать <b>одно</b> «опорное» решение, мы выбираем <b>главное значение</b> — это и есть $\\arcsin\\dfrac{1}{2}$.</p>`);
html += makeCard('rule', 'arcsin a', '7.2', `
<p style="background:var(--sec-acc-soft);padding:10px 14px;border-radius:8px"><b>Определение.</b> $\\arcsin a$ — это <b>такое число</b> $\\alpha \\in \\left[-\\dfrac{\\pi}{2};\\,\\dfrac{\\pi}{2}\\right]$, что $\\sin\\alpha = a$.</p>
<p>Существует только при $a \\in [-1;\\,1]$. Главные значения:</p>
<table style="width:100%;border-collapse:collapse;margin:8px 0;font-size:.94rem">
<tr style="background:var(--sec-acc-soft)"><th style="padding:6px;border:1px solid var(--border)">$a$</th><th>$0$</th><th>$\\frac{1}{2}$</th><th>$\\frac{\\sqrt{2}}{2}$</th><th>$\\frac{\\sqrt{3}}{2}$</th><th>$1$</th></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>$\\arcsin a$</b></td><td style="padding:6px;border:1px solid var(--border);text-align:center">$0$</td><td style="padding:6px;border:1px solid var(--border);text-align:center">$\\frac{\\pi}{6}$</td><td style="padding:6px;border:1px solid var(--border);text-align:center">$\\frac{\\pi}{4}$</td><td style="padding:6px;border:1px solid var(--border);text-align:center">$\\frac{\\pi}{3}$</td><td style="padding:6px;border:1px solid var(--border);text-align:center">$\\frac{\\pi}{2}$</td></tr>
</table>
<p>$\\arcsin$ — <b>нечётная</b>: $\\arcsin(-a) = -\\arcsin a$.</p>
<div class="svg-host">${svgAsin}</div>`);
html += makeCard('rule', 'arccos a', '7.3', `
<p style="background:var(--sec-acc-soft);padding:10px 14px;border-radius:8px"><b>Определение.</b> $\\arccos a$ — это <b>такое число</b> $\\alpha \\in [0;\\,\\pi]$, что $\\cos\\alpha = a$.</p>
<p>Существует только при $a \\in [-1;\\,1]$. Главные значения:</p>
<table style="width:100%;border-collapse:collapse;margin:8px 0;font-size:.94rem">
<tr style="background:var(--sec-acc-soft)"><th style="padding:6px;border:1px solid var(--border)">$a$</th><th>$1$</th><th>$\\frac{\\sqrt{3}}{2}$</th><th>$\\frac{\\sqrt{2}}{2}$</th><th>$\\frac{1}{2}$</th><th>$0$</th><th>$-1$</th></tr>
<tr><td style="padding:6px;border:1px solid var(--border)"><b>$\\arccos a$</b></td><td style="padding:6px;border:1px solid var(--border);text-align:center">$0$</td><td style="padding:6px;border:1px solid var(--border);text-align:center">$\\frac{\\pi}{6}$</td><td style="padding:6px;border:1px solid var(--border);text-align:center">$\\frac{\\pi}{4}$</td><td style="padding:6px;border:1px solid var(--border);text-align:center">$\\frac{\\pi}{3}$</td><td style="padding:6px;border:1px solid var(--border);text-align:center">$\\frac{\\pi}{2}$</td><td style="padding:6px;border:1px solid var(--border);text-align:center">$\\pi$</td></tr>
</table>
<p style="background:var(--warn-bg);padding:9px 13px;border-radius:8px;border-left:4px solid var(--warn)"><b>Важно:</b> $\\arccos$ <b>не является нечётной</b>! $\\arccos(-a) = \\pi - \\arccos a$.</p>
<div class="svg-host">${svgAcos}</div>`);
html += makeCard('rule', 'arctg a и arcctg a', '7.4', `
<p style="background:var(--sec-acc-soft);padding:10px 14px;border-radius:8px"><b>Определение.</b></p>
<ul style="padding-left:22px;line-height:1.85">
<li>$\\arctg a$ — такое $\\alpha \\in \\left(-\\dfrac{\\pi}{2};\\,\\dfrac{\\pi}{2}\\right)$, что $\\tg\\alpha = a$. Определено для всех $a \\in \\mathbb{R}$.</li>
<li>$\\arcctg a$ — такое $\\alpha \\in (0;\\,\\pi)$, что $\\ctg\\alpha = a$. Определено для всех $a \\in \\mathbb{R}$.</li>
</ul>
<p>Главные значения: $\\arctg 0 = 0$, $\\arctg 1 = \\dfrac{\\pi}{4}$, $\\arctg\\sqrt{3} = \\dfrac{\\pi}{3}$, $\\arctg\\dfrac{1}{\\sqrt{3}} = \\dfrac{\\pi}{6}$.</p>
<p>$\\arctg$ — <b>нечётная</b>: $\\arctg(-a) = -\\arctg a$. $\\arcctg$ — нет: $\\arcctg(-a) = \\pi - \\arcctg a$.</p>
<div class="svg-host-row">${svgAtg}${svgActg}</div>`);
html += makeCard('rule', 'Полезные связки', '7.5', `
<p>Эти две формулы стоит запомнить:</p>
<p style="text-align:center;font-size:1.1rem;margin:10px 0">$\\arcsin a + \\arccos a = \\dfrac{\\pi}{2}$</p>
<p style="text-align:center;font-size:1.1rem;margin:10px 0">$\\arctg a + \\arcctg a = \\dfrac{\\pi}{2}$</p>
<p>Например, $\\arccos\\dfrac{1}{2} = \\dfrac{\\pi}{2} - \\arcsin\\dfrac{1}{2} = \\dfrac{\\pi}{2} - \\dfrac{\\pi}{6} = \\dfrac{\\pi}{3}$.</p>`);
/* === ИНТЕРАКТИВ 1: Главные значения === */
html += '<div class="wg" id="p7-iv1">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Найди главное значение</div></div>'
+'<div class="wg-help">Ответ — в виде дроби: <b>pi/6</b>, <b>pi/3</b>, <b>-pi/4</b>, или просто число (для нуля).</div>'
+trainerHTML('p7-iv1', 8, 'значение')
+'</div>';
/* === ИНТЕРАКТИВ 2: arc(sin(α)) vs α === */
html += '<div class="wg" id="p7-iv2">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">arcsin(sin α) vs α</div></div>'
+'<div class="wg-help">$\\sin(\\arcsin a) = a$ всегда. Но $\\arcsin(\\sin\\alpha) = \\alpha$ <b>только если</b> $\\alpha \\in [-\\pi/2;\\,\\pi/2]$. Иначе нужно привести!</div>'
+trainerHTML('p7-iv2', 5, 'ответ')
+'</div>';
/* === БОСС === */
html += '<h3 style="font-family:Unbounded,sans-serif;font-size:1.05rem;color:var(--pri2);margin:20px 0 12px">Босс §7 — Обратные функции</h3>';
html += makeBoss('p7', {
color:'#7c3aed',
title:'Босс §7 — Обратные функции',
steps:[
{ q:'Чему равен $\\arcsin 0$?', verify:(v)=>+v===0, hint:'$\\sin 0 = 0$.' },
{ q:'$\\arcsin\\dfrac{1}{2} = ?$ (введи как pi/n)', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/6'||s==='π/6';}, hint:'$\\sin(\\pi/6) = 1/2$.' },
{ q:'$\\arccos(-1) = ?$ (введи как pi или 0)', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi'||s==='π';}, hint:'$\\cos\\pi = -1$.' },
{ q:'$\\arcsin\\dfrac{\\sqrt{3}}{2} + \\arccos\\dfrac{\\sqrt{3}}{2} = ?$ (введи pi/n)', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/2'||s==='π/2';}, hint:'Сумма всегда $= \\pi/2$.' },
{ q:'$\\arcsin\\left(\\sin\\dfrac{5\\pi}{6}\\right) = ?$ (внимание, $5\\pi/6$ вне $[-\\pi/2;\\,\\pi/2]$! Введи pi/n.)', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/6'||s==='π/6';}, hint:'$\\sin(5\\pi/6) = \\sin(\\pi - \\pi/6) = \\sin(\\pi/6) = 1/2$. arcsin(1/2) = $\\pi/6$.' },
]
});
html += secNav('p6', 'p8') + readButton('p7');
box.innerHTML = html; renderMath(box);
/* IV1: главные значения */
makeTrainer({
idPrefix:'p7-iv1',
parser:(v)=>v,
questions:[
{ q:'$\\arcsin 1 = ?$ (введи pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/2'||s==='π/2';}, show:'$\\pi/2$' },
{ q:'$\\arcsin(-1) = ?$ (введи -pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-pi/2'||s==='-π/2';}, show:'$-\\pi/2$' },
{ q:'$\\arccos 1 = ?$', a:(v)=>+v===0, show:'$0$' },
{ q:'$\\arccos 0 = ?$ (введи pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/2'||s==='π/2';}, show:'$\\pi/2$' },
{ q:'$\\arctg 1 = ?$ (введи pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/4'||s==='π/4';}, show:'$\\pi/4$' },
{ q:'$\\arctg(-1) = ?$ (введи -pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-pi/4'||s==='-π/4';}, show:'$-\\pi/4$' },
{ q:'$\\arccos\\dfrac{1}{2} = ?$ (введи pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/3'||s==='π/3';}, show:'$\\pi/3$' },
{ q:'$\\arccos\\left(-\\dfrac{1}{2}\\right) = ?$ (введи 2pi/3)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='2pi/3'||s==='2π/3';}, show:'$2\\pi/3$ ($\\pi - \\pi/3$)' },
],
onComplete:(s,n)=>{ if(s===n){addXp(20,'p7-iv1');bumpProgress('p7',32);} else if(s>=5){addXp(10,'p7-iv1');bumpProgress('p7',15);} }
});
/* IV2: arcsin(sin α) */
makeTrainer({
idPrefix:'p7-iv2',
parser:(v)=>v,
questions:[
{ q:'$\\sin(\\arcsin 0{,}5) = ?$', a:(v)=>+v===0.5, show:'$0{,}5$' },
{ q:'$\\arcsin\\left(\\sin\\dfrac{\\pi}{4}\\right) = ?$ (введи pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/4'||s==='π/4';}, show:'$\\pi/4$ — внутри $[-\\pi/2;\\pi/2]$' },
{ q:'$\\arcsin\\left(\\sin\\dfrac{3\\pi}{4}\\right) = ?$ (введи pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/4'||s==='π/4';}, show:'$\\pi/4$ ($\\sin(3\\pi/4) = \\sin(\\pi/4)$)' },
{ q:'$\\cos(\\arccos(-0{,}3)) = ?$', a:(v)=>+v===-0.3, show:'$-0{,}3$' },
{ q:'$\\arccos\\left(\\cos\\dfrac{5\\pi}{4}\\right) = ?$ (введи как 3pi/4)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='3pi/4'||s==='3π/4';}, show:'$3\\pi/4$ ($\\cos(5\\pi/4) = -\\frac{\\sqrt{2}}{2}$, $\\arccos = 3\\pi/4$)' },
],
onComplete:(s,n)=>{ if(s===n){addXp(18,'p7-iv2');bumpProgress('p7',28);} else if(s>=3){addXp(9,'p7-iv2');bumpProgress('p7',14);} }
});
wireReadBtn('p7');
}
/* ============================================================
§ 8 — Тригонометрические уравнения
============================================================ */
function buildP8(){
const box = document.getElementById('p8-body');
const A = window.ALG10;
let html = '';
/* === SVG 1: геометрия решения sin x = a (премиум) === */
let svgSin = '';
if(A){
const c = A.tri.canvas({id:'p8-sin', W:400, H:430, R:125, bg:'#fff'});
const a = 0.5; /* sin x = 1/2 */
const x1 = Math.asin(a); /* π/6 */
const x2 = Math.PI - x1; /* 5π/6 */
const yL = c.cy - a * c.R;
const p1 = c.pointPx(x1);
const p2 = c.pointPx(x2);
let s = c.open
/* === Заголовочная плашка === */
+ '<rect x="0" y="0" width="'+c.W+'" height="48" fill="rgba(13,148,136,.08)"/>'
+ '<text x="'+(c.W/2)+'" y="22" text-anchor="middle" font-size="14" font-family="Unbounded,Inter,sans-serif" font-weight="800" fill="#0d9488">УРАВНЕНИЕ: sin x = a</text>'
+ '<text x="'+(c.W/2)+'" y="40" text-anchor="middle" font-size="11" font-family="Inter,sans-serif" font-style="italic" fill="#64748b">Пример: a = 1/2 → корни π/6 и 5π/6</text>'
/* === Оси и окружность === */
+ c.axes()
+ c.circle({width:2.5})
/* === Горизонтальная линия y = a === */
+ '<line x1="55" y1="'+yL+'" x2="345" y2="'+yL+'" stroke="#dc2626" stroke-width="2.2" stroke-dasharray="7 4"/>'
+ '<rect x="346" y="'+(yL-11)+'" width="48" height="22" fill="#fee2e2" stroke="#dc2626" stroke-width="1.2" rx="4"/>'
+ '<text x="370" y="'+(yL+4)+'" text-anchor="middle" font-size="12" font-family="JetBrains Mono,monospace" font-weight="800" fill="#dc2626">y = a</text>'
/* Метка значения a на оси y */
+ '<text x="'+(c.cx-9)+'" y="'+(yL+4)+'" text-anchor="end" font-size="12" font-family="JetBrains Mono,monospace" font-weight="800" fill="#dc2626">a</text>'
/* === Сектор угла π/6 === */
+ '<path d="M '+c.cx+' '+c.cy+' L '+(c.cx+34)+' '+c.cy+' A 34 34 0 0 0 '+(c.cx + 34*Math.cos(x1))+' '+(c.cy - 34*Math.sin(x1))+' Z" fill="rgba(13,148,136,.22)" stroke="#0d9488" stroke-width="1.5"/>'
+ '<text x="'+(c.cx+44)+'" y="'+(c.cy-12)+'" font-size="11" font-family="JetBrains Mono,monospace" font-weight="800" fill="#0f766e">π/6</text>'
/* === Сектор угла 5π/6 (от 0 идём CCW почти до 5π/6, но рисуем оба угла рядом) === */
+ '<path d="M '+c.cx+' '+c.cy+' L '+(c.cx+30*Math.cos(x1))+' '+(c.cy-30*Math.sin(x1))+' A 30 30 0 0 0 '+(c.cx+30*Math.cos(x2))+' '+(c.cy-30*Math.sin(x2))+' Z" fill="rgba(124,58,237,.18)" stroke="#7c3aed" stroke-width="1.4" stroke-dasharray="3 2"/>'
/* === Радиусы к точкам решения === */
+ c.radius(x1, {color:'#0d9488', width:2.8})
+ c.radius(x2, {color:'#7c3aed', width:2.8})
/* === Точки решения P_{π/6} и P_{5π/6} с подписями === */
+ c.point(x1, {color:'#0d9488', label:'P_{π/6}', labelOffset:22, fontSize:13, labelColor:'#0f766e'})
+ c.point(x2, {color:'#7c3aed', label:'P_{5π/6}', labelOffset:22, fontSize:13, labelColor:'#6d28d9'})
/* === Вертикальные пунктиры — sin α для обеих точек === */
+ '<line x1="'+p1.px+'" y1="'+p1.py+'" x2="'+p1.px+'" y2="'+c.cy+'" stroke="#dc2626" stroke-width="1.4" stroke-dasharray="2 3"/>'
+ '<line x1="'+p2.px+'" y1="'+p2.py+'" x2="'+p2.px+'" y2="'+c.cy+'" stroke="#dc2626" stroke-width="1.4" stroke-dasharray="2 3"/>'
/* === Формульный блок === */
+ '<rect x="22" y="368" width="356" height="56" rx="10" fill="rgba(13,148,136,.10)" stroke="#0d9488" stroke-width="2"/>'
+ '<text x="'+(c.W/2)+'" y="386" text-anchor="middle" font-size="10" font-family="Unbounded,Inter,sans-serif" font-weight="800" fill="#0f766e" letter-spacing="1px">ОБЩАЯ ФОРМУЛА</text>'
+ '<text x="'+(c.W/2)+'" y="412" text-anchor="middle" font-size="16" font-family="JetBrains Mono,monospace" font-weight="800" fill="#0d9488">x = (1)ⁿ · arcsin a + πn, n ∈ Z</text>'
+ c.close;
svgSin = s;
}
/* === SVG 2: геометрия cos x = a (премиум) === */
let svgCos = '';
if(A){
const c = A.tri.canvas({id:'p8-cos', W:400, H:430, R:125, bg:'#fff'});
const a = 0.5; /* cos x = 1/2 */
const x1 = Math.acos(a); /* π/3 */
const x2 = -x1; /* -π/3 */
const xL = c.cx + a * c.R;
const p1 = c.pointPx(x1);
const p2 = c.pointPx(x2);
let s = c.open
/* === Заголовочная плашка === */
+ '<rect x="0" y="0" width="'+c.W+'" height="48" fill="rgba(8,145,178,.08)"/>'
+ '<text x="'+(c.W/2)+'" y="22" text-anchor="middle" font-size="14" font-family="Unbounded,Inter,sans-serif" font-weight="800" fill="#0891b2">УРАВНЕНИЕ: cos x = a</text>'
+ '<text x="'+(c.W/2)+'" y="40" text-anchor="middle" font-size="11" font-family="Inter,sans-serif" font-style="italic" fill="#64748b">Пример: a = 1/2 → корни ±π/3</text>'
/* === Оси и окружность === */
+ c.axes()
+ c.circle({width:2.5})
/* === Вертикальная линия x = a === */
+ '<line x1="'+xL+'" y1="55" x2="'+xL+'" y2="345" stroke="#dc2626" stroke-width="2.2" stroke-dasharray="7 4"/>'
+ '<rect x="'+(xL-22)+'" y="42" width="44" height="20" fill="#fee2e2" stroke="#dc2626" stroke-width="1.2" rx="4"/>'
+ '<text x="'+xL+'" y="56" text-anchor="middle" font-size="12" font-family="JetBrains Mono,monospace" font-weight="800" fill="#dc2626">x = a</text>'
/* Метка значения a на оси x */
+ '<text x="'+(xL-3)+'" y="'+(c.cy+18)+'" text-anchor="middle" font-size="12" font-family="JetBrains Mono,monospace" font-weight="800" fill="#dc2626">a</text>'
/* === Сектор угла π/3 (верхний) === */
+ '<path d="M '+c.cx+' '+c.cy+' L '+(c.cx+34)+' '+c.cy+' A 34 34 0 0 0 '+(c.cx + 34*Math.cos(x1))+' '+(c.cy - 34*Math.sin(x1))+' Z" fill="rgba(8,145,178,.22)" stroke="#0891b2" stroke-width="1.5"/>'
+ '<text x="'+(c.cx+44)+'" y="'+(c.cy-10)+'" font-size="11" font-family="JetBrains Mono,monospace" font-weight="800" fill="#0e7490">π/3</text>'
/* === Сектор угла -π/3 (нижний) === */
+ '<path d="M '+c.cx+' '+c.cy+' L '+(c.cx+30)+' '+c.cy+' A 30 30 0 0 1 '+(c.cx + 30*Math.cos(x2))+' '+(c.cy - 30*Math.sin(x2))+' Z" fill="rgba(124,58,237,.18)" stroke="#7c3aed" stroke-width="1.4"/>'
+ '<text x="'+(c.cx+44)+'" y="'+(c.cy+22)+'" font-size="11" font-family="JetBrains Mono,monospace" font-weight="800" fill="#6d28d9">-π/3</text>'
/* === Радиусы === */
+ c.radius(x1, {color:'#0891b2', width:2.8})
+ c.radius(x2, {color:'#7c3aed', width:2.8})
/* === Точки решения === */
+ c.point(x1, {color:'#0891b2', label:'P_{π/3}', labelOffset:22, fontSize:13, labelColor:'#0e7490'})
+ c.point(x2, {color:'#7c3aed', label:'P_{-π/3}', labelOffset:22, fontSize:13, labelColor:'#6d28d9'})
/* === Горизонтальные пунктиры — cos α для обеих точек (от P до оси y) === */
+ '<line x1="'+p1.px+'" y1="'+p1.py+'" x2="'+c.cx+'" y2="'+p1.py+'" stroke="#dc2626" stroke-width="1.4" stroke-dasharray="2 3"/>'
+ '<line x1="'+p2.px+'" y1="'+p2.py+'" x2="'+c.cx+'" y2="'+p2.py+'" stroke="#dc2626" stroke-width="1.4" stroke-dasharray="2 3"/>'
/* === Формульный блок === */
+ '<rect x="22" y="368" width="356" height="56" rx="10" fill="rgba(8,145,178,.10)" stroke="#0891b2" stroke-width="2"/>'
+ '<text x="'+(c.W/2)+'" y="386" text-anchor="middle" font-size="10" font-family="Unbounded,Inter,sans-serif" font-weight="800" fill="#0e7490" letter-spacing="1px">ОБЩАЯ ФОРМУЛА</text>'
+ '<text x="'+(c.W/2)+'" y="412" text-anchor="middle" font-size="16" font-family="JetBrains Mono,monospace" font-weight="800" fill="#0891b2">x = ± arccos a + 2πn, n ∈ Z</text>'
+ c.close;
svgCos = s;
}
/* === SVG 3: геометрия tg x = a (премиум) === */
let svgTg = '';
if(A){
const c = A.tri.canvas({id:'p8-tg', W:440, H:430, R:125, bg:'#fff'});
const a = Math.sqrt(3)/3; /* tg x = √3/3 ≈ 0.577 */
const x1 = Math.atan(a); /* π/6 */
const x2 = x1 + Math.PI; /* 7π/6 */
const xAx = c.cx + c.R;
const yA = c.cy - a * c.R;
/* Прямая через O и A_a, продлённая в обе стороны */
const k = a; /* y = kx */
const xL_start = c.cx - c.R - 12;
const xL_end = c.cx + c.R + 12;
const yL_start = c.cy + k * (c.cx - xL_start);
const yL_end = c.cy - k * (xL_end - c.cx);
let s = c.open
/* === Заголовочная плашка === */
+ '<rect x="0" y="0" width="'+c.W+'" height="48" fill="rgba(22,163,74,.08)"/>'
+ '<text x="'+(c.W/2)+'" y="22" text-anchor="middle" font-size="14" font-family="Unbounded,Inter,sans-serif" font-weight="800" fill="#16a34a">УРАВНЕНИЕ: tg x = a</text>'
+ '<text x="'+(c.W/2)+'" y="40" text-anchor="middle" font-size="11" font-family="Inter,sans-serif" font-style="italic" fill="#64748b">Пример: a = √3/3 → корни π/6 и 7π/6 (одна серия!)</text>'
/* === Оси, окружность, ось тангенсов === */
+ c.axes({xExt:c.R+50})
+ c.circle({width:2.5})
+ c.tgAxis({color:'#16a34a', ext:c.R+5})
/* === Прямая через O и A_a === */
+ '<line x1="'+xL_start+'" y1="'+yL_start+'" x2="'+xL_end+'" y2="'+yL_end+'" stroke="#dc2626" stroke-width="2" stroke-dasharray="6 3"/>'
/* === Точка A_a на оси тангенсов === */
+ '<circle cx="'+xAx+'" cy="'+yA+'" r="5" fill="#dc2626" stroke="#fff" stroke-width="2"/>'
+ '<rect x="'+(xAx+8)+'" y="'+(yA-12)+'" width="90" height="24" fill="#fee2e2" stroke="#dc2626" stroke-width="1.2" rx="4"/>'
+ '<text x="'+(xAx+53)+'" y="'+(yA+4)+'" text-anchor="middle" font-size="11" font-family="JetBrains Mono,monospace" font-weight="800" fill="#dc2626">A_a = (1; a)</text>'
/* === Сектор угла π/6 === */
+ '<path d="M '+c.cx+' '+c.cy+' L '+(c.cx+34)+' '+c.cy+' A 34 34 0 0 0 '+(c.cx + 34*Math.cos(x1))+' '+(c.cy - 34*Math.sin(x1))+' Z" fill="rgba(22,163,74,.22)" stroke="#16a34a" stroke-width="1.5"/>'
+ '<text x="'+(c.cx+44)+'" y="'+(c.cy-10)+'" font-size="11" font-family="JetBrains Mono,monospace" font-weight="800" fill="#15803d">π/6</text>'
/* === Точки решения === */
+ c.point(x1, {color:'#16a34a', label:'P_{π/6}', labelOffset:22, fontSize:13, labelColor:'#15803d'})
+ c.point(x2, {color:'#7c3aed', label:'P_{7π/6}', labelOffset:22, fontSize:13, labelColor:'#6d28d9'})
/* === Формульный блок === */
+ '<rect x="22" y="368" width="396" height="56" rx="10" fill="rgba(22,163,74,.10)" stroke="#16a34a" stroke-width="2"/>'
+ '<text x="'+(c.W/2)+'" y="386" text-anchor="middle" font-size="10" font-family="Unbounded,Inter,sans-serif" font-weight="800" fill="#15803d" letter-spacing="1px">ОБЩАЯ ФОРМУЛА (одна серия, период π)</text>'
+ '<text x="'+(c.W/2)+'" y="412" text-anchor="middle" font-size="16" font-family="JetBrains Mono,monospace" font-weight="800" fill="#16a34a">x = arctg a + πn, n ∈ Z</text>'
+ c.close;
svgTg = s;
}
html += makeCard('theory', 'Зачем геометрия?', '8.1', `
<p>Уравнение $\\sin x = a$ — это «на каких углах ордината точки $P_x$ равна $a$?». Геометрия даёт нам наглядный способ найти <b>все</b> решения.</p>
<p>В простейшем случае берём горизонтальную линию $y = a$ и находим точки её пересечения с единичной окружностью. От них уже получаем все остальные корни через периодичность.</p>`);
html += makeCard('rule', 'Уравнение sin x = a', '8.2', `
<p>Горизонтальная прямая $y = a$ пересекает единичную окружность в <b>двух точках</b> (если $|a| < 1$).</p>
<div class="svg-host">${svgSin}</div>
<p>Эти точки симметричны относительно оси $y$, поэтому:</p>
<ul style="padding-left:22px;line-height:1.85">
<li>$x_1 = \\arcsin a + 2\\pi n$</li>
<li>$x_2 = \\pi - \\arcsin a + 2\\pi n$</li>
</ul>
<p>Эти две серии объединяются <b>одной формулой</b>:</p>
<p style="text-align:center;font-size:1.15rem;margin:10px 0;padding:10px;background:var(--sec-acc-soft);border-radius:8px">$x = (-1)^n \\arcsin a + \\pi n, \\quad n \\in \\mathbb{Z}$</p>
<p>При $|a| > 1$ — <b>корней нет</b>.</p>`);
html += makeCard('rule', 'Уравнение cos x = a', '8.3', `
<p>Вертикальная прямая $x = a$ пересекает окружность в двух точках, симметричных относительно оси $x$.</p>
<div class="svg-host">${svgCos}</div>
<p>Поэтому формула короче:</p>
<p style="text-align:center;font-size:1.15rem;margin:10px 0;padding:10px;background:var(--sec-acc-soft);border-radius:8px">$x = \\pm \\arccos a + 2\\pi n, \\quad n \\in \\mathbb{Z}$</p>
<p>При $|a| > 1$ — корней нет.</p>`);
html += makeCard('rule', 'Уравнение tg x = a', '8.4', `
<p>На оси тангенсов отмечаем точку $A_a = (1;\\,a)$. Прямая через $O$ и $A_a$ пересекает окружность в <b>двух точках</b>, лежащих на одной прямой (симметрично относительно $O$).</p>
<div class="svg-host">${svgTg}</div>
<p>А период tg равен $\\pi$ — поэтому формула одна:</p>
<p style="text-align:center;font-size:1.15rem;margin:10px 0;padding:10px;background:var(--sec-acc-soft);border-radius:8px">$x = \\arctg a + \\pi n, \\quad n \\in \\mathbb{Z}$</p>
<p>Для $\\ctg x = a$ аналогично: $x = \\arcctg a + \\pi n$.</p>
<p>Здесь $a$ <b>любое</b> — ограничений нет.</p>`);
html += makeCard('algo', 'Особые случаи (запомнить!)', '8.5', `
<p>Когда $a = 0, \\pm 1$ — лучше использовать частные формулы вместо общих:</p>
<table style="width:100%;border-collapse:collapse;margin:8px 0;font-size:.94rem">
<tr style="background:var(--sec-acc-soft)"><th style="padding:6px;border:1px solid var(--border);text-align:left">Уравнение</th><th style="padding:6px;border:1px solid var(--border);text-align:left">Решение</th></tr>
<tr><td style="padding:6px;border:1px solid var(--border)">$\\sin x = 0$</td><td style="padding:6px;border:1px solid var(--border)">$x = \\pi n$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)">$\\sin x = 1$</td><td style="padding:6px;border:1px solid var(--border)">$x = \\dfrac{\\pi}{2} + 2\\pi n$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)">$\\sin x = -1$</td><td style="padding:6px;border:1px solid var(--border)">$x = -\\dfrac{\\pi}{2} + 2\\pi n$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)">$\\cos x = 0$</td><td style="padding:6px;border:1px solid var(--border)">$x = \\dfrac{\\pi}{2} + \\pi n$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)">$\\cos x = 1$</td><td style="padding:6px;border:1px solid var(--border)">$x = 2\\pi n$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)">$\\cos x = -1$</td><td style="padding:6px;border:1px solid var(--border)">$x = \\pi + 2\\pi n$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)">$\\tg x = 0$</td><td style="padding:6px;border:1px solid var(--border)">$x = \\pi n$</td></tr>
<tr><td style="padding:6px;border:1px solid var(--border)">$\\ctg x = 0$</td><td style="padding:6px;border:1px solid var(--border)">$x = \\dfrac{\\pi}{2} + \\pi n$</td></tr>
</table>`);
html += makeCard('algo', 'Метод замены переменной', '8.6', `
<p>Если в уравнении встречается одна тригонометрическая функция — обозначь её переменной $t$ и реши получившееся алгебраическое уравнение.</p>
<p><b>Пример.</b> $2\\sin^2 x - 3\\sin x + 1 = 0$.</p>
<p>Пусть $t = \\sin x$, тогда $2t^2 - 3t + 1 = 0$. Корни: $t_1 = 1, t_2 = 0{,}5$.</p>
<p>Возвращаемся: $\\sin x = 1$ или $\\sin x = 0{,}5$.</p>
<ul style="padding-left:22px;line-height:1.85">
<li>$\\sin x = 1$ ⇒ $x = \\dfrac{\\pi}{2} + 2\\pi n$.</li>
<li>$\\sin x = 0{,}5$ ⇒ $x = (-1)^k \\dfrac{\\pi}{6} + \\pi k$.</li>
</ul>`);
html += makeCard('algo', 'Метод разложения на множители', '8.7', `
<p>Если уравнение приводится к виду $f_1(x) \\cdot f_2(x) = 0$ — оно распадается на два простейших.</p>
<p><b>Пример.</b> $\\sqrt{3}\\sin x = \\cos^2 x \\sin x$.</p>
<p>Переносим всё в одну сторону: $\\sin x (\\sqrt{3} - \\cos^2 x) = 0$.</p>
<p>Либо $\\sin x = 0$ (тогда $x = \\pi n$), либо $\\cos^2 x = \\sqrt{3} > 1$ — корней нет.</p>
<p>Итого: $x = \\pi n$.</p>`);
html += makeCard('algo', 'Однородные уравнения', '8.8', `
<p><b>Однородное 1-й степени</b> $a\\sin x + b\\cos x = 0$ — делим на $\\cos x$ (при условии $\\cos x \\ne 0$, что проверяем): $a\\tg x + b = 0$ ⇒ $\\tg x = -\\dfrac{b}{a}$.</p>
<p><b>Однородное 2-й степени</b> $a\\sin^2 x + b\\sin x \\cos x + c\\cos^2 x = 0$ — делим на $\\cos^2 x$: $a\\tg^2 x + b\\tg x + c = 0$. Замена $t = \\tg x$.</p>`);
/* === ИНТЕРАКТИВ 1: Простейшие === */
html += '<div class="wg" id="p8-iv1">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Простейшие тригонометрические</div></div>'
+'<div class="wg-help">Для серий с πn — введи <b>один корень</b> в $[0;\\,2\\pi)$. Если корней несколько в этом промежутке — введи наименьший положительный.</div>'
+trainerHTML('p8-iv1', 10, 'корень в [0;2π)')
+'</div>';
/* === ИНТЕРАКТИВ 2: Сколько корней в промежутке === */
html += '<div class="wg" id="p8-iv2">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Сколько корней в промежутке?</div></div>'
+'<div class="wg-help">Найди серии корней, потом отсчитай, сколько из них попало в указанный промежуток.</div>'
+trainerHTML('p8-iv2', 6, 'число')
+'</div>';
/* === ИНТЕРАКТИВ 3: Замена/разложение === */
html += '<div class="wg" id="p8-iv3">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 3</span><div class="wg-title">Замена переменной</div></div>'
+'<div class="wg-help">Сделай замену $t = \\sin x$ или $\\cos x$ и реши квадратное.</div>'
+trainerHTML('p8-iv3', 5, 'число корней в [0;2π)')
+'</div>';
/* === БОСС §8 — 6 этапов === */
html += '<h3 style="font-family:Unbounded,sans-serif;font-size:1.05rem;color:var(--pri2);margin:20px 0 12px">Босс §8 — Тригонометрические уравнения</h3>';
html += makeBoss('p8', {
color:'#dc2626',
title:'Босс §8 — Тригонометрические уравнения',
steps:[
{ q:'Уравнение $\\sin x = 2$ имеет корни? «да» или «нет»', verify:(v)=>String(v).trim().toLowerCase().startsWith('н'), hint:'$|2| > 1$, корней нет.' },
{ q:'Сколько корней у $\\sin x = 0{,}5$ на промежутке $[0;\\,2\\pi]$?', verify:(v)=>+v===2, hint:'$x_1 = \\pi/6$ и $x_2 = 5\\pi/6$ — обе в промежутке.' },
{ q:'Реши $\\cos x = -1$. Введи корень в $[0;\\,2\\pi]$ как pi (если ответ $\\pi$).', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi'||s==='π';}, hint:'$\\cos\\pi = -1$.' },
{ q:'Реши $2\\cos^2 x + 3\\cos x + 1 = 0$. Сколько корней в $[0;\\,2\\pi)$?', verify:(v)=>+v===3, hint:'$t = \\cos x$: $2t^2+3t+1=0$, $t = -1$ или $t = -1/2$. cos=1: x=π. cos=1/2: x=2π/3, 4π/3. Итого 3.' },
{ q:'Решает ли значение $x = \\dfrac{\\pi}{2}$ уравнение $\\sin x \\cos x = 0$? «да» или «нет»', verify:(v)=>String(v).trim().toLowerCase().startsWith('д'), hint:'$\\cos(\\pi/2) = 0$, произведение = 0 &#10003;.' },
{ q:'Реши $\\tg x = 1$. Введи наименьший положительный корень как pi/n.', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/4'||s==='π/4';}, hint:'$\\arctg 1 = \\pi/4$, серия $x = \\pi/4 + \\pi n$.' },
]
});
html += secNav('p7', 'p9') + readButton('p8');
box.innerHTML = html; renderMath(box);
/* IV1: простейшие */
makeTrainer({
idPrefix:'p8-iv1',
parser:(v)=>v,
questions:[
{ q:'$\\sin x = 0$. Наименьший корень в $[0;\\,2\\pi)$?', a:(v)=>+v===0, show:'$0$' },
{ q:'$\\sin x = 1$. Корень в $[0;\\,2\\pi)$? (введи pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/2'||s==='π/2';}, show:'$\\pi/2$' },
{ q:'$\\cos x = 1$. Наименьший корень в $[0;\\,2\\pi)$?', a:(v)=>+v===0, show:'$0$' },
{ q:'$\\cos x = -1$. Корень в $[0;\\,2\\pi)$?', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi'||s==='π';}, show:'$\\pi$' },
{ q:'$\\sin x = 0{,}5$. Наименьший корень в $[0;\\,2\\pi)$? (pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/6'||s==='π/6';}, show:'$\\pi/6$' },
{ q:'$\\cos x = 0{,}5$. Наименьший корень в $[0;\\,2\\pi)$? (pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/3'||s==='π/3';}, show:'$\\pi/3$' },
{ q:'$\\sin x = -1$. Корень в $[0;\\,2\\pi)$? (введи 3pi/2)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='3pi/2'||s==='3π/2';}, show:'$3\\pi/2$' },
{ q:'$\\tg x = 0$. Наименьший корень в $[0;\\,2\\pi)$?', a:(v)=>+v===0, show:'$0$' },
{ q:'$\\tg x = \\sqrt{3}$. Наименьший корень в $[0;\\,2\\pi)$? (pi/n)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/3'||s==='π/3';}, show:'$\\pi/3$' },
{ q:'$\\sin x = 3$. Сколько корней? (число)', a:(v)=>+v===0, show:'$0$ (нет, $|3|>1$)' },
],
onComplete:(s,n)=>{ if(s===n){addXp(22,'p8-iv1');bumpProgress('p8',32);} else if(s>=6){addXp(11,'p8-iv1');bumpProgress('p8',16);} }
});
/* IV2: сколько корней */
makeTrainer({
idPrefix:'p8-iv2',
questions:[
{ q:'Сколько корней у $\\sin x = 0$ на $[0;\\,2\\pi]$?', a:3, show:'3 ($0, \\pi, 2\\pi$)' },
{ q:'Сколько корней у $\\sin x = 0{,}5$ на $[0;\\,2\\pi]$?', a:2, show:'2 ($\\pi/6$ и $5\\pi/6$)' },
{ q:'Сколько корней у $\\cos x = 0$ на $[0;\\,2\\pi]$?', a:2, show:'2 ($\\pi/2$ и $3\\pi/2$)' },
{ q:'Сколько корней у $\\cos x = 1$ на $[0;\\,2\\pi]$?', a:2, show:'2 ($0$ и $2\\pi$)' },
{ q:'Сколько корней у $\\tg x = 1$ на $[0;\\,\\pi]$?', a:1, show:'1 ($\\pi/4$)' },
{ q:'Сколько корней у $\\sin x = \\dfrac{\\sqrt{2}}{2}$ на $[0;\\,4\\pi]$?', a:4, show:'4 (на каждом периоде по 2)' },
],
onComplete:(s,n)=>{ if(s===n){addXp(18,'p8-iv2');bumpProgress('p8',26);} else if(s>=4){addXp(9,'p8-iv2');bumpProgress('p8',12);} }
});
/* IV3: замена */
makeTrainer({
idPrefix:'p8-iv3',
questions:[
{ q:'$2\\sin^2 x - \\sin x = 0$. Сколько корней в $[0;\\,2\\pi)$?', a:4, show:'4 ($\\sin x(2\\sin x - 1) = 0$: sin x = 0 ⇒ 0, π; sin x = 1/2 ⇒ π/6, 5π/6)' },
{ q:'$\\cos^2 x = 1$. Сколько корней в $[0;\\,2\\pi)$?', a:2, show:'2 (cos x = ±1 ⇒ x = 0, π)' },
{ q:'$2\\sin^2 x - 3\\sin x + 1 = 0$. Сколько корней в $[0;\\,2\\pi)$?', a:3, show:'3 (sin = 1: π/2; sin = 1/2: π/6, 5π/6)' },
{ q:'$\\sin^2 x + \\sin x = 0$. Сколько корней в $[0;\\,2\\pi)$?', a:3, show:'3 (sin x = 0: 0, π; sin x = -1: 3π/2)' },
{ q:'$\\tg^2 x - 1 = 0$. Сколько корней в $[0;\\,2\\pi)$?', a:4, show:'4 (tg = ±1, серии π/4 + πn/2)' },
],
onComplete:(s,n)=>{ if(s===n){addXp(18,'p8-iv3');bumpProgress('p8',26);} else if(s>=2){addXp(9,'p8-iv3');bumpProgress('p8',12);} }
});
wireReadBtn('p8');
}
/* ============================================================
§ 9 — Формулы приведения
============================================================ */
function buildP9(){
const box = document.getElementById('p9-body');
const A = window.ALG10;
let html = '';
/* === SVG: единичная окружность со знаками по четвертям === */
let svgSigns = '';
if(A){
const c = A.tri.canvas({id:'p9-q', W:380, H:360, R:130});
let s = c.open
/* Заголовок */
+ '<rect x="0" y="0" width="'+c.W+'" height="44" fill="rgba(8,145,178,.08)"/>'
+ '<text x="'+(c.W/2)+'" y="22" text-anchor="middle" font-size="13" font-family="Unbounded,Inter,sans-serif" font-weight="800" fill="#0e7490">ЗНАКИ ТРИГОНОМЕТРИЧЕСКИХ ФУНКЦИЙ ПО ЧЕТВЕРТЯМ</text>'
+ '<text x="'+(c.W/2)+'" y="38" text-anchor="middle" font-size="10" font-family="Inter,sans-serif" font-style="italic" fill="#64748b">Шаг 1 правила приведения: какой знак ставить?</text>'
+ c.quadrant(1, {fill:'rgba(16,185,129,.16)'})
+ c.quadrant(2, {fill:'rgba(245,158,11,.16)'})
+ c.quadrant(3, {fill:'rgba(239,68,68,.13)'})
+ c.quadrant(4, {fill:'rgba(124,58,237,.13)'})
+ c.axes()
+ c.circle({width:2.5})
+ c.quadrantLabels()
/* Подписи знаков в каждой четверти */
/* I (правый верх) */
+ '<text x="270" y="135" text-anchor="middle" font-size="11" font-family="JetBrains Mono,monospace" font-weight="800" fill="#065f46">sin +</text>'
+ '<text x="270" y="150" text-anchor="middle" font-size="11" font-family="JetBrains Mono,monospace" font-weight="800" fill="#065f46">cos +</text>'
+ '<text x="270" y="165" text-anchor="middle" font-size="11" font-family="JetBrains Mono,monospace" font-weight="800" fill="#065f46">tg, ctg +</text>'
/* II (левый верх) */
+ '<text x="110" y="135" text-anchor="middle" font-size="11" font-family="JetBrains Mono,monospace" font-weight="800" fill="#065f46">sin +</text>'
+ '<text x="110" y="150" text-anchor="middle" font-size="11" font-family="JetBrains Mono,monospace" font-weight="800" fill="#dc2626">cos </text>'
+ '<text x="110" y="165" text-anchor="middle" font-size="11" font-family="JetBrains Mono,monospace" font-weight="800" fill="#dc2626">tg, ctg </text>'
/* III (левый низ) */
+ '<text x="110" y="225" text-anchor="middle" font-size="11" font-family="JetBrains Mono,monospace" font-weight="800" fill="#dc2626">sin </text>'
+ '<text x="110" y="240" text-anchor="middle" font-size="11" font-family="JetBrains Mono,monospace" font-weight="800" fill="#dc2626">cos </text>'
+ '<text x="110" y="255" text-anchor="middle" font-size="11" font-family="JetBrains Mono,monospace" font-weight="800" fill="#065f46">tg, ctg +</text>'
/* IV (правый низ) */
+ '<text x="270" y="225" text-anchor="middle" font-size="11" font-family="JetBrains Mono,monospace" font-weight="800" fill="#dc2626">sin </text>'
+ '<text x="270" y="240" text-anchor="middle" font-size="11" font-family="JetBrains Mono,monospace" font-weight="800" fill="#065f46">cos +</text>'
+ '<text x="270" y="255" text-anchor="middle" font-size="11" font-family="JetBrains Mono,monospace" font-weight="800" fill="#dc2626">tg, ctg </text>'
/* Пояснительная плашка снизу */
+ '<rect x="22" y="312" width="336" height="38" rx="8" fill="rgba(245,158,11,.10)" stroke="#f59e0b" stroke-width="1.5"/>'
+ '<text x="'+(c.W/2)+'" y="328" text-anchor="middle" font-size="10" font-family="Inter,sans-serif" font-weight="700" fill="#92400e">Запоминалка: tg и ctg положительны в I и III</text>'
+ '<text x="'+(c.W/2)+'" y="343" text-anchor="middle" font-size="10" font-family="Inter,sans-serif" font-weight="700" fill="#92400e">(там, где знаки sin и cos совпадают)</text>'
+ c.close;
svgSigns = s;
}
html += makeCard('theory', 'Зачем нужны формулы приведения', '9.1', `
<p>Все таблицы значений тригонометрии — это значения для <b>острых углов</b> ($0;\\,\\frac{\\pi}{2}$).</p>
<p>Если в задаче встретился угол вроде $\\dfrac{3\\pi}{2} - \\alpha$ или $\\pi + \\alpha$, формулы приведения позволяют <b>свести</b> его к функции острого угла $\\alpha$.</p>
<div class="svg-host">${svgSigns}</div>`);
html += makeCard('algo', 'Правило двух шагов', '9.2', `
<p style="background:var(--sec-acc-soft);padding:10px 14px;border-radius:8px"><b>Шаг 1. Знак.</b> Поставь в правой части тот знак, который имеет <b>исходная функция</b> в той четверти, куда попадает аргумент, считая $\\alpha$ острым.</p>
<p style="background:var(--sec-acc-soft);padding:10px 14px;border-radius:8px"><b>Шаг 2. Имя функции.</b></p>
<ul style="padding-left:22px;line-height:1.9">
<li>Если аргумент имеет вид <b>$\\dfrac{\\pi}{2} \\pm \\alpha$</b> или <b>$\\dfrac{3\\pi}{2} \\pm \\alpha$</b> — <b>имя меняется</b> (sin ↔ cos, tg ↔ ctg).</li>
<li>Если аргумент имеет вид <b>$\\pi \\pm \\alpha$</b> или <b>$2\\pi \\pm \\alpha$</b> — <b>имя не меняется</b>.</li>
</ul>
<p><b>Пример. Применим правило к $\\cos\\left(\\dfrac{3\\pi}{2} - \\alpha\\right)$:</b></p>
<ol style="padding-left:22px;line-height:1.9">
<li>Если $\\alpha$ острый, то $\\dfrac{3\\pi}{2} - \\alpha$ попадает в <b>III четверть</b>. В ней $\\cos < 0$, значит ставим знак <b>«минус»</b>.</li>
<li>Аргумент имеет вид $\\dfrac{3\\pi}{2} - \\alpha$ — <b>имя меняется</b>: cos → sin.</li>
</ol>
<p>Итог: $\\cos\\left(\\dfrac{3\\pi}{2} - \\alpha\\right) = -\\sin\\alpha$.</p>`);
html += makeCard('rule', 'Полная таблица формул приведения', '9.3', `
<div style="overflow-x:auto;margin:8px 0">
<table style="width:100%;border-collapse:collapse;font-size:.88rem;min-width:520px">
<tr style="background:var(--sec-acc-soft)">
<th style="padding:6px 8px;border:1px solid var(--border)">Аргумент</th>
<th style="padding:6px 8px;border:1px solid var(--border)">sin</th>
<th style="padding:6px 8px;border:1px solid var(--border)">cos</th>
<th style="padding:6px 8px;border:1px solid var(--border)">tg</th>
<th style="padding:6px 8px;border:1px solid var(--border)">ctg</th>
</tr>
<tr><td style="padding:6px 8px;border:1px solid var(--border)"><b>$\\frac{\\pi}{2} - \\alpha$</b></td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$\\cos\\alpha$</td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$\\sin\\alpha$</td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$\\ctg\\alpha$</td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$\\tg\\alpha$</td></tr>
<tr><td style="padding:6px 8px;border:1px solid var(--border)"><b>$\\frac{\\pi}{2} + \\alpha$</b></td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$\\cos\\alpha$</td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$-\\sin\\alpha$</td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$-\\ctg\\alpha$</td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$-\\tg\\alpha$</td></tr>
<tr><td style="padding:6px 8px;border:1px solid var(--border)"><b>$\\pi - \\alpha$</b></td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$\\sin\\alpha$</td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$-\\cos\\alpha$</td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$-\\tg\\alpha$</td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$-\\ctg\\alpha$</td></tr>
<tr><td style="padding:6px 8px;border:1px solid var(--border)"><b>$\\pi + \\alpha$</b></td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$-\\sin\\alpha$</td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$-\\cos\\alpha$</td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$\\tg\\alpha$</td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$\\ctg\\alpha$</td></tr>
<tr><td style="padding:6px 8px;border:1px solid var(--border)"><b>$\\frac{3\\pi}{2} - \\alpha$</b></td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$-\\cos\\alpha$</td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$-\\sin\\alpha$</td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$\\ctg\\alpha$</td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$\\tg\\alpha$</td></tr>
<tr><td style="padding:6px 8px;border:1px solid var(--border)"><b>$\\frac{3\\pi}{2} + \\alpha$</b></td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$-\\cos\\alpha$</td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$\\sin\\alpha$</td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$-\\ctg\\alpha$</td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$-\\tg\\alpha$</td></tr>
<tr><td style="padding:6px 8px;border:1px solid var(--border)"><b>$2\\pi - \\alpha$</b></td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$-\\sin\\alpha$</td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$\\cos\\alpha$</td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$-\\tg\\alpha$</td><td style="padding:6px 8px;border:1px solid var(--border);text-align:center">$-\\ctg\\alpha$</td></tr>
</table>
</div>
<p style="font-size:.86rem;color:var(--muted);font-style:italic">Учить таблицу наизусть необязательно — достаточно знать правило двух шагов и применять его.</p>`);
html += makeCard('example', 'Применение для вычисления', '9.4', `
<p><b>Задача 1.</b> Вычисли $\\sin 120°$.</p>
<p>$\\sin 120° = \\sin(180° - 60°) = \\sin 60° = \\dfrac{\\sqrt{3}}{2}$.</p>
<p>Здесь имя не менялось ($\\pi - \\alpha$), знак $+$ (II четверть, sin положителен).</p>
<p><b>Задача 2.</b> Вычисли $\\cos 240°$.</p>
<p>$\\cos 240° = \\cos(180° + 60°) = -\\cos 60° = -\\dfrac{1}{2}$.</p>
<p>Имя не менялось ($\\pi + \\alpha$), знак $-$ (III четверть, cos отрицателен).</p>`);
/* === ИНТЕРАКТИВ 1: Приведи к острому === */
html += '<div class="wg" id="p9-iv1">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Приведи к функции острого угла</div></div>'
+'<div class="wg-help">Введи результат с правильным знаком. Например, $\\cos(\\pi - \\alpha) = -\\cos\\alpha$ — пиши «-cos a» или «-cosa».</div>'
+trainerHTML('p9-iv1', 8, 'результат')
+'</div>';
/* === ИНТЕРАКТИВ 2: Вычисли значение === */
html += '<div class="wg" id="p9-iv2">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Вычисли значение</div></div>'
+'<div class="wg-help">Сначала приведи к острому углу, затем подставь значение по таблице. Введи как дробь или десятичное число.</div>'
+trainerHTML('p9-iv2', 8, 'значение')
+'</div>';
/* === БОСС === */
html += '<h3 style="font-family:Unbounded,sans-serif;font-size:1.05rem;color:var(--pri2);margin:20px 0 12px">Босс §9 — Формулы приведения</h3>';
html += makeBoss('p9', {
color:'#0e7490',
title:'Босс §9 — Формулы приведения',
steps:[
{ q:'$\\sin(\\pi - \\alpha) = ?$ (вид «sin a» или «-sin a»)', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='sina'||s==='sin(a)'||s==='sinα';}, hint:'$\\pi - \\alpha$: II четверть, $\\sin > 0$; имя не меняется.' },
{ q:'$\\cos(\\frac{\\pi}{2} + \\alpha) = ?$ (имя меняется + знак)', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-sina'||s==='-sin(a)'||s==='-sinα';}, hint:'II четверть, $\\cos < 0$; имя меняется cos → sin.' },
{ q:'Вычисли $\\sin 150°$. Введи как дробь (1/2).', verify:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='1/2'||+v===0.5;}, hint:'$\\sin 150° = \\sin(180° - 30°) = \\sin 30° = 1/2$.' },
{ q:'Вычисли $\\cos 210°$. Введи (-sqrt3/2).', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-sqrt3/2'||s==='-√3/2'||Math.abs(+v - (-Math.sqrt(3)/2))<0.02;}, hint:'$\\cos 210° = \\cos(180° + 30°) = -\\cos 30° = -\\sqrt{3}/2$.' },
{ q:'$\\tg(\\frac{3\\pi}{2} - \\alpha) = ?$ (3 варианта: ctg a, -ctg a, tg a)', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='ctga'||s==='ctg(a)'||s==='ctgα';}, hint:'III четверть, $\\tg > 0$; имя меняется tg → ctg.' },
]
});
html += secNav('p8', 'p10') + readButton('p9');
box.innerHTML = html; renderMath(box);
/* IV1: приведение */
makeTrainer({
idPrefix:'p9-iv1',
parser:(v)=>v,
questions:[
{ q:'$\\sin(\\pi + \\alpha) = ?$ (sin a или -sin a)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-sina'||s==='-sin(a)'||s==='-sinα';}, show:'$-\\sin\\alpha$' },
{ q:'$\\cos(2\\pi - \\alpha) = ?$', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='cosa'||s==='cos(a)'||s==='cosα';}, show:'$\\cos\\alpha$' },
{ q:'$\\sin(\\frac{\\pi}{2} - \\alpha) = ?$ (имя меняется)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='cosa'||s==='cos(a)'||s==='cosα';}, show:'$\\cos\\alpha$' },
{ q:'$\\cos(\\pi + \\alpha) = ?$', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-cosa'||s==='-cos(a)'||s==='-cosα';}, show:'$-\\cos\\alpha$' },
{ q:'$\\tg(\\pi - \\alpha) = ?$', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-tga'||s==='-tg(a)'||s==='-tgα';}, show:'$-\\tg\\alpha$' },
{ q:'$\\sin(\\frac{3\\pi}{2} + \\alpha) = ?$', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-cosa'||s==='-cos(a)'||s==='-cosα';}, show:'$-\\cos\\alpha$' },
{ q:'$\\cos(\\frac{3\\pi}{2} - \\alpha) = ?$', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-sina'||s==='-sin(a)'||s==='-sinα';}, show:'$-\\sin\\alpha$' },
{ q:'$\\ctg(\\frac{\\pi}{2} + \\alpha) = ?$', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-tga'||s==='-tg(a)'||s==='-tgα';}, show:'$-\\tg\\alpha$' },
],
onComplete:(s,n)=>{ if(s===n){addXp(20,'p9-iv1');bumpProgress('p9',32);} else if(s>=5){addXp(10,'p9-iv1');bumpProgress('p9',15);} }
});
/* IV2: вычисли значение */
makeTrainer({
idPrefix:'p9-iv2',
parser:(v)=>v,
questions:[
{ q:'$\\sin 120° = ?$ (введи sqrt3/2)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='sqrt3/2'||s==='√3/2'||Math.abs(+v - Math.sqrt(3)/2)<0.02;}, show:'$\\sqrt{3}/2$' },
{ q:'$\\cos 150° = ?$ (введи -sqrt3/2)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-sqrt3/2'||s==='-√3/2'||Math.abs(+v - (-Math.sqrt(3)/2))<0.02;}, show:'$-\\sqrt{3}/2$' },
{ q:'$\\sin 225° = ?$ (-sqrt2/2)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-sqrt2/2'||s==='-√2/2'||Math.abs(+v - (-Math.sqrt(2)/2))<0.02;}, show:'$-\\sqrt{2}/2$' },
{ q:'$\\cos 300° = ?$ (1/2)', a:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='1/2'||+v===0.5;}, show:'$1/2$' },
{ q:'$\\tg 135° = ?$ (-1)', a:(v)=>+v===-1, show:'$-1$' },
{ q:'$\\sin(-150°) = ?$ (-1/2)', a:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='-1/2'||+v===-0.5;}, show:'$-1/2$' },
{ q:'$\\cos 240° = ?$ (-1/2)', a:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='-1/2'||+v===-0.5;}, show:'$-1/2$' },
{ q:'$\\sin\\frac{5\\pi}{6} = ?$ (1/2)', a:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='1/2'||+v===0.5;}, show:'$1/2$' },
],
onComplete:(s,n)=>{ if(s===n){addXp(20,'p9-iv2');bumpProgress('p9',32);} else if(s>=5){addXp(10,'p9-iv2');bumpProgress('p9',15);} }
});
wireReadBtn('p9');
}
/* ============================================================
§ 10 — Синус, косинус, тангенс суммы и разности
============================================================ */
function buildP10(){
const box = document.getElementById('p10-body');
let html = '';
/* === Плакат: 8 формул сложения и вычитания (HTML + KaTeX) === */
const svgFormulas = '<div class="formula-plate">'
+ '<div class="formula-plate-head teal">'
+ '<div class="formula-plate-title">8 формул сложения и вычитания углов</div>'
+ '<div class="formula-plate-sub">учат наизусть — это база для всей старшей тригонометрии</div>'
+ '</div>'
+ '<div class="formula-plate-body">'
+ '<div class="formula-row">$\\sin(\\alpha + \\beta) = \\sin\\alpha\\cos\\beta + \\cos\\alpha\\sin\\beta$</div>'
+ '<div class="formula-row alt">$\\sin(\\alpha - \\beta) = \\sin\\alpha\\cos\\beta - \\cos\\alpha\\sin\\beta$</div>'
+ '<div class="formula-row">$\\cos(\\alpha + \\beta) = \\cos\\alpha\\cos\\beta - \\sin\\alpha\\sin\\beta$</div>'
+ '<div class="formula-row alt">$\\cos(\\alpha - \\beta) = \\cos\\alpha\\cos\\beta + \\sin\\alpha\\sin\\beta$</div>'
+ '</div>'
+ '<div class="formula-section">'
+ '<div class="formula-section-title">Тангенсы</div>'
+ '<div class="formula-row">$\\tg(\\alpha + \\beta) = \\dfrac{\\tg\\alpha + \\tg\\beta}{1 - \\tg\\alpha \\, \\tg\\beta}$</div>'
+ '<div class="formula-row">$\\tg(\\alpha - \\beta) = \\dfrac{\\tg\\alpha - \\tg\\beta}{1 + \\tg\\alpha \\, \\tg\\beta}$</div>'
+ '</div>'
+ '</div>';
html += makeCard('rule', 'Формулы синуса и косинуса суммы/разности', '10.1', `
<p>Сложение углов в тригонометрии — это четыре формулы. Их нужно знать наизусть.</p>
<div class="svg-host">${svgFormulas}</div>
<p><b>Мнемоника:</b></p>
<ul style="padding-left:22px;line-height:1.85">
<li>В формулах <b>для sin</b> — знаки совпадают: $+ \\Rightarrow +$, $- \\Rightarrow -$.</li>
<li>В формулах <b>для cos</b> — знаки чередуются: $+ \\Rightarrow -$, $- \\Rightarrow +$.</li>
<li>В обеих формулах sin — структура «sin·cos + cos·sin»; в cos — «cos·cos $\\mp$ sin·sin».</li>
</ul>`);
html += makeCard('rule', 'Формулы тангенса', '10.2', `
<p>Тангенс суммы и разности выводятся делением sin на cos:</p>
<p style="text-align:center;font-size:1.1rem;margin:10px 0">$\\tg(\\alpha + \\beta) = \\dfrac{\\tg\\alpha + \\tg\\beta}{1 - \\tg\\alpha \\tg\\beta}$</p>
<p style="text-align:center;font-size:1.1rem;margin:10px 0">$\\tg(\\alpha - \\beta) = \\dfrac{\\tg\\alpha - \\tg\\beta}{1 + \\tg\\alpha \\tg\\beta}$</p>
<p>ОДЗ: $\\tg\\alpha$, $\\tg\\beta$ существуют, и знаменатель $\\ne 0$.</p>`);
html += makeCard('example', 'Применение для нестандартных углов', '10.3', `
<p>Многие «неудобные» углы — это суммы или разности из таблицы:</p>
<ul style="padding-left:22px;line-height:1.9">
<li><b>$75° = 45° + 30°$</b></li>
<li><b>$15° = 45° - 30°$</b></li>
<li><b>$105° = 60° + 45°$</b></li>
</ul>
<p><b>Пример. Вычисли $\\sin 75°$.</b></p>
<p>$\\sin 75° = \\sin(45° + 30°) = \\sin 45° \\cos 30° + \\cos 45° \\sin 30°$</p>
<p>$= \\dfrac{\\sqrt{2}}{2} \\cdot \\dfrac{\\sqrt{3}}{2} + \\dfrac{\\sqrt{2}}{2} \\cdot \\dfrac{1}{2} = \\dfrac{\\sqrt{6}}{4} + \\dfrac{\\sqrt{2}}{4} = \\dfrac{\\sqrt{6} + \\sqrt{2}}{4}$.</p>`);
html += makeCard('theory', 'Доказательство для cos(α − β)', '10.4', `
<details class="spoiler"><summary>Развернуть классическое доказательство</summary>
<div class="spoiler-body">
<p>Рассмотрим на единичной окружности точки $P_\\alpha = (\\cos\\alpha;\\sin\\alpha)$ и $P_\\beta = (\\cos\\beta;\\sin\\beta)$.</p>
<p>Квадрат расстояния между ними: $|P_\\alpha P_\\beta|^2 = (\\cos\\alpha - \\cos\\beta)^2 + (\\sin\\alpha - \\sin\\beta)^2 =$ $2 - 2(\\cos\\alpha\\cos\\beta + \\sin\\alpha\\sin\\beta)$.</p>
<p>С другой стороны, по теореме косинусов для треугольника $OP_\\alpha P_\\beta$ ($OP_\\alpha = OP_\\beta = 1$, угол между ними $\\alpha - \\beta$):</p>
<p>$|P_\\alpha P_\\beta|^2 = 1 + 1 - 2\\cos(\\alpha - \\beta) = 2 - 2\\cos(\\alpha - \\beta)$.</p>
<p>Приравниваем правые части и сокращаем: $\\cos(\\alpha - \\beta) = \\cos\\alpha\\cos\\beta + \\sin\\alpha\\sin\\beta$. ■</p>
<p>Остальные формулы выводятся отсюда заменой $\\beta \\to -\\beta$ и формулами приведения.</p>
</div></details>`);
/* === ИНТЕРАКТИВ 1: Вычисли нестандартный угол === */
html += '<div class="wg" id="p10-iv1">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Вычисли значение</div></div>'
+'<div class="wg-help">Разложи угол на сумму/разность табличных и применяй формулы сложения.</div>'
+trainerHTML('p10-iv1', 6, 'значение')
+'</div>';
/* === ИНТЕРАКТИВ 2: Упрости === */
html += '<div class="wg" id="p10-iv2">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Упрости / найди значение</div></div>'
+'<div class="wg-help">Используй формулы для свёртки выражения.</div>'
+trainerHTML('p10-iv2', 5, 'результат')
+'</div>';
/* === БОСС === */
html += '<h3 style="font-family:Unbounded,sans-serif;font-size:1.05rem;color:var(--pri2);margin:20px 0 12px">Босс §10 — Сумма и разность углов</h3>';
html += makeBoss('p10', {
color:'#0d9488',
title:'Босс §10 — Сумма и разность',
steps:[
{ q:'Чему равно $\\sin(\\alpha + \\beta) - \\sin(\\alpha - \\beta)$? Введи в виде "2sinX·cosY", т.е. цифру (коэффициент перед $\\cos\\alpha\\sin\\beta$).', verify:(v)=>+v===2, hint:'Раскрой обе формулы — выживет $2\\cos\\alpha\\sin\\beta$.' },
{ q:'Вычисли $\\cos 15° = \\dfrac{\\sqrt{6}+\\sqrt{2}}{?}$. Чему равен знаменатель?', verify:(v)=>+v===4, hint:'$\\cos 15° = \\cos(45° - 30°) = \\frac{\\sqrt{6}+\\sqrt{2}}{4}$.' },
{ q:'Если $\\sin\\alpha = 3/5$ (I четв.), найди $\\sin(\\alpha + \\frac{\\pi}{2})$. (Введи дробь например 4/5)', verify:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='4/5'||+v===0.8;}, hint:'$\\sin(\\alpha + \\pi/2) = \\cos\\alpha = 4/5$.' },
{ q:'$\\sin(\\alpha + \\pi) = ?$ Введи: «sin a», «-sin a», «cos a», «-cos a».', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-sina'||s==='-sin(a)'||s==='-sinα';}, hint:'По формуле или приведению: $-\\sin\\alpha$.' },
{ q:'$\\tg(45° + 45°) = ?$ (Введи число, $\\infty$ напиши как 9999)', verify:(v)=>+v===9999, hint:'$\\tg 90°$ не существует ($\\to \\infty$).' },
]
});
html += secNav('p9', 'p11') + readButton('p10');
box.innerHTML = html; renderMath(box);
/* IV1 */
makeTrainer({
idPrefix:'p10-iv1',
parser:(v)=>v,
questions:[
{ q:'$\\sin 75° = \\dfrac{\\sqrt{6}+\\sqrt{2}}{?}$. Знаменатель?', a:(v)=>+v===4, show:'$4$' },
{ q:'$\\cos 75° = \\dfrac{\\sqrt{6}-\\sqrt{2}}{?}$. Знаменатель?', a:(v)=>+v===4, show:'$4$' },
{ q:'$\\sin(45° + 45°) = ?$', a:(v)=>+v===1, show:'$1$' },
{ q:'$\\cos(60° - 60°) = ?$', a:(v)=>+v===1, show:'$1$' },
{ q:'$\\sin 30° \\cos 30° + \\cos 30° \\sin 30° = ?$ (используй формулу sin($60°$))', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='sqrt3/2'||s==='√3/2'||Math.abs(+v - Math.sqrt(3)/2)<0.02;}, show:'$\\sin 60° = \\sqrt{3}/2$' },
{ q:'$\\cos(\\alpha + \\beta) + \\cos(\\alpha - \\beta) = ?$ (как 2cos·cos: введи 2cosα·cosβ — целое число коэф.)', a:(v)=>+v===2, show:'$2\\cos\\alpha\\cos\\beta$ — коэф. 2' },
],
onComplete:(s,n)=>{ if(s===n){addXp(18,'p10-iv1');bumpProgress('p10',32);} else if(s>=3){addXp(9,'p10-iv1');bumpProgress('p10',14);} }
});
/* IV2 */
makeTrainer({
idPrefix:'p10-iv2',
parser:(v)=>v,
questions:[
{ q:'Если $\\sin\\alpha = 3/5$ ($\\alpha$ в I четв.), то $\\sin(\\alpha + \\pi/6) = ?$ (введи (3sqrt3+4)/10)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='(3sqrt3+4)/10'||Math.abs(+v - (3*Math.sqrt(3)+4)/10)<0.02;}, show:'$(3\\sqrt{3}+4)/10$' },
{ q:'$\\tg(45° + 30°) = ?$ (введи (sqrt3+1)/(sqrt3-1) или 2+sqrt3)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='2+sqrt3'||s==='2+√3'||Math.abs(+v - (2+Math.sqrt(3)))<0.02;}, show:'$2+\\sqrt{3}$' },
{ q:'$\\sin(\\alpha + \\beta)\\cos\\beta - \\cos(\\alpha + \\beta)\\sin\\beta = ?$ Введи как «sin a» (сократись по обратной формуле!)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='sina'||s==='sin(a)'||s==='sinα';}, show:'$\\sin\\alpha$' },
{ q:'$\\cos 50° \\cos 10° + \\sin 50° \\sin 10° = ?$ (введи как cos40 или 0.766)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='cos40'||Math.abs(+v - Math.cos(40*Math.PI/180))<0.02;}, show:'$\\cos 40°$' },
{ q:'$\\sin 105° = \\dfrac{\\sqrt{6}+\\sqrt{2}}{?}$. Знаменатель?', a:(v)=>+v===4, show:'$4$ ($\\sin 105° = \\sin 75°$, потому что $105° = 180° - 75°$)' },
],
onComplete:(s,n)=>{ if(s===n){addXp(18,'p10-iv2');bumpProgress('p10',32);} else if(s>=3){addXp(9,'p10-iv2');bumpProgress('p10',14);} }
});
wireReadBtn('p10');
}
/* ============================================================
§ 11 — Формулы двойного аргумента
============================================================ */
function buildP11(){
const box = document.getElementById('p11-body');
const A = window.ALG10;
let html = '';
/* === SVG: α и 2α на единичной окружности (только геометрия) === */
let svgDouble = '';
if(A){
const c = A.tri.canvas({id:'p11-d', W:380, H:360, R:130});
const ang = 30 * Math.PI / 180; /* α = 30° */
const ang2 = 60 * Math.PI / 180; /* 2α = 60° */
const p1 = c.pointPx(ang);
const p2 = c.pointPx(ang2);
let s = c.open
/* === Заголовочная плашка === */
+ '<rect x="0" y="0" width="'+c.W+'" height="44" fill="rgba(13,148,136,.10)"/>'
+ '<text x="'+(c.W/2)+'" y="22" text-anchor="middle" font-size="13" font-family="Unbounded,Inter,sans-serif" font-weight="800" fill="#0d9488">УГОЛ α И ДВОЙНОЙ УГОЛ 2α</text>'
+ '<text x="'+(c.W/2)+'" y="38" text-anchor="middle" font-size="10" font-family="Inter,sans-serif" font-style="italic" fill="#64748b">Пример: α = 30°, 2α = 60°</text>'
/* === Оси и окружность === */
+ c.axes()
+ c.circle({width:2.5})
/* === Сектор 2α (фиолетовый пунктирный, под α) === */
+ '<path d="M '+c.cx+' '+c.cy+' L '+(c.cx+65)+' '+c.cy+' A 65 65 0 0 0 '+(c.cx + 65*Math.cos(ang2))+' '+(c.cy - 65*Math.sin(ang2))+' Z" fill="rgba(124,58,237,.14)" stroke="#7c3aed" stroke-width="1.5" stroke-dasharray="4 2"/>'
/* === Сектор α (бирюзовый, поверх) === */
+ '<path d="M '+c.cx+' '+c.cy+' L '+(c.cx+36)+' '+c.cy+' A 36 36 0 0 0 '+(c.cx + 36*Math.cos(ang))+' '+(c.cy - 36*Math.sin(ang))+' Z" fill="rgba(13,148,136,.30)" stroke="#0d9488" stroke-width="1.5"/>'
/* === Подписи углов внутри секторов === */
+ '<text x="'+(c.cx + 48*Math.cos(ang/2))+'" y="'+(c.cy - 48*Math.sin(ang/2) + 4)+'" text-anchor="middle" font-size="13" font-family="Unbounded,Inter,sans-serif" font-weight="800" fill="#0f766e">α</text>'
+ '<text x="'+(c.cx + 77*Math.cos(ang2/2))+'" y="'+(c.cy - 77*Math.sin(ang2/2) + 4)+'" text-anchor="middle" font-size="13" font-family="Unbounded,Inter,sans-serif" font-weight="800" fill="#6d28d9">2α</text>'
/* === Радиусы === */
+ c.radius(ang, {color:'#0d9488', width:2.8})
+ c.radius(ang2, {color:'#7c3aed', width:2.8})
/* === Точки P_α и P_{2α} (рисуем вручную, чтобы подписи не наезжали на оси) === */
+ '<circle cx="'+p1.px+'" cy="'+p1.py+'" r="5" fill="#0d9488" stroke="#fff" stroke-width="2"/>'
+ '<circle cx="'+p2.px+'" cy="'+p2.py+'" r="5" fill="#7c3aed" stroke="#fff" stroke-width="2"/>'
/* P_α — подпись справа-сверху от точки (она в правом нижнем углу I четверти) */
+ '<text x="'+(p1.px + 14)+'" y="'+(p1.py - 10)+'" font-size="13" font-family="Unbounded,Inter,sans-serif" font-weight="800" fill="#0f766e">P(α)</text>'
/* P_{2α} — подпись справа от точки (она ближе к верху), уводим вправо чтобы не пересечь "1" на оси y */
+ '<text x="'+(p2.px + 14)+'" y="'+(p2.py + 4)+'" font-size="13" font-family="Unbounded,Inter,sans-serif" font-weight="800" fill="#6d28d9">P(2α)</text>'
+ c.close;
svgDouble = s;
}
/* === Плакат: 3 формулы двойного аргумента (HTML + KaTeX) === */
const plateDouble = '<div class="formula-plate">'
+ '<div class="formula-plate-head teal">'
+ '<div class="formula-plate-title">3 формулы двойного аргумента</div>'
+ '<div class="formula-plate-sub">это частный случай формул сложения при $\\beta = \\alpha$</div>'
+ '</div>'
+ '<div class="formula-plate-body">'
+ '<div class="formula-row">$\\sin 2\\alpha = 2\\sin\\alpha \\cos\\alpha$</div>'
+ '<div class="formula-row alt">$\\cos 2\\alpha = \\cos^2\\alpha - \\sin^2\\alpha = 1 - 2\\sin^2\\alpha = 2\\cos^2\\alpha - 1$</div>'
+ '<div class="formula-row alt2">$\\tg 2\\alpha = \\dfrac{2\\tg\\alpha}{1 - \\tg^2\\alpha}$</div>'
+ '</div>'
+ '</div>';
html += makeCard('rule', 'Формулы двойного аргумента', '11.1', `
${plateDouble}
<div class="svg-host">${svgDouble}</div>
<p><b>Вывод.</b> $\\sin 2\\alpha = \\sin(\\alpha + \\alpha) = \\sin\\alpha\\cos\\alpha + \\cos\\alpha\\sin\\alpha = 2\\sin\\alpha\\cos\\alpha$. Аналогично для $\\cos 2\\alpha$ и $\\tg 2\\alpha$.</p>`);
html += makeCard('rule', 'Три формы для cos 2α', '11.2', `
<p>Используя $\\sin^2\\alpha + \\cos^2\\alpha = 1$, переписываем по-разному:</p>
<p style="text-align:center;font-size:1.05rem;margin:8px 0">$\\cos 2\\alpha = \\cos^2\\alpha - \\sin^2\\alpha$</p>
<p style="text-align:center;font-size:1.05rem;margin:8px 0">$\\cos 2\\alpha = 1 - 2\\sin^2\\alpha$</p>
<p style="text-align:center;font-size:1.05rem;margin:8px 0">$\\cos 2\\alpha = 2\\cos^2\\alpha - 1$</p>
<p><b>Когда какую использовать:</b></p>
<ul style="padding-left:22px;line-height:1.85">
<li>Если дано $\\sin\\alpha$ — бери <b>$1 - 2\\sin^2\\alpha$</b>.</li>
<li>Если дано $\\cos\\alpha$ — бери <b>$2\\cos^2\\alpha - 1$</b>.</li>
<li>Для упрощения выражений (например, разложения на множители) — бери <b>$\\cos^2 - \\sin^2$</b>.</li>
</ul>`);
html += makeCard('rule', 'Формулы понижения степени', '11.3', `
<p>Из формул для cos 2α выражаем sin² и cos²:</p>
<p style="background:var(--sec-acc-soft);padding:10px 14px;border-radius:8px;font-size:1.1rem;text-align:center"><b>$\\sin^2\\alpha = \\dfrac{1 - \\cos 2\\alpha}{2}$</b></p>
<p style="background:var(--sec-acc-soft);padding:10px 14px;border-radius:8px;font-size:1.1rem;text-align:center"><b>$\\cos^2\\alpha = \\dfrac{1 + \\cos 2\\alpha}{2}$</b></p>
<p>Это нужно, когда мы хотим избавиться от квадратов синуса/косинуса (например, в интегралах или для упрощения).</p>`);
html += makeCard('example', 'Применение', '11.4', `
<p><b>Задача 1.</b> $\\sin\\alpha = \\dfrac{3}{5}$, $\\alpha$ в I четверти. Найди $\\sin 2\\alpha$ и $\\cos 2\\alpha$.</p>
<p>$\\cos\\alpha = \\sqrt{1 - 9/25} = \\dfrac{4}{5}$.</p>
<p>$\\sin 2\\alpha = 2 \\cdot \\dfrac{3}{5} \\cdot \\dfrac{4}{5} = \\dfrac{24}{25}$.</p>
<p>$\\cos 2\\alpha = 1 - 2 \\cdot \\dfrac{9}{25} = 1 - \\dfrac{18}{25} = \\dfrac{7}{25}$.</p>
<p><b>Задача 2.</b> Упрости $\\sin 4x - \\sin 2x$, заменив $\\sin 4x$ через $\\sin 2 \\cdot 2x$.</p>
<p>$\\sin 4x = 2\\sin 2x\\cos 2x$, тогда $\\sin 4x - \\sin 2x = \\sin 2x(2\\cos 2x - 1)$.</p>`);
/* === ИНТЕРАКТИВ 1: Вычисли по данной cos α === */
html += '<div class="wg" id="p11-iv1">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Найди sin 2α, cos 2α по данным</div></div>'
+'<div class="wg-help">Дано: один из sin α / cos α + четверть. Найди указанную величину.</div>'
+trainerHTML('p11-iv1', 6, 'дробь')
+'</div>';
/* === ИНТЕРАКТИВ 2: Упрости === */
html += '<div class="wg" id="p11-iv2">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Упрости с двойным углом</div></div>'
+'<div class="wg-help">Свёртывай или раскрывай 2α там, где удобно.</div>'
+trainerHTML('p11-iv2', 5, 'результат')
+'</div>';
/* === БОСС === */
html += '<h3 style="font-family:Unbounded,sans-serif;font-size:1.05rem;color:var(--pri2);margin:20px 0 12px">Босс §11 — Двойной аргумент</h3>';
html += makeBoss('p11', {
color:'#0f766e',
title:'Босс §11 — Двойной аргумент',
steps:[
{ q:'Чему равно $2\\sin 15° \\cos 15°$? (Введи дробь как 1/2)', verify:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='1/2'||+v===0.5;}, hint:'Это $\\sin 30° = 1/2$.' },
{ q:'Если $\\sin\\alpha = 0{,}6$, найди $\\cos 2\\alpha$. (введи 0.28)', verify:(v)=>Math.abs(+v - 0.28)<0.01, hint:'$\\cos 2\\alpha = 1 - 2(0.6)^2 = 1 - 0.72 = 0.28$.' },
{ q:'Сколько решений у $\\sin 2x = 0$ на $[0;\\,\\pi]$?', verify:(v)=>+v===3, hint:'$2x = \\pi n$ ⇒ $x = 0, \\pi/2, \\pi$ — 3 значения.' },
{ q:'Чему равно $\\dfrac{1 - \\cos 2\\alpha}{2}$? Введи слово: «sin²» или «cos²».', verify:(v)=>{const s=String(v).replace(/[\\s²]/g,'').toLowerCase(); return s==='sin2'||s==='sin';}, hint:'Формула понижения для $\\sin^2$.' },
{ q:'Если $\\cos\\alpha = -4/5$, $\\alpha$ во II четв., найди $\\sin 2\\alpha$ (введи как -24/25 или -0.96)', verify:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='-24/25'||Math.abs(+v - (-0.96))<0.01;}, hint:'$\\sin\\alpha = 3/5$ (sin > 0 во II четв.), $\\sin 2\\alpha = 2 \\cdot 3/5 \\cdot (-4/5) = -24/25$.' },
]
});
html += secNav('p10', 'p12') + readButton('p11');
box.innerHTML = html; renderMath(box);
/* IV1 */
makeTrainer({
idPrefix:'p11-iv1',
parser:(v)=>v,
questions:[
{ q:'$\\sin\\alpha = 3/5$, $\\alpha$ в I четв. Найди $\\sin 2\\alpha$.', a:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='24/25'||+v===0.96;}, show:'$24/25 = 0{,}96$' },
{ q:'$\\sin\\alpha = 3/5$, $\\alpha$ в I четв. Найди $\\cos 2\\alpha$.', a:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='7/25'||+v===0.28;}, show:'$7/25 = 0{,}28$' },
{ q:'$\\cos\\alpha = 3/5$, $\\alpha$ в I четв. Найди $\\cos 2\\alpha$.', a:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='-7/25'||+v===-0.28;}, show:'$-7/25 = -0{,}28$' },
{ q:'$\\sin\\alpha = -1/3$, $\\alpha$ в III четв. Найди $\\cos 2\\alpha$ (введи 7/9)', a:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='7/9'||Math.abs(+v - 7/9)<0.01;}, show:'$7/9$' },
{ q:'$\\tg\\alpha = 2$. Найди $\\tg 2\\alpha$ (введи -4/3)', a:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='-4/3'||Math.abs(+v - (-4/3))<0.02;}, show:'$-4/3$' },
{ q:'$\\sin\\alpha = 0{,}8$, $\\alpha$ во II четв. Найди $\\sin 2\\alpha$ (-0.96)', a:(v)=>Math.abs(+v - (-0.96))<0.02, show:'$-0{,}96$' },
],
onComplete:(s,n)=>{ if(s===n){addXp(20,'p11-iv1');bumpProgress('p11',32);} else if(s>=4){addXp(10,'p11-iv1');bumpProgress('p11',15);} }
});
/* IV2 */
makeTrainer({
idPrefix:'p11-iv2',
parser:(v)=>v,
questions:[
{ q:'Чему равно $2\\sin 22{,}5° \\cos 22{,}5°$? (введи sqrt2/2 или 0.71)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='sqrt2/2'||s==='√2/2'||Math.abs(+v - Math.sqrt(2)/2)<0.02;}, show:'$\\sqrt{2}/2$ ($\\sin 45°$)' },
{ q:'$1 - 2\\sin^2 15° = ?$ (введи sqrt3/2)', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='sqrt3/2'||s==='√3/2'||Math.abs(+v - Math.sqrt(3)/2)<0.02;}, show:'$\\sqrt{3}/2$ ($\\cos 30°$)' },
{ q:'$\\dfrac{\\sin 2\\alpha}{2\\sin\\alpha} = ?$ Введи как «cos a».', a:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='cosa'||s==='cos(a)'||s==='cosα';}, show:'$\\cos\\alpha$' },
{ q:'$\\cos^2 30° - \\sin^2 30° = ?$ (введи 1/2)', a:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='1/2'||+v===0.5;}, show:'$1/2$ ($\\cos 60° = 1/2$)' },
{ q:'$\\sin 100°\\cos 10° + \\cos 100°\\sin 10° = \\sin ?°$. Чему равен угол?', a:(v)=>+v===110, show:'$110°$ ($\\sin 110°$)' },
],
onComplete:(s,n)=>{ if(s===n){addXp(18,'p11-iv2');bumpProgress('p11',30);} else if(s>=3){addXp(9,'p11-iv2');bumpProgress('p11',14);} }
});
wireReadBtn('p11');
}
/* ============================================================
§ 12 — Преобразование суммы (разности) в произведение
============================================================ */
function buildP12(){
const box = document.getElementById('p12-body');
let html = '';
const svgFormulas = '<div class="formula-plate">'
+ '<div class="formula-plate-head violet">'
+ '<div class="formula-plate-title">4 формулы: сумма → произведение</div>'
+ '<div class="formula-plate-sub">структура: 2 · функция полусуммы · функция полуразности</div>'
+ '</div>'
+ '<div class="formula-plate-body">'
+ '<div class="formula-row">$\\sin\\alpha + \\sin\\beta = 2 \\sin\\dfrac{\\alpha+\\beta}{2} \\cos\\dfrac{\\alpha-\\beta}{2}$</div>'
+ '<div class="formula-row">$\\sin\\alpha - \\sin\\beta = 2 \\sin\\dfrac{\\alpha-\\beta}{2} \\cos\\dfrac{\\alpha+\\beta}{2}$</div>'
+ '<div class="formula-row alt2">$\\cos\\alpha + \\cos\\beta = 2 \\cos\\dfrac{\\alpha+\\beta}{2} \\cos\\dfrac{\\alpha-\\beta}{2}$</div>'
+ '<div class="formula-row danger">$\\cos\\alpha - \\cos\\beta = -2 \\sin\\dfrac{\\alpha+\\beta}{2} \\sin\\dfrac{\\alpha-\\beta}{2}$</div>'
+ '</div>'
+ '<div class="formula-mnem">'
+ '<div class="formula-mnem-title">Мнемоника</div>'
+ '<ul>'
+ '<li><b>$\\sin \\pm \\sin \\to \\sin \\cdot \\cos$</b> (порядок «полусуммы/полуразности» зависит от знака)</li>'
+ '<li><b>$\\cos + \\cos \\to \\cos \\cdot \\cos$</b>, &nbsp; <b>$\\cos - \\cos \\to -\\sin \\cdot \\sin$</b> (минус снаружи!)</li>'
+ '</ul>'
+ '</div>'
+ '</div>';
html += makeCard('rule', '4 формулы преобразования', '12.1', `
<p>Эти формулы превращают <b>сумму</b> (или разность) тригонометрических функций в <b>произведение</b>.</p>
<div class="svg-host">${svgFormulas}</div>
<p>Они полезны для:</p>
<ul style="padding-left:22px;line-height:1.85">
<li>Решения уравнений вида $\\sin 3x + \\sin x = 0$ — разложение на множители.</li>
<li>Упрощения выражений и доказательства тождеств.</li>
<li>Численного вычисления некоторых углов.</li>
</ul>`);
html += makeCard('example', 'Применение для уравнения', '12.2', `
<p><b>Решим</b> $\\sin 3x + \\sin x = 0$.</p>
<p>$\\sin 3x + \\sin x = 2\\sin\\dfrac{3x + x}{2} \\cos\\dfrac{3x - x}{2} = 2\\sin 2x \\cos x$.</p>
<p>Получили $2\\sin 2x \\cos x = 0$ ⇒ $\\sin 2x = 0$ или $\\cos x = 0$.</p>
<ul style="padding-left:22px;line-height:1.9">
<li>$\\sin 2x = 0$ ⇒ $x = \\dfrac{\\pi n}{2}$.</li>
<li>$\\cos x = 0$ ⇒ $x = \\dfrac{\\pi}{2} + \\pi n$.</li>
</ul>
<p>Заметим: вторая серия — частный случай первой ($n = 2k+1$), поэтому общее решение: $x = \\dfrac{\\pi n}{2}$, $n \\in \\mathbb{Z}$.</p>`);
html += makeCard('example', 'Применение для упрощения', '12.3', `
<p><b>Упрости</b> $\\dfrac{\\sin 5x + \\sin 3x}{\\cos 5x + \\cos 3x}$.</p>
<p>Числитель: $\\sin 5x + \\sin 3x = 2\\sin 4x \\cos x$.</p>
<p>Знаменатель: $\\cos 5x + \\cos 3x = 2\\cos 4x \\cos x$.</p>
<p>$\\dfrac{2\\sin 4x \\cos x}{2\\cos 4x \\cos x} = \\dfrac{\\sin 4x}{\\cos 4x} = \\tg 4x$.</p>`);
/* === ИНТЕРАКТИВ 1: преобразуй === */
html += '<div class="wg" id="p12-iv1">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Преобразуй в произведение</div></div>'
+'<div class="wg-help">Введи результат в виде «2sinX·cosY» — числа X и Y (углы или функции от x).</div>'
+trainerHTML('p12-iv1', 5, 'результат')
+'</div>';
/* === ИНТЕРАКТИВ 2: реши уравнение === */
html += '<div class="wg" id="p12-iv2">'
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Реши уравнение методом</div></div>'
+'<div class="wg-help">Преобразуй сумму/разность в произведение и реши.</div>'
+trainerHTML('p12-iv2', 4, 'число корней')
+'</div>';
/* === БОСС === */
html += '<h3 style="font-family:Unbounded,sans-serif;font-size:1.05rem;color:var(--pri2);margin:20px 0 12px">Босс §12 — Сумма → произведение</h3>';
html += makeBoss('p12', {
color:'#7c3aed',
title:'Босс §12 — Сумма в произведение',
steps:[
{ q:'$\\sin 30° + \\sin 90° = 2\\sin 60° \\cos 30° = ?$ (введи 3/2)', verify:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='3/2'||+v===1.5;}, hint:'$2 \\cdot \\frac{\\sqrt{3}}{2} \\cdot \\frac{\\sqrt{3}}{2} = \\frac{3}{2}$.' },
{ q:'Сколько корней у $\\sin 3x + \\sin x = 0$ на $[0;\\,2\\pi)$?', verify:(v)=>+v===4, hint:'$2\\sin 2x \\cos x = 0$. $\\sin 2x = 0$: 0, π/2, π, 3π/2 (4 шт). $\\cos x = 0$: π/2, 3π/2 — уже учтены. Итого 4.' },
{ q:'Чему равно $\\dfrac{\\sin 5x + \\sin x}{\\cos 5x + \\cos x}$? Введи как «tg X», где X = коэффициент при x.', verify:(v)=>+v===3, hint:'$\\frac{2\\sin 3x \\cos 2x}{2\\cos 3x \\cos 2x} = \\tg 3x$.' },
{ q:'$\\cos 80° + \\cos 20° = 2\\cos 50° \\cos 30°$. Чему равно $\\cos 50° \\cdot \\dfrac{\\sqrt{3}}{?}$? (введи 1)', verify:(v)=>+v===1, hint:'$\\cos 80° + \\cos 20° = 2\\cos 50° \\cdot \\frac{\\sqrt{3}}{2} = \\sqrt{3}\\cos 50°$. То есть с коэф. $\\sqrt{3}/1$.' },
]
});
html += secNav('p11', 'final1') + readButton('p12');
box.innerHTML = html; renderMath(box);
/* IV1 */
makeTrainer({
idPrefix:'p12-iv1',
parser:(v)=>v,
questions:[
{ q:'$\\sin 80° + \\sin 40° = 2\\sin 60° \\cos ?°$. Введи угол.', a:(v)=>+v===20, show:'$20°$' },
{ q:'$\\sin 50° - \\sin 20° = 2\\sin 15° \\cos ?°$. Введи угол.', a:(v)=>+v===35, show:'$35°$' },
{ q:'$\\cos 70° + \\cos 10° = 2\\cos ?° \\cos 30°$. Введи угол.', a:(v)=>+v===40, show:'$40°$' },
{ q:'$\\sin 3x + \\sin x = 2\\sin ?x \\cos x$. Введи коэф.', a:(v)=>+v===2, show:'$2$ ($2\\sin 2x \\cos x$)' },
{ q:'$\\cos 5x - \\cos x = -2\\sin 3x \\sin ?x$. Введи коэф.', a:(v)=>+v===2, show:'$2$ ($-2\\sin 3x \\sin 2x$)' },
],
onComplete:(s,n)=>{ if(s===n){addXp(18,'p12-iv1');bumpProgress('p12',32);} else if(s>=3){addXp(9,'p12-iv1');bumpProgress('p12',14);} }
});
/* IV2 */
makeTrainer({
idPrefix:'p12-iv2',
questions:[
{ q:'Сколько корней у $\\sin 2x + \\sin 4x = 0$ на $[0;\\,\\pi)$?', a:3, show:'3 ($2\\sin 3x \\cos x = 0$: $\\sin 3x = 0$ ⇒ 0, π/3, 2π/3; $\\cos x = 0$ ⇒ π/2)' },
{ q:'Сколько корней у $\\cos x - \\cos 3x = 0$ на $[0;\\,2\\pi)$?', a:4, show:'4 ($2\\sin 2x \\sin x = 0$: $\\sin 2x = 0$ ⇒ 0, π/2, π, 3π/2 (4 шт); $\\sin x = 0$ ⇒ уже учтено)' },
{ q:'Сколько корней у $\\sin x + \\cos x = 0$ на $[0;\\,2\\pi)$? (используй $\\cos x = \\sin(\\pi/2 - x)$)', a:2, show:'2 ($\\tg x = -1$ ⇒ $x = 3\\pi/4, 7\\pi/4$)' },
{ q:'Сколько корней у $\\sin 5x = \\sin x$ на $[0;\\,\\pi)$?', a:5, show:'5 (через $\\sin 5x - \\sin x = 0$ ⇒ $2\\sin 2x \\cos 3x = 0$, серии комбинируются)' },
],
onComplete:(s,n)=>{ if(s===n){addXp(20,'p12-iv2');bumpProgress('p12',35);} else if(s>=2){addXp(10,'p12-iv2');bumpProgress('p12',16);} }
});
wireReadBtn('p12');
}
/* ============================================================
ФИНАЛ ГЛАВЫ 1 — 6 интегрированных боссов
============================================================ */
const FINAL1_BOSSES = [
{
n:1, tag:'§ 14',
title:'Окружность, sin/cos, tg/ctg, тождества',
color:'#0d9488',
steps:[
{ q:'Преобразуй $240°$ в радианы. Введи как 4pi/3.', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='4pi/3'||s==='4π/3';}, hint:'$240 \\cdot \\pi / 180 = 4\\pi/3$.' },
{ q:'Найди $\\sin\\dfrac{\\pi}{4} \\cdot \\cos\\dfrac{\\pi}{4}$. Введи как 1/2.', verify:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='1/2'||+v===0.5;}, hint:'$(\\sqrt{2}/2)^2 = 1/2$.' },
{ q:'В какой четверти $\\tg\\alpha > 0$ <b>и</b> $\\cos\\alpha < 0$? (1/2/3/4)', verify:(v)=>+v===3, hint:'tg > 0: I или III; cos < 0: II или III. Пересечение — III.' },
{ q:'$\\sin^2 30° + \\cos^2 60° = ?$ Введи 1/2.', verify:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='1/2'||+v===0.5;}, hint:'$(1/2)^2 + (1/2)^2 = 1/4 + 1/4$.' },
{ q:'$\\sin\\alpha = -3/5$, $\\alpha \\in (\\pi;\\,3\\pi/2)$. Найди $\\tg\\alpha$ (введи 3/4).', verify:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='3/4'||+v===0.75;}, hint:'cos = -4/5 (III четв.), tg = sin/cos = (-3/5)/(-4/5) = 3/4.' },
]
},
{
n:2, tag:'§ 57',
title:'Графики, обратные функции',
color:'#0891b2',
steps:[
{ q:'Период функции $y = \\sin 3x$. Введи как 2pi/n.', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='2pi/3'||s==='2π/3';}, hint:'$T = 2\\pi / 3$.' },
{ q:'$y = \\cos x$ — чётная или нечётная? Введи слово.', verify:(v)=>String(v).trim().toLowerCase().startsWith('чёт')||String(v).trim().toLowerCase().startsWith('чет'), hint:'$\\cos(-x) = \\cos x$.' },
{ q:'Наибольшее значение функции $y = 3\\sin x - 1$?', verify:(v)=>+v===2, hint:'При $\\sin x = 1$: $3 - 1 = 2$.' },
{ q:'$\\arcsin(-1) = ?$ Введи как -pi/2.', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-pi/2'||s==='-π/2';}, hint:'$\\sin(-\\pi/2) = -1$.' },
{ q:'$\\arccos\\dfrac{\\sqrt{2}}{2} = ?$ Введи pi/4.', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/4'||s==='π/4';}, hint:'$\\cos(\\pi/4) = \\sqrt{2}/2$.' },
]
},
{
n:3, tag:'§ 8',
title:'Тригонометрические уравнения',
color:'#dc2626',
steps:[
{ q:'Сколько корней у $\\sin x = 0{,}5$ на $[0;\\,2\\pi]$?', verify:(v)=>+v===2, hint:'$\\pi/6$ и $5\\pi/6$.' },
{ q:'Реши $\\cos x = -1$. Корень в $[0;\\,2\\pi]$? Введи pi.', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi'||s==='π';}, hint:'$\\cos\\pi = -1$.' },
{ q:'$2\\sin^2 x - \\sin x - 1 = 0$. Сколько корней в $[0;\\,2\\pi)$?', verify:(v)=>+v===3, hint:'$t = \\sin x$: $2t^2 - t - 1 = 0$, $t = 1$ или $t = -1/2$. sin = 1: π/2 (1 корень). sin = -1/2: 7π/6, 11π/6 (2 корня). Итого 3.' },
{ q:'$\\tg x = \\sqrt{3}$. Наименьший положительный корень? Введи pi/n.', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='pi/3'||s==='π/3';}, hint:'$\\arctg\\sqrt{3} = \\pi/3$.' },
{ q:'$\\sin x \\cdot \\cos x = 0$. Сколько корней в $[0;\\,2\\pi)$?', verify:(v)=>+v===4, hint:'$\\sin x = 0$: 0, π. $\\cos x = 0$: π/2, 3π/2. Все различны — 4.' },
]
},
{
n:4, tag:'§ 9',
title:'Формулы приведения',
color:'#0e7490',
steps:[
{ q:'$\\sin(\\pi - \\alpha) = ?$ Введи: «sin a» или «-sin a».', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='sina'||s==='sin(a)'||s==='sinα';}, hint:'II четв., sin > 0; имя не меняется.' },
{ q:'$\\cos\\left(\\dfrac{\\pi}{2} + \\alpha\\right) = ?$ Введи «-sin a».', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-sina'||s==='-sin(a)'||s==='-sinα';}, hint:'II четв., cos < 0; имя меняется cos → sin.' },
{ q:'Вычисли $\\sin 150°$. Введи 1/2.', verify:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='1/2'||+v===0.5;}, hint:'$\\sin(180° - 30°) = \\sin 30° = 1/2$.' },
{ q:'Вычисли $\\cos 210°$. Введи -sqrt3/2.', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='-sqrt3/2'||s==='-√3/2'||Math.abs(+v - (-Math.sqrt(3)/2))<0.02;}, hint:'$\\cos(180° + 30°) = -\\cos 30°$.' },
{ q:'$\\tg\\left(\\dfrac{3\\pi}{2} - \\alpha\\right) = ?$ Введи «ctg a», «-ctg a» или «tg a».', verify:(v)=>{const s=String(v).replace(/\\s/g,'').toLowerCase(); return s==='ctga'||s==='ctg(a)'||s==='ctgα';}, hint:'III четв., tg > 0; имя меняется tg → ctg.' },
]
},
{
n:5, tag:'§ 1011',
title:'Сумма, разность, двойной аргумент',
color:'#0f766e',
steps:[
{ q:'$\\sin 75° = \\dfrac{\\sqrt{6} + \\sqrt{2}}{?}$ — введи знаменатель.', verify:(v)=>+v===4, hint:'$\\sin(45° + 30°) = \\sin 45 \\cos 30 + \\cos 45 \\sin 30$.' },
{ q:'$\\sin\\alpha = 3/5$, $\\alpha$ в I четв. Найди $\\sin 2\\alpha$ (введи 24/25).', verify:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='24/25'||+v===0.96;}, hint:'$\\cos\\alpha = 4/5$, $\\sin 2\\alpha = 2 \\cdot 3/5 \\cdot 4/5 = 24/25$.' },
{ q:'$\\cos^2 30° - \\sin^2 30° = ?$ Введи 1/2.', verify:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='1/2'||+v===0.5;}, hint:'Это $\\cos 60° = 1/2$.' },
{ q:'$\\tg(45° + 45°) = ?$ Введи 9999 (это $\\infty$).', verify:(v)=>+v===9999, hint:'$\\tg 90°$ не существует.' },
{ q:'$\\sin^2 22{,}5° = \\dfrac{1 - \\cos 45°}{?}$ — введи знаменатель.', verify:(v)=>+v===2, hint:'Формула понижения степени.' },
]
},
{
n:6, tag:'§ 12+',
title:'Финальный — синтез всех тем',
color:'#7c3aed',
steps:[
{ q:'$\\sin 3x + \\sin x = 2\\sin ?x \\cos x$. Введи коэф.', verify:(v)=>+v===2, hint:'$\\frac{3x+x}{2} = 2x$.' },
{ q:'$\\dfrac{\\sin 5x - \\sin x}{\\cos 5x + \\cos x} = \\tg ?x$. Введи коэф.', verify:(v)=>+v===2, hint:'Числитель: $2\\sin 2x \\cos 3x$. Знаменатель: $2\\cos 3x \\cos 2x$. Сокращаем — $\\tg 2x$.' },
{ q:'Сколько корней у $\\cos x = 0{,}5$ на $[-2\\pi;\\,2\\pi]$?', verify:(v)=>+v===4, hint:'$x = \\pm\\pi/3 + 2\\pi n$: $-5\\pi/3, -\\pi/3, \\pi/3, 5\\pi/3$ — 4 корня.' },
{ q:'$\\sin\\alpha = 0{,}6$, $\\alpha$ в I четв. Найди $\\cos 2\\alpha$ (введи 0.28).', verify:(v)=>Math.abs(+v - 0.28)<0.01, hint:'$\\cos 2\\alpha = 1 - 2 \\cdot 0{,}36 = 0{,}28$.' },
{ q:'Сколько <b>различных</b> точек $P_\\alpha$ на окружности при $\\alpha = \\dfrac{\\pi}{4}, \\dfrac{9\\pi}{4}, -\\dfrac{7\\pi}{4}, \\dfrac{17\\pi}{4}$?', verify:(v)=>+v===1, hint:'Все отличаются на $2\\pi k$, значит совпадают.' },
]
},
];
function buildFinal1(){
const box = document.getElementById('final1-body');
let html = '';
/* === Hero card === */
html += '<div style="background:linear-gradient(135deg,#0d9488,#7c3aed);color:#fff;border-radius:18px;padding:24px 22px;margin-bottom:24px;box-shadow:0 8px 28px rgba(13,148,136,.25);position:relative;overflow:hidden">'
+'<div style="position:absolute;right:-20px;top:-30px;font-size:8rem;font-weight:900;color:rgba(255,255,255,.1);font-family:Unbounded,sans-serif;line-height:1;pointer-events:none">&#9733;</div>'
+'<div style="position:relative;z-index:1">'
+'<div style="font-size:.78rem;font-weight:800;letter-spacing:.1em;text-transform:uppercase;opacity:.85;margin-bottom:6px">ФИНАЛ ГЛАВЫ 1</div>'
+'<h2 style="font-family:Unbounded,sans-serif;font-size:1.55rem;font-weight:800;margin-bottom:8px">6 интегрированных боссов</h2>'
+'<p style="font-size:.95rem;opacity:.92;margin-bottom:14px;max-width:580px">Каждый босс проверяет синтез нескольких параграфов главы. Победи всех — получи ачивку <b>«Магистр тригонометрии»</b> и +150 XP.</p>'
+'<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center">'
+'<div style="padding:8px 14px;background:rgba(255,255,255,.18);border-radius:99px;font-size:.82rem;font-weight:700">&#9733; 6 боссов</div>'
+'<div style="padding:8px 14px;background:rgba(255,255,255,.18);border-radius:99px;font-size:.82rem;font-weight:700">+ до 300 XP</div>'
+'<div style="padding:8px 14px;background:rgba(255,255,255,.18);border-radius:99px;font-size:.82rem;font-weight:700">&#9733; Финальная ачивка</div>'
+'</div></div></div>';
/* === Overall progress === */
html += '<div style="background:var(--card);border:1.5px solid var(--border);border-radius:14px;padding:16px 20px;margin-bottom:20px">'
+'<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:10px">'
+'<div style="font-family:Unbounded,sans-serif;font-size:.85rem;font-weight:800;color:var(--text);letter-spacing:.06em;text-transform:uppercase">Прогресс по боссам</div>'
+'<div id="final1-overall" style="font-size:.95rem;font-weight:700;color:var(--pri2)">0 / 6 побеждено</div>'
+'</div>'
+'<div style="height:12px;background:rgba(13,148,136,.12);border-radius:8px;overflow:hidden">'
+'<div id="final1-overall-fill" style="height:100%;width:0%;background:linear-gradient(90deg,#0d9488,#7c3aed);transition:width .6s cubic-bezier(.16,1,.3,1)"></div>'
+'</div></div>';
/* === Bosses container === */
html += '<div id="final1-bosses"></div>';
/* === Celebration === */
html += '<div id="final1-cel" style="display:none;margin:24px 0;padding:24px 22px;background:linear-gradient(135deg,#fef3c7,#fde68a);border:2px solid #f59e0b;border-radius:18px;text-align:center;box-shadow:0 6px 22px rgba(245,158,11,.25)">'
+'<div style="font-size:3rem;margin-bottom:6px">&#9733;</div>'
+'<div style="font-family:Unbounded,sans-serif;font-size:1.4rem;font-weight:900;color:#92400e;margin-bottom:6px">МАГИСТР ТРИГОНОМЕТРИИ!</div>'
+'<div style="font-size:.95rem;color:#78350f;margin-bottom:14px">Ты победил всех 6 боссов главы 1 и освоил тригонометрию.<br>Получено: <b>+150 XP</b> и финальная ачивка.</div>'
+'<a href="/textbook/algebra-10" style="display:inline-flex;align-items:center;gap:8px;padding:11px 22px;background:linear-gradient(135deg,#0d9488,#7c3aed);color:#fff;border-radius:11px;font-weight:700;text-decoration:none">Вернуться к Алгебре 10 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" style="width:16px;height:16px"><polyline points="9 18 15 12 9 6"/></svg></a>'
+'</div>';
html += secNav('p12', null) + readButton('final1');
box.innerHTML = html; renderMath(box);
/* === State === */
const SKEY = 'algebra10_ch1_final1_state';
let state = {};
try{ const s=localStorage.getItem(SKEY); if(s) state = JSON.parse(s); }catch(e){}
/* инициализация */
FINAL1_BOSSES.forEach(b => {
if(!state['b'+b.n]) state['b'+b.n] = {stage:0, defeated:false};
});
function save(){ try{ localStorage.setItem(SKEY, JSON.stringify(state)); }catch(e){} }
function refreshOverall(){
let won = 0;
FINAL1_BOSSES.forEach(b => { if(state['b'+b.n].defeated) won++; });
document.getElementById('final1-overall').textContent = won + ' / 6 побеждено';
document.getElementById('final1-overall-fill').style.width = (won*100/6) + '%';
if(won >= 6){
document.getElementById('final1-cel').style.display = 'block';
if(STATE.progress.final1 < 100){
bumpProgress('final1', 100);
}
if(!STATE.achievements.has('trig_master')){
achievement('trig_master');
/* Бонус 150 XP */
addXp(150, 'trig-master');
}
}
}
/* === Build boss cards === */
const cont = document.getElementById('final1-bosses');
cont.innerHTML = FINAL1_BOSSES.map(b => {
return '<div class="boss-card" id="bb-'+b.n+'-card" style="border-color:'+b.color+'">'
+'<div class="boss-head" style="flex-wrap:wrap">'
+'<svg viewBox="0 0 24 24" fill="none" stroke="'+b.color+'" stroke-width="2.2" style="width:28px;height:28px"><polygon points="12,2 22,20 2,20"/></svg>'
+'<div style="padding:3px 10px;background:'+b.color+'22;color:'+b.color+';border-radius:99px;font-family:Unbounded,sans-serif;font-size:.7rem;font-weight:800;letter-spacing:.06em;text-transform:uppercase">'+b.tag+'</div>'
+'<div class="boss-title" style="color:'+b.color+';flex:1;min-width:0">Босс '+b.n+'. '+b.title+'</div>'
+'<div class="boss-stage" id="bb-'+b.n+'-stage">Этап 1 / '+b.steps.length+'</div>'
+'</div>'
+'<div class="hp-boss" style="border-color:'+b.color+'66;background:'+b.color+'1a"><div class="hp-boss-fill" id="bb-'+b.n+'-fill" style="width:0%;background:linear-gradient(90deg,'+b.color+',#f59e0b)"></div></div>'
+'<div class="boss-q" id="bb-'+b.n+'-q" style="border-color:'+b.color+'"></div>'
+'<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap">'
+'<input type="text" id="bb-'+b.n+'-input" class="tinp" placeholder="Ответ" style="width:160px;text-align:center">'
+'<button class="btn primary" id="bb-'+b.n+'-go" style="background:'+b.color+';border-color:'+b.color+'">Атака</button>'
+'<button class="btn" id="bb-'+b.n+'-hint">Подсказка</button>'
+'<button class="btn" id="bb-'+b.n+'-restart">↻</button>'
+'</div>'
+'<div class="feedback" id="bb-'+b.n+'-fb"></div>'
+'</div>';
}).join('');
if(window.renderMathInElement) try{ renderMath(cont); }catch(e){}
/* === Bind handlers === */
FINAL1_BOSSES.forEach(b => {
const stKey = 'b' + b.n;
function show(){
const st = state[stKey];
const stageEl=document.getElementById('bb-'+b.n+'-stage');
const fill=document.getElementById('bb-'+b.n+'-fill');
const q=document.getElementById('bb-'+b.n+'-q');
const fb=document.getElementById('bb-'+b.n+'-fb');
if(st.defeated){
stageEl.innerHTML='&#10003; Побеждён';
fill.style.width='100%';
q.innerHTML='<b style="color:'+b.color+'">Босс повержен!</b>';
document.getElementById('bb-'+b.n+'-go').disabled=true;
document.getElementById('bb-'+b.n+'-go').style.opacity=.5;
return;
}
stageEl.textContent='Этап '+(st.stage+1)+' / '+b.steps.length;
fill.style.width=(st.stage*100/b.steps.length)+'%';
q.innerHTML=b.steps[st.stage].q;
document.getElementById('bb-'+b.n+'-input').value='';
fb.style.display='none';
renderMath(q);
}
document.getElementById('bb-'+b.n+'-go').addEventListener('click', ()=>{
const st = state[stKey];
if(st.defeated) return;
const step=b.steps[st.stage];
const val=document.getElementById('bb-'+b.n+'-input').value;
const fb=document.getElementById('bb-'+b.n+'-fb');
if(!val.trim()){ feedback(fb,false,'&#10007; Введи ответ.'); return; }
if(step.verify(val)){
st.stage++;
if(st.stage>=b.steps.length){
st.defeated=true; save();
feedback(fb,true,'&#10003; Босс '+b.n+' повержен! +25 XP');
addXp(25,'final1-b'+b.n);
refreshOverall();
setTimeout(show, 1400);
} else {
save();
feedback(fb,true,'&#10003; Верно! +5 XP');
addXp(5,'final1-b'+b.n+'-step');
setTimeout(show, 1100);
}
} else {
feedback(fb,false,'&#10007; Промах. Подумай ещё.');
}
});
document.getElementById('bb-'+b.n+'-hint').addEventListener('click', ()=>{
const st = state[stKey];
if(st.defeated) return;
const fb=document.getElementById('bb-'+b.n+'-fb');
fb.className='feedback ok';
fb.innerHTML='<span style="color:#92400e">\u{1F4A1} Подсказка:</span> '+b.steps[st.stage].hint;
fb.style.display='block';
fb.style.background='var(--warn-bg)'; fb.style.color='#92400e'; fb.style.borderLeftColor='var(--warn)';
renderMath(fb);
});
document.getElementById('bb-'+b.n+'-restart').addEventListener('click', ()=>{
state[stKey] = {stage:0, defeated:false}; save();
document.getElementById('bb-'+b.n+'-go').disabled=false;
document.getElementById('bb-'+b.n+'-go').style.opacity=1;
show(); refreshOverall();
});
show();
});
refreshOverall();
wireReadBtn('final1');
}
</script>
</body>
</html>