@ -13,80 +13,90 @@ enum Durations {
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 < 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 ] ? ? [ ] ;
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 ( ) ) ) {
print ( " the value for the monthly filter is ${ vital . value } with the timestamp ${ vital . timestamp } and the current date is $ currentDate and the parse date is $ parseDate " ) ;
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 ' ) ;
}
List < DataPoint > dataPoints = [ ] ;
for ( var vital in item ) {
String key = " " ;
if ( vital . value = = " " | | vital . timestamp = = " " ) continue ;
DateTime parseDate ;
try {
parseDate = DateTime . parse ( vital . timestamp ) ;
} catch ( e ) {
print ( ' Error parsing timestamp " ${ vital . timestamp } ": $ e ' ) ;
continue ; / / Skip this vital if timestamp is invalid
}
var currentDate = normalizeToStartOfDay ( DateTime . now ( ) ) ;
if ( filterType = = Durations . daily . value ) {
if ( isBetweenInclusive ( parseDate , currentDate , DateTime . now ( ) ) ) {
key = DateFormat ( ' yyyy-MM-dd HH ' ) . format ( parseDate ) ;
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 ( parseDate ) ;
groupedData . putIfAbsent ( key , ( ) = > [ ] ) . add ( vital ) ;
} / / Group by day
} else if ( filterType = = Durations . monthly . value ) {
if ( isBetweenInclusive ( parseDate , currentDate . subtract ( Duration ( days: 30 ) ) , DateTime . now ( ) ) ) {
print ( " the value for the monthly filter is ${ vital . value } with the timestamp ${ vital . timestamp } and the current date is $ currentDate and the parse date is $ parseDate " ) ;
key = DateFormat ( ' yyyy-MM-dd ' ) . format ( parseDate ) ;
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 ( parseDate ) ;
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 ;
if ( selectedSection = = " bodyOxygen " | | selectedSection = = " bodyTemperature " ) {
mean = sum / values . length ;
} else {
mean = sum ;
}
double finalValue = mean ;
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 ;
}
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 ;
if ( selectedSection = = " bodyOxygen " | | selectedSection = = " bodyTemperature " ) {
mean = sum / values . length ;
} else {
mean = sum ;
}
double finalValue = mean ;
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 ;
}
@ -109,10 +119,10 @@ class HealthDataTransformation {
final random = Random ( ) ;
/ / Smooth compression scaling
double baseScaled = number < 20 ? number: 100 * ( number / ( number + 100 ) ) ;
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 randomFactor = number < 20 ? random . nextDouble ( ) * 1.5 : 0.9 + random . nextDouble ( ) * 0.2 ;
double result = baseScaled * randomFactor ;
@ -122,13 +132,12 @@ class HealthDataTransformation {
DateTime normalizeToStartOfDay ( DateTime date ) {
return DateTime ( date . year , date . month , date . day ) ;
}
bool isBetweenInclusive (
DateTime target ,
DateTime start ,
DateTime end ,
) {
DateTime target ,
DateTime start ,
DateTime end ,
) {
return ! normalizeToStartOfDay ( target ) . isBefore ( start ) & & ! normalizeToStartOfDay ( target ) . isAfter ( end ) ;
}
}
}