108 lines
3.3 KiB
Swift
108 lines
3.3 KiB
Swift
import Foundation
|
|
import HealthKitExtensions
|
|
import HealthKit
|
|
import Charts
|
|
|
|
struct HRSample: Identifiable {
|
|
|
|
let id = UUID()
|
|
|
|
let startDate: Date
|
|
|
|
let endDate: Date
|
|
|
|
let min: Int
|
|
|
|
let max: Int
|
|
|
|
init(date: Date, duration: TimeInterval, min: Int, max: Int) {
|
|
self.startDate = date
|
|
self.endDate = date.addingTimeInterval(duration)
|
|
self.min = min
|
|
self.max = max
|
|
}
|
|
|
|
static func create(from samples: [HeartRate], start: Date, end: Date, categories: Int) -> [HRSample] {
|
|
let interval = end.timeIntervalSince(start) / Double(categories)
|
|
var categories: [HRSample] = []
|
|
var categoryEndDuration = interval
|
|
var minimum = Int.max
|
|
var maximum = Int.min
|
|
var hasSamplesInCategory = false
|
|
|
|
let unit = HKUnit.count().unitDivided(by: .minute())
|
|
|
|
func advanceToNextCategory() {
|
|
defer { categoryEndDuration += interval }
|
|
guard hasSamplesInCategory else {
|
|
return
|
|
}
|
|
categories.append(.init(
|
|
date: start.addingTimeInterval(categoryEndDuration - (interval * 0.48)),
|
|
duration: interval * 0.96,
|
|
min: minimum,
|
|
max: maximum))
|
|
minimum = Int.max
|
|
maximum = Int.min
|
|
hasSamplesInCategory = false
|
|
}
|
|
|
|
for sample in samples.sorted(ascending: true, using: { $0.startDate }) {
|
|
let timestamp = sample.startDate.timeIntervalSince(start)
|
|
while timestamp > categoryEndDuration {
|
|
advanceToNextCategory()
|
|
}
|
|
let value = sample.quantity.doubleValue(for: unit).roundedInt
|
|
minimum = Swift.min(minimum, value)
|
|
maximum = Swift.max(maximum, value)
|
|
hasSamplesInCategory = true
|
|
}
|
|
|
|
advanceToNextCategory()
|
|
return categories
|
|
}
|
|
|
|
func test(start: Date, end: Date) {
|
|
let duration = end.timeIntervalSince(start)
|
|
let interval = DateComponents(second: Int(duration) / 20)
|
|
|
|
let quantityType = HKObjectType.quantityType(
|
|
forIdentifier: .heartRate
|
|
)!
|
|
|
|
let query = HKStatisticsCollectionQuery(
|
|
quantityType: quantityType,
|
|
quantitySamplePredicate: nil,
|
|
options: [.discreteMax, .discreteMin],
|
|
anchorDate: start,
|
|
intervalComponents: interval
|
|
)
|
|
|
|
query.initialResultsHandler = { _, results, error in
|
|
var weeklyData: [Date: (Double, Double)] = [:]
|
|
|
|
results!.enumerateStatistics(
|
|
from: start,
|
|
to: end
|
|
) { statistics, _ in
|
|
if let minValue = statistics.minimumQuantity() {
|
|
if let maxValue = statistics.maximumQuantity() {
|
|
let minHeartRate = minValue.doubleValue(
|
|
for: HKUnit(from: "count/min")
|
|
)
|
|
let maxHeartRate = maxValue.doubleValue(
|
|
for: HKUnit(from: "count/min")
|
|
)
|
|
|
|
weeklyData[statistics.startDate] = (
|
|
minHeartRate, maxHeartRate
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
// use `weeklyData`
|
|
}
|
|
}
|
|
}
|