BolusStateModel.swift 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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 error: Bool = false
  14. @Published var errorString: Decimal = 0
  15. @Published var evBG: Int = 0
  16. @Published var insulin: Decimal = 0
  17. @Published var target: Decimal = 0
  18. @Published var isf: Decimal = 0
  19. @Published var percentage: Decimal = 0
  20. @Published var threshold: Decimal = 0
  21. @Published var minGuardBG: Decimal = 0
  22. @Published var minDelta: Decimal = 0
  23. @Published var expectedDelta: Decimal = 0
  24. @Published var minPredBG: Decimal = 0
  25. @Published var units: GlucoseUnits = .mmolL
  26. @Published var maxBolus: Decimal = 0
  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 = provider.suggestion?.threshold ?? 0
  34. maxBolus = provider.pumpSettings().maxBolus
  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, 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. isExternalInsulin: true
  80. )
  81. ]
  82. )
  83. showModal(for: nil)
  84. }
  85. func setupInsulinRequired() {
  86. DispatchQueue.main.async {
  87. self.insulinRequired = self.provider.suggestion?.insulinReq ?? 0
  88. // Manual Bolus recommendation (normally) yields a higher amount than the insulin reqiured amount computed for SMBs (auto boluses). 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).
  89. var conversion: Decimal = 1.0
  90. if self.units == .mmolL {
  91. conversion = 0.0555
  92. }
  93. self.evBG = self.provider.suggestion?.eventualBG ?? 0
  94. self.insulin = self.provider.suggestion?.insulinForManualBolus ?? 0
  95. self.target = self.provider.suggestion?.current_target ?? 0
  96. self.isf = self.provider.suggestion?.isf ?? 0
  97. if self.settingsManager.settings.insulinReqPercentage != 100 {
  98. self.insulinRecommended = self.insulin * (self.settingsManager.settings.insulinReqPercentage / 100)
  99. } else { self.insulinRecommended = self.insulin }
  100. self.errorString = self.provider.suggestion?.manualBolusErrorString ?? 0
  101. if self.errorString != 0 {
  102. self.error = true
  103. self.minGuardBG = (self.provider.suggestion?.minGuardBG ?? 0) * conversion
  104. self.minDelta = (self.provider.suggestion?.minDelta ?? 0) * conversion
  105. self.expectedDelta = (self.provider.suggestion?.expectedDelta ?? 0) * conversion
  106. self.minPredBG = (self.provider.suggestion?.minPredBG ?? 0) * conversion
  107. } else { self.error = false }
  108. self.insulinRecommended = self.apsManager
  109. .roundBolus(amount: max(self.insulinRecommended, 0))
  110. }
  111. }
  112. }
  113. }
  114. extension Bolus.StateModel: SuggestionObserver {
  115. func suggestionDidUpdate(_: Suggestion) {
  116. DispatchQueue.main.async {
  117. self.waitForSuggestion = false
  118. }
  119. setupInsulinRequired()
  120. }
  121. }