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 Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@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 obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@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 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
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.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@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 obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@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 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
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.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
: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