DataTableDataFlow.swift 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. import CoreData
  2. import Foundation
  3. import HealthKit
  4. import SwiftUI
  5. enum DataTable {
  6. enum Config {}
  7. enum Mode: String, Hashable, Identifiable, CaseIterable {
  8. case treatments
  9. case meals
  10. case glucose
  11. var id: String { rawValue }
  12. var name: String {
  13. var name: String = ""
  14. switch self {
  15. case .treatments:
  16. name = "Treatments"
  17. case .meals:
  18. name = "Meals"
  19. case .glucose:
  20. name = "Glucose"
  21. }
  22. return NSLocalizedString(name, comment: "History Mode")
  23. }
  24. }
  25. enum DataType: String, Equatable {
  26. case carbs
  27. case fpus
  28. case bolus
  29. case tempBasal
  30. case tempTarget
  31. case suspend
  32. case resume
  33. var name: String {
  34. var name: String = ""
  35. switch self {
  36. case .carbs:
  37. name = "Carbs"
  38. case .fpus:
  39. name = "Protein / Fat"
  40. case .bolus:
  41. name = "Bolus"
  42. case .tempBasal:
  43. name = "Temp Basal"
  44. case .tempTarget:
  45. name = "Temp Target"
  46. case .suspend:
  47. name = "Suspend"
  48. case .resume:
  49. name = "Resume"
  50. }
  51. return NSLocalizedString(name, comment: "Treatment type")
  52. }
  53. }
  54. class Treatment: Identifiable, Hashable, Equatable {
  55. let id: String
  56. let idPumpEvent: String?
  57. let units: GlucoseUnits
  58. let type: DataType
  59. let date: Date
  60. let amount: Decimal?
  61. let secondAmount: Decimal?
  62. let duration: Decimal?
  63. let isFPU: Bool?
  64. let fpuID: String?
  65. let note: String?
  66. let isSMB: Bool?
  67. let isExternal: Bool?
  68. private var numberFormatter: NumberFormatter {
  69. let formatter = NumberFormatter()
  70. formatter.numberStyle = .decimal
  71. formatter.maximumFractionDigits = 2
  72. return formatter
  73. }
  74. private var tempTargetFormater: NumberFormatter {
  75. let formatter = NumberFormatter()
  76. formatter.numberStyle = .decimal
  77. formatter.maximumFractionDigits = 1
  78. return formatter
  79. }
  80. init(
  81. units: GlucoseUnits,
  82. type: DataType,
  83. date: Date,
  84. amount: Decimal? = nil,
  85. secondAmount: Decimal? = nil,
  86. duration: Decimal? = nil,
  87. id: String? = nil,
  88. idPumpEvent: String? = nil,
  89. isFPU: Bool? = nil,
  90. fpuID: String? = nil,
  91. note: String? = nil,
  92. isSMB: Bool? = nil,
  93. isExternal: Bool? = nil
  94. ) {
  95. self.units = units
  96. self.type = type
  97. self.date = date
  98. self.amount = amount
  99. self.secondAmount = secondAmount
  100. self.duration = duration
  101. self.id = id ?? UUID().uuidString
  102. self.idPumpEvent = idPumpEvent
  103. self.isFPU = isFPU
  104. self.fpuID = fpuID
  105. self.note = note
  106. self.isSMB = isSMB
  107. self.isExternal = isExternal
  108. }
  109. static func == (lhs: Treatment, rhs: Treatment) -> Bool {
  110. lhs.id == rhs.id
  111. }
  112. func hash(into hasher: inout Hasher) {
  113. hasher.combine(id)
  114. }
  115. var amountText: String {
  116. guard let amount = amount else {
  117. return ""
  118. }
  119. if amount == 0, duration == 0 {
  120. return "Cancel temp"
  121. }
  122. switch type {
  123. case .carbs:
  124. return numberFormatter
  125. .string(from: amount as NSNumber)! + NSLocalizedString(" g", comment: "gram of carbs")
  126. case .fpus:
  127. return numberFormatter
  128. .string(from: amount as NSNumber)! + NSLocalizedString(" g", comment: "gram of carb equilvalents")
  129. case .bolus:
  130. var bolusText = " "
  131. if isSMB ?? false {}
  132. else if isExternal ?? false {
  133. bolusText += NSLocalizedString("External", comment: "External Insulin")
  134. } else {
  135. bolusText += NSLocalizedString("Manual", comment: "Manual Bolus")
  136. }
  137. return numberFormatter
  138. .string(from: amount as NSNumber)! + NSLocalizedString(" U", comment: "Insulin unit") + bolusText
  139. case .tempBasal:
  140. return numberFormatter
  141. .string(from: amount as NSNumber)! + NSLocalizedString(" U/hr", comment: "Unit insulin per hour")
  142. case .tempTarget:
  143. var converted = amount
  144. if units == .mmolL {
  145. converted = converted.asMmolL
  146. }
  147. guard var secondAmount = secondAmount else {
  148. return numberFormatter.string(from: converted as NSNumber)! + " \(units.rawValue)"
  149. }
  150. if units == .mmolL {
  151. secondAmount = secondAmount.asMmolL
  152. }
  153. return tempTargetFormater.string(from: converted as NSNumber)! + " - " + tempTargetFormater
  154. .string(from: secondAmount as NSNumber)! + " \(units.rawValue)"
  155. case .resume,
  156. .suspend:
  157. return type.name
  158. }
  159. }
  160. var color: Color {
  161. switch type {
  162. case .carbs:
  163. return .loopYellow
  164. case .fpus:
  165. return .orange.opacity(0.5)
  166. case .bolus:
  167. return Color.insulin
  168. case .tempBasal:
  169. return Color.insulin.opacity(0.4)
  170. case .resume,
  171. .suspend,
  172. .tempTarget:
  173. return .loopGray
  174. }
  175. }
  176. var durationText: String? {
  177. guard let duration = duration, duration > 0 else {
  178. return nil
  179. }
  180. return numberFormatter.string(from: duration as NSNumber)! + " min"
  181. }
  182. }
  183. class Glucose: Identifiable, Hashable, Equatable {
  184. static func == (lhs: DataTable.Glucose, rhs: DataTable.Glucose) -> Bool {
  185. lhs.glucose == rhs.glucose
  186. }
  187. let glucose: BloodGlucose
  188. init(glucose: BloodGlucose) {
  189. self.glucose = glucose
  190. }
  191. var id: String { glucose.id }
  192. }
  193. }
  194. protocol DataTableProvider: Provider {
  195. func deleteCarbsFromNightscout(withID id: String)
  196. func deleteInsulinFromNightscout(withID id: String)
  197. func deleteManualGlucoseFromNightscout(withID id: String)
  198. func deleteGlucoseFromHealth(withSyncID id: String)
  199. func deleteMealDataFromHealth(byID id: String, sampleType: HKSampleType)
  200. func deleteInsulinFromHealth(withSyncID id: String)
  201. }