@@ -0,0 +1,402 @@
// Физика 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 ) ;
}
/* Экспорт — заглушки для остальных §, добавятся в следующих волнах */
window . PHYS7 _CH1 _WIDGETS = {
p1 : add _p1 ,
p2 : add _p2
// p3..p7, final1 — в Wave 2/3
} ;
} ) ( ) ;