BolusStateModel.swift 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  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. var waitForSuggestionInitial: Bool = false
  15. override func subscribe() {
  16. setupInsulinRequired()
  17. broadcaster.register(SuggestionObserver.self, observer: self)
  18. if waitForSuggestionInitial {
  19. apsManager.determineBasal()
  20. .receive(on: DispatchQueue.main)
  21. .sink { [weak self] ok in
  22. guard let self = self else { return }
  23. if !ok {
  24. self.waitForSuggestion = false
  25. self.insulinRequired = 0
  26. self.insulinRecommended = 0
  27. }
  28. }.store(in: &lifetime)
  29. }
  30. }
  31. func add() {
  32. guard amount > 0 else {
  33. showModal(for: nil)
  34. return
  35. }
  36. let maxAmount = Double(min(amount, provider.pumpSettings().maxBolus))
  37. unlockmanager.unlock()
  38. .sink { _ in } receiveValue: { [weak self] _ in
  39. guard let self = self else { return }
  40. self.apsManager.enactBolus(amount: maxAmount, isSMB: false)
  41. self.showModal(for: nil)
  42. }
  43. .store(in: &lifetime)
  44. }
  45. func addWithoutBolus() {
  46. guard amount > 0 else {
  47. showModal(for: nil)
  48. return
  49. }
  50. pumpHistoryStorage.storeEvents(
  51. [
  52. PumpHistoryEvent(
  53. id: UUID().uuidString,
  54. type: .bolus,
  55. timestamp: Date(),
  56. amount: amount,
  57. duration: nil,
  58. durationMin: nil,
  59. rate: nil,
  60. temp: nil,
  61. carbInput: nil
  62. )
  63. ]
  64. )
  65. showModal(for: nil)
  66. }
  67. func setupInsulinRequired() {
  68. DispatchQueue.main.async {
  69. // 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 (and for manual boluses not combined with a carb entry) uses the minPredBG for glucose prediction (typically lower than Eventual BG).
  70. if self.manual {
  71. self.insulinRequired = self.provider.suggestion?.insulinForManualBolus ?? 0
  72. if self.settingsManager.settings.insulinReqPercentage != 100 {
  73. self.insulinRecommended = self
  74. .insulinRequired * (self.settingsManager.settings.insulinReqPercentage / 100)
  75. } else { self.insulinRecommended = self.insulinRequired }
  76. } else {
  77. self.insulinRequired = self.provider.suggestion?.insulinReq ?? 0
  78. self.insulinRecommended = self
  79. .insulinRequired * (self.settingsManager.settings.insulinReqPercentage / 100) * 2
  80. }
  81. self.insulinRecommended = self.apsManager
  82. .roundBolus(amount: max(self.insulinRecommended, 0))
  83. }
  84. }
  85. }
  86. }
  87. extension Bolus.StateModel: SuggestionObserver {
  88. func suggestionDidUpdate(_: Suggestion) {
  89. DispatchQueue.main.async {
  90. self.waitForSuggestion = false
  91. }
  92. setupInsulinRequired()
  93. }
  94. }