Files
dashboard/utils/chartDataUtils.ts

125 lines
4.5 KiB
TypeScript

import { BehaviorDataPoint, CycleData } from '../types.ts';
type TimeRange = '24h' | '7d' | '30d' | 'cycle';
export const generateBehaviorChartData = (
data: BehaviorDataPoint[],
timeRange: TimeRange,
cycleData: CycleData
) => {
const now = new Date();
if (timeRange === '24h') {
const hourlyAverages: {
[key: string]: { totalActivity: number; totalStress: number; count: number };
} = {};
const startOfPeriod = new Date(now);
startOfPeriod.setHours(startOfPeriod.getHours() - 24);
data.forEach((point) => {
if (point.timestamp >= startOfPeriod) {
const hourKey = `${point.timestamp.getFullYear()}-${point.timestamp.getMonth()}-${point.timestamp.getDate()}-${point.timestamp.getHours()}`;
if (!hourlyAverages[hourKey]) {
hourlyAverages[hourKey] = { totalActivity: 0, totalStress: 0, count: 0 };
}
hourlyAverages[hourKey].totalActivity += point.activity;
hourlyAverages[hourKey].totalStress += point.stress;
hourlyAverages[hourKey].count++;
}
});
const result: { date: string; activity: number; stress: number }[] = [];
for (let i = 23; i >= 0; i--) {
const date = new Date(now);
date.setHours(now.getHours() - i, 0, 0, 0);
const hourKey = `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}-${date.getHours()}`;
const hourString = date.toLocaleTimeString('id-ID', { hour: '2-digit' }) + ':00';
if (hourlyAverages[hourKey]) {
result.push({
date: hourString,
activity: hourlyAverages[hourKey].totalActivity / hourlyAverages[hourKey].count,
stress: hourlyAverages[hourKey].totalStress / hourlyAverages[hourKey].count,
});
} else {
result.push({ date: hourString, activity: 0, stress: 0 });
}
}
return result;
}
if (timeRange === 'cycle') {
const weeklyAverages: {
[key: string]: { totalActivity: number; totalStress: number; count: number };
} = {};
const cycleStartDate = new Date(cycleData.startDate);
const totalWeeks = Math.ceil(cycleData.totalDays / 7);
for (let i = 1; i <= totalWeeks; i++) {
weeklyAverages[`M${i}`] = { totalActivity: 0, totalStress: 0, count: 0 };
}
data.forEach((point) => {
if (point.timestamp >= cycleStartDate) {
const diffTime = point.timestamp.getTime() - cycleStartDate.getTime();
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
if (diffDays >= 0 && diffDays < cycleData.totalDays) {
const weekNumber = Math.floor(diffDays / 7) + 1;
if (weekNumber > 0 && weekNumber <= totalWeeks) {
const week = weeklyAverages[`M${weekNumber}`];
if (week) {
week.totalActivity += point.activity;
week.totalStress += point.stress;
week.count++;
}
}
}
}
});
return Object.entries(weeklyAverages).map(([date, values]) => ({
date,
activity: values.count > 0 ? values.totalActivity / values.count : 0,
stress: values.count > 0 ? values.totalStress / values.count : 0,
}));
}
const days = timeRange === '7d' ? 7 : 30;
const dailyAverages: {
[key: string]: { totalActivity: number; totalStress: number; count: number };
} = {};
for (let i = days - 1; i >= 0; i--) {
const date = new Date(now);
date.setDate(now.getDate() - i);
const formatOptions: Intl.DateTimeFormatOptions =
timeRange === '7d' ? { weekday: 'short' } : { day: 'numeric', month: 'short' };
const dateString = date.toLocaleDateString('id-ID', formatOptions);
dailyAverages[dateString] = { totalActivity: 0, totalStress: 0, count: 0 };
}
const startOfPeriod = new Date(now);
startOfPeriod.setDate(startOfPeriod.getDate() - days);
startOfPeriod.setHours(0, 0, 0, 0);
data.forEach((point) => {
if (point.timestamp >= startOfPeriod) {
const formatOptions: Intl.DateTimeFormatOptions =
timeRange === '7d' ? { weekday: 'short' } : { day: 'numeric', month: 'short' };
const dateString = point.timestamp.toLocaleDateString('id-ID', formatOptions);
if (dailyAverages[dateString]) {
dailyAverages[dateString].totalActivity += point.activity;
dailyAverages[dateString].totalStress += point.stress;
dailyAverages[dateString].count++;
}
}
});
return Object.entries(dailyAverages).map(([date, values]) => ({
date,
activity: values.count > 0 ? values.totalActivity / values.count : 0,
stress: values.count > 0 ? values.totalStress / values.count : 0,
}));
};