Spaces:
Running
Running
File size: 3,049 Bytes
35527e2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
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 };
}
|