PumpEvent+helper.swift 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. import CoreData
  2. import Foundation
  3. extension PumpEventStored {
  4. static func fetch(_ predicate: NSPredicate, ascending: Bool, fetchLimit: Int? = nil) -> NSFetchRequest<PumpEventStored> {
  5. let request = PumpEventStored.fetchRequest()
  6. request.sortDescriptors = [NSSortDescriptor(key: "timestamp", ascending: ascending)]
  7. request.resultType = .managedObjectResultType
  8. request.predicate = predicate
  9. if let fetchLimit = fetchLimit {
  10. request.fetchLimit = fetchLimit
  11. }
  12. return request
  13. }
  14. }
  15. public extension PumpEventStored {
  16. enum EventType: String, JSON {
  17. case bolus = "Bolus"
  18. case smb = "SMB"
  19. case isExternal = "External Insulin"
  20. case mealBolus = "Meal Bolus"
  21. case correctionBolus = "Correction Bolus"
  22. case snackBolus = "Snack Bolus"
  23. case bolusWizard = "BolusWizard"
  24. case tempBasal = "TempBasal"
  25. case tempBasalDuration = "TempBasalDuration"
  26. case pumpSuspend = "PumpSuspend"
  27. case pumpResume = "PumpResume"
  28. case pumpAlarm = "PumpAlarm"
  29. case pumpBattery = "PumpBattery"
  30. case rewind = "Rewind"
  31. case prime = "Prime"
  32. case journalCarbs = "JournalEntryMealMarker"
  33. case nsTempBasal = "Temp Basal"
  34. case nsCarbCorrection = "Carb Correction"
  35. case nsTempTarget = "Temporary Target"
  36. case nsInsulinChange = "Insulin Change"
  37. case nsSiteChange = "Site Change"
  38. case nsBatteryChange = "Pump Battery Change"
  39. case nsAnnouncement = "Announcement"
  40. case nsSensorChange = "Sensor Start"
  41. case capillaryGlucose = "BG Check"
  42. }
  43. enum TempType: String, JSON {
  44. case absolute
  45. case percent
  46. }
  47. }
  48. extension NSPredicate {
  49. static var pumpHistoryLast24h: NSPredicate {
  50. let date = Date.oneDayAgo
  51. return NSPredicate(format: "timestamp >= %@", date as NSDate)
  52. }
  53. }
  54. // Declare helper structs ("data transfer objects" = DTO) to utilize parsing a flattened pump history
  55. struct BolusDTO: Codable {
  56. var id: String
  57. var timestamp: String
  58. var amount: Double
  59. var isExternal: Bool
  60. var isSMB: Bool
  61. var duration: Int
  62. var _type: String = "Bolus"
  63. }
  64. struct TempBasalDTO: Codable {
  65. var id: String
  66. var timestamp: String
  67. var temp: String
  68. var rate: Double
  69. var _type: String = "TempBasal"
  70. }
  71. struct TempBasalDurationDTO: Codable {
  72. var id: String
  73. var timestamp: String
  74. var duration: Int
  75. var _type: String = "TempBasalDuration"
  76. private enum CodingKeys: String, CodingKey {
  77. case id
  78. case timestamp
  79. case duration = "duration (min)"
  80. case _type
  81. }
  82. }
  83. // Mask distinct DTO subtypes with a common enum that conforms to Encodable
  84. enum PumpEventDTO: Encodable {
  85. case bolus(BolusDTO)
  86. case tempBasal(TempBasalDTO)
  87. case tempBasalDuration(TempBasalDurationDTO)
  88. func encode(to encoder: Encoder) throws {
  89. switch self {
  90. case let .bolus(bolus):
  91. try bolus.encode(to: encoder)
  92. case let .tempBasal(tempBasal):
  93. try tempBasal.encode(to: encoder)
  94. case let .tempBasalDuration(tempBasalDuration):
  95. try tempBasalDuration.encode(to: encoder)
  96. }
  97. }
  98. }
  99. // Extension with helper functions to map pump events to DTO objects via uniform masking enum
  100. extension PumpEventStored {
  101. static let dateFormatter = ISO8601DateFormatter()
  102. func toBolusDTOEnum() -> PumpEventDTO? {
  103. guard let id = id, let timestamp = timestamp, let bolus = bolus, let amount = bolus.amount else {
  104. return nil
  105. }
  106. let bolusDTO = BolusDTO(
  107. id: id,
  108. timestamp: PumpEventStored.dateFormatter.string(from: timestamp),
  109. amount: amount.doubleValue,
  110. isExternal: bolus.isExternal,
  111. isSMB: bolus.isSMB,
  112. duration: 0
  113. )
  114. return .bolus(bolusDTO)
  115. }
  116. func toTempBasalDTOEnum() -> PumpEventDTO? {
  117. guard let id = id, let timestamp = timestamp, let tempBasal = tempBasal, let rate = tempBasal.rate else {
  118. return nil
  119. }
  120. let tempBasalDTO = TempBasalDTO(
  121. id: "_\(id)",
  122. timestamp: PumpEventStored.dateFormatter.string(from: timestamp),
  123. temp: tempBasal.tempType ?? "unknown",
  124. rate: rate.doubleValue
  125. )
  126. return .tempBasal(tempBasalDTO)
  127. }
  128. func toTempBasalDurationDTOEnum() -> PumpEventDTO? {
  129. guard let id = id, let timestamp = timestamp, let tempBasal = tempBasal else {
  130. return nil
  131. }
  132. let tempBasalDurationDTO = TempBasalDurationDTO(
  133. id: id,
  134. timestamp: PumpEventStored.dateFormatter.string(from: timestamp),
  135. duration: Int(tempBasal.duration)
  136. )
  137. return .tempBasalDuration(tempBasalDurationDTO)
  138. }
  139. }