TherapySettingsViewModel.swift 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. //
  2. // TherapySettingsViewModel.swift
  3. // LoopKitUI
  4. //
  5. // Created by Rick Pasetto on 7/13/20.
  6. // Copyright © 2020 LoopKit Authors. All rights reserved.
  7. //
  8. import Combine
  9. import LoopKit
  10. import HealthKit
  11. import SwiftUI
  12. public protocol TherapySettingsViewModelDelegate: AnyObject {
  13. func syncBasalRateSchedule(items: [RepeatingScheduleValue<Double>], completion: @escaping (Result<BasalRateSchedule, Error>) -> Void)
  14. func syncDeliveryLimits(deliveryLimits: DeliveryLimits, completion: @escaping (Result<DeliveryLimits, Error>) -> Void)
  15. func saveCompletion(for therapySetting: TherapySetting, therapySettings: TherapySettings)
  16. func pumpSupportedIncrements() -> PumpSupportedIncrements?
  17. }
  18. public class TherapySettingsViewModel: ObservableObject {
  19. @Published public var therapySettings: TherapySettings
  20. private let initialTherapySettings: TherapySettings
  21. let sensitivityOverridesEnabled: Bool
  22. let adultChildInsulinModelSelectionEnabled: Bool
  23. public var prescription: Prescription?
  24. private weak var delegate: TherapySettingsViewModelDelegate?
  25. public init(therapySettings: TherapySettings,
  26. pumpSupportedIncrements: (() -> PumpSupportedIncrements?)? = nil,
  27. sensitivityOverridesEnabled: Bool = false,
  28. adultChildInsulinModelSelectionEnabled: Bool = false,
  29. prescription: Prescription? = nil,
  30. delegate: TherapySettingsViewModelDelegate? = nil) {
  31. self.therapySettings = therapySettings
  32. self.initialTherapySettings = therapySettings
  33. self.sensitivityOverridesEnabled = sensitivityOverridesEnabled
  34. self.adultChildInsulinModelSelectionEnabled = adultChildInsulinModelSelectionEnabled
  35. self.prescription = prescription
  36. self.delegate = delegate
  37. }
  38. var deliveryLimits: DeliveryLimits {
  39. return DeliveryLimits(maximumBasalRate: therapySettings.maximumBasalRatePerHour.map { HKQuantity(unit: .internationalUnitsPerHour, doubleValue: $0) },
  40. maximumBolus: therapySettings.maximumBolus.map { HKQuantity(unit: .internationalUnit(), doubleValue: $0) } )
  41. }
  42. var suspendThreshold: GlucoseThreshold? {
  43. return therapySettings.suspendThreshold
  44. }
  45. var glucoseTargetRangeSchedule: GlucoseRangeSchedule? {
  46. return therapySettings.glucoseTargetRangeSchedule
  47. }
  48. func glucoseTargetRangeSchedule(for glucoseUnit: HKUnit) -> GlucoseRangeSchedule? {
  49. return glucoseTargetRangeSchedule?.schedule(for: glucoseUnit)
  50. }
  51. var correctionRangeOverrides: CorrectionRangeOverrides {
  52. return CorrectionRangeOverrides(preMeal: therapySettings.correctionRangeOverrides?.preMeal,
  53. workout: therapySettings.correctionRangeOverrides?.workout)
  54. }
  55. var correctionRangeScheduleRange: ClosedRange<HKQuantity> {
  56. precondition(therapySettings.glucoseTargetRangeSchedule != nil)
  57. return therapySettings.glucoseTargetRangeSchedule!.scheduleRange()
  58. }
  59. var insulinSensitivitySchedule: InsulinSensitivitySchedule? {
  60. return therapySettings.insulinSensitivitySchedule
  61. }
  62. func insulinSensitivitySchedule(for glucoseUnit: HKUnit) -> InsulinSensitivitySchedule? {
  63. return insulinSensitivitySchedule?.schedule(for: glucoseUnit)
  64. }
  65. /// Reset to initial
  66. public func reset() {
  67. therapySettings = initialTherapySettings
  68. }
  69. }
  70. // MARK: Passing along to the delegate
  71. extension TherapySettingsViewModel {
  72. public var maximumBasalScheduleEntryCount: Int? {
  73. pumpSupportedIncrements()?.maximumBasalScheduleEntryCount
  74. }
  75. public func pumpSupportedIncrements() -> PumpSupportedIncrements? {
  76. return delegate?.pumpSupportedIncrements()
  77. }
  78. public func syncBasalRateSchedule(items: [RepeatingScheduleValue<Double>], completion: @escaping (Result<BasalRateSchedule, Error>) -> Void) {
  79. delegate?.syncBasalRateSchedule(items: items, completion: completion)
  80. }
  81. public func syncDeliveryLimits(deliveryLimits: DeliveryLimits, completion: @escaping (Result<DeliveryLimits, Error>) -> Void) {
  82. delegate?.syncDeliveryLimits(deliveryLimits: deliveryLimits, completion: completion)
  83. }
  84. }
  85. // MARK: Saving
  86. extension TherapySettingsViewModel {
  87. public func saveCorrectionRange(range: GlucoseRangeSchedule) {
  88. therapySettings.glucoseTargetRangeSchedule = range
  89. delegate?.saveCompletion(for: TherapySetting.glucoseTargetRange, therapySettings: therapySettings)
  90. }
  91. public func saveCorrectionRangeOverride(preset: CorrectionRangeOverrides.Preset,
  92. correctionRangeOverrides: CorrectionRangeOverrides) {
  93. therapySettings.correctionRangeOverrides = correctionRangeOverrides
  94. switch preset {
  95. case .preMeal:
  96. delegate?.saveCompletion(for: TherapySetting.preMealCorrectionRangeOverride, therapySettings: therapySettings)
  97. case .workout:
  98. delegate?.saveCompletion(for: TherapySetting.workoutCorrectionRangeOverride, therapySettings: therapySettings)
  99. }
  100. }
  101. public func saveSuspendThreshold(quantity: HKQuantity, withDisplayGlucoseUnit displayGlucoseUnit: HKUnit) {
  102. therapySettings.suspendThreshold = GlucoseThreshold(unit: displayGlucoseUnit, value: quantity.doubleValue(for: displayGlucoseUnit))
  103. delegate?.saveCompletion(for: TherapySetting.suspendThreshold, therapySettings: therapySettings)
  104. }
  105. public func saveBasalRates(basalRates: BasalRateSchedule) {
  106. therapySettings.basalRateSchedule = basalRates
  107. delegate?.saveCompletion(for: TherapySetting.basalRate, therapySettings: therapySettings)
  108. }
  109. public func saveDeliveryLimits(limits: DeliveryLimits) {
  110. therapySettings.maximumBasalRatePerHour = limits.maximumBasalRate?.doubleValue(for: .internationalUnitsPerHour)
  111. therapySettings.maximumBolus = limits.maximumBolus?.doubleValue(for: .internationalUnit())
  112. delegate?.saveCompletion(for: TherapySetting.deliveryLimits, therapySettings: therapySettings)
  113. }
  114. public func saveInsulinModel(insulinModelPreset: ExponentialInsulinModelPreset) {
  115. therapySettings.defaultRapidActingModel = insulinModelPreset
  116. delegate?.saveCompletion(for: TherapySetting.insulinModel, therapySettings: therapySettings)
  117. }
  118. public func saveCarbRatioSchedule(carbRatioSchedule: CarbRatioSchedule) {
  119. therapySettings.carbRatioSchedule = carbRatioSchedule
  120. delegate?.saveCompletion(for: TherapySetting.carbRatio, therapySettings: therapySettings)
  121. }
  122. public func saveInsulinSensitivitySchedule(insulinSensitivitySchedule: InsulinSensitivitySchedule) {
  123. therapySettings.insulinSensitivitySchedule = insulinSensitivitySchedule
  124. delegate?.saveCompletion(for: TherapySetting.insulinSensitivity, therapySettings: therapySettings)
  125. }
  126. }