TherapySettings.swift 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. //
  2. // TherapySettings.swift
  3. // LoopKit
  4. //
  5. // Created by Anna Quinlan on 7/6/20.
  6. // Copyright © 2020 LoopKit Authors. All rights reserved.
  7. //
  8. import HealthKit
  9. public struct TherapySettings: Equatable {
  10. public var glucoseTargetRangeSchedule: GlucoseRangeSchedule?
  11. public var correctionRangeOverrides: CorrectionRangeOverrides?
  12. public var overridePresets: [TemporaryScheduleOverridePreset]?
  13. public var maximumBasalRatePerHour: Double?
  14. public var maximumBolus: Double?
  15. public var suspendThreshold: GlucoseThreshold?
  16. public var insulinSensitivitySchedule: InsulinSensitivitySchedule?
  17. public var carbRatioSchedule: CarbRatioSchedule?
  18. public var basalRateSchedule: BasalRateSchedule?
  19. public var defaultRapidActingModel: ExponentialInsulinModelPreset?
  20. public var isComplete: Bool {
  21. return
  22. glucoseTargetRangeSchedule != nil &&
  23. /* Correction Range (Premeal and workout) targets are optional */
  24. // correctionRangeOverrides != nil &&
  25. maximumBasalRatePerHour != nil &&
  26. maximumBolus != nil &&
  27. suspendThreshold != nil &&
  28. insulinSensitivitySchedule != nil &&
  29. carbRatioSchedule != nil &&
  30. basalRateSchedule != nil
  31. }
  32. public init(
  33. glucoseTargetRangeSchedule: GlucoseRangeSchedule? = nil,
  34. correctionRangeOverrides: CorrectionRangeOverrides? = nil,
  35. overridePresets: [TemporaryScheduleOverridePreset]? = nil,
  36. maximumBasalRatePerHour: Double? = nil,
  37. maximumBolus: Double? = nil,
  38. suspendThreshold: GlucoseThreshold? = nil,
  39. insulinSensitivitySchedule: InsulinSensitivitySchedule? = nil,
  40. carbRatioSchedule: CarbRatioSchedule? = nil,
  41. basalRateSchedule: BasalRateSchedule? = nil,
  42. defaultRapidActingModel: ExponentialInsulinModelPreset? = nil
  43. ){
  44. self.glucoseTargetRangeSchedule = glucoseTargetRangeSchedule
  45. self.correctionRangeOverrides = correctionRangeOverrides
  46. self.overridePresets = overridePresets
  47. self.maximumBasalRatePerHour = maximumBasalRatePerHour
  48. self.maximumBolus = maximumBolus
  49. self.suspendThreshold = suspendThreshold
  50. self.insulinSensitivitySchedule = insulinSensitivitySchedule
  51. self.carbRatioSchedule = carbRatioSchedule
  52. self.basalRateSchedule = basalRateSchedule
  53. self.defaultRapidActingModel = defaultRapidActingModel
  54. }
  55. }
  56. extension TherapySettings: Codable {
  57. public init(from decoder: Decoder) throws {
  58. let container = try decoder.container(keyedBy: CodingKeys.self)
  59. let glucoseTargetRangeSchedule = try container.decodeIfPresent(GlucoseRangeSchedule.self, forKey: .glucoseTargetRangeSchedule)
  60. let correctionRangeOverrides = try container.decodeIfPresent(CorrectionRangeOverrides.self, forKey: .correctionRangeOverrides)
  61. let maximumBasalRatePerHour = try container.decodeIfPresent(Double.self, forKey: .maximumBasalRatePerHour)
  62. let maximumBolus = try container.decodeIfPresent(Double.self, forKey: .maximumBolus)
  63. let suspendThreshold = try container.decodeIfPresent(GlucoseThreshold.self, forKey: .suspendThreshold)
  64. let insulinSensitivitySchedule = try container.decodeIfPresent(InsulinSensitivitySchedule.self, forKey: .insulinSensitivitySchedule)
  65. let carbRatioSchedule = try container.decodeIfPresent(CarbRatioSchedule.self, forKey: .carbRatioSchedule)
  66. let basalRateSchedule = try container.decodeIfPresent(BasalRateSchedule.self, forKey: .basalRateSchedule)
  67. let defaultRapidActingModel = try container.decodeIfPresent(ExponentialInsulinModelPreset.self, forKey: .defaultRapidActingModel)
  68. self.init(glucoseTargetRangeSchedule: glucoseTargetRangeSchedule,
  69. correctionRangeOverrides: correctionRangeOverrides,
  70. maximumBasalRatePerHour: maximumBasalRatePerHour,
  71. maximumBolus: maximumBolus,
  72. suspendThreshold: suspendThreshold,
  73. insulinSensitivitySchedule: insulinSensitivitySchedule,
  74. carbRatioSchedule: carbRatioSchedule,
  75. basalRateSchedule: basalRateSchedule,
  76. defaultRapidActingModel: defaultRapidActingModel)
  77. }
  78. public func encode(to encoder: Encoder) throws {
  79. var container = encoder.container(keyedBy: CodingKeys.self)
  80. try container.encodeIfPresent(glucoseTargetRangeSchedule, forKey: .glucoseTargetRangeSchedule)
  81. try container.encodeIfPresent(correctionRangeOverrides, forKey: .correctionRangeOverrides)
  82. try container.encodeIfPresent(maximumBasalRatePerHour, forKey: .maximumBasalRatePerHour)
  83. try container.encodeIfPresent(maximumBolus, forKey: .maximumBolus)
  84. try container.encodeIfPresent(suspendThreshold, forKey: .suspendThreshold)
  85. try container.encodeIfPresent(insulinSensitivitySchedule, forKey: .insulinSensitivitySchedule)
  86. try container.encodeIfPresent(carbRatioSchedule, forKey: .carbRatioSchedule)
  87. try container.encodeIfPresent(basalRateSchedule, forKey: .basalRateSchedule)
  88. try container.encodeIfPresent(defaultRapidActingModel, forKey: .defaultRapidActingModel)
  89. }
  90. private enum CodingKeys: String, CodingKey {
  91. case glucoseTargetRangeSchedule
  92. case correctionRangeOverrides
  93. case maximumBasalRatePerHour
  94. case maximumBolus
  95. case suspendThreshold
  96. case insulinSensitivitySchedule
  97. case carbRatioSchedule
  98. case basalRateSchedule
  99. case defaultRapidActingModel
  100. }
  101. }
  102. extension TherapySettings {
  103. // Mock therapy settings for QA and mock prescriptions
  104. public static var mockTherapySettings: TherapySettings {
  105. let timeZone = TimeZone(identifier: "America/Los_Angeles")!
  106. let glucoseTargetRangeSchedule = GlucoseRangeSchedule(
  107. rangeSchedule: DailyQuantitySchedule(unit: .milligramsPerDeciliter,
  108. dailyItems: [RepeatingScheduleValue(startTime: .hours(0), value: DoubleRange(minValue: 100.0, maxValue: 110.0)),
  109. RepeatingScheduleValue(startTime: .hours(8), value: DoubleRange(minValue: 105.0, maxValue: 115.0)),
  110. RepeatingScheduleValue(startTime: .hours(21), value: DoubleRange(minValue: 100.0, maxValue: 110.0))],
  111. timeZone: timeZone)!,
  112. override: GlucoseRangeSchedule.Override(value: DoubleRange(minValue: 80.0, maxValue: 90.0),
  113. start: Date().addingTimeInterval(.minutes(-30)),
  114. end: Date().addingTimeInterval(.minutes(30)))
  115. )
  116. let correctionRangeOverrides = CorrectionRangeOverrides(preMeal: DoubleRange(minValue: 80.0, maxValue: 90.0),
  117. workout: DoubleRange(minValue: 140.0, maxValue: 160.0),
  118. unit: .milligramsPerDeciliter)
  119. let basalRateSchedule = BasalRateSchedule(
  120. dailyItems: [RepeatingScheduleValue(startTime: .hours(0), value: 1),
  121. RepeatingScheduleValue(startTime: .hours(15), value: 0.85)],
  122. timeZone: timeZone)!
  123. let insulinSensitivitySchedule = InsulinSensitivitySchedule(
  124. unit: .milligramsPerDeciliter,
  125. dailyItems: [RepeatingScheduleValue(startTime: .hours(0), value: 45.0),
  126. RepeatingScheduleValue(startTime: .hours(9), value: 55.0)],
  127. timeZone: timeZone)!
  128. let carbRatioSchedule = CarbRatioSchedule(
  129. unit: .gram(),
  130. dailyItems: [RepeatingScheduleValue(startTime: .hours(0), value: 10.0)],
  131. timeZone: timeZone)!
  132. return TherapySettings(
  133. glucoseTargetRangeSchedule: glucoseTargetRangeSchedule,
  134. correctionRangeOverrides: correctionRangeOverrides,
  135. maximumBasalRatePerHour: 5,
  136. maximumBolus: 10,
  137. suspendThreshold: GlucoseThreshold(unit: .milligramsPerDeciliter, value: 75),
  138. insulinSensitivitySchedule: insulinSensitivitySchedule,
  139. carbRatioSchedule: carbRatioSchedule,
  140. basalRateSchedule: basalRateSchedule,
  141. defaultRapidActingModel: .rapidActingAdult
  142. )
  143. }
  144. }