'use strict'; /* ════════════════════════════════════════════════════════════════════════ _sim_demo — рукописная демо-спека «Бросок тела» (projectile) для проверки рантайма Фазы 0. Регистрируется как id 'customdemo' ТОЛЬКО за флагом — не светится ученикам в каталоге (карточка не добавляется в SIMS). Включение для проверки (любой из вариантов): - URL: /lab?simdemo=1 (или ?sim=customdemo прямой deep-link) - глоб: window.LAB_SHOW_SPEC_DEMO = true (до загрузки labs-скриптов) - localStorage.setItem('lab-spec-demo','1') Проверка: открыть /lab?simdemo=1 -> карточка появится; либо открыть /lab?sim=customdemo напрямую. Слайдеры угла/скорости меняют траекторию, play/pause/reset работают. Это ВРЕМЕННЫЙ раздел (удалить после Фазы 4). ════════════════════════════════════════════════════════════════════════ */ (function (global) { function demoEnabled() { try { var qs = (global.location && global.location.search) || ''; if (/[?&]simdemo=1\b/.test(qs)) return true; if (/[?&]sim=customdemo\b/.test(qs)) return true; if (global.LAB_SHOW_SPEC_DEMO === true) return true; if (global.localStorage && global.localStorage.getItem('lab-spec-demo') === '1') return true; } catch (e) { /* noop */ } return false; } // Спека v1: бросок тела. g фиксирован 10 -> y = v*sin(θ)*t - 5*t^2. var PROJECTILE_DEMO = { id: 'customdemo', cat: 'phys', meta: { title: 'Демо: бросок тела', desc: 'Спек-симуляция (Фаза 0). Угол и скорость — слайдеры.' }, viewport: { xmin: 0, xmax: 60, ymin: 0, ymax: 30, grid: true, axes: true, bg: '#0D0D1A' }, time: { autoplay: false, loop: true, duration: 8, speed: 1 }, params: [ { name: 'theta', label: 'Угол θ', min: 0, max: 90, step: 1, value: 45, unit: '°' }, { name: 'v', label: 'Скорость v', min: 0, max: 30, step: 0.5, value: 20, unit: 'м/с' } ], objects: [ // снаряд: x = v*cos(θ)*t, y = v*sin(θ)*t - 5 t^2 (но не ниже 0) { id: 'ball', type: 'point', x: 'v*cos(theta*pi/180)*t', y: 'max(0, v*sin(theta*pi/180)*t - 5*t^2)', r: 7, color: '#06D6E0', trail: true, trailColor: '#9B5DE5' }, // вектор начальной скорости из старта { type: 'vector', x1: 0, y1: 0, x2: 'cos(theta*pi/180)*v*0.4', y2: 'sin(theta*pi/180)*v*0.4', color: '#FFD166', width: 3 }, // земля { type: 'segment', x1: 0, y1: 0, x2: 60, y2: 0, color: 'rgba(255,255,255,0.35)', width: 2 }, // подпись над снарядом { type: 'label', latex: true, x: 'ball.x', y: 'ball.y + 2.5', text: 'v_0', color: '#06D6E0', size: 15 } ] }; function tryRegister() { if (!demoEnabled()) return; if (typeof global.registerSpecSim !== 'function') { if (global.console) console.warn('[sim-demo] registerSpecSim недоступен'); return; } global.registerSpecSim(PROJECTILE_DEMO); // Если каталог уже отрисован, добавить карточку демо вручную (минимально- // инвазивно: только когда флаг включён; не трогаем SIMS/каталожный рендер). addDemoCardIfNeeded(); } function addDemoCardIfNeeded() { var grid = document.getElementById('sim-grid'); if (!grid) return; if (document.getElementById('sim-card-customdemo')) return; var m = global.LabRegistry && global.LabRegistry.get('customdemo'); if (!m) return; var preview = global.LabRegistry.resolvePreview(m); var card = document.createElement('div'); card.id = 'sim-card-customdemo'; card.className = 'sim-card'; card.setAttribute('onclick', "openSim('customdemo')"); card.innerHTML = preview + '