@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 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 nullable fields guaranteed to be defined.
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 = Required<{
47
- [K in keyof WorkoutSet]: NonNullable<WorkoutSet[K]>;
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;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;KACxC,CAAC,IAAI,MAAM,UAAU,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;CACpD,CAAC,CAAC"}
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 nullable fields guaranteed to be defined.
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 = Required<{
98
- [K in keyof WorkoutSet]: NonNullable<WorkoutSet[K]>;
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 progressed target weight and reps for an exercise based on microcycle progression.
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
- * This method applies either rep-based or load-based progression depending on the exercise's
35
- * preferred progression type, then rounds the weight to available equipment options.
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 a `previousFirstSet` is provided, autoregulation adjusts progression based on the
38
- * surplus between planned and actual performance. Without it, the calibration-based formula
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
- * Checks whether a set has all the data needed for autoregulation calculations.
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 hasCompleteAutoRegulationData;
84
+ private static toCompletedSet;
89
85
  /**
90
- * Calculates targets using the calibration-based formula (original behavior).
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;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,CAAC,uCAAuC,CAAC,MAAM,EAAE;QACrD,QAAQ,EAAE,eAAe,CAAC;QAC1B,WAAW,EAAE,0BAA0B,CAAC;QACxC,SAAS,EAAE,oBAAoB,CAAC;QAChC,eAAe,EAAE,MAAM,CAAC;QACxB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,gBAAgB,CAAC,EAAE,UAAU,CAAC;KAC/B,GAAG;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE;IA2ChD;;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;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,6BAA6B;IAU5C;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,gCAAgC;IAgG/C,OAAO,CAAC,MAAM,CAAC,wBAAwB;CAgBxC"}
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 progressed target weight and reps for an exercise based on microcycle progression.
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
- * This method applies either rep-based or load-based progression depending on the exercise's
43
- * preferred progression type, then rounds the weight to available equipment options.
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 a `previousFirstSet` is provided, autoregulation adjusts progression based on the
46
- * surplus between planned and actual performance. Without it, the calibration-based formula
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, microcycleIndex, firstMicrocycleRir, previousFirstSet } = params;
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
- // If we have a previous set with complete data, use autoregulation
66
- if (previousFirstSet && this.hasCompleteAutoRegulationData(previousFirstSet)) {
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
- * Checks whether a set has all the data needed for autoregulation calculations.
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 hasCompleteAutoRegulationData(set) {
182
- return (set.actualReps != null &&
183
- set.plannedReps != null &&
184
- set.rir != null &&
185
- set.plannedRir != null &&
186
- set.plannedWeight != null);
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 using the calibration-based formula (original behavior).
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, microcycleIndex, firstMicrocycleRir, repRange, repRangeMidpoint } = params;
193
- // For rep progression, calculate weight based on reps at microcycle 0
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
- let baseRepsForWeight;
196
- if (exercise.preferredProgressionType === ExerciseProgressionType.Rep) {
197
- baseRepsForWeight = repRangeMidpoint + firstMicrocycleRir;
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
- let targetWeight = WorkoutExerciseCalibrationService.getTargetWeight(calibration, baseRepsForWeight);
205
- // Round to nearest available weight, preferring lower
206
- const roundedWeight = WorkoutEquipmentTypeService.findNearestWeight(equipment, targetWeight, 'prefer-down');
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
- targetWeight = roundedWeight;
211
- // Calculate target reps based on progression type
212
- let targetReps;
213
- if (exercise.preferredProgressionType === ExerciseProgressionType.Rep) {
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":"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"}
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 progressed target weight and reps for an exercise based on microcycle progression.
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
- * This method applies either rep-based or load-based progression depending on the exercise's
53
- * preferred progression type, then rounds the weight to available equipment options.
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 a `previousFirstSet` is provided, autoregulation adjusts progression based on the
56
- * surplus between planned and actual performance. Without it, the calibration-based formula
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
- // If we have a previous set with complete data, use autoregulation
95
- if (previousFirstSet && this.hasCompleteAutoRegulationData(previousFirstSet)) {
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
- * Checks whether a set has all the data needed for autoregulation calculations.
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 hasCompleteAutoRegulationData(set: WorkoutSet): set is CompletedWorkoutSet {
252
- return (
253
- set.actualReps != null &&
254
- set.plannedReps != null &&
255
- set.rir != null &&
256
- set.plannedRir != null &&
257
- set.plannedWeight != null
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 using the calibration-based formula (original behavior).
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
- exercise,
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 reps at microcycle 0
278
+ // For rep progression, calculate weight based on midpoint + RIR reps
284
279
  // For load progression, use max reps
285
- let baseRepsForWeight: number;
286
- if (exercise.preferredProgressionType === ExerciseProgressionType.Rep) {
287
- baseRepsForWeight = repRangeMidpoint + firstMicrocycleRir;
288
- } else {
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
- let targetWeight = WorkoutExerciseCalibrationService.getTargetWeight(
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
- targetWeight,
292
+ rawWeight,
303
293
  'prefer-down'
304
294
  );
305
- if (roundedWeight === null) {
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
- // Apply load progression if applicable for the weight
347
- if (exercise.preferredProgressionType === ExerciseProgressionType.Load && microcycleIndex > 0) {
348
- const nextWeight = this.findNextTwoPercentWeight(targetWeight, equipment);
349
- if (nextWeight !== null) {
350
- targetWeight = nextWeight;
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;IA6DR;;;;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"}
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
- // For deload microcycles, use the previous microcycle's index so we base
27
- // the deload on the last accumulation weight rather than progressing further.
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":"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"}
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
- // For deload microcycles, use the previous microcycle's index so we base
61
- // the deload on the last accumulation weight rather than progressing further.
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
@@ -2,7 +2,7 @@
2
2
  "name": "@aneuhold/core-ts-db-lib",
3
3
  "author": "Anton G. Neuhold Jr.",
4
4
  "license": "MIT",
5
- "version": "4.1.14",
5
+ "version": "4.1.15",
6
6
  "description": "A core database library used for personal projects",
7
7
  "packageManager": "pnpm@10.25.0",
8
8
  "type": "module",