first2
This commit is contained in:
160
frontend/lib/chartDataAggregator.ts
Normal file
160
frontend/lib/chartDataAggregator.ts
Normal file
@@ -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<string, { sum: number; count: number; date: Date }>()
|
||||
|
||||
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<string, { sum: number; count: number; date: Date }>()
|
||||
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user