| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- import Foundation
- import HealthKit
- import LoopKit
- struct BloodGlucose: JSON, Identifiable, Hashable {
- enum Direction: String, JSON {
- case tripleUp = "TripleUp"
- case doubleUp = "DoubleUp"
- case singleUp = "SingleUp"
- case fortyFiveUp = "FortyFiveUp"
- case flat = "Flat"
- case fortyFiveDown = "FortyFiveDown"
- case singleDown = "SingleDown"
- case doubleDown = "DoubleDown"
- case tripleDown = "TripleDown"
- case none = "NONE"
- case notComputable = "NOT COMPUTABLE"
- case rateOutOfRange = "RATE OUT OF RANGE"
- init?(from string: String) {
- switch string {
- case "\u{2191}\u{2191}\u{2191}",
- "TripleUp":
- self = .tripleUp
- case "\u{2191}\u{2191}",
- "DoubleUp":
- self = .doubleUp
- case "\u{2191}",
- "SingleUp":
- self = .singleUp
- case "\u{2197}",
- "FortyFiveUp":
- self = .fortyFiveUp
- case "\u{2192}",
- "Flat":
- self = .flat
- case "\u{2198}",
- "FortyFiveDown":
- self = .fortyFiveDown
- case "\u{2193}",
- "SingleDown":
- self = .singleDown
- case "\u{2193}\u{2193}",
- "DoubleDown":
- self = .doubleDown
- case "\u{2193}\u{2193}\u{2193}",
- "TripleDown":
- self = .tripleDown
- case "\u{2194}",
- "NONE":
- self = .none
- case "NOT COMPUTABLE":
- self = .notComputable
- case "RATE OUT OF RANGE":
- self = .rateOutOfRange
- default:
- return nil
- }
- }
- }
- var _id: String?
- var id: String {
- _id ?? UUID().uuidString
- }
- var sgv: Int?
- var direction: Direction?
- let date: Decimal
- let dateString: Date
- let unfiltered: Decimal?
- let filtered: Decimal?
- let noise: Int?
- var glucose: Int?
- var type: String? = nil
- var activationDate: Date? = nil
- var sessionStartDate: Date? = nil
- var transmitterID: String? = nil
- var isStateValid: Bool { sgv ?? 0 >= 39 && noise ?? 1 != 4 }
- static func == (lhs: BloodGlucose, rhs: BloodGlucose) -> Bool {
- lhs.dateString == rhs.dateString
- }
- func hash(into hasher: inout Hasher) {
- hasher.combine(dateString)
- }
- }
- enum GlucoseUnits: String, JSON, Equatable {
- case mgdL = "mg/dL"
- case mmolL = "mmol/L"
- static let exchangeRate: Decimal = 0.0555
- }
- extension Int {
- var asMmolL: Decimal {
- FreeAPS.rounded(Decimal(self) * GlucoseUnits.exchangeRate, scale: 1, roundingMode: .plain)
- }
- var formattedAsMmolL: String {
- NumberFormatter.glucoseFormatter.string(from: asMmolL as NSDecimalNumber) ?? "\(asMmolL)"
- }
- }
- extension Decimal {
- var asMmolL: Decimal {
- FreeAPS.rounded(self * GlucoseUnits.exchangeRate, scale: 1, roundingMode: .plain)
- }
- var asMgdL: Decimal {
- FreeAPS.rounded(self / GlucoseUnits.exchangeRate, scale: 0, roundingMode: .plain)
- }
- var formattedAsMmolL: String {
- NumberFormatter.glucoseFormatter.string(from: asMmolL as NSDecimalNumber) ?? "\(asMmolL)"
- }
- }
- extension Double {
- var asMmolL: Decimal {
- FreeAPS.rounded(Decimal(self) * GlucoseUnits.exchangeRate, scale: 1, roundingMode: .plain)
- }
- var asMgdL: Decimal {
- FreeAPS.rounded(Decimal(self) / GlucoseUnits.exchangeRate, scale: 0, roundingMode: .plain)
- }
- var formattedAsMmolL: String {
- NumberFormatter.glucoseFormatter.string(from: asMmolL as NSDecimalNumber) ?? "\(asMmolL)"
- }
- }
- extension NumberFormatter {
- static let glucoseFormatter: NumberFormatter = {
- let formatter = NumberFormatter()
- formatter.locale = Locale.current
- formatter.numberStyle = .decimal
- formatter.minimumFractionDigits = 1
- formatter.maximumFractionDigits = 1
- return formatter
- }()
- }
- extension BloodGlucose: SavitzkyGolaySmoothable {
- var value: Double {
- get {
- Double(glucose ?? 0)
- }
- set {
- glucose = Int(newValue)
- sgv = Int(newValue)
- }
- }
- }
- extension BloodGlucose {
- func convertStoredGlucoseSample(device: HKDevice?) -> StoredGlucoseSample {
- StoredGlucoseSample(
- syncIdentifier: id,
- startDate: dateString.date,
- quantity: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: Double(glucose!)),
- device: device
- )
- }
- }
|