data integration along with the data representation
parent
5ea70397e2
commit
bfeb3dce4e
@ -1,4 +1,4 @@
|
||||
package com.ejada.hmg.samsung_watch.model
|
||||
package com.ejada.hmg.watch.huawei.samsung_watch.model
|
||||
|
||||
data class Vitals(
|
||||
var value : String = "",
|
||||
@ -0,0 +1,128 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:hmg_patient_app_new/core/common_models/data_points.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import 'model/Vitals.dart';
|
||||
|
||||
enum Durations {
|
||||
daily("daily"),
|
||||
weekly("weekly"),
|
||||
monthly("weekly"),
|
||||
halfYearly("halfYearly"),
|
||||
yearly("yearly");
|
||||
|
||||
final String value;
|
||||
const Durations(this.value);
|
||||
}
|
||||
|
||||
class HealthDataTransformation {
|
||||
Map<String, List<DataPoint>> transformVitalsToDataPoints(VitalsWRTType vitals, String filterType, String selectedSection,) {
|
||||
final Map<String, List<DataPoint>> dataPointMap = {};
|
||||
Map<String, List<Vitals>> data = vitals.getVitals();
|
||||
// Group data based on the filter type
|
||||
Map<String, List<Vitals>> groupedData = {};
|
||||
// List<List<Vitals> > items = data.values.toList();
|
||||
List<String> keys = data.keys.toList();
|
||||
var count = 0;
|
||||
List<Vitals> item = data[selectedSection] ?? [];
|
||||
// for(var item in items) {
|
||||
List<DataPoint> dataPoints = [];
|
||||
|
||||
for (var vital in item) {
|
||||
String key = "";
|
||||
if (vital.value == "" || vital.timestamp == "") continue;
|
||||
var parseDate = DateTime.parse(vital.timestamp);
|
||||
var currentDate = normalizeToStartOfDay(DateTime.now());
|
||||
if (filterType == Durations.daily.value) {
|
||||
if(isBetweenInclusive(parseDate, currentDate, DateTime.now())) {
|
||||
key = DateFormat('yyyy-MM-dd HH').format(DateTime.parse(vital.timestamp));
|
||||
groupedData.putIfAbsent(key, () => []).add(vital);
|
||||
}// Group by hour
|
||||
} else if (filterType == Durations.weekly.value) {
|
||||
if(isBetweenInclusive(parseDate, currentDate.subtract(Duration(days: 7)), DateTime.now())) {
|
||||
key = DateFormat('yyyy-MM-dd').format(DateTime.parse(vital.timestamp));
|
||||
groupedData.putIfAbsent(key, () => []).add(vital);
|
||||
|
||||
} // Group by day
|
||||
} else if (filterType == Durations.monthly.value) {
|
||||
if(isBetweenInclusive(parseDate, currentDate.subtract(Duration(days: 30)), DateTime.now())) {
|
||||
key = DateFormat('yyyy-MM-dd').format(DateTime.parse(vital.timestamp));
|
||||
groupedData.putIfAbsent(key, () => []).add(vital);
|
||||
|
||||
} // Group by day
|
||||
} else if (filterType == Durations.halfYearly.value || filterType == Durations.yearly.value) {
|
||||
if(isBetweenInclusive(parseDate, currentDate.subtract(Duration(days: filterType == Durations.halfYearly.value?180: 365)), DateTime.now())) {
|
||||
key = DateFormat('yyyy-MM').format(DateTime.parse(vital.timestamp));
|
||||
groupedData.putIfAbsent(key, () => []).add(vital);
|
||||
|
||||
} // Group by month
|
||||
} else {
|
||||
throw ArgumentError('Invalid filter type');
|
||||
}
|
||||
}
|
||||
print("the size of groupData is ${groupedData.values.length}");
|
||||
|
||||
// Process grouped data
|
||||
groupedData.forEach((key, values) {
|
||||
double sum = values.fold(0, (acc, v) => acc + num.parse(v.value));
|
||||
double mean = sum / values.length;
|
||||
|
||||
double finalValue = filterType == 'weekly' ? mean : sum;
|
||||
print("the final value is $finalValue for the key $key with the original values ${values.map((v) => v.value).toList()} and uom is ${values.first.unitOfMeasure}");
|
||||
dataPoints.add(DataPoint(
|
||||
value: smartScale(finalValue),
|
||||
label: key,
|
||||
actualValue: finalValue.toStringAsFixed(2),
|
||||
displayTime: key,
|
||||
unitOfMeasurement:values.first.unitOfMeasure ,
|
||||
time: DateTime.parse(values.first.timestamp),
|
||||
));
|
||||
});
|
||||
|
||||
dataPointMap[filterType] = dataPoints;
|
||||
// }
|
||||
return dataPointMap;
|
||||
}
|
||||
|
||||
double smartScale(double number) {
|
||||
// if (number <= 0) return 0;
|
||||
// final _random = Random();
|
||||
// double ratio = number / 100;
|
||||
//
|
||||
// double scalingFactor = ratio > 1 ? 100 / number : 100;
|
||||
//
|
||||
// double result = (number / 100) * scalingFactor;
|
||||
// print("the ratio is ${ratio.toInt()+1}");
|
||||
// double max = (100+_random.nextInt(ratio.toInt()+10)).toDouble();
|
||||
//
|
||||
// return result.clamp(0, max);
|
||||
|
||||
if (number <= 0) return 0;
|
||||
|
||||
final random = Random();
|
||||
|
||||
// Smooth compression scaling
|
||||
double baseScaled = number <20 ? number:100 * (number / (number + 100));
|
||||
|
||||
// Random factor between 0.9 and 1.1 (±10%)
|
||||
double randomFactor = number <20 ? random.nextDouble() * 1.5: 0.9 + random.nextDouble() * 0.2;
|
||||
|
||||
double result = baseScaled * randomFactor;
|
||||
|
||||
return result.clamp(0, 100);
|
||||
}
|
||||
|
||||
DateTime normalizeToStartOfDay(DateTime date) {
|
||||
return DateTime(date.year, date.month, date.day);
|
||||
}
|
||||
bool isBetweenInclusive(
|
||||
DateTime target,
|
||||
DateTime start,
|
||||
DateTime end,
|
||||
) {
|
||||
return !normalizeToStartOfDay(target).isBefore(start) && !normalizeToStartOfDay(target).isAfter(end);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,86 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:async/src/result/result.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:hmg_patient_app_new/features/smartwatch_health_data/watch_connectors/watch_helper.dart';
|
||||
import 'package:huawei_health/huawei_health.dart';
|
||||
|
||||
class HuaweiHealthDataConnector extends WatchHelper{
|
||||
final MethodChannel _channel = MethodChannel('huawei_watch');
|
||||
@override
|
||||
Future<Result<bool>> initDevice() async{
|
||||
try{
|
||||
await _channel.invokeMethod('init');
|
||||
|
||||
}catch(e){
|
||||
|
||||
}
|
||||
// List of scopes to ask for authorization.
|
||||
// Note: These scopes should also be authorized on the Huawei Developer Console.
|
||||
List<Scope> scopes = [
|
||||
Scope.HEALTHKIT_STEP_READ, Scope.HEALTHKIT_OXYGEN_SATURATION_READ, // View and store height and weight data in Health Service Kit.
|
||||
Scope.HEALTHKIT_HEARTRATE_READ, Scope.HEALTHKIT_SLEEP_READ,
|
||||
Scope.HEALTHKIT_BODYTEMPERATURE_READ, Scope.HEALTHKIT_CALORIES_READ
|
||||
];
|
||||
try {
|
||||
bool? result = await SettingController.getHealthAppAuthorization();
|
||||
debugPrint(
|
||||
'Granted Scopes for result == is $result}',
|
||||
);
|
||||
return Result.value(true);
|
||||
} catch (e) {
|
||||
debugPrint('Error on authorization, Error:${e.toString()}');
|
||||
return Result.error(false);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> getActivity() async {
|
||||
DataType dataTypeResult = await SettingController.readDataType(
|
||||
DataType.DT_CONTINUOUS_STEPS_DELTA.name
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@override
|
||||
Future getBloodOxygen() {
|
||||
throw UnimplementedError();
|
||||
|
||||
}
|
||||
|
||||
@override
|
||||
Future getBodyTemperature() {
|
||||
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
FutureOr<void> getHeartRate() {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
FutureOr<void> getSleep() {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
FutureOr<void> getSteps() {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Future retrieveData() {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
FutureOr<void> getDistance() {
|
||||
// TODO: implement getDistance
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue