| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 |
- // LoopFollow
- // AGPCalculator.swift
- import Foundation
- class AGPCalculator {
- static func calculate(bgData: [ShareGlucoseData]) -> [AGPDataPoint] {
- guard !bgData.isEmpty else { return [] }
- var hourData: [Int: [Double]] = [:]
- let calendar = dateTimeUtils.displayCalendar()
- for reading in bgData {
- let date = Date(timeIntervalSince1970: reading.date)
- let components = calendar.dateComponents([.hour], from: date)
- let hour = components.hour ?? 0
- let glucose = Double(reading.sgv)
- let glucoseMgdL = Storage.shared.units.value == "mg/dL" ? glucose : glucose * GlucoseConversion.mmolToMgDl
- if hourData[hour] == nil {
- hourData[hour] = []
- }
- hourData[hour]?.append(glucoseMgdL)
- }
- var agpPoints: [AGPDataPoint] = []
- for hour in 0 ..< 24 {
- guard let values = hourData[hour], !values.isEmpty else { continue }
- let sorted = values.sorted()
- let p5 = PercentileCalculator.percentile(sorted, p: 0.05)
- let p25 = PercentileCalculator.percentile(sorted, p: 0.25)
- let p50 = PercentileCalculator.percentile(sorted, p: 0.50)
- let p75 = PercentileCalculator.percentile(sorted, p: 0.75)
- let p95 = PercentileCalculator.percentile(sorted, p: 0.95)
- let convert: (Double) -> Double = { value in
- Storage.shared.units.value == "mg/dL" ? value : value * GlucoseConversion.mgDlToMmolL
- }
- let minutesSinceMidnight = hour * 60
- agpPoints.append(AGPDataPoint(
- timeOfDay: minutesSinceMidnight,
- p5: convert(p5),
- p25: convert(p25),
- p50: convert(p50),
- p75: convert(p75),
- p95: convert(p95)
- ))
- }
- return agpPoints.sorted { $0.timeOfDay < $1.timeOfDay }
- }
- }
- class PercentileCalculator {
- static func percentile(_ sorted: [Double], p: Double) -> Double {
- guard !sorted.isEmpty else { return 0.0 }
- if sorted.count == 1 { return sorted[0] }
- let index = p * Double(sorted.count - 1)
- let lower = Int(index.rounded(.down))
- let upper = min(lower + 1, sorted.count - 1)
- let weight = index - Double(lower)
- return sorted[lower] * (1.0 - weight) + sorted[upper] * weight
- }
- }
|