125 lines
4.5 KiB
TypeScript
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,
|
|
}));
|
|
};
|