feat(phys10 ch1 wave4): §7 «Твёрдые тела» + §8 «Жидкости»

This commit is contained in:
Maxim Dolgolyov
2026-05-29 16:42:20 +03:00
parent 5356096349
commit 4154e0b791
+762 -12
View File
@@ -2803,34 +2803,784 @@ function build_p6(){
function build_p7(){
const box = document.getElementById('p7-body');
let html = '';
html += makeCard('theory', "Строение и свойства твёрдых тел", "§7", `
<p><b>Строение и свойства твёрдых тел</b> — этот параграф в разработке (Phase 1+).</p>
<p>Здесь появятся: теория, формулы, разобранные примеры и 3–4 интерактива в стиле «алгебры 11» — таблицы, симуляции, ползунки, drag-and-drop и автопроверяемые тренажёры.</p>
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.92rem">
<b>Phase 0:</b> создан скелет учебника. <b>Phase 1+:</b> наполнение этого § содержанием по учебнику «Физика 10» (Беларусь, 2019).
</p>
/* THEORY 1 — Кристаллические и аморфные тела */
html += makeCard('theory', "Кристаллические и аморфные тела", "§7", `
<p><b>Кристаллические тела</b> имеют упорядоченное расположение частиц — <b>кристаллическую решётку</b>.</p>
<p style="margin-top:8px">Виды кристаллических тел:</p>
<ul style="margin:6px 0 8px 22px;line-height:1.75">
<li><b>Монокристалл</b> — единая решётка во всём объёме (кварц, алмаз, поваренная соль, сахар).</li>
<li><b>Поликристалл</b> — много мелких кристалликов, ориентированных хаотически (металлы, лёд, керамика).</li>
</ul>
<p>У кристаллических тел есть <b>точная температура плавления</b>: при $t_{\\text{пл}}$ решётка разрушается, и тело переходит в жидкое состояние.</p>
<p style="margin-top:10px"><b>Аморфные тела</b> (стекло, смола, пластмассы, янтарь, воск) не имеют упорядоченной решётки. Их называют «переохлаждёнными жидкостями». При нагревании они <b>размягчаются плавно</b>, без чёткой температуры плавления.</p>
`);
/* THEORY 2 — Анизотропия и изотропия */
html += makeCard('rule', "Анизотропия и изотропия", "§7", `
<p><b>Анизотропия</b> — зависимость физических свойств от направления (твёрдость, теплопроводность, скорость распространения света). <b>Характерна для монокристаллов.</b></p>
<p style="margin-top:8px">Примеры:</p>
<ul style="margin:6px 0 8px 22px;line-height:1.75">
<li>Алмаз в одном направлении режется легче, чем в другом.</li>
<li>Графит легко расщепляется на тонкие чешуйки (вдоль слоёв).</li>
<li>В кварце скорость звука зависит от оси кристалла.</li>
</ul>
<p><b>Изотропия</b> — свойства одинаковы во всех направлениях. <b>Характерна для поликристаллов и аморфных тел.</b></p>
<p style="margin-top:8px">Поликристаллы состоят из множества мелких разно ориентированных кристалликов, поэтому в среднем свойства одинаковы по всем направлениям.</p>
`);
/* THEORY 3 — Типы кристаллических решёток */
html += makeCard('example', "Типы кристаллических решёток", "§7", `
<p>По типу связи частиц различают четыре основных типа решёток:</p>
<ul style="margin:6px 0 8px 22px;line-height:1.85">
<li><b style="color:#e11d48">Ионная</b> (NaCl, KCl, CaF$_2$): чередование «+» и «−» ионов. Очень прочные, твёрдые, высокая $t_{\\text{пл}}$.</li>
<li><b style="color:#475569">Атомная</b> (алмаз, графит, кремний, германий): атомы связаны ковалентными связями. Очень твёрдые, тугоплавкие.</li>
<li><b style="color:#0ea5e9">Молекулярная</b> (лёд, нафталин, парафин, сахар, йод): связи между молекулами слабые. Мягкие, легкоплавкие.</li>
<li><b style="color:#f59e0b">Металлическая</b> (медь, железо, алюминий): положительные ионы в «море» свободных электронов. Пластичные, хорошо проводят ток и тепло.</li>
</ul>
<p style="margin-top:8px">Один и тот же элемент может образовывать разные решётки: <b>алмаз</b> (атомная решётка, очень твёрдый) и <b>графит</b> (слоистая, мягкий) — оба состоят из углерода.</p>
`);
/* INTERACTIVE 1 — Визуализатор кристаллической решётки */
html += `<div class="wg" id="p7-iv1">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Визуализатор кристаллической решётки</div></div>
<div class="wg-help">Переключай тип решётки и наблюдай расположение частиц. Просмотри все 4 типа.</div>
<div style="display:flex;gap:10px;flex-wrap:wrap;justify-content:center;margin-bottom:10px" id="p7-iv1-tabs">
<button class="btn primary" data-mode="ion" style="background:#e11d48;border-color:#e11d48">Ионная</button>
<button class="btn" data-mode="atom">Атомная</button>
<button class="btn" data-mode="mol">Молекулярная</button>
<button class="btn" data-mode="met">Металлическая</button>
</div>
<div style="background:var(--card);border:1px solid var(--border);border-radius:10px;padding:10px;display:flex;justify-content:center">
<svg id="p7-iv1-svg" viewBox="0 0 380 280" width="100%" style="max-width:520px;height:auto"></svg>
</div>
<div style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.94rem;line-height:1.75" id="p7-iv1-info"></div>
</div>`;
/* INTERACTIVE 2 — Кристалл или аморфное (DnD) */
html += `<div class="wg" id="p7-iv2">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Кристалл или аморфное?</div></div>
<div class="wg-help">Перетащи 8 веществ в нужный ящик.</div>
<div class="dnd-hint"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 11V6a3 3 0 0 1 6 0v5"/><path d="M9 11h6v8a4 4 0 0 1-8 0z"/></svg> 8 веществ — 2 группы</div>
<div id="p7-iv2-pool"></div>
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:10px;margin-top:8px">
<div class="drop-box"><h5 data-cat="cryst" style="color:#2563eb">Кристаллическое</h5><div class="drop-items" data-cat="cryst"></div></div>
<div class="drop-box"><h5 data-cat="amorph" style="color:#10b981">Аморфное</h5><div class="drop-items" data-cat="amorph"></div></div>
</div>
<div class="actions"><button class="btn primary" id="p7-iv2-check">Проверить</button><button class="btn" id="p7-iv2-reset">Сначала</button></div>
<div class="feedback" id="p7-iv2-fb"></div>
</div>`;
/* INTERACTIVE 3 — квикфайр: свойство → тип решётки */
html += `<div class="wg" id="p7-iv3">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 3</span><div class="wg-title">Какой тип решётки?</div></div>
<div class="wg-help">6 веществ. Жми кнопку с типом решётки.</div>
<div class="score-display"><span>Задача <b id="p7-iv3-i">1</b> / 6</span><span>Очки: <b id="p7-iv3-s">0</b> / 6</span></div>
<div id="p7-iv3-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.05rem;margin-bottom:10px;text-align:center;min-height:54px"></div>
<div id="p7-iv3-opts" style="display:grid;grid-template-columns:1fr 1fr;gap:8px"></div>
<div class="feedback" id="p7-iv3-fb"></div>
<div class="actions"><button class="btn" id="p7-iv3-restart">Начать заново</button></div>
</div>`;
/* INTERACTIVE 4 — тренажёр свойств твёрдых тел */
html += `<div class="wg" id="p7-iv4">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 4</span><div class="wg-title">Тренажёр свойств твёрдых тел</div></div>
<div class="wg-help">5 задач. Допуск для чисел $\\pm 5\\%$.</div>
<div class="score-display"><span>Задача <b id="p7-iv4-i">1</b> / 5</span><span>Очки: <b id="p7-iv4-s">0</b> / 5</span></div>
<div id="p7-iv4-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.05rem;margin-bottom:10px;text-align:center;min-height:54px"></div>
<div style="display:flex;gap:10px;align-items:center;flex-wrap:wrap;justify-content:center">
<span style="font-family:'JetBrains Mono',monospace">ответ =</span>
<input type="number" id="p7-iv4-ans" class="tinp" style="width:130px;text-align:center" step="any">
<button class="btn primary" id="p7-iv4-go">Проверить</button>
<button class="btn" id="p7-iv4-start">Заново</button>
</div>
<div class="feedback" id="p7-iv4-fb"></div>
</div>`;
html += secNav('p6', 'p8');
html += readButton('p7');
box.innerHTML = html;
renderMath(box);
/* IV1 — Визуализатор решётки */
(function(){
const tabs = document.getElementById('p7-iv1-tabs');
const svg = document.getElementById('p7-iv1-svg');
const info = document.getElementById('p7-iv1-info');
const seen = new Set();
let _done = false;
let mode = 'ion';
function drawIon(){
// 5×5 сетка чередующихся Na+/Cl−
let g = '<rect x="0" y="0" width="380" height="280" fill="#fafafa"/>';
const cols = 6, rows = 5, sx = 50, sy = 30, dx = 56, dy = 48;
for(let j = 0; j < rows; j++){
for(let i = 0; i < cols; i++){
const cx = sx + i * dx, cy = sy + j * dy;
const isPlus = ((i + j) % 2 === 0);
// соединительные линии (соседи справа/снизу)
if(i < cols-1) g += '<line x1="'+cx+'" y1="'+cy+'" x2="'+(cx+dx)+'" y2="'+cy+'" stroke="#94a3b8" stroke-width="1" stroke-dasharray="3 3"/>';
if(j < rows-1) g += '<line x1="'+cx+'" y1="'+cy+'" x2="'+cx+'" y2="'+(cy+dy)+'" stroke="#94a3b8" stroke-width="1" stroke-dasharray="3 3"/>';
}
}
for(let j = 0; j < rows; j++){
for(let i = 0; i < cols; i++){
const cx = sx + i * dx, cy = sy + j * dy;
const isPlus = ((i + j) % 2 === 0);
const col = isPlus ? '#e11d48' : '#2563eb';
const r = isPlus ? 13 : 17;
g += '<circle cx="'+cx+'" cy="'+cy+'" r="'+r+'" fill="'+col+'" stroke="#0f172a" stroke-width="1.2"/>';
g += '<text x="'+cx+'" y="'+(cy+4)+'" text-anchor="middle" font-size="11" font-weight="700" fill="#fff">'+(isPlus?'Na⁺':'Cl⁻')+'</text>';
}
}
svg.innerHTML = g;
}
function drawAtom(){
// Тетраэдрическая сетка алмаза — упрощённая 2D-проекция
let g = '<rect x="0" y="0" width="380" height="280" fill="#fafafa"/>';
const sx = 50, sy = 40, dx = 70, dy = 60;
const nodes = [];
for(let j = 0; j < 4; j++){
for(let i = 0; i < 5; i++){
const off = (j % 2) * dx / 2;
nodes.push({x: sx + i*dx + off, y: sy + j*dy, i, j});
}
}
// соединения — ковалентные связи (жирные линии к ближайшим)
for(const a of nodes){
for(const b of nodes){
if(a === b) continue;
const d = Math.hypot(a.x - b.x, a.y - b.y);
if(d < dx * 1.05 && d > 0.1){
g += '<line x1="'+a.x+'" y1="'+a.y+'" x2="'+b.x+'" y2="'+b.y+'" stroke="#475569" stroke-width="3" opacity="0.7"/>';
}
}
}
for(const n of nodes){
g += '<circle cx="'+n.x+'" cy="'+n.y+'" r="11" fill="#64748b" stroke="#0f172a" stroke-width="1.2"/>';
g += '<text x="'+n.x+'" y="'+(n.y+4)+'" text-anchor="middle" font-size="10" font-weight="700" fill="#fff">C</text>';
}
svg.innerHTML = g;
}
function drawMol(){
// Молекулы H₂O в упорядоченной сетке + водородные связи (пунктир)
let g = '<rect x="0" y="0" width="380" height="280" fill="#fafafa"/>';
const cols = 4, rows = 3, sx = 60, sy = 50, dx = 90, dy = 80;
const centers = [];
for(let j = 0; j < rows; j++){
for(let i = 0; i < cols; i++){
centers.push({x: sx + i*dx, y: sy + j*dy});
}
}
// водородные связи (пунктир) между соседями
for(let i = 0; i < centers.length; i++){
for(let k = i+1; k < centers.length; k++){
const d = Math.hypot(centers[i].x - centers[k].x, centers[i].y - centers[k].y);
if(d < dx * 1.05){
g += '<line x1="'+centers[i].x+'" y1="'+centers[i].y+'" x2="'+centers[k].x+'" y2="'+centers[k].y+'" stroke="#94a3b8" stroke-width="1.5" stroke-dasharray="4 4"/>';
}
}
}
// молекулы H₂O: 1 кислород (синий) + 2 водорода (белые)
for(const c of centers){
const ox = c.x, oy = c.y;
const ang1 = -Math.PI/2 - 0.5, ang2 = -Math.PI/2 + 0.5;
const hr = 18;
const h1x = ox + hr*Math.cos(ang1), h1y = oy + hr*Math.sin(ang1);
const h2x = ox + hr*Math.cos(ang2), h2y = oy + hr*Math.sin(ang2);
g += '<line x1="'+ox+'" y1="'+oy+'" x2="'+h1x+'" y2="'+h1y+'" stroke="#0f172a" stroke-width="2"/>';
g += '<line x1="'+ox+'" y1="'+oy+'" x2="'+h2x+'" y2="'+h2y+'" stroke="#0f172a" stroke-width="2"/>';
g += '<circle cx="'+ox+'" cy="'+oy+'" r="11" fill="#0ea5e9" stroke="#0f172a" stroke-width="1.2"/>';
g += '<text x="'+ox+'" y="'+(oy+4)+'" text-anchor="middle" font-size="10" font-weight="700" fill="#fff">O</text>';
g += '<circle cx="'+h1x+'" cy="'+h1y+'" r="7" fill="#fff" stroke="#0f172a" stroke-width="1"/>';
g += '<text x="'+h1x+'" y="'+(h1y+3)+'" text-anchor="middle" font-size="9" font-weight="700" fill="#0f172a">H</text>';
g += '<circle cx="'+h2x+'" cy="'+h2y+'" r="7" fill="#fff" stroke="#0f172a" stroke-width="1"/>';
g += '<text x="'+h2x+'" y="'+(h2y+3)+'" text-anchor="middle" font-size="9" font-weight="700" fill="#0f172a">H</text>';
}
svg.innerHTML = g;
}
function drawMet(){
// Положительные ионы (большие синие круги) + свободные электроны (точки)
let g = '<rect x="0" y="0" width="380" height="280" fill="#fafafa"/>';
const cols = 5, rows = 4, sx = 50, sy = 40, dx = 70, dy = 60;
// электронное «море» — фоновая дымка
g += '<rect x="20" y="20" width="340" height="240" fill="#fde68a" opacity="0.3" rx="8"/>';
// свободные электроны (50 хаотичных точек)
for(let k = 0; k < 70; k++){
const ex = 30 + Math.random() * 320;
const ey = 30 + Math.random() * 220;
g += '<circle cx="'+ex.toFixed(1)+'" cy="'+ey.toFixed(1)+'" r="2.5" fill="#e11d48" opacity="0.85"/>';
g += '<text x="'+(ex+4).toFixed(1)+'" y="'+(ey+2).toFixed(1)+'" font-size="8" fill="#e11d48" font-weight="700"></text>';
}
// положительные ионы
for(let j = 0; j < rows; j++){
for(let i = 0; i < cols; i++){
const cx = sx + i*dx, cy = sy + j*dy;
g += '<circle cx="'+cx+'" cy="'+cy+'" r="15" fill="#f59e0b" stroke="#0f172a" stroke-width="1.4"/>';
g += '<text x="'+cx+'" y="'+(cy+4)+'" text-anchor="middle" font-size="11" font-weight="700" fill="#fff">+</text>';
}
}
svg.innerHTML = g;
}
const INFO = {
ion: '<b style="color:#e11d48">Ионная решётка</b> (пример: NaCl, поваренная соль). Связь: электростатическая между «+» и «−» ионами. Свойства: твёрдые, $t_{\\text{пл}}$ высокая (≈ 800°C), хрупкие, в расплаве проводят ток.',
atom: '<b style="color:#475569">Атомная решётка</b> (пример: алмаз, кремний). Связь: ковалентная между атомами. Свойства: очень твёрдые, тугоплавкие ($t_{\\text{пл}}$ > 1000°C), плохо проводят ток.',
mol: '<b style="color:#0ea5e9">Молекулярная решётка</b> (пример: лёд H$_2$O, нафталин, йод). Связь: слабая (Ван-дер-Ваальса, водородные связи). Свойства: мягкие, легкоплавкие, не проводят ток.',
met: '<b style="color:#f59e0b">Металлическая решётка</b> (пример: Cu, Fe, Al). «+» ионы в «море» свободных электронов. Свойства: пластичные, отлично проводят ток и тепло, имеют металлический блеск.'
};
function render(){
if(mode === 'ion') drawIon();
else if(mode === 'atom') drawAtom();
else if(mode === 'mol') drawMol();
else drawMet();
info.innerHTML = INFO[mode];
renderMath(info);
seen.add(mode);
if(!_done && seen.size >= 4){ _done = true; addXp(10, 'p7-iv1'); bumpProgress('p7', 15); }
}
tabs.querySelectorAll('button').forEach(b => {
b.addEventListener('click', () => {
mode = b.dataset.mode;
const colMap = { ion:'#e11d48', atom:'#475569', mol:'#0ea5e9', met:'#f59e0b' };
tabs.querySelectorAll('button').forEach(x => { x.className = 'btn'; x.style.background=''; x.style.borderColor=''; });
b.className = 'btn primary';
b.style.background = colMap[mode]; b.style.borderColor = colMap[mode];
render();
});
});
render();
})();
/* IV2 — DnD: кристалл/аморф */
(function(){
const items = [
{ id:'s1', cat:'cryst', html:'Поваренная соль (NaCl)' },
{ id:'s2', cat:'amorph', html:'Стекло' },
{ id:'s3', cat:'cryst', html:'Алмаз' },
{ id:'s4', cat:'amorph', html:'Янтарь' },
{ id:'s5', cat:'cryst', html:'Лёд' },
{ id:'s6', cat:'amorph', html:'Парафин' },
{ id:'s7', cat:'cryst', html:'Железо' },
{ id:'s8', cat:'amorph', html:'Резина' },
];
const sorter = setupSorter({
poolId:'p7-iv2-pool',
scopeSelector:'#p7-iv2',
items: items,
cats:['cryst','amorph'],
columnLayout:false,
});
document.getElementById('p7-iv2-check').addEventListener('click', () => {
const fb = document.getElementById('p7-iv2-fb');
const placedCount = items.filter(it => sorter.placed[it.id]).length;
const correct = items.filter(it => sorter.placed[it.id] === it.cat).length;
if(placedCount < items.length){ feedback(fb, false, '&#10007; Размести все 8 веществ.'); return; }
if(correct === items.length){ feedback(fb, true, '&#10003; Все 8 верно! +10 XP'); addXp(10,'p7-iv2'); bumpProgress('p7', 15); }
else feedback(fb, false, '&#10007; Правильно ' + correct + ' из 8. Попробуй ещё.');
});
document.getElementById('p7-iv2-reset').addEventListener('click', () => { sorter.reset(); document.getElementById('p7-iv2-fb').style.display = 'none'; });
})();
/* IV3 — квикфайр: тип решётки */
(function(){
// ans: 0=ион, 1=атом, 2=мол, 3=метал
const Q = [
{ q:'NaCl — поваренная соль', ans:0, why:'Чередование Na⁺ и Cl⁻ — ионная решётка.' },
{ q:'Алмаз', ans:1, why:'Атомы углерода связаны ковалентными связями — атомная решётка.' },
{ q:'Лёд (H$_2$O в твёрдом состоянии)', ans:2, why:'Между молекулами H$_2$O слабые водородные связи — молекулярная решётка.' },
{ q:'Медь, железо, алюминий', ans:3, why:'Положительные ионы в «море» свободных электронов — металлическая.' },
{ q:'Кремний (полупроводник)', ans:1, why:'Атомная решётка (как у алмаза), ковалентные связи.' },
{ q:'Йод (I$_2$)', ans:2, why:'Молекулы I$_2$ связаны слабыми силами — молекулярная.' },
];
const LABELS = ['Ионная','Атомная','Молекулярная','Металлическая'];
const COLS = ['#e11d48','#475569','#0ea5e9','#f59e0b'];
let i = 0, score = 0;
const qEl = document.getElementById('p7-iv3-q');
const oEl = document.getElementById('p7-iv3-opts');
const fb = document.getElementById('p7-iv3-fb');
const iEl = document.getElementById('p7-iv3-i');
const sEl = document.getElementById('p7-iv3-s');
function show(){
if(i >= Q.length){
qEl.innerHTML = '<b>Готово!</b> Результат: ' + score + ' / ' + Q.length;
oEl.innerHTML = '';
if(score === Q.length){ addXp(15, 'p7-iv3'); bumpProgress('p7', 25); }
else if(score >= 4){ addXp(8, 'p7-iv3'); bumpProgress('p7', 15); }
return;
}
iEl.textContent = (i+1); sEl.textContent = score;
qEl.innerHTML = Q[i].q;
let opts = '';
for(let k = 0; k < 4; k++){
opts += '<button class="btn primary" data-v="'+k+'" style="background:'+COLS[k]+';border-color:'+COLS[k]+'">'+LABELS[k]+'</button>';
}
oEl.innerHTML = opts;
fb.style.display = 'none';
renderMath(qEl);
oEl.querySelectorAll('button').forEach(b => {
b.addEventListener('click', () => {
const v = +b.dataset.v;
if(v === Q[i].ans){ score++; feedback(fb, true, '&#10003; Верно! ' + Q[i].why + ' Дальше ▶'); }
else feedback(fb, false, '&#10007; Неверно. Правильно: '+LABELS[Q[i].ans]+'. '+Q[i].why+' Дальше ▶');
sEl.textContent = score;
oEl.querySelectorAll('button').forEach(x => x.disabled = true);
i++;
setTimeout(show, 1700);
});
});
}
document.getElementById('p7-iv3-restart').addEventListener('click', () => { i = 0; score = 0; show(); });
show();
})();
/* IV4 — Тренажёр свойств твёрдых тел */
(function(){
const Q = [
{ q:'В монокристалле скорость звука вдоль оси $X$ равна $5000$ м/с, вдоль $Y$ — $3000$ м/с. Найди разность в м/с (это пример анизотропии).', ans:2000, hint:'$5000 - 3000 = 2000$ м/с — разные направления, разные скорости.' },
{ q:'Стекло — это кристаллическое (1) или аморфное (2) тело?', ans:2, hint:'Стекло не имеет упорядоченной решётки — это «переохлаждённая жидкость».' },
{ q:'Алмаз и графит — оба состоят из углерода. У какого больше твёрдость? Введи: алмаз = 1, графит = 2.', ans:1, hint:'У алмаза 3D-решётка ковалентных связей — он твёрже. Графит — слоистый.' },
{ q:'Сколько типов кристаллических решёток рассматривается в §7?', ans:4, hint:'Ионная, атомная, молекулярная, металлическая.' },
{ q:'Какой тип решётки у меди? Введи цифру: 1 = ионная, 2 = атомная, 3 = молекулярная, 4 = металлическая.', ans:4, hint:'Cu — металл, значит решётка металлическая («+» ионы в «море» электронов).' },
];
let i = 0, score = 0;
function show(){
if(i >= Q.length){
document.getElementById('p7-iv4-q').innerHTML = '<b>Готово!</b> Результат: ' + score + ' / ' + Q.length;
if(score === Q.length){ addXp(15, 'p7-iv4'); bumpProgress('p7', 25); }
else if(score >= 3){ addXp(8, 'p7-iv4'); bumpProgress('p7', 15); }
return;
}
document.getElementById('p7-iv4-i').textContent = (i+1);
document.getElementById('p7-iv4-s').textContent = score;
document.getElementById('p7-iv4-q').innerHTML = Q[i].q;
document.getElementById('p7-iv4-ans').value = '';
renderMath(document.getElementById('p7-iv4-q'));
document.getElementById('p7-iv4-fb').style.display = 'none';
}
function go(){
if(i >= Q.length) return;
const fb = document.getElementById('p7-iv4-fb');
const raw = document.getElementById('p7-iv4-ans').value.replace(',', '.');
const ans = parseFloat(raw);
if(isNaN(ans)){ feedback(fb, false, '&#10007; Введи число.'); return; }
const tol = Math.max(0.05 * Math.abs(Q[i].ans), 0.5);
if(Math.abs(ans - Q[i].ans) < tol + 0.001){ score++; feedback(fb, true, '&#10003; Верно! '+Q[i].hint+' Дальше ▶'); }
else feedback(fb, false, '&#10007; Неверно. Ответ: $'+Q[i].ans+'$. '+Q[i].hint+' Дальше ▶');
document.getElementById('p7-iv4-s').textContent = score;
i++;
setTimeout(show, 1800);
}
document.getElementById('p7-iv4-go').addEventListener('click', go);
document.getElementById('p7-iv4-ans').addEventListener('keydown', e => { if(e.key === 'Enter') go(); });
document.getElementById('p7-iv4-start').addEventListener('click', () => { i = 0; score = 0; show(); });
show();
})();
wireReadBtn('p7');
}
function build_p8(){
const box = document.getElementById('p8-body');
let html = '';
html += makeCard('theory', "Строение и свойства жидкостей", "§8", `
<p><b>Строение и свойства жидкостей</b> — этот параграф в разработке (Phase 1+).</p>
<p>Здесь появятся: теория, формулы, разобранные примеры и 3–4 интерактива в стиле «алгебры 11» — таблицы, симуляции, ползунки, drag-and-drop и автопроверяемые тренажёры.</p>
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.92rem">
<b>Phase 0:</b> создан скелет учебника. <b>Phase 1+:</b> наполнение этого § содержанием по учебнику «Физика 10» (Беларусь, 2019).
</p>
/* THEORY 1 — Свойства и строение жидкостей */
html += makeCard('theory', "Свойства и строение жидкостей", "§8", `
<p>Жидкости занимают <b>промежуточное положение</b> между газами и твёрдыми телами:</p>
<ul style="margin:6px 0 8px 22px;line-height:1.75">
<li>От <b>твёрдых тел</b> жидкость унаследовала: <b>сохранение объёма</b> (несжимаемость).</li>
<li>От <b>газов</b>: <b>отсутствие собственной формы</b> — жидкость принимает форму сосуда.</li>
</ul>
<p>Молекулы жидкости расположены тесно (как в твёрдом теле), но могут перемещаться (как в газе).</p>
<p style="margin-top:8px"><b>Ближний порядок</b> — упорядоченность молекул в области порядка нескольких диаметров молекулы. На больших расстояниях упорядоченности нет (в отличие от кристалла).</p>
<p style="margin-top:8px">При охлаждении жидкость может <b>кристаллизоваться</b> (вода → лёд) или, при особых условиях, остаться аморфной (стекло — переохлаждённая жидкость).</p>
`);
/* THEORY 2 — Поверхностное натяжение */
html += makeCard('rule', "Поверхностное натяжение", "§8", `
<p>На поверхности жидкости молекулы испытывают силу, направленную <b>внутрь жидкости</b>. Это объясняется тем, что молекула в объёме окружена молекулами со всех сторон, а молекула на поверхности — только снизу и с боков.</p>
<p style="margin-top:8px">В результате жидкость стремится <b>минимизировать площадь поверхности</b>. Поэтому маленькая капля принимает почти сферическую форму.</p>
<p style="margin-top:10px"><b>Сила поверхностного натяжения</b> на границе пленки длиной $L$:</p>
<p style="text-align:center;margin:10px 0">$$F = \\sigma L$$</p>
<p>где $\\sigma$ — <b>коэффициент поверхностного натяжения</b> (Н/м).</p>
<p style="margin-top:8px">Значения $\\sigma$ при $20°$C:</p>
<ul style="margin:6px 0 8px 22px;line-height:1.7">
<li>вода: $\\sigma_{\\text{в}} \\approx 0{,}073$ Н/м;</li>
<li>спирт: $\\sigma_{\\text{сп}} \\approx 0{,}022$ Н/м;</li>
<li>ртуть: $\\sigma_{\\text{Hg}} \\approx 0{,}465$ Н/м.</li>
</ul>
`);
/* THEORY 3 — Смачивание и капиллярность */
html += makeCard('example', "Смачивание и капиллярность", "§8", `
<p>Когда жидкость соприкасается с твёрдой поверхностью, поверхность жидкости образует <b>краевой угол</b> $\\theta$ с твёрдым телом:</p>
<ul style="margin:6px 0 8px 22px;line-height:1.75">
<li>$\\theta < 90°$ — <b>смачивание</b> (вода на чистом стекле: $\\theta \\approx 0°$).</li>
<li>$\\theta > 90°$ — <b>несмачивание</b> (ртуть на стекле: $\\theta \\approx 140°$).</li>
</ul>
<p><b>Капиллярные явления</b>: в тонкой трубке (капилляре) смачивающая жидкость <b>поднимается</b>, несмачивающая — <b>опускается</b> ниже общего уровня.</p>
<p style="margin-top:8px">Высота поднятия в капилляре радиуса $r$:</p>
<p style="text-align:center;margin:10px 0">$$h = \\dfrac{2 \\sigma \\cos\\theta}{\\rho g r}$$</p>
<p>где $\\rho$ — плотность жидкости, $g$ — ускорение свободного падения.</p>
<p style="margin-top:8px"><b>Пример.</b> Вода в капилляре $r = 1$ мм: $h = \\dfrac{2 \\cdot 0{,}073}{1000 \\cdot 10 \\cdot 10^{-3}} \\approx 0{,}015$ м $= 15$ мм.</p>
<p style="margin-top:8px">Капиллярность важна в природе: вода поднимается по корням растений, по тонким сосудам в почве, по фитилю свечи.</p>
`);
/* INTERACTIVE 1 — Симуляция жидкости */
html += `<div class="wg" id="p8-iv1">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Симуляция жидкости: молекулы плотно упакованы</div></div>
<div class="wg-help">Молекулы расположены тесно и колеблются. Меняй $t$: при росте температуры амплитуда колебаний растёт, при $t \\to 100°$C — молекулы начинают «вырываться» (испарение → §9).</div>
<div class="sliders">
<label>Температура $t$: <b id="p8-iv1-tL">20</b> °C <input type="range" id="p8-iv1-t" min="0" max="100" value="20" step="5"></label>
</div>
<div style="background:#1e293b;border:1px solid var(--border);border-radius:10px;padding:6px;margin-top:8px">
<svg id="p8-iv1-svg" viewBox="0 0 360 240" width="100%" style="max-width:520px;height:auto;display:block;margin:0 auto"></svg>
</div>
<div class="actions" style="justify-content:center">
<button class="btn" id="p8-iv1-pause">Пауза</button>
<button class="btn" id="p8-iv1-reset">Сначала</button>
</div>
<div style="margin-top:8px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.93rem;line-height:1.75" id="p8-iv1-info"></div>
</div>`;
/* INTERACTIVE 2 — Калькулятор поверхностного натяжения */
html += `<div class="wg" id="p8-iv2">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Калькулятор поверхностного натяжения</div></div>
<div class="wg-help">Выбери жидкость, введи длину $L$ — получишь силу $F = \\sigma L$. Дополнительно — высота поднятия в капилляре $r = 1$ мм.</div>
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:10px;margin-bottom:10px">
<label style="display:block;font-size:.9rem;color:var(--muted);background:var(--card);padding:8px 12px;border-radius:8px;border:1px solid var(--border)">Жидкость
<select id="p8-iv2-liq" class="tinp" style="width:100%;margin-top:6px">
<option value="water">Вода (σ = 0,073 Н/м, ρ = 1000)</option>
<option value="alc">Спирт (σ = 0,022 Н/м, ρ = 790)</option>
<option value="hg">Ртуть (σ = 0,465 Н/м, ρ = 13600)</option>
</select>
</label>
<label style="display:block;font-size:.9rem;color:var(--muted);background:var(--card);padding:8px 12px;border-radius:8px;border:1px solid var(--border)">Длина $L$, м
<input type="number" id="p8-iv2-L" class="tinp" style="width:100%;margin-top:6px" value="0.2" step="any">
</label>
<label style="display:block;font-size:.9rem;color:var(--muted);background:var(--card);padding:8px 12px;border-radius:8px;border:1px solid var(--border)">Радиус капилляра $r$, мм
<input type="number" id="p8-iv2-r" class="tinp" style="width:100%;margin-top:6px" value="1" step="any">
</label>
</div>
<div class="actions" style="justify-content:center">
<button class="btn primary" id="p8-iv2-go">Вычислить</button>
</div>
<div id="p8-iv2-out" style="margin-top:10px;padding:12px 14px;background:var(--card);border-radius:9px;font-size:.94rem;min-height:80px;line-height:1.85"></div>
<div class="feedback" id="p8-iv2-fb"></div>
</div>`;
/* INTERACTIVE 3 — квикфайр: смачивает или нет */
html += `<div class="wg" id="p8-iv3">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 3</span><div class="wg-title">Смачивает или нет?</div></div>
<div class="wg-help">6 ситуаций. Жми соответствующую кнопку.</div>
<div class="score-display"><span>Задача <b id="p8-iv3-i">1</b> / 6</span><span>Очки: <b id="p8-iv3-s">0</b> / 6</span></div>
<div id="p8-iv3-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.05rem;margin-bottom:10px;text-align:center;min-height:54px"></div>
<div id="p8-iv3-opts" style="display:grid;grid-template-columns:1fr 1fr;gap:8px"></div>
<div class="feedback" id="p8-iv3-fb"></div>
<div class="actions"><button class="btn" id="p8-iv3-restart">Начать заново</button></div>
</div>`;
/* INTERACTIVE 4 — Тренажёр жидкости */
html += `<div class="wg" id="p8-iv4">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 4</span><div class="wg-title">Тренажёр жидкости</div></div>
<div class="wg-help">5 задач. Допуск ±5%.</div>
<div class="score-display"><span>Задача <b id="p8-iv4-i">1</b> / 5</span><span>Очки: <b id="p8-iv4-s">0</b> / 5</span></div>
<div id="p8-iv4-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.05rem;margin-bottom:10px;text-align:center;min-height:54px"></div>
<div style="display:flex;gap:10px;align-items:center;flex-wrap:wrap;justify-content:center">
<span style="font-family:'JetBrains Mono',monospace">ответ =</span>
<input type="number" id="p8-iv4-ans" class="tinp" style="width:130px;text-align:center" step="any">
<button class="btn primary" id="p8-iv4-go">Проверить</button>
<button class="btn" id="p8-iv4-start">Заново</button>
</div>
<div class="feedback" id="p8-iv4-fb"></div>
</div>`;
html += secNav('p7', 'p9');
html += readButton('p8');
box.innerHTML = html;
renderMath(box);
/* IV1 — Симуляция жидкости */
(function(){
const svg = document.getElementById('p8-iv1-svg');
const tInp = document.getElementById('p8-iv1-t');
const tLab = document.getElementById('p8-iv1-tL');
const btnPause = document.getElementById('p8-iv1-pause');
const btnReset = document.getElementById('p8-iv1-reset');
const info = document.getElementById('p8-iv1-info');
const W = 360, H = 240;
const N = 60; // число молекул
let raf = null, lastT = 0, paused = false;
let parts = [];
const tempChanges = new Set();
let _xpDone = false;
function makeParts(){
parts = [];
const cols = 10, rows = 6, sx = 30, sy = 80, dx = 30, dy = 24;
for(let j = 0; j < rows; j++){
for(let i = 0; i < cols; i++){
parts.push({
x0: sx + i*dx + (j%2)*dx/2,
y0: sy + j*dy,
x: sx + i*dx + (j%2)*dx/2,
y: sy + j*dy,
vx: 0, vy: 0,
escaped: false
});
}
}
}
function frame(t){
raf = requestAnimationFrame(frame);
if(!lastT){ lastT = t; return; }
let dt = (t - lastT) / 1000;
lastT = t;
if(paused){ render(); return; }
if(dt > 0.06) dt = 0.06;
const T = +tInp.value;
// амплитуда колебаний ~ T (px)
const amp = 1 + T * 0.12;
// вероятность испарения ~ при T → 100
const escapeProb = Math.max(0, (T - 75)) / 25 * 0.0005;
for(const p of parts){
if(p.escaped){
// улетает вверх
p.x += p.vx * dt;
p.y += p.vy * dt;
p.vy -= 30 * dt; // тянет вверх (отрицательное y)
if(p.y < -10){
// респаун обратно в массу
p.escaped = false;
p.vx = 0; p.vy = 0;
p.x = p.x0; p.y = p.y0;
}
} else {
// случайные толчки + возврат к равновесному положению
p.vx += (Math.random() - 0.5) * amp * 20 * dt;
p.vy += (Math.random() - 0.5) * amp * 20 * dt;
// пружина к (x0, y0)
p.vx += (p.x0 - p.x) * 8 * dt;
p.vy += (p.y0 - p.y) * 8 * dt;
// демпфирование
p.vx *= 0.92;
p.vy *= 0.92;
p.x += p.vx * dt;
p.y += p.vy * dt;
// шанс испариться (для верхнего ряда)
if(p.y0 < 100 && Math.random() < escapeProb){
p.escaped = true;
p.vx = (Math.random() - 0.5) * 40;
p.vy = -60 - Math.random() * 40;
}
}
}
render();
}
function render(){
let g = '';
g += '<rect x="0" y="0" width="'+W+'" height="'+H+'" fill="#1e293b"/>';
// «поверхность» воды
g += '<line x1="0" y1="70" x2="'+W+'" y2="70" stroke="#0ea5e9" stroke-width="1.2" stroke-dasharray="4 4" opacity="0.5"/>';
g += '<text x="6" y="64" font-size="10" fill="#7dd3fc">поверхность</text>';
// дно
g += '<line x1="0" y1="'+(H-10)+'" x2="'+W+'" y2="'+(H-10)+'" stroke="#94a3b8" stroke-width="1"/>';
for(const p of parts){
const col = p.escaped ? '#fbbf24' : '#60a5fa';
g += '<circle cx="'+p.x.toFixed(1)+'" cy="'+p.y.toFixed(1)+'" r="5" fill="'+col+'" stroke="#0f172a" stroke-width="0.6"/>';
}
svg.innerHTML = g;
}
function updateInfo(T){
let txt;
if(T < 30){
txt = '<b>Низкая $t$.</b> Молекулы колеблются слабо, плотно упакованы. Ближний порядок чётко виден.';
} else if(T < 70){
txt = '<b>Комнатная $t$.</b> Амплитуда колебаний растёт, отдельные молекулы могут менять соседей.';
} else if(T < 95){
txt = '<b>Высокая $t$.</b> Колебания сильные, ближний порядок размывается. Возможно появление пузырьков пара.';
} else {
txt = '<b>$t \\to 100°$C.</b> Молекулы у поверхности «вырываются» наружу — <b>испарение</b> (см. §9).';
}
info.innerHTML = txt;
renderMath(info);
}
makeParts();
raf = requestAnimationFrame(frame);
updateInfo(+tInp.value);
tInp.addEventListener('input', () => {
const T = +tInp.value;
tLab.textContent = T;
updateInfo(T);
tempChanges.add(Math.round(T/20));
if(!_xpDone && tempChanges.size >= 3){
_xpDone = true;
addXp(10, 'p8-iv1');
bumpProgress('p8', 15);
}
});
btnPause.addEventListener('click', () => {
paused = !paused;
btnPause.textContent = paused ? 'Продолжить' : 'Пауза';
});
btnReset.addEventListener('click', () => { makeParts(); });
document.addEventListener('visibilitychange', () => {
if(document.hidden && raf){ cancelAnimationFrame(raf); raf = null; lastT = 0; }
else if(!document.hidden && !raf){ raf = requestAnimationFrame(frame); }
});
})();
/* IV2 — Калькулятор поверхностного натяжения */
(function(){
const liqSel = document.getElementById('p8-iv2-liq');
const lInp = document.getElementById('p8-iv2-L');
const rInp = document.getElementById('p8-iv2-r');
const out = document.getElementById('p8-iv2-out');
const fb = document.getElementById('p8-iv2-fb');
const go = document.getElementById('p8-iv2-go');
const DATA = {
water: { sigma: 0.073, rho: 1000, name: 'Вода' },
alc: { sigma: 0.022, rho: 790, name: 'Спирт' },
hg: { sigma: 0.465, rho: 13600, name: 'Ртуть' },
};
const used = new Set();
let _done = false;
function calc(){
const liq = liqSel.value;
const d = DATA[liq];
const L = parseFloat((lInp.value||'').replace(',','.'));
const r_mm = parseFloat((rInp.value||'').replace(',','.'));
if(!isFinite(L) || L <= 0 || !isFinite(r_mm) || r_mm <= 0){
feedback(fb, false, '&#10007; $L$ и $r$ должны быть положительными.');
return;
}
const F = d.sigma * L;
const r = r_mm / 1000;
const g = 9.8;
// для смачивающей (вода/спирт) θ ≈ 0, cosθ = 1; для ртути — несмачивает, θ > 90 → h отрицательное
let h_m, hLabel;
if(liq === 'hg'){
// ртуть на стекле: θ ≈ 140°, cos ≈ 0.766
h_m = 2 * d.sigma * Math.cos(140 * Math.PI / 180) / (d.rho * g * r);
hLabel = 'опускается на $|h| \\approx '+(Math.abs(h_m)*1000).toFixed(2)+'$ мм (несмачивание)';
} else {
h_m = 2 * d.sigma / (d.rho * g * r);
hLabel = 'поднимается на $h \\approx '+(h_m*1000).toFixed(2)+'$ мм';
}
out.innerHTML =
'<div><b>'+d.name+':</b> $\\sigma = '+d.sigma+'$ Н/м, $\\rho = '+d.rho+'$ кг/м³</div>'
+ '<div style="margin-top:6px"><b>Сила натяжения:</b> $F = \\sigma L = '+d.sigma+' \\cdot '+L+' \\approx '+(+F.toFixed(5))+'$ Н</div>'
+ '<div style="margin-top:6px"><b>В капилляре $r = '+r_mm+'$ мм:</b> жидкость '+hLabel+'</div>';
renderMath(out);
feedback(fb, true, '&#10003; Вычислено.');
used.add(liq);
if(!_done && used.size >= 2){ _done = true; addXp(10, 'p8-iv2'); bumpProgress('p8', 15); }
}
go.addEventListener('click', calc);
})();
/* IV3 — квикфайр: смачивает или нет */
(function(){
const Q = [
{ q:'Вода на чистом стекле', ans:1, why:'Стекло хорошо смачивается водой ($\\theta \\approx 0°$).' },
{ q:'Ртуть на стекле', ans:0, why:'Ртуть не смачивает стекло, $\\theta \\approx 140°$, образует выпуклый мениск.' },
{ q:'Вода на парафине (свечном воске)', ans:0, why:'Парафин гидрофобен — вода не смачивает, скатывается каплями.' },
{ q:'Спирт на стекле', ans:1, why:'Спирт смачивает стекло ещё лучше воды.' },
{ q:'Жидкое мыло на тарелке', ans:1, why:'Мыло — поверхностно-активное вещество, отлично смачивает.' },
{ q:'Капля воды на листе лотоса', ans:0, why:'Лист лотоса имеет микрорельеф и воск — вода скатывается шариками.' },
];
let i = 0, score = 0;
const qEl = document.getElementById('p8-iv3-q');
const oEl = document.getElementById('p8-iv3-opts');
const fb = document.getElementById('p8-iv3-fb');
const iEl = document.getElementById('p8-iv3-i');
const sEl = document.getElementById('p8-iv3-s');
function show(){
if(i >= Q.length){
qEl.innerHTML = '<b>Готово!</b> Результат: ' + score + ' / ' + Q.length;
oEl.innerHTML = '';
if(score === Q.length){ addXp(15, 'p8-iv3'); bumpProgress('p8', 25); }
else if(score >= 4){ addXp(8, 'p8-iv3'); bumpProgress('p8', 15); }
return;
}
iEl.textContent = (i+1); sEl.textContent = score;
qEl.innerHTML = Q[i].q;
oEl.innerHTML = '<button class="btn primary" data-v="1">Смачивает</button><button class="btn primary" data-v="0" style="background:#ef4444;border-color:#ef4444">Не смачивает</button>';
fb.style.display = 'none';
renderMath(qEl);
oEl.querySelectorAll('button').forEach(b => {
b.addEventListener('click', () => {
const v = +b.dataset.v;
if(v === Q[i].ans){ score++; feedback(fb, true, '&#10003; Верно! '+Q[i].why+' Дальше ▶'); }
else feedback(fb, false, '&#10007; Неверно. '+Q[i].why+' Дальше ▶');
sEl.textContent = score;
oEl.querySelectorAll('button').forEach(x => x.disabled = true);
i++;
setTimeout(show, 1700);
});
});
}
document.getElementById('p8-iv3-restart').addEventListener('click', () => { i = 0; score = 0; show(); });
show();
})();
/* IV4 — Тренажёр жидкости */
(function(){
const Q = [
{ q:'$\\sigma = 0{,}073$ Н/м, $L = 0{,}2$ м. Найди силу $F$ в Н (с точностью до 3 знаков).', ans:0.0146, hint:'$F = \\sigma L = 0{,}073 \\cdot 0{,}2 = 0{,}0146$ Н.', tol:0.002 },
{ q:'При одинаковой длине $L = 1$ м что больше: $F$ для воды или для ртути? Введи 1 = вода, 2 = ртуть.', ans:2, hint:'$\\sigma_{\\text{Hg}} = 0{,}465 > \\sigma_{\\text{в}} = 0{,}073$ — больше у ртути.', tol:0.1 },
{ q:'Высота поднятия воды в капилляре $r = 0{,}5$ мм. Введи в мм (целое). $\\sigma = 0{,}073$, $\\rho = 1000$, $g = 10$, $\\cos\\theta = 1$.', ans:29, hint:'$h = \\dfrac{2\\sigma}{\\rho g r} = \\dfrac{2 \\cdot 0{,}073}{1000 \\cdot 10 \\cdot 0{,}0005} \\approx 0{,}029$ м $\\approx 29$ мм.', tol:3 },
{ q:'Жидкость, у которой $\\theta < 90°$ на твёрдой поверхности — смачивает (1) или нет (2)?', ans:1, hint:'По определению, $\\theta < 90°$ — это смачивание.', tol:0.1 },
{ q:'В капилляре жидкость поднимается выше при меньшем (1) или большем (2) радиусе?', ans:1, hint:'$h \\sim 1/r$ — чем тоньше капилляр, тем выше поднятие.', tol:0.1 },
];
let i = 0, score = 0;
function show(){
if(i >= Q.length){
document.getElementById('p8-iv4-q').innerHTML = '<b>Готово!</b> Результат: ' + score + ' / ' + Q.length;
if(score === Q.length){ addXp(15, 'p8-iv4'); bumpProgress('p8', 25); }
else if(score >= 3){ addXp(8, 'p8-iv4'); bumpProgress('p8', 15); }
return;
}
document.getElementById('p8-iv4-i').textContent = (i+1);
document.getElementById('p8-iv4-s').textContent = score;
document.getElementById('p8-iv4-q').innerHTML = Q[i].q;
document.getElementById('p8-iv4-ans').value = '';
renderMath(document.getElementById('p8-iv4-q'));
document.getElementById('p8-iv4-fb').style.display = 'none';
}
function go(){
if(i >= Q.length) return;
const fb = document.getElementById('p8-iv4-fb');
const raw = document.getElementById('p8-iv4-ans').value.replace(',', '.');
const ans = parseFloat(raw);
if(isNaN(ans)){ feedback(fb, false, '&#10007; Введи число.'); return; }
const tol = Q[i].tol || Math.max(0.05 * Math.abs(Q[i].ans), 0.05);
if(Math.abs(ans - Q[i].ans) < tol + 0.001){ score++; feedback(fb, true, '&#10003; Верно! '+Q[i].hint+' Дальше ▶'); }
else feedback(fb, false, '&#10007; Неверно. Ответ: $'+Q[i].ans+'$. '+Q[i].hint+' Дальше ▶');
document.getElementById('p8-iv4-s').textContent = score;
i++;
setTimeout(show, 1900);
}
document.getElementById('p8-iv4-go').addEventListener('click', go);
document.getElementById('p8-iv4-ans').addEventListener('keydown', e => { if(e.key === 'Enter') go(); });
document.getElementById('p8-iv4-start').addEventListener('click', () => { i = 0; score = 0; show(); });
show();
})();
wireReadBtn('p8');
}