@aneuhold/core-ts-db-lib 4.0.3 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -1
- package/lib/browser.d.ts +36 -4
- package/lib/browser.d.ts.map +1 -1
- package/lib/browser.js +23 -2
- package/lib/browser.js.map +1 -1
- package/lib/browser.ts +126 -4
- package/lib/documents/BaseDocument.d.ts +8 -0
- package/lib/documents/BaseDocument.d.ts.map +1 -1
- package/lib/documents/BaseDocument.js +10 -0
- package/lib/documents/BaseDocument.js.map +1 -1
- package/lib/documents/BaseDocument.ts +18 -0
- package/lib/documents/common/User.d.ts +1 -0
- package/lib/documents/common/User.d.ts.map +1 -1
- package/lib/documents/common/User.js +4 -2
- package/lib/documents/common/User.js.map +1 -1
- package/lib/documents/common/User.ts +4 -2
- package/lib/documents/dashboard/NonogramKatanaItem.d.ts +1 -1
- package/lib/documents/dashboard/NonogramKatanaItem.js +1 -1
- package/lib/documents/dashboard/NonogramKatanaItem.js.map +1 -1
- package/lib/documents/dashboard/NonogramKatanaItem.ts +1 -1
- package/lib/documents/dashboard/NonogramKatanaUpgrade.d.ts +1 -1
- package/lib/documents/dashboard/NonogramKatanaUpgrade.js +1 -1
- package/lib/documents/dashboard/NonogramKatanaUpgrade.js.map +1 -1
- package/lib/documents/dashboard/NonogramKatanaUpgrade.ts +1 -1
- package/lib/documents/dashboard/Task.d.ts +4 -4
- package/lib/documents/dashboard/UserConfig.d.ts +4 -4
- package/lib/documents/workout/README.md +557 -0
- package/lib/documents/workout/WorkoutEquipmentType.d.ts +22 -0
- package/lib/documents/workout/WorkoutEquipmentType.d.ts.map +1 -0
- package/lib/documents/workout/WorkoutEquipmentType.js +31 -0
- package/lib/documents/workout/WorkoutEquipmentType.js.map +1 -0
- package/lib/documents/workout/WorkoutEquipmentType.ts +40 -0
- package/lib/documents/workout/WorkoutExercise.d.ts +82 -0
- package/lib/documents/workout/WorkoutExercise.d.ts.map +1 -0
- package/lib/documents/workout/WorkoutExercise.js +124 -0
- package/lib/documents/workout/WorkoutExercise.js.map +1 -0
- package/lib/documents/workout/WorkoutExercise.ts +143 -0
- package/lib/documents/workout/WorkoutExerciseCalibration.d.ts +43 -0
- package/lib/documents/workout/WorkoutExerciseCalibration.d.ts.map +1 -0
- package/lib/documents/workout/WorkoutExerciseCalibration.js +45 -0
- package/lib/documents/workout/WorkoutExerciseCalibration.js.map +1 -0
- package/lib/documents/workout/WorkoutExerciseCalibration.ts +74 -0
- package/lib/documents/workout/WorkoutMesocycle.d.ts +49 -0
- package/lib/documents/workout/WorkoutMesocycle.d.ts.map +1 -0
- package/lib/documents/workout/WorkoutMesocycle.js +84 -0
- package/lib/documents/workout/WorkoutMesocycle.js.map +1 -0
- package/lib/documents/workout/WorkoutMesocycle.ts +102 -0
- package/lib/documents/workout/WorkoutMicrocycle.d.ts +27 -0
- package/lib/documents/workout/WorkoutMicrocycle.d.ts.map +1 -0
- package/lib/documents/workout/WorkoutMicrocycle.js +42 -0
- package/lib/documents/workout/WorkoutMicrocycle.js.map +1 -0
- package/lib/documents/workout/WorkoutMicrocycle.ts +55 -0
- package/lib/documents/workout/WorkoutMuscleGroup.d.ts +22 -0
- package/lib/documents/workout/WorkoutMuscleGroup.d.ts.map +1 -0
- package/lib/documents/workout/WorkoutMuscleGroup.js +25 -0
- package/lib/documents/workout/WorkoutMuscleGroup.js.map +1 -0
- package/lib/documents/workout/WorkoutMuscleGroup.ts +34 -0
- package/lib/documents/workout/WorkoutSession.d.ts +39 -0
- package/lib/documents/workout/WorkoutSession.d.ts.map +1 -0
- package/lib/documents/workout/WorkoutSession.js +66 -0
- package/lib/documents/workout/WorkoutSession.js.map +1 -0
- package/lib/documents/workout/WorkoutSession.ts +79 -0
- package/lib/documents/workout/WorkoutSessionExercise.d.ts +39 -0
- package/lib/documents/workout/WorkoutSessionExercise.d.ts.map +1 -0
- package/lib/documents/workout/WorkoutSessionExercise.js +66 -0
- package/lib/documents/workout/WorkoutSessionExercise.js.map +1 -0
- package/lib/documents/workout/WorkoutSessionExercise.ts +79 -0
- package/lib/documents/workout/WorkoutSet.d.ts +41 -0
- package/lib/documents/workout/WorkoutSet.d.ts.map +1 -0
- package/lib/documents/workout/WorkoutSet.js +69 -0
- package/lib/documents/workout/WorkoutSet.js.map +1 -0
- package/lib/documents/workout/WorkoutSet.ts +90 -0
- package/lib/embedded-types/dashboard/task/FilterSettings.d.ts +6 -6
- package/lib/embedded-types/dashboard/task/FilterSettings.d.ts.map +1 -1
- package/lib/embedded-types/dashboard/task/FilterSettings.js +4 -2
- package/lib/embedded-types/dashboard/task/FilterSettings.js.map +1 -1
- package/lib/embedded-types/dashboard/task/FilterSettings.ts +5 -3
- package/lib/embedded-types/dashboard/task/SortSettings.d.ts +6 -6
- package/lib/embedded-types/dashboard/task/SortSettings.js +1 -1
- package/lib/embedded-types/dashboard/task/SortSettings.js.map +1 -1
- package/lib/embedded-types/dashboard/task/SortSettings.ts +1 -1
- package/lib/embedded-types/workout/Fatigue.d.ts +16 -0
- package/lib/embedded-types/workout/Fatigue.d.ts.map +1 -0
- package/lib/embedded-types/workout/Fatigue.js +34 -0
- package/lib/embedded-types/workout/Fatigue.js.map +1 -0
- package/lib/embedded-types/workout/Fatigue.ts +41 -0
- package/lib/embedded-types/workout/Rsm.d.ts +17 -0
- package/lib/embedded-types/workout/Rsm.d.ts.map +1 -0
- package/lib/embedded-types/workout/Rsm.js +34 -0
- package/lib/embedded-types/workout/Rsm.js.map +1 -0
- package/lib/embedded-types/workout/Rsm.ts +42 -0
- package/lib/services/DocumentService.d.ts +19 -0
- package/lib/services/DocumentService.d.ts.map +1 -1
- package/lib/services/DocumentService.js.map +1 -1
- package/lib/services/DocumentService.ts +20 -0
- package/lib/services/workout/EquipmentType/WorkoutEquipmentTypeService.d.ts +35 -0
- package/lib/services/workout/EquipmentType/WorkoutEquipmentTypeService.d.ts.map +1 -0
- package/lib/services/workout/EquipmentType/WorkoutEquipmentTypeService.js +74 -0
- package/lib/services/workout/EquipmentType/WorkoutEquipmentTypeService.js.map +1 -0
- package/lib/services/workout/EquipmentType/WorkoutEquipmentTypeService.ts +90 -0
- package/lib/services/workout/Exercise/WorkoutExerciseService.d.ts +55 -0
- package/lib/services/workout/Exercise/WorkoutExerciseService.d.ts.map +1 -0
- package/lib/services/workout/Exercise/WorkoutExerciseService.js +133 -0
- package/lib/services/workout/Exercise/WorkoutExerciseService.js.map +1 -0
- package/lib/services/workout/Exercise/WorkoutExerciseService.ts +173 -0
- package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.d.ts +35 -0
- package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.d.ts.map +1 -0
- package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.js +42 -0
- package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.js.map +1 -0
- package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.ts +45 -0
- package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.d.ts +90 -0
- package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.d.ts.map +1 -0
- package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.js +131 -0
- package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.js.map +1 -0
- package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.ts +159 -0
- package/lib/services/workout/Mesocycle/WorkoutMesocycleService.d.ts +52 -0
- package/lib/services/workout/Mesocycle/WorkoutMesocycleService.d.ts.map +1 -0
- package/lib/services/workout/Mesocycle/WorkoutMesocycleService.js +180 -0
- package/lib/services/workout/Mesocycle/WorkoutMesocycleService.js.map +1 -0
- package/lib/services/workout/Mesocycle/WorkoutMesocycleService.ts +274 -0
- package/lib/services/workout/Microcycle/WorkoutMicrocycleService.d.ts +28 -0
- package/lib/services/workout/Microcycle/WorkoutMicrocycleService.d.ts.map +1 -0
- package/lib/services/workout/Microcycle/WorkoutMicrocycleService.js +172 -0
- package/lib/services/workout/Microcycle/WorkoutMicrocycleService.js.map +1 -0
- package/lib/services/workout/Microcycle/WorkoutMicrocycleService.ts +236 -0
- package/lib/services/workout/Session/WorkoutSessionService.d.ts +49 -0
- package/lib/services/workout/Session/WorkoutSessionService.d.ts.map +1 -0
- package/lib/services/workout/Session/WorkoutSessionService.js +95 -0
- package/lib/services/workout/Session/WorkoutSessionService.js.map +1 -0
- package/lib/services/workout/Session/WorkoutSessionService.ts +136 -0
- package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.d.ts +45 -0
- package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.d.ts.map +1 -0
- package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.js +69 -0
- package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.js.map +1 -0
- package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.ts +77 -0
- package/lib/services/workout/Set/WorkoutSetService.d.ts +36 -0
- package/lib/services/workout/Set/WorkoutSetService.d.ts.map +1 -0
- package/lib/services/workout/Set/WorkoutSetService.js +90 -0
- package/lib/services/workout/Set/WorkoutSetService.js.map +1 -0
- package/lib/services/workout/Set/WorkoutSetService.ts +153 -0
- package/lib/services/workout/util/SFR/WorkoutSFRService.d.ts +29 -0
- package/lib/services/workout/util/SFR/WorkoutSFRService.d.ts.map +1 -0
- package/lib/services/workout/util/SFR/WorkoutSFRService.js +50 -0
- package/lib/services/workout/util/SFR/WorkoutSFRService.js.map +1 -0
- package/lib/services/workout/util/SFR/WorkoutSFRService.ts +61 -0
- package/lib/services/workout/util/VolumePlanning/WorkoutVolumePlanningService.d.ts +48 -0
- package/lib/services/workout/util/VolumePlanning/WorkoutVolumePlanningService.d.ts.map +1 -0
- package/lib/services/workout/util/VolumePlanning/WorkoutVolumePlanningService.js +261 -0
- package/lib/services/workout/util/VolumePlanning/WorkoutVolumePlanningService.js.map +1 -0
- package/lib/services/workout/util/VolumePlanning/WorkoutVolumePlanningService.ts +339 -0
- package/package.json +5 -4
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import type { UUID } from 'crypto';
|
|
2
|
+
import type { WorkoutEquipmentType } from '../../../documents/workout/WorkoutEquipmentType.js';
|
|
3
|
+
import type { WorkoutExercise } from '../../../documents/workout/WorkoutExercise.js';
|
|
4
|
+
import type {
|
|
5
|
+
CalibrationExercisePair,
|
|
6
|
+
WorkoutExerciseCalibration
|
|
7
|
+
} from '../../../documents/workout/WorkoutExerciseCalibration.js';
|
|
8
|
+
import type { WorkoutMesocycle } from '../../../documents/workout/WorkoutMesocycle.js';
|
|
9
|
+
import type { WorkoutMicrocycle } from '../../../documents/workout/WorkoutMicrocycle.js';
|
|
10
|
+
import type { WorkoutSession } from '../../../documents/workout/WorkoutSession.js';
|
|
11
|
+
import type { WorkoutSessionExercise } from '../../../documents/workout/WorkoutSessionExercise.js';
|
|
12
|
+
import type { WorkoutSet } from '../../../documents/workout/WorkoutSet.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Central shared context for generating or updating a {@link WorkoutMesocycle}.
|
|
16
|
+
*
|
|
17
|
+
* This keeps the generation pipeline (Mesocycle -> Microcycle -> Session -> Set) from needing to
|
|
18
|
+
* thread the same inputs (mesocycle config + document lookups + optional historical docs) through
|
|
19
|
+
* every method.
|
|
20
|
+
*/
|
|
21
|
+
export default class WorkoutMesocyclePlanContext {
|
|
22
|
+
/**
|
|
23
|
+
* A constant for now that defines what the target RIR is for the first microcycle of every mesocycle,
|
|
24
|
+
* regardless of anything else.
|
|
25
|
+
*/
|
|
26
|
+
public readonly FIRST_MICROCYCLE_RIR = 4;
|
|
27
|
+
|
|
28
|
+
public readonly calibrationMap: Map<UUID, WorkoutExerciseCalibration>;
|
|
29
|
+
public readonly exerciseMap: Map<UUID, WorkoutExercise>;
|
|
30
|
+
public readonly equipmentMap: Map<UUID, WorkoutEquipmentType>;
|
|
31
|
+
public readonly sessionMap: Map<UUID, WorkoutSession>;
|
|
32
|
+
public readonly sessionExerciseMap: Map<UUID, WorkoutSessionExercise>;
|
|
33
|
+
|
|
34
|
+
public readonly microcyclesToCreate: WorkoutMicrocycle[] = [];
|
|
35
|
+
/**
|
|
36
|
+
* All microcycles for this mesocycle in chronological order.
|
|
37
|
+
*
|
|
38
|
+
* This includes any existing microcycles (filtered to the target mesocycle) and
|
|
39
|
+
* all newly generated microcycles.
|
|
40
|
+
*/
|
|
41
|
+
public readonly microcyclesInOrder: WorkoutMicrocycle[] = [];
|
|
42
|
+
public readonly sessionsToCreate: WorkoutSession[] = [];
|
|
43
|
+
public readonly sessionExercisesToCreate: WorkoutSessionExercise[] = [];
|
|
44
|
+
public readonly setsToCreate: WorkoutSet[] = [];
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The array of sessions corresponding to the array of calibration exercise pairs, in order,
|
|
48
|
+
* for that session.
|
|
49
|
+
*/
|
|
50
|
+
public plannedSessionExercisePairs: CalibrationExercisePair[][] | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Stores the mesocycle's muscle-group-wide exercise ordering.
|
|
53
|
+
*
|
|
54
|
+
* This is used by session generation to distribute set progression evenly across
|
|
55
|
+
* exercises that share a primary muscle group, regardless of which session they
|
|
56
|
+
* ended up in.
|
|
57
|
+
*/
|
|
58
|
+
public muscleGroupToExercisePairsMap: Map<UUID, CalibrationExercisePair[]> | undefined;
|
|
59
|
+
public exerciseIdToSessionIndex: Map<UUID, number> | undefined;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Creates a new workout mesocycle planning context.
|
|
63
|
+
*/
|
|
64
|
+
constructor(
|
|
65
|
+
public mesocycle: WorkoutMesocycle,
|
|
66
|
+
calibrations: WorkoutExerciseCalibration[],
|
|
67
|
+
exercises: WorkoutExercise[],
|
|
68
|
+
equipmentTypes: WorkoutEquipmentType[],
|
|
69
|
+
public existingMicrocycles: WorkoutMicrocycle[] = [],
|
|
70
|
+
public existingSessions: WorkoutSession[] = [],
|
|
71
|
+
public existingSessionExercises: WorkoutSessionExercise[] = [],
|
|
72
|
+
public existingSets: WorkoutSet[] = []
|
|
73
|
+
) {
|
|
74
|
+
this.calibrationMap = new Map(calibrations.map((c) => [c._id, c]));
|
|
75
|
+
this.exerciseMap = new Map(exercises.map((e) => [e._id, e]));
|
|
76
|
+
this.equipmentMap = new Map(equipmentTypes.map((et) => [et._id, et]));
|
|
77
|
+
this.sessionMap = new Map(existingSessions.map((s) => [s._id, s]));
|
|
78
|
+
this.sessionExerciseMap = new Map(existingSessionExercises.map((s) => [s._id, s]));
|
|
79
|
+
|
|
80
|
+
const existingMicrocyclesForMesocycle = existingMicrocycles
|
|
81
|
+
.filter((m) => m.workoutMesocycleId === mesocycle._id)
|
|
82
|
+
.sort((a, b) => a.startDate.getTime() - b.startDate.getTime());
|
|
83
|
+
this.microcyclesInOrder.push(...existingMicrocyclesForMesocycle);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Adds a microcycle to the list of microcycles to create and the overall chronological list.
|
|
88
|
+
*/
|
|
89
|
+
public addMicrocycle(toCreate: WorkoutMicrocycle): void {
|
|
90
|
+
this.microcyclesToCreate.push(toCreate);
|
|
91
|
+
this.microcyclesInOrder.push(toCreate);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Adds a session to the context and updates internal maps.
|
|
96
|
+
*/
|
|
97
|
+
public addSession(session: WorkoutSession): void {
|
|
98
|
+
this.sessionsToCreate.push(session);
|
|
99
|
+
this.sessionMap.set(session._id, session);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Adds a session exercise to the context and updates internal maps.
|
|
104
|
+
*/
|
|
105
|
+
public addSessionExercise(sessionExercise: WorkoutSessionExercise): void {
|
|
106
|
+
this.sessionExercisesToCreate.push(sessionExercise);
|
|
107
|
+
this.sessionExerciseMap.set(sessionExercise._id, sessionExercise);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Stores the planned session -> exercises structure for the mesocycle and derives
|
|
112
|
+
* the muscle-group-wide ordering used for set progression.
|
|
113
|
+
*/
|
|
114
|
+
public setPlannedSessionExercisePairs(
|
|
115
|
+
plannedSessionExercisePairs: CalibrationExercisePair[][]
|
|
116
|
+
): void {
|
|
117
|
+
this.plannedSessionExercisePairs = plannedSessionExercisePairs;
|
|
118
|
+
this.buildSessionPairsMaps(plannedSessionExercisePairs);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Builds and stores a map of primary muscle group -> ordered exercise pairs for the mesocycle plan.
|
|
123
|
+
*
|
|
124
|
+
* Also builds a map of exercise ID -> session index for use during session generation.
|
|
125
|
+
*
|
|
126
|
+
* The ordering is determined by flattening the planned sessions in order, then the exercises within
|
|
127
|
+
* each session in order. This allows set progression to be distributed evenly across a muscle group
|
|
128
|
+
* for the entire microcycle, even when exercises are split across sessions.
|
|
129
|
+
*/
|
|
130
|
+
private buildSessionPairsMaps(sessionsToExercisePairs: CalibrationExercisePair[][]): void {
|
|
131
|
+
const muscleGroupToPairsMap = new Map<UUID, CalibrationExercisePair[]>();
|
|
132
|
+
const exerciseIdToSessionIndex = new Map<UUID, number>();
|
|
133
|
+
|
|
134
|
+
for (let sessionIndex = 0; sessionIndex < sessionsToExercisePairs.length; sessionIndex++) {
|
|
135
|
+
const sessionExercisePairs = sessionsToExercisePairs[sessionIndex];
|
|
136
|
+
for (const exercisePair of sessionExercisePairs) {
|
|
137
|
+
// Set the session index for this exercise as well
|
|
138
|
+
exerciseIdToSessionIndex.set(exercisePair.exercise._id, sessionIndex);
|
|
139
|
+
|
|
140
|
+
const primaryMuscleGroupId = exercisePair.exercise.primaryMuscleGroups[0];
|
|
141
|
+
if (!primaryMuscleGroupId) {
|
|
142
|
+
throw new Error(
|
|
143
|
+
`Exercise ${exercisePair.exercise._id}, ${exercisePair.exercise.exerciseName} has no primary muscle group`
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const existing = muscleGroupToPairsMap.get(primaryMuscleGroupId);
|
|
148
|
+
if (existing) {
|
|
149
|
+
existing.push(exercisePair);
|
|
150
|
+
} else {
|
|
151
|
+
muscleGroupToPairsMap.set(primaryMuscleGroupId, [exercisePair]);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
this.muscleGroupToExercisePairsMap = muscleGroupToPairsMap;
|
|
157
|
+
this.exerciseIdToSessionIndex = exerciseIdToSessionIndex;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { WorkoutEquipmentType } from '../../../documents/workout/WorkoutEquipmentType.js';
|
|
2
|
+
import type { WorkoutExercise } from '../../../documents/workout/WorkoutExercise.js';
|
|
3
|
+
import type { WorkoutExerciseCalibration } from '../../../documents/workout/WorkoutExerciseCalibration.js';
|
|
4
|
+
import { type WorkoutMesocycle } from '../../../documents/workout/WorkoutMesocycle.js';
|
|
5
|
+
import type { WorkoutMicrocycle } from '../../../documents/workout/WorkoutMicrocycle.js';
|
|
6
|
+
import type { WorkoutSession } from '../../../documents/workout/WorkoutSession.js';
|
|
7
|
+
import type { WorkoutSessionExercise } from '../../../documents/workout/WorkoutSessionExercise.js';
|
|
8
|
+
import type { WorkoutSet } from '../../../documents/workout/WorkoutSet.js';
|
|
9
|
+
import type { DocumentOperations } from '../../DocumentService.js';
|
|
10
|
+
/**
|
|
11
|
+
* A service for handling operations related to {@link WorkoutMesocycle}s.
|
|
12
|
+
*/
|
|
13
|
+
export default class WorkoutMesocycleService {
|
|
14
|
+
/**
|
|
15
|
+
* Generates or updates the workout plan for a mesocycle.
|
|
16
|
+
*
|
|
17
|
+
* This method supports incremental generation by only creating new microcycles that don't
|
|
18
|
+
* yet exist. It expects that the mesocycle's core parameters (planned session count,
|
|
19
|
+
* microcycle count, microcycle length) and exercise ordering have not changed since
|
|
20
|
+
* initial creation. If these parameters have changed, it is the responsibility of a
|
|
21
|
+
* higher-level service to convert the mesocycle to free-form mode before calling this method.
|
|
22
|
+
*
|
|
23
|
+
* The method will clean up any incomplete microcycles (where the last session is not
|
|
24
|
+
* complete) and regenerate from that point, unless the microcycle has already started
|
|
25
|
+
* (first session complete), in which case it will throw an error.
|
|
26
|
+
*
|
|
27
|
+
* @param mesocycle The mesocycle configuration.
|
|
28
|
+
* @param calibrations The calibration documents referenced by the mesocycle.
|
|
29
|
+
* @param exercises The exercise definitions for the calibrations.
|
|
30
|
+
* @param equipmentTypes The equipment types for weight increment calculations.
|
|
31
|
+
* @param existingMicrocycles Existing microcycle documents for this mesocycle.
|
|
32
|
+
* @param existingSessions Existing session documents.
|
|
33
|
+
* @param existingSessionExercises Existing session exercise documents.
|
|
34
|
+
* @param existingSets Existing set documents.
|
|
35
|
+
*/
|
|
36
|
+
static generateOrUpdateMesocycle(mesocycle: WorkoutMesocycle, calibrations: WorkoutExerciseCalibration[], exercises: WorkoutExercise[], equipmentTypes: WorkoutEquipmentType[], existingMicrocycles?: WorkoutMicrocycle[], existingSessions?: WorkoutSession[], existingSessionExercises?: WorkoutSessionExercise[], existingSets?: WorkoutSet[]): {
|
|
37
|
+
mesocycleUpdate?: Partial<WorkoutMesocycle>;
|
|
38
|
+
microcycles?: DocumentOperations<WorkoutMicrocycle>;
|
|
39
|
+
sessions?: DocumentOperations<WorkoutSession>;
|
|
40
|
+
sessionExercises?: DocumentOperations<WorkoutSessionExercise>;
|
|
41
|
+
sets?: DocumentOperations<WorkoutSet>;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Cleans up incomplete microcycles and their associated documents.
|
|
45
|
+
*
|
|
46
|
+
* Finds the first microcycle where the last session is not complete, validates that it
|
|
47
|
+
* hasn't started (first session incomplete), and returns IDs of all documents that should
|
|
48
|
+
* be deleted (microcycles from that point forward and all their associated data).
|
|
49
|
+
*/
|
|
50
|
+
private static cleanUpIncompleteMicrocycles;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=WorkoutMesocycleService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkoutMesocycleService.d.ts","sourceRoot":"","sources":["../../../../src/services/workout/Mesocycle/WorkoutMesocycleService.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oDAAoD,CAAC;AAC/F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+CAA+C,CAAC;AACrF,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,0DAA0D,CAAC;AAC3G,OAAO,EAAa,KAAK,gBAAgB,EAAE,MAAM,gDAAgD,CAAC;AAClG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iDAAiD,CAAC;AAEzF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8CAA8C,CAAC;AACnF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sDAAsD,CAAC;AACnG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAC3E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAInE;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,uBAAuB;IAC1C;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,MAAM,CAAC,yBAAyB,CAC9B,SAAS,EAAE,gBAAgB,EAC3B,YAAY,EAAE,0BAA0B,EAAE,EAC1C,SAAS,EAAE,eAAe,EAAE,EAC5B,cAAc,EAAE,oBAAoB,EAAE,EACtC,mBAAmB,GAAE,iBAAiB,EAAO,EAC7C,gBAAgB,GAAE,cAAc,EAAO,EACvC,wBAAwB,GAAE,sBAAsB,EAAO,EACvD,YAAY,GAAE,UAAU,EAAO,GAC9B;QACD,eAAe,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAC5C,WAAW,CAAC,EAAE,kBAAkB,CAAC,iBAAiB,CAAC,CAAC;QACpD,QAAQ,CAAC,EAAE,kBAAkB,CAAC,cAAc,CAAC,CAAC;QAC9C,gBAAgB,CAAC,EAAE,kBAAkB,CAAC,sBAAsB,CAAC,CAAC;QAC9D,IAAI,CAAC,EAAE,kBAAkB,CAAC,UAAU,CAAC,CAAC;KACvC;IAyHD;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,4BAA4B;CAyF5C"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { DateService } from '@aneuhold/core-ts-lib';
|
|
2
|
+
import { CycleType } from '../../../documents/workout/WorkoutMesocycle.js';
|
|
3
|
+
import { WorkoutMicrocycleSchema } from '../../../documents/workout/WorkoutMicrocycle.js';
|
|
4
|
+
import WorkoutMicrocycleService from '../Microcycle/WorkoutMicrocycleService.js';
|
|
5
|
+
import WorkoutMesocyclePlanContext from './WorkoutMesocyclePlanContext.js';
|
|
6
|
+
/**
|
|
7
|
+
* A service for handling operations related to {@link WorkoutMesocycle}s.
|
|
8
|
+
*/
|
|
9
|
+
export default class WorkoutMesocycleService {
|
|
10
|
+
/**
|
|
11
|
+
* Generates or updates the workout plan for a mesocycle.
|
|
12
|
+
*
|
|
13
|
+
* This method supports incremental generation by only creating new microcycles that don't
|
|
14
|
+
* yet exist. It expects that the mesocycle's core parameters (planned session count,
|
|
15
|
+
* microcycle count, microcycle length) and exercise ordering have not changed since
|
|
16
|
+
* initial creation. If these parameters have changed, it is the responsibility of a
|
|
17
|
+
* higher-level service to convert the mesocycle to free-form mode before calling this method.
|
|
18
|
+
*
|
|
19
|
+
* The method will clean up any incomplete microcycles (where the last session is not
|
|
20
|
+
* complete) and regenerate from that point, unless the microcycle has already started
|
|
21
|
+
* (first session complete), in which case it will throw an error.
|
|
22
|
+
*
|
|
23
|
+
* @param mesocycle The mesocycle configuration.
|
|
24
|
+
* @param calibrations The calibration documents referenced by the mesocycle.
|
|
25
|
+
* @param exercises The exercise definitions for the calibrations.
|
|
26
|
+
* @param equipmentTypes The equipment types for weight increment calculations.
|
|
27
|
+
* @param existingMicrocycles Existing microcycle documents for this mesocycle.
|
|
28
|
+
* @param existingSessions Existing session documents.
|
|
29
|
+
* @param existingSessionExercises Existing session exercise documents.
|
|
30
|
+
* @param existingSets Existing set documents.
|
|
31
|
+
*/
|
|
32
|
+
static generateOrUpdateMesocycle(mesocycle, calibrations, exercises, equipmentTypes, existingMicrocycles = [], existingSessions = [], existingSessionExercises = [], existingSets = []) {
|
|
33
|
+
// Free-form mesocycles are intentionally not auto-planned. The user can still log workouts,
|
|
34
|
+
// but we avoid generating microcycles/sessions/sets because recommendations wouldn't be able
|
|
35
|
+
// to be done / make any sense.
|
|
36
|
+
if (mesocycle.cycleType === CycleType.FreeForm) {
|
|
37
|
+
return {};
|
|
38
|
+
}
|
|
39
|
+
// Clean up incomplete microcycles before creating context
|
|
40
|
+
const cleanupResult = this.cleanUpIncompleteMicrocycles(mesocycle, existingMicrocycles, existingSessions, existingSessionExercises, existingSets);
|
|
41
|
+
// Filter out documents that will be deleted
|
|
42
|
+
const cleanMicrocycles = existingMicrocycles.filter((m) => !cleanupResult.microcyclesToDelete.includes(m._id));
|
|
43
|
+
const cleanSessions = existingSessions.filter((s) => !cleanupResult.sessionsToDelete.includes(s._id));
|
|
44
|
+
const cleanSessionExercises = existingSessionExercises.filter((se) => !cleanupResult.sessionExercisesToDelete.includes(se._id));
|
|
45
|
+
const cleanSets = existingSets.filter((s) => !cleanupResult.setsToDelete.includes(s._id));
|
|
46
|
+
// Create planning context with clean data
|
|
47
|
+
const context = new WorkoutMesocyclePlanContext(mesocycle, calibrations, exercises, equipmentTypes, cleanMicrocycles, cleanSessions, cleanSessionExercises, cleanSets);
|
|
48
|
+
// Distribute exercises across sessions once for the entire mesocycle plan.
|
|
49
|
+
// This session layout is expected to be stable across microcycles.
|
|
50
|
+
context.setPlannedSessionExercisePairs(WorkoutMicrocycleService.distributeExercisesAcrossSessions(mesocycle.plannedSessionCountPerMicrocycle, context.calibrationMap, context.exerciseMap));
|
|
51
|
+
// Determine number of microcycles (default to 6 if not specified: 5 accumulation + 1 deload)
|
|
52
|
+
const totalMicrocycles = mesocycle.plannedMicrocycleCount ?? 6;
|
|
53
|
+
const deloadMicrocycleIndex = totalMicrocycles - 1;
|
|
54
|
+
// Determine starting point for generation
|
|
55
|
+
const startMicrocycleIndex = context.microcyclesInOrder.length;
|
|
56
|
+
let currentDate;
|
|
57
|
+
if (startMicrocycleIndex === 0) {
|
|
58
|
+
// No existing microcycles, start from current date
|
|
59
|
+
currentDate = new Date();
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
// Continue from where the last existing microcycle ended
|
|
63
|
+
const lastExistingMicrocycle = context.microcyclesInOrder[startMicrocycleIndex - 1];
|
|
64
|
+
currentDate = new Date(lastExistingMicrocycle.endDate);
|
|
65
|
+
}
|
|
66
|
+
// Generate remaining microcycles
|
|
67
|
+
for (let microcycleIndex = startMicrocycleIndex; microcycleIndex < totalMicrocycles; microcycleIndex++) {
|
|
68
|
+
const isDeloadMicrocycle = microcycleIndex === deloadMicrocycleIndex;
|
|
69
|
+
// Calculate RIR for this microcycle (4 -> 3 -> 2 -> 1 -> 0, capped at microcycle 5)
|
|
70
|
+
const rirForMicrocycle = Math.min(microcycleIndex, 4);
|
|
71
|
+
const targetRir = 4 - rirForMicrocycle;
|
|
72
|
+
// Create microcycle
|
|
73
|
+
const microcycle = WorkoutMicrocycleSchema.parse({
|
|
74
|
+
userId: mesocycle.userId,
|
|
75
|
+
workoutMesocycleId: mesocycle._id,
|
|
76
|
+
startDate: new Date(currentDate),
|
|
77
|
+
endDate: DateService.addDays(currentDate, mesocycle.plannedMicrocycleLengthInDays)
|
|
78
|
+
});
|
|
79
|
+
context.addMicrocycle(microcycle);
|
|
80
|
+
WorkoutMicrocycleService.generateSessionsForMicrocycle({
|
|
81
|
+
context,
|
|
82
|
+
microcycleIndex,
|
|
83
|
+
targetRir,
|
|
84
|
+
isDeloadMicrocycle
|
|
85
|
+
});
|
|
86
|
+
// Move to next microcycle
|
|
87
|
+
currentDate = new Date(microcycle.endDate);
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
mesocycleUpdate: undefined,
|
|
91
|
+
microcycles: {
|
|
92
|
+
create: context.microcyclesToCreate,
|
|
93
|
+
update: [],
|
|
94
|
+
delete: cleanupResult.microcyclesToDelete
|
|
95
|
+
},
|
|
96
|
+
sessions: {
|
|
97
|
+
create: context.sessionsToCreate,
|
|
98
|
+
update: [],
|
|
99
|
+
delete: cleanupResult.sessionsToDelete
|
|
100
|
+
},
|
|
101
|
+
sessionExercises: {
|
|
102
|
+
create: context.sessionExercisesToCreate,
|
|
103
|
+
update: [],
|
|
104
|
+
delete: cleanupResult.sessionExercisesToDelete
|
|
105
|
+
},
|
|
106
|
+
sets: { create: context.setsToCreate, update: [], delete: cleanupResult.setsToDelete }
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Cleans up incomplete microcycles and their associated documents.
|
|
111
|
+
*
|
|
112
|
+
* Finds the first microcycle where the last session is not complete, validates that it
|
|
113
|
+
* hasn't started (first session incomplete), and returns IDs of all documents that should
|
|
114
|
+
* be deleted (microcycles from that point forward and all their associated data).
|
|
115
|
+
*/
|
|
116
|
+
static cleanUpIncompleteMicrocycles(mesocycle, existingMicrocycles, existingSessions, existingSessionExercises, existingSets) {
|
|
117
|
+
const microcyclesToDelete = [];
|
|
118
|
+
const sessionsToDelete = [];
|
|
119
|
+
const sessionExercisesToDelete = [];
|
|
120
|
+
const setsToDelete = [];
|
|
121
|
+
// Sort microcycles for this mesocycle
|
|
122
|
+
const microcyclesForMesocycle = existingMicrocycles.sort((a, b) => a.startDate.getTime() - b.startDate.getTime());
|
|
123
|
+
// Find first incomplete microcycle
|
|
124
|
+
let firstIncompleteMicrocycleIndex = -1;
|
|
125
|
+
for (let i = 0; i < microcyclesForMesocycle.length; i++) {
|
|
126
|
+
const microcycle = microcyclesForMesocycle[i];
|
|
127
|
+
if (microcycle.sessionOrder.length === 0) {
|
|
128
|
+
// Microcycle has no sessions, it's incomplete
|
|
129
|
+
firstIncompleteMicrocycleIndex = i;
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
// Check if last session is complete
|
|
133
|
+
const lastSessionId = microcycle.sessionOrder[microcycle.sessionOrder.length - 1];
|
|
134
|
+
const lastSession = existingSessions.find((s) => s._id === lastSessionId);
|
|
135
|
+
if (!lastSession?.complete) {
|
|
136
|
+
firstIncompleteMicrocycleIndex = i;
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// If all microcycles are complete, nothing to clean up
|
|
141
|
+
if (firstIncompleteMicrocycleIndex === -1) {
|
|
142
|
+
return { microcyclesToDelete, sessionsToDelete, sessionExercisesToDelete, setsToDelete };
|
|
143
|
+
}
|
|
144
|
+
const firstIncompleteMicrocycle = microcyclesForMesocycle[firstIncompleteMicrocycleIndex];
|
|
145
|
+
// Check if the incomplete microcycle has started (first session complete)
|
|
146
|
+
if (firstIncompleteMicrocycle.sessionOrder.length > 0) {
|
|
147
|
+
const firstSessionId = firstIncompleteMicrocycle.sessionOrder[0];
|
|
148
|
+
const firstSession = existingSessions.find((s) => s._id === firstSessionId);
|
|
149
|
+
if (firstSession?.complete) {
|
|
150
|
+
throw new Error(`Cannot generate new microcycles for mesocycle ${mesocycle._id}: ` +
|
|
151
|
+
`Microcycle at index ${firstIncompleteMicrocycleIndex} has started but is not complete. ` +
|
|
152
|
+
`All sessions in the current microcycle must be completed before generating new microcycles.`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// Collect IDs of incomplete microcycles (from firstIncompleteMicrocycleIndex onward)
|
|
156
|
+
const incompleteMicrocycles = microcyclesForMesocycle.slice(firstIncompleteMicrocycleIndex);
|
|
157
|
+
microcyclesToDelete.push(...incompleteMicrocycles.map((m) => m._id));
|
|
158
|
+
// Collect all sessions, session exercises, and sets associated with incomplete microcycles
|
|
159
|
+
const incompleteMicrocycleIds = new Set(incompleteMicrocycles.map((m) => m._id));
|
|
160
|
+
for (const session of existingSessions) {
|
|
161
|
+
if (session.workoutMicrocycleId && incompleteMicrocycleIds.has(session.workoutMicrocycleId)) {
|
|
162
|
+
sessionsToDelete.push(session._id);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
const sessionIdsToDelete = new Set(sessionsToDelete);
|
|
166
|
+
for (const sessionExercise of existingSessionExercises) {
|
|
167
|
+
if (sessionIdsToDelete.has(sessionExercise.workoutSessionId)) {
|
|
168
|
+
sessionExercisesToDelete.push(sessionExercise._id);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const sessionExerciseIdsToDelete = new Set(sessionExercisesToDelete);
|
|
172
|
+
for (const set of existingSets) {
|
|
173
|
+
if (sessionExerciseIdsToDelete.has(set.workoutSessionExerciseId)) {
|
|
174
|
+
setsToDelete.push(set._id);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return { microcyclesToDelete, sessionsToDelete, sessionExercisesToDelete, setsToDelete };
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=WorkoutMesocycleService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkoutMesocycleService.js","sourceRoot":"","sources":["../../../../src/services/workout/Mesocycle/WorkoutMesocycleService.ts"],"names":[],"mappings":"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"}
|