TherapySettings.swift 8.2 KB

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