799f651777
Глава 3 «Движение и силы» закрыта целиком. Файл вырос с 1082 до 2124 строк (+1042). Экспортирует 15 функций: p14..p27 + final3. §21 Сила: - 3 карточки (что такое сила / стрелка-вектор / 4 силы из жизни) - IV-1 СИМ: интерактивная стрелка силы с slider модуля и угла (0..360°) - DnD 8→4 (Ft/Fупр/Fтр/N) / квиз 4 / тренажёр 4 §22 Сила тяжести: - 3 карточки + IV-1 КАЛЬК: 4 кнопки планет (Земля/Луна/Марс/Юпитер) + slider m → Ft = mg с правильным g, выводом и подписью планеты - DnD 6→3 (1Н/10Н/100Н) / квиз 4 / тренажёр 5 §23 Сила упругости: - 3 карточки (когда возникает / Гук качественно / примеры) - IV-1 СИМ: SVG-пружина с подвешенным грузом, slider Δl=0..20 см → растягивается, стрелки Fупр↑ (зелёная) и Fт↓ (фиолетовая) - DnD 6→2 (есть/нет деформации) / квиз 3 / тренажёр 4 §24 Вес тела: - 3 карточки (P vs Ft / невесомость / взвешивание) - IV-1 СИМ: 4 ситуации (покой / падение / ускорение вверх=перегрузка / вниз), для каждой — стрелки Ft (фиолет, на тело) и P (индиго, на опору) - DnD 6→3 (Ft/P/P=0) / квиз 4 / тренажёр 4 §25 Динамометр: - 3 карточки + IV-1 СИМ: использует window.PHYS.dynamometer из phys.js, slider F и Fmax → SVG с пружиной, шкалой, указателем; warning при превышении - IV-2 КАЛЬК m = F/g с выбором планеты - DnD 6→3 (школьный/мед./пром.) / тренажёр 4 §26 СЛОЖЕНИЕ СИЛ — ГЛАВНЫЙ ВИЗУАЛ ГЛАВЫ 3: - 3 карточки (равнодействующая / сонапр/противопол / перетягивание каната) - IV-1 «Конструктор сил на теле»: 4 slider'а Ft↓ + N↑ + Fтяги→ + Fтр←, SVG-сцена с цветными стрелками от центра кубика и большой красной стрелкой R; вердикт «уравновешены / ускоряется вправо/влево/падает/подпрыгнет/под углом» - IV-2 КАЛЬК сложения 2 сил с переключателем сонапр./противопол. - IV-3 DnD 6→3 (R вправо/влево/0) / тренажёр 5 §27 Сила трения: - 3 карточки (откуда / виды / польза vs вред) - IV-1 СИМ-симулятор: slider m, F, выбор μ из 4 поверхностей (лёд / сталь / дерево / резина-асфальт). SVG с бруском, стрелками F→ и Fтр←, вердикт «ЕДЕТ / ПОКОИТСЯ» по сравнению F с μN - DnD 6→2 (полезно/мешает) / квиз 4 / тренажёр 5 ФИНАЛ ГЛАВЫ 3 (10 боссов + ачивка «Мастер движения» +50 XP): 1. v = s/t (20 м/с) 2. Средняя скорость с равным временем (7 м/с) 3. Плотность бруска → железо (7.8 г/см³) 4. Ft на Земле (39.2 Н) 5. Ft того же тела на Луне (6.4 Н) 6. Динамометр → масса (750 г) 7. R двух сил противоположных (12 Н) 8. R трёх сил на одной прямой (10 Н) 9. Сила трения скольжения (6 Н) 10. Магистр: брусок едет, Fтр_max < F, R = ? (2 Н) Все интерактивы wireDnd/wireQuiz/слайдеры/SVG привязаны. Parse OK, smoke OK.
2125 lines
165 KiB
JavaScript
2125 lines
165 KiB
JavaScript
// Физика 7 · Глава 3 «Движение и силы» · виджеты §§14–20 (часть 1: кинематика).
|
||
// Силы §§21–27 + финал — в Phase 4 (phys7_ch3b_widgets.js или этот же файл, расширим).
|
||
// Палитра главы — red (#dc2626).
|
||
|
||
(function(){
|
||
'use strict';
|
||
|
||
const ACCENT = '#dc2626';
|
||
const ACCENT_D = '#991b1b';
|
||
const ACCENT_SOFT = '#fee2e2';
|
||
|
||
function renderMath(root){
|
||
if(window.renderMathInElement){
|
||
try{
|
||
window.renderMathInElement(root, {
|
||
delimiters: [{left:'$$',right:'$$',display:true},{left:'$',right:'$',display:false}],
|
||
throwOnError: false
|
||
});
|
||
}catch(e){}
|
||
}
|
||
}
|
||
|
||
function makeCard(kind, title, badge, body){
|
||
const colorByKind = { theory:ACCENT, rule:'#0284c7', example:'#10b981' };
|
||
const labelByKind = { theory:'Теория', rule:'Правило', example:'Пример' };
|
||
const c = colorByKind[kind] || ACCENT;
|
||
return '<div style="background:#fff;border:1.5px solid ' + ACCENT_SOFT + ';border-left:5px solid ' + c + ';border-radius:11px;padding:14px 16px;margin-bottom:14px;box-shadow:0 2px 8px rgba(0,0,0,.05)">'
|
||
+ '<div style="display:flex;align-items:center;gap:10px;margin-bottom:8px;flex-wrap:wrap">'
|
||
+ '<span style="background:' + c + ';color:#fff;padding:3px 10px;border-radius:99px;font-size:.7rem;font-weight:800;text-transform:uppercase;letter-spacing:.05em">' + labelByKind[kind] + '</span>'
|
||
+ '<span style="font-size:.72rem;font-weight:700;color:#64748b;letter-spacing:.04em">' + (badge||'') + '</span>'
|
||
+ '<span style="font-family:Unbounded,sans-serif;font-weight:800;font-size:.96rem;color:#0f172a;flex:1;min-width:0">' + title + '</span>'
|
||
+ '</div>'
|
||
+ '<div style="font-size:.94rem;line-height:1.6;color:#0f172a">' + body + '</div>'
|
||
+ '</div>';
|
||
}
|
||
|
||
function wgWrap(id, badge, title, hint, body){
|
||
return '<div id="' + id + '" style="background:#fff;border:1.5px solid ' + ACCENT_SOFT + ';border-radius:12px;padding:14px 16px;margin-bottom:14px;box-shadow:0 2px 8px rgba(0,0,0,.05)">'
|
||
+ '<div style="display:flex;align-items:center;gap:10px;margin-bottom:8px;flex-wrap:wrap">'
|
||
+ '<span style="background:' + ACCENT + ';color:#fff;padding:3px 10px;border-radius:99px;font-size:.7rem;font-weight:800;letter-spacing:.05em">' + badge + '</span>'
|
||
+ '<span style="font-family:Unbounded,sans-serif;font-weight:800;font-size:.92rem;color:#0f172a">' + title + '</span>'
|
||
+ '</div>'
|
||
+ (hint ? '<div style="font-size:.84rem;color:#64748b;background:' + ACCENT_SOFT + ';border-left:3px solid ' + ACCENT + ';border-radius:6px;padding:8px 12px;margin-bottom:10px;line-height:1.5">' + hint + '</div>' : '')
|
||
+ body
|
||
+ '</div>';
|
||
}
|
||
|
||
function readButton(pid){
|
||
return '<div style="text-align:center;margin-top:18px"><button class="ph7-read-btn" data-pid="' + pid + '" '
|
||
+ 'style="background:linear-gradient(135deg,#10b981,#047857);color:#fff;border:none;padding:11px 22px;border-radius:11px;font-weight:700;font-size:.92rem;cursor:pointer;font-family:inherit;display:inline-flex;align-items:center;gap:8px;box-shadow:0 4px 14px rgba(16,185,129,.32)">'
|
||
+ '<svg viewBox="0 0 24 24" style="width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round"><polyline points="20 6 9 17 4 12"/></svg>'
|
||
+ 'Я прочитал § <span style="opacity:.85;font-size:.86rem">+10 XP</span>'
|
||
+ '</button></div>';
|
||
}
|
||
|
||
function wireReadBtn(pid){
|
||
const btn = document.querySelector('.ph7-read-btn[data-pid="' + pid + '"]');
|
||
if(!btn) return;
|
||
const KEY = 'physics7_ch3_read_' + pid;
|
||
if(localStorage.getItem(KEY) === '1'){
|
||
btn.innerHTML = '<svg viewBox="0 0 24 24" style="width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round"><polyline points="20 6 9 17 4 12"/></svg> Прочитано';
|
||
btn.disabled = true; btn.style.background = '#94a3b8'; btn.style.cursor = 'default';
|
||
return;
|
||
}
|
||
btn.addEventListener('click', function(){
|
||
if(localStorage.getItem(KEY) === '1') return;
|
||
localStorage.setItem(KEY, '1');
|
||
if(typeof window.bumpProgress === 'function') window.bumpProgress(pid, 30);
|
||
if(typeof window.addXp === 'function') window.addXp(10, 'read-' + pid);
|
||
btn.innerHTML = '<svg viewBox="0 0 24 24" style="width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round"><polyline points="20 6 9 17 4 12"/></svg> Прочитано';
|
||
btn.disabled = true; btn.style.background = '#94a3b8'; btn.style.cursor = 'default';
|
||
});
|
||
}
|
||
|
||
function wireDnd(host, items){
|
||
const root = document.getElementById(host);
|
||
if(!root) return;
|
||
const checkBtn = root.querySelector('.dnd-check');
|
||
const fb = root.querySelector('.dnd-fb');
|
||
let placed = {}, armed = null;
|
||
root.querySelectorAll('.dnd-chip').forEach(chip => chip.addEventListener('click', () => {
|
||
if(armed === chip){ armed.classList.remove('armed'); armed.style.boxShadow = ''; armed = null; return; }
|
||
if(armed){ armed.classList.remove('armed'); armed.style.boxShadow = ''; }
|
||
armed = chip;
|
||
chip.classList.add('armed');
|
||
chip.style.boxShadow = '0 0 0 3px rgba(220,38,38,.3)';
|
||
}));
|
||
root.querySelectorAll('.drop-box').forEach(box => box.addEventListener('click', () => {
|
||
if(!armed) return;
|
||
const cat = box.dataset.cat;
|
||
const id = armed.dataset.id;
|
||
placed[id] = cat;
|
||
const clone = armed.cloneNode(true);
|
||
clone.classList.remove('armed'); clone.classList.add('placed');
|
||
clone.style.background = ACCENT_SOFT; clone.style.borderColor = ACCENT; clone.style.boxShadow = '';
|
||
clone.addEventListener('click', e => {
|
||
e.stopPropagation();
|
||
delete placed[id];
|
||
clone.remove();
|
||
armed = null;
|
||
const orig = root.querySelector('.dnd-chip[data-id="' + id + '"]:not(.placed)');
|
||
if(orig) orig.style.display = '';
|
||
});
|
||
box.querySelector('.drop-items').appendChild(clone);
|
||
armed.style.display = 'none';
|
||
armed.classList.remove('armed'); armed.style.boxShadow = '';
|
||
armed = null;
|
||
}));
|
||
if(checkBtn) checkBtn.addEventListener('click', () => {
|
||
const total = items.length;
|
||
let correct = 0;
|
||
items.forEach(it => { if(placed[it.id] === it.cat) correct++; });
|
||
fb.style.display = 'block';
|
||
if(correct === total){
|
||
fb.style.background = '#d1fae5'; fb.style.color = '#065f46'; fb.style.borderLeft = '4px solid #10b981';
|
||
fb.innerHTML = '✓ Идеально! ' + total + '/' + total + '.';
|
||
if(typeof window.addXp === 'function') window.addXp(15, 'dnd-' + host);
|
||
} else {
|
||
fb.style.background = '#fee2e2'; fb.style.color = '#7f1d1d'; fb.style.borderLeft = '4px solid #dc2626';
|
||
fb.innerHTML = '✗ Правильно: ' + correct + '/' + total + '. Попробуй ещё раз.';
|
||
}
|
||
});
|
||
}
|
||
|
||
function dndPool(host, items, cats){
|
||
const chips = items.map(it => '<button class="dnd-chip" data-id="' + it.id + '" type="button" style="background:#fff;border:1.5px solid ' + ACCENT_SOFT + ';border-radius:10px;padding:7px 13px;cursor:pointer;font-size:.9rem;font-family:inherit;transition:all .15s">' + it.html + '</button>').join('');
|
||
const boxes = cats.map(c => '<div class="drop-box" data-cat="' + c.cat + '" style="background:#fff;border:1.5px dashed ' + ACCENT_SOFT + ';border-radius:10px;padding:10px;min-height:80px"><h5 style="font-family:Unbounded,sans-serif;font-size:.76rem;color:' + ACCENT_D + ';margin-bottom:8px;text-transform:uppercase;letter-spacing:.04em">' + c.label + '</h5><div class="drop-items" style="display:flex;flex-wrap:wrap;gap:6px;min-height:32px"></div></div>').join('');
|
||
return '<div id="' + host + '" class="dnd-host">'
|
||
+ '<div style="font-size:.86rem;color:#475569;margin-bottom:10px">Кликни по карточке, потом по корзине. Чтобы вернуть — кликни в корзине.</div>'
|
||
+ '<div style="display:flex;flex-wrap:wrap;gap:8px;margin-bottom:14px;padding:10px;border:1.5px dashed ' + ACCENT_SOFT + ';border-radius:10px;background:#fef2f2">' + chips + '</div>'
|
||
+ '<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:10px;margin-bottom:12px">' + boxes + '</div>'
|
||
+ '<div style="display:flex;gap:8px"><button class="dnd-check" type="button" style="background:linear-gradient(135deg,' + ACCENT + ',' + ACCENT_D + ');color:#fff;border:none;padding:9px 18px;border-radius:9px;font-weight:700;font-size:.86rem;cursor:pointer;font-family:inherit">Проверить</button></div>'
|
||
+ '<div class="dnd-fb" style="padding:10px 14px;border-radius:9px;font-weight:600;font-size:.88rem;margin-top:8px;display:none;line-height:1.45"></div>'
|
||
+ '</div>';
|
||
}
|
||
|
||
function quizQuestion(host, idx, q, opts, correctIdx, explain){
|
||
const optsHtml = opts.map((o,i) => '<button class="qz-opt" data-i="' + i + '" type="button" style="background:#fff;border:1.5px solid ' + ACCENT_SOFT + ';border-radius:9px;padding:9px 14px;cursor:pointer;font-size:.92rem;font-family:inherit;text-align:left;width:100%;margin-bottom:6px">' + o + '</button>').join('');
|
||
return '<div class="qz-q" data-idx="' + idx + '" style="background:' + ACCENT_SOFT + ';border:1.5px solid ' + ACCENT_SOFT + ';border-radius:10px;padding:12px 14px;margin-bottom:10px">'
|
||
+ '<div style="font-weight:700;margin-bottom:8px;font-size:.94rem">' + (idx+1) + '. ' + q + '</div>'
|
||
+ '<div class="qz-opts" data-correct="' + correctIdx + '" data-explain="' + (explain||'').replace(/"/g,'"') + '">' + optsHtml + '</div>'
|
||
+ '<div class="qz-fb" style="padding:9px 12px;border-radius:8px;font-size:.86rem;margin-top:6px;display:none;line-height:1.45"></div>'
|
||
+ '</div>';
|
||
}
|
||
|
||
function wireQuiz(host, onAllCorrect){
|
||
const root = document.getElementById(host);
|
||
if(!root) return;
|
||
const all = root.querySelectorAll('.qz-q');
|
||
const done = new Set();
|
||
all.forEach(qDiv => {
|
||
const opts = qDiv.querySelectorAll('.qz-opt');
|
||
const correct = +qDiv.querySelector('.qz-opts').dataset.correct;
|
||
const explain = qDiv.querySelector('.qz-opts').dataset.explain;
|
||
const fb = qDiv.querySelector('.qz-fb');
|
||
opts.forEach(o => o.addEventListener('click', () => {
|
||
if(done.has(qDiv)) return;
|
||
const i = +o.dataset.i;
|
||
opts.forEach(x => x.disabled = true);
|
||
if(i === correct){
|
||
o.style.background = '#d1fae5'; o.style.borderColor = '#10b981'; o.style.color = '#065f46';
|
||
fb.style.display = 'block'; fb.style.background = '#d1fae5'; fb.style.color = '#065f46'; fb.style.borderLeft = '4px solid #10b981';
|
||
fb.innerHTML = '✓ Верно!' + (explain ? ' ' + explain : '');
|
||
done.add(qDiv);
|
||
if(done.size === all.length && typeof onAllCorrect === 'function') onAllCorrect();
|
||
} else {
|
||
o.style.background = '#fee2e2'; o.style.borderColor = '#dc2626'; o.style.color = '#7f1d1d';
|
||
opts[correct].style.background = '#d1fae5'; opts[correct].style.borderColor = '#10b981'; opts[correct].style.color = '#065f46';
|
||
fb.style.display = 'block'; fb.style.background = '#fee2e2'; fb.style.color = '#7f1d1d'; fb.style.borderLeft = '4px solid #dc2626';
|
||
fb.innerHTML = '✗ Неверно. Правильно: «' + opts[correct].textContent + '».' + (explain ? ' ' + explain : '');
|
||
done.add(qDiv);
|
||
}
|
||
}));
|
||
});
|
||
}
|
||
|
||
/* ========================================================== */
|
||
/* §14 — Механическое движение. Относительность */
|
||
/* ========================================================== */
|
||
function add_p14(){
|
||
const body = document.getElementById('p14-body');
|
||
if(!body) return;
|
||
let h = '';
|
||
|
||
h += makeCard('theory', 'Что такое механическое движение', '§ 14.1',
|
||
'<b>Механическое движение</b> — это изменение положения тела относительно других тел с течением времени.<br><br>'
|
||
+ 'Чтобы описать движение, нужно выбрать <b>тело отсчёта</b> — то, относительно которого смотрим. '
|
||
+ 'Тело отсчёта + связанные с ним оси координат + часы = <b>система отсчёта (СО)</b>.');
|
||
|
||
h += makeCard('rule', 'Относительность движения и покоя', '§ 14.2',
|
||
'Одно и то же тело может <b>одновременно</b> и покоиться, и двигаться — в зависимости от выбранной СО.<br><br>'
|
||
+ 'Пример: пассажир в вагоне сидит на месте — относительно вагона он <b>покоится</b>; '
|
||
+ 'относительно земли он <b>движется</b> вместе с поездом со скоростью $v$.<br><br>'
|
||
+ 'Часто за тело отсчёта удобно брать Землю.');
|
||
|
||
h += makeCard('example', 'Облако и самолёт', '§ 14.3',
|
||
'Из иллюминатора самолёта вы видите облако.<br>'
|
||
+ '<b>Относительно земли</b>: самолёт летит со скоростью $900$ км/ч, облако почти неподвижно.<br>'
|
||
+ '<b>Относительно самолёта</b>: самолёт «стоит на месте» — а облако «летит» назад со скоростью $\\approx 900$ км/ч.<br>'
|
||
+ 'И то, и другое — правильно. Просто <b>СО разные</b>.');
|
||
|
||
/* IV-1 СИМ: 2 СО — поезд + пассажир + станция */
|
||
h += wgWrap('p14-iv1', 'СИМ', 'Откуда смотришь — то и видишь', 'Переключай систему отсчёта и наблюдай, кто движется, а кто стоит.',
|
||
'<div style="display:flex;gap:6px;margin-bottom:10px">'
|
||
+ '<button class="p14-co" data-co="ground" type="button" style="background:#dc2626;color:#fff;border:none;padding:8px 16px;border-radius:9px;cursor:pointer;font-weight:700;font-family:inherit">СО: Земля</button>'
|
||
+ '<button class="p14-co" data-co="train" type="button" style="background:#fff;color:#dc2626;border:2px solid #dc2626;padding:8px 16px;border-radius:9px;cursor:pointer;font-weight:700;font-family:inherit">СО: Поезд</button>'
|
||
+ '</div>'
|
||
+ '<svg id="p14-svg" viewBox="0 0 380 160" width="100%" style="max-width:600px;display:block;margin:0 auto;background:#fef2f2;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>'
|
||
+ '<div id="p14-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:10px 14px;margin-top:8px;font-size:.92rem;line-height:1.55"></div>');
|
||
|
||
/* IV-2 КВИЗ */
|
||
h += wgWrap('p14-iv2', 'КВИЗ', 'Покой или движение?', '',
|
||
'<div id="p14-q-host">'
|
||
+ quizQuestion('p14-q', 0, 'Пассажир сидит в едущем автобусе. Относительно сидящих рядом пассажиров он:', ['Движется','Покоится','И то, и другое','Невозможно определить'], 1)
|
||
+ quizQuestion('p14-q', 1, 'Тот же пассажир относительно дороги:', ['Движется','Покоится','Невозможно сказать','Только при остановке'], 0)
|
||
+ quizQuestion('p14-q', 2, 'Дерево у дороги относительно проезжающей машины:', ['Покоится','Движется в сторону, противоположную машине','Движется в ту же сторону','Зависит от скорости'], 1, 'Если за СО взять машину, дерево «летит» назад со скоростью машины.')
|
||
+ quizQuestion('p14-q', 3, 'Что такое система отсчёта?', ['Только тело отсчёта','Тело отсчёта + оси координат + часы','Только часы','Любая точка'], 1)
|
||
+ '</div>');
|
||
|
||
/* IV-3 DnD */
|
||
h += wgWrap('p14-iv3', 'DnD', 'Что движется относительно чего', '',
|
||
dndPool('p14-dnd', [
|
||
{ id:'a1', cat:'mov', html:'Луна относительно Земли' },
|
||
{ id:'a2', cat:'mov', html:'Машина относительно дороги' },
|
||
{ id:'a3', cat:'rest', html:'Светильник относительно потолка' },
|
||
{ id:'a4', cat:'rest', html:'Пассажир относительно вагона' },
|
||
{ id:'a5', cat:'mov', html:'Стрелка часов относительно циферблата' },
|
||
{ id:'a6', cat:'rest', html:'Книга на столе относительно стола' }
|
||
], [
|
||
{ cat:'mov', label:'Движется' },
|
||
{ cat:'rest', label:'Покоится' }
|
||
]));
|
||
|
||
/* IV-4 ТРН */
|
||
h += wgWrap('p14-iv4', 'ТРН', 'Тренажёр §14', '',
|
||
'<div id="p14-tr-host">'
|
||
+ quizQuestion('p14-tr', 0, 'Что НЕ входит в систему отсчёта?', ['Тело отсчёта','Оси координат','Часы','Скорость движения'], 3)
|
||
+ quizQuestion('p14-tr', 1, 'Покой или движение — это:', ['Абсолютные понятия','Относительные понятия (зависят от СО)','Существует только покой','Существует только движение'], 1)
|
||
+ quizQuestion('p14-tr', 2, 'Если за тело отсчёта взять движущийся поезд, то платформа:', ['Покоится','Движется','Не существует','Не имеет значения'], 1)
|
||
+ quizQuestion('p14-tr', 3, 'Можно ли утверждать, что Земля покоится?', ['Да, всегда','Нет, в одной СО — да, в другой — нет','Нет, никогда','Только ночью'], 1, 'Относительно Солнца Земля движется. Относительно дома — обычно её удобно считать покоящейся.')
|
||
+ '</div>');
|
||
|
||
h += readButton('p14');
|
||
body.innerHTML = h;
|
||
|
||
// §14 IV-1 wire
|
||
let frame14 = 0, raf14 = 0;
|
||
function draw14(){
|
||
const co = body.querySelector('.p14-co[style*="background: rgb(220, 38, 38)"], .p14-co[style*="background:#dc2626"]');
|
||
const isGround = !co || co.dataset.co === 'ground';
|
||
const W = 380, H = 160;
|
||
let trainX, treeX;
|
||
if(isGround){
|
||
trainX = 20 + (frame14 % 320);
|
||
treeX = 250;
|
||
} else {
|
||
trainX = 100; // поезд стоит
|
||
treeX = 380 - (frame14 % 320);
|
||
}
|
||
let s = '';
|
||
// Небо
|
||
s += '<rect x="0" y="0" width="' + W + '" height="' + (H - 30) + '" fill="#dbeafe"/>';
|
||
// Земля
|
||
s += '<rect x="0" y="' + (H - 30) + '" width="' + W + '" height="30" fill="#86efac"/>';
|
||
// Рельсы
|
||
s += '<line x1="0" y1="' + (H - 22) + '" x2="' + W + '" y2="' + (H - 22) + '" stroke="#374151" stroke-width="1.5"/>';
|
||
s += '<line x1="0" y1="' + (H - 18) + '" x2="' + W + '" y2="' + (H - 18) + '" stroke="#374151" stroke-width="1.5"/>';
|
||
// Дерево
|
||
s += '<rect x="' + treeX + '" y="' + (H - 60) + '" width="6" height="30" fill="#92400e"/>';
|
||
s += '<circle cx="' + (treeX + 3) + '" cy="' + (H - 65) + '" r="15" fill="#16a34a"/>';
|
||
// Поезд
|
||
s += '<rect x="' + trainX + '" y="' + (H - 70) + '" width="80" height="40" fill="#dc2626" stroke="#7f1d1d" stroke-width="1.5" rx="4"/>';
|
||
s += '<rect x="' + (trainX + 10) + '" y="' + (H - 60) + '" width="20" height="14" fill="#bfdbfe" stroke="#0c4a6e" stroke-width="1"/>';
|
||
s += '<rect x="' + (trainX + 40) + '" y="' + (H - 60) + '" width="20" height="14" fill="#bfdbfe" stroke="#0c4a6e" stroke-width="1"/>';
|
||
s += '<circle cx="' + (trainX + 18) + '" cy="' + (H - 28) + '" r="8" fill="#1f2937"/>';
|
||
s += '<circle cx="' + (trainX + 62) + '" cy="' + (H - 28) + '" r="8" fill="#1f2937"/>';
|
||
// Пассажир в окне
|
||
s += '<circle cx="' + (trainX + 20) + '" cy="' + (H - 56) + '" r="4" fill="#fbbf24"/>';
|
||
// Стрелка «направление обзора»
|
||
if(isGround){
|
||
s += '<text x="10" y="20" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="#0c4a6e">Наблюдатель на земле</text>';
|
||
} else {
|
||
s += '<text x="10" y="20" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="#0c4a6e">Наблюдатель в поезде</text>';
|
||
}
|
||
document.getElementById('p14-svg').innerHTML = s;
|
||
const info = document.getElementById('p14-info');
|
||
if(isGround){
|
||
info.innerHTML = '<b>СО: Земля.</b> Поезд <span style="color:#dc2626;font-weight:700">движется</span> направо. Дерево <span style="color:#10b981;font-weight:700">покоится</span>.';
|
||
} else {
|
||
info.innerHTML = '<b>СО: Поезд.</b> Поезд <span style="color:#10b981;font-weight:700">покоится</span>. Дерево <span style="color:#dc2626;font-weight:700">«движется»</span> назад с той же скоростью.';
|
||
}
|
||
}
|
||
function loop14(){
|
||
frame14 += 1;
|
||
if(!document.getElementById('p14-svg')){ cancelAnimationFrame(raf14); return; }
|
||
draw14();
|
||
raf14 = requestAnimationFrame(loop14);
|
||
}
|
||
body.querySelectorAll('.p14-co').forEach(btn => btn.addEventListener('click', () => {
|
||
body.querySelectorAll('.p14-co').forEach(b => { b.style.background = '#fff'; b.style.color = '#dc2626'; b.style.border = '2px solid #dc2626'; });
|
||
btn.style.background = '#dc2626'; btn.style.color = '#fff'; btn.style.border = 'none';
|
||
btn.style.padding = '8px 16px'; // компенсировать border
|
||
frame14 = 0;
|
||
draw14();
|
||
}));
|
||
raf14 = requestAnimationFrame(loop14);
|
||
|
||
wireDnd('p14-dnd', [
|
||
{ id:'a1', cat:'mov' },{ id:'a2', cat:'mov' },{ id:'a3', cat:'rest' },
|
||
{ id:'a4', cat:'rest' },{ id:'a5', cat:'mov' },{ id:'a6', cat:'rest' }
|
||
]);
|
||
wireQuiz('p14-q-host', () => { if(window.addXp) window.addXp(10, 'q-p14'); });
|
||
wireQuiz('p14-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p14'); });
|
||
wireReadBtn('p14');
|
||
renderMath(body);
|
||
}
|
||
|
||
/* ========================================================== */
|
||
/* §15 — Траектория, путь, время */
|
||
/* ========================================================== */
|
||
function add_p15(){
|
||
const body = document.getElementById('p15-body');
|
||
if(!body) return;
|
||
let h = '';
|
||
|
||
h += makeCard('theory', 'Три ключевых понятия', '§ 15.1',
|
||
'<b>Траектория</b> — это линия, по которой движется тело.<br>'
|
||
+ '<b>Путь</b> $s$ — длина этой линии. $[s] = $ м (метр).<br>'
|
||
+ '<b>Время</b> $t$ — длительность движения. $[t] = $ с (секунда).');
|
||
|
||
h += makeCard('rule', 'Виды траекторий', '§ 15.2',
|
||
'<ul style="padding-left:20px;margin:6px 0">'
|
||
+ '<li><b>Прямолинейная</b> — лифт, шарик в трубке.</li>'
|
||
+ '<li><b>Криволинейная</b> — поворот машины, спутник вокруг Земли.</li>'
|
||
+ '<li><b>Замкнутая</b> — бегун на круговой дорожке возвращается в старт; путь $\\neq 0$, а вот «перемещение» (вектор) равно $0$.</li>'
|
||
+ '</ul>'
|
||
+ 'Длина траектории <b>не зависит от направления</b> — это всегда положительное число.');
|
||
|
||
h += makeCard('example', 'Школьник идёт в школу', '§ 15.3',
|
||
'<b>Сценарий:</b> школьник прошёл $200$ м прямо, потом свернул и прошёл ещё $150$ м, через $5$ мин был в школе.<br>'
|
||
+ '<b>Траектория:</b> ломаная из двух прямых.<br>'
|
||
+ '<b>Путь:</b> $s = 200 + 150 = 350$ м.<br>'
|
||
+ '<b>Время:</b> $t = 5$ мин $= 300$ с.');
|
||
|
||
/* IV-1 СИМ: интерактивная траектория — нажимай по квадратам, считаем путь */
|
||
h += wgWrap('p15-iv1', 'СИМ', 'Считаем путь по траектории', 'Кликай по точкам сетки, чтобы построить ломаную траекторию. Путь будет суммироваться.',
|
||
'<div style="margin-bottom:8px;display:flex;gap:6px;flex-wrap:wrap;align-items:center">'
|
||
+ '<button id="p15-reset" type="button" style="background:#fff;border:1.5px solid ' + ACCENT_SOFT + ';padding:6px 12px;border-radius:8px;cursor:pointer;font-family:inherit;font-weight:600;font-size:.84rem">Сброс</button>'
|
||
+ '<div style="font-size:.84rem;color:#475569">Каждая клетка — $\\textbf{1}$ м.</div>'
|
||
+ '</div>'
|
||
+ '<svg id="p15-svg" viewBox="0 0 360 220" width="100%" style="max-width:600px;display:block;margin:0 auto;background:#fef2f2;border-radius:9px;border:1px solid ' + ACCENT_SOFT + ';cursor:crosshair"></svg>'
|
||
+ '<div id="p15-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:10px 14px;margin-top:8px;font-size:.94rem;text-align:center">Кликай по клеткам, чтобы построить путь.</div>');
|
||
|
||
/* IV-2 КВИЗ */
|
||
h += wgWrap('p15-iv2', 'КВИЗ', 'Что есть что', '',
|
||
'<div id="p15-q-host">'
|
||
+ quizQuestion('p15-q', 0, 'Длина траектории — это:', ['Время','Скорость','Путь','Перемещение'], 2)
|
||
+ quizQuestion('p15-q', 1, 'Бегун пробежал круг $400$ м и вернулся в старт. Путь равен:', ['0 м','200 м','400 м','800 м'], 2, 'Путь = длина траектории, не зависит от того, что бегун вернулся.')
|
||
+ quizQuestion('p15-q', 2, 'Единица пути в СИ:', ['Секунда','Метр','Километр','Минута'], 1)
|
||
+ '</div>');
|
||
|
||
/* IV-3 DnD */
|
||
h += wgWrap('p15-iv3', 'DnD', 'Тип траектории', '',
|
||
dndPool('p15-dnd', [
|
||
{ id:'a1', cat:'st', html:'Лифт' },
|
||
{ id:'a2', cat:'st', html:'Падающий мяч (вертикально)' },
|
||
{ id:'a3', cat:'cv', html:'Поворот машины' },
|
||
{ id:'a4', cat:'cv', html:'Спутник вокруг Земли' },
|
||
{ id:'a5', cat:'cl', html:'Бегун по круговой дорожке' },
|
||
{ id:'a6', cat:'cl', html:'Стрелка часов' }
|
||
], [
|
||
{ cat:'st', label:'Прямолинейная' },
|
||
{ cat:'cv', label:'Криволинейная' },
|
||
{ cat:'cl', label:'Замкнутая' }
|
||
]));
|
||
|
||
/* IV-4 ТРН */
|
||
h += wgWrap('p15-iv4', 'ТРН', 'Тренажёр §15', '',
|
||
'<div id="p15-tr-host">'
|
||
+ quizQuestion('p15-tr', 0, 'Велосипедист проехал $2$ км и вернулся обратно. Какой путь он проехал?', ['0 км','1 км','2 км','4 км'], 3, 'Путь — сумма длин всех участков: $2 + 2 = 4$ км.')
|
||
+ quizQuestion('p15-tr', 1, '$5$ мин $= ?$ с', ['50','300','500','3000'], 1)
|
||
+ quizQuestion('p15-tr', 2, '$1{,}5$ км $= ?$ м', ['15','150','1 500','15 000'], 2)
|
||
+ quizQuestion('p15-tr', 3, 'Может ли путь быть отрицательным?', ['Да','Нет — это длина, всегда $\\ge 0$','Только в нестандартных СО','Зависит от направления'], 1)
|
||
+ quizQuestion('p15-tr', 4, 'Что такое траектория?', ['Скорость движения','Линия, по которой движется тело','Длина пути','Время в пути'], 1)
|
||
+ '</div>');
|
||
|
||
h += readButton('p15');
|
||
body.innerHTML = h;
|
||
|
||
// §15 IV-1: clickable path
|
||
const W = 360, H = 220, cell = 20;
|
||
const points = [];
|
||
function draw15(){
|
||
let s = '';
|
||
// Сетка
|
||
for(let x = 0; x <= W; x += cell) s += '<line x1="' + x + '" y1="0" x2="' + x + '" y2="' + H + '" stroke="#fecaca" stroke-width="0.5"/>';
|
||
for(let y = 0; y <= H; y += cell) s += '<line x1="0" y1="' + y + '" x2="' + W + '" y2="' + y + '" stroke="#fecaca" stroke-width="0.5"/>';
|
||
// Линии между точками
|
||
if(points.length > 1){
|
||
let d = 'M ' + points[0].x + ' ' + points[0].y;
|
||
for(let i = 1; i < points.length; i++) d += ' L ' + points[i].x + ' ' + points[i].y;
|
||
s += '<path d="' + d + '" fill="none" stroke="#dc2626" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>';
|
||
}
|
||
// Точки
|
||
points.forEach((p, i) => {
|
||
s += '<circle cx="' + p.x + '" cy="' + p.y + '" r="6" fill="#dc2626" stroke="#fff" stroke-width="2"/>';
|
||
if(i === 0) s += '<text x="' + (p.x + 10) + '" y="' + (p.y - 6) + '" font-family="Inter,sans-serif" font-size="10" font-weight="700" fill="#0f172a">старт</text>';
|
||
else if(i === points.length - 1) s += '<text x="' + (p.x + 10) + '" y="' + (p.y - 6) + '" font-family="Inter,sans-serif" font-size="10" font-weight="700" fill="#0f172a">' + (i+1) + '</text>';
|
||
});
|
||
document.getElementById('p15-svg').innerHTML = s;
|
||
// Считаем путь
|
||
let total = 0;
|
||
for(let i = 1; i < points.length; i++){
|
||
total += Math.hypot(points[i].x - points[i-1].x, points[i].y - points[i-1].y);
|
||
}
|
||
const meters = (total / cell);
|
||
document.getElementById('p15-info').innerHTML = points.length < 2
|
||
? 'Кликай по клеткам, чтобы построить путь. (Кликнуто: ' + points.length + ')'
|
||
: 'Точек: <b>' + points.length + '</b> · Путь $s = $ <b>' + meters.toFixed(1) + '</b> м';
|
||
renderMath(document.getElementById('p15-info'));
|
||
}
|
||
document.getElementById('p15-svg').addEventListener('click', e => {
|
||
const rect = e.target.getBoundingClientRect();
|
||
const svgW = rect.width, svgH = rect.height;
|
||
const rawX = (e.clientX - rect.left) * (W / svgW);
|
||
const rawY = (e.clientY - rect.top) * (H / svgH);
|
||
const x = Math.round(rawX / cell) * cell;
|
||
const y = Math.round(rawY / cell) * cell;
|
||
points.push({ x, y });
|
||
draw15();
|
||
});
|
||
document.getElementById('p15-reset').addEventListener('click', () => { points.length = 0; draw15(); });
|
||
draw15();
|
||
|
||
wireDnd('p15-dnd', [
|
||
{ id:'a1', cat:'st' },{ id:'a2', cat:'st' },{ id:'a3', cat:'cv' },
|
||
{ id:'a4', cat:'cv' },{ id:'a5', cat:'cl' },{ id:'a6', cat:'cl' }
|
||
]);
|
||
wireQuiz('p15-q-host', () => { if(window.addXp) window.addXp(10, 'q-p15'); });
|
||
wireQuiz('p15-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p15'); });
|
||
wireReadBtn('p15');
|
||
renderMath(body);
|
||
}
|
||
|
||
/* ========================================================== */
|
||
/* §16 — Равномерное движение. Скорость */
|
||
/* ========================================================== */
|
||
function add_p16(){
|
||
const body = document.getElementById('p16-body');
|
||
if(!body) return;
|
||
let h = '';
|
||
|
||
h += makeCard('theory', 'Равномерное прямолинейное движение', '§ 16.1',
|
||
'<b>Равномерное</b> — это движение, при котором за <i>любые равные промежутки времени</i> тело проходит <i>равные</i> расстояния.<br><br>'
|
||
+ 'Скорость такого движения:<br>'
|
||
+ '$$v = \\dfrac{s}{t}$$<br>'
|
||
+ '$[v] = $ м/с (или км/ч). Это <b>векторная</b> величина — у неё есть направление, но в 7-м классе мы пишем как скаляр (без минуса).');
|
||
|
||
h += makeCard('rule', 'Единицы скорости', '§ 16.2',
|
||
'<table style="width:100%;border-collapse:collapse;margin-top:4px;font-size:.92rem">'
|
||
+ '<tr style="background:' + ACCENT_SOFT + '"><th style="padding:6px 10px;text-align:left;border-bottom:2px solid ' + ACCENT + '">Единица</th><th style="padding:6px 10px;text-align:left;border-bottom:2px solid ' + ACCENT + '">Перевод</th><th style="padding:6px 10px;text-align:left;border-bottom:2px solid ' + ACCENT + '">Где встречается</th></tr>'
|
||
+ [['м/с','1 м/с = 3,6 км/ч','физика, наука'],['км/ч','1 км/ч ≈ 0,28 м/с','транспорт, спидометры'],['см/с','100 см/с = 1 м/с','биология, мелкие объекты'],['км/с','1 км/с = 1000 м/с','космос, ракеты']].map(r =>
|
||
'<tr><td style="padding:5px 10px;border-bottom:1px solid ' + ACCENT_SOFT + ';font-family:JetBrains Mono,monospace;font-weight:700">' + r[0] + '</td><td style="padding:5px 10px;border-bottom:1px solid ' + ACCENT_SOFT + ';font-family:JetBrains Mono,monospace">' + r[1] + '</td><td style="padding:5px 10px;border-bottom:1px solid ' + ACCENT_SOFT + '">' + r[2] + '</td></tr>').join('')
|
||
+ '</table>');
|
||
|
||
h += makeCard('example', 'Простой расчёт', '§ 16.3',
|
||
'Поезд за $t = 2$ ч проехал $s = 180$ км равномерно.<br>'
|
||
+ '$v = s/t = 180\\,\\text{км}/2\\,\\text{ч} = 90$ км/ч $= 25$ м/с.<br><br>'
|
||
+ 'Из формулы $v = s/t$ можно выразить и другие: $s = v t$, $t = s/v$.');
|
||
|
||
/* IV-1 СИМ: автомобиль с slider v */
|
||
h += wgWrap('p16-iv1', 'СИМ', 'Автомобиль со скоростью v', 'Меняй скорость — наблюдай, как меняется путь за одно и то же время.',
|
||
'<div style="margin-bottom:10px"><label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Скорость $v$, м/с: <b id="p16-v" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">10</b><input type="range" id="p16-v-r" min="1" max="30" step="1" value="10" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label></div>'
|
||
+ '<svg id="p16-svg" viewBox="0 0 380 110" width="100%" style="max-width:600px;display:block;margin:0 auto;background:#fef2f2;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>'
|
||
+ '<div id="p16-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:10px 14px;margin-top:8px;font-size:.92rem;text-align:center"></div>');
|
||
|
||
/* IV-2 КАЛЬК: v = s/t */
|
||
h += wgWrap('p16-iv2', 'КАЛЬК', 'Калькулятор $v = s/t$', '',
|
||
'<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Путь $s$, м: <b id="p16c-s" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">100</b><input type="range" id="p16c-s-r" min="10" max="10000" step="10" value="100" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Время $t$, с: <b id="p16c-t" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">20</b><input type="range" id="p16c-t-r" min="1" max="3600" step="1" value="20" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
|
||
+ '</div>'
|
||
+ '<div style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:12px 14px;font-size:.96rem;line-height:1.7">'
|
||
+ '$v = s/t = $ <b id="p16c-v" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">5</b> м/с $= $ <b id="p16c-vkmh" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">18</b> км/ч'
|
||
+ '</div>');
|
||
|
||
/* IV-3 DnD: скорости из жизни */
|
||
h += wgWrap('p16-iv3', 'DnD', 'Скорости в жизни', 'Сопоставь объекты с их скоростями.',
|
||
dndPool('p16-dnd', [
|
||
{ id:'a1', cat:'low', html:'$1$ м/с' },
|
||
{ id:'a2', cat:'low', html:'$5$ км/ч' },
|
||
{ id:'a3', cat:'mid', html:'$60$ км/ч' },
|
||
{ id:'a4', cat:'mid', html:'$20$ м/с' },
|
||
{ id:'a5', cat:'high', html:'$900$ км/ч' },
|
||
{ id:'a6', cat:'high', html:'$340$ м/с' }
|
||
], [
|
||
{ cat:'low', label:'Пешеход' },
|
||
{ cat:'mid', label:'Машина / велосипедист' },
|
||
{ cat:'high', label:'Самолёт / звук' }
|
||
]));
|
||
|
||
/* IV-4 ТРН */
|
||
h += wgWrap('p16-iv4', 'ТРН', 'Тренажёр §16', '',
|
||
'<div id="p16-tr-host">'
|
||
+ quizQuestion('p16-tr', 0, 'Велосипедист за $30$ с проехал $150$ м. Скорость?', ['3 м/с','5 м/с','10 м/с','15 м/с'], 1, '$v = s/t = 150/30 = 5$ м/с.')
|
||
+ quizQuestion('p16-tr', 1, 'Автобус едет $54$ км/ч. Какой это путь за $10$ с?', ['90 м','120 м','150 м','180 м'], 2, '$v = 54/3{,}6 = 15$ м/с; $s = vt = 15 \\cdot 10 = 150$ м.')
|
||
+ quizQuestion('p16-tr', 2, 'Самолёт пролетает $720$ км за $1$ ч $30$ мин. Скорость в км/ч?', ['360','480','540','720'], 1, '$1$ ч $30$ мин $= 1{,}5$ ч. $v = 720/1{,}5 = 480$ км/ч.')
|
||
+ quizQuestion('p16-tr', 3, 'За какое время поезд проедет $300$ км со скоростью $100$ км/ч?', ['1 ч','2 ч','3 ч','4 ч'], 2, '$t = s/v = 300/100 = 3$ ч.')
|
||
+ quizQuestion('p16-tr', 4, 'Звук в воздухе $340$ м/с. Сколько это км/ч?', ['1024 км/ч','1224 км/ч','1340 км/ч','1500 км/ч'], 1, '$340 \\cdot 3{,}6 = 1224$ км/ч.')
|
||
+ '</div>');
|
||
|
||
h += readButton('p16');
|
||
body.innerHTML = h;
|
||
|
||
// §16 IV-1: car sim
|
||
let frame16 = 0, raf16 = 0;
|
||
function draw16(){
|
||
const v = +document.getElementById('p16-v-r').value;
|
||
document.getElementById('p16-v').textContent = v;
|
||
const W = 380, H = 110;
|
||
const t = frame16 / 60; // секунды (60 fps)
|
||
const pxPerM = 5;
|
||
let pos = (v * t * pxPerM) % (W - 60);
|
||
let s = '';
|
||
s += '<rect x="0" y="0" width="' + W + '" height="' + (H - 20) + '" fill="#dbeafe"/>';
|
||
s += '<rect x="0" y="' + (H - 20) + '" width="' + W + '" height="20" fill="#94a3b8"/>';
|
||
// Разметка
|
||
for(let x = 0; x < W; x += 20){
|
||
s += '<rect x="' + x + '" y="' + (H - 11) + '" width="10" height="2" fill="#fff"/>';
|
||
}
|
||
// Машина
|
||
s += '<rect x="' + pos + '" y="' + (H - 45) + '" width="50" height="22" fill="#dc2626" stroke="#7f1d1d" stroke-width="1.5" rx="3"/>';
|
||
s += '<rect x="' + (pos + 8) + '" y="' + (H - 41) + '" width="14" height="10" fill="#bfdbfe" stroke="#0c4a6e" stroke-width="0.5"/>';
|
||
s += '<rect x="' + (pos + 28) + '" y="' + (H - 41) + '" width="14" height="10" fill="#bfdbfe" stroke="#0c4a6e" stroke-width="0.5"/>';
|
||
s += '<circle cx="' + (pos + 12) + '" cy="' + (H - 20) + '" r="5" fill="#1f2937"/>';
|
||
s += '<circle cx="' + (pos + 38) + '" cy="' + (H - 20) + '" r="5" fill="#1f2937"/>';
|
||
document.getElementById('p16-svg').innerHTML = s;
|
||
const traveled = (v * t).toFixed(1);
|
||
document.getElementById('p16-info').innerHTML = '$v = ' + v + '$ м/с · время $t = ' + t.toFixed(1) + '$ с · путь $s = vt = $ <b>' + traveled + '</b> м';
|
||
renderMath(document.getElementById('p16-info'));
|
||
}
|
||
function loop16(){
|
||
frame16 += 1;
|
||
if(!document.getElementById('p16-svg')){ cancelAnimationFrame(raf16); return; }
|
||
draw16();
|
||
raf16 = requestAnimationFrame(loop16);
|
||
}
|
||
document.getElementById('p16-v-r').addEventListener('input', () => { frame16 = 0; draw16(); });
|
||
raf16 = requestAnimationFrame(loop16);
|
||
|
||
// §16 IV-2: calc v=s/t
|
||
const upd16c = () => {
|
||
const s = +document.getElementById('p16c-s-r').value;
|
||
const t = +document.getElementById('p16c-t-r').value;
|
||
document.getElementById('p16c-s').textContent = s;
|
||
document.getElementById('p16c-t').textContent = t;
|
||
const v = s / t;
|
||
document.getElementById('p16c-v').textContent = v.toFixed(2);
|
||
document.getElementById('p16c-vkmh').textContent = (v * 3.6).toFixed(1);
|
||
};
|
||
['p16c-s-r','p16c-t-r'].forEach(id => document.getElementById(id).addEventListener('input', upd16c));
|
||
upd16c();
|
||
|
||
wireDnd('p16-dnd', [
|
||
{ id:'a1', cat:'low' },{ id:'a2', cat:'low' },{ id:'a3', cat:'mid' },
|
||
{ id:'a4', cat:'mid' },{ id:'a5', cat:'high' },{ id:'a6', cat:'high' }
|
||
]);
|
||
wireQuiz('p16-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p16'); });
|
||
wireReadBtn('p16');
|
||
renderMath(body);
|
||
}
|
||
|
||
/* ========================================================== */
|
||
/* §17 — Графики пути и скорости (ГЛАВНЫЙ ВИЗУАЛ КИНЕМАТИКИ) */
|
||
/* ========================================================== */
|
||
function add_p17(){
|
||
const body = document.getElementById('p17-body');
|
||
if(!body) return;
|
||
let h = '';
|
||
|
||
h += makeCard('theory', 'График $s(t)$', '§ 17.1',
|
||
'При равномерном движении путь растёт <b>линейно</b> со временем: $s = v t$.<br>'
|
||
+ 'На графике «путь от времени» — это <b>прямая линия</b>, проходящая через начало координат '
|
||
+ '(если в момент $t = 0$ тело было в стартовой точке).<br><br>'
|
||
+ '<b>Наклон</b> прямой равен скорости $v$. Чем круче линия — тем быстрее движется тело.');
|
||
|
||
h += makeCard('rule', 'График $v(t)$', '§ 17.2',
|
||
'При равномерном движении скорость <b>постоянна</b>: $v(t) = $ const.<br>'
|
||
+ 'На графике «скорость от времени» — это <b>горизонтальная линия</b>.<br><br>'
|
||
+ '<b>Площадь под графиком</b> $v(t)$ равна <b>пройденному пути</b>: $s = v \\cdot t$ (площадь прямоугольника).');
|
||
|
||
h += makeCard('example', 'Два тела на одном графике', '§ 17.3',
|
||
'Если на $s(t)$ две прямые — та, у которой <b>больше наклон</b>, движется быстрее. '
|
||
+ 'Если линии пересекаются — в эту точку оба тела пришли одновременно. '
|
||
+ 'Параллельные прямые → одинаковые скорости.');
|
||
|
||
/* IV-1 ГЛАВНЫЙ ВИЗУАЛ: интерактивные графики */
|
||
h += wgWrap('p17-iv1', 'СИМ', 'Главный визуал: графики s(t) и v(t)', 'Меняй $v_1$ и $v_2$ — наблюдай два тела одновременно.',
|
||
'<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Тело 1: $v_1$, м/с: <b id="p17-v1" style="color:#dc2626;font-family:JetBrains Mono,monospace">3</b><input type="range" id="p17-v1-r" min="1" max="10" step="1" value="3" style="display:block;width:100%;margin-top:6px;accent-color:#dc2626"></label>'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Тело 2: $v_2$, м/с: <b id="p17-v2" style="color:#0284c7;font-family:JetBrains Mono,monospace">6</b><input type="range" id="p17-v2-r" min="1" max="10" step="1" value="6" style="display:block;width:100%;margin-top:6px;accent-color:#0284c7"></label>'
|
||
+ '</div>'
|
||
+ '<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px">'
|
||
+ '<div><div style="text-align:center;font-weight:700;font-size:.88rem;color:#0c4a6e;margin-bottom:4px">График $s(t)$</div><svg id="p17-svg-s" viewBox="0 0 220 170" width="100%" style="background:#fef2f2;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg></div>'
|
||
+ '<div><div style="text-align:center;font-weight:700;font-size:.88rem;color:#0c4a6e;margin-bottom:4px">График $v(t)$</div><svg id="p17-svg-v" viewBox="0 0 220 170" width="100%" style="background:#fef2f2;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg></div>'
|
||
+ '</div>'
|
||
+ '<div id="p17-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:10px 14px;margin-top:10px;font-size:.92rem;line-height:1.6"></div>');
|
||
|
||
/* IV-2 КВИЗ */
|
||
h += wgWrap('p17-iv2', 'КВИЗ', 'Чтение графиков', '',
|
||
'<div id="p17-q-host">'
|
||
+ quizQuestion('p17-q', 0, 'На графике $s(t)$ прямая поднимается круче — что это значит?', ['Тело тяжелее','Тело движется быстрее','Тело покоится','Тело останавливается'], 1, 'Чем круче наклон, тем больше $v = s/t$.')
|
||
+ quizQuestion('p17-q', 1, 'На графике $v(t)$ — горизонтальная линия. Что движется?', ['Тело ускоряется','Тело движется равномерно','Тело покоится','Невозможно сказать'], 1)
|
||
+ quizQuestion('p17-q', 2, 'Что равно площадь под графиком $v(t)$ (прямоугольник)?', ['Скорости','Времени','Пути','Массе'], 2, '$s = v \\cdot t$ — это произведение, оно же площадь прямоугольника.')
|
||
+ quizQuestion('p17-q', 3, 'Две параллельные прямые на $s(t)$ — что это значит?', ['Тела имеют одинаковую скорость','Тела покоятся','Тела движутся в разных направлениях','Тела разной массы'], 0)
|
||
+ '</div>');
|
||
|
||
/* IV-3 DnD */
|
||
h += wgWrap('p17-iv3', 'DnD', 'Опиши график', '',
|
||
dndPool('p17-dnd', [
|
||
{ id:'a1', cat:'st_rest', html:'$s(t)$ — горизонтальная' },
|
||
{ id:'a2', cat:'st_move', html:'$s(t)$ — наклонная вверх' },
|
||
{ id:'a3', cat:'v_rest', html:'$v(t)$ — лежит на оси $t$' },
|
||
{ id:'a4', cat:'v_move', html:'$v(t)$ — горизонтальная не на 0' },
|
||
{ id:'a5', cat:'st_move', html:'$s = 3t$' },
|
||
{ id:'a6', cat:'v_move', html:'$v = 5$ м/с (const)' }
|
||
], [
|
||
{ cat:'st_rest', label:'Тело покоится' },
|
||
{ cat:'st_move', label:'Равномерное движение' },
|
||
{ cat:'v_rest', label:'$v = 0$ (покой)' },
|
||
{ cat:'v_move', label:'$v \\ne 0$ (движется)' }
|
||
]));
|
||
|
||
/* IV-4 ТРН */
|
||
h += wgWrap('p17-iv4', 'ТРН', 'Тренажёр §17', '',
|
||
'<div id="p17-tr-host">'
|
||
+ quizQuestion('p17-tr', 0, 'Тело прошло $40$ м за $8$ с равномерно. Скорость $v$?', ['3 м/с','4 м/с','5 м/с','8 м/с'], 2)
|
||
+ quizQuestion('p17-tr', 1, 'На графике $v(t)$ — линия $v = 4$ м/с. Какой путь за $6$ с?', ['10 м','18 м','24 м','30 м'], 2, '$s = vt = 4 \\cdot 6 = 24$ м (площадь прямоугольника).')
|
||
+ quizQuestion('p17-tr', 2, 'Два тела. На $s(t)$ первое — прямая $s = 2t$, второе — $s = 5t$. Кто быстрее?', ['Первое','Второе','Одинаково','Нельзя определить'], 1, '$v_2 = 5$ м/с $> v_1 = 2$ м/с.')
|
||
+ quizQuestion('p17-tr', 3, 'Тело покоится. Как выглядит $s(t)$?', ['Прямая через 0','Горизонтальная линия','Линия под углом 45°','Парабола'], 1)
|
||
+ '</div>');
|
||
|
||
h += readButton('p17');
|
||
body.innerHTML = h;
|
||
|
||
// §17 IV-1 graphs
|
||
function draw17(){
|
||
const v1 = +document.getElementById('p17-v1-r').value;
|
||
const v2 = +document.getElementById('p17-v2-r').value;
|
||
document.getElementById('p17-v1').textContent = v1;
|
||
document.getElementById('p17-v2').textContent = v2;
|
||
const W = 220, H = 170, pad = 30;
|
||
const tMax = 10, vMax = 12, sMax = 100;
|
||
// s(t)
|
||
function toXs(t){ return pad + (W - 2*pad) * t / tMax; }
|
||
function toYs(s){ return H - pad - (H - 2*pad) * s / sMax; }
|
||
let ss = '';
|
||
ss += '<line x1="' + pad + '" y1="' + (H - pad) + '" x2="' + (W - pad + 4) + '" y2="' + (H - pad) + '" stroke="#0f172a" stroke-width="1.5"/>';
|
||
ss += '<line x1="' + pad + '" y1="' + (pad - 4) + '" x2="' + pad + '" y2="' + (H - pad) + '" stroke="#0f172a" stroke-width="1.5"/>';
|
||
ss += '<text x="' + (W - pad + 6) + '" y="' + (H - pad + 4) + '" font-family="Inter,sans-serif" font-size="10" fill="#0f172a">t, с</text>';
|
||
ss += '<text x="' + (pad - 4) + '" y="' + (pad - 6) + '" text-anchor="end" font-family="Inter,sans-serif" font-size="10" fill="#0f172a">s, м</text>';
|
||
// ticks
|
||
for(let t = 0; t <= tMax; t += 2){
|
||
const x = toXs(t);
|
||
ss += '<line x1="' + x + '" y1="' + (H - pad) + '" x2="' + x + '" y2="' + (H - pad + 3) + '" stroke="#0f172a" stroke-width="1"/>';
|
||
if(t > 0) ss += '<text x="' + x + '" y="' + (H - pad + 13) + '" text-anchor="middle" font-family="Inter,sans-serif" font-size="8" fill="#0f172a">' + t + '</text>';
|
||
}
|
||
for(let s = 0; s <= sMax; s += 20){
|
||
const y = toYs(s);
|
||
ss += '<line x1="' + pad + '" y1="' + y + '" x2="' + (pad - 3) + '" y2="' + y + '" stroke="#0f172a" stroke-width="1"/>';
|
||
if(s > 0) ss += '<text x="' + (pad - 5) + '" y="' + (y + 3) + '" text-anchor="end" font-family="Inter,sans-serif" font-size="8" fill="#0f172a">' + s + '</text>';
|
||
}
|
||
// Lines
|
||
ss += '<line x1="' + toXs(0) + '" y1="' + toYs(0) + '" x2="' + toXs(tMax) + '" y2="' + toYs(Math.min(sMax, v1 * tMax)) + '" stroke="#dc2626" stroke-width="2.5"/>';
|
||
ss += '<line x1="' + toXs(0) + '" y1="' + toYs(0) + '" x2="' + toXs(tMax) + '" y2="' + toYs(Math.min(sMax, v2 * tMax)) + '" stroke="#0284c7" stroke-width="2.5"/>';
|
||
ss += '<text x="' + (W - 60) + '" y="20" font-family="Inter,sans-serif" font-size="10" font-weight="700" fill="#dc2626">тело 1: v=' + v1 + '</text>';
|
||
ss += '<text x="' + (W - 60) + '" y="34" font-family="Inter,sans-serif" font-size="10" font-weight="700" fill="#0284c7">тело 2: v=' + v2 + '</text>';
|
||
document.getElementById('p17-svg-s').innerHTML = ss;
|
||
// v(t)
|
||
function toYv(v){ return H - pad - (H - 2*pad) * v / vMax; }
|
||
let sv = '';
|
||
sv += '<line x1="' + pad + '" y1="' + (H - pad) + '" x2="' + (W - pad + 4) + '" y2="' + (H - pad) + '" stroke="#0f172a" stroke-width="1.5"/>';
|
||
sv += '<line x1="' + pad + '" y1="' + (pad - 4) + '" x2="' + pad + '" y2="' + (H - pad) + '" stroke="#0f172a" stroke-width="1.5"/>';
|
||
sv += '<text x="' + (W - pad + 6) + '" y="' + (H - pad + 4) + '" font-family="Inter,sans-serif" font-size="10" fill="#0f172a">t, с</text>';
|
||
sv += '<text x="' + (pad - 4) + '" y="' + (pad - 6) + '" text-anchor="end" font-family="Inter,sans-serif" font-size="10" fill="#0f172a">v, м/с</text>';
|
||
for(let t = 0; t <= tMax; t += 2){
|
||
const x = toXs(t);
|
||
sv += '<line x1="' + x + '" y1="' + (H - pad) + '" x2="' + x + '" y2="' + (H - pad + 3) + '" stroke="#0f172a" stroke-width="1"/>';
|
||
if(t > 0) sv += '<text x="' + x + '" y="' + (H - pad + 13) + '" text-anchor="middle" font-family="Inter,sans-serif" font-size="8" fill="#0f172a">' + t + '</text>';
|
||
}
|
||
for(let v = 0; v <= vMax; v += 2){
|
||
const y = toYv(v);
|
||
sv += '<line x1="' + pad + '" y1="' + y + '" x2="' + (pad - 3) + '" y2="' + y + '" stroke="#0f172a" stroke-width="1"/>';
|
||
if(v > 0) sv += '<text x="' + (pad - 5) + '" y="' + (y + 3) + '" text-anchor="end" font-family="Inter,sans-serif" font-size="8" fill="#0f172a">' + v + '</text>';
|
||
}
|
||
// Площадь под v1 (заливка)
|
||
sv += '<rect x="' + toXs(0) + '" y="' + toYv(v1) + '" width="' + (toXs(tMax) - toXs(0)) + '" height="' + (toYv(0) - toYv(v1)) + '" fill="#dc2626" opacity="0.18"/>';
|
||
sv += '<line x1="' + toXs(0) + '" y1="' + toYv(v1) + '" x2="' + toXs(tMax) + '" y2="' + toYv(v1) + '" stroke="#dc2626" stroke-width="2.5"/>';
|
||
sv += '<line x1="' + toXs(0) + '" y1="' + toYv(v2) + '" x2="' + toXs(tMax) + '" y2="' + toYv(v2) + '" stroke="#0284c7" stroke-width="2.5"/>';
|
||
sv += '<text x="' + (toXs(5)) + '" y="' + (toYv(v1/2)) + '" text-anchor="middle" font-family="Inter,sans-serif" font-size="9" font-weight="700" fill="#dc2626">s₁ = v₁·t</text>';
|
||
document.getElementById('p17-svg-v').innerHTML = sv;
|
||
// Info
|
||
document.getElementById('p17-info').innerHTML = 'За $t = 10$ с тело 1 пройдёт $s_1 = v_1 t = ' + (v1 * 10) + '$ м, тело 2 — $s_2 = v_2 t = ' + (v2 * 10) + '$ м. ' + (v1 === v2 ? 'Скорости равны — графики $s(t)$ параллельны.' : 'Скорости разные → разный наклон.');
|
||
renderMath(document.getElementById('p17-info'));
|
||
}
|
||
['p17-v1-r','p17-v2-r'].forEach(id => document.getElementById(id).addEventListener('input', draw17));
|
||
draw17();
|
||
|
||
wireDnd('p17-dnd', [
|
||
{ id:'a1', cat:'st_rest' },{ id:'a2', cat:'st_move' },{ id:'a3', cat:'v_rest' },
|
||
{ id:'a4', cat:'v_move' },{ id:'a5', cat:'st_move' },{ id:'a6', cat:'v_move' }
|
||
]);
|
||
wireQuiz('p17-q-host', () => { if(window.addXp) window.addXp(10, 'q-p17'); });
|
||
wireQuiz('p17-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p17'); });
|
||
wireReadBtn('p17');
|
||
renderMath(body);
|
||
}
|
||
|
||
/* ========================================================== */
|
||
/* §18 — Неравномерное движение. Средняя скорость */
|
||
/* ========================================================== */
|
||
function add_p18(){
|
||
const body = document.getElementById('p18-body');
|
||
if(!body) return;
|
||
let h = '';
|
||
|
||
h += makeCard('theory', 'Неравномерное движение', '§ 18.1',
|
||
'В реальности тела почти никогда не движутся <b>идеально равномерно</b>: машина в городе разгоняется, тормозит у светофоров, '
|
||
+ 'снова разгоняется. Скорость <b>меняется</b> со временем — это <b>неравномерное (переменное) движение</b>.<br><br>'
|
||
+ 'Чтобы охарактеризовать его «в среднем», используют <b>среднюю скорость</b>.');
|
||
|
||
h += makeCard('rule', 'Формула средней скорости', '§ 18.2',
|
||
'$$\\langle v\\rangle = \\dfrac{s_{полн}}{t_{полн}}$$<br>'
|
||
+ '«Средняя скорость = весь путь, делённый на всё время».<br><br>'
|
||
+ '<b>Внимание!</b> Часто путают: $\\langle v\\rangle \\ne (v_1 + v_2)/2$ — среднеарифметическое <b>не работает</b>, '
|
||
+ 'если на участках разное <b>время</b>. Среднее по пути считается через массы (произведение $v \\cdot t$ на каждом участке).');
|
||
|
||
h += makeCard('example', 'Пешеход и метро', '§ 18.3',
|
||
'Девочка прошла пешком $0{,}5$ км за $10$ мин, потом проехала $5$ км на метро за $10$ мин.<br>'
|
||
+ '$s_{полн} = 0{,}5 + 5 = 5{,}5$ км, $t_{полн} = 20$ мин $= 1/3$ ч.<br>'
|
||
+ '$\\langle v\\rangle = 5{,}5 / (1/3) = 16{,}5$ км/ч.<br><br>'
|
||
+ 'Хотя метро ехало $30$ км/ч, а пешком — $3$ км/ч, средняя — <b>не</b> $(30+3)/2 = 16{,}5$. Совпало здесь только потому, что время оказалось равным!');
|
||
|
||
/* IV-1 КАЛЬК */
|
||
h += wgWrap('p18-iv1', 'КАЛЬК', 'Средняя на двух участках', 'Меняй $v_1, t_1, v_2, t_2$ — сравнивай среднюю и среднеарифметическое.',
|
||
'<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:8px;margin-bottom:10px">'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$v_1$, м/с: <b id="p18-v1" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">20</b><input type="range" id="p18-v1-r" min="1" max="50" step="1" value="20" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$t_1$, с: <b id="p18-t1" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">60</b><input type="range" id="p18-t1-r" min="5" max="300" step="5" value="60" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$v_2$, м/с: <b id="p18-v2" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">10</b><input type="range" id="p18-v2-r" min="1" max="50" step="1" value="10" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$t_2$, с: <b id="p18-t2" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">120</b><input type="range" id="p18-t2-r" min="5" max="300" step="5" value="120" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
|
||
+ '</div>'
|
||
+ '<div style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:12px 14px;display:flex;flex-direction:column;gap:6px;font-size:.94rem">'
|
||
+ '<div>$\\langle v\\rangle = (v_1 t_1 + v_2 t_2)/(t_1+t_2) = $ <b id="p18-vavg" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">13.33</b> м/с</div>'
|
||
+ '<div style="font-size:.86rem;color:#475569">Ловушка: $(v_1+v_2)/2 = $ <b id="p18-trap" style="color:#dc2626;font-family:JetBrains Mono,monospace">15.00</b> м/с — <span id="p18-trap-lbl" style="font-weight:700;color:#dc2626">НЕВЕРНО</span></div>'
|
||
+ '</div>');
|
||
|
||
/* IV-2 КВИЗ */
|
||
h += wgWrap('p18-iv2', 'КВИЗ', 'Среднеарифметическое и средняя', '',
|
||
'<div id="p18-q-host">'
|
||
+ quizQuestion('p18-q', 0, 'Когда $\\langle v\\rangle$ равна среднему арифметическому?', ['Всегда','Когда время на участках одинаковое','Когда путь одинаковый','Никогда'], 1, 'Среднее арифметическое — это $\\langle v\\rangle$ только если $t_1 = t_2$.')
|
||
+ quizQuestion('p18-q', 1, 'Половину пути тело шло $5$ м/с, вторую половину — $20$ м/с. $\\langle v\\rangle$ ближе к…', ['5 м/с','12,5 м/с','20 м/с','8 м/с'], 3, 'Если одинаковые пути, то $\\langle v\\rangle = 2 v_1 v_2 / (v_1 + v_2) = 8$ м/с (ближе к меньшей).')
|
||
+ quizQuestion('p18-q', 2, 'Если тело часть времени стояло (т.е. $v = 0$), $\\langle v\\rangle$ всего пути…', ['Стала больше','Уменьшилась','Не изменилась','Стала равна нулю'], 1)
|
||
+ '</div>');
|
||
|
||
/* IV-3 DnD */
|
||
h += wgWrap('p18-iv3', 'DnD', 'Какое движение?', '',
|
||
dndPool('p18-dnd', [
|
||
{ id:'a1', cat:'eq', html:'Лифт между этажами на постоянной скорости' },
|
||
{ id:'a2', cat:'eq', html:'Шарик в воде, опускающийся равномерно' },
|
||
{ id:'a3', cat:'neq', html:'Машина в городе' },
|
||
{ id:'a4', cat:'neq', html:'Падающий камень (в воздухе)' },
|
||
{ id:'a5', cat:'neq', html:'Поезд от станции до станции' },
|
||
{ id:'a6', cat:'eq', html:'Звук в воздухе на короткой дистанции' }
|
||
], [
|
||
{ cat:'eq', label:'Равномерное' },
|
||
{ cat:'neq', label:'Неравномерное' }
|
||
]));
|
||
|
||
/* IV-4 ТРН */
|
||
h += wgWrap('p18-iv4', 'ТРН', 'Тренажёр §18', '',
|
||
'<div id="p18-tr-host">'
|
||
+ quizQuestion('p18-tr', 0, 'Тело прошло $60$ м за $4$ с и ещё $80$ м за $6$ с. $\\langle v\\rangle$?', ['10 м/с','12 м/с','14 м/с','15 м/с'], 2, '$\\langle v\\rangle = (60+80)/(4+6) = 140/10 = 14$ м/с.')
|
||
+ quizQuestion('p18-tr', 1, 'Машина $1$ ч ехала $60$ км/ч, потом $2$ ч — $90$ км/ч. $\\langle v\\rangle$ в км/ч?', ['70','75','80','85'], 2, '$(60 \\cdot 1 + 90 \\cdot 2)/(1+2) = 240/3 = 80$ км/ч.')
|
||
+ quizQuestion('p18-tr', 2, 'Поезд проехал $300$ км за $5$ ч, при этом $1$ ч стоял на станции. Средняя скорость движения?', ['50 км/ч','60 км/ч','75 км/ч','100 км/ч'], 2, '«Средняя скорость движения» — без учёта стоянки: $300 / (5-1) = 75$ км/ч.')
|
||
+ quizQuestion('p18-tr', 3, 'Велосипедист первые $5$ км ехал $20$ мин, ещё $5$ км — $40$ мин. $\\langle v\\rangle$?', ['7,5 км/ч','10 км/ч','12 км/ч','15 км/ч'], 1, '$s = 10$ км, $t = 1$ ч. $\\langle v\\rangle = 10$ км/ч.')
|
||
+ '</div>');
|
||
|
||
h += readButton('p18');
|
||
body.innerHTML = h;
|
||
|
||
// §18 IV-1
|
||
const upd18 = () => {
|
||
const v1 = +document.getElementById('p18-v1-r').value;
|
||
const t1 = +document.getElementById('p18-t1-r').value;
|
||
const v2 = +document.getElementById('p18-v2-r').value;
|
||
const t2 = +document.getElementById('p18-t2-r').value;
|
||
document.getElementById('p18-v1').textContent = v1;
|
||
document.getElementById('p18-t1').textContent = t1;
|
||
document.getElementById('p18-v2').textContent = v2;
|
||
document.getElementById('p18-t2').textContent = t2;
|
||
const vavg = (v1*t1 + v2*t2)/(t1+t2);
|
||
const arith = (v1+v2)/2;
|
||
document.getElementById('p18-vavg').textContent = vavg.toFixed(2);
|
||
document.getElementById('p18-trap').textContent = arith.toFixed(2);
|
||
const same = Math.abs(vavg - arith) < 0.01;
|
||
document.getElementById('p18-trap-lbl').textContent = same ? 'СОВПАЛО (t₁ = t₂)' : 'НЕВЕРНО';
|
||
document.getElementById('p18-trap-lbl').style.color = same ? '#10b981' : '#dc2626';
|
||
};
|
||
['p18-v1-r','p18-t1-r','p18-v2-r','p18-t2-r'].forEach(id => document.getElementById(id).addEventListener('input', upd18));
|
||
upd18();
|
||
|
||
wireDnd('p18-dnd', [
|
||
{ id:'a1', cat:'eq' },{ id:'a2', cat:'eq' },{ id:'a3', cat:'neq' },
|
||
{ id:'a4', cat:'neq' },{ id:'a5', cat:'neq' },{ id:'a6', cat:'eq' }
|
||
]);
|
||
wireQuiz('p18-q-host', () => { if(window.addXp) window.addXp(10, 'q-p18'); });
|
||
wireQuiz('p18-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p18'); });
|
||
wireReadBtn('p18');
|
||
renderMath(body);
|
||
}
|
||
|
||
/* ========================================================== */
|
||
/* §19 — Инерция */
|
||
/* ========================================================== */
|
||
function add_p19(){
|
||
const body = document.getElementById('p19-body');
|
||
if(!body) return;
|
||
let h = '';
|
||
|
||
h += makeCard('theory', 'Закон инерции Галилея', '§ 19.1',
|
||
'Тело сохраняет состояние <b>покоя</b> или <b>равномерного прямолинейного движения</b>, '
|
||
+ 'пока на него <b>не действуют другие тела</b> (или действия уравновешены).<br><br>'
|
||
+ 'Это явление называется <b>инерцией</b>. Оно открыто Галилеем в начале XVII века.');
|
||
|
||
h += makeCard('rule', 'Что меняет скорость', '§ 19.2',
|
||
'Чтобы изменить скорость тела (величину или направление), нужно <b>воздействие другого тела</b>:'
|
||
+ '<ul style="padding-left:20px;margin:5px 0">'
|
||
+ '<li>Толкнули — мяч полетел.</li>'
|
||
+ '<li>Поймали — мяч остановился.</li>'
|
||
+ '<li>Если на тело ничего не действует, оно <b>само собой</b> двигаться/останавливаться <b>не может</b>.</li>'
|
||
+ '</ul>'
|
||
+ 'Тело сопротивляется изменению скорости. <b>Мера этой инертности — масса</b>: тяжёлое тело сложнее разогнать и сложнее остановить.');
|
||
|
||
h += makeCard('example', 'Пассажиры в автобусе', '§ 19.3',
|
||
'<b>Автобус резко тормозит.</b> Пассажиры (которые ещё не получили воздействие от спинки сиденья) '
|
||
+ 'по инерции продолжают двигаться вперёд — поэтому их «бросает» вперёд.<br>'
|
||
+ '<b>Автобус резко трогается.</b> Пассажиры по инерции пока остаются на месте, а автобус «уезжает из-под них» — их откидывает назад.<br>'
|
||
+ 'Поэтому в транспорте важно держаться или пристёгиваться.');
|
||
|
||
/* IV-1 СИМ: шарик на гладком столе с переключателем «удар»/«трение» */
|
||
h += wgWrap('p19-iv1', 'СИМ', 'Шарик: с трением и без', 'Запусти шарик и сравни: с трением он остановится, без трения — будет двигаться вечно.',
|
||
'<div style="display:flex;gap:6px;margin-bottom:10px;flex-wrap:wrap">'
|
||
+ '<button id="p19-launch" type="button" style="background:#dc2626;color:#fff;border:none;padding:8px 16px;border-radius:9px;cursor:pointer;font-weight:700;font-family:inherit">Запустить</button>'
|
||
+ '<button id="p19-toggle" type="button" style="background:#fff;color:#dc2626;border:1.5px solid #dc2626;padding:8px 16px;border-radius:9px;cursor:pointer;font-weight:700;font-family:inherit">Трение: ВКЛ</button>'
|
||
+ '</div>'
|
||
+ '<svg id="p19-svg" viewBox="0 0 380 130" width="100%" style="max-width:600px;display:block;margin:0 auto;background:#fef2f2;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>'
|
||
+ '<div id="p19-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:10px 14px;margin-top:8px;font-size:.92rem;text-align:center"></div>');
|
||
|
||
/* IV-2 КВИЗ */
|
||
h += wgWrap('p19-iv2', 'КВИЗ', 'Инерция в жизни', '',
|
||
'<div id="p19-q-host">'
|
||
+ quizQuestion('p19-q', 0, 'Автобус резко тормозит. Куда «летят» пассажиры?', ['Вверх','Вниз','Вперёд','Назад'], 2, 'По инерции тело сохраняет движение вперёд.')
|
||
+ quizQuestion('p19-q', 1, 'Без действия других тел тело будет…', ['Останавливаться','Сохранять скорость или покой','Самопроизвольно ускоряться','Разваливаться'], 1)
|
||
+ quizQuestion('p19-q', 2, 'Что является мерой инертности тела?', ['Размер','Цвет','Масса','Объём'], 2)
|
||
+ quizQuestion('p19-q', 3, 'Кто сформулировал закон инерции?', ['Архимед','Галилей','Ньютон','Эйнштейн'], 1)
|
||
+ '</div>');
|
||
|
||
/* IV-3 DnD */
|
||
h += wgWrap('p19-iv3', 'DnD', 'Кого тяжелее остановить?', '',
|
||
dndPool('p19-dnd', [
|
||
{ id:'a1', cat:'easy', html:'Пушинка' },
|
||
{ id:'a2', cat:'easy', html:'Теннисный мячик' },
|
||
{ id:'a3', cat:'mid', html:'Велосипедист' },
|
||
{ id:'a4', cat:'mid', html:'Школьник на роликах' },
|
||
{ id:'a5', cat:'hard', html:'Грузовик с песком' },
|
||
{ id:'a6', cat:'hard', html:'Корабль' }
|
||
], [
|
||
{ cat:'easy', label:'Легко (малая масса)' },
|
||
{ cat:'mid', label:'Средне' },
|
||
{ cat:'hard', label:'Тяжело (большая масса)' }
|
||
]));
|
||
|
||
/* IV-4 ТРН */
|
||
h += wgWrap('p19-iv4', 'ТРН', 'Тренажёр §19', '',
|
||
'<div id="p19-tr-host">'
|
||
+ quizQuestion('p19-tr', 0, 'На тело не действуют другие тела. Что произойдёт?', ['Оно остановится','Оно ускорится','Оно сохранит скорость и направление','Невозможно сказать'], 2)
|
||
+ quizQuestion('p19-tr', 1, 'Почему машина после выключения мотора всё-таки тормозит?', ['Из-за инерции','Из-за силы трения о дорогу и сопротивления воздуха','Сама по себе','Из-за гравитации'], 1)
|
||
+ quizQuestion('p19-tr', 2, 'У какого тела инертность больше: у $1$ кг или $10$ кг?', ['1 кг','10 кг','Одинакова','Зависит от формы'], 1)
|
||
+ quizQuestion('p19-tr', 3, 'Зачем нужны ремни безопасности в машине?', ['Чтобы держать форму сиденья','Чтобы при резком торможении не «улететь» по инерции вперёд','Для красоты','Чтобы не сидеть прямо'], 1)
|
||
+ '</div>');
|
||
|
||
h += readButton('p19');
|
||
body.innerHTML = h;
|
||
|
||
// §19 IV-1 sim
|
||
let p19 = { x: 30, v: 0, friction: true, raf: 0 };
|
||
function draw19(){
|
||
const svg = document.getElementById('p19-svg');
|
||
if(!svg){ cancelAnimationFrame(p19.raf); return; }
|
||
if(p19.friction && p19.v > 0){
|
||
p19.v -= 0.04;
|
||
if(p19.v < 0) p19.v = 0;
|
||
}
|
||
p19.x += p19.v;
|
||
if(p19.x > 350){ p19.x = 350; p19.v = 0; }
|
||
let s = '';
|
||
s += '<rect x="0" y="0" width="380" height="100" fill="#dbeafe"/>';
|
||
s += '<rect x="0" y="100" width="380" height="30" fill="#94a3b8"/>';
|
||
if(!p19.friction){
|
||
s += '<text x="190" y="20" text-anchor="middle" font-family="Inter,sans-serif" font-size="10" font-weight="700" fill="#10b981">идеально гладкая поверхность</text>';
|
||
} else {
|
||
// Зубчатая текстура трения
|
||
for(let i = 0; i < 18; i++) s += '<line x1="' + (i*22+5) + '" y1="100" x2="' + (i*22+15) + '" y2="105" stroke="#374151" stroke-width="1"/>';
|
||
}
|
||
s += '<circle cx="' + p19.x + '" cy="92" r="10" fill="#dc2626" stroke="#7f1d1d" stroke-width="1.5"/>';
|
||
svg.innerHTML = s;
|
||
document.getElementById('p19-info').innerHTML = 'Скорость шарика: <b>' + p19.v.toFixed(2) + '</b> у. е. ' + (p19.friction ? '(с трением — тормозит)' : '(без трения — будет двигаться вечно)');
|
||
if(p19.v > 0 || !p19.friction) p19.raf = requestAnimationFrame(draw19);
|
||
}
|
||
document.getElementById('p19-launch').addEventListener('click', () => { p19.x = 30; p19.v = 3.5; if(p19.raf) cancelAnimationFrame(p19.raf); draw19(); });
|
||
document.getElementById('p19-toggle').addEventListener('click', () => {
|
||
p19.friction = !p19.friction;
|
||
const btn = document.getElementById('p19-toggle');
|
||
btn.textContent = 'Трение: ' + (p19.friction ? 'ВКЛ' : 'ВЫКЛ');
|
||
btn.style.background = p19.friction ? '#fff' : '#10b981';
|
||
btn.style.color = p19.friction ? '#dc2626' : '#fff';
|
||
btn.style.borderColor = p19.friction ? '#dc2626' : '#10b981';
|
||
if(!p19.friction && p19.v === 0){ p19.v = 1.5; if(p19.raf) cancelAnimationFrame(p19.raf); draw19(); }
|
||
});
|
||
draw19();
|
||
|
||
wireDnd('p19-dnd', [
|
||
{ id:'a1', cat:'easy' },{ id:'a2', cat:'easy' },{ id:'a3', cat:'mid' },
|
||
{ id:'a4', cat:'mid' },{ id:'a5', cat:'hard' },{ id:'a6', cat:'hard' }
|
||
]);
|
||
wireQuiz('p19-q-host', () => { if(window.addXp) window.addXp(10, 'q-p19'); });
|
||
wireQuiz('p19-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p19'); });
|
||
wireReadBtn('p19');
|
||
renderMath(body);
|
||
}
|
||
|
||
/* ========================================================== */
|
||
/* §20 — Масса тела. Плотность вещества */
|
||
/* ========================================================== */
|
||
function add_p20(){
|
||
const body = document.getElementById('p20-body');
|
||
if(!body) return;
|
||
let h = '';
|
||
|
||
h += makeCard('theory', 'Что такое масса', '§ 20.1',
|
||
'Масса $m$ — физическая величина, характеризующая <b>количество вещества</b> в теле '
|
||
+ 'и <b>инертность</b> (то, как трудно изменить скорость тела).<br><br>'
|
||
+ '$[m] = $ кг (килограмм) — основная единица СИ. Кратные: $1$ т = $1000$ кг; '
|
||
+ 'дольные: $1$ г = $0{,}001$ кг.');
|
||
|
||
h += makeCard('rule', 'Плотность вещества', '§ 20.2',
|
||
'<b>Плотность</b> $\\rho$ показывает, какая масса вещества содержится в единице объёма:<br>'
|
||
+ '$$\\rho = \\dfrac{m}{V}$$<br>'
|
||
+ '$[\\rho] = $ кг/м³. Также используют г/см³: $1$ г/см³ $= 1000$ кг/м³.<br><br>'
|
||
+ 'Из формулы $\\rho = m/V$ можно выразить и другие: $m = \\rho V$, $V = m/\\rho$.');
|
||
|
||
h += makeCard('example', 'Таблица плотностей', '§ 20.3',
|
||
'<table style="width:100%;border-collapse:collapse;margin-top:4px;font-size:.92rem">'
|
||
+ '<tr style="background:' + ACCENT_SOFT + '"><th style="padding:6px 10px;text-align:left;border-bottom:2px solid ' + ACCENT + '">Вещество</th><th style="padding:6px 10px;text-align:right;border-bottom:2px solid ' + ACCENT + '">кг/м³</th><th style="padding:6px 10px;text-align:right;border-bottom:2px solid ' + ACCENT + '">г/см³</th></tr>'
|
||
+ [['Воздух',1.29,0.00129],['Пенопласт',40,0.04],['Сосна',520,0.52],['Лёд',900,0.9],['Вода',1000,1.0],['Алюминий',2700,2.7],['Железо',7800,7.8],['Медь',8900,8.9],['Свинец',11300,11.3],['Ртуть',13600,13.6],['Золото',19300,19.3]].map(r =>
|
||
'<tr><td style="padding:5px 10px;border-bottom:1px solid ' + ACCENT_SOFT + '">' + r[0] + '</td><td style="padding:5px 10px;text-align:right;border-bottom:1px solid ' + ACCENT_SOFT + ';font-family:JetBrains Mono,monospace">' + r[1].toLocaleString('ru-RU') + '</td><td style="padding:5px 10px;text-align:right;border-bottom:1px solid ' + ACCENT_SOFT + ';font-family:JetBrains Mono,monospace">' + r[2] + '</td></tr>').join('')
|
||
+ '</table>');
|
||
|
||
/* IV-1 КАЛЬК: rho = m/V */
|
||
h += wgWrap('p20-iv1', 'КАЛЬК', 'Калькулятор $\\rho = m/V$', 'Меняй массу и объём — увидь плотность и узнай вещество.',
|
||
'<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$m$, г: <b id="p20-m" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">270</b><input type="range" id="p20-m-r" min="1" max="20000" step="1" value="270" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$V$, см³: <b id="p20-V" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">100</b><input type="range" id="p20-V-r" min="1" max="2000" step="1" value="100" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
|
||
+ '</div>'
|
||
+ '<div style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:12px 14px;font-size:.94rem;line-height:1.7">'
|
||
+ '$\\rho = m/V = $ <b id="p20-rho" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">2.70</b> г/см³ $= $ <b id="p20-rho-si" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">2700</b> кг/м³'
|
||
+ '<div id="p20-mat" style="font-size:.86rem;color:#475569;margin-top:4px"></div>'
|
||
+ '</div>');
|
||
|
||
/* IV-2 СИМ: куб 1 дм³ из разных материалов */
|
||
h += wgWrap('p20-iv2', 'СИМ', 'Куб 1 дм³: какой массы?', 'Выбери вещество — увидь массу для куба объёмом $1$ дм³ $= 1$ литр.',
|
||
'<div style="display:flex;flex-wrap:wrap;gap:6px;margin-bottom:10px">'
|
||
+ [['Пенопласт',40,'#fde68a'],['Сосна',520,'#92400e'],['Вода',1000,'#0284c7'],['Алюминий',2700,'#94a3b8'],['Железо',7800,'#374151'],['Свинец',11300,'#1f2937'],['Ртуть',13600,'#475569'],['Золото',19300,'#fbbf24']].map(([nm, rho, col]) =>
|
||
'<button class="p20-mat" data-rho="' + rho + '" data-nm="' + nm + '" data-col="' + col + '" type="button" style="background:#fff;border:1.5px solid ' + ACCENT_SOFT + ';border-radius:8px;padding:6px 12px;cursor:pointer;font-family:inherit;font-size:.85rem">' + nm + '</button>').join('')
|
||
+ '</div>'
|
||
+ '<div style="display:grid;grid-template-columns:120px 1fr;gap:14px;align-items:center">'
|
||
+ '<svg id="p20-cube" viewBox="0 0 120 120" width="120"><polygon points="20,40 60,20 100,40 100,90 60,110 20,90" fill="#0284c7" stroke="#0c4a6e" stroke-width="2"/><polyline points="20,40 60,60 100,40" fill="none" stroke="#0c4a6e" stroke-width="1.5"/><line x1="60" y1="60" x2="60" y2="110" stroke="#0c4a6e" stroke-width="1.5"/></svg>'
|
||
+ '<div style="font-size:.94rem;line-height:1.7">'
|
||
+ '<b id="p20-mat-nm" style="color:#0c4a6e">Вода</b><br>'
|
||
+ 'Объём: $V = 1$ дм³ $= 1$ л $= 1000$ см³<br>'
|
||
+ '$m = \\rho V = $ <b id="p20-mat-m" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">1</b> кг'
|
||
+ '</div>'
|
||
+ '</div>');
|
||
|
||
/* IV-3 DnD */
|
||
h += wgWrap('p20-iv3', 'DnD', 'Какое вещество?', '',
|
||
dndPool('p20-dnd', [
|
||
{ id:'a1', cat:'light', html:'$\\rho = 0{,}5$ г/см³' },
|
||
{ id:'a2', cat:'light', html:'$\\rho = 0{,}9$ г/см³' },
|
||
{ id:'a3', cat:'mid', html:'$\\rho = 2{,}7$ г/см³' },
|
||
{ id:'a4', cat:'mid', html:'$\\rho = 7{,}8$ г/см³' },
|
||
{ id:'a5', cat:'heavy', html:'$\\rho = 11{,}3$ г/см³' },
|
||
{ id:'a6', cat:'heavy', html:'$\\rho = 19{,}3$ г/см³' }
|
||
], [
|
||
{ cat:'light', label:'Лёгкий: дерево / лёд' },
|
||
{ cat:'mid', label:'Средний: алюминий / железо' },
|
||
{ cat:'heavy', label:'Тяжёлый: свинец / золото' }
|
||
]));
|
||
|
||
/* IV-4 ТРН */
|
||
h += wgWrap('p20-iv4', 'ТРН', 'Тренажёр §20', '',
|
||
'<div id="p20-tr-host">'
|
||
+ quizQuestion('p20-tr', 0, 'Брусок $m = 540$ г, $V = 200$ см³. $\\rho$?', ['2,7 г/см³','3,5 г/см³','5,4 г/см³','27 г/см³'], 0, '$\\rho = 540/200 = 2{,}7$ — алюминий.')
|
||
+ quizQuestion('p20-tr', 1, 'Какой объём занимает $7{,}8$ кг железа? ($\\rho = 7800$ кг/м³)', ['10 см³','100 см³','1000 см³','10 л'], 2, '$V = m/\\rho = 7{,}8/7800 = 0{,}001$ м³ $= 1000$ см³.')
|
||
+ quizQuestion('p20-tr', 2, 'Масса куба $V = 1$ м³ воды равна:', ['100 кг','500 кг','1000 кг','1 т'], 2, '$m = \\rho V = 1000 \\cdot 1 = 1000$ кг $= 1$ т. Оба ответа верны, но «1000 кг» — самый точный.')
|
||
+ quizQuestion('p20-tr', 3, '$\\rho = 13{,}6$ г/см³. Какое это вещество?', ['Железо','Свинец','Ртуть','Золото'], 2)
|
||
+ quizQuestion('p20-tr', 4, 'Из бруска $\\rho_1 = 1000$ кг/м³ и $\\rho_2 = 2000$ кг/м³ при одинаковом объёме легче будет:', ['Первый','Второй','Одинаково','Зависит от формы'], 0, 'При $V = $ const, $m \\sim \\rho$. Меньшая плотность → меньшая масса.')
|
||
+ '</div>');
|
||
|
||
h += readButton('p20');
|
||
body.innerHTML = h;
|
||
|
||
// §20 IV-1
|
||
const matName = (rho) => {
|
||
if(rho < 0.2) return 'газ / лёгкий пористый материал';
|
||
if(rho < 0.6) return 'пенопласт / лёгкое дерево';
|
||
if(rho < 0.95) return 'дерево / лёд';
|
||
if(rho < 1.1) return 'вода';
|
||
if(rho < 3) return 'алюминий / стекло';
|
||
if(rho < 9) return 'железо / медь';
|
||
if(rho < 14) return 'свинец / ртуть';
|
||
if(rho < 22) return 'золото / платина';
|
||
return 'плотнее любого металла на Земле';
|
||
};
|
||
const upd20 = () => {
|
||
const m = +document.getElementById('p20-m-r').value;
|
||
const V = +document.getElementById('p20-V-r').value;
|
||
document.getElementById('p20-m').textContent = m;
|
||
document.getElementById('p20-V').textContent = V;
|
||
const rho = m / V;
|
||
document.getElementById('p20-rho').textContent = rho.toFixed(2);
|
||
document.getElementById('p20-rho-si').textContent = (rho * 1000).toFixed(0);
|
||
document.getElementById('p20-mat').textContent = 'Похоже на: ' + matName(rho);
|
||
};
|
||
['p20-m-r','p20-V-r'].forEach(id => document.getElementById(id).addEventListener('input', upd20));
|
||
upd20();
|
||
|
||
// §20 IV-2 cube
|
||
body.querySelectorAll('.p20-mat').forEach(btn => btn.addEventListener('click', () => {
|
||
body.querySelectorAll('.p20-mat').forEach(b => { b.style.background = '#fff'; b.style.color = '#0f172a'; });
|
||
btn.style.background = btn.dataset.col; btn.style.color = '#fff';
|
||
const rho = +btn.dataset.rho; // кг/м³
|
||
const m = rho * 0.001; // V = 1 дм³ = 0.001 м³
|
||
document.getElementById('p20-mat-nm').textContent = btn.dataset.nm;
|
||
document.getElementById('p20-mat-m').textContent = m.toFixed(2);
|
||
document.getElementById('p20-cube').querySelector('polygon').setAttribute('fill', btn.dataset.col);
|
||
}));
|
||
// Default selected — water
|
||
const waterBtn = body.querySelector('.p20-mat[data-nm="Вода"]');
|
||
if(waterBtn){ waterBtn.style.background = waterBtn.dataset.col; waterBtn.style.color = '#fff'; }
|
||
|
||
wireDnd('p20-dnd', [
|
||
{ id:'a1', cat:'light' },{ id:'a2', cat:'light' },{ id:'a3', cat:'mid' },
|
||
{ id:'a4', cat:'mid' },{ id:'a5', cat:'heavy' },{ id:'a6', cat:'heavy' }
|
||
]);
|
||
wireQuiz('p20-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p20'); });
|
||
wireReadBtn('p20');
|
||
renderMath(body);
|
||
}
|
||
|
||
/* ========================================================== */
|
||
/* §21 — Сила */
|
||
/* ========================================================== */
|
||
function add_p21(){
|
||
const body = document.getElementById('p21-body');
|
||
if(!body) return;
|
||
let h = '';
|
||
|
||
h += makeCard('theory', 'Что такое сила', '§ 21.1',
|
||
'<b>Сила</b> $\\vec F$ — физическая величина, которая характеризует <b>взаимодействие</b> двух тел. '
|
||
+ 'Сила всегда возникает в паре: одно тело действует на другое.<br><br>'
|
||
+ '$[F] = $ Н (ньютон) — в честь Исаака Ньютона.');
|
||
|
||
h += makeCard('rule', 'Что значит «изобразить силу»', '§ 21.2',
|
||
'У силы три характеристики (поэтому её рисуют <b>стрелкой</b> — вектором):'
|
||
+ '<ul style="padding-left:20px;margin:6px 0">'
|
||
+ '<li><b>Модуль</b> (длина стрелки) — численное значение в ньютонах.</li>'
|
||
+ '<li><b>Направление</b> — куда направлена стрелка.</li>'
|
||
+ '<li><b>Точка приложения</b> — где начало стрелки (где сила «приложена» к телу).</li>'
|
||
+ '</ul>');
|
||
|
||
h += makeCard('example', 'Четыре силы из жизни', '§ 21.3',
|
||
'<table style="width:100%;border-collapse:collapse;margin-top:4px;font-size:.92rem">'
|
||
+ '<tr style="background:' + ACCENT_SOFT + '"><th style="padding:6px 10px;text-align:left;border-bottom:2px solid ' + ACCENT + '">Сила</th><th style="padding:6px 10px;text-align:left;border-bottom:2px solid ' + ACCENT + '">Когда возникает</th></tr>'
|
||
+ [
|
||
['<b>$\\vec F_т$</b> — сила тяжести', 'Земля притягивает тело'],
|
||
['<b>$\\vec F_{упр}$</b> — упругости', 'Тело деформировано (сжато, растянуто)'],
|
||
['<b>$\\vec F_{тр}$</b> — трения', 'Тело движется (или пытается) по другому'],
|
||
['<b>$\\vec N$</b> — нормальная реакция', 'Тело давит на опору; опора отвечает']
|
||
].map(r => '<tr><td style="padding:5px 10px;border-bottom:1px solid ' + ACCENT_SOFT + '">' + r[0] + '</td><td style="padding:5px 10px;border-bottom:1px solid ' + ACCENT_SOFT + '">' + r[1] + '</td></tr>').join('')
|
||
+ '</table>');
|
||
|
||
/* IV-1 СИМ: визуал силы со стрелкой */
|
||
h += wgWrap('p21-iv1', 'СИМ', 'Сила-стрелка', 'Меняй модуль и направление — посмотри, как меняется стрелка.',
|
||
'<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Модуль $F$, Н: <b id="p21-F" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">10</b><input type="range" id="p21-F-r" min="1" max="50" step="1" value="10" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Угол, °: <b id="p21-ang" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">0</b><input type="range" id="p21-ang-r" min="0" max="360" step="15" value="0" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
|
||
+ '</div>'
|
||
+ '<svg id="p21-svg" viewBox="0 0 300 220" width="100%" style="max-width:400px;display:block;margin:0 auto;background:#fef2f2;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>');
|
||
|
||
/* IV-2 КВИЗ */
|
||
h += wgWrap('p21-iv2', 'КВИЗ', 'Что такое сила', '',
|
||
'<div id="p21-q-host">'
|
||
+ quizQuestion('p21-q', 0, 'В каких единицах измеряют силу?', ['Килограммы','Метры','Ньютоны','Джоули'], 2)
|
||
+ quizQuestion('p21-q', 1, 'Сила — это…', ['Скалярная величина','Векторная величина','Время','Длина'], 1)
|
||
+ quizQuestion('p21-q', 2, 'Что НЕ относится к характеристикам силы?', ['Модуль','Направление','Точка приложения','Цвет'], 3)
|
||
+ quizQuestion('p21-q', 3, 'Что произойдёт с покоящимся телом, если на него действует одна сила?', ['Ничего','Тело изменит скорость','Тело пропадёт','Не меняется'], 1, 'Если силы не уравновешены — тело меняет скорость.')
|
||
+ '</div>');
|
||
|
||
/* IV-3 DnD */
|
||
h += wgWrap('p21-iv3', 'DnD', 'Какая сила?', '',
|
||
dndPool('p21-dnd', [
|
||
{ id:'a1', cat:'grav', html:'Яблоко падает с дерева' },
|
||
{ id:'a2', cat:'grav', html:'Снежинки летят на землю' },
|
||
{ id:'a3', cat:'el', html:'Сжатая пружина возвращается' },
|
||
{ id:'a4', cat:'el', html:'Растянутая резинка' },
|
||
{ id:'a5', cat:'fr', html:'Машина тормозит' },
|
||
{ id:'a6', cat:'fr', html:'Книга по столу не скользит' },
|
||
{ id:'a7', cat:'norm', html:'Стол держит лежащую книгу' },
|
||
{ id:'a8', cat:'norm', html:'Пол не пускает человека провалиться' }
|
||
], [
|
||
{ cat:'grav', label:'$\\vec F_т$ (тяжести)' },
|
||
{ cat:'el', label:'$\\vec F_{упр}$ (упругости)' },
|
||
{ cat:'fr', label:'$\\vec F_{тр}$ (трения)' },
|
||
{ cat:'norm', label:'$\\vec N$ (нормальная реакция)' }
|
||
]));
|
||
|
||
/* IV-4 ТРН */
|
||
h += wgWrap('p21-iv4', 'ТРН', 'Тренажёр §21', '',
|
||
'<div id="p21-tr-host">'
|
||
+ quizQuestion('p21-tr', 0, 'Силу обозначают…', ['$s$','$v$','$F$','$t$'], 2)
|
||
+ quizQuestion('p21-tr', 1, 'Сила — мера…', ['Длины','Времени','Взаимодействия тел','Объёма'], 2)
|
||
+ quizQuestion('p21-tr', 2, 'В каких единицах СИ выражают силу?', ['Кг','Н (ньютоны)','Дж','м/с²'], 1)
|
||
+ quizQuestion('p21-tr', 3, 'Что нужно для того, чтобы изобразить силу?', ['Только число','Только направление','Стрелка с заданной длиной, направлением и точкой приложения','Только подпись'], 2)
|
||
+ '</div>');
|
||
|
||
h += readButton('p21');
|
||
body.innerHTML = h;
|
||
|
||
function draw21(){
|
||
const F = +document.getElementById('p21-F-r').value;
|
||
const ang = +document.getElementById('p21-ang-r').value;
|
||
document.getElementById('p21-F').textContent = F;
|
||
document.getElementById('p21-ang').textContent = ang;
|
||
const cx = 150, cy = 110;
|
||
const len = F * 2.5;
|
||
const a = -ang * Math.PI / 180;
|
||
const x2 = cx + len * Math.cos(a);
|
||
const y2 = cy + len * Math.sin(a);
|
||
let s = '';
|
||
// Тело — кружок
|
||
s += '<circle cx="' + cx + '" cy="' + cy + '" r="14" fill="#dc2626" stroke="#7f1d1d" stroke-width="1.5"/>';
|
||
// Стрелка силы
|
||
s += '<line x1="' + cx + '" y1="' + cy + '" x2="' + x2.toFixed(1) + '" y2="' + y2.toFixed(1) + '" stroke="#0c4a6e" stroke-width="3"/>';
|
||
// Наконечник
|
||
const ah = 10;
|
||
const ax1 = x2 - ah * Math.cos(a - 0.4);
|
||
const ay1 = y2 - ah * Math.sin(a - 0.4);
|
||
const ax2 = x2 - ah * Math.cos(a + 0.4);
|
||
const ay2 = y2 - ah * Math.sin(a + 0.4);
|
||
s += '<polygon points="' + x2.toFixed(1) + ',' + y2.toFixed(1) + ' ' + ax1.toFixed(1) + ',' + ay1.toFixed(1) + ' ' + ax2.toFixed(1) + ',' + ay2.toFixed(1) + '" fill="#0c4a6e"/>';
|
||
// Подпись
|
||
s += '<text x="' + (x2 + 8 * Math.cos(a)) + '" y="' + (y2 + 8 * Math.sin(a) + 5) + '" font-family="Inter,sans-serif" font-size="13" font-weight="700" fill="#0c4a6e">F = ' + F + ' Н</text>';
|
||
document.getElementById('p21-svg').innerHTML = s;
|
||
}
|
||
['p21-F-r','p21-ang-r'].forEach(id => document.getElementById(id).addEventListener('input', draw21));
|
||
draw21();
|
||
|
||
wireDnd('p21-dnd', [
|
||
{ id:'a1', cat:'grav' },{ id:'a2', cat:'grav' },{ id:'a3', cat:'el' },{ id:'a4', cat:'el' },
|
||
{ id:'a5', cat:'fr' },{ id:'a6', cat:'fr' },{ id:'a7', cat:'norm' },{ id:'a8', cat:'norm' }
|
||
]);
|
||
wireQuiz('p21-q-host', () => { if(window.addXp) window.addXp(10, 'q-p21'); });
|
||
wireQuiz('p21-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p21'); });
|
||
wireReadBtn('p21');
|
||
renderMath(body);
|
||
}
|
||
|
||
/* ========================================================== */
|
||
/* §22 — Сила тяжести */
|
||
/* ========================================================== */
|
||
function add_p22(){
|
||
const body = document.getElementById('p22-body');
|
||
if(!body) return;
|
||
let h = '';
|
||
|
||
h += makeCard('theory', 'Притяжение к Земле', '§ 22.1',
|
||
'Земля притягивает все тела возле своей поверхности. Сила, с которой Земля действует на тело, '
|
||
+ 'называется <b>силой тяжести</b> $\\vec F_т$. Она направлена <b>вертикально вниз</b> '
|
||
+ '(точнее — к центру Земли).');
|
||
|
||
h += makeCard('rule', 'Формула силы тяжести', '§ 22.2',
|
||
'$$F_т = m g$$<br>'
|
||
+ 'где $m$ — масса тела (кг), $g$ — ускорение свободного падения.<br><br>'
|
||
+ '<b>На Земле:</b> $g = 9{,}8$ Н/кг (часто округляют до $g \\approx 10$ Н/кг).<br>'
|
||
+ '<b>На Луне:</b> $g_Л \\approx 1{,}6$ Н/кг (в 6 раз меньше).<br>'
|
||
+ '<b>На Марсе:</b> $g_М \\approx 3{,}7$ Н/кг.<br>'
|
||
+ '<b>На Юпитере:</b> $g_Ю \\approx 24{,}8$ Н/кг.');
|
||
|
||
h += makeCard('example', 'Сколько весит яблоко?', '§ 22.3',
|
||
'Масса среднего яблока $m = 100$ г $= 0{,}1$ кг. На Земле:<br>'
|
||
+ '$F_т = mg = 0{,}1 \\cdot 9{,}8 \\approx 1$ Н.<br><br>'
|
||
+ 'Поэтому 1 ньютон — это «сила, с которой Земля притягивает 100 г».');
|
||
|
||
/* IV-1 КАЛЬК: F_т = mg, выбор планеты */
|
||
h += wgWrap('p22-iv1', 'КАЛЬК', 'Сила тяжести на разных планетах', 'Выбери планету и тело — узнай, как меняется $F_т$.',
|
||
'<div style="display:flex;gap:6px;margin-bottom:10px;flex-wrap:wrap">'
|
||
+ [['earth','Земля',9.8],['moon','Луна',1.6],['mars','Марс',3.7],['jupiter','Юпитер',24.8]].map((p, i) =>
|
||
'<button class="p22-pl" data-g="' + p[2] + '" data-nm="' + p[1] + '" type="button" style="background:' + (i===0 ? '#dc2626' : '#fff') + ';color:' + (i===0 ? '#fff' : '#dc2626') + ';border:2px solid #dc2626;padding:8px 14px;border-radius:9px;cursor:pointer;font-weight:700;font-family:inherit;font-size:.86rem">' + p[1] + '</button>').join('')
|
||
+ '</div>'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + ';margin-bottom:10px">Масса $m$, кг: <b id="p22-m" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">0.1</b><input type="range" id="p22-m-r" min="1" max="1000" step="1" value="100" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
|
||
+ '<div style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:12px 14px;font-size:.94rem;line-height:1.7">'
|
||
+ '$F_т = m g = $ <b id="p22-Ft" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">0.98</b> Н (на <span id="p22-pl-nm" style="font-weight:700">Земле</span>, $g = $ <span id="p22-g-val" style="font-family:JetBrains Mono,monospace;font-weight:700">9.8</span> Н/кг)'
|
||
+ '</div>');
|
||
|
||
/* IV-2 КВИЗ */
|
||
h += wgWrap('p22-iv2', 'КВИЗ', 'Сила тяжести', '',
|
||
'<div id="p22-q-host">'
|
||
+ quizQuestion('p22-q', 0, 'Куда направлена сила тяжести на поверхности Земли?', ['Вверх','Вертикально вниз (к центру Земли)','В сторону Солнца','В произвольном направлении'], 1)
|
||
+ quizQuestion('p22-q', 1, '$g$ на Земле примерно равно…', ['1 Н/кг','9,8 Н/кг','100 Н/кг','1000 Н/кг'], 1)
|
||
+ quizQuestion('p22-q', 2, 'На Луне $g_Л$ примерно в 6 раз меньше земного. Что произойдёт с $F_т$ камня?', ['Не изменится','Увеличится в 6 раз','Уменьшится в 6 раз','Станет нулевой'], 2)
|
||
+ quizQuestion('p22-q', 3, 'Масса остаётся постоянной на Земле и Луне, а сила тяжести?', ['Тоже постоянна','Уменьшается на Луне','Увеличивается на Луне','Зависит от формы тела'], 1, 'Масса = «количество вещества», она не меняется. А $F_т = mg$ меняется через $g$.')
|
||
+ '</div>');
|
||
|
||
/* IV-3 DnD */
|
||
h += wgWrap('p22-iv3', 'DnD', 'Сопоставь массу и силу тяжести (на Земле)', '',
|
||
dndPool('p22-dnd', [
|
||
{ id:'a1', cat:'1n', html:'$m = 100$ г' },
|
||
{ id:'a2', cat:'10n', html:'$m = 1$ кг' },
|
||
{ id:'a3', cat:'100n', html:'$m = 10$ кг' },
|
||
{ id:'a4', cat:'1n', html:'$m = 0{,}1$ кг' },
|
||
{ id:'a5', cat:'10n', html:'$m = 1000$ г' },
|
||
{ id:'a6', cat:'100n', html:'$m = 10\\,000$ г' }
|
||
], [
|
||
{ cat:'1n', label:'$F_т \\approx 1$ Н' },
|
||
{ cat:'10n', label:'$F_т \\approx 10$ Н' },
|
||
{ cat:'100n', label:'$F_т \\approx 100$ Н' }
|
||
]));
|
||
|
||
/* IV-4 ТРН */
|
||
h += wgWrap('p22-iv4', 'ТРН', 'Тренажёр §22', '',
|
||
'<div id="p22-tr-host">'
|
||
+ quizQuestion('p22-tr', 0, '$m = 5$ кг. $F_т$ на Земле ($g = 10$ Н/кг)?', ['5 Н','15 Н','50 Н','500 Н'], 2, '$F_т = mg = 5 \\cdot 10 = 50$ Н.')
|
||
+ quizQuestion('p22-tr', 1, '$m = 200$ г. $F_т$ на Земле ($g = 9{,}8$ Н/кг) ≈?', ['0,98 Н','1,96 Н','19,6 Н','2 Н'], 1, '$F_т = 0{,}2 \\cdot 9{,}8 = 1{,}96$ Н.')
|
||
+ quizQuestion('p22-tr', 2, 'Космонавт $m = 80$ кг. $F_т$ на Луне ($g_Л = 1{,}6$ Н/кг)?', ['80 Н','128 Н','480 Н','800 Н'], 1, '$F_т = 80 \\cdot 1{,}6 = 128$ Н.')
|
||
+ quizQuestion('p22-tr', 3, 'Где $F_т$ одной и той же массы больше: на Юпитере или Луне?', ['На Луне','На Юпитере','Одинаково','Зависит от вещества'], 1, 'У Юпитера $g$ намного больше.')
|
||
+ quizQuestion('p22-tr', 4, 'Чтобы $F_т$ на Земле была $30$ Н, нужна масса…', ['1 кг','2 кг','3 кг','30 кг'], 2, 'При $g \\approx 10$ Н/кг: $m = F_т/g = 30/10 = 3$ кг.')
|
||
+ '</div>');
|
||
|
||
h += readButton('p22');
|
||
body.innerHTML = h;
|
||
|
||
let g22 = 9.8;
|
||
let plName = 'Земле';
|
||
function upd22(){
|
||
const m = +document.getElementById('p22-m-r').value / 1000; // ползунок в граммах
|
||
document.getElementById('p22-m').textContent = (m).toFixed(2);
|
||
const Ft = m * g22;
|
||
document.getElementById('p22-Ft').textContent = Ft.toFixed(2);
|
||
document.getElementById('p22-pl-nm').textContent = plName;
|
||
document.getElementById('p22-g-val').textContent = g22.toString().replace('.', ',');
|
||
}
|
||
body.querySelectorAll('.p22-pl').forEach(btn => btn.addEventListener('click', () => {
|
||
body.querySelectorAll('.p22-pl').forEach(b => { b.style.background = '#fff'; b.style.color = '#dc2626'; });
|
||
btn.style.background = '#dc2626'; btn.style.color = '#fff';
|
||
g22 = +btn.dataset.g;
|
||
plName = btn.dataset.nm;
|
||
upd22();
|
||
}));
|
||
document.getElementById('p22-m-r').addEventListener('input', upd22);
|
||
upd22();
|
||
|
||
wireDnd('p22-dnd', [
|
||
{ id:'a1', cat:'1n' },{ id:'a2', cat:'10n' },{ id:'a3', cat:'100n' },
|
||
{ id:'a4', cat:'1n' },{ id:'a5', cat:'10n' },{ id:'a6', cat:'100n' }
|
||
]);
|
||
wireQuiz('p22-q-host', () => { if(window.addXp) window.addXp(10, 'q-p22'); });
|
||
wireQuiz('p22-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p22'); });
|
||
wireReadBtn('p22');
|
||
renderMath(body);
|
||
}
|
||
|
||
/* ========================================================== */
|
||
/* §23 — Сила упругости */
|
||
/* ========================================================== */
|
||
function add_p23(){
|
||
const body = document.getElementById('p23-body');
|
||
if(!body) return;
|
||
let h = '';
|
||
|
||
h += makeCard('theory', 'Когда возникает упругая сила', '§ 23.1',
|
||
'Если тело <b>деформировано</b> (сжато, растянуто, изогнуто), внутри него возникает '
|
||
+ '<b>сила упругости</b> $\\vec F_{упр}$, которая <b>стремится вернуть тело в исходную форму</b>.<br><br>'
|
||
+ 'Природа этой силы — взаимодействие молекул, изученное в §10.');
|
||
|
||
h += makeCard('rule', 'Закон Гука (качественно)', '§ 23.2',
|
||
'$$F_{упр} \\sim \\Delta l$$<br>'
|
||
+ 'Сила упругости <b>пропорциональна удлинению</b> $\\Delta l$. '
|
||
+ 'То есть в 2 раза больше растянули → в 2 раза больше сила.<br><br>'
|
||
+ '<b>Внимание:</b> закон работает только пока деформация мала. Если перерастянуть пружину — '
|
||
+ 'она <b>не вернётся</b> в исходное положение (пластическая деформация).');
|
||
|
||
h += makeCard('example', 'Где встречается', '§ 23.3',
|
||
'<ul style="padding-left:20px;margin:6px 0">'
|
||
+ '<li><b>Пружина</b> матраса, ручки, амортизатора.</li>'
|
||
+ '<li><b>Резинка</b> для волос, рогатка.</li>'
|
||
+ '<li><b>Лук</b>: тетива растянута → возвращает стрелу.</li>'
|
||
+ '<li><b>Опора</b> прогибается под весом и отвечает реакцией $\\vec N$ — это тоже упругая сила.</li>'
|
||
+ '</ul>');
|
||
|
||
/* IV-1 СИМ: пружина с slider */
|
||
h += wgWrap('p23-iv1', 'СИМ', 'Пружина: растяжение и сила', 'Меняй удлинение — увидь, как растёт сила упругости.',
|
||
'<div style="margin-bottom:10px"><label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Удлинение $\\Delta l$, см: <b id="p23-dl" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">5</b><input type="range" id="p23-dl-r" min="0" max="20" step="1" value="5" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label></div>'
|
||
+ '<svg id="p23-svg" viewBox="0 0 380 160" width="100%" style="max-width:600px;display:block;margin:0 auto;background:#fef2f2;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>'
|
||
+ '<div id="p23-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:10px 14px;margin-top:8px;font-size:.94rem;text-align:center"></div>');
|
||
|
||
/* IV-2 КВИЗ */
|
||
h += wgWrap('p23-iv2', 'КВИЗ', 'Упругость', '',
|
||
'<div id="p23-q-host">'
|
||
+ quizQuestion('p23-q', 0, 'Когда возникает сила упругости?', ['Всегда','Только в жидкостях','При деформации тела','При движении'], 2)
|
||
+ quizQuestion('p23-q', 1, 'Куда направлена $\\vec F_{упр}$?', ['В сторону деформации','Против деформации (возвращает в исходное)','Вертикально вниз','Зависит от тела'], 1)
|
||
+ quizQuestion('p23-q', 2, 'Если растянуть пружину в 3 раза сильнее, $F_{упр}$ изменится…', ['Не изменится','Увеличится в 3 раза','Уменьшится в 3 раза','Увеличится в 9 раз'], 1, 'Это закон Гука: $F \\sim \\Delta l$.')
|
||
+ '</div>');
|
||
|
||
/* IV-3 DnD */
|
||
h += wgWrap('p23-iv3', 'DnD', 'Деформация или нет?', '',
|
||
dndPool('p23-dnd', [
|
||
{ id:'a1', cat:'def', html:'Сжатая пружина матраса' },
|
||
{ id:'a2', cat:'def', html:'Растянутая резинка' },
|
||
{ id:'a3', cat:'def', html:'Прогнутая доска под весом' },
|
||
{ id:'a4', cat:'def', html:'Натянутая тетива лука' },
|
||
{ id:'a5', cat:'no', html:'Лежащий камень (нет видимой деформации)' },
|
||
{ id:'a6', cat:'no', html:'Висящая на крючке шапка' }
|
||
], [
|
||
{ cat:'def', label:'Есть деформация → есть $F_{упр}$' },
|
||
{ cat:'no', label:'Нет видимой деформации' }
|
||
]));
|
||
|
||
/* IV-4 ТРН */
|
||
h += wgWrap('p23-iv4', 'ТРН', 'Тренажёр §23', '',
|
||
'<div id="p23-tr-host">'
|
||
+ quizQuestion('p23-tr', 0, 'Природа силы упругости — это…', ['Гравитация','Взаимодействие молекул','Магнетизм','Электричество'], 1)
|
||
+ quizQuestion('p23-tr', 1, 'Если пружину растянуть слишком сильно, она…', ['Останется упругой','Может остаться растянутой (пластическая деформация)','Станет тяжелее','Не изменится'], 1)
|
||
+ quizQuestion('p23-tr', 2, 'Что является примером упругой деформации?', ['Растяжение пружины и возврат','Лепка из пластилина','Раскалывание камня','Резка хлеба'], 0)
|
||
+ quizQuestion('p23-tr', 3, 'Какая из сил из жизни — упругая?', ['Сила тяжести','Сила трения','Реакция опоры $\\vec N$','Лунное притяжение'], 2, 'Опора прогибается и «отвечает» упругой силой.')
|
||
+ '</div>');
|
||
|
||
h += readButton('p23');
|
||
body.innerHTML = h;
|
||
|
||
function draw23(){
|
||
const dl = +document.getElementById('p23-dl-r').value;
|
||
document.getElementById('p23-dl').textContent = dl;
|
||
const F = dl * 2; // условный коэф. жёсткости 2 Н/см
|
||
const W = 380, H = 160;
|
||
const topY = 20, hookX = 80;
|
||
const naturalLen = 60;
|
||
const totalLen = naturalLen + dl * 3.5; // визуально усилено
|
||
let s = '';
|
||
// Потолок
|
||
s += '<rect x="20" y="10" width="120" height="10" fill="#475569" stroke="#0f172a" stroke-width="1"/>';
|
||
for(let i = 0; i < 6; i++) s += '<line x1="' + (20 + i*20) + '" y1="20" x2="' + (10 + i*20) + '" y2="30" stroke="#0f172a" stroke-width="0.8"/>';
|
||
// Подвес
|
||
s += '<line x1="' + hookX + '" y1="20" x2="' + hookX + '" y2="' + topY + '" stroke="#374151" stroke-width="1.5"/>';
|
||
// Пружина (зигзаг)
|
||
const coils = 8;
|
||
let path = 'M ' + hookX + ' ' + topY;
|
||
for(let i = 0; i < coils; i++){
|
||
const y = topY + (i + 0.5) * (totalLen / coils);
|
||
path += ' L ' + (hookX + (i%2 ? 18 : -18)) + ' ' + y;
|
||
}
|
||
path += ' L ' + hookX + ' ' + (topY + totalLen);
|
||
s += '<path d="' + path + '" fill="none" stroke="#dc2626" stroke-width="2.5"/>';
|
||
// Груз
|
||
s += '<rect x="' + (hookX - 22) + '" y="' + (topY + totalLen) + '" width="44" height="28" fill="#7c3aed" stroke="#5b21b6" stroke-width="1.5" rx="3"/>';
|
||
s += '<text x="' + hookX + '" y="' + (topY + totalLen + 19) + '" text-anchor="middle" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="#fff">груз</text>';
|
||
// Стрелка F_упр (вверх) и F_т (вниз) если dl>0
|
||
if(dl > 0){
|
||
const arrY = topY + totalLen + 50;
|
||
// F_упр вверх
|
||
s += '<line x1="200" y1="' + arrY + '" x2="200" y2="' + (arrY - 35) + '" stroke="#10b981" stroke-width="2.5"/>';
|
||
s += '<polygon points="200,' + (arrY - 35) + ' 195,' + (arrY - 28) + ' 205,' + (arrY - 28) + '" fill="#10b981"/>';
|
||
s += '<text x="210" y="' + (arrY - 28) + '" font-family="Inter,sans-serif" font-size="12" font-weight="700" fill="#10b981">F_упр = ' + F + ' Н ↑</text>';
|
||
// F_т вниз
|
||
s += '<line x1="260" y1="' + arrY + '" x2="260" y2="' + (arrY + 30) + '" stroke="#7c3aed" stroke-width="2.5"/>';
|
||
s += '<polygon points="260,' + (arrY + 30) + ' 255,' + (arrY + 23) + ' 265,' + (arrY + 23) + '" fill="#7c3aed"/>';
|
||
s += '<text x="270" y="' + (arrY + 25) + '" font-family="Inter,sans-serif" font-size="12" font-weight="700" fill="#7c3aed">F_т ↓</text>';
|
||
}
|
||
document.getElementById('p23-svg').innerHTML = s;
|
||
document.getElementById('p23-info').innerHTML = 'Удлинение $\\Delta l = ' + dl + '$ см · $F_{упр} \\approx $ <b>' + F + '</b> Н (при коэф. жёсткости $k = 2$ Н/см)';
|
||
renderMath(document.getElementById('p23-info'));
|
||
}
|
||
document.getElementById('p23-dl-r').addEventListener('input', draw23);
|
||
draw23();
|
||
|
||
wireDnd('p23-dnd', [
|
||
{ id:'a1', cat:'def' },{ id:'a2', cat:'def' },{ id:'a3', cat:'def' },
|
||
{ id:'a4', cat:'def' },{ id:'a5', cat:'no' },{ id:'a6', cat:'no' }
|
||
]);
|
||
wireQuiz('p23-q-host', () => { if(window.addXp) window.addXp(10, 'q-p23'); });
|
||
wireQuiz('p23-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p23'); });
|
||
wireReadBtn('p23');
|
||
renderMath(body);
|
||
}
|
||
|
||
/* ========================================================== */
|
||
/* §24 — Вес тела */
|
||
/* ========================================================== */
|
||
function add_p24(){
|
||
const body = document.getElementById('p24-body');
|
||
if(!body) return;
|
||
let h = '';
|
||
|
||
h += makeCard('theory', 'Что такое вес', '§ 24.1',
|
||
'<b>Вес</b> $\\vec P$ — это сила, с которой тело <b>давит на опору</b> (или растягивает подвес) '
|
||
+ 'вследствие притяжения к Земле.<br><br>'
|
||
+ 'Это <b>не</b> то же самое, что сила тяжести! Хоть на покоящемся теле они равны по модулю, '
|
||
+ 'они приложены к <b>разным телам</b>:'
|
||
+ '<ul style="padding-left:20px;margin:5px 0">'
|
||
+ '<li>$\\vec F_т$ — действует на <b>само тело</b> от Земли;</li>'
|
||
+ '<li>$\\vec P$ — действует на <b>опору или подвес</b> от тела.</li>'
|
||
+ '</ul>');
|
||
|
||
h += makeCard('rule', 'Когда $P = F_т$, а когда нет', '§ 24.2',
|
||
'<b>Покоится</b> на горизонтальной опоре или висит на нити: $P = F_т = mg$.<br><br>'
|
||
+ '<b>Невесомость</b> (свободное падение): $P = 0$ — тело не давит на опору. '
|
||
+ 'Космонавт на МКС в невесомости — у него масса есть, $F_т$ от Земли тоже есть, '
|
||
+ 'а вот вес $P = 0$, потому что станция падает на Землю вместе с ним.<br><br>'
|
||
+ '<b>Перегрузка</b>: в ускоряющемся лифте вверх вес <b>больше</b> $mg$. В лифте вниз — <b>меньше</b>.');
|
||
|
||
h += makeCard('example', 'Как взвешивают тело', '§ 24.3',
|
||
'На <b>чашечных весах</b> сравнивают вес тела и вес гирь. '
|
||
+ 'Когда чашечки уравновешены — массы равны (поскольку $g$ одинаков, и $P = mg$).<br><br>'
|
||
+ 'На <b>пружинных весах (динамометре)</b> измеряют силу, с которой тело растягивает пружину. '
|
||
+ 'Это и есть вес тела в Ньютонах.');
|
||
|
||
/* IV-1 СИМ: тело в 3 ситуациях */
|
||
h += wgWrap('p24-iv1', 'СИМ', 'Три ситуации: покой, падение, ускорение', 'Выбери ситуацию — увидь стрелки сил.',
|
||
'<div style="display:flex;gap:6px;margin-bottom:10px;flex-wrap:wrap">'
|
||
+ [['rest','На столе (покой)'],['fall','Свободное падение'],['up','Ускоряется вверх'],['down','Ускоряется вниз']].map((s, i) =>
|
||
'<button class="p24-sit" data-s="' + s[0] + '" type="button" style="background:' + (i===0 ? '#dc2626' : '#fff') + ';color:' + (i===0 ? '#fff' : '#dc2626') + ';border:2px solid #dc2626;padding:7px 12px;border-radius:9px;cursor:pointer;font-weight:700;font-family:inherit;font-size:.84rem">' + s[1] + '</button>').join('')
|
||
+ '</div>'
|
||
+ '<svg id="p24-svg" viewBox="0 0 360 200" width="100%" style="max-width:500px;display:block;margin:0 auto;background:#fef2f2;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>'
|
||
+ '<div id="p24-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:10px 14px;margin-top:8px;font-size:.92rem;line-height:1.6"></div>');
|
||
|
||
/* IV-2 КВИЗ */
|
||
h += wgWrap('p24-iv2', 'КВИЗ', 'Вес vs сила тяжести', '',
|
||
'<div id="p24-q-host">'
|
||
+ quizQuestion('p24-q', 0, 'К чему приложена сила тяжести $\\vec F_т$?', ['К опоре','К самому телу','К центру Земли','К воздуху'], 1)
|
||
+ quizQuestion('p24-q', 1, 'К чему приложен вес $\\vec P$?', ['К телу','К опоре или подвесу','К атмосфере','К центру Земли'], 1)
|
||
+ quizQuestion('p24-q', 2, 'Космонавт в МКС находится в…', ['Состоянии покоя','Невесомости (P = 0)','Перегрузке','Постоянной силе'], 1)
|
||
+ quizQuestion('p24-q', 3, 'Тело $m = 2$ кг лежит на столе. Чему равен вес? ($g = 10$ Н/кг)', ['2 Н','10 Н','20 Н','200 Н'], 2, '$P = mg = 2 \\cdot 10 = 20$ Н.')
|
||
+ '</div>');
|
||
|
||
/* IV-3 DnD */
|
||
h += wgWrap('p24-iv3', 'DnD', 'Какая сила куда приложена?', '',
|
||
dndPool('p24-dnd', [
|
||
{ id:'a1', cat:'ft', html:'Земля тянет яблоко вниз' },
|
||
{ id:'a2', cat:'ft', html:'Земля тянет космонавта на орбите' },
|
||
{ id:'a3', cat:'p', html:'Книга давит на стол' },
|
||
{ id:'a4', cat:'p', html:'Гирька растягивает пружину' },
|
||
{ id:'a5', cat:'zero', html:'Космонавт в невесомости (P = 0)' },
|
||
{ id:'a6', cat:'zero', html:'Шарик в свободном падении' }
|
||
], [
|
||
{ cat:'ft', label:'$\\vec F_т$ (на тело)' },
|
||
{ cat:'p', label:'$\\vec P$ (на опору/подвес)' },
|
||
{ cat:'zero', label:'$P = 0$ (невесомость)' }
|
||
]));
|
||
|
||
/* IV-4 ТРН */
|
||
h += wgWrap('p24-iv4', 'ТРН', 'Тренажёр §24', '',
|
||
'<div id="p24-tr-host">'
|
||
+ quizQuestion('p24-tr', 0, '$m = 0{,}5$ кг лежит на столе. Вес (при $g = 10$ Н/кг)?', ['0,5 Н','5 Н','50 Н','500 Н'], 1)
|
||
+ quizQuestion('p24-tr', 1, 'Гиря $m = 100$ г висит на нити. Сила, с которой нить растягивается, равна:', ['1 Н','10 Н','100 Н','0,1 Н'], 0, '$P = mg = 0{,}1 \\cdot 10 = 1$ Н.')
|
||
+ quizQuestion('p24-tr', 2, 'В свободно падающем лифте чувствует ли пассажир свой вес?', ['Да, как всегда','Нет, наступает невесомость','В 2 раза больше','В 2 раза меньше'], 1)
|
||
+ quizQuestion('p24-tr', 3, 'На Луне ($g_Л = 1{,}6$ Н/кг) тело массой $5$ кг весит:', ['5 Н','8 Н','16 Н','50 Н'], 1, '$P = 5 \\cdot 1{,}6 = 8$ Н.')
|
||
+ '</div>');
|
||
|
||
h += readButton('p24');
|
||
body.innerHTML = h;
|
||
|
||
function draw24(s){
|
||
const svg = document.getElementById('p24-svg');
|
||
if(!svg) return;
|
||
const cx = 180, cy = 100;
|
||
let html = '';
|
||
let info = '';
|
||
if(s === 'rest'){
|
||
// Тело на столе
|
||
html += '<rect x="20" y="160" width="320" height="10" fill="#475569"/>';
|
||
for(let i = 0; i < 14; i++) html += '<line x1="' + (30 + i*22) + '" y1="170" x2="' + (24 + i*22) + '" y2="180" stroke="#0f172a" stroke-width="0.8"/>';
|
||
html += '<rect x="' + (cx-25) + '" y="' + (cy+30) + '" width="50" height="30" fill="#dc2626" stroke="#7f1d1d" stroke-width="1.5" rx="3"/>';
|
||
// F_т вниз (фиолетовая)
|
||
html += '<line x1="' + (cx-30) + '" y1="' + (cy+45) + '" x2="' + (cx-30) + '" y2="' + (cy+85) + '" stroke="#7c3aed" stroke-width="3"/>';
|
||
html += '<polygon points="' + (cx-35) + ',' + (cy+78) + ' ' + (cx-25) + ',' + (cy+78) + ' ' + (cx-30) + ',' + (cy+88) + '" fill="#7c3aed"/>';
|
||
html += '<text x="' + (cx-70) + '" y="' + (cy+85) + '" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="#7c3aed">F_т (на тело)</text>';
|
||
// P вниз от низа тела (индиго)
|
||
html += '<line x1="' + (cx+30) + '" y1="' + (cy+60) + '" x2="' + (cx+30) + '" y2="' + (cy+100) + '" stroke="#4338ca" stroke-width="3"/>';
|
||
html += '<polygon points="' + (cx+25) + ',' + (cy+93) + ' ' + (cx+35) + ',' + (cy+93) + ' ' + (cx+30) + ',' + (cy+103) + '" fill="#4338ca"/>';
|
||
html += '<text x="' + (cx+40) + '" y="' + (cy+100) + '" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="#4338ca">P (на стол)</text>';
|
||
info = '<b>Покой на горизонтальной опоре:</b> $P = F_т = mg$, но приложены к разным телам.';
|
||
} else if(s === 'fall'){
|
||
html += '<rect x="' + (cx-25) + '" y="' + (cy-15) + '" width="50" height="30" fill="#dc2626" stroke="#7f1d1d" stroke-width="1.5" rx="3"/>';
|
||
// F_т вниз
|
||
html += '<line x1="' + cx + '" y1="' + (cy+20) + '" x2="' + cx + '" y2="' + (cy+70) + '" stroke="#7c3aed" stroke-width="3"/>';
|
||
html += '<polygon points="' + (cx-5) + ',' + (cy+63) + ' ' + (cx+5) + ',' + (cy+63) + ' ' + cx + ',' + (cy+73) + '" fill="#7c3aed"/>';
|
||
html += '<text x="' + (cx+10) + '" y="' + (cy+55) + '" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="#7c3aed">F_т ↓</text>';
|
||
// P = 0 — пиктограмма
|
||
html += '<text x="' + (cx-100) + '" y="' + (cy-15) + '" font-family="Inter,sans-serif" font-size="14" font-weight="700" fill="#10b981">P = 0</text>';
|
||
html += '<text x="' + (cx-100) + '" y="' + (cy+5) + '" font-family="Inter,sans-serif" font-size="10" fill="#475569">невесомость</text>';
|
||
info = '<b>Свободное падение / орбита:</b> сила тяжести есть ($F_т = mg \\ne 0$), но вес $P = 0$ — тело ни на что не давит.';
|
||
} else if(s === 'up'){
|
||
html += '<rect x="20" y="160" width="320" height="10" fill="#475569"/>';
|
||
html += '<line x1="' + cx + '" y1="160" x2="' + cx + '" y2="' + (cy+30) + '" stroke="#92400e" stroke-width="2"/>'; // тяга вверх
|
||
html += '<rect x="' + (cx-25) + '" y="' + (cy+30) + '" width="50" height="30" fill="#dc2626" stroke="#7f1d1d" stroke-width="1.5" rx="3"/>';
|
||
// F_т
|
||
html += '<line x1="' + (cx-30) + '" y1="' + (cy+45) + '" x2="' + (cx-30) + '" y2="' + (cy+85) + '" stroke="#7c3aed" stroke-width="3"/>';
|
||
html += '<polygon points="' + (cx-35) + ',' + (cy+78) + ' ' + (cx-25) + ',' + (cy+78) + ' ' + (cx-30) + ',' + (cy+88) + '" fill="#7c3aed"/>';
|
||
html += '<text x="' + (cx-90) + '" y="' + (cy+88) + '" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="#7c3aed">F_т = mg</text>';
|
||
// P больше — длинная стрелка
|
||
html += '<line x1="' + (cx+30) + '" y1="' + (cy+60) + '" x2="' + (cx+30) + '" y2="' + (cy+115) + '" stroke="#dc2626" stroke-width="3.5"/>';
|
||
html += '<polygon points="' + (cx+25) + ',' + (cy+108) + ' ' + (cx+35) + ',' + (cy+108) + ' ' + (cx+30) + ',' + (cy+118) + '" fill="#dc2626"/>';
|
||
html += '<text x="' + (cx+40) + '" y="' + (cy+118) + '" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="#dc2626">P > mg (перегрузка)</text>';
|
||
info = '<b>Лифт ускоряется вверх:</b> вес <b>больше</b> $mg$ — это перегрузка. Космонавты на старте испытывают $P \\approx 3 mg$.';
|
||
} else {
|
||
// down
|
||
html += '<rect x="20" y="160" width="320" height="10" fill="#475569"/>';
|
||
html += '<rect x="' + (cx-25) + '" y="' + (cy+30) + '" width="50" height="30" fill="#dc2626" stroke="#7f1d1d" stroke-width="1.5" rx="3"/>';
|
||
html += '<line x1="' + (cx-30) + '" y1="' + (cy+45) + '" x2="' + (cx-30) + '" y2="' + (cy+85) + '" stroke="#7c3aed" stroke-width="3"/>';
|
||
html += '<polygon points="' + (cx-35) + ',' + (cy+78) + ' ' + (cx-25) + ',' + (cy+78) + ' ' + (cx-30) + ',' + (cy+88) + '" fill="#7c3aed"/>';
|
||
html += '<text x="' + (cx-90) + '" y="' + (cy+88) + '" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="#7c3aed">F_т = mg</text>';
|
||
// P меньше — короткая стрелка
|
||
html += '<line x1="' + (cx+30) + '" y1="' + (cy+60) + '" x2="' + (cx+30) + '" y2="' + (cy+80) + '" stroke="#10b981" stroke-width="2.5"/>';
|
||
html += '<polygon points="' + (cx+25) + ',' + (cy+73) + ' ' + (cx+35) + ',' + (cy+73) + ' ' + (cx+30) + ',' + (cy+83) + '" fill="#10b981"/>';
|
||
html += '<text x="' + (cx+40) + '" y="' + (cy+78) + '" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="#10b981">P < mg</text>';
|
||
info = '<b>Лифт ускоряется вниз:</b> вес <b>меньше</b> $mg$. Если ускорение $= g$, то $P = 0$ — невесомость.';
|
||
}
|
||
svg.innerHTML = html;
|
||
document.getElementById('p24-info').innerHTML = info;
|
||
renderMath(document.getElementById('p24-info'));
|
||
}
|
||
body.querySelectorAll('.p24-sit').forEach(btn => btn.addEventListener('click', () => {
|
||
body.querySelectorAll('.p24-sit').forEach(b => { b.style.background = '#fff'; b.style.color = '#dc2626'; });
|
||
btn.style.background = '#dc2626'; btn.style.color = '#fff';
|
||
draw24(btn.dataset.s);
|
||
}));
|
||
draw24('rest');
|
||
|
||
wireDnd('p24-dnd', [
|
||
{ id:'a1', cat:'ft' },{ id:'a2', cat:'ft' },{ id:'a3', cat:'p' },
|
||
{ id:'a4', cat:'p' },{ id:'a5', cat:'zero' },{ id:'a6', cat:'zero' }
|
||
]);
|
||
wireQuiz('p24-q-host', () => { if(window.addXp) window.addXp(10, 'q-p24'); });
|
||
wireQuiz('p24-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p24'); });
|
||
wireReadBtn('p24');
|
||
renderMath(body);
|
||
}
|
||
|
||
/* ========================================================== */
|
||
/* §25 — Динамометр */
|
||
/* ========================================================== */
|
||
function add_p25(){
|
||
const body = document.getElementById('p25-body');
|
||
if(!body) return;
|
||
let h = '';
|
||
|
||
h += makeCard('theory', 'Принцип работы', '§ 25.1',
|
||
'<b>Динамометр</b> (от греч. <i>динамис</i> — сила) — прибор для измерения силы.<br><br>'
|
||
+ 'В основе — пружина: чем сильнее её растягивают, тем больше она удлиняется. '
|
||
+ 'Шкала проградуирована так, чтобы каждому положению указателя соответствовала сила в <b>ньютонах</b>.');
|
||
|
||
h += makeCard('rule', 'Виды динамометров', '§ 25.2',
|
||
'<ul style="padding-left:20px;margin:6px 0">'
|
||
+ '<li><b>Школьный лабораторный</b> — обычно $0..4$ Н или $0..10$ Н, цена деления $0{,}1$ Н.</li>'
|
||
+ '<li><b>Медицинский (для силы кисти)</b> — до $600$ Н.</li>'
|
||
+ '<li><b>Промышленный</b> — для измерения тяги машин, до тысяч Н и больше.</li>'
|
||
+ '</ul>'
|
||
+ '<b>Правила:</b> прибор калибруют в вертикальном положении; не превышай предел шкалы (иначе пружина испортится).');
|
||
|
||
h += makeCard('example', 'Связь с массой', '§ 25.3',
|
||
'Динамометр измеряет <b>силу</b> (например, вес висящего груза). Если знаешь $g$, можно найти массу:<br>'
|
||
+ '$$m = \\dfrac{F}{g}$$<br>'
|
||
+ 'Например, динамометр показал $P = 5$ Н. Тогда $m = 5 / 10 = 0{,}5$ кг $= 500$ г.');
|
||
|
||
/* IV-1 СИМ: виртуальный динамометр */
|
||
h += wgWrap('p25-iv1', 'СИМ', 'Виртуальный динамометр', 'Меняй силу — наблюдай растяжение пружины и положение указателя.',
|
||
'<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Сила $F$, Н: <b id="p25-F" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">2</b><input type="range" id="p25-F-r" min="0" max="10" step="0.1" value="2" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Предел $F_{max}$, Н: <b id="p25-Fmax" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">10</b><input type="range" id="p25-Fmax-r" min="2" max="50" step="1" value="10" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
|
||
+ '</div>'
|
||
+ '<svg id="p25-svg" viewBox="0 0 200 240" width="100%" style="max-width:280px;display:block;margin:0 auto"></svg>'
|
||
+ '<div id="p25-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:10px 14px;margin-top:8px;font-size:.92rem;text-align:center"></div>');
|
||
|
||
/* IV-2 КАЛЬК: F = mg обратное */
|
||
h += wgWrap('p25-iv2', 'КАЛЬК', 'Динамометр → масса', 'По показанию динамометра найди массу тела.',
|
||
'<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Показание $F$, Н: <b id="p25c-F" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">5</b><input type="range" id="p25c-F-r" min="0.1" max="100" step="0.1" value="5" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$g$, Н/кг: <b id="p25c-g" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">9.8</b><select id="p25c-g-s" style="width:100%;margin-top:6px;padding:6px;border-radius:6px;border:1px solid ' + ACCENT_SOFT + ';font-family:inherit"><option value="9.8" selected>9,8 (Земля)</option><option value="1.6">1,6 (Луна)</option><option value="3.7">3,7 (Марс)</option><option value="24.8">24,8 (Юпитер)</option></select></label>'
|
||
+ '</div>'
|
||
+ '<div style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:12px 14px;font-size:.94rem">$m = F/g = $ <b id="p25c-m" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">0.51</b> кг $= $ <b id="p25c-mg" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">510</b> г</div>');
|
||
|
||
/* IV-3 DnD */
|
||
h += wgWrap('p25-iv3', 'DnD', 'Выбери подходящий динамометр', '',
|
||
dndPool('p25-dnd', [
|
||
{ id:'a1', cat:'school', html:'Измерить вес гирьки 200 г' },
|
||
{ id:'a2', cat:'school', html:'Найти силу упругости школьной пружины' },
|
||
{ id:'a3', cat:'med', html:'Измерить силу кисти руки спортсмена' },
|
||
{ id:'a4', cat:'med', html:'Тест на здоровье в поликлинике' },
|
||
{ id:'a5', cat:'ind', html:'Тяга трактора, тащащего прицеп' },
|
||
{ id:'a6', cat:'ind', html:'Сила, с которой буксир тянет баржу' }
|
||
], [
|
||
{ cat:'school', label:'Школьный (0..10 Н)' },
|
||
{ cat:'med', label:'Медицинский (до 600 Н)' },
|
||
{ cat:'ind', label:'Промышленный (тысячи Н)' }
|
||
]));
|
||
|
||
/* IV-4 ТРН */
|
||
h += wgWrap('p25-iv4', 'ТРН', 'Тренажёр §25', '',
|
||
'<div id="p25-tr-host">'
|
||
+ quizQuestion('p25-tr', 0, 'Динамометр показал $F = 4$ Н на Земле ($g = 10$). Масса тела?', ['0,4 кг','4 кг','40 кг','0,04 кг'], 0)
|
||
+ quizQuestion('p25-tr', 1, 'Какова цена деления школьного динамометра 0..4 Н с 40 малыми делениями?', ['0,01 Н','0,1 Н','0,4 Н','1 Н'], 1, '$C = 4/40 = 0{,}1$ Н.')
|
||
+ quizQuestion('p25-tr', 2, 'Принцип работы динамометра основан на…', ['Силе тяжести','Растяжении пружины (упругая сила)','Магнитном поле','Электричестве'], 1)
|
||
+ quizQuestion('p25-tr', 3, 'Что произойдёт, если превысить предел шкалы?', ['Ничего','Пружина испортится','Прибор сам сломается','Подаст звуковой сигнал'], 1)
|
||
+ '</div>');
|
||
|
||
h += readButton('p25');
|
||
body.innerHTML = h;
|
||
|
||
function draw25(){
|
||
const F = +document.getElementById('p25-F-r').value;
|
||
const Fmax = +document.getElementById('p25-Fmax-r').value;
|
||
document.getElementById('p25-F').textContent = F.toFixed(1);
|
||
document.getElementById('p25-Fmax').textContent = Fmax;
|
||
if(window.PHYS && window.PHYS.dynamometer){
|
||
let svgInner = window.PHYS.dynamometer(80, 20, 160, Fmax, Math.min(F, Fmax));
|
||
// Цвет фона для подложки
|
||
document.getElementById('p25-svg').innerHTML = '<rect x="0" y="0" width="200" height="240" fill="#fef2f2" rx="8"/>' + svgInner;
|
||
}
|
||
document.getElementById('p25-info').innerHTML = F > Fmax
|
||
? '<b style="color:#dc2626">Превышение предела!</b> Реальная сила $F = ' + F.toFixed(1) + '$ Н > $F_{max} = ' + Fmax + '$ Н. Пружина может испортиться.'
|
||
: 'Показание: $F = ' + F.toFixed(1) + '$ Н из $' + Fmax + '$ Н. Цена деления $\\approx ' + (Fmax/20).toFixed(2) + '$ Н.';
|
||
renderMath(document.getElementById('p25-info'));
|
||
}
|
||
['p25-F-r','p25-Fmax-r'].forEach(id => document.getElementById(id).addEventListener('input', draw25));
|
||
draw25();
|
||
|
||
const upd25c = () => {
|
||
const F = +document.getElementById('p25c-F-r').value;
|
||
const g = +document.getElementById('p25c-g-s').value;
|
||
document.getElementById('p25c-F').textContent = F.toFixed(1);
|
||
document.getElementById('p25c-g').textContent = g.toString().replace('.', ',');
|
||
const m = F / g;
|
||
document.getElementById('p25c-m').textContent = m.toFixed(3);
|
||
document.getElementById('p25c-mg').textContent = (m * 1000).toFixed(0);
|
||
};
|
||
document.getElementById('p25c-F-r').addEventListener('input', upd25c);
|
||
document.getElementById('p25c-g-s').addEventListener('change', upd25c);
|
||
upd25c();
|
||
|
||
wireDnd('p25-dnd', [
|
||
{ id:'a1', cat:'school' },{ id:'a2', cat:'school' },{ id:'a3', cat:'med' },
|
||
{ id:'a4', cat:'med' },{ id:'a5', cat:'ind' },{ id:'a6', cat:'ind' }
|
||
]);
|
||
wireQuiz('p25-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p25'); });
|
||
wireReadBtn('p25');
|
||
renderMath(body);
|
||
}
|
||
|
||
/* ========================================================== */
|
||
/* §26 — Сложение сил. Равнодействующая (ГЛАВНЫЙ ВИЗУАЛ ГЛАВЫ 3) */
|
||
/* ========================================================== */
|
||
function add_p26(){
|
||
const body = document.getElementById('p26-body');
|
||
if(!body) return;
|
||
let h = '';
|
||
|
||
h += makeCard('theory', 'Что такое равнодействующая', '§ 26.1',
|
||
'Если на тело действует <b>несколько сил</b>, их совместное действие можно заменить <b>одной силой</b> — '
|
||
+ '<b>равнодействующей</b> $\\vec R$.<br><br>'
|
||
+ 'Тело ведёт себя так, словно на него действует только $\\vec R$. Например, если $R = 0$ — тело покоится '
|
||
+ 'или движется равномерно (силы уравновешены).');
|
||
|
||
h += makeCard('rule', 'Силы на одной прямой', '§ 26.2',
|
||
'<b>Сонаправленные силы</b> (в одну сторону): $$R = F_1 + F_2$$ направление — то же.<br><br>'
|
||
+ '<b>Противоположные силы</b>: $$R = |F_1 - F_2|$$ направление — в сторону <b>большей</b> силы.<br><br>'
|
||
+ 'Если $F_1 = F_2$ и они противоположны — $R = 0$, тело в равновесии.');
|
||
|
||
h += makeCard('example', 'Перетягивание каната', '§ 26.3',
|
||
'Команда А тянет канат с силой $F_A = 600$ Н вправо. Команда Б — $F_Б = 500$ Н влево.<br>'
|
||
+ '$R = 600 - 500 = 100$ Н вправо. Канат смещается в сторону команды А.<br><br>'
|
||
+ 'Если бы $F_A = F_Б = 600$ Н, было бы равновесие — канат стоял бы на месте.');
|
||
|
||
/* IV-1 ГЛАВНЫЙ ВИЗУАЛ: Конструктор сил на теле */
|
||
h += wgWrap('p26-iv1', 'СИМ', 'Конструктор сил на теле — главный визуал', 'Двигай ползунки 4 сил → видишь, как меняется равнодействующая и поведение тела.',
|
||
'<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:8px;margin-bottom:12px">'
|
||
+ '<label style="display:block;font-size:.84rem;color:#475569;background:#fff;padding:7px 11px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$F_т$ (вниз), Н: <b id="p26-ft" style="color:#7c3aed;font-family:JetBrains Mono,monospace">10</b><input type="range" id="p26-ft-r" min="0" max="30" step="1" value="10" style="display:block;width:100%;margin-top:6px;accent-color:#7c3aed"></label>'
|
||
+ '<label style="display:block;font-size:.84rem;color:#475569;background:#fff;padding:7px 11px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$N$ (вверх), Н: <b id="p26-N" style="color:#475569;font-family:JetBrains Mono,monospace">10</b><input type="range" id="p26-N-r" min="0" max="30" step="1" value="10" style="display:block;width:100%;margin-top:6px;accent-color:#475569"></label>'
|
||
+ '<label style="display:block;font-size:.84rem;color:#475569;background:#fff;padding:7px 11px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$F_{тяги}$ (вправо), Н: <b id="p26-Ft2" style="color:#10b981;font-family:JetBrains Mono,monospace">8</b><input type="range" id="p26-Ft2-r" min="0" max="30" step="1" value="8" style="display:block;width:100%;margin-top:6px;accent-color:#10b981"></label>'
|
||
+ '<label style="display:block;font-size:.84rem;color:#475569;background:#fff;padding:7px 11px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$F_{тр}$ (влево), Н: <b id="p26-Ftr" style="color:#92400e;font-family:JetBrains Mono,monospace">3</b><input type="range" id="p26-Ftr-r" min="0" max="30" step="1" value="3" style="display:block;width:100%;margin-top:6px;accent-color:#92400e"></label>'
|
||
+ '</div>'
|
||
+ '<svg id="p26-svg" viewBox="0 0 400 240" width="100%" style="max-width:600px;display:block;margin:0 auto;background:#fef2f2;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>'
|
||
+ '<div id="p26-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:10px 14px;margin-top:8px;font-size:.94rem;line-height:1.65"></div>');
|
||
|
||
/* IV-2 КАЛЬК */
|
||
h += wgWrap('p26-iv2', 'КАЛЬК', 'Сложение двух сил на одной прямой', '',
|
||
'<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px;margin-bottom:10px">'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$F_1$, Н: <b id="p26c-F1" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">5</b><input type="range" id="p26c-F1-r" min="0" max="30" step="1" value="5" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$F_2$, Н: <b id="p26c-F2" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">3</b><input type="range" id="p26c-F2-r" min="0" max="30" step="1" value="3" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Направления:<select id="p26c-dir" style="width:100%;margin-top:6px;padding:6px;border-radius:6px;border:1px solid ' + ACCENT_SOFT + ';font-family:inherit"><option value="same" selected>Сонаправлены</option><option value="opp">Противоположны</option></select></label>'
|
||
+ '</div>'
|
||
+ '<div id="p26c-out" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:12px 14px;font-size:.96rem;line-height:1.7"></div>');
|
||
|
||
/* IV-3 DnD */
|
||
h += wgWrap('p26-iv3', 'DnD', 'Куда направлена R?', '',
|
||
dndPool('p26-dnd', [
|
||
{ id:'a1', cat:'right', html:'$F_1 = 10$ Н →, $F_2 = 4$ Н →' },
|
||
{ id:'a2', cat:'right', html:'$F_1 = 8$ Н →, $F_2 = 5$ Н ←' },
|
||
{ id:'a3', cat:'left', html:'$F_1 = 3$ Н →, $F_2 = 9$ Н ←' },
|
||
{ id:'a4', cat:'left', html:'$F_1 = 5$ Н ←, $F_2 = 5$ Н ←' },
|
||
{ id:'a5', cat:'zero', html:'$F_1 = 7$ Н →, $F_2 = 7$ Н ←' },
|
||
{ id:'a6', cat:'zero', html:'Только $F_т$ и $N$ равны на горизонтальной опоре' }
|
||
], [
|
||
{ cat:'right', label:'R направлена →' },
|
||
{ cat:'left', label:'R направлена ←' },
|
||
{ cat:'zero', label:'R = 0' }
|
||
]));
|
||
|
||
/* IV-4 ТРН */
|
||
h += wgWrap('p26-iv4', 'ТРН', 'Тренажёр §26', '',
|
||
'<div id="p26-tr-host">'
|
||
+ quizQuestion('p26-tr', 0, '$F_1 = 6$ Н, $F_2 = 4$ Н, сонаправлены. R?', ['2 Н','4 Н','10 Н','24 Н'], 2)
|
||
+ quizQuestion('p26-tr', 1, '$F_1 = 10$ Н, $F_2 = 6$ Н, противоположны. Модуль R?', ['4 Н','6 Н','10 Н','16 Н'], 0)
|
||
+ quizQuestion('p26-tr', 2, 'Книга лежит на столе. Действуют $F_т$ и $N$. Чему равна R?', ['$mg$','$2mg$','$0$','$N - F_т$'], 2, 'Тело в покое → силы уравновешены, $R = 0$.')
|
||
+ quizQuestion('p26-tr', 3, 'На брусок действуют $F_{тяги} = 12$ Н → и $F_{тр} = 5$ Н ←. Куда движется?', ['Покоится','Влево','Вправо','Невозможно сказать'], 2, '$R = 12-5 = 7$ Н → — вправо.')
|
||
+ quizQuestion('p26-tr', 4, '$F_1 = F_2 = 8$ Н, противоположны. R?', ['0','8 Н','16 Н','Зависит от массы'], 0)
|
||
+ '</div>');
|
||
|
||
h += readButton('p26');
|
||
body.innerHTML = h;
|
||
|
||
function draw26(){
|
||
const Ft = +document.getElementById('p26-ft-r').value;
|
||
const N = +document.getElementById('p26-N-r').value;
|
||
const Ftt = +document.getElementById('p26-Ft2-r').value;
|
||
const Ftr = +document.getElementById('p26-Ftr-r').value;
|
||
document.getElementById('p26-ft').textContent = Ft;
|
||
document.getElementById('p26-N').textContent = N;
|
||
document.getElementById('p26-Ft2').textContent = Ftt;
|
||
document.getElementById('p26-Ftr').textContent = Ftr;
|
||
const Rx = Ftt - Ftr;
|
||
const Ry = Ft - N; // положительное Ry — вниз
|
||
const R = Math.hypot(Rx, Ry);
|
||
|
||
const cx = 200, cy = 130;
|
||
const sc = 3.5; // px/Н
|
||
let s = '';
|
||
// Земля
|
||
s += '<rect x="40" y="200" width="320" height="10" fill="#475569"/>';
|
||
for(let i = 0; i < 14; i++) s += '<line x1="' + (50 + i*22) + '" y1="210" x2="' + (44 + i*22) + '" y2="220" stroke="#0f172a" stroke-width="0.8"/>';
|
||
// Тело — куб
|
||
s += '<rect x="' + (cx-22) + '" y="' + (cy-22) + '" width="44" height="44" fill="#dc2626" stroke="#7f1d1d" stroke-width="1.5" rx="3"/>';
|
||
// Стрелки сил
|
||
function arrow(x1,y1,x2,y2,col,label){
|
||
const len = Math.hypot(x2-x1, y2-y1);
|
||
if(len < 4) return '';
|
||
const a = Math.atan2(y2-y1, x2-x1);
|
||
const ah = 8;
|
||
const ax1 = x2 - ah * Math.cos(a - 0.45);
|
||
const ay1 = y2 - ah * Math.sin(a - 0.45);
|
||
const ax2 = x2 - ah * Math.cos(a + 0.45);
|
||
const ay2 = y2 - ah * Math.sin(a + 0.45);
|
||
return '<line x1="' + x1 + '" y1="' + y1 + '" x2="' + x2.toFixed(1) + '" y2="' + y2.toFixed(1) + '" stroke="' + col + '" stroke-width="2.5"/>'
|
||
+ '<polygon points="' + x2.toFixed(1) + ',' + y2.toFixed(1) + ' ' + ax1.toFixed(1) + ',' + ay1.toFixed(1) + ' ' + ax2.toFixed(1) + ',' + ay2.toFixed(1) + '" fill="' + col + '"/>'
|
||
+ '<text x="' + (x2 + 6*Math.cos(a)).toFixed(1) + '" y="' + (y2 + 6*Math.sin(a) + 4).toFixed(1) + '" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="' + col + '">' + label + '</text>';
|
||
}
|
||
s += arrow(cx, cy, cx, cy + Ft * sc, '#7c3aed', 'F_т=' + Ft); // вниз
|
||
s += arrow(cx, cy, cx, cy - N * sc, '#475569', 'N=' + N); // вверх
|
||
s += arrow(cx, cy, cx + Ftt * sc, cy, '#10b981', 'F_тяги=' + Ftt); // вправо
|
||
s += arrow(cx, cy, cx - Ftr * sc, cy, '#92400e', 'F_тр=' + Ftr); // влево
|
||
// Равнодействующая
|
||
if(R > 0.1){
|
||
s += arrow(cx, cy, cx + Rx * sc, cy + Ry * sc, '#dc2626', 'R=' + R.toFixed(1));
|
||
}
|
||
document.getElementById('p26-svg').innerHTML = s;
|
||
|
||
// Info
|
||
let verdict;
|
||
if(R < 0.1) verdict = '<b style="color:#10b981">Силы уравновешены. R = 0</b> — тело в покое или движется равномерно.';
|
||
else if(Math.abs(Ry) < 0.1 && Rx > 0) verdict = '<b style="color:#dc2626">R = ' + Rx + ' Н вправо</b> — тело ускоряется вправо.';
|
||
else if(Math.abs(Ry) < 0.1 && Rx < 0) verdict = '<b style="color:#dc2626">R = ' + (-Rx) + ' Н влево</b> — тело ускоряется влево.';
|
||
else if(Math.abs(Rx) < 0.1 && Ry > 0) verdict = '<b style="color:#dc2626">R = ' + Ry + ' Н вниз</b> — тело падает / провалится.';
|
||
else if(Math.abs(Rx) < 0.1 && Ry < 0) verdict = '<b style="color:#dc2626">R = ' + (-Ry) + ' Н вверх</b> — тело подпрыгнет.';
|
||
else verdict = '<b style="color:#dc2626">R ≈ ' + R.toFixed(1) + ' Н</b> — тело ускоряется под углом.';
|
||
document.getElementById('p26-info').innerHTML = verdict + '<br><span style="font-size:.84rem;color:#475569">$R_x = F_{тяги} - F_{тр} = ' + Rx + '$, $R_y = F_т - N = ' + Ry + '$</span>';
|
||
renderMath(document.getElementById('p26-info'));
|
||
}
|
||
['p26-ft-r','p26-N-r','p26-Ft2-r','p26-Ftr-r'].forEach(id => document.getElementById(id).addEventListener('input', draw26));
|
||
draw26();
|
||
|
||
const upd26c = () => {
|
||
const F1 = +document.getElementById('p26c-F1-r').value;
|
||
const F2 = +document.getElementById('p26c-F2-r').value;
|
||
const dir = document.getElementById('p26c-dir').value;
|
||
document.getElementById('p26c-F1').textContent = F1;
|
||
document.getElementById('p26c-F2').textContent = F2;
|
||
let R;
|
||
if(dir === 'same') R = F1 + F2;
|
||
else R = Math.abs(F1 - F2);
|
||
let arrow1 = '→', arrow2 = '→';
|
||
if(dir === 'opp') arrow2 = '←';
|
||
let result;
|
||
if(dir === 'same') result = '$R = F_1 + F_2 = ' + F1 + ' + ' + F2 + ' = $ <b>' + R + '</b> Н (→)';
|
||
else {
|
||
const dir_arrow = F1 > F2 ? '→' : (F2 > F1 ? '←' : '');
|
||
result = '$R = |F_1 - F_2| = |' + F1 + ' - ' + F2 + '| = $ <b>' + R + '</b> Н ' + (R === 0 ? '<b style="color:#10b981">(равновесие)</b>' : '(' + dir_arrow + ')');
|
||
}
|
||
document.getElementById('p26c-out').innerHTML = result;
|
||
renderMath(document.getElementById('p26c-out'));
|
||
};
|
||
['p26c-F1-r','p26c-F2-r'].forEach(id => document.getElementById(id).addEventListener('input', upd26c));
|
||
document.getElementById('p26c-dir').addEventListener('change', upd26c);
|
||
upd26c();
|
||
|
||
wireDnd('p26-dnd', [
|
||
{ id:'a1', cat:'right' },{ id:'a2', cat:'right' },{ id:'a3', cat:'left' },
|
||
{ id:'a4', cat:'left' },{ id:'a5', cat:'zero' },{ id:'a6', cat:'zero' }
|
||
]);
|
||
wireQuiz('p26-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p26'); });
|
||
wireReadBtn('p26');
|
||
renderMath(body);
|
||
}
|
||
|
||
/* ========================================================== */
|
||
/* §27 — Трение. Сила трения */
|
||
/* ========================================================== */
|
||
function add_p27(){
|
||
const body = document.getElementById('p27-body');
|
||
if(!body) return;
|
||
let h = '';
|
||
|
||
h += makeCard('theory', 'Откуда берётся трение', '§ 27.1',
|
||
'При движении (или попытке движения) одного тела по поверхности другого возникает сила, '
|
||
+ 'мешающая движению — <b>сила трения</b> $\\vec F_{тр}$. Она направлена <b>против движения</b>.<br><br>'
|
||
+ 'Причины: <b>шероховатость</b> поверхностей и <b>притяжение молекул</b> в местах контакта.');
|
||
|
||
h += makeCard('rule', 'Виды трения', '§ 27.2',
|
||
'<ul style="padding-left:20px;margin:6px 0">'
|
||
+ '<li><b>Трение покоя</b> — мешает сдвинуть тело с места. Бывает максимальным, после чего тело начинает скользить.</li>'
|
||
+ '<li><b>Трение скольжения</b> — действует на скользящее тело. $F_{тр} \\approx \\mu N$, где $\\mu$ — коэффициент трения, $N$ — нормальная реакция (≈ вес).</li>'
|
||
+ '<li><b>Трение качения</b> — катит колесо. Намного меньше скольжения. Поэтому колесо — гениальное изобретение.</li>'
|
||
+ '</ul>'
|
||
+ '$F_{тр}$ <b>не зависит</b> (почти) от площади контакта, но зависит от $N$ и от шероховатости.');
|
||
|
||
h += makeCard('example', 'Где трение мешает, а где помогает', '§ 27.3',
|
||
'<b>Полезно:</b> идти и ехать (без трения — гололёд!), тормоза, гвозди в дереве, держать карандаш.<br>'
|
||
+ '<b>Мешает:</b> греет и изнашивает детали машин, замедляет движение. Чтобы уменьшить — смазывают маслом, ставят подшипники.');
|
||
|
||
/* IV-1 СИМ: брусок на поверхности с slider массы, μ, тяги */
|
||
h += wgWrap('p27-iv1', 'СИМ', 'Симулятор трения', 'Меняй массу, материал и силу тяги — посмотри, едет брусок или стоит.',
|
||
'<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:8px;margin-bottom:10px">'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:7px 11px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Масса $m$, кг: <b id="p27-m" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">5</b><input type="range" id="p27-m-r" min="0.5" max="20" step="0.5" value="5" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:7px 11px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Сила тяги $F$, Н: <b id="p27-F" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">15</b><input type="range" id="p27-F-r" min="0" max="100" step="1" value="15" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:7px 11px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Поверхность:<select id="p27-mu" style="width:100%;margin-top:6px;padding:6px;border-radius:6px;border:1px solid ' + ACCENT_SOFT + ';font-family:inherit"><option value="0.04">Лёд ($\\mu = 0{,}04$)</option><option value="0.2" selected>Сталь по стали ($0{,}2$)</option><option value="0.4">Дерево по дереву ($0{,}4$)</option><option value="0.7">Резина по асфальту ($0{,}7$)</option></select></label>'
|
||
+ '</div>'
|
||
+ '<svg id="p27-svg" viewBox="0 0 380 150" width="100%" style="max-width:600px;display:block;margin:0 auto;background:#fef2f2;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>'
|
||
+ '<div id="p27-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:10px 14px;margin-top:8px;font-size:.94rem;line-height:1.65"></div>');
|
||
|
||
/* IV-2 КВИЗ */
|
||
h += wgWrap('p27-iv2', 'КВИЗ', 'Трение', '',
|
||
'<div id="p27-q-host">'
|
||
+ quizQuestion('p27-q', 0, 'Куда направлена сила трения скольжения?', ['Перпендикулярно движению','Против движения','Вверх','Куда угодно'], 1)
|
||
+ quizQuestion('p27-q', 1, 'Какое трение наименьшее (при прочих равных)?', ['Покоя','Скольжения','Качения','Все одинаковы'], 2)
|
||
+ quizQuestion('p27-q', 2, 'Если на тело давит больший вес, $F_{тр}$ при скольжении…', ['Не меняется','Увеличивается','Уменьшается','Становится 0'], 1, '$F_{тр} \\sim N$, а $N$ зависит от веса.')
|
||
+ quizQuestion('p27-q', 3, 'Гололёд опасен, потому что коэф. трения…', ['Очень большой','Очень маленький','Не существует','Зависит от веса'], 1)
|
||
+ '</div>');
|
||
|
||
/* IV-3 DnD */
|
||
h += wgWrap('p27-iv3', 'DnD', 'Трение полезно или вредно?', '',
|
||
dndPool('p27-dnd', [
|
||
{ id:'a1', cat:'good', html:'Можно идти (нога не скользит)' },
|
||
{ id:'a2', cat:'good', html:'Тормоза машины' },
|
||
{ id:'a3', cat:'good', html:'Гвоздь держится в доске' },
|
||
{ id:'a4', cat:'bad', html:'Шестерёнки изнашиваются' },
|
||
{ id:'a5', cat:'bad', html:'Двигатель греется и теряет КПД' },
|
||
{ id:'a6', cat:'bad', html:'Лыжи скользят медленнее без смазки' }
|
||
], [
|
||
{ cat:'good', label:'Полезно' },
|
||
{ cat:'bad', label:'Мешает' }
|
||
]));
|
||
|
||
/* IV-4 ТРН */
|
||
h += wgWrap('p27-iv4', 'ТРН', 'Тренажёр §27', '',
|
||
'<div id="p27-tr-host">'
|
||
+ quizQuestion('p27-tr', 0, 'Брусок $m = 2$ кг, $\\mu = 0{,}3$. $F_{тр}$ при скольжении (g=10)?', ['3 Н','6 Н','10 Н','20 Н'], 1, '$N = mg = 20$ Н. $F_{тр} = \\mu N = 0{,}3 \\cdot 20 = 6$ Н.')
|
||
+ quizQuestion('p27-tr', 1, 'Чтобы брусок $m = 5$ кг сдвинуть, надо приложить $F > F_{тр\\,пок}$. Если $\\mu_{пок} = 0{,}4$ и $g = 10$, минимальная $F$?', ['10 Н','15 Н','20 Н','25 Н'], 2, '$F_{тр\\,пок} = \\mu N = 0{,}4 \\cdot 50 = 20$ Н.')
|
||
+ quizQuestion('p27-tr', 2, 'Подшипники нужны, чтобы…', ['Увеличить трение','Заменить трение скольжения трением качения','Прибавить веса','Соединить детали'], 1)
|
||
+ quizQuestion('p27-tr', 3, 'Если смазать ось маслом, $F_{тр}$ …', ['Увеличится','Уменьшится','Не изменится','Станет нулевой'], 1)
|
||
+ quizQuestion('p27-tr', 4, 'Лыжи покрывают воском, чтобы…', ['Защитить от воды','Уменьшить трение','Увеличить массу','Покрасить'], 1)
|
||
+ '</div>');
|
||
|
||
h += readButton('p27');
|
||
body.innerHTML = h;
|
||
|
||
function draw27(){
|
||
const m = +document.getElementById('p27-m-r').value;
|
||
const F = +document.getElementById('p27-F-r').value;
|
||
const mu = +document.getElementById('p27-mu').value;
|
||
document.getElementById('p27-m').textContent = m;
|
||
document.getElementById('p27-F').textContent = F;
|
||
const g = 10;
|
||
const N = m * g;
|
||
const FtrMax = mu * N;
|
||
const moving = F > FtrMax;
|
||
const Ftr = moving ? FtrMax : F;
|
||
const R = moving ? (F - FtrMax) : 0;
|
||
|
||
const W = 380, H = 150, baseY = 110;
|
||
let s = '';
|
||
s += '<rect x="0" y="' + baseY + '" width="' + W + '" height="30" fill="#94a3b8"/>';
|
||
for(let i = 0; i < 18; i++) s += '<line x1="' + (i*22+5) + '" y1="' + baseY + '" x2="' + (i*22+15) + '" y2="' + (baseY+8) + '" stroke="#374151" stroke-width="0.8"/>';
|
||
// Брусок
|
||
const bx = 130, bw = 80, bh = 40;
|
||
s += '<rect x="' + bx + '" y="' + (baseY - bh) + '" width="' + bw + '" height="' + bh + '" fill="#dc2626" stroke="#7f1d1d" stroke-width="1.5" rx="3"/>';
|
||
s += '<text x="' + (bx + bw/2) + '" y="' + (baseY - bh/2 + 5) + '" text-anchor="middle" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="#fff">m=' + m + ' кг</text>';
|
||
// F тяги (вправо)
|
||
const fLen = Math.min(80, F * 1.5);
|
||
s += '<line x1="' + (bx + bw) + '" y1="' + (baseY - bh/2) + '" x2="' + (bx + bw + fLen) + '" y2="' + (baseY - bh/2) + '" stroke="#10b981" stroke-width="3"/>';
|
||
s += '<polygon points="' + (bx + bw + fLen) + ',' + (baseY - bh/2) + ' ' + (bx + bw + fLen - 8) + ',' + (baseY - bh/2 - 5) + ' ' + (bx + bw + fLen - 8) + ',' + (baseY - bh/2 + 5) + '" fill="#10b981"/>';
|
||
s += '<text x="' + (bx + bw + fLen + 5) + '" y="' + (baseY - bh/2 - 4) + '" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="#10b981">F=' + F + 'Н</text>';
|
||
// F_тр (влево, от низа бруска)
|
||
const trLen = Math.min(80, Ftr * 1.5);
|
||
if(trLen > 2){
|
||
s += '<line x1="' + bx + '" y1="' + (baseY - 6) + '" x2="' + (bx - trLen) + '" y2="' + (baseY - 6) + '" stroke="#92400e" stroke-width="3"/>';
|
||
s += '<polygon points="' + (bx - trLen) + ',' + (baseY - 6) + ' ' + (bx - trLen + 8) + ',' + (baseY - 11) + ' ' + (bx - trLen + 8) + ',' + (baseY - 1) + '" fill="#92400e"/>';
|
||
s += '<text x="' + (bx - trLen - 5) + '" y="' + (baseY - 12) + '" text-anchor="end" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="#92400e">F_тр=' + Ftr.toFixed(1) + 'Н</text>';
|
||
}
|
||
// Verdict
|
||
s += '<text x="' + (W/2) + '" y="20" text-anchor="middle" font-family="Unbounded,sans-serif" font-size="13" font-weight="800" fill="' + (moving ? '#dc2626' : '#10b981') + '">' + (moving ? 'ЕДЕТ →' : 'ПОКОИТСЯ') + '</text>';
|
||
document.getElementById('p27-svg').innerHTML = s;
|
||
|
||
document.getElementById('p27-info').innerHTML =
|
||
'$N = mg = ' + N + '$ Н, $F_{тр\\,max} = \\mu N = ' + FtrMax.toFixed(1) + '$ Н<br>'
|
||
+ (moving
|
||
? '$F$ > $F_{тр}$ → тело ускоряется, $R = F - F_{тр} = ' + R.toFixed(1) + '$ Н вправо.'
|
||
: '$F \\le F_{тр\\,max}$ → трение покоя уравновешивает силу тяги, $R = 0$. Тело <b>не сдвинется</b>.');
|
||
renderMath(document.getElementById('p27-info'));
|
||
}
|
||
['p27-m-r','p27-F-r'].forEach(id => document.getElementById(id).addEventListener('input', draw27));
|
||
document.getElementById('p27-mu').addEventListener('change', draw27);
|
||
draw27();
|
||
|
||
wireDnd('p27-dnd', [
|
||
{ id:'a1', cat:'good' },{ id:'a2', cat:'good' },{ id:'a3', cat:'good' },
|
||
{ id:'a4', cat:'bad' },{ id:'a5', cat:'bad' },{ id:'a6', cat:'bad' }
|
||
]);
|
||
wireQuiz('p27-q-host', () => { if(window.addXp) window.addXp(10, 'q-p27'); });
|
||
wireQuiz('p27-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p27'); });
|
||
wireReadBtn('p27');
|
||
renderMath(body);
|
||
}
|
||
|
||
/* ========================================================== */
|
||
/* Финал главы 3 — 10 боссов + ачивка «Мастер движения» */
|
||
/* ========================================================== */
|
||
function add_final3(){
|
||
const body = document.getElementById('final3-body');
|
||
if(!body) return;
|
||
let h = '';
|
||
|
||
h += '<div style="background:linear-gradient(135deg,' + ACCENT_SOFT + ',#fff1f2);border:1.5px solid ' + ACCENT + ';border-radius:14px;padding:16px;margin-bottom:14px;text-align:center">'
|
||
+ '<div style="font-family:Unbounded,sans-serif;font-weight:800;font-size:1.12rem;color:' + ACCENT_D + '">Финал главы 3: победи 10 боссов</div>'
|
||
+ '<div style="font-size:.88rem;color:#475569;margin-top:5px">Реши все 10 задач — получишь ачивку «Мастер движения» и +50 XP.</div>'
|
||
+ '<div style="height:10px;background:#fff;border-radius:6px;overflow:hidden;margin-top:12px;border:1px solid ' + ACCENT_SOFT + '"><div id="ch3-fin-fill" style="height:100%;background:linear-gradient(90deg,' + ACCENT + ',' + ACCENT_D + ');width:0%;transition:width .4s"></div></div>'
|
||
+ '<div id="ch3-fin-lab" style="font-size:.84rem;color:#475569;margin-top:6px">Побеждено: 0 / 10</div>'
|
||
+ '</div>';
|
||
|
||
const bosses = [
|
||
{ n:1, tag:'§16', title:'Скорость',
|
||
q:'Автомобиль за $t = 4$ с проехал $s = 80$ м равномерно. Найди $v$ в м/с.',
|
||
hint:'$v = s/t = 80/4 = 20$ м/с.',
|
||
ans:20, tol:0.2, step:'0.1' },
|
||
{ n:2, tag:'§18', title:'Средняя скорость',
|
||
q:'Велосипедист: $v_1 = 10$ м/с за $t_1 = 60$ с, потом $v_2 = 4$ м/с за $t_2 = 60$ с. $\\langle v\\rangle$ в м/с?',
|
||
hint:'$\\langle v\\rangle = (10\\cdot 60 + 4\\cdot 60)/(60+60) = 840/120 = 7$ м/с.',
|
||
ans:7, tol:0.2, step:'0.1' },
|
||
{ n:3, tag:'§20', title:'Плотность',
|
||
q:'Брусок $V = 50$ см³, $m = 390$ г. Плотность $\\rho$ в г/см³? Что за вещество?',
|
||
hint:'$\\rho = 390/50 = 7{,}8$ г/см³ — железо.',
|
||
ans:7.8, tol:0.1, step:'0.1' },
|
||
{ n:4, tag:'§22', title:'Сила тяжести на Земле',
|
||
q:'$m = 4$ кг, $g = 9{,}8$ Н/кг. Найди $F_т$ в Н (округли до десятых).',
|
||
hint:'$F_т = mg = 4 \\cdot 9{,}8 = 39{,}2$ Н.',
|
||
ans:39.2, tol:0.2, step:'0.1' },
|
||
{ n:5, tag:'§22', title:'Сила тяжести на Луне',
|
||
q:'Тот же камень $m = 4$ кг на Луне ($g_Л = 1{,}6$ Н/кг). $F_т$ в Н?',
|
||
hint:'$F_т = 4 \\cdot 1{,}6 = 6{,}4$ Н.',
|
||
ans:6.4, tol:0.1, step:'0.1' },
|
||
{ n:6, tag:'§25', title:'Динамометр',
|
||
q:'Динамометр показал $P = 7{,}5$ Н на Земле ($g = 10$ Н/кг). Масса тела в граммах?',
|
||
hint:'$m = P/g = 0{,}75$ кг $= 750$ г.',
|
||
ans:750, tol:5, step:'1' },
|
||
{ n:7, tag:'§26', title:'Равнодействующая 2 сил',
|
||
q:'$F_1 = 30$ Н →, $F_2 = 18$ Н ←. Модуль R в Н?',
|
||
hint:'$R = |30 - 18| = 12$ Н вправо.',
|
||
ans:12, tol:0.5, step:'1' },
|
||
{ n:8, tag:'§26', title:'Равнодействующая 3 сил',
|
||
q:'$F_1 = 25$ Н →, $F_2 = 15$ Н →, $F_3 = 30$ Н ←. Модуль R в Н?',
|
||
hint:'Вправо: $25 + 15 = 40$. Влево: $30$. $R = |40 - 30| = 10$ Н вправо.',
|
||
ans:10, tol:0.5, step:'1' },
|
||
{ n:9, tag:'§27', title:'Сила трения',
|
||
q:'Брусок $m = 3$ кг скользит по столу с $\\mu = 0{,}2$ ($g = 10$ Н/кг). $F_{тр}$ в Н?',
|
||
hint:'$N = mg = 30$ Н. $F_{тр} = \\mu N = 0{,}2 \\cdot 30 = 6$ Н.',
|
||
ans:6, tol:0.2, step:'0.1' },
|
||
{ n:10, tag:'синтез', title:'Мастер движения',
|
||
q:'Брусок $m = 2$ кг с силой тяги $F = 8$ Н вправо. Коэф. трения $\\mu = 0{,}3$, $g = 10$ Н/кг. Найди равнодействующую R в Н (со знаком: + если вправо, − если влево, 0 если покой).',
|
||
hint:'$F_{тр\\,max} = \\mu mg = 0{,}3 \\cdot 2 \\cdot 10 = 6$ Н. $F = 8$ Н > $F_{тр\\,max} = 6$ Н — едет. $R = 8 - 6 = 2$ Н (вправо).',
|
||
ans:2, tol:0.2, step:'0.1' }
|
||
];
|
||
|
||
const STATE_KEY = 'physics7_ch3_final_bosses';
|
||
let solved = {};
|
||
try{ solved = JSON.parse(localStorage.getItem(STATE_KEY) || '{}') || {}; }catch(e){}
|
||
|
||
bosses.forEach(b => {
|
||
const isSolved = !!solved[b.n];
|
||
h += '<div data-boss="' + b.n + '" style="background:#fff;border:2px solid ' + (isSolved ? '#10b981' : ACCENT_SOFT) + ';border-radius:12px;padding:14px 16px;margin-bottom:12px;box-shadow:' + (isSolved ? '0 0 0 3px rgba(16,185,129,.16)' : '0 2px 8px rgba(0,0,0,.05)') + '">'
|
||
+ '<div style="display:flex;align-items:center;gap:10px;margin-bottom:8px;flex-wrap:wrap">'
|
||
+ '<span style="background:' + ACCENT + ';color:#fff;padding:3px 10px;border-radius:99px;font-size:.7rem;font-weight:800;letter-spacing:.04em">' + b.tag + '</span>'
|
||
+ '<span style="font-family:Unbounded,sans-serif;font-weight:800;font-size:.96rem;color:#0f172a">Босс ' + b.n + '. ' + b.title + '</span>'
|
||
+ '</div>'
|
||
+ '<div style="padding:10px 12px;background:' + ACCENT_SOFT + ';border-radius:8px;margin-bottom:10px;font-size:.94rem;line-height:1.55">' + b.q + '</div>'
|
||
+ '<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center">'
|
||
+ '<input type="number" step="' + b.step + '" class="boss-inp" data-n="' + b.n + '" placeholder="число" style="padding:8px 12px;border:1.5px solid ' + ACCENT_SOFT + ';border-radius:8px;width:140px;text-align:center;font-family:JetBrains Mono,monospace;font-size:.95rem"' + (isSolved ? ' value="' + b.ans + '" disabled' : '') + '>'
|
||
+ '<button class="boss-go" data-n="' + b.n + '" type="button" style="background:linear-gradient(135deg,' + ACCENT + ',' + ACCENT_D + ');color:#fff;border:none;padding:8px 16px;border-radius:9px;font-weight:700;font-size:.88rem;cursor:pointer;font-family:inherit"' + (isSolved ? ' disabled' : '') + '>Атаковать</button>'
|
||
+ '<button class="boss-hint" data-n="' + b.n + '" type="button" style="background:#fff;color:#475569;border:1.5px solid ' + ACCENT_SOFT + ';padding:8px 14px;border-radius:9px;font-weight:600;font-size:.86rem;cursor:pointer;font-family:inherit">Подсказка</button>'
|
||
+ '</div>'
|
||
+ '<div class="boss-hint-txt" data-n="' + b.n + '" style="margin-top:8px;padding:9px 13px;background:#fef3c7;border-left:3px solid #f59e0b;border-radius:6px;font-size:.86rem;line-height:1.5;display:none">' + b.hint + '</div>'
|
||
+ '<div class="boss-fb" data-n="' + b.n + '" style="margin-top:8px;padding:9px 13px;border-radius:8px;font-weight:600;font-size:.88rem;line-height:1.45;' + (isSolved ? 'background:#d1fae5;color:#065f46;border-left:4px solid #10b981' : 'display:none') + '">' + (isSolved ? '✓ Босс повержен! +20 XP.' : '') + '</div>'
|
||
+ '</div>';
|
||
});
|
||
|
||
h += '<div id="ch3-mastered" style="margin-top:14px;padding:14px 18px;border-radius:12px;background:linear-gradient(135deg,#fef3c7,#fde68a);border:1.5px solid #f59e0b;display:none;align-items:center;gap:12px"><svg style="width:32px;height:32px;stroke:#92400e;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round" viewBox="0 0 24 24"><polygon points="12,2 15,9 22,9.3 17,14 18.5,21 12,17 5.5,21 7,14 2,9.3 9,9"/></svg><div style="flex:1"><div style="font-weight:800;color:#92400e;font-family:Unbounded,sans-serif">Ачивка «Мастер движения» получена!</div><div style="font-size:.86rem;color:#78350f;margin-top:2px">+50 XP · Глава 3 полностью пройдена.</div></div></div>';
|
||
|
||
body.innerHTML = h;
|
||
renderMath(body);
|
||
|
||
function updateBar(){
|
||
const cnt = bosses.filter(b => solved[b.n]).length;
|
||
document.getElementById('ch3-fin-fill').style.width = (cnt * 100 / bosses.length) + '%';
|
||
document.getElementById('ch3-fin-lab').textContent = 'Побеждено: ' + cnt + ' / ' + bosses.length;
|
||
if(cnt === bosses.length){
|
||
document.getElementById('ch3-mastered').style.display = 'flex';
|
||
const ACH_KEY = 'physics7_ch3_master';
|
||
if(localStorage.getItem(ACH_KEY) !== '1'){
|
||
localStorage.setItem(ACH_KEY, '1');
|
||
if(window.addXp) window.addXp(50, 'ach-ch3-master');
|
||
if(window.achievement) window.achievement('ch_done', 'Мастер движения');
|
||
}
|
||
}
|
||
}
|
||
updateBar();
|
||
|
||
body.querySelectorAll('.boss-hint').forEach(btn => btn.addEventListener('click', () => {
|
||
const n = btn.dataset.n;
|
||
const txt = body.querySelector('.boss-hint-txt[data-n="' + n + '"]');
|
||
if(txt) txt.style.display = txt.style.display === 'none' ? 'block' : 'none';
|
||
}));
|
||
body.querySelectorAll('.boss-go').forEach(btn => btn.addEventListener('click', () => {
|
||
const n = +btn.dataset.n;
|
||
const b = bosses.find(x => x.n === n);
|
||
const inp = body.querySelector('.boss-inp[data-n="' + n + '"]');
|
||
const fb = body.querySelector('.boss-fb[data-n="' + n + '"]');
|
||
const card = body.querySelector('[data-boss="' + n + '"]');
|
||
const v = parseFloat((inp.value || '').replace(',', '.'));
|
||
if(isNaN(v)){
|
||
fb.style.display = 'block';
|
||
fb.style.background = '#fee2e2'; fb.style.color = '#7f1d1d'; fb.style.borderLeft = '4px solid #dc2626';
|
||
fb.textContent = 'Введи число.';
|
||
return;
|
||
}
|
||
if(Math.abs(v - b.ans) < b.tol){
|
||
fb.style.display = 'block';
|
||
fb.style.background = '#d1fae5'; fb.style.color = '#065f46'; fb.style.borderLeft = '4px solid #10b981';
|
||
fb.innerHTML = '✓ Босс повержен! +20 XP.';
|
||
card.style.border = '2px solid #10b981';
|
||
card.style.boxShadow = '0 0 0 3px rgba(16,185,129,.16)';
|
||
btn.disabled = true; inp.disabled = true;
|
||
if(!solved[n]){
|
||
solved[n] = true;
|
||
try{ localStorage.setItem(STATE_KEY, JSON.stringify(solved)); }catch(e){}
|
||
if(window.addXp) window.addXp(20, 'boss-ch3-' + n);
|
||
updateBar();
|
||
}
|
||
} else {
|
||
fb.style.display = 'block';
|
||
fb.style.background = '#fee2e2'; fb.style.color = '#7f1d1d'; fb.style.borderLeft = '4px solid #dc2626';
|
||
fb.textContent = 'Не то. Перепроверь решение.';
|
||
}
|
||
}));
|
||
body.querySelectorAll('.boss-inp').forEach(inp => inp.addEventListener('keydown', e => {
|
||
if(e.key === 'Enter'){ e.preventDefault(); body.querySelector('.boss-go[data-n="' + inp.dataset.n + '"]').click(); }
|
||
}));
|
||
}
|
||
|
||
window.PHYS7_CH3_WIDGETS = {
|
||
p14: add_p14, p15: add_p15, p16: add_p16, p17: add_p17,
|
||
p18: add_p18, p19: add_p19, p20: add_p20,
|
||
p21: add_p21, p22: add_p22, p23: add_p23,
|
||
p24: add_p24, p25: add_p25,
|
||
p26: add_p26, p27: add_p27,
|
||
final3: add_final3
|
||
};
|
||
|
||
})();
|