@aneuhold/core-ts-db-lib 4.0.3 → 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 (151) hide show
  1. package/CHANGELOG.md +29 -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/dashboard/Task.d.ts +4 -4
  26. package/lib/documents/dashboard/UserConfig.d.ts +4 -4
  27. package/lib/documents/workout/README.md +557 -0
  28. package/lib/documents/workout/WorkoutEquipmentType.d.ts +22 -0
  29. package/lib/documents/workout/WorkoutEquipmentType.d.ts.map +1 -0
  30. package/lib/documents/workout/WorkoutEquipmentType.js +31 -0
  31. package/lib/documents/workout/WorkoutEquipmentType.js.map +1 -0
  32. package/lib/documents/workout/WorkoutEquipmentType.ts +40 -0
  33. package/lib/documents/workout/WorkoutExercise.d.ts +82 -0
  34. package/lib/documents/workout/WorkoutExercise.d.ts.map +1 -0
  35. package/lib/documents/workout/WorkoutExercise.js +124 -0
  36. package/lib/documents/workout/WorkoutExercise.js.map +1 -0
  37. package/lib/documents/workout/WorkoutExercise.ts +143 -0
  38. package/lib/documents/workout/WorkoutExerciseCalibration.d.ts +43 -0
  39. package/lib/documents/workout/WorkoutExerciseCalibration.d.ts.map +1 -0
  40. package/lib/documents/workout/WorkoutExerciseCalibration.js +45 -0
  41. package/lib/documents/workout/WorkoutExerciseCalibration.js.map +1 -0
  42. package/lib/documents/workout/WorkoutExerciseCalibration.ts +74 -0
  43. package/lib/documents/workout/WorkoutMesocycle.d.ts +49 -0
  44. package/lib/documents/workout/WorkoutMesocycle.d.ts.map +1 -0
  45. package/lib/documents/workout/WorkoutMesocycle.js +84 -0
  46. package/lib/documents/workout/WorkoutMesocycle.js.map +1 -0
  47. package/lib/documents/workout/WorkoutMesocycle.ts +102 -0
  48. package/lib/documents/workout/WorkoutMicrocycle.d.ts +27 -0
  49. package/lib/documents/workout/WorkoutMicrocycle.d.ts.map +1 -0
  50. package/lib/documents/workout/WorkoutMicrocycle.js +42 -0
  51. package/lib/documents/workout/WorkoutMicrocycle.js.map +1 -0
  52. package/lib/documents/workout/WorkoutMicrocycle.ts +55 -0
  53. package/lib/documents/workout/WorkoutMuscleGroup.d.ts +22 -0
  54. package/lib/documents/workout/WorkoutMuscleGroup.d.ts.map +1 -0
  55. package/lib/documents/workout/WorkoutMuscleGroup.js +25 -0
  56. package/lib/documents/workout/WorkoutMuscleGroup.js.map +1 -0
  57. package/lib/documents/workout/WorkoutMuscleGroup.ts +34 -0
  58. package/lib/documents/workout/WorkoutSession.d.ts +39 -0
  59. package/lib/documents/workout/WorkoutSession.d.ts.map +1 -0
  60. package/lib/documents/workout/WorkoutSession.js +66 -0
  61. package/lib/documents/workout/WorkoutSession.js.map +1 -0
  62. package/lib/documents/workout/WorkoutSession.ts +79 -0
  63. package/lib/documents/workout/WorkoutSessionExercise.d.ts +39 -0
  64. package/lib/documents/workout/WorkoutSessionExercise.d.ts.map +1 -0
  65. package/lib/documents/workout/WorkoutSessionExercise.js +66 -0
  66. package/lib/documents/workout/WorkoutSessionExercise.js.map +1 -0
  67. package/lib/documents/workout/WorkoutSessionExercise.ts +79 -0
  68. package/lib/documents/workout/WorkoutSet.d.ts +41 -0
  69. package/lib/documents/workout/WorkoutSet.d.ts.map +1 -0
  70. package/lib/documents/workout/WorkoutSet.js +69 -0
  71. package/lib/documents/workout/WorkoutSet.js.map +1 -0
  72. package/lib/documents/workout/WorkoutSet.ts +90 -0
  73. package/lib/embedded-types/dashboard/task/FilterSettings.d.ts +6 -6
  74. package/lib/embedded-types/dashboard/task/FilterSettings.d.ts.map +1 -1
  75. package/lib/embedded-types/dashboard/task/FilterSettings.js +4 -2
  76. package/lib/embedded-types/dashboard/task/FilterSettings.js.map +1 -1
  77. package/lib/embedded-types/dashboard/task/FilterSettings.ts +5 -3
  78. package/lib/embedded-types/dashboard/task/SortSettings.d.ts +6 -6
  79. package/lib/embedded-types/dashboard/task/SortSettings.js +1 -1
  80. package/lib/embedded-types/dashboard/task/SortSettings.js.map +1 -1
  81. package/lib/embedded-types/dashboard/task/SortSettings.ts +1 -1
  82. package/lib/embedded-types/workout/Fatigue.d.ts +16 -0
  83. package/lib/embedded-types/workout/Fatigue.d.ts.map +1 -0
  84. package/lib/embedded-types/workout/Fatigue.js +34 -0
  85. package/lib/embedded-types/workout/Fatigue.js.map +1 -0
  86. package/lib/embedded-types/workout/Fatigue.ts +41 -0
  87. package/lib/embedded-types/workout/Rsm.d.ts +17 -0
  88. package/lib/embedded-types/workout/Rsm.d.ts.map +1 -0
  89. package/lib/embedded-types/workout/Rsm.js +34 -0
  90. package/lib/embedded-types/workout/Rsm.js.map +1 -0
  91. package/lib/embedded-types/workout/Rsm.ts +42 -0
  92. package/lib/services/DocumentService.d.ts +19 -0
  93. package/lib/services/DocumentService.d.ts.map +1 -1
  94. package/lib/services/DocumentService.js.map +1 -1
  95. package/lib/services/DocumentService.ts +20 -0
  96. package/lib/services/workout/EquipmentType/WorkoutEquipmentTypeService.d.ts +35 -0
  97. package/lib/services/workout/EquipmentType/WorkoutEquipmentTypeService.d.ts.map +1 -0
  98. package/lib/services/workout/EquipmentType/WorkoutEquipmentTypeService.js +74 -0
  99. package/lib/services/workout/EquipmentType/WorkoutEquipmentTypeService.js.map +1 -0
  100. package/lib/services/workout/EquipmentType/WorkoutEquipmentTypeService.ts +90 -0
  101. package/lib/services/workout/Exercise/WorkoutExerciseService.d.ts +55 -0
  102. package/lib/services/workout/Exercise/WorkoutExerciseService.d.ts.map +1 -0
  103. package/lib/services/workout/Exercise/WorkoutExerciseService.js +133 -0
  104. package/lib/services/workout/Exercise/WorkoutExerciseService.js.map +1 -0
  105. package/lib/services/workout/Exercise/WorkoutExerciseService.ts +173 -0
  106. package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.d.ts +35 -0
  107. package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.d.ts.map +1 -0
  108. package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.js +42 -0
  109. package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.js.map +1 -0
  110. package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.ts +45 -0
  111. package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.d.ts +90 -0
  112. package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.d.ts.map +1 -0
  113. package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.js +131 -0
  114. package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.js.map +1 -0
  115. package/lib/services/workout/Mesocycle/WorkoutMesocyclePlanContext.ts +159 -0
  116. package/lib/services/workout/Mesocycle/WorkoutMesocycleService.d.ts +52 -0
  117. package/lib/services/workout/Mesocycle/WorkoutMesocycleService.d.ts.map +1 -0
  118. package/lib/services/workout/Mesocycle/WorkoutMesocycleService.js +180 -0
  119. package/lib/services/workout/Mesocycle/WorkoutMesocycleService.js.map +1 -0
  120. package/lib/services/workout/Mesocycle/WorkoutMesocycleService.ts +274 -0
  121. package/lib/services/workout/Microcycle/WorkoutMicrocycleService.d.ts +28 -0
  122. package/lib/services/workout/Microcycle/WorkoutMicrocycleService.d.ts.map +1 -0
  123. package/lib/services/workout/Microcycle/WorkoutMicrocycleService.js +172 -0
  124. package/lib/services/workout/Microcycle/WorkoutMicrocycleService.js.map +1 -0
  125. package/lib/services/workout/Microcycle/WorkoutMicrocycleService.ts +236 -0
  126. package/lib/services/workout/Session/WorkoutSessionService.d.ts +49 -0
  127. package/lib/services/workout/Session/WorkoutSessionService.d.ts.map +1 -0
  128. package/lib/services/workout/Session/WorkoutSessionService.js +95 -0
  129. package/lib/services/workout/Session/WorkoutSessionService.js.map +1 -0
  130. package/lib/services/workout/Session/WorkoutSessionService.ts +136 -0
  131. package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.d.ts +45 -0
  132. package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.d.ts.map +1 -0
  133. package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.js +69 -0
  134. package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.js.map +1 -0
  135. package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.ts +77 -0
  136. package/lib/services/workout/Set/WorkoutSetService.d.ts +36 -0
  137. package/lib/services/workout/Set/WorkoutSetService.d.ts.map +1 -0
  138. package/lib/services/workout/Set/WorkoutSetService.js +90 -0
  139. package/lib/services/workout/Set/WorkoutSetService.js.map +1 -0
  140. package/lib/services/workout/Set/WorkoutSetService.ts +153 -0
  141. package/lib/services/workout/util/SFR/WorkoutSFRService.d.ts +29 -0
  142. package/lib/services/workout/util/SFR/WorkoutSFRService.d.ts.map +1 -0
  143. package/lib/services/workout/util/SFR/WorkoutSFRService.js +50 -0
  144. package/lib/services/workout/util/SFR/WorkoutSFRService.js.map +1 -0
  145. package/lib/services/workout/util/SFR/WorkoutSFRService.ts +61 -0
  146. package/lib/services/workout/util/VolumePlanning/WorkoutVolumePlanningService.d.ts +48 -0
  147. package/lib/services/workout/util/VolumePlanning/WorkoutVolumePlanningService.d.ts.map +1 -0
  148. package/lib/services/workout/util/VolumePlanning/WorkoutVolumePlanningService.js +261 -0
  149. package/lib/services/workout/util/VolumePlanning/WorkoutVolumePlanningService.js.map +1 -0
  150. package/lib/services/workout/util/VolumePlanning/WorkoutVolumePlanningService.ts +339 -0
  151. package/package.json +5 -4
@@ -0,0 +1,173 @@
1
+ import type { WorkoutEquipmentType } from '../../../documents/workout/WorkoutEquipmentType.js';
2
+ import type { WorkoutExercise } from '../../../documents/workout/WorkoutExercise.js';
3
+ import {
4
+ ExerciseProgressionType,
5
+ ExerciseRepRange
6
+ } from '../../../documents/workout/WorkoutExercise.js';
7
+ import type { WorkoutExerciseCalibration } from '../../../documents/workout/WorkoutExerciseCalibration.js';
8
+ import WorkoutEquipmentTypeService from '../EquipmentType/WorkoutEquipmentTypeService.js';
9
+ import WorkoutExerciseCalibrationService from '../ExerciseCalibration/WorkoutExerciseCalibrationService.js';
10
+ import WorkoutSFRService from '../util/SFR/WorkoutSFRService.js';
11
+
12
+ /**
13
+ * A service for handling operations related to {@link WorkoutExercise}s.
14
+ */
15
+ export default class WorkoutExerciseService {
16
+ /**
17
+ * Returns the numeric rep range based on the ExerciseRepRange enum.
18
+ *
19
+ * - Heavy: { min: 5, max: 15 }
20
+ * - Medium: { min: 10, max: 20 }
21
+ * - Light: { min: 15, max: 30 }
22
+ *
23
+ * @param repRange The exercise rep range.
24
+ */
25
+ static getRepRangeValues(repRange: ExerciseRepRange): { min: number; max: number } {
26
+ switch (repRange) {
27
+ case ExerciseRepRange.Heavy:
28
+ return { min: 5, max: 15 };
29
+ case ExerciseRepRange.Medium:
30
+ return { min: 10, max: 20 };
31
+ case ExerciseRepRange.Light:
32
+ return { min: 15, max: 30 };
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Gets the fatigue score for an exercise.
38
+ *
39
+ * @param exercise The exercise to get the fatigue score for.
40
+ */
41
+ static getFatigueScore(exercise: WorkoutExercise): number {
42
+ return WorkoutSFRService.getFatigueTotal(exercise.initialFatigueGuess) || 0;
43
+ }
44
+
45
+ /**
46
+ * Calculates the progressed target weight and reps for an exercise based on microcycle progression.
47
+ * This returns the target weight and reps for the FIRST set of the exercise in the given microcycle,
48
+ * assuming it is an accumulation phase (i.e., not a deload).
49
+ *
50
+ * This method applies either rep-based or load-based progression depending on the exercise's
51
+ * preferred progression type, then rounds the weight to available equipment options.
52
+ *
53
+ * Rep progression: The weight is calculated based on reps at microcycle 0, and reps increase
54
+ * by 2 per microcycle to reach max reps at the final accumulation microcycle (ideally),
55
+ * or drop back down and increase weight by 2%.
56
+ *
57
+ * Load progression: Increases weight by at least 2% per microcycle.
58
+ * If weight can't be increased, adds 2 reps instead.
59
+ */
60
+ static calculateTargetRepsAndWeightForFirstSet(params: {
61
+ exercise: WorkoutExercise;
62
+ calibration: WorkoutExerciseCalibration;
63
+ equipment: WorkoutEquipmentType;
64
+ microcycleIndex: number;
65
+ firstMicrocycleRir: number;
66
+ }): { targetWeight: number; targetReps: number } {
67
+ const { exercise, calibration, equipment, microcycleIndex, firstMicrocycleRir } = params;
68
+
69
+ // Validate equipment has weight options
70
+ if (!equipment.weightOptions || equipment.weightOptions.length === 0) {
71
+ throw new Error(
72
+ `No weight options defined for equipment type ${equipment._id}, ${equipment.title}`
73
+ );
74
+ }
75
+
76
+ // Get rep range for this exercise
77
+ const repRange = this.getRepRangeValues(exercise.repRange);
78
+ const repRangeMidpoint = Math.floor((repRange.min + repRange.max) / 2);
79
+
80
+ // For rep progression, calculate weight based on reps at microcycle 0
81
+ // For load progression, use max reps
82
+ let baseRepsForWeight: number;
83
+ if (exercise.preferredProgressionType === ExerciseProgressionType.Rep) {
84
+ baseRepsForWeight = repRangeMidpoint + firstMicrocycleRir;
85
+ } else {
86
+ // Load progression uses max reps for initial weight calculation
87
+ baseRepsForWeight = repRange.max;
88
+ }
89
+
90
+ // Calculate base weight
91
+ let targetWeight = WorkoutExerciseCalibrationService.getTargetWeight(
92
+ calibration,
93
+ baseRepsForWeight
94
+ );
95
+
96
+ // Round to nearest available weight, preferring lower
97
+ const roundedWeight = WorkoutEquipmentTypeService.findNearestWeight(
98
+ equipment,
99
+ targetWeight,
100
+ 'prefer-down'
101
+ );
102
+ if (roundedWeight === null) {
103
+ throw new Error(
104
+ `No available weight options found for equipment type ${equipment._id}, ${equipment.title}`
105
+ );
106
+ }
107
+ targetWeight = roundedWeight;
108
+
109
+ // Calculate target reps based on progression type
110
+ let targetReps: number;
111
+ if (exercise.preferredProgressionType === ExerciseProgressionType.Rep) {
112
+ // Rep progression: Add up to max reps, then loop back if needed
113
+ let currentMicrocycleIndex = 0;
114
+ targetReps = repRangeMidpoint;
115
+
116
+ while (currentMicrocycleIndex < microcycleIndex) {
117
+ targetReps += 2;
118
+ if (targetReps > repRange.max) {
119
+ // Different reset amounts based on the rep range
120
+ switch (exercise.repRange) {
121
+ case ExerciseRepRange.Heavy:
122
+ targetReps = targetReps - 4;
123
+ break;
124
+ case ExerciseRepRange.Medium:
125
+ targetReps = targetReps - 6;
126
+ break;
127
+ case ExerciseRepRange.Light:
128
+ targetReps = targetReps - 8;
129
+ break;
130
+ }
131
+ const nextWeight = this.findNextTwoPercentWeight(targetWeight, equipment);
132
+ if (nextWeight !== null) {
133
+ targetWeight = nextWeight;
134
+ }
135
+ }
136
+ currentMicrocycleIndex++;
137
+ }
138
+ } else {
139
+ // Load progression: Start at max reps
140
+ targetReps = repRange.max;
141
+ }
142
+
143
+ // Apply load progression if applicable for the weight
144
+ if (exercise.preferredProgressionType === ExerciseProgressionType.Load && microcycleIndex > 0) {
145
+ const nextWeight = this.findNextTwoPercentWeight(targetWeight, equipment);
146
+ if (nextWeight !== null) {
147
+ targetWeight = nextWeight;
148
+ } else {
149
+ // Increase reps if we can't increase weight
150
+ targetReps = targetReps + 2;
151
+ }
152
+ }
153
+
154
+ return { targetWeight, targetReps };
155
+ }
156
+
157
+ private static findNextTwoPercentWeight(
158
+ currentWeight: number,
159
+ equipment: WorkoutEquipmentType
160
+ ): number | null {
161
+ // Increase weight by at least 2%
162
+ const twoPercentIncrease = currentWeight * 1.02;
163
+
164
+ // Find the smallest weight >= 2% increase (This is purposefully done from the rounded weight
165
+ // because the rounded weight will be what the user would have actually lifted previously)
166
+ const nextWeight = WorkoutEquipmentTypeService.findNearestWeight(
167
+ equipment,
168
+ twoPercentIncrease,
169
+ 'up'
170
+ );
171
+ return nextWeight;
172
+ }
173
+ }
@@ -0,0 +1,35 @@
1
+ import type { WorkoutExerciseCalibration } from '../../../documents/workout/WorkoutExerciseCalibration.js';
2
+ /**
3
+ * A service for handling operations related to {@link WorkoutExerciseCalibration}s.
4
+ */
5
+ export default class WorkoutExerciseCalibrationService {
6
+ /**
7
+ * Calculates the 1 Rep Max using the NASM formula.
8
+ *
9
+ * Formula: (Weight Lifted × Reps / 30.48) + Weight Lifted
10
+ *
11
+ * @param calibration The workout exercise calibration.
12
+ */
13
+ static get1RM(calibration: WorkoutExerciseCalibration): number;
14
+ /**
15
+ * Calculates the target weight for a set based on target reps and 1RM.
16
+ *
17
+ * Returns the calculated weight without rounding. Consumer can use
18
+ * WorkoutEquipmentTypeService.findNearestWeight() to round if needed.
19
+ *
20
+ * @param calibration The workout exercise calibration.
21
+ * @param targetReps The target number of reps.
22
+ */
23
+ static getTargetWeight(calibration: WorkoutExerciseCalibration, targetReps: number): number;
24
+ /**
25
+ * Calculates the target percentage of 1RM for a given target rep count.
26
+ *
27
+ * Uses the formula: targetPercentage = 30 + ((targetReps - 5) * 2.2)
28
+ *
29
+ * This ensures training stays within the 30%-85% 1RM range (30 reps to 5 reps).
30
+ *
31
+ * @param targetReps The target number of reps.
32
+ */
33
+ private static getTargetPercentage;
34
+ }
35
+ //# sourceMappingURL=WorkoutExerciseCalibrationService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkoutExerciseCalibrationService.d.ts","sourceRoot":"","sources":["../../../../src/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,0DAA0D,CAAC;AAE3G;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,iCAAiC;IACpD;;;;;;OAMG;IACH,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,0BAA0B,GAAG,MAAM;IAI9D;;;;;;;;OAQG;IACH,MAAM,CAAC,eAAe,CAAC,WAAW,EAAE,0BAA0B,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM;IAM3F;;;;;;;;OAQG;IACH,OAAO,CAAC,MAAM,CAAC,mBAAmB;CAGnC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * A service for handling operations related to {@link WorkoutExerciseCalibration}s.
3
+ */
4
+ export default class WorkoutExerciseCalibrationService {
5
+ /**
6
+ * Calculates the 1 Rep Max using the NASM formula.
7
+ *
8
+ * Formula: (Weight Lifted × Reps / 30.48) + Weight Lifted
9
+ *
10
+ * @param calibration The workout exercise calibration.
11
+ */
12
+ static get1RM(calibration) {
13
+ return (calibration.weight * calibration.reps) / 30.48 + calibration.weight;
14
+ }
15
+ /**
16
+ * Calculates the target weight for a set based on target reps and 1RM.
17
+ *
18
+ * Returns the calculated weight without rounding. Consumer can use
19
+ * WorkoutEquipmentTypeService.findNearestWeight() to round if needed.
20
+ *
21
+ * @param calibration The workout exercise calibration.
22
+ * @param targetReps The target number of reps.
23
+ */
24
+ static getTargetWeight(calibration, targetReps) {
25
+ const oneRepMax = this.get1RM(calibration);
26
+ const targetPercentage = this.getTargetPercentage(targetReps);
27
+ return (targetPercentage / 100) * oneRepMax;
28
+ }
29
+ /**
30
+ * Calculates the target percentage of 1RM for a given target rep count.
31
+ *
32
+ * Uses the formula: targetPercentage = 30 + ((targetReps - 5) * 2.2)
33
+ *
34
+ * This ensures training stays within the 30%-85% 1RM range (30 reps to 5 reps).
35
+ *
36
+ * @param targetReps The target number of reps.
37
+ */
38
+ static getTargetPercentage(targetReps) {
39
+ return 30 + (targetReps - 5) * 2.2;
40
+ }
41
+ }
42
+ //# sourceMappingURL=WorkoutExerciseCalibrationService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkoutExerciseCalibrationService.js","sourceRoot":"","sources":["../../../../src/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,iCAAiC;IACpD;;;;;;OAMG;IACH,MAAM,CAAC,MAAM,CAAC,WAAuC;QACnD,OAAO,CAAC,WAAW,CAAC,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC;IAC9E,CAAC;IAED;;;;;;;;OAQG;IACH,MAAM,CAAC,eAAe,CAAC,WAAuC,EAAE,UAAkB;QAChF,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,gBAAgB,GAAG,IAAI,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC;QAC9D,OAAO,CAAC,gBAAgB,GAAG,GAAG,CAAC,GAAG,SAAS,CAAC;IAC9C,CAAC;IAED;;;;;;;;OAQG;IACK,MAAM,CAAC,mBAAmB,CAAC,UAAkB;QACnD,OAAO,EAAE,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;IACrC,CAAC;CACF"}
@@ -0,0 +1,45 @@
1
+ import type { WorkoutExerciseCalibration } from '../../../documents/workout/WorkoutExerciseCalibration.js';
2
+
3
+ /**
4
+ * A service for handling operations related to {@link WorkoutExerciseCalibration}s.
5
+ */
6
+ export default class WorkoutExerciseCalibrationService {
7
+ /**
8
+ * Calculates the 1 Rep Max using the NASM formula.
9
+ *
10
+ * Formula: (Weight Lifted × Reps / 30.48) + Weight Lifted
11
+ *
12
+ * @param calibration The workout exercise calibration.
13
+ */
14
+ static get1RM(calibration: WorkoutExerciseCalibration): number {
15
+ return (calibration.weight * calibration.reps) / 30.48 + calibration.weight;
16
+ }
17
+
18
+ /**
19
+ * Calculates the target weight for a set based on target reps and 1RM.
20
+ *
21
+ * Returns the calculated weight without rounding. Consumer can use
22
+ * WorkoutEquipmentTypeService.findNearestWeight() to round if needed.
23
+ *
24
+ * @param calibration The workout exercise calibration.
25
+ * @param targetReps The target number of reps.
26
+ */
27
+ static getTargetWeight(calibration: WorkoutExerciseCalibration, targetReps: number): number {
28
+ const oneRepMax = this.get1RM(calibration);
29
+ const targetPercentage = this.getTargetPercentage(targetReps);
30
+ return (targetPercentage / 100) * oneRepMax;
31
+ }
32
+
33
+ /**
34
+ * Calculates the target percentage of 1RM for a given target rep count.
35
+ *
36
+ * Uses the formula: targetPercentage = 30 + ((targetReps - 5) * 2.2)
37
+ *
38
+ * This ensures training stays within the 30%-85% 1RM range (30 reps to 5 reps).
39
+ *
40
+ * @param targetReps The target number of reps.
41
+ */
42
+ private static getTargetPercentage(targetReps: number): number {
43
+ return 30 + (targetReps - 5) * 2.2;
44
+ }
45
+ }
@@ -0,0 +1,90 @@
1
+ import type { UUID } from 'crypto';
2
+ import type { WorkoutEquipmentType } from '../../../documents/workout/WorkoutEquipmentType.js';
3
+ import type { WorkoutExercise } from '../../../documents/workout/WorkoutExercise.js';
4
+ import type { CalibrationExercisePair, WorkoutExerciseCalibration } from '../../../documents/workout/WorkoutExerciseCalibration.js';
5
+ import type { WorkoutMesocycle } from '../../../documents/workout/WorkoutMesocycle.js';
6
+ import type { WorkoutMicrocycle } from '../../../documents/workout/WorkoutMicrocycle.js';
7
+ import type { WorkoutSession } from '../../../documents/workout/WorkoutSession.js';
8
+ import type { WorkoutSessionExercise } from '../../../documents/workout/WorkoutSessionExercise.js';
9
+ import type { WorkoutSet } from '../../../documents/workout/WorkoutSet.js';
10
+ /**
11
+ * Central shared context for generating or updating a {@link WorkoutMesocycle}.
12
+ *
13
+ * This keeps the generation pipeline (Mesocycle -> Microcycle -> Session -> Set) from needing to
14
+ * thread the same inputs (mesocycle config + document lookups + optional historical docs) through
15
+ * every method.
16
+ */
17
+ export default class WorkoutMesocyclePlanContext {
18
+ mesocycle: WorkoutMesocycle;
19
+ existingMicrocycles: WorkoutMicrocycle[];
20
+ existingSessions: WorkoutSession[];
21
+ existingSessionExercises: WorkoutSessionExercise[];
22
+ existingSets: WorkoutSet[];
23
+ /**
24
+ * A constant for now that defines what the target RIR is for the first microcycle of every mesocycle,
25
+ * regardless of anything else.
26
+ */
27
+ readonly FIRST_MICROCYCLE_RIR = 4;
28
+ readonly calibrationMap: Map<UUID, WorkoutExerciseCalibration>;
29
+ readonly exerciseMap: Map<UUID, WorkoutExercise>;
30
+ readonly equipmentMap: Map<UUID, WorkoutEquipmentType>;
31
+ readonly sessionMap: Map<UUID, WorkoutSession>;
32
+ readonly sessionExerciseMap: Map<UUID, WorkoutSessionExercise>;
33
+ readonly microcyclesToCreate: WorkoutMicrocycle[];
34
+ /**
35
+ * All microcycles for this mesocycle in chronological order.
36
+ *
37
+ * This includes any existing microcycles (filtered to the target mesocycle) and
38
+ * all newly generated microcycles.
39
+ */
40
+ readonly microcyclesInOrder: WorkoutMicrocycle[];
41
+ readonly sessionsToCreate: WorkoutSession[];
42
+ readonly sessionExercisesToCreate: WorkoutSessionExercise[];
43
+ readonly setsToCreate: WorkoutSet[];
44
+ /**
45
+ * The array of sessions corresponding to the array of calibration exercise pairs, in order,
46
+ * for that session.
47
+ */
48
+ plannedSessionExercisePairs: CalibrationExercisePair[][] | undefined;
49
+ /**
50
+ * Stores the mesocycle's muscle-group-wide exercise ordering.
51
+ *
52
+ * This is used by session generation to distribute set progression evenly across
53
+ * exercises that share a primary muscle group, regardless of which session they
54
+ * ended up in.
55
+ */
56
+ muscleGroupToExercisePairsMap: Map<UUID, CalibrationExercisePair[]> | undefined;
57
+ exerciseIdToSessionIndex: Map<UUID, number> | undefined;
58
+ /**
59
+ * Creates a new workout mesocycle planning context.
60
+ */
61
+ constructor(mesocycle: WorkoutMesocycle, calibrations: WorkoutExerciseCalibration[], exercises: WorkoutExercise[], equipmentTypes: WorkoutEquipmentType[], existingMicrocycles?: WorkoutMicrocycle[], existingSessions?: WorkoutSession[], existingSessionExercises?: WorkoutSessionExercise[], existingSets?: WorkoutSet[]);
62
+ /**
63
+ * Adds a microcycle to the list of microcycles to create and the overall chronological list.
64
+ */
65
+ addMicrocycle(toCreate: WorkoutMicrocycle): void;
66
+ /**
67
+ * Adds a session to the context and updates internal maps.
68
+ */
69
+ addSession(session: WorkoutSession): void;
70
+ /**
71
+ * Adds a session exercise to the context and updates internal maps.
72
+ */
73
+ addSessionExercise(sessionExercise: WorkoutSessionExercise): void;
74
+ /**
75
+ * Stores the planned session -> exercises structure for the mesocycle and derives
76
+ * the muscle-group-wide ordering used for set progression.
77
+ */
78
+ setPlannedSessionExercisePairs(plannedSessionExercisePairs: CalibrationExercisePair[][]): void;
79
+ /**
80
+ * Builds and stores a map of primary muscle group -> ordered exercise pairs for the mesocycle plan.
81
+ *
82
+ * Also builds a map of exercise ID -> session index for use during session generation.
83
+ *
84
+ * The ordering is determined by flattening the planned sessions in order, then the exercises within
85
+ * each session in order. This allows set progression to be distributed evenly across a muscle group
86
+ * for the entire microcycle, even when exercises are split across sessions.
87
+ */
88
+ private buildSessionPairsMaps;
89
+ }
90
+ //# sourceMappingURL=WorkoutMesocyclePlanContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkoutMesocyclePlanContext.d.ts","sourceRoot":"","sources":["../../../../src/services/workout/Mesocycle/WorkoutMesocyclePlanContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oDAAoD,CAAC;AAC/F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+CAA+C,CAAC;AACrF,OAAO,KAAK,EACV,uBAAuB,EACvB,0BAA0B,EAC3B,MAAM,0DAA0D,CAAC;AAClE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gDAAgD,CAAC;AACvF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iDAAiD,CAAC;AACzF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8CAA8C,CAAC;AACnF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sDAAsD,CAAC;AACnG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAE3E;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,OAAO,2BAA2B;IA4CrC,SAAS,EAAE,gBAAgB;IAI3B,mBAAmB,EAAE,iBAAiB,EAAE;IACxC,gBAAgB,EAAE,cAAc,EAAE;IAClC,wBAAwB,EAAE,sBAAsB,EAAE;IAClD,YAAY,EAAE,UAAU,EAAE;IAlDnC;;;OAGG;IACH,SAAgB,oBAAoB,KAAK;IAEzC,SAAgB,cAAc,EAAE,GAAG,CAAC,IAAI,EAAE,0BAA0B,CAAC,CAAC;IACtE,SAAgB,WAAW,EAAE,GAAG,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IACxD,SAAgB,YAAY,EAAE,GAAG,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;IAC9D,SAAgB,UAAU,EAAE,GAAG,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IACtD,SAAgB,kBAAkB,EAAE,GAAG,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC;IAEtE,SAAgB,mBAAmB,EAAE,iBAAiB,EAAE,CAAM;IAC9D;;;;;OAKG;IACH,SAAgB,kBAAkB,EAAE,iBAAiB,EAAE,CAAM;IAC7D,SAAgB,gBAAgB,EAAE,cAAc,EAAE,CAAM;IACxD,SAAgB,wBAAwB,EAAE,sBAAsB,EAAE,CAAM;IACxE,SAAgB,YAAY,EAAE,UAAU,EAAE,CAAM;IAEhD;;;OAGG;IACI,2BAA2B,EAAE,uBAAuB,EAAE,EAAE,GAAG,SAAS,CAAC;IAC5E;;;;;;OAMG;IACI,6BAA6B,EAAE,GAAG,CAAC,IAAI,EAAE,uBAAuB,EAAE,CAAC,GAAG,SAAS,CAAC;IAChF,wBAAwB,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IAE/D;;OAEG;gBAEM,SAAS,EAAE,gBAAgB,EAClC,YAAY,EAAE,0BAA0B,EAAE,EAC1C,SAAS,EAAE,eAAe,EAAE,EAC5B,cAAc,EAAE,oBAAoB,EAAE,EAC/B,mBAAmB,GAAE,iBAAiB,EAAO,EAC7C,gBAAgB,GAAE,cAAc,EAAO,EACvC,wBAAwB,GAAE,sBAAsB,EAAO,EACvD,YAAY,GAAE,UAAU,EAAO;IAcxC;;OAEG;IACI,aAAa,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI;IAKvD;;OAEG;IACI,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAKhD;;OAEG;IACI,kBAAkB,CAAC,eAAe,EAAE,sBAAsB,GAAG,IAAI;IAKxE;;;OAGG;IACI,8BAA8B,CACnC,2BAA2B,EAAE,uBAAuB,EAAE,EAAE,GACvD,IAAI;IAKP;;;;;;;;OAQG;IACH,OAAO,CAAC,qBAAqB;CA6B9B"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Central shared context for generating or updating a {@link WorkoutMesocycle}.
3
+ *
4
+ * This keeps the generation pipeline (Mesocycle -> Microcycle -> Session -> Set) from needing to
5
+ * thread the same inputs (mesocycle config + document lookups + optional historical docs) through
6
+ * every method.
7
+ */
8
+ export default class WorkoutMesocyclePlanContext {
9
+ mesocycle;
10
+ existingMicrocycles;
11
+ existingSessions;
12
+ existingSessionExercises;
13
+ existingSets;
14
+ /**
15
+ * A constant for now that defines what the target RIR is for the first microcycle of every mesocycle,
16
+ * regardless of anything else.
17
+ */
18
+ FIRST_MICROCYCLE_RIR = 4;
19
+ calibrationMap;
20
+ exerciseMap;
21
+ equipmentMap;
22
+ sessionMap;
23
+ sessionExerciseMap;
24
+ microcyclesToCreate = [];
25
+ /**
26
+ * All microcycles for this mesocycle in chronological order.
27
+ *
28
+ * This includes any existing microcycles (filtered to the target mesocycle) and
29
+ * all newly generated microcycles.
30
+ */
31
+ microcyclesInOrder = [];
32
+ sessionsToCreate = [];
33
+ sessionExercisesToCreate = [];
34
+ setsToCreate = [];
35
+ /**
36
+ * The array of sessions corresponding to the array of calibration exercise pairs, in order,
37
+ * for that session.
38
+ */
39
+ plannedSessionExercisePairs;
40
+ /**
41
+ * Stores the mesocycle's muscle-group-wide exercise ordering.
42
+ *
43
+ * This is used by session generation to distribute set progression evenly across
44
+ * exercises that share a primary muscle group, regardless of which session they
45
+ * ended up in.
46
+ */
47
+ muscleGroupToExercisePairsMap;
48
+ exerciseIdToSessionIndex;
49
+ /**
50
+ * Creates a new workout mesocycle planning context.
51
+ */
52
+ constructor(mesocycle, calibrations, exercises, equipmentTypes, existingMicrocycles = [], existingSessions = [], existingSessionExercises = [], existingSets = []) {
53
+ this.mesocycle = mesocycle;
54
+ this.existingMicrocycles = existingMicrocycles;
55
+ this.existingSessions = existingSessions;
56
+ this.existingSessionExercises = existingSessionExercises;
57
+ this.existingSets = existingSets;
58
+ this.calibrationMap = new Map(calibrations.map((c) => [c._id, c]));
59
+ this.exerciseMap = new Map(exercises.map((e) => [e._id, e]));
60
+ this.equipmentMap = new Map(equipmentTypes.map((et) => [et._id, et]));
61
+ this.sessionMap = new Map(existingSessions.map((s) => [s._id, s]));
62
+ this.sessionExerciseMap = new Map(existingSessionExercises.map((s) => [s._id, s]));
63
+ const existingMicrocyclesForMesocycle = existingMicrocycles
64
+ .filter((m) => m.workoutMesocycleId === mesocycle._id)
65
+ .sort((a, b) => a.startDate.getTime() - b.startDate.getTime());
66
+ this.microcyclesInOrder.push(...existingMicrocyclesForMesocycle);
67
+ }
68
+ /**
69
+ * Adds a microcycle to the list of microcycles to create and the overall chronological list.
70
+ */
71
+ addMicrocycle(toCreate) {
72
+ this.microcyclesToCreate.push(toCreate);
73
+ this.microcyclesInOrder.push(toCreate);
74
+ }
75
+ /**
76
+ * Adds a session to the context and updates internal maps.
77
+ */
78
+ addSession(session) {
79
+ this.sessionsToCreate.push(session);
80
+ this.sessionMap.set(session._id, session);
81
+ }
82
+ /**
83
+ * Adds a session exercise to the context and updates internal maps.
84
+ */
85
+ addSessionExercise(sessionExercise) {
86
+ this.sessionExercisesToCreate.push(sessionExercise);
87
+ this.sessionExerciseMap.set(sessionExercise._id, sessionExercise);
88
+ }
89
+ /**
90
+ * Stores the planned session -> exercises structure for the mesocycle and derives
91
+ * the muscle-group-wide ordering used for set progression.
92
+ */
93
+ setPlannedSessionExercisePairs(plannedSessionExercisePairs) {
94
+ this.plannedSessionExercisePairs = plannedSessionExercisePairs;
95
+ this.buildSessionPairsMaps(plannedSessionExercisePairs);
96
+ }
97
+ /**
98
+ * Builds and stores a map of primary muscle group -> ordered exercise pairs for the mesocycle plan.
99
+ *
100
+ * Also builds a map of exercise ID -> session index for use during session generation.
101
+ *
102
+ * The ordering is determined by flattening the planned sessions in order, then the exercises within
103
+ * each session in order. This allows set progression to be distributed evenly across a muscle group
104
+ * for the entire microcycle, even when exercises are split across sessions.
105
+ */
106
+ buildSessionPairsMaps(sessionsToExercisePairs) {
107
+ const muscleGroupToPairsMap = new Map();
108
+ const exerciseIdToSessionIndex = new Map();
109
+ for (let sessionIndex = 0; sessionIndex < sessionsToExercisePairs.length; sessionIndex++) {
110
+ const sessionExercisePairs = sessionsToExercisePairs[sessionIndex];
111
+ for (const exercisePair of sessionExercisePairs) {
112
+ // Set the session index for this exercise as well
113
+ exerciseIdToSessionIndex.set(exercisePair.exercise._id, sessionIndex);
114
+ const primaryMuscleGroupId = exercisePair.exercise.primaryMuscleGroups[0];
115
+ if (!primaryMuscleGroupId) {
116
+ throw new Error(`Exercise ${exercisePair.exercise._id}, ${exercisePair.exercise.exerciseName} has no primary muscle group`);
117
+ }
118
+ const existing = muscleGroupToPairsMap.get(primaryMuscleGroupId);
119
+ if (existing) {
120
+ existing.push(exercisePair);
121
+ }
122
+ else {
123
+ muscleGroupToPairsMap.set(primaryMuscleGroupId, [exercisePair]);
124
+ }
125
+ }
126
+ }
127
+ this.muscleGroupToExercisePairsMap = muscleGroupToPairsMap;
128
+ this.exerciseIdToSessionIndex = exerciseIdToSessionIndex;
129
+ }
130
+ }
131
+ //# sourceMappingURL=WorkoutMesocyclePlanContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkoutMesocyclePlanContext.js","sourceRoot":"","sources":["../../../../src/services/workout/Mesocycle/WorkoutMesocyclePlanContext.ts"],"names":[],"mappings":"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"}