@aneuhold/core-ts-db-lib 4.1.14 → 4.1.15
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 +11 -0
- package/lib/documents/workout/WorkoutSet.d.ts +9 -6
- package/lib/documents/workout/WorkoutSet.d.ts.map +1 -1
- package/lib/documents/workout/WorkoutSet.ts +9 -6
- package/lib/services/workout/Exercise/WorkoutExerciseService.d.ts +17 -19
- package/lib/services/workout/Exercise/WorkoutExerciseService.d.ts.map +1 -1
- package/lib/services/workout/Exercise/WorkoutExerciseService.js +53 -87
- package/lib/services/workout/Exercise/WorkoutExerciseService.js.map +1 -1
- package/lib/services/workout/Exercise/WorkoutExerciseService.ts +57 -107
- package/lib/services/workout/Set/WorkoutSetService.d.ts.map +1 -1
- package/lib/services/workout/Set/WorkoutSetService.js +2 -3
- package/lib/services/workout/Set/WorkoutSetService.js.map +1 -1
- package/lib/services/workout/Set/WorkoutSetService.ts +2 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## 🔖 [4.1.15] (2026-03-12)
|
|
9
|
+
|
|
10
|
+
### 🏗️ Changed
|
|
11
|
+
|
|
12
|
+
- `CompletedWorkoutSet` type refined to only require planned and actual performance fields (`plannedReps`, `plannedWeight`, `plannedRir`, `actualReps`, `actualWeight`, `rir`) to be non-nullable, rather than all fields.
|
|
13
|
+
- `WorkoutExerciseService.calculateTargetRepsAndWeightForFirstSet` no longer accepts a `microcycleIndex` parameter; all microcycle-to-microcycle progression is now handled by autoregulation/forecasting from the previous set.
|
|
14
|
+
- Replaced `hasCompleteAutoRegulationData` with `toCompletedSet`, which converts a `WorkoutSet` to a `CompletedWorkoutSet` and forecasts planned-only sets (surplus = 0) so progression continues smoothly even without actual performance data.
|
|
15
|
+
- `calculateCalibrationBasedTargets` now computes initial targets only (no microcycle loops); it is used exclusively when no previous set exists.
|
|
16
|
+
- `WorkoutSetService` no longer passes `microcycleIndex` to `calculateTargetRepsAndWeightForFirstSet`.
|
|
17
|
+
|
|
8
18
|
## 🔖 [4.1.14] (2026-03-07)
|
|
9
19
|
|
|
10
20
|
### 🏗️ Changed
|
|
@@ -375,6 +385,7 @@ Updated dependency: now requires `@aneuhold/core-ts-lib@^2.3.11`.
|
|
|
375
385
|
|
|
376
386
|
<!-- Link References -->
|
|
377
387
|
|
|
388
|
+
[4.1.15]: https://github.com/aneuhold/ts-libs/compare/core-ts-db-lib-v4.1.14...core-ts-db-lib-v4.1.15
|
|
378
389
|
[4.1.14]: https://github.com/aneuhold/ts-libs/compare/core-ts-db-lib-v4.1.13...core-ts-db-lib-v4.1.14
|
|
379
390
|
[4.1.13]: https://github.com/aneuhold/ts-libs/compare/core-ts-db-lib-v4.1.12...core-ts-db-lib-v4.1.13
|
|
380
391
|
[4.1.12]: https://github.com/aneuhold/ts-libs/compare/core-ts-db-lib-v4.1.11...core-ts-db-lib-v4.1.12
|
|
@@ -39,11 +39,14 @@ export declare const WorkoutSetSchema: z.ZodObject<{
|
|
|
39
39
|
*/
|
|
40
40
|
export type WorkoutSet = z.infer<typeof WorkoutSetSchema>;
|
|
41
41
|
/**
|
|
42
|
-
* A {@link WorkoutSet} with all
|
|
43
|
-
* Zod's `.nullish()` produces `T | null | undefined`, so `Required` alone
|
|
44
|
-
* only strips the optional `?` — `NonNullable` is needed to also strip `null`.
|
|
42
|
+
* A {@link WorkoutSet} with all planned and actual performance fields guaranteed non-nullable.
|
|
45
43
|
*/
|
|
46
|
-
export type CompletedWorkoutSet =
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
export type CompletedWorkoutSet = WorkoutSet & {
|
|
45
|
+
plannedReps: NonNullable<WorkoutSet['plannedReps']>;
|
|
46
|
+
plannedWeight: NonNullable<WorkoutSet['plannedWeight']>;
|
|
47
|
+
plannedRir: NonNullable<WorkoutSet['plannedRir']>;
|
|
48
|
+
actualReps: NonNullable<WorkoutSet['actualReps']>;
|
|
49
|
+
actualWeight: NonNullable<WorkoutSet['actualWeight']>;
|
|
50
|
+
rir: NonNullable<WorkoutSet['rir']>;
|
|
51
|
+
};
|
|
49
52
|
//# sourceMappingURL=WorkoutSet.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkoutSet.d.ts","sourceRoot":"","sources":["../../../src/documents/workout/WorkoutSet.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB;;GAEG;AACH,eAAO,MAAM,kBAAkB,eAAe,CAAC;AAE/C;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;iBAyD3B,CAAC;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D
|
|
1
|
+
{"version":3,"file":"WorkoutSet.d.ts","sourceRoot":"","sources":["../../../src/documents/workout/WorkoutSet.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB;;GAEG;AACH,eAAO,MAAM,kBAAkB,eAAe,CAAC;AAE/C;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;iBAyD3B,CAAC;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG;IAC7C,WAAW,EAAE,WAAW,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC;IACpD,aAAa,EAAE,WAAW,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC;IACxD,UAAU,EAAE,WAAW,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC;IAClD,UAAU,EAAE,WAAW,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC;IAClD,YAAY,EAAE,WAAW,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC;IACtD,GAAG,EAAE,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;CACrC,CAAC"}
|
|
@@ -90,10 +90,13 @@ export const WorkoutSetSchema = z.object({
|
|
|
90
90
|
export type WorkoutSet = z.infer<typeof WorkoutSetSchema>;
|
|
91
91
|
|
|
92
92
|
/**
|
|
93
|
-
* A {@link WorkoutSet} with all
|
|
94
|
-
* Zod's `.nullish()` produces `T | null | undefined`, so `Required` alone
|
|
95
|
-
* only strips the optional `?` — `NonNullable` is needed to also strip `null`.
|
|
93
|
+
* A {@link WorkoutSet} with all planned and actual performance fields guaranteed non-nullable.
|
|
96
94
|
*/
|
|
97
|
-
export type CompletedWorkoutSet =
|
|
98
|
-
|
|
99
|
-
|
|
95
|
+
export type CompletedWorkoutSet = WorkoutSet & {
|
|
96
|
+
plannedReps: NonNullable<WorkoutSet['plannedReps']>;
|
|
97
|
+
plannedWeight: NonNullable<WorkoutSet['plannedWeight']>;
|
|
98
|
+
plannedRir: NonNullable<WorkoutSet['plannedRir']>;
|
|
99
|
+
actualReps: NonNullable<WorkoutSet['actualReps']>;
|
|
100
|
+
actualWeight: NonNullable<WorkoutSet['actualWeight']>;
|
|
101
|
+
rir: NonNullable<WorkoutSet['rir']>;
|
|
102
|
+
};
|
|
@@ -27,29 +27,19 @@ export default class WorkoutExerciseService {
|
|
|
27
27
|
*/
|
|
28
28
|
static getFatigueScore(exercise: WorkoutExercise): number;
|
|
29
29
|
/**
|
|
30
|
-
* Calculates the
|
|
31
|
-
* This returns the target weight and reps for the FIRST set of the exercise in the given microcycle,
|
|
32
|
-
* assuming it is an accumulation phase (i.e., not a deload).
|
|
30
|
+
* Calculates the target weight and reps for the FIRST set of an exercise.
|
|
33
31
|
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
32
|
+
* When a `previousFirstSet` is provided (completed or planned-only), autoregulation
|
|
33
|
+
* computes a surplus and applies progression. Planned-only sets are forecasted with
|
|
34
|
+
* surplus = 0 so the plan progresses smoothly without falling back to calibration.
|
|
36
35
|
*
|
|
37
|
-
* When
|
|
38
|
-
*
|
|
39
|
-
* is used as a baseline.
|
|
40
|
-
*
|
|
41
|
-
* Rep progression: The weight is calculated based on reps at microcycle 0, and reps increase
|
|
42
|
-
* by 2 per microcycle to reach max reps at the final accumulation microcycle (ideally),
|
|
43
|
-
* or drop back down and increase weight by 2%.
|
|
44
|
-
*
|
|
45
|
-
* Load progression: Increases weight by at least 2% per microcycle.
|
|
46
|
-
* If weight can't be increased, adds 2 reps instead.
|
|
36
|
+
* When no previous set exists (first mesocycle or new exercise), the calibration-based
|
|
37
|
+
* formula computes initial targets from the exercise's 1RM and rep range.
|
|
47
38
|
*/
|
|
48
39
|
static calculateTargetRepsAndWeightForFirstSet(params: {
|
|
49
40
|
exercise: WorkoutExercise;
|
|
50
41
|
calibration: WorkoutExerciseCalibration;
|
|
51
42
|
equipment: WorkoutEquipmentType;
|
|
52
|
-
microcycleIndex: number;
|
|
53
43
|
firstMicrocycleRir: number;
|
|
54
44
|
previousFirstSet?: WorkoutSet;
|
|
55
45
|
}): {
|
|
@@ -83,11 +73,19 @@ export default class WorkoutExerciseService {
|
|
|
83
73
|
*/
|
|
84
74
|
private static calculateAutoRegulatedLoadTargets;
|
|
85
75
|
/**
|
|
86
|
-
*
|
|
76
|
+
* Converts a {@link WorkoutSet} into a {@link CompletedWorkoutSet} for autoregulation.
|
|
77
|
+
*
|
|
78
|
+
* If actual performance data exists, returns the set with those values. Otherwise,
|
|
79
|
+
* forecasts by copying planned values into the actual fields (producing surplus = 0)
|
|
80
|
+
* so that autoregulation applies normal progression from the planned baseline.
|
|
81
|
+
*
|
|
82
|
+
* Returns null if the set lacks the minimum planned data needed.
|
|
87
83
|
*/
|
|
88
|
-
private static
|
|
84
|
+
private static toCompletedSet;
|
|
89
85
|
/**
|
|
90
|
-
* Calculates targets
|
|
86
|
+
* Calculates initial targets from calibration data. Used only when no previous
|
|
87
|
+
* set exists (first microcycle of the first mesocycle, or brand-new exercise).
|
|
88
|
+
* All subsequent microcycle progression is handled by autoregulation/forecasting.
|
|
91
89
|
*/
|
|
92
90
|
private static calculateCalibrationBasedTargets;
|
|
93
91
|
private static findNextTwoPercentWeight;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkoutExerciseService.d.ts","sourceRoot":"","sources":["../../../../src/services/workout/Exercise/WorkoutExerciseService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oDAAoD,CAAC;AAC/F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+CAA+C,CAAC;AACrF,OAAO,EAEL,gBAAgB,EACjB,MAAM,+CAA+C,CAAC;AACvD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,0DAA0D,CAAC;AAC3G,OAAO,KAAK,EAAuB,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAMhG;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,sBAAsB;IACzC;;;;;;;;OAQG;IACH,MAAM,CAAC,iBAAiB,CAAC,QAAQ,EAAE,gBAAgB,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE;IAWlF;;;;OAIG;IACH,MAAM,CAAC,eAAe,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM;IAIzD
|
|
1
|
+
{"version":3,"file":"WorkoutExerciseService.d.ts","sourceRoot":"","sources":["../../../../src/services/workout/Exercise/WorkoutExerciseService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oDAAoD,CAAC;AAC/F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+CAA+C,CAAC;AACrF,OAAO,EAEL,gBAAgB,EACjB,MAAM,+CAA+C,CAAC;AACvD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,0DAA0D,CAAC;AAC3G,OAAO,KAAK,EAAuB,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAMhG;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,sBAAsB;IACzC;;;;;;;;OAQG;IACH,MAAM,CAAC,iBAAiB,CAAC,QAAQ,EAAE,gBAAgB,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE;IAWlF;;;;OAIG;IACH,MAAM,CAAC,eAAe,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM;IAIzD;;;;;;;;;OASG;IACH,MAAM,CAAC,uCAAuC,CAAC,MAAM,EAAE;QACrD,QAAQ,EAAE,eAAe,CAAC;QAC1B,WAAW,EAAE,0BAA0B,CAAC;QACxC,SAAS,EAAE,oBAAoB,CAAC;QAChC,kBAAkB,EAAE,MAAM,CAAC;QAC3B,gBAAgB,CAAC,EAAE,UAAU,CAAC;KAC/B,GAAG;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE;IAuChD;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,6BAA6B;IAsB5C;;;;;;;;;OASG;IACH,OAAO,CAAC,MAAM,CAAC,gCAAgC;IA4C/C;;;;;;;;;OASG;IACH,OAAO,CAAC,MAAM,CAAC,iCAAiC;IA2ChD;;;;;;;;OAQG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAmB7B;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,gCAAgC;IA2C/C,OAAO,CAAC,MAAM,CAAC,wBAAwB;CAgBxC"}
|
|
@@ -35,26 +35,17 @@ export default class WorkoutExerciseService {
|
|
|
35
35
|
return WorkoutSFRService.getFatigueTotal(exercise.initialFatigueGuess) || 0;
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
|
-
* Calculates the
|
|
39
|
-
* This returns the target weight and reps for the FIRST set of the exercise in the given microcycle,
|
|
40
|
-
* assuming it is an accumulation phase (i.e., not a deload).
|
|
38
|
+
* Calculates the target weight and reps for the FIRST set of an exercise.
|
|
41
39
|
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
40
|
+
* When a `previousFirstSet` is provided (completed or planned-only), autoregulation
|
|
41
|
+
* computes a surplus and applies progression. Planned-only sets are forecasted with
|
|
42
|
+
* surplus = 0 so the plan progresses smoothly without falling back to calibration.
|
|
44
43
|
*
|
|
45
|
-
* When
|
|
46
|
-
*
|
|
47
|
-
* is used as a baseline.
|
|
48
|
-
*
|
|
49
|
-
* Rep progression: The weight is calculated based on reps at microcycle 0, and reps increase
|
|
50
|
-
* by 2 per microcycle to reach max reps at the final accumulation microcycle (ideally),
|
|
51
|
-
* or drop back down and increase weight by 2%.
|
|
52
|
-
*
|
|
53
|
-
* Load progression: Increases weight by at least 2% per microcycle.
|
|
54
|
-
* If weight can't be increased, adds 2 reps instead.
|
|
44
|
+
* When no previous set exists (first mesocycle or new exercise), the calibration-based
|
|
45
|
+
* formula computes initial targets from the exercise's 1RM and rep range.
|
|
55
46
|
*/
|
|
56
47
|
static calculateTargetRepsAndWeightForFirstSet(params) {
|
|
57
|
-
const { exercise, calibration, equipment,
|
|
48
|
+
const { exercise, calibration, equipment, firstMicrocycleRir, previousFirstSet } = params;
|
|
58
49
|
// Validate equipment has weight options
|
|
59
50
|
if (!equipment.weightOptions || equipment.weightOptions.length === 0) {
|
|
60
51
|
throw new Error(`No weight options defined for equipment type ${equipment._id}, ${equipment.title}`);
|
|
@@ -62,12 +53,16 @@ export default class WorkoutExerciseService {
|
|
|
62
53
|
// Get rep range for this exercise
|
|
63
54
|
const repRange = this.getRepRangeValues(exercise.repRange);
|
|
64
55
|
const repRangeMidpoint = Math.floor((repRange.min + repRange.max) / 2);
|
|
65
|
-
//
|
|
66
|
-
|
|
56
|
+
// When a previous set is available, use autoregulation for progression.
|
|
57
|
+
// toCompletedSet returns the real data when actual performance exists, or
|
|
58
|
+
// forecasts by copying planned values into actuals (surplus = 0) so the
|
|
59
|
+
// plan progresses smoothly from the planned baseline.
|
|
60
|
+
const completedPreviousSet = this.toCompletedSet(previousFirstSet);
|
|
61
|
+
if (completedPreviousSet) {
|
|
67
62
|
return this.calculateAutoRegulatedTargets({
|
|
68
63
|
exercise,
|
|
69
64
|
equipment,
|
|
70
|
-
previousFirstSet,
|
|
65
|
+
previousFirstSet: completedPreviousSet,
|
|
71
66
|
repRange
|
|
72
67
|
});
|
|
73
68
|
}
|
|
@@ -76,7 +71,6 @@ export default class WorkoutExerciseService {
|
|
|
76
71
|
exercise,
|
|
77
72
|
calibration,
|
|
78
73
|
equipment,
|
|
79
|
-
microcycleIndex,
|
|
80
74
|
firstMicrocycleRir,
|
|
81
75
|
repRange,
|
|
82
76
|
repRangeMidpoint
|
|
@@ -176,82 +170,54 @@ export default class WorkoutExerciseService {
|
|
|
176
170
|
return { targetWeight, targetReps };
|
|
177
171
|
}
|
|
178
172
|
/**
|
|
179
|
-
*
|
|
173
|
+
* Converts a {@link WorkoutSet} into a {@link CompletedWorkoutSet} for autoregulation.
|
|
174
|
+
*
|
|
175
|
+
* If actual performance data exists, returns the set with those values. Otherwise,
|
|
176
|
+
* forecasts by copying planned values into the actual fields (producing surplus = 0)
|
|
177
|
+
* so that autoregulation applies normal progression from the planned baseline.
|
|
178
|
+
*
|
|
179
|
+
* Returns null if the set lacks the minimum planned data needed.
|
|
180
180
|
*/
|
|
181
|
-
static
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
181
|
+
static toCompletedSet(set) {
|
|
182
|
+
if (!set) {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
const { plannedReps, plannedWeight, plannedRir } = set;
|
|
186
|
+
if (plannedReps == null || plannedWeight == null || plannedRir == null) {
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
...set,
|
|
191
|
+
plannedReps,
|
|
192
|
+
plannedWeight,
|
|
193
|
+
plannedRir,
|
|
194
|
+
actualReps: set.actualReps ?? plannedReps,
|
|
195
|
+
actualWeight: set.actualWeight ?? plannedWeight,
|
|
196
|
+
rir: set.rir ?? plannedRir
|
|
197
|
+
};
|
|
187
198
|
}
|
|
188
199
|
/**
|
|
189
|
-
* Calculates targets
|
|
200
|
+
* Calculates initial targets from calibration data. Used only when no previous
|
|
201
|
+
* set exists (first microcycle of the first mesocycle, or brand-new exercise).
|
|
202
|
+
* All subsequent microcycle progression is handled by autoregulation/forecasting.
|
|
190
203
|
*/
|
|
191
204
|
static calculateCalibrationBasedTargets(params) {
|
|
192
|
-
const { exercise, calibration, equipment,
|
|
193
|
-
// For rep progression, calculate weight based on
|
|
205
|
+
const { exercise, calibration, equipment, firstMicrocycleRir, repRange, repRangeMidpoint } = params;
|
|
206
|
+
// For rep progression, calculate weight based on midpoint + RIR reps
|
|
194
207
|
// For load progression, use max reps
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
199
|
-
else {
|
|
200
|
-
// Load progression uses max reps for initial weight calculation
|
|
201
|
-
baseRepsForWeight = repRange.max;
|
|
202
|
-
}
|
|
208
|
+
const baseRepsForWeight = exercise.preferredProgressionType === ExerciseProgressionType.Rep
|
|
209
|
+
? repRangeMidpoint + firstMicrocycleRir
|
|
210
|
+
: repRange.max;
|
|
203
211
|
// Calculate base weight
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
if (roundedWeight === null) {
|
|
212
|
+
const rawWeight = WorkoutExerciseCalibrationService.getTargetWeight(calibration, baseRepsForWeight);
|
|
213
|
+
const targetWeight = WorkoutEquipmentTypeService.findNearestWeight(equipment, rawWeight, 'prefer-down');
|
|
214
|
+
if (targetWeight === null) {
|
|
208
215
|
throw new Error(`No available weight options found for equipment type ${equipment._id}, ${equipment.title}`);
|
|
209
216
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
// Rep progression: Add up to max reps, then loop back if needed
|
|
215
|
-
let currentMicrocycleIndex = 0;
|
|
216
|
-
targetReps = repRangeMidpoint;
|
|
217
|
-
while (currentMicrocycleIndex < microcycleIndex) {
|
|
218
|
-
targetReps += 2;
|
|
219
|
-
if (targetReps > repRange.max) {
|
|
220
|
-
// Different reset amounts based on the rep range
|
|
221
|
-
switch (exercise.repRange) {
|
|
222
|
-
case ExerciseRepRange.Heavy:
|
|
223
|
-
targetReps = targetReps - 4;
|
|
224
|
-
break;
|
|
225
|
-
case ExerciseRepRange.Medium:
|
|
226
|
-
targetReps = targetReps - 6;
|
|
227
|
-
break;
|
|
228
|
-
case ExerciseRepRange.Light:
|
|
229
|
-
targetReps = targetReps - 8;
|
|
230
|
-
break;
|
|
231
|
-
}
|
|
232
|
-
const nextWeight = this.findNextTwoPercentWeight(targetWeight, equipment);
|
|
233
|
-
if (nextWeight !== null) {
|
|
234
|
-
targetWeight = nextWeight;
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
currentMicrocycleIndex++;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
else {
|
|
241
|
-
// Load progression: Start at max reps
|
|
242
|
-
targetReps = repRange.max;
|
|
243
|
-
}
|
|
244
|
-
// Apply load progression if applicable for the weight
|
|
245
|
-
if (exercise.preferredProgressionType === ExerciseProgressionType.Load && microcycleIndex > 0) {
|
|
246
|
-
const nextWeight = this.findNextTwoPercentWeight(targetWeight, equipment);
|
|
247
|
-
if (nextWeight !== null) {
|
|
248
|
-
targetWeight = nextWeight;
|
|
249
|
-
}
|
|
250
|
-
else {
|
|
251
|
-
// Increase reps if we can't increase weight
|
|
252
|
-
targetReps = targetReps + 2;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
217
|
+
// Rep progression starts at midpoint; load progression starts at max reps
|
|
218
|
+
const targetReps = exercise.preferredProgressionType === ExerciseProgressionType.Rep
|
|
219
|
+
? repRangeMidpoint
|
|
220
|
+
: repRange.max;
|
|
255
221
|
return { targetWeight, targetReps };
|
|
256
222
|
}
|
|
257
223
|
static findNextTwoPercentWeight(currentWeight, equipment) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkoutExerciseService.js","sourceRoot":"","sources":["../../../../src/services/workout/Exercise/WorkoutExerciseService.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EACjB,MAAM,+CAA+C,CAAC;AAGvD,OAAO,2BAA2B,MAAM,iDAAiD,CAAC;AAC1F,OAAO,iCAAiC,MAAM,6DAA6D,CAAC;AAC5G,OAAO,6BAA6B,MAAM,qDAAqD,CAAC;AAChG,OAAO,iBAAiB,MAAM,kCAAkC,CAAC;AAEjE;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,sBAAsB;IACzC;;;;;;;;OAQG;IACH,MAAM,CAAC,iBAAiB,CAAC,QAA0B;QACjD,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,gBAAgB,CAAC,KAAK;gBACzB,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC;YAC7B,KAAK,gBAAgB,CAAC,MAAM;gBAC1B,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC;YAC9B,KAAK,gBAAgB,CAAC,KAAK;gBACzB,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC;QAChC,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,eAAe,CAAC,QAAyB;QAC9C,OAAO,iBAAiB,CAAC,eAAe,CAAC,QAAQ,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAC9E,CAAC;IAED
|
|
1
|
+
{"version":3,"file":"WorkoutExerciseService.js","sourceRoot":"","sources":["../../../../src/services/workout/Exercise/WorkoutExerciseService.ts"],"names":[],"mappings":"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"}
|
|
@@ -45,40 +45,23 @@ export default class WorkoutExerciseService {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
|
-
* Calculates the
|
|
49
|
-
* This returns the target weight and reps for the FIRST set of the exercise in the given microcycle,
|
|
50
|
-
* assuming it is an accumulation phase (i.e., not a deload).
|
|
48
|
+
* Calculates the target weight and reps for the FIRST set of an exercise.
|
|
51
49
|
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
50
|
+
* When a `previousFirstSet` is provided (completed or planned-only), autoregulation
|
|
51
|
+
* computes a surplus and applies progression. Planned-only sets are forecasted with
|
|
52
|
+
* surplus = 0 so the plan progresses smoothly without falling back to calibration.
|
|
54
53
|
*
|
|
55
|
-
* When
|
|
56
|
-
*
|
|
57
|
-
* is used as a baseline.
|
|
58
|
-
*
|
|
59
|
-
* Rep progression: The weight is calculated based on reps at microcycle 0, and reps increase
|
|
60
|
-
* by 2 per microcycle to reach max reps at the final accumulation microcycle (ideally),
|
|
61
|
-
* or drop back down and increase weight by 2%.
|
|
62
|
-
*
|
|
63
|
-
* Load progression: Increases weight by at least 2% per microcycle.
|
|
64
|
-
* If weight can't be increased, adds 2 reps instead.
|
|
54
|
+
* When no previous set exists (first mesocycle or new exercise), the calibration-based
|
|
55
|
+
* formula computes initial targets from the exercise's 1RM and rep range.
|
|
65
56
|
*/
|
|
66
57
|
static calculateTargetRepsAndWeightForFirstSet(params: {
|
|
67
58
|
exercise: WorkoutExercise;
|
|
68
59
|
calibration: WorkoutExerciseCalibration;
|
|
69
60
|
equipment: WorkoutEquipmentType;
|
|
70
|
-
microcycleIndex: number;
|
|
71
61
|
firstMicrocycleRir: number;
|
|
72
62
|
previousFirstSet?: WorkoutSet;
|
|
73
63
|
}): { targetWeight: number; targetReps: number } {
|
|
74
|
-
const {
|
|
75
|
-
exercise,
|
|
76
|
-
calibration,
|
|
77
|
-
equipment,
|
|
78
|
-
microcycleIndex,
|
|
79
|
-
firstMicrocycleRir,
|
|
80
|
-
previousFirstSet
|
|
81
|
-
} = params;
|
|
64
|
+
const { exercise, calibration, equipment, firstMicrocycleRir, previousFirstSet } = params;
|
|
82
65
|
|
|
83
66
|
// Validate equipment has weight options
|
|
84
67
|
if (!equipment.weightOptions || equipment.weightOptions.length === 0) {
|
|
@@ -91,12 +74,16 @@ export default class WorkoutExerciseService {
|
|
|
91
74
|
const repRange = this.getRepRangeValues(exercise.repRange);
|
|
92
75
|
const repRangeMidpoint = Math.floor((repRange.min + repRange.max) / 2);
|
|
93
76
|
|
|
94
|
-
//
|
|
95
|
-
|
|
77
|
+
// When a previous set is available, use autoregulation for progression.
|
|
78
|
+
// toCompletedSet returns the real data when actual performance exists, or
|
|
79
|
+
// forecasts by copying planned values into actuals (surplus = 0) so the
|
|
80
|
+
// plan progresses smoothly from the planned baseline.
|
|
81
|
+
const completedPreviousSet = this.toCompletedSet(previousFirstSet);
|
|
82
|
+
if (completedPreviousSet) {
|
|
96
83
|
return this.calculateAutoRegulatedTargets({
|
|
97
84
|
exercise,
|
|
98
85
|
equipment,
|
|
99
|
-
previousFirstSet,
|
|
86
|
+
previousFirstSet: completedPreviousSet,
|
|
100
87
|
repRange
|
|
101
88
|
});
|
|
102
89
|
}
|
|
@@ -106,7 +93,6 @@ export default class WorkoutExerciseService {
|
|
|
106
93
|
exercise,
|
|
107
94
|
calibration,
|
|
108
95
|
equipment,
|
|
109
|
-
microcycleIndex,
|
|
110
96
|
firstMicrocycleRir,
|
|
111
97
|
repRange,
|
|
112
98
|
repRangeMidpoint
|
|
@@ -246,113 +232,77 @@ export default class WorkoutExerciseService {
|
|
|
246
232
|
}
|
|
247
233
|
|
|
248
234
|
/**
|
|
249
|
-
*
|
|
235
|
+
* Converts a {@link WorkoutSet} into a {@link CompletedWorkoutSet} for autoregulation.
|
|
236
|
+
*
|
|
237
|
+
* If actual performance data exists, returns the set with those values. Otherwise,
|
|
238
|
+
* forecasts by copying planned values into the actual fields (producing surplus = 0)
|
|
239
|
+
* so that autoregulation applies normal progression from the planned baseline.
|
|
240
|
+
*
|
|
241
|
+
* Returns null if the set lacks the minimum planned data needed.
|
|
250
242
|
*/
|
|
251
|
-
private static
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
243
|
+
private static toCompletedSet(set?: WorkoutSet): CompletedWorkoutSet | null {
|
|
244
|
+
if (!set) {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
const { plannedReps, plannedWeight, plannedRir } = set;
|
|
248
|
+
if (plannedReps == null || plannedWeight == null || plannedRir == null) {
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
return {
|
|
252
|
+
...set,
|
|
253
|
+
plannedReps,
|
|
254
|
+
plannedWeight,
|
|
255
|
+
plannedRir,
|
|
256
|
+
actualReps: set.actualReps ?? plannedReps,
|
|
257
|
+
actualWeight: set.actualWeight ?? plannedWeight,
|
|
258
|
+
rir: set.rir ?? plannedRir
|
|
259
|
+
};
|
|
259
260
|
}
|
|
260
261
|
|
|
261
262
|
/**
|
|
262
|
-
* Calculates targets
|
|
263
|
+
* Calculates initial targets from calibration data. Used only when no previous
|
|
264
|
+
* set exists (first microcycle of the first mesocycle, or brand-new exercise).
|
|
265
|
+
* All subsequent microcycle progression is handled by autoregulation/forecasting.
|
|
263
266
|
*/
|
|
264
267
|
private static calculateCalibrationBasedTargets(params: {
|
|
265
268
|
exercise: WorkoutExercise;
|
|
266
269
|
calibration: WorkoutExerciseCalibration;
|
|
267
270
|
equipment: WorkoutEquipmentType;
|
|
268
|
-
microcycleIndex: number;
|
|
269
271
|
firstMicrocycleRir: number;
|
|
270
272
|
repRange: { min: number; max: number };
|
|
271
273
|
repRangeMidpoint: number;
|
|
272
274
|
}): { targetWeight: number; targetReps: number } {
|
|
273
|
-
const {
|
|
274
|
-
|
|
275
|
-
calibration,
|
|
276
|
-
equipment,
|
|
277
|
-
microcycleIndex,
|
|
278
|
-
firstMicrocycleRir,
|
|
279
|
-
repRange,
|
|
280
|
-
repRangeMidpoint
|
|
281
|
-
} = params;
|
|
275
|
+
const { exercise, calibration, equipment, firstMicrocycleRir, repRange, repRangeMidpoint } =
|
|
276
|
+
params;
|
|
282
277
|
|
|
283
|
-
// For rep progression, calculate weight based on
|
|
278
|
+
// For rep progression, calculate weight based on midpoint + RIR reps
|
|
284
279
|
// For load progression, use max reps
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
// Load progression uses max reps for initial weight calculation
|
|
290
|
-
baseRepsForWeight = repRange.max;
|
|
291
|
-
}
|
|
280
|
+
const baseRepsForWeight =
|
|
281
|
+
exercise.preferredProgressionType === ExerciseProgressionType.Rep
|
|
282
|
+
? repRangeMidpoint + firstMicrocycleRir
|
|
283
|
+
: repRange.max;
|
|
292
284
|
|
|
293
285
|
// Calculate base weight
|
|
294
|
-
|
|
286
|
+
const rawWeight = WorkoutExerciseCalibrationService.getTargetWeight(
|
|
295
287
|
calibration,
|
|
296
288
|
baseRepsForWeight
|
|
297
289
|
);
|
|
298
|
-
|
|
299
|
-
// Round to nearest available weight, preferring lower
|
|
300
|
-
const roundedWeight = WorkoutEquipmentTypeService.findNearestWeight(
|
|
290
|
+
const targetWeight = WorkoutEquipmentTypeService.findNearestWeight(
|
|
301
291
|
equipment,
|
|
302
|
-
|
|
292
|
+
rawWeight,
|
|
303
293
|
'prefer-down'
|
|
304
294
|
);
|
|
305
|
-
if (
|
|
295
|
+
if (targetWeight === null) {
|
|
306
296
|
throw new Error(
|
|
307
297
|
`No available weight options found for equipment type ${equipment._id}, ${equipment.title}`
|
|
308
298
|
);
|
|
309
299
|
}
|
|
310
|
-
targetWeight = roundedWeight;
|
|
311
|
-
|
|
312
|
-
// Calculate target reps based on progression type
|
|
313
|
-
let targetReps: number;
|
|
314
|
-
if (exercise.preferredProgressionType === ExerciseProgressionType.Rep) {
|
|
315
|
-
// Rep progression: Add up to max reps, then loop back if needed
|
|
316
|
-
let currentMicrocycleIndex = 0;
|
|
317
|
-
targetReps = repRangeMidpoint;
|
|
318
|
-
|
|
319
|
-
while (currentMicrocycleIndex < microcycleIndex) {
|
|
320
|
-
targetReps += 2;
|
|
321
|
-
if (targetReps > repRange.max) {
|
|
322
|
-
// Different reset amounts based on the rep range
|
|
323
|
-
switch (exercise.repRange) {
|
|
324
|
-
case ExerciseRepRange.Heavy:
|
|
325
|
-
targetReps = targetReps - 4;
|
|
326
|
-
break;
|
|
327
|
-
case ExerciseRepRange.Medium:
|
|
328
|
-
targetReps = targetReps - 6;
|
|
329
|
-
break;
|
|
330
|
-
case ExerciseRepRange.Light:
|
|
331
|
-
targetReps = targetReps - 8;
|
|
332
|
-
break;
|
|
333
|
-
}
|
|
334
|
-
const nextWeight = this.findNextTwoPercentWeight(targetWeight, equipment);
|
|
335
|
-
if (nextWeight !== null) {
|
|
336
|
-
targetWeight = nextWeight;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
currentMicrocycleIndex++;
|
|
340
|
-
}
|
|
341
|
-
} else {
|
|
342
|
-
// Load progression: Start at max reps
|
|
343
|
-
targetReps = repRange.max;
|
|
344
|
-
}
|
|
345
300
|
|
|
346
|
-
//
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
} else {
|
|
352
|
-
// Increase reps if we can't increase weight
|
|
353
|
-
targetReps = targetReps + 2;
|
|
354
|
-
}
|
|
355
|
-
}
|
|
301
|
+
// Rep progression starts at midpoint; load progression starts at max reps
|
|
302
|
+
const targetReps =
|
|
303
|
+
exercise.preferredProgressionType === ExerciseProgressionType.Rep
|
|
304
|
+
? repRangeMidpoint
|
|
305
|
+
: repRange.max;
|
|
356
306
|
|
|
357
307
|
return { targetWeight, targetReps };
|
|
358
308
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkoutSetService.d.ts","sourceRoot":"","sources":["../../../../src/services/workout/Set/WorkoutSetService.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;AAGtF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8CAA8C,CAAC;AACnF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sDAAsD,CAAC;AACnG,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAG7F,OAAO,KAAK,2BAA2B,MAAM,6CAA6C,CAAC;AAE3F,MAAM,CAAC,OAAO,OAAO,iBAAiB;IACpC;;;;;;;;OAQG;IACH,MAAM,CAAC,8BAA8B,CAAC,EACpC,OAAO,EACP,WAAW,EACX,OAAO,EACP,eAAe,EACf,eAAe,EACf,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,kBAAkB,EACnB,EAAE;QACD,OAAO,EAAE,2BAA2B,CAAC;QACrC,WAAW,EAAE,kBAAkB,CAAC;QAChC,OAAO,EAAE,cAAc,CAAC;QACxB,eAAe,EAAE,sBAAsB,CAAC;QACxC,eAAe,EAAE,MAAM,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,kBAAkB,EAAE,OAAO,CAAC;KAC7B,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"WorkoutSetService.d.ts","sourceRoot":"","sources":["../../../../src/services/workout/Set/WorkoutSetService.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;AAGtF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8CAA8C,CAAC;AACnF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sDAAsD,CAAC;AACnG,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAG7F,OAAO,KAAK,2BAA2B,MAAM,6CAA6C,CAAC;AAE3F,MAAM,CAAC,OAAO,OAAO,iBAAiB;IACpC;;;;;;;;OAQG;IACH,MAAM,CAAC,8BAA8B,CAAC,EACpC,OAAO,EACP,WAAW,EACX,OAAO,EACP,eAAe,EACf,eAAe,EACf,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,kBAAkB,EACnB,EAAE;QACD,OAAO,EAAE,2BAA2B,CAAC;QACrC,WAAW,EAAE,kBAAkB,CAAC;QAChC,OAAO,EAAE,cAAc,CAAC;QACxB,eAAe,EAAE,sBAAsB,CAAC;QACxC,eAAe,EAAE,MAAM,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,kBAAkB,EAAE,OAAO,CAAC;KAC7B,GAAG,IAAI;IA4DR;;;;OAIG;IACH,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO;IAQ5C;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAmEnC;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,wBAAwB;CAuDxC"}
|
|
@@ -23,13 +23,12 @@ export default class WorkoutSetService {
|
|
|
23
23
|
? (exerciseCTO.lastFirstSet ?? undefined)
|
|
24
24
|
: this.findPreviousFirstSet(context, exerciseCTO._id, microcycleIndex);
|
|
25
25
|
// Calculate progressed targets for the first set.
|
|
26
|
-
//
|
|
27
|
-
//
|
|
26
|
+
// Autoregulation/forecasting handles progression from the previous set's data.
|
|
27
|
+
// Calibration is only used when no previous set exists (first microcycle ever).
|
|
28
28
|
const { targetReps: firstSetReps, targetWeight: firstSetWeight } = WorkoutExerciseService.calculateTargetRepsAndWeightForFirstSet({
|
|
29
29
|
exercise: exerciseCTO,
|
|
30
30
|
calibration: bestCalibration,
|
|
31
31
|
equipment: equipmentType,
|
|
32
|
-
microcycleIndex: isDeloadMicrocycle ? microcycleIndex - 1 : microcycleIndex,
|
|
33
32
|
firstMicrocycleRir: context.firstMicrocycleRir,
|
|
34
33
|
previousFirstSet
|
|
35
34
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkoutSetService.js","sourceRoot":"","sources":["../../../../src/services/workout/Set/WorkoutSetService.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,gBAAgB,EAAmB,MAAM,0CAA0C,CAAC;AAC7F,OAAO,2BAA2B,MAAM,iDAAiD,CAAC;AAC1F,OAAO,sBAAsB,MAAM,uCAAuC,CAAC;AAG3E,MAAM,CAAC,OAAO,OAAO,iBAAiB;IACpC;;;;;;;;OAQG;IACH,MAAM,CAAC,8BAA8B,CAAC,EACpC,OAAO,EACP,WAAW,EACX,OAAO,EACP,eAAe,EACf,eAAe,EACf,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,kBAAkB,EAWnB;QACC,MAAM,EAAE,aAAa,EAAE,eAAe,EAAE,GAAG,WAAW,CAAC;QACvD,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CACb,qCAAqC,WAAW,CAAC,GAAG,KAAK,WAAW,CAAC,YAAY,EAAE,CACpF,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAiB,EAAE,CAAC;QAE9B,qEAAqE;QACrE,4FAA4F;QAC5F,MAAM,gBAAgB,GACpB,eAAe,KAAK,CAAC;YACnB,CAAC,CAAC,CAAC,WAAW,CAAC,YAAY,IAAI,SAAS,CAAC;YACzC,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,OAAO,EAAE,WAAW,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;QAE3E,kDAAkD;QAClD
|
|
1
|
+
{"version":3,"file":"WorkoutSetService.js","sourceRoot":"","sources":["../../../../src/services/workout/Set/WorkoutSetService.ts"],"names":[],"mappings":"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"}
|
|
@@ -57,14 +57,13 @@ export default class WorkoutSetService {
|
|
|
57
57
|
: this.findPreviousFirstSet(context, exerciseCTO._id, microcycleIndex);
|
|
58
58
|
|
|
59
59
|
// Calculate progressed targets for the first set.
|
|
60
|
-
//
|
|
61
|
-
//
|
|
60
|
+
// Autoregulation/forecasting handles progression from the previous set's data.
|
|
61
|
+
// Calibration is only used when no previous set exists (first microcycle ever).
|
|
62
62
|
const { targetReps: firstSetReps, targetWeight: firstSetWeight } =
|
|
63
63
|
WorkoutExerciseService.calculateTargetRepsAndWeightForFirstSet({
|
|
64
64
|
exercise: exerciseCTO,
|
|
65
65
|
calibration: bestCalibration,
|
|
66
66
|
equipment: equipmentType,
|
|
67
|
-
microcycleIndex: isDeloadMicrocycle ? microcycleIndex - 1 : microcycleIndex,
|
|
68
67
|
firstMicrocycleRir: context.firstMicrocycleRir,
|
|
69
68
|
previousFirstSet
|
|
70
69
|
});
|
package/package.json
CHANGED