feat(alg11 ch3 wave4 + final): §10 «Логарифмические неравенства» + Финал Главы 3
This commit is contained in:
@@ -1952,31 +1952,774 @@ function buildP9(){
|
||||
function buildP10(){
|
||||
const box = document.getElementById('p10-body');
|
||||
let html = '';
|
||||
html += makeCard('theory', 'В разработке', '10.0', `
|
||||
<p>Содержание параграфа <b>Логарифмические неравенства</b> будет добавлено в Phase 1+.</p>
|
||||
<p style="color:var(--muted);font-size:.9rem">Раздел Phase 0 — skeleton. Здесь появятся теория, примеры и интерактивы.</p>
|
||||
<p style="color:var(--muted);font-size:.9rem">Ключевая формула: $\log_a f > b$</p>
|
||||
`);
|
||||
html += secNavFor('p10');
|
||||
|
||||
/* === ТЕОРИЯ === */
|
||||
|
||||
html += makeCard('theory', 'Основное правило и ОДЗ', '10.1', `
|
||||
<p><b>Логарифмическим неравенством</b> называется неравенство, в котором переменная содержится <b>под знаком логарифма</b>. Простейший вид:</p>
|
||||
<p style="text-align:center;font-size:1.04rem">$\\log_a f(x) > \\log_a g(x)$ (или $<$, $\\ge$, $\\le$).</p>
|
||||
<p>Здесь $a > 0$, $a \\ne 1$. Подход к решению опирается на <b>монотонность</b> логарифмической функции (см. §8):</p>
|
||||
<p style="text-align:center;padding:10px;background:var(--sec-acc-soft);border-radius:9px;margin:10px 0">
|
||||
$\\log_a f(x) > \\log_a g(x) \\;\\Leftrightarrow\\; \\begin{cases} f(x) > g(x), & \\text{если } a > 1 \\\\\\\\ f(x) < g(x), & \\text{если } 0 < a < 1 \\end{cases}$
|
||||
</p>
|
||||
<p>Кроме того <b>всегда</b> требуем положительности выражений под логарифмами (ОДЗ):</p>
|
||||
<p style="text-align:center;padding:10px;background:var(--sec-acc-soft);border-radius:9px;margin:10px 0">
|
||||
$\\begin{cases} f(x) > 0 \\\\\\\\ g(x) > 0 \\end{cases}$
|
||||
</p>
|
||||
<p style="padding:10px 12px;background:#fef3c7;border-left:4px solid #f59e0b;border-radius:6px;margin:12px 0"><b>Запомни:</b></p>
|
||||
<ul style="margin:8px 0 8px 22px;line-height:1.75">
|
||||
<li>При $a > 1$ — функция возрастает, знак неравенства <b>сохраняется</b>.</li>
|
||||
<li>При $0 < a < 1$ — функция убывает, знак неравенства <b>меняется</b>.</li>
|
||||
<li>ОДЗ требует <b>положительности обоих</b> выражений под логарифмами.</li>
|
||||
</ul>
|
||||
<details class="spoiler"><summary>Почему знак меняется при $0 < a < 1$?</summary><div class="spoiler-body">
|
||||
<p>Функция $y = \\log_a x$ при $0 < a < 1$ строго убывает: чем больше $x$, тем меньше $y$.</p>
|
||||
<p>Поэтому неравенство $\\log_a f > \\log_a g$ означает $f < g$: чтобы $\\log$ был больше, аргумент должен быть меньше.</p>
|
||||
</div></details>`);
|
||||
|
||||
html += makeCard('rule', 'Алгоритм решения', '10.2', `
|
||||
<p><b>Шаги</b> для решения неравенства $\\log_a f(x) \\gtrless \\log_a g(x)$:</p>
|
||||
<ol style="margin:8px 0 8px 22px;line-height:1.75">
|
||||
<li>Записать <b>ОДЗ</b>: $f(x) > 0$ и $g(x) > 0$.</li>
|
||||
<li>Привести обе части к <b>одному основанию</b> (если нужно).</li>
|
||||
<li>Использовать правило монотонности: при $a > 1$ <b>сохранить</b> знак, при $0 < a < 1$ — <b>изменить</b>.</li>
|
||||
<li>Решить полученное алгебраическое неравенство.</li>
|
||||
<li><b>Пересечь</b> ответ с ОДЗ — это и есть финальное решение.</li>
|
||||
</ol>
|
||||
<hr style="margin:14px 0;border:none;border-top:1px solid var(--border)">
|
||||
<p><b>Пример 1.</b> $\\log_2 (x - 1) > 3$.</p>
|
||||
<p><b>ОДЗ:</b> $x - 1 > 0 \\Rightarrow x > 1$.</p>
|
||||
<p>Перепишем $3 = \\log_2 8$: $\\log_2 (x - 1) > \\log_2 8$. $\\;a = 2 > 1$ — знак сохраняется:</p>
|
||||
<p>$x - 1 > 8 \\Rightarrow x > 9$.</p>
|
||||
<p>Пересечение с ОДЗ ($x > 1$): <b>$x > 9$</b>.</p>
|
||||
<p><b>Ответ:</b> $x \\in (9; +\\infty)$.</p>
|
||||
<hr style="margin:14px 0;border:none;border-top:1px solid var(--border)">
|
||||
<p><b>Пример 2.</b> $\\log_{1/3} (x - 2) > -2$.</p>
|
||||
<p><b>ОДЗ:</b> $x - 2 > 0 \\Rightarrow x > 2$.</p>
|
||||
<p>Перепишем $-2 = \\log_{1/3} 9$ (т.к. $(1/3)^{-2} = 9$): $\\log_{1/3} (x - 2) > \\log_{1/3} 9$. $\\;a = 1/3 < 1$ — знак <b>меняется</b>:</p>
|
||||
<p>$x - 2 < 9 \\Rightarrow x < 11$.</p>
|
||||
<p>Пересечение с ОДЗ: $2 < x < 11$.</p>
|
||||
<p><b>Ответ:</b> $x \\in (2; 11)$.</p>`);
|
||||
|
||||
html += makeCard('example', 'Замена переменной и графический метод', '10.3', `
|
||||
<p><b>Метод замены.</b> При наличии в неравенстве $\\log_a x$ и $\\log_a^2 x$ выполняют подстановку $t = \\log_a x$ — и получают <b>квадратное</b> неравенство относительно $t$.</p>
|
||||
<p><b>Пример.</b> $\\log_2^2 x - 3 \\log_2 x + 2 \\le 0$.</p>
|
||||
<p>ОДЗ: $x > 0$. Замена $t = \\log_2 x$: $t^2 - 3t + 2 \\le 0$.</p>
|
||||
<p>Корни уравнения $t^2 - 3t + 2 = 0$: $t_1 = 1$, $t_2 = 2$. Парабола ветвями вверх $\\le 0$ между корнями: $t \\in [1; 2]$.</p>
|
||||
<p>Обратно: $1 \\le \\log_2 x \\le 2 \\Leftrightarrow 2^1 \\le x \\le 2^2 \\Leftrightarrow 2 \\le x \\le 4$.</p>
|
||||
<p><b>Ответ:</b> $x \\in [2; 4]$.</p>
|
||||
<hr style="margin:14px 0;border:none;border-top:1px solid var(--border)">
|
||||
<p><b>Графический метод.</b> Если неравенство нельзя свести к одному основанию или замене — используем графики. Строим $y = \\log_a f(x)$ и $y = \\log_a g(x)$ (или константу) на одной координатной плоскости и смотрим, где один график выше другого.</p>
|
||||
<p style="padding:10px 12px;background:var(--sec-acc-soft);border-radius:9px"><b>Когда применять?</b> Когда $f$ и $g$ имеют разную природу (например, степенная и логарифмическая). Метод не даёт точный ответ, но позволяет понять <b>число и расположение</b> решений.</p>
|
||||
<p><b>Пример.</b> $\\log_2 x < 3 - x$. Строим $y = \\log_2 x$ (растёт) и $y = 3 - x$ (убывает). Точка пересечения примерно при $x \\approx 2$. При $x < 2$ кривая логарифма ниже прямой — это и есть решение. Уточнение: проверяем $x = 2$: $\\log_2 2 = 1$, $3 - 2 = 1$. Значит ответ $x \\in (0; 2)$.</p>`);
|
||||
|
||||
/* === ИНТЕРАКТИВЫ === */
|
||||
|
||||
/* IV1 — пошаговый решатель неравенств с числовой прямой */
|
||||
html += `<div class="wg" id="p10-iv1">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Решатель логарифмических неравенств</div></div>
|
||||
<div class="wg-help">Выбери задачу ползунком и нажимай «Следующий шаг ▶». Особое внимание — ОДЗ и правилу монотонности. После шага «Ответ» появится визуализация на числовой прямой. Просмотри все 5 задач — получишь XP.</div>
|
||||
<div class="sliders">
|
||||
<label>Задача № <b id="p10-iv1-n">1</b> / 5<input type="range" id="p10-iv1-sn" min="1" max="5" step="1" value="1"></label>
|
||||
</div>
|
||||
<div id="p10-iv1-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.08rem;text-align:center;margin-bottom:10px"></div>
|
||||
<div id="p10-iv1-steps" style="display:flex;flex-direction:column;gap:8px;margin-bottom:10px"></div>
|
||||
<div id="p10-iv1-axis" style="display:flex;justify-content:center;margin-bottom:10px"></div>
|
||||
<div class="actions" style="justify-content:center">
|
||||
<button class="btn primary" id="p10-iv1-next">Следующий шаг ▶</button>
|
||||
<button class="btn" id="p10-iv1-all">Показать все шаги</button>
|
||||
<button class="btn" id="p10-iv1-reset">Скрыть шаги</button>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
/* IV2 — калькулятор log_a (kx + b) ⋚ c */
|
||||
html += `<div class="wg" id="p10-iv2">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Калькулятор $\\log_a (kx + b) \\gtrless c$</div></div>
|
||||
<div class="wg-help">Введи основание $a$, коэффициенты $k$, $b$, правую часть $c$ и выбери знак — калькулятор решит неравенство с учётом монотонности и ОДЗ, покажет числовую прямую.</div>
|
||||
<div style="display:flex;gap:10px;align-items:center;flex-wrap:wrap;justify-content:center;margin-bottom:8px">
|
||||
<span style="font-family:'JetBrains Mono',monospace">$a$ =</span>
|
||||
<input type="number" id="p10-iv2-a" class="tinp" style="width:70px;text-align:center" value="2" step="0.5">
|
||||
<span style="font-family:'JetBrains Mono',monospace">$k$ =</span>
|
||||
<input type="number" id="p10-iv2-k" class="tinp" style="width:70px;text-align:center" value="1" step="1">
|
||||
<span style="font-family:'JetBrains Mono',monospace">$b$ =</span>
|
||||
<input type="number" id="p10-iv2-b" class="tinp" style="width:70px;text-align:center" value="-1" step="1">
|
||||
<select id="p10-iv2-sign" class="tinp" style="width:70px;text-align:center">
|
||||
<option value="gt">></option>
|
||||
<option value="lt"><</option>
|
||||
<option value="ge">≥</option>
|
||||
<option value="le">≤</option>
|
||||
</select>
|
||||
<span style="font-family:'JetBrains Mono',monospace">$c$ =</span>
|
||||
<input type="number" id="p10-iv2-c" class="tinp" style="width:70px;text-align:center" value="3" step="1">
|
||||
<button class="btn primary" id="p10-iv2-go">Решить</button>
|
||||
</div>
|
||||
<div style="display:flex;gap:6px;flex-wrap:wrap;justify-content:center;margin-bottom:10px;font-size:.82rem">
|
||||
<span style="color:var(--muted)">Примеры:</span>
|
||||
<button class="btn" data-set="2,1,-1,gt,3" style="padding:4px 10px;font-size:.82rem">$\\log_2(x-1)>3$</button>
|
||||
<button class="btn" data-set="0.333,1,-2,gt,-2" style="padding:4px 10px;font-size:.82rem">$\\log_{1/3}(x-2)>-2$</button>
|
||||
<button class="btn" data-set="5,2,1,lt,1" style="padding:4px 10px;font-size:.82rem">$\\log_5(2x+1)<1$</button>
|
||||
<button class="btn" data-set="10,1,1,le,1" style="padding:4px 10px;font-size:.82rem">$\\lg(x+1) \\le 1$</button>
|
||||
</div>
|
||||
<div id="p10-iv2-out" style="padding:12px 14px;background:var(--card);border-radius:9px;font-size:.96rem;min-height:60px;line-height:1.8"></div>
|
||||
<div id="p10-iv2-axis" style="display:flex;justify-content:center;margin-top:10px"></div>
|
||||
<div class="feedback" id="p10-iv2-fb"></div>
|
||||
</div>`;
|
||||
|
||||
/* IV3 — знак сохраняется или меняется? */
|
||||
html += `<div class="wg" id="p10-iv3">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 3</span><div class="wg-title">Знак меняется или сохраняется?</div></div>
|
||||
<div class="wg-help">Дано логарифмическое неравенство. Определи: при переходе к выражениям под логарифмом знак <b>сохраняется</b> ($a > 1$) или <b>меняется</b> ($0 < a < 1$)? 8 заданий.</div>
|
||||
<div class="score-display"><span>Задача <b id="p10-iv3-i">1</b> / 8</span><span>Очки: <b id="p10-iv3-s">0</b> / 8</span></div>
|
||||
<div id="p10-iv3-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.08rem;margin-bottom:10px;text-align:center;min-height:54px"></div>
|
||||
<div id="p10-iv3-opts" style="display:grid;grid-template-columns:1fr 1fr;gap:10px;max-width:420px;margin:0 auto"></div>
|
||||
<div class="feedback" id="p10-iv3-fb"></div>
|
||||
<div class="actions" style="justify-content:center"><button class="btn" id="p10-iv3-restart">Начать заново</button></div>
|
||||
</div>`;
|
||||
|
||||
/* IV4 — тренажёр неравенств */
|
||||
html += `<div class="wg" id="p10-iv4">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 4</span><div class="wg-title">Тренажёр неравенств</div></div>
|
||||
<div class="wg-help">Реши неравенство и введи <b>число</b> — указанную границу интервала ответа. 6 задач.</div>
|
||||
<div class="score-display"><span>Задача <b id="p10-iv4-i">1</b> / 6</span><span>Очки: <b id="p10-iv4-s">0</b> / 6</span></div>
|
||||
<div id="p10-iv4-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.12rem;margin-bottom:10px;text-align:center;min-height:54px"></div>
|
||||
<div style="display:flex;gap:10px;align-items:center;flex-wrap:wrap;justify-content:center">
|
||||
<span style="font-family:'JetBrains Mono',monospace">ответ =</span>
|
||||
<input type="number" id="p10-iv4-ans" class="tinp" style="width:120px;text-align:center" step="0.01">
|
||||
<button class="btn primary" id="p10-iv4-go">Проверить</button>
|
||||
<button class="btn" id="p10-iv4-start">Заново</button>
|
||||
</div>
|
||||
<div class="feedback" id="p10-iv4-fb"></div>
|
||||
</div>`;
|
||||
|
||||
html += secNav('p9', 'final3');
|
||||
html += readButton('p10');
|
||||
|
||||
box.innerHTML = html;
|
||||
renderMath(box);
|
||||
|
||||
/* Хелпер: рисует числовую прямую с интервалом */
|
||||
function drawAxis(lo, hi, segs){
|
||||
// segs: [{a, b, closedA, closedB, color}]
|
||||
// a/b могут быть -Infinity / +Infinity
|
||||
const W = 480, H = 80;
|
||||
const padL = 40, padR = 40;
|
||||
const ax = padL, bx = W - padR;
|
||||
const y0 = 46;
|
||||
const range = hi - lo;
|
||||
function xpos(v){
|
||||
if(v === -Infinity) return ax;
|
||||
if(v === +Infinity) return bx;
|
||||
return ax + (v - lo) / range * (bx - ax);
|
||||
}
|
||||
let svg = '<svg viewBox="0 0 '+W+' '+H+'" width="100%" style="max-width:480px;background:var(--card);border-radius:8px;border:1px solid var(--border)">';
|
||||
// ось
|
||||
svg += '<line x1="'+ax+'" y1="'+y0+'" x2="'+bx+'" y2="'+y0+'" stroke="#475569" stroke-width="1.5"/>';
|
||||
// стрелки
|
||||
svg += '<polygon points="'+(bx)+','+y0+' '+(bx-8)+','+(y0-4)+' '+(bx-8)+','+(y0+4)+'" fill="#475569"/>';
|
||||
svg += '<polygon points="'+(ax)+','+y0+' '+(ax+8)+','+(y0-4)+' '+(ax+8)+','+(y0+4)+'" fill="#475569"/>';
|
||||
// деления
|
||||
const ticks = [];
|
||||
for(let v = Math.ceil(lo); v <= Math.floor(hi); v++) ticks.push(v);
|
||||
ticks.forEach(v => {
|
||||
const x = xpos(v);
|
||||
svg += '<line x1="'+x+'" y1="'+(y0-3)+'" x2="'+x+'" y2="'+(y0+3)+'" stroke="#475569" stroke-width="1"/>';
|
||||
svg += '<text x="'+x+'" y="'+(y0+18)+'" text-anchor="middle" font-size="11" fill="#475569" font-family="JetBrains Mono,monospace">'+v+'</text>';
|
||||
});
|
||||
// интервалы
|
||||
segs.forEach(s => {
|
||||
const x1 = xpos(s.a), x2 = xpos(s.b);
|
||||
const color = s.color || '#7c3aed';
|
||||
svg += '<line x1="'+x1+'" y1="'+y0+'" x2="'+x2+'" y2="'+y0+'" stroke="'+color+'" stroke-width="5" opacity="0.7"/>';
|
||||
// концы
|
||||
if(s.a !== -Infinity){
|
||||
if(s.closedA) svg += '<circle cx="'+x1+'" cy="'+y0+'" r="5" fill="'+color+'"/>';
|
||||
else svg += '<circle cx="'+x1+'" cy="'+y0+'" r="5" fill="var(--card)" stroke="'+color+'" stroke-width="2"/>';
|
||||
}
|
||||
if(s.b !== +Infinity){
|
||||
if(s.closedB) svg += '<circle cx="'+x2+'" cy="'+y0+'" r="5" fill="'+color+'"/>';
|
||||
else svg += '<circle cx="'+x2+'" cy="'+y0+'" r="5" fill="var(--card)" stroke="'+color+'" stroke-width="2"/>';
|
||||
}
|
||||
});
|
||||
svg += '</svg>';
|
||||
return svg;
|
||||
}
|
||||
|
||||
/* === IV1 — пошаговый решатель неравенств === */
|
||||
(function(){
|
||||
const TASKS = [
|
||||
{
|
||||
q: '$\\log_2 (x - 1) > 3$',
|
||||
steps: [
|
||||
'<b>ОДЗ:</b> $x - 1 > 0 \\Rightarrow x > 1$.',
|
||||
'Переписываем правую часть: $3 = \\log_2 2^3 = \\log_2 8$. Неравенство: $\\log_2 (x - 1) > \\log_2 8$.',
|
||||
'Учитываем монотонность: $a = 2 > 1$, знак <b>сохраняется</b>: $x - 1 > 8$.',
|
||||
'Решаем: $x > 9$.',
|
||||
'Пересечение с ОДЗ ($x > 1$): $x > 9$.',
|
||||
'<b>Ответ:</b> $x \\in (9; +\\infty)$.'
|
||||
],
|
||||
axis: { lo: 0, hi: 14, segs: [{a:9, b:+Infinity, closedA:false, color:'#7c3aed'}] }
|
||||
},
|
||||
{
|
||||
q: '$\\log_{1/3} (x - 2) > -2$',
|
||||
steps: [
|
||||
'<b>ОДЗ:</b> $x - 2 > 0 \\Rightarrow x > 2$.',
|
||||
'Переписываем: $-2 = \\log_{1/3} (1/3)^{-2} = \\log_{1/3} 9$. Неравенство: $\\log_{1/3} (x - 2) > \\log_{1/3} 9$.',
|
||||
'Учитываем монотонность: $a = 1/3 < 1$, знак <b>меняется</b>: $x - 2 < 9$.',
|
||||
'Решаем: $x < 11$.',
|
||||
'Пересечение с ОДЗ ($x > 2$): $2 < x < 11$.',
|
||||
'<b>Ответ:</b> $x \\in (2; 11)$.'
|
||||
],
|
||||
axis: { lo: 0, hi: 14, segs: [{a:2, b:11, closedA:false, closedB:false, color:'#7c3aed'}] }
|
||||
},
|
||||
{
|
||||
q: '$\\log_5 (2x + 1) < 1$',
|
||||
steps: [
|
||||
'<b>ОДЗ:</b> $2x + 1 > 0 \\Rightarrow x > -\\dfrac{1}{2}$.',
|
||||
'Переписываем: $1 = \\log_5 5$. Неравенство: $\\log_5 (2x + 1) < \\log_5 5$.',
|
||||
'Учитываем монотонность: $a = 5 > 1$, знак сохраняется: $2x + 1 < 5$.',
|
||||
'Решаем: $2x < 4 \\Rightarrow x < 2$.',
|
||||
'Пересечение с ОДЗ ($x > -1/2$): $-\\dfrac{1}{2} < x < 2$.',
|
||||
'<b>Ответ:</b> $x \\in \\left(-\\dfrac{1}{2};\\,2\\right)$.'
|
||||
],
|
||||
axis: { lo: -3, hi: 5, segs: [{a:-0.5, b:2, closedA:false, closedB:false, color:'#7c3aed'}] }
|
||||
},
|
||||
{
|
||||
q: '$\\log_2^2 x - 3 \\log_2 x + 2 \\le 0$',
|
||||
steps: [
|
||||
'<b>ОДЗ:</b> $x > 0$.',
|
||||
'Замена $t = \\log_2 x$: $t^2 - 3t + 2 \\le 0$.',
|
||||
'Корни уравнения: $t = 1, t = 2$. Парабола ветвями вверх $\\le 0$ <b>между</b> корнями: $1 \\le t \\le 2$.',
|
||||
'Обратно: $1 \\le \\log_2 x \\le 2 \\Leftrightarrow 2 \\le x \\le 4$.',
|
||||
'$[2; 4] \\subset (0; +\\infty)$ — ОДЗ выполняется.',
|
||||
'<b>Ответ:</b> $x \\in [2; 4]$.'
|
||||
],
|
||||
axis: { lo: 0, hi: 6, segs: [{a:2, b:4, closedA:true, closedB:true, color:'#7c3aed'}] }
|
||||
},
|
||||
{
|
||||
q: '$\\lg (x + 1) \\le 1$',
|
||||
steps: [
|
||||
'<b>ОДЗ:</b> $x + 1 > 0 \\Rightarrow x > -1$.',
|
||||
'Переписываем: $1 = \\lg 10$. Неравенство: $\\lg (x + 1) \\le \\lg 10$.',
|
||||
'Учитываем монотонность: $a = 10 > 1$, знак сохраняется: $x + 1 \\le 10$.',
|
||||
'Решаем: $x \\le 9$.',
|
||||
'Пересечение с ОДЗ ($x > -1$): $-1 < x \\le 9$.',
|
||||
'<b>Ответ:</b> $x \\in (-1; 9]$.'
|
||||
],
|
||||
axis: { lo: -3, hi: 12, segs: [{a:-1, b:9, closedA:false, closedB:true, color:'#7c3aed'}] }
|
||||
}
|
||||
];
|
||||
const sn = document.getElementById('p10-iv1-sn');
|
||||
const nL = document.getElementById('p10-iv1-n');
|
||||
const qEl = document.getElementById('p10-iv1-q');
|
||||
const stepsEl = document.getElementById('p10-iv1-steps');
|
||||
const axisEl = document.getElementById('p10-iv1-axis');
|
||||
const nextBtn = document.getElementById('p10-iv1-next');
|
||||
const allBtn = document.getElementById('p10-iv1-all');
|
||||
const resetBtn = document.getElementById('p10-iv1-reset');
|
||||
const seen = new Set();
|
||||
let _done = false;
|
||||
let cur = 0, shown = 0;
|
||||
|
||||
function render(){
|
||||
const t = TASKS[cur];
|
||||
nL.textContent = (cur + 1);
|
||||
qEl.innerHTML = t.q;
|
||||
stepsEl.innerHTML = t.steps.map((s, i) => {
|
||||
const visible = i < shown;
|
||||
const isLast = i === t.steps.length - 1 && visible;
|
||||
const bg = isLast ? '#dcfce7' : 'var(--card)';
|
||||
const brd = isLast ? '2px solid #16a34a' : '1px solid var(--border)';
|
||||
return '<div data-i="'+i+'" style="padding:10px 12px;background:'+bg+';border:'+brd+';border-radius:8px;font-size:.95rem;display:'+(visible?'block':'none')+'"><span style="color:var(--muted);font-weight:700;margin-right:6px">Шаг '+(i+1)+':</span>'+s+'</div>';
|
||||
}).join('');
|
||||
renderMath(qEl);
|
||||
renderMath(stepsEl);
|
||||
if(shown >= t.steps.length){
|
||||
axisEl.innerHTML = drawAxis(t.axis.lo, t.axis.hi, t.axis.segs);
|
||||
seen.add(cur);
|
||||
if(!_done && seen.size >= 5){ _done = true; addXp(10, 'p10-iv1'); bumpProgress('p10', 15); }
|
||||
} else {
|
||||
axisEl.innerHTML = '';
|
||||
}
|
||||
}
|
||||
function load(n){ cur = Math.max(0, Math.min(TASKS.length - 1, n)); shown = 1; render(); }
|
||||
sn.addEventListener('input', () => load((+sn.value) - 1));
|
||||
nextBtn.addEventListener('click', () => {
|
||||
if(shown < TASKS[cur].steps.length){ shown++; render(); }
|
||||
});
|
||||
allBtn.addEventListener('click', () => { shown = TASKS[cur].steps.length; render(); });
|
||||
resetBtn.addEventListener('click', () => { shown = 1; render(); });
|
||||
load(0);
|
||||
})();
|
||||
|
||||
/* === IV2 — калькулятор log_a (kx + b) ⋚ c === */
|
||||
(function(){
|
||||
const aI = document.getElementById('p10-iv2-a');
|
||||
const kI = document.getElementById('p10-iv2-k');
|
||||
const bI = document.getElementById('p10-iv2-b');
|
||||
const cI = document.getElementById('p10-iv2-c');
|
||||
const sSel = document.getElementById('p10-iv2-sign');
|
||||
const go = document.getElementById('p10-iv2-go');
|
||||
const out = document.getElementById('p10-iv2-out');
|
||||
const axisEl = document.getElementById('p10-iv2-axis');
|
||||
const fb = document.getElementById('p10-iv2-fb');
|
||||
const used = new Set();
|
||||
let _done = false;
|
||||
|
||||
document.querySelectorAll('#p10-iv2 [data-set]').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
const v = btn.dataset.set.split(',');
|
||||
aI.value = v[0]; kI.value = v[1]; bI.value = v[2]; sSel.value = v[3]; cI.value = v[4];
|
||||
calc();
|
||||
});
|
||||
});
|
||||
|
||||
function aLabel(a){
|
||||
if(Math.abs(a - 10) < 1e-9) return '\\lg';
|
||||
if(Math.abs(a - 1/3) < 1e-3) return '\\log_{1/3}';
|
||||
if(Math.abs(a - 0.5) < 1e-9) return '\\log_{1/2}';
|
||||
return '\\log_{' + (+a.toFixed(4)) + '}';
|
||||
}
|
||||
function fxLabel(k, b){
|
||||
let s = '';
|
||||
if(k === 1) s = 'x';
|
||||
else if(k === -1) s = '-x';
|
||||
else s = k + 'x';
|
||||
if(b > 0) s += ' + ' + b;
|
||||
else if(b < 0) s += ' - ' + (-b);
|
||||
return s;
|
||||
}
|
||||
function signStr(s){
|
||||
return {gt:'>', lt:'<', ge:'\\ge', le:'\\le'}[s];
|
||||
}
|
||||
function flipSign(s){
|
||||
return {gt:'lt', lt:'gt', ge:'le', le:'ge'}[s];
|
||||
}
|
||||
function isStrict(s){ return s === 'gt' || s === 'lt'; }
|
||||
|
||||
function calc(){
|
||||
const a = parseFloat(aI.value);
|
||||
const k = parseFloat(kI.value);
|
||||
const b = parseFloat(bI.value);
|
||||
const c = parseFloat(cI.value);
|
||||
const s = sSel.value;
|
||||
if(![a,k,b,c].every(isFinite)){ feedback(fb, false, '✗ Введи все четыре числа.'); return; }
|
||||
if(a <= 0 || Math.abs(a - 1) < 1e-9){ feedback(fb, false, '✗ Основание $a$ должно быть $> 0$ и $\\ne 1$.'); return; }
|
||||
if(k === 0){ feedback(fb, false, '✗ При $k = 0$ выражение под логарифмом не зависит от $x$.'); return; }
|
||||
|
||||
const fx = fxLabel(k, b);
|
||||
const eq = '$' + aLabel(a) + '(' + fx + ') ' + signStr(s) + ' ' + c + '$';
|
||||
let html = '<div style="font-size:1.04rem;margin-bottom:8px;text-align:center">Неравенство: '+eq+'</div>';
|
||||
|
||||
// ОДЗ: kx + b > 0
|
||||
const odzBound = -b / k;
|
||||
const odzDir = k > 0 ? 'gt' : 'lt';
|
||||
const odzStr = k > 0 ? '$x > ' + (+odzBound.toFixed(4)) + '$' : '$x < ' + (+odzBound.toFixed(4)) + '$';
|
||||
html += '<div style="margin-bottom:6px"><b>Шаг 1. ОДЗ:</b> $' + fx + ' > 0 \\Rightarrow$ ' + odzStr + '.</div>';
|
||||
|
||||
// Шаг 2: перевод правой части a^c
|
||||
const ac = Math.pow(a, c);
|
||||
html += '<div style="margin-bottom:6px"><b>Шаг 2.</b> Переписываем правую часть: $' + c + ' = ' + aLabel(a) + ' ' + a + '^{' + c + '} = ' + aLabel(a) + ' ' + (+ac.toFixed(4)) + '$.</div>';
|
||||
|
||||
// Шаг 3: монотонность
|
||||
let curSign = s;
|
||||
let monoText;
|
||||
if(a > 1){
|
||||
monoText = '$a = ' + a + ' > 1$ — знак <b>сохраняется</b>';
|
||||
} else {
|
||||
monoText = '$0 < a = ' + (+a.toFixed(4)) + ' < 1$ — знак <b>меняется</b>';
|
||||
curSign = flipSign(curSign);
|
||||
}
|
||||
html += '<div style="margin-bottom:6px"><b>Шаг 3.</b> Монотонность: ' + monoText + '. Переход: $' + fx + ' ' + signStr(curSign) + ' ' + (+ac.toFixed(4)) + '$.</div>';
|
||||
|
||||
// Шаг 4: решить относительно x
|
||||
// kx + b [sign] ac => kx [sign] ac - b => x [sign|flip if k<0] (ac - b)/k
|
||||
const rhs = (ac - b) / k;
|
||||
let finalSign = curSign;
|
||||
if(k < 0) finalSign = flipSign(finalSign);
|
||||
html += '<div style="margin-bottom:6px"><b>Шаг 4.</b> Решаем: $kx ' + signStr(curSign) + ' ' + (+ac.toFixed(4)) + ' - (' + b + ')';
|
||||
if(k < 0) html += '$, делим на $k = ' + k + ' < 0$ — знак меняется: $x ' + signStr(finalSign) + ' ' + (+rhs.toFixed(4)) + '$.</div>';
|
||||
else html += ' \\Rightarrow x ' + signStr(finalSign) + ' ' + (+rhs.toFixed(4)) + '$.</div>';
|
||||
|
||||
// Шаг 5: пересечь с ОДЗ
|
||||
// Решение исходного: x [finalSign] rhs. ОДЗ: x [odzDir] odzBound.
|
||||
// Найдём интервал пересечения
|
||||
function rangeFromIneq(dir, bound){
|
||||
// dir in {gt, lt, ge, le}
|
||||
if(dir === 'gt') return {lo: bound, hi: +Infinity, closedLo: false, closedHi: false};
|
||||
if(dir === 'ge') return {lo: bound, hi: +Infinity, closedLo: true, closedHi: false};
|
||||
if(dir === 'lt') return {lo: -Infinity, hi: bound, closedLo: false, closedHi: false};
|
||||
if(dir === 'le') return {lo: -Infinity, hi: bound, closedLo: false, closedHi: true};
|
||||
}
|
||||
const r1 = rangeFromIneq(finalSign, rhs);
|
||||
const r2 = rangeFromIneq(odzDir, odzBound);
|
||||
const lo = Math.max(r1.lo, r2.lo);
|
||||
const hi = Math.min(r1.hi, r2.hi);
|
||||
const closedLo = (lo === r1.lo ? r1.closedLo : false) && (lo === r2.lo ? r2.closedLo : false) || (lo === r1.lo && lo !== r2.lo && r1.closedLo) || (lo === r2.lo && lo !== r1.lo && r2.closedLo);
|
||||
// Простая логика: closedLo true только если lo пришёл из границы, которая closed; ОДЗ всегда строгое, так что closedLo возможен только если lo === rhs && finalSign in {ge, le}
|
||||
let cLo = false, cHi = false;
|
||||
if(lo === r1.lo) cLo = r1.closedLo;
|
||||
if(lo === r2.lo) cLo = cLo && r2.closedLo;
|
||||
if(hi === r1.hi) cHi = r1.closedHi;
|
||||
if(hi === r2.hi) cHi = cHi && r2.closedHi;
|
||||
// Однако если lo берётся только из одной стороны (другая = -Inf), то closed зависит только от той стороны.
|
||||
if(r1.lo === -Infinity) cLo = r2.closedLo;
|
||||
if(r2.lo === -Infinity) cLo = r1.closedLo;
|
||||
if(r1.hi === +Infinity) cHi = r2.closedHi;
|
||||
if(r2.hi === +Infinity) cHi = r1.closedHi;
|
||||
|
||||
if(lo >= hi && !(lo === hi && cLo && cHi)){
|
||||
html += '<div style="margin-bottom:4px;color:#b91c1c"><b>Шаг 5.</b> Пересечение пустое — решений нет.</div>';
|
||||
html += '<div style="font-weight:700;color:#b91c1c">Ответ: $x \\in \\varnothing$.</div>';
|
||||
axisEl.innerHTML = '';
|
||||
} else {
|
||||
// Сформируем строку интервала
|
||||
const lp = (lo === -Infinity) ? '(-\\infty' : ((cLo ? '[' : '(') + (+lo.toFixed(4)));
|
||||
const rp = (hi === +Infinity) ? '+\\infty)' : ((+hi.toFixed(4)) + (cHi ? ']' : ')'));
|
||||
html += '<div style="margin-bottom:4px;color:#15803d"><b>Шаг 5.</b> Пересечение исходного и ОДЗ: $' + lp + ';\\, ' + rp + '$.</div>';
|
||||
html += '<div style="font-weight:700;color:#15803d">Ответ: $x \\in ' + lp + ';\\, ' + rp + '$.</div>';
|
||||
|
||||
// Визуализация
|
||||
const lo2 = (lo === -Infinity) ? Math.floor(hi) - 5 : Math.floor(lo) - 2;
|
||||
const hi2 = (hi === +Infinity) ? Math.ceil(lo) + 5 : Math.ceil(hi) + 2;
|
||||
const segLo = (lo === -Infinity) ? -Infinity : lo;
|
||||
const segHi = (hi === +Infinity) ? +Infinity : hi;
|
||||
axisEl.innerHTML = drawAxis(lo2, hi2, [{a:segLo, b:segHi, closedA:cLo, closedB:cHi, color:'#7c3aed'}]);
|
||||
}
|
||||
|
||||
out.innerHTML = html;
|
||||
renderMath(out);
|
||||
feedback(fb, true, '✓ Решено.');
|
||||
used.add(aI.value+','+kI.value+','+bI.value+','+sSel.value+','+cI.value);
|
||||
if(!_done && used.size >= 4){ _done = true; addXp(10, 'p10-iv2'); bumpProgress('p10', 15); }
|
||||
}
|
||||
go.addEventListener('click', calc);
|
||||
[aI, kI, bI, cI].forEach(i => i.addEventListener('keydown', e => { if(e.key === 'Enter') calc(); }));
|
||||
sSel.addEventListener('change', calc);
|
||||
calc();
|
||||
})();
|
||||
|
||||
/* === IV3 — знак сохраняется или меняется? === */
|
||||
(function(){
|
||||
const OPTS = ['Сохраняется', 'Меняется'];
|
||||
const Q = [
|
||||
{ q: '$\\log_2 (x - 1) > \\log_2 5$', ans: 0, hint: 'Основание $a = 2 > 1$ — функция возрастает, знак сохраняется.' },
|
||||
{ q: '$\\log_{1/3} (x + 2) < \\log_{1/3} 7$', ans: 1, hint: 'Основание $a = 1/3 < 1$ — функция убывает, знак меняется.' },
|
||||
{ q: '$\\log_5 x > 2$', ans: 0, hint: 'Перепишем $2 = \\log_5 25$. $a = 5 > 1$ — знак сохраняется.' },
|
||||
{ q: '$\\log_{0{,}5} (x - 1) \\ge 3$', ans: 1, hint: 'Основание $a = 0{,}5 < 1$ — знак меняется.' },
|
||||
{ q: '$\\lg (2x) > 1$', ans: 0, hint: '$\\lg = \\log_{10}$, $a = 10 > 1$ — знак сохраняется.' },
|
||||
{ q: '$\\log_{1/2} x \\le 4$', ans: 1, hint: 'Основание $a = 1/2 < 1$ — знак меняется.' },
|
||||
{ q: '$\\log_3 (x + 4) > 0$', ans: 0, hint: 'Основание $a = 3 > 1$ — знак сохраняется. (А $0 = \\log_3 1$.)' },
|
||||
{ q: '$\\log_{0{,}1} x \\ge -1$', ans: 1, hint: 'Основание $a = 0{,}1 < 1$ — знак меняется.' },
|
||||
];
|
||||
let i = 0, score = 0;
|
||||
const qEl = document.getElementById('p10-iv3-q');
|
||||
const oEl = document.getElementById('p10-iv3-opts');
|
||||
const fb = document.getElementById('p10-iv3-fb');
|
||||
const iEl = document.getElementById('p10-iv3-i');
|
||||
const sEl = document.getElementById('p10-iv3-s');
|
||||
|
||||
function show(){
|
||||
if(i >= Q.length){
|
||||
qEl.innerHTML = '<b>Готово!</b> Результат: '+score+' / '+Q.length;
|
||||
oEl.innerHTML = '';
|
||||
if(score === Q.length){ addXp(15, 'p10-iv3'); bumpProgress('p10', 25); }
|
||||
else if(score >= 6){ addXp(8, 'p10-iv3'); bumpProgress('p10', 15); }
|
||||
return;
|
||||
}
|
||||
iEl.textContent = (i + 1);
|
||||
sEl.textContent = score;
|
||||
const item = Q[i];
|
||||
qEl.innerHTML = item.q;
|
||||
oEl.innerHTML = OPTS.map((o, k) => '<button class="btn primary" data-k="'+k+'">'+o+'</button>').join('');
|
||||
fb.style.display = 'none';
|
||||
renderMath(qEl);
|
||||
oEl.querySelectorAll('button').forEach(b => {
|
||||
b.addEventListener('click', () => {
|
||||
const k = +b.dataset.k;
|
||||
if(k === item.ans){ score++; feedback(fb, true, '✓ Верно! '+item.hint+' Дальше ▶'); }
|
||||
else feedback(fb, false, '✗ Неверно. Правильно: <b>'+OPTS[item.ans]+'</b>. '+item.hint+' Дальше ▶');
|
||||
sEl.textContent = score;
|
||||
oEl.querySelectorAll('button').forEach(x => x.disabled = true);
|
||||
i++;
|
||||
setTimeout(show, 1700);
|
||||
});
|
||||
});
|
||||
}
|
||||
document.getElementById('p10-iv3-restart').addEventListener('click', () => { i = 0; score = 0; show(); });
|
||||
show();
|
||||
})();
|
||||
|
||||
/* === IV4 — тренажёр неравенств === */
|
||||
(function(){
|
||||
const Q = [
|
||||
{ q: '$\\log_2 (x - 1) > 3$ — введи <b>нижнюю</b> границу интервала ответа', ans: 9, hint: 'ОДЗ $x > 1$. $x - 1 > 8 \\Rightarrow x > 9$. Ответ $(9; +\\infty)$, граница — $9$.' },
|
||||
{ q: '$\\log_{1/3} (x - 2) > -2$ — введи <b>верхнюю</b> границу интервала ответа', ans: 11, hint: 'ОДЗ $x > 2$. $-2 = \\log_{1/3} 9$, знак меняется: $x - 2 < 9 \\Rightarrow x < 11$. Ответ $(2; 11)$, верхняя граница — $11$.' },
|
||||
{ q: '$\\log_5 x < 2$ — введи <b>верхнюю</b> границу интервала ответа', ans: 25, hint: 'ОДЗ $x > 0$. $2 = \\log_5 25$, знак сохраняется: $x < 25$. Ответ $(0; 25)$, верхняя граница — $25$.' },
|
||||
{ q: '$\\log_{1/2} (x - 3) \\ge -2$ — введи <b>верхнюю</b> границу интервала ответа', ans: 7, hint: 'ОДЗ $x > 3$. $-2 = \\log_{1/2} 4$, знак меняется: $x - 3 \\le 4 \\Rightarrow x \\le 7$. Ответ $(3; 7]$, верхняя граница — $7$.' },
|
||||
{ q: '$\\lg x > 1$ — введи <b>нижнюю</b> границу интервала ответа', ans: 10, hint: 'ОДЗ $x > 0$. $1 = \\lg 10$, знак сохраняется: $x > 10$. Ответ $(10; +\\infty)$, граница — $10$.' },
|
||||
{ q: '$\\log_3 (x + 1) \\le 2$ — введи <b>верхнюю</b> границу интервала ответа', ans: 8, hint: 'ОДЗ $x > -1$. $2 = \\log_3 9$, знак сохраняется: $x + 1 \\le 9 \\Rightarrow x \\le 8$. Ответ $(-1; 8]$, верхняя граница — $8$.' },
|
||||
];
|
||||
let i = 0, score = 0;
|
||||
function show(){
|
||||
const qEl = document.getElementById('p10-iv4-q');
|
||||
const iEl = document.getElementById('p10-iv4-i');
|
||||
const sEl = document.getElementById('p10-iv4-s');
|
||||
const fb = document.getElementById('p10-iv4-fb');
|
||||
const ansI = document.getElementById('p10-iv4-ans');
|
||||
if(i >= Q.length){
|
||||
qEl.innerHTML = '<b>Готово!</b> Результат: '+score+' / '+Q.length;
|
||||
if(score === Q.length){ addXp(15, 'p10-iv4'); bumpProgress('p10', 25); }
|
||||
else if(score >= 4){ addXp(8, 'p10-iv4'); bumpProgress('p10', 15); }
|
||||
return;
|
||||
}
|
||||
iEl.textContent = (i + 1);
|
||||
sEl.textContent = score;
|
||||
qEl.innerHTML = Q[i].q;
|
||||
ansI.value = '';
|
||||
renderMath(qEl);
|
||||
fb.style.display = 'none';
|
||||
setTimeout(() => ansI.focus(), 30);
|
||||
}
|
||||
function go(){
|
||||
if(i >= Q.length) return;
|
||||
const fb = document.getElementById('p10-iv4-fb');
|
||||
const raw = document.getElementById('p10-iv4-ans').value.replace(',', '.');
|
||||
const ans = parseFloat(raw);
|
||||
if(isNaN(ans)){ feedback(fb, false, '✗ Введи число.'); return; }
|
||||
if(Math.abs(ans - Q[i].ans) < 0.05){
|
||||
score++;
|
||||
feedback(fb, true, '✓ Верно! '+Q[i].hint+' Дальше ▶');
|
||||
} else {
|
||||
feedback(fb, false, '✗ Неверно. Ответ: $'+Q[i].ans+'$. '+Q[i].hint+' Дальше ▶');
|
||||
}
|
||||
document.getElementById('p10-iv4-s').textContent = score;
|
||||
i++;
|
||||
setTimeout(show, 1700);
|
||||
}
|
||||
document.getElementById('p10-iv4-go').addEventListener('click', go);
|
||||
document.getElementById('p10-iv4-ans').addEventListener('keydown', e => { if(e.key === 'Enter') go(); });
|
||||
document.getElementById('p10-iv4-start').addEventListener('click', () => { i = 0; score = 0; show(); });
|
||||
show();
|
||||
})();
|
||||
|
||||
wireReadBtn('p10');
|
||||
}
|
||||
|
||||
function buildFinal3(){
|
||||
const box = document.getElementById('final3-body');
|
||||
let html = '';
|
||||
html += makeCard('theory', 'В разработке', '★.0', `
|
||||
<p>Содержание финала главы <b>Финал главы</b> будет добавлено в Phase 1+.</p>
|
||||
<p style="color:var(--muted);font-size:.9rem">Раздел Phase 0 — skeleton. Здесь появятся теория, примеры и интерактивы.</p>
|
||||
<p style="color:var(--muted);font-size:.9rem">Ключевая формула: Итоги · боссы главы 3</p>
|
||||
`);
|
||||
html += secNavFor('final3');
|
||||
html += readButton('final3');
|
||||
|
||||
/* Часть А — Шпаргалка главы 3 (4 mini-карточки) */
|
||||
html += `<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-icon theory">${ICONS.theory}</div>
|
||||
<div class="card-title">Шпаргалка главы 3</div>
|
||||
<div class="card-num">Итог</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>Ключевые формулы и идеи всех четырёх параграфов в одном месте — просмотри перед битвой с боссами.</p>
|
||||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px;margin-top:10px">
|
||||
<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">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="#7c3aed" stroke-width="2" style="width:18px;height:18px"><path d="M12 3v18"/><path d="M3 12h18"/><circle cx="12" cy="12" r="9"/></svg>
|
||||
<div style="font-family:'Unbounded',sans-serif;font-weight:700;color:var(--pri2);font-size:.92rem">§ 7 · Свойства логарифмов</div>
|
||||
</div>
|
||||
<div style="font-size:.95rem">$\\log_a (bc) = \\log_a b + \\log_a c$, $\\;\\log_a \\dfrac{b}{c} = \\log_a b - \\log_a c$, $\\;\\log_a b^n = n \\log_a b$, $\\;\\log_a b = \\dfrac{\\log_c b}{\\log_c a}$.</div>
|
||||
</div>
|
||||
<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">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="#6d28d9" stroke-width="2" style="width:18px;height:18px"><path d="M3 21c4-12 8-18 18-18"/><line x1="3" y1="21" x2="21" y2="21"/></svg>
|
||||
<div style="font-family:'Unbounded',sans-serif;font-weight:700;color:var(--pri2);font-size:.92rem">§ 8 · Логарифмическая функция</div>
|
||||
</div>
|
||||
<div style="font-size:.95rem">$y = \\log_a x$. $D = (0; +\\infty)$, $E = \\mathbb{R}$. При $a > 1$ — возрастает, при $0 < a < 1$ — убывает. Точка $(1; 0)$. Асимптота $x = 0$. Обратная к $y = a^x$.</div>
|
||||
</div>
|
||||
<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">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="#0891b2" stroke-width="2" style="width:18px;height:18px"><path d="M5 12h14"/><polyline points="12 5 19 12 12 19"/></svg>
|
||||
<div style="font-family:'Unbounded',sans-serif;font-weight:700;color:var(--pri2);font-size:.92rem">§ 9 · Логарифм. уравнения</div>
|
||||
</div>
|
||||
<div style="font-size:.95rem">$\\log_a f = \\log_a g \\Rightarrow f = g$ + ОДЗ ($f, g > 0$). Методы: потенциирование, замена, свойства, графический. <b>Проверять корни!</b></div>
|
||||
</div>
|
||||
<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">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="#f59e0b" stroke-width="2" style="width:18px;height:18px"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="18" x2="21" y2="18"/><polyline points="7 10 3 14 7 18"/></svg>
|
||||
<div style="font-family:'Unbounded',sans-serif;font-weight:700;color:var(--pri2);font-size:.92rem">§ 10 · Логарифм. неравенства</div>
|
||||
</div>
|
||||
<div style="font-size:.95rem">При $a > 1$ знак <b>сохраняется</b>, при $0 < a < 1$ — <b>меняется</b>. ВСЕГДА учитываем ОДЗ: всё под $\\log$ должно быть строго положительно.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
/* Часть Б — 5 боссов (intro) */
|
||||
html += `<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-icon rule">${ICONS.rule}</div>
|
||||
<div class="card-title">Боссы главы 3</div>
|
||||
<div class="card-num">5</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>5 интегрированных задач по всей главе. За каждого побеждённого босса: <b>+10 XP, +18% к прогрессу</b>. Победишь всех — ачивка <b>«Магистр логарифмической функции»</b> и <b>+50 XP бонус</b>.</p>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
html += '<div id="ch3-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="ch3-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="ch3-boss-overall" style="font-size:.95rem;color:var(--text);margin-bottom:10px">0 / 5 боссов побеждено</div>
|
||||
<div style="height:12px;background:var(--card);border-radius:8px;overflow:hidden;border:1px solid var(--border)">
|
||||
<div id="ch3-boss-overall-fill" style="height:100%;width:0%;background:linear-gradient(90deg,#7c3aed,#a78bfa);transition:width .35s"></div>
|
||||
</div>
|
||||
<div id="ch3-final-reward" style="margin-top:14px;display:none;padding:14px;background:var(--card);border-radius:11px;border:2px solid #7c3aed">
|
||||
<div style="font-family:'Unbounded',sans-serif;font-weight:800;color:#6d28d9;font-size:1.05rem;margin-bottom:6px">Магистр логарифмической функции</div>
|
||||
<div style="font-size:.92rem;margin-bottom:10px">Все 3 главы изучены. Готовы к финалу курса! +50 XP бонус.</div>
|
||||
<a class="btn primary" href="/textbook/algebra-11" style="text-decoration:none">К хабу Алгебры 11 <svg class="ic" viewBox="0 0 24 24"><polyline points="9 18 15 12 9 6"/></svg></a>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
html += secNav('p10', null);
|
||||
|
||||
box.innerHTML = html;
|
||||
renderMath(box);
|
||||
wireReadBtn('final3');
|
||||
|
||||
/* Боссы */
|
||||
const BOSSES = [
|
||||
{
|
||||
n:1, color:'#10b981',
|
||||
title:'Циклоп Свойств',
|
||||
tag:'§ 7',
|
||||
q:'Вычислите: $\\log_2 24 - \\log_2 3 - \\log_2 \\sqrt{16}$. Введите числовой ответ.',
|
||||
ans:1,
|
||||
hint:'$\\log_2 24 - \\log_2 3 = \\log_2 \\dfrac{24}{3} = \\log_2 8 = 3$. $\\;\\log_2 \\sqrt{16} = \\log_2 4 = 2$. Итог: $3 - 2 = 1$.'
|
||||
},
|
||||
{
|
||||
n:2, color:'#0891b2',
|
||||
title:'Минотавр Логарифмической',
|
||||
tag:'§ 8',
|
||||
q:'У функции $y = \\log_{1/3} x$ найдите $y(81)$.',
|
||||
ans:-4,
|
||||
hint:'$\\log_{1/3} 81 = \\log_{1/3} (1/3)^{-4} = -4$ (т.к. $(1/3)^{-4} = 3^4 = 81$).'
|
||||
},
|
||||
{
|
||||
n:3, color:'#7c3aed',
|
||||
title:'Гарпия Уравнений',
|
||||
tag:'§ 9',
|
||||
q:'Решите $\\log_3 (x^2 - 2x) = \\log_3 3$. Найдите <b>сумму корней</b>.',
|
||||
ans:2,
|
||||
hint:'Потенциируем: $x^2 - 2x = 3 \\Rightarrow (x-3)(x+1) = 0 \\Rightarrow x = 3, x = -1$. ОДЗ $x^2 - 2x > 0$: $x < 0$ или $x > 2$. Оба корня подходят. Сумма $= 3 + (-1) = 2$.'
|
||||
},
|
||||
{
|
||||
n:4, color:'#dc2626',
|
||||
title:'Дракон Неравенств',
|
||||
tag:'§ 10',
|
||||
q:'Решите $\\log_{1/2} (x - 3) \\ge -2$. Найдите <b>наибольшее целое</b> $x$ из решения.',
|
||||
ans:7,
|
||||
hint:'ОДЗ $x > 3$. $-2 = \\log_{1/2} 4$, $a < 1$ — знак меняется: $x - 3 \\le 4 \\Rightarrow x \\le 7$. Решение $(3; 7]$, наибольшее целое — $7$.'
|
||||
},
|
||||
{
|
||||
n:5, color:'#f59e0b',
|
||||
title:'Мастер Логарифмов',
|
||||
tag:'§ 7 + § 8 + § 9 + § 10',
|
||||
q:'Решите $\\log_2^2 x - \\log_2 x = 2$. Найдите <b>произведение корней</b>.',
|
||||
ans:2,
|
||||
hint:'Замена $t = \\log_2 x$: $t^2 - t - 2 = 0 \\Rightarrow t = 2$ или $t = -1$. $x_1 = 2^2 = 4$, $x_2 = 2^{-1} = 1/2$. Произведение: $4 \\cdot 1/2 = 2$.'
|
||||
},
|
||||
];
|
||||
|
||||
const cont = document.getElementById('ch3-bosses-container');
|
||||
const STATE_KEY = 'algebra11_ch3_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, idx)=>{
|
||||
return '<div class="boss-card" id="boss3-'+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="boss3-'+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="boss3-'+b.n+'-ans" class="tinp" style="width:120px;text-align:center" step="0.01" placeholder="число">'
|
||||
+'<button class="btn primary" id="boss3-'+b.n+'-go" style="background:'+b.color+';border-color:'+b.color+'">Атаковать</button>'
|
||||
+'<button class="btn" id="boss3-'+b.n+'-hint">Подсказка</button>'
|
||||
+'</div>'
|
||||
+'<div class="feedback" id="boss3-'+b.n+'-fb"></div>'
|
||||
+'</div>';
|
||||
}).join('');
|
||||
renderMath(cont);
|
||||
|
||||
function refreshOverall(){
|
||||
const won = BOSS_STATE.filter(s => s.defeated).length;
|
||||
const txt = document.getElementById('ch3-boss-overall');
|
||||
const fill = document.getElementById('ch3-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('ch3-final-reward');
|
||||
if(reward && reward.style.display === 'none'){
|
||||
reward.style.display = 'block';
|
||||
if(!STATE.achievements.has('ch3_done')){
|
||||
achievement('ch3_done','Магистр логарифмической функции');
|
||||
addXp(50, 'ch3-bonus');
|
||||
bumpProgress('final3', 30);
|
||||
if(window.confetti){ try{ confetti(); }catch(e){} }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOSSES.forEach((b, idx)=>{
|
||||
const card = document.getElementById('boss3-'+b.n+'-card');
|
||||
const goBtn = document.getElementById('boss3-'+b.n+'-go');
|
||||
const hintBtn = document.getElementById('boss3-'+b.n+'-hint');
|
||||
const ansInp = document.getElementById('boss3-'+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('boss3-'+b.n+'-fb');
|
||||
const raw = ansInp.value.replace(',', '.');
|
||||
const val = parseFloat(raw);
|
||||
if(isNaN(val)){ feedback(fb, false, '✗ Введи число.'); return; }
|
||||
if(Math.abs(val - b.ans) < 0.05){
|
||||
BOSS_STATE[idx].defeated = true; saveBosses();
|
||||
feedback(fb, true, '✓ Босс '+b.n+' повержен! +10 XP. '+b.hint);
|
||||
addXp(10, 'boss-ch3-'+b.n);
|
||||
bumpProgress('final3', 18);
|
||||
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('boss3-'+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