/
hamster75
/
Life
Обзор
Документация
Войти
/
hamster75
/
Life
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
6
CI/CD
Аналитика
Безопасность
master
js/controls.js
152 строки
5 KB
Dmitry Smirnov
on the road to fix freeze
26 май 2026, 08:04
26 май 2026, 08:04
d56cea3
Код
Авторство
О чём код?
import { SimState } from './simulation.js'; import { markPlayPressed } from './quest-events.js'; export class Controls { constructor(simulation, algorithms) { this.sim = simulation; this._algorithms = algorithms; this._btnPlay = document.getElementById('btn-play'); this._btnPause = document.getElementById('btn-pause'); this._btnStop = document.getElementById('btn-stop'); this._btnReset = document.getElementById('btn-reset'); this._btnClear = document.getElementById('btn-clear'); this._slider = document.getElementById('speed-slider'); this._speedLabel = document.getElementById('speed-label'); this._statusMode = document.getElementById('status-mode'); this._statusGen = document.getElementById('status-gen'); this._statusPop = document.getElementById('status-pop'); this._algoSelect = document.getElementById('algo-select'); this._algoDesc = document.getElementById('algo-description'); this._perfCounter = document.getElementById('perf-counter'); this._stepControl = document.getElementById('step-control'); this._stepSlider = document.getElementById('step-log2-slider'); this._stepLog2Label = document.getElementById('step-log2-label'); this._computingEl = document.getElementById('computing-indicator'); this._busyTimer = null; this._bindButtons(); this._bindSlider(); this._bindAlgoSelect(); this._bindStepSlider(); simulation.onState(() => this._syncButtons(simulation.state)); simulation.onBusy(isBusy => this._onBusy(isBusy)); simulation.onTick(gen => { this._statusGen.textContent = `Поколение: ${gen}`; if (this._statusPop) { const ts = typeof simulation.algorithm.getTreeState === 'function' ? simulation.algorithm.getTreeState() : null; const pop = ts ? ts.root.population : typeof simulation.algorithm.getPopulation === 'function' ? simulation.algorithm.getPopulation() : null; this._statusPop.textContent = pop !== null ? `Клеток: ${pop.toLocaleString('ru')}` : ''; } this._tickCount++; }); this._syncButtons(SimState.STOPPED); this._updateAlgoDesc(); this._startPerfCounter(); } _bindButtons() { this._btnPlay.addEventListener('click', () => { this.sim.play(); markPlayPressed(); }); this._btnPause.addEventListener('click', () => this.sim.pause()); this._btnStop.addEventListener('click', () => this.sim.stop()); this._btnReset.addEventListener('click', () => this.sim.reset()); this._btnClear.addEventListener('click', () => this.sim.clear()); } _bindSlider() { const update = () => { const v = Number(this._slider.value); this._speedLabel.textContent = v; this.sim.setSpeed(v); }; this._slider.addEventListener('input', update); this.sim.setSpeed(Number(this._slider.value)); } _bindAlgoSelect() { this._algoSelect.addEventListener('change', () => { const key = this._algoSelect.value; const algo = this._algorithms[key](); this.sim.setAlgorithm(algo); this._updateAlgoDesc(); this._syncButtons(this.sim.state); this._syncStepControl(); }); } _bindStepSlider() { this._stepSlider.addEventListener('input', () => { const bits = Number(this._stepSlider.value); this._stepLog2Label.textContent = bits; if (this.sim.algorithm.stepLog2 !== undefined) { this.sim.algorithm.stepLog2 = bits; } }); this._syncStepControl(); } _syncStepControl() { const isHashLife = this.sim.algorithm.stepLog2 !== undefined; this._stepControl.style.display = isHashLife ? '' : 'none'; if (isHashLife) { this.sim.algorithm.stepLog2 = Number(this._stepSlider.value); } } _updateAlgoDesc() { this._algoDesc.textContent = this.sim.algorithm.description; } _syncButtons(state) { const stopped = state === SimState.STOPPED; const running = state === SimState.RUNNING; const paused = state === SimState.PAUSED; this._btnPlay.disabled = running; this._btnPause.disabled = !running; this._btnStop.disabled = stopped; this._btnReset.disabled = false; const modeText = running ? 'симуляция' : paused ? 'пауза' : 'редактирование'; this._statusMode.textContent = `Режим: ${modeText}`; } _onBusy(isBusy) { if (isBusy) { this._busyTimer = setTimeout(() => { if (this._computingEl) this._computingEl.classList.add('visible'); }, 150); } else { clearTimeout(this._busyTimer); if (this._computingEl) this._computingEl.classList.remove('visible'); } } _startPerfCounter() { this._tickCount = 0; this._perfT0 = performance.now(); setInterval(() => { const dt = (performance.now() - this._perfT0) / 1000; if (dt > 0 && this.sim.state === SimState.RUNNING) { const tps = Math.round(this._tickCount / dt); this._perfCounter.textContent = `${tps} t/s`; } else if (this.sim.state !== SimState.RUNNING) { this._perfCounter.textContent = ''; } this._tickCount = 0; this._perfT0 = performance.now(); }, 500); } }