@aneuhold/core-ts-db-lib 4.1.10 → 4.1.12

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.
Files changed (67) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/lib/browser.d.ts +9 -3
  3. package/lib/browser.d.ts.map +1 -1
  4. package/lib/browser.js +4 -1
  5. package/lib/browser.js.map +1 -1
  6. package/lib/browser.ts +13 -5
  7. package/lib/ctos/workout/WorkoutExerciseCTO.d.ts +121 -0
  8. package/lib/ctos/workout/WorkoutExerciseCTO.d.ts.map +1 -0
  9. package/lib/ctos/workout/WorkoutExerciseCTO.js +58 -0
  10. package/lib/ctos/workout/WorkoutExerciseCTO.js.map +1 -0
  11. package/lib/ctos/workout/WorkoutExerciseCTO.ts +71 -0
  12. package/lib/ctos/workout/WorkoutMuscleGroupVolumeCTO.d.ts +36 -0
  13. package/lib/ctos/workout/WorkoutMuscleGroupVolumeCTO.d.ts.map +1 -0
  14. package/lib/ctos/workout/WorkoutMuscleGroupVolumeCTO.js +21 -0
  15. package/lib/ctos/workout/WorkoutMuscleGroupVolumeCTO.js.map +1 -0
  16. package/lib/ctos/workout/WorkoutMuscleGroupVolumeCTO.ts +29 -0
  17. package/lib/documents/workout/README.md +5 -5
  18. package/lib/documents/workout/WorkoutExerciseCalibration.d.ts +1 -8
  19. package/lib/documents/workout/WorkoutExerciseCalibration.d.ts.map +1 -1
  20. package/lib/documents/workout/WorkoutExerciseCalibration.js +12 -1
  21. package/lib/documents/workout/WorkoutExerciseCalibration.js.map +1 -1
  22. package/lib/documents/workout/WorkoutExerciseCalibration.ts +12 -10
  23. package/lib/documents/workout/WorkoutSessionExercise.js +4 -4
  24. package/lib/documents/workout/WorkoutSessionExercise.ts +4 -4
  25. package/lib/embedded-types/workout/MesocycleVolumeSummary.d.ts +27 -0
  26. package/lib/embedded-types/workout/MesocycleVolumeSummary.d.ts.map +1 -0
  27. package/lib/embedded-types/workout/MesocycleVolumeSummary.js +39 -0
  28. package/lib/embedded-types/workout/MesocycleVolumeSummary.js.map +1 -0
  29. package/lib/embedded-types/workout/MesocycleVolumeSummary.ts +55 -0
  30. package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.d.ts +33 -2
  31. package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.d.ts.map +1 -1
  32. package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.js +55 -4
  33. package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.js.map +1 -1
  34. package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.ts +69 -4
  35. package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.d.ts +8 -9
  36. package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.d.ts.map +1 -1
  37. package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.js +24 -25
  38. package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.js.map +1 -1
  39. package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.ts +29 -35
  40. package/lib/services/workout/Mesocycle/WorkoutMesocycleService.d.ts +4 -9
  41. package/lib/services/workout/Mesocycle/WorkoutMesocycleService.d.ts.map +1 -1
  42. package/lib/services/workout/Mesocycle/WorkoutMesocycleService.js +12 -8
  43. package/lib/services/workout/Mesocycle/WorkoutMesocycleService.js.map +1 -1
  44. package/lib/services/workout/Mesocycle/WorkoutMesocycleService.ts +17 -17
  45. package/lib/services/workout/Microcycle/WorkoutMicrocycleService.d.ts +3 -6
  46. package/lib/services/workout/Microcycle/WorkoutMicrocycleService.d.ts.map +1 -1
  47. package/lib/services/workout/Microcycle/WorkoutMicrocycleService.js +22 -34
  48. package/lib/services/workout/Microcycle/WorkoutMicrocycleService.js.map +1 -1
  49. package/lib/services/workout/Microcycle/WorkoutMicrocycleService.ts +30 -52
  50. package/lib/services/workout/Session/WorkoutSessionService.d.ts +7 -7
  51. package/lib/services/workout/Session/WorkoutSessionService.d.ts.map +1 -1
  52. package/lib/services/workout/Session/WorkoutSessionService.js +32 -31
  53. package/lib/services/workout/Session/WorkoutSessionService.js.map +1 -1
  54. package/lib/services/workout/Session/WorkoutSessionService.ts +38 -36
  55. package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.d.ts +3 -3
  56. package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.d.ts.map +1 -1
  57. package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.js +4 -4
  58. package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.js.map +1 -1
  59. package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.ts +4 -4
  60. package/lib/services/workout/Set/WorkoutSetService.d.ts.map +1 -1
  61. package/lib/services/workout/Set/WorkoutSetService.js +3 -1
  62. package/lib/services/workout/Set/WorkoutSetService.js.map +1 -1
  63. package/lib/services/workout/Set/WorkoutSetService.ts +7 -1
  64. package/lib/services/workout/util/VolumePlanning/WorkoutVolumePlanningService.js +21 -21
  65. package/lib/services/workout/util/VolumePlanning/WorkoutVolumePlanningService.js.map +1 -1
  66. package/lib/services/workout/util/VolumePlanning/WorkoutVolumePlanningService.ts +22 -22
  67. package/package.json +3 -3
@@ -13,13 +13,13 @@ export default class WorkoutMicrocycleService {
13
13
  static generateSessionsForMicrocycle({ context, microcycleIndex, targetRir, isDeloadMicrocycle }) {
14
14
  const mesocycle = context.mesocycle;
15
15
  const microcycle = context.microcyclesInOrder[microcycleIndex];
16
- if (!context.plannedSessionExercisePairs) {
17
- throw new Error('WorkoutMesocyclePlanContext.plannedSessionExercisePairs is not initialized. This should be set during mesocycle planning.');
16
+ if (!context.plannedSessionExerciseCTOs) {
17
+ throw new Error('WorkoutMesocyclePlanContext.plannedSessionExerciseCTOs is not initialized. This should be set during mesocycle planning.');
18
18
  }
19
- if (!context.muscleGroupToExercisePairsMap) {
20
- throw new Error('WorkoutMesocyclePlanContext.muscleGroupToExercisePairsMap is not initialized. This should be derived when the planned session exercise pairs are set.');
19
+ if (!context.muscleGroupToExerciseCTOsMap) {
20
+ throw new Error('WorkoutMesocyclePlanContext.muscleGroupToExerciseCTOsMap is not initialized. This should be derived when the planned session exercise CTOs are set.');
21
21
  }
22
- const sessionsToExerciseSessionsArray = context.plannedSessionExercisePairs;
22
+ const sessionsToExerciseCTOsArray = context.plannedSessionExerciseCTOs;
23
23
  const setPlan = WorkoutVolumePlanningService.calculateSetPlanForMicrocycle(context, microcycleIndex, isDeloadMicrocycle);
24
24
  // Build list of non-rest day dates
25
25
  const nonRestDayDates = [];
@@ -40,7 +40,7 @@ export default class WorkoutMicrocycleService {
40
40
  for (let dayIndex = 0; dayIndex < dayCount; dayIndex++) {
41
41
  const sessionsOnThisDay = basePerDay + (dayIndex < remainder ? 1 : 0);
42
42
  for (let s = 0; s < sessionsOnThisDay; s++) {
43
- const sessionExerciseList = sessionsToExerciseSessionsArray[sessionIndex] || [];
43
+ const sessionExerciseList = sessionsToExerciseCTOsArray[sessionIndex] || [];
44
44
  WorkoutSessionService.generateSession({
45
45
  context,
46
46
  microcycleIndex,
@@ -60,36 +60,26 @@ export default class WorkoutMicrocycleService {
60
60
  * array of arrays structure. The embedded array is the list of exercises for that session.
61
61
  *
62
62
  * @param sessionCount The number of sessions to distribute exercises across.
63
- * @param calibrationMap The map of calibration documents.
64
- * @param exerciseMap The map of exercise documents.
63
+ * @param exerciseCTOs The exercise CTOs to distribute.
65
64
  */
66
- static distributeExercisesAcrossSessions(sessionCount, calibrationMap, exerciseMap) {
67
- // Build calibration-exercise pairs from the provided maps
68
- const validExercises = [];
69
- for (const calibration of calibrationMap.values()) {
70
- const exercise = exerciseMap.get(calibration.workoutExerciseId);
71
- if (!exercise) {
72
- throw new Error(`Exercise ${calibration.workoutExerciseId} not found for calibration ${calibration._id}`);
73
- }
74
- validExercises.push({ calibration, exercise });
75
- }
65
+ static distributeExercisesAcrossSessions(sessionCount, exerciseCTOs) {
76
66
  // Group exercises by their primary muscle group (use first one as main identifier, this might
77
67
  // need to be revisited later for multi-group exercises)
78
68
  const muscleGroupsMap = new Map();
79
- for (const exercisePair of validExercises) {
80
- const muscleGroupId = exercisePair.exercise.primaryMuscleGroups[0];
69
+ for (const cto of exerciseCTOs) {
70
+ const muscleGroupId = cto.primaryMuscleGroups[0];
81
71
  const existingGroup = muscleGroupsMap.get(muscleGroupId);
82
72
  if (existingGroup) {
83
- existingGroup.push(exercisePair);
73
+ existingGroup.push(cto);
84
74
  }
85
75
  else {
86
- muscleGroupsMap.set(muscleGroupId, [exercisePair]);
76
+ muscleGroupsMap.set(muscleGroupId, [cto]);
87
77
  }
88
78
  }
89
79
  // 1. Calculate max fatigue for each muscle group to sort them initially
90
80
  const muscleGroupFatigueScores = new Map();
91
- for (const [muscleGroupId, muscleGroupExercises] of muscleGroupsMap.entries()) {
92
- const fatigueScores = muscleGroupExercises.map((pair) => WorkoutExerciseService.getFatigueScore(pair.exercise));
81
+ for (const [muscleGroupId, muscleGroupCTOs] of muscleGroupsMap.entries()) {
82
+ const fatigueScores = muscleGroupCTOs.map((cto) => WorkoutExerciseService.getFatigueScore(cto));
93
83
  const maxFatigue = Math.max(...fatigueScores);
94
84
  muscleGroupFatigueScores.set(muscleGroupId, maxFatigue);
95
85
  }
@@ -117,9 +107,9 @@ export default class WorkoutMicrocycleService {
117
107
  if (!candidateMuscleGroupId) {
118
108
  let maxFatigue = -1;
119
109
  for (const groupId of sortedMuscleGroupIds) {
120
- const exercisePairs = muscleGroupsMap.get(groupId);
121
- if (exercisePairs && exercisePairs.length > 0) {
122
- const fatigueScoresAmongExercises = exercisePairs.map((pair) => WorkoutExerciseService.getFatigueScore(pair.exercise));
110
+ const ctos = muscleGroupsMap.get(groupId);
111
+ if (ctos && ctos.length > 0) {
112
+ const fatigueScoresAmongExercises = ctos.map((cto) => WorkoutExerciseService.getFatigueScore(cto));
123
113
  const groupMax = Math.max(...fatigueScoresAmongExercises);
124
114
  if (groupMax > maxFatigue) {
125
115
  maxFatigue = groupMax;
@@ -132,8 +122,7 @@ export default class WorkoutMicrocycleService {
132
122
  const group = muscleGroupsMap.get(candidateMuscleGroupId);
133
123
  if (group && group.length > 0) {
134
124
  // Pick highest fatigue exercise in this group to be the headliner
135
- group.sort((a, b) => WorkoutExerciseService.getFatigueScore(b.exercise) -
136
- WorkoutExerciseService.getFatigueScore(a.exercise));
125
+ group.sort((a, b) => WorkoutExerciseService.getFatigueScore(b) - WorkoutExerciseService.getFatigueScore(a));
137
126
  const headliner = group.shift();
138
127
  if (headliner) {
139
128
  sessions[sessionIndex].push(headliner);
@@ -148,12 +137,11 @@ export default class WorkoutMicrocycleService {
148
137
  remainingExercises.push(...group);
149
138
  }
150
139
  // Sort remaining by fatigue (High -> Low)
151
- remainingExercises.sort((a, b) => WorkoutExerciseService.getFatigueScore(b.exercise) -
152
- WorkoutExerciseService.getFatigueScore(a.exercise));
140
+ remainingExercises.sort((a, b) => WorkoutExerciseService.getFatigueScore(b) - WorkoutExerciseService.getFatigueScore(a));
153
141
  // Distribute round-robin
154
142
  let currentSessionIndex = 0;
155
- for (const pair of remainingExercises) {
156
- sessions[currentSessionIndex].push(pair);
143
+ for (const cto of remainingExercises) {
144
+ sessions[currentSessionIndex].push(cto);
157
145
  currentSessionIndex = (currentSessionIndex + 1) % sessionCount;
158
146
  }
159
147
  // 5. Sort within session (Priority 3)
@@ -168,7 +156,7 @@ export default class WorkoutMicrocycleService {
168
156
  [ExerciseRepRange.Medium]: 1,
169
157
  [ExerciseRepRange.Light]: 2
170
158
  };
171
- return order[a.exercise.repRange] - order[b.exercise.repRange];
159
+ return order[a.repRange] - order[b.repRange];
172
160
  });
173
161
  session.length = 0;
174
162
  session.push(headliner, ...rest);
@@ -1 +1 @@
1
- {"version":3,"file":"WorkoutMicrocycleService.js","sourceRoot":"","sources":["../../../../src/services/workout/Microcycle/WorkoutMicrocycleService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"WorkoutMicrocycleService.js","sourceRoot":"","sources":["../../../../src/services/workout/Microcycle/WorkoutMicrocycleService.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,7 @@
1
1
  import { DateService } from '@aneuhold/core-ts-lib';
2
2
  import type { UUID } from 'crypto';
3
- import {
4
- ExerciseRepRange,
5
- type WorkoutExercise
6
- } from '../../../documents/workout/WorkoutExercise.js';
7
- import type {
8
- CalibrationExercisePair,
9
- WorkoutExerciseCalibration
10
- } from '../../../documents/workout/WorkoutExerciseCalibration.js';
3
+ import type { WorkoutExerciseCTO } from '../../../ctos/workout/WorkoutExerciseCTO.js';
4
+ import { ExerciseRepRange } from '../../../documents/workout/WorkoutExercise.js';
11
5
  import WorkoutExerciseService from '../Exercise/WorkoutExerciseService.js';
12
6
  import type WorkoutMesocyclePlanContext from '../Mesocycle/WorkoutMesocyclePlanContext.js';
13
7
  import WorkoutSessionService from '../Session/WorkoutSessionService.js';
@@ -34,18 +28,18 @@ export default class WorkoutMicrocycleService {
34
28
  const mesocycle = context.mesocycle;
35
29
  const microcycle = context.microcyclesInOrder[microcycleIndex];
36
30
 
37
- if (!context.plannedSessionExercisePairs) {
31
+ if (!context.plannedSessionExerciseCTOs) {
38
32
  throw new Error(
39
- 'WorkoutMesocyclePlanContext.plannedSessionExercisePairs is not initialized. This should be set during mesocycle planning.'
33
+ 'WorkoutMesocyclePlanContext.plannedSessionExerciseCTOs is not initialized. This should be set during mesocycle planning.'
40
34
  );
41
35
  }
42
- if (!context.muscleGroupToExercisePairsMap) {
36
+ if (!context.muscleGroupToExerciseCTOsMap) {
43
37
  throw new Error(
44
- 'WorkoutMesocyclePlanContext.muscleGroupToExercisePairsMap is not initialized. This should be derived when the planned session exercise pairs are set.'
38
+ 'WorkoutMesocyclePlanContext.muscleGroupToExerciseCTOsMap is not initialized. This should be derived when the planned session exercise CTOs are set.'
45
39
  );
46
40
  }
47
41
 
48
- const sessionsToExerciseSessionsArray = context.plannedSessionExercisePairs;
42
+ const sessionsToExerciseCTOsArray = context.plannedSessionExerciseCTOs;
49
43
 
50
44
  const setPlan = WorkoutVolumePlanningService.calculateSetPlanForMicrocycle(
51
45
  context,
@@ -74,7 +68,7 @@ export default class WorkoutMicrocycleService {
74
68
  for (let dayIndex = 0; dayIndex < dayCount; dayIndex++) {
75
69
  const sessionsOnThisDay = basePerDay + (dayIndex < remainder ? 1 : 0);
76
70
  for (let s = 0; s < sessionsOnThisDay; s++) {
77
- const sessionExerciseList = sessionsToExerciseSessionsArray[sessionIndex] || [];
71
+ const sessionExerciseList = sessionsToExerciseCTOsArray[sessionIndex] || [];
78
72
 
79
73
  WorkoutSessionService.generateSession({
80
74
  context,
@@ -97,44 +91,30 @@ export default class WorkoutMicrocycleService {
97
91
  * array of arrays structure. The embedded array is the list of exercises for that session.
98
92
  *
99
93
  * @param sessionCount The number of sessions to distribute exercises across.
100
- * @param calibrationMap The map of calibration documents.
101
- * @param exerciseMap The map of exercise documents.
94
+ * @param exerciseCTOs The exercise CTOs to distribute.
102
95
  */
103
96
  static distributeExercisesAcrossSessions(
104
97
  sessionCount: number,
105
- calibrationMap: Map<UUID, WorkoutExerciseCalibration>,
106
- exerciseMap: Map<UUID, WorkoutExercise>
107
- ): CalibrationExercisePair[][] {
108
- // Build calibration-exercise pairs from the provided maps
109
- const validExercises: CalibrationExercisePair[] = [];
110
- for (const calibration of calibrationMap.values()) {
111
- const exercise = exerciseMap.get(calibration.workoutExerciseId);
112
- if (!exercise) {
113
- throw new Error(
114
- `Exercise ${calibration.workoutExerciseId} not found for calibration ${calibration._id}`
115
- );
116
- }
117
- validExercises.push({ calibration, exercise });
118
- }
119
-
98
+ exerciseCTOs: WorkoutExerciseCTO[]
99
+ ): WorkoutExerciseCTO[][] {
120
100
  // Group exercises by their primary muscle group (use first one as main identifier, this might
121
101
  // need to be revisited later for multi-group exercises)
122
- const muscleGroupsMap = new Map<UUID, CalibrationExercisePair[]>();
123
- for (const exercisePair of validExercises) {
124
- const muscleGroupId = exercisePair.exercise.primaryMuscleGroups[0];
102
+ const muscleGroupsMap = new Map<UUID, WorkoutExerciseCTO[]>();
103
+ for (const cto of exerciseCTOs) {
104
+ const muscleGroupId = cto.primaryMuscleGroups[0];
125
105
  const existingGroup = muscleGroupsMap.get(muscleGroupId);
126
106
  if (existingGroup) {
127
- existingGroup.push(exercisePair);
107
+ existingGroup.push(cto);
128
108
  } else {
129
- muscleGroupsMap.set(muscleGroupId, [exercisePair]);
109
+ muscleGroupsMap.set(muscleGroupId, [cto]);
130
110
  }
131
111
  }
132
112
 
133
113
  // 1. Calculate max fatigue for each muscle group to sort them initially
134
114
  const muscleGroupFatigueScores = new Map<UUID, number>();
135
- for (const [muscleGroupId, muscleGroupExercises] of muscleGroupsMap.entries()) {
136
- const fatigueScores = muscleGroupExercises.map((pair) =>
137
- WorkoutExerciseService.getFatigueScore(pair.exercise)
115
+ for (const [muscleGroupId, muscleGroupCTOs] of muscleGroupsMap.entries()) {
116
+ const fatigueScores = muscleGroupCTOs.map((cto) =>
117
+ WorkoutExerciseService.getFatigueScore(cto)
138
118
  );
139
119
  const maxFatigue = Math.max(...fatigueScores);
140
120
  muscleGroupFatigueScores.set(muscleGroupId, maxFatigue);
@@ -148,7 +128,7 @@ export default class WorkoutMicrocycleService {
148
128
  });
149
129
 
150
130
  // Prepare sessions array (so we can push exercises into each empty array)
151
- const sessions: CalibrationExercisePair[][] = Array.from({ length: sessionCount }, () => []);
131
+ const sessions: WorkoutExerciseCTO[][] = Array.from({ length: sessionCount }, () => []);
152
132
  const usedStarterGroups = new Set<UUID>();
153
133
 
154
134
  // 3. Assign Headliners (Priority 1 & 2)
@@ -168,10 +148,10 @@ export default class WorkoutMicrocycleService {
168
148
  if (!candidateMuscleGroupId) {
169
149
  let maxFatigue = -1;
170
150
  for (const groupId of sortedMuscleGroupIds) {
171
- const exercisePairs = muscleGroupsMap.get(groupId);
172
- if (exercisePairs && exercisePairs.length > 0) {
173
- const fatigueScoresAmongExercises = exercisePairs.map((pair) =>
174
- WorkoutExerciseService.getFatigueScore(pair.exercise)
151
+ const ctos = muscleGroupsMap.get(groupId);
152
+ if (ctos && ctos.length > 0) {
153
+ const fatigueScoresAmongExercises = ctos.map((cto) =>
154
+ WorkoutExerciseService.getFatigueScore(cto)
175
155
  );
176
156
  const groupMax = Math.max(...fatigueScoresAmongExercises);
177
157
  if (groupMax > maxFatigue) {
@@ -188,8 +168,7 @@ export default class WorkoutMicrocycleService {
188
168
  // Pick highest fatigue exercise in this group to be the headliner
189
169
  group.sort(
190
170
  (a, b) =>
191
- WorkoutExerciseService.getFatigueScore(b.exercise) -
192
- WorkoutExerciseService.getFatigueScore(a.exercise)
171
+ WorkoutExerciseService.getFatigueScore(b) - WorkoutExerciseService.getFatigueScore(a)
193
172
  );
194
173
  const headliner = group.shift();
195
174
  if (headliner) {
@@ -201,7 +180,7 @@ export default class WorkoutMicrocycleService {
201
180
  }
202
181
 
203
182
  // 4. Distribute Remainder (Priority 2 continued)
204
- const remainingExercises: CalibrationExercisePair[] = [];
183
+ const remainingExercises: WorkoutExerciseCTO[] = [];
205
184
  for (const group of muscleGroupsMap.values()) {
206
185
  remainingExercises.push(...group);
207
186
  }
@@ -209,14 +188,13 @@ export default class WorkoutMicrocycleService {
209
188
  // Sort remaining by fatigue (High -> Low)
210
189
  remainingExercises.sort(
211
190
  (a, b) =>
212
- WorkoutExerciseService.getFatigueScore(b.exercise) -
213
- WorkoutExerciseService.getFatigueScore(a.exercise)
191
+ WorkoutExerciseService.getFatigueScore(b) - WorkoutExerciseService.getFatigueScore(a)
214
192
  );
215
193
 
216
194
  // Distribute round-robin
217
195
  let currentSessionIndex = 0;
218
- for (const pair of remainingExercises) {
219
- sessions[currentSessionIndex].push(pair);
196
+ for (const cto of remainingExercises) {
197
+ sessions[currentSessionIndex].push(cto);
220
198
  currentSessionIndex = (currentSessionIndex + 1) % sessionCount;
221
199
  }
222
200
 
@@ -231,7 +209,7 @@ export default class WorkoutMicrocycleService {
231
209
  [ExerciseRepRange.Medium]: 1,
232
210
  [ExerciseRepRange.Light]: 2
233
211
  };
234
- return order[a.exercise.repRange] - order[b.exercise.repRange];
212
+ return order[a.repRange] - order[b.repRange];
235
213
  });
236
214
  session.length = 0;
237
215
  session.push(headliner, ...rest);
@@ -1,5 +1,5 @@
1
1
  import type { UUID } from 'crypto';
2
- import type { CalibrationExercisePair } from '../../../documents/workout/WorkoutExerciseCalibration.js';
2
+ import type { WorkoutExerciseCTO } from '../../../ctos/workout/WorkoutExerciseCTO.js';
3
3
  import type { WorkoutMesocycle } from '../../../documents/workout/WorkoutMesocycle.js';
4
4
  import type { WorkoutMicrocycle } from '../../../documents/workout/WorkoutMicrocycle.js';
5
5
  import type { WorkoutSession } from '../../../documents/workout/WorkoutSession.js';
@@ -74,11 +74,6 @@ export default class WorkoutSessionService {
74
74
  inProgressSession: WorkoutSession | null;
75
75
  nextUpSession: WorkoutSession | null;
76
76
  };
77
- /**
78
- * Returns true if any set in the session has actualReps != null.
79
- * Traverses session → sessionExercises → sets via order arrays and map lookups.
80
- */
81
- private static sessionHasLoggedSets;
82
77
  /**
83
78
  * Generates a session and its associated exercises and sets.
84
79
  */
@@ -87,7 +82,7 @@ export default class WorkoutSessionService {
87
82
  microcycleIndex: number;
88
83
  sessionIndex: number;
89
84
  sessionStartDate: Date;
90
- sessionExerciseList: CalibrationExercisePair[];
85
+ sessionExerciseList: WorkoutExerciseCTO[];
91
86
  targetRir: number | null;
92
87
  isDeloadMicrocycle: boolean;
93
88
  setPlan: {
@@ -95,5 +90,10 @@ export default class WorkoutSessionService {
95
90
  recoveryExerciseIds: Set<UUID>;
96
91
  };
97
92
  }): void;
93
+ /**
94
+ * Returns true if any set in the session has actualReps != null.
95
+ * Traverses session -> sessionExercises -> sets via order arrays and map lookups.
96
+ */
97
+ private static sessionHasLoggedSets;
98
98
  }
99
99
  //# sourceMappingURL=WorkoutSessionService.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"WorkoutSessionService.d.ts","sourceRoot":"","sources":["../../../../src/services/workout/Session/WorkoutSessionService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,0DAA0D,CAAC;AACxG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gDAAgD,CAAC;AACvF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iDAAiD,CAAC;AACzF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8CAA8C,CAAC;AAEnF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sDAAsD,CAAC;AAEnG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAC3E,OAAO,KAAK,2BAA2B,MAAM,6CAA6C,CAAC;AAI3F;;GAEG;AACH,oBAAY,wBAAwB;IAClC,mBAAmB,wBAAwB;IAC3C,8BAA8B,mCAAmC;IACjE,2BAA2B,gCAAgC;CAC5D;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,OAAO,OAAO,qBAAqB;IACxC;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI;IAI1D;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI;IAI9D;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI;IAIrD;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,oBAAoB,CACzB,UAAU,EAAE,iBAAiB,GAAG,IAAI,GAAG,SAAS,EAChD,SAAS,EAAE,gBAAgB,GAAG,IAAI,GAAG,SAAS,EAC9C,kBAAkB,EAAE,iBAAiB,GAAG,IAAI,GAAG,SAAS,EACxD,2BAA2B,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,GAC7D,wBAAwB,GAAG,IAAI;IAalC;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,wBAAwB,CAC7B,QAAQ,EAAE,cAAc,EAAE,EAC1B,kBAAkB,EAAE,GAAG,CAAC,IAAI,EAAE,sBAAsB,CAAC,EACrD,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,GAC5B;QAAE,iBAAiB,EAAE,cAAc,GAAG,IAAI,CAAC;QAAC,aAAa,EAAE,cAAc,GAAG,IAAI,CAAA;KAAE;IAkBrF;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAgBnC;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,EACrB,OAAO,EACP,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,SAAS,EACT,kBAAkB,EAClB,OAAO,EACR,EAAE;QACD,OAAO,EAAE,2BAA2B,CAAC;QACrC,eAAe,EAAE,MAAM,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,IAAI,CAAC;QACvB,mBAAmB,EAAE,uBAAuB,EAAE,CAAC;QAC/C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,kBAAkB,EAAE,OAAO,CAAC;QAC5B,OAAO,EAAE;YAAE,oBAAoB,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAAC,mBAAmB,EAAE,GAAG,CAAC,IAAI,CAAC,CAAA;SAAE,CAAC;KACtF,GAAG,IAAI;CAqET"}
1
+ {"version":3,"file":"WorkoutSessionService.d.ts","sourceRoot":"","sources":["../../../../src/services/workout/Session/WorkoutSessionService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;AACtF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gDAAgD,CAAC;AACvF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iDAAiD,CAAC;AACzF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8CAA8C,CAAC;AAEnF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sDAAsD,CAAC;AAEnG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAC3E,OAAO,KAAK,2BAA2B,MAAM,6CAA6C,CAAC;AAI3F;;GAEG;AACH,oBAAY,wBAAwB;IAClC,mBAAmB,wBAAwB;IAC3C,8BAA8B,mCAAmC;IACjE,2BAA2B,gCAAgC;CAC5D;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,OAAO,OAAO,qBAAqB;IACxC;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI;IAI1D;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI;IAI9D;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI;IAIrD;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,oBAAoB,CACzB,UAAU,EAAE,iBAAiB,GAAG,IAAI,GAAG,SAAS,EAChD,SAAS,EAAE,gBAAgB,GAAG,IAAI,GAAG,SAAS,EAC9C,kBAAkB,EAAE,iBAAiB,GAAG,IAAI,GAAG,SAAS,EACxD,2BAA2B,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,GAC7D,wBAAwB,GAAG,IAAI;IAalC;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,wBAAwB,CAC7B,QAAQ,EAAE,cAAc,EAAE,EAC1B,kBAAkB,EAAE,GAAG,CAAC,IAAI,EAAE,sBAAsB,CAAC,EACrD,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,GAC5B;QAAE,iBAAiB,EAAE,cAAc,GAAG,IAAI,CAAC;QAAC,aAAa,EAAE,cAAc,GAAG,IAAI,CAAA;KAAE;IAkBrF;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,EACrB,OAAO,EACP,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,SAAS,EACT,kBAAkB,EAClB,OAAO,EACR,EAAE;QACD,OAAO,EAAE,2BAA2B,CAAC;QACrC,eAAe,EAAE,MAAM,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,IAAI,CAAC;QACvB,mBAAmB,EAAE,kBAAkB,EAAE,CAAC;QAC1C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,kBAAkB,EAAE,OAAO,CAAC;QAC5B,OAAO,EAAE;YAAE,oBAAoB,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAAC,mBAAmB,EAAE,GAAG,CAAC,IAAI,CAAC,CAAA;SAAE,CAAC;KACtF,GAAG,IAAI;IAwER;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,oBAAoB;CAepC"}
@@ -106,23 +106,6 @@ export default class WorkoutSessionService {
106
106
  }
107
107
  return { inProgressSession, nextUpSession };
108
108
  }
109
- /**
110
- * Returns true if any set in the session has actualReps != null.
111
- * Traverses session → sessionExercises → sets via order arrays and map lookups.
112
- */
113
- static sessionHasLoggedSets(session, sessionExerciseMap, setMap) {
114
- for (const seId of session.sessionExerciseOrder) {
115
- const se = sessionExerciseMap.get(seId);
116
- if (!se)
117
- continue;
118
- for (const setId of se.setOrder) {
119
- const set = setMap.get(setId);
120
- if (set?.actualReps != null)
121
- return true;
122
- }
123
- }
124
- return false;
125
- }
126
109
  /**
127
110
  * Generates a session and its associated exercises and sets.
128
111
  */
@@ -139,29 +122,30 @@ export default class WorkoutSessionService {
139
122
  });
140
123
  // Create session exercise groupings and associated sets
141
124
  for (let exerciseIndex = 0; exerciseIndex < sessionExerciseList.length; exerciseIndex++) {
142
- const { calibration, exercise } = sessionExerciseList[exerciseIndex];
143
- const setCountFromPlan = resolvedSetPlan.exerciseIdToSetCount.get(exercise._id);
144
- if (setCountFromPlan == null) {
145
- throw new Error(`No set plan found for exercise ${exercise._id}, ${exercise.exerciseName} in microcycle ${microcycleIndex}`);
125
+ const exerciseCTO = sessionExerciseList[exerciseIndex];
126
+ const { bestCalibration } = exerciseCTO;
127
+ if (!bestCalibration) {
128
+ throw new Error(`No calibration found for exercise ${exerciseCTO._id}, ${exerciseCTO.exerciseName}`);
146
129
  }
147
- // Get equipment for weight calculations
148
- const equipment = context.equipmentMap.get(exercise.workoutEquipmentTypeId);
149
- if (!equipment) {
150
- throw new Error(`Equipment type not found for exercise ${exercise._id}, ${exercise.exerciseName}`);
130
+ const setCountFromPlan = resolvedSetPlan.exerciseIdToSetCount.get(exerciseCTO._id);
131
+ if (setCountFromPlan == null) {
132
+ throw new Error(`No set plan found for exercise ${exerciseCTO._id}, ${exerciseCTO.exerciseName} in microcycle ${microcycleIndex}`);
151
133
  }
152
- if (!equipment.weightOptions || equipment.weightOptions.length === 0) {
153
- throw new Error(`No weight options defined for equipment type ${equipment._id}, ${equipment.title}`);
134
+ // Equipment is already available on the CTO
135
+ const { equipmentType } = exerciseCTO;
136
+ if (!equipmentType.weightOptions || equipmentType.weightOptions.length === 0) {
137
+ throw new Error(`No weight options defined for equipment type ${equipmentType._id}, ${equipmentType.title}`);
154
138
  }
155
139
  const sessionExercise = WorkoutSessionExerciseSchema.parse({
156
140
  userId: mesocycle.userId,
157
141
  workoutSessionId: session._id,
158
- workoutExerciseId: exercise._id,
159
- isRecoveryExercise: resolvedSetPlan.recoveryExerciseIds.has(exercise._id)
142
+ workoutExerciseId: exerciseCTO._id,
143
+ isRecoveryExercise: resolvedSetPlan.recoveryExerciseIds.has(exerciseCTO._id)
160
144
  });
161
145
  WorkoutSetService.generateSetsForSessionExercise({
162
146
  context,
163
- exercise,
164
- calibration,
147
+ exercise: exerciseCTO,
148
+ calibration: bestCalibration,
165
149
  session,
166
150
  sessionExercise,
167
151
  microcycleIndex,
@@ -179,5 +163,22 @@ export default class WorkoutSessionService {
179
163
  microcycle.sessionOrder.push(session._id);
180
164
  context.addSession(session);
181
165
  }
166
+ /**
167
+ * Returns true if any set in the session has actualReps != null.
168
+ * Traverses session -> sessionExercises -> sets via order arrays and map lookups.
169
+ */
170
+ static sessionHasLoggedSets(session, sessionExerciseMap, setMap) {
171
+ for (const seId of session.sessionExerciseOrder) {
172
+ const se = sessionExerciseMap.get(seId);
173
+ if (!se)
174
+ continue;
175
+ for (const setId of se.setOrder) {
176
+ const set = setMap.get(setId);
177
+ if (set?.actualReps != null)
178
+ return true;
179
+ }
180
+ }
181
+ return false;
182
+ }
182
183
  }
183
184
  //# sourceMappingURL=WorkoutSessionService.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"WorkoutSessionService.js","sourceRoot":"","sources":["../../../../src/services/workout/Session/WorkoutSessionService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"WorkoutSessionService.js","sourceRoot":"","sources":["../../../../src/services/workout/Session/WorkoutSessionService.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import type { UUID } from 'crypto';
2
- import type { CalibrationExercisePair } from '../../../documents/workout/WorkoutExerciseCalibration.js';
2
+ import type { WorkoutExerciseCTO } from '../../../ctos/workout/WorkoutExerciseCTO.js';
3
3
  import type { WorkoutMesocycle } from '../../../documents/workout/WorkoutMesocycle.js';
4
4
  import type { WorkoutMicrocycle } from '../../../documents/workout/WorkoutMicrocycle.js';
5
5
  import type { WorkoutSession } from '../../../documents/workout/WorkoutSession.js';
@@ -124,26 +124,6 @@ export default class WorkoutSessionService {
124
124
  return { inProgressSession, nextUpSession };
125
125
  }
126
126
 
127
- /**
128
- * Returns true if any set in the session has actualReps != null.
129
- * Traverses session → sessionExercises → sets via order arrays and map lookups.
130
- */
131
- private static sessionHasLoggedSets(
132
- session: WorkoutSession,
133
- sessionExerciseMap: Map<UUID, WorkoutSessionExercise>,
134
- setMap: Map<UUID, WorkoutSet>
135
- ): boolean {
136
- for (const seId of session.sessionExerciseOrder) {
137
- const se = sessionExerciseMap.get(seId);
138
- if (!se) continue;
139
- for (const setId of se.setOrder) {
140
- const set = setMap.get(setId);
141
- if (set?.actualReps != null) return true;
142
- }
143
- }
144
- return false;
145
- }
146
-
147
127
  /**
148
128
  * Generates a session and its associated exercises and sets.
149
129
  */
@@ -161,7 +141,7 @@ export default class WorkoutSessionService {
161
141
  microcycleIndex: number;
162
142
  sessionIndex: number;
163
143
  sessionStartDate: Date;
164
- sessionExerciseList: CalibrationExercisePair[];
144
+ sessionExerciseList: WorkoutExerciseCTO[];
165
145
  targetRir: number | null;
166
146
  isDeloadMicrocycle: boolean;
167
147
  setPlan: { exerciseIdToSetCount: Map<UUID, number>; recoveryExerciseIds: Set<UUID> };
@@ -181,39 +161,41 @@ export default class WorkoutSessionService {
181
161
 
182
162
  // Create session exercise groupings and associated sets
183
163
  for (let exerciseIndex = 0; exerciseIndex < sessionExerciseList.length; exerciseIndex++) {
184
- const { calibration, exercise } = sessionExerciseList[exerciseIndex];
164
+ const exerciseCTO = sessionExerciseList[exerciseIndex];
165
+ const { bestCalibration } = exerciseCTO;
185
166
 
186
- const setCountFromPlan = resolvedSetPlan.exerciseIdToSetCount.get(exercise._id);
187
- if (setCountFromPlan == null) {
167
+ if (!bestCalibration) {
188
168
  throw new Error(
189
- `No set plan found for exercise ${exercise._id}, ${exercise.exerciseName} in microcycle ${microcycleIndex}`
169
+ `No calibration found for exercise ${exerciseCTO._id}, ${exerciseCTO.exerciseName}`
190
170
  );
191
171
  }
192
172
 
193
- // Get equipment for weight calculations
194
- const equipment = context.equipmentMap.get(exercise.workoutEquipmentTypeId);
195
- if (!equipment) {
173
+ const setCountFromPlan = resolvedSetPlan.exerciseIdToSetCount.get(exerciseCTO._id);
174
+ if (setCountFromPlan == null) {
196
175
  throw new Error(
197
- `Equipment type not found for exercise ${exercise._id}, ${exercise.exerciseName}`
176
+ `No set plan found for exercise ${exerciseCTO._id}, ${exerciseCTO.exerciseName} in microcycle ${microcycleIndex}`
198
177
  );
199
178
  }
200
- if (!equipment.weightOptions || equipment.weightOptions.length === 0) {
179
+
180
+ // Equipment is already available on the CTO
181
+ const { equipmentType } = exerciseCTO;
182
+ if (!equipmentType.weightOptions || equipmentType.weightOptions.length === 0) {
201
183
  throw new Error(
202
- `No weight options defined for equipment type ${equipment._id}, ${equipment.title}`
184
+ `No weight options defined for equipment type ${equipmentType._id}, ${equipmentType.title}`
203
185
  );
204
186
  }
205
187
 
206
188
  const sessionExercise = WorkoutSessionExerciseSchema.parse({
207
189
  userId: mesocycle.userId,
208
190
  workoutSessionId: session._id,
209
- workoutExerciseId: exercise._id,
210
- isRecoveryExercise: resolvedSetPlan.recoveryExerciseIds.has(exercise._id)
191
+ workoutExerciseId: exerciseCTO._id,
192
+ isRecoveryExercise: resolvedSetPlan.recoveryExerciseIds.has(exerciseCTO._id)
211
193
  });
212
194
 
213
195
  WorkoutSetService.generateSetsForSessionExercise({
214
196
  context,
215
- exercise,
216
- calibration,
197
+ exercise: exerciseCTO,
198
+ calibration: bestCalibration,
217
199
  session,
218
200
  sessionExercise,
219
201
  microcycleIndex,
@@ -234,4 +216,24 @@ export default class WorkoutSessionService {
234
216
  microcycle.sessionOrder.push(session._id);
235
217
  context.addSession(session);
236
218
  }
219
+
220
+ /**
221
+ * Returns true if any set in the session has actualReps != null.
222
+ * Traverses session -> sessionExercises -> sets via order arrays and map lookups.
223
+ */
224
+ private static sessionHasLoggedSets(
225
+ session: WorkoutSession,
226
+ sessionExerciseMap: Map<UUID, WorkoutSessionExercise>,
227
+ setMap: Map<UUID, WorkoutSet>
228
+ ): boolean {
229
+ for (const seId of session.sessionExerciseOrder) {
230
+ const se = sessionExerciseMap.get(seId);
231
+ if (!se) continue;
232
+ for (const setId of se.setOrder) {
233
+ const set = setMap.get(setId);
234
+ if (set?.actualReps != null) return true;
235
+ }
236
+ }
237
+ return false;
238
+ }
237
239
  }
@@ -63,14 +63,14 @@ export default class WorkoutSessionExerciseService {
63
63
  /**
64
64
  * Returns true if all mid-session metrics are filled out for the session exercise.
65
65
  * Mid-session metrics are filled out right after performing the exercise:
66
- * mindMuscleConnection, pump, unusedMusclePerformance, perceivedEffort,
66
+ * mindMuscleConnection, pump, unusedMusclePerformance,
67
67
  * and performanceScore. Deload exercises are always considered filled.
68
68
  */
69
69
  static hasMidSessionMetricsFilled(sessionExercise: WorkoutSessionExercise, exerciseSets: WorkoutSet[]): boolean;
70
70
  /**
71
71
  * Returns true if all session metrics (both mid-session and post-session) are filled out.
72
- * Post-session metrics are disruption, jointAndTissueDisruption, and sorenessScore.
73
- * Deload exercises are always considered filled.
72
+ * Post-session metrics are disruption, jointAndTissueDisruption, perceivedEffort,
73
+ * and sorenessScore. Deload exercises are always considered filled.
74
74
  */
75
75
  static hasAllSessionMetricsFilled(sessionExercise: WorkoutSessionExercise, exerciseSets: WorkoutSet[]): boolean;
76
76
  }