Просмотр исходного кода

Improve the bolus calculator. (#98)

When entering carbs and coming to the bolus recommendation screen, use the EventualBG instead of the minPredBG when computing recommended bolus. Only used when directly combined with carbs. If not everything else is as before.

To not make things overly complicated I'm using this new bolus recommendation for Watch App also, but always, until I find a neat way of collecting the manual state from the BolusStateModel.

For testing. Tested for about a week without any dramatic adverse effects, but needs more testing from more users.
Jon B Mårtensson 2 лет назад
Родитель
Сommit
6edda045d3

+ 1 - 1
Config.xcconfig

@@ -1,5 +1,5 @@
 APP_DISPLAY_NAME = iAPS
 APP_DISPLAY_NAME = iAPS
-APP_VERSION = 2.1.7
+APP_VERSION = 2.1.8
 APP_BUILD_NUMBER = 1
 APP_BUILD_NUMBER = 1
 COPYRIGHT_NOTICE =
 COPYRIGHT_NOTICE =
 DEVELOPER_TEAM = ##TEAM_ID##
 DEVELOPER_TEAM = ##TEAM_ID##

Разница между файлами не показана из-за своего большого размера
+ 1 - 2
FreeAPS/Resources/javascript/bundle/determine-basal.js


+ 2 - 0
FreeAPS/Sources/Models/Suggestion.swift

@@ -22,6 +22,7 @@ struct Suggestion: JSON, Equatable {
     let tdd: Decimal?
     let tdd: Decimal?
     let insulin: Insulin?
     let insulin: Insulin?
     let current_target: Decimal?
     let current_target: Decimal?
+    let insulinForManualBolus: Decimal?
 }
 }
 
 
 struct Predictions: JSON, Equatable {
 struct Predictions: JSON, Equatable {
@@ -61,6 +62,7 @@ extension Suggestion {
         case tdd = "TDD"
         case tdd = "TDD"
         case insulin
         case insulin
         case current_target
         case current_target
+        case insulinForManualBolus
     }
     }
 }
 }
 
 

+ 3 - 1
FreeAPS/Sources/Modules/AddCarbs/AddCarbsStateModel.swift

@@ -16,6 +16,7 @@ extension AddCarbs {
         @Published var dish: String = ""
         @Published var dish: String = ""
         @Published var selection: Presets?
         @Published var selection: Presets?
         @Published var summation: [String] = []
         @Published var summation: [String] = []
+        @Published var manualBolus: Bool = false
 
 
         let coredataContext = CoreDataStack.shared.persistentContainer.viewContext
         let coredataContext = CoreDataStack.shared.persistentContainer.viewContext
 
 
@@ -108,7 +109,8 @@ extension AddCarbs {
                 apsManager.determineBasalSync()
                 apsManager.determineBasalSync()
                 showModal(for: nil)
                 showModal(for: nil)
             } else {
             } else {
-                showModal(for: .bolus(waitForSuggestion: true))
+                manualBolus.toggle()
+                showModal(for: .bolus(waitForSuggestion: true, manualBolus: manualBolus))
             }
             }
         }
         }
 
 

+ 19 - 5
FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift

@@ -11,6 +11,8 @@ extension Bolus {
         @Published var insulinRecommended: Decimal = 0
         @Published var insulinRecommended: Decimal = 0
         @Published var insulinRequired: Decimal = 0
         @Published var insulinRequired: Decimal = 0
         @Published var waitForSuggestion: Bool = false
         @Published var waitForSuggestion: Bool = false
+        @Published var manual: Bool = false
+
         var waitForSuggestionInitial: Bool = false
         var waitForSuggestionInitial: Bool = false
 
 
         override func subscribe() {
         override func subscribe() {
@@ -74,12 +76,24 @@ extension Bolus {
 
 
         func setupInsulinRequired() {
         func setupInsulinRequired() {
             DispatchQueue.main.async {
             DispatchQueue.main.async {
-                self.insulinRequired = self.provider.suggestion?.insulinReq ?? 0
+                // 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).
+
+                if self.manual {
+                    self.insulinRequired = self.provider.suggestion?.insulinForManualBolus ?? 0
+
+                    if self.settingsManager.settings.insulinReqPercentage != 100 {
+                        self.insulinRecommended = self
+                            .insulinRequired * (self.settingsManager.settings.insulinReqPercentage / 100)
+                    } else { self.insulinRecommended = self.insulinRequired }
+
+                } else {
+                    self.insulinRequired = self.provider.suggestion?.insulinReq ?? 0
+                    self.insulinRecommended = self
+                        .insulinRequired * (self.settingsManager.settings.insulinReqPercentage / 100) * 2
+                }
+
                 self.insulinRecommended = self.apsManager
                 self.insulinRecommended = self.apsManager
-                    .roundBolus(amount: max(
-                        self.insulinRequired * (self.settingsManager.settings.insulinReqPercentage / 100) * 2,
-                        0
-                    ))
+                    .roundBolus(amount: max(self.insulinRecommended, 0))
             }
             }
         }
         }
     }
     }

+ 47 - 27
FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift

@@ -5,6 +5,7 @@ extension Bolus {
     struct RootView: BaseView {
     struct RootView: BaseView {
         let resolver: Resolver
         let resolver: Resolver
         let waitForSuggestion: Bool
         let waitForSuggestion: Bool
+        let manualBolus: Bool
         @StateObject var state = StateModel()
         @StateObject var state = StateModel()
         @State private var isAddInsulinAlertPresented = false
         @State private var isAddInsulinAlertPresented = false
 
 
@@ -17,7 +18,7 @@ extension Bolus {
 
 
         var body: some View {
         var body: some View {
             Form {
             Form {
-                Section(header: Text("Recommendation")) {
+                Section {
                     if state.waitForSuggestion {
                     if state.waitForSuggestion {
                         HStack {
                         HStack {
                             Text("Wait please").foregroundColor(.secondary)
                             Text("Wait please").foregroundColor(.secondary)
@@ -25,35 +26,52 @@ extension Bolus {
                             ActivityIndicator(isAnimating: .constant(true), style: .medium) // fix iOS 15 bug
                             ActivityIndicator(isAnimating: .constant(true), style: .medium) // fix iOS 15 bug
                         }
                         }
                     } else {
                     } else {
-                        HStack {
-                            Text("Insulin required").foregroundColor(.secondary)
-                            Spacer()
-                            Text(
-                                formatter
-                                    .string(from: state.insulinRequired as NSNumber)! +
-                                    NSLocalizedString(" U", comment: "Insulin unit")
-                            ).foregroundColor(.secondary)
-                        }.contentShape(Rectangle())
-                            .onTapGesture {
-                                state.amount = state.insulinRequired
-                            }
-                        HStack {
-                            Text("Insulin recommended")
-                            Spacer()
-                            Text(
-                                formatter
-                                    .string(from: state.insulinRecommended as NSNumber)! +
-                                    NSLocalizedString(" U", comment: "Insulin unit")
-                            ).foregroundColor(.secondary)
-                        }.contentShape(Rectangle())
-                            .onTapGesture {
-                                state.amount = state.insulinRecommended
-                            }
+                        if state.manual {
+                            HStack {
+                                Text("Insulin recommended")
+                                Spacer()
+                                Text(
+                                    formatter
+                                        .string(from: state.insulinRecommended as NSNumber)! +
+                                        NSLocalizedString(" U", comment: "Insulin unit")
+                                ).foregroundColor(.secondary)
+                            }.contentShape(Rectangle())
+                                .onTapGesture {
+                                    state.amount = state.insulinRecommended
+                                }
+                        } else {
+                            HStack {
+                                Text("Insulin required").foregroundColor(.secondary)
+                                Spacer()
+                                Text(
+                                    formatter
+                                        .string(from: state.insulinRequired as NSNumber)! +
+                                        NSLocalizedString(" U", comment: "Insulin unit")
+                                ).foregroundColor(.secondary)
+                            }.contentShape(Rectangle())
+                                .onTapGesture {
+                                    state.amount = state.insulinRequired
+                                }
+
+                            HStack {
+                                Text("Insulin recommended")
+                                Spacer()
+                                Text(
+                                    formatter
+                                        .string(from: state.insulinRecommended as NSNumber)! +
+                                        NSLocalizedString(" U", comment: "Insulin unit")
+                                ).foregroundColor(.secondary)
+                            }.contentShape(Rectangle())
+                                .onTapGesture {
+                                    state.amount = state.insulinRecommended
+                                }
+                        }
                     }
                     }
                 }
                 }
-
+                header: { Text("Recommendation") }
+                
                 if !state.waitForSuggestion {
                 if !state.waitForSuggestion {
-                    Section(header: Text("Bolus")) {
+                    Section {
                         HStack {
                         HStack {
                             Text("Amount")
                             Text("Amount")
                             Spacer()
                             Spacer()
@@ -67,6 +85,7 @@ extension Bolus {
                             Text("U").foregroundColor(.secondary)
                             Text("U").foregroundColor(.secondary)
                         }
                         }
                     }
                     }
+                    header: { Text("Bolus") }
 
 
                     Section {
                     Section {
                         Button { state.add() }
                         Button { state.add() }
@@ -103,6 +122,7 @@ extension Bolus {
                 configureView {
                 configureView {
                     state.waitForSuggestionInitial = waitForSuggestion
                     state.waitForSuggestionInitial = waitForSuggestion
                     state.waitForSuggestion = waitForSuggestion
                     state.waitForSuggestion = waitForSuggestion
+                    state.manual = manualBolus
                 }
                 }
             }
             }
             .navigationTitle("Enact Bolus")
             .navigationTitle("Enact Bolus")

+ 1 - 1
FreeAPS/Sources/Modules/Home/View/HomeRootView.swift

@@ -502,7 +502,7 @@ extension Home {
                             .padding(8)
                             .padding(8)
                     }.foregroundColor(.loopGreen)
                     }.foregroundColor(.loopGreen)
                     Spacer()
                     Spacer()
-                    Button { state.showModal(for: .bolus(waitForSuggestion: false)) }
+                    Button { state.showModal(for: .bolus(waitForSuggestion: false, manualBolus: false)) }
                     label: {
                     label: {
                         Image("bolus")
                         Image("bolus")
                             .renderingMode(.template)
                             .renderingMode(.template)

+ 0 - 6
FreeAPS/Sources/Modules/Stat/View/ChartsView.swift

@@ -1,9 +1,3 @@
-//
-//  FilteredLoopsView.swift
-//  FreeAPS
-//
-//  Created by Jon Mårtensson on 2023-05-29.
-//
 import Charts
 import Charts
 import CoreData
 import CoreData
 import SwiftDate
 import SwiftDate

+ 0 - 6
FreeAPS/Sources/Modules/Stat/View/StatsView.swift

@@ -1,9 +1,3 @@
-//
-//  FilteredLoopsView.swift
-//  FreeAPS
-//
-//  Created by Jon Mårtensson on 2023-05-29.
-//
 import CoreData
 import CoreData
 import SwiftDate
 import SwiftDate
 import SwiftUI
 import SwiftUI

+ 3 - 3
FreeAPS/Sources/Router/Screen.swift

@@ -16,7 +16,7 @@ enum Screen: Identifiable, Hashable {
     case preferencesEditor
     case preferencesEditor
     case addCarbs
     case addCarbs
     case addTempTarget
     case addTempTarget
-    case bolus(waitForSuggestion: Bool)
+    case bolus(waitForSuggestion: Bool, manualBolus: Bool)
     case manualTempBasal
     case manualTempBasal
     case autotuneConfig
     case autotuneConfig
     case dataTable
     case dataTable
@@ -67,8 +67,8 @@ extension Screen {
             AddCarbs.RootView(resolver: resolver)
             AddCarbs.RootView(resolver: resolver)
         case .addTempTarget:
         case .addTempTarget:
             AddTempTarget.RootView(resolver: resolver)
             AddTempTarget.RootView(resolver: resolver)
-        case let .bolus(waitForSuggestion):
-            Bolus.RootView(resolver: resolver, waitForSuggestion: waitForSuggestion)
+        case let .bolus(waitForSuggestion, manualBolus):
+            Bolus.RootView(resolver: resolver, waitForSuggestion: waitForSuggestion, manualBolus: manualBolus)
         case .manualTempBasal:
         case .manualTempBasal:
             ManualTempBasal.RootView(resolver: resolver)
             ManualTempBasal.RootView(resolver: resolver)
         case .autotuneConfig:
         case .autotuneConfig:

+ 8 - 2
FreeAPS/Sources/Services/WatchManager/WatchManager.swift

@@ -75,9 +75,15 @@ final class BaseWatchManager: NSObject, WatchManager, Injectable {
             self.state.maxBolus = self.settingsManager.pumpSettings.maxBolus
             self.state.maxBolus = self.settingsManager.pumpSettings.maxBolus
             self.state.carbsRequired = self.suggestion?.carbsReq
             self.state.carbsRequired = self.suggestion?.carbsReq
 
 
-            let insulinRequired = self.suggestion?.insulinReq ?? 0
+            var insulinRequired = self.suggestion?.insulinReq ?? 0
+            var double: Decimal = 2
+            if (self.suggestion?.cob ?? 0) > 0 {
+                insulinRequired = self.suggestion?.insulinForManualBolus ?? 0
+                double = 1
+            }
+
             self.state.bolusRecommended = self.apsManager
             self.state.bolusRecommended = self.apsManager
-                .roundBolus(amount: max(insulinRequired * (self.settingsManager.settings.insulinReqPercentage / 100) * 2, 0))
+                .roundBolus(amount: max(insulinRequired * (self.settingsManager.settings.insulinReqPercentage / 100) * double, 0))
 
 
             self.state.iob = self.suggestion?.iob
             self.state.iob = self.suggestion?.iob
             self.state.cob = self.suggestion?.cob
             self.state.cob = self.suggestion?.cob