diff --git a/src/lib/utils/mesocycleUtils.ts b/src/lib/utils/mesocycleUtils.ts index 6d61257d..71087ab7 100644 --- a/src/lib/utils/mesocycleUtils.ts +++ b/src/lib/utils/mesocycleUtils.ts @@ -1,6 +1,6 @@ import { arrayAverage, averagePercentageChange } from '$lib/utils'; -import type { WorkoutExercise, WorkoutsOfMesocycle } from './types'; -import { getExerciseVolume } from './workoutUtils'; +import type { Mesocycle, Workout, WorkoutExercise, WorkoutsOfMesocycle } from './types'; +import { getExerciseVolume, getWorkoutVolume } from './workoutUtils'; type GroupedExercisesByMuscleGroup = { muscleGroup: string; @@ -24,7 +24,7 @@ type GroupedExercisesByName = { }[]; export function groupExercisesByName(exercises: WorkoutExercise[]): GroupedExercisesByName { - return Object.entries(Object.groupBy(exercises ?? [], ({ name }) => name)).map(([name, exercises]) => ({ + return Object.entries(Object.groupBy(exercises, ({ name }) => name)).map(([name, exercises]) => ({ name, performances: exercises ?? [] })); @@ -41,7 +41,7 @@ export function getAveragePercentageChangeOfExercisePerformances( return averagePercentageChange(exerciseVolumes); } -export function generatePerformanceChanges(workoutsOfMesocycle: WorkoutsOfMesocycle) { +export function generatePerformanceChangesPerMuscleGroup(workoutsOfMesocycle: WorkoutsOfMesocycle) { const allExercises = workoutsOfMesocycle.flatMap((wm) => wm.workout.workoutExercises); const groupedExercisesByMuscleGroup = groupExercisesByMuscleGroup(allExercises); @@ -52,13 +52,40 @@ export function generatePerformanceChanges(workoutsOfMesocycle: WorkoutsOfMesocy const performanceChangesPerMuscleGroups = fullyGroupedExercises.map(({ exercises, muscleGroup }) => ({ muscleGroup, - averageIncrease: arrayAverage( + averagePercentageChange: arrayAverage( exercises.map(({ performances }) => getAveragePercentageChangeOfExercisePerformances(performances, workoutsOfMesocycle) ) ) })); - performanceChangesPerMuscleGroups.sort((a, b) => a.averageIncrease - b.averageIncrease); + performanceChangesPerMuscleGroups.sort((a, b) => a.averagePercentageChange - b.averagePercentageChange); return performanceChangesPerMuscleGroups; } + +type GroupedWorkoutsBySplitDayName = { + splitDayName: string; + workouts: Workout[]; +}[]; + +export function groupWorkoutsBySplitDayName( + workoutsOfMesocycle: WorkoutsOfMesocycle, + splitDays: Mesocycle['mesocycleExerciseSplitDays'] +): GroupedWorkoutsBySplitDayName { + const groupedObject = Object.groupBy(workoutsOfMesocycle, ({ splitDayIndex }) => splitDayIndex); + + return Object.entries(groupedObject).map(([splitDayIndex, workoutsOfMesocycle]) => ({ + splitDayName: splitDays[Number(splitDayIndex)].name, + workouts: (workoutsOfMesocycle ?? []).map((wm) => wm.workout) + })); +} + +export function generatePerformanceChangesPerSplitDay(mesocycle: Mesocycle) { + const workoutsOfMesocycle = mesocycle.workoutsOfMesocycle.filter((wm) => wm.workoutStatus === null); + const groupedWorkouts = groupWorkoutsBySplitDayName(workoutsOfMesocycle, mesocycle.mesocycleExerciseSplitDays); + + return groupedWorkouts.map(({ splitDayName, workouts }) => ({ + splitDayName, + averagePercentageChange: averagePercentageChange(workouts.map((workout) => getWorkoutVolume(workout))) + })); +} diff --git a/src/lib/utils/types.ts b/src/lib/utils/types.ts index 4524f64e..d158d3c6 100644 --- a/src/lib/utils/types.ts +++ b/src/lib/utils/types.ts @@ -1,4 +1,6 @@ import type { RouterOutputs } from '$lib/trpc/router'; -export type WorkoutsOfMesocycle = NonNullable['workoutsOfMesocycle']; -export type WorkoutExercise = WorkoutsOfMesocycle[number]['workout']['workoutExercises'][number]; \ No newline at end of file +export type Mesocycle = NonNullable; +export type WorkoutsOfMesocycle = Mesocycle['workoutsOfMesocycle']; +export type Workout = WorkoutsOfMesocycle[number]['workout']; +export type WorkoutExercise = Workout['workoutExercises'][number]; diff --git a/src/lib/utils/workoutUtils.ts b/src/lib/utils/workoutUtils.ts index ccbd0ea8..f4c143ec 100644 --- a/src/lib/utils/workoutUtils.ts +++ b/src/lib/utils/workoutUtils.ts @@ -1,17 +1,21 @@ import { arraySum } from '$lib/utils'; -import type { WorkoutExercise } from './types'; - -export function getExerciseVolume(workoutExercise: WorkoutExercise, userBodyweight: number) { - return arraySum( - workoutExercise.sets.map((set) => getSetVolume(set, userBodyweight, workoutExercise.bodyweightFraction)) - ); -} +import type { Workout, WorkoutExercise } from './types'; export function getSetVolume( set: WorkoutExercise['sets'][number], userBodyweight: number, bodyweightFraction: number | null ) { - // TODO: Mini sets? + // TODO: Mini sets? return (set.reps + set.RIR) * set.load + (bodyweightFraction ?? 0) * userBodyweight; } + +export function getExerciseVolume(workoutExercise: WorkoutExercise, userBodyweight: number) { + return arraySum( + workoutExercise.sets.map((set) => getSetVolume(set, userBodyweight, workoutExercise.bodyweightFraction)) + ); +} + +export function getWorkoutVolume(workout: Workout) { + return arraySum(workout.workoutExercises.map((exercise) => getExerciseVolume(exercise, workout.userBodyweight))); +} diff --git a/src/routes/mesocycles/[mesocycleId]/(components)/MesocycleWorkoutsTab.svelte b/src/routes/mesocycles/[mesocycleId]/(components)/MesocycleStats.svelte similarity index 62% rename from src/routes/mesocycles/[mesocycleId]/(components)/MesocycleWorkoutsTab.svelte rename to src/routes/mesocycles/[mesocycleId]/(components)/MesocycleStats.svelte index d489760d..8aa2a8b8 100644 --- a/src/routes/mesocycles/[mesocycleId]/(components)/MesocycleWorkoutsTab.svelte +++ b/src/routes/mesocycles/[mesocycleId]/(components)/MesocycleStats.svelte @@ -1,7 +1,10 @@ {#if mesocycle.workoutsOfMesocycle.length} @@ -74,13 +81,13 @@
{convertCamelCaseToNormal( - sortedByPerformanceChangeMuscleGroups[sortedByPerformanceChangeMuscleGroups.length - 1].muscleGroup + performanceChangesPerMuscleGroups[performanceChangesPerMuscleGroups.length - 1].muscleGroup )}

- {sortedByPerformanceChangeMuscleGroups[ - sortedByPerformanceChangeMuscleGroups.length - 1 - ].averageIncrease.toFixed(2)}% cyclic increase + {performanceChangesPerMuscleGroups[ + performanceChangesPerMuscleGroups.length - 1 + ].averagePercentageChange.toFixed(2)}% cyclic increase

@@ -91,19 +98,43 @@
- {convertCamelCaseToNormal(sortedByPerformanceChangeMuscleGroups[0].muscleGroup)} + {convertCamelCaseToNormal(performanceChangesPerMuscleGroups[0].muscleGroup)} +
+

+ {performanceChangesPerMuscleGroups[0].averagePercentageChange.toFixed(2)}% cyclic increase +

+
+ + + + + Best day + + +
+ {performanceChangesPerSplitDay[performanceChangesPerSplitDay.length - 1].splitDayName}

- {sortedByPerformanceChangeMuscleGroups[0].averageIncrease.toFixed(2)}% cyclic increase + {performanceChangesPerSplitDay[performanceChangesPerSplitDay.length - 1].averagePercentageChange.toFixed(2)}% + cyclic increase +

+
+
+ + + + Worst day + + +
+ {performanceChangesPerSplitDay[0].splitDayName} +
+

+ {performanceChangesPerSplitDay[0].averagePercentageChange.toFixed(2)}% cyclic increase

{:else} -
No workouts created
+
No workouts for stat generation
{/if} - -
-TODO: Maybe put these stats in basics tab chart mode, makes more sense that way -

-TODO: Workouts list diff --git a/src/routes/mesocycles/[mesocycleId]/+page.svelte b/src/routes/mesocycles/[mesocycleId]/+page.svelte index 59143ed4..a4e0f59a 100644 --- a/src/routes/mesocycles/[mesocycleId]/+page.svelte +++ b/src/routes/mesocycles/[mesocycleId]/+page.svelte @@ -9,8 +9,8 @@ import MesocycleExerciseSplitStats from './(components)/MesocycleExerciseSplitStats.svelte'; import MesocycleSkeleton from './(components)/MesocycleSkeleton.svelte'; import MesocycleSplitTab from './(components)/MesocycleSplitTab.svelte'; + import MesocycleStats from './(components)/MesocycleStats.svelte'; import MesocycleVolumeTab from './(components)/MesocycleVolumeTab.svelte'; - import MesocycleWorkoutsTab from './(components)/MesocycleWorkoutsTab.svelte'; import type { FullMesocycle } from './+layout.server'; let { data } = $props(); @@ -25,7 +25,7 @@ }); -

View mesocycle

+

View mesocycle

{#if mesocycle === 'loading'} @@ -38,7 +38,11 @@ Workouts - + {#if !chartMode} + + {:else} + + {/if} {#if !chartMode} @@ -62,7 +66,7 @@ {#if !chartMode} - + {:else} TODO: charts that show progression {/if}