96a2097e70
Глава 3 «Движение и силы», часть 1 (без сил — Phase 4). Файл: phys7_ch3_widgets.js (1082 строк, экспорт p14..p20). §14 Мех. движение, относительность: - 3 карточки (СО / относительность / самолёт-облако) - IV-1 СИМ: переключатель СО (Земля/Поезд) с анимацией поезда vs дерева - IV-2 КВИЗ 4 / IV-3 DnD 6→2 / IV-4 ТРН 4 §15 Траектория, путь, время: - 3 карточки + IV-1 СИМ: интерактивная сетка SVG, клик → точка → построение ломаной траектории + автоподсчёт пути (1 клетка = 1 м), кнопка «Сброс» - DnD 6→3 (прямолин/криволин/замкн) + квиз 3 + тренажёр 5 §16 Равномерное движение, скорость: - 3 карточки (определение / 4 единицы скорости / расчёт) - IV-1 СИМ: автомобиль на дороге, slider v=1..30 м/с, анимация движения с пересчётом пройденного пути в реальном времени - IV-2 КАЛЬК v=s/t, slider s и t, вывод в м/с и км/ч - DnD 6→3 (пешеход/машина/самолёт) + тренажёр 5 §17 Графики s(t) и v(t) — ГЛАВНЫЙ ВИЗУАЛ КИНЕМАТИКИ: - 3 карточки (наклон=v / горизонталь / параллельные = равные v) - IV-1 СИМ: рядом 2 графика SVG — s(t) с двумя прямыми (v1, v2) и v(t) с двумя горизонтальными + заливка площади под v1 как «s = v·t»; slider v1, v2 - КВИЗ 4 / DnD 6 → 4 типа линий / ТРН 4 §18 Средняя скорость: - 3 карточки (формула / ловушка ≠ среднеарифм. / пешеход + метро) - IV-1 КАЛЬК: 4 slider'а v1/t1/v2/t2, средневзвешенная vs ловушка с авто- индикатором «СОВПАЛО (t1=t2) / НЕВЕРНО» - КВИЗ 3 / DnD 6→2 / ТРН 4 §19 Инерция: - 3 карточки (закон Галилея / масса как мера инертности / пассажиры в автобусе) - IV-1 СИМ: шарик на поверхности SVG с кнопкой «Запустить» и переключателем «Трение ВКЛ/ВЫКЛ»: с трением — тормозит и останавливается; без — катится вечно - КВИЗ 4 / DnD 6→3 (легко/средне/тяжело) / ТРН 4 §20 Масса. Плотность: - 3 карточки (масса / формула ρ=m/V / таблица 11 веществ) - IV-1 КАЛЬК ρ=m/V: slider m=1..20000 г и V=1..2000 см³, вывод в г/см³ и кг/м³ + автоопределение вещества (газ/пенопласт/дерево/вода/.../золото) - IV-2 СИМ: 8 кнопок материалов → SVG-куб 1 дм³ меняет цвет и подпись массы - DnD 6→3 (лёгкий/средний/тяжёлый) / ТРН 5 Парсинг OK, smoke-test (7 экспортов) OK. Phase 3 — 7 из 14 § главы 3. Силы (§§21-27) + финал «Мастер движения» — Phase 4.
1083 lines
82 KiB
JavaScript
1083 lines
82 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);
|
||
}
|
||
|
||
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..p27 + final3 — в Phase 4 (силы)
|
||
};
|
||
|
||
})();
|