training-load-dataviz / src /utils /dataProcessor.ts
glutamatt's picture
glutamatt HF Staff
init
35527e2 verified
raw
history blame
3.22 kB
import type { Activity, ProcessedData } from '@/types';
/**
* Format date to YYYY-MM-DD in local timezone (not UTC)
*/
function formatDateLocal(date: Date): string {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
export function processActivities(activities: Activity[], dateRange?: { start: Date; end: Date }): ProcessedData {
if (activities.length === 0 && !dateRange) {
return {
activities: [],
dates: [],
distances: [],
durations: [],
tss: [],
};
}
// Sort activities by date
const sortedActivities = [...activities].sort((a, b) => a.date.getTime() - b.date.getTime());
// Get date range
const startDate = dateRange?.start || (sortedActivities.length > 0 ? new Date(sortedActivities[0].date) : new Date());
const endDate = dateRange?.end || (sortedActivities.length > 0 ? new Date(sortedActivities[sortedActivities.length - 1].date) : new Date());
// Create a map of date -> activities
const activityMap = new Map<string, Activity[]>();
sortedActivities.forEach(activity => {
const dateStr = formatDateLocal(activity.date);
if (!activityMap.has(dateStr)) {
activityMap.set(dateStr, []);
}
activityMap.get(dateStr)!.push(activity);
});
// Generate all dates in range
const dates: string[] = [];
const distances: (number | null)[] = [];
const durations: (number | null)[] = [];
const tss: (number | null)[] = [];
for (let d = new Date(startDate); d <= endDate; d.setDate(d.getDate() + 1)) {
const dateStr = formatDateLocal(d);
dates.push(dateStr);
const dayActivities = activityMap.get(dateStr) || [];
if (dayActivities.length === 0) {
// No activity this day
distances.push(null);
durations.push(null);
tss.push(null);
} else {
// Sum up activities for the day
let totalDistance = 0;
let totalDuration = 0;
let totalTss = 0;
let hasDistance = false;
let hasDuration = false;
let hasTss = false;
dayActivities.forEach(activity => {
if (activity.distance !== undefined) {
totalDistance += activity.distance;
hasDistance = true;
}
if (activity.duration !== undefined) {
totalDuration += activity.duration;
hasDuration = true;
}
if (activity.trainingStressScore !== undefined) {
totalTss += activity.trainingStressScore;
hasTss = true;
}
});
distances.push(hasDistance ? totalDistance : null);
durations.push(hasDuration ? totalDuration : null);
tss.push(hasTss ? totalTss : null);
}
}
return {
activities: sortedActivities,
dates,
distances,
durations,
tss,
};
}