@sency/react-native-smkit-ui 2.2.0 → 2.2.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.
- package/README.md +218 -65
- package/android/build.gradle +3 -1
- package/android/src/main/java/com/smkituilibrary/SmkitUiLibraryModule.kt +237 -3
- package/android/src/main/java/com/smkituilibrary/mapper/SMMapper.kt +70 -10
- package/android/src/main/java/com/smkituilibrary/model/SMKitExercise.kt +40 -0
- package/android/src/main/java/com/smkituilibrary/model/SMKitWorkout.kt +8 -0
- package/android/src/main/java/com/smkituilibrary/model/SMKitWorkoutConfig.kt +2 -0
- package/android/src/main/java/com/smkituilibrary/model/SMUserData.kt +5 -1
- package/ios/SMKitUIManager.mm +33 -11
- package/ios/SMKitUIManager.swift +243 -26
- package/lib/commonjs/SMWorkout.js +239 -177
- package/lib/commonjs/SMWorkout.js.map +1 -1
- package/lib/commonjs/index.js +187 -5
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/SMWorkout.js +232 -181
- package/lib/module/SMWorkout.js.map +1 -1
- package/lib/module/index.js +165 -5
- package/lib/module/index.js.map +1 -1
- package/package.json +2 -2
- package/react-native-smkit-ui.podspec +2 -2
- package/src/SMWorkout.tsx +353 -176
- package/src/index.tsx +167 -8
- package/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
- package/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +0 -0
- package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +0 -1
- package/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +0 -2
- package/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +0 -2
- package/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +0 -2
- package/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +0 -1
- package/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +0 -1
package/src/SMWorkout.tsx
CHANGED
|
@@ -1,7 +1,35 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
type JsonPrimitive = string | number | boolean | null;
|
|
2
|
+
type JsonValue = JsonPrimitive | JsonObject | JsonValue[];
|
|
3
|
+
type JsonObject = { [key: string]: JsonValue | undefined };
|
|
4
|
+
|
|
5
|
+
function withoutUndefined(value: JsonObject): { [key: string]: JsonValue } {
|
|
6
|
+
return Object.entries(value).reduce<{ [key: string]: JsonValue }>((result, [key, item]) => {
|
|
7
|
+
if (item !== undefined) {
|
|
8
|
+
result[key] = item;
|
|
9
|
+
}
|
|
10
|
+
return result;
|
|
11
|
+
}, {});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function serializeGuidanceVideoSegments(
|
|
15
|
+
segments: Record<string, GuidanceVideoSegment | GuidanceVideoSegmentConfig> | undefined
|
|
16
|
+
): JsonObject | undefined {
|
|
17
|
+
if (segments === undefined) {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return Object.entries(segments).reduce<JsonObject>((result, [key, segment]) => {
|
|
22
|
+
result[key] = segment instanceof GuidanceVideoSegment
|
|
23
|
+
? segment.toJSON()
|
|
24
|
+
: withoutUndefined({
|
|
25
|
+
kind: segment.kind,
|
|
26
|
+
startSeconds: segment.startSeconds,
|
|
27
|
+
endSeconds: segment.endSeconds ?? undefined,
|
|
28
|
+
});
|
|
29
|
+
return result;
|
|
30
|
+
}, {});
|
|
31
|
+
}
|
|
32
|
+
|
|
5
33
|
export enum AssessmentTypes {
|
|
6
34
|
Fitness = 'fitness',
|
|
7
35
|
Custom = 'custom',
|
|
@@ -19,59 +47,39 @@ export enum PauseType {
|
|
|
19
47
|
Switch = 'switchExercise',
|
|
20
48
|
}
|
|
21
49
|
|
|
22
|
-
/**
|
|
23
|
-
* Enum representing UI elements that can be displayed during workouts.
|
|
24
|
-
* @enum {string}
|
|
25
|
-
*/
|
|
26
50
|
export enum UIElement {
|
|
27
51
|
RepsCounter = 'repsCounter',
|
|
28
52
|
Timer = 'timer',
|
|
29
53
|
GaugeOfMotion = 'gaugeOfMotion',
|
|
54
|
+
Skeleton = 'skeleton',
|
|
55
|
+
HoldingPosition = 'holdingPosition',
|
|
56
|
+
CountdownTimer = 'countdownTimer',
|
|
57
|
+
QuickMotion = 'quickMotion',
|
|
30
58
|
}
|
|
31
59
|
|
|
32
|
-
/**
|
|
33
|
-
* Enum representing body zones targeted in workouts.
|
|
34
|
-
* @enum {string}
|
|
35
|
-
*/
|
|
36
60
|
export enum BodyZone {
|
|
37
61
|
UpperBody = 'UpperBody',
|
|
38
62
|
LowerBody = 'LowerBody',
|
|
39
63
|
FullBody = 'FullBody',
|
|
40
64
|
}
|
|
41
65
|
|
|
42
|
-
/**
|
|
43
|
-
* Enum representing workout difficulty levels.
|
|
44
|
-
* @enum {string}
|
|
45
|
-
*/
|
|
46
66
|
export enum WorkoutDifficulty {
|
|
47
67
|
LowDifficulty = 'LowDifficulty',
|
|
48
68
|
MidDifficulty = 'MidDifficulty',
|
|
49
69
|
HighDifficulty = 'HighDifficulty',
|
|
50
70
|
}
|
|
51
71
|
|
|
52
|
-
/**
|
|
53
|
-
* Enum representing workout durations.
|
|
54
|
-
* @enum {string}
|
|
55
|
-
*/
|
|
56
72
|
export enum WorkoutDuration {
|
|
57
73
|
Short = 'Short',
|
|
58
74
|
Long = 'Long',
|
|
59
75
|
}
|
|
60
76
|
|
|
61
|
-
/**
|
|
62
|
-
* Enum representing different types of scoring methods.
|
|
63
|
-
* @enum {string}
|
|
64
|
-
*/
|
|
65
77
|
export enum ScoringType {
|
|
66
78
|
Rom = 'rom',
|
|
67
79
|
Time = 'time',
|
|
68
80
|
Reps = 'reps',
|
|
69
81
|
}
|
|
70
82
|
|
|
71
|
-
/**
|
|
72
|
-
* Enum representing gender options for user data.
|
|
73
|
-
* @enum {string}
|
|
74
|
-
*/
|
|
75
83
|
export enum Gender {
|
|
76
84
|
Female = 'Female',
|
|
77
85
|
Male = 'Male',
|
|
@@ -83,22 +91,49 @@ export enum Language {
|
|
|
83
91
|
Hebrew = 'he',
|
|
84
92
|
}
|
|
85
93
|
|
|
86
|
-
/**
|
|
87
|
-
* Enum representing the exercise rep counter prefrence.
|
|
88
|
-
* @enum {string}
|
|
89
|
-
*/
|
|
90
94
|
export enum CounterPreferences {
|
|
91
95
|
Default = 'Default',
|
|
92
96
|
PerfectOnly = 'PerfectOnly',
|
|
93
97
|
}
|
|
94
98
|
|
|
95
|
-
/**
|
|
96
|
-
* Enum representing the workout couser type.
|
|
97
|
-
* @enum {string}
|
|
98
|
-
*/
|
|
99
99
|
export enum EndExercisePreferences {
|
|
100
|
-
Default = 'Default',
|
|
101
|
-
TargetBased = 'TargetBased',
|
|
100
|
+
Default = 'Default',
|
|
101
|
+
TargetBased = 'TargetBased',
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export enum ColorTheme {
|
|
105
|
+
Blue = 'blue',
|
|
106
|
+
Green = 'green',
|
|
107
|
+
Purple = 'purple',
|
|
108
|
+
Orange = 'orange',
|
|
109
|
+
Silver = 'silver',
|
|
110
|
+
Gold = 'gold',
|
|
111
|
+
Pink = 'pink',
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export enum PoseModelChoice {
|
|
115
|
+
AdaptiveChoice = 'AdaptiveChoice',
|
|
116
|
+
Prime = 'Prime',
|
|
117
|
+
Pro = 'Pro',
|
|
118
|
+
Lite = 'Lite',
|
|
119
|
+
UltraLite = 'UltraLite',
|
|
120
|
+
Basic = 'Basic',
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export enum PhonePosition {
|
|
124
|
+
Floor = 'floor',
|
|
125
|
+
Elevated = 'elevated',
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export enum RowingFeedbackLevel {
|
|
129
|
+
Expert = 'expert',
|
|
130
|
+
Advanced = 'advanced',
|
|
131
|
+
Beginner = 'beginner',
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export enum GuidanceVideoSegmentKind {
|
|
135
|
+
Freeze = 'freeze',
|
|
136
|
+
Play = 'play',
|
|
102
137
|
}
|
|
103
138
|
|
|
104
139
|
export enum SkeletonPreset {
|
|
@@ -181,77 +216,108 @@ export class SkeletonConfig {
|
|
|
181
216
|
animationDuration?: number;
|
|
182
217
|
}
|
|
183
218
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
name: string | null;
|
|
200
|
-
workoutIntro: string | null;
|
|
201
|
-
soundtrack: string | null;
|
|
202
|
-
exercises: SMExercise[];
|
|
203
|
-
getInFrame: string | null;
|
|
204
|
-
bodycalFinished: string | null;
|
|
205
|
-
workoutClosure: string | null;
|
|
219
|
+
export type QuickMotionParams = {
|
|
220
|
+
validityWindow?: number;
|
|
221
|
+
checkInterval?: number;
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
export type GuidanceVideoSegmentConfig = {
|
|
225
|
+
kind: GuidanceVideoSegmentKind | 'freeze' | 'play';
|
|
226
|
+
startSeconds: number;
|
|
227
|
+
endSeconds?: number | null;
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
export class GuidanceVideoSegment {
|
|
231
|
+
kind: GuidanceVideoSegmentKind | 'freeze' | 'play';
|
|
232
|
+
startSeconds: number;
|
|
233
|
+
endSeconds: number | null;
|
|
206
234
|
|
|
207
235
|
constructor(
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
soundtrack: string | null,
|
|
212
|
-
exercises: SMExercise[],
|
|
213
|
-
getInFrame: string | null,
|
|
214
|
-
bodycalFinished: string | null,
|
|
215
|
-
workoutClosure: string | null
|
|
236
|
+
kind: GuidanceVideoSegmentKind | 'freeze' | 'play',
|
|
237
|
+
startSeconds: number,
|
|
238
|
+
endSeconds: number | null = null
|
|
216
239
|
) {
|
|
217
|
-
this.
|
|
218
|
-
this.
|
|
219
|
-
this.
|
|
220
|
-
this.soundtrack = soundtrack || null;
|
|
221
|
-
this.exercises = exercises;
|
|
222
|
-
this.getInFrame = getInFrame || null;
|
|
223
|
-
this.bodycalFinished = bodycalFinished || null;
|
|
224
|
-
this.workoutClosure = workoutClosure || null;
|
|
240
|
+
this.kind = kind;
|
|
241
|
+
this.startSeconds = startSeconds;
|
|
242
|
+
this.endSeconds = endSeconds;
|
|
225
243
|
}
|
|
226
244
|
|
|
227
|
-
|
|
228
|
-
return
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
245
|
+
static freeze(at: number): GuidanceVideoSegment {
|
|
246
|
+
return new GuidanceVideoSegment(GuidanceVideoSegmentKind.Freeze, at, at);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
static play(from: number, to: number | null = null): GuidanceVideoSegment {
|
|
250
|
+
return new GuidanceVideoSegment(GuidanceVideoSegmentKind.Play, from, to);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
toJSON(): { [key: string]: JsonValue } {
|
|
254
|
+
return withoutUndefined({
|
|
255
|
+
kind: this.kind,
|
|
256
|
+
startSeconds: this.startSeconds,
|
|
257
|
+
endSeconds: this.endSeconds ?? undefined,
|
|
237
258
|
});
|
|
238
259
|
}
|
|
239
260
|
}
|
|
240
261
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
262
|
+
export type StretchSetConfigOptions = {
|
|
263
|
+
enabled?: boolean;
|
|
264
|
+
restSecondsBetweenStretches?: number;
|
|
265
|
+
introSoundKey?: string | null;
|
|
266
|
+
positionDetectors?: string[] | null;
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
export class StretchSetConfig {
|
|
270
|
+
enabled: boolean;
|
|
271
|
+
repetitions: number;
|
|
272
|
+
secondsPerStretch: number;
|
|
273
|
+
restSecondsBetweenStretches: number;
|
|
274
|
+
introSoundKey: string | null;
|
|
275
|
+
positionDetectors: string[] | null;
|
|
276
|
+
|
|
277
|
+
constructor(
|
|
278
|
+
repetitions: number,
|
|
279
|
+
secondsPerStretch: number,
|
|
280
|
+
options: StretchSetConfigOptions = {}
|
|
281
|
+
) {
|
|
282
|
+
this.enabled = options.enabled ?? true;
|
|
283
|
+
this.repetitions = repetitions;
|
|
284
|
+
this.secondsPerStretch = secondsPerStretch;
|
|
285
|
+
this.restSecondsBetweenStretches = options.restSecondsBetweenStretches ?? 3;
|
|
286
|
+
this.introSoundKey = options.introSoundKey ?? null;
|
|
287
|
+
this.positionDetectors = options.positionDetectors ?? null;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
toJSON(): { [key: string]: JsonValue } {
|
|
291
|
+
return withoutUndefined({
|
|
292
|
+
enabled: this.enabled,
|
|
293
|
+
repetitions: this.repetitions,
|
|
294
|
+
secondsPerStretch: this.secondsPerStretch,
|
|
295
|
+
restSecondsBetweenStretches: this.restSecondsBetweenStretches,
|
|
296
|
+
introSoundKey: this.introSoundKey,
|
|
297
|
+
positionDetectors: this.positionDetectors,
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export type ExerciseOptions = {
|
|
303
|
+
shortIntro?: boolean;
|
|
304
|
+
quickMotionParams?: QuickMotionParams | null;
|
|
305
|
+
rowingFeedbackLevel?: RowingFeedbackLevel | number | null;
|
|
306
|
+
phonePosition?: PhonePosition | null;
|
|
307
|
+
guidanceMode?: boolean | null;
|
|
308
|
+
useWideAngleCamera?: boolean | null;
|
|
309
|
+
playPreExerciseCountdown?: boolean;
|
|
310
|
+
playRepMilestoneVoice?: boolean;
|
|
311
|
+
repMilestoneInterval?: number;
|
|
312
|
+
playSoundOnEachRep?: boolean;
|
|
313
|
+
adaptiveRomFeedbackEnabled?: boolean;
|
|
314
|
+
adaptiveRomWarmupReps?: number;
|
|
315
|
+
guidanceVideoSegments?: Record<string, GuidanceVideoSegment | GuidanceVideoSegmentConfig> | null;
|
|
316
|
+
stretchSetConfig?: StretchSetConfig | null;
|
|
317
|
+
side?: string | null;
|
|
318
|
+
};
|
|
319
|
+
|
|
244
320
|
export class SMExercise {
|
|
245
|
-
/**
|
|
246
|
-
* @param {string | null} prettyName - Name of the exercise.
|
|
247
|
-
* @param {number | null} totalSeconds - Duration of the exercise in seconds.
|
|
248
|
-
* @param {string | null} videoInstruction - Video instruction URL.
|
|
249
|
-
* @param {string | null} exerciseIntro - URL for exercise intro sound.
|
|
250
|
-
* @param {UIElement[] | null} uiElements - List of UI elements for this exercise.
|
|
251
|
-
* @param {string} detector - Name of the detector for tracking exercise movement.
|
|
252
|
-
* @param {string | null} exerciseClosure - URL for exercise closer sound.
|
|
253
|
-
* @param {SMScoringParams | null} scoringParams - Parameters for exercise scoring.
|
|
254
|
-
*/
|
|
255
321
|
detector: string;
|
|
256
322
|
uiElements: UIElement[] | null;
|
|
257
323
|
videoInstruction: string | null;
|
|
@@ -260,6 +326,7 @@ export class SMExercise {
|
|
|
260
326
|
exerciseIntro: string | null;
|
|
261
327
|
exerciseClosure: string | null;
|
|
262
328
|
scoringParams: SMScoringParams | null;
|
|
329
|
+
options: ExerciseOptions;
|
|
263
330
|
|
|
264
331
|
constructor(
|
|
265
332
|
prettyName: string | null,
|
|
@@ -269,39 +336,55 @@ export class SMExercise {
|
|
|
269
336
|
uiElements: UIElement[] | null,
|
|
270
337
|
detector: string,
|
|
271
338
|
exerciseClosure: string | null,
|
|
272
|
-
scoringParams: SMScoringParams | null
|
|
339
|
+
scoringParams: SMScoringParams | null,
|
|
340
|
+
options: ExerciseOptions = {}
|
|
273
341
|
) {
|
|
274
|
-
this.prettyName = prettyName
|
|
275
|
-
this.totalSeconds = totalSeconds
|
|
276
|
-
this.videoInstruction = videoInstruction
|
|
277
|
-
this.exerciseIntro = exerciseIntro
|
|
278
|
-
this.uiElements = uiElements
|
|
342
|
+
this.prettyName = prettyName ?? null;
|
|
343
|
+
this.totalSeconds = totalSeconds ?? null;
|
|
344
|
+
this.videoInstruction = videoInstruction ?? null;
|
|
345
|
+
this.exerciseIntro = exerciseIntro ?? null;
|
|
346
|
+
this.uiElements = uiElements ?? null;
|
|
279
347
|
this.detector = detector;
|
|
280
|
-
this.exerciseClosure = exerciseClosure
|
|
281
|
-
this.scoringParams = scoringParams
|
|
348
|
+
this.exerciseClosure = exerciseClosure ?? null;
|
|
349
|
+
this.scoringParams = scoringParams ?? null;
|
|
350
|
+
this.options = options;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
toJSON(): { [key: string]: JsonValue } {
|
|
354
|
+
return withoutUndefined({
|
|
355
|
+
name: this.prettyName,
|
|
356
|
+
prettyName: this.prettyName,
|
|
357
|
+
totalSeconds: this.totalSeconds,
|
|
358
|
+
videoInstruction: this.videoInstruction,
|
|
359
|
+
exerciseIntro: this.exerciseIntro,
|
|
360
|
+
uiElements: this.uiElements,
|
|
361
|
+
detector: this.detector,
|
|
362
|
+
exerciseClosure: this.exerciseClosure,
|
|
363
|
+
scoringParams: this.scoringParams?.toJSON() ?? null,
|
|
364
|
+
shortIntro: this.options.shortIntro,
|
|
365
|
+
quickMotionParams: this.options.quickMotionParams ?? undefined,
|
|
366
|
+
rowingFeedbackLevel: this.options.rowingFeedbackLevel ?? undefined,
|
|
367
|
+
phonePosition: this.options.phonePosition ?? undefined,
|
|
368
|
+
guidanceMode: this.options.guidanceMode ?? undefined,
|
|
369
|
+
useWideAngleCamera: this.options.useWideAngleCamera ?? undefined,
|
|
370
|
+
playPreExerciseCountdown: this.options.playPreExerciseCountdown,
|
|
371
|
+
playRepMilestoneVoice: this.options.playRepMilestoneVoice,
|
|
372
|
+
repMilestoneInterval: this.options.repMilestoneInterval,
|
|
373
|
+
playSoundOnEachRep: this.options.playSoundOnEachRep,
|
|
374
|
+
adaptiveRomFeedbackEnabled: this.options.adaptiveRomFeedbackEnabled,
|
|
375
|
+
adaptiveRomWarmupReps: this.options.adaptiveRomWarmupReps,
|
|
376
|
+
guidanceVideoSegments: this.options.guidanceVideoSegments === null
|
|
377
|
+
? null
|
|
378
|
+
: serializeGuidanceVideoSegments(this.options.guidanceVideoSegments),
|
|
379
|
+
stretchSetConfig: this.options.stretchSetConfig?.toJSON() ?? (this.options.stretchSetConfig === null ? null : undefined),
|
|
380
|
+
side: this.options.side ?? undefined,
|
|
381
|
+
});
|
|
282
382
|
}
|
|
283
383
|
}
|
|
284
384
|
|
|
285
|
-
|
|
286
|
-
* Class representing an exercise in an assessment.
|
|
287
|
-
*/
|
|
288
|
-
export class SMAssessmentExercise extends SMExercise {
|
|
289
|
-
/**
|
|
290
|
-
* @param {string | null} prettyName - Name of the exercise.
|
|
291
|
-
* @param {number | null} totalSeconds - Duration of the exercise in seconds.
|
|
292
|
-
* @param {string | null} videoInstruction - Video instruction URL.
|
|
293
|
-
* @param {string | null} exerciseIntro - URL for exercise intro sound.
|
|
294
|
-
* @param {UIElement[] | null} uiElements - List of UI elements for this exercise.
|
|
295
|
-
* @param {string} detector - Name of the detector for tracking exercise movement.
|
|
296
|
-
* @param {string | null} exerciseClosure - URL for exercise closer sound.
|
|
297
|
-
* @param {SMScoringParams | null} scoringParams - Parameters for exercise scoring.
|
|
298
|
-
* @param {string | null} closureFailedSound - Applicable only for ClouserTarget.TargetBased, URL for exercise closure sound If you did not reach clouser target.
|
|
299
|
-
* @param {string | null} summaryTitle - Title for the exercise summary.
|
|
300
|
-
* @param {string | null} summarySubTitle - Subtitle for the exercise summary.
|
|
301
|
-
* @param {string | null} summaryMainMetricTitle - Main metric title in the summary.
|
|
302
|
-
* @param {string | null} summaryMainMetricSubTitle - Main metric subtitle in the summary.
|
|
303
|
-
*/
|
|
385
|
+
export type AssessmentExerciseOptions = ExerciseOptions;
|
|
304
386
|
|
|
387
|
+
export class SMAssessmentExercise extends SMExercise {
|
|
305
388
|
closureFailedSound: string | null;
|
|
306
389
|
summaryTitle: string | null;
|
|
307
390
|
summarySubTitle: string | null;
|
|
@@ -321,9 +404,9 @@ export class SMAssessmentExercise extends SMExercise {
|
|
|
321
404
|
summaryTitle: string | null,
|
|
322
405
|
summarySubTitle: string | null,
|
|
323
406
|
summaryMainMetricTitle: string | null,
|
|
324
|
-
summaryMainMetricSubTitle: string | null
|
|
407
|
+
summaryMainMetricSubTitle: string | null,
|
|
408
|
+
options: AssessmentExerciseOptions = {}
|
|
325
409
|
) {
|
|
326
|
-
// Call the constructor of the parent class (SMExercise)
|
|
327
410
|
super(
|
|
328
411
|
prettyName,
|
|
329
412
|
totalSeconds,
|
|
@@ -332,30 +415,108 @@ export class SMAssessmentExercise extends SMExercise {
|
|
|
332
415
|
uiElements,
|
|
333
416
|
detector,
|
|
334
417
|
exerciseClosure,
|
|
335
|
-
scoringParams
|
|
418
|
+
scoringParams,
|
|
419
|
+
options
|
|
336
420
|
);
|
|
337
421
|
|
|
338
|
-
|
|
339
|
-
this.
|
|
340
|
-
this.
|
|
341
|
-
this.
|
|
342
|
-
this.
|
|
343
|
-
|
|
422
|
+
this.closureFailedSound = closureFailedSound ?? null;
|
|
423
|
+
this.summaryTitle = summaryTitle ?? null;
|
|
424
|
+
this.summarySubTitle = summarySubTitle ?? null;
|
|
425
|
+
this.summaryMainMetricTitle = summaryMainMetricTitle ?? null;
|
|
426
|
+
this.summaryMainMetricSubTitle = summaryMainMetricSubTitle ?? null;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
override toJSON(): { [key: string]: JsonValue } {
|
|
430
|
+
return withoutUndefined({
|
|
431
|
+
...super.toJSON(),
|
|
432
|
+
closureFailedSound: this.closureFailedSound,
|
|
433
|
+
summaryTitle: this.summaryTitle,
|
|
434
|
+
summarySubTitle: this.summarySubTitle,
|
|
435
|
+
summaryMainMetricTitle: this.summaryMainMetricTitle,
|
|
436
|
+
summaryMainMetricSubTitle: this.summaryMainMetricSubTitle,
|
|
437
|
+
summaryTitleMainMetric: this.summaryMainMetricTitle,
|
|
438
|
+
summarySubTitleMainMetric: this.summaryMainMetricSubTitle,
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
export class WorkoutContinuation {
|
|
444
|
+
introSoundKey: string | null;
|
|
445
|
+
interactionUnlockSoundKey: string;
|
|
446
|
+
exercises: SMExercise[];
|
|
447
|
+
|
|
448
|
+
constructor(
|
|
449
|
+
interactionUnlockSoundKey: string,
|
|
450
|
+
exercises: SMExercise[],
|
|
451
|
+
introSoundKey: string | null = null
|
|
452
|
+
) {
|
|
453
|
+
this.introSoundKey = introSoundKey ?? null;
|
|
454
|
+
this.interactionUnlockSoundKey = interactionUnlockSoundKey;
|
|
455
|
+
this.exercises = exercises;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
toJSON(): { [key: string]: JsonValue } {
|
|
459
|
+
return withoutUndefined({
|
|
460
|
+
introSoundKey: this.introSoundKey,
|
|
461
|
+
interactionUnlockSoundKey: this.interactionUnlockSoundKey,
|
|
462
|
+
exercises: this.exercises.map((exercise) => exercise.toJSON()),
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
export class SMWorkout {
|
|
468
|
+
id: string | null;
|
|
469
|
+
name: string | null;
|
|
470
|
+
workoutIntro: string | null;
|
|
471
|
+
soundtrack: string | null;
|
|
472
|
+
exercises: SMExercise[];
|
|
473
|
+
getInFrame: string | null;
|
|
474
|
+
bodycalFinished: string | null;
|
|
475
|
+
workoutClosure: string | null;
|
|
476
|
+
continuation: WorkoutContinuation | null;
|
|
477
|
+
|
|
478
|
+
constructor(
|
|
479
|
+
id: string | null,
|
|
480
|
+
name: string | null,
|
|
481
|
+
workoutIntro: string | null,
|
|
482
|
+
soundtrack: string | null,
|
|
483
|
+
exercises: SMExercise[],
|
|
484
|
+
getInFrame: string | null,
|
|
485
|
+
bodycalFinished: string | null,
|
|
486
|
+
workoutClosure: string | null,
|
|
487
|
+
continuation: WorkoutContinuation | null = null
|
|
488
|
+
) {
|
|
489
|
+
this.id = id ?? null;
|
|
490
|
+
this.name = name ?? null;
|
|
491
|
+
this.workoutIntro = workoutIntro ?? null;
|
|
492
|
+
this.soundtrack = soundtrack ?? null;
|
|
493
|
+
this.exercises = exercises;
|
|
494
|
+
this.getInFrame = getInFrame ?? null;
|
|
495
|
+
this.bodycalFinished = bodycalFinished ?? null;
|
|
496
|
+
this.workoutClosure = workoutClosure ?? null;
|
|
497
|
+
this.continuation = continuation ?? null;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
toJSON(): { [key: string]: JsonValue } {
|
|
501
|
+
return withoutUndefined({
|
|
502
|
+
id: this.id,
|
|
503
|
+
name: this.name,
|
|
504
|
+
workoutIntro: this.workoutIntro,
|
|
505
|
+
soundtrack: this.soundtrack,
|
|
506
|
+
exercises: this.exercises.map((exercise) => exercise.toJSON()),
|
|
507
|
+
getInFrame: this.getInFrame,
|
|
508
|
+
bodycalFinished: this.bodycalFinished,
|
|
509
|
+
workoutClosure: this.workoutClosure,
|
|
510
|
+
continuation: this.continuation?.toJSON() ?? (this.continuation === null ? null : undefined),
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
toJson(): string {
|
|
515
|
+
return JSON.stringify(this.toJSON());
|
|
344
516
|
}
|
|
345
517
|
}
|
|
346
518
|
|
|
347
|
-
/**
|
|
348
|
-
* Class representing scoring parameters for an exercise.
|
|
349
|
-
*/
|
|
350
519
|
export class SMScoringParams {
|
|
351
|
-
/**
|
|
352
|
-
* @param {ScoringType | null} type - Type of scoring (e.g., ROM, time, reps).
|
|
353
|
-
* @param {number | null} scoreFactor - Factor to adjust the score.
|
|
354
|
-
* @param {number | null} targetTime - Target time for time-based scoring.
|
|
355
|
-
* @param {number | null} targetReps - Target reps for rep-based scoring.
|
|
356
|
-
* @param {string | null} targetRom - Range of motion target for ROM-based scoring.
|
|
357
|
-
* @param {string[] | null} passCriteria - List of criteria required to pass.
|
|
358
|
-
*/
|
|
359
520
|
type: ScoringType | null;
|
|
360
521
|
scoreFactor: number | null;
|
|
361
522
|
targetTime: number | null;
|
|
@@ -371,33 +532,40 @@ export class SMScoringParams {
|
|
|
371
532
|
targetRom: string | null,
|
|
372
533
|
passCriteria: string[] | null
|
|
373
534
|
) {
|
|
374
|
-
this.type = type
|
|
375
|
-
this.scoreFactor = scoreFactor
|
|
376
|
-
this.targetTime = targetTime
|
|
377
|
-
this.targetReps = targetReps
|
|
378
|
-
this.targetRom = targetRom
|
|
379
|
-
this.passCriteria = passCriteria
|
|
535
|
+
this.type = type ?? null;
|
|
536
|
+
this.scoreFactor = scoreFactor ?? null;
|
|
537
|
+
this.targetTime = targetTime ?? null;
|
|
538
|
+
this.targetReps = targetReps ?? null;
|
|
539
|
+
this.targetRom = targetRom ?? null;
|
|
540
|
+
this.passCriteria = passCriteria ?? null;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
toJSON(): { [key: string]: JsonValue } {
|
|
544
|
+
return withoutUndefined({
|
|
545
|
+
type: this.type,
|
|
546
|
+
scoreFactor: this.scoreFactor,
|
|
547
|
+
targetTime: this.targetTime,
|
|
548
|
+
targetReps: this.targetReps,
|
|
549
|
+
targetRom: this.targetRom,
|
|
550
|
+
passCriteria: this.passCriteria,
|
|
551
|
+
});
|
|
380
552
|
}
|
|
381
553
|
}
|
|
382
554
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
555
|
+
export type WorkoutConfigOptions = {
|
|
556
|
+
phonePosition?: PhonePosition;
|
|
557
|
+
shortIntro?: boolean;
|
|
558
|
+
};
|
|
559
|
+
|
|
386
560
|
export class WorkoutConfig {
|
|
387
|
-
/**
|
|
388
|
-
* @param {number} week - Week number in the program.
|
|
389
|
-
* @param {BodyZone} bodyZone - Targeted body zone for the workout.
|
|
390
|
-
* @param {WorkoutDifficulty} difficultyLevel - Difficulty level of the workout.
|
|
391
|
-
* @param {WorkoutDuration} workoutDuration - Duration of the workout.
|
|
392
|
-
* @param {Language} language - The session language
|
|
393
|
-
* @param {string} programID - Unique identifier for the workout program.
|
|
394
|
-
*/
|
|
395
561
|
week: number;
|
|
396
562
|
bodyZone: BodyZone;
|
|
397
563
|
difficultyLevel: WorkoutDifficulty;
|
|
398
564
|
workoutDuration: WorkoutDuration;
|
|
399
565
|
language: Language;
|
|
400
566
|
programID: string;
|
|
567
|
+
phonePosition: PhonePosition;
|
|
568
|
+
shortIntro: boolean;
|
|
401
569
|
|
|
402
570
|
constructor(
|
|
403
571
|
week: number,
|
|
@@ -405,7 +573,8 @@ export class WorkoutConfig {
|
|
|
405
573
|
difficultyLevel: WorkoutDifficulty,
|
|
406
574
|
workoutDuration: WorkoutDuration,
|
|
407
575
|
language: Language,
|
|
408
|
-
programID: string
|
|
576
|
+
programID: string,
|
|
577
|
+
options: WorkoutConfigOptions = {}
|
|
409
578
|
) {
|
|
410
579
|
this.week = week;
|
|
411
580
|
this.bodyZone = bodyZone;
|
|
@@ -413,40 +582,48 @@ export class WorkoutConfig {
|
|
|
413
582
|
this.workoutDuration = workoutDuration;
|
|
414
583
|
this.language = language;
|
|
415
584
|
this.programID = programID;
|
|
585
|
+
this.phonePosition = options.phonePosition ?? PhonePosition.Floor;
|
|
586
|
+
this.shortIntro = options.shortIntro ?? false;
|
|
416
587
|
}
|
|
417
588
|
|
|
418
|
-
|
|
419
|
-
return
|
|
589
|
+
toJSON(): { [key: string]: JsonValue } {
|
|
590
|
+
return withoutUndefined({
|
|
420
591
|
week: this.week,
|
|
421
592
|
bodyZone: this.bodyZone,
|
|
422
593
|
difficultyLevel: this.difficultyLevel,
|
|
423
594
|
workoutDuration: this.workoutDuration,
|
|
424
595
|
language: this.language,
|
|
425
596
|
programID: this.programID,
|
|
597
|
+
phonePosition: this.phonePosition,
|
|
598
|
+
shortIntro: this.shortIntro,
|
|
426
599
|
});
|
|
427
600
|
}
|
|
601
|
+
|
|
602
|
+
toJson(): string {
|
|
603
|
+
return JSON.stringify(this.toJSON());
|
|
604
|
+
}
|
|
428
605
|
}
|
|
429
606
|
|
|
430
|
-
/**
|
|
431
|
-
* Class representing user data.
|
|
432
|
-
*/
|
|
433
607
|
export class UserData {
|
|
434
|
-
/**
|
|
435
|
-
* @param {Gender} gender - User's gender.
|
|
436
|
-
* @param {number} age - User's age.
|
|
437
|
-
*/
|
|
438
608
|
gender: Gender;
|
|
439
609
|
age: number;
|
|
610
|
+
email: string | null;
|
|
440
611
|
|
|
441
|
-
constructor(gender: Gender, age: number) {
|
|
612
|
+
constructor(gender: Gender, age: number, email: string | null = null) {
|
|
442
613
|
this.gender = gender;
|
|
443
614
|
this.age = age;
|
|
615
|
+
this.email = email ?? null;
|
|
444
616
|
}
|
|
445
617
|
|
|
446
|
-
|
|
447
|
-
return
|
|
618
|
+
toJSON(): { [key: string]: JsonValue } {
|
|
619
|
+
return withoutUndefined({
|
|
448
620
|
gender: this.gender,
|
|
449
621
|
age: this.age,
|
|
622
|
+
email: this.email,
|
|
450
623
|
});
|
|
451
624
|
}
|
|
625
|
+
|
|
626
|
+
toJson(): string {
|
|
627
|
+
return JSON.stringify(this.toJSON());
|
|
628
|
+
}
|
|
452
629
|
}
|