diff --git a/frontend/textbooks/physics_10_ch3.html b/frontend/textbooks/physics_10_ch3.html
index 35f0be0..ea24aa4 100644
--- a/frontend/textbooks/physics_10_ch3.html
+++ b/frontend/textbooks/physics_10_ch3.html
@@ -664,34 +664,701 @@ function wireReadBtn(paraId){
function build_p16(){
const box = document.getElementById('p16-body');
let html = '';
- html += makeCard('theory', "Электрический заряд", "§16", `
-
Электрический заряд — этот параграф в разработке (Phase 1+).
- Здесь появятся: теория, формулы, разобранные примеры и 3–4 интерактива в стиле «алгебры 11» — таблицы, симуляции, ползунки, drag-and-drop и автопроверяемые тренажёры.
-
- Phase 0: создан скелет учебника. Phase 3+: наполнение этого § содержанием по учебнику «Физика 10» (Беларусь, 2019).
-
+
+ /* THEORY 1 — Электрический заряд и виды */
+ html += makeCard('theory', "Электрический заряд и виды", "§16", `
+ Электрический заряд $q$ — физическая величина, характеризующая способность тел и частиц участвовать в электромагнитных взаимодействиях.
+ Бывает двух видов : положительный (+) и отрицательный (−).
+
+ Одноимённые заряды отталкиваются .
+ Разноимённые заряды притягиваются .
+
+ Элементарный заряд — наименьший существующий в природе модуль заряда:
+ $$e = 1{,}6 \\cdot 10^{-19} \\text{ Кл}$$
+
+ Электрон : заряд $-e$, масса $\\sim 9{,}1 \\cdot 10^{-31}$ кг.
+ Протон : заряд $+e$, масса $\\sim 1{,}67 \\cdot 10^{-27}$ кг (в 1836 раз больше электрона).
+ Нейтрон : заряд $0$.
+
+ Любой макроскопический заряд кратен элементарному : $q = ne$, где $n$ — целое число.
`);
+
+ /* THEORY 2 — Закон сохранения заряда */
+ html += makeCard('rule', "Закон сохранения заряда", "§16", `
+ Закон сохранения электрического заряда : в любой замкнутой (изолированной) системе алгебраическая сумма электрических зарядов сохраняется:
+ $$\\sum q_i = \\text{const}$$
+ Заряды могут перераспределяться между телами, но общий заряд не меняется.
+ Способы электризации (передачи заряда):
+
+ Трением : например, расчёска из пластика трением о волосы.
+ Прикосновением : заряженное тело передаёт часть заряда нейтральному.
+ Через индукцию : заряженное тело наводит противоположный заряд на близлежащее проводящее тело (без касания).
+
+ Пример: два одинаковых металлических шара. Один заряжен зарядом $q$, другой нейтрален. После соприкосновения заряд распределится поровну: на каждом по $q/2$.
+ `);
+
+ /* THEORY 3 — Единица заряда */
+ html += makeCard('example', "Единица заряда и примеры", "§16", `
+ Единица заряда в СИ — Кулон (Кл). Назван в честь Шарля Кулона.
+ $1$ Кл — заряд, эквивалентный $1/e \\approx 6{,}25 \\cdot 10^{18}$ элементарных зарядов.
+ Это очень большой заряд ! В реальных задачах часто используются:
+
+ мкКл (микроКулон) $= 10^{-6}$ Кл
+ нКл (наноКулон) $= 10^{-9}$ Кл
+ пКл (пикоКулон) $= 10^{-12}$ Кл
+
+ Примеры зарядов :
+
+ Заряд электрона: $-1{,}6 \\cdot 10^{-19}$ Кл.
+ Заряд натёртой стеклянной палочки: $\\sim 10^{-7}-10^{-9}$ Кл.
+ Заряд молнии: $\\sim 10-100$ Кл.
+ Заряд при касании дверной ручки в сухом помещении: пара нКл, но напряжение огромно!
+
+ Точечный заряд — модель: заряженное тело, размерами которого можно пренебречь по сравнению с расстояниями до других объектов.
+ `);
+
+ /* INTERACTIVE 1 — Симуляция передачи заряда */
+ html += `
+
+
Два одинаковых металлических шара. Задай заряды и нажми «Прикоснуть» — заряды распределятся поровну. Сумма $q_1 + q_2$ сохранится!
+
+ $q_1$: +5 нКл
+ $q_2$: -3 нКл
+
+
+
+
+
+ Прикоснуть шары
+ Сначала
+
+
+
+
`;
+
+ /* INTERACTIVE 2 — Калькулятор электронов */
+ html += `
+
+
Введи заряд $q$ — получи число электронов $|n| = |q|/e$ (избыток при $q<0$, недостаток при $q>0$).
+
+ $q =$
+
+ нКл
+ мкКл
+ пКл
+ Кл
+
+ Вычислить
+
+
+
+
`;
+
+ /* INTERACTIVE 3 — квикфайр «Притяжение или отталкивание?» */
+ html += `
+
+
6 ситуаций — выбери, что произойдёт между телами.
+
Задача 1 / 6 Очки: 0 / 6
+
+
+
+
Начать заново
+
`;
+
+ /* INTERACTIVE 4 — Тренажёр заряда */
+ html += `
+
+
5 задач. $e = 1{,}6 \\cdot 10^{-19}$ Кл. Допуск $\\pm 5\\%$.
+
Задача 1 / 5 Очки: 0 / 5
+
+
+ ответ =
+
+ Проверить
+ Заново
+
+
+
`;
+
html += secNav(null, 'p17');
html += readButton('p16');
+
box.innerHTML = html;
renderMath(box);
+
+ /* IV1 — Симуляция передачи заряда */
+ (function(){
+ const svg = document.getElementById('p16-iv1-svg');
+ const q1S = document.getElementById('p16-iv1-q1');
+ const q2S = document.getElementById('p16-iv1-q2');
+ const q1L = document.getElementById('p16-iv1-q1L');
+ const q2L = document.getElementById('p16-iv1-q2L');
+ const out = document.getElementById('p16-iv1-out');
+ const fb = document.getElementById('p16-iv1-fb');
+ let q1 = +q1S.value, q2 = +q2S.value;
+ const seen = new Set();
+ let _done = false;
+
+ function fmtQ(q){ return (q>=0?'+':'') + q; }
+ function render(){
+ const W=380, H=220;
+ // Координаты шаров
+ const cx1 = 110, cx2 = 270, cy = 120;
+ const r = 30;
+ let g = '';
+ // Подставка
+ g += ' ';
+ g += ' ';
+ g += ' ';
+ // Шары
+ g += PHYS.chargeMark(cx1, cy, q1 === 0 ? 1 : (q1 > 0 ? 1 : -1), r, '');
+ if(q1 === 0){
+ // overlay серый круг для нейтрального
+ g += ' ';
+ g += '0 ';
+ }
+ g += PHYS.chargeMark(cx2, cy, q2 === 0 ? 1 : (q2 > 0 ? 1 : -1), r, '');
+ if(q2 === 0){
+ g += ' ';
+ g += '0 ';
+ }
+ // Подписи
+ g += 'q₁ = ' + fmtQ(q1) + ' нКл ';
+ g += 'q₂ = ' + fmtQ(q2) + ' нКл ';
+ // Заголовок
+ g += 'Два металлических шара ';
+ svg.innerHTML = g;
+ const sum = q1 + q2;
+ out.innerHTML = 'Сумма зарядов: $q_1 + q_2 = ' + fmtQ(q1) + ' + (' + fmtQ(q2) + ') = ' + fmtQ(sum) + '$ нКл (сохраняется!)';
+ renderMath(out);
+ }
+ function sync(){
+ q1 = +q1S.value; q2 = +q2S.value;
+ q1L.textContent = fmtQ(q1); q2L.textContent = fmtQ(q2);
+ render();
+ }
+ q1S.addEventListener('input', sync);
+ q2S.addEventListener('input', sync);
+
+ document.getElementById('p16-iv1-touch').addEventListener('click', () => {
+ const sum = q1 + q2;
+ const avg = sum / 2;
+ q1 = avg; q2 = avg;
+ q1S.value = q1; q2S.value = q2;
+ q1L.textContent = fmtQ(q1); q2L.textContent = fmtQ(q2);
+ render();
+ feedback(fb, true, '✓ После касания: $q_1 = q_2 = (q_1 + q_2)/2 = ' + fmtQ(avg) + '$ нКл. Сумма сохранилась!');
+ const key = (+q1S.value) + ':' + (+q2S.value);
+ seen.add(key);
+ if(!_done && seen.size >= 4){ _done = true; addXp(10, 'p16-iv1'); bumpProgress('p16', 15); }
+ });
+ document.getElementById('p16-iv1-reset').addEventListener('click', () => {
+ q1 = 5; q2 = -3; q1S.value = 5; q2S.value = -3;
+ q1L.textContent = '+5'; q2L.textContent = '-3';
+ fb.style.display = 'none';
+ render();
+ });
+ sync();
+ })();
+
+ /* IV2 — Калькулятор электронов */
+ (function(){
+ const qI = document.getElementById('p16-iv2-q');
+ const uI = document.getElementById('p16-iv2-unit');
+ const out = document.getElementById('p16-iv2-out');
+ const fb = document.getElementById('p16-iv2-fb');
+ const seen = new Set();
+ let _done = false;
+ const e = PHYS.CONST.e;
+
+ function calc(){
+ const qv = parseFloat(qI.value);
+ if(!isFinite(qv)){ feedback(fb, false, '✗ Введи число.'); return; }
+ const unit = parseFloat(uI.value);
+ const qC = qv * unit;
+ const n = Math.abs(qC) / e;
+ const exp = Math.floor(Math.log10(n));
+ const coef = n / Math.pow(10, exp);
+ const sign = qC < 0 ? 'избыток ' : (qC > 0 ? 'недостаток ' : 'нет ');
+ const qExp = qC === 0 ? 0 : Math.floor(Math.log10(Math.abs(qC)));
+ const qCoef = qC === 0 ? 0 : qC / Math.pow(10, qExp);
+ out.innerHTML = 'Заряд в Кл: $q = ' + (qC === 0 ? '0' : (+qCoef.toFixed(3) + ' \\cdot 10^{' + qExp + '}')) + '$ Кл
'
+ + 'Число электронов: $|n| = \\dfrac{|q|}{e} = \\dfrac{' + Math.abs(qC).toExponential(2).replace('e','\\cdot 10^{') + '}}{1{,}6 \\cdot 10^{-19}} \\approx ' + (+coef.toFixed(2)) + ' \\cdot 10^{' + exp + '}$
'
+ + '' + sign + ' электронов (' + (qC < 0 ? 'заряд отрицательный' : (qC > 0 ? 'заряд положительный' : 'нейтрально')) + ').
';
+ renderMath(out);
+ feedback(fb, true, '✓ Вычислено.');
+ seen.add((+qv.toFixed(3)) + ':' + uI.value);
+ if(!_done && seen.size >= 4){ _done = true; addXp(10, 'p16-iv2'); bumpProgress('p16', 15); }
+ }
+ document.getElementById('p16-iv2-go').addEventListener('click', calc);
+ qI.addEventListener('keydown', e => { if(e.key === 'Enter') calc(); });
+ })();
+
+ /* IV3 — квикфайр Притяжение/Отталкивание */
+ (function(){
+ const Q = [
+ { q:'Два положительно заряженных шарика рядом. Что происходит?', a:'Притяжение', b:'Отталкивание', ans:1, why:'Одноимённые ($+$ и $+$) отталкиваются.' },
+ { q:'Положительный заряд и отрицательный заряд рядом.', a:'Притяжение', b:'Отталкивание', ans:0, why:'Разноимённые ($+$ и $-$) притягиваются.' },
+ { q:'Два отрицательно заряженных тела рядом.', a:'Притяжение', b:'Отталкивание', ans:1, why:'Одноимённые ($-$ и $-$) отталкиваются.' },
+ { q:'Заряженная стеклянная палочка подносится к нейтральному бумажному шарику (без касания).', a:'Притяжение (через индукцию)', b:'Отталкивание', ans:0, why:'На нейтральном шарике наводится противоположный заряд — индукция вызывает притяжение.' },
+ { q:'Электрон и протон.', a:'Притяжение', b:'Отталкивание', ans:0, why:'Электрон $-e$, протон $+e$ — разноимённые, притягиваются.' },
+ { q:'Два электрона.', a:'Притяжение', b:'Отталкивание', ans:1, why:'Оба отрицательны ($-e$, $-e$) — отталкиваются.' },
+ ];
+ let i = 0, score = 0;
+ const qEl = document.getElementById('p16-iv3-q');
+ const oEl = document.getElementById('p16-iv3-opts');
+ const fb = document.getElementById('p16-iv3-fb');
+ const iEl = document.getElementById('p16-iv3-i');
+ const sEl = document.getElementById('p16-iv3-s');
+
+ function show(){
+ if(i >= Q.length){
+ qEl.innerHTML = 'Готово! Результат: ' + score + ' / ' + Q.length;
+ oEl.innerHTML = '';
+ if(score === Q.length){ addXp(15, 'p16-iv3'); bumpProgress('p16', 25); }
+ else if(score >= 4){ addXp(8, 'p16-iv3'); bumpProgress('p16', 15); }
+ return;
+ }
+ iEl.textContent = (i+1);
+ sEl.textContent = score;
+ const item = Q[i];
+ qEl.innerHTML = item.q;
+ oEl.innerHTML = '' + item.a + ' ' + item.b + ' ';
+ fb.style.display = 'none';
+ renderMath(qEl); renderMath(oEl);
+ oEl.querySelectorAll('button').forEach(b => {
+ b.addEventListener('click', () => {
+ const v = +b.dataset.v;
+ if(v === item.ans){ score++; feedback(fb, true, '✓ Верно! ' + item.why + ' Дальше ▶'); }
+ else feedback(fb, false, '✗ Неверно. ' + item.why + ' Дальше ▶');
+ sEl.textContent = score;
+ oEl.querySelectorAll('button').forEach(x => x.disabled = true);
+ i++;
+ setTimeout(show, 1600);
+ });
+ });
+ }
+ document.getElementById('p16-iv3-restart').addEventListener('click', () => { i = 0; score = 0; show(); });
+ show();
+ })();
+
+ /* IV4 — Тренажёр заряда */
+ (function(){
+ const Q = [
+ { q:'Сколько электронов нужно для заряда $-1$ нКл? Введи мантиссу при $10^9$.', ans:6.25, tol:0.3, hint:'$n = 10^{-9}/(1{,}6\\cdot 10^{-19}) = 6{,}25 \\cdot 10^9$.' },
+ { q:'Два одинаковых шара с зарядами $+4$ нКл и $-6$ нКл соприкоснулись. Заряд каждого после (в нКл)?', ans:-1, tol:0.1, hint:'$(q_1+q_2)/2 = (4-6)/2 = -1$ нКл.' },
+ { q:'Заряд $q = +3{,}2 \\cdot 10^{-19}$ Кл соответствует скольким элементарным?', ans:2, tol:0.1, hint:'$n = 3{,}2/1{,}6 = 2$.' },
+ { q:'Заряженный шар отдал половину своего заряда. Если был $+10$ нКл, сколько осталось (в нКл)?', ans:5, tol:0.2, hint:'$10/2 = 5$ нКл.' },
+ { q:'Заряд молнии $\\approx 30$ Кл. Сколько это электронов? Введи мантиссу при $10^{20}$.', ans:1.9, tol:0.3, hint:'$n = 30/(1{,}6 \\cdot 10^{-19}) \\approx 1{,}9 \\cdot 10^{20}$.' },
+ ];
+ let i = 0, score = 0;
+ function show(){
+ if(i >= Q.length){
+ document.getElementById('p16-iv4-q').innerHTML = 'Готово! Результат: ' + score + ' / ' + Q.length;
+ if(score === Q.length){ addXp(15, 'p16-iv4'); bumpProgress('p16', 25); }
+ else if(score >= 3){ addXp(8, 'p16-iv4'); bumpProgress('p16', 15); }
+ return;
+ }
+ document.getElementById('p16-iv4-i').textContent = (i+1);
+ document.getElementById('p16-iv4-s').textContent = score;
+ document.getElementById('p16-iv4-q').innerHTML = Q[i].q;
+ document.getElementById('p16-iv4-ans').value = '';
+ renderMath(document.getElementById('p16-iv4-q'));
+ document.getElementById('p16-iv4-fb').style.display = 'none';
+ }
+ function go(){
+ if(i >= Q.length) return;
+ const fb = document.getElementById('p16-iv4-fb');
+ const raw = document.getElementById('p16-iv4-ans').value.replace(',', '.');
+ const ans = parseFloat(raw);
+ if(isNaN(ans)){ feedback(fb, false, '✗ Введи число.'); return; }
+ if(Math.abs(ans - Q[i].ans) <= Q[i].tol + 0.001){ score++; feedback(fb, true, '✓ Верно! '+Q[i].hint+' Дальше ▶'); }
+ else feedback(fb, false, '✗ Неверно. Ответ: $'+Q[i].ans+'$. '+Q[i].hint+' Дальше ▶');
+ document.getElementById('p16-iv4-s').textContent = score;
+ i++;
+ setTimeout(show, 1800);
+ }
+ document.getElementById('p16-iv4-go').addEventListener('click', go);
+ document.getElementById('p16-iv4-ans').addEventListener('keydown', e => { if(e.key === 'Enter') go(); });
+ document.getElementById('p16-iv4-start').addEventListener('click', () => { i = 0; score = 0; show(); });
+ show();
+ })();
+
wireReadBtn('p16');
}
function build_p17(){
const box = document.getElementById('p17-body');
let html = '';
+
+ /* THEORY 1 — Закон Кулона */
html += makeCard('theory', "Закон Кулона", "§17", `
- Закон Кулона — этот параграф в разработке (Phase 1+).
- Здесь появятся: теория, формулы, разобранные примеры и 3–4 интерактива в стиле «алгебры 11» — таблицы, симуляции, ползунки, drag-and-drop и автопроверяемые тренажёры.
-
- Phase 0: создан скелет учебника. Phase 3+: наполнение этого § содержанием по учебнику «Физика 10» (Беларусь, 2019).
-
+ Закон Кулона : сила взаимодействия двух точечных зарядов прямо пропорциональна произведению модулей зарядов и обратно пропорциональна квадрату расстояния между ними:
+ $$F = k\\,\\dfrac{|q_1 q_2|}{r^2}$$
+ где:
+
+ $F$ — сила (Н);
+ $q_1, q_2$ — заряды (Кл);
+ $r$ — расстояние между зарядами (м);
+ $k = 9 \\cdot 10^9$ Н$\\cdot$м$^2$/Кл$^2$ — коэффициент пропорциональности.
+
+ Альтернативная форма:
+ $$F = \\dfrac{1}{4\\pi\\varepsilon_0} \\cdot \\dfrac{|q_1 q_2|}{r^2}$$
+ где $\\varepsilon_0 = 8{,}85 \\cdot 10^{-12}$ Ф/м — электрическая постоянная .
+ Направление :
+
+ Одноимённые ($q_1 q_2 > 0$): силы направлены от другого заряда (отталкивание).
+ Разноимённые ($q_1 q_2 < 0$): силы направлены к другому заряду (притяжение).
+
+ По 3-му закону Ньютона $\\vec{F}_{12} = -\\vec{F}_{21}$.
`);
+
+ /* THEORY 2 — Закон Кулона в среде */
+ html += makeCard('rule', "Закон Кулона в среде", "§17", `
+ В диэлектрической среде сила Кулона уменьшается в $\\varepsilon$ раз:
+ $$F = k\\,\\dfrac{|q_1 q_2|}{\\varepsilon\\, r^2}$$
+ где $\\varepsilon$ — относительная диэлектрическая проницаемость среды (безразмерная).
+ Примеры :
+
+ Вакуум, воздух : $\\varepsilon \\approx 1$.
+ Бензин : $\\varepsilon \\approx 2$.
+ Стекло : $\\varepsilon \\approx 5-10$.
+ Вода : $\\varepsilon \\approx 81$ (сильное ослабление сил!).
+ Сегнетоэлектрики : $\\varepsilon$ может достигать сотен и тысяч.
+
+ Это объясняет, почему соли и кислоты легко диссоциируют в воде: силы между ионами в воде в $81$ раз слабее, чем в вакууме.
+ `);
+
+ /* THEORY 3 — Принцип суперпозиции */
+ html += makeCard('example', "Принцип суперпозиции и пример", "§17", `
+ Принцип суперпозиции : если на заряд $q$ действуют несколько других зарядов, результирующая сила равна векторной сумме сил от каждого заряда отдельно:
+ $$\\vec{F} = \\vec{F_1} + \\vec{F_2} + \\vec{F_3} + \\ldots$$
+ Силы складываются как векторы (учитывая направления!).
+ Пример. Два заряда по $+1$ мкКл расположены на расстоянии $0{,}1$ м. Найти силу.
+ $$F = 9 \\cdot 10^9 \\cdot \\dfrac{(10^{-6})^2}{(0{,}1)^2} = 9 \\cdot 10^9 \\cdot \\dfrac{10^{-12}}{0{,}01} = 0{,}9 \\text{ Н}$$
+ Сравнение с гравитацией : кулоновская сила между двумя протонами в $\\sim 10^{36}$ раз сильнее гравитации. В макромире доминирует электромагнетизм; гравитация важна только потому, что положительные и отрицательные заряды в обычных телах в среднем уравновешиваются.
+ `);
+
+ /* INTERACTIVE 1 — Визуализатор закона Кулона (главный) */
+ html += `
+
+
Меняй заряды и расстояние — стрелки покажут силы, формула $F = k|q_1 q_2|/r^2$ пересчитается.
+
+ $q_1$: +5 нКл
+ $q_2$: +5 нКл
+ $r$: 0.20 м
+
+
+
+
+
+
`;
+
+ /* INTERACTIVE 2 — Калькулятор силы Кулона */
+ html += `
+
+
Введи заряды, расстояние, выбери среду. $F = k|q_1 q_2|/(\\varepsilon r^2)$, $k = 9 \\cdot 10^9$.
+
+
Вычислить $F$
+
+
+
`;
+
+ /* INTERACTIVE 3 — квикфайр «Как изменится сила?» */
+ html += `
+
+
6 ситуаций — как изменится сила Кулона? 4 варианта ответа.
+
Задача 1 / 6 Очки: 0 / 6
+
+
+
+
Начать заново
+
`;
+
+ /* INTERACTIVE 4 — Тренажёр Кулона */
+ html += `
+
+
5 задач. $k = 9 \\cdot 10^9$ Н$\\cdot$м$^2$/Кл$^2$. Допуск $\\pm 5\\%$.
+
Задача 1 / 5 Очки: 0 / 5
+
+
+ ответ =
+
+ Проверить
+ Заново
+
+
+
`;
+
html += secNav('p16', 'p18');
html += readButton('p17');
+
box.innerHTML = html;
renderMath(box);
+
+ /* IV1 — Главный визуализатор закона Кулона */
+ (function(){
+ const svg = document.getElementById('p17-iv1-svg');
+ const q1S = document.getElementById('p17-iv1-q1');
+ const q2S = document.getElementById('p17-iv1-q2');
+ const rS = document.getElementById('p17-iv1-r');
+ const q1L = document.getElementById('p17-iv1-q1L');
+ const q2L = document.getElementById('p17-iv1-q2L');
+ const rL = document.getElementById('p17-iv1-rL');
+ const out = document.getElementById('p17-iv1-out');
+ const seen = new Set();
+ let _done = false;
+ const k = PHYS.CONST.k;
+
+ function fmtQ(q){ return (q>=0?'+':'') + q.toFixed(1); }
+ function render(){
+ const q1 = +q1S.value, q2 = +q2S.value, r = +rS.value;
+ q1L.textContent = fmtQ(q1); q2L.textContent = fmtQ(q2); rL.textContent = r.toFixed(2);
+ const W = 480, H = 260;
+ const cy = 130;
+ // Картина: q1 слева, q2 справа. Минимальное расстояние пикселями для наглядности
+ const minPx = 90, maxPx = 360;
+ // Линейно: r=0.05 -> minPx, r=0.5 -> maxPx
+ const pxR = minPx + (r - 0.05) / (0.5 - 0.05) * (maxPx - minPx);
+ const cx1 = (W - pxR) / 2;
+ const cx2 = cx1 + pxR;
+ const radius = 22;
+
+ let g = '';
+ // Линия расстояния
+ g += ' ';
+ g += ' ';
+ g += ' ';
+ g += 'r = ' + r.toFixed(2) + ' м ';
+
+ // Заряды
+ g += PHYS.chargeMark(cx1, cy, q1 === 0 ? 1 : (q1 > 0 ? 1 : -1), radius, '');
+ if(q1 === 0){
+ g += ' ';
+ g += '0 ';
+ }
+ g += PHYS.chargeMark(cx2, cy, q2 === 0 ? 1 : (q2 > 0 ? 1 : -1), radius, '');
+ if(q2 === 0){
+ g += ' ';
+ g += '0 ';
+ }
+ // Подписи зарядов
+ g += 'q₁ = ' + fmtQ(q1) + ' нКл ';
+ g += 'q₂ = ' + fmtQ(q2) + ' нКл ';
+
+ // Расчёт силы (в Н). Заряды в нКл -> Кл
+ const qC1 = q1 * 1e-9, qC2 = q2 * 1e-9;
+ const F = k * Math.abs(qC1 * qC2) / (r * r);
+ // Преобразование в мН/мкН
+ let Fdisp, Funit;
+ if(F >= 1e-3){ Fdisp = (F * 1000).toFixed(2); Funit = 'мН'; }
+ else if(F >= 1e-6){ Fdisp = (F * 1e6).toFixed(2); Funit = 'мкН'; }
+ else { Fdisp = F.toExponential(2); Funit = 'Н'; }
+
+ // Стрелки силы
+ const prod = q1 * q2;
+ let kind;
+ if(prod === 0){
+ kind = 'Один из зарядов = 0: сила отсутствует';
+ } else {
+ const repulse = prod > 0;
+ kind = repulse ? 'Одноимённые: отталкиваются ' : 'Разноимённые: притягиваются ';
+ // Длина стрелки пропорциональна F (нормируем)
+ const maxArrowLen = 60;
+ // Нормировка относительно F при q1=q2=10 нКл, r=0.05м
+ const Fref = k * (10e-9 * 10e-9) / (0.05 * 0.05);
+ let arrowLen = Math.min(maxArrowLen, Math.sqrt(F / Fref) * maxArrowLen);
+ arrowLen = Math.max(15, arrowLen);
+
+ if(repulse){
+ // q1 толкается влево, q2 — вправо
+ g += PHYS.drawArrow(cx1 - 4, cy, cx1 - 4 - arrowLen, cy, '#dc2626', 3, 11);
+ g += PHYS.drawArrow(cx2 + 4, cy, cx2 + 4 + arrowLen, cy, '#dc2626', 3, 11);
+ g += 'F ';
+ g += 'F ';
+ } else {
+ // q1 тянется вправо, q2 — влево
+ g += PHYS.drawArrow(cx1 + 4, cy, cx1 + 4 + arrowLen, cy, '#10b981', 3, 11);
+ g += PHYS.drawArrow(cx2 - 4, cy, cx2 - 4 - arrowLen, cy, '#10b981', 3, 11);
+ g += 'F ';
+ g += 'F ';
+ }
+ }
+ // Заголовок
+ g += 'Закон Кулона: F = k|q₁q₂|/r² ';
+ svg.innerHTML = g;
+
+ out.innerHTML = '' + kind + '
'
+ + 'Сила: $F = k\\dfrac{|q_1 q_2|}{r^2} = ' + Fdisp + '$ ' + Funit + '
';
+ renderMath(out);
+
+ seen.add(q1.toFixed(1) + ':' + q2.toFixed(1) + ':' + r.toFixed(2));
+ if(!_done && seen.size >= 4){ _done = true; addXp(10, 'p17-iv1'); bumpProgress('p17', 15); }
+ }
+ q1S.addEventListener('input', render);
+ q2S.addEventListener('input', render);
+ rS.addEventListener('input', render);
+ render();
+ })();
+
+ /* IV2 — Калькулятор силы Кулона */
+ (function(){
+ const out = document.getElementById('p17-iv2-out');
+ const fb = document.getElementById('p17-iv2-fb');
+ const seen = new Set();
+ let _done = false;
+ const k = PHYS.CONST.k;
+
+ function calc(){
+ const q1 = parseFloat(document.getElementById('p17-iv2-q1').value);
+ const q2 = parseFloat(document.getElementById('p17-iv2-q2').value);
+ const r = parseFloat(document.getElementById('p17-iv2-r').value);
+ const u1 = parseFloat(document.getElementById('p17-iv2-u1').value);
+ const u2 = parseFloat(document.getElementById('p17-iv2-u2').value);
+ const ur = parseFloat(document.getElementById('p17-iv2-ur').value);
+ const eps = parseFloat(document.getElementById('p17-iv2-eps').value);
+ if(!isFinite(q1) || !isFinite(q2)){ feedback(fb, false, '✗ Введи заряды.'); return; }
+ if(!isFinite(r) || r <= 0){ feedback(fb, false, '✗ Расстояние должно быть положительным.'); return; }
+ const qC1 = q1 * u1, qC2 = q2 * u2, rM = r * ur;
+ const F = k * Math.abs(qC1 * qC2) / (eps * rM * rM);
+ // подача в подходящих единицах
+ let Fdisp, Funit;
+ if(F >= 1){ Fdisp = (+F.toFixed(3)); Funit = 'Н'; }
+ else if(F >= 1e-3){ Fdisp = (+(F*1000).toFixed(3)); Funit = 'мН'; }
+ else if(F >= 1e-6){ Fdisp = (+(F*1e6).toFixed(3)); Funit = 'мкН'; }
+ else { Fdisp = F.toExponential(3); Funit = 'Н'; }
+ const epsStr = eps === 1 ? '' : '\\varepsilon';
+ const epsForm = eps === 1 ? '' : (' \\cdot \\dfrac{1}{' + eps + '}');
+ out.innerHTML = 'В СИ: $q_1 = ' + qC1.toExponential(2) + '$ Кл, $q_2 = ' + qC2.toExponential(2) + '$ Кл, $r = ' + rM + '$ м'+(eps===1?'':', $\\varepsilon = '+eps+'$')+'
'
+ + 'Подстановка: $F = \\dfrac{9 \\cdot 10^9 \\cdot |' + qC1.toExponential(1) + ' \\cdot ' + qC2.toExponential(1) + '|}{' + (eps===1?'':eps+' \\cdot ') + (rM*rM).toExponential(2) + '}$
'
+ + 'Сила: $F \\approx ' + Fdisp + '$ ' + Funit + '
';
+ renderMath(out);
+ feedback(fb, true, '✓ Вычислено.');
+ seen.add(qC1.toExponential(1) + ':' + qC2.toExponential(1) + ':' + rM + ':' + eps);
+ if(!_done && seen.size >= 3){ _done = true; addXp(10, 'p17-iv2'); bumpProgress('p17', 15); }
+ }
+ document.getElementById('p17-iv2-go').addEventListener('click', calc);
+ })();
+
+ /* IV3 — квикфайр «Как изменится сила?» */
+ (function(){
+ // 4 опции на каждый вопрос
+ const OPTS = ['Увеличится в 2 раза', 'Уменьшится в 2 раза', 'Увеличится в 4 раза', 'Уменьшится в 4 раза'];
+ const Q = [
+ { q:'Если расстояние $r$ удвоить (заряды без изменений) — как изменится $F$?', ans:3, why:'$F \\propto 1/r^2$; при $r\\to 2r$ сила уменьшается в $4$ раза.' },
+ { q:'Если заряд $q_1$ удвоить (остальное без изменений) — как изменится $F$?', ans:0, why:'$F \\propto q_1$; сила увеличится в $2$ раза.' },
+ { q:'Если оба заряда $q_1, q_2$ удвоить (расстояние без изменений) — как изменится $F$?', ans:2, why:'$F \\propto q_1 q_2$; при $q_1\\to 2q_1$ и $q_2\\to 2q_2$ сила увеличится в $4$ раза.' },
+ { q:'Если расстояние $r$ уменьшить в $2$ раза — как изменится $F$?', ans:2, why:'$F \\propto 1/r^2$; при $r\\to r/2$ сила увеличится в $4$ раза.' },
+ { q:'Если заряды поместить в среду с $\\varepsilon = 2$ (вместо вакуума) — как изменится $F$?', ans:1, why:'$F = k|q_1q_2|/(\\varepsilon r^2)$; при $\\varepsilon = 2$ сила уменьшится в $2$ раза.' },
+ { q:'Если один из зарядов удвоить И расстояние удвоить — как изменится $F$?', ans:1, why:'$F \\propto q/r^2$; множитель $2/4 = 1/2$ — сила уменьшится в $2$ раза.' },
+ ];
+ let i = 0, score = 0;
+ const qEl = document.getElementById('p17-iv3-q');
+ const oEl = document.getElementById('p17-iv3-opts');
+ const fb = document.getElementById('p17-iv3-fb');
+ const iEl = document.getElementById('p17-iv3-i');
+ const sEl = document.getElementById('p17-iv3-s');
+
+ function show(){
+ if(i >= Q.length){
+ qEl.innerHTML = 'Готово! Результат: ' + score + ' / ' + Q.length;
+ oEl.innerHTML = '';
+ if(score === Q.length){ addXp(15, 'p17-iv3'); bumpProgress('p17', 25); }
+ else if(score >= 4){ addXp(8, 'p17-iv3'); bumpProgress('p17', 15); }
+ return;
+ }
+ iEl.textContent = (i+1);
+ sEl.textContent = score;
+ const item = Q[i];
+ qEl.innerHTML = item.q;
+ oEl.innerHTML = OPTS.map((t, k) => '' + t + ' ').join('');
+ fb.style.display = 'none';
+ renderMath(qEl); renderMath(oEl);
+ oEl.querySelectorAll('button').forEach(b => {
+ b.addEventListener('click', () => {
+ const v = +b.dataset.v;
+ if(v === item.ans){ score++; feedback(fb, true, '✓ Верно! ' + item.why + ' Дальше ▶'); }
+ else feedback(fb, false, '✗ Неверно. ' + item.why + ' Дальше ▶');
+ sEl.textContent = score;
+ oEl.querySelectorAll('button').forEach(x => x.disabled = true);
+ i++;
+ setTimeout(show, 1700);
+ });
+ });
+ }
+ document.getElementById('p17-iv3-restart').addEventListener('click', () => { i = 0; score = 0; show(); });
+ show();
+ })();
+
+ /* IV4 — Тренажёр Кулона */
+ (function(){
+ const Q = [
+ { q:'Два заряда по $+1$ мкКл на расстоянии $0{,}1$ м (в вакууме). Сила в Н?', ans:0.9, tol:0.05, hint:'$F = 9\\cdot10^9 \\cdot (10^{-6})^2/(0{,}1)^2 = 0{,}9$ Н.' },
+ { q:'Заряды $+2$ нКл и $-3$ нКл на $r = 0{,}06$ м. Сила в мН?', ans:15, tol:1, hint:'$F = 9\\cdot10^9 \\cdot 6\\cdot10^{-18}/0{,}0036 = 0{,}015$ Н $= 15$ мН.' },
+ { q:'При $r = 1$ м сила Кулона $F_0$. При каком $r$ (м) сила станет в $4$ раза меньше?', ans:2, tol:0.1, hint:'$F \\propto 1/r^2$; чтобы $F\\to F_0/4$, нужно $r \\to 2r_0 = 2$ м.' },
+ { q:'В воде ($\\varepsilon = 81$) сила Кулона во сколько раз меньше, чем в вакууме (при тех же зарядах и $r$)?', ans:81, tol:2, hint:'$F = k|q_1q_2|/(\\varepsilon r^2)$ — делится на $\\varepsilon = 81$.' },
+ { q:'Два электрона на $r = 10^{-10}$ м. Сила в Н? Введи мантиссу при $10^{-8}$.', ans:2.3, tol:0.3, hint:'$F = 9\\cdot10^9 \\cdot (1{,}6\\cdot10^{-19})^2/(10^{-10})^2 \\approx 2{,}3 \\cdot 10^{-8}$ Н.' },
+ ];
+ let i = 0, score = 0;
+ function show(){
+ if(i >= Q.length){
+ document.getElementById('p17-iv4-q').innerHTML = 'Готово! Результат: ' + score + ' / ' + Q.length;
+ if(score === Q.length){ addXp(15, 'p17-iv4'); bumpProgress('p17', 25); }
+ else if(score >= 3){ addXp(8, 'p17-iv4'); bumpProgress('p17', 15); }
+ return;
+ }
+ document.getElementById('p17-iv4-i').textContent = (i+1);
+ document.getElementById('p17-iv4-s').textContent = score;
+ document.getElementById('p17-iv4-q').innerHTML = Q[i].q;
+ document.getElementById('p17-iv4-ans').value = '';
+ renderMath(document.getElementById('p17-iv4-q'));
+ document.getElementById('p17-iv4-fb').style.display = 'none';
+ }
+ function go(){
+ if(i >= Q.length) return;
+ const fb = document.getElementById('p17-iv4-fb');
+ const raw = document.getElementById('p17-iv4-ans').value.replace(',', '.');
+ const ans = parseFloat(raw);
+ if(isNaN(ans)){ feedback(fb, false, '✗ Введи число.'); return; }
+ if(Math.abs(ans - Q[i].ans) <= Q[i].tol + 0.001){ score++; feedback(fb, true, '✓ Верно! '+Q[i].hint+' Дальше ▶'); }
+ else feedback(fb, false, '✗ Неверно. Ответ: $'+Q[i].ans+'$. '+Q[i].hint+' Дальше ▶');
+ document.getElementById('p17-iv4-s').textContent = score;
+ i++;
+ setTimeout(show, 1800);
+ }
+ document.getElementById('p17-iv4-go').addEventListener('click', go);
+ document.getElementById('p17-iv4-ans').addEventListener('keydown', e => { if(e.key === 'Enter') go(); });
+ document.getElementById('p17-iv4-start').addEventListener('click', () => { i = 0; score = 0; show(); });
+ show();
+ })();
+
wireReadBtn('p17');
}