@aneuhold/core-ts-db-lib 4.0.4 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/lib/browser.d.ts +36 -4
  3. package/lib/browser.d.ts.map +1 -1
  4. package/lib/browser.js +23 -2
  5. package/lib/browser.js.map +1 -1
  6. package/lib/browser.ts +126 -4
  7. package/lib/documents/BaseDocument.d.ts +8 -0
  8. package/lib/documents/BaseDocument.d.ts.map +1 -1
  9. package/lib/documents/BaseDocument.js +10 -0
  10. package/lib/documents/BaseDocument.js.map +1 -1
  11. package/lib/documents/BaseDocument.ts +18 -0
  12. package/lib/documents/common/User.d.ts +1 -0
  13. package/lib/documents/common/User.d.ts.map +1 -1
  14. package/lib/documents/common/User.js +4 -2
  15. package/lib/documents/common/User.js.map +1 -1
  16. package/lib/documents/common/User.ts +4 -2
  17. package/lib/documents/dashboard/NonogramKatanaItem.d.ts +1 -1
  18. package/lib/documents/dashboard/NonogramKatanaItem.js +1 -1
  19. package/lib/documents/dashboard/NonogramKatanaItem.js.map +1 -1
  20. package/lib/documents/dashboard/NonogramKatanaItem.ts +1 -1
  21. package/lib/documents/dashboard/NonogramKatanaUpgrade.d.ts +1 -1
  22. package/lib/documents/dashboard/NonogramKatanaUpgrade.js +1 -1
  23. package/lib/documents/dashboard/NonogramKatanaUpgrade.js.map +1 -1
  24. package/lib/documents/dashboard/NonogramKatanaUpgrade.ts +1 -1
  25. package/lib/documents/workout/README.md +557 -0
  26. package/lib/documents/workout/WorkoutEquipmentType.d.ts +22 -0
  27. package/lib/documents/workout/WorkoutEquipmentType.d.ts.map +1 -0
  28. package/lib/documents/workout/WorkoutEquipmentType.js +31 -0
  29. package/lib/documents/workout/WorkoutEquipmentType.js.map +1 -0
  30. package/lib/documents/workout/WorkoutEquipmentType.ts +40 -0
  31. package/lib/documents/workout/WorkoutExercise.d.ts +82 -0
  32. package/lib/documents/workout/WorkoutExercise.d.ts.map +1 -0
  33. package/lib/documents/workout/WorkoutExercise.js +124 -0
  34. package/lib/documents/workout/WorkoutExercise.js.map +1 -0
  35. package/lib/documents/workout/WorkoutExercise.ts +143 -0
  36. package/lib/documents/workout/WorkoutExerciseCalibration.d.ts +43 -0
  37. package/lib/documents/workout/WorkoutExerciseCalibration.d.ts.map +1 -0
  38. package/lib/documents/workout/WorkoutExerciseCalibration.js +45 -0
  39. package/lib/documents/workout/WorkoutExerciseCalibration.js.map +1 -0
  40. package/lib/documents/workout/WorkoutExerciseCalibration.ts +74 -0
  41. package/lib/documents/workout/WorkoutMesocycle.d.ts +49 -0
  42. package/lib/documents/workout/WorkoutMesocycle.d.ts.map +1 -0
  43. package/lib/documents/workout/WorkoutMesocycle.js +84 -0
  44. package/lib/documents/workout/WorkoutMesocycle.js.map +1 -0
  45. package/lib/documents/workout/WorkoutMesocycle.ts +102 -0
  46. package/lib/documents/workout/WorkoutMicrocycle.d.ts +27 -0
  47. package/lib/documents/workout/WorkoutMicrocycle.d.ts.map +1 -0
  48. package/lib/documents/workout/WorkoutMicrocycle.js +42 -0
  49. package/lib/documents/workout/WorkoutMicrocycle.js.map +1 -0
  50. package/lib/documents/workout/WorkoutMicrocycle.ts +55 -0
  51. package/lib/documents/workout/WorkoutMuscleGroup.d.ts +22 -0
  52. package/lib/documents/workout/WorkoutMuscleGroup.d.ts.map +1 -0
  53. package/lib/documents/workout/WorkoutMuscleGroup.js +25 -0
  54. package/lib/documents/workout/WorkoutMuscleGroup.js.map +1 -0
  55. package/lib/documents/workout/WorkoutMuscleGroup.ts +34 -0
  56. package/lib/documents/workout/WorkoutSession.d.ts +39 -0
  57. package/lib/documents/workout/WorkoutSession.d.ts.map +1 -0
  58. package/lib/documents/workout/WorkoutSession.js +66 -0
  59. package/lib/documents/workout/WorkoutSession.js.map +1 -0
  60. package/lib/documents/workout/WorkoutSession.ts +79 -0
  61. package/lib/documents/workout/WorkoutSessionExercise.d.ts +39 -0
  62. package/lib/documents/workout/WorkoutSessionExercise.d.ts.map +1 -0
  63. package/lib/documents/workout/WorkoutSessionExercise.js +66 -0
  64. package/lib/documents/workout/WorkoutSessionExercise.js.map +1 -0
  65. package/lib/documents/workout/WorkoutSessionExercise.ts +79 -0
  66. package/lib/documents/workout/WorkoutSet.d.ts +41 -0
  67. package/lib/documents/workout/WorkoutSet.d.ts.map +1 -0
  68. package/lib/documents/workout/WorkoutSet.js +69 -0
  69. package/lib/documents/workout/WorkoutSet.js.map +1 -0
  70. package/lib/documents/workout/WorkoutSet.ts +90 -0
  71. package/lib/embedded-types/workout/Fatigue.d.ts +16 -0
  72. package/lib/embedded-types/workout/Fatigue.d.ts.map +1 -0
  73. package/lib/embedded-types/workout/Fatigue.js +34 -0
  74. package/lib/embedded-types/workout/Fatigue.js.map +1 -0
  75. package/lib/embedded-types/workout/Fatigue.ts +41 -0
  76. package/lib/embedded-types/workout/Rsm.d.ts +17 -0
  77. package/lib/embedded-types/workout/Rsm.d.ts.map +1 -0
  78. package/lib/embedded-types/workout/Rsm.js +34 -0
  79. package/lib/embedded-types/workout/Rsm.js.map +1 -0
  80. package/lib/embedded-types/workout/Rsm.ts +42 -0
  81. package/lib/services/DocumentService.d.ts +19 -0
  82. package/lib/services/DocumentService.d.ts.map +1 -1
  83. package/lib/services/DocumentService.js.map +1 -1
  84. package/lib/services/DocumentService.ts +20 -0
  85. package/lib/services/workout/EquipmentType/WorkoutEquipmentTypeService.d.ts +35 -0
  86. package/lib/services/workout/EquipmentType/WorkoutEquipmentTypeService.d.ts.map +1 -0
  87. package/lib/services/workout/EquipmentType/WorkoutEquipmentTypeService.js +74 -0
  88. package/lib/services/workout/EquipmentType/WorkoutEquipmentTypeService.js.map +1 -0
  89. package/lib/services/workout/EquipmentType/WorkoutEquipmentTypeService.ts +90 -0
  90. package/lib/services/workout/Exercise/WorkoutExerciseService.d.ts +55 -0
  91. package/lib/services/workout/Exercise/WorkoutExerciseService.d.ts.map +1 -0
  92. package/lib/services/workout/Exercise/WorkoutExerciseService.js +133 -0
  93. package/lib/services/workout/Exercise/WorkoutExerciseService.js.map +1 -0
  94. package/lib/services/workout/Exercise/WorkoutExerciseService.ts +173 -0
  95. package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.d.ts +35 -0
  96. package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.d.ts.map +1 -0
  97. package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.js +42 -0
  98. package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.js.map +1 -0
  99. package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.ts +45 -0
  100. package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.d.ts +90 -0
  101. package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.d.ts.map +1 -0
  102. package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.js +131 -0
  103. package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.js.map +1 -0
  104. package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.ts +159 -0
  105. package/lib/services/workout/Mesocycle/WorkoutMesocycleService.d.ts +52 -0
  106. package/lib/services/workout/Mesocycle/WorkoutMesocycleService.d.ts.map +1 -0
  107. package/lib/services/workout/Mesocycle/WorkoutMesocycleService.js +180 -0
  108. package/lib/services/workout/Mesocycle/WorkoutMesocycleService.js.map +1 -0
  109. package/lib/services/workout/Mesocycle/WorkoutMesocycleService.ts +274 -0
  110. package/lib/services/workout/Microcycle/WorkoutMicrocycleService.d.ts +28 -0
  111. package/lib/services/workout/Microcycle/WorkoutMicrocycleService.d.ts.map +1 -0
  112. package/lib/services/workout/Microcycle/WorkoutMicrocycleService.js +172 -0
  113. package/lib/services/workout/Microcycle/WorkoutMicrocycleService.js.map +1 -0
  114. package/lib/services/workout/Microcycle/WorkoutMicrocycleService.ts +236 -0
  115. package/lib/services/workout/Session/WorkoutSessionService.d.ts +49 -0
  116. package/lib/services/workout/Session/WorkoutSessionService.d.ts.map +1 -0
  117. package/lib/services/workout/Session/WorkoutSessionService.js +95 -0
  118. package/lib/services/workout/Session/WorkoutSessionService.js.map +1 -0
  119. package/lib/services/workout/Session/WorkoutSessionService.ts +136 -0
  120. package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.d.ts +45 -0
  121. package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.d.ts.map +1 -0
  122. package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.js +69 -0
  123. package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.js.map +1 -0
  124. package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.ts +77 -0
  125. package/lib/services/workout/Set/WorkoutSetService.d.ts +36 -0
  126. package/lib/services/workout/Set/WorkoutSetService.d.ts.map +1 -0
  127. package/lib/services/workout/Set/WorkoutSetService.js +90 -0
  128. package/lib/services/workout/Set/WorkoutSetService.js.map +1 -0
  129. package/lib/services/workout/Set/WorkoutSetService.ts +153 -0
  130. package/lib/services/workout/util/SFR/WorkoutSFRService.d.ts +29 -0
  131. package/lib/services/workout/util/SFR/WorkoutSFRService.d.ts.map +1 -0
  132. package/lib/services/workout/util/SFR/WorkoutSFRService.js +50 -0
  133. package/lib/services/workout/util/SFR/WorkoutSFRService.js.map +1 -0
  134. package/lib/services/workout/util/SFR/WorkoutSFRService.ts +61 -0
  135. package/lib/services/workout/util/VolumePlanning/WorkoutVolumePlanningService.d.ts +48 -0
  136. package/lib/services/workout/util/VolumePlanning/WorkoutVolumePlanningService.d.ts.map +1 -0
  137. package/lib/services/workout/util/VolumePlanning/WorkoutVolumePlanningService.js +261 -0
  138. package/lib/services/workout/util/VolumePlanning/WorkoutVolumePlanningService.js.map +1 -0
  139. package/lib/services/workout/util/VolumePlanning/WorkoutVolumePlanningService.ts +339 -0
  140. package/package.json +5 -4
@@ -0,0 +1,50 @@
1
+ /**
2
+ * A service for handling Stimulus to Fatigue Ratio (SFR) calculations.
3
+ *
4
+ * This service works with any object that has RSM and Fatigue data.
5
+ */
6
+ export default class WorkoutSFRService {
7
+ /**
8
+ * Calculates the total Raw Stimulus Magnitude.
9
+ *
10
+ * @param rsm The RSM data.
11
+ */
12
+ static getRsmTotal(rsm) {
13
+ if (!rsm || rsm.mindMuscleConnection == null || rsm.pump == null || rsm.disruption == null) {
14
+ return null;
15
+ }
16
+ return rsm.mindMuscleConnection + rsm.pump + rsm.disruption;
17
+ }
18
+ /**
19
+ * Calculates the total fatigue score.
20
+ *
21
+ * @param fatigue The fatigue data.
22
+ */
23
+ static getFatigueTotal(fatigue) {
24
+ if (!fatigue ||
25
+ fatigue.jointAndTissueDisruption == null ||
26
+ fatigue.perceivedEffort == null ||
27
+ fatigue.unusedMusclePerformance == null) {
28
+ return null;
29
+ }
30
+ return (fatigue.jointAndTissueDisruption + fatigue.perceivedEffort + fatigue.unusedMusclePerformance);
31
+ }
32
+ /**
33
+ * Calculates the Stimulus to Fatigue Ratio (SFR).
34
+ *
35
+ * @param rsm The RSM data.
36
+ * @param fatigue The fatigue data.
37
+ */
38
+ static getSFR(rsm, fatigue) {
39
+ const rsmTotal = this.getRsmTotal(rsm);
40
+ const fatigueTotal = this.getFatigueTotal(fatigue);
41
+ if (rsmTotal === null || fatigueTotal === null) {
42
+ return null;
43
+ }
44
+ if (fatigueTotal === 0) {
45
+ return rsmTotal;
46
+ }
47
+ return rsmTotal / fatigueTotal;
48
+ }
49
+ }
50
+ //# sourceMappingURL=WorkoutSFRService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkoutSFRService.js","sourceRoot":"","sources":["../../../../../src/services/workout/util/SFR/WorkoutSFRService.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,iBAAiB;IACpC;;;;OAIG;IACH,MAAM,CAAC,WAAW,CAAC,GAA2B;QAC5C,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,oBAAoB,IAAI,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,GAAG,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC;YAC3F,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,GAAG,CAAC,oBAAoB,GAAG,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC;IAC9D,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,eAAe,CAAC,OAAmC;QACxD,IACE,CAAC,OAAO;YACR,OAAO,CAAC,wBAAwB,IAAI,IAAI;YACxC,OAAO,CAAC,eAAe,IAAI,IAAI;YAC/B,OAAO,CAAC,uBAAuB,IAAI,IAAI,EACvC,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,CACL,OAAO,CAAC,wBAAwB,GAAG,OAAO,CAAC,eAAe,GAAG,OAAO,CAAC,uBAAuB,CAC7F,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,MAAM,CAAC,GAA2B,EAAE,OAAmC;QAC5E,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACvC,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QAEnD,IAAI,QAAQ,KAAK,IAAI,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;YAC/C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,OAAO,QAAQ,GAAG,YAAY,CAAC;IACjC,CAAC;CACF"}
@@ -0,0 +1,61 @@
1
+ import type { Fatigue } from '../../../../embedded-types/workout/Fatigue.js';
2
+ import type { RSM } from '../../../../embedded-types/workout/Rsm.js';
3
+
4
+ /**
5
+ * A service for handling Stimulus to Fatigue Ratio (SFR) calculations.
6
+ *
7
+ * This service works with any object that has RSM and Fatigue data.
8
+ */
9
+ export default class WorkoutSFRService {
10
+ /**
11
+ * Calculates the total Raw Stimulus Magnitude.
12
+ *
13
+ * @param rsm The RSM data.
14
+ */
15
+ static getRsmTotal(rsm: RSM | null | undefined): number | null {
16
+ if (!rsm || rsm.mindMuscleConnection == null || rsm.pump == null || rsm.disruption == null) {
17
+ return null;
18
+ }
19
+ return rsm.mindMuscleConnection + rsm.pump + rsm.disruption;
20
+ }
21
+
22
+ /**
23
+ * Calculates the total fatigue score.
24
+ *
25
+ * @param fatigue The fatigue data.
26
+ */
27
+ static getFatigueTotal(fatigue: Fatigue | null | undefined): number | null {
28
+ if (
29
+ !fatigue ||
30
+ fatigue.jointAndTissueDisruption == null ||
31
+ fatigue.perceivedEffort == null ||
32
+ fatigue.unusedMusclePerformance == null
33
+ ) {
34
+ return null;
35
+ }
36
+ return (
37
+ fatigue.jointAndTissueDisruption + fatigue.perceivedEffort + fatigue.unusedMusclePerformance
38
+ );
39
+ }
40
+
41
+ /**
42
+ * Calculates the Stimulus to Fatigue Ratio (SFR).
43
+ *
44
+ * @param rsm The RSM data.
45
+ * @param fatigue The fatigue data.
46
+ */
47
+ static getSFR(rsm: RSM | null | undefined, fatigue: Fatigue | null | undefined): number | null {
48
+ const rsmTotal = this.getRsmTotal(rsm);
49
+ const fatigueTotal = this.getFatigueTotal(fatigue);
50
+
51
+ if (rsmTotal === null || fatigueTotal === null) {
52
+ return null;
53
+ }
54
+
55
+ if (fatigueTotal === 0) {
56
+ return rsmTotal;
57
+ }
58
+
59
+ return rsmTotal / fatigueTotal;
60
+ }
61
+ }
@@ -0,0 +1,48 @@
1
+ import type { UUID } from 'crypto';
2
+ import type WorkoutMesocyclePlanContext from '../../Mesocycle/WorkoutMesocyclePlanContext.js';
3
+ /**
4
+ * A service for handling volume planning operations across microcycles.
5
+ *
6
+ * SCOPE: Microcycle-level volume distribution (calculating set counts per exercise)
7
+ *
8
+ * RESPONSIBILITIES:
9
+ * - Calculate set counts for exercises across a microcycle
10
+ * - Apply progressive overload rules (baseline + historical adjustments)
11
+ * - Handle recovery exercise identification
12
+ * - Enforce volume limits (per exercise, per muscle group per session)
13
+ *
14
+ * RELATED SERVICES:
15
+ * - {@link WorkoutMicrocycleService} - Calls this to get set plans before generating sessions
16
+ * - {@link WorkoutSessionService} - Uses the output to generate actual sessions
17
+ * - {@link WorkoutSessionExerciseService} - Used to calculate SFR and recovery recommendations
18
+ */
19
+ export default class WorkoutVolumePlanningService {
20
+ private static readonly MAX_SETS_PER_EXERCISE;
21
+ private static readonly MAX_SETS_PER_MUSCLE_GROUP_PER_SESSION;
22
+ /**
23
+ * Calculates the set plan for an entire microcycle.
24
+ */
25
+ static calculateSetPlanForMicrocycle(context: WorkoutMesocyclePlanContext, microcycleIndex: number, isDeloadMicrocycle: boolean): {
26
+ exerciseIdToSetCount: Map<UUID, number>;
27
+ recoveryExerciseIds: Set<UUID>;
28
+ };
29
+ /**
30
+ * Calculates the set count for each exercise in a particular muscle group for this microcycle.
31
+ *
32
+ * If there is no previous microcycle data for the muscle group, this falls back to
33
+ * the baseline progression rules.
34
+ */
35
+ private static calculateSetCountForEachExerciseInMuscleGroup;
36
+ /**
37
+ * Calculates the default number of sets for an exercise based on microcycle progression.
38
+ *
39
+ * Key rule: set progression is distributed across exercises that share the same primary muscle group
40
+ * for the entire microcycle, regardless of which session those exercises are in.
41
+ *
42
+ * Baseline: 2 sets per exercise in the muscle group.
43
+ * Progression: add 1 total set per microcycle per muscle group (distributed to earlier exercises
44
+ * in the muscle-group-wide ordering).
45
+ */
46
+ private static calculateBaselineSetCount;
47
+ }
48
+ //# sourceMappingURL=WorkoutVolumePlanningService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkoutVolumePlanningService.d.ts","sourceRoot":"","sources":["../../../../../src/services/workout/util/VolumePlanning/WorkoutVolumePlanningService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAGnC,OAAO,KAAK,2BAA2B,MAAM,gDAAgD,CAAC;AAG9F;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,OAAO,OAAO,4BAA4B;IAC/C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,qBAAqB,CAAK;IAClD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,qCAAqC,CAAM;IAEnE;;OAEG;IACH,MAAM,CAAC,6BAA6B,CAClC,OAAO,EAAE,2BAA2B,EACpC,eAAe,EAAE,MAAM,EACvB,kBAAkB,EAAE,OAAO,GAC1B;QAAE,oBAAoB,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAAC,mBAAmB,EAAE,GAAG,CAAC,IAAI,CAAC,CAAA;KAAE;IA4B9E;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,6CAA6C;IAwO5D;;;;;;;;;OASG;IACH,OAAO,CAAC,MAAM,CAAC,yBAAyB;CA6BzC"}
@@ -0,0 +1,261 @@
1
+ import WorkoutSessionExerciseService from '../../SessionExercise/WorkoutSessionExerciseService.js';
2
+ /**
3
+ * A service for handling volume planning operations across microcycles.
4
+ *
5
+ * SCOPE: Microcycle-level volume distribution (calculating set counts per exercise)
6
+ *
7
+ * RESPONSIBILITIES:
8
+ * - Calculate set counts for exercises across a microcycle
9
+ * - Apply progressive overload rules (baseline + historical adjustments)
10
+ * - Handle recovery exercise identification
11
+ * - Enforce volume limits (per exercise, per muscle group per session)
12
+ *
13
+ * RELATED SERVICES:
14
+ * - {@link WorkoutMicrocycleService} - Calls this to get set plans before generating sessions
15
+ * - {@link WorkoutSessionService} - Uses the output to generate actual sessions
16
+ * - {@link WorkoutSessionExerciseService} - Used to calculate SFR and recovery recommendations
17
+ */
18
+ export default class WorkoutVolumePlanningService {
19
+ static MAX_SETS_PER_EXERCISE = 8;
20
+ static MAX_SETS_PER_MUSCLE_GROUP_PER_SESSION = 10;
21
+ /**
22
+ * Calculates the set plan for an entire microcycle.
23
+ */
24
+ static calculateSetPlanForMicrocycle(context, microcycleIndex, isDeloadMicrocycle) {
25
+ if (!context.muscleGroupToExercisePairsMap) {
26
+ throw new Error('WorkoutMesocyclePlanContext.muscleGroupToExercisePairsMap is not initialized. This should be set during mesocycle planning.');
27
+ }
28
+ const exerciseIdToSetCount = new Map();
29
+ const recoveryExerciseIds = new Set();
30
+ context.muscleGroupToExercisePairsMap.values().forEach((muscleGroupExercisePairs) => {
31
+ const result = this.calculateSetCountForEachExerciseInMuscleGroup(context, microcycleIndex, muscleGroupExercisePairs, isDeloadMicrocycle);
32
+ for (const [workoutExerciseId, setCount] of result.exerciseIdToSetCount) {
33
+ exerciseIdToSetCount.set(workoutExerciseId, setCount);
34
+ }
35
+ for (const recoveryExerciseId of result.recoveryExerciseIds) {
36
+ recoveryExerciseIds.add(recoveryExerciseId);
37
+ }
38
+ });
39
+ return { exerciseIdToSetCount, recoveryExerciseIds };
40
+ }
41
+ /**
42
+ * Calculates the set count for each exercise in a particular muscle group for this microcycle.
43
+ *
44
+ * If there is no previous microcycle data for the muscle group, this falls back to
45
+ * the baseline progression rules.
46
+ */
47
+ static calculateSetCountForEachExerciseInMuscleGroup(context, microcycleIndex, muscleGroupExercisePairs, isDeloadMicrocycle) {
48
+ const exerciseIdToSetCount = new Map();
49
+ const recoveryExerciseIds = new Set();
50
+ const sessionIndexToExerciseIds = new Map();
51
+ // 1. Calculate baselines for all exercises in muscle group
52
+ muscleGroupExercisePairs.forEach((pair, index) => {
53
+ const baseline = this.calculateBaselineSetCount(microcycleIndex, muscleGroupExercisePairs.length, index, isDeloadMicrocycle);
54
+ exerciseIdToSetCount.set(pair.exercise._id, Math.min(baseline, this.MAX_SETS_PER_EXERCISE));
55
+ // Build out the map for session indices to the array of exercise IDs as it pertains to this
56
+ // muscle group.
57
+ if (!context.exerciseIdToSessionIndex)
58
+ return;
59
+ const exerciseSessionIndex = context.exerciseIdToSessionIndex.get(pair.exercise._id);
60
+ if (exerciseSessionIndex === undefined)
61
+ return;
62
+ const existingExerciseIdsForSession = sessionIndexToExerciseIds.get(exerciseSessionIndex) || [];
63
+ existingExerciseIdsForSession.push(pair.exercise._id);
64
+ sessionIndexToExerciseIds.set(exerciseSessionIndex, existingExerciseIdsForSession);
65
+ });
66
+ // 2. Resolve historical performance data
67
+ // Return if no previous microcycle
68
+ let previousMicrocycleIndex = microcycleIndex - 1;
69
+ let previousMicrocycle = context.microcyclesInOrder[previousMicrocycleIndex];
70
+ if (!previousMicrocycle)
71
+ return { exerciseIdToSetCount, recoveryExerciseIds };
72
+ // Map previous session exercises
73
+ const exerciseIds = new Set(muscleGroupExercisePairs.map((p) => p.exercise._id));
74
+ const exerciseIdToPrevSessionExercise = new Map();
75
+ const foundExerciseIds = new Set();
76
+ const exercisesThatWerePreviouslyInRecovery = new Set();
77
+ // Loop through each previous microcycle until we find all exercises or run out of microcycles
78
+ while (exerciseIdToPrevSessionExercise.size < exerciseIds.size && previousMicrocycle) {
79
+ // Check if the previous microcycle is complete; if not, we cannot use its data
80
+ const lastSessionId = previousMicrocycle.sessionOrder[previousMicrocycle.sessionOrder.length - 1];
81
+ const microcycleIsComplete = context.sessionMap.get(lastSessionId)?.complete;
82
+ if (!microcycleIsComplete) {
83
+ break;
84
+ }
85
+ // Start with session order
86
+ for (const sessionId of previousMicrocycle.sessionOrder) {
87
+ const session = context.sessionMap.get(sessionId);
88
+ if (!session)
89
+ continue;
90
+ // Get the session exercises for this session
91
+ for (const sessionExerciseId of session.sessionExerciseOrder) {
92
+ const sessionExercise = context.sessionExerciseMap.get(sessionExerciseId);
93
+ // Map if in our muscle group && it isn't a recovery exercise
94
+ if (sessionExercise &&
95
+ exerciseIds.has(sessionExercise.workoutExerciseId) &&
96
+ !foundExerciseIds.has(sessionExercise.workoutExerciseId) &&
97
+ !sessionExercise.isRecoveryExercise) {
98
+ exerciseIdToPrevSessionExercise.set(sessionExercise.workoutExerciseId, sessionExercise);
99
+ foundExerciseIds.add(sessionExercise.workoutExerciseId);
100
+ if (previousMicrocycleIndex < microcycleIndex - 1) {
101
+ exercisesThatWerePreviouslyInRecovery.add(sessionExercise.workoutExerciseId);
102
+ }
103
+ }
104
+ }
105
+ }
106
+ // Move to earlier microcycle
107
+ previousMicrocycleIndex = previousMicrocycleIndex - 1;
108
+ previousMicrocycle = context.microcyclesInOrder[previousMicrocycleIndex];
109
+ }
110
+ if (exerciseIdToPrevSessionExercise.size === 0)
111
+ return { exerciseIdToSetCount, recoveryExerciseIds };
112
+ // Update baseline with historical set counts when available
113
+ muscleGroupExercisePairs.forEach((pair) => {
114
+ const previousSessionExercise = exerciseIdToPrevSessionExercise.get(pair.exercise._id);
115
+ if (previousSessionExercise) {
116
+ exerciseIdToSetCount.set(pair.exercise._id, Math.min(previousSessionExercise.setOrder.length, this.MAX_SETS_PER_EXERCISE));
117
+ }
118
+ });
119
+ /**
120
+ * Determines if the session for the given exercise is already capped for this muscle group.
121
+ */
122
+ function sessionIsCapped(exerciseId) {
123
+ if (!context.exerciseIdToSessionIndex) {
124
+ throw new Error('WorkoutMesocyclePlanContext.exerciseIdToSessionIndex is not initialized. This should be set during mesocycle planning.');
125
+ }
126
+ const sessionIndex = context.exerciseIdToSessionIndex.get(exerciseId);
127
+ if (sessionIndex === undefined)
128
+ return false;
129
+ const exerciseIdsInSession = sessionIndexToExerciseIds.get(sessionIndex);
130
+ if (!exerciseIdsInSession)
131
+ return false;
132
+ let totalSetsInSession = 0;
133
+ exerciseIdsInSession.forEach((id) => {
134
+ // Use the sets from the previous microcycle's session exercise
135
+ totalSetsInSession += exerciseIdToPrevSessionExercise.get(id)?.setOrder.length || 0;
136
+ });
137
+ return (totalSetsInSession >= WorkoutVolumePlanningService.MAX_SETS_PER_MUSCLE_GROUP_PER_SESSION);
138
+ }
139
+ // 3. Determine sets to add and valid candidates
140
+ let totalSetsToAdd = 0;
141
+ const candidates = [];
142
+ muscleGroupExercisePairs.forEach((pair, muscleGroupIndex) => {
143
+ const previousSessionExercise = exerciseIdToPrevSessionExercise.get(pair.exercise._id);
144
+ if (!previousSessionExercise)
145
+ return;
146
+ let recommendation = null;
147
+ if (!exercisesThatWerePreviouslyInRecovery.has(pair.exercise._id)) {
148
+ recommendation =
149
+ WorkoutSessionExerciseService.getRecommendedSetAdditionsOrRecovery(previousSessionExercise);
150
+ }
151
+ else {
152
+ // If previously in recovery, do not recommend adding sets this microcycle. Also, this is
153
+ // the only thing we are overriding. We still want to use the historical data for
154
+ // SFR calculations, even though that one was the one that triggered a recovery session.
155
+ // This should make it so that it is less likely to have sets added to it.
156
+ recommendation = 0;
157
+ }
158
+ if (recommendation === -1) {
159
+ recoveryExerciseIds.add(pair.exercise._id);
160
+ // Cut sets in half (rounded down, minimum 1) for recovery
161
+ const previousSetCount = previousSessionExercise.setOrder.length;
162
+ const recoverySets = Math.max(1, Math.floor(previousSetCount / 2));
163
+ exerciseIdToSetCount.set(pair.exercise._id, recoverySets);
164
+ }
165
+ else if (recommendation != null && recommendation >= 0) {
166
+ totalSetsToAdd += recommendation;
167
+ // Consider as candidate if session is not already capped
168
+ if (previousSessionExercise.setOrder.length < this.MAX_SETS_PER_EXERCISE &&
169
+ !sessionIsCapped(pair.exercise._id)) {
170
+ candidates.push({
171
+ exerciseId: pair.exercise._id,
172
+ // Don't error if SFR is null for now, just treat as very low
173
+ sfr: WorkoutSessionExerciseService.getSFR(previousSessionExercise) ??
174
+ Number.NEGATIVE_INFINITY,
175
+ muscleGroupIndex,
176
+ previousSetCount: previousSessionExercise.setOrder.length
177
+ });
178
+ }
179
+ }
180
+ });
181
+ // Return if nothing to add or no candidates
182
+ if (totalSetsToAdd === 0 || candidates.length === 0) {
183
+ return { exerciseIdToSetCount, recoveryExerciseIds };
184
+ }
185
+ // 4. Distribute added sets based on SFR quality
186
+ // Sort by SFR descending, then by muscleGroupIndex ascending (as tie-breaker)
187
+ candidates.sort((candidateA, candidateB) => candidateA.sfr !== candidateB.sfr
188
+ ? candidateB.sfr - candidateA.sfr
189
+ : candidateA.muscleGroupIndex - candidateB.muscleGroupIndex);
190
+ /**
191
+ * Gets the total sets currently planned for a session.
192
+ */
193
+ function getSessionTotal(exerciseId) {
194
+ if (!context.exerciseIdToSessionIndex)
195
+ return 0;
196
+ const sessionIndex = context.exerciseIdToSessionIndex.get(exerciseId);
197
+ if (sessionIndex === undefined)
198
+ return 0;
199
+ const exerciseIdsInSession = sessionIndexToExerciseIds.get(sessionIndex);
200
+ if (!exerciseIdsInSession)
201
+ return 0;
202
+ let total = 0;
203
+ exerciseIdsInSession.forEach((id) => {
204
+ total += exerciseIdToSetCount.get(id) || 0;
205
+ });
206
+ return total;
207
+ }
208
+ /**
209
+ * Attempts to add sets to an exercise, respecting all constraints.
210
+ * Returns the number of sets actually added.
211
+ */
212
+ function addSetsToExercise(exerciseId, setsToAdd) {
213
+ const currentSets = exerciseIdToSetCount.get(exerciseId) || 0;
214
+ const sessionTotal = getSessionTotal(exerciseId);
215
+ const maxDueToExerciseLimit = WorkoutVolumePlanningService.MAX_SETS_PER_EXERCISE - currentSets;
216
+ const maxDueToSessionLimit = WorkoutVolumePlanningService.MAX_SETS_PER_MUSCLE_GROUP_PER_SESSION - sessionTotal;
217
+ // Hard limit of 2 to add to a particular exercise at once
218
+ const maxAddable = Math.min(setsToAdd, maxDueToExerciseLimit, maxDueToSessionLimit, 2);
219
+ if (maxAddable > 0) {
220
+ exerciseIdToSetCount.set(exerciseId, currentSets + maxAddable);
221
+ }
222
+ return maxAddable;
223
+ }
224
+ // Cap the actual sets to add to 3 total
225
+ let setsRemaining = totalSetsToAdd >= 3 ? 3 : totalSetsToAdd;
226
+ for (const candidate of candidates) {
227
+ const added = addSetsToExercise(candidate.exerciseId, setsRemaining);
228
+ setsRemaining -= added;
229
+ if (setsRemaining === 0)
230
+ break;
231
+ }
232
+ return { exerciseIdToSetCount, recoveryExerciseIds };
233
+ }
234
+ /**
235
+ * Calculates the default number of sets for an exercise based on microcycle progression.
236
+ *
237
+ * Key rule: set progression is distributed across exercises that share the same primary muscle group
238
+ * for the entire microcycle, regardless of which session those exercises are in.
239
+ *
240
+ * Baseline: 2 sets per exercise in the muscle group.
241
+ * Progression: add 1 total set per microcycle per muscle group (distributed to earlier exercises
242
+ * in the muscle-group-wide ordering).
243
+ */
244
+ static calculateBaselineSetCount(microcycleIndex, totalExercisesInMuscleGroupForMicrocycle, exerciseIndexInMuscleGroupForMicrocycle, isDeloadMicrocycle) {
245
+ // Deload microcycle: half the sets from the previous microcycle, minimum 1 set.
246
+ if (isDeloadMicrocycle) {
247
+ const baselineSets = this.calculateBaselineSetCount(microcycleIndex - 1, totalExercisesInMuscleGroupForMicrocycle, exerciseIndexInMuscleGroupForMicrocycle, false);
248
+ return Math.max(1, Math.floor(baselineSets / 2));
249
+ }
250
+ // Total sets to distribute for this muscle group in this microcycle.
251
+ // For now, add exactly +1 total set per microcycle per muscle group.
252
+ const totalSets = 2 * totalExercisesInMuscleGroupForMicrocycle + microcycleIndex;
253
+ // Distribute sets evenly, with earlier exercises getting extra sets from the remainder.
254
+ const baseSetsPerExercise = Math.floor(totalSets / totalExercisesInMuscleGroupForMicrocycle);
255
+ const remainder = totalSets % totalExercisesInMuscleGroupForMicrocycle;
256
+ return exerciseIndexInMuscleGroupForMicrocycle < remainder
257
+ ? baseSetsPerExercise + 1
258
+ : baseSetsPerExercise;
259
+ }
260
+ }
261
+ //# sourceMappingURL=WorkoutVolumePlanningService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkoutVolumePlanningService.js","sourceRoot":"","sources":["../../../../../src/services/workout/util/VolumePlanning/WorkoutVolumePlanningService.ts"],"names":[],"mappings":"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"}