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

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 (20) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/lib/documents/workout/WorkoutMesocycle.d.ts.map +1 -1
  3. package/lib/documents/workout/WorkoutMesocycle.js +1 -7
  4. package/lib/documents/workout/WorkoutMesocycle.js.map +1 -1
  5. package/lib/documents/workout/WorkoutMesocycle.ts +52 -59
  6. package/lib/services/workout/EquipmentType/WorkoutEquipmentTypeService.d.ts +16 -3
  7. package/lib/services/workout/EquipmentType/WorkoutEquipmentTypeService.d.ts.map +1 -1
  8. package/lib/services/workout/EquipmentType/WorkoutEquipmentTypeService.js +33 -3
  9. package/lib/services/workout/EquipmentType/WorkoutEquipmentTypeService.js.map +1 -1
  10. package/lib/services/workout/EquipmentType/WorkoutEquipmentTypeService.ts +35 -3
  11. package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.d.ts +7 -0
  12. package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.d.ts.map +1 -1
  13. package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.js +10 -1
  14. package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.js.map +1 -1
  15. package/lib/services/workout/ExerciseCalibration/WorkoutExerciseCalibrationService.ts +11 -1
  16. package/lib/services/workout/Microcycle/WorkoutMicrocycleService.d.ts.map +1 -1
  17. package/lib/services/workout/Microcycle/WorkoutMicrocycleService.js +29 -22
  18. package/lib/services/workout/Microcycle/WorkoutMicrocycleService.js.map +1 -1
  19. package/lib/services/workout/Microcycle/WorkoutMicrocycleService.ts +32 -26
  20. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -5,6 +5,27 @@ 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.2] (2026-02-15)
9
+
10
+ ### ✅ Added
11
+
12
+ - Added `generatePlateWeightOptions()` method to `WorkoutEquipmentTypeService` to generate all achievable weight combinations from a bar and plate pairs.
13
+ - Added `get1RMRaw()` static method to `WorkoutExerciseCalibrationService` for calculating 1RM from weight and reps.
14
+
15
+ ### 🏗️ Changed
16
+
17
+ - Refactored `generateSessionsForMicrocycle()` in `WorkoutMicrocycleService` to support creating more sessions than available non-rest days by distributing sessions chronologically across days.
18
+
19
+ ## 🔖 [4.1.1] (2026-02-06)
20
+
21
+ ### 🏗️ Changed
22
+
23
+ - Relaxed validation in `WorkoutMesocycleSchema`: removed minimum length check for `calibratedExercises` array.
24
+
25
+ ### 🩹 Fixed
26
+
27
+ - No other direct code changes; version bump for compatibility with new major versions of dependencies.
28
+
8
29
  ## 🔖 [4.1.0] (2026-02-06)
9
30
 
10
31
  ### ✅ Added
@@ -204,6 +225,8 @@ Updated dependency: now requires `@aneuhold/core-ts-lib@^2.3.11`.
204
225
 
205
226
  <!-- Link References -->
206
227
 
228
+ [4.1.2]: https://github.com/aneuhold/ts-libs/compare/core-ts-db-lib-v4.1.1...core-ts-db-lib-v4.1.2
229
+ [4.1.1]: https://github.com/aneuhold/ts-libs/compare/core-ts-db-lib-v4.1.0...core-ts-db-lib-v4.1.1
207
230
  [4.1.0]: https://github.com/aneuhold/ts-libs/compare/core-ts-db-lib-v4.0.4...core-ts-db-lib-v4.1.0
208
231
  [4.0.4]: https://github.com/aneuhold/ts-libs/compare/core-ts-db-lib-v4.0.3...core-ts-db-lib-v4.0.4
209
232
  [4.0.3]: https://github.com/aneuhold/ts-libs/compare/core-ts-db-lib-v4.0.2...core-ts-db-lib-v4.0.3
@@ -1 +1 @@
1
- {"version":3,"file":"WorkoutMesocycle.d.ts","sourceRoot":"","sources":["../../../src/documents/workout/WorkoutMesocycle.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB;;;;;;;GAOG;AACH,oBAAY,SAAS;IACnB,UAAU,eAAe;IACzB,eAAe,oBAAoB;IACnC,GAAG,QAAQ;IACX,QAAQ,aAAa;CACtB;AAED;;GAEG;AACH,eAAO,MAAM,wBAAwB,qBAAqB,CAAC;AAE3D;;GAEG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;iBA0D/B,CAAC;AAEL;;;;;;;;;GASG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
1
+ {"version":3,"file":"WorkoutMesocycle.d.ts","sourceRoot":"","sources":["../../../src/documents/workout/WorkoutMesocycle.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB;;;;;;;GAOG;AACH,oBAAY,SAAS;IACnB,UAAU,eAAe;IACzB,eAAe,oBAAoB;IACnC,GAAG,QAAQ;IACX,QAAQ,aAAa;CACtB;AAED;;GAEG;AACH,eAAO,MAAM,wBAAwB,qBAAqB,CAAC;AAE3D;;GAEG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;iBAmDjC,CAAC;AAEH;;;;;;;;;GASG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
@@ -23,8 +23,7 @@ export const WorkoutMesocycle_docType = 'workoutMesocycle';
23
23
  /**
24
24
  * The schema for {@link WorkoutMesocycle} documents.
25
25
  */
26
- export const WorkoutMesocycleSchema = z
27
- .object({
26
+ export const WorkoutMesocycleSchema = z.object({
28
27
  ...BaseDocumentWithTypeSchema.shape,
29
28
  ...RequiredUserIdSchema.shape,
30
29
  ...BaseDocumentWithUpdatedAndCreatedDatesSchema.shape,
@@ -75,10 +74,5 @@ export const WorkoutMesocycleSchema = z
75
74
  * mesocycle.
76
75
  */
77
76
  completedDate: z.date().nullish()
78
- })
79
- .refine((data) => data.calibratedExercises.length >= data.plannedSessionCountPerMicrocycle, {
80
- message: 'Number of calibrated exercises must be at least equal to planned sessions per microcycle.' +
81
- ' Create a slight variation of an existing exercise if needed.',
82
- path: ['calibratedExercises']
83
77
  });
84
78
  //# sourceMappingURL=WorkoutMesocycle.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"WorkoutMesocycle.js","sourceRoot":"","sources":["../../../src/documents/workout/WorkoutMesocycle.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,oBAAoB,EAAE,MAAM,+CAA+C,CAAC;AACrF,OAAO,EACL,0BAA0B,EAC1B,4CAA4C,EAC7C,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;GAOG;AACH,MAAM,CAAN,IAAY,SAKX;AALD,WAAY,SAAS;IACnB,sCAAyB,CAAA;IACzB,gDAAmC,CAAA;IACnC,wBAAW,CAAA;IACX,kCAAqB,CAAA;AACvB,CAAC,EALW,SAAS,KAAT,SAAS,QAKpB;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,kBAAkB,CAAC;AAE3D;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC;KACpC,MAAM,CAAC;IACN,GAAG,0BAA0B,CAAC,KAAK;IACnC,GAAG,oBAAoB,CAAC,KAAK;IAC7B,GAAG,4CAA4C,CAAC,KAAK;IACrD,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC,OAAO,CAAC,wBAAwB,CAAC;IAC9E;;OAEG;IACH,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IAC3B;;;;;OAKG;IACH,mBAAmB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAW,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACpF;;OAEG;IACH,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;IAC5B;;OAEG;IACH,gCAAgC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACpD;;;;OAIG;IACH,6BAA6B,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACjD;;;;;OAKG;IACH,yBAAyB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACrE;;;;OAIG;IACH,sBAAsB,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE;IACxD;;;;;;OAMG;IACH,aAAa,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE;CAClC,CAAC;KACD,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,MAAM,IAAI,IAAI,CAAC,gCAAgC,EAAE;IAC1F,OAAO,EACL,2FAA2F;QAC3F,+DAA+D;IACjE,IAAI,EAAE,CAAC,qBAAqB,CAAC;CAC9B,CAAC,CAAC"}
1
+ {"version":3,"file":"WorkoutMesocycle.js","sourceRoot":"","sources":["../../../src/documents/workout/WorkoutMesocycle.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,oBAAoB,EAAE,MAAM,+CAA+C,CAAC;AACrF,OAAO,EACL,0BAA0B,EAC1B,4CAA4C,EAC7C,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;GAOG;AACH,MAAM,CAAN,IAAY,SAKX;AALD,WAAY,SAAS;IACnB,sCAAyB,CAAA;IACzB,gDAAmC,CAAA;IACnC,wBAAW,CAAA;IACX,kCAAqB,CAAA;AACvB,CAAC,EALW,SAAS,KAAT,SAAS,QAKpB;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,kBAAkB,CAAC;AAE3D;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,GAAG,0BAA0B,CAAC,KAAK;IACnC,GAAG,oBAAoB,CAAC,KAAK;IAC7B,GAAG,4CAA4C,CAAC,KAAK;IACrD,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC,OAAO,CAAC,wBAAwB,CAAC;IAC9E;;OAEG;IACH,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IAC3B;;;;;OAKG;IACH,mBAAmB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAW,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACpF;;OAEG;IACH,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;IAC5B;;OAEG;IACH,gCAAgC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACpD;;;;OAIG;IACH,6BAA6B,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACjD;;;;;OAKG;IACH,yBAAyB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACrE;;;;OAIG;IACH,sBAAsB,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE;IACxD;;;;;;OAMG;IACH,aAAa,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE;CAClC,CAAC,CAAC"}
@@ -29,65 +29,58 @@ export const WorkoutMesocycle_docType = 'workoutMesocycle';
29
29
  /**
30
30
  * The schema for {@link WorkoutMesocycle} documents.
31
31
  */
32
- export const WorkoutMesocycleSchema = z
33
- .object({
34
- ...BaseDocumentWithTypeSchema.shape,
35
- ...RequiredUserIdSchema.shape,
36
- ...BaseDocumentWithUpdatedAndCreatedDatesSchema.shape,
37
- docType: z.literal(WorkoutMesocycle_docType).default(WorkoutMesocycle_docType),
38
- /**
39
- * An optional title for this mesocycle.
40
- */
41
- title: z.string().nullish(),
42
- /**
43
- * The IDs of WorkoutExerciseCalibration documents used for this mesocycle.
44
- *
45
- * This locks which calibration was used for a mesocycle so historical 1RM
46
- * values remain accurate even if calibrations are changed later.
47
- */
48
- calibratedExercises: z.array(z.uuidv7().transform((val) => val as UUID)).default([]),
49
- /**
50
- * The type of this mesocycle. See {@link CycleType} for details.
51
- */
52
- cycleType: z.enum(CycleType),
53
- /**
54
- * The planned number of workout sessions per microcycle.
55
- */
56
- plannedSessionCountPerMicrocycle: z.int().positive(),
57
- /**
58
- * The planned length of each microcycle in days.
59
- *
60
- * Typically 7 days (one week), but can vary.
61
- */
62
- plannedMicrocycleLengthInDays: z.int().positive(),
63
- /**
64
- * The planned rest days within each microcycle, represented as day indices.
65
- *
66
- * For example, [0, 3] would indicate rest on the first and fourth days of
67
- * the microcycle.
68
- */
69
- plannedMicrocycleRestDays: z.array(z.int().nonnegative()).default([]),
70
- /**
71
- * The planned total number of microcycles including accumulation and deload.
72
- *
73
- * Should typically be 5-9 microcycles (4-8 accumulation weeks + 1 deload week).
74
- */
75
- plannedMicrocycleCount: z.int().min(2).max(20).nullish(),
76
- /**
77
- * The date this mesocycle was completed.
78
- *
79
- * This should be set after the user gets a "success" completion screen and
80
- * has buttoned up any last prompts. This should guide them into the next
81
- * mesocycle.
82
- */
83
- completedDate: z.date().nullish()
84
- })
85
- .refine((data) => data.calibratedExercises.length >= data.plannedSessionCountPerMicrocycle, {
86
- message:
87
- 'Number of calibrated exercises must be at least equal to planned sessions per microcycle.' +
88
- ' Create a slight variation of an existing exercise if needed.',
89
- path: ['calibratedExercises']
90
- });
32
+ export const WorkoutMesocycleSchema = z.object({
33
+ ...BaseDocumentWithTypeSchema.shape,
34
+ ...RequiredUserIdSchema.shape,
35
+ ...BaseDocumentWithUpdatedAndCreatedDatesSchema.shape,
36
+ docType: z.literal(WorkoutMesocycle_docType).default(WorkoutMesocycle_docType),
37
+ /**
38
+ * An optional title for this mesocycle.
39
+ */
40
+ title: z.string().nullish(),
41
+ /**
42
+ * The IDs of WorkoutExerciseCalibration documents used for this mesocycle.
43
+ *
44
+ * This locks which calibration was used for a mesocycle so historical 1RM
45
+ * values remain accurate even if calibrations are changed later.
46
+ */
47
+ calibratedExercises: z.array(z.uuidv7().transform((val) => val as UUID)).default([]),
48
+ /**
49
+ * The type of this mesocycle. See {@link CycleType} for details.
50
+ */
51
+ cycleType: z.enum(CycleType),
52
+ /**
53
+ * The planned number of workout sessions per microcycle.
54
+ */
55
+ plannedSessionCountPerMicrocycle: z.int().positive(),
56
+ /**
57
+ * The planned length of each microcycle in days.
58
+ *
59
+ * Typically 7 days (one week), but can vary.
60
+ */
61
+ plannedMicrocycleLengthInDays: z.int().positive(),
62
+ /**
63
+ * The planned rest days within each microcycle, represented as day indices.
64
+ *
65
+ * For example, [0, 3] would indicate rest on the first and fourth days of
66
+ * the microcycle.
67
+ */
68
+ plannedMicrocycleRestDays: z.array(z.int().nonnegative()).default([]),
69
+ /**
70
+ * The planned total number of microcycles including accumulation and deload.
71
+ *
72
+ * Should typically be 5-9 microcycles (4-8 accumulation weeks + 1 deload week).
73
+ */
74
+ plannedMicrocycleCount: z.int().min(2).max(20).nullish(),
75
+ /**
76
+ * The date this mesocycle was completed.
77
+ *
78
+ * This should be set after the user gets a "success" completion screen and
79
+ * has buttoned up any last prompts. This should guide them into the next
80
+ * mesocycle.
81
+ */
82
+ completedDate: z.date().nullish()
83
+ });
91
84
 
92
85
  /**
93
86
  * Represents a mesocycle - an organized sequence of microcycles ordered to
@@ -9,14 +9,27 @@ export default class WorkoutEquipmentTypeService {
9
9
  * Starts at minWeight (e.g., the bar weight), increments by increment (e.g., 2.5, 5, 10 lbs),
10
10
  * and continues until maxWeight is reached or exceeded.
11
11
  *
12
- * This may be refactored / maybe a new method will be created in the future to handle a given
13
- * set of weight plates to generate all possible combinations.
14
- *
15
12
  * @param minWeight The minimum weight (e.g., bar weight).
16
13
  * @param increment The weight increment.
17
14
  * @param maxWeight The maximum weight.
18
15
  */
19
16
  static generateWeightOptions(minWeight: number, increment: number, maxWeight: number): number[];
17
+ /**
18
+ * Generates all achievable weights from a bar weight and a set of plate pairs.
19
+ *
20
+ * Each plate entry specifies a plate weight and the number of pairs available.
21
+ * Plates are added in pairs (both sides of the bar), so each plate adds
22
+ * `weight * 2` to the total. All combinations of plates are computed to
23
+ * produce the full set of achievable weights.
24
+ *
25
+ * @param barWeight The weight of the bar alone.
26
+ * @param plates Array of plate entries, each with a `weight` and `pairs` count.
27
+ * @returns Sorted, deduplicated array of all achievable weights.
28
+ */
29
+ static generatePlateWeightOptions(barWeight: number, plates: Array<{
30
+ weight: number;
31
+ pairs: number;
32
+ }>): number[];
20
33
  /**
21
34
  * Finds the nearest available weight from equipmentType.weightOptions.
22
35
  *
@@ -1 +1 @@
1
- {"version":3,"file":"WorkoutEquipmentTypeService.d.ts","sourceRoot":"","sources":["../../../../src/services/workout/EquipmentType/WorkoutEquipmentTypeService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oDAAoD,CAAC;AAE/F;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,2BAA2B;IAC9C;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE;IAY/F;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,iBAAiB,CACtB,aAAa,EAAE,oBAAoB,EACnC,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,GAAG,WAAW,GACjE,MAAM,GAAG,IAAI;CAyCjB"}
1
+ {"version":3,"file":"WorkoutEquipmentTypeService.d.ts","sourceRoot":"","sources":["../../../../src/services/workout/EquipmentType/WorkoutEquipmentTypeService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oDAAoD,CAAC;AAE/F;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,2BAA2B;IAC9C;;;;;;;;;OASG;IACH,MAAM,CAAC,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE;IAY/F;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,0BAA0B,CAC/B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,GAC/C,MAAM,EAAE;IAoBX;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,iBAAiB,CACtB,aAAa,EAAE,oBAAoB,EACnC,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,GAAG,WAAW,GACjE,MAAM,GAAG,IAAI;CAyCjB"}
@@ -8,9 +8,6 @@ export default class WorkoutEquipmentTypeService {
8
8
  * Starts at minWeight (e.g., the bar weight), increments by increment (e.g., 2.5, 5, 10 lbs),
9
9
  * and continues until maxWeight is reached or exceeded.
10
10
  *
11
- * This may be refactored / maybe a new method will be created in the future to handle a given
12
- * set of weight plates to generate all possible combinations.
13
- *
14
11
  * @param minWeight The minimum weight (e.g., bar weight).
15
12
  * @param increment The weight increment.
16
13
  * @param maxWeight The maximum weight.
@@ -24,6 +21,39 @@ export default class WorkoutEquipmentTypeService {
24
21
  }
25
22
  return weights;
26
23
  }
24
+ /**
25
+ * Generates all achievable weights from a bar weight and a set of plate pairs.
26
+ *
27
+ * Each plate entry specifies a plate weight and the number of pairs available.
28
+ * Plates are added in pairs (both sides of the bar), so each plate adds
29
+ * `weight * 2` to the total. All combinations of plates are computed to
30
+ * produce the full set of achievable weights.
31
+ *
32
+ * @param barWeight The weight of the bar alone.
33
+ * @param plates Array of plate entries, each with a `weight` and `pairs` count.
34
+ * @returns Sorted, deduplicated array of all achievable weights.
35
+ */
36
+ static generatePlateWeightOptions(barWeight, plates) {
37
+ let additions = new Set([0]);
38
+ for (const plate of plates) {
39
+ if (plate.weight <= 0 || plate.pairs <= 0)
40
+ continue;
41
+ const expanded = [];
42
+ for (const existing of additions) {
43
+ for (let count = 1; count <= plate.pairs; count++) {
44
+ expanded.push(existing + plate.weight * 2 * count);
45
+ }
46
+ }
47
+ additions = new Set([...additions, ...expanded]);
48
+ if (additions.size > 1000)
49
+ break;
50
+ }
51
+ const weights = [...additions]
52
+ .map((a) => barWeight + a)
53
+ .filter((w) => w >= 0)
54
+ .sort((a, b) => a - b);
55
+ return [...new Set(weights)];
56
+ }
27
57
  /**
28
58
  * Finds the nearest available weight from equipmentType.weightOptions.
29
59
  *
@@ -1 +1 @@
1
- {"version":3,"file":"WorkoutEquipmentTypeService.js","sourceRoot":"","sources":["../../../../src/services/workout/EquipmentType/WorkoutEquipmentTypeService.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,2BAA2B;IAC9C;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,qBAAqB,CAAC,SAAiB,EAAE,SAAiB,EAAE,SAAiB;QAClF,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,IAAI,aAAa,GAAG,SAAS,CAAC;QAE9B,OAAO,aAAa,IAAI,SAAS,EAAE,CAAC;YAClC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAC5B,aAAa,IAAI,SAAS,CAAC;QAC7B,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,iBAAiB,CACtB,aAAmC,EACnC,YAAoB,EACpB,SAAkE;QAElE,IAAI,CAAC,aAAa,CAAC,aAAa,IAAI,aAAa,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7E,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,aAAa,GAAG,CAAC,GAAG,aAAa,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAE7E,gDAAgD;QAChD,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,IAAI,YAAY,CAAC,IAAI,IAAI,CAAC;QAChF,MAAM,UAAU,GACd,aAAa;aACV,KAAK,EAAE;aACP,OAAO,EAAE;aACT,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,IAAI,YAAY,CAAC,IAAI,IAAI,CAAC;QAEtD,wBAAwB;QACxB,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;YACzB,OAAO,UAAU,CAAC;QACpB,CAAC;QAED,IAAI,SAAS,KAAK,aAAa,EAAE,CAAC;YAChC,OAAO,UAAU,IAAI,QAAQ,CAAC;QAChC,CAAC;QAED,IAAI,SAAS,KAAK,WAAW,EAAE,CAAC;YAC9B,OAAO,QAAQ,IAAI,UAAU,CAAC;QAChC,CAAC;QAED,0BAA0B;QAC1B,IAAI,QAAQ,KAAK,IAAI;YAAE,OAAO,UAAU,CAAC;QACzC,IAAI,UAAU,KAAK,IAAI;YAAE,OAAO,QAAQ,CAAC;QAEzC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,GAAG,QAAQ,CAAC,CAAC;QACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,GAAG,UAAU,CAAC,CAAC;QAErD,OAAO,QAAQ,IAAI,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC;IACpD,CAAC;CACF"}
1
+ {"version":3,"file":"WorkoutEquipmentTypeService.js","sourceRoot":"","sources":["../../../../src/services/workout/EquipmentType/WorkoutEquipmentTypeService.ts"],"names":[],"mappings":"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"}
@@ -10,9 +10,6 @@ export default class WorkoutEquipmentTypeService {
10
10
  * Starts at minWeight (e.g., the bar weight), increments by increment (e.g., 2.5, 5, 10 lbs),
11
11
  * and continues until maxWeight is reached or exceeded.
12
12
  *
13
- * This may be refactored / maybe a new method will be created in the future to handle a given
14
- * set of weight plates to generate all possible combinations.
15
- *
16
13
  * @param minWeight The minimum weight (e.g., bar weight).
17
14
  * @param increment The weight increment.
18
15
  * @param maxWeight The maximum weight.
@@ -29,6 +26,41 @@ export default class WorkoutEquipmentTypeService {
29
26
  return weights;
30
27
  }
31
28
 
29
+ /**
30
+ * Generates all achievable weights from a bar weight and a set of plate pairs.
31
+ *
32
+ * Each plate entry specifies a plate weight and the number of pairs available.
33
+ * Plates are added in pairs (both sides of the bar), so each plate adds
34
+ * `weight * 2` to the total. All combinations of plates are computed to
35
+ * produce the full set of achievable weights.
36
+ *
37
+ * @param barWeight The weight of the bar alone.
38
+ * @param plates Array of plate entries, each with a `weight` and `pairs` count.
39
+ * @returns Sorted, deduplicated array of all achievable weights.
40
+ */
41
+ static generatePlateWeightOptions(
42
+ barWeight: number,
43
+ plates: Array<{ weight: number; pairs: number }>
44
+ ): number[] {
45
+ let additions = new Set<number>([0]);
46
+ for (const plate of plates) {
47
+ if (plate.weight <= 0 || plate.pairs <= 0) continue;
48
+ const expanded: number[] = [];
49
+ for (const existing of additions) {
50
+ for (let count = 1; count <= plate.pairs; count++) {
51
+ expanded.push(existing + plate.weight * 2 * count);
52
+ }
53
+ }
54
+ additions = new Set([...additions, ...expanded]);
55
+ if (additions.size > 1000) break;
56
+ }
57
+ const weights = [...additions]
58
+ .map((a) => barWeight + a)
59
+ .filter((w) => w >= 0)
60
+ .sort((a, b) => a - b);
61
+ return [...new Set(weights)];
62
+ }
63
+
32
64
  /**
33
65
  * Finds the nearest available weight from equipmentType.weightOptions.
34
66
  *
@@ -11,6 +11,13 @@ export default class WorkoutExerciseCalibrationService {
11
11
  * @param calibration The workout exercise calibration.
12
12
  */
13
13
  static get1RM(calibration: WorkoutExerciseCalibration): number;
14
+ /**
15
+ * Calculates the 1 Rep Max using the NASM formula based on provided weight and reps.
16
+ *
17
+ * @param weight The weight lifted.
18
+ * @param reps The number of reps performed.
19
+ */
20
+ static get1RMRaw(weight: number, reps: number): number;
14
21
  /**
15
22
  * Calculates the target weight for a set based on target reps and 1RM.
16
23
  *
@@ -1 +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"}
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;;;;;OAKG;IACH,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IAItD;;;;;;;;OAQG;IACH,MAAM,CAAC,eAAe,CAAC,WAAW,EAAE,0BAA0B,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM;IAM3F;;;;;;;;OAQG;IACH,OAAO,CAAC,MAAM,CAAC,mBAAmB;CAGnC"}
@@ -10,7 +10,16 @@ export default class WorkoutExerciseCalibrationService {
10
10
  * @param calibration The workout exercise calibration.
11
11
  */
12
12
  static get1RM(calibration) {
13
- return (calibration.weight * calibration.reps) / 30.48 + calibration.weight;
13
+ return this.get1RMRaw(calibration.weight, calibration.reps);
14
+ }
15
+ /**
16
+ * Calculates the 1 Rep Max using the NASM formula based on provided weight and reps.
17
+ *
18
+ * @param weight The weight lifted.
19
+ * @param reps The number of reps performed.
20
+ */
21
+ static get1RMRaw(weight, reps) {
22
+ return (weight * reps) / 30.48 + weight;
14
23
  }
15
24
  /**
16
25
  * Calculates the target weight for a set based on target reps and 1RM.
@@ -1 +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"}
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,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC;IAC9D,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,SAAS,CAAC,MAAc,EAAE,IAAY;QAC3C,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,KAAK,GAAG,MAAM,CAAC;IAC1C,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"}
@@ -12,7 +12,17 @@ export default class WorkoutExerciseCalibrationService {
12
12
  * @param calibration The workout exercise calibration.
13
13
  */
14
14
  static get1RM(calibration: WorkoutExerciseCalibration): number {
15
- return (calibration.weight * calibration.reps) / 30.48 + calibration.weight;
15
+ return this.get1RMRaw(calibration.weight, calibration.reps);
16
+ }
17
+
18
+ /**
19
+ * Calculates the 1 Rep Max using the NASM formula based on provided weight and reps.
20
+ *
21
+ * @param weight The weight lifted.
22
+ * @param reps The number of reps performed.
23
+ */
24
+ static get1RMRaw(weight: number, reps: number): number {
25
+ return (weight * reps) / 30.48 + weight;
16
26
  }
17
27
 
18
28
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"WorkoutMicrocycleService.d.ts","sourceRoot":"","sources":["../../../../src/services/workout/Microcycle/WorkoutMicrocycleService.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,+CAA+C,CAAC;AACvD,OAAO,KAAK,EACV,uBAAuB,EACvB,0BAA0B,EAC3B,MAAM,0DAA0D,CAAC;AAElE,OAAO,KAAK,2BAA2B,MAAM,6CAA6C,CAAC;AAI3F;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,wBAAwB;IAC3C;;OAEG;IACH,MAAM,CAAC,6BAA6B,CAAC,EACnC,OAAO,EACP,eAAe,EACf,SAAS,EACT,kBAAkB,EACnB,EAAE;QACD,OAAO,EAAE,2BAA2B,CAAC;QACrC,eAAe,EAAE,MAAM,CAAC;QACxB,SAAS,EAAE,MAAM,CAAC;QAClB,kBAAkB,EAAE,OAAO,CAAC;KAC7B,GAAG,IAAI;IAwDR;;;;;;;OAOG;IACH,MAAM,CAAC,iCAAiC,CACtC,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,GAAG,CAAC,IAAI,EAAE,0BAA0B,CAAC,EACrD,WAAW,EAAE,GAAG,CAAC,IAAI,EAAE,eAAe,CAAC,GACtC,uBAAuB,EAAE,EAAE;CAuI/B"}
1
+ {"version":3,"file":"WorkoutMicrocycleService.d.ts","sourceRoot":"","sources":["../../../../src/services/workout/Microcycle/WorkoutMicrocycleService.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,+CAA+C,CAAC;AACvD,OAAO,KAAK,EACV,uBAAuB,EACvB,0BAA0B,EAC3B,MAAM,0DAA0D,CAAC;AAElE,OAAO,KAAK,2BAA2B,MAAM,6CAA6C,CAAC;AAI3F;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,wBAAwB;IAC3C;;OAEG;IACH,MAAM,CAAC,6BAA6B,CAAC,EACnC,OAAO,EACP,eAAe,EACf,SAAS,EACT,kBAAkB,EACnB,EAAE;QACD,OAAO,EAAE,2BAA2B,CAAC;QACrC,eAAe,EAAE,MAAM,CAAC;QACxB,SAAS,EAAE,MAAM,CAAC;QAClB,kBAAkB,EAAE,OAAO,CAAC;KAC7B,GAAG,IAAI;IA8DR;;;;;;;OAOG;IACH,MAAM,CAAC,iCAAiC,CACtC,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,GAAG,CAAC,IAAI,EAAE,0BAA0B,CAAC,EACrD,WAAW,EAAE,GAAG,CAAC,IAAI,EAAE,eAAe,CAAC,GACtC,uBAAuB,EAAE,EAAE;CAuI/B"}
@@ -21,31 +21,38 @@ export default class WorkoutMicrocycleService {
21
21
  }
22
22
  const sessionsToExerciseSessionsArray = context.plannedSessionExercisePairs;
23
23
  const setPlan = WorkoutVolumePlanningService.calculateSetPlanForMicrocycle(context, microcycleIndex, isDeloadMicrocycle);
24
- let currentSessionDate = new Date(microcycle.startDate);
25
- let sessionIndex = 0;
24
+ // Build list of non-rest day dates
25
+ const nonRestDayDates = [];
26
+ let currentDate = new Date(microcycle.startDate);
26
27
  for (let day = 0; day < mesocycle.plannedMicrocycleLengthInDays; day++) {
27
- // Skip rest days
28
- if (mesocycle.plannedMicrocycleRestDays.includes(day)) {
29
- currentSessionDate = DateService.addDays(currentSessionDate, 1);
30
- continue;
28
+ if (!mesocycle.plannedMicrocycleRestDays.includes(day)) {
29
+ nonRestDayDates.push(new Date(currentDate));
31
30
  }
32
- // Stop if we've created all planned sessions
33
- if (sessionIndex >= mesocycle.plannedSessionCountPerMicrocycle) {
34
- break;
31
+ currentDate = DateService.addDays(currentDate, 1);
32
+ }
33
+ // Distribute sessions across non-rest days chronologically. If there are
34
+ // more sessions than non-rest days, the earliest days get extra sessions.
35
+ const totalSessions = mesocycle.plannedSessionCountPerMicrocycle;
36
+ const dayCount = nonRestDayDates.length;
37
+ const basePerDay = Math.floor(totalSessions / dayCount);
38
+ const remainder = totalSessions % dayCount;
39
+ let sessionIndex = 0;
40
+ for (let dayIndex = 0; dayIndex < dayCount; dayIndex++) {
41
+ const sessionsOnThisDay = basePerDay + (dayIndex < remainder ? 1 : 0);
42
+ for (let s = 0; s < sessionsOnThisDay; s++) {
43
+ const sessionExerciseList = sessionsToExerciseSessionsArray[sessionIndex] || [];
44
+ WorkoutSessionService.generateSession({
45
+ context,
46
+ microcycleIndex,
47
+ sessionIndex,
48
+ sessionStartDate: nonRestDayDates[dayIndex],
49
+ sessionExerciseList,
50
+ targetRir,
51
+ isDeloadMicrocycle,
52
+ setPlan
53
+ });
54
+ sessionIndex++;
35
55
  }
36
- const sessionExerciseList = sessionsToExerciseSessionsArray[sessionIndex] || [];
37
- WorkoutSessionService.generateSession({
38
- context,
39
- microcycleIndex,
40
- sessionIndex,
41
- sessionStartDate: currentSessionDate,
42
- sessionExerciseList,
43
- targetRir,
44
- isDeloadMicrocycle,
45
- setPlan
46
- });
47
- sessionIndex++;
48
- currentSessionDate = DateService.addDays(currentSessionDate, 1);
49
56
  }
50
57
  }
51
58
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"WorkoutMicrocycleService.js","sourceRoot":"","sources":["../../../../src/services/workout/Microcycle/WorkoutMicrocycleService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"WorkoutMicrocycleService.js","sourceRoot":"","sources":["../../../../src/services/workout/Microcycle/WorkoutMicrocycleService.ts"],"names":[],"mappings":"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"}
@@ -53,36 +53,42 @@ export default class WorkoutMicrocycleService {
53
53
  isDeloadMicrocycle
54
54
  );
55
55
 
56
- let currentSessionDate = new Date(microcycle.startDate);
57
- let sessionIndex = 0;
58
-
56
+ // Build list of non-rest day dates
57
+ const nonRestDayDates: Date[] = [];
58
+ let currentDate = new Date(microcycle.startDate);
59
59
  for (let day = 0; day < mesocycle.plannedMicrocycleLengthInDays; day++) {
60
- // Skip rest days
61
- if (mesocycle.plannedMicrocycleRestDays.includes(day)) {
62
- currentSessionDate = DateService.addDays(currentSessionDate, 1);
63
- continue;
64
- }
65
-
66
- // Stop if we've created all planned sessions
67
- if (sessionIndex >= mesocycle.plannedSessionCountPerMicrocycle) {
68
- break;
60
+ if (!mesocycle.plannedMicrocycleRestDays.includes(day)) {
61
+ nonRestDayDates.push(new Date(currentDate));
69
62
  }
63
+ currentDate = DateService.addDays(currentDate, 1);
64
+ }
70
65
 
71
- const sessionExerciseList = sessionsToExerciseSessionsArray[sessionIndex] || [];
72
-
73
- WorkoutSessionService.generateSession({
74
- context,
75
- microcycleIndex,
76
- sessionIndex,
77
- sessionStartDate: currentSessionDate,
78
- sessionExerciseList,
79
- targetRir,
80
- isDeloadMicrocycle,
81
- setPlan
82
- });
66
+ // Distribute sessions across non-rest days chronologically. If there are
67
+ // more sessions than non-rest days, the earliest days get extra sessions.
68
+ const totalSessions = mesocycle.plannedSessionCountPerMicrocycle;
69
+ const dayCount = nonRestDayDates.length;
70
+ const basePerDay = Math.floor(totalSessions / dayCount);
71
+ const remainder = totalSessions % dayCount;
83
72
 
84
- sessionIndex++;
85
- currentSessionDate = DateService.addDays(currentSessionDate, 1);
73
+ let sessionIndex = 0;
74
+ for (let dayIndex = 0; dayIndex < dayCount; dayIndex++) {
75
+ const sessionsOnThisDay = basePerDay + (dayIndex < remainder ? 1 : 0);
76
+ for (let s = 0; s < sessionsOnThisDay; s++) {
77
+ const sessionExerciseList = sessionsToExerciseSessionsArray[sessionIndex] || [];
78
+
79
+ WorkoutSessionService.generateSession({
80
+ context,
81
+ microcycleIndex,
82
+ sessionIndex,
83
+ sessionStartDate: nonRestDayDates[dayIndex],
84
+ sessionExerciseList,
85
+ targetRir,
86
+ isDeloadMicrocycle,
87
+ setPlan
88
+ });
89
+
90
+ sessionIndex++;
91
+ }
86
92
  }
87
93
  }
88
94
 
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.0",
5
+ "version": "4.1.2",
6
6
  "description": "A core database library used for personal projects",
7
7
  "packageManager": "pnpm@10.25.0",
8
8
  "type": "module",
@@ -88,4 +88,4 @@
88
88
  "typescript": "^5.9.3",
89
89
  "vitest": "^4.0.15"
90
90
  }
91
- }
91
+ }