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` } } }