@ -13,11 +13,16 @@ enum Durations {
yearly ( " yearly " ) ;
yearly ( " yearly " ) ;
final String value ;
final String value ;
const Durations ( this . value ) ;
const Durations ( this . value ) ;
}
}
class HealthDataTransformation {
class HealthDataTransformation {
Map < String , List < DataPoint > > transformVitalsToDataPoints ( VitalsWRTType vitals , String filterType , String selectedSection , ) {
Map < String , List < DataPoint > > transformVitalsToDataPoints (
VitalsWRTType vitals ,
String filterType ,
String selectedSection ,
) {
final Map < String , List < DataPoint > > dataPointMap = { } ;
final Map < String , List < DataPoint > > dataPointMap = { } ;
Map < String , List < Vitals > > data = vitals . getVitals ( ) ;
Map < String , List < Vitals > > data = vitals . getVitals ( ) ;
/ / Group data based on the filter type
/ / Group data based on the filter type
@ -32,31 +37,36 @@ class HealthDataTransformation {
for ( var vital in item ) {
for ( var vital in item ) {
String key = " " ;
String key = " " ;
if ( vital . value = = " " | | vital . timestamp = = " " ) continue ;
if ( vital . value = = " " | | vital . timestamp = = " " ) continue ;
var parseDate = DateTime . parse ( vital . timestamp ) ;
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 ( ) ) ;
var currentDate = normalizeToStartOfDay ( DateTime . now ( ) ) ;
if ( filterType = = Durations . daily . value ) {
if ( filterType = = Durations . daily . value ) {
if ( isBetweenInclusive ( parseDate , currentDate , DateTime . now ( ) ) ) {
if ( isBetweenInclusive ( parseDate , currentDate , DateTime . now ( ) ) ) {
key = DateFormat ( ' yyyy-MM-dd HH ' ) . format ( DateTime . parse ( vital . timestamp ) ) ;
key = DateFormat ( ' yyyy-MM-dd HH ' ) . format ( parseDate ) ;
groupedData . putIfAbsent ( key , ( ) = > [ ] ) . add ( vital ) ;
groupedData . putIfAbsent ( key , ( ) = > [ ] ) . add ( vital ) ;
} / / Group by hour
} / / Group by hour
} else if ( filterType = = Durations . weekly . value ) {
} else if ( filterType = = Durations . weekly . value ) {
if ( isBetweenInclusive ( parseDate , currentDate . subtract ( Duration ( days: 7 ) ) , DateTime . now ( ) ) ) {
if ( isBetweenInclusive ( parseDate , currentDate . subtract ( Duration ( days: 7 ) ) , DateTime . now ( ) ) ) {
key = DateFormat ( ' yyyy-MM-dd ' ) . format ( DateTime. parse ( vital . timestamp ) ) ;
key = DateFormat ( ' yyyy-MM-dd ' ) . format ( parseDate ) ;
groupedData . putIfAbsent ( key , ( ) = > [ ] ) . add ( vital ) ;
groupedData . putIfAbsent ( key , ( ) = > [ ] ) . add ( vital ) ;
} / / Group by day
} / / Group by day
} else if ( filterType = = Durations . monthly . value ) {
} else if ( filterType = = Durations . monthly . value ) {
if ( isBetweenInclusive ( parseDate , currentDate . subtract ( Duration ( days: 30 ) ) , DateTime . now ( ) ) ) {
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 " ) ;
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 ) ) ;
key = DateFormat ( ' yyyy-MM-dd ' ) . format ( parseDate ) ;
groupedData . putIfAbsent ( key , ( ) = > [ ] ) . add ( vital ) ;
groupedData . putIfAbsent ( key , ( ) = > [ ] ) . add ( vital ) ;
} / / Group by day
} / / Group by day
} else if ( filterType = = Durations . halfYearly . value | | filterType = = Durations . yearly . value ) {
} 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 ( ) ) ) {
if ( isBetweenInclusive ( parseDate , currentDate . subtract ( Duration ( days: filterType = = Durations . halfYearly . value ? 180 : 365 ) ) , DateTime . now ( ) ) ) {
key = DateFormat ( ' yyyy-MM ' ) . format ( DateTime. parse ( vital . timestamp ) ) ;
key = DateFormat ( ' yyyy-MM ' ) . format ( parseDate ) ;
groupedData . putIfAbsent ( key , ( ) = > [ ] ) . add ( vital ) ;
groupedData . putIfAbsent ( key , ( ) = > [ ] ) . add ( vital ) ;
} / / Group by month
} / / Group by month
} else {
} else {
throw ArgumentError ( ' Invalid filter type ' ) ;
throw ArgumentError ( ' Invalid filter type ' ) ;
@ -68,9 +78,9 @@ class HealthDataTransformation {
groupedData . forEach ( ( key , values ) {
groupedData . forEach ( ( key , values ) {
double sum = values . fold ( 0 , ( acc , v ) = > acc + num . parse ( v . value ) ) ;
double sum = values . fold ( 0 , ( acc , v ) = > acc + num . parse ( v . value ) ) ;
double mean = sum / values . length ;
double mean = sum / values . length ;
if ( selectedSection = = " bodyOxygen " | | selectedSection = = " bodyTemperature " ) {
if ( selectedSection = = " bodyOxygen " | | selectedSection = = " bodyTemperature " ) {
mean = sum / values . length ;
mean = sum / values . length ;
} else {
} else {
mean = sum ;
mean = sum ;
}
}
@ -81,7 +91,7 @@ class HealthDataTransformation {
label: key ,
label: key ,
actualValue: finalValue . toStringAsFixed ( 2 ) ,
actualValue: finalValue . toStringAsFixed ( 2 ) ,
displayTime: key ,
displayTime: key ,
unitOfMeasurement: values . first . unitOfMeasure ,
unitOfMeasurement: values . first . unitOfMeasure ,
time: DateTime . parse ( values . first . timestamp ) ,
time: DateTime . parse ( values . first . timestamp ) ,
) ) ;
) ) ;
} ) ;
} ) ;
@ -109,10 +119,10 @@ class HealthDataTransformation {
final random = Random ( ) ;
final random = Random ( ) ;
/ / Smooth compression scaling
/ / 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 % )
/ / 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 ;
double result = baseScaled * randomFactor ;
@ -122,6 +132,7 @@ class HealthDataTransformation {
DateTime normalizeToStartOfDay ( DateTime date ) {
DateTime normalizeToStartOfDay ( DateTime date ) {
return DateTime ( date . year , date . month , date . day ) ;
return DateTime ( date . year , date . month , date . day ) ;
}
}
bool isBetweenInclusive (
bool isBetweenInclusive (
DateTime target ,
DateTime target ,
DateTime start ,
DateTime start ,
@ -129,6 +140,4 @@ class HealthDataTransformation {
) {
) {
return ! normalizeToStartOfDay ( target ) . isBefore ( start ) & & ! normalizeToStartOfDay ( target ) . isAfter ( end ) ;
return ! normalizeToStartOfDay ( target ) . isBefore ( start ) & & ! normalizeToStartOfDay ( target ) . isAfter ( end ) ;
}
}
}
}