Created
August 28, 2015 20:07
-
-
Save 0thernet/eae5d069c7c38f008f2a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// PFTrendsViewModel.m | |
// SUM | |
// | |
// Created by Ben Guo on 11/26/14. | |
// Copyright (c) 2014 Project Florida. All rights reserved. | |
// | |
#import "PFTestUtilities.h" | |
#import "PFTrendsViewModel.h" | |
#import "UIColor+SUM.h" | |
#import "PFTrendsCategoryCellModel.h" | |
#import "PFTrendsDetailViewModel.h" | |
#import "NSCalendar+SUM.h" | |
#import "NSDate+SUM.h" | |
#import "PFDateUtils.h" | |
#import "PFChartValue.h" | |
#import "PFScoreManager.h" | |
#import "PFDailyScoreModel.h" | |
#import "PFTimeseriesDescriptor.h" | |
#import "PFAPIManager+Timeseries.h" | |
#import "PFAccountManager.h" | |
#import "PFUserModel.h" | |
#import "PFUserProfileModel.h" | |
#import "PFAccountManager.h" | |
@interface PFTrendsViewModel () | |
@property (nonatomic, strong, readwrite) NSDate *startDate; | |
@property (nonatomic, strong, readwrite) NSDate *endDate; | |
@property (nonatomic, readwrite) NSUInteger numberOfWeeks; | |
@property (nonatomic, readwrite) BOOL rightBarButtonVisible; | |
@property (nonatomic, strong, readwrite) NSString *title; | |
@property (nonatomic, strong, readwrite) NSString *allTimeHeaderTopText; | |
@property (nonatomic, strong, readwrite) NSString *allTimeHeaderMiddleText; | |
@property (nonatomic, strong, readwrite) NSString *allTimeHeaderBottomText; | |
@property (nonatomic, strong, readwrite) NSString *weeklyHeaderTopText; | |
@property (nonatomic, strong, readwrite) NSString *weeklyHeaderMiddleText; | |
@property (nonatomic, strong, readwrite) NSString *weeklyHeaderBottomText; | |
@property (nonatomic, strong, readwrite) NSString *categoryHeaderDetailText; | |
@property (nonatomic, strong) RACSignal *allTimeScoreSignal; | |
@property (nonatomic, strong) RACSignal *createdDateSignal; | |
@property (nonatomic, strong) PFTrendsDetailViewModel *detailViewModel; | |
@property (nonatomic, strong) PFTrendsDataSourceObject *sleepPointsDataSourceObject; | |
@property (nonatomic, strong) PFTrendsDataSourceObject *activityPointsDataSourceObject; | |
@property (nonatomic, strong) PFTrendsDataSourceObject *calmPointsDataSourceObject; | |
@property (nonatomic, strong) PFTrendsDataSourceObject *stressPointsDataSourceObject; | |
@end | |
@implementation PFTrendsViewModel | |
- (instancetype)initWithAllTimeScoreSignal:(RACSignal *)scoreSignal userCreatedDateSignal:(RACSignal *)createdDateSignal | |
{ | |
self = [super init]; | |
if (self) { | |
_allTimeScoreSignal = scoreSignal; | |
_createdDateSignal = createdDateSignal; | |
_title = NSLocalizedString(@"Trends", @"Trends title"); | |
_timeseriesDescriptor = [PFTimeseriesDescriptor descriptorWithId:PFTimeseriesIdPoints]; | |
_backgroundColor = [UIColor pf_darkBlueColor]; | |
_darkBackgroundColor = [UIColor pf_darkBlueDarkColor]; | |
NSDate *now = [NSDate date]; | |
NSDate *beginningOfWeek = [now beginningOfWeek]; | |
NSDate *endOfWeek = [now endOfWeek]; | |
_startDate = beginningOfWeek; | |
_endDate = endOfWeek; | |
_allTimeHeaderTopText = [PFTrendsDetailViewModel stringForDataType:PFTrendsDataTypeSumScore]; | |
_allTimeHeaderBottomText = [NSLocalizedString(@"All-Time Average", @"Trends header text") uppercaseStringWithLocale:[NSLocale currentLocale]]; | |
_weeklyHeaderTopText = _allTimeHeaderTopText; | |
_categoryCells = @[ | |
[[PFTrendsCategoryCellModel alloc] initWithCategory:PFTrendsCategorySleep score:@(0)], | |
[[PFTrendsCategoryCellModel alloc] initWithCategory:PFTrendsCategoryActivity score:@(0)], | |
[[PFTrendsCategoryCellModel alloc] initWithCategory:PFTrendsCategoryCalm score:@(0)], | |
[[PFTrendsCategoryCellModel alloc] initWithCategory:PFTrendsCategoryStress score:@(0)] | |
]; | |
_timeWindowType = PFTrendsTimeWindowTypeWeekly; | |
@weakify(self) | |
[[[self.createdDateSignal ignore:nil] take:1] subscribeNext:^(NSDate *createdDate) { | |
@strongify(self) | |
NSDate *todayEnd = [[NSDate date] trailingEdge]; | |
NSDate *beginningOfWeekJoined = [createdDate beginningOfWeek]; | |
NSDate *endOfCurrentWeek = [todayEnd endOfWeek]; | |
self.startDate = beginningOfWeekJoined; | |
self.endDate = endOfCurrentWeek; | |
self.numberOfWeeks = [endOfCurrentWeek numberOfWeeksSinceDate:beginningOfWeekJoined]; | |
/// Only show the all-time toggle after 2 full weeks | |
NSUInteger numberOfDaysInWeek = [NSCalendar numberOfDaysPerWeek]; | |
NSUInteger days = [[NSCalendar pf_currentCalendar] components:NSCalendarUnitDay fromDate:createdDate | |
toDate:todayEnd options:0].day; | |
self.rightBarButtonVisible = days >= numberOfDaysInWeek*2; | |
self.currentWeek = self.numberOfWeeks - 1; | |
self.dataSource = [[PFTrendsDataSourceObject alloc] initWithDataType:PFTrendsDataTypeSumScore | |
startDate:self.startDate]; | |
self.detailViewModel = [[PFTrendsDetailViewModel alloc] initWithCategory:PFTrendsCategoryActivity | |
dataType:PFTrendsDataTypeActivityPoints | |
timeWindowType:PFTrendsTimeWindowTypeWeekly | |
numberOfWeeks:self.numberOfWeeks | |
currentWeek:self.currentWeek | |
startDate:self.startDate]; | |
self.activityPointsDataSourceObject = [self.detailViewModel dataSourceForDataType:PFTrendsDataTypeActivityPoints]; | |
self.sleepPointsDataSourceObject = [self.detailViewModel dataSourceForDataType:PFTrendsDataTypeSleepPoints]; | |
self.calmPointsDataSourceObject = [self.detailViewModel dataSourceForDataType:PFTrendsDataTypeCalmPoints]; | |
self.stressPointsDataSourceObject = [self.detailViewModel dataSourceForDataType:PFTrendsDataTypeStressPoints]; | |
[PFTrendsViewModel fetchDataWithStartDate:self.startDate numberOfWeeks:self.numberOfWeeks | |
timeseries:self.timeseriesDescriptor | |
apiManager:[PFAPIManager sharedManager] | |
callback:^(NSArray *data, NSArray *trendlineData, NSError *error) { | |
if (data) { | |
self.dataSource.data = data; | |
self.dataSource.trendlineData = trendlineData; | |
self.active = YES; | |
} | |
else { | |
// TODO: handle this error | |
} | |
}]; | |
}]; | |
RACSignal *dateRangeStringSignal = | |
[[RACSignal combineLatest:@[RACObserve(self, currentWeek), RACObserve(self, startDate)]] map:^NSString *(RACTuple *value) { | |
NSUInteger weekIndex = [[value first] unsignedIntegerValue]; | |
NSDate *startDate = [value second]; | |
NSDate *weekStart = [PFTrendsViewModel dateForDayAtIndex:0 weekIndex:weekIndex startDate:startDate]; | |
NSDate *weekEnd = [PFTrendsViewModel dateForDayAtIndex:6 weekIndex:weekIndex startDate:startDate]; | |
return [PFDateUtils stringForRangeOfDatesWithStartDate:weekStart endDate:weekEnd]; | |
}]; | |
RAC(self, weeklyHeaderMiddleText) = dateRangeStringSignal; | |
RAC(self, categoryHeaderDetailText) = | |
[RACSignal combineLatest:@[dateRangeStringSignal, RACObserve(self, timeWindowType)] | |
reduce:^NSString *(NSString *dateRangeString, NSNumber *boxedTimeWindowType) { | |
PFTrendsTimeWindowType timeWindowType = [boxedTimeWindowType integerValue]; | |
if (timeWindowType == PFTrendsTimeWindowTypeWeekly) { | |
NSString *formatString = NSLocalizedString(@"Averages for %@", @"Averages for {DATE RANGE}"); | |
return [[NSString stringWithFormat:formatString, dateRangeString] | |
uppercaseStringWithLocale:[NSLocale currentLocale]]; | |
} | |
else { | |
return [NSLocalizedString(@"All-Time Averages", @"Trends category header detail text") uppercaseStringWithLocale:[NSLocale currentLocale]]; | |
} | |
}]; | |
RAC(self, weeklyHeaderBottomText) = | |
[RACSignal combineLatest:@[RACObserve(self, currentWeek), | |
self.didBecomeActiveSignal] | |
reduce:^NSString *(NSNumber *boxedWeek, NSNumber *_) { | |
@strongify(self); | |
NSString *bottomPrefix = NSLocalizedString(@"Weekly Avg", @"part of Weekly Avg: 72"); | |
CGFloat average = [self.dataSource averageForWeek:[boxedWeek integerValue]]; | |
return [[NSString stringWithFormat:@"%@: %d", bottomPrefix, (int)round(average)] | |
uppercaseStringWithLocale:[NSLocale currentLocale]]; | |
}]; | |
RAC(self, allTimeHeaderMiddleText) = | |
[self.allTimeScoreSignal map:^NSString *(PFDailyScoreModel *scoreModel) { | |
return [NSString stringWithFormat:@"%d", (int)round([scoreModel.totalScore floatValue])]; | |
}]; | |
// Category cells should display all time averages when viewing the all-time chart, and otherwise display | |
// weekly averages for the current week. | |
RACSignal *isAllTimeSignal = [RACObserve(self, timeWindowType) map:^id(id value) { | |
return @([value unsignedIntegerValue] == PFTrendsTimeWindowTypeAllTime); | |
}]; | |
RACSignal *allTimeCellsSignal = | |
[self.allTimeScoreSignal map:^NSArray *(PFDailyScoreModel *scoreModel) { | |
return @[ | |
[[PFTrendsCategoryCellModel alloc] initWithCategory:PFTrendsCategorySleep | |
score:scoreModel.sleep], | |
[[PFTrendsCategoryCellModel alloc] initWithCategory:PFTrendsCategoryActivity | |
score:scoreModel.activity], | |
[[PFTrendsCategoryCellModel alloc] initWithCategory:PFTrendsCategoryCalm | |
score:scoreModel.calm], | |
[[PFTrendsCategoryCellModel alloc] initWithCategory:PFTrendsCategoryStress | |
score:scoreModel.stress], | |
]; | |
}]; | |
RACSignal *allLoadedSignal = | |
[[[RACSignal combineLatest:@[ | |
[RACObserve(self, sleepPointsDataSourceObject.dataLoaded) ignore:nil], | |
[RACObserve(self, activityPointsDataSourceObject.dataLoaded) ignore:nil], | |
[RACObserve(self, calmPointsDataSourceObject.dataLoaded) ignore:nil], | |
[RACObserve(self, stressPointsDataSourceObject.dataLoaded) ignore:nil] | |
]] and] distinctUntilChanged]; | |
RACSignal *emptyWeeklyCellsSignal = | |
[RACSignal return:@[ | |
[[PFTrendsCategoryCellModel alloc] initWithCategory:PFTrendsCategorySleep score:nil], | |
[[PFTrendsCategoryCellModel alloc] initWithCategory:PFTrendsCategoryActivity score:nil], | |
[[PFTrendsCategoryCellModel alloc] initWithCategory:PFTrendsCategoryCalm score:nil], | |
[[PFTrendsCategoryCellModel alloc] initWithCategory:PFTrendsCategoryStress score:nil], | |
]]; | |
RACSignal *loadedWeeklyCellsSignal = | |
[RACObserve(self, currentWeek) map:^NSArray *(NSNumber *boxedWeek) { | |
NSUInteger currentWeek = [boxedWeek unsignedIntegerValue]; | |
CGFloat sleepAvg = [self.sleepPointsDataSourceObject averageForWeek:currentWeek]; | |
CGFloat activityAvg = [self.activityPointsDataSourceObject averageForWeek:currentWeek]; | |
CGFloat calmAvg = [self.calmPointsDataSourceObject averageForWeek:currentWeek]; | |
CGFloat stressAvg = [self.stressPointsDataSourceObject averageForWeek:currentWeek]; | |
return @[ | |
[[PFTrendsCategoryCellModel alloc] initWithCategory:PFTrendsCategorySleep score:@(sleepAvg)], | |
[[PFTrendsCategoryCellModel alloc] initWithCategory:PFTrendsCategoryActivity score:@(activityAvg)], | |
[[PFTrendsCategoryCellModel alloc] initWithCategory:PFTrendsCategoryCalm score:@(calmAvg)], | |
[[PFTrendsCategoryCellModel alloc] initWithCategory:PFTrendsCategoryStress score:@(stressAvg)] | |
]; | |
}]; | |
RACSignal *weeklyCellsSignal = [RACSignal if:allLoadedSignal then:loadedWeeklyCellsSignal else:emptyWeeklyCellsSignal]; | |
RAC(self, categoryCells) = [[RACSignal if:isAllTimeSignal then:allTimeCellsSignal else:weeklyCellsSignal] deliverOn:[RACScheduler mainThreadScheduler]]; | |
} | |
return self; | |
} | |
- (void)setTimeWindowType:(PFTrendsTimeWindowType)timeWindowType | |
{ | |
_timeWindowType = timeWindowType; | |
if (timeWindowType == PFTrendsTimeWindowTypeAllTime) { | |
[[PFAnalytics sharedInstance] trackEvent:[PFAnalyticsEvent eventWithCategory:kPFEventCategoryUI action:kPFEventActionButtonPress label:@"trends_all_time" value:nil]]; | |
} | |
else { | |
[[PFAnalytics sharedInstance] trackEvent:[PFAnalyticsEvent eventWithCategory:kPFEventCategoryUI action:kPFEventActionButtonPress label:@"trends_weekly" value:nil]]; | |
} | |
} | |
- (PFTrendsDetailViewModel *)detailViewModelForCategory:(PFTrendsCategory)category | |
{ | |
[self.detailViewModel selectCategory:category]; | |
return self.detailViewModel; | |
} | |
// Returns the time series descriptor for the given data type. | |
+ (PFTimeseriesDescriptor *)timeseriesDescriptorForDataType:(PFTrendsDataType)type | |
{ | |
switch (type) { | |
case PFTrendsDataTypeSumScore: | |
return [PFTimeseriesDescriptor descriptorWithId:PFTimeseriesIdPoints]; | |
break; | |
case PFTrendsDataTypeSleepPoints: | |
return [PFTimeseriesDescriptor descriptorWithId:PFTimeseriesIdSleepPoints]; | |
break; | |
case PFTrendsDataTypeWakes: | |
return nil; | |
break; | |
case PFTrendsDataTypeSleepTotalTime: | |
return [PFTimeseriesDescriptor descriptorWithId:PFTimeseriesIdSleepMinutes]; | |
break; | |
case PFTrendsDataTypeSleepEfficiency: | |
return nil; | |
break; | |
case PFTrendsDataTypeActivityPoints: | |
return [PFTimeseriesDescriptor descriptorWithId:PFTimeseriesIdActivityPoints]; | |
break; | |
case PFTrendsDataTypeSteps: | |
return [PFTimeseriesDescriptor descriptorWithId:PFTimeseriesIdSteps]; | |
break; | |
case PFTrendsDataTypeCalories: | |
return nil; | |
break; | |
case PFTrendsDataTypeActivityTotalTime: | |
return [PFTimeseriesDescriptor descriptorWithId:PFTimeseriesIdActivityMinutes]; | |
break; | |
case PFTrendsDataTypeActivityHighIntensityTime: | |
return nil; | |
break; | |
case PFTrendsDataTypeStressPoints: | |
return [PFTimeseriesDescriptor descriptorWithId:PFTimeseriesIdStressPoints]; | |
break; | |
case PFTrendsDataTypeStressTotalTime: | |
return [PFTimeseriesDescriptor descriptorWithId:PFTimeseriesIdStressMinutes]; | |
break; | |
case PFTrendsDataTypeCalmPoints: | |
return [PFTimeseriesDescriptor descriptorWithId:PFTimeseriesIdCalmPoints]; | |
break; | |
case PFTrendsDataTypeCalmTotalTime: | |
return [PFTimeseriesDescriptor descriptorWithId:PFTimeseriesIdCalmMinutes]; | |
break; | |
default: | |
break; | |
} | |
} | |
+ (NSArray *)emptyDataArrayForNumberOfWeeks:(NSUInteger)numberOfWeeks descriptor:(PFTimeseriesDescriptor *)descriptor | |
{ | |
NSUInteger daysPerWeek = [NSCalendar numberOfDaysPerWeek]; | |
NSArray *data = @[]; | |
BOOL isMinutes = descriptor.timeseriesId == PFTimeseriesIdCalmMinutes || | |
descriptor.timeseriesId == PFTimeseriesIdSleepMinutes || | |
descriptor.timeseriesId == PFTimeseriesIdActivityMinutes || | |
descriptor.timeseriesId == PFTimeseriesIdStressMinutes; | |
BOOL isTrendline = !descriptor; | |
if (isTrendline) { | |
NSUInteger pointCount = numberOfWeeks*daysPerWeek; | |
for (int d=0; d < pointCount; d++) { | |
NSNumber *v = @(d/2.0); | |
PFChartValue *value = [[PFChartValue alloc] initWithValue:v]; | |
data = [data arrayByAddingObject:value]; | |
} | |
return data; | |
} | |
for (int w = 0; w < numberOfWeeks; w++) { | |
NSMutableArray *dayValues = [NSMutableArray new]; | |
for (int d = 0; d < daysPerWeek; d++) { | |
NSNumber *v = isMinutes ? @(arc4random_uniform(180)): @(arc4random_uniform(120)); | |
PFChartValue *value = [[PFChartValue alloc] initWithValue:v]; | |
[dayValues addObject:value]; | |
} | |
data = [data arrayByAddingObject:dayValues]; | |
} | |
return data; | |
} | |
+ (void)fetchDataWithStartDate:(NSDate *)startDate numberOfWeeks:(NSUInteger)numberOfWeeks | |
timeseries:(PFTimeseriesDescriptor *)timeseries | |
apiManager:(PFAPIManager *)apiManager | |
callback:(void(^)(NSArray *data, NSArray *trendline, NSError *error))callback { | |
if (!callback) { | |
return; | |
} | |
if ([PFAccountManager sharedInstance].showFakeData) { | |
NSArray *trendlineData = [self emptyDataArrayForNumberOfWeeks:numberOfWeeks descriptor:nil]; | |
NSArray *data = [self emptyDataArrayForNumberOfWeeks:numberOfWeeks descriptor:timeseries]; | |
callback(data, trendlineData, nil); | |
} | |
else { | |
NSUInteger daysPerWeek = [NSCalendar numberOfDaysPerWeek]; | |
NSUInteger numberOfDays = numberOfWeeks * daysPerWeek; | |
NSDate *endDate = [startDate dateByAddingDays:numberOfDays]; | |
// NOTE: this method is inefficient but defensive - we check the date of each item update the data array, | |
// rather than assuming the API will return everything in the expected order. | |
void(^_callback)(id, NSError *) = ^(PFTimeseriesResponse *payload, NSError *error) { | |
NSArray *data = nil; | |
NSArray *trendlineData = [self emptyDataArrayForNumberOfWeeks:numberOfWeeks descriptor:nil]; | |
NSDate *now = [NSDate date]; | |
if (payload) { | |
data = [self emptyDataArrayForNumberOfWeeks:numberOfWeeks descriptor:timeseries]; | |
for (PFTimeseriesItem *item in payload.items) { | |
// convert start date to a day boundary. | |
NSDateComponents *components = [item.startDate components:(NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay)]; | |
components.hour = 12; | |
NSCalendar *calendar = [NSCalendar pf_currentCalendar]; | |
NSDate *date = [[calendar dateFromComponents:components] leadingEdge]; | |
NSNumber *boxedWeek = [PFTrendsViewModel weekIndexForDate:date startDate:startDate]; | |
NSNumber *boxedDay = [PFTrendsViewModel dayIndexForDate:date startDate:startDate]; | |
BOOL weekAndDayAreNonNil = boxedWeek && boxedDay; | |
BOOL enoughWeeks = [boxedWeek integerValue] < [data count]; | |
if (weekAndDayAreNonNil && enoughWeeks && | |
[boxedDay integerValue] < [data[[boxedWeek integerValue]] count] && | |
[[item.startDate laterDate:now] isEqualToDate:now]) { | |
NSUInteger weekIndex = [boxedWeek unsignedIntegerValue]; | |
NSUInteger dayIndex = [boxedDay unsignedIntegerValue]; | |
PFChartValue *value = [[PFChartValue alloc] initWithValue:item.value]; | |
data[weekIndex][dayIndex] = value; | |
} | |
} | |
if (payload.trendlineItems && payload.trendlineItems.count == payload.items.count) { | |
NSArray *sortedTrendlineItems = [payload.trendlineItems sortedArrayUsingComparator:^NSComparisonResult(PFTimeseriesItem *obj1, PFTimeseriesItem * obj2) { | |
return [obj1.startDate compare:obj2.startDate]; | |
}]; | |
trendlineData = [[[sortedTrendlineItems rac_sequence] map:^PFChartValue *(PFTimeseriesItem *currentItem) { | |
return [[PFChartValue alloc] initWithValue:currentItem.value]; | |
}] array]; | |
} | |
} | |
callback(data, trendlineData, nil); | |
}; | |
[apiManager fetchTimeseriesWithId:timeseries.remoteId | |
start:startDate | |
end:endDate | |
resolution:PFTimeseriesResolutionDay | |
binWidth:1 | |
binDownsample:PFTimeseriesBinDownsampleDefault | |
includesTrendline:YES | |
callback:_callback]; | |
} | |
} | |
+ (NSDate *)dateForDayAtIndex:(NSUInteger)dayIndex | |
weekIndex:(NSUInteger)weekIndex | |
startDate:(NSDate *)startDate | |
{ | |
NSDate *weekStartDate = [startDate dateByAddingDays:weekIndex * 7]; | |
return [[weekStartDate dateByAddingDays:dayIndex] leadingEdge]; | |
} | |
+ (NSNumber *)weekIndexForDate:(NSDate *)date startDate:(NSDate *)startDate | |
{ | |
if (![[date earlierDate:startDate] isEqualToDate:startDate] && ![date isEqualToDate:startDate]) { | |
return nil; | |
} | |
NSDate *end = [date trailingEdge]; | |
NSDateComponents *components = [[NSCalendar pf_currentCalendar] components:NSCalendarUnitDay | |
fromDate:startDate toDate:end options:0]; | |
NSInteger days = components.day; | |
if (days < 1) { | |
return nil; | |
} | |
return @((NSUInteger)((days - 1)/7.0)); | |
} | |
+ (NSNumber *)dayIndexForDate:(NSDate *)date startDate:(NSDate *)startDate | |
{ | |
if (![[date earlierDate:startDate] isEqualToDate:startDate] && ![date isEqualToDate:startDate]) { | |
return nil; | |
} | |
NSDate *end = [date trailingEdge]; | |
NSDateComponents *components = [[NSCalendar pf_currentCalendar] components:NSCalendarUnitDay | |
fromDate:startDate toDate:end options:0]; | |
NSInteger days = components.day; | |
if (days < 1) { | |
return nil; | |
} | |
return @((days - 1)%7); | |
} | |
+ (NSNumber *)categoryForDataType:(PFTrendsDataType)dataType | |
{ | |
switch (dataType) { | |
case PFTrendsDataTypeSleepPoints: | |
case PFTrendsDataTypeWakes: | |
case PFTrendsDataTypeSleepTotalTime: | |
case PFTrendsDataTypeSleepEfficiency: | |
return @(PFTrendsCategorySleep); | |
break; | |
case PFTrendsDataTypeActivityPoints: | |
case PFTrendsDataTypeSteps: | |
case PFTrendsDataTypeCalories: | |
case PFTrendsDataTypeActivityTotalTime: | |
case PFTrendsDataTypeActivityHighIntensityTime: | |
return @(PFTrendsCategoryActivity); | |
break; | |
case PFTrendsDataTypeStressPoints: | |
case PFTrendsDataTypeStressTotalTime: | |
return @(PFTrendsCategoryStress); | |
break; | |
case PFTrendsDataTypeCalmPoints: | |
case PFTrendsDataTypeCalmTotalTime: | |
return @(PFTrendsCategoryCalm); | |
break; | |
case PFTrendsDataTypeSumScore: | |
default: | |
return nil; | |
break; | |
} | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment