Skip to content

Commit 7cec8f6

Browse files
committed
Custom Exercises with Custom ROM
1 parent 91a1ecb commit 7cec8f6

File tree

10 files changed

+95
-10
lines changed

10 files changed

+95
-10
lines changed

.DS_Store

0 Bytes
Binary file not shown.

FitCount.xcodeproj/project.pbxproj

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
6C3A46602ECE21970013F19A /* FrontPushupExercise.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3A465F2ECE21970013F19A /* FrontPushupExercise.swift */; };
1011
6C88C6772E68604700223401 /* CustomExerciseEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C88C6752E68604700223401 /* CustomExerciseEngine.swift */; };
1112
6C88C6782E68604700223401 /* SideTiltsExercise.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C88C6762E68604700223401 /* SideTiltsExercise.swift */; };
1213
6C88C6EF2E69BDBE00223401 /* KneeRaisesExercise.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C88C6EE2E69BDBE00223401 /* KneeRaisesExercise.swift */; };
@@ -33,6 +34,7 @@
3334
/* End PBXBuildFile section */
3435

3536
/* Begin PBXFileReference section */
37+
6C3A465F2ECE21970013F19A /* FrontPushupExercise.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrontPushupExercise.swift; sourceTree = "<group>"; };
3638
6C88C6752E68604700223401 /* CustomExerciseEngine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomExerciseEngine.swift; sourceTree = "<group>"; };
3739
6C88C6762E68604700223401 /* SideTiltsExercise.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SideTiltsExercise.swift; sourceTree = "<group>"; };
3840
6C88C6EE2E69BDBE00223401 /* KneeRaisesExercise.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KneeRaisesExercise.swift; sourceTree = "<group>"; };
@@ -130,6 +132,7 @@
130132
6C88C6752E68604700223401 /* CustomExerciseEngine.swift */,
131133
6C88C6EE2E69BDBE00223401 /* KneeRaisesExercise.swift */,
132134
6C88C6762E68604700223401 /* SideTiltsExercise.swift */,
135+
6C3A465F2ECE21970013F19A /* FrontPushupExercise.swift */,
133136
92F2D1FA2A1D0C8400EC1B81 /* Text2Speech.swift */,
134137
924D6E212A264B3600227183 /* JsonWriter.swift */,
135138
920A3EEB2A1F6E0E00EC6FC9 /* Timer.swift */,
@@ -233,6 +236,7 @@
233236
buildActionMask = 2147483647;
234237
files = (
235238
92CACFD32A1B7DD100DA2B40 /* ContentView.swift in Sources */,
239+
6C3A46602ECE21970013F19A /* FrontPushupExercise.swift in Sources */,
236240
9215905F2A2A10BF001254BC /* InstructionsView.swift in Sources */,
237241
92CACFD12A1B7DD100DA2B40 /* FitCountApp.swift in Sources */,
238242
6C88C6772E68604700223401 /* CustomExerciseEngine.swift in Sources */,
@@ -379,23 +383,24 @@
379383
ENABLE_PREVIEWS = YES;
380384
GENERATE_INFOPLIST_FILE = YES;
381385
INFOPLIST_FILE = FitCount/Info.plist;
382-
INFOPLIST_KEY_NSCameraUsageDescription = "We use your camera to provide movements feedback during a workout";
386+
INFOPLIST_KEY_NSCameraUsageDescription = "We use your camera to provide movement feedback during a workout";
383387
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
384388
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
385389
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
386390
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
387391
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
388-
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
392+
IPHONEOS_DEPLOYMENT_TARGET = 18;
389393
LD_RUNPATH_SEARCH_PATHS = (
390394
"$(inherited)",
391395
"@executable_path/Frameworks",
392396
);
393-
MARKETING_VERSION = 0.4;
394-
PRODUCT_BUNDLE_IDENTIFIER = ai.quickpose.demo;
397+
MARKETING_VERSION = 1.0;
398+
PRODUCT_BUNDLE_IDENTIFIER = ai.quickpose.repcount;
395399
PRODUCT_NAME = "$(TARGET_NAME)";
396400
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
397401
SUPPORTS_MACCATALYST = NO;
398402
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
403+
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
399404
SWIFT_EMIT_LOC_STRINGS = YES;
400405
SWIFT_VERSION = 5.0;
401406
TARGETED_DEVICE_FAMILY = 1;
@@ -413,23 +418,24 @@
413418
ENABLE_PREVIEWS = YES;
414419
GENERATE_INFOPLIST_FILE = YES;
415420
INFOPLIST_FILE = FitCount/Info.plist;
416-
INFOPLIST_KEY_NSCameraUsageDescription = "We use your camera to provide movements feedback during a workout";
421+
INFOPLIST_KEY_NSCameraUsageDescription = "We use your camera to provide movement feedback during a workout";
417422
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
418423
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
419424
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
420425
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
421426
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
422-
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
427+
IPHONEOS_DEPLOYMENT_TARGET = 18;
423428
LD_RUNPATH_SEARCH_PATHS = (
424429
"$(inherited)",
425430
"@executable_path/Frameworks",
426431
);
427-
MARKETING_VERSION = 0.4;
428-
PRODUCT_BUNDLE_IDENTIFIER = ai.quickpose.demo;
432+
MARKETING_VERSION = 1.0;
433+
PRODUCT_BUNDLE_IDENTIFIER = ai.quickpose.repcount;
429434
PRODUCT_NAME = "$(TARGET_NAME)";
430435
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
431436
SUPPORTS_MACCATALYST = NO;
432437
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
438+
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
433439
SWIFT_EMIT_LOC_STRINGS = YES;
434440
SWIFT_VERSION = 5.0;
435441
TARGETED_DEVICE_FAMILY = 1;

FitCount/.DS_Store

6 KB
Binary file not shown.

FitCount/Assets.xcassets/AppIcon.appiconset/Contents.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"images" : [
33
{
4-
"filename" : "dsyntha_ios_app_abstract_icon_of_a_fitness_app_barbells_blue_an_57a91e90-e96e-48d8-8383-e2f346456c15.png",
4+
"filename" : "fitcountlogo.png",
55
"idiom" : "universal",
66
"platform" : "ios",
77
"size" : "1024x1024"
388 KB
Loading

FitCount/FitCountApp.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ let exercises = [
4242
),
4343
SideTiltsExercise.createExercise().exerciseDefinition,
4444
KneeRaisesExercise.createExercise().exerciseDefinition,
45+
FrontPushupExercise.createExercise().exerciseDefinition,
4546
]
4647

4748

FitCount/FrontPushupExercise.swift

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
//
2+
// FrontPush-upExercise.swift
3+
// Generated by QuickPose Exercise Creator
4+
//
5+
6+
import Foundation
7+
import QuickPoseCore
8+
9+
// MARK: - Front Push-up Exercise Definition
10+
class FrontPushupExercise {
11+
static func createExercise(hideFeedback: Bool = true) -> CustomExercise {
12+
let stages = [
13+
// Stage 1: Top Position (Arms Extended)
14+
ExerciseStage(
15+
id: "top_position",
16+
name: "Top Position",
17+
requirements: [
18+
.elbow(side: .right): AngleRange(min: 150, max: 210),
19+
.shoulder(side: .right): AngleRange(min: 10, max: 90),
20+
.elbow(side: .left): AngleRange(min: 150, max: 210),
21+
.shoulder(side: .left): AngleRange(min: 10, max: 90),
22+
],
23+
description: "Arms extended at the top of the push-up"
24+
),
25+
// Stage 2: Bottom Position (Arms Bent)
26+
ExerciseStage(
27+
id: "bottom_position",
28+
name: "Bottom Position",
29+
requirements: [
30+
.elbow(side: .right): AngleRange(min: 50, max: 110),
31+
.shoulder(side: .right): AngleRange(min: 50, max: 100),
32+
.elbow(side: .left): AngleRange(min: 50, max: 110),
33+
.shoulder(side: .left): AngleRange(min: 50, max: 100),
34+
],
35+
description: "Arms bent at the bottom of the push-up"
36+
),
37+
ExerciseStage(
38+
id: "Top Position",
39+
name: "Bottom Position",
40+
requirements: [
41+
.elbow(side: .right): AngleRange(min: 50, max: 110),
42+
.shoulder(side: .right): AngleRange(min: 50, max: 100),
43+
.elbow(side: .left): AngleRange(min: 50, max: 110),
44+
.shoulder(side: .left): AngleRange(min: 50, max: 100),
45+
],
46+
description: "Arms bent at the bottom of the push-up"
47+
)
48+
]
49+
50+
// Define the required QuickPose features for range of motion tracking
51+
// Create custom styles for overlay
52+
let lightOverlayStyle = QuickPose.Style(relativeFontSize: 0.0, relativeArcSize: 0.3, relativeLineWidth: 1.0)
53+
let noOverlayStyle = QuickPose.Style(relativeFontSize: 0.0, relativeArcSize: 0.0, relativeLineWidth: 0.0)
54+
55+
let requiredFeatures: [QuickPose.Feature] = [
56+
.rangeOfMotion(.elbow(side: .left, clockwiseDirection: true), style: lightOverlayStyle),
57+
.rangeOfMotion(.hip(side: .left, clockwiseDirection: true), style: noOverlayStyle),
58+
.rangeOfMotion(.knee(side: .left, clockwiseDirection: true), style: noOverlayStyle),
59+
.rangeOfMotion(.shoulder(side: .left, clockwiseDirection: false), style: lightOverlayStyle),
60+
.rangeOfMotion(.elbow(side: .right, clockwiseDirection: false), style: lightOverlayStyle),
61+
.rangeOfMotion(.hip(side: .right, clockwiseDirection: true), style: noOverlayStyle),
62+
.rangeOfMotion(.knee(side: .right, clockwiseDirection: true), style: noOverlayStyle),
63+
.rangeOfMotion(.shoulder(side: .right, clockwiseDirection: true), style: lightOverlayStyle),
64+
.overlay(.wholeBody, style: noOverlayStyle) // Light body outline
65+
]
66+
67+
return CustomExercise(
68+
id: "front_push-up",
69+
name: "Front Push-up",
70+
description: "Front Push-up",
71+
stages: stages,
72+
requiredFeatures: requiredFeatures,
73+
hideFeedback: hideFeedback
74+
)
75+
}
76+
}

FitCount/Workout/QuickPoseBasicView.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ enum ViewState: Equatable {
3737
}
3838

3939
struct QuickPoseBasicView: View {
40-
private var quickPose = QuickPose(sdkKey: "ENTER YOUR SDK KEY HERE") // register for your free key at https://dev.quickpose.ai
40+
private var quickPose = QuickPose(sdkKey: "") // register for your free key at https://dev.quickpose.ai
4141
@EnvironmentObject var viewModel: ViewModel
4242
@EnvironmentObject var sessionConfig: SessionConfig
4343

@@ -260,6 +260,8 @@ struct QuickPoseBasicView: View {
260260
customExerciseEngine = CustomExerciseEngine(exercise: SideTiltsExercise.createExercise())
261261
} else if sessionConfig.exercise.name == "Knee Raises" {
262262
customExerciseEngine = CustomExerciseEngine(exercise: KneeRaisesExercise.createExercise())
263+
} else if sessionConfig.exercise.name == "Front Push-up" {
264+
customExerciseEngine = CustomExerciseEngine(exercise: FrontPushupExercise.createExercise())
263265
}
264266
}
265267
DispatchQueue.main.asyncAfter(deadline: .now()+0.5) {

0 commit comments

Comments
 (0)