@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.
- package/CHANGELOG.md +29 -0
- package/lib/browser.d.ts +9 -3
- package/lib/browser.d.ts.map +1 -1
- package/lib/browser.js +4 -1
- package/lib/browser.js.map +1 -1
- package/lib/browser.ts +13 -5
- package/lib/ctos/workout/WorkoutExerciseCTO.d.ts +121 -0
- package/lib/ctos/workout/WorkoutExerciseCTO.d.ts.map +1 -0
- package/lib/ctos/workout/WorkoutExerciseCTO.js +58 -0
- package/lib/ctos/workout/WorkoutExerciseCTO.js.map +1 -0
- package/lib/ctos/workout/WorkoutExerciseCTO.ts +71 -0
- package/lib/ctos/workout/WorkoutMuscleGroupVolumeCTO.d.ts +36 -0
- package/lib/ctos/workout/WorkoutMuscleGroupVolumeCTO.d.ts.map +1 -0
- package/lib/ctos/workout/WorkoutMuscleGroupVolumeCTO.js +21 -0
- package/lib/ctos/workout/WorkoutMuscleGroupVolumeCTO.js.map +1 -0
- package/lib/ctos/workout/WorkoutMuscleGroupVolumeCTO.ts +29 -0
- package/lib/documents/workout/README.md +5 -5
- package/lib/documents/workout/WorkoutExerciseCalibration.d.ts +1 -8
- package/lib/documents/workout/WorkoutExerciseCalibration.d.ts.map +1 -1
- package/lib/documents/workout/WorkoutExerciseCalibration.js +12 -1
- package/lib/documents/workout/WorkoutExerciseCalibration.js.map +1 -1
- package/lib/documents/workout/WorkoutExerciseCalibration.ts +12 -10
- package/lib/documents/workout/WorkoutSessionExercise.js +4 -4
- package/lib/documents/workout/WorkoutSessionExercise.ts +4 -4
- package/lib/embedded-types/workout/MesocycleVolumeSummary.d.ts +27 -0
- package/lib/embedded-types/workout/MesocycleVolumeSummary.d.ts.map +1 -0
- package/lib/embedded-types/workout/MesocycleVolumeSummary.js +39 -0
- package/lib/embedded-types/workout/MesocycleVolumeSummary.js.map +1 -0
- package/lib/embedded-types/workout/MesocycleVolumeSummary.ts +55 -0
- package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.d.ts +33 -2
- package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.d.ts.map +1 -1
- package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.js +55 -4
- package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.js.map +1 -1
- package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.ts +69 -4
- package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.d.ts +8 -9
- package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.d.ts.map +1 -1
- package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.js +24 -25
- package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.js.map +1 -1
- package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.ts +29 -35
- package/lib/services/workout/Mesocycle/WorkoutMesocycleService.d.ts +4 -9
- package/lib/services/workout/Mesocycle/WorkoutMesocycleService.d.ts.map +1 -1
- package/lib/services/workout/Mesocycle/WorkoutMesocycleService.js +12 -8
- package/lib/services/workout/Mesocycle/WorkoutMesocycleService.js.map +1 -1
- package/lib/services/workout/Mesocycle/WorkoutMesocycleService.ts +17 -17
- package/lib/services/workout/Microcycle/WorkoutMicrocycleService.d.ts +3 -6
- package/lib/services/workout/Microcycle/WorkoutMicrocycleService.d.ts.map +1 -1
- package/lib/services/workout/Microcycle/WorkoutMicrocycleService.js +22 -34
- package/lib/services/workout/Microcycle/WorkoutMicrocycleService.js.map +1 -1
- package/lib/services/workout/Microcycle/WorkoutMicrocycleService.ts +30 -52
- package/lib/services/workout/Session/WorkoutSessionService.d.ts +7 -7
- package/lib/services/workout/Session/WorkoutSessionService.d.ts.map +1 -1
- package/lib/services/workout/Session/WorkoutSessionService.js +32 -31
- package/lib/services/workout/Session/WorkoutSessionService.js.map +1 -1
- package/lib/services/workout/Session/WorkoutSessionService.ts +38 -36
- package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.d.ts +3 -3
- package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.d.ts.map +1 -1
- package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.js +4 -4
- package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.js.map +1 -1
- package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.ts +4 -4
- package/lib/services/workout/Set/WorkoutSetService.d.ts.map +1 -1
- package/lib/services/workout/Set/WorkoutSetService.js +3 -1
- package/lib/services/workout/Set/WorkoutSetService.js.map +1 -1
- package/lib/services/workout/Set/WorkoutSetService.ts +7 -1
- package/lib/services/workout/util/VolumePlanning/WorkoutVolumePlanningService.js +21 -21
- package/lib/services/workout/util/VolumePlanning/WorkoutVolumePlanningService.js.map +1 -1
- package/lib/services/workout/util/VolumePlanning/WorkoutVolumePlanningService.ts +22 -22
- 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.
|
|
17
|
-
throw new Error('WorkoutMesocyclePlanContext.
|
|
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.
|
|
20
|
-
throw new Error('WorkoutMesocyclePlanContext.
|
|
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
|
|
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 =
|
|
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
|
|
64
|
-
* @param exerciseMap The map of exercise documents.
|
|
63
|
+
* @param exerciseCTOs The exercise CTOs to distribute.
|
|
65
64
|
*/
|
|
66
|
-
static distributeExercisesAcrossSessions(sessionCount,
|
|
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
|
|
80
|
-
const muscleGroupId =
|
|
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(
|
|
73
|
+
existingGroup.push(cto);
|
|
84
74
|
}
|
|
85
75
|
else {
|
|
86
|
-
muscleGroupsMap.set(muscleGroupId, [
|
|
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,
|
|
92
|
-
const fatigueScores =
|
|
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
|
|
121
|
-
if (
|
|
122
|
-
const fatigueScoresAmongExercises =
|
|
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
|
|
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
|
|
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
|
|
156
|
-
sessions[currentSessionIndex].push(
|
|
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.
|
|
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":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;
|
|
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
|
-
|
|
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.
|
|
31
|
+
if (!context.plannedSessionExerciseCTOs) {
|
|
38
32
|
throw new Error(
|
|
39
|
-
'WorkoutMesocyclePlanContext.
|
|
33
|
+
'WorkoutMesocyclePlanContext.plannedSessionExerciseCTOs is not initialized. This should be set during mesocycle planning.'
|
|
40
34
|
);
|
|
41
35
|
}
|
|
42
|
-
if (!context.
|
|
36
|
+
if (!context.muscleGroupToExerciseCTOsMap) {
|
|
43
37
|
throw new Error(
|
|
44
|
-
'WorkoutMesocyclePlanContext.
|
|
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
|
|
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 =
|
|
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
|
|
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
|
-
|
|
106
|
-
|
|
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,
|
|
123
|
-
for (const
|
|
124
|
-
const muscleGroupId =
|
|
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(
|
|
107
|
+
existingGroup.push(cto);
|
|
128
108
|
} else {
|
|
129
|
-
muscleGroupsMap.set(muscleGroupId, [
|
|
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,
|
|
136
|
-
const fatigueScores =
|
|
137
|
-
WorkoutExerciseService.getFatigueScore(
|
|
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:
|
|
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
|
|
172
|
-
if (
|
|
173
|
-
const fatigueScoresAmongExercises =
|
|
174
|
-
WorkoutExerciseService.getFatigueScore(
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
219
|
-
sessions[currentSessionIndex].push(
|
|
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.
|
|
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 {
|
|
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:
|
|
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,
|
|
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
|
|
143
|
-
const
|
|
144
|
-
if (
|
|
145
|
-
throw new Error(`No
|
|
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
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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
|
-
|
|
153
|
-
|
|
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:
|
|
159
|
-
isRecoveryExercise: resolvedSetPlan.recoveryExerciseIds.has(
|
|
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":"AAKA,OAAO,EAAE,oBAAoB,EAAE,MAAM,8CAA8C,CAAC;AAEpF,OAAO,EAAE,4BAA4B,EAAE,MAAM,sDAAsD,CAAC;AAGpG,OAAO,iBAAiB,MAAM,6BAA6B,CAAC;AAC5D,OAAO,iBAAiB,MAAM,kCAAkC,CAAC;AAEjE;;GAEG;AACH,MAAM,CAAN,IAAY,wBAIX;AAJD,WAAY,wBAAwB;IAClC,uEAA2C,CAAA;IAC3C,6FAAiE,CAAA;IACjE,uFAA2D,CAAA;AAC7D,CAAC,EAJW,wBAAwB,KAAxB,wBAAwB,QAInC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,OAAO,OAAO,qBAAqB;IACxC;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,OAAuB;QACxC,OAAO,iBAAiB,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACpD,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,OAAuB;QAC5C,OAAO,iBAAiB,CAAC,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5D,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,OAAuB;QACnC,OAAO,iBAAiB,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAChE,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,oBAAoB,CACzB,UAAgD,EAChD,SAA8C,EAC9C,kBAAwD,EACxD,2BAA8D;QAE9D,IAAI,CAAC,UAAU;YAAE,OAAO,IAAI,CAAC;QAC7B,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAC;QAC5B,IAAI,SAAS,CAAC,SAAS,IAAI,IAAI;YAAE,OAAO,wBAAwB,CAAC,mBAAmB,CAAC;QACrF,IAAI,kBAAkB,IAAI,kBAAkB,CAAC,aAAa,IAAI,IAAI,EAAE,CAAC;YACnE,OAAO,wBAAwB,CAAC,8BAA8B,CAAC;QACjE,CAAC;QACD,IAAI,2BAA2B,IAAI,CAAC,2BAA2B,CAAC,QAAQ,EAAE,CAAC;YACzE,OAAO,wBAAwB,CAAC,2BAA2B,CAAC;QAC9D,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,wBAAwB,CAC7B,QAA0B,EAC1B,kBAAqD,EACrD,MAA6B;QAE7B,IAAI,iBAAiB,GAA0B,IAAI,CAAC;QACpD,IAAI,aAAa,GAA0B,IAAI,CAAC;QAEhD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,OAAO,CAAC,QAAQ;gBAAE,SAAS;YAE/B,IAAI,IAAI,CAAC,oBAAoB,CAAC,OAAO,EAAE,kBAAkB,EAAE,MAAM,CAAC,EAAE,CAAC;gBACnE,IAAI,CAAC,iBAAiB;oBAAE,iBAAiB,GAAG,OAAO,CAAC;YACtD,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,aAAa;oBAAE,aAAa,GAAG,OAAO,CAAC;YAC9C,CAAC;YACD,IAAI,iBAAiB,IAAI,aAAa;gBAAE,MAAM;QAChD,CAAC;QAED,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,CAAC;IAC9C,CAAC;IAED
|
|
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 {
|
|
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:
|
|
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
|
|
164
|
+
const exerciseCTO = sessionExerciseList[exerciseIndex];
|
|
165
|
+
const { bestCalibration } = exerciseCTO;
|
|
185
166
|
|
|
186
|
-
|
|
187
|
-
if (setCountFromPlan == null) {
|
|
167
|
+
if (!bestCalibration) {
|
|
188
168
|
throw new Error(
|
|
189
|
-
`No
|
|
169
|
+
`No calibration found for exercise ${exerciseCTO._id}, ${exerciseCTO.exerciseName}`
|
|
190
170
|
);
|
|
191
171
|
}
|
|
192
172
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
if (!equipment) {
|
|
173
|
+
const setCountFromPlan = resolvedSetPlan.exerciseIdToSetCount.get(exerciseCTO._id);
|
|
174
|
+
if (setCountFromPlan == null) {
|
|
196
175
|
throw new Error(
|
|
197
|
-
`
|
|
176
|
+
`No set plan found for exercise ${exerciseCTO._id}, ${exerciseCTO.exerciseName} in microcycle ${microcycleIndex}`
|
|
198
177
|
);
|
|
199
178
|
}
|
|
200
|
-
|
|
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 ${
|
|
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:
|
|
210
|
-
isRecoveryExercise: resolvedSetPlan.recoveryExerciseIds.has(
|
|
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,
|
|
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,
|
|
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
|
}
|