DataTableDataFlow.swift 6.9 KB

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