BolusStateModel.swift 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. import SwiftUI
  2. import Swinject
  3. extension Bolus {
  4. final class StateModel: BaseStateModel<Provider> {
  5. @Injected() var unlockmanager: UnlockManager!
  6. @Injected() var apsManager: APSManager!
  7. @Injected() var broadcaster: Broadcaster!
  8. @Injected() var pumpHistoryStorage: PumpHistoryStorage!
  9. @Published var amount: Decimal = 0
  10. @Published var insulinRecommended: Decimal = 0
  11. @Published var insulinRequired: Decimal = 0
  12. @Published var waitForSuggestion: Bool = false
  13. @Published var manual: Bool = false
  14. @Published var error: Bool = false
  15. @Published var errorString: Decimal = 0
  16. @Published var evBG: Int = 0
  17. @Published var insulin: Decimal = 0
  18. @Published var target: Decimal = 0
  19. @Published var isf: Decimal = 0
  20. @Published var percentage: Decimal = 0
  21. @Published var threshold: Decimal = 0
  22. @Published var minGuardBG: Decimal = 0
  23. @Published var minDelta: Decimal = 0
  24. @Published var expectedDelta: Decimal = 0
  25. @Published var minPredBG: Decimal = 0
  26. @Published var units: GlucoseUnits = .mmolL
  27. var waitForSuggestionInitial: Bool = false
  28. override func subscribe() {
  29. setupInsulinRequired()
  30. broadcaster.register(SuggestionObserver.self, observer: self)
  31. units = settingsManager.settings.units
  32. percentage = settingsManager.settings.insulinReqPercentage
  33. threshold = units == .mmolL ? settingsManager.preferences.threshold_setting.asMmolL : settingsManager.preferences
  34. .threshold_setting
  35. if waitForSuggestionInitial {
  36. apsManager.determineBasal()
  37. .receive(on: DispatchQueue.main)
  38. .sink { [weak self] ok in
  39. guard let self = self else { return }
  40. if !ok {
  41. self.waitForSuggestion = false
  42. self.insulinRequired = 0
  43. self.insulinRecommended = 0
  44. }
  45. }.store(in: &lifetime)
  46. }
  47. }
  48. func add() {
  49. guard amount > 0 else {
  50. showModal(for: nil)
  51. return
  52. }
  53. let maxAmount = Double(min(amount, provider.pumpSettings().maxBolus))
  54. unlockmanager.unlock()
  55. .sink { _ in } receiveValue: { [weak self] _ in
  56. guard let self = self else { return }
  57. self.apsManager.enactBolus(amount: maxAmount, isSMB: false)
  58. self.showModal(for: nil)
  59. }
  60. .store(in: &lifetime)
  61. }
  62. func addWithoutBolus() {
  63. guard amount > 0 else {
  64. showModal(for: nil)
  65. return
  66. }
  67. pumpHistoryStorage.storeEvents(
  68. [
  69. PumpHistoryEvent(
  70. id: UUID().uuidString,
  71. type: .bolus,
  72. timestamp: Date(),
  73. amount: amount,
  74. duration: nil,
  75. durationMin: nil,
  76. rate: nil,
  77. temp: nil,
  78. carbInput: nil
  79. )
  80. ]
  81. )
  82. showModal(for: nil)
  83. }
  84. func setupInsulinRequired() {
  85. DispatchQueue.main.async {
  86. self.insulinRequired = self.provider.suggestion?.insulinReq ?? 0
  87. // Manual Bolus recommendation screen after a carb entry (normally) yields a higher amount than the insulin reqiured amount computed for SMBs (auto boluses). Carbs combined with a manual bolus threfore now (test) uses the Eventual BG for glucose prediction, whereas the insulinReg for SMBs uses the minPredBG for glucose prediction (typically lower than Eventual BG).
  88. var conversion: Decimal = 1.0
  89. if self.units == .mmolL {
  90. conversion = 0.0555
  91. }
  92. self.evBG = self.provider.suggestion?.eventualBG ?? 0
  93. self.insulin = self.provider.suggestion?.insulinForManualBolus ?? 0
  94. self.target = self.provider.suggestion?.current_target ?? 0
  95. self.isf = self.provider.suggestion?.isf ?? 0
  96. if self.settingsManager.settings.insulinReqPercentage != 100 {
  97. self.insulinRecommended = self.insulin * (self.settingsManager.settings.insulinReqPercentage / 100)
  98. } else { self.insulinRecommended = self.insulin }
  99. self.errorString = self.provider.suggestion?.manualBolusErrorString ?? 0
  100. if self.errorString != 0 {
  101. self.error = true
  102. self.minGuardBG = (self.provider.suggestion?.minGuardBG ?? 0) * conversion
  103. self.minDelta = (self.provider.suggestion?.minDelta ?? 0) * conversion
  104. self.expectedDelta = (self.provider.suggestion?.expectedDelta ?? 0) * conversion
  105. self.minPredBG = (self.provider.suggestion?.minPredBG ?? 0) * conversion
  106. } else { self.error = false }
  107. self.insulinRecommended = self.apsManager
  108. .roundBolus(amount: max(self.insulinRecommended, 0))
  109. }
  110. }
  111. }
  112. }
  113. extension Bolus.StateModel: SuggestionObserver {
  114. func suggestionDidUpdate(_: Suggestion) {
  115. DispatchQueue.main.async {
  116. self.waitForSuggestion = false
  117. }
  118. setupInsulinRequired()
  119. }
  120. }