glutamatt HF Staff commited on
Commit
1db0278
·
verified ·
1 Parent(s): b27fe22

acwr curve render if enough points

Browse files
Files changed (2) hide show
  1. src/main.ts +7 -2
  2. src/utils/metricAcwr.ts +10 -23
src/main.ts CHANGED
@@ -355,9 +355,14 @@ function renderCharts(activities: Activity[], targetAcwr: number, predictToday:
355
  }
356
  endDate.setHours(23, 59, 59, 999);
357
 
358
- // Calculate start date as 1.5 times chronic workload period (28 days) before end date
 
 
 
 
 
359
  const startDate = new Date(endDate);
360
- startDate.setDate(startDate.getDate() - Math.floor(28 * 1.5));
361
  startDate.setHours(0, 0, 0, 0);
362
 
363
  dateRange = {
 
355
  }
356
  endDate.setHours(23, 59, 59, 999);
357
 
358
+ // Calculate start date: use longer history for activities with less frequency
359
+ // Base: 2x chronic period (56 days), extended up to 3x (84 days) for sparse activities
360
+ const activityFrequency = activities.length / Math.max(1,
361
+ (endDate.getTime() - activities[0].date.getTime()) / (1000 * 60 * 60 * 24));
362
+ const multiplier = activityFrequency < 0.2 ? 3 : activityFrequency < 0.5 ? 2.5 : 2;
363
+
364
  const startDate = new Date(endDate);
365
+ startDate.setDate(startDate.getDate() - Math.floor(28 * multiplier));
366
  startDate.setHours(0, 0, 0, 0);
367
 
368
  dateRange = {
src/utils/metricAcwr.ts CHANGED
@@ -334,32 +334,19 @@ export function calculateMetricACWR(
334
  const chronicAvg = chronicCount > 0 ? chronicSum / 28 : null;
335
  average28d.push(chronicAvg);
336
 
337
- // Calculate ACWR (need at least 28 days of data)
338
- if (index < 27) {
339
- acwr.push(null);
340
- return;
341
- }
342
-
343
- // For ACWR, use the full 28-day sum (not average)
344
- let acwrChronicSum = 0;
345
- for (let i = index - 27; i <= index; i++) {
346
- const checkDateStr = formatDateLocal(allDates[i]);
347
- const val = dailyValues.get(checkDateStr);
348
- if (val !== undefined) {
349
- acwrChronicSum += val;
350
- }
351
- }
352
- const acwrChronicAvg = acwrChronicSum / 28;
353
-
354
- // Calculate ACWR
355
- if (acwrChronicAvg > 0 && acuteAvg !== null) {
356
- acwr.push(acuteAvg / acwrChronicAvg);
357
  } else {
358
  acwr.push(null);
359
  }
360
- });
361
-
362
- // Calculate tomorrow's required value to reach ACWR
363
  let targetTomorrowValue: number | null = null;
364
 
365
  if (allDates.length >= 28) {
 
334
  const chronicAvg = chronicCount > 0 ? chronicSum / 28 : null;
335
  average28d.push(chronicAvg);
336
 
337
+ // Calculate ACWR with smart requirements:
338
+ // - At the beginning (first 28 days): need at least 8 data points to avoid unrealistic spikes
339
+ // - After that: calculate whenever both averages are available (minimum 4 data points)
340
+ // This avoids spikes at the start while ensuring the end is always visible
341
+ const needsMinimumData = index < 28;
342
+ const hasEnoughData = needsMinimumData ? chronicCount >= 8 : chronicCount >= 4;
343
+
344
+ if (hasEnoughData && acuteAvg !== null && chronicAvg !== null && chronicAvg > 0) {
345
+ acwr.push(acuteAvg / chronicAvg);
 
 
 
 
 
 
 
 
 
 
 
346
  } else {
347
  acwr.push(null);
348
  }
349
+ }); // Calculate tomorrow's required value to reach ACWR
 
 
350
  let targetTomorrowValue: number | null = null;
351
 
352
  if (allDates.length >= 28) {