glutamatt's picture
glutamatt HF Staff
init
35527e2 verified
import type { Activity } from '@/types';
// This file is deprecated - functionality moved to metricAcwr.ts
// Kept for reference only
interface ACWRData {
dates: string[];
acwr: (number | null)[];
acuteLoad: (number | null)[];
chronicLoad: (number | null)[];
}
/**
* Calculate Acute-Chronic Workload Ratio (ACWR)
* Acute load: 7-day rolling average
* Chronic load: 28-day rolling average
* ACWR = Acute / Chronic
* Optimal range: 0.8 - 1.3
*/
export function calculateACWR(activities: Activity[], dateRange?: { start: Date; end: Date }): ACWRData {
if (activities.length === 0 && !dateRange) {
return { dates: [], acwr: [], acuteLoad: [], chronicLoad: [] };
}
const dates: string[] = [];
const acwr: (number | null)[] = [];
const acuteLoad: (number | null)[] = [];
const chronicLoad: (number | null)[] = [];
// Create a map of date to total load (using TSS, or distance as fallback)
const dailyLoad = new Map<string, number>();
activities.forEach(activity => {
const dateKey = activity.date.toISOString().split('T')[0];
const load = activity.trainingStressScore || activity.distance || 0;
if (!dailyLoad.has(dateKey)) {
dailyLoad.set(dateKey, 0);
}
dailyLoad.set(dateKey, dailyLoad.get(dateKey)! + load);
});
// Get all dates in range
const startDate = dateRange?.start || (activities.length > 0 ? activities[0].date : new Date());
const endDate = dateRange?.end || (activities.length > 0 ? activities[activities.length - 1].date : new Date());
const allDates: Date[] = [];
for (let d = new Date(startDate); d <= endDate; d.setDate(d.getDate() + 1)) {
allDates.push(new Date(d));
}
// Calculate ACWR for each date
allDates.forEach((date, index) => {
const dateKey = date.toISOString().split('T')[0];
dates.push(dateKey);
// Need at least 28 days of data for chronic load
if (index < 27) {
acuteLoad.push(null);
chronicLoad.push(null);
acwr.push(null);
return;
}
// Calculate acute load (7-day average)
let acuteSum = 0;
for (let i = 0; i < 7; i++) {
const d = allDates[index - i];
const key = d.toISOString().split('T')[0];
acuteSum += dailyLoad.get(key) || 0;
}
const acuteAvg = acuteSum / 7;
// Calculate chronic load (28-day average)
let chronicSum = 0;
for (let i = 0; i < 28; i++) {
const d = allDates[index - i];
const key = d.toISOString().split('T')[0];
chronicSum += dailyLoad.get(key) || 0;
}
const chronicAvg = chronicSum / 28;
acuteLoad.push(acuteAvg);
chronicLoad.push(chronicAvg);
// Calculate ACWR
if (chronicAvg > 0) {
acwr.push(acuteAvg / chronicAvg);
} else {
acwr.push(null);
}
});
return { dates, acwr, acuteLoad, chronicLoad };
}