feat(p8 ch2-3): IV-5 расчётные задачи для всех MCQ-only параграфов

Завершение Physics 8 — IV-5 добавлен в оставшиеся 13 параграфов:

Ch2 (Электромагнитные явления, 11 параграфов):
- §12 Электризация: 5 (выравнивание зарядов, n=q/e)
- §13 Проводники/диэлектрики: 5 (плотность носителей, I=q/t)
- §14 Электростатическая индукция: 5 (заземление, угол отклонения)
- §16 Строение атома: 5 (q=ne, заряд ядра)
- §17 Электрическое поле: 5 (E=F/q, F=qE, A=qEd, плотность линий)
- §19 Источники тока: 5 (ЭДС = A/q, A = εIt)
- §21 Электрическая цепь: 5 (I = q/t, числ. электронов)
- §28 Постоянные магниты: 5 (полюса, северный/южный)
- §29 Магнитное поле тока: 5 (F = BIL, B ∝ I)
- §30 Опыт Эрстеда: 5 (правило буравчика, год открытия)
- §31 Электромагнит: 5 (B ∝ N, B ∝ I, сердечник)

Ch3 (Световые явления, 2 параграфа):
- §32 Источники света: 5 (c=3·10^8, время до Луны/Солнца)
- §39 Дисперсия/глаз: 5 (спектр, длины волн, D=1/F)

Итого: 65 новых задач с автопроверкой, подсказкой-решением (KaTeX),
+20 XP. Все Phys 8 параграфы теперь имеют числовой тренажёр.
This commit is contained in:
Maxim Dolgolyov
2026-05-30 09:36:22 +03:00
parent ce9f29fcd0
commit 15fbd73847
3 changed files with 879 additions and 2 deletions
+101 -1
View File
@@ -1,4 +1,86 @@
<!doctype html>
<!
function _initp39_iv5(){
const TASKS = [{"q":"Из скольких основных цветов состоит спектр белого света (радуга)?","ans":7,"tol":0.1,"why":"$7$ цветов: красный, оранжевый, жёлтый, зелёный, голубой, синий, фиолетовый."},{"q":"У какого цвета света наибольшая длина волны: ($1$ — красный, $2$ — синий, $3$ — фиолетовый, $4$ — зелёный)?","ans":1,"tol":0.1,"why":"Красный свет имеет наибольшую длину волны ($\\sim 700$ нм) среди видимого спектра."},{"q":"У какого цвета света наименьшая длина волны: ($1$ — красный, $2$ — жёлтый, $3$ — зелёный, $4$ — фиолетовый)?","ans":4,"tol":0.1,"why":"Фиолетовый свет имеет наименьшую длину волны ($\\sim 400$ нм)."},{"q":"Линза с фокусом $F = 25$ см. Оптическая сила $D = 1/F$ (дптр). Найдите $D$ при $F$ в метрах.","ans":4,"tol":0.1,"why":"$F = 0{,}25$ м, $D = 1/F = 1/0{,}25 = 4$ дптр."},{"q":"У близорукого человека очки $-2$ дптр. Найдите фокусное расстояние линзы $F$ в м.","ans":-0.5,"tol":0.02,"why":"$F = 1/D = 1/(-2) = -0{,}5$ м (рассеивающая линза)."}];
let i = 0, ok = 0, awarded = false;
function render(){
const t = TASKS[i]; const wrap = document.getElementById('p39-tasks5'); if(!wrap) return;
wrap.innerHTML =
'<div style="padding:10px 14px;background:rgba(15,23,42,.04);border-radius:9px;margin-bottom:10px;font-size:.95rem;line-height:1.55"><b>Задача '+(i+1)+'.</b> '+t.q+'</div>'
+'<div class="actions"><input type="number" step="0.001" class="tinp" id="p39-iv5-inp" placeholder="число" style="width:140px">'
+'<button class="btn primary" id="p39-iv5-go">Ответ</button>'
+'<button class="btn" id="p39-iv5-hint">Подсказка</button>'
+'<button class="btn" id="p39-iv5-next">Следующая</button></div>'
+'<details class="spoiler" id="p39-iv5-why-wrap" style="margin-top:8px;display:none"><summary>Решение</summary><div class="spoiler-body">'+t.why+'</div></details>'
+'<div class="feedback" id="p39-iv5-fb"></div>';
if (window.renderMathInElement) try { renderMathInElement(wrap, {delimiters:[{left:'$',right:'$',display:false}],throwOnError:false}); } catch(e){}
document.getElementById('p39-iv5-go').onclick = () => {
const v = parseFloat(document.getElementById('p39-iv5-inp').value.replace(',','.'));
const fb = document.getElementById('p39-iv5-fb');
const wh = document.getElementById('p39-iv5-why-wrap');
if (Math.abs(v - t.ans) <= t.tol) {
fb.className = 'feedback ok'; fb.innerHTML = 'Верно!'; ok++;
document.getElementById('p39-tasks5-ok').textContent = ok;
wh.style.display = 'block';
} else {
fb.className = 'feedback fail'; fb.innerHTML = 'Не совсем. Ожидался $' + t.ans + '$. Загляни в подсказку.';
if (window.renderMathInElement) try { renderMathInElement(fb, {delimiters:[{left:'$',right:'$',display:false}],throwOnError:false}); } catch(e){}
}
};
document.getElementById('p39-iv5-hint').onclick = () => {
const wh = document.getElementById('p39-iv5-why-wrap');
wh.style.display = wh.style.display === 'block' ? 'none' : 'block';
};
document.getElementById('p39-iv5-next').onclick = () => {
i = (i + 1) % TASKS.length;
document.getElementById('p39-tasks5-i').textContent = i + 1;
render();
if (ok === TASKS.length && !awarded) { awarded = true; if (typeof addXp === 'function') addXp(20, 'p39-iv5'); }
};
}
render();
}
function _initp32_iv5(){
const TASKS = [{"q":"Скорость света в вакууме $c = 3 \\cdot 10^{8}$ м/с. За какое время (мкс) свет пройдёт $L = 300$ км?","ans":1000,"tol":10,"why":"$t = L/c = 3 \\cdot 10^{5} / 3 \\cdot 10^{8} = 10^{-3}$ с $= 1000$ мкс."},{"q":"Свет от Солнца достигает Земли за $t = 500$ с. Какое расстояние (в км)? Ответ $\\times 10^{8}$.","ans":1.5,"tol":0.05,"why":"$L = ct = 3 \\cdot 10^{8} \\cdot 500 = 1{,}5 \\cdot 10^{11}$ м $= 1{,}5 \\cdot 10^{8}$ км."},{"q":"Сколько секунд лётит свет от Луны до Земли, если расстояние $L = 384\\,000$ км?","ans":1.28,"tol":0.05,"why":"$t = L/c = 3{,}84 \\cdot 10^{8} / 3 \\cdot 10^{8} = 1{,}28$ с."},{"q":"Свет звезды доходит до нас за $4$ года. Сколько $4$ световых лет в км? Ответ $\\times 10^{13}$.","ans":3.78,"tol":0.05,"why":"$1$ год $\\approx 3{,}15 \\cdot 10^{7}$ с. $L = c \\cdot 4 \\cdot 3{,}15 \\cdot 10^{7} = 3{,}78 \\cdot 10^{16}$ м $= 3{,}78 \\cdot 10^{13}$ км."},{"q":"Какой из источников света — точечный с практической точки зрения: ($1$ — Солнце на небе для нас, $2$ — лампа в комнате с метра, $3$ — звезда)?","ans":3,"tol":0.1,"why":"Звёзды настолько далеки, что их можно считать точечными источниками света. Солнце и лампа — нет."}];
let i = 0, ok = 0, awarded = false;
function render(){
const t = TASKS[i]; const wrap = document.getElementById('p32-tasks5'); if(!wrap) return;
wrap.innerHTML =
'<div style="padding:10px 14px;background:rgba(15,23,42,.04);border-radius:9px;margin-bottom:10px;font-size:.95rem;line-height:1.55"><b>Задача '+(i+1)+'.</b> '+t.q+'</div>'
+'<div class="actions"><input type="number" step="0.001" class="tinp" id="p32-iv5-inp" placeholder="число" style="width:140px">'
+'<button class="btn primary" id="p32-iv5-go">Ответ</button>'
+'<button class="btn" id="p32-iv5-hint">Подсказка</button>'
+'<button class="btn" id="p32-iv5-next">Следующая</button></div>'
+'<details class="spoiler" id="p32-iv5-why-wrap" style="margin-top:8px;display:none"><summary>Решение</summary><div class="spoiler-body">'+t.why+'</div></details>'
+'<div class="feedback" id="p32-iv5-fb"></div>';
if (window.renderMathInElement) try { renderMathInElement(wrap, {delimiters:[{left:'$',right:'$',display:false}],throwOnError:false}); } catch(e){}
document.getElementById('p32-iv5-go').onclick = () => {
const v = parseFloat(document.getElementById('p32-iv5-inp').value.replace(',','.'));
const fb = document.getElementById('p32-iv5-fb');
const wh = document.getElementById('p32-iv5-why-wrap');
if (Math.abs(v - t.ans) <= t.tol) {
fb.className = 'feedback ok'; fb.innerHTML = 'Верно!'; ok++;
document.getElementById('p32-tasks5-ok').textContent = ok;
wh.style.display = 'block';
} else {
fb.className = 'feedback fail'; fb.innerHTML = 'Не совсем. Ожидался $' + t.ans + '$. Загляни в подсказку.';
if (window.renderMathInElement) try { renderMathInElement(fb, {delimiters:[{left:'$',right:'$',display:false}],throwOnError:false}); } catch(e){}
}
};
document.getElementById('p32-iv5-hint').onclick = () => {
const wh = document.getElementById('p32-iv5-why-wrap');
wh.style.display = wh.style.display === 'block' ? 'none' : 'block';
};
document.getElementById('p32-iv5-next').onclick = () => {
i = (i + 1) % TASKS.length;
document.getElementById('p32-tasks5-i').textContent = i + 1;
render();
if (ok === TASKS.length && !awarded) { awarded = true; if (typeof addXp === 'function') addXp(20, 'p32-iv5'); }
};
}
render();
}
doctype html>
<html lang="ru">
<head>
<meta charset="UTF-8">
@@ -689,8 +771,17 @@ function build_p32(){
+'<div class="wg-help">4+ — +15 XP.</div>'
+'<div id="p32-mcq"></div>'
+'<div class="score-display" style="margin-top:10px"><span>Вопрос: <b id="p32-mcq-i">1</b>/6</span><span>Правильно: <b id="p32-mcq-ok">0</b></span></div></div>';
/* IV5 — Расчётные задачи (auto-injected) */
h += '<div class="wg">'
+'<div class="wg-header"><span class="wg-badge">IV-5</span><div class="wg-title">Тренажёр: 5 расчётных задач</div></div>'
+'<div class="wg-help">Введи числовой ответ (точка как разделитель). Решено все верно — +20 XP.</div>'
+'<div id="p32-tasks5"></div>'
+'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="p32-tasks5-i">1</b> / 5</span><span>Правильно: <b id="p32-tasks5-ok">0</b></span></div>'
+'</div>';
box.innerHTML = h + secNavFor('p32') + readButton('p32');
renderMath(box); wireReadBtn('p32');
_initp32_iv5();
_p32_quiz1(); _p32_quiz2(); _p32_dnd(); _p32_mcq();
}
function _p32_quiz1(){
@@ -1792,8 +1883,17 @@ function build_p39(){
h += '<div class="wg"><div class="wg-header"><span class="wg-badge">IV-4</span><div class="wg-title">Тренажёр: 6 MCQ</div></div>'
+'<div id="p39-mcq"></div>'
+'<div class="score-display" style="margin-top:10px"><span>Вопрос: <b id="p39-mcq-i">1</b>/6</span><span>Правильно: <b id="p39-mcq-ok">0</b></span></div></div>';
/* IV5 — Расчётные задачи (auto-injected) */
h += '<div class="wg">'
+'<div class="wg-header"><span class="wg-badge">IV-5</span><div class="wg-title">Тренажёр: 5 расчётных задач</div></div>'
+'<div class="wg-help">Введи числовой ответ (точка как разделитель). Решено все верно — +20 XP.</div>'
+'<div id="p39-tasks5"></div>'
+'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="p39-tasks5-i">1</b> / 5</span><span>Правильно: <b id="p39-tasks5-ok">0</b></span></div>'
+'</div>';
box.innerHTML = h + secNavFor('p39') + readButton('p39');
renderMath(box); wireReadBtn('p39');
_initp39_iv5();
_p39_eye(); _p39_quiz(); _p39_dnd(); _p39_mcq();
}
function _p39_eye(){