updates
parent
ff7afe5997
commit
a144d5fafe
Binary file not shown.
|
After Width: | Height: | Size: 520 B |
Binary file not shown.
|
After Width: | Height: | Size: 428 B |
@ -0,0 +1,28 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class BackHomeButton extends StatelessWidget {
|
||||||
|
final void Function() onPressed;
|
||||||
|
final Size deviceSize;
|
||||||
|
|
||||||
|
const BackHomeButton({
|
||||||
|
Key? key,
|
||||||
|
required this.onPressed,
|
||||||
|
required this.deviceSize,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Align(
|
||||||
|
alignment: Alignment.topLeft,
|
||||||
|
child: Container(
|
||||||
|
margin: EdgeInsets.fromLTRB(15, deviceSize.height * 0.05, 0, 0),
|
||||||
|
child: IconButton(
|
||||||
|
icon: const Icon(Icons.arrow_back),
|
||||||
|
color: Colors.white,
|
||||||
|
iconSize: 25,
|
||||||
|
onPressed: onPressed,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,87 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:vital_sign_camera/vital_sign_camera.dart';
|
||||||
|
|
||||||
|
class BoundingBoxWidget extends StatelessWidget {
|
||||||
|
final Size deviceSize;
|
||||||
|
final NormalizedFaceBox? facebox;
|
||||||
|
final VideoFrameInfo? videoFrameInfo;
|
||||||
|
|
||||||
|
const BoundingBoxWidget({
|
||||||
|
Key? key,
|
||||||
|
required this.deviceSize,
|
||||||
|
required this.facebox,
|
||||||
|
required this.videoFrameInfo,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (facebox == null || videoFrameInfo == null) {
|
||||||
|
return Container();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a map with left, top, width, and height of the bounding box for the face
|
||||||
|
Map boundingBox = computeBoundingBox();
|
||||||
|
|
||||||
|
return Positioned(
|
||||||
|
left: boundingBox['left'],
|
||||||
|
top: boundingBox['top'],
|
||||||
|
child: Container(
|
||||||
|
width: boundingBox['width'],
|
||||||
|
height: boundingBox['height'],
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(
|
||||||
|
color: Colors.red,
|
||||||
|
width: 2,
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to compute the left, top, width, and height of the bounding box
|
||||||
|
Map computeBoundingBox() {
|
||||||
|
double width = videoFrameInfo!.width;
|
||||||
|
double height = videoFrameInfo!.height;
|
||||||
|
double windowWidth = deviceSize.width;
|
||||||
|
double windowHeight = deviceSize.height;
|
||||||
|
|
||||||
|
double screenAspectRatio = deviceSize.aspectRatio;
|
||||||
|
double frameAspectRatio = width / height;
|
||||||
|
|
||||||
|
int xTransform = 1;
|
||||||
|
if (Platform.isAndroid) {
|
||||||
|
xTransform = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
double scale = 1;
|
||||||
|
if (screenAspectRatio < frameAspectRatio) {
|
||||||
|
scale = windowHeight / height;
|
||||||
|
} else {
|
||||||
|
scale = windowWidth / width;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map scaledFrameBounds = {
|
||||||
|
'x': (windowWidth - scale * width) / 2,
|
||||||
|
'y': (windowHeight - scale * height) / 2,
|
||||||
|
'width': scale * width,
|
||||||
|
'height': scale * height,
|
||||||
|
};
|
||||||
|
|
||||||
|
double x = facebox!.xCenter - facebox!.width / 2;
|
||||||
|
double y = facebox!.yCenter - facebox!.height / 2;
|
||||||
|
|
||||||
|
if (xTransform < 0) {
|
||||||
|
x = 1 - x - facebox!.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map result = {
|
||||||
|
'left': scaledFrameBounds['x'] + x * scaledFrameBounds['width'],
|
||||||
|
'top': scaledFrameBounds['y'] + y * scaledFrameBounds['height'],
|
||||||
|
'width': facebox!.width * scaledFrameBounds['width'],
|
||||||
|
'height': facebox!.height * scaledFrameBounds['height'],
|
||||||
|
};
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class Button extends StatelessWidget {
|
||||||
|
final void Function() onPressed;
|
||||||
|
final Size deviceSize;
|
||||||
|
final String title;
|
||||||
|
final Alignment alignment;
|
||||||
|
final EdgeInsets margin;
|
||||||
|
|
||||||
|
const Button({
|
||||||
|
Key? key,
|
||||||
|
required this.onPressed,
|
||||||
|
required this.deviceSize,
|
||||||
|
required this.title,
|
||||||
|
required this.alignment,
|
||||||
|
required this.margin,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Align(
|
||||||
|
alignment: alignment,
|
||||||
|
child: Container(
|
||||||
|
margin: margin,
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: onPressed,
|
||||||
|
child: Text(
|
||||||
|
title,
|
||||||
|
style: const TextStyle(fontSize: 18),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class Error extends StatelessWidget {
|
||||||
|
final dynamic error;
|
||||||
|
final int? errorCode;
|
||||||
|
|
||||||
|
const Error({
|
||||||
|
Key? key,
|
||||||
|
this.error,
|
||||||
|
this.errorCode,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Center(
|
||||||
|
child: Text(
|
||||||
|
"$error $errorCode",
|
||||||
|
style: const TextStyle(color: Colors.white),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,222 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:vital_sign_camera/vital_sign_camera.dart';
|
||||||
|
import 'vital_sign_widget.dart';
|
||||||
|
|
||||||
|
class HealthResultWidget extends StatelessWidget {
|
||||||
|
final Size deviceSize;
|
||||||
|
final void Function() onTap;
|
||||||
|
final Health? healthResult;
|
||||||
|
|
||||||
|
late final VitalSign? _vitalSign;
|
||||||
|
late final HolisticAnalysis? _holisticAnalysis;
|
||||||
|
late final CardiovascularRisks? _cardiovascularRisks;
|
||||||
|
late final CovidRisk? _covidRisk;
|
||||||
|
late final ScanParameters? _scanParameters;
|
||||||
|
|
||||||
|
HealthResultWidget({
|
||||||
|
Key? key,
|
||||||
|
required this.deviceSize,
|
||||||
|
required this.onTap,
|
||||||
|
required this.healthResult,
|
||||||
|
}) : super(key: key) {
|
||||||
|
_vitalSign = healthResult?.vitalSigns;
|
||||||
|
_holisticAnalysis = healthResult?.holisticHealth;
|
||||||
|
_cardiovascularRisks = healthResult?.risks?.cardiovascularRisks;
|
||||||
|
_covidRisk = healthResult?.risks?.covidRisk;
|
||||||
|
_scanParameters = healthResult?.scanParameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Positioned(
|
||||||
|
top: deviceSize.height * 0.07,
|
||||||
|
left: deviceSize.width * 0.05,
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: onTap,
|
||||||
|
child: SizedBox(
|
||||||
|
width: deviceSize.width * 0.9,
|
||||||
|
child: Container(
|
||||||
|
color: Colors.black38,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(15),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.fromLTRB(0, 0, 0, 10),
|
||||||
|
child: const Text(
|
||||||
|
"Vital Signs",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 15,
|
||||||
|
color: Colors.amber,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
VitalSignWidget(
|
||||||
|
vitalSignName: "Heart Rate",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.vitalSigns.heartRate)),
|
||||||
|
VitalSignWidget(
|
||||||
|
vitalSignName: "SPO2",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.vitalSigns.spo2)),
|
||||||
|
VitalSignWidget(
|
||||||
|
vitalSignName: "IBI",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.vitalSigns.ibi)),
|
||||||
|
if (_vitalSign?.stress != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
vitalSignName: "Stress",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.vitalSigns.stress)),
|
||||||
|
if (_vitalSign?.respiratoryRate != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
vitalSignName: "Respiratory Rate",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult
|
||||||
|
?.vitalSigns.respiratoryRate)),
|
||||||
|
if (_vitalSign?.hrvRmssd != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
vitalSignName: "HRV RMSSD",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.vitalSigns.hrvRmssd)),
|
||||||
|
if (_vitalSign?.hrvSdnn != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
vitalSignName: "HRV SDNN",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.vitalSigns.hrvSdnn)),
|
||||||
|
if (_vitalSign?.temperature != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
vitalSignName: "Temperature",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.vitalSigns.temperature)),
|
||||||
|
if (_vitalSign?.bloodPressure != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
vitalSignName: "Blood Pressure",
|
||||||
|
vitalSignValue:
|
||||||
|
healthResult?.vitalSigns.bloodPressure ??
|
||||||
|
""),
|
||||||
|
if (_vitalSign?.bloodPressureSystolic != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
vitalSignName: "Blood Pressure Systolic",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult
|
||||||
|
?.vitalSigns.bloodPressureSystolic)),
|
||||||
|
if (_vitalSign?.bloodPressureDiastolic != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
vitalSignName: "Blood Pressure Diastolic",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult
|
||||||
|
?.vitalSigns.bloodPressureDiastolic)),
|
||||||
|
if (_holisticAnalysis != null)
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.fromLTRB(0, 25, 0, 10),
|
||||||
|
child: const Text(
|
||||||
|
"Holistic Analysis",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 15,
|
||||||
|
color: Colors.amber,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (_holisticAnalysis != null &&
|
||||||
|
_holisticAnalysis?.bmi != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
vitalSignName: "BMI",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.holisticHealth?.bmi)),
|
||||||
|
if (_holisticAnalysis != null &&
|
||||||
|
_holisticAnalysis?.generalWellness != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
vitalSignName: "General Wellness",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult
|
||||||
|
?.holisticHealth?.generalWellness)),
|
||||||
|
if (_cardiovascularRisks != null)
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.fromLTRB(0, 25, 0, 10),
|
||||||
|
child: const Text(
|
||||||
|
"Cardiovascular Risks",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 15,
|
||||||
|
color: Colors.amber,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (_cardiovascularRisks != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
vitalSignName: "General",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.risks?.cardiovascularRisks
|
||||||
|
?.generalRisk)),
|
||||||
|
if (_cardiovascularRisks != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
vitalSignName: "Congestive Heart Failure",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.risks?.cardiovascularRisks
|
||||||
|
?.congestiveHeartFailure)),
|
||||||
|
if (_cardiovascularRisks != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
vitalSignName: "Coronary Heart Disease",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.risks?.cardiovascularRisks
|
||||||
|
?.coronaryHeartDisease)),
|
||||||
|
if (_cardiovascularRisks != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
vitalSignName: "Intermittent Claudication",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.risks?.cardiovascularRisks
|
||||||
|
?.intermittentClaudication)),
|
||||||
|
if (_cardiovascularRisks != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
vitalSignName: "Stroke",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.risks?.cardiovascularRisks
|
||||||
|
?.stroke)),
|
||||||
|
if (_covidRisk != null)
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.fromLTRB(0, 25, 0, 10),
|
||||||
|
child: const Text(
|
||||||
|
"Covid Risks",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 15,
|
||||||
|
color: Colors.amber,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (_covidRisk != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
vitalSignName: "Risk",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult
|
||||||
|
?.risks?.covidRisk?.covidRisk)),
|
||||||
|
if (_scanParameters != null)
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.fromLTRB(0, 25, 0, 10),
|
||||||
|
child: const Text(
|
||||||
|
"Scan Parameters",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 15,
|
||||||
|
color: Colors.amber,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (_scanParameters != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
vitalSignName: "Signal Quality",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult
|
||||||
|
?.scanParameters?.signalQuality)),
|
||||||
|
])))),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
String formatValueToTwoDp(double? value) {
|
||||||
|
return (value != null) ? value.toStringAsFixed(2) : "";
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ScanCondition extends StatelessWidget {
|
||||||
|
final String scanConditionName;
|
||||||
|
final bool isConditionSatisfied;
|
||||||
|
|
||||||
|
const ScanCondition({
|
||||||
|
Key? key,
|
||||||
|
required this.scanConditionName, // condition
|
||||||
|
required this.isConditionSatisfied, // status
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(0, 5, 0, 0),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
(isConditionSatisfied)
|
||||||
|
? Image.asset('assets/images/checkmark.png', width: 14)
|
||||||
|
: Image.asset('assets/images/crossmark.png', width: 14),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
|
||||||
|
child: Text(
|
||||||
|
scanConditionName,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,75 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:vital_sign_camera/vital_sign_camera.dart';
|
||||||
|
import 'scan_condition.dart';
|
||||||
|
|
||||||
|
class ScanConditionChecklist extends StatelessWidget {
|
||||||
|
final ScanConditions conditions; // ScanCondition
|
||||||
|
|
||||||
|
const ScanConditionChecklist({
|
||||||
|
Key? key,
|
||||||
|
required this.deviceSize,
|
||||||
|
required this.conditions, // ScanCondition
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final Size deviceSize;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Positioned(
|
||||||
|
top: deviceSize.height * 0.12,
|
||||||
|
left: deviceSize.width * 0.05,
|
||||||
|
child: SizedBox(
|
||||||
|
width: deviceSize.width * 0.9,
|
||||||
|
child: Container(
|
||||||
|
color: Colors.black38,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(15),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
"Scanning Conditions",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 15,
|
||||||
|
color: Colors.amber,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(0, 10, 0, 0),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
ScanCondition(
|
||||||
|
scanConditionName: "Lighting",
|
||||||
|
isConditionSatisfied: conditions.lighting,
|
||||||
|
),
|
||||||
|
ScanCondition(
|
||||||
|
scanConditionName: "Distance",
|
||||||
|
isConditionSatisfied: conditions.distance,
|
||||||
|
),
|
||||||
|
ScanCondition(
|
||||||
|
scanConditionName: "Centered",
|
||||||
|
isConditionSatisfied: conditions.centered,
|
||||||
|
),
|
||||||
|
ScanCondition(
|
||||||
|
scanConditionName: "Movement",
|
||||||
|
isConditionSatisfied: conditions.movement,
|
||||||
|
),
|
||||||
|
ScanCondition(
|
||||||
|
scanConditionName: "FrameRate",
|
||||||
|
isConditionSatisfied: conditions.frameRate,
|
||||||
|
),
|
||||||
|
ScanCondition(
|
||||||
|
scanConditionName: "Server Ready",
|
||||||
|
isConditionSatisfied: conditions.serverReady,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:vital_sign_camera/vital_sign_camera.dart';
|
||||||
|
|
||||||
|
class ScanStatus extends StatelessWidget {
|
||||||
|
final GetHealthStage? stage;
|
||||||
|
final double? remainingTime;
|
||||||
|
|
||||||
|
const ScanStatus({
|
||||||
|
Key? key,
|
||||||
|
required this.stage,
|
||||||
|
required this.remainingTime,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
getRemainingTime(),
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
getScanStage(),
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(height: 100),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String getScanStage() {
|
||||||
|
if (stage == GetHealthStage.waitingData) {
|
||||||
|
return 'Waiting Data...';
|
||||||
|
} else if (stage == GetHealthStage.collectingData) {
|
||||||
|
return 'Collecting Data...';
|
||||||
|
} else if (stage == GetHealthStage.analyzingData) {
|
||||||
|
return 'Analyzing Data...';
|
||||||
|
}
|
||||||
|
return ''; // idle
|
||||||
|
}
|
||||||
|
|
||||||
|
String getRemainingTime() {
|
||||||
|
return (remainingTime != null && remainingTime != double.infinity)
|
||||||
|
? remainingTime!.toStringAsFixed(0)
|
||||||
|
: "";
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class StartButton extends StatelessWidget {
|
||||||
|
final void Function() onPressed;
|
||||||
|
final bool disabled;
|
||||||
|
|
||||||
|
const StartButton({
|
||||||
|
Key? key,
|
||||||
|
required this.onPressed,
|
||||||
|
required this.disabled,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Align(
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.fromLTRB(0, 0, 0, 50),
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: (disabled) ? () {} : onPressed,
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
fixedSize: const Size(100, 100),
|
||||||
|
shape: const CircleBorder(),
|
||||||
|
backgroundColor: (disabled) ? Colors.grey : Colors.orangeAccent,
|
||||||
|
elevation: 8,
|
||||||
|
),
|
||||||
|
child: const Text(
|
||||||
|
"START",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class VitalSignWidget extends StatelessWidget {
|
||||||
|
final String vitalSignName;
|
||||||
|
final String vitalSignValue;
|
||||||
|
final Color? textColor;
|
||||||
|
|
||||||
|
const VitalSignWidget({
|
||||||
|
Key? key,
|
||||||
|
required this.vitalSignName,
|
||||||
|
required this.vitalSignValue,
|
||||||
|
this.textColor,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
margin: const EdgeInsets.fromLTRB(0, 0, 0, 2),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
vitalSignName,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: textColor ?? Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
vitalSignValue,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: textColor ?? Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,270 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:vital_sign_camera/vital_sign_camera.dart';
|
||||||
|
|
||||||
|
import 'components/vital_sign_widget.dart';
|
||||||
|
|
||||||
|
class ResultScreen extends StatelessWidget {
|
||||||
|
final Health? healthResult;
|
||||||
|
|
||||||
|
late final VitalSign? _vitalSign;
|
||||||
|
late final HolisticAnalysis? _holisticAnalysis;
|
||||||
|
late final CardiovascularRisks? _cardiovascularRisks;
|
||||||
|
late final CovidRisk? _covidRisk;
|
||||||
|
late final ScanParameters? _scanParameters;
|
||||||
|
|
||||||
|
ResultScreen({
|
||||||
|
Key? key,
|
||||||
|
required this.healthResult,
|
||||||
|
}) : super(key: key) {
|
||||||
|
_vitalSign = healthResult?.vitalSigns;
|
||||||
|
_holisticAnalysis = healthResult?.holisticHealth;
|
||||||
|
_cardiovascularRisks = healthResult?.risks?.cardiovascularRisks;
|
||||||
|
_covidRisk = healthResult?.risks?.covidRisk;
|
||||||
|
_scanParameters = healthResult?.scanParameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final deviceSize = MediaQuery.of(context).size;
|
||||||
|
const textColor = Color.fromARGB(255, 0, 0, 0);
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('Result'),
|
||||||
|
),
|
||||||
|
body: SingleChildScrollView(
|
||||||
|
child: Center(
|
||||||
|
child: SizedBox(
|
||||||
|
width: deviceSize.width * 0.9,
|
||||||
|
child: Container(
|
||||||
|
color: const Color.fromARGB(0, 255, 255, 255),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(15),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.fromLTRB(0, 0, 0, 10),
|
||||||
|
child: const Text(
|
||||||
|
"Vital Signs",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 15,
|
||||||
|
color: Colors.amber,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "Heart Rate",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.vitalSigns.heartRate)),
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "SPO2",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.vitalSigns.spo2)),
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "IBI",
|
||||||
|
vitalSignValue:
|
||||||
|
formatValueToTwoDp(healthResult?.vitalSigns.ibi)),
|
||||||
|
if (_vitalSign?.stress != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "Stress",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.vitalSigns.stress)),
|
||||||
|
if (_vitalSign?.respiratoryRate != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "Respiratory Rate",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.vitalSigns.respiratoryRate)),
|
||||||
|
if (_vitalSign?.hrvRmssd != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "HRV RMSSD",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.vitalSigns.hrvRmssd)),
|
||||||
|
if (_vitalSign?.hrvSdnn != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "HRV SDNN",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.vitalSigns.hrvSdnn)),
|
||||||
|
if (_vitalSign?.temperature != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "Temperature",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.vitalSigns.temperature)),
|
||||||
|
if (_vitalSign?.bloodPressure != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "Blood Pressure",
|
||||||
|
vitalSignValue:
|
||||||
|
healthResult?.vitalSigns.bloodPressure ?? ""),
|
||||||
|
if (_vitalSign?.bloodPressureSystolic != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "Blood Pressure Systolic",
|
||||||
|
vitalSignValue: formatValueToTwoDp(healthResult
|
||||||
|
?.vitalSigns.bloodPressureSystolic)),
|
||||||
|
if (_vitalSign?.bloodPressureDiastolic != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "Blood Pressure Diastolic",
|
||||||
|
vitalSignValue: formatValueToTwoDp(healthResult
|
||||||
|
?.vitalSigns.bloodPressureDiastolic)),
|
||||||
|
if (_holisticAnalysis != null)
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.fromLTRB(0, 25, 0, 10),
|
||||||
|
child: const Text(
|
||||||
|
"Holistic Analysis",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 15,
|
||||||
|
color: Colors.amber,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (_holisticAnalysis != null &&
|
||||||
|
_holisticAnalysis?.bmi != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "BMI",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.holisticHealth?.bmi)),
|
||||||
|
if (_holisticAnalysis != null &&
|
||||||
|
_holisticAnalysis?.generalWellness != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "General Wellness",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.holisticHealth?.generalWellness)),
|
||||||
|
if (_holisticAnalysis != null &&
|
||||||
|
_holisticAnalysis?.absi != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "ABSI",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.holisticHealth?.absi)),
|
||||||
|
if (_holisticAnalysis != null &&
|
||||||
|
_holisticAnalysis?.cardiacWorkload != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "Cardiac Workload",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.holisticHealth?.cardiacWorkload)),
|
||||||
|
if (_holisticAnalysis != null &&
|
||||||
|
_holisticAnalysis?.pulseRespiratoryQuotient != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "Pulse Respiratory Quotient",
|
||||||
|
vitalSignValue: formatValueToTwoDp(healthResult
|
||||||
|
?.holisticHealth?.pulseRespiratoryQuotient)),
|
||||||
|
if (_holisticAnalysis != null &&
|
||||||
|
_holisticAnalysis?.waistToHeightRatio != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "Waist to Height Ratio",
|
||||||
|
vitalSignValue: formatValueToTwoDp(healthResult
|
||||||
|
?.holisticHealth?.waistToHeightRatio)),
|
||||||
|
if (_cardiovascularRisks != null)
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.fromLTRB(0, 25, 0, 10),
|
||||||
|
child: const Text(
|
||||||
|
"Cardiovascular Risks",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 15,
|
||||||
|
color: Colors.amber,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (_cardiovascularRisks != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "General",
|
||||||
|
vitalSignValue: formatValueToTwoDp(healthResult
|
||||||
|
?.risks?.cardiovascularRisks?.generalRisk)),
|
||||||
|
if (_cardiovascularRisks != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "Congestive Heart Failure",
|
||||||
|
vitalSignValue: formatValueToTwoDp(healthResult
|
||||||
|
?.risks
|
||||||
|
?.cardiovascularRisks
|
||||||
|
?.congestiveHeartFailure)),
|
||||||
|
if (_cardiovascularRisks != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "Coronary Heart Disease",
|
||||||
|
vitalSignValue: formatValueToTwoDp(healthResult
|
||||||
|
?.risks
|
||||||
|
?.cardiovascularRisks
|
||||||
|
?.coronaryHeartDisease)),
|
||||||
|
if (_cardiovascularRisks != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "Intermittent Claudication",
|
||||||
|
vitalSignValue: formatValueToTwoDp(healthResult
|
||||||
|
?.risks
|
||||||
|
?.cardiovascularRisks
|
||||||
|
?.intermittentClaudication)),
|
||||||
|
if (_cardiovascularRisks != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "Stroke",
|
||||||
|
vitalSignValue: formatValueToTwoDp(healthResult
|
||||||
|
?.risks?.cardiovascularRisks?.stroke)),
|
||||||
|
if (_covidRisk != null)
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.fromLTRB(0, 25, 0, 10),
|
||||||
|
child: const Text(
|
||||||
|
"Covid Risks",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 15,
|
||||||
|
color: Colors.amber,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (_covidRisk != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "Risk",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.risks?.covidRisk?.covidRisk)),
|
||||||
|
if (_scanParameters != null)
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.fromLTRB(0, 25, 0, 10),
|
||||||
|
child: const Text(
|
||||||
|
"Scan Parameters",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 15,
|
||||||
|
color: Colors.amber,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (_scanParameters != null)
|
||||||
|
VitalSignWidget(
|
||||||
|
textColor: textColor,
|
||||||
|
vitalSignName: "Signal Quality",
|
||||||
|
vitalSignValue: formatValueToTwoDp(
|
||||||
|
healthResult?.scanParameters?.signalQuality)),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String formatValueToTwoDp(double? value) {
|
||||||
|
return (value != null) ? value.toStringAsFixed(2) : "";
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
TODO: Add your license here.
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
include: package:flutter_lints/flutter.yaml
|
||||||
|
|
||||||
|
# Additional information about this file can be found at
|
||||||
|
# https://dart.dev/guides/language/analysis-options
|
||||||
@ -1,89 +1,89 @@
|
|||||||
@rem
|
@rem
|
||||||
@rem Copyright 2015 the original author or authors.
|
@rem Copyright 2015 the original author or authors.
|
||||||
@rem
|
@rem
|
||||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@rem you may not use this file except in compliance with the License.
|
@rem you may not use this file except in compliance with the License.
|
||||||
@rem You may obtain a copy of the License at
|
@rem You may obtain a copy of the License at
|
||||||
@rem
|
@rem
|
||||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
@rem
|
@rem
|
||||||
@rem Unless required by applicable law or agreed to in writing, software
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@rem See the License for the specific language governing permissions and
|
@rem See the License for the specific language governing permissions and
|
||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%" == "" @echo off
|
@if "%DEBUG%" == "" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@rem
|
@rem
|
||||||
@rem Gradle startup script for Windows
|
@rem Gradle startup script for Windows
|
||||||
@rem
|
@rem
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
|
|
||||||
@rem Set local scope for the variables with windows NT shell
|
@rem Set local scope for the variables with windows NT shell
|
||||||
if "%OS%"=="Windows_NT" setlocal
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
@rem Find java.exe
|
@rem Find java.exe
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if "%ERRORLEVEL%" == "0" goto execute
|
if "%ERRORLEVEL%" == "0" goto execute
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
echo.
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation.
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:findJavaFromJavaHome
|
:findJavaFromJavaHome
|
||||||
set JAVA_HOME=%JAVA_HOME:"=%
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
echo.
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation.
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute Gradle
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
rem the _cmd.exe /c_ return code!
|
rem the _cmd.exe /c_ return code!
|
||||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
exit /b 1
|
exit /b 1
|
||||||
|
|
||||||
:mainEnd
|
:mainEnd
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
:omega
|
:omega
|
||||||
|
|||||||
@ -0,0 +1,19 @@
|
|||||||
|
/// Represents the pixel format of a `Frame`.
|
||||||
|
/// * `v420`: 420 YpCbCr 8 Bi-Planar Video Range
|
||||||
|
/// * `f420`: 420 YpCbCr 8 Bi-Planar Full Range
|
||||||
|
/// * `x420`: 420 YpCbCr 10 Bi-Planar Video Range
|
||||||
|
enum PixelFormat { f420, v420, x420 }
|
||||||
|
|
||||||
|
PixelFormat pixelFormatFromString(String string) {
|
||||||
|
switch (string) {
|
||||||
|
case '420f':
|
||||||
|
return PixelFormat.f420;
|
||||||
|
case '420v':
|
||||||
|
return PixelFormat.v420;
|
||||||
|
case 'x420':
|
||||||
|
return PixelFormat.x420;
|
||||||
|
default:
|
||||||
|
// ignore: fixme
|
||||||
|
return PixelFormat.f420;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,138 @@
|
|||||||
|
/// The vital signs result of a scan.
|
||||||
|
class VitalSign {
|
||||||
|
final double heartRate;
|
||||||
|
final double spo2;
|
||||||
|
final double ibi;
|
||||||
|
final double? stress;
|
||||||
|
final double? stressScore;
|
||||||
|
final double? respiratoryRate;
|
||||||
|
final double? hrvSdnn;
|
||||||
|
final double? hrvRmssd;
|
||||||
|
final double? temperature;
|
||||||
|
final String? bloodPressure;
|
||||||
|
final double? bloodPressureSystolic;
|
||||||
|
final double? bloodPressureDiastolic;
|
||||||
|
final double? facialSkinAge;
|
||||||
|
final double? bloodAlcohol;
|
||||||
|
final double? bloodSugar;
|
||||||
|
final String? version;
|
||||||
|
|
||||||
|
const VitalSign(
|
||||||
|
this.heartRate,
|
||||||
|
this.spo2,
|
||||||
|
this.ibi,
|
||||||
|
this.stress,
|
||||||
|
this.stressScore,
|
||||||
|
this.respiratoryRate,
|
||||||
|
this.hrvSdnn,
|
||||||
|
this.hrvRmssd,
|
||||||
|
this.temperature,
|
||||||
|
this.bloodPressure,
|
||||||
|
this.bloodPressureSystolic,
|
||||||
|
this.bloodPressureDiastolic,
|
||||||
|
this.facialSkinAge,
|
||||||
|
this.bloodAlcohol,
|
||||||
|
this.bloodSugar,
|
||||||
|
this.version);
|
||||||
|
|
||||||
|
factory VitalSign.fromMap(Map map) {
|
||||||
|
return VitalSign(
|
||||||
|
map['heartRate'],
|
||||||
|
map['spo2'],
|
||||||
|
map['ibi'],
|
||||||
|
map['stress'],
|
||||||
|
map['stressScore'],
|
||||||
|
map['respiratoryRate'],
|
||||||
|
map['hrvSdnn'],
|
||||||
|
map['hrvRmssd'],
|
||||||
|
map['temperature'],
|
||||||
|
map['bloodPressure'],
|
||||||
|
map['bloodPressureSystolic'],
|
||||||
|
map['bloodPressureDiastolic'],
|
||||||
|
map['facialSkinAge'],
|
||||||
|
map['bloodAlcohol'],
|
||||||
|
map['bloodSugar'],
|
||||||
|
map['version']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The cardiovascular risks result of a scan.
|
||||||
|
class CardiovascularRisks {
|
||||||
|
final double generalRisk;
|
||||||
|
final double coronaryHeartDisease;
|
||||||
|
final double congestiveHeartFailure;
|
||||||
|
final double intermittentClaudication;
|
||||||
|
final double stroke;
|
||||||
|
|
||||||
|
const CardiovascularRisks(this.generalRisk, this.coronaryHeartDisease,
|
||||||
|
this.congestiveHeartFailure, this.intermittentClaudication, this.stroke);
|
||||||
|
|
||||||
|
factory CardiovascularRisks.fromMap(Map map) {
|
||||||
|
return CardiovascularRisks(
|
||||||
|
map['generalRisk'],
|
||||||
|
map['coronaryHeartDisease'],
|
||||||
|
map['congestiveHeartFailure'],
|
||||||
|
map['intermittentClaudication'],
|
||||||
|
map['stroke']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The covid risk result of a scan.
|
||||||
|
class CovidRisk {
|
||||||
|
final double covidRisk;
|
||||||
|
|
||||||
|
const CovidRisk(this.covidRisk);
|
||||||
|
|
||||||
|
factory CovidRisk.fromMap(Map map) {
|
||||||
|
return CovidRisk(map['covidRisk']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The health risks result of a scan.
|
||||||
|
class HealthRisks {
|
||||||
|
final CardiovascularRisks? cardiovascularRisks;
|
||||||
|
final CovidRisk? covidRisk;
|
||||||
|
final String version;
|
||||||
|
|
||||||
|
const HealthRisks(this.cardiovascularRisks, this.covidRisk, this.version);
|
||||||
|
|
||||||
|
factory HealthRisks.fromMap(Map map) {
|
||||||
|
return HealthRisks(
|
||||||
|
map['cardiovascularRisks'] != null
|
||||||
|
? CardiovascularRisks.fromMap(map['cardiovascularRisks'])
|
||||||
|
: null,
|
||||||
|
map['covidRisk'] != null ? CovidRisk.fromMap(map['covidRisk']) : null,
|
||||||
|
map['version']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The holistic analysis result of a scan.
|
||||||
|
class HolisticAnalysis {
|
||||||
|
final double? generalWellness;
|
||||||
|
final double? bmi;
|
||||||
|
final double? absi;
|
||||||
|
final double? cardiacWorkload;
|
||||||
|
final double? pulseRespiratoryQuotient;
|
||||||
|
final double? waistToHeightRatio;
|
||||||
|
final String? version;
|
||||||
|
|
||||||
|
const HolisticAnalysis(
|
||||||
|
this.generalWellness,
|
||||||
|
this.bmi,
|
||||||
|
this.absi,
|
||||||
|
this.cardiacWorkload,
|
||||||
|
this.pulseRespiratoryQuotient,
|
||||||
|
this.waistToHeightRatio,
|
||||||
|
this.version);
|
||||||
|
|
||||||
|
factory HolisticAnalysis.fromMap(Map map) {
|
||||||
|
return HolisticAnalysis(
|
||||||
|
map['generalWellness'],
|
||||||
|
map['bmi'],
|
||||||
|
map['absi'],
|
||||||
|
map['cardiacWorkload'],
|
||||||
|
map['pulseRespiratoryQuotient'],
|
||||||
|
map['waistToHeightRatio'],
|
||||||
|
map['version']);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
||||||
|
import 'camera_permission.dart';
|
||||||
|
|
||||||
|
import 'camera_device.dart';
|
||||||
|
import 'vital_sign_camera_method_channel.dart';
|
||||||
|
|
||||||
|
abstract class VitalSignCameraPlatform extends PlatformInterface {
|
||||||
|
/// Constructs a VitalSignCameraPlatform.
|
||||||
|
VitalSignCameraPlatform() : super(token: _token);
|
||||||
|
|
||||||
|
static final Object _token = Object();
|
||||||
|
|
||||||
|
static VitalSignCameraPlatform _instance = MethodChannelVitalSignCamera();
|
||||||
|
|
||||||
|
/// The default instance of [VitalSignCameraPlatform] to use.
|
||||||
|
///
|
||||||
|
/// Defaults to [MethodChannelVitalSignCamera].
|
||||||
|
static VitalSignCameraPlatform get instance => _instance;
|
||||||
|
|
||||||
|
/// Platform-specific implementations should set this with their own
|
||||||
|
/// platform-specific class that extends [VitalSignCameraPlatform] when
|
||||||
|
/// they register themselves.
|
||||||
|
static set instance(VitalSignCameraPlatform instance) {
|
||||||
|
PlatformInterface.verifyToken(instance, _token);
|
||||||
|
_instance = instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<CameraDevice>> availableCameraDevices() {
|
||||||
|
throw UnimplementedError(
|
||||||
|
'availableCameraDevices() has not been implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<CameraPermissionStatus> requestCameraPermission() {
|
||||||
|
throw UnimplementedError(
|
||||||
|
'availableCameraDevices() has not been implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<CameraPermissionStatus> getCameraPermissionStatus() {
|
||||||
|
throw UnimplementedError(
|
||||||
|
'getCameraPermissionStatus() has not been implemented.');
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue