feat(phys10 ch5 wave4 + final): §33 «Самоиндукция» + Финал Главы 5 (7 боссов)
This commit is contained in:
@@ -2874,35 +2874,629 @@ function build_p32(){
|
||||
function build_p33(){
|
||||
const box = document.getElementById('p33-body');
|
||||
let html = '';
|
||||
html += makeCard('theory', "Самоиндукция", "§33", `
|
||||
<p><b>Самоиндукция</b> — этот параграф в разработке (Phase 1+).</p>
|
||||
<p>Здесь появятся: теория, формулы, разобранные примеры и 3–4 интерактива в стиле «алгебры 11» — таблицы, симуляции, ползунки, drag-and-drop и автопроверяемые тренажёры.</p>
|
||||
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.92rem">
|
||||
<b>Phase 0:</b> создан скелет учебника. <b>Phase 5+:</b> наполнение этого § содержанием по учебнику «Физика 10» (Беларусь, 2019).
|
||||
</p>
|
||||
|
||||
/* THEORY 1 — Самоиндукция и индуктивность */
|
||||
html += makeCard('theory', "Самоиндукция и индуктивность", "§33", `
|
||||
<p><b>Самоиндукция</b> — возникновение ЭДС индукции в катушке при изменении тока в <b>этой же</b> катушке.</p>
|
||||
<p style="margin-top:10px">Когда ток меняется, магнитный поток через катушку (созданный её собственным током) тоже меняется — это вызывает ЭДС индукции по закону Фарадея.</p>
|
||||
<p style="margin-top:10px"><b>Индуктивность</b> $L$ — характеристика катушки, показывающая, какой магнитный поток создаётся в ней при данном токе:</p>
|
||||
<p style="text-align:center;margin:8px 0">$$\\Phi = LI$$</p>
|
||||
<p>где $\\Phi$ — магнитный поток через все витки катушки, $I$ — ток в ней.</p>
|
||||
<p style="margin-top:10px"><b>Единица индуктивности</b>: <b>Генри</b> (Гн) = Вб/А. 1 Гн — индуктивность катушки, в которой ток 1 А создаёт магнитный поток 1 Вб.</p>
|
||||
<p style="margin-top:10px">$L$ зависит от:</p>
|
||||
<ul style="margin:6px 0 6px 22px">
|
||||
<li>числа витков $N$ (квадратично — $L \\propto N^2$);</li>
|
||||
<li>геометрии (длина $\\ell$, площадь сечения $S$);</li>
|
||||
<li>магнитной проницаемости сердечника (с ферромагнитным сердечником $L$ в сотни раз больше).</li>
|
||||
</ul>
|
||||
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px"><b>Аналогия.</b> Индуктивность $L$ для тока — как масса $m$ для скорости: чем больше $L$, тем «тяжелее» меняется ток. Это «электромагнитная инерция».</p>
|
||||
`);
|
||||
|
||||
/* THEORY 2 — ЭДС самоиндукции */
|
||||
html += makeCard('rule', "ЭДС самоиндукции", "§33", `
|
||||
<p>Если ток в катушке меняется со скоростью $\\Delta I/\\Delta t$, в ней возникает ЭДС самоиндукции:</p>
|
||||
<p style="text-align:center;margin:8px 0">$$\\mathcal{E}_{si} = -L\\,\\dfrac{\\Delta I}{\\Delta t}$$</p>
|
||||
<p>Знак «минус» — правило Ленца: ЭДС самоиндукции <b>препятствует</b> изменению тока.</p>
|
||||
<p style="margin-top:10px"><b>При замыкании цепи</b> (ток растёт от 0):</p>
|
||||
<ul style="margin:6px 0 6px 22px">
|
||||
<li>самоиндукция тормозит рост тока;</li>
|
||||
<li>ток нарастает <b>постепенно</b>, а не мгновенно;</li>
|
||||
<li>характерное время: $\\tau = L/R$ — <b>постоянная времени</b> $RL$-цепи.</li>
|
||||
</ul>
|
||||
<p style="margin-top:10px"><b>При размыкании цепи</b> (ток резко падает):</p>
|
||||
<ul style="margin:6px 0 6px 22px">
|
||||
<li>самоиндукция поддерживает ток;</li>
|
||||
<li>может возникнуть <b>искра</b> или большой импульс напряжения на размыкаемом ключе;</li>
|
||||
<li>в мощных катушках при размыкании может быть электрическая дуга или удар.</li>
|
||||
</ul>
|
||||
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px"><b>Мнемоника.</b> Большая $L$ — большая «инерция тока». Ток в катушке не может меняться скачком, как скорость массы не может меняться мгновенно.</p>
|
||||
`);
|
||||
|
||||
/* THEORY 3 — Энергия магнитного поля катушки */
|
||||
html += makeCard('example', "Энергия магнитного поля катушки", "§33", `
|
||||
<p>Заряженный конденсатор запасает энергию в <b>электрическом</b> поле. Катушка с током запасает энергию в <b>магнитном</b> поле:</p>
|
||||
<p style="text-align:center;margin:8px 0">$$W = \\dfrac{LI^2}{2}$$</p>
|
||||
<p>Эта энергия запасена в магнитном поле <b>внутри катушки</b>. При размыкании цепи она возвращается обратно — может уйти в искру, тепло или работу.</p>
|
||||
<p style="margin-top:10px"><b>Аналогия с механикой:</b></p>
|
||||
<ul style="margin:6px 0 6px 22px">
|
||||
<li>$W_k = \\dfrac{mv^2}{2}$ — кинетическая энергия (механика);</li>
|
||||
<li>$W_L = \\dfrac{LI^2}{2}$ — энергия магнитного поля (электродинамика);</li>
|
||||
<li>$L \\leftrightarrow m$, $I \\leftrightarrow v$.</li>
|
||||
</ul>
|
||||
<p style="margin-top:10px"><b>Пример.</b> $L = 0{,}5$ Гн, $I = 4$ А. Тогда $W = LI^2/2 = 0{,}5 \\cdot 16 / 2 = 4$ Дж.</p>
|
||||
<p style="margin-top:10px"><b>Применение:</b></p>
|
||||
<ul style="margin:6px 0 6px 22px">
|
||||
<li><b>Балласты</b> в люминесцентных лампах — индуктивность ограничивает ток при включении;</li>
|
||||
<li><b>Дроссели</b> — ограничивают высокочастотные токи в радиосхемах;</li>
|
||||
<li><b>Импульсные источники питания</b> — запасают и отдают энергию через катушку;</li>
|
||||
<li><b>Беспроводная зарядка</b> (Qi) — передача энергии через переменное магнитное поле;</li>
|
||||
<li><b>Электромагнитные пусковые устройства</b> — огромные токи запасают много энергии для импульсного применения.</li>
|
||||
</ul>
|
||||
`);
|
||||
|
||||
/* INTERACTIVE 1 — LR-цепь: нарастание тока */
|
||||
html += `<div class="wg" id="p33-iv1">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">LR-цепь: нарастание тока при замыкании</div></div>
|
||||
<div class="wg-help">При замыкании цепи ток не достигает $I_{\\max} = \\mathcal{E}/R$ мгновенно — самоиндукция тормозит его рост: $I(t) = I_{\\max}(1 - e^{-t/\\tau})$, где $\\tau = L/R$.</div>
|
||||
<div class="sliders" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:8px">
|
||||
<label>$\\mathcal{E}$ (В): <b id="p33-iv1-EL">6.0</b><input type="range" id="p33-iv1-E" min="1" max="12" value="6" step="0.5"></label>
|
||||
<label>$R$ (Ом): <b id="p33-iv1-RL">10</b><input type="range" id="p33-iv1-R" min="1" max="100" value="10" step="1"></label>
|
||||
<label>$L$ (мГн): <b id="p33-iv1-LL">100</b><input type="range" id="p33-iv1-L" min="1" max="1000" value="100" step="1"></label>
|
||||
</div>
|
||||
<div style="background:var(--card);border:1px solid var(--border);border-radius:9px;padding:8px;margin-top:8px">
|
||||
<svg id="p33-iv1-svg" viewBox="0 0 480 260" width="100%" style="height:auto"></svg>
|
||||
</div>
|
||||
<div class="actions" style="margin-top:8px"><button class="btn primary" id="p33-iv1-go">Замкнуть цепь</button><button class="btn" id="p33-iv1-reset">Сброс</button></div>
|
||||
<div id="p33-iv1-out" style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.95rem;line-height:1.7;text-align:center"></div>
|
||||
</div>`;
|
||||
|
||||
/* INTERACTIVE 2 — Калькулятор индуктивности и энергии */
|
||||
html += `<div class="wg" id="p33-iv2">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Калькулятор: $\\Phi$, $W$ и ЭДС самоиндукции</div></div>
|
||||
<div class="wg-help">$\\Phi = LI$, $W = LI^2/2$, $|\\mathcal{E}_{si}| = L\\,|\\Delta I|/\\Delta t$.</div>
|
||||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:10px;margin-bottom:10px">
|
||||
<label style="display:flex;flex-direction:column;gap:4px;font-size:.92rem">$L$ (Гн):<input type="number" id="p33-iv2-L" value="0.5" step="any" min="0" style="padding:7px;border:1px solid var(--border);border-radius:6px"></label>
|
||||
<label style="display:flex;flex-direction:column;gap:4px;font-size:.92rem">$I$ (А):<input type="number" id="p33-iv2-I" value="4" step="any" style="padding:7px;border:1px solid var(--border);border-radius:6px"></label>
|
||||
<label style="display:flex;flex-direction:column;gap:4px;font-size:.92rem">$\\Delta I$ (А):<input type="number" id="p33-iv2-dI" value="2" step="any" style="padding:7px;border:1px solid var(--border);border-radius:6px"></label>
|
||||
<label style="display:flex;flex-direction:column;gap:4px;font-size:.92rem">$\\Delta t$ (с):<input type="number" id="p33-iv2-dt" value="0.1" step="any" min="0" style="padding:7px;border:1px solid var(--border);border-radius:6px"></label>
|
||||
</div>
|
||||
<div class="actions"><button class="btn primary" id="p33-iv2-calc">Вычислить $\\Phi$, $W$, $|\\mathcal{E}_{si}|$</button></div>
|
||||
<div id="p33-iv2-out" style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.98rem;line-height:1.8;text-align:center;min-height:40px"></div>
|
||||
</div>`;
|
||||
|
||||
/* INTERACTIVE 3 — Что произойдёт с током? */
|
||||
html += `<div class="wg" id="p33-iv3">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 3</span><div class="wg-title">Что произойдёт с током?</div></div>
|
||||
<div class="wg-help">Самоиндукция всегда <b>препятствует</b> изменению тока. При $\\Delta I = 0$ — ЭДС нет.</div>
|
||||
<div class="score-display"><span>Задача <b id="p33-iv3-i">1</b> / 6</span><span>Очки: <b id="p33-iv3-s">0</b> / 6</span></div>
|
||||
<div id="p33-iv3-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.02rem;margin-bottom:10px;text-align:center;min-height:54px"></div>
|
||||
<div id="p33-iv3-opts" style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px"></div>
|
||||
<div class="feedback" id="p33-iv3-fb"></div>
|
||||
<div class="actions"><button class="btn" id="p33-iv3-restart">Начать заново</button></div>
|
||||
</div>`;
|
||||
|
||||
/* INTERACTIVE 4 — Тренажёр индуктивности */
|
||||
html += `<div class="wg" id="p33-iv4">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 4</span><div class="wg-title">Тренажёр: индуктивность и энергия</div></div>
|
||||
<div class="wg-help">5 задач. Допуск ±5%. Формулы: $\\Phi = LI$, $W = LI^2/2$, $|\\mathcal{E}_{si}| = L\\,|\\Delta I|/\\Delta t$, $\\tau = L/R$.</div>
|
||||
<div class="score-display"><span>Задача <b id="p33-iv4-i">1</b> / 5</span><span>Очки: <b id="p33-iv4-s">0</b> / 5</span></div>
|
||||
<div id="p33-iv4-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.02rem;margin-bottom:10px;text-align:center;min-height:54px"></div>
|
||||
<div id="p33-iv4-form" style="display:flex;gap:8px;justify-content:center;margin-bottom:8px;flex-wrap:wrap">
|
||||
<input type="number" id="p33-iv4-inp" step="any" style="padding:8px 10px;border:1px solid var(--border);border-radius:6px;width:140px;font-size:1rem">
|
||||
<button class="btn primary" id="p33-iv4-go">Проверить</button>
|
||||
</div>
|
||||
<div class="feedback" id="p33-iv4-fb"></div>
|
||||
<div class="actions"><button class="btn" id="p33-iv4-restart">Начать заново</button></div>
|
||||
</div>`;
|
||||
|
||||
html += secNav('p32', 'final5');
|
||||
html += readButton('p33');
|
||||
|
||||
box.innerHTML = html;
|
||||
renderMath(box);
|
||||
|
||||
/* IV1 — LR-цепь */
|
||||
(function(){
|
||||
const svg = document.getElementById('p33-iv1-svg');
|
||||
const out = document.getElementById('p33-iv1-out');
|
||||
const EI = document.getElementById('p33-iv1-E'), EL = document.getElementById('p33-iv1-EL');
|
||||
const RI = document.getElementById('p33-iv1-R'), RL = document.getElementById('p33-iv1-RL');
|
||||
const LI = document.getElementById('p33-iv1-L'), LL = document.getElementById('p33-iv1-LL');
|
||||
const bGo = document.getElementById('p33-iv1-go');
|
||||
const bRs = document.getElementById('p33-iv1-reset');
|
||||
let animT0 = null, running = false, rafId = null;
|
||||
let configs = new Set();
|
||||
let _done = false;
|
||||
|
||||
function draw(progress){
|
||||
const W = 480, H = 260;
|
||||
const E = +EI.value, R = +RI.value, L = (+LI.value) / 1000; // Гн
|
||||
EL.textContent = E.toFixed(1);
|
||||
RL.textContent = R.toString();
|
||||
LL.textContent = (+LI.value).toString();
|
||||
const Imax = E / R;
|
||||
const tau = L / R;
|
||||
// total animation time ~ 5*tau, мин 0.6 с, макс 3 с
|
||||
const animDur = Math.max(0.6, Math.min(3, 5*tau));
|
||||
const tReal = progress * animDur;
|
||||
const I = Imax * (1 - Math.exp(-tReal / tau));
|
||||
|
||||
let g = '';
|
||||
g += '<rect x="0" y="0" width="'+W+'" height="'+H+'" fill="#fafafa"/>';
|
||||
g += '<text x="240" y="20" text-anchor="middle" font-family="Inter,sans-serif" font-size="13" font-weight="700" fill="#0f172a">RL-цепь: ток нарастает как $I(t) = I_{max}(1 - e^{-t/τ})$</text>';
|
||||
|
||||
// Schema slot (left): battery + switch + R + L (квадрат)
|
||||
// Координаты схемы
|
||||
const sx = 30, sy = 60, sw = 200, sh = 160;
|
||||
g += '<rect x="'+sx+'" y="'+sy+'" width="'+sw+'" height="'+sh+'" fill="white" stroke="#cbd5e1" stroke-width="1" rx="6"/>';
|
||||
// прямоугольный контур цепи
|
||||
const cx1 = sx+30, cx2 = sx+sw-20;
|
||||
const cy1 = sy+40, cy2 = sy+sh-30;
|
||||
// верх
|
||||
g += PHYS.wire(cx1, cy1, cx1+50, cy1); // от + батареи направо
|
||||
g += PHYS.wire(cx1+50+10, cy1, cx2, cy1); // через ключ к правому верх. углу (промежуток для ключа)
|
||||
// правый бок (L)
|
||||
g += PHYS.wire(cx2, cy1, cx2, cy1+30);
|
||||
// L symbol в правой стороне (горизонталь нарисуем посередине правой стороны)
|
||||
g += PHYS.inductorSymbol((cx2), (cy1+cy2)/2, undefined, 'h');
|
||||
// соединение L и правого бока
|
||||
g += PHYS.wire(cx2, (cy1+cy2)/2 + 12, cx2, cy2);
|
||||
// низ
|
||||
g += PHYS.wire(cx2, cy2, cx1+90, cy2);
|
||||
// R в нижней части
|
||||
g += PHYS.resistor(cx1+70, cy2);
|
||||
g += PHYS.wire(cx1+70-20, cy2, cx1, cy2);
|
||||
// левый бок (батарея)
|
||||
g += PHYS.wire(cx1, cy2, cx1, cy1+30);
|
||||
g += PHYS.batteryEMF(cx1, (cy1+cy2)/2, undefined, 'v');
|
||||
g += PHYS.wire(cx1, (cy1+cy2)/2 - 12, cx1, cy1);
|
||||
|
||||
// Ключ (наклонная линия): закрыт если running или progress>0
|
||||
const swX1 = cx1+50, swX2 = cx1+50+10;
|
||||
if(running || progress > 0){
|
||||
g += '<line x1="'+swX1+'" y1="'+cy1+'" x2="'+swX2+'" y2="'+cy1+'" stroke="#10b981" stroke-width="2"/>';
|
||||
} else {
|
||||
g += '<line x1="'+swX1+'" y1="'+cy1+'" x2="'+(swX2-2)+'" y2="'+(cy1-12)+'" stroke="#dc2626" stroke-width="2"/>';
|
||||
}
|
||||
g += '<circle cx="'+swX1+'" cy="'+cy1+'" r="2.5" fill="#0f172a"/>';
|
||||
g += '<circle cx="'+swX2+'" cy="'+cy1+'" r="2.5" fill="#0f172a"/>';
|
||||
|
||||
// Подписи параметров
|
||||
g += '<text x="'+(cx1-2)+'" y="'+(sy+sh-6)+'" font-family="JetBrains Mono,monospace" font-size="11" fill="#0f172a">ε='+E.toFixed(1)+' В</text>';
|
||||
g += '<text x="'+(cx1+70)+'" y="'+(cy2+18)+'" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="11" fill="#0f172a">R='+R+' Ом</text>';
|
||||
g += '<text x="'+(cx2+10)+'" y="'+((cy1+cy2)/2 + 4)+'" font-family="JetBrains Mono,monospace" font-size="11" fill="#0f172a">L='+(+LI.value)+' мГн</text>';
|
||||
|
||||
// График справа
|
||||
const gx = 260, gy = 50, gw = 200, gh = 170;
|
||||
g += '<rect x="'+gx+'" y="'+gy+'" width="'+gw+'" height="'+gh+'" fill="white" stroke="#cbd5e1" stroke-width="1" rx="6"/>';
|
||||
// оси
|
||||
g += '<line x1="'+(gx+30)+'" y1="'+(gy+gh-25)+'" x2="'+(gx+gw-10)+'" y2="'+(gy+gh-25)+'" stroke="#0f172a" stroke-width="1.4"/>';
|
||||
g += '<line x1="'+(gx+30)+'" y1="'+(gy+15)+'" x2="'+(gx+30)+'" y2="'+(gy+gh-25)+'" stroke="#0f172a" stroke-width="1.4"/>';
|
||||
g += '<text x="'+(gx+gw-12)+'" y="'+(gy+gh-10)+'" text-anchor="end" font-family="JetBrains Mono,monospace" font-size="10" fill="#0f172a">t</text>';
|
||||
g += '<text x="'+(gx+28)+'" y="'+(gy+14)+'" text-anchor="end" font-family="JetBrains Mono,monospace" font-size="10" fill="#0f172a">I</text>';
|
||||
// линия Imax (пунктир)
|
||||
const imaxY = gy + 22;
|
||||
g += '<line x1="'+(gx+30)+'" y1="'+imaxY+'" x2="'+(gx+gw-10)+'" y2="'+imaxY+'" stroke="#dc2626" stroke-width="1" stroke-dasharray="4 3"/>';
|
||||
g += '<text x="'+(gx+gw-14)+'" y="'+(imaxY-3)+'" text-anchor="end" font-family="JetBrains Mono,monospace" font-size="10" fill="#dc2626">I_max</text>';
|
||||
// линия 0.63 Imax — для подписи τ
|
||||
const tauY = gy + 22 + 0.37 * ((gy+gh-25) - imaxY);
|
||||
g += '<line x1="'+(gx+30)+'" y1="'+tauY+'" x2="'+(gx+gw-10)+'" y2="'+tauY+'" stroke="#0891b2" stroke-width="0.8" stroke-dasharray="2 3"/>';
|
||||
g += '<text x="'+(gx+34)+'" y="'+(tauY-3)+'" font-family="JetBrains Mono,monospace" font-size="9" fill="#0891b2">0.63 I_max</text>';
|
||||
// кривая до текущего progress (или полная при progress=1)
|
||||
const steps = 60;
|
||||
let path = '';
|
||||
const tFinal = progress * 5*tau / Math.max(1e-9, animDur); // нормированно к τ
|
||||
const sMax = Math.min(5, 5 * progress * (animDur / (5*tau))); // безразмерное по τ
|
||||
for(let k=0; k<=steps; k++){
|
||||
const s = (k/steps) * sMax; // s = t/τ
|
||||
const iv = 1 - Math.exp(-s);
|
||||
const px = (gx+30) + (s/5) * ((gx+gw-10) - (gx+30));
|
||||
const py = imaxY + (1 - iv) * ((gy+gh-25) - imaxY);
|
||||
path += (k===0?'M ':'L ') + px.toFixed(1) + ' ' + py.toFixed(1) + ' ';
|
||||
}
|
||||
if(progress > 0) g += '<path d="'+path+'" fill="none" stroke="#7c3aed" stroke-width="2.2"/>';
|
||||
|
||||
// подпись τ — отметка x = τ на оси (s=1 в нормировке)
|
||||
const tauX = (gx+30) + (1/5) * ((gx+gw-10) - (gx+30));
|
||||
g += '<line x1="'+tauX+'" y1="'+(gy+gh-25)+'" x2="'+tauX+'" y2="'+(gy+gh-22)+'" stroke="#0f172a" stroke-width="1.2"/>';
|
||||
g += '<text x="'+tauX+'" y="'+(gy+gh-12)+'" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="10" fill="#0f172a">τ</text>';
|
||||
|
||||
svg.innerHTML = g;
|
||||
|
||||
const tauMs = tau * 1000;
|
||||
out.innerHTML = '$I_{max} = \\mathcal{E}/R = '+Imax.toFixed(3)+'$ А $\\tau = L/R = '+tauMs.toFixed(2)+'$ мс <b>Текущий ток</b>: $I = '+I.toFixed(3)+'$ А';
|
||||
renderMath(out);
|
||||
}
|
||||
|
||||
function step(now){
|
||||
if(!running){ return; }
|
||||
if(!animT0) animT0 = now;
|
||||
const E = +EI.value, R = +RI.value, L = (+LI.value)/1000;
|
||||
const tau = L/R;
|
||||
const animDur = Math.max(0.6, Math.min(3, 5*tau));
|
||||
const elapsed = (now - animT0) / 1000;
|
||||
const p = Math.min(1, elapsed / animDur);
|
||||
draw(p);
|
||||
if(p < 1){ rafId = requestAnimationFrame(step); }
|
||||
else {
|
||||
running = false;
|
||||
const key = (+EI.value).toFixed(1)+'|'+RI.value+'|'+LI.value;
|
||||
configs.add(key);
|
||||
if(!_done && configs.size >= 4){ _done = true; addXp(15, 'p33-iv1'); bumpProgress('p33', 20); }
|
||||
}
|
||||
}
|
||||
function start(){
|
||||
if(running) return;
|
||||
animT0 = null; running = true;
|
||||
rafId = requestAnimationFrame(step);
|
||||
}
|
||||
function reset(){
|
||||
running = false; if(rafId) cancelAnimationFrame(rafId);
|
||||
draw(0);
|
||||
}
|
||||
bGo.addEventListener('click', start);
|
||||
bRs.addEventListener('click', reset);
|
||||
[EI, RI, LI].forEach(el => el.addEventListener('input', ()=>{ reset(); }));
|
||||
draw(0);
|
||||
})();
|
||||
|
||||
/* IV2 — Калькулятор */
|
||||
(function(){
|
||||
const out = document.getElementById('p33-iv2-out');
|
||||
const bGo = document.getElementById('p33-iv2-calc');
|
||||
const iL = document.getElementById('p33-iv2-L');
|
||||
const iI = document.getElementById('p33-iv2-I');
|
||||
const iDI = document.getElementById('p33-iv2-dI');
|
||||
const iDT = document.getElementById('p33-iv2-dt');
|
||||
let count = 0, _done = false;
|
||||
|
||||
function calc(){
|
||||
const L = +iL.value, I = +iI.value, dI = +iDI.value, dt = +iDT.value;
|
||||
if(![L,I,dI,dt].every(isFinite) || L < 0 || dt <= 0){
|
||||
out.innerHTML = '<b style="color:#dc2626">Проверь ввод: $L \\ge 0$, $\\Delta t > 0$.</b>';
|
||||
renderMath(out);
|
||||
return;
|
||||
}
|
||||
const phi = L * I;
|
||||
const W = L * I * I / 2;
|
||||
const Esi = L * Math.abs(dI) / dt;
|
||||
let html = '';
|
||||
html += '$\\Phi = LI = '+L+'\\cdot '+I+' = $ <b>'+phi.toFixed(4)+' Вб</b><br>';
|
||||
html += '$W = \\dfrac{LI^2}{2} = \\dfrac{'+L+'\\cdot '+(I*I)+'}{2} = $ <b>'+W.toFixed(4)+' Дж</b><br>';
|
||||
html += '$|\\mathcal{E}_{si}| = L\\,\\dfrac{|\\Delta I|}{\\Delta t} = '+L+'\\cdot \\dfrac{'+Math.abs(dI)+'}{'+dt+'} = $ <b>'+Esi.toFixed(4)+' В</b>';
|
||||
out.innerHTML = html;
|
||||
renderMath(out);
|
||||
count++;
|
||||
if(!_done && count >= 3){ _done = true; addXp(10, 'p33-iv2'); bumpProgress('p33', 15); }
|
||||
}
|
||||
bGo.addEventListener('click', calc);
|
||||
[iL, iI, iDI, iDT].forEach(x => x.addEventListener('keydown', e => { if(e.key==='Enter') calc(); }));
|
||||
})();
|
||||
|
||||
/* IV3 — Что произойдёт с током? */
|
||||
(function(){
|
||||
const OPTS = ['Растёт постепенно', 'Падает постепенно', 'Не меняется / нет ЭДС'];
|
||||
const Q = [
|
||||
{ q:'Цепь с $L$ <b>замыкают</b> (был разомкнут). Что происходит с током?', ans:0, why:'Самоиндукция тормозит рост, но ток постепенно растёт от 0 до $I_{max} = \\mathcal{E}/R$.' },
|
||||
{ q:'Цепь с $L$ <b>размыкают</b>. Что происходит с током до размыкания (в катушке)?', ans:1, why:'Самоиндукция поддерживает ток, но он постепенно падает до 0 (может проскочить искра).' },
|
||||
{ q:'В катушке течёт <b>постоянный</b> ток $I = 5$ А ($\\Delta I = 0$). Чему равна $\\mathcal{E}_{si}$?', ans:2, why:'$\\mathcal{E}_{si} = -L\\,\\Delta I/\\Delta t = 0$ при $\\Delta I = 0$. ЭДС самоиндукции не возникает.' },
|
||||
{ q:'В цепи <b>нет</b> индуктивности ($L = 0$). Замкнули — что с током?', ans:2, why:'$\\tau = L/R = 0$. Ток мгновенно устанавливается на $I_{max} = \\mathcal{E}/R$. Постепенного изменения нет.' },
|
||||
{ q:'$L$ увеличили в 2 раза (при тех же $\\mathcal{E}$ и $R$). После замыкания цепи — как ведёт себя ток?', ans:0, why:'$\\tau = L/R$ удвоится → ток растёт <b>медленнее</b>, но всё равно растёт до того же $I_{max}$.' },
|
||||
{ q:'Катушку с током отключили от источника, но замкнули на резистор. Что с током в катушке сразу после?', ans:1, why:'Энергия $LI^2/2$ постепенно рассеивается в $R$ → ток экспоненциально падает: $I(t) = I_0 e^{-t/\\tau}$.' }
|
||||
];
|
||||
let i = 0, score = 0;
|
||||
const qEl = document.getElementById('p33-iv3-q');
|
||||
const oEl = document.getElementById('p33-iv3-opts');
|
||||
const fb = document.getElementById('p33-iv3-fb');
|
||||
const iEl = document.getElementById('p33-iv3-i');
|
||||
const sEl = document.getElementById('p33-iv3-s');
|
||||
|
||||
function show(){
|
||||
if(i >= Q.length){
|
||||
qEl.innerHTML = '<b>Готово!</b> Результат: ' + score + ' / ' + Q.length;
|
||||
oEl.innerHTML = '';
|
||||
if(score === Q.length){ addXp(15, 'p33-iv3'); bumpProgress('p33', 25); }
|
||||
else if(score >= 4){ addXp(8, 'p33-iv3'); bumpProgress('p33', 15); }
|
||||
return;
|
||||
}
|
||||
iEl.textContent = (i+1);
|
||||
sEl.textContent = score;
|
||||
qEl.innerHTML = Q[i].q;
|
||||
oEl.innerHTML = OPTS.map((t, k) => '<button class="btn primary" data-v="' + k + '">' + t + '</button>').join('');
|
||||
fb.style.display = 'none';
|
||||
renderMath(qEl);
|
||||
oEl.querySelectorAll('button').forEach(b => {
|
||||
b.addEventListener('click', () => {
|
||||
const v = +b.dataset.v;
|
||||
if(v === Q[i].ans){ score++; feedback(fb, true, '✓ Верно! ' + Q[i].why + ' Дальше ▶'); }
|
||||
else feedback(fb, false, '✗ Верно: ' + OPTS[Q[i].ans] + '. ' + Q[i].why + ' Дальше ▶');
|
||||
sEl.textContent = score;
|
||||
oEl.querySelectorAll('button').forEach(x => x.disabled = true);
|
||||
i++;
|
||||
setTimeout(show, 1900);
|
||||
});
|
||||
});
|
||||
}
|
||||
document.getElementById('p33-iv3-restart').addEventListener('click', () => { i = 0; score = 0; show(); });
|
||||
show();
|
||||
})();
|
||||
|
||||
/* IV4 — Тренажёр индуктивности */
|
||||
(function(){
|
||||
const Q = [
|
||||
{ q:'$L = 0{,}5$ Гн, $I = 4$ А. Найди энергию магнитного поля $W$ (в <b>Дж</b>).', ans:4, tol:0.25, why:'$W = LI^2/2 = 0{,}5\\cdot 16/2 = 4$ Дж.' },
|
||||
{ q:'$L = 100$ мГн, $I = 2$ А. Найди магнитный поток $\\Phi$ (в <b>мВб</b>).', ans:200, tol:10, why:'$\\Phi = LI = 0{,}1\\cdot 2 = 0{,}2$ Вб $= 200$ мВб.' },
|
||||
{ q:'$L = 1$ Гн, $\\Delta I = 5$ А за $\\Delta t = 0{,}1$ с. Найди $|\\mathcal{E}_{si}|$ (в <b>В</b>).', ans:50, tol:2.5, why:'$|\\mathcal{E}_{si}| = L\\,|\\Delta I|/\\Delta t = 1\\cdot 5/0{,}1 = 50$ В.' },
|
||||
{ q:'Постоянная времени RL-цепи: $L = 0{,}5$ Гн, $R = 10$ Ом. Найди $\\tau$ (в <b>мс</b>).', ans:50, tol:2.5, why:'$\\tau = L/R = 0{,}5/10 = 0{,}05$ с $= 50$ мс.' },
|
||||
{ q:'Во сколько раз изменится энергия магнитного поля $W = LI^2/2$, если ток $I$ <b>удвоить</b> (при том же $L$)?', ans:4, tol:0.2, why:'$W \\propto I^2$ → удвоение $I$ даёт рост $W$ в $2^2 = 4$ раза.' }
|
||||
];
|
||||
let i = 0, score = 0;
|
||||
const qEl = document.getElementById('p33-iv4-q');
|
||||
const fb = document.getElementById('p33-iv4-fb');
|
||||
const iEl = document.getElementById('p33-iv4-i');
|
||||
const sEl = document.getElementById('p33-iv4-s');
|
||||
const inp = document.getElementById('p33-iv4-inp');
|
||||
const bGo = document.getElementById('p33-iv4-go');
|
||||
|
||||
function show(){
|
||||
if(i >= Q.length){
|
||||
qEl.innerHTML = '<b>Готово!</b> Результат: ' + score + ' / ' + Q.length;
|
||||
inp.disabled = true; bGo.disabled = true;
|
||||
if(score === Q.length){ addXp(15, 'p33-iv4'); bumpProgress('p33', 25); }
|
||||
else if(score >= 3){ addXp(8, 'p33-iv4'); bumpProgress('p33', 15); }
|
||||
return;
|
||||
}
|
||||
iEl.textContent = (i+1);
|
||||
sEl.textContent = score;
|
||||
qEl.innerHTML = Q[i].q;
|
||||
fb.style.display = 'none';
|
||||
inp.value = ''; inp.disabled = false; bGo.disabled = false; inp.focus();
|
||||
renderMath(qEl);
|
||||
}
|
||||
function check(){
|
||||
if(inp.disabled) return;
|
||||
const v = parseFloat(inp.value.replace(',','.'));
|
||||
if(!isFinite(v)){ feedback(fb, false, 'Введи число.'); return; }
|
||||
const tol = Math.max(Q[i].tol, Math.abs(Q[i].ans)*0.05);
|
||||
const ok = Math.abs(v - Q[i].ans) <= tol;
|
||||
if(ok){ score++; feedback(fb, true, '✓ Верно! ' + Q[i].why + ' Дальше ▶'); }
|
||||
else feedback(fb, false, '✗ Верно: ' + Q[i].ans + '. ' + Q[i].why + ' Дальше ▶');
|
||||
sEl.textContent = score;
|
||||
inp.disabled = true; bGo.disabled = true;
|
||||
i++;
|
||||
setTimeout(show, 1900);
|
||||
}
|
||||
bGo.addEventListener('click', check);
|
||||
inp.addEventListener('keydown', e => { if(e.key==='Enter') check(); });
|
||||
document.getElementById('p33-iv4-restart').addEventListener('click', () => { i = 0; score = 0; inp.disabled=false; bGo.disabled=false; show(); });
|
||||
show();
|
||||
})();
|
||||
|
||||
wireReadBtn('p33');
|
||||
}
|
||||
|
||||
function build_final5(){
|
||||
const box = document.getElementById('final5-body');
|
||||
let html = '';
|
||||
html += makeCard('theory', "Финал главы 5", "★", `
|
||||
<p><b>Финал главы 5</b> — этот параграф в разработке (Phase 1+).</p>
|
||||
<p>Здесь появятся: теория, формулы, разобранные примеры и 3–4 интерактива в стиле «алгебры 11» — таблицы, симуляции, ползунки, drag-and-drop и автопроверяемые тренажёры.</p>
|
||||
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.92rem">
|
||||
<b>Phase 0:</b> создан скелет учебника. <b>Phase 5+:</b> наполнение этого § содержанием по учебнику «Физика 10» (Беларусь, 2019).
|
||||
</p>
|
||||
`);
|
||||
|
||||
/* Часть А — Шпаргалка главы (7 mini-карточек) */
|
||||
const SHEET = [
|
||||
{ t:'§ 27 · Поле тока', icon:'<svg viewBox="0 0 24 24" fill="none" stroke="#0891b2" stroke-width="2" style="width:18px;height:18px"><circle cx="12" cy="12" r="3"/><path d="M12 2v3"/><path d="M12 19v3"/><path d="M4 12h3"/><path d="M17 12h3"/></svg>', body:'Создаётся <b>движущимися зарядами</b>. Опыт Эрстеда: стрелка возле проводника отклоняется.' },
|
||||
{ t:'§ 28 · Индукция $\\vec{B}$', icon:'<svg viewBox="0 0 24 24" fill="none" stroke="#7c3aed" stroke-width="2" style="width:18px;height:18px"><path d="M4 12c4-6 12-6 16 0"/><polyline points="18 9 20 12 17 14"/></svg>', body:'$\\vec{B}$ — векторная характеристика поля (Тл). Правило буравчика. Линии замкнуты.' },
|
||||
{ t:'§ 29 · Сила Ампера', icon:'<svg viewBox="0 0 24 24" fill="none" stroke="#dc2626" stroke-width="2" style="width:18px;height:18px"><path d="M5 12h14"/><polyline points="13 6 19 12 13 18"/></svg>', body:'$F_A = BIL\\sin\\alpha$. Правило левой руки: 4 пальца — ток, ладонь — $\\vec{B}$, большой — $\\vec{F}$.' },
|
||||
{ t:'§ 30 · Лоренц', icon:'<svg viewBox="0 0 24 24" fill="none" stroke="#f59e0b" stroke-width="2" style="width:18px;height:18px"><circle cx="12" cy="12" r="8"/><path d="M12 4v8l5 3"/></svg>', body:'$F_L = qvB\\sin\\alpha$. Окружность: $R = mv/(qB)$. Работа $\\vec{F}_L$ = 0.' },
|
||||
{ t:'§ 31 · Поток $\\Phi$', icon:'<svg viewBox="0 0 24 24" fill="none" stroke="#10b981" stroke-width="2" style="width:18px;height:18px"><rect x="4" y="6" width="16" height="12" rx="1"/><path d="M8 10l8 4"/></svg>', body:'$\\Phi = BS\\cos\\alpha$ [Вб]. ЭМИ — ток в контуре возникает при <b>изменении</b> $\\Phi$.' },
|
||||
{ t:'§ 32 · Фарадей + Ленц', icon:'<svg viewBox="0 0 24 24" fill="none" stroke="#0ea5e9" stroke-width="2" style="width:18px;height:18px"><path d="M4 17l4-4 4 2 8-8"/><polyline points="14 7 20 7 20 13"/></svg>', body:'$\\mathcal{E}_i = -N\\,\\Delta\\Phi/\\Delta t$. Ток индукции <b>противодействует</b> изменению потока.' },
|
||||
{ t:'§ 33 · Самоиндукция', icon:'<svg viewBox="0 0 24 24" fill="none" stroke="#8b5cf6" stroke-width="2" style="width:18px;height:18px"><path d="M3 12c2-3 4-3 6 0s4 3 6 0 4-3 6 0"/></svg>', body:'$\\Phi = LI$, $L$ в Гн. $W = LI^2/2$. $\\mathcal{E}_{si} = -L\\,\\Delta I/\\Delta t$. $\\tau = L/R$.' },
|
||||
];
|
||||
|
||||
html += `<div class="card">
|
||||
<div class="card-header">
|
||||
<span class="card-icon theory">${ICONS.theory}</span>
|
||||
<span class="card-title">Шпаргалка главы 5 — Магнитное поле и ЭМИ</span>
|
||||
<span class="card-num">Итог</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>Ключевые формулы и идеи всех 7 параграфов главы — повтори перед битвой с боссами.</p>
|
||||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:12px;margin-top:10px">
|
||||
${SHEET.map(s => `<div style="padding:12px 14px;background:var(--sec-acc-soft);border-radius:11px;border-left:3px solid var(--pri)">
|
||||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px">
|
||||
${s.icon}
|
||||
<div style="font-family:'Unbounded',sans-serif;font-weight:700;color:var(--pri2);font-size:.88rem">${s.t}</div>
|
||||
</div>
|
||||
<div style="font-size:.92rem;line-height:1.55">${s.body}</div>
|
||||
</div>`).join('')}
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
/* Часть Б — 7 боссов intro */
|
||||
html += `<div class="card">
|
||||
<div class="card-header">
|
||||
<span class="card-icon rule">${ICONS.rule}</span>
|
||||
<span class="card-title">Боссы главы 5</span>
|
||||
<span class="card-num">7</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>7 интегрированных задач по §§27–33. За каждого побеждённого босса: <b>+10 XP, +14% к прогрессу</b>. Победишь всех — ачивка <b>«Мастер магнетизма»</b> и <b>+50 XP бонус</b>.</p>
|
||||
<p style="margin-top:6px;font-size:.92rem;color:var(--muted)">Константы: $e = 1{,}6\\cdot 10^{-19}$ Кл, $m_p = 1{,}67\\cdot 10^{-27}$ кг. Допуск $\\pm 5\\%$.</p>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
html += '<div id="ch5-bosses-container"></div>';
|
||||
|
||||
html += `<div style="margin-top:18px;padding:18px 20px;background:linear-gradient(135deg,var(--pri-soft),var(--sec-acc-soft));border-radius:14px;border:1.5px solid var(--pri);text-align:center" id="ch5-final-summary">
|
||||
<div style="font-family:'Unbounded',sans-serif;font-weight:800;color:var(--pri2);font-size:1.1rem;margin-bottom:6px">Прогресс по боссам</div>
|
||||
<div id="ch5-boss-overall" style="font-size:.95rem;color:var(--text);margin-bottom:10px">0 / 7 боссов побеждено</div>
|
||||
<div style="height:12px;background:var(--card);border-radius:8px;overflow:hidden;border:1px solid var(--border)">
|
||||
<div id="ch5-boss-overall-fill" style="height:100%;width:0%;background:linear-gradient(90deg,#0891b2,#22d3ee);transition:width .35s"></div>
|
||||
</div>
|
||||
<div id="ch5-final-reward" style="margin-top:14px;display:none;padding:14px;background:var(--card);border-radius:11px;border:2px solid #0891b2">
|
||||
<div style="font-family:'Unbounded',sans-serif;font-weight:800;color:#0e7490;font-size:1.05rem;margin-bottom:6px">Мастер магнетизма</div>
|
||||
<div style="font-size:.92rem;margin-bottom:10px">Глава 5 пройдена! Все 7 боссов повержены. +50 XP бонус.</div>
|
||||
<a class="btn primary" href="/textbook/physics-10-ch6" style="text-decoration:none">Дальше: Глава 6 <svg class="ic" viewBox="0 0 24 24"><polyline points="9 18 15 12 9 6"/></svg></a>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
html += secNav('p33', null);
|
||||
html += readButton('final5');
|
||||
|
||||
box.innerHTML = html;
|
||||
renderMath(box);
|
||||
wireReadBtn('final5');
|
||||
|
||||
/* Боссы главы 5 */
|
||||
const BOSSES = [
|
||||
{
|
||||
n:1, color:'#dc2626',
|
||||
title:'Страж Ампера',
|
||||
tag:'§ 29',
|
||||
q:'$B = 0{,}5$ Тл, $I = 3$ А, $L = 0{,}2$ м, $\\alpha = 90°$. Найди силу Ампера $F_A$ в <b>Н</b>.',
|
||||
ans:0.3, tol:0.02,
|
||||
hint:'$F_A = BIL\\sin\\alpha = 0{,}5\\cdot 3\\cdot 0{,}2\\cdot 1 = 0{,}3$ Н.'
|
||||
},
|
||||
{
|
||||
n:2, color:'#f59e0b',
|
||||
title:'Жнец Лоренца',
|
||||
tag:'§ 30',
|
||||
q:'Электрон ($e = 1{,}6\\cdot 10^{-19}$ Кл) движется со скоростью $v = 10^6$ м/с перпендикулярно $\\vec{B} = 0{,}5$ Тл. Найди $F_L$ в виде $a \\cdot 10^{-14}$ Н. Введи $a$.',
|
||||
ans:8, tol:0.4,
|
||||
hint:'$F_L = qvB = 1{,}6\\cdot 10^{-19}\\cdot 10^6\\cdot 0{,}5 = 8\\cdot 10^{-14}$ Н.'
|
||||
},
|
||||
{
|
||||
n:3, color:'#10b981',
|
||||
title:'Хранитель Потока',
|
||||
tag:'§ 31',
|
||||
q:'$B = 0{,}2$ Тл, $S = 0{,}1$ м², $\\alpha = 60°$ (между $\\vec{B}$ и нормалью). Найди $\\Phi$ в <b>мВб</b>.',
|
||||
ans:10, tol:0.6,
|
||||
hint:'$\\Phi = BS\\cos\\alpha = 0{,}2\\cdot 0{,}1\\cdot 0{,}5 = 0{,}01$ Вб $= 10$ мВб.'
|
||||
},
|
||||
{
|
||||
n:4, color:'#0ea5e9',
|
||||
title:'Дракон Фарадея',
|
||||
tag:'§ 32',
|
||||
q:'Катушка из $N = 100$ витков. Поток изменился на $\\Delta\\Phi = 0{,}5$ Вб за $\\Delta t = 0{,}05$ с. Найди $|\\mathcal{E}_i|$ в <b>В</b>.',
|
||||
ans:1000, tol:50,
|
||||
hint:'$|\\mathcal{E}_i| = N\\,|\\Delta\\Phi|/\\Delta t = 100\\cdot 0{,}5/0{,}05 = 1000$ В.'
|
||||
},
|
||||
{
|
||||
n:5, color:'#8b5cf6',
|
||||
title:'Капитан Индуктивности',
|
||||
tag:'§ 33',
|
||||
q:'$L = 2$ Гн, $I = 3$ А. Найди энергию магнитного поля $W$ в <b>Дж</b>.',
|
||||
ans:9, tol:0.5,
|
||||
hint:'$W = LI^2/2 = 2\\cdot 9/2 = 9$ Дж.'
|
||||
},
|
||||
{
|
||||
n:6, color:'#dc2626',
|
||||
title:'Циклотронный Левиафан',
|
||||
tag:'§ 30',
|
||||
q:'Протон ($m_p = 1{,}67\\cdot 10^{-27}$ кг, $q = 1{,}6\\cdot 10^{-19}$ Кл) влетает перпендикулярно в $\\vec{B} = 0{,}5$ Тл со $v = 2\\cdot 10^7$ м/с. Найди радиус окружности $R$ в <b>см</b> (округли).',
|
||||
ans:42, tol:3,
|
||||
hint:'$R = m v/(qB) = 1{,}67\\cdot 10^{-27}\\cdot 2\\cdot 10^7/(1{,}6\\cdot 10^{-19}\\cdot 0{,}5) \\approx 0{,}418$ м $\\approx 42$ см.'
|
||||
},
|
||||
{
|
||||
n:7, color:'#22d3ee',
|
||||
title:'Магистр Магнетизма',
|
||||
tag:'§ 33 (синтез)',
|
||||
q:'Катушка с $L = 0{,}4$ Гн, $R = 8$ Ом подключается к источнику. Через какое время ток достигнет $\\approx 63\\%$ от максимума (это $\\tau$)? Ответ в <b>мс</b>.',
|
||||
ans:50, tol:3,
|
||||
hint:'$\\tau = L/R = 0{,}4/8 = 0{,}05$ с $= 50$ мс.'
|
||||
},
|
||||
];
|
||||
|
||||
const cont = document.getElementById('ch5-bosses-container');
|
||||
const STATE_KEY = 'physics10_ch5_bosses';
|
||||
const BOSS_STATE = (function(){
|
||||
try{ const s = localStorage.getItem(STATE_KEY); if(s){ const p = JSON.parse(s); if(Array.isArray(p) && p.length === BOSSES.length) return p; } }catch(e){}
|
||||
return BOSSES.map(()=>({defeated:false}));
|
||||
})();
|
||||
function saveBosses(){ try{ localStorage.setItem(STATE_KEY, JSON.stringify(BOSS_STATE)); }catch(e){} }
|
||||
|
||||
cont.innerHTML = BOSSES.map((b)=>{
|
||||
return '<div class="boss-card" id="boss5-'+b.n+'-card" style="padding:16px;background:var(--card);border-radius:12px;border:2px solid '+b.color+';margin-bottom:14px">'
|
||||
+'<div style="display:flex;align-items:center;gap:10px;margin-bottom:10px;flex-wrap:wrap">'
|
||||
+'<svg viewBox="0 0 24 24" fill="none" stroke="'+b.color+'" stroke-width="2.2" style="width:28px;height:28px;flex-shrink:0"><polygon points="12,2 22,20 2,20"/></svg>'
|
||||
+'<div style="font-family:\'Unbounded\',sans-serif;font-weight:800;color:'+b.color+';font-size:1.05rem">Босс '+b.n+': '+b.title+'</div>'
|
||||
+'<div style="margin-left:auto;font-size:.78rem;color:var(--muted);padding:3px 8px;background:var(--sec-acc-soft);border-radius:6px">'+b.tag+'</div>'
|
||||
+'</div>'
|
||||
+'<div class="boss-q" id="boss5-'+b.n+'-q" style="padding:12px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:1rem;line-height:1.5;margin-bottom:10px">'+b.q+'</div>'
|
||||
+'<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap">'
|
||||
+'<span style="font-family:\'JetBrains Mono\',monospace;font-size:.92rem">ответ =</span>'
|
||||
+'<input type="number" id="boss5-'+b.n+'-ans" class="tinp" style="width:130px;text-align:center" step="0.01" placeholder="число">'
|
||||
+'<button class="btn primary" id="boss5-'+b.n+'-go" style="background:'+b.color+';border-color:'+b.color+'">Атаковать</button>'
|
||||
+'<button class="btn" id="boss5-'+b.n+'-hint">Подсказка</button>'
|
||||
+'</div>'
|
||||
+'<div class="feedback" id="boss5-'+b.n+'-fb"></div>'
|
||||
+'</div>';
|
||||
}).join('');
|
||||
renderMath(cont);
|
||||
|
||||
function refreshOverall(){
|
||||
const won = BOSS_STATE.filter(s => s.defeated).length;
|
||||
const txt = document.getElementById('ch5-boss-overall');
|
||||
const fill = document.getElementById('ch5-boss-overall-fill');
|
||||
if(txt) txt.textContent = won + ' / ' + BOSSES.length + ' боссов побеждено';
|
||||
if(fill) fill.style.width = (won * 100 / BOSSES.length) + '%';
|
||||
if(won >= BOSSES.length){
|
||||
const reward = document.getElementById('ch5-final-reward');
|
||||
if(reward && reward.style.display === 'none'){
|
||||
reward.style.display = 'block';
|
||||
if(!STATE.achievements.has('ch5_done')){
|
||||
achievement('ch5_done','Мастер магнетизма');
|
||||
addXp(50, 'ch5-bonus');
|
||||
bumpProgress('final5', 30);
|
||||
if(window.confetti){ try{ confetti(); }catch(e){} }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOSSES.forEach((b, idx)=>{
|
||||
const card = document.getElementById('boss5-'+b.n+'-card');
|
||||
const goBtn = document.getElementById('boss5-'+b.n+'-go');
|
||||
const hintBtn = document.getElementById('boss5-'+b.n+'-hint');
|
||||
const ansInp = document.getElementById('boss5-'+b.n+'-ans');
|
||||
if(BOSS_STATE[idx].defeated){
|
||||
card.style.background = 'linear-gradient(135deg,var(--sec-acc-soft),var(--pri-soft))';
|
||||
card.classList.add('glow');
|
||||
goBtn.disabled = true; goBtn.style.opacity = .55; goBtn.textContent = '✓ Повержен';
|
||||
ansInp.disabled = true;
|
||||
}
|
||||
goBtn.addEventListener('click', ()=>{
|
||||
if(BOSS_STATE[idx].defeated) return;
|
||||
const fb = document.getElementById('boss5-'+b.n+'-fb');
|
||||
const raw = ansInp.value.replace(',', '.');
|
||||
const val = parseFloat(raw);
|
||||
if(isNaN(val)){ feedback(fb, false, '✗ Введи число.'); return; }
|
||||
const tol = (typeof b.tol === 'number') ? b.tol : Math.max(0.05 * Math.abs(b.ans), 0.05);
|
||||
if(Math.abs(val - b.ans) < tol + 0.001){
|
||||
BOSS_STATE[idx].defeated = true; saveBosses();
|
||||
feedback(fb, true, '✓ Босс '+b.n+' повержен! +10 XP. '+b.hint);
|
||||
addXp(10, 'boss-ch5-'+b.n);
|
||||
bumpProgress('final5', 14);
|
||||
goBtn.disabled = true; goBtn.style.opacity = .55; goBtn.textContent = '✓ Повержен';
|
||||
ansInp.disabled = true;
|
||||
card.style.background = 'linear-gradient(135deg,var(--sec-acc-soft),var(--pri-soft))';
|
||||
card.classList.add('glow','pulse');
|
||||
setTimeout(()=>card.classList.remove('pulse'), 900);
|
||||
refreshOverall();
|
||||
} else {
|
||||
feedback(fb, false, '✗ Промах. Попробуй ещё. Подсказка доступна.');
|
||||
}
|
||||
});
|
||||
hintBtn.addEventListener('click', ()=>{
|
||||
const fb = document.getElementById('boss5-'+b.n+'-fb');
|
||||
fb.className = 'feedback ok';
|
||||
fb.innerHTML = '<b>Подсказка:</b> '+b.hint;
|
||||
fb.style.display = 'block';
|
||||
fb.style.background = 'var(--warn-bg)';
|
||||
fb.style.color = '#92400e';
|
||||
fb.style.borderLeftColor = 'var(--warn)';
|
||||
renderMath(fb);
|
||||
});
|
||||
ansInp.addEventListener('keydown', e=>{ if(e.key === 'Enter') goBtn.click(); });
|
||||
});
|
||||
|
||||
refreshOverall();
|
||||
}
|
||||
|
||||
/* ===== Search ===== */
|
||||
|
||||
Reference in New Issue
Block a user