903bc5cf42
WIDGETS (+390 строк, теперь 1139 строк, экспорт p1..p7 + final1): §6 «Действия над физическими величинами»: - 3 карточки (однородные величины / переводы скорости/плотности/мощности/энергии / умножение единиц m·V → плотность) - IV-1 СИМ: таблица типичных скоростей (улитка → звук в воздухе) в м/с и км/ч - IV-2 КАЛЬК конвертер (главный визуал §6): 5 типов величин (скорость/плотность/ мощность/энергия/время), slider значения → перевод во все связанные единицы - IV-3 DnD: 8 эквивалентных пар (1 мин=60 с, 1 кВт=1000 Вт, и т.д.) - IV-4 ТРН: 5 задач (км/ч↔м/с, г/см³→кг/м³, ч+мин→с, сумма в разных приставках) §7 «Цена деления. Погрешность»: - 3 карточки (C = (X2-X1)/N / ΔX = C/2, запись X±ΔX / правила снятия отсчёта) - IV-1 СИМ (главный визуал §7): виртуальная линейка SVG со сменой цены деления (10/5/2/1 мм) и подвижной красной риской; авто-округление до ближайшего деления, запись результата с погрешностью в KaTeX - IV-2 КАЛЬК: 3 slider'а X1/X2/N → формула C и ΔX - IV-3 DnD: 6 приборов (линейка/штангенциркуль/микрометр/термометры/секундомер) → 6 типичных цен деления - IV-4 ТРН: 5 задач на цену деления и погрешность ФИНАЛ ГЛАВЫ 1 (5 боссов + ачивка «Юный физик» +50 XP): - Боссы (синтез §4-§7): 1. Площадь листа A4 в м² (перевод см→м + S=ab) 2. Плотность бруска с m=135 г и V=50 см³ (алюминий) 3. Скорость 90 км/ч в м/с 4. Цена деления (5 см = 50 делений → 1 мм) 5. Погрешность мензурки (C=2 мл → ΔV=1 мл) — Магистр-задача - Прогресс-бар «Побеждено: N/5», localStorage-сохранение между сессиями, +20 XP за каждого босса, ачивка +50 XP при 5/5 победах. - Все боссы с подсказками (toggle), Enter-submit, валидация числа. Все 4 IV в §6 и §7 wireDnd/wireQuiz/калькуляторы привязаны. parse-check, smoke-test (8 экспортов) пройдены.
1140 lines
88 KiB
JavaScript
1140 lines
88 KiB
JavaScript
// Физика 7 · Глава 1 · виджеты §§1–7 (Wave 1: §1, §2).
|
||
// Экспорт: window.PHYS7_CH1_WIDGETS = { p1: fn, p2: fn, ... }.
|
||
// Каждая функция вставляет в pN-body: 3 теоретические карточки + 4 виджета + кнопку «Прочитал».
|
||
|
||
(function(){
|
||
'use strict';
|
||
|
||
/* === Общие хелперы (вдохновлено phys9_ch1_widgets.js, но независимо) === */
|
||
|
||
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){
|
||
// kind: 'theory' | 'rule' | 'example'
|
||
const colorByKind = { theory:'#0284c7', rule:'#dc2626', example:'#10b981' };
|
||
const labelByKind = { theory:'Теория', rule:'Правило', example:'Пример' };
|
||
const c = colorByKind[kind] || '#0284c7';
|
||
return '<div class="th-card" style="background:#fff;border:1.5px solid #e0f2fe;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 class="wg" id="' + id + '" style="background:#fff;border:1.5px solid #e0f2fe;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:#4f46e5;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:#f0f9ff;border-left:3px solid #0284c7;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="phys7-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);transition:filter .15s">'
|
||
+ '<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('.phys7-read-btn[data-pid="' + pid + '"]');
|
||
if(!btn) return;
|
||
const KEY = 'physics7_ch1_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';
|
||
});
|
||
}
|
||
|
||
/* DnD на 4 корзины — общий движок */
|
||
function wireDnd(host, items, cats){
|
||
const root = document.getElementById(host);
|
||
if(!root) return;
|
||
const checkBtn = root.querySelector('.dnd-check');
|
||
const fb = root.querySelector('.dnd-fb');
|
||
let placed = {}; // itemId -> catKey
|
||
let armed = null;
|
||
// Pool clicks
|
||
root.querySelectorAll('.dnd-chip').forEach(chip => {
|
||
chip.addEventListener('click', () => {
|
||
if(armed === chip){ armed.classList.remove('armed'); armed = null; return; }
|
||
if(armed) armed.classList.remove('armed');
|
||
armed = chip;
|
||
chip.classList.add('armed');
|
||
});
|
||
});
|
||
// Drop boxes
|
||
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 inner = box.querySelector('.drop-items');
|
||
const clone = armed.cloneNode(true);
|
||
clone.classList.remove('armed');
|
||
clone.classList.add('placed');
|
||
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 = '';
|
||
});
|
||
inner.appendChild(clone);
|
||
armed.style.display = 'none';
|
||
armed.classList.remove('armed');
|
||
armed = null;
|
||
});
|
||
});
|
||
// Check
|
||
if(checkBtn) checkBtn.addEventListener('click', () => {
|
||
const total = items.length;
|
||
let correct = 0;
|
||
items.forEach(it => { if(placed[it.id] === it.cat) correct++; });
|
||
const pct = Math.round(correct * 100 / total);
|
||
fb.style.display = 'block';
|
||
if(correct === total){
|
||
fb.style.background = '#d1fae5'; fb.style.color = '#065f46'; fb.style.borderLeft = '4px solid #10b981';
|
||
fb.innerHTML = '✓ Идеально! Все ' + total + ' карточек на своих местах.';
|
||
if(typeof window.bumpProgress === 'function') window.bumpProgress(host.split('-')[0].replace('p','p') === host ? host : null, 0);
|
||
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 + ' (' + pct + '%). Попробуй ещё раз.';
|
||
}
|
||
});
|
||
}
|
||
|
||
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 #bae6fd;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 #bae6fd;border-radius:10px;padding:10px;min-height:80px"><h5 style="font-family:Unbounded,sans-serif;font-size:.76rem;color:#0c4a6e;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 class="dnd-pool" style="display:flex;flex-wrap:wrap;gap:8px;margin-bottom:14px;padding:10px;border:1.5px dashed #bae6fd;border-radius:10px;background:#f0f9ff">' + 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,#0284c7,#0c4a6e);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>';
|
||
}
|
||
|
||
/* Quiz одиночного выбора — карточка вопроса */
|
||
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 #bae6fd;border-radius:9px;padding:9px 14px;cursor:pointer;font-size:.92rem;font-family:inherit;text-align:left;transition:all .15s;width:100%;margin-bottom:6px">' + o + '</button>').join('');
|
||
return '<div class="qz-q" data-host="' + host + '" data-idx="' + idx + '" style="background:#f0f9ff;border:1.5px solid #bae6fd;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);
|
||
}
|
||
// Renable click-через-кнопки запрещён, но повторное прохождение через reset:
|
||
}));
|
||
});
|
||
}
|
||
|
||
/* ========================================================== */
|
||
/* §1 — Физика — наука о природе. Связь с другими науками */
|
||
/* ========================================================== */
|
||
function add_p1(){
|
||
const body = document.getElementById('p1-body');
|
||
if(!body) return;
|
||
let h = '';
|
||
|
||
/* 3 теоретические карточки */
|
||
h += makeCard('theory', 'Что изучает физика', '§ 1.1',
|
||
'Физика — это <b>наука о природе</b>. Она изучает <b>физические явления</b>: '
|
||
+ 'падение тел, движение машин, нагрев и охлаждение, свет, звук, электрический ток, магниты. '
|
||
+ 'Слово «физика» произошло от греческого <i>фюзис</i> — «природа».');
|
||
|
||
h += makeCard('rule', 'Связь с другими науками', '§ 1.2',
|
||
'<ul style="padding-left:20px;margin:4px 0">'
|
||
+ '<li><b>Астрономия</b> — изучает звёзды и планеты, использует физические законы движения.</li>'
|
||
+ '<li><b>Химия</b> — превращения веществ; в основе лежит строение атомов (физика).</li>'
|
||
+ '<li><b>Биология</b> — живые организмы; физика помогает понять работу сердца, глаза, мышц.</li>'
|
||
+ '<li><b>География</b> — погода, ветра, реки — это всё движущиеся вещества и силы.</li>'
|
||
+ '<li><b>Техника</b> — машины, компьютеры, мобильная связь — всё построено на физике.</li>'
|
||
+ '</ul>');
|
||
|
||
h += makeCard('example', 'Примеры физических явлений', '§ 1.3',
|
||
'<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:8px;margin-top:4px">'
|
||
+ '<div style="background:#f0f9ff;border-left:3px solid #0284c7;padding:8px 10px;border-radius:6px"><b>Радуга</b><br><span style="font-size:.84rem;color:#475569">световое явление</span></div>'
|
||
+ '<div style="background:#fef3c7;border-left:3px solid #d97706;padding:8px 10px;border-radius:6px"><b>Гром</b><br><span style="font-size:.84rem;color:#475569">звуковое явление</span></div>'
|
||
+ '<div style="background:#fee2e2;border-left:3px solid #dc2626;padding:8px 10px;border-radius:6px"><b>Северное сияние</b><br><span style="font-size:.84rem;color:#475569">электрическое</span></div>'
|
||
+ '<div style="background:#ede9fe;border-left:3px solid #7c3aed;padding:8px 10px;border-radius:6px"><b>Падение яблока</b><br><span style="font-size:.84rem;color:#475569">механическое</span></div>'
|
||
+ '<div style="background:#d1fae5;border-left:3px solid #10b981;padding:8px 10px;border-radius:6px"><b>Кипение чайника</b><br><span style="font-size:.84rem;color:#475569">тепловое</span></div>'
|
||
+ '<div style="background:#cffafe;border-left:3px solid #0891b2;padding:8px 10px;border-radius:6px"><b>Тающий лёд</b><br><span style="font-size:.84rem;color:#475569">фазовое</span></div>'
|
||
+ '</div>');
|
||
|
||
/* IV-1: галерея явлений (визуализатор) */
|
||
h += wgWrap('p1-iv1', 'СИМ', 'Явления вокруг нас', 'Наведи курсор на иконку, чтобы увидеть, какую сторону природы изучает физика.',
|
||
'<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(110px,1fr));gap:10px">'
|
||
+ ['Свет','Звук','Тепло','Движение','Электричество','Магнетизм','Жидкости','Газы'].map((nm,i) =>
|
||
'<div class="ph-card" style="background:#f0f9ff;border:1.5px solid #bae6fd;border-radius:10px;padding:14px 10px;text-align:center;cursor:default;transition:transform .15s,box-shadow .15s" onmouseover="this.style.transform=\'translateY(-3px)\';this.style.boxShadow=\'0 6px 16px rgba(2,132,199,.18)\'" onmouseout="this.style.transform=\'none\';this.style.boxShadow=\'none\'">'
|
||
+ '<div style="font-size:1.8rem;color:#0284c7;font-weight:800;font-family:Unbounded,sans-serif">' + ['☀','♪','♨','→','⚡','⌘','≈','○'][i] + '</div>'
|
||
+ '<div style="font-weight:700;font-size:.88rem;margin-top:4px">' + nm + '</div>'
|
||
+ '</div>').join('')
|
||
+ '</div>');
|
||
|
||
/* IV-2: квикфайр-понимание */
|
||
h += wgWrap('p1-iv2', 'КВИЗ', 'Понятия физики', 'Отметь верное утверждение.',
|
||
'<div id="p1-q-host">'
|
||
+ quizQuestion('p1-q', 0,
|
||
'Что НЕ изучает физика?',
|
||
['Падение тел','Образование облаков','Историю Древнего Рима','Электрический ток'],
|
||
2, 'История — это гуманитарная наука; физика изучает явления природы.')
|
||
+ quizQuestion('p1-q', 1,
|
||
'От какого греческого слова произошло название «физика»?',
|
||
['Фюзис (природа)','Космос (мир)','Логос (учение)','Софос (мудрость)'],
|
||
0, 'Греческое <i>фюзис</i> = «природа», поэтому физика — наука о природе.')
|
||
+ quizQuestion('p1-q', 2,
|
||
'Какая наука изучает планеты и звёзды и опирается на физику?',
|
||
['Биология','Астрономия','География','Химия'],
|
||
1, 'Астрономия — наука о небесных телах.')
|
||
+ '</div>');
|
||
|
||
/* IV-3: DnD соответствие наука↔область */
|
||
h += wgWrap('p1-iv3', 'DnD', 'Связь наук', 'Соедини науку с её областью изучения.',
|
||
dndPool('p1-dnd', [
|
||
{ id:'i1', cat:'astro', html:'Звёзды и планеты' },
|
||
{ id:'i2', cat:'chem', html:'Кислоты и щёлочи' },
|
||
{ id:'i3', cat:'bio', html:'Клетка и ДНК' },
|
||
{ id:'i4', cat:'phys', html:'Падение мяча' },
|
||
{ id:'i5', cat:'astro', html:'Затмение Солнца' },
|
||
{ id:'i6', cat:'chem', html:'Реакция железа с кислородом' },
|
||
{ id:'i7', cat:'bio', html:'Работа сердца' },
|
||
{ id:'i8', cat:'phys', html:'Электрический ток' }
|
||
], [
|
||
{ cat:'astro', label:'Астрономия' },
|
||
{ cat:'chem', label:'Химия' },
|
||
{ cat:'bio', label:'Биология' },
|
||
{ cat:'phys', label:'Физика' }
|
||
]));
|
||
|
||
/* IV-4: тренажёр (5 вопросов) */
|
||
h += wgWrap('p1-iv4', 'ТРН', 'Тренажёр §1', 'Ответь на 5 вопросов подряд — получишь +10 XP.',
|
||
'<div id="p1-tr-host">'
|
||
+ quizQuestion('p1-tr', 0, 'Что изучает физика?', ['Только живую природу','Природные явления (свет, звук, тепло, движение, …)','Только звёзды','Только химические реакции'], 1)
|
||
+ quizQuestion('p1-tr', 1, 'Какое из явлений — НЕ физическое?', ['Кипение воды','Дыхание человека','Падение мяча','Работа лампочки'], 1, 'Дыхание — биологический процесс.')
|
||
+ quizQuestion('p1-tr', 2, 'Электромобиль — пример…', ['Биологического объекта','Технического устройства, основанного на физике','Химического вещества','Астрономического тела'], 1)
|
||
+ quizQuestion('p1-tr', 3, 'Какая пара тесно связана?', ['Физика — литература','Физика — техника','Физика — история','Физика — музыка'], 1, 'Без физики нет техники.')
|
||
+ quizQuestion('p1-tr', 4, 'Слово «физика» означает…', ['Мудрость','Природу','Знание','Закон'], 1)
|
||
+ '</div>');
|
||
|
||
h += readButton('p1');
|
||
|
||
body.innerHTML = h;
|
||
// Wire interactivity
|
||
wireDnd('p1-dnd', [
|
||
{ id:'i1', cat:'astro' },{ id:'i2', cat:'chem' },{ id:'i3', cat:'bio' },{ id:'i4', cat:'phys' },
|
||
{ id:'i5', cat:'astro' },{ id:'i6', cat:'chem' },{ id:'i7', cat:'bio' },{ id:'i8', cat:'phys' }
|
||
], []);
|
||
wireQuiz('p1-q-host', () => { if(window.addXp) window.addXp(10, 'quiz-p1'); });
|
||
wireQuiz('p1-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p1'); });
|
||
wireReadBtn('p1');
|
||
renderMath(body);
|
||
}
|
||
|
||
/* ========================================================== */
|
||
/* §2 — Физическое тело, физическое явление, физическая величина */
|
||
/* ========================================================== */
|
||
function add_p2(){
|
||
const body = document.getElementById('p2-body');
|
||
if(!body) return;
|
||
let h = '';
|
||
|
||
/* 3 теоретические карточки */
|
||
h += makeCard('theory', 'Четыре главных понятия', '§ 2.1',
|
||
'<table style="width:100%;border-collapse:collapse;margin-top:4px;font-size:.92rem">'
|
||
+ '<tr style="background:#e0f2fe"><th style="text-align:left;padding:8px 10px;border-bottom:2px solid #0284c7">Понятие</th><th style="text-align:left;padding:8px 10px;border-bottom:2px solid #0284c7">Что это</th><th style="text-align:left;padding:8px 10px;border-bottom:2px solid #0284c7">Пример</th></tr>'
|
||
+ '<tr><td style="padding:6px 10px;border-bottom:1px solid #e0f2fe"><b>Тело</b></td><td style="padding:6px 10px;border-bottom:1px solid #e0f2fe">конкретный объект</td><td style="padding:6px 10px;border-bottom:1px solid #e0f2fe">мяч, книга, дом</td></tr>'
|
||
+ '<tr><td style="padding:6px 10px;border-bottom:1px solid #e0f2fe"><b>Вещество</b></td><td style="padding:6px 10px;border-bottom:1px solid #e0f2fe">из чего сделано тело</td><td style="padding:6px 10px;border-bottom:1px solid #e0f2fe">дерево, железо, вода</td></tr>'
|
||
+ '<tr><td style="padding:6px 10px;border-bottom:1px solid #e0f2fe"><b>Явление</b></td><td style="padding:6px 10px;border-bottom:1px solid #e0f2fe">изменение в природе</td><td style="padding:6px 10px;border-bottom:1px solid #e0f2fe">падение, кипение, гроза</td></tr>'
|
||
+ '<tr><td style="padding:6px 10px"><b>Величина</b></td><td style="padding:6px 10px">то, что можно измерить</td><td style="padding:6px 10px">масса, скорость, температура</td></tr>'
|
||
+ '</table>');
|
||
|
||
h += makeCard('rule', 'Как отличать?', '§ 2.2',
|
||
'<b>Тело</b> — отвечает на вопрос «<i>что это</i>?» — конкретный предмет.<br>'
|
||
+ '<b>Вещество</b> — отвечает «<i>из чего</i>?» — материал.<br>'
|
||
+ '<b>Явление</b> — отвечает «<i>что происходит</i>?» — изменение, процесс.<br>'
|
||
+ '<b>Величина</b> — отвечает «<i>сколько</i>? в каких единицах?» — у неё всегда есть <b>число и единица</b>: $m = 5$ кг, $v = 10$ м/с, $t = 20$ °C.');
|
||
|
||
h += makeCard('example', 'Один и тот же объект — разные роли', '§ 2.3',
|
||
'Рассмотрим <b>стакан с водой</b>:<br>'
|
||
+ '<ul style="padding-left:20px;margin:4px 0">'
|
||
+ '<li><b>Стакан</b> — это <b>тело</b>.</li>'
|
||
+ '<li>Он сделан из <b>стекла</b> — это <b>вещество</b>.</li>'
|
||
+ '<li>В нём — другое тело: <b>вода</b> (из вещества «вода»).</li>'
|
||
+ '<li>Когда вода <b>кипит</b> — это <b>явление</b>.</li>'
|
||
+ '<li>Температура $t = 100$ °C — это <b>величина</b> с числом 100 и единицей °C.</li>'
|
||
+ '</ul>');
|
||
|
||
/* IV-1: главный DnD — 12 карточек по 4 корзинам */
|
||
h += wgWrap('p2-iv1', 'СИМ', 'Сортировщик: тело / вещество / явление / величина', 'Перетащи 12 карточек в правильные корзины. Это главный визуал §2 — потренируй интуицию.',
|
||
dndPool('p2-dnd', [
|
||
{ id:'a1', cat:'body', html:'Стол' },
|
||
{ id:'a2', cat:'body', html:'Автомобиль' },
|
||
{ id:'a3', cat:'body', html:'Капля росы' },
|
||
{ id:'b1', cat:'subst', html:'Алюминий' },
|
||
{ id:'b2', cat:'subst', html:'Кислород' },
|
||
{ id:'b3', cat:'subst', html:'Сахар' },
|
||
{ id:'c1', cat:'phen', html:'Молния' },
|
||
{ id:'c2', cat:'phen', html:'Замерзание воды' },
|
||
{ id:'c3', cat:'phen', html:'Движение поезда' },
|
||
{ id:'d1', cat:'val', html:'$m = 5$ кг' },
|
||
{ id:'d2', cat:'val', html:'$t = -10$ °C' },
|
||
{ id:'d3', cat:'val', html:'$v = 30$ км/ч' }
|
||
], [
|
||
{ cat:'body', label:'Тело' },
|
||
{ cat:'subst', label:'Вещество' },
|
||
{ cat:'phen', label:'Явление' },
|
||
{ cat:'val', label:'Величина' }
|
||
]));
|
||
|
||
/* IV-2: «найди величину» — выбрать из списка */
|
||
h += wgWrap('p2-iv2', 'КВИЗ', 'Найди величину', 'У величины всегда есть число и единица измерения.',
|
||
'<div id="p2-q-host">'
|
||
+ quizQuestion('p2-q', 0, 'Что из списка — физическая величина?', ['Скорость','Скоростной поезд','Стрелка часов','Кипение'], 0, 'Скорость измеряется (м/с, км/ч) — это величина.')
|
||
+ quizQuestion('p2-q', 1, 'А что из этого — явление?', ['Лужа','Испарение воды','Лёд','Холодильник'], 1, 'Испарение — процесс, изменение состояния.')
|
||
+ quizQuestion('p2-q', 2, 'Какое слово обозначает вещество?', ['Гвоздь','Сталь','Молоток','Удар'], 1, 'Сталь — материал, из которого сделан гвоздь.')
|
||
+ '</div>');
|
||
|
||
/* IV-3: квикфайр да/нет по 8 утверждениям */
|
||
h += wgWrap('p2-iv3', 'ТЕСТ', 'Тело vs величина (быстрые ответы)', 'Прочитай и отметь верное.',
|
||
'<div id="p2-tn-host">'
|
||
+ quizQuestion('p2-tn', 0, '«Карандаш» — это…', ['Тело','Вещество','Явление','Величина'], 0)
|
||
+ quizQuestion('p2-tn', 1, '«Дерево» (из чего сделана линейка) — это…', ['Тело','Вещество','Явление','Величина'], 1)
|
||
+ quizQuestion('p2-tn', 2, '«Длина» — это…', ['Тело','Вещество','Явление','Величина'], 3)
|
||
+ quizQuestion('p2-tn', 3, '«Замерзание» — это…', ['Тело','Вещество','Явление','Величина'], 2)
|
||
+ quizQuestion('p2-tn', 4, '$10$ кг — это…', ['Тело','Вещество','Явление','Значение величины'], 3, 'Число + единица = величина.')
|
||
+ '</div>');
|
||
|
||
/* IV-4: тренажёр — 4 практических вопроса */
|
||
h += wgWrap('p2-iv4', 'ТРН', 'Тренажёр §2', 'Закрепи материал — 4 вопроса.',
|
||
'<div id="p2-tr-host">'
|
||
+ quizQuestion('p2-tr', 0, 'Что НЕ является телом?', ['Воздушный шар','Капля воды','Скорость','Кирпич'], 2, 'Скорость — величина, а не тело.')
|
||
+ quizQuestion('p2-tr', 1, 'Стакан с молоком: молоко в стакане — это…', ['Тело','Вещество','Явление','Величина'], 0, 'Молоко в этой ситуации — отдельное тело со своей формой (формой стакана).')
|
||
+ quizQuestion('p2-tr', 2, 'Парусник, плывущий в океане. Назови явление.', ['Парусник','Дерево (мачта)','Движение','Длина паруса'], 2)
|
||
+ quizQuestion('p2-tr', 3, 'Что нужно для записи величины?', ['Только число','Только единица','Число + единица','Только название'], 2, 'Например: $v = 20$ м/с — число 20 и единица м/с.')
|
||
+ '</div>');
|
||
|
||
h += readButton('p2');
|
||
|
||
body.innerHTML = h;
|
||
wireDnd('p2-dnd', [
|
||
{ id:'a1', cat:'body' },{ id:'a2', cat:'body' },{ id:'a3', cat:'body' },
|
||
{ id:'b1', cat:'subst' },{ id:'b2', cat:'subst' },{ id:'b3', cat:'subst' },
|
||
{ id:'c1', cat:'phen' },{ id:'c2', cat:'phen' },{ id:'c3', cat:'phen' },
|
||
{ id:'d1', cat:'val' },{ id:'d2', cat:'val' },{ id:'d3', cat:'val' }
|
||
], []);
|
||
wireQuiz('p2-q-host', () => { if(window.addXp) window.addXp(10, 'quiz-p2'); });
|
||
wireQuiz('p2-tn-host', () => { if(window.addXp) window.addXp(10, 'tn-p2'); });
|
||
wireQuiz('p2-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p2'); });
|
||
wireReadBtn('p2');
|
||
renderMath(body);
|
||
}
|
||
|
||
/* ========================================================== */
|
||
/* §3 — Методы исследования в физике */
|
||
/* ========================================================== */
|
||
function add_p3(){
|
||
const body = document.getElementById('p3-body');
|
||
if(!body) return;
|
||
let h = '';
|
||
|
||
h += makeCard('theory', 'Как физики изучают природу', '§ 3.1',
|
||
'Физика использует <b>три метода познания</b>:'
|
||
+ '<ol style="padding-left:20px;margin:6px 0">'
|
||
+ '<li><b>Наблюдение</b> — изучение явления <i>без вмешательства</i>. Учёный смотрит, фиксирует, не изменяя условий.</li>'
|
||
+ '<li><b>Эксперимент</b> — <i>целенаправленное</i> воссоздание явления в нужных условиях с измерениями.</li>'
|
||
+ '<li><b>Теоретическое описание</b> — построение модели, формул, законов; <i>гипотеза</i> сначала, потом — проверка.</li>'
|
||
+ '</ol>');
|
||
|
||
h += makeCard('rule', 'Чем отличаются?', '§ 3.2',
|
||
'<b>Наблюдение</b>: смотрим за грозой — не запускаем её сами.<br>'
|
||
+ '<b>Эксперимент</b>: бросаем шары разной массы в трубке без воздуха и измеряем время падения.<br>'
|
||
+ '<b>Гипотеза</b>: «может быть, тела падают одинаково в вакууме?» — её надо <i>проверить</i> экспериментом.<br>'
|
||
+ '<b>Теория</b>: подтверждённая гипотеза становится частью знаний — например, закон всемирного тяготения.');
|
||
|
||
h += makeCard('example', 'Опыт Галилея с Пизанской башней', '§ 3.3',
|
||
'По легенде, в конце XVI века <b>Галилео Галилей</b> поднялся на наклонную Пизанскую башню '
|
||
+ 'и одновременно бросил с её вершины два шара разной массы — тяжёлый и лёгкий. '
|
||
+ 'Шары упали на землю <b>почти одновременно</b>. Это был <b>эксперимент</b>, '
|
||
+ 'опровергнувший представление Аристотеля о том, что тяжёлые тела падают быстрее. '
|
||
+ 'Так появилась гипотеза «все тела падают с одним ускорением», позже подтверждённая в опытах с вакуумной трубкой.');
|
||
|
||
/* IV-1: timeline исторических опытов */
|
||
h += wgWrap('p3-iv1', 'СИМ', 'Великие опыты и наблюдения', 'Кликай по этапам — узнавай, чем прославился каждый учёный.',
|
||
'<div style="position:relative;padding:8px 0">'
|
||
+ ['Архимед / III в. до н. э. — закон рычага. Наблюдение и расчёт.',
|
||
'Галилей / 1590-е — падение тел с башни. Эксперимент.',
|
||
'Торричелли / 1643 — открыл атмосферное давление. Эксперимент с ртутью.',
|
||
'Паскаль / 1648 — закон передачи давления. Эксперимент и теория.',
|
||
'Ньютон / 1687 — закон всемирного тяготения. Теория, объединившая всё.'].map((txt, i) => {
|
||
const [name, rest] = txt.split(' — ');
|
||
return '<details style="background:#f0f9ff;border-left:3px solid #4f46e5;border-radius:6px;margin-bottom:6px;padding:8px 12px"><summary style="font-weight:700;cursor:pointer;font-size:.94rem">' + (i+1) + '. ' + name + '</summary><div style="margin-top:6px;color:#475569;font-size:.88rem;line-height:1.55">' + rest + '</div></details>';
|
||
}).join('')
|
||
+ '</div>');
|
||
|
||
/* IV-2: КВИЗ опыт vs наблюдение */
|
||
h += wgWrap('p3-iv2', 'КВИЗ', 'Опыт или наблюдение?', 'Выбери, какой метод использован.',
|
||
'<div id="p3-q-host">'
|
||
+ quizQuestion('p3-q', 0, 'Метеоролог смотрит на облака и записывает их форму.', ['Наблюдение','Эксперимент','Гипотеза','Теория'], 0)
|
||
+ quizQuestion('p3-q', 1, 'Ученик помещает шарик в воду и измеряет, насколько поднялся уровень.', ['Наблюдение','Эксперимент','Гипотеза','Теория'], 1)
|
||
+ quizQuestion('p3-q', 2, 'Учёный предполагает: «возможно, металл проводит тепло из-за свободных электронов».', ['Наблюдение','Эксперимент','Гипотеза','Теория'], 2)
|
||
+ quizQuestion('p3-q', 3, 'Архимед открыл закон рычага и записал его в виде формулы $F_1 l_1 = F_2 l_2$.', ['Наблюдение','Эксперимент','Гипотеза','Теория'], 3, 'Подтверждённое соотношение — это теория (закон).')
|
||
+ '</div>');
|
||
|
||
/* IV-3: DnD «классифицируй» */
|
||
h += wgWrap('p3-iv3', 'DnD', 'Классификация ситуаций', 'Распредели 8 ситуаций по трём корзинам.',
|
||
dndPool('p3-dnd', [
|
||
{ id:'a1', cat:'obs', html:'Смотрим, как тает снег весной' },
|
||
{ id:'a2', cat:'obs', html:'Записываем температуру за неделю' },
|
||
{ id:'a3', cat:'exp', html:'Нагреваем металл лампой и измеряем удлинение' },
|
||
{ id:'a4', cat:'exp', html:'Сравниваем падение перышка в трубке с воздухом и без' },
|
||
{ id:'a5', cat:'hyp', html:'Возможно, скорость света — максимальная во Вселенной' },
|
||
{ id:'a6', cat:'hyp', html:'Может быть, существуют тёмная материя и тёмная энергия' },
|
||
{ id:'a7', cat:'exp', html:'Бросаем мяч с разной высоты и засекаем время полёта' },
|
||
{ id:'a8', cat:'obs', html:'Изучаем затмение Луны' }
|
||
], [
|
||
{ cat:'obs', label:'Наблюдение' },
|
||
{ cat:'exp', label:'Эксперимент' },
|
||
{ cat:'hyp', label:'Гипотеза' }
|
||
]));
|
||
|
||
/* IV-4: тренажёр */
|
||
h += wgWrap('p3-iv4', 'ТРН', 'Тренажёр §3', 'Закрепи материал.',
|
||
'<div id="p3-tr-host">'
|
||
+ quizQuestion('p3-tr', 0, 'Что НЕ относится к методам познания в физике?', ['Наблюдение','Эксперимент','Угадывание','Теория'], 2, 'Угадывание — это не научный метод.')
|
||
+ quizQuestion('p3-tr', 1, 'Главное отличие эксперимента от наблюдения — это…', ['Использование приборов','Активное вмешательство и контроль условий','Запись результатов','Участие учёного'], 1)
|
||
+ quizQuestion('p3-tr', 2, 'Гипотеза становится теорией, когда…', ['Её опубликовали','Она проверена опытом','Её одобрил профессор','Её записали в учебник'], 1)
|
||
+ quizQuestion('p3-tr', 3, 'Какой учёный знаменит опытами с падающими телами?', ['Архимед','Галилей','Ньютон','Эйнштейн'], 1)
|
||
+ quizQuestion('p3-tr', 4, 'Что такое физическая модель?', ['Реальный прибор','Упрощённое представление явления для расчётов','Любая теория','Только формула'], 1, 'Модель опускает несущественные детали ради простоты.')
|
||
+ '</div>');
|
||
|
||
h += readButton('p3');
|
||
|
||
body.innerHTML = h;
|
||
wireDnd('p3-dnd', [
|
||
{ id:'a1', cat:'obs' },{ id:'a2', cat:'obs' },{ id:'a3', cat:'exp' },{ id:'a4', cat:'exp' },
|
||
{ id:'a5', cat:'hyp' },{ id:'a6', cat:'hyp' },{ id:'a7', cat:'exp' },{ id:'a8', cat:'obs' }
|
||
], []);
|
||
wireQuiz('p3-q-host', () => { if(window.addXp) window.addXp(10, 'quiz-p3'); });
|
||
wireQuiz('p3-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p3'); });
|
||
wireReadBtn('p3');
|
||
renderMath(body);
|
||
}
|
||
|
||
/* ========================================================== */
|
||
/* §4 — Прямые и косвенные измерения */
|
||
/* ========================================================== */
|
||
function add_p4(){
|
||
const body = document.getElementById('p4-body');
|
||
if(!body) return;
|
||
let h = '';
|
||
|
||
h += makeCard('theory', 'Два типа измерений', '§ 4.1',
|
||
'<b>Прямое измерение</b> — значение читается <i>прямо со шкалы прибора</i>. '
|
||
+ 'Длину книги — линейкой, массу — весами, время — секундомером, температуру — термометром.<br><br>'
|
||
+ '<b>Косвенное измерение</b> — значение <i>вычисляется по формуле</i> из других величин, '
|
||
+ 'измеренных прямо. Например, чтобы найти площадь стола, измеряют длину и ширину линейкой '
|
||
+ '(прямые), а площадь $S = a b$ — это уже косвенное измерение.');
|
||
|
||
h += makeCard('rule', 'Основные формулы косвенных измерений', '§ 4.2',
|
||
'<ul style="padding-left:20px;margin:4px 0;line-height:1.85">'
|
||
+ '<li><b>Площадь прямоугольника:</b> $S = a \\cdot b$, $[S] = $ м²</li>'
|
||
+ '<li><b>Объём прямоугольного параллелепипеда:</b> $V = a \\cdot b \\cdot c$, $[V] = $ м³</li>'
|
||
+ '<li><b>Объём через цилиндр:</b> $V = S \\cdot h$ (если известна площадь основания)</li>'
|
||
+ '<li><b>Плотность вещества:</b> $\\rho = \\dfrac{m}{V}$, $[\\rho] = $ кг/м³</li>'
|
||
+ '<li><b>Скорость:</b> $v = \\dfrac{s}{t}$, $[v] = $ м/с</li>'
|
||
+ '</ul>');
|
||
|
||
h += makeCard('example', 'Объём картофеля', '§ 4.3',
|
||
'Картофелина имеет неправильную форму — линейкой её не измерить. Но можно сделать так:'
|
||
+ '<ol style="padding-left:20px;margin:6px 0">'
|
||
+ '<li>Налить в мензурку воды до отметки $V_1 = 200$ мл (прямое измерение).</li>'
|
||
+ '<li>Опустить картофелину; уровень поднялся до $V_2 = 280$ мл (прямое).</li>'
|
||
+ '<li>Объём картофелины: $V = V_2 - V_1 = 80$ мл $= 80$ см³ (косвенное).</li>'
|
||
+ '</ol>');
|
||
|
||
/* IV-1: лаборатория приборов */
|
||
h += wgWrap('p4-iv1', 'СИМ', 'Лаборатория измерительных приборов', 'Каждый прибор даёт <i>прямое</i> измерение одной величины.',
|
||
'<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:10px">'
|
||
+ [
|
||
['Линейка','длина','м, см, мм','#0284c7'],
|
||
['Весы','масса','кг, г','#7c3aed'],
|
||
['Термометр','температура','°C','#dc2626'],
|
||
['Секундомер','время','с, мин','#10b981'],
|
||
['Мензурка','объём жидкости','мл, л','#0891b2'],
|
||
['Динамометр','сила','Н','#d97706']
|
||
].map(([nm, v, u, col]) =>
|
||
'<div style="background:#f0f9ff;border:1.5px solid ' + col + ';border-radius:10px;padding:12px;text-align:center">'
|
||
+ '<div style="font-family:Unbounded,sans-serif;font-weight:800;color:' + col + ';font-size:.96rem">' + nm + '</div>'
|
||
+ '<div style="font-size:.84rem;color:#475569;margin-top:4px">' + v + '</div>'
|
||
+ '<div style="font-size:.76rem;color:#64748b;margin-top:2px;font-family:JetBrains Mono,monospace">' + u + '</div>'
|
||
+ '</div>').join('')
|
||
+ '</div>');
|
||
|
||
/* IV-2: главный калькулятор косвенных измерений */
|
||
h += wgWrap('p4-iv2', 'КАЛЬК', 'Калькулятор косвенных измерений', 'Меняй размеры $a, b, c$ и массу $m$ — формулы пересчитываются автоматически.',
|
||
'<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:10px;margin-bottom:12px">'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid #bae6fd">$a$, см: <b id="p4-a" style="color:#0c4a6e;font-family:JetBrains Mono,monospace">10</b><input type="range" id="p4-a-r" min="1" max="50" step="1" value="10" style="display:block;width:100%;margin-top:6px;accent-color:#0284c7"></label>'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid #bae6fd">$b$, см: <b id="p4-b" style="color:#0c4a6e;font-family:JetBrains Mono,monospace">5</b><input type="range" id="p4-b-r" min="1" max="50" step="1" value="5" style="display:block;width:100%;margin-top:6px;accent-color:#0284c7"></label>'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid #bae6fd">$c$, см: <b id="p4-c" style="color:#0c4a6e;font-family:JetBrains Mono,monospace">3</b><input type="range" id="p4-c-r" min="1" max="50" step="1" value="3" style="display:block;width:100%;margin-top:6px;accent-color:#0284c7"></label>'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid #bae6fd">$m$, г: <b id="p4-m" style="color:#0c4a6e;font-family:JetBrains Mono,monospace">405</b><input type="range" id="p4-m-r" min="10" max="5000" step="5" value="405" style="display:block;width:100%;margin-top:6px;accent-color:#0284c7"></label>'
|
||
+ '</div>'
|
||
+ '<div style="background:#e0f2fe;border-radius:9px;padding:12px 14px;display:flex;flex-direction:column;gap:6px;font-size:.94rem">'
|
||
+ '<div>Площадь: $S = a b = $ <b id="p4-S" style="color:#0c4a6e;font-family:JetBrains Mono,monospace">50</b> см²</div>'
|
||
+ '<div>Объём: $V = a b c = $ <b id="p4-V" style="color:#0c4a6e;font-family:JetBrains Mono,monospace">150</b> см³</div>'
|
||
+ '<div>Плотность: $\\rho = m/V = $ <b id="p4-rho" style="color:#0c4a6e;font-family:JetBrains Mono,monospace">2.7</b> г/см³ <span id="p4-rho-name" style="color:#475569;font-size:.84rem;margin-left:6px">(близко к алюминию)</span></div>'
|
||
+ '</div>');
|
||
|
||
/* IV-3: DnD прямое/косвенное */
|
||
h += wgWrap('p4-iv3', 'DnD', 'Прямое или косвенное?', 'Распредели измерения по типу.',
|
||
dndPool('p4-dnd', [
|
||
{ id:'a1', cat:'dir', html:'Длина книги линейкой' },
|
||
{ id:'a2', cat:'ind', html:'Площадь стола из длины × ширины' },
|
||
{ id:'a3', cat:'dir', html:'Температура воздуха термометром' },
|
||
{ id:'a4', cat:'ind', html:'Скорость велосипедиста (путь / время)' },
|
||
{ id:'a5', cat:'dir', html:'Время урока секундомером' },
|
||
{ id:'a6', cat:'ind', html:'Объём картофеля через вытеснение воды' },
|
||
{ id:'a7', cat:'dir', html:'Масса яблока на весах' },
|
||
{ id:'a8', cat:'ind', html:'Плотность металла $\\rho = m/V$' }
|
||
], [
|
||
{ cat:'dir', label:'Прямое' },
|
||
{ cat:'ind', label:'Косвенное' }
|
||
]));
|
||
|
||
/* IV-4: тренажёр расчётных */
|
||
h += wgWrap('p4-iv4', 'ТРН', 'Тренажёр §4', '5 расчётных задач.',
|
||
'<div id="p4-tr-host">'
|
||
+ quizQuestion('p4-tr', 0, 'Прямоугольник: $a = 6$ см, $b = 4$ см. Площадь $S = ?$', ['10 см²','24 см²','12 см²','20 см²'], 1, '$S = 6 \\cdot 4 = 24$ см².')
|
||
+ quizQuestion('p4-tr', 1, 'Кирпич: $a = 25$ см, $b = 12$ см, $c = 6{,}5$ см. Объём $V$?', ['1900 см³','1950 см³','2000 см³','2500 см³'], 1, '$V = 25 \\cdot 12 \\cdot 6{,}5 = 1950$ см³.')
|
||
+ quizQuestion('p4-tr', 2, 'Тело массой $m = 200$ г занимает объём $V = 25$ см³. Плотность?', ['4 г/см³','6 г/см³','8 г/см³','10 г/см³'], 2, '$\\rho = m/V = 200/25 = 8$ г/см³ (близко к железу).')
|
||
+ quizQuestion('p4-tr', 3, 'Путь $s = 60$ м, время $t = 12$ с. Скорость?', ['4 м/с','5 м/с','6 м/с','8 м/с'], 1, '$v = s/t = 60/12 = 5$ м/с.')
|
||
+ quizQuestion('p4-tr', 4, 'В мензурку с водой $V_1 = 50$ мл опустили камень — уровень поднялся до $V_2 = 78$ мл. Объём камня?', ['22 мл','28 мл','32 мл','78 мл'], 1, '$V = V_2 - V_1 = 78 - 50 = 28$ мл.')
|
||
+ '</div>');
|
||
|
||
h += readButton('p4');
|
||
|
||
body.innerHTML = h;
|
||
|
||
// Wire calc §4 IV-2
|
||
const upd = () => {
|
||
const a = +document.getElementById('p4-a-r').value;
|
||
const b = +document.getElementById('p4-b-r').value;
|
||
const c = +document.getElementById('p4-c-r').value;
|
||
const m = +document.getElementById('p4-m-r').value;
|
||
document.getElementById('p4-a').textContent = a;
|
||
document.getElementById('p4-b').textContent = b;
|
||
document.getElementById('p4-c').textContent = c;
|
||
document.getElementById('p4-m').textContent = m;
|
||
const S = a * b;
|
||
const V = a * b * c;
|
||
const rho = m / V;
|
||
document.getElementById('p4-S').textContent = S;
|
||
document.getElementById('p4-V').textContent = V;
|
||
document.getElementById('p4-rho').textContent = rho.toFixed(2);
|
||
// Угадывание вещества по плотности (г/см³)
|
||
let name = '';
|
||
if(rho < 0.3) name = '(легче пенопласта — нереально!)';
|
||
else if(rho < 0.7) name = '(дерево / сосна)';
|
||
else if(rho < 1.1) name = '(вода или лёд)';
|
||
else if(rho < 3.5) name = '(алюминий / стекло)';
|
||
else if(rho < 9) name = '(железо / медь)';
|
||
else if(rho < 15) name = '(свинец / ртуть)';
|
||
else if(rho < 22) name = '(золото / платина)';
|
||
else name = '(плотнее любого металла)';
|
||
document.getElementById('p4-rho-name').textContent = name;
|
||
};
|
||
['p4-a-r','p4-b-r','p4-c-r','p4-m-r'].forEach(id => document.getElementById(id).addEventListener('input', upd));
|
||
upd();
|
||
|
||
wireDnd('p4-dnd', [
|
||
{ id:'a1', cat:'dir' },{ id:'a2', cat:'ind' },{ id:'a3', cat:'dir' },{ id:'a4', cat:'ind' },
|
||
{ id:'a5', cat:'dir' },{ id:'a6', cat:'ind' },{ id:'a7', cat:'dir' },{ id:'a8', cat:'ind' }
|
||
], []);
|
||
wireQuiz('p4-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p4'); });
|
||
wireReadBtn('p4');
|
||
renderMath(body);
|
||
}
|
||
|
||
/* ========================================================== */
|
||
/* §5 — Единицы измерения физических величин. СИ */
|
||
/* ========================================================== */
|
||
function add_p5(){
|
||
const body = document.getElementById('p5-body');
|
||
if(!body) return;
|
||
let h = '';
|
||
|
||
h += makeCard('theory', 'Зачем СИ?', '§ 5.1',
|
||
'Если каждый учёный использует свои единицы — результаты невозможно сравнить. '
|
||
+ 'В 1960 году принята <b>Международная система единиц (СИ)</b> — единый стандарт. '
|
||
+ 'В СИ — <b>7 основных единиц</b>; все остальные получаются комбинацией основных.');
|
||
|
||
h += makeCard('rule', '7 основных единиц СИ', '§ 5.2',
|
||
'<table style="width:100%;border-collapse:collapse;margin-top:4px;font-size:.92rem">'
|
||
+ '<tr style="background:#e0f2fe"><th style="text-align:left;padding:6px 10px;border-bottom:2px solid #0284c7">Величина</th><th style="text-align:left;padding:6px 10px;border-bottom:2px solid #0284c7">Единица</th><th style="text-align:left;padding:6px 10px;border-bottom:2px solid #0284c7">Обозначение</th></tr>'
|
||
+ [['Длина','метр','м'],['Масса','килограмм','кг'],['Время','секунда','с'],['Сила тока','ампер','А'],['Температура','кельвин','К'],['Кол-во вещества','моль','моль'],['Сила света','кандела','кд']].map(([v,u,s]) =>
|
||
'<tr><td style="padding:5px 10px;border-bottom:1px solid #e0f2fe">' + v + '</td><td style="padding:5px 10px;border-bottom:1px solid #e0f2fe"><b>' + u + '</b></td><td style="padding:5px 10px;border-bottom:1px solid #e0f2fe;font-family:JetBrains Mono,monospace;color:#0c4a6e">' + s + '</td></tr>').join('')
|
||
+ '</table>');
|
||
|
||
h += makeCard('example', 'Кратные и дольные приставки', '§ 5.3',
|
||
'<table style="width:100%;border-collapse:collapse;margin-top:4px;font-size:.92rem">'
|
||
+ '<tr style="background:#e0f2fe"><th style="text-align:left;padding:6px 10px">Приставка</th><th style="text-align:left;padding:6px 10px">Множитель</th><th style="text-align:left;padding:6px 10px">Пример</th></tr>'
|
||
+ [['Г (гига)','$10^9$','1 ГГц = $10^9$ Гц'],['М (мега)','$10^6$','1 МВт = $10^6$ Вт'],['к (кило)','$10^3$','1 кг = 1000 г'],['—','1','1 м'],['м (милли)','$10^{-3}$','1 мс = 0,001 с'],['мк (микро)','$10^{-6}$','1 мкм = $10^{-6}$ м'],['н (нано)','$10^{-9}$','1 нс = $10^{-9}$ с']].map(([pf,k,ex]) =>
|
||
'<tr><td style="padding:4px 10px;border-bottom:1px solid #e0f2fe"><b>' + pf + '</b></td><td style="padding:4px 10px;border-bottom:1px solid #e0f2fe">' + k + '</td><td style="padding:4px 10px;border-bottom:1px solid #e0f2fe;font-family:JetBrains Mono,monospace;font-size:.84rem">' + ex + '</td></tr>').join('')
|
||
+ '</table>');
|
||
|
||
/* IV-1: визуал — 7 основных */
|
||
h += wgWrap('p5-iv1', 'СИМ', '7 китов СИ', 'Семь основных единиц — фундамент всех физических измерений.',
|
||
'<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:10px">'
|
||
+ [['Длина','м','#0284c7'],['Масса','кг','#7c3aed'],['Время','с','#10b981'],['Ток','А','#d97706'],['Темп.','К','#dc2626'],['Вещ-во','моль','#0891b2'],['Свет','кд','#fbbf24']].map(([v, u, col]) =>
|
||
'<div style="background:linear-gradient(135deg,' + col + ',' + col + '99);color:#fff;border-radius:11px;padding:14px 10px;text-align:center;box-shadow:0 3px 10px rgba(0,0,0,.12)">'
|
||
+ '<div style="font-family:JetBrains Mono,monospace;font-weight:900;font-size:1.6rem">' + u + '</div>'
|
||
+ '<div style="font-weight:700;font-size:.84rem;margin-top:4px;opacity:.95">' + v + '</div>'
|
||
+ '</div>').join('')
|
||
+ '</div>');
|
||
|
||
/* IV-2: главный конвертер */
|
||
h += wgWrap('p5-iv2', 'КАЛЬК', 'Конвертер единиц', 'Выбери приставку и величину — увидь перевод в основную единицу СИ.',
|
||
'<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px;margin-bottom:12px">'
|
||
+ '<label style="display:block;font-size:.84rem;color:#475569;background:#fff;padding:8px 10px;border-radius:8px;border:1px solid #bae6fd">Число: <b id="p5-n" style="color:#0c4a6e;font-family:JetBrains Mono,monospace">5</b><input type="range" id="p5-n-r" min="1" max="999" step="1" value="5" style="display:block;width:100%;margin-top:6px;accent-color:#0284c7"></label>'
|
||
+ '<label style="display:block;font-size:.84rem;color:#475569;background:#fff;padding:8px 10px;border-radius:8px;border:1px solid #bae6fd">Приставка:<select id="p5-pf" style="width:100%;margin-top:6px;padding:5px;border-radius:6px;border:1px solid #bae6fd;font-family:inherit"><option value="1e9">Г (гига, $10^9$)</option><option value="1e6">М (мега, $10^6$)</option><option value="1e3" selected>к (кило, $10^3$)</option><option value="1">— (без приставки)</option><option value="1e-2">с (санти, $10^{-2}$)</option><option value="1e-3">м (милли, $10^{-3}$)</option><option value="1e-6">мк (микро, $10^{-6}$)</option><option value="1e-9">н (нано, $10^{-9}$)</option></select></label>'
|
||
+ '<label style="display:block;font-size:.84rem;color:#475569;background:#fff;padding:8px 10px;border-radius:8px;border:1px solid #bae6fd">Единица:<select id="p5-u" style="width:100%;margin-top:6px;padding:5px;border-radius:6px;border:1px solid #bae6fd;font-family:inherit"><option value="м" selected>м (метр)</option><option value="г">г (грамм)</option><option value="с">с (секунда)</option><option value="Вт">Вт (ватт)</option><option value="Гц">Гц (герц)</option><option value="Н">Н (ньютон)</option></select></label>'
|
||
+ '</div>'
|
||
+ '<div style="background:#e0f2fe;border-radius:9px;padding:12px 14px;font-size:.96rem">'
|
||
+ '<span id="p5-src" style="font-family:JetBrains Mono,monospace;color:#0c4a6e;font-weight:700">5 км</span>'
|
||
+ ' = '
|
||
+ '<span id="p5-dst" style="font-family:JetBrains Mono,monospace;color:#0c4a6e;font-weight:700">5000 м</span>'
|
||
+ '<div id="p5-explain" style="font-size:.82rem;color:#475569;margin-top:6px"></div>'
|
||
+ '</div>');
|
||
|
||
/* IV-3: DnD — величина ↔ единица СИ */
|
||
h += wgWrap('p5-iv3', 'DnD', 'Величина ↔ единица СИ', 'Соедини каждую величину с её основной единицей.',
|
||
dndPool('p5-dnd', [
|
||
{ id:'a1', cat:'m', html:'Длина' },
|
||
{ id:'a2', cat:'kg', html:'Масса' },
|
||
{ id:'a3', cat:'s', html:'Время' },
|
||
{ id:'a4', cat:'K', html:'Температура' },
|
||
{ id:'a5', cat:'A', html:'Сила тока' },
|
||
{ id:'a6', cat:'m', html:'Расстояние от Минска до Бреста' },
|
||
{ id:'a7', cat:'kg', html:'Масса арбуза' },
|
||
{ id:'a8', cat:'s', html:'Длительность урока' }
|
||
], [
|
||
{ cat:'m', label:'метр (м)' },
|
||
{ cat:'kg', label:'килограмм (кг)' },
|
||
{ cat:'s', label:'секунда (с)' },
|
||
{ cat:'K', label:'кельвин (К)' },
|
||
{ cat:'A', label:'ампер (А)' }
|
||
]));
|
||
|
||
/* IV-4: тренажёр на перевод */
|
||
h += wgWrap('p5-iv4', 'ТРН', 'Тренажёр §5', '5 задач на перевод единиц.',
|
||
'<div id="p5-tr-host">'
|
||
+ quizQuestion('p5-tr', 0, '$5$ км $= ?$ м', ['50','500','5 000','50 000'], 2, '$5 \\cdot 1000 = 5\\,000$ м.')
|
||
+ quizQuestion('p5-tr', 1, '$0{,}25$ кг $= ?$ г', ['25','100','250','2500'], 2, '$0{,}25 \\cdot 1000 = 250$ г.')
|
||
+ quizQuestion('p5-tr', 2, '$2$ ч $= ?$ с', ['120','3 600','7 200','12 000'], 2, '$2 \\cdot 60 \\cdot 60 = 7\\,200$ с.')
|
||
+ quizQuestion('p5-tr', 3, '$300$ мс $= ?$ с', ['0,03','0,3','3','30'], 1, '$300 \\cdot 10^{-3} = 0{,}3$ с.')
|
||
+ quizQuestion('p5-tr', 4, '$1$ см² $= ?$ м²', ['0,1','0,01','0,001','0,0001'], 3, '$1\\,\\text{см}^2 = (10^{-2}\\,\\text{м})^2 = 10^{-4}\\,\\text{м}^2$.')
|
||
+ '</div>');
|
||
|
||
h += readButton('p5');
|
||
|
||
body.innerHTML = h;
|
||
|
||
// Wire converter §5 IV-2
|
||
const updConv = () => {
|
||
const n = +document.getElementById('p5-n-r').value;
|
||
const pf = +document.getElementById('p5-pf').value;
|
||
const u = document.getElementById('p5-u').value;
|
||
document.getElementById('p5-n').textContent = n;
|
||
const prefixLabels = { '1000000000':'Г','1000000':'М','1000':'к','1':'','0.01':'с','0.001':'м','1e-6':'мк','1e-9':'н' };
|
||
// Получим символ по value
|
||
const sel = document.getElementById('p5-pf');
|
||
const pfLabel = (sel.options[sel.selectedIndex].text.match(/^([А-Яа-я—]+)/) || ['',''])[1];
|
||
const result = n * pf;
|
||
// Format result
|
||
let resStr;
|
||
if(Math.abs(result) >= 1e6 || (Math.abs(result) > 0 && Math.abs(result) < 0.001)) resStr = result.toExponential(2);
|
||
else if(Number.isInteger(result)) resStr = result.toLocaleString('ru-RU');
|
||
else resStr = (+result.toPrecision(6)).toLocaleString('ru-RU');
|
||
document.getElementById('p5-src').textContent = n + ' ' + pfLabel + u;
|
||
document.getElementById('p5-dst').textContent = resStr + ' ' + u;
|
||
const explain = pf === 1 ? 'Без приставки.' : ('Множитель ' + (pf >= 1 ? pf.toLocaleString('ru-RU') : pf) + '. Умножаем число на этот множитель.');
|
||
document.getElementById('p5-explain').textContent = explain;
|
||
};
|
||
document.getElementById('p5-n-r').addEventListener('input', updConv);
|
||
document.getElementById('p5-pf').addEventListener('change', updConv);
|
||
document.getElementById('p5-u').addEventListener('change', updConv);
|
||
updConv();
|
||
|
||
wireDnd('p5-dnd', [
|
||
{ id:'a1', cat:'m' },{ id:'a2', cat:'kg' },{ id:'a3', cat:'s' },{ id:'a4', cat:'K' },
|
||
{ id:'a5', cat:'A' },{ id:'a6', cat:'m' },{ id:'a7', cat:'kg' },{ id:'a8', cat:'s' }
|
||
], []);
|
||
wireQuiz('p5-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p5'); });
|
||
wireReadBtn('p5');
|
||
renderMath(body);
|
||
}
|
||
|
||
/* ========================================================== */
|
||
/* §6 — Действия над физическими величинами */
|
||
/* ========================================================== */
|
||
function add_p6(){
|
||
const body = document.getElementById('p6-body');
|
||
if(!body) return;
|
||
let h = '';
|
||
|
||
h += makeCard('theory', 'Правила сложения и сравнения', '§ 6.1',
|
||
'Складывать, вычитать и сравнивать можно <b>только однородные величины</b> (одного типа) '
|
||
+ 'и только в <b>одинаковых единицах</b>. Нельзя сложить $2$ кг и $3$ м — это разные физические величины. '
|
||
+ 'Нельзя сложить $5$ м и $2$ см без предварительного перевода в одну единицу: $5$ м $+ 0{,}02$ м $= 5{,}02$ м.');
|
||
|
||
h += makeCard('rule', 'Перевод между разными системами', '§ 6.2',
|
||
'<b>Скорость:</b> $1$ км/ч $= \\dfrac{1000\\,\\text{м}}{3600\\,\\text{с}} \\approx 0{,}278$ м/с;<br>'
|
||
+ 'обратно: $1$ м/с $= 3{,}6$ км/ч.<br><br>'
|
||
+ '<b>Плотность:</b> $1$ г/см³ $= 1000$ кг/м³ (умножаем на $1000$).<br><br>'
|
||
+ '<b>Мощность:</b> $1$ л. с. $= 736$ Вт; $1$ кВт $= 1000$ Вт.<br><br>'
|
||
+ '<b>Энергия / работа:</b> $1$ кДж $= 1000$ Дж, $1$ кВт·ч $= 3{,}6 \\cdot 10^6$ Дж.');
|
||
|
||
h += makeCard('example', 'Умножение / деление величин', '§ 6.3',
|
||
'При действиях с величинами <b>числа умножаются/делятся отдельно от единиц</b>:'
|
||
+ '<ul style="padding-left:20px;margin:6px 0">'
|
||
+ '<li>$v \\cdot t = 5\\,\\dfrac{\\text{м}}{\\text{с}} \\cdot 4\\,\\text{с} = 20\\,\\text{м}$ (секунды сократились — получили путь)</li>'
|
||
+ '<li>$\\dfrac{m}{V} = \\dfrac{200\\,\\text{г}}{50\\,\\text{см}^3} = 4\\,\\dfrac{\\text{г}}{\\text{см}^3}$</li>'
|
||
+ '<li>$S = 2\\,\\text{м} \\cdot 3\\,\\text{м} = 6\\,\\text{м}^2$ (метры в квадрате)</li>'
|
||
+ '</ul>');
|
||
|
||
/* IV-1: визуал — таблица переводов скорости */
|
||
h += wgWrap('p6-iv1', 'СИМ', 'Скорости в природе', 'Сравни типичные скорости — одно и то же в разных единицах.',
|
||
'<table style="width:100%;border-collapse:collapse;font-size:.9rem">'
|
||
+ '<tr style="background:#e0f2fe"><th style="padding:6px 10px;text-align:left;border-bottom:2px solid #0284c7">Объект</th><th style="padding:6px 10px;text-align:right;border-bottom:2px solid #0284c7">м/с</th><th style="padding:6px 10px;text-align:right;border-bottom:2px solid #0284c7">км/ч</th></tr>'
|
||
+ [['Улитка',0.001,0.0036],['Пешеход',1.4,5],['Велосипедист',5.5,20],['Автомобиль в городе',16.7,60],['Гепард',31,112],['Самолёт',250,900],['Звук в воздухе',340,1224]].map(([nm,ms,kh]) =>
|
||
'<tr><td style="padding:5px 10px;border-bottom:1px solid #e0f2fe">' + nm + '</td><td style="padding:5px 10px;text-align:right;border-bottom:1px solid #e0f2fe;font-family:JetBrains Mono,monospace">' + ms + '</td><td style="padding:5px 10px;text-align:right;border-bottom:1px solid #e0f2fe;font-family:JetBrains Mono,monospace">' + kh + '</td></tr>').join('')
|
||
+ '</table>');
|
||
|
||
/* IV-2: главный калькулятор-конвертер */
|
||
h += wgWrap('p6-iv2', 'КАЛЬК', 'Конвертер величин', 'Выбери, что переводишь — двигай slider.',
|
||
'<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:12px">'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid #bae6fd">Что переводим:<select id="p6-kind" style="width:100%;margin-top:5px;padding:6px;border-radius:6px;border:1px solid #bae6fd;font-family:inherit"><option value="vel" selected>Скорость</option><option value="den">Плотность</option><option value="pow">Мощность</option><option value="en">Энергия</option><option value="t">Время</option></select></label>'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid #bae6fd">Значение: <b id="p6-v" style="color:#0c4a6e;font-family:JetBrains Mono,monospace">60</b><input type="range" id="p6-v-r" min="1" max="1000" step="1" value="60" style="display:block;width:100%;margin-top:6px;accent-color:#0284c7"></label>'
|
||
+ '</div>'
|
||
+ '<div id="p6-out" style="background:#e0f2fe;border-radius:9px;padding:12px 14px;font-size:.94rem;line-height:1.7"></div>');
|
||
|
||
/* IV-3: DnD равные величины */
|
||
h += wgWrap('p6-iv3', 'DnD', 'Найди равные пары', 'Соедини 8 эквивалентных записей.',
|
||
dndPool('p6-dnd', [
|
||
{ id:'a1', cat:'60', html:'$1$ мин' },
|
||
{ id:'a2', cat:'1000', html:'$1$ кВт' },
|
||
{ id:'a3', cat:'10', html:'$10$ см' },
|
||
{ id:'a4', cat:'500', html:'$\\dfrac{1}{2}$ кг' },
|
||
{ id:'a5', cat:'60', html:'$60$ с' },
|
||
{ id:'a6', cat:'1000', html:'$1000$ Вт' },
|
||
{ id:'a7', cat:'10', html:'$0{,}1$ м' },
|
||
{ id:'a8', cat:'500', html:'$500$ г' }
|
||
], [
|
||
{ cat:'60', label:'1 мин = 60 с' },
|
||
{ cat:'1000', label:'1 кВт = 1000 Вт' },
|
||
{ cat:'10', label:'10 см = 0,1 м' },
|
||
{ cat:'500', label:'0,5 кг = 500 г' }
|
||
]));
|
||
|
||
/* IV-4: тренажёр */
|
||
h += wgWrap('p6-iv4', 'ТРН', 'Тренажёр §6', '5 задач на действия с величинами.',
|
||
'<div id="p6-tr-host">'
|
||
+ quizQuestion('p6-tr', 0, '$72$ км/ч $= ?$ м/с', ['10','15','20','25'], 2, '$72 / 3{,}6 = 20$ м/с.')
|
||
+ quizQuestion('p6-tr', 1, '$5$ м/с $= ?$ км/ч', ['15','18','20','25'], 1, '$5 \\cdot 3{,}6 = 18$ км/ч.')
|
||
+ quizQuestion('p6-tr', 2, '$2{,}5$ г/см³ $= ?$ кг/м³', ['25','250','2500','25000'], 2, '$2{,}5 \\cdot 1000 = 2500$ кг/м³.')
|
||
+ quizQuestion('p6-tr', 3, '$3$ ч $20$ мин $= ?$ с', ['12 000','11 200','12 200','13 200'], 0, '$3 \\cdot 3600 + 20 \\cdot 60 = 10\\,800 + 1\\,200 = 12\\,000$ с.')
|
||
+ quizQuestion('p6-tr', 4, 'Сложить: $5$ м $+ 40$ см $+ 10$ мм $= ?$ м', ['5,41','5,5','5,401','5,41'], 0, '$5 + 0{,}40 + 0{,}010 = 5{,}41$ м.')
|
||
+ '</div>');
|
||
|
||
h += readButton('p6');
|
||
|
||
body.innerHTML = h;
|
||
|
||
// Wire converter §6 IV-2
|
||
const updConv6 = () => {
|
||
const kind = document.getElementById('p6-kind').value;
|
||
const v = +document.getElementById('p6-v-r').value;
|
||
document.getElementById('p6-v').textContent = v;
|
||
const out = document.getElementById('p6-out');
|
||
let html = '';
|
||
if(kind === 'vel'){
|
||
html = '$' + v + '$ км/ч $= $ <b style="color:#0c4a6e;font-family:JetBrains Mono,monospace">' + (v / 3.6).toFixed(2) + '</b> м/с'
|
||
+ '<br>$' + v + '$ м/с $= $ <b style="color:#0c4a6e;font-family:JetBrains Mono,monospace">' + (v * 3.6).toFixed(1) + '</b> км/ч';
|
||
} else if(kind === 'den'){
|
||
html = '$' + v + '$ г/см³ $= $ <b style="color:#0c4a6e;font-family:JetBrains Mono,monospace">' + (v * 1000).toLocaleString('ru-RU') + '</b> кг/м³';
|
||
} else if(kind === 'pow'){
|
||
html = '$' + v + '$ кВт $= $ <b style="color:#0c4a6e;font-family:JetBrains Mono,monospace">' + (v * 1000).toLocaleString('ru-RU') + '</b> Вт'
|
||
+ '<br>$' + v + '$ л. с. $= $ <b style="color:#0c4a6e;font-family:JetBrains Mono,monospace">' + (v * 736).toLocaleString('ru-RU') + '</b> Вт';
|
||
} else if(kind === 'en'){
|
||
html = '$' + v + '$ кДж $= $ <b style="color:#0c4a6e;font-family:JetBrains Mono,monospace">' + (v * 1000).toLocaleString('ru-RU') + '</b> Дж'
|
||
+ '<br>$' + v + '$ кВт·ч $= $ <b style="color:#0c4a6e;font-family:JetBrains Mono,monospace">' + (v * 3.6e6).toExponential(2) + '</b> Дж';
|
||
} else if(kind === 't'){
|
||
html = '$' + v + '$ мин $= $ <b style="color:#0c4a6e;font-family:JetBrains Mono,monospace">' + (v * 60).toLocaleString('ru-RU') + '</b> с'
|
||
+ '<br>$' + v + '$ ч $= $ <b style="color:#0c4a6e;font-family:JetBrains Mono,monospace">' + (v * 3600).toLocaleString('ru-RU') + '</b> с';
|
||
}
|
||
out.innerHTML = html;
|
||
renderMath(out);
|
||
};
|
||
document.getElementById('p6-kind').addEventListener('change', updConv6);
|
||
document.getElementById('p6-v-r').addEventListener('input', updConv6);
|
||
updConv6();
|
||
|
||
wireDnd('p6-dnd', [
|
||
{ id:'a1', cat:'60' },{ id:'a2', cat:'1000' },{ id:'a3', cat:'10' },{ id:'a4', cat:'500' },
|
||
{ id:'a5', cat:'60' },{ id:'a6', cat:'1000' },{ id:'a7', cat:'10' },{ id:'a8', cat:'500' }
|
||
], []);
|
||
wireQuiz('p6-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p6'); });
|
||
wireReadBtn('p6');
|
||
renderMath(body);
|
||
}
|
||
|
||
/* ========================================================== */
|
||
/* §7 — Измерительные приборы. Цена деления. Погрешность */
|
||
/* ========================================================== */
|
||
function add_p7(){
|
||
const body = document.getElementById('p7-body');
|
||
if(!body) return;
|
||
let h = '';
|
||
|
||
h += makeCard('theory', 'Цена деления шкалы', '§ 7.1',
|
||
'<b>Цена деления</b> — это значение наименьшего деления на шкале прибора. Формула:<br>'
|
||
+ '$$C = \\dfrac{X_2 - X_1}{N}$$ где $X_1$, $X_2$ — два соседних подписанных значения, $N$ — число малых делений между ними.<br><br>'
|
||
+ '<b>Пример:</b> на линейке между отметками $0$ и $1$ см нанесено $10$ делений. '
|
||
+ '$C = (1 - 0)/10 = 0{,}1$ см $= 1$ мм.');
|
||
|
||
h += makeCard('rule', 'Погрешность измерения', '§ 7.2',
|
||
'Любое измерение имеет <b>погрешность</b> $\\Delta X$. Обычно берут <b>половину цены деления</b>:<br>'
|
||
+ '$$\\Delta X = \\dfrac{C}{2}$$'
|
||
+ 'Результат записывают как $X = X_0 \\pm \\Delta X$, например: $l = (15{,}3 \\pm 0{,}05)$ см.<br><br>'
|
||
+ 'Чем <b>меньше цена деления</b>, тем <b>точнее</b> прибор.');
|
||
|
||
h += makeCard('example', 'Как снять отсчёт', '§ 7.3',
|
||
'<b>Правила:</b>'
|
||
+ '<ol style="padding-left:20px;margin:6px 0">'
|
||
+ '<li>Определи цену деления по двум соседним подписанным отметкам.</li>'
|
||
+ '<li>Смотри на шкалу <b>перпендикулярно</b> (избегая параллакса).</li>'
|
||
+ '<li>Если стрелка между делениями — округли до ближайшего.</li>'
|
||
+ '<li>Запиши с погрешностью $\\pm C/2$.</li>'
|
||
+ '</ol>');
|
||
|
||
/* IV-1: главный визуал — виртуальная линейка с переключаемой ценой деления */
|
||
h += wgWrap('p7-iv1', 'СИМ', 'Виртуальная линейка', 'Меняй цену деления и положение риски — наблюдай, как меняется точность.',
|
||
'<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:14px">'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid #bae6fd">Цена деления:<select id="p7-cd" style="width:100%;margin-top:5px;padding:6px;border-radius:6px;border:1px solid #bae6fd;font-family:inherit"><option value="10">10 мм (грубая)</option><option value="5">5 мм</option><option value="2">2 мм</option><option value="1" selected>1 мм (стандартная)</option></select></label>'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid #bae6fd">Положение риски, мм: <b id="p7-pos" style="color:#0c4a6e;font-family:JetBrains Mono,monospace">37</b><input type="range" id="p7-pos-r" min="0" max="100" step="1" value="37" style="display:block;width:100%;margin-top:6px;accent-color:#0284c7"></label>'
|
||
+ '</div>'
|
||
+ '<div style="background:#fff;border:1.5px solid #bae6fd;border-radius:10px;padding:14px;text-align:center;overflow-x:auto">'
|
||
+ '<svg id="p7-svg" viewBox="0 0 360 80" width="100%" style="max-width:600px;display:block;margin:0 auto"></svg>'
|
||
+ '</div>'
|
||
+ '<div id="p7-info" style="background:#e0f2fe;border-radius:9px;padding:10px 14px;margin-top:10px;font-size:.94rem;line-height:1.7"></div>');
|
||
|
||
/* IV-2: калькулятор цены деления */
|
||
h += wgWrap('p7-iv2', 'КАЛЬК', 'Калькулятор цены деления', 'Введи две подписанные отметки и количество делений.',
|
||
'<div style="display:grid;grid-template-columns:repeat(3,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 #bae6fd">$X_1$: <b id="p7-x1" style="color:#0c4a6e;font-family:JetBrains Mono,monospace">0</b><input type="range" id="p7-x1-r" min="0" max="50" step="1" value="0" style="display:block;width:100%;margin-top:6px;accent-color:#0284c7"></label>'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid #bae6fd">$X_2$: <b id="p7-x2" style="color:#0c4a6e;font-family:JetBrains Mono,monospace">10</b><input type="range" id="p7-x2-r" min="5" max="100" step="1" value="10" style="display:block;width:100%;margin-top:6px;accent-color:#0284c7"></label>'
|
||
+ '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid #bae6fd">$N$ (делений): <b id="p7-N" style="color:#0c4a6e;font-family:JetBrains Mono,monospace">10</b><input type="range" id="p7-N-r" min="2" max="50" step="1" value="10" style="display:block;width:100%;margin-top:6px;accent-color:#0284c7"></label>'
|
||
+ '</div>'
|
||
+ '<div style="background:#e0f2fe;border-radius:9px;padding:12px 14px;font-size:.94rem;line-height:1.7">'
|
||
+ 'Цена деления: $C = \\dfrac{X_2 - X_1}{N} = \\dfrac{$<span id="p7-cd2-x2">10</span>$ - $<span id="p7-cd2-x1">0</span>$}{$<span id="p7-cd2-N">10</span>$} = $ <b id="p7-cd2" style="color:#0c4a6e;font-family:JetBrains Mono,monospace">1</b>'
|
||
+ '<br>Погрешность: $\\Delta X = C/2 = $ <b id="p7-dx" style="color:#dc2626;font-family:JetBrains Mono,monospace">0,5</b>'
|
||
+ '</div>');
|
||
|
||
/* IV-3: DnD — соедини прибор с подходящей ценой деления */
|
||
h += wgWrap('p7-iv3', 'DnD', 'Прибор и его точность', 'Соотнеси приборы и их типичную цену деления.',
|
||
dndPool('p7-dnd', [
|
||
{ id:'a1', cat:'mm', html:'Школьная линейка' },
|
||
{ id:'a2', cat:'01mm', html:'Штангенциркуль' },
|
||
{ id:'a3', cat:'001mm', html:'Микрометр' },
|
||
{ id:'a4', cat:'1c', html:'Бытовой термометр' },
|
||
{ id:'a5', cat:'01c', html:'Лабораторный термометр' },
|
||
{ id:'a6', cat:'01s', html:'Школьный секундомер' }
|
||
], [
|
||
{ cat:'mm', label:'1 мм' },
|
||
{ cat:'01mm', label:'0,1 мм' },
|
||
{ cat:'001mm', label:'0,01 мм' },
|
||
{ cat:'1c', label:'1 °C' },
|
||
{ cat:'01c', label:'0,1 °C' },
|
||
{ cat:'01s', label:'0,1 с' }
|
||
]));
|
||
|
||
/* IV-4: тренажёр */
|
||
h += wgWrap('p7-iv4', 'ТРН', 'Тренажёр §7', '5 задач на цену деления и погрешность.',
|
||
'<div id="p7-tr-host">'
|
||
+ quizQuestion('p7-tr', 0, 'Между отметками $0$ и $1$ см на линейке $10$ маленьких делений. Цена деления?', ['0,1 мм','1 мм','5 мм','10 мм'], 1, '$C = (10-0)/10 = 1$ мм.')
|
||
+ quizQuestion('p7-tr', 1, 'Цена деления $C = 0{,}5$ см. Погрешность?', ['0,25 мм','0,25 см','0,5 см','5 мм'], 1, '$\\Delta X = C/2 = 0{,}25$ см.')
|
||
+ quizQuestion('p7-tr', 2, 'Какой прибор точнее: с $C = 1$ мм или с $C = 0{,}1$ мм?', ['Первый','Второй','Они одинаково точны','Зависит от величины'], 1, 'Чем меньше цена деления, тем точнее прибор.')
|
||
+ quizQuestion('p7-tr', 3, 'Длина $l = (12{,}3 \\pm 0{,}05)$ см. Какова цена деления линейки?', ['0,05 см','0,1 см','0,5 см','1 см'], 1, '$C = 2 \\Delta X = 2 \\cdot 0{,}05 = 0{,}1$ см.')
|
||
+ quizQuestion('p7-tr', 4, 'Стрелка термометра стоит между $20$ и $21$ °C, ближе к $20$. Цена деления $1$ °C. Запиши температуру.', ['20 °C','20,5 °C','21 °C','20,3 °C'], 0, 'Округляем до ближайшего деления — $20$ °C; запись с погрешностью: $(20 \\pm 0{,}5)$ °C.')
|
||
+ '</div>');
|
||
|
||
h += readButton('p7');
|
||
|
||
body.innerHTML = h;
|
||
|
||
// §7 IV-1 wire: SVG ruler
|
||
function drawRuler(){
|
||
const cd = +document.getElementById('p7-cd').value;
|
||
const pos = +document.getElementById('p7-pos-r').value;
|
||
const W = 360, leftPad = 14, scaleW = W - 2 * leftPad;
|
||
const totalMm = 100;
|
||
const pxPerMm = scaleW / totalMm;
|
||
let s = '';
|
||
s += '<rect x="0" y="20" width="' + W + '" height="40" fill="#fef3c7" stroke="#92400e" stroke-width="1.5" rx="2"/>';
|
||
for(let mm = 0; mm <= totalMm; mm += cd){
|
||
const x = leftPad + mm * pxPerMm;
|
||
const isCm = mm % 10 === 0;
|
||
const tickH = isCm ? 18 : 10;
|
||
s += '<line x1="' + x.toFixed(1) + '" y1="20" x2="' + x.toFixed(1) + '" y2="' + (20 + tickH) + '" stroke="#0f172a" stroke-width="' + (isCm ? 1.5 : 1) + '"/>';
|
||
if(isCm) s += '<text x="' + x.toFixed(1) + '" y="56" text-anchor="middle" font-family="Inter,sans-serif" font-size="9" font-weight="600" fill="#0f172a">' + (mm/10) + '</text>';
|
||
}
|
||
s += '<text x="' + (W - 6) + '" y="34" text-anchor="end" font-family="Inter,sans-serif" font-size="10" font-weight="700" fill="#92400e">см</text>';
|
||
// Риска
|
||
const rx = leftPad + pos * pxPerMm;
|
||
s += '<polygon points="' + (rx-6) + ',8 ' + (rx+6) + ',8 ' + rx + ',22" fill="#dc2626"/>';
|
||
s += '<line x1="' + rx + '" y1="22" x2="' + rx + '" y2="64" stroke="#dc2626" stroke-width="2" stroke-dasharray="3 2"/>';
|
||
document.getElementById('p7-svg').innerHTML = s;
|
||
// Info
|
||
document.getElementById('p7-pos').textContent = pos;
|
||
// Округление до ближайшей цены деления
|
||
const rounded = Math.round(pos / cd) * cd;
|
||
const dx = cd / 2;
|
||
document.getElementById('p7-info').innerHTML =
|
||
'Цена деления: <b style="font-family:JetBrains Mono,monospace;color:#0c4a6e">' + cd + ' мм</b><br>'
|
||
+ 'Отсчёт (округлён до деления): <b style="font-family:JetBrains Mono,monospace;color:#0c4a6e">' + rounded + ' мм</b><br>'
|
||
+ 'Запись с погрешностью: $l = (' + rounded + ' \\pm ' + dx + ')$ мм';
|
||
renderMath(document.getElementById('p7-info'));
|
||
}
|
||
document.getElementById('p7-cd').addEventListener('change', drawRuler);
|
||
document.getElementById('p7-pos-r').addEventListener('input', drawRuler);
|
||
drawRuler();
|
||
|
||
// §7 IV-2 wire: calc
|
||
const updCalc = () => {
|
||
let x1 = +document.getElementById('p7-x1-r').value;
|
||
let x2 = +document.getElementById('p7-x2-r').value;
|
||
const N = +document.getElementById('p7-N-r').value;
|
||
if(x2 <= x1){ x2 = x1 + 1; document.getElementById('p7-x2-r').value = x2; }
|
||
document.getElementById('p7-x1').textContent = x1;
|
||
document.getElementById('p7-x2').textContent = x2;
|
||
document.getElementById('p7-N').textContent = N;
|
||
const C = (x2 - x1) / N;
|
||
document.getElementById('p7-cd2-x1').textContent = x1;
|
||
document.getElementById('p7-cd2-x2').textContent = x2;
|
||
document.getElementById('p7-cd2-N').textContent = N;
|
||
document.getElementById('p7-cd2').textContent = (+C.toPrecision(4)).toString().replace('.', ',');
|
||
document.getElementById('p7-dx').textContent = (+(C/2).toPrecision(4)).toString().replace('.', ',');
|
||
};
|
||
['p7-x1-r','p7-x2-r','p7-N-r'].forEach(id => document.getElementById(id).addEventListener('input', updCalc));
|
||
updCalc();
|
||
|
||
wireDnd('p7-dnd', [
|
||
{ id:'a1', cat:'mm' },{ id:'a2', cat:'01mm' },{ id:'a3', cat:'001mm' },
|
||
{ id:'a4', cat:'1c' },{ id:'a5', cat:'01c' },{ id:'a6', cat:'01s' }
|
||
], []);
|
||
wireQuiz('p7-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p7'); });
|
||
wireReadBtn('p7');
|
||
renderMath(body);
|
||
}
|
||
|
||
/* ========================================================== */
|
||
/* Финал главы 1 — 5 боссов + ачивка «Юный физик» (+50 XP) */
|
||
/* ========================================================== */
|
||
function add_final1(){
|
||
const body = document.getElementById('final1-body');
|
||
if(!body) return;
|
||
let h = '';
|
||
|
||
h += '<div style="background:linear-gradient(135deg,#e0e7ff,#ede9fe);border:1.5px solid #4f46e5;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:#312e81">Финал главы 1: победи 5 боссов</div>'
|
||
+ '<div style="font-size:.88rem;color:#475569;margin-top:5px">Реши все 5 задач — получишь ачивку «Юный физик» и +50 XP.</div>'
|
||
+ '<div style="height:10px;background:#fff;border-radius:6px;overflow:hidden;margin-top:12px;border:1px solid #c7d2fe"><div id="ch1-fin-fill" style="height:100%;background:linear-gradient(90deg,#4f46e5,#7c3aed);width:0%;transition:width .4s"></div></div>'
|
||
+ '<div id="ch1-fin-lab" style="font-size:.84rem;color:#475569;margin-top:6px">Побеждено: 0 / 5</div>'
|
||
+ '</div>';
|
||
|
||
const bosses = [
|
||
{ n:1, tag:'§4–6', title:'Перевод и площадь',
|
||
q:'Прямоугольный лист бумаги: $a = 21$ см, $b = 30$ см. Найди площадь в м².',
|
||
hint:'$a = 0{,}21$ м, $b = 0{,}30$ м. $S = a b = 0{,}21 \\cdot 0{,}30 = 0{,}063$ м².',
|
||
ans:0.063, tol:0.001, step:'0.001' },
|
||
{ n:2, tag:'§4 + §6', title:'Плотность бруска',
|
||
q:'Брусок $a = 4$ см, $b = 5$ см, $c = 2{,}5$ см, $m = 135$ г. Найди $\\rho$ в г/см³.',
|
||
hint:'$V = 4 \\cdot 5 \\cdot 2{,}5 = 50$ см³. $\\rho = m/V = 135/50 = 2{,}7$ г/см³ (алюминий).',
|
||
ans:2.7, tol:0.05, step:'0.01' },
|
||
{ n:3, tag:'§6', title:'Скорость в м/с',
|
||
q:'Автомобиль едет $v = 90$ км/ч. Найди $v$ в м/с.',
|
||
hint:'$v = 90/3{,}6 = 25$ м/с.',
|
||
ans:25, tol:0.2, step:'0.1' },
|
||
{ n:4, tag:'§7', title:'Цена деления',
|
||
q:'Между отметками $10$ см и $15$ см на линейке $50$ малых делений. Какова цена деления в мм?',
|
||
hint:'$X_2 - X_1 = 5$ см $= 50$ мм. $C = 50/50 = 1$ мм.',
|
||
ans:1, tol:0.05, step:'0.1' },
|
||
{ n:5, tag:'§7', title:'Юный физик (погрешность)',
|
||
q:'Цена деления мензурки $C = 2$ мл. Отсчёт $V = 84$ мл. Запиши погрешность $\\Delta V$ в мл.',
|
||
hint:'$\\Delta V = C/2 = 2/2 = 1$ мл. (Запись: $V = (84 \\pm 1)$ мл.)',
|
||
ans:1, tol:0.05, step:'0.1' }
|
||
];
|
||
|
||
const STATE_KEY = 'physics7_ch1_final_bosses';
|
||
let solved = {};
|
||
try{ solved = JSON.parse(localStorage.getItem(STATE_KEY) || '{}') || {}; }catch(e){}
|
||
|
||
bosses.forEach(b => {
|
||
const isSolved = !!solved[b.n];
|
||
h += '<div class="boss-card" data-boss="' + b.n + '" style="background:#fff;border:2px solid ' + (isSolved ? '#10b981' : '#bae6fd') + ';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:#4f46e5;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:#f0f9ff;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 #bae6fd;border-radius:8px;width:130px;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,#4f46e5,#7c3aed);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 #bae6fd;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="ch1-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 · Глава 1 полностью пройдена.</div></div></div>';
|
||
|
||
body.innerHTML = h;
|
||
renderMath(body);
|
||
|
||
function updateBar(){
|
||
const cnt = bosses.filter(b => solved[b.n]).length;
|
||
document.getElementById('ch1-fin-fill').style.width = (cnt * 100 / bosses.length) + '%';
|
||
document.getElementById('ch1-fin-lab').textContent = 'Побеждено: ' + cnt + ' / ' + bosses.length;
|
||
if(cnt === bosses.length){
|
||
document.getElementById('ch1-mastered').style.display = 'flex';
|
||
const ACH_KEY = 'physics7_ch1_yphys';
|
||
if(localStorage.getItem(ACH_KEY) !== '1'){
|
||
localStorage.setItem(ACH_KEY, '1');
|
||
if(window.addXp) window.addXp(50, 'ach-ch1-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('.boss-card[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-ch1-' + 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_CH1_WIDGETS = {
|
||
p1: add_p1,
|
||
p2: add_p2,
|
||
p3: add_p3,
|
||
p4: add_p4,
|
||
p5: add_p5,
|
||
p6: add_p6,
|
||
p7: add_p7,
|
||
final1: add_final1
|
||
};
|
||
|
||
})();
|