Skip to content

Commit aba1acf

Browse files
authored
Fix calculation for meditation minutes (#453)
Previously meditation minutes used the same algorithm as we used for time in bed. This was overly generous. It would count minutes containing meditation, which is different from the apple algorithm which counts total duration rounded to the nearest minute. Update the calculation used in the app to match the Apple algorithm. Fixes #452 Testing: Put various test data into the simulator, and checked beeminder synced appropriately.
1 parent f4440f6 commit aba1acf

File tree

1 file changed

+40
-2
lines changed

1 file changed

+40
-2
lines changed

BeeKit/HeathKit/MindfulSessionHealthKitMetric.swift

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,46 @@ class MindfulSessionHealthKitMetric : CategoryHealthKitMetric {
88
super.init(humanText: humanText, databaseString: databaseString, category: category, hkSampleType: HKObjectType.categoryType(forIdentifier: .mindfulSession)!)
99
}
1010

11-
override func valueInAppropriateUnits(rawValue: Double) -> Double {
12-
return rawValue / minuteInSeconds
11+
override func hkDatapointValueForSamples(samples: [HKSample], startOfDate: Date) -> Double {
12+
let endOfDate = startOfDate.addingTimeInterval(24 * 60 * 60)
13+
14+
let orderedSamples = samples.sorted(by: { $0.startDate < $1.startDate })
15+
16+
var spanStart: Optional<Date> = nil
17+
var spanEnd: Optional<Date> = nil
18+
var totalSeconds = 0.0
19+
20+
for sample in orderedSamples {
21+
if sample.hasUndeterminedDuration {
22+
continue
23+
}
24+
25+
let sampleStart = max(sample.startDate, startOfDate)
26+
let sampleEnd = min(sample.endDate, endOfDate)
27+
28+
if let start = spanStart, let end = spanEnd {
29+
// There is an existing span to examine
30+
if sampleStart <= end {
31+
// If the sample overlaps with the current span, extend the span
32+
spanEnd = max(end, sampleEnd)
33+
} else {
34+
// Otherwise, add the span to the total and start a new span
35+
totalSeconds += end.timeIntervalSince(start)
36+
spanStart = sampleStart
37+
spanEnd = sampleEnd
38+
}
39+
} else {
40+
// No prior span, start with this one
41+
spanStart = sampleStart
42+
spanEnd = sampleEnd
43+
}
44+
}
45+
if let end = spanEnd {
46+
totalSeconds += end.timeIntervalSince(spanStart!)
47+
}
48+
49+
let totalMinutes = totalSeconds / minuteInSeconds
50+
return totalMinutes.rounded()
1351
}
1452

1553
override func units(healthStore : HKHealthStore) async throws -> HKUnit {

0 commit comments

Comments
 (0)