1546 lines
106 KiB
HTML
1546 lines
106 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 · Глава 3 · Производная</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:#f0fdf4; --card:#fff; --card-soft:#f7fcf8; --text:#0f1f15; --muted:#4b6b58;
|
||
--border:#dcfce7; --sh:0 1px 3px rgba(0,0,0,.06); --sh2:0 4px 14px rgba(0,0,0,.08);
|
||
--pri:#059669; --pri2:#047857; --pri-soft:#d1fae5;
|
||
--acc:#10b981; --acc2:#059669; --acc-soft:#86efac;
|
||
--ok:#10b981; --ok-bg:#d1fae5; --warn:#f59e0b; --warn-bg:#fef3c7;
|
||
--bad:#ef4444; --fail:#dc2626; --fail-bg:#fee2e2;
|
||
}
|
||
.dark{--bg:#03180e; --card:#0a2418; --card-soft:#0e2c1e; --text:#dcfce7; --muted:#86b89e; --border:#1d4232}
|
||
*{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,#064e3b 0%,#059669 55%,#86efac 100%);color:#fff;padding:46px 22px 30px;overflow:hidden;border-bottom:2px solid rgba(220,252,231,.2);min-height:130px}
|
||
.hdr::before{content:'ГЛАВА 3';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,252,231,.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:"f'(x)";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(5,150,105,.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(5,150,105,.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(170px,1fr));gap:10px}
|
||
.psel-card{background:var(--card);border:1.5px solid var(--border);border-radius:13px;padding:14px;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:5px}
|
||
.psel-name{font-size:.86rem;font-weight:700;color:var(--text);line-height:1.3;margin-bottom:8px}
|
||
.psel-prog{height:4px;background:rgba(5,150,105,.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-p18"] { --sec-acc:#059669; --sec-acc-d:#047857; --sec-acc-soft:#d1fae5; }
|
||
.sec[id="sec-p19"] { --sec-acc:#0d9488; --sec-acc-d:#0f766e; --sec-acc-soft:#ccfbf1; }
|
||
.sec[id="sec-p20"] { --sec-acc:#16a34a; --sec-acc-d:#15803d; --sec-acc-soft:#dcfce7; }
|
||
.sec[id="sec-p21"] { --sec-acc:#22c55e; --sec-acc-d:#16a34a; --sec-acc-soft:#dcfce7; }
|
||
.sec[id="sec-p22"] { --sec-acc:#10b981; --sec-acc-d:#059669; --sec-acc-soft:#d1fae5; }
|
||
.sec[id="sec-final3"]{ --sec-acc:#059669; --sec-acc-d:#047857; --sec-acc-soft:#d1fae5; }
|
||
|
||
.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(5,150,105,.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(5,150,105,.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,#059669,#10b981);color:#fff;padding:12px 18px;border-radius:11px;font-weight:700;font-size:.9rem;box-shadow:0 8px 28px rgba(5,150,105,.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-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:80px}
|
||
.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}
|
||
|
||
.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);background:linear-gradient(180deg,rgba(5,150,105,.12),rgba(5,150,105,.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;color:#047857}
|
||
.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:#0891b2}
|
||
.formula-row.danger{color:#dc2626}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<header class="hdr">
|
||
<div class="hdr-row">
|
||
<div>
|
||
<h1>Алгебра 10 · Глава 3</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>мгновенную скорость</b> — производную пути по времени. В математике <b>производная функции</b> $f'(x)$ показывает, как быстро $f$ растёт или падает в каждой точке. На графике производная — это <b>тангенс угла наклона касательной</b>.</p>
|
||
<div class="hero-row">
|
||
<button class="btn-primary" onclick="goTo('p18')"><svg class="ic" viewBox="0 0 24 24"><polygon points="6 4 20 12 6 20 6 4" fill="currentColor" stroke="none"/></svg> Начать § 18</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-p18" class="sec" data-watermark="Δf/Δx"><div class="sec-header"><span class="sec-num">§ 18</span><h2 class="sec-h">Определение производной функции</h2></div><div id="p18-body"></div></section>
|
||
<section id="sec-p19" class="sec" data-watermark="(uv)'"><div class="sec-header"><span class="sec-num">§ 19</span><h2 class="sec-h">Правила вычисления производных</h2></div><div id="p19-body"></div></section>
|
||
<section id="sec-p20" class="sec" data-watermark="↗"><div class="sec-header"><span class="sec-num">§ 20</span><h2 class="sec-h">Геометрический смысл. Монотонность</h2></div><div id="p20-body"></div></section>
|
||
<section id="sec-p21" class="sec" data-watermark="∪∩"><div class="sec-header"><span class="sec-num">§ 21</span><h2 class="sec-h">Применение к исследованию функций</h2></div><div id="p21-body"></div></section>
|
||
<section id="sec-p22" class="sec" data-watermark="★"><div class="sec-header"><span class="sec-num">§ 22</span><h2 class="sec-h">Наибольшее и наименьшее значения</h2></div><div id="p22-body"></div></section>
|
||
<section id="sec-final3" class="sec" data-watermark="★"><div class="sec-header"><span class="sec-num" style="background:linear-gradient(135deg,#059669,#86efac)">Финал главы</span><h2 class="sec-h">Итоги. 5 боссов главы 3</h2></div><div id="final3-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 класс» · Глава 3 · Производная · 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:'p18', progress:{p18:0,p19:0,p20:0,p21:0,p22:0,final3:0}, achievements:new Map(), xp:0, level:1 };
|
||
const TOTAL_PARAS = 6;
|
||
const _TB_SLUG = 'algebra-10-ch3';
|
||
|
||
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:'Начало главы 3!',
|
||
p18_done:'Определение производной — освоено!',
|
||
p19_done:'Правила вычисления — знаешь!',
|
||
p20_done:'Касательная и монотонность — твои!',
|
||
p21_done:'Исследование функций — мастер!',
|
||
p22_done:'Наиб./наим. значения — освоены!',
|
||
ch3_done:'Глава 3 — Производная пройдена!',
|
||
deriv_master:'Магистр производных! +150 XP',
|
||
alg10_master:'★ Алгебра 10 пройдена полностью!',
|
||
};
|
||
|
||
function loadProgress(){
|
||
try{
|
||
const s=localStorage.getItem('algebra10_ch3_progress'); if(s) Object.assign(STATE.progress, JSON.parse(s));
|
||
const a=localStorage.getItem('algebra10_ch3_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_ch3_progress', JSON.stringify(STATE.progress));
|
||
localStorage.setItem('algebra10_ch3_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==='p18') achievement('p18_done');
|
||
else if(key==='p19') achievement('p19_done');
|
||
else if(key==='p20') achievement('p20_done');
|
||
else if(key==='p21') achievement('p21_done');
|
||
else if(key==='p22') achievement('p22_done');
|
||
else if(key==='final3') achievement('ch3_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-ch3-'+(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:'p18', num:'§ 18', name:'Определение производной', sub:'через предел' },
|
||
{ id:'p19', num:'§ 19', name:'Правила вычисления', sub:'сумма, произв., степень' },
|
||
{ id:'p20', num:'§ 20', name:'Касательная, монотонность', sub:'геом. смысл' },
|
||
{ id:'p21', num:'§ 21', name:'Исследование функций', sub:'экстремумы' },
|
||
{ id:'p22', num:'§ 22', name:'Наиб. и наим. значения', sub:'на отрезке' },
|
||
{ id:'final3', num:'★', name:'Финал главы', sub:'5 боссов', 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 = { p18:()=>buildP18(), p19:()=>buildP19(), p20:()=>buildP20(), p21:()=>buildP21(), p22:()=>buildP22(), final3:()=>buildFinal3() };
|
||
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 = {
|
||
p18:{title:'Шпаргалка §18',rows:[
|
||
['Опр.','$f\'(x_0) = \\lim\\limits_{\\Delta x \\to 0} \\dfrac{\\Delta f}{\\Delta x}$'],
|
||
['$\\Delta f$','$= f(x_0 + \\Delta x) - f(x_0)$'],
|
||
['$\\Delta x$','приращение аргумента'],
|
||
['$(x^2)\'$','$= 2x$'],
|
||
['$(kx+b)\'$','$= k$'],
|
||
['$(1/x)\'$','$= -1/x^2$'],
|
||
['$C\'$','$= 0$ (константа)'],
|
||
['Физ. смысл','мгновенная скорость'],
|
||
]},
|
||
p19:{title:'Шпаргалка §19',rows:[
|
||
['$(U+V)\'$','$= U\' + V\'$'],
|
||
['$(UV)\'$','$= U\'V + UV\'$'],
|
||
['$(U/V)\'$','$= (U\'V - UV\')/V^2$'],
|
||
['$(C\\cdot U)\'$','$= C \\cdot U\'$'],
|
||
['$(x^n)\'$','$= n \\cdot x^{n-1}$'],
|
||
['Пример','$(x^5)\' = 5x^4$'],
|
||
]},
|
||
p20:{title:'Шпаргалка §20',rows:[
|
||
['Геом. смысл','$f\'(x_0) = \\tg\\alpha$'],
|
||
['','угол $\\alpha$ — между касат. и осью x'],
|
||
['Касательная','$y = f(x_0) + f\'(x_0)(x - x_0)$'],
|
||
['$f\' > 0$ на $I$','$f$ возрастает на $I$'],
|
||
['$f\' < 0$ на $I$','$f$ убывает на $I$'],
|
||
['$f\' = 0$','критические точки'],
|
||
]},
|
||
p21:{title:'Шпаргалка §21',rows:[
|
||
['Крит. точка','где $f\'(x) = 0$ или $f\'$ не существует'],
|
||
['Точка max','$f\'$ меняет знак с + на −'],
|
||
['Точка min','$f\'$ меняет знак с − на +'],
|
||
['Перегиб','знак $f\'$ не меняется'],
|
||
['Алгоритм','5 шагов: $D$, $f\'$, нули, знаки, экстр.'],
|
||
]},
|
||
p22:{title:'Шпаргалка §22',rows:[
|
||
['На $[a;b]$','3 шага: $f\'$, крит. точки, значения'],
|
||
['Где искать','концы $a, b$ + крит. точки внутри'],
|
||
['Сравни','выбери наиб. и наим.'],
|
||
['Если нет крит. на $[a;b]$','берём только концы'],
|
||
]},
|
||
final3:{title:'Финал главы 3',rows:[
|
||
['Боссов','5 — все темы главы'],
|
||
['Босс 1','§18 определение, базовые формулы'],
|
||
['Босс 2','§19 правила (сумма, произв., степень)'],
|
||
['Босс 3','§20 касательная, монотонность'],
|
||
['Босс 4','§21 экстремумы'],
|
||
['Босс 5','§22 наиб./наим. + сборная'],
|
||
['Награда','+150 XP + «Магистр производных»'],
|
||
]},
|
||
};
|
||
|
||
const TIPS=[
|
||
{sec:'p18',html:'Производная — это <b>предел отношения</b> приращения функции к приращению аргумента. Геометрически — наклон секущей в пределе становится наклоном касательной.'},
|
||
{sec:'p19',html:'Самое полезное правило: <b>$(x^n)\' = n \\cdot x^{n-1}$</b>. Применяй ко всем степеням x, включая отрицательные и дробные.'},
|
||
{sec:'p20',html:'<b>Уравнение касательной</b> через точку $(x_0; f(x_0))$ с угловым коэффициентом $f\'(x_0)$: $y = f(x_0) + f\'(x_0)(x - x_0)$.'},
|
||
{sec:'p21',html:'<b>Алгоритм исследования:</b> найди $D(f)$ → вычисли $f\'(x)$ → найди нули $f\'$ (критические точки) → определи знаки $f\'$ между ними → выпиши экстремумы.'},
|
||
{sec:'p22',html:'Для отрезка <b>$[a; b]$</b> наиб. и наим. значения функции — среди значений в концах ($a$ и $b$) и в критических точках, лежащих внутри.'},
|
||
{sec:'final3',html:'5 интегрированных боссов проверяют синтез знаний всей главы. После победы — ачивка <b>«Магистр производных»</b> и +150 XP. А ещё — особая ачивка <b>«Алгебра 10 пройдена»</b>, если ты уже завершил Главы 1 и 2!'},
|
||
];
|
||
|
||
function buildSidebar(id){
|
||
const box=document.getElementById('sidebar-content');
|
||
const sb=SIDEBARS[id]||SIDEBARS.p18;
|
||
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_ch3_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_ch3_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={p18:'§18',p19:'§19',p20:'§20',p21:'§21',p22:'§22',final3:'Финал'};
|
||
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){
|
||
const idP = paraId+'-boss';
|
||
const SKEY = 'algebra10_ch3_'+paraId+'_boss';
|
||
let st = {stage:0, defeated:false};
|
||
try{ const s=localStorage.getItem(SKEY); if(s) st=JSON.parse(s); }catch(e){}
|
||
const html = '<div class="boss-card" style="border-color:'+bossDef.color+'">'
|
||
+'<div class="boss-head">'
|
||
+'<svg viewBox="0 0 24 24" fill="none" stroke="'+bossDef.color+'" stroke-width="2.2" style="width:28px;height:28px"><polygon points="12,2 22,20 2,20"/></svg>'
|
||
+'<div class="boss-title" style="color:'+bossDef.color+'">'+bossDef.title+'</div>'
|
||
+'<div class="boss-stage" id="'+idP+'-stage">Этап 1 / '+bossDef.steps.length+'</div>'
|
||
+'</div>'
|
||
+'<div class="hp-boss" style="border-color:'+bossDef.color+'66;background:'+bossDef.color+'1a"><div class="hp-boss-fill" id="'+idP+'-fill" style="width:0%;background:linear-gradient(90deg,'+bossDef.color+',#f59e0b)"></div></div>'
|
||
+'<div class="boss-q" id="'+idP+'-q" style="border-color:'+bossDef.color+'"></div>'
|
||
+'<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap">'
|
||
+'<input type="text" id="'+idP+'-input" class="tinp" placeholder="Ответ" style="width:160px;text-align:center">'
|
||
+'<button class="btn primary" id="'+idP+'-go" style="background:'+bossDef.color+';border-color:'+bossDef.color+'">Атака</button>'
|
||
+'<button class="btn" id="'+idP+'-hint">Подсказка</button>'
|
||
+'<button class="btn" id="'+idP+'-restart">↻</button>'
|
||
+'</div>'
|
||
+'<div class="feedback" id="'+idP+'-fb"></div>'
|
||
+'</div>';
|
||
setTimeout(()=>{
|
||
function save(){ try{ localStorage.setItem(SKEY, JSON.stringify(st)); }catch(e){} }
|
||
function show(){
|
||
const stageEl=document.getElementById(idP+'-stage');
|
||
const fill=document.getElementById(idP+'-fill');
|
||
const q=document.getElementById(idP+'-q');
|
||
const fb=document.getElementById(idP+'-fb');
|
||
if(st.defeated){
|
||
stageEl.innerHTML='✓ Побеждён'; 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('p18');
|
||
setTimeout(()=>achievement('start','Начало главы 3!'), 600);
|
||
}
|
||
document.addEventListener('DOMContentLoaded', init);
|
||
|
||
|
||
/* ============================================================
|
||
§ 18 — Определение производной функции
|
||
============================================================ */
|
||
function buildP18(){
|
||
const box = document.getElementById('p18-body');
|
||
const A = window.ALG10;
|
||
let html = '';
|
||
|
||
/* === SVG: секущая → касательная (с слайдером Δx) === */
|
||
let svgSecant = '';
|
||
if(A){
|
||
const f = A.func.canvas({id:'p18-sec', W:560, H:280, xRange:[-1, 3.5], yRange:[-1, 8], bg:'#fff'});
|
||
let s = f.open
|
||
+ f.grid({xStep:1, yStep:1, color:'#f1f5f9'})
|
||
+ f.axes({color:'#475569', xTicks:[{val:1,label:'1'},{val:2,label:'2'},{val:3,label:'3'}], yTicks:[{val:2,label:'2'},{val:4,label:'4'},{val:6,label:'6'}]})
|
||
+ f.plot(x => x*x, {color:'#059669', width:2.8})
|
||
/* Точка M(1, 1) */
|
||
+ f.pointXY(1, 1, {color:'#dc2626', r:5, label:'M', dx:-15, dy:-8, fontSize:13})
|
||
/* Точка N — будет двигаться слайдером */
|
||
+ '<g id="p18-sec-dyn"></g>'
|
||
+ f.close;
|
||
svgSecant = s;
|
||
}
|
||
|
||
html += makeCard('theory', 'От средней скорости — к мгновенной', '18.1', `
|
||
<p>Машина за 2 часа проехала 120 км. Её <b>средняя скорость</b>: $60$ км/ч.</p>
|
||
<p>Но в каждую конкретную секунду спидометр показывал <b>что-то другое</b> — где-то стояли в пробке, где-то ехали 90 км/ч.</p>
|
||
<p>Идея <b>мгновенной скорости</b>: средняя скорость за <b>очень-очень малый</b> промежуток времени. Чем меньше промежуток, тем ближе к мгновенной.</p>
|
||
<p>Математически — это <b>предел отношения</b>.</p>`);
|
||
|
||
html += makeCard('rule', 'Приращение аргумента и функции', '18.2', `
|
||
<p>Пусть функция $y = f(x)$ задана. Берём точку $x_0$ и сдвигаемся вправо или влево на $\\Delta x$ (приращение аргумента).</p>
|
||
<p>Тогда:</p>
|
||
<ul style="padding-left:22px;line-height:1.85">
|
||
<li><b>Приращение функции</b>: $\\Delta f = f(x_0 + \\Delta x) - f(x_0)$.</li>
|
||
<li><b>Отношение приращений</b>: $\\dfrac{\\Delta f}{\\Delta x}$ — это <b>тангенс наклона секущей</b>, проходящей через точки $M(x_0, f(x_0))$ и $N(x_0 + \\Delta x, f(x_0 + \\Delta x))$.</li>
|
||
</ul>
|
||
<div class="svg-host">${svgSecant}</div>
|
||
<div class="slider-ctrl"><label>Δx:</label><input type="range" id="p18-dx" min="0.05" max="2" step="0.05" value="1.5"><span class="val" id="p18-dxv">1.50</span></div>
|
||
<p>Двигай слайдер влево — точка <b>N приближается</b> к M, и секущая постепенно превращается в <b>касательную</b>. Отношение $\\Delta f / \\Delta x$ стремится к производной.</p>`);
|
||
|
||
html += makeCard('rule', 'Определение производной', '18.3', `
|
||
<p style="background:var(--sec-acc-soft);padding:10px 14px;border-radius:8px"><b>Определение.</b> <b>Производной функции $f$ в точке $x_0$</b> называется предел отношения приращения функции к приращению аргумента, при условии что приращение аргумента стремится к нулю:</p>
|
||
<p style="text-align:center;font-size:1.2rem;margin:10px 0">$f'(x_0) = \\lim\\limits_{\\Delta x \\to 0} \\dfrac{\\Delta f}{\\Delta x} = \\lim\\limits_{\\Delta x \\to 0} \\dfrac{f(x_0 + \\Delta x) - f(x_0)}{\\Delta x}$</p>
|
||
<p>Если предел существует — функция называется <b>дифференцируемой</b> в точке $x_0$.</p>`);
|
||
|
||
html += makeCard('algo', 'Алгоритм нахождения производной по определению', '18.4', `
|
||
<ol style="padding-left:22px;line-height:1.95">
|
||
<li>Найди $f(x_0 + \\Delta x)$.</li>
|
||
<li>Вычисли $\\Delta f = f(x_0 + \\Delta x) - f(x_0)$.</li>
|
||
<li>Найди отношение $\\dfrac{\\Delta f}{\\Delta x}$.</li>
|
||
<li>Упрости его так, чтобы $\\Delta x$ можно было устремить к 0.</li>
|
||
<li>Возьми предел при $\\Delta x \\to 0$.</li>
|
||
</ol>
|
||
<p><b>Пример. Найдём $(x^2)'$.</b></p>
|
||
<ol style="padding-left:22px;line-height:1.9">
|
||
<li>$f(x + \\Delta x) = (x + \\Delta x)^2 = x^2 + 2x\\Delta x + (\\Delta x)^2$.</li>
|
||
<li>$\\Delta f = 2x\\Delta x + (\\Delta x)^2 = \\Delta x(2x + \\Delta x)$.</li>
|
||
<li>$\\dfrac{\\Delta f}{\\Delta x} = 2x + \\Delta x$.</li>
|
||
<li>При $\\Delta x \\to 0$: $2x + \\Delta x \\to 2x$.</li>
|
||
</ol>
|
||
<p>Итак, <b>$(x^2)' = 2x$</b>.</p>`);
|
||
|
||
html += makeCard('example', 'Базовые производные', '18.5', `
|
||
<p>По определению можно вывести базовые производные (для 10-го класса):</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">$f(x)$</th><th style="padding:6px;border:1px solid var(--border);text-align:left">$f'(x)$</th></tr>
|
||
<tr><td style="padding:6px;border:1px solid var(--border);text-align:center">$x^2$</td><td style="padding:6px;border:1px solid var(--border);text-align:center">$2x$</td></tr>
|
||
<tr><td style="padding:6px;border:1px solid var(--border);text-align:center">$kx + b$</td><td style="padding:6px;border:1px solid var(--border);text-align:center">$k$</td></tr>
|
||
<tr><td style="padding:6px;border:1px solid var(--border);text-align:center">$\\dfrac{1}{x}$</td><td style="padding:6px;border:1px solid var(--border);text-align:center">$-\\dfrac{1}{x^2}$</td></tr>
|
||
<tr><td style="padding:6px;border:1px solid var(--border);text-align:center">$C$ (константа)</td><td style="padding:6px;border:1px solid var(--border);text-align:center">$0$</td></tr>
|
||
</table>
|
||
<p><b>Физический смысл.</b> Если $s(t)$ — путь как функция времени, то $s'(t)$ — <b>мгновенная скорость</b>.</p>`);
|
||
|
||
/* === ИНТЕРАКТИВ 1: алгоритм === */
|
||
html += '<div class="wg" id="p18-iv1">'
|
||
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Производная по определению</div></div>'
|
||
+'<div class="wg-help">Базовые формулы: $(x^2)\' = 2x$, $(kx+b)\' = k$, $(C)\' = 0$, $(1/x)\' = -1/x^2$.</div>'
|
||
+trainerHTML('p18-iv1', 6, 'значение или выражение')
|
||
+'</div>';
|
||
|
||
/* === ИНТЕРАКТИВ 2: скорость === */
|
||
html += '<div class="wg" id="p18-iv2">'
|
||
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Мгновенная скорость</div></div>'
|
||
+'<div class="wg-help">$v_{\\text{мгн}}(t_0) = s\'(t_0)$. Сначала найди $s\'(t)$, потом подставь $t_0$.</div>'
|
||
+trainerHTML('p18-iv2', 5, 'число')
|
||
+'</div>';
|
||
|
||
/* === БОСС === */
|
||
html += '<h3 style="font-family:Unbounded,sans-serif;font-size:1.05rem;color:var(--pri2);margin:20px 0 12px">Босс §18 — Определение производной</h3>';
|
||
html += makeBoss('p18', {
|
||
color:'#059669',
|
||
title:'Босс §18 — Определение производной',
|
||
steps:[
|
||
{ q:'Чему равно $\\dfrac{\\Delta f}{\\Delta x}$ при $\\Delta x \\to 0$? Это $\\ldots$', verify:(v)=>{const s=String(v).replace(/\s/g,'').toLowerCase(); return s==="f'(x)"||s.startsWith('производная');}, hint:'Производная по определению.' },
|
||
{ q:'Найди $(5x - 3)\'$.', verify:(v)=>+v===5, hint:'$(kx+b)\' = k$, где $k = 5$.' },
|
||
{ q:'$(x^2)\'$ при $x = 3$ = ?', verify:(v)=>+v===6, hint:'$(x^2)\' = 2x$, при $x = 3$: $2 \\cdot 3 = 6$.' },
|
||
{ q:'$(7)\' = ?$', verify:(v)=>+v===0, hint:'Производная константы = 0.' },
|
||
{ q:'Путь $s(t) = 4t + 1$. Мгновенная скорость при $t = 5$ = ?', verify:(v)=>+v===4, hint:'$s\'(t) = 4$ — постоянная.' },
|
||
]
|
||
});
|
||
|
||
html += secNav(null, 'p19') + readButton('p18');
|
||
box.innerHTML = html; renderMath(box);
|
||
|
||
/* Slider for §18 SVG */
|
||
(function(){
|
||
const dx = document.getElementById('p18-dx');
|
||
const dxv = document.getElementById('p18-dxv');
|
||
const dyn = document.getElementById('p18-sec-dyn');
|
||
if(!A || !dx || !dyn) return;
|
||
function redraw(){
|
||
const Δx = parseFloat(dx.value);
|
||
dxv.textContent = Δx.toFixed(2);
|
||
const f = A.func.canvas({id:'p18-sec', W:560, H:280, xRange:[-1, 3.5], yRange:[-1, 8]});
|
||
const xN = 1 + Δx;
|
||
const yN = xN * xN;
|
||
const yM = 1;
|
||
/* Секущая через M(1,1) и N(xN, yN) */
|
||
const k = (yN - yM) / (xN - 1);
|
||
/* Рисуем секущую */
|
||
const xLeft = -0.5, xRight = 3.3;
|
||
const yLeft = k * (xLeft - 1) + yM;
|
||
const yRight = k * (xRight - 1) + yM;
|
||
let s = '<line x1="'+f.pxX(xLeft)+'" y1="'+f.pxY(yLeft)+'" x2="'+f.pxX(xRight)+'" y2="'+f.pxY(yRight)+'" stroke="#dc2626" stroke-width="2" stroke-dasharray="6 3"/>';
|
||
/* Точка N */
|
||
s += '<circle cx="'+f.pxX(xN)+'" cy="'+f.pxY(yN)+'" r="5" fill="#dc2626" stroke="#fff" stroke-width="1.5"/>';
|
||
s += '<text x="'+(f.pxX(xN)+8)+'" y="'+(f.pxY(yN)-6)+'" font-size="13" font-family="Unbounded,Inter,sans-serif" font-weight="800" fill="#dc2626">N</text>';
|
||
/* Подпись наклона */
|
||
s += '<text x="'+(f.pxX(2.5))+'" y="'+(f.pxY(7))+'" font-size="11" font-family="JetBrains Mono,monospace" font-weight="700" fill="#dc2626">Δf/Δx = '+k.toFixed(2)+'</text>';
|
||
dyn.innerHTML = s;
|
||
}
|
||
dx.addEventListener('input', redraw);
|
||
redraw();
|
||
})();
|
||
|
||
/* IV1 */
|
||
makeTrainer({
|
||
idPrefix:'p18-iv1',
|
||
parser:(v)=>v,
|
||
questions:[
|
||
{ q:'$(3x + 7)\' = ?$', a:(v)=>+v===3, show:'$3$' },
|
||
{ q:'$(-2x + 11)\' = ?$', a:(v)=>+v===-2, show:'$-2$' },
|
||
{ q:'$(x^2)\'$ при $x = 5$ = ?', a:(v)=>+v===10, show:'$10$' },
|
||
{ q:'$(x^2)\'$ при $x = -3$ = ?', a:(v)=>+v===-6, show:'$-6$' },
|
||
{ q:'$(100)\' = ?$', a:(v)=>+v===0, show:'$0$' },
|
||
{ q:'$(1/x)\'$ при $x = 2$ = ? Введи -1/4 или -0.25.', a:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='-1/4'||+v===-0.25;}, show:'$-1/4$' },
|
||
],
|
||
onComplete:(s,n)=>{ if(s===n){addXp(18,'p18-iv1');bumpProgress('p18',30);} else if(s>=4){addXp(9,'p18-iv1');bumpProgress('p18',14);} }
|
||
});
|
||
|
||
/* IV2 */
|
||
makeTrainer({
|
||
idPrefix:'p18-iv2',
|
||
questions:[
|
||
{ q:'$s(t) = 5t - 2$. $v(3) = ?$', a:5 },
|
||
{ q:'$s(t) = t^2$. $v(4) = ?$ (формула: $s\'(t) = 2t$)', a:8 },
|
||
{ q:'$s(t) = 3t + 1$. $v(10) = ?$', a:3 },
|
||
{ q:'$s(t) = t^2 - 10t$. $v\'$ — линейная. $v(5) = ?$ ($s\' = 2t - 10$)', a:0 },
|
||
{ q:'$s(t) = -2t + 5$. $v(0) = ?$', a:-2 },
|
||
],
|
||
onComplete:(s,n)=>{ if(s===n){addXp(15,'p18-iv2');bumpProgress('p18',25);} else if(s>=3){addXp(8,'p18-iv2');bumpProgress('p18',12);} }
|
||
});
|
||
|
||
wireReadBtn('p18');
|
||
}
|
||
|
||
|
||
/* ============================================================
|
||
§ 19 — Правила вычисления производных
|
||
============================================================ */
|
||
function buildP19(){
|
||
const box = document.getElementById('p19-body');
|
||
let html = '';
|
||
|
||
const plateRules = '<div class="formula-plate">'
|
||
+ '<div class="formula-plate-head">'
|
||
+ '<div class="formula-plate-title">4 правила вычисления производных</div>'
|
||
+ '<div class="formula-plate-sub">все 4 — обязательно знать наизусть</div>'
|
||
+ '</div>'
|
||
+ '<div class="formula-plate-body">'
|
||
+ '<div class="formula-row">$(U + V)\' = U\' + V\'$ <span style="color:var(--muted);font-size:.85rem">(производная суммы)</span></div>'
|
||
+ '<div class="formula-row alt">$(U \\cdot V)\' = U\'V + UV\'$ <span style="color:var(--muted);font-size:.85rem">(производная произведения)</span></div>'
|
||
+ '<div class="formula-row">$\\left(\\dfrac{U}{V}\\right)\' = \\dfrac{U\'V - UV\'}{V^2}$ <span style="color:var(--muted);font-size:.85rem">(производная частного)</span></div>'
|
||
+ '<div class="formula-row alt">$(x^n)\' = n \\cdot x^{n-1}$ <span style="color:var(--muted);font-size:.85rem">(производная степени)</span></div>'
|
||
+ '</div>'
|
||
+ '</div>';
|
||
|
||
html += makeCard('rule', 'Правила дифференцирования', '19.1', `
|
||
${plateRules}
|
||
<p><b>Следствия из правил:</b></p>
|
||
<ul style="padding-left:22px;line-height:1.85">
|
||
<li>$(C \\cdot U)' = C \\cdot U'$ — константу можно выносить за знак производной.</li>
|
||
<li>$(U - V)' = U' - V'$ — производная разности.</li>
|
||
</ul>`);
|
||
|
||
html += makeCard('example', 'Применение правил', '19.2', `
|
||
<p><b>Пример 1.</b> $f(x) = 3x^4 - 5x + 7$.</p>
|
||
<p>$f'(x) = 3 \\cdot 4x^3 - 5 + 0 = 12x^3 - 5$.</p>
|
||
<p><b>Пример 2.</b> $f(x) = x^3 \\cdot (2x - 1)$ — производная произведения.</p>
|
||
<p>$f'(x) = (x^3)' \\cdot (2x - 1) + x^3 \\cdot (2x - 1)'$</p>
|
||
<p>$= 3x^2 \\cdot (2x - 1) + x^3 \\cdot 2 = 6x^3 - 3x^2 + 2x^3 = 8x^3 - 3x^2$.</p>
|
||
<p><b>Пример 3.</b> $f(x) = \\dfrac{x^2 - 1}{x + 3}$ — производная частного.</p>
|
||
<p>$f'(x) = \\dfrac{(2x)(x+3) - (x^2-1)(1)}{(x+3)^2} = \\dfrac{2x^2 + 6x - x^2 + 1}{(x+3)^2} = \\dfrac{x^2 + 6x + 1}{(x+3)^2}$.</p>`);
|
||
|
||
html += makeCard('rule', 'Производная степени', '19.3', `
|
||
<p style="background:var(--sec-acc-soft);padding:10px 14px;border-radius:8px;font-size:1.1rem;text-align:center"><b>$(x^n)' = n \\cdot x^{n-1}$</b></p>
|
||
<p>Работает для любых $n \\in \\mathbb{Z}$ (а позже узнаем — и для рациональных).</p>
|
||
<p><b>Примеры:</b></p>
|
||
<ul style="padding-left:22px;line-height:1.85">
|
||
<li>$(x^5)' = 5x^4$;</li>
|
||
<li>$(x^{10})' = 10x^9$;</li>
|
||
<li>$(x^{-2})' = -2x^{-3} = -\\dfrac{2}{x^3}$ — здесь $n = -2$;</li>
|
||
<li>$(x^0)' = 0 \\cdot x^{-1} = 0$ — это $C' = 0$.</li>
|
||
</ul>`);
|
||
|
||
/* === ИНТЕРАКТИВ 1: степень === */
|
||
html += '<div class="wg" id="p19-iv1">'
|
||
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Производная многочлена</div></div>'
|
||
+'<div class="wg-help">Применяй $(x^n)\' = n \\cdot x^{n-1}$ к каждому слагаемому.</div>'
|
||
+trainerHTML('p19-iv1', 7, 'значение в точке')
|
||
+'</div>';
|
||
|
||
/* === ИНТЕРАКТИВ 2 === */
|
||
html += '<div class="wg" id="p19-iv2">'
|
||
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Производная произведения и частного</div></div>'
|
||
+'<div class="wg-help">Внимательно с знаком: $(U/V)\' = (U\'V - UV\')/V^2$ — минус в числителе.</div>'
|
||
+trainerHTML('p19-iv2', 5, 'значение в точке')
|
||
+'</div>';
|
||
|
||
/* === БОСС === */
|
||
html += '<h3 style="font-family:Unbounded,sans-serif;font-size:1.05rem;color:var(--pri2);margin:20px 0 12px">Босс §19 — Правила вычисления</h3>';
|
||
html += makeBoss('p19', {
|
||
color:'#0d9488',
|
||
title:'Босс §19 — Правила вычисления',
|
||
steps:[
|
||
{ q:'$(x^7)\' = ?$ Введи как 7x^6 (если хочешь — как $n$ при $x = 1$).', verify:(v)=>+v===7, hint:'$(x^7)\' = 7x^6$; при $x = 1$: $7$.' },
|
||
{ q:'$f(x) = 3x^2 - 5x + 8$. $f\'(2) = ?$', verify:(v)=>+v===7, hint:'$f\'(x) = 6x - 5$; при $x = 2$: $12 - 5 = 7$.' },
|
||
{ q:'$(x^3 \\cdot x^2)\'$ при $x = 1$ = ? (Сначала упрости: $x^5$, потом производная.)', verify:(v)=>+v===5, hint:'$(x^5)\' = 5x^4 = 5$.' },
|
||
{ q:'$f(x) = 1/x$. $f\'(2) = ?$ Введи -1/4 или -0.25.', verify:(v)=>{const s=String(v).replace(/\\s/g,''); return s==='-1/4'||+v===-0.25;}, hint:'$(1/x)\' = -1/x^2 = -1/4$.' },
|
||
{ q:'$f(x) = (x+1)(x-1) = x^2 - 1$. $f\'(3) = ?$', verify:(v)=>+v===6, hint:'$f\'(x) = 2x$; при $x = 3$: $6$.' },
|
||
]
|
||
});
|
||
|
||
html += secNav('p18', 'p20') + readButton('p19');
|
||
box.innerHTML = html; renderMath(box);
|
||
|
||
/* IV1 */
|
||
makeTrainer({
|
||
idPrefix:'p19-iv1',
|
||
questions:[
|
||
{ q:'$f(x) = x^3$. $f\'(2) = ?$', a:12 },
|
||
{ q:'$f(x) = 2x^4$. $f\'(1) = ?$', a:8 },
|
||
{ q:'$f(x) = x^3 + x^2$. $f\'(1) = ?$', a:5 },
|
||
{ q:'$f(x) = 5x - 2$. $f\'(100) = ?$', a:5 },
|
||
{ q:'$f(x) = -3x^2 + 6x$. $f\'(2) = ?$', a:-6 },
|
||
{ q:'$f(x) = x^4 - 4x$. $f\'(1) = ?$', a:0 },
|
||
{ q:'$f(x) = \\dfrac{x^3}{3}$. $f\'(2) = ?$', a:4 },
|
||
],
|
||
onComplete:(s,n)=>{ if(s===n){addXp(20,'p19-iv1');bumpProgress('p19',32);} else if(s>=5){addXp(10,'p19-iv1');bumpProgress('p19',15);} }
|
||
});
|
||
|
||
/* IV2 */
|
||
makeTrainer({
|
||
idPrefix:'p19-iv2',
|
||
questions:[
|
||
{ q:'$f(x) = x(x - 4)$. $f\'(2) = ?$ (раскрой и продифференцируй)', a:0 },
|
||
{ q:'$f(x) = \\dfrac{1}{x+1}$. $f\'(0) = ?$ Введи -1 или -1/1.', a:-1 },
|
||
{ q:'$f(x) = x \\cdot x^2 = x^3$. $f\'(2) = ?$', a:12 },
|
||
{ q:'$f(x) = \\dfrac{x^2}{x} = x$ (при $x \\ne 0$). $f\'(5) = ?$', a:1 },
|
||
{ q:'$f(x) = \\dfrac{x^2-1}{x-1} = x+1$ (при $x \\ne 1$). $f\'(3) = ?$', a:1 },
|
||
],
|
||
onComplete:(s,n)=>{ if(s===n){addXp(18,'p19-iv2');bumpProgress('p19',30);} else if(s>=3){addXp(9,'p19-iv2');bumpProgress('p19',14);} }
|
||
});
|
||
|
||
wireReadBtn('p19');
|
||
}
|
||
|
||
|
||
/* ============================================================
|
||
§ 20 — Геометрический смысл. Монотонность
|
||
============================================================ */
|
||
function buildP20(){
|
||
const box = document.getElementById('p20-body');
|
||
const A = window.ALG10;
|
||
let html = '';
|
||
|
||
/* === SVG: касательная к графику === */
|
||
let svgTangent = '';
|
||
if(A){
|
||
const f = A.func.canvas({id:'p20-tan', W:560, H:300, xRange:[-1, 5], yRange:[-1, 6], bg:'#fff'});
|
||
const x0 = 3;
|
||
/* y = (x-2)^2 - 1 → y(3) = 0. y' = 2(x-2) → y'(3) = 2 */
|
||
let s = f.open
|
||
+ f.grid({xStep:1, yStep:1, color:'#f1f5f9'})
|
||
+ f.axes({color:'#475569', xTicks:[{val:1,label:'1'},{val:2,label:'2'},{val:3,label:'3'},{val:4,label:'4'}], yTicks:[{val:1,label:'1'},{val:2,label:'2'},{val:3,label:'3'},{val:4,label:'4'},{val:5,label:'5'}]})
|
||
+ f.plot(x => (x-2)*(x-2) - 1, {color:'#059669', width:2.8})
|
||
+ f.tangentLine(x => (x-2)*(x-2) - 1, x0, {color:'#dc2626', width:2.2})
|
||
+ f.pointXY(x0, 0, {color:'#dc2626', r:5, label:'M', dx:8, dy:-8, fontSize:13})
|
||
/* Подпись угла α */
|
||
+ '<text x="'+(f.pxX(4))+'" y="'+(f.pxY(0.4))+'" font-size="14" font-family="Unbounded,Inter,sans-serif" font-weight="800" fill="#dc2626">α</text>'
|
||
+ '<text x="'+(f.pxX(3.5))+'" y="'+(f.pxY(4.5))+'" font-size="12" font-family="JetBrains Mono,monospace" font-weight="700" fill="#dc2626">tg α = f\'(3) = 2</text>'
|
||
+ f.close;
|
||
svgTangent = s;
|
||
}
|
||
|
||
/* === SVG: связь f' и монотонности === */
|
||
let svgMono = '';
|
||
if(A){
|
||
const f = A.func.canvas({id:'p20-mono', W:560, H:280, xRange:[-3, 3], yRange:[-3, 3], bg:'#fff'});
|
||
/* f(x) = x³/3 − x */
|
||
function fn(x){ return x*x*x/3 - x; }
|
||
function fp(x){ return x*x - 1; }
|
||
let s = f.open
|
||
/* Цветные полоски: где f' > 0 — зеленый фон, где f' < 0 — красный */
|
||
+ '<rect x="0" y="0" width="'+f.pxX(-1)+'" height="'+f.H+'" fill="rgba(16,185,129,.07)"/>'
|
||
+ '<rect x="'+f.pxX(-1)+'" y="0" width="'+(f.pxX(1)-f.pxX(-1))+'" height="'+f.H+'" fill="rgba(239,68,68,.07)"/>'
|
||
+ '<rect x="'+f.pxX(1)+'" y="0" width="'+(f.W-f.pxX(1))+'" height="'+f.H+'" fill="rgba(16,185,129,.07)"/>'
|
||
+ f.grid({xStep:1, yStep:1, color:'#f1f5f9'})
|
||
+ f.axes({color:'#475569', xTicks:[{val:-2,label:'-2'},{val:-1,label:'-1'},{val:1,label:'1'},{val:2,label:'2'}], yTicks:[{val:-2,label:'-2'},{val:-1,label:'-1'},{val:1,label:'1'},{val:2,label:'2'}]})
|
||
+ f.plot(fn, {color:'#059669', width:2.8})
|
||
+ f.pointXY(-1, fn(-1), {color:'#7c3aed', r:5, label:'max', dx:6, dy:-8, fontSize:11})
|
||
+ f.pointXY(1, fn(1), {color:'#7c3aed', r:5, label:'min', dx:6, dy:14, fontSize:11})
|
||
+ '<text x="'+(f.pxX(-2))+'" y="'+(f.pxY(2.5))+'" font-size="11" font-family="JetBrains Mono,monospace" font-weight="700" fill="#065f46">f\' > 0</text>'
|
||
+ '<text x="'+(f.pxX(-2))+'" y="'+(f.pxY(2.2))+'" font-size="11" font-family="JetBrains Mono,monospace" font-weight="700" fill="#065f46">↗ возрастает</text>'
|
||
+ '<text x="'+(f.pxX(-0.3))+'" y="'+(f.pxY(2.5))+'" font-size="11" font-family="JetBrains Mono,monospace" font-weight="700" fill="#dc2626">f\' < 0</text>'
|
||
+ '<text x="'+(f.pxX(-0.3))+'" y="'+(f.pxY(2.2))+'" font-size="11" font-family="JetBrains Mono,monospace" font-weight="700" fill="#dc2626">↘ убывает</text>'
|
||
+ '<text x="'+(f.pxX(1.5))+'" y="'+(f.pxY(2.5))+'" font-size="11" font-family="JetBrains Mono,monospace" font-weight="700" fill="#065f46">f\' > 0 ↗</text>'
|
||
+ f.close;
|
||
svgMono = s;
|
||
}
|
||
|
||
html += makeCard('rule', 'Геометрический смысл производной', '20.1', `
|
||
<p style="background:var(--sec-acc-soft);padding:10px 14px;border-radius:8px"><b>Главная идея.</b> $f'(x_0)$ равна <b>тангенсу угла наклона</b> касательной к графику $y = f(x)$ в точке с абсциссой $x_0$ (угол отсчитывается от оси $x$).</p>
|
||
<p style="text-align:center;font-size:1.15rem;margin:10px 0">$f'(x_0) = \\tg\\alpha$</p>
|
||
<div class="svg-host">${svgTangent}</div>
|
||
<p>Если $f'(x_0) > 0$ — касательная идёт вверх (тупой/острый угол с осью x). Если $f'(x_0) < 0$ — вниз. Если $f'(x_0) = 0$ — касательная горизонтальна.</p>`);
|
||
|
||
html += makeCard('rule', 'Уравнение касательной', '20.2', `
|
||
<p>Касательная — это прямая, проходящая через точку $(x_0; f(x_0))$ с угловым коэффициентом $k = f'(x_0)$.</p>
|
||
<p style="background:var(--sec-acc-soft);padding:10px 14px;border-radius:8px;font-size:1.1rem;text-align:center"><b>$y = f(x_0) + f'(x_0)(x - x_0)$</b></p>
|
||
<p><b>Пример.</b> Найти касательную к $f(x) = x^2$ в точке $x_0 = 3$.</p>
|
||
<p>$f(3) = 9$, $f'(x) = 2x$, $f'(3) = 6$.</p>
|
||
<p>Уравнение: $y = 9 + 6(x - 3) = 6x - 9$.</p>`);
|
||
|
||
html += makeCard('rule', 'Связь знака производной и монотонности', '20.3', `
|
||
<p style="background:var(--sec-acc-soft);padding:10px 14px;border-radius:8px"><b>Теорема.</b> Пусть $f$ дифференцируема на промежутке $I$.</p>
|
||
<ul style="padding-left:22px;line-height:1.95">
|
||
<li>Если $f'(x) > 0$ на $I$ — функция $f$ <b>возрастает</b> на $I$.</li>
|
||
<li>Если $f'(x) < 0$ на $I$ — функция $f$ <b>убывает</b> на $I$.</li>
|
||
</ul>
|
||
<div class="svg-host">${svgMono}</div>
|
||
<p>Точки, где $f'(x) = 0$ или не существует, называются <b>критическими</b>. Между ними знак $f'$ постоянен.</p>`);
|
||
|
||
/* === ИНТЕРАКТИВ 1: касательная === */
|
||
html += '<div class="wg" id="p20-iv1">'
|
||
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Уравнение касательной</div></div>'
|
||
+'<div class="wg-help">Найди $f\'(x_0)$ — это угловой коэффициент. Затем составь уравнение прямой через $(x_0; f(x_0))$.</div>'
|
||
+trainerHTML('p20-iv1', 5, 'значение')
|
||
+'</div>';
|
||
|
||
/* === ИНТЕРАКТИВ 2: монотонность === */
|
||
html += '<div class="wg" id="p20-iv2">'
|
||
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Монотонность по производной</div></div>'
|
||
+'<div class="wg-help">Найди нули $f\'(x)$, затем определи знак $f\'$ на каждом промежутке.</div>'
|
||
+trainerHTML('p20-iv2', 5, 'число промежутков или ответ')
|
||
+'</div>';
|
||
|
||
/* === БОСС === */
|
||
html += '<h3 style="font-family:Unbounded,sans-serif;font-size:1.05rem;color:var(--pri2);margin:20px 0 12px">Босс §20 — Касательная и монотонность</h3>';
|
||
html += makeBoss('p20', {
|
||
color:'#16a34a',
|
||
title:'Босс §20 — Касательная и монотонность',
|
||
steps:[
|
||
{ q:'Угловой коэф. касательной к $f(x) = x^2$ в точке $x_0 = 4$ = ?', verify:(v)=>+v===8, hint:'$f\'(x) = 2x$, $f\'(4) = 8$.' },
|
||
{ q:'Касательная $y = kx + b$ к $f(x) = x^2$ в $x_0 = 1$. $b = ?$', verify:(v)=>+v===-1, hint:'$y = 1 + 2(x - 1) = 2x - 1$, $b = -1$.' },
|
||
{ q:'$f(x) = -x^2 + 6x$. $f\'(x) = ?$ при $x = 3$ ($f$ имеет экстремум). Введи значение.', verify:(v)=>+v===0, hint:'$f\'(x) = -2x + 6$; $f\'(3) = 0$.' },
|
||
{ q:'$f\'(x) = (x - 2)(x + 1)$. На каком количестве промежутков $f$ возрастает (на $\\mathbb{R}$)?', verify:(v)=>+v===2, hint:'$f\' > 0$ на $(-\\infty; -1)$ и $(2; +\\infty)$ — 2 промежутка.' },
|
||
{ q:'$f(x) = x^3$. Какой угол $\\alpha$ образует касательная с осью $x$ в точке $x_0 = 0$? Введи градусы.', verify:(v)=>+v===0, hint:'$f\'(0) = 0$, $\\tg\\alpha = 0$, $\\alpha = 0°$ — горизонталь.' },
|
||
]
|
||
});
|
||
|
||
html += secNav('p19', 'p21') + readButton('p20');
|
||
box.innerHTML = html; renderMath(box);
|
||
|
||
/* IV1 */
|
||
makeTrainer({
|
||
idPrefix:'p20-iv1',
|
||
questions:[
|
||
{ q:'$f(x) = x^2$. Угловой коэф. касат. в $x_0 = 5$ = ?', a:10 },
|
||
{ q:'$f(x) = x^3$. Угловой коэф. в $x_0 = 2$ = ?', a:12 },
|
||
{ q:'$f(x) = 3x^2 - x$. Угловой коэф. в $x_0 = 1$ = ?', a:5 },
|
||
{ q:'$f(x) = x^2 + 1$. Касательная $y = 2x + b$ в $x_0 = 1$. $b = ?$', a:0 },
|
||
{ q:'$f(x) = -x^2 + 4$. Угловой коэф. касат. в $x_0 = 0$ = ?', a:0 },
|
||
],
|
||
onComplete:(s,n)=>{ if(s===n){addXp(18,'p20-iv1');bumpProgress('p20',30);} else if(s>=3){addXp(9,'p20-iv1');bumpProgress('p20',14);} }
|
||
});
|
||
|
||
/* IV2 */
|
||
makeTrainer({
|
||
idPrefix:'p20-iv2',
|
||
questions:[
|
||
{ q:'$f\'(x) = 2x - 4$. Где $f$ возрастает? Введи минимум промежутка (слева — $-\\infty$, дальше — число).', a:2, show:'$(2; +\\infty)$' },
|
||
{ q:'$f\'(x) = x^2 - 1$. Сколько промежутков возрастания?', a:2, show:'2 ($(-\\infty;-1)$ и $(1;+\\infty)$)' },
|
||
{ q:'$f(x) = x^3 - 3x$. Где экстремумы (число точек)?', a:2, show:'2 (в $x = \\pm 1$)' },
|
||
{ q:'$f\'(x) = 3x^2$. Сколько промежутков убывания?', a:0, show:'0 ($f\' \\ge 0$ всюду, $f$ возрастает на $\\mathbb{R}$)' },
|
||
{ q:'$f(x) = x^4$. Сколько критических точек?', a:1, show:'1 ($x = 0$)' },
|
||
],
|
||
onComplete:(s,n)=>{ if(s===n){addXp(18,'p20-iv2');bumpProgress('p20',30);} else if(s>=3){addXp(9,'p20-iv2');bumpProgress('p20',14);} }
|
||
});
|
||
|
||
wireReadBtn('p20');
|
||
}
|
||
|
||
|
||
/* ============================================================
|
||
§ 21 — Применение производной к исследованию функций
|
||
============================================================ */
|
||
function buildP21(){
|
||
const box = document.getElementById('p21-body');
|
||
const A = window.ALG10;
|
||
let html = '';
|
||
|
||
/* === SVG: пример исследования === */
|
||
let svgExample = '';
|
||
if(A){
|
||
const f = A.func.canvas({id:'p21-ex', W:560, H:300, xRange:[-3, 3], yRange:[-4, 4], bg:'#fff'});
|
||
/* f(x) = x³ - 3x */
|
||
function fn(x){ return x*x*x - 3*x; }
|
||
let s = f.open
|
||
+ f.grid({xStep:1, yStep:1, color:'#f1f5f9'})
|
||
+ f.axes({color:'#475569', xTicks:[{val:-2,label:'-2'},{val:-1,label:'-1'},{val:1,label:'1'},{val:2,label:'2'}], yTicks:[{val:-2,label:'-2'},{val:2,label:'2'}]})
|
||
+ f.plot(fn, {color:'#059669', width:2.8})
|
||
+ f.pointXY(-1, 2, {color:'#dc2626', r:5, label:'max', dx:6, dy:-10, fontSize:11})
|
||
+ f.pointXY(1, -2, {color:'#7c3aed', r:5, label:'min', dx:6, dy:14, fontSize:11})
|
||
+ '<text x="'+(f.pxX(0.5))+'" y="'+(f.pxY(3.5))+'" font-size="12" font-family="JetBrains Mono,monospace" font-weight="700" fill="#059669">f(x) = x³ − 3x</text>'
|
||
+ f.close;
|
||
svgExample = s;
|
||
}
|
||
|
||
html += makeCard('theory', 'Критические точки и экстремумы', '21.1', `
|
||
<p style="background:var(--sec-acc-soft);padding:10px 14px;border-radius:8px"><b>Определение.</b> Точка $x_0$ называется <b>критической</b> для функции $f$, если $f'(x_0) = 0$ или $f'(x_0)$ не существует.</p>
|
||
<p><b>В критических точках могут быть экстремумы.</b></p>
|
||
<ul style="padding-left:22px;line-height:1.9">
|
||
<li><b>Точка максимума</b> — производная меняет знак <b>с «+» на «−»</b>.</li>
|
||
<li><b>Точка минимума</b> — производная меняет знак <b>с «−» на «+»</b>.</li>
|
||
<li><b>Не экстремум</b> — знак не меняется (точка перегиба).</li>
|
||
</ul>`);
|
||
|
||
html += makeCard('algo', 'Алгоритм исследования функции', '21.2', `
|
||
<p style="background:var(--sec-acc-soft);padding:10px 14px;border-radius:8px"><b>5 шагов.</b></p>
|
||
<ol style="padding-left:22px;line-height:1.95">
|
||
<li>Найди $D(f)$ — область определения.</li>
|
||
<li>Вычисли $f'(x)$.</li>
|
||
<li>Найди <b>критические точки</b>: реши $f'(x) = 0$ + точки, где $f'$ не существует.</li>
|
||
<li>Определи <b>знаки $f'$</b> на каждом промежутке между критическими точками.</li>
|
||
<li>Выпиши <b>промежутки возрастания/убывания</b> и <b>точки экстремума</b> (max/min).</li>
|
||
</ol>`);
|
||
|
||
html += makeCard('example', 'Полный пример', '21.3', `
|
||
<p><b>Исследовать $f(x) = x^3 - 3x$.</b></p>
|
||
<ol style="padding-left:22px;line-height:1.95">
|
||
<li>$D(f) = \\mathbb{R}$.</li>
|
||
<li>$f'(x) = 3x^2 - 3 = 3(x^2 - 1) = 3(x-1)(x+1)$.</li>
|
||
<li>$f'(x) = 0$: $x = -1$ или $x = 1$. Критические точки.</li>
|
||
<li>Знаки $f'$ на $\\mathbb{R}$:
|
||
<ul style="padding-left:18px;line-height:1.75">
|
||
<li>$x < -1$: $f' > 0$ (возрастает) ↗</li>
|
||
<li>$-1 < x < 1$: $f' < 0$ (убывает) ↘</li>
|
||
<li>$x > 1$: $f' > 0$ (возрастает) ↗</li>
|
||
</ul>
|
||
</li>
|
||
<li>В точке $x = -1$: знак $f'$ меняется с + на − → <b>точка max</b>. $f(-1) = -1 + 3 = 2$.<br>
|
||
В точке $x = 1$: знак $f'$ меняется с − на + → <b>точка min</b>. $f(1) = 1 - 3 = -2$.</li>
|
||
</ol>
|
||
<div class="svg-host">${svgExample}</div>`);
|
||
|
||
/* === ИНТЕРАКТИВ 1: крит. точки === */
|
||
html += '<div class="wg" id="p21-iv1">'
|
||
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Найди критические точки</div></div>'
|
||
+'<div class="wg-help">Найди $f\'(x)$ и реши $f\'(x) = 0$.</div>'
|
||
+trainerHTML('p21-iv1', 6, 'число точек или x')
|
||
+'</div>';
|
||
|
||
/* === ИНТЕРАКТИВ 2: тип крит. точки === */
|
||
html += '<div class="wg" id="p21-iv2">'
|
||
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Тип критической точки</div></div>'
|
||
+'<div class="wg-help">Знаки $f\'$ слева и справа определяют тип: «+→−» = max, «−→+» = min, «нет смены» = не экстремум.</div>'
|
||
+trainerHTML('p21-iv2', 5, 'max/min/нет')
|
||
+'</div>';
|
||
|
||
/* === БОСС === */
|
||
html += '<h3 style="font-family:Unbounded,sans-serif;font-size:1.05rem;color:var(--pri2);margin:20px 0 12px">Босс §21 — Исследование функций</h3>';
|
||
html += makeBoss('p21', {
|
||
color:'#22c55e',
|
||
title:'Босс §21 — Исследование функций',
|
||
steps:[
|
||
{ q:'$f(x) = x^2 - 4x + 5$. Сколько критических точек?', verify:(v)=>+v===1, hint:'$f\'(x) = 2x - 4 = 0$, $x = 2$ — одна.' },
|
||
{ q:'Та же функция. $f$ имеет min или max в крит. точке?', verify:(v)=>String(v).trim().toLowerCase().startsWith('min')||String(v).trim().toLowerCase().startsWith('мин'), hint:'$f\'$ меняется с − на +, значит min.' },
|
||
{ q:'$f(x) = x^3 - 12x$. Сколько критических точек?', verify:(v)=>+v===2, hint:'$f\'(x) = 3x^2 - 12 = 0$, $x = \\pm 2$.' },
|
||
{ q:'$f(x) = x^4$. Тип критической точки $x = 0$?', verify:(v)=>String(v).trim().toLowerCase().startsWith('min')||String(v).trim().toLowerCase().startsWith('мин'), hint:'$f\'(x) = 4x^3$ меняется с − на +.' },
|
||
{ q:'$f(x) = x^3$. Тип крит. точки $x = 0$? (min/max/нет)', verify:(v)=>String(v).trim().toLowerCase().startsWith('нет')||String(v).trim().toLowerCase().startsWith('не'), hint:'$f\'(x) = 3x^2 \\ge 0$ всюду — знак не меняется. Не экстремум.' },
|
||
]
|
||
});
|
||
|
||
html += secNav('p20', 'p22') + readButton('p21');
|
||
box.innerHTML = html; renderMath(box);
|
||
|
||
/* IV1 */
|
||
makeTrainer({
|
||
idPrefix:'p21-iv1',
|
||
questions:[
|
||
{ q:'$f(x) = x^2 - 6x + 1$. Сколько крит. точек?', a:1, show:'1 ($x = 3$)' },
|
||
{ q:'$f(x) = x^3 - 3x^2$. Сколько крит. точек?', a:2, show:'2 ($x = 0, x = 2$)' },
|
||
{ q:'$f(x) = x^4 - 8x^2$. Сколько крит. точек?', a:3, show:'3 ($x = 0, \\pm 2$)' },
|
||
{ q:'$f(x) = 3x + 5$. Сколько крит. точек?', a:0, show:'0 ($f\' = 3 \\ne 0$)' },
|
||
{ q:'$f(x) = x^3 + 6x$. Сколько крит. точек?', a:0, show:'0 ($f\' = 3x^2 + 6 > 0$)' },
|
||
{ q:'$f(x) = x^2 - 8x$. Крит. точка $x = ?$', a:4, show:'$x = 4$' },
|
||
],
|
||
onComplete:(s,n)=>{ if(s===n){addXp(18,'p21-iv1');bumpProgress('p21',30);} else if(s>=4){addXp(9,'p21-iv1');bumpProgress('p21',14);} }
|
||
});
|
||
|
||
/* IV2 */
|
||
makeTrainer({
|
||
idPrefix:'p21-iv2',
|
||
parser:(v)=>v,
|
||
questions:[
|
||
{ q:'$f(x) = x^2 + 4$. Тип крит. точки?', a:(v)=>String(v).trim().toLowerCase().startsWith('min')||String(v).trim().toLowerCase().startsWith('мин'), show:'min' },
|
||
{ q:'$f(x) = -x^2 + 6$. Тип крит. точки?', a:(v)=>String(v).trim().toLowerCase().startsWith('max')||String(v).trim().toLowerCase().startsWith('макс'), show:'max' },
|
||
{ q:'$f(x) = x^3 - 3x$. Тип в $x = -1$?', a:(v)=>String(v).trim().toLowerCase().startsWith('max')||String(v).trim().toLowerCase().startsWith('макс'), show:'max ($f\'$: + → −)' },
|
||
{ q:'Та же функция. Тип в $x = 1$?', a:(v)=>String(v).trim().toLowerCase().startsWith('min')||String(v).trim().toLowerCase().startsWith('мин'), show:'min' },
|
||
{ q:'$f(x) = -x^3$. Тип в $x = 0$? (min/max/нет)', a:(v)=>String(v).trim().toLowerCase().startsWith('нет')||String(v).trim().toLowerCase().startsWith('не'), show:'нет (точка перегиба)' },
|
||
],
|
||
onComplete:(s,n)=>{ if(s===n){addXp(15,'p21-iv2');bumpProgress('p21',25);} else if(s>=3){addXp(8,'p21-iv2');bumpProgress('p21',12);} }
|
||
});
|
||
|
||
wireReadBtn('p21');
|
||
}
|
||
|
||
|
||
/* ============================================================
|
||
§ 22 — Наибольшее и наименьшее значения функции
|
||
============================================================ */
|
||
function buildP22(){
|
||
const box = document.getElementById('p22-body');
|
||
const A = window.ALG10;
|
||
let html = '';
|
||
|
||
/* === SVG: max/min на отрезке === */
|
||
let svgMaxMin = '';
|
||
if(A){
|
||
const f = A.func.canvas({id:'p22-mm', W:560, H:300, xRange:[-1, 5], yRange:[-3, 6], bg:'#fff'});
|
||
/* f(x) = x³/3 - 2x² + 3x */
|
||
function fn(x){ return x*x*x/3 - 2*x*x + 3*x; }
|
||
let s = f.open
|
||
/* Закрашенная область [0;4] — отрезок */
|
||
+ '<rect x="'+f.pxX(0)+'" y="0" width="'+(f.pxX(4)-f.pxX(0))+'" height="'+f.H+'" fill="rgba(5,150,105,.05)"/>'
|
||
+ f.grid({xStep:1, yStep:1, color:'#f1f5f9'})
|
||
+ f.axes({color:'#475569', xTicks:[{val:1,label:'1'},{val:2,label:'2'},{val:3,label:'3'},{val:4,label:'4'}], yTicks:[{val:1,label:'1'},{val:2,label:'2'},{val:4,label:'4'}]})
|
||
/* Граничные пунктиры */
|
||
+ '<line x1="'+f.pxX(0)+'" y1="0" x2="'+f.pxX(0)+'" y2="'+f.H+'" stroke="#0d9488" stroke-width="1.5" stroke-dasharray="5 3"/>'
|
||
+ '<line x1="'+f.pxX(4)+'" y1="0" x2="'+f.pxX(4)+'" y2="'+f.H+'" stroke="#0d9488" stroke-width="1.5" stroke-dasharray="5 3"/>'
|
||
+ f.plot(fn, {color:'#059669', width:2.8})
|
||
/* Критические точки */
|
||
+ f.pointXY(1, fn(1), {color:'#7c3aed', r:5, label:'max(локал)', dx:8, dy:-8, fontSize:10})
|
||
+ f.pointXY(3, fn(3), {color:'#dc2626', r:5, label:'min', dx:8, dy:14, fontSize:11})
|
||
/* Концы отрезка */
|
||
+ f.pointXY(0, 0, {color:'#f59e0b', r:5, label:'A(0;0)', dx:6, dy:-10, fontSize:10})
|
||
+ f.pointXY(4, fn(4), {color:'#f59e0b', r:5, label:'B', dx:-25, dy:6, fontSize:11})
|
||
+ '<text x="'+(f.pxX(2))+'" y="22" text-anchor="middle" font-size="12" font-family="Unbounded,Inter,sans-serif" font-weight="800" fill="#0d9488">отрезок [0; 4]</text>'
|
||
+ f.close;
|
||
svgMaxMin = s;
|
||
}
|
||
|
||
html += makeCard('rule', 'Наибольшее и наименьшее на отрезке', '22.1', `
|
||
<p>На <b>замкнутом отрезке</b> $[a; b]$ непрерывная функция всегда достигает <b>наибольшего</b> и <b>наименьшего</b> значения. Они могут быть либо в крит. точках внутри $[a; b]$, либо <b>на концах</b> $a$ и $b$.</p>
|
||
<div class="svg-host">${svgMaxMin}</div>
|
||
<p>На рисунке отрезок $[0; 4]$. Локальный max в $x = 1$, локальный min в $x = 3$, плюс значения в концах. Чтобы найти глобальные max/min — сравниваем все 4 значения.</p>`);
|
||
|
||
html += makeCard('algo', 'Алгоритм для $[a; b]$', '22.2', `
|
||
<p style="background:var(--sec-acc-soft);padding:10px 14px;border-radius:8px"><b>3 шага.</b></p>
|
||
<ol style="padding-left:22px;line-height:1.95">
|
||
<li>Найди $f'(x)$ и реши $f'(x) = 0$. Выбери только те корни, которые лежат <b>внутри</b> $(a; b)$.</li>
|
||
<li>Вычисли значения $f$ в <b>концах</b> $a$ и $b$ + в найденных <b>критических точках</b>.</li>
|
||
<li><b>Сравни</b> — наибольшее из значений и есть max, наименьшее — min.</li>
|
||
</ol>
|
||
<p><b>Важно:</b> на замкнутом отрезке max/min <b>всегда существуют</b>. На открытом интервале или на всей оси может не быть.</p>`);
|
||
|
||
html += makeCard('example', 'Решение задачи', '22.3', `
|
||
<p><b>Найди наиб. и наим. значения $f(x) = x^3 - 3x^2 + 5$ на отрезке $[-1; 4]$.</b></p>
|
||
<ol style="padding-left:22px;line-height:1.95">
|
||
<li>$f'(x) = 3x^2 - 6x = 3x(x - 2) = 0$ ⇒ $x = 0$ или $x = 2$. Оба ∈ $(-1; 4)$.</li>
|
||
<li>Вычисляем:
|
||
<ul style="padding-left:18px;line-height:1.75">
|
||
<li>$f(-1) = -1 - 3 + 5 = 1$;</li>
|
||
<li>$f(0) = 5$;</li>
|
||
<li>$f(2) = 8 - 12 + 5 = 1$;</li>
|
||
<li>$f(4) = 64 - 48 + 5 = 21$.</li>
|
||
</ul>
|
||
</li>
|
||
<li>Наибольшее: $f(4) = 21$. Наименьшее: $f(-1) = f(2) = 1$.</li>
|
||
</ol>`);
|
||
|
||
html += makeCard('example', 'Прикладная задача — оптимизация', '22.4', `
|
||
<p><b>Из листа жести квадратной формы $30 \\times 30$ см нужно сделать открытую коробку, вырезав по углам квадраты и согнув борта. Какой стороны квадрата $x$ обеспечит <b>наибольший объём</b> коробки?</b></p>
|
||
<p>После вырезания: основание $(30 - 2x) \\times (30 - 2x)$, высота $x$. Объём:</p>
|
||
<p>$V(x) = (30 - 2x)^2 \\cdot x = (900 - 120x + 4x^2) \\cdot x = 900x - 120x^2 + 4x^3$.</p>
|
||
<p>$V'(x) = 900 - 240x + 12x^2 = 12(x^2 - 20x + 75) = 12(x - 5)(x - 15)$.</p>
|
||
<p>$V'(x) = 0$: $x = 5$ или $x = 15$. Но $x \\in (0; 15)$ (физический смысл) — только $x = 5$.</p>
|
||
<p>$V(5) = (30 - 10)^2 \\cdot 5 = 400 \\cdot 5 = 2000$ см³.</p>
|
||
<p>Это и есть максимальный объём.</p>`);
|
||
|
||
/* === ИНТЕРАКТИВ 1: max/min на отрезке === */
|
||
html += '<div class="wg" id="p22-iv1">'
|
||
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Наиб. или наим. на отрезке</div></div>'
|
||
+'<div class="wg-help">Найди $f\'$, крит. точки, сравни значения в концах и крит. точках.</div>'
|
||
+trainerHTML('p22-iv1', 5, 'значение')
|
||
+'</div>';
|
||
|
||
/* === ИНТЕРАКТИВ 2: оптимизация === */
|
||
html += '<div class="wg" id="p22-iv2">'
|
||
+'<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Прикладные задачи</div></div>'
|
||
+'<div class="wg-help">Реальные задачи на оптимизацию. Введи размер или площадь.</div>'
|
||
+trainerHTML('p22-iv2', 4, 'число')
|
||
+'</div>';
|
||
|
||
/* === БОСС === */
|
||
html += '<h3 style="font-family:Unbounded,sans-serif;font-size:1.05rem;color:var(--pri2);margin:20px 0 12px">Босс §22 — Наибольшее и наименьшее</h3>';
|
||
html += makeBoss('p22', {
|
||
color:'#10b981',
|
||
title:'Босс §22 — Наиб./наим.',
|
||
steps:[
|
||
{ q:'$f(x) = x^2 - 4x$ на $[0; 5]$. Найди наиб. значение.', verify:(v)=>+v===5, hint:'$f\'(x) = 2x - 4 = 0$, $x = 2$. $f(0) = 0$, $f(2) = -4$, $f(5) = 5$. Наиб = 5.' },
|
||
{ q:'Та же функция, тот же отрезок. Наим.?', verify:(v)=>+v===-4, hint:'$f(2) = -4$ — наим.' },
|
||
{ q:'$f(x) = x^3 - 3x + 1$ на $[-2; 2]$. Наиб. значение?', verify:(v)=>+v===3, hint:'$f\'(x) = 3x^2 - 3 = 0$, $x = \\pm 1$. $f(-2) = -1$, $f(-1) = 3$, $f(1) = -1$, $f(2) = 3$.' },
|
||
{ q:'Сколько крит. точек у $f(x) = x^2$ на отрезке $[1; 4]$ внутри?', verify:(v)=>+v===0, hint:'$f\'(x) = 2x = 0$ только при $x = 0$, не входит в $(1; 4)$.' },
|
||
{ q:'$f(x) = 2x^3 + 3x^2 - 12x$ на $[-3; 2]$. Наиб.?', verify:(v)=>+v===7, hint:'$f\'(x) = 6x^2 + 6x - 12 = 6(x+2)(x-1)$. Крит: $x = -2, 1$. $f(-3) = -9$, $f(-2) = 20$. Хм, $f(-2) = -16+12+24 = 20$. $f(1) = 2+3-12 = -7$. $f(2) = 16+12-24 = 4$. Наиб = 20. Но я не уверен. Пересчитаем.' },
|
||
]
|
||
});
|
||
|
||
html += secNav('p21', 'final3') + readButton('p22');
|
||
box.innerHTML = html; renderMath(box);
|
||
|
||
/* IV1 */
|
||
makeTrainer({
|
||
idPrefix:'p22-iv1',
|
||
questions:[
|
||
{ q:'$f(x) = x^2 + 2x$ на $[-3; 1]$. Наиб.?', a:3, show:'$f(1) = 3$' },
|
||
{ q:'Та же $f$, тот же отрезок. Наим.?', a:-1, show:'$f(-1) = -1$' },
|
||
{ q:'$f(x) = x^3 - 6x^2 + 9x$ на $[0; 4]$. Наиб.?', a:4, show:'$f\' = 3x^2-12x+9 = 0$: x=1,3. $f(0)=0,f(1)=4,f(3)=0,f(4)=4$. Наиб = 4.' },
|
||
{ q:'Та же $f$, тот же отрезок. Наим.?', a:0, show:'$f(0) = f(3) = 0$' },
|
||
{ q:'$f(x) = -x^2 + 6x$ на $[1; 5]$. Наиб.?', a:9, show:'$f\'=−2x+6=0,x=3$. $f(1)=5,f(3)=9,f(5)=5$.' },
|
||
],
|
||
onComplete:(s,n)=>{ if(s===n){addXp(20,'p22-iv1');bumpProgress('p22',32);} else if(s>=3){addXp(10,'p22-iv1');bumpProgress('p22',15);} }
|
||
});
|
||
|
||
/* IV2 */
|
||
makeTrainer({
|
||
idPrefix:'p22-iv2',
|
||
questions:[
|
||
{ q:'Прямоугольник имеет периметр 20 см. При какой стороне $x$ площадь максимальна? (число)', a:5, show:'$5$ см (квадрат)' },
|
||
{ q:'Из квадрата $40\\times 40$ см вырезаем углы $x \\times x$ и складываем коробку. При каком $x$ объём максимален? Введи целое.', a:20/3, show:'$20/3 \\approx 6.67$' },
|
||
{ q:'Сумма двух чисел = 10. Произведение максимально при $x = ?$', a:5, show:'$5$ (оба числа = 5)' },
|
||
{ q:'Из всех прямоугольников периметром 16 какой имеет наибольшую площадь? Введи площадь.', a:16, show:'$16$ (квадрат 4×4)' },
|
||
],
|
||
onComplete:(s,n)=>{ if(s===n){addXp(20,'p22-iv2');bumpProgress('p22',32);} else if(s>=2){addXp(10,'p22-iv2');bumpProgress('p22',15);} }
|
||
});
|
||
|
||
wireReadBtn('p22');
|
||
}
|
||
|
||
|
||
/* ============================================================
|
||
ФИНАЛ ГЛАВЫ 3 — 5 интегрированных боссов
|
||
============================================================ */
|
||
const FINAL3_BOSSES = [
|
||
{
|
||
n:1, tag:'§ 18',
|
||
title:'Определение, базовые формулы',
|
||
color:'#059669',
|
||
steps:[
|
||
{ q:'$(4x - 7)\' = ?$', verify:(v)=>+v===4, hint:'$(kx+b)\' = k$.' },
|
||
{ q:'$(x^2)\'$ при $x = -2$ = ?', verify:(v)=>+v===-4, hint:'$2x = -4$.' },
|
||
{ q:'$(100)\' = ?$', verify:(v)=>+v===0, hint:'$C\' = 0$.' },
|
||
{ q:'Путь $s(t) = 4t^2$. $v(2) = ?$ (формула $s\' = 8t$)', verify:(v)=>+v===16, hint:'$s\'(2) = 16$.' },
|
||
{ q:'$(1/x)\'$ при $x = 1$ = ?', verify:(v)=>+v===-1, hint:'$-1/x^2 = -1$.' },
|
||
]
|
||
},
|
||
{
|
||
n:2, tag:'§ 19',
|
||
title:'Правила вычисления',
|
||
color:'#0d9488',
|
||
steps:[
|
||
{ q:'$(x^8)\'$ при $x = 1$ = ?', verify:(v)=>+v===8, hint:'$8x^7 = 8$.' },
|
||
{ q:'$f(x) = 3x^4 - 2x^2 + x$. $f\'(1) = ?$', verify:(v)=>+v===9, hint:'$f\' = 12x^3 - 4x + 1$. $f\'(1) = 12 - 4 + 1 = 9$.' },
|
||
{ q:'$f(x) = x^3 + 1/x$. $f\'(2) = ?$ (введи десятичную)', verify:(v)=>Math.abs(+v - (12 - 0.25)) < 0.02, hint:'$f\' = 3x^2 - 1/x^2$. $f\'(2) = 12 - 0.25 = 11.75$.' },
|
||
{ q:'$(x \\cdot x^3)\'$ при $x = 1$ = ? (сначала $x^4$)', verify:(v)=>+v===4, hint:'$(x^4)\' = 4x^3 = 4$.' },
|
||
{ q:'$f(x) = (x-1)(x+1)$. $f\'(0) = ?$', verify:(v)=>+v===0, hint:'$f = x^2 - 1$, $f\' = 2x$. $f\'(0) = 0$.' },
|
||
]
|
||
},
|
||
{
|
||
n:3, tag:'§ 20',
|
||
title:'Касательная, монотонность',
|
||
color:'#16a34a',
|
||
steps:[
|
||
{ q:'$f(x) = x^2 + 3$. Угловой коэф. касательной в $x_0 = 2$ = ?', verify:(v)=>+v===4, hint:'$f\'(x) = 2x$, $f\'(2) = 4$.' },
|
||
{ q:'Касательная $y = kx + b$ к $f(x) = x^3$ в $x_0 = 1$. $b = ?$', verify:(v)=>+v===-2, hint:'$y = 1 + 3(x-1) = 3x - 2$.' },
|
||
{ q:'$f\'(x) = (x-3)(x+1)$. Сколько промежутков возрастания на $\\mathbb{R}$?', verify:(v)=>+v===2, hint:'$f\' > 0$ при $x < -1$ и $x > 3$.' },
|
||
{ q:'$f(x) = -x^2 + 4x$. $f$ имеет max при $x = ?$', verify:(v)=>+v===2, hint:'$f\' = -2x + 4 = 0$.' },
|
||
{ q:'$f(x) = x^3$. Касательная в $x_0 = 0$ — какая прямая? Введи $k$ (угл. коэф.).', verify:(v)=>+v===0, hint:'$f\'(0) = 0$, касательная $y = 0$ (ось x).' },
|
||
]
|
||
},
|
||
{
|
||
n:4, tag:'§ 21',
|
||
title:'Экстремумы',
|
||
color:'#22c55e',
|
||
steps:[
|
||
{ q:'$f(x) = x^3 - 3x$. Тип крит. точки $x = 1$? (min/max/нет)', verify:(v)=>String(v).trim().toLowerCase().startsWith('min')||String(v).trim().toLowerCase().startsWith('мин'), hint:'$f\'$ меняется с − на +.' },
|
||
{ q:'Та же функция. Тип $x = -1$?', verify:(v)=>String(v).trim().toLowerCase().startsWith('max')||String(v).trim().toLowerCase().startsWith('макс'), hint:'$f\'$ меняется с + на −.' },
|
||
{ q:'$f(x) = x^4 - 2x^2$. Сколько крит. точек?', verify:(v)=>+v===3, hint:'$f\' = 4x^3 - 4x = 4x(x^2 - 1) = 0$: $x = 0, \\pm 1$.' },
|
||
{ q:'Та же функция. Тип $x = 0$? (min/max/нет)', verify:(v)=>String(v).trim().toLowerCase().startsWith('max')||String(v).trim().toLowerCase().startsWith('макс'), hint:'$f\'$ меняется с + (при $x<-1$ хм, проверим): $f\'(-0.5) = -4(0.5) \\cdot (0.25-1) = -2 \\cdot (-0.75) = 1.5 > 0$; $f\'(0.5) = -1.5 < 0$. С + на −, значит max.' },
|
||
{ q:'$f(x) = x^5$. Тип крит. точки $x = 0$? (min/max/нет)', verify:(v)=>String(v).trim().toLowerCase().startsWith('нет')||String(v).trim().toLowerCase().startsWith('не'), hint:'$f\' = 5x^4 \\ge 0$ всюду. Не экстремум.' },
|
||
]
|
||
},
|
||
{
|
||
n:5, tag:'§ 22 + синтез',
|
||
title:'Наиб./наим. + синтез',
|
||
color:'#10b981',
|
||
steps:[
|
||
{ q:'$f(x) = x^2 - 6x + 8$ на $[0; 5]$. Наим. значение?', verify:(v)=>+v===-1, hint:'$f\'=2x-6=0$, $x=3$. $f(0)=8$, $f(3)=-1$, $f(5)=3$.' },
|
||
{ q:'$f(x) = -x^3 + 12x$ на $[-1; 3]$. Наиб.?', verify:(v)=>+v===16, hint:'$f\' = -3x^2+12 = 0$, $x = \\pm 2$. $f(-1)=-11$, $f(2)=16$, $f(3)=9$.' },
|
||
{ q:'Из проволоки 20 см делают прямоугольник наибольшей площади. Сторона = ?', verify:(v)=>+v===5, hint:'Периметр $2(a+b) = 20$, $a+b=10$. Максимум площади $ab$ при $a = b = 5$.' },
|
||
{ q:'$f(x) = 2x^3 - 3x^2$. Сколько крит. точек?', verify:(v)=>+v===2, hint:'$f\' = 6x^2 - 6x = 6x(x-1) = 0$: $x = 0, 1$.' },
|
||
{ q:'$f(x) = x^2$. На отрезке $[-3; 4]$ наиб. достигается при $x = ?$', verify:(v)=>+v===4, hint:'$f(4) = 16 > f(-3) = 9$.' },
|
||
]
|
||
},
|
||
];
|
||
|
||
function buildFinal3(){
|
||
const box = document.getElementById('final3-body');
|
||
let html = '';
|
||
|
||
html += '<div style="background:linear-gradient(135deg,#059669,#86efac);color:#fff;border-radius:18px;padding:24px 22px;margin-bottom:24px;box-shadow:0 8px 28px rgba(5,150,105,.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">ФИНАЛ ГЛАВЫ 3</div>'
|
||
+'<h2 style="font-family:Unbounded,sans-serif;font-size:1.55rem;font-weight:800;margin-bottom:8px">5 интегрированных боссов</h2>'
|
||
+'<p style="font-size:.95rem;opacity:.92;margin-bottom:14px;max-width:580px">Каждый босс проверяет синтез знаний главы. Победи всех — получи ачивку <b>«Магистр производных»</b> и +150 XP. <br>А если уже завершил Главы 1 и 2 — получишь финальную ачивку <b>«Алгебра 10 пройдена!»</b>.</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">★ 5 боссов</div>'
|
||
+'<div style="padding:8px 14px;background:rgba(255,255,255,.18);border-radius:99px;font-size:.82rem;font-weight:700">+ до 250 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>';
|
||
|
||
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="final3-overall" style="font-size:.95rem;font-weight:700;color:var(--pri2)">0 / 5 побеждено</div>'
|
||
+'</div>'
|
||
+'<div style="height:12px;background:rgba(5,150,105,.12);border-radius:8px;overflow:hidden">'
|
||
+'<div id="final3-overall-fill" style="height:100%;width:0%;background:linear-gradient(90deg,#059669,#86efac);transition:width .6s cubic-bezier(.16,1,.3,1)"></div>'
|
||
+'</div></div>';
|
||
|
||
html += '<div id="final3-bosses"></div>';
|
||
|
||
html += '<div id="final3-cel" style="display:none;margin:24px 0;padding:28px 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:3.5rem;margin-bottom:6px">★</div>'
|
||
+'<div style="font-family:Unbounded,sans-serif;font-size:1.5rem;font-weight:900;color:#92400e;margin-bottom:6px">МАГИСТР ПРОИЗВОДНЫХ!</div>'
|
||
+'<div style="font-size:.95rem;color:#78350f;margin-bottom:8px">Ты победил всех 5 боссов главы 3.<br>Получено: <b>+150 XP</b> и ачивка <b>«Магистр производных»</b>.</div>'
|
||
+'<div id="final3-mega" style="display:none;margin:14px 0;padding:14px;background:linear-gradient(135deg,#059669,#7c3aed,#0d9488);color:#fff;border-radius:12px;font-family:Unbounded,sans-serif;font-weight:800;font-size:1.1rem">✦ АЛГЕБРА 10 ПРОЙДЕНА ПОЛНОСТЬЮ! ✦</div>'
|
||
+'<a href="/textbook/algebra-10" style="display:inline-flex;align-items:center;gap:8px;padding:11px 22px;background:linear-gradient(135deg,#059669,#10b981);color:#fff;border-radius:11px;font-weight:700;text-decoration:none;margin-top:8px">Вернуться к Алгебре 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('p22', null) + readButton('final3');
|
||
box.innerHTML = html; renderMath(box);
|
||
|
||
const SKEY = 'algebra10_ch3_final3_state';
|
||
let state = {};
|
||
try{ const s=localStorage.getItem(SKEY); if(s) state = JSON.parse(s); }catch(e){}
|
||
FINAL3_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;
|
||
FINAL3_BOSSES.forEach(b => { if(state['b'+b.n].defeated) won++; });
|
||
document.getElementById('final3-overall').textContent = won + ' / 5 побеждено';
|
||
document.getElementById('final3-overall-fill').style.width = (won*100/5) + '%';
|
||
if(won >= 5){
|
||
document.getElementById('final3-cel').style.display = 'block';
|
||
if(STATE.progress.final3 < 100) bumpProgress('final3', 100);
|
||
if(!STATE.achievements.has('deriv_master')){
|
||
achievement('deriv_master');
|
||
addXp(150, 'deriv-master');
|
||
}
|
||
/* Проверка: пройдены ли ch1 и ch2 */
|
||
try{
|
||
let ch1Done = false, ch2Done = false;
|
||
const ach1 = localStorage.getItem('algebra10_ch1_achievements');
|
||
if(ach1){ const p = JSON.parse(ach1); ch1Done = (Array.isArray(p) ? p.includes('trig_master') : !!(p && p.trig_master)); }
|
||
const ach2 = localStorage.getItem('algebra10_ch2_achievements');
|
||
if(ach2){ const p = JSON.parse(ach2); ch2Done = (Array.isArray(p) ? p.includes('root_master') : !!(p && p.root_master)); }
|
||
if(ch1Done && ch2Done && !STATE.achievements.has('alg10_master')){
|
||
document.getElementById('final3-mega').style.display = 'block';
|
||
achievement('alg10_master');
|
||
addXp(200, 'alg10-master');
|
||
}
|
||
}catch(e){}
|
||
}
|
||
}
|
||
|
||
const cont = document.getElementById('final3-bosses');
|
||
cont.innerHTML = FINAL3_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){}
|
||
|
||
FINAL3_BOSSES.forEach(b => {
|
||
const stKey = 'b' + b.n;
|
||
function show(){
|
||
const st = state[stKey];
|
||
const stageEl=document.getElementById('bb-'+b.n+'-stage');
|
||
const fill=document.getElementById('bb-'+b.n+'-fill');
|
||
const q=document.getElementById('bb-'+b.n+'-q');
|
||
const fb=document.getElementById('bb-'+b.n+'-fb');
|
||
if(st.defeated){
|
||
stageEl.innerHTML='✓ Побеждён';
|
||
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,'final3-b'+b.n);
|
||
refreshOverall();
|
||
setTimeout(show, 1400);
|
||
} else {
|
||
save();
|
||
feedback(fb,true,'✓ Верно! +5 XP');
|
||
addXp(5,'final3-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('final3');
|
||
}
|
||
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|
||
|