Skip to content

Commit

Permalink
Merge pull request #21 from Ornament-Health/develop
Browse files Browse the repository at this point in the history
Added a new aggregation type: daily average
  • Loading branch information
Cirych authored Aug 8, 2024
2 parents 57e6ec3 + 1d67d30 commit 6e78329
Show file tree
Hide file tree
Showing 15 changed files with 7,764 additions and 128 deletions.
3 changes: 2 additions & 1 deletion RCTAppleHealthKit/RCTAggregatorType.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ typedef enum : NSUInteger {
RCTAggregatorTypeAverage,
RTCAggregatorCumulativeSum,
RCTAggregatorTypeFirst,
RCTAggregatorTypeLast
RCTAggregatorTypeLast,
RCTAggregatorTypeDailyAverage
} RCTAggregatorType;
6 changes: 6 additions & 0 deletions RCTAppleHealthKit/RCTStatisticRequest.m
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ - (HKStatisticsOptions)statisticsOptions {
case RTCAggregatorCumulativeSum: {
return HKStatisticsOptionCumulativeSum;
}
case RCTAggregatorTypeDailyAverage: {
return HKStatisticsOptionCumulativeSum;
}
default: {
return nil;
}
Expand All @@ -107,6 +110,9 @@ - (HKQuantity *)fetchValue:(HKStatistics *)statistics {
case RTCAggregatorCumulativeSum: {
return statistics.sumQuantity;
}
case RCTAggregatorTypeDailyAverage: {
return statistics.sumQuantity;
}
default: {
return nil;
}
Expand Down
41 changes: 35 additions & 6 deletions RCTAppleHealthKit/RTCAppleHealthKit+Methods_Statistics.m
Original file line number Diff line number Diff line change
Expand Up @@ -705,22 +705,30 @@ - (void)basicDietaryStatisticsRequest:(NSDictionary *)input
[self averageDietaryStatisticsRequest:input
callback:callback
quantity:quantity
unit:unit];
unit:unit
dailyAverage:false];
} else if (aggregatorType == 3) {
[self basicStatisticsRequest:input
callback:callback
quantity:quantity
unit:unit];
} else if (aggregatorType == 6) {
[self averageDietaryStatisticsRequest:input
callback:callback
quantity:quantity
unit:unit
dailyAverage:true];
} else {
callback(@[RCTMakeError(@"RNHealth: Aggregator should be CUMULATIVE_SUM = 3 or AVERAGE = 2", nil, nil)]);
callback(@[RCTMakeError(@"RNHealth: Aggregator should be AVERAGE = 2, CUMULATIVE_SUM = 3, DAILY_AVERAGE = 6", nil, nil)]);
return;
}
}

- (void)averageDietaryStatisticsRequest:(NSDictionary *)input
callback:(RCTResponseSenderBlock)callback
quantity:(HKQuantityTypeIdentifier)quantity
unit:(HKUnit *)unit {
unit:(HKUnit *)unit
dailyAverage: (BOOL)dailyAverage {

NSDate *startDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:nil];
NSDate *endDate = [RCTAppleHealthKit dateFromOptions:input key:@"endDate" withDefault:[NSDate date]];
Expand Down Expand Up @@ -834,15 +842,21 @@ - (void)averageDietaryStatisticsRequest:(NSDictionary *)input
NSArray *intervals = [samplesOutput filteredArrayUsingPredicate:predicate];
[groupedByInterval setObject:intervals forKey:name];
}


NSMutableSet *setOfDatesWithEntries = [NSMutableSet new];
NSMutableArray *resultWithSumForInterval = [NSMutableArray new];
for (NSString* key in groupedByInterval) {
NSArray<__kindof NSDictionary *> *intervalValues = groupedByInterval[key];
double intervalValue = 0;
double entriesCount = 0;
setOfDatesWithEntries = [NSMutableSet new];
for (NSDictionary *intervalValueObj in intervalValues) {
intervalValue += [intervalValueObj[@"value"] doubleValue];
entriesCount += 1;
NSDateFormatter *intervalDateFormatter = [[NSDateFormatter alloc] init];
[intervalDateFormatter setDateFormat:@"yyyy-MM-dd"];
NSString *intervalDay = [intervalDateFormatter stringFromDate:intervalValueObj[@"startDate"]];
[setOfDatesWithEntries addObject:intervalDay];
}

NSDate *startIntervalDate;
Expand Down Expand Up @@ -873,9 +887,24 @@ - (void)averageDietaryStatisticsRequest:(NSDictionary *)input
resultForInterval[@"endDate"] = endDateString;

double averageValue = 0;
if (entriesCount != 0) {
averageValue = intervalValue / entriesCount;

if (dailyAverage) {
if (intervalType == RCTIntervalDay) {
if (entriesCount != 0) {
averageValue = intervalValue / entriesCount;
}
} else {
double datesWithEntries = setOfDatesWithEntries.count;
if (datesWithEntries != 0) {
averageValue = intervalValue / datesWithEntries;
}
}
} else {
if (entriesCount != 0) {
averageValue = intervalValue / entriesCount;
}
}

resultForInterval[@"value"] = @(averageValue);

NSString *json = [RCTAppleHealthKit stringFromObject:resultForInterval];
Expand Down
3 changes: 2 additions & 1 deletion docs/statistics.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ AppleHealthKit.getStatisticBodyMass(
},
)
```
For dietary biomarkers (Macronutrients, Vitamins, Minerals, Hydration, Caffeination, Ultratrace Minerals types) could be calculated average or cumulative values.
For dietary biomarkers (Macronutrients, Vitamins, Minerals, Hydration, Caffeination, Ultratrace Minerals types) could be calculated interval average, daily average or cumulative values.

## Request payload

Expand All @@ -128,6 +128,7 @@ enum GenericAggregatorsType {

enum AverageAggregatorsType {
AVERAGE = 2,
DAILY_AVERAGE = 6,
}

enum CumulativeAggregatorsType {
Expand Down
2 changes: 1 addition & 1 deletion example/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
root: true,
extends: '@react-native-community',
extends: '@react-native',
};
3 changes: 2 additions & 1 deletion example/.prettierrc.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module.exports = {
arrowParens: 'avoid',
bracketSameLine: true,
bracketSpacing: false,
jsxBracketSameLine: true,
singleQuote: true,
trailingComma: 'all',
};
11 changes: 11 additions & 0 deletions example/ios/.xcode.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# This `.xcode.env` file is versioned and is used to source the environment
# used when running script phases inside Xcode.
# To customize your local environment, you can create an `.xcode.env.local`
# file that is not versioned.

# NODE_BINARY variable contains the PATH to the node executable.
#
# Customize the NODE_BINARY variable here.
# For example, to use nvm with brew, add the following line
# . "$(brew --prefix nvm)/nvm.sh" --no-use
export NODE_BINARY=$(command -v node)
69 changes: 49 additions & 20 deletions example/ios/Podfile
Original file line number Diff line number Diff line change
@@ -1,36 +1,65 @@
require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
# Resolve react_native_pods.rb with node to allow for hoisting
require Pod::Executable.execute_command('node', ['-p',
'require.resolve(
"react-native/scripts/react_native_pods.rb",
{paths: [process.argv[1]]},
)', __dir__]).strip

platform :ios, '13.0'
platform :ios, 14.0
prepare_react_native_project!

linkage = ENV['USE_FRAMEWORKS']
if linkage != nil
Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
use_frameworks! :linkage => linkage.to_sym
end

target 'example' do
config = use_native_modules!

use_react_native!(:path => config["reactNativePath"])
# Flags change depending on the env values.
flags = get_default_flags()

use_react_native!(
:path => config[:reactNativePath],
# Hermes is now enabled by default. Disable by setting this flag to false.
:hermes_enabled => flags[:hermes_enabled],
:fabric_enabled => flags[:fabric_enabled],
:app_path => "#{Pod::Config.instance.installation_root}/.."
)

target 'exampleTests' do
inherit! :complete
# Pods for testing
end

# Enables Flipper.
#
# Note that if you have use_frameworks! enabled, Flipper will not work and
# you should disable these next few lines.
use_flipper!({ 'Flipper-Folly' => '2.5.3', 'Flipper' => '0.87.0', 'Flipper-RSocket' => '1.3.1' })
post_install do |installer|
flipper_post_install(installer)
installer.pods_project.build_configurations.each do |config|
config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"
end
end
end
# https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
# FIXES BUILD ON Apple Silicon M1+
projects = installer.aggregate_targets
.map{ |t| t.user_project }
.uniq{ |p| p.path }

target 'example-tvOS' do
# Pods for example-tvOS
# project.pbxproj
projects.each do |project|
project.build_configurations.each do |config|
config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'
end

target 'example-tvOSTests' do
inherit! :search_paths
# Pods for testing
project.save()
end

installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'
end
end

react_native_post_install(
installer,
config[:reactNativePath],
:mac_catalyst_enabled => false
)
__apply_Xcode_12_5_M1_post_install_workaround(installer)
end
end
Loading

0 comments on commit 6e78329

Please sign in to comment.