Skip to content
This repository was archived by the owner on Jan 27, 2026. It is now read-only.
Merged

1.1.4 #218

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
f01bc85
WIP feat: adjust table to fit all data
charlieforward9 Jun 10, 2024
0f1078d
WIP feat: adjust table to fit all data
charlieforward9 Jun 10, 2024
cb51302
Merge branch 'feat/equilibrium_score' of https://github.com/VisualPT/…
charlieforward9 Jun 10, 2024
c9204ff
feat(inference): updated pose class model
charlieforward9 Jun 12, 2024
3a6151e
fix(ctsib): return 0 for NaN equlibrium scores
charlieforward9 Jun 28, 2024
a7016cf
feat(inference): updated pose class model
charlieforward9 Jun 28, 2024
bd61b7b
WIP feat: adjust table to fit all data
charlieforward9 Jun 28, 2024
916f93d
Merge branch 'feat/equilibrium_score' of https://github.com/VisualPT/…
charlieforward9 Jun 28, 2024
69f85c6
feat: equilibrium score for frontal plane
charlieforward9 Jul 14, 2024
2cf36b8
refactor: enhance UI/UX
charlieforward9 Jul 14, 2024
04e5182
fix: reset assessment start time on redo
charlieforward9 Jul 14, 2024
c9a19a8
fix(ctsib): use equilibrium scores for condition ratios
charlieforward9 Jul 14, 2024
c141da5
fix: flutter extension auto fixes
charlieforward9 Jul 14, 2024
8ea45b2
chore(git): cleanup contributor details
charlieforward9 Jul 14, 2024
27030e6
chore(deps): 1.1.2
charlieforward9 Jul 14, 2024
0e974f5
feat(assessment): add duration to config, link to timer
charlieforward9 Jul 15, 2024
075e14f
feat(assesment): add ctsib demo
charlieforward9 Jul 15, 2024
ed8824b
fix(video): onStop bug where camera is "already stopped"
charlieforward9 Jul 15, 2024
5b55fa0
minor
charlieforward9 Jul 15, 2024
4652414
chore(version): bump
charlieforward9 Jul 15, 2024
538a61c
chore: remove demo/collect assessments in favor of official data coll…
charlieforward9 Sep 5, 2024
4b80b4b
feat: add y axis divisions
charlieforward9 Sep 5, 2024
6d6c2f1
feat(data): update schema with Norm model and AgeRange enum
charlieforward9 Sep 10, 2024
fd66092
refactor: Change Condition Timer from 30s to 20s #203
charlieforward9 Sep 11, 2024
1d93b0e
WIP feat: norms functionality integrated, storeData toggle
charlieforward9 Sep 18, 2024
2bb060b
feat: owner-based auth
charlieforward9 Sep 18, 2024
9cd4711
fix: font size on indicators
charlieforward9 Sep 20, 2024
7cab54b
feat(assessment): add onComplete capture flag
charlieforward9 Sep 20, 2024
cc12562
refactor: consolidate video/timer bloc
charlieforward9 Sep 20, 2024
fd74b3b
feat(video): paused state
charlieforward9 Oct 3, 2024
1ff6d54
fix(ctsib): max sway angle
charlieforward9 Oct 3, 2024
50ad8e8
chore: bump pdf
charlieforward9 Oct 3, 2024
5f21926
refactor(analysis): improve logging/functionality
charlieforward9 Oct 8, 2024
cf62f89
minor: styles
charlieforward9 Oct 8, 2024
fda5b41
feat(storage): control what gets stored better
charlieforward9 Oct 8, 2024
15d22b4
feat: add type for rapid dev
charlieforward9 Oct 9, 2024
03081af
refactor: rename objects for clarity
charlieforward9 Oct 9, 2024
f13288a
fix: add pause flag to VideoBloc to delegate next state
charlieforward9 Oct 9, 2024
5be2c47
minor: styles, warnings
charlieforward9 Oct 9, 2024
5cac96f
feat(analysis): add norms to PDF
charlieforward9 Oct 11, 2024
221a289
chore: bump bloc
charlieforward9 Oct 11, 2024
02f0bae
feat(ctsib): sensory ratios/mismatch analysis
charlieforward9 Oct 11, 2024
39a888c
minor
charlieforward9 Oct 11, 2024
843d957
fix: Back button confuses typical users #201
charlieforward9 Oct 11, 2024
b8f4b4f
fix(video): lock capture orientation
charlieforward9 Oct 11, 2024
5f2404f
Merge pull request #186 from VisualPT/feat/equilibrium_score
charlieforward9 Oct 11, 2024
f9b0b73
minor
charlieforward9 Oct 11, 2024
da6898b
chore(version): bump to 1.1.4
charlieforward9 Oct 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .mailmap
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Charles Richardson <charlesrichardsonusa@gmail.com> charlieforward9 <charlesrichardsonusa@gmail.com>
Charles Richardson <charlesrichardsonusa@gmail.com> charlieforward9 <62311337+charlieforward9@users.noreply.github.com>
Charles Richardson <charlesrichardsonusa@gmail.com> Charles Richardson <62311337+charlieforward9@users.noreply.github.com>
9 changes: 2 additions & 7 deletions amplify/backend/api/visualpt/cli-inputs.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,12 @@
"apiName": "visualpt",
"serviceName": "AppSync",
"defaultAuthType": {
"mode": "API_KEY",
"keyDescription": "api key description",
"expirationTime": 30
"mode": "AMAZON_COGNITO_USER_POOLS",
"cognitoUserPoolId": "authvisualpt"
},
"additionalAuthTypes": [
{
"mode": "AWS_IAM"
},
{
"mode": "AMAZON_COGNITO_USER_POOLS",
"cognitoUserPoolId": "authvisualpt"
}
],
"conflictResolution": {
Expand Down
2 changes: 1 addition & 1 deletion amplify/backend/api/visualpt/parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"Outputs.UserPoolId"
]
},
"AuthModeLastUpdated": "2024-05-05T02:49:18.520Z"
"AuthModeLastUpdated": "2024-09-18T03:43:56.263Z"
}
44 changes: 39 additions & 5 deletions amplify/backend/api/visualpt/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,31 @@ enum Gender {
FEMALE
}

enum AgeRange {
BABY_0_5
CHILD_6_12
TEEN_13_19
ADULT_20_39
ADULT_40_64
SENIOR_65_69
SENIOR_70_79
SENIOR_80_84
SENIOR_85_89
}

enum AssessmentType {
CTSIB
MCTSIB
GAIT
BERG
REACH
FIST
DEV
}

type User @model @auth(rules: [{ allow: public }]) {
type User
@model
@auth(rules: [{ allow: groups, groups: ["Admin"] }, { allow: owner }]) {
id: ID!
email: AWSEmail!
first_name: String!
Expand All @@ -30,7 +46,9 @@ type User @model @auth(rules: [{ allow: public }]) {
Subjects: [Subject!] @hasMany(indexName: "byUser", fields: ["id"])
}

type Subject @model @auth(rules: [{ allow: owner }]) {
type Subject
@model
@auth(rules: [{ allow: groups, groups: ["Admin"] }, { allow: owner }]) {
id: ID!
userID: ID! @index(name: "byUser")
first_name: String!
Expand All @@ -43,7 +61,9 @@ type Subject @model @auth(rules: [{ allow: owner }]) {
Assessments: [Assessment!] @hasMany(indexName: "bySubject", fields: ["id"])
}

type Assessment @model @auth(rules: [{ allow: owner }]) {
type Assessment
@model
@auth(rules: [{ allow: groups, groups: ["Admin"] }, { allow: owner }]) {
id: ID!
subjectID: ID! @index(name: "bySubject")
type: AssessmentType!
Expand All @@ -53,22 +73,36 @@ type Assessment @model @auth(rules: [{ allow: owner }]) {
Conditions: [Condition!] @hasMany(indexName: "byAssessment", fields: ["id"])
}

type Condition @model @auth(rules: [{ allow: owner }]) {
type Condition
@model
@auth(rules: [{ allow: groups, groups: ["Admin"] }, { allow: owner }]) {
id: ID!
assessmentID: ID! @index(name: "byAssessment")
sequenceNumber: Int!
duration: Float! #seconds
trials: [Trial!] @hasMany(indexName: "byCondition", fields: ["id"])
}

type Trial @model @auth(rules: [{ allow: owner }]) {
type Trial
@model
@auth(rules: [{ allow: groups, groups: ["Admin"] }, { allow: owner }]) {
id: ID!
conditionID: ID! @index(name: "byCondition")
start_time: AWSDateTime!
duration: Float! #seconds
Detections: [Detection!]
}

type Norm @model @auth(rules: [{ allow: private }]) {
id: ID!
type: AssessmentType!
sequenceNumber: Int!
age_range: AgeRange!
gender: Gender!
score_sum: Float!
trial_sum: Int!
}

type Detection {
id: String!
version: Int!
Expand Down
15 changes: 4 additions & 11 deletions amplify/backend/backend-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,13 @@
"additionalAuthenticationProviders": [
{
"authenticationType": "AWS_IAM"
},
{
"authenticationType": "AMAZON_COGNITO_USER_POOLS",
"userPoolConfig": {
"userPoolId": "authvisualpt"
}
}
],
"defaultAuthentication": {
"apiKeyConfig": {
"apiKeyExpirationDays": 30,
"description": "api key description"
},
"authenticationType": "API_KEY"
"authenticationType": "AMAZON_COGNITO_USER_POOLS",
"userPoolConfig": {
"userPoolId": "authvisualpt"
}
}
}
},
Expand Down
3 changes: 1 addition & 2 deletions amplify/backend/types/amplify-dependent-resources-ref.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ export type AmplifyDependentResourcesAttributes = {
"api": {
"visualpt": {
"GraphQLAPIEndpointOutput": "string",
"GraphQLAPIIdOutput": "string",
"GraphQLAPIKeyOutput": "string"
"GraphQLAPIIdOutput": "string"
}
},
"auth": {
Expand Down
Binary file added assets/images/vpt_appicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/models/pose_classification.tflite
Binary file not shown.
14 changes: 3 additions & 11 deletions lib/amplifyconfiguration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ const amplifyconfig = '''{
"endpointType": "GraphQL",
"endpoint": "https://pzdub2f2czghti3zlrepb5awv4.appsync-api.us-east-1.amazonaws.com/graphql",
"region": "us-east-1",
"authorizationType": "API_KEY",
"apiKey": "da2-uj6vhfa3mna7hfwciugu7juooq"
"authorizationType": "AMAZON_COGNITO_USER_POOLS"
}
}
}
Expand All @@ -26,21 +25,14 @@ const amplifyconfig = '''{
"Default": {
"ApiUrl": "https://pzdub2f2czghti3zlrepb5awv4.appsync-api.us-east-1.amazonaws.com/graphql",
"Region": "us-east-1",
"AuthMode": "API_KEY",
"ApiKey": "da2-uj6vhfa3mna7hfwciugu7juooq",
"ClientDatabasePrefix": "visualpt_API_KEY"
"AuthMode": "AMAZON_COGNITO_USER_POOLS",
"ClientDatabasePrefix": "visualpt_AMAZON_COGNITO_USER_POOLS"
},
"visualpt_AWS_IAM": {
"ApiUrl": "https://pzdub2f2czghti3zlrepb5awv4.appsync-api.us-east-1.amazonaws.com/graphql",
"Region": "us-east-1",
"AuthMode": "AWS_IAM",
"ClientDatabasePrefix": "visualpt_AWS_IAM"
},
"visualpt_AMAZON_COGNITO_USER_POOLS": {
"ApiUrl": "https://pzdub2f2czghti3zlrepb5awv4.appsync-api.us-east-1.amazonaws.com/graphql",
"Region": "us-east-1",
"AuthMode": "AMAZON_COGNITO_USER_POOLS",
"ClientDatabasePrefix": "visualpt_AMAZON_COGNITO_USER_POOLS"
}
},
"CredentialsProvider": {
Expand Down
6 changes: 5 additions & 1 deletion lib/core/services/repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import 'dart:async';
import 'package:visualpt/features/assessment/types.dart';

abstract class Repository<I, O> {
final AssessmentMeta meta;
final TrialMeta meta;
final StreamController<I> _streamController;
var isInitialized = false;
var count = 0;
Expand All @@ -24,6 +24,10 @@ abstract class Repository<I, O> {
Future<O?> runPredict(String id, I input, Map<String, dynamic>? params);
Future<void> store(
String id, I input, O output, Map<String, dynamic>? params);
void reset() {
localStorage.clear();
count = 0;
}

void dispose() {
_streamController.close();
Expand Down
144 changes: 84 additions & 60 deletions lib/core/views/base_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@ import 'package:visualpt/features/assessment/view/components/assessment_instruct

class BaseView extends StatefulWidget {
const BaseView(
{super.key, required this.child, this.instructions, this.pageTitle});
{super.key,
required this.child,
this.instructions,
this.pageTitle,
this.poppable = true});
final Widget child;
final AssessmentInstructions? instructions;
final String? pageTitle;
final bool poppable;

@override
State<BaseView> createState() => _BaseViewState();
Expand All @@ -17,76 +22,95 @@ class BaseView extends StatefulWidget {
class _BaseViewState extends State<BaseView> {
bool showInstructions = true;

@override
void initState() {
super.initState();
setState(() {
showInstructions = widget.instructions == null ? false : true;
});
}

@override
void didUpdateWidget(BaseView oldWidget) {
super.didUpdateWidget(oldWidget);
setState(() => showInstructions = true);
}

bool _canPop() {
if (!widget.poppable || showInstructions) {
return false;
}
return true; // Allow navigation otherwise
}

@override
Widget build(BuildContext context) {
final screenSize = MediaQuery.of(context).size;

return Stack(alignment: Alignment.center, children: [
CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
backgroundColor: Styles.backgroundAccent,
middle: ConstrainedBox(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width * 0.75),
child: widget.pageTitle == null
? const Image(
image: AssetImage(Styles.mainLogoPath),
fit: BoxFit.fitWidth)
: Text(
widget.pageTitle!,
style: Styles.heading3,
textAlign: TextAlign.center,
)),
trailing: widget.pageTitle == null
? GestureDetector(
onTap: () => Navigator.pushNamed(context, "/settings"),
child: const Icon(
CupertinoIcons.settings,
color: Styles.black,
))
: widget.instructions != null
? GestureDetector(
onTap: () => setState(
() => showInstructions = !showInstructions),
child: const Icon(
CupertinoIcons.info,
color: Styles.black,
))
: null,
),
child: SizedBox(
height: screenSize.height,
width: screenSize.width,
child: Stack(alignment: Alignment.center, children: [
const ViewBackground(),
SafeArea(
child: widget.child,
)
]),
)),
//InstructionModal below
showInstructions && widget.instructions != null
? Container(
alignment: Alignment.center,
return PopScope(
canPop: _canPop(), // Override back button behavior
child: Stack(alignment: Alignment.center, children: [
CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
automaticallyImplyLeading: _canPop() ? true : false,
backgroundColor: Styles.backgroundAccent,
middle: ConstrainedBox(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width * 0.75),
child: widget.pageTitle == null
? const Image(
image: AssetImage(Styles.mainLogoPath),
fit: BoxFit.fitWidth)
: Text(
widget.pageTitle!,
style: Styles.heading3,
textAlign: TextAlign.center,
)),
trailing: widget.pageTitle == null
? GestureDetector(
onTap: () => Navigator.pushNamed(context, "/settings"),
child: const Icon(
CupertinoIcons.settings,
color: Styles.black,
))
: widget.instructions != null
? GestureDetector(
onTap: () => setState(
() => showInstructions = !showInstructions),
child: const Icon(
CupertinoIcons.info,
color: Styles.black,
))
: null,
),
child: SizedBox(
height: screenSize.height,
width: screenSize.width,
color: Styles.black.withOpacity(0.5),
child: GestureDetector(
child: Container(
height: screenSize.height * 0.8,
width: screenSize.width * 0.8,
decoration: const BoxDecoration(
borderRadius: Styles.borderRadiusM,
color: Styles.ceruleanBlue),
child: widget.instructions),
onTap: () => setState(() => showInstructions = false)))
: Container()
]);
child: Stack(alignment: Alignment.center, children: [
const ViewBackground(),
SafeArea(
child: widget.child,
)
]),
)),
// InstructionModal below
showInstructions && widget.instructions != null
? Container(
alignment: Alignment.center,
height: screenSize.height,
width: screenSize.width,
color: Styles.black.withOpacity(0.5),
child: GestureDetector(
child: Container(
height: screenSize.height * 0.9,
width: screenSize.width * 0.9,
decoration: const BoxDecoration(
borderRadius: Styles.borderRadiusM,
color: Styles.ceruleanBlue),
child: widget.instructions),
onTap: () => setState(() => showInstructions = false)))
: Container()
]),
);
}
}
Loading