// F6. Симулятор скоростной дороги (§20 в ch2) — μ и тормозной путь. (function(){ 'use strict'; const B = () => window.PHYS9_FLAG_BASE; const C = () => window.PHYS9_COLORS || {}; const SURFACES = { asphalt_dry: { mu: 0.7, name: 'асфальт сухой', col: '#1e293b' }, asphalt_wet: { mu: 0.4, name: 'асфальт мокрый', col: '#475569' }, gravel: { mu: 0.55, name: 'гравий', col: '#92400e' }, snow: { mu: 0.2, name: 'снег', col: '#cbd5e1' }, ice: { mu: 0.08, name: 'лёд', col: '#bfdbfe' } }; function init(secId){ if (!B()) return false; let surfBtns = ''; for (const id in SURFACES){ const s = SURFACES[id]; surfBtns += ''; } const body = '' + '
'+surfBtns+'
' + '
' + '' + '
' + '' + '
' + '' + '' + '
' + '
' + '
Покрытиесухой асфальт
' + '
μ0.7
' + '
Тормозной путь20.4 м
' + '
Время торможения2.43 с
' + '
' + '
'; const card = B().makeCard(secId, 'F6. Симулятор скоростной дороги', 'Выбери покрытие и скорость. При торможении: $s = v^2/(2\\mu g)$. На льду путь в 8 раз длиннее!', body); if (!card) return false; const cv = document.getElementById('F6-cv'); const ctx = cv.getContext('2d'); const W = cv.width, H = cv.height; let surf = 'asphalt_dry'; let st = { x: 50, v: 0, vTarget: 60/3.6, mode: 'cruise' }; function update(){ const v_kmh = +document.getElementById('F6-v').value; document.getElementById('F6-vv').textContent = v_kmh; st.vTarget = v_kmh / 3.6; const mu = SURFACES[surf].mu; const v = st.vTarget; const sStop = v*v / (2 * mu * 9.8); const tStop = v / (mu * 9.8); document.getElementById('F6-surf').textContent = SURFACES[surf].name; document.getElementById('F6-mu').textContent = mu; document.getElementById('F6-stop').textContent = sStop.toFixed(1) + ' м'; document.getElementById('F6-tstop').textContent = tStop.toFixed(2) + ' с'; } function reset(){ st = { x: 50, v: st.vTarget, mode: 'cruise' }; document.getElementById('F6-fb').className = 'flag-feedback'; draw(); } function tick(dt){ const mu = SURFACES[surf].mu; if (st.mode === 'cruise'){ st.v = st.vTarget; st.x += st.v * dt * 5; /* 5 px = 1 м */ if (st.x > W + 50) st.x = -20; } else if (st.mode === 'brake'){ st.v -= mu * 9.8 * dt; if (st.v < 0){ st.v = 0; st.mode = 'stopped'; } st.x += st.v * dt * 5; } draw(); } function draw(){ const col = C(); ctx.fillStyle = col.bg || '#fafafa'; ctx.fillRect(0, 0, W, H); /* небо */ ctx.fillStyle = col.gas || '#dbeafe'; ctx.fillRect(0, 0, W, 80); /* дорога */ const s = SURFACES[surf]; ctx.fillStyle = s.col; ctx.fillRect(0, 80, W, 80); /* разметка */ ctx.strokeStyle = '#fff'; ctx.lineWidth = 3; ctx.setLineDash([24, 16]); ctx.beginPath(); ctx.moveTo(0, 120); ctx.lineTo(W, 120); ctx.stroke(); ctx.setLineDash([]); /* шкала метров */ ctx.fillStyle = col.text || '#0f172a'; ctx.font = '11px Inter,sans-serif'; for (let m = 0; m <= 140; m += 10){ const px = 50 + m*5; if (px > W) break; ctx.fillRect(px-1, 160, 2, 6); if (m % 20 === 0) ctx.fillText(m + ' м', px - 8, 178); } /* трава */ ctx.fillStyle = '#16a34a'; ctx.fillRect(0, 180, W, H - 180); /* машина */ ctx.fillStyle = col.fail || '#dc2626'; ctx.fillRect(st.x - 25, 95, 50, 22); ctx.fillRect(st.x - 18, 88, 36, 9); ctx.fillStyle = '#0f172a'; ctx.fillRect(st.x - 16, 117, 8, 8); ctx.fillRect(st.x + 8, 117, 8, 8); /* подпись */ ctx.fillStyle = col.text || '#0f172a'; ctx.font = 'bold 13px Inter,sans-serif'; ctx.fillText((st.v*3.6).toFixed(0) + ' км/ч', st.x - 22, 78); /* shadow */ ctx.fillStyle = 'rgba(0,0,0,0.3)'; ctx.fillRect(st.x - 25, 130, 50, 4); } card.querySelectorAll('[data-surf]').forEach(btn => { btn.addEventListener('click', () => { surf = btn.dataset.surf; card.querySelectorAll('[data-surf]').forEach(b => b.classList.remove('primary')); btn.classList.add('primary'); update(); reset(); }); }); document.getElementById('F6-v').addEventListener('input', () => { update(); if(st.mode==='cruise') st.v = st.vTarget; }); document.getElementById('F6-brake').addEventListener('click', () => { if (st.mode === 'cruise'){ st.mode = 'brake'; const fb = document.getElementById('F6-fb'); const mu = SURFACES[surf].mu; const v = st.v; const sStop = v*v / (2 * mu * 9.8); fb.className = 'flag-feedback warn show'; fb.innerHTML = 'Торможение на ' + SURFACES[surf].name + ' с ' + (v*3.6).toFixed(0) + ' км/ч — потребуется ' + sStop.toFixed(1) + ' м.'; } }); document.getElementById('F6-reset').addEventListener('click', reset); update(); reset(); B().startLoop('F6', cv, tick); return true; } if (window.PHYS9_FLAG_BASE) window.PHYS9_FLAG_BASE.register('F6', { init: init, cleanup: function(){} }); else document.addEventListener('DOMContentLoaded', ()=>{ if (window.PHYS9_FLAG_BASE) window.PHYS9_FLAG_BASE.register('F6', { init: init, cleanup: function(){} }); }); })();