Files
Learn_System/frontend/js/phys7_ch1_widgets.js
T
Maxim Dolgolyov 65c2e7dac1 feat(phys7 ch1): Phase 1 Wave 1 — §1, §2 + интеграция widgets
GEN: gen_phys7_ch.js теперь подключает <script src=phys7_chN_widgets.js> и
вызывает PHYS7_CHN_WIDGETS[id] в ensureBuilt, удаляя placeholder. Все 5 chN
регенерированы под этот hook.

WIDGETS (frontend/js/phys7_ch1_widgets.js, 402 строки, экспорт p1+p2):
- §1 «Физика — наука о природе»:
  * 3 теор. карточки (что изучает / связь с науками / 6 примеров явлений)
  * IV-1 СИМ: галерея 8 областей физики с hover-эффектом
  * IV-2 КВИЗ: 3 вопроса о предмете физики и слове «фюзис»
  * IV-3 DnD: 8 карточек → 4 науки (астро/химия/био/физика)
  * IV-4 ТРН: 5 вопросов тренажёр
- §2 «Физическое тело, явление, величина»:
  * 3 теор. карточки (4-понятийная таблица / как отличать / стакан-пример)
  * IV-1 СИМ (главный): DnD 12 карточек → 4 корзины (тело/вещество/явление/величина),
    в т.ч. KaTeX-величины (=5$ кг, =-10$ °C, =30$ км/ч)
  * IV-2 КВИЗ: «найди величину/явление/вещество» (3 вопроса)
  * IV-3 ТЕСТ: 5 быстрых вопросов на классификацию
  * IV-4 ТРН: 4 расчётных + концептуальных вопроса
- Кнопка «Я прочитал §» (+10 XP), localStorage-фиксация, серая «Прочитано»
  после первого нажатия.

ИНФРАСТРУКТУРА:
- Общие хелперы внутри файла: makeCard (theory/rule/example), wgWrap, dndPool,
  wireDnd, quizQuestion, wireQuiz, readButton, wireReadBtn, renderMath с правильными
  delimiters $..$ и $$..$$.
- XP: DnD +15, квиз +10, тренажёр +15, прочитал +10. Прогресс параграфа +30 при
  «прочитал», +10 базово при открытии. Цвета §1+§2 единые с темой главы 1 (indigo).
- Parse-check, KaTeX-аудит ($$ только двойной backslash), smoke-test пройдены.
2026-05-30 10:41:27 +03:00

403 lines
29 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Физика 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>'
+ 'Я прочитал § &nbsp;<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 = '&#10003; Идеально! Все ' + 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 = '&#10007; Правильно: ' + 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,'&quot;') + '">' + 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 = '&#10003; Верно!' + (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 = '&#10007; Неверно. Правильно: «' + 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);
}
/* Экспорт — заглушки для остальных §, добавятся в следующих волнах */
window.PHYS7_CH1_WIDGETS = {
p1: add_p1,
p2: add_p2
// p3..p7, final1 — в Wave 2/3
};
})();