BolusStateModel.swift 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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. var waitForSuggestionInitial: Bool = false
  27. override func subscribe() {
  28. setupInsulinRequired()
  29. broadcaster.register(SuggestionObserver.self, observer: self)
  30. units = settingsManager.settings.units
  31. percentage = settingsManager.settings.insulinReqPercentage
  32. threshold = provider.suggestion?.threshold ?? 0
  33. if waitForSuggestionInitial {
  34. apsManager.determineBasal()
  35. .receive(on: DispatchQueue.main)
  36. .sink { [weak self] ok in
  37. guard let self = self else { return }
  38. if !ok {
  39. self.waitForSuggestion = false
  40. self.insulinRequired = 0
  41. self.insulinRecommended = 0
  42. }
  43. }.store(in: &lifetime)
  44. }
  45. }
  46. func add() {
  47. guard amount > 0 else {
  48. showModal(for: nil)
  49. return
  50. }
  51. let maxAmount = Double(min(amount, provider.pumpSettings().maxBolus))
  52. unlockmanager.unlock()
  53. .sink { _ in } receiveValue: { [weak self] _ in
  54. guard let self = self else { return }
  55. self.apsManager.enactBolus(amount: maxAmount, isSMB: false)
  56. self.showModal(for: nil)
  57. }
  58. .store(in: &lifetime)
  59. }
  60. func addWithoutBolus() {
  61. guard amount > 0 else {
  62. showModal(for: nil)
  63. return
  64. }
  65. pumpHistoryStorage.storeEvents(
  66. [
  67. PumpHistoryEvent(
  68. id: UUID().uuidString,
  69. type: .bolus,
  70. timestamp: Date(),
  71. amount: amount,
  72. duration: nil,
  73. durationMin: nil,
  74. rate: nil,
  75. temp: nil,
  76. carbInput: nil,
  77. isExternalInsulin: true
  78. )
  79. ]
  80. )
  81. showModal(for: nil)
  82. }
  83. func setupInsulinRequired() {
  84. DispatchQueue.main.async {
  85. self.insulinRequired = self.provider.suggestion?.insulinReq ?? 0
  86. // 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).
  87. var conversion: Decimal = 1.0
  88. if self.units == .mmolL {
  89. conversion = 0.0555
  90. }
  91. self.evBG = self.provider.suggestion?.eventualBG ?? 0
  92. self.insulin = self.provider.suggestion?.insulinForManualBolus ?? 0
  93. self.target = self.provider.suggestion?.current_target ?? 0
  94. self.isf = self.provider.suggestion?.isf ?? 0
  95. if self.settingsManager.settings.insulinReqPercentage != 100 {
  96. self.insulinRecommended = self.insulin * (self.settingsManager.settings.insulinReqPercentage / 100)
  97. } else { self.insulinRecommended = self.insulin }
  98. self.errorString = self.provider.suggestion?.manualBolusErrorString ?? 0
  99. if self.errorString != 0 {
  100. self.error = true
  101. self.minGuardBG = (self.provider.suggestion?.minGuardBG ?? 0) * conversion
  102. self.minDelta = (self.provider.suggestion?.minDelta ?? 0) * conversion
  103. self.expectedDelta = (self.provider.suggestion?.expectedDelta ?? 0) * conversion
  104. self.minPredBG = (self.provider.suggestion?.minPredBG ?? 0) * conversion
  105. } else { self.error = false }
  106. self.insulinRecommended = self.apsManager
  107. .roundBolus(amount: max(self.insulinRecommended, 0))
  108. }
  109. }
  110. }
  111. }
  112. extension Bolus.StateModel: SuggestionObserver {
  113. func suggestionDidUpdate(_: Suggestion) {
  114. DispatchQueue.main.async {
  115. self.waitForSuggestion = false
  116. }
  117. setupInsulinRequired()
  118. }
  119. }