DataTableDataFlow.swift 6.8 KB

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