660e7e2747
Until now the 'gamification' feature flag did nothing: it had no row in
app_settings, the admin couldn't toggle it, awardXP/awardCoins ignored
it, and the CSS only hid three dashboard widgets — XP bars in textbooks
stayed visible regardless.
Phase 1 closes every hole.
Backend (source of truth):
• migration 029 seeds feature_gamification_enabled=1
• new isGamificationEnabled() helper in gamification/_shared.js with a
30s cache + invalidateGamificationCache() for instant admin toggles
• awardXP / awardCoins / updateStreak / unlockAchievement /
checkAchievements all bail out when the flag is off
• /api/gamification/* and /api/shop/* (user routes) return 404 when
disabled; admin routes remain open so the switch itself is reachable
• adminController.updateFeatures gains 'gamification' in the allow-list
and invalidates the cache on flip
Frontend:
• LS.isGamificationEnabled() (synchronous, populated by loadFeatures)
so xp.js + applyCosmetics can bail without a round-trip
• xp.js load/add/flush become no-ops when the flag is off
• applyCosmetics skips the round-trip when off
• CSS .no-gamification rule expanded to cover .hero-xp-badge, .po-xp,
.xp-card, .xp-bar, #frames-section, and a universal [data-gamified]
hook for future blocks
Textbooks (Variant 2 of the plan):
• backend/scripts/wrap_textbook_xp.py — idempotent script that adds
data-gamified to 167 XP tags across 63 textbook files (chapters +
hubs, all subjects/grades). Single CSS rule now hides everything.
Verified end-to-end: with the flag off, awardXP/awardCoins write nothing;
flipping back restores normal behavior.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3133 lines
236 KiB
HTML
3133 lines
236 KiB
HTML
<!doctype html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
|
||
<meta 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(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="★"><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:'★', 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)">✓ '+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?'✓ Верно!':'✗ Неверно'); 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, '✗ Введи ответ.'); 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, '✓ Верно! Дальше ▶'); }
|
||
else feedback(fb, false, '✗ Неверно. Правильно: <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.textContent='✓ Побеждён'; 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,'✗ Введи ответ.'); return; }
|
||
if(step.verify(val)){
|
||
st.stage++;
|
||
if(st.stage>=bossDef.steps.length){
|
||
st.defeated=true; save();
|
||
feedback(fb,true,'✓ Босс повержен! +20 XP');
|
||
addXp(20,paraId+'-boss'); bumpProgress(paraId, 30);
|
||
setTimeout(show,1400);
|
||
}else{
|
||
save(); feedback(fb,true,'✓ Верно! +3 XP'); addXp(3,paraId+'-boss-step'); setTimeout(show,1100);
|
||
}
|
||
}else{ feedback(fb,false,'✗ Промах.'); }
|
||
});
|
||
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$ ✓' },
|
||
{ 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$ ✓' },
|
||
{ 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,'✓ Верно! '+Q[i].why); }
|
||
else feedback(fb,false,'✗ '+(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,'✓ Верно! '+Q[i].why); }
|
||
else feedback(fb,false,'✗ '+(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$ ✓.' },
|
||
{ 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"><</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">></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,'✓ Верно!'); }
|
||
else{ const lab={lt:'<',eq:'=',gt:'>'}; feedback(fb,false,'✗ Правильно: <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 ✓.' },
|
||
{ 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>, <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:'§ 1–4',
|
||
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:'§ 5–7',
|
||
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:'§ 10–11',
|
||
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">★</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">★ 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">★ Финальная ачивка</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">★</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.textContent='✓ Побеждён';
|
||
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,'✗ Введи ответ.'); return; }
|
||
if(step.verify(val)){
|
||
st.stage++;
|
||
if(st.stage>=b.steps.length){
|
||
st.defeated=true; save();
|
||
feedback(fb,true,'✓ Босс '+b.n+' повержен! +25 XP');
|
||
addXp(25,'final1-b'+b.n);
|
||
refreshOverall();
|
||
setTimeout(show, 1400);
|
||
} else {
|
||
save();
|
||
feedback(fb,true,'✓ Верно! +5 XP');
|
||
addXp(5,'final1-b'+b.n+'-step');
|
||
setTimeout(show, 1100);
|
||
}
|
||
} else {
|
||
feedback(fb,false,'✗ Промах. Подумай ещё.');
|
||
}
|
||
});
|
||
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>
|