diff --git a/cmd/server/web/js/app.ts b/cmd/server/web/js/app.ts index 10fc24b..b05742b 100644 --- a/cmd/server/web/js/app.ts +++ b/cmd/server/web/js/app.ts @@ -1,6 +1,6 @@ // app.js (оркестратор) import { fetchHealth, fetchHistory } from "./data.js"; -import { state, smooth, addSignals, resetBufferTracking } from "./state.js"; +import { state, addSignals, resetBufferTracking, updatePeakHolder, forceResetPeak, getPeakInfo } from "./state.js"; import { initDOM, setStatus, setMeta, setBars, setSignal, DOM } from "./ui.js"; import { initAccordion } from "./accordion.js"; import { drawChart } from "./chart.js"; @@ -86,11 +86,13 @@ async function update(): Promise { const percent = (value / 63) * 100; if (isOnline) { - setBars(smooth(percent)); - setSignal(level); + const displayValue = updatePeakHolder(percent); + setBars(displayValue); + setSignal(level); } else { - setBars(0, true); - setSignal(0, true); + // Сервер НЕ на связи - сбрасываем индикаторы в 0 и делаем серыми + setBars(0, true); // true = режим "нет соединения" + setSignal(0, true); // true = режим "нет соединения" } if (DOM.lastByte) { diff --git a/cmd/server/web/js/state.ts b/cmd/server/web/js/state.ts index ea7f473..6fb6d4e 100644 --- a/cmd/server/web/js/state.ts +++ b/cmd/server/web/js/state.ts @@ -1,23 +1,115 @@ -// state.js (вся логика состояния) +// state.ts - Peak Holder алгоритм с таймером + interface AppState { maxPoints: number; signalHistory: number[]; - smoothValue: number; lastBufferSize: number; + + // Peak Holder параметры + peakValue: number; // Текущее удерживаемое пиковое значение + currentValue: number; // Текущее реальное значение (без сглаживания) + peakTimer: number | null; // Таймер для сброса пика + peakHoldTime: number; // Время удержания пика в миллисекундах } export const state: AppState = { maxPoints: 1000, signalHistory: [], - smoothValue: 0, lastBufferSize: 0, + + peakValue: 0, + currentValue: 0, + peakTimer: null, + peakHoldTime: 3000, // миллисекунды удержания пика }; -export function smooth(target: number): number { - state.smoothValue += 0.2 * (target - state.smoothValue); - return state.smoothValue; +/** + * Основная функция peak holder + * @param target - новое значение (0-63) + * @returns значение для отображения (пик, если таймер активен) + */ +export function updatePeakHolder(target: number): number { + // Обновляем текущее значение + state.currentValue = target; + + // Если новое значение больше текущего пика + if (target > state.peakValue) { + // Устанавливаем новый пик + state.peakValue = target; + + // Сбрасываем и перезапускаем таймер + resetPeakTimer(); + startPeakTimer(); + } + + // Возвращаем текущий пик для отображения + return state.peakValue; } +/** + * Запуск таймера сброса пика + */ +function startPeakTimer(): void { + if (state.peakTimer !== null) { + clearTimeout(state.peakTimer); + } + + state.peakTimer = window.setTimeout(() => { + resetPeak(); + }, state.peakHoldTime); +} + +/** + * Сброс таймера пика + */ +function resetPeakTimer(): void { + if (state.peakTimer !== null) { + clearTimeout(state.peakTimer); + state.peakTimer = null; + } +} + +/** + * Сброс пикового значения до текущего уровня + */ +function resetPeak(): void { + state.peakValue = state.currentValue; + state.peakTimer = null; + + // Опционально: лог для отладки + // console.log(`[PeakHolder] Reset to: ${state.peakValue}`); +} + +/** + * Принудительный сброс пика (например, при потере связи) + */ +export function forceResetPeak(): void { + resetPeakTimer(); + state.peakValue = 0; + state.currentValue = 0; +} + +/** + * Обновление времени удержания пика + * @param ms - время в миллисекундах + */ +export function setPeakHoldTime(ms: number): void { + state.peakHoldTime = ms; +} + +/** + * Получение текущего состояния пика (для отладки) + */ +export function getPeakInfo(): { peak: number; current: number; timerActive: boolean } { + return { + peak: state.peakValue, + current: state.currentValue, + timerActive: state.peakTimer !== null, + }; +} + +// ===== ОСТАВЛЯЕМ СУЩЕСТВУЮЩИЕ ФУНКЦИИ БЕЗ ИЗМЕНЕНИЙ ===== + export function addSignal(value: number): void { state.signalHistory.push(value); if (state.signalHistory.length > state.maxPoints) { @@ -45,4 +137,5 @@ export function addSignals(values: number[], bufferSize: number): void { export function resetBufferTracking(): void { state.lastBufferSize = 0; + forceResetPeak(); // Также сбрасываем пик при потере связи } \ No newline at end of file