From 135921eb14dae2eab378f57606d813cbb7b202b2 Mon Sep 17 00:00:00 2001 From: sysadminix Date: Mon, 2 Feb 2026 13:40:13 +0300 Subject: [PATCH] first2 --- frontend/lib/chartDataAggregator.ts | 160 ++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 frontend/lib/chartDataAggregator.ts diff --git a/frontend/lib/chartDataAggregator.ts b/frontend/lib/chartDataAggregator.ts new file mode 100644 index 0000000..add25fc --- /dev/null +++ b/frontend/lib/chartDataAggregator.ts @@ -0,0 +1,160 @@ +/** + * Утилита для агрегации часовых данных в дневные + */ + +export interface ChartDataPoint { + timestamp: string + value: number + label?: string +} + +/** + * Агрегирует часовые данные в дневные на основе периода + * @param hourlyData - Массив часовых данных + * @param timePeriod - Период в часах ('24', '72', '168', '720') + * @returns Агрегированные дневные данные + */ +export function aggregateChartDataByDays( + hourlyData: ChartDataPoint[], + timePeriod: string +): ChartDataPoint[] { + if (!Array.isArray(hourlyData) || hourlyData.length === 0) { + return [] + } + + // Для периода в 24 часа - возвращаем часовые данные как есть + if (timePeriod === '24') { + return hourlyData.map(d => ({ + ...d, + label: d.label || new Date(d.timestamp).toLocaleTimeString('ru-RU', { + hour: '2-digit', + minute: '2-digit' + }) + })) + } + + // Для остальных периодов - агрегируем по дням + const dailyMap = new Map() + + hourlyData.forEach(point => { + const date = new Date(point.timestamp) + // Получаем дату в формате YYYY-MM-DD + const dateKey = date.toISOString().split('T')[0] + + if (!dailyMap.has(dateKey)) { + dailyMap.set(dateKey, { sum: 0, count: 0, date }) + } + + const entry = dailyMap.get(dateKey)! + entry.sum += point.value + entry.count += 1 + }) + + // Преобразуем в массив и сортируем по дате + const dailyData = Array.from(dailyMap.entries()) + .sort((a, b) => new Date(a[0]).getTime() - new Date(b[0]).getTime()) + .map(([dateKey, data]) => { + const date = new Date(dateKey) + + // Форматируем подпись в зависимости от периода + let label = '' + if (timePeriod === '72') { + // 3 дня - показываем день недели и дату + label = date.toLocaleDateString('ru-RU', { + weekday: 'short', + day: '2-digit', + month: '2-digit' + }) + } else if (timePeriod === '168') { + // Неделя - показываем день недели + label = date.toLocaleDateString('ru-RU', { + weekday: 'short', + day: '2-digit' + }) + } else if (timePeriod === '720') { + // Месяц - показываем дату + label = date.toLocaleDateString('ru-RU', { + day: '2-digit', + month: '2-digit' + }) + } + + return { + timestamp: date.toISOString(), + value: data.sum, + label + } + }) + + return dailyData +} + +/** + * Получает среднее значение за день (для альтернативной агрегации) + */ +export function aggregateChartDataByDaysAverage( + hourlyData: ChartDataPoint[], + timePeriod: string +): ChartDataPoint[] { + if (!Array.isArray(hourlyData) || hourlyData.length === 0) { + return [] + } + + if (timePeriod === '24') { + return hourlyData.map(d => ({ + ...d, + label: d.label || new Date(d.timestamp).toLocaleTimeString('ru-RU', { + hour: '2-digit', + minute: '2-digit' + }) + })) + } + + const dailyMap = new Map() + + hourlyData.forEach(point => { + const date = new Date(point.timestamp) + const dateKey = date.toISOString().split('T')[0] + + if (!dailyMap.has(dateKey)) { + dailyMap.set(dateKey, { sum: 0, count: 0, date }) + } + + const entry = dailyMap.get(dateKey)! + entry.sum += point.value + entry.count += 1 + }) + + const dailyData = Array.from(dailyMap.entries()) + .sort((a, b) => new Date(a[0]).getTime() - new Date(b[0]).getTime()) + .map(([dateKey, data]) => { + const date = new Date(dateKey) + + let label = '' + if (timePeriod === '72') { + label = date.toLocaleDateString('ru-RU', { + weekday: 'short', + day: '2-digit', + month: '2-digit' + }) + } else if (timePeriod === '168') { + label = date.toLocaleDateString('ru-RU', { + weekday: 'short', + day: '2-digit' + }) + } else if (timePeriod === '720') { + label = date.toLocaleDateString('ru-RU', { + day: '2-digit', + month: '2-digit' + }) + } + + return { + timestamp: date.toISOString(), + value: Math.round(data.sum / data.count), // Среднее значение + label + } + }) + + return dailyData +}