@aneuhold/core-ts-db-lib 4.1.2 → 4.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/lib/documents/workout/WorkoutEquipmentType.d.ts +1 -0
- package/lib/documents/workout/WorkoutEquipmentType.d.ts.map +1 -1
- package/lib/documents/workout/WorkoutEquipmentType.js +4 -0
- package/lib/documents/workout/WorkoutEquipmentType.js.map +1 -1
- package/lib/documents/workout/WorkoutEquipmentType.ts +4 -0
- package/lib/documents/workout/WorkoutMesocycle.d.ts +1 -0
- package/lib/documents/workout/WorkoutMesocycle.d.ts.map +1 -1
- package/lib/documents/workout/WorkoutMesocycle.js +8 -0
- package/lib/documents/workout/WorkoutMesocycle.js.map +1 -1
- package/lib/documents/workout/WorkoutMesocycle.ts +8 -0
- package/lib/documents/workout/WorkoutMicrocycle.d.ts +1 -0
- package/lib/documents/workout/WorkoutMicrocycle.d.ts.map +1 -1
- package/lib/documents/workout/WorkoutMicrocycle.js +8 -1
- package/lib/documents/workout/WorkoutMicrocycle.js.map +1 -1
- package/lib/documents/workout/WorkoutMicrocycle.ts +8 -1
- package/lib/services/workout/Mesocycle/WorkoutMesocycleService.d.ts +3 -1
- package/lib/services/workout/Mesocycle/WorkoutMesocycleService.d.ts.map +1 -1
- package/lib/services/workout/Mesocycle/WorkoutMesocycleService.js +8 -4
- package/lib/services/workout/Mesocycle/WorkoutMesocycleService.js.map +1 -1
- package/lib/services/workout/Mesocycle/WorkoutMesocycleService.ts +9 -4
- package/lib/services/workout/Microcycle/WorkoutMicrocycleService.d.ts +1 -1
- package/lib/services/workout/Microcycle/WorkoutMicrocycleService.d.ts.map +1 -1
- package/lib/services/workout/Microcycle/WorkoutMicrocycleService.ts +1 -1
- package/lib/services/workout/Session/WorkoutSessionService.d.ts +24 -1
- package/lib/services/workout/Session/WorkoutSessionService.d.ts.map +1 -1
- package/lib/services/workout/Session/WorkoutSessionService.js +48 -0
- package/lib/services/workout/Session/WorkoutSessionService.js.map +1 -1
- package/lib/services/workout/Session/WorkoutSessionService.ts +57 -1
- package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.d.ts +10 -0
- package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.d.ts.map +1 -1
- package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.js +17 -0
- package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.js.map +1 -1
- package/lib/services/workout/SessionExercise/WorkoutSessionExerciseService.ts +21 -0
- package/lib/services/workout/Set/WorkoutSetService.d.ts +8 -1
- package/lib/services/workout/Set/WorkoutSetService.d.ts.map +1 -1
- package/lib/services/workout/Set/WorkoutSetService.js +10 -0
- package/lib/services/workout/Set/WorkoutSetService.js.map +1 -1
- package/lib/services/workout/Set/WorkoutSetService.ts +14 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,33 @@ 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.4] (2026-02-20)
|
|
9
|
+
|
|
10
|
+
### ✅ Added
|
|
11
|
+
|
|
12
|
+
- Added optional `description` field to `WorkoutEquipmentType` for additional equipment details.
|
|
13
|
+
- Added `startDate` field to `WorkoutMesocycle` to track when a user explicitly begins training.
|
|
14
|
+
- Added `completedDate` field to `WorkoutMicrocycle` to mark completion and indicate regeneration state.
|
|
15
|
+
|
|
16
|
+
### 🏗️ Changed
|
|
17
|
+
|
|
18
|
+
- Updated `WorkoutMesocycleService` to preserve microcycles with `completedDate` set during mesocycle regeneration, even when sessions are incomplete.
|
|
19
|
+
|
|
20
|
+
## 🔖 [4.1.3] (2026-02-17)
|
|
21
|
+
|
|
22
|
+
### ✅ Added
|
|
23
|
+
|
|
24
|
+
- Added `getActiveAndNextSessions()` method to `WorkoutSessionService` for efficiently finding in-progress and next-up sessions.
|
|
25
|
+
- Added `isDeloadExercise()` method to `WorkoutSessionExerciseService` to identify deload exercises.
|
|
26
|
+
- Added `needsReview()` method to `WorkoutSessionExerciseService` to check if late session fields are missing.
|
|
27
|
+
- Added `isCompleted()` method to `WorkoutSetService` to verify if a set has been fully logged.
|
|
28
|
+
- Added comprehensive unit tests for workout session, exercise, and set services.
|
|
29
|
+
|
|
30
|
+
### 🏗️ Changed
|
|
31
|
+
|
|
32
|
+
- Updated deload microcycle handling: `targetRir` is now `null` for deload microcycles instead of using a numeric value.
|
|
33
|
+
- Refactored method signatures to support `targetRir: number | null` across workout services.
|
|
34
|
+
|
|
8
35
|
## 🔖 [4.1.2] (2026-02-15)
|
|
9
36
|
|
|
10
37
|
### ✅ Added
|
|
@@ -225,6 +252,8 @@ Updated dependency: now requires `@aneuhold/core-ts-lib@^2.3.11`.
|
|
|
225
252
|
|
|
226
253
|
<!-- Link References -->
|
|
227
254
|
|
|
255
|
+
[4.1.4]: https://github.com/aneuhold/ts-libs/compare/core-ts-db-lib-v4.1.3...core-ts-db-lib-v4.1.4
|
|
256
|
+
[4.1.3]: https://github.com/aneuhold/ts-libs/compare/core-ts-db-lib-v4.1.2...core-ts-db-lib-v4.1.3
|
|
228
257
|
[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
258
|
[4.1.1]: https://github.com/aneuhold/ts-libs/compare/core-ts-db-lib-v4.1.0...core-ts-db-lib-v4.1.1
|
|
230
259
|
[4.1.0]: https://github.com/aneuhold/ts-libs/compare/core-ts-db-lib-v4.0.4...core-ts-db-lib-v4.1.0
|
|
@@ -9,6 +9,7 @@ export declare const WorkoutEquipmentType_docType = "workoutEquipmentType";
|
|
|
9
9
|
export declare const WorkoutEquipmentTypeSchema: z.ZodObject<{
|
|
10
10
|
docType: z.ZodDefault<z.ZodLiteral<"workoutEquipmentType">>;
|
|
11
11
|
title: z.ZodString;
|
|
12
|
+
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
12
13
|
weightOptions: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber>>>;
|
|
13
14
|
createdDate: z.ZodDefault<z.ZodDate>;
|
|
14
15
|
lastUpdatedDate: z.ZodDefault<z.ZodDate>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkoutEquipmentType.d.ts","sourceRoot":"","sources":["../../../src/documents/workout/WorkoutEquipmentType.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB;;GAEG;AACH,eAAO,MAAM,4BAA4B,yBAAyB,CAAC;AAEnE;;GAEG;AACH,eAAO,MAAM,0BAA0B
|
|
1
|
+
{"version":3,"file":"WorkoutEquipmentType.d.ts","sourceRoot":"","sources":["../../../src/documents/workout/WorkoutEquipmentType.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB;;GAEG;AACH,eAAO,MAAM,4BAA4B,yBAAyB,CAAC;AAEnE;;GAEG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;iBAuBrC,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC"}
|
|
@@ -17,6 +17,10 @@ export const WorkoutEquipmentTypeSchema = z.object({
|
|
|
17
17
|
* The title of the equipment type.
|
|
18
18
|
*/
|
|
19
19
|
title: z.string(),
|
|
20
|
+
/**
|
|
21
|
+
* An optional description of the equipment type.
|
|
22
|
+
*/
|
|
23
|
+
description: z.string().nullish(),
|
|
20
24
|
/**
|
|
21
25
|
* The available weight options for this equipment type.
|
|
22
26
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkoutEquipmentType.js","sourceRoot":"","sources":["../../../src/documents/workout/WorkoutEquipmentType.ts"],"names":[],"mappings":"AAAA,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;;GAEG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,sBAAsB,CAAC;AAEnE;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IACjD,GAAG,0BAA0B,CAAC,KAAK;IACnC,GAAG,oBAAoB,CAAC,KAAK;IAC7B,GAAG,4CAA4C,CAAC,KAAK;IACrD,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAC,OAAO,CAAC,4BAA4B,CAAC;IACtF;;OAEG;IACH,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB;;;;;;;;OAQG;IACH,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE;CAC3D,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"WorkoutEquipmentType.js","sourceRoot":"","sources":["../../../src/documents/workout/WorkoutEquipmentType.ts"],"names":[],"mappings":"AAAA,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;;GAEG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,sBAAsB,CAAC;AAEnE;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IACjD,GAAG,0BAA0B,CAAC,KAAK;IACnC,GAAG,oBAAoB,CAAC,KAAK;IAC7B,GAAG,4CAA4C,CAAC,KAAK;IACrD,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAC,OAAO,CAAC,4BAA4B,CAAC;IACtF;;OAEG;IACH,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB;;OAEG;IACH,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IACjC;;;;;;;;OAQG;IACH,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE;CAC3D,CAAC,CAAC"}
|
|
@@ -22,6 +22,10 @@ export const WorkoutEquipmentTypeSchema = z.object({
|
|
|
22
22
|
* The title of the equipment type.
|
|
23
23
|
*/
|
|
24
24
|
title: z.string(),
|
|
25
|
+
/**
|
|
26
|
+
* An optional description of the equipment type.
|
|
27
|
+
*/
|
|
28
|
+
description: z.string().nullish(),
|
|
25
29
|
/**
|
|
26
30
|
* The available weight options for this equipment type.
|
|
27
31
|
*
|
|
@@ -29,6 +29,7 @@ export declare const WorkoutMesocycleSchema: z.ZodObject<{
|
|
|
29
29
|
plannedMicrocycleLengthInDays: z.ZodInt;
|
|
30
30
|
plannedMicrocycleRestDays: z.ZodDefault<z.ZodArray<z.ZodInt>>;
|
|
31
31
|
plannedMicrocycleCount: z.ZodOptional<z.ZodNullable<z.ZodInt>>;
|
|
32
|
+
startDate: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
|
|
32
33
|
completedDate: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
|
|
33
34
|
createdDate: z.ZodDefault<z.ZodDate>;
|
|
34
35
|
lastUpdatedDate: z.ZodDefault<z.ZodDate>;
|
|
@@ -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
|
|
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;;;;;;;;;;;;;;;iBA2DjC,CAAC;AAEH;;;;;;;;;GASG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
|
|
@@ -66,6 +66,14 @@ export const WorkoutMesocycleSchema = z.object({
|
|
|
66
66
|
* Should typically be 5-9 microcycles (4-8 accumulation weeks + 1 deload week).
|
|
67
67
|
*/
|
|
68
68
|
plannedMicrocycleCount: z.int().min(2).max(20).nullish(),
|
|
69
|
+
/**
|
|
70
|
+
* The date this mesocycle was started by the user.
|
|
71
|
+
*
|
|
72
|
+
* Distinct from `createdDate` — this is set when the user explicitly clicks
|
|
73
|
+
* "Start Mesocycle" to begin training. This is helpful because we need a way to indicate that
|
|
74
|
+
* the final regeneration has been done just before they start.
|
|
75
|
+
*/
|
|
76
|
+
startDate: z.date().nullish(),
|
|
69
77
|
/**
|
|
70
78
|
* The date this mesocycle was completed.
|
|
71
79
|
*
|
|
@@ -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,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"}
|
|
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,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE;IAC7B;;;;;;OAMG;IACH,aAAa,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE;CAClC,CAAC,CAAC"}
|
|
@@ -72,6 +72,14 @@ export const WorkoutMesocycleSchema = z.object({
|
|
|
72
72
|
* Should typically be 5-9 microcycles (4-8 accumulation weeks + 1 deload week).
|
|
73
73
|
*/
|
|
74
74
|
plannedMicrocycleCount: z.int().min(2).max(20).nullish(),
|
|
75
|
+
/**
|
|
76
|
+
* The date this mesocycle was started by the user.
|
|
77
|
+
*
|
|
78
|
+
* Distinct from `createdDate` — this is set when the user explicitly clicks
|
|
79
|
+
* "Start Mesocycle" to begin training. This is helpful because we need a way to indicate that
|
|
80
|
+
* the final regeneration has been done just before they start.
|
|
81
|
+
*/
|
|
82
|
+
startDate: z.date().nullish(),
|
|
75
83
|
/**
|
|
76
84
|
* The date this mesocycle was completed.
|
|
77
85
|
*
|
|
@@ -12,6 +12,7 @@ export declare const WorkoutMicrocycleSchema: z.ZodObject<{
|
|
|
12
12
|
startDate: z.ZodDate;
|
|
13
13
|
endDate: z.ZodDate;
|
|
14
14
|
sessionOrder: z.ZodDefault<z.ZodArray<z.ZodPipe<z.ZodUUID, z.ZodTransform<`${string}-${string}-${string}-${string}-${string}`, string>>>>;
|
|
15
|
+
completedDate: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
|
|
15
16
|
createdDate: z.ZodDefault<z.ZodDate>;
|
|
16
17
|
lastUpdatedDate: z.ZodDefault<z.ZodDate>;
|
|
17
18
|
_id: z.ZodPipe<z.ZodDefault<z.ZodUUID>, z.ZodTransform<`${string}-${string}-${string}-${string}-${string}`, string>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkoutMicrocycle.d.ts","sourceRoot":"","sources":["../../../src/documents/workout/WorkoutMicrocycle.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB;;GAEG;AACH,eAAO,MAAM,yBAAyB,sBAAsB,CAAC;AAE7D;;GAEG;AACH,eAAO,MAAM,uBAAuB
|
|
1
|
+
{"version":3,"file":"WorkoutMicrocycle.d.ts","sourceRoot":"","sources":["../../../src/documents/workout/WorkoutMicrocycle.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB;;GAEG;AACH,eAAO,MAAM,yBAAyB,sBAAsB,CAAC;AAE7D;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;iBAqClC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC"}
|
|
@@ -37,6 +37,13 @@ export const WorkoutMicrocycleSchema = z.object({
|
|
|
37
37
|
* This makes it easier to reason about the order of sessions before dates
|
|
38
38
|
* are assigned.
|
|
39
39
|
*/
|
|
40
|
-
sessionOrder: z.array(z.uuidv7().transform((val) => val)).default([])
|
|
40
|
+
sessionOrder: z.array(z.uuidv7().transform((val) => val)).default([]),
|
|
41
|
+
/**
|
|
42
|
+
* The date this microcycle was marked as completed by the user.
|
|
43
|
+
*
|
|
44
|
+
* This helps for performance reasons, but also acts as our indicator that the mesocycle has been
|
|
45
|
+
* regenerated after the microcycle was completed.
|
|
46
|
+
*/
|
|
47
|
+
completedDate: z.date().nullish()
|
|
41
48
|
});
|
|
42
49
|
//# sourceMappingURL=WorkoutMicrocycle.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkoutMicrocycle.js","sourceRoot":"","sources":["../../../src/documents/workout/WorkoutMicrocycle.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;;GAEG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,mBAAmB,CAAC;AAE7D;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,GAAG,0BAA0B,CAAC,KAAK;IACnC,GAAG,oBAAoB,CAAC,KAAK;IAC7B,GAAG,4CAA4C,CAAC,KAAK;IACrD,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC,OAAO,CAAC,yBAAyB,CAAC;IAChF;;;;OAIG;IACH,kBAAkB,EAAE,CAAC;SAClB,MAAM,EAAE;SACR,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAW,CAAC;SAC/B,OAAO,EAAE;IACZ;;OAEG;IACH,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE;IACnB;;OAEG;IACH,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE;IACjB;;;;;;OAMG;IACH,YAAY,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;
|
|
1
|
+
{"version":3,"file":"WorkoutMicrocycle.js","sourceRoot":"","sources":["../../../src/documents/workout/WorkoutMicrocycle.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;;GAEG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,mBAAmB,CAAC;AAE7D;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,GAAG,0BAA0B,CAAC,KAAK;IACnC,GAAG,oBAAoB,CAAC,KAAK;IAC7B,GAAG,4CAA4C,CAAC,KAAK;IACrD,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC,OAAO,CAAC,yBAAyB,CAAC;IAChF;;;;OAIG;IACH,kBAAkB,EAAE,CAAC;SAClB,MAAM,EAAE;SACR,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAW,CAAC;SAC/B,OAAO,EAAE;IACZ;;OAEG;IACH,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE;IACnB;;OAEG;IACH,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE;IACjB;;;;;;OAMG;IACH,YAAY,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;IAC7E;;;;;OAKG;IACH,aAAa,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE;CAClC,CAAC,CAAC"}
|
|
@@ -43,7 +43,14 @@ export const WorkoutMicrocycleSchema = z.object({
|
|
|
43
43
|
* This makes it easier to reason about the order of sessions before dates
|
|
44
44
|
* are assigned.
|
|
45
45
|
*/
|
|
46
|
-
sessionOrder: z.array(z.uuidv7().transform((val) => val as UUID)).default([])
|
|
46
|
+
sessionOrder: z.array(z.uuidv7().transform((val) => val as UUID)).default([]),
|
|
47
|
+
/**
|
|
48
|
+
* The date this microcycle was marked as completed by the user.
|
|
49
|
+
*
|
|
50
|
+
* This helps for performance reasons, but also acts as our indicator that the mesocycle has been
|
|
51
|
+
* regenerated after the microcycle was completed.
|
|
52
|
+
*/
|
|
53
|
+
completedDate: z.date().nullish()
|
|
47
54
|
});
|
|
48
55
|
|
|
49
56
|
/**
|
|
@@ -32,8 +32,10 @@ export default class WorkoutMesocycleService {
|
|
|
32
32
|
* @param existingSessions Existing session documents.
|
|
33
33
|
* @param existingSessionExercises Existing session exercise documents.
|
|
34
34
|
* @param existingSets Existing set documents.
|
|
35
|
+
* @param startDate Optional start date for the first microcycle. Defaults to
|
|
36
|
+
* the current date when not provided.
|
|
35
37
|
*/
|
|
36
|
-
static generateOrUpdateMesocycle(mesocycle: WorkoutMesocycle, calibrations: WorkoutExerciseCalibration[], exercises: WorkoutExercise[], equipmentTypes: WorkoutEquipmentType[], existingMicrocycles?: WorkoutMicrocycle[], existingSessions?: WorkoutSession[], existingSessionExercises?: WorkoutSessionExercise[], existingSets?: WorkoutSet[]): {
|
|
38
|
+
static generateOrUpdateMesocycle(mesocycle: WorkoutMesocycle, calibrations: WorkoutExerciseCalibration[], exercises: WorkoutExercise[], equipmentTypes: WorkoutEquipmentType[], existingMicrocycles?: WorkoutMicrocycle[], existingSessions?: WorkoutSession[], existingSessionExercises?: WorkoutSessionExercise[], existingSets?: WorkoutSet[], startDate?: Date): {
|
|
37
39
|
mesocycleUpdate?: Partial<WorkoutMesocycle>;
|
|
38
40
|
microcycles?: DocumentOperations<WorkoutMicrocycle>;
|
|
39
41
|
sessions?: DocumentOperations<WorkoutSession>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkoutMesocycleService.d.ts","sourceRoot":"","sources":["../../../../src/services/workout/Mesocycle/WorkoutMesocycleService.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oDAAoD,CAAC;AAC/F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+CAA+C,CAAC;AACrF,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,0DAA0D,CAAC;AAC3G,OAAO,EAAa,KAAK,gBAAgB,EAAE,MAAM,gDAAgD,CAAC;AAClG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iDAAiD,CAAC;AAEzF,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;AAC3E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAInE;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,uBAAuB;IAC1C
|
|
1
|
+
{"version":3,"file":"WorkoutMesocycleService.d.ts","sourceRoot":"","sources":["../../../../src/services/workout/Mesocycle/WorkoutMesocycleService.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oDAAoD,CAAC;AAC/F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+CAA+C,CAAC;AACrF,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,0DAA0D,CAAC;AAC3G,OAAO,EAAa,KAAK,gBAAgB,EAAE,MAAM,gDAAgD,CAAC;AAClG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iDAAiD,CAAC;AAEzF,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;AAC3E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAInE;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,uBAAuB;IAC1C;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,MAAM,CAAC,yBAAyB,CAC9B,SAAS,EAAE,gBAAgB,EAC3B,YAAY,EAAE,0BAA0B,EAAE,EAC1C,SAAS,EAAE,eAAe,EAAE,EAC5B,cAAc,EAAE,oBAAoB,EAAE,EACtC,mBAAmB,GAAE,iBAAiB,EAAO,EAC7C,gBAAgB,GAAE,cAAc,EAAO,EACvC,wBAAwB,GAAE,sBAAsB,EAAO,EACvD,YAAY,GAAE,UAAU,EAAO,EAC/B,SAAS,CAAC,EAAE,IAAI,GACf;QACD,eAAe,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAC5C,WAAW,CAAC,EAAE,kBAAkB,CAAC,iBAAiB,CAAC,CAAC;QACpD,QAAQ,CAAC,EAAE,kBAAkB,CAAC,cAAc,CAAC,CAAC;QAC9C,gBAAgB,CAAC,EAAE,kBAAkB,CAAC,sBAAsB,CAAC,CAAC;QAC9D,IAAI,CAAC,EAAE,kBAAkB,CAAC,UAAU,CAAC,CAAC;KACvC;IAwHD;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,4BAA4B;CA4F5C"}
|
|
@@ -28,8 +28,10 @@ export default class WorkoutMesocycleService {
|
|
|
28
28
|
* @param existingSessions Existing session documents.
|
|
29
29
|
* @param existingSessionExercises Existing session exercise documents.
|
|
30
30
|
* @param existingSets Existing set documents.
|
|
31
|
+
* @param startDate Optional start date for the first microcycle. Defaults to
|
|
32
|
+
* the current date when not provided.
|
|
31
33
|
*/
|
|
32
|
-
static generateOrUpdateMesocycle(mesocycle, calibrations, exercises, equipmentTypes, existingMicrocycles = [], existingSessions = [], existingSessionExercises = [], existingSets = []) {
|
|
34
|
+
static generateOrUpdateMesocycle(mesocycle, calibrations, exercises, equipmentTypes, existingMicrocycles = [], existingSessions = [], existingSessionExercises = [], existingSets = [], startDate) {
|
|
33
35
|
// Free-form mesocycles are intentionally not auto-planned. The user can still log workouts,
|
|
34
36
|
// but we avoid generating microcycles/sessions/sets because recommendations wouldn't be able
|
|
35
37
|
// to be done / make any sense.
|
|
@@ -55,8 +57,7 @@ export default class WorkoutMesocycleService {
|
|
|
55
57
|
const startMicrocycleIndex = context.microcyclesInOrder.length;
|
|
56
58
|
let currentDate;
|
|
57
59
|
if (startMicrocycleIndex === 0) {
|
|
58
|
-
|
|
59
|
-
currentDate = new Date();
|
|
60
|
+
currentDate = startDate ? new Date(startDate) : new Date();
|
|
60
61
|
}
|
|
61
62
|
else {
|
|
62
63
|
// Continue from where the last existing microcycle ended
|
|
@@ -68,7 +69,7 @@ export default class WorkoutMesocycleService {
|
|
|
68
69
|
const isDeloadMicrocycle = microcycleIndex === deloadMicrocycleIndex;
|
|
69
70
|
// Calculate RIR for this microcycle (4 -> 3 -> 2 -> 1 -> 0, capped at microcycle 5)
|
|
70
71
|
const rirForMicrocycle = Math.min(microcycleIndex, 4);
|
|
71
|
-
const targetRir = 4 - rirForMicrocycle;
|
|
72
|
+
const targetRir = isDeloadMicrocycle ? null : 4 - rirForMicrocycle;
|
|
72
73
|
// Create microcycle
|
|
73
74
|
const microcycle = WorkoutMicrocycleSchema.parse({
|
|
74
75
|
userId: mesocycle.userId,
|
|
@@ -124,6 +125,9 @@ export default class WorkoutMesocycleService {
|
|
|
124
125
|
let firstIncompleteMicrocycleIndex = -1;
|
|
125
126
|
for (let i = 0; i < microcyclesForMesocycle.length; i++) {
|
|
126
127
|
const microcycle = microcyclesForMesocycle[i];
|
|
128
|
+
if (microcycle.completedDate) {
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
127
131
|
if (microcycle.sessionOrder.length === 0) {
|
|
128
132
|
// Microcycle has no sessions, it's incomplete
|
|
129
133
|
firstIncompleteMicrocycleIndex = i;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkoutMesocycleService.js","sourceRoot":"","sources":["../../../../src/services/workout/Mesocycle/WorkoutMesocycleService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAKpD,OAAO,EAAE,SAAS,EAAyB,MAAM,gDAAgD,CAAC;AAElG,OAAO,EAAE,uBAAuB,EAAE,MAAM,iDAAiD,CAAC;AAK1F,OAAO,wBAAwB,MAAM,2CAA2C,CAAC;AACjF,OAAO,2BAA2B,MAAM,kCAAkC,CAAC;AAE3E;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,uBAAuB;IAC1C
|
|
1
|
+
{"version":3,"file":"WorkoutMesocycleService.js","sourceRoot":"","sources":["../../../../src/services/workout/Mesocycle/WorkoutMesocycleService.ts"],"names":[],"mappings":"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"}
|
|
@@ -38,6 +38,8 @@ export default class WorkoutMesocycleService {
|
|
|
38
38
|
* @param existingSessions Existing session documents.
|
|
39
39
|
* @param existingSessionExercises Existing session exercise documents.
|
|
40
40
|
* @param existingSets Existing set documents.
|
|
41
|
+
* @param startDate Optional start date for the first microcycle. Defaults to
|
|
42
|
+
* the current date when not provided.
|
|
41
43
|
*/
|
|
42
44
|
static generateOrUpdateMesocycle(
|
|
43
45
|
mesocycle: WorkoutMesocycle,
|
|
@@ -47,7 +49,8 @@ export default class WorkoutMesocycleService {
|
|
|
47
49
|
existingMicrocycles: WorkoutMicrocycle[] = [],
|
|
48
50
|
existingSessions: WorkoutSession[] = [],
|
|
49
51
|
existingSessionExercises: WorkoutSessionExercise[] = [],
|
|
50
|
-
existingSets: WorkoutSet[] = []
|
|
52
|
+
existingSets: WorkoutSet[] = [],
|
|
53
|
+
startDate?: Date
|
|
51
54
|
): {
|
|
52
55
|
mesocycleUpdate?: Partial<WorkoutMesocycle>;
|
|
53
56
|
microcycles?: DocumentOperations<WorkoutMicrocycle>;
|
|
@@ -114,8 +117,7 @@ export default class WorkoutMesocycleService {
|
|
|
114
117
|
let currentDate: Date;
|
|
115
118
|
|
|
116
119
|
if (startMicrocycleIndex === 0) {
|
|
117
|
-
|
|
118
|
-
currentDate = new Date();
|
|
120
|
+
currentDate = startDate ? new Date(startDate) : new Date();
|
|
119
121
|
} else {
|
|
120
122
|
// Continue from where the last existing microcycle ended
|
|
121
123
|
const lastExistingMicrocycle = context.microcyclesInOrder[startMicrocycleIndex - 1];
|
|
@@ -132,7 +134,7 @@ export default class WorkoutMesocycleService {
|
|
|
132
134
|
|
|
133
135
|
// Calculate RIR for this microcycle (4 -> 3 -> 2 -> 1 -> 0, capped at microcycle 5)
|
|
134
136
|
const rirForMicrocycle = Math.min(microcycleIndex, 4);
|
|
135
|
-
const targetRir = 4 - rirForMicrocycle;
|
|
137
|
+
const targetRir = isDeloadMicrocycle ? null : 4 - rirForMicrocycle;
|
|
136
138
|
|
|
137
139
|
// Create microcycle
|
|
138
140
|
const microcycle = WorkoutMicrocycleSchema.parse({
|
|
@@ -208,6 +210,9 @@ export default class WorkoutMesocycleService {
|
|
|
208
210
|
let firstIncompleteMicrocycleIndex = -1;
|
|
209
211
|
for (let i = 0; i < microcyclesForMesocycle.length; i++) {
|
|
210
212
|
const microcycle = microcyclesForMesocycle[i];
|
|
213
|
+
if (microcycle.completedDate) {
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
211
216
|
if (microcycle.sessionOrder.length === 0) {
|
|
212
217
|
// Microcycle has no sessions, it's incomplete
|
|
213
218
|
firstIncompleteMicrocycleIndex = i;
|
|
@@ -12,7 +12,7 @@ export default class WorkoutMicrocycleService {
|
|
|
12
12
|
static generateSessionsForMicrocycle({ context, microcycleIndex, targetRir, isDeloadMicrocycle }: {
|
|
13
13
|
context: WorkoutMesocyclePlanContext;
|
|
14
14
|
microcycleIndex: number;
|
|
15
|
-
targetRir: number;
|
|
15
|
+
targetRir: number | null;
|
|
16
16
|
isDeloadMicrocycle: boolean;
|
|
17
17
|
}): void;
|
|
18
18
|
/**
|
|
@@ -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;
|
|
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,GAAG,IAAI,CAAC;QACzB,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"}
|
|
@@ -28,7 +28,7 @@ export default class WorkoutMicrocycleService {
|
|
|
28
28
|
}: {
|
|
29
29
|
context: WorkoutMesocyclePlanContext;
|
|
30
30
|
microcycleIndex: number;
|
|
31
|
-
targetRir: number;
|
|
31
|
+
targetRir: number | null;
|
|
32
32
|
isDeloadMicrocycle: boolean;
|
|
33
33
|
}): void {
|
|
34
34
|
const mesocycle = context.mesocycle;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { UUID } from 'crypto';
|
|
2
2
|
import type { CalibrationExercisePair } from '../../../documents/workout/WorkoutExerciseCalibration.js';
|
|
3
3
|
import type { WorkoutSession } from '../../../documents/workout/WorkoutSession.js';
|
|
4
|
+
import type { WorkoutSessionExercise } from '../../../documents/workout/WorkoutSessionExercise.js';
|
|
5
|
+
import type { WorkoutSet } from '../../../documents/workout/WorkoutSet.js';
|
|
4
6
|
import type WorkoutMesocyclePlanContext from '../Mesocycle/WorkoutMesocyclePlanContext.js';
|
|
5
7
|
/**
|
|
6
8
|
* A service for handling operations related to {@link WorkoutSession}s.
|
|
@@ -29,6 +31,27 @@ export default class WorkoutSessionService {
|
|
|
29
31
|
* Calculates the Stimulus to Fatigue Ratio (SFR) for a session.
|
|
30
32
|
*/
|
|
31
33
|
static getSFR(session: WorkoutSession): number | null;
|
|
34
|
+
/**
|
|
35
|
+
* Finds the in-progress session and the next-up session in a single pass.
|
|
36
|
+
* - In-progress: complete === false, at least one set has actualReps != null
|
|
37
|
+
* - Next-up: first complete === false session with no logged sets (after any in-progress)
|
|
38
|
+
*
|
|
39
|
+
* Sessions should be in microcycle order (as returned by getAssociatedDocsForMesocycle).
|
|
40
|
+
* Only checks sets for incomplete sessions, skipping completed ones entirely.
|
|
41
|
+
*
|
|
42
|
+
* @param sessions Ordered sessions for the mesocycle.
|
|
43
|
+
* @param sessionExerciseMap Map of session exercise ID to WorkoutSessionExercise.
|
|
44
|
+
* @param setMap Map of set ID to WorkoutSet.
|
|
45
|
+
*/
|
|
46
|
+
static getActiveAndNextSessions(sessions: WorkoutSession[], sessionExerciseMap: Map<UUID, WorkoutSessionExercise>, setMap: Map<UUID, WorkoutSet>): {
|
|
47
|
+
inProgressSession: WorkoutSession | null;
|
|
48
|
+
nextUpSession: WorkoutSession | null;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Returns true if any set in the session has actualReps != null.
|
|
52
|
+
* Traverses session → sessionExercises → sets via order arrays and map lookups.
|
|
53
|
+
*/
|
|
54
|
+
private static sessionHasLoggedSets;
|
|
32
55
|
/**
|
|
33
56
|
* Generates a session and its associated exercises and sets.
|
|
34
57
|
*/
|
|
@@ -38,7 +61,7 @@ export default class WorkoutSessionService {
|
|
|
38
61
|
sessionIndex: number;
|
|
39
62
|
sessionStartDate: Date;
|
|
40
63
|
sessionExerciseList: CalibrationExercisePair[];
|
|
41
|
-
targetRir: number;
|
|
64
|
+
targetRir: number | null;
|
|
42
65
|
isDeloadMicrocycle: boolean;
|
|
43
66
|
setPlan: {
|
|
44
67
|
exerciseIdToSetCount: Map<UUID, number>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkoutSessionService.d.ts","sourceRoot":"","sources":["../../../../src/services/workout/Session/WorkoutSessionService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,0DAA0D,CAAC;AACxG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8CAA8C,CAAC;AAGnF,OAAO,KAAK,2BAA2B,MAAM,6CAA6C,CAAC;AAI3F;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,OAAO,OAAO,qBAAqB;IACxC;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI;IAI1D;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI;IAI9D;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI;IAIrD;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,EACrB,OAAO,EACP,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,SAAS,EACT,kBAAkB,EAClB,OAAO,EACR,EAAE;QACD,OAAO,EAAE,2BAA2B,CAAC;QACrC,eAAe,EAAE,MAAM,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,IAAI,CAAC;QACvB,mBAAmB,EAAE,uBAAuB,EAAE,CAAC;QAC/C,SAAS,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"WorkoutSessionService.d.ts","sourceRoot":"","sources":["../../../../src/services/workout/Session/WorkoutSessionService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,0DAA0D,CAAC;AACxG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8CAA8C,CAAC;AAGnF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sDAAsD,CAAC;AACnG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAC3E,OAAO,KAAK,2BAA2B,MAAM,6CAA6C,CAAC;AAI3F;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,OAAO,OAAO,qBAAqB;IACxC;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI;IAI1D;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI;IAI9D;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI;IAIrD;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,wBAAwB,CAC7B,QAAQ,EAAE,cAAc,EAAE,EAC1B,kBAAkB,EAAE,GAAG,CAAC,IAAI,EAAE,sBAAsB,CAAC,EACrD,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,GAC5B;QAAE,iBAAiB,EAAE,cAAc,GAAG,IAAI,CAAC;QAAC,aAAa,EAAE,cAAc,GAAG,IAAI,CAAA;KAAE;IAkBrF;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAgBnC;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,EACrB,OAAO,EACP,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,SAAS,EACT,kBAAkB,EAClB,OAAO,EACR,EAAE;QACD,OAAO,EAAE,2BAA2B,CAAC;QACrC,eAAe,EAAE,MAAM,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,IAAI,CAAC;QACvB,mBAAmB,EAAE,uBAAuB,EAAE,CAAC;QAC/C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,kBAAkB,EAAE,OAAO,CAAC;QAC5B,OAAO,EAAE;YAAE,oBAAoB,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAAC,mBAAmB,EAAE,GAAG,CAAC,IAAI,CAAC,CAAA;SAAE,CAAC;KACtF,GAAG,IAAI;CAqET"}
|
|
@@ -35,6 +35,54 @@ export default class WorkoutSessionService {
|
|
|
35
35
|
static getSFR(session) {
|
|
36
36
|
return WorkoutSFRService.getSFR(session.rsm, session.fatigue);
|
|
37
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Finds the in-progress session and the next-up session in a single pass.
|
|
40
|
+
* - In-progress: complete === false, at least one set has actualReps != null
|
|
41
|
+
* - Next-up: first complete === false session with no logged sets (after any in-progress)
|
|
42
|
+
*
|
|
43
|
+
* Sessions should be in microcycle order (as returned by getAssociatedDocsForMesocycle).
|
|
44
|
+
* Only checks sets for incomplete sessions, skipping completed ones entirely.
|
|
45
|
+
*
|
|
46
|
+
* @param sessions Ordered sessions for the mesocycle.
|
|
47
|
+
* @param sessionExerciseMap Map of session exercise ID to WorkoutSessionExercise.
|
|
48
|
+
* @param setMap Map of set ID to WorkoutSet.
|
|
49
|
+
*/
|
|
50
|
+
static getActiveAndNextSessions(sessions, sessionExerciseMap, setMap) {
|
|
51
|
+
let inProgressSession = null;
|
|
52
|
+
let nextUpSession = null;
|
|
53
|
+
for (const session of sessions) {
|
|
54
|
+
if (session.complete)
|
|
55
|
+
continue;
|
|
56
|
+
if (this.sessionHasLoggedSets(session, sessionExerciseMap, setMap)) {
|
|
57
|
+
if (!inProgressSession)
|
|
58
|
+
inProgressSession = session;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
if (!nextUpSession)
|
|
62
|
+
nextUpSession = session;
|
|
63
|
+
}
|
|
64
|
+
if (inProgressSession && nextUpSession)
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
return { inProgressSession, nextUpSession };
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Returns true if any set in the session has actualReps != null.
|
|
71
|
+
* Traverses session → sessionExercises → sets via order arrays and map lookups.
|
|
72
|
+
*/
|
|
73
|
+
static sessionHasLoggedSets(session, sessionExerciseMap, setMap) {
|
|
74
|
+
for (const seId of session.sessionExerciseOrder) {
|
|
75
|
+
const se = sessionExerciseMap.get(seId);
|
|
76
|
+
if (!se)
|
|
77
|
+
continue;
|
|
78
|
+
for (const setId of se.setOrder) {
|
|
79
|
+
const set = setMap.get(setId);
|
|
80
|
+
if (set?.actualReps != null)
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
38
86
|
/**
|
|
39
87
|
* Generates a session and its associated exercises and sets.
|
|
40
88
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkoutSessionService.js","sourceRoot":"","sources":["../../../../src/services/workout/Session/WorkoutSessionService.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,8CAA8C,CAAC;AACpF,OAAO,EAAE,4BAA4B,EAAE,MAAM,sDAAsD,CAAC;
|
|
1
|
+
{"version":3,"file":"WorkoutSessionService.js","sourceRoot":"","sources":["../../../../src/services/workout/Session/WorkoutSessionService.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,8 @@ import type { CalibrationExercisePair } from '../../../documents/workout/Workout
|
|
|
3
3
|
import type { WorkoutSession } from '../../../documents/workout/WorkoutSession.js';
|
|
4
4
|
import { WorkoutSessionSchema } from '../../../documents/workout/WorkoutSession.js';
|
|
5
5
|
import { WorkoutSessionExerciseSchema } from '../../../documents/workout/WorkoutSessionExercise.js';
|
|
6
|
+
import type { WorkoutSessionExercise } from '../../../documents/workout/WorkoutSessionExercise.js';
|
|
7
|
+
import type { WorkoutSet } from '../../../documents/workout/WorkoutSet.js';
|
|
6
8
|
import type WorkoutMesocyclePlanContext from '../Mesocycle/WorkoutMesocyclePlanContext.js';
|
|
7
9
|
import WorkoutSetService from '../Set/WorkoutSetService.js';
|
|
8
10
|
import WorkoutSFRService from '../util/SFR/WorkoutSFRService.js';
|
|
@@ -43,6 +45,60 @@ export default class WorkoutSessionService {
|
|
|
43
45
|
return WorkoutSFRService.getSFR(session.rsm, session.fatigue);
|
|
44
46
|
}
|
|
45
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Finds the in-progress session and the next-up session in a single pass.
|
|
50
|
+
* - In-progress: complete === false, at least one set has actualReps != null
|
|
51
|
+
* - Next-up: first complete === false session with no logged sets (after any in-progress)
|
|
52
|
+
*
|
|
53
|
+
* Sessions should be in microcycle order (as returned by getAssociatedDocsForMesocycle).
|
|
54
|
+
* Only checks sets for incomplete sessions, skipping completed ones entirely.
|
|
55
|
+
*
|
|
56
|
+
* @param sessions Ordered sessions for the mesocycle.
|
|
57
|
+
* @param sessionExerciseMap Map of session exercise ID to WorkoutSessionExercise.
|
|
58
|
+
* @param setMap Map of set ID to WorkoutSet.
|
|
59
|
+
*/
|
|
60
|
+
static getActiveAndNextSessions(
|
|
61
|
+
sessions: WorkoutSession[],
|
|
62
|
+
sessionExerciseMap: Map<UUID, WorkoutSessionExercise>,
|
|
63
|
+
setMap: Map<UUID, WorkoutSet>
|
|
64
|
+
): { inProgressSession: WorkoutSession | null; nextUpSession: WorkoutSession | null } {
|
|
65
|
+
let inProgressSession: WorkoutSession | null = null;
|
|
66
|
+
let nextUpSession: WorkoutSession | null = null;
|
|
67
|
+
|
|
68
|
+
for (const session of sessions) {
|
|
69
|
+
if (session.complete) continue;
|
|
70
|
+
|
|
71
|
+
if (this.sessionHasLoggedSets(session, sessionExerciseMap, setMap)) {
|
|
72
|
+
if (!inProgressSession) inProgressSession = session;
|
|
73
|
+
} else {
|
|
74
|
+
if (!nextUpSession) nextUpSession = session;
|
|
75
|
+
}
|
|
76
|
+
if (inProgressSession && nextUpSession) break;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return { inProgressSession, nextUpSession };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Returns true if any set in the session has actualReps != null.
|
|
84
|
+
* Traverses session → sessionExercises → sets via order arrays and map lookups.
|
|
85
|
+
*/
|
|
86
|
+
private static sessionHasLoggedSets(
|
|
87
|
+
session: WorkoutSession,
|
|
88
|
+
sessionExerciseMap: Map<UUID, WorkoutSessionExercise>,
|
|
89
|
+
setMap: Map<UUID, WorkoutSet>
|
|
90
|
+
): boolean {
|
|
91
|
+
for (const seId of session.sessionExerciseOrder) {
|
|
92
|
+
const se = sessionExerciseMap.get(seId);
|
|
93
|
+
if (!se) continue;
|
|
94
|
+
for (const setId of se.setOrder) {
|
|
95
|
+
const set = setMap.get(setId);
|
|
96
|
+
if (set?.actualReps != null) return true;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
|
|
46
102
|
/**
|
|
47
103
|
* Generates a session and its associated exercises and sets.
|
|
48
104
|
*/
|
|
@@ -61,7 +117,7 @@ export default class WorkoutSessionService {
|
|
|
61
117
|
sessionIndex: number;
|
|
62
118
|
sessionStartDate: Date;
|
|
63
119
|
sessionExerciseList: CalibrationExercisePair[];
|
|
64
|
-
targetRir: number;
|
|
120
|
+
targetRir: number | null;
|
|
65
121
|
isDeloadMicrocycle: boolean;
|
|
66
122
|
setPlan: { exerciseIdToSetCount: Map<UUID, number>; recoveryExerciseIds: Set<UUID> };
|
|
67
123
|
}): void {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { WorkoutSessionExercise } from '../../../documents/workout/WorkoutSessionExercise.js';
|
|
2
|
+
import type { WorkoutSet } from '../../../documents/workout/WorkoutSet.js';
|
|
2
3
|
/**
|
|
3
4
|
* A service for handling operations related to {@link WorkoutSessionExercise}s.
|
|
4
5
|
*/
|
|
@@ -41,5 +42,14 @@ export default class WorkoutSessionExerciseService {
|
|
|
41
42
|
| **3** | Do not add sets | Do not add sets | Do not add sets | Employ recovery sessions (see Fatigue Management) |
|
|
42
43
|
*/
|
|
43
44
|
static getRecommendedSetAdditionsOrRecovery(workoutSessionExercise: WorkoutSessionExercise): number | null;
|
|
45
|
+
/**
|
|
46
|
+
* Returns true if the exercise is a deload exercise (all sets have plannedRir == null).
|
|
47
|
+
*/
|
|
48
|
+
static isDeloadExercise(exerciseSets: WorkoutSet[]): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Returns true if the session exercise needs review (complete session but missing late fields).
|
|
51
|
+
* Deload exercises never need review.
|
|
52
|
+
*/
|
|
53
|
+
static needsReview(sessionExercise: WorkoutSessionExercise, exerciseSets: WorkoutSet[]): boolean;
|
|
44
54
|
}
|
|
45
55
|
//# sourceMappingURL=WorkoutSessionExerciseService.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkoutSessionExerciseService.d.ts","sourceRoot":"","sources":["../../../../src/services/workout/SessionExercise/WorkoutSessionExerciseService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sDAAsD,CAAC;
|
|
1
|
+
{"version":3,"file":"WorkoutSessionExerciseService.d.ts","sourceRoot":"","sources":["../../../../src/services/workout/SessionExercise/WorkoutSessionExerciseService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sDAAsD,CAAC;AACnG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAG3E;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,6BAA6B;IAChD;;;;OAIG;IACH,MAAM,CAAC,WAAW,CAAC,eAAe,EAAE,sBAAsB,GAAG,MAAM,GAAG,IAAI;IAI1E;;;;OAIG;IACH,MAAM,CAAC,eAAe,CAAC,eAAe,EAAE,sBAAsB,GAAG,MAAM,GAAG,IAAI;IAI9E;;;;OAIG;IACH,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,sBAAsB,GAAG,MAAM,GAAG,IAAI;IAIrE;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,CAAC,oCAAoC,CACzC,sBAAsB,EAAE,sBAAsB,GAC7C,MAAM,GAAG,IAAI;IAsBhB;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,YAAY,EAAE,UAAU,EAAE,GAAG,OAAO;IAI5D;;;OAGG;IACH,MAAM,CAAC,WAAW,CAAC,eAAe,EAAE,sBAAsB,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,OAAO;CAQjG"}
|
|
@@ -65,5 +65,22 @@ export default class WorkoutSessionExerciseService {
|
|
|
65
65
|
];
|
|
66
66
|
return table[sorenessScore]?.[performanceScore] ?? null;
|
|
67
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Returns true if the exercise is a deload exercise (all sets have plannedRir == null).
|
|
70
|
+
*/
|
|
71
|
+
static isDeloadExercise(exerciseSets) {
|
|
72
|
+
return exerciseSets.length > 0 && exerciseSets.every((s) => s.plannedRir == null);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Returns true if the session exercise needs review (complete session but missing late fields).
|
|
76
|
+
* Deload exercises never need review.
|
|
77
|
+
*/
|
|
78
|
+
static needsReview(sessionExercise, exerciseSets) {
|
|
79
|
+
if (WorkoutSessionExerciseService.isDeloadExercise(exerciseSets))
|
|
80
|
+
return false;
|
|
81
|
+
return (sessionExercise.rsm?.disruption == null ||
|
|
82
|
+
sessionExercise.fatigue?.unusedMusclePerformance == null ||
|
|
83
|
+
sessionExercise.sorenessScore == null);
|
|
84
|
+
}
|
|
68
85
|
}
|
|
69
86
|
//# sourceMappingURL=WorkoutSessionExerciseService.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkoutSessionExerciseService.js","sourceRoot":"","sources":["../../../../src/services/workout/SessionExercise/WorkoutSessionExerciseService.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"WorkoutSessionExerciseService.js","sourceRoot":"","sources":["../../../../src/services/workout/SessionExercise/WorkoutSessionExerciseService.ts"],"names":[],"mappings":"AAEA,OAAO,iBAAiB,MAAM,kCAAkC,CAAC;AAEjE;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,6BAA6B;IAChD;;;;OAIG;IACH,MAAM,CAAC,WAAW,CAAC,eAAuC;QACxD,OAAO,iBAAiB,CAAC,WAAW,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IAC5D,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,eAAe,CAAC,eAAuC;QAC5D,OAAO,iBAAiB,CAAC,eAAe,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IACpE,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,MAAM,CAAC,eAAuC;QACnD,OAAO,iBAAiB,CAAC,MAAM,CAAC,eAAe,CAAC,GAAG,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IAChF,CAAC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,CAAC,oCAAoC,CACzC,sBAA8C;QAE9C,MAAM,EAAE,gBAAgB,EAAE,aAAa,EAAE,GAAG,sBAAsB,CAAC;QACnE,IAAI,aAAa,IAAI,IAAI,IAAI,gBAAgB,IAAI,IAAI,EAAE,CAAC;YACtD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,gEAAgE;QAChE,0FAA0F;QAC1F,MAAM,KAAK,GAAe;YACxB,uDAAuD;YACvD,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YACb,uDAAuD;YACvD,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YACb,6DAA6D;YAC7D,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YACb,6DAA6D;YAC7D,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;SACd,CAAC;QAEF,OAAO,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC,gBAAgB,CAAC,IAAI,IAAI,CAAC;IAC1D,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,YAA0B;QAChD,OAAO,YAAY,CAAC,MAAM,GAAG,CAAC,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC,CAAC;IACpF,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,WAAW,CAAC,eAAuC,EAAE,YAA0B;QACpF,IAAI,6BAA6B,CAAC,gBAAgB,CAAC,YAAY,CAAC;YAAE,OAAO,KAAK,CAAC;QAC/E,OAAO,CACL,eAAe,CAAC,GAAG,EAAE,UAAU,IAAI,IAAI;YACvC,eAAe,CAAC,OAAO,EAAE,uBAAuB,IAAI,IAAI;YACxD,eAAe,CAAC,aAAa,IAAI,IAAI,CACtC,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { WorkoutSessionExercise } from '../../../documents/workout/WorkoutSessionExercise.js';
|
|
2
|
+
import type { WorkoutSet } from '../../../documents/workout/WorkoutSet.js';
|
|
2
3
|
import WorkoutSFRService from '../util/SFR/WorkoutSFRService.js';
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -74,4 +75,24 @@ export default class WorkoutSessionExerciseService {
|
|
|
74
75
|
|
|
75
76
|
return table[sorenessScore]?.[performanceScore] ?? null;
|
|
76
77
|
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Returns true if the exercise is a deload exercise (all sets have plannedRir == null).
|
|
81
|
+
*/
|
|
82
|
+
static isDeloadExercise(exerciseSets: WorkoutSet[]): boolean {
|
|
83
|
+
return exerciseSets.length > 0 && exerciseSets.every((s) => s.plannedRir == null);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Returns true if the session exercise needs review (complete session but missing late fields).
|
|
88
|
+
* Deload exercises never need review.
|
|
89
|
+
*/
|
|
90
|
+
static needsReview(sessionExercise: WorkoutSessionExercise, exerciseSets: WorkoutSet[]): boolean {
|
|
91
|
+
if (WorkoutSessionExerciseService.isDeloadExercise(exerciseSets)) return false;
|
|
92
|
+
return (
|
|
93
|
+
sessionExercise.rsm?.disruption == null ||
|
|
94
|
+
sessionExercise.fatigue?.unusedMusclePerformance == null ||
|
|
95
|
+
sessionExercise.sorenessScore == null
|
|
96
|
+
);
|
|
97
|
+
}
|
|
77
98
|
}
|
|
@@ -2,6 +2,7 @@ import type { WorkoutExercise } from '../../../documents/workout/WorkoutExercise
|
|
|
2
2
|
import type { WorkoutExerciseCalibration } from '../../../documents/workout/WorkoutExerciseCalibration.js';
|
|
3
3
|
import type { WorkoutSession } from '../../../documents/workout/WorkoutSession.js';
|
|
4
4
|
import type { WorkoutSessionExercise } from '../../../documents/workout/WorkoutSessionExercise.js';
|
|
5
|
+
import { type WorkoutSet } from '../../../documents/workout/WorkoutSet.js';
|
|
5
6
|
import type WorkoutMesocyclePlanContext from '../Mesocycle/WorkoutMesocyclePlanContext.js';
|
|
6
7
|
export default class WorkoutSetService {
|
|
7
8
|
/**
|
|
@@ -21,9 +22,15 @@ export default class WorkoutSetService {
|
|
|
21
22
|
microcycleIndex: number;
|
|
22
23
|
sessionIndex: number;
|
|
23
24
|
setCount: number;
|
|
24
|
-
targetRir: number;
|
|
25
|
+
targetRir: number | null;
|
|
25
26
|
isDeloadMicrocycle: boolean;
|
|
26
27
|
}): void;
|
|
28
|
+
/**
|
|
29
|
+
* Returns true if the set has been logged (has actual performance data).
|
|
30
|
+
* A set is considered completed when actualReps and actualWeight are recorded,
|
|
31
|
+
* and either rir is recorded or no plannedRir was expected (deload sets).
|
|
32
|
+
*/
|
|
33
|
+
static isCompleted(set: WorkoutSet): boolean;
|
|
27
34
|
/**
|
|
28
35
|
* Generates the planned reps and weight for a specific set within a session exercise, only
|
|
29
36
|
* taking into account simple -2 reps drop per set logic, and deload modifications.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkoutSetService.d.ts","sourceRoot":"","sources":["../../../../src/services/workout/Set/WorkoutSetService.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,eAAe,EAChB,MAAM,+CAA+C,CAAC;AACvD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,0DAA0D,CAAC;AAC3G,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8CAA8C,CAAC;AACnF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sDAAsD,CAAC;
|
|
1
|
+
{"version":3,"file":"WorkoutSetService.d.ts","sourceRoot":"","sources":["../../../../src/services/workout/Set/WorkoutSetService.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,eAAe,EAChB,MAAM,+CAA+C,CAAC;AACvD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,0DAA0D,CAAC;AAC3G,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8CAA8C,CAAC;AACnF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sDAAsD,CAAC;AACnG,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAG7F,OAAO,KAAK,2BAA2B,MAAM,6CAA6C,CAAC;AAE3F,MAAM,CAAC,OAAO,OAAO,iBAAiB;IACpC;;;;;;;OAOG;IACH,MAAM,CAAC,8BAA8B,CAAC,EACpC,OAAO,EACP,QAAQ,EACR,WAAW,EACX,OAAO,EACP,eAAe,EACf,eAAe,EACf,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,kBAAkB,EACnB,EAAE;QACD,OAAO,EAAE,2BAA2B,CAAC;QACrC,QAAQ,EAAE,eAAe,CAAC;QAC1B,WAAW,EAAE,0BAA0B,CAAC;QACxC,OAAO,EAAE,cAAc,CAAC;QACxB,eAAe,EAAE,sBAAsB,CAAC;QACxC,eAAe,EAAE,MAAM,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,kBAAkB,EAAE,OAAO,CAAC;KAC7B,GAAG,IAAI;IAoDR;;;;OAIG;IACH,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO;IAQ5C;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,wBAAwB;CAiDxC"}
|
|
@@ -46,6 +46,16 @@ export default class WorkoutSetService {
|
|
|
46
46
|
}
|
|
47
47
|
context.setsToCreate.push(...sets);
|
|
48
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Returns true if the set has been logged (has actual performance data).
|
|
51
|
+
* A set is considered completed when actualReps and actualWeight are recorded,
|
|
52
|
+
* and either rir is recorded or no plannedRir was expected (deload sets).
|
|
53
|
+
*/
|
|
54
|
+
static isCompleted(set) {
|
|
55
|
+
return (set.actualReps != null &&
|
|
56
|
+
set.actualWeight != null &&
|
|
57
|
+
(set.rir != null || set.plannedRir == null));
|
|
58
|
+
}
|
|
49
59
|
/**
|
|
50
60
|
* Generates the planned reps and weight for a specific set within a session exercise, only
|
|
51
61
|
* taking into account simple -2 reps drop per set logic, and deload modifications.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkoutSetService.js","sourceRoot":"","sources":["../../../../src/services/workout/Set/WorkoutSetService.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WorkoutSetService.js","sourceRoot":"","sources":["../../../../src/services/workout/Set/WorkoutSetService.ts"],"names":[],"mappings":"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"}
|
|
@@ -40,7 +40,7 @@ export default class WorkoutSetService {
|
|
|
40
40
|
microcycleIndex: number;
|
|
41
41
|
sessionIndex: number;
|
|
42
42
|
setCount: number;
|
|
43
|
-
targetRir: number;
|
|
43
|
+
targetRir: number | null;
|
|
44
44
|
isDeloadMicrocycle: boolean;
|
|
45
45
|
}): void {
|
|
46
46
|
const equipment = context.equipmentMap.get(exercise.workoutEquipmentTypeId);
|
|
@@ -94,6 +94,19 @@ export default class WorkoutSetService {
|
|
|
94
94
|
context.setsToCreate.push(...sets);
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Returns true if the set has been logged (has actual performance data).
|
|
99
|
+
* A set is considered completed when actualReps and actualWeight are recorded,
|
|
100
|
+
* and either rir is recorded or no plannedRir was expected (deload sets).
|
|
101
|
+
*/
|
|
102
|
+
static isCompleted(set: WorkoutSet): boolean {
|
|
103
|
+
return (
|
|
104
|
+
set.actualReps != null &&
|
|
105
|
+
set.actualWeight != null &&
|
|
106
|
+
(set.rir != null || set.plannedRir == null)
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
97
110
|
/**
|
|
98
111
|
* Generates the planned reps and weight for a specific set within a session exercise, only
|
|
99
112
|
* taking into account simple -2 reps drop per set logic, and deload modifications.
|
package/package.json
CHANGED