Explorar el Código

Use simulated minPredBG for limits in BolusCalculationManager

polscm32 hace 1 año
padre
commit
afc4c8db25

+ 2 - 1
Trio/Sources/Modules/Treatments/TreatmentsStateModel.swift

@@ -374,7 +374,8 @@ extension Treatments {
             let result = await bolusCalculationManager.handleBolusCalculation(
                 carbs: carbs,
                 useFattyMealCorrection: useFattyMealCorrectionFactor,
-                useSuperBolus: useSuperBolus
+                useSuperBolus: useSuperBolus,
+                minPredBG: minPredBG
             )
 
             // Update state properties with calculation results on main thread

+ 1 - 1
Trio/Sources/Modules/Treatments/View/TreatmentsRootView.swift

@@ -73,8 +73,8 @@ extension Treatments {
             debounce?.cancel()
             debounce = DispatchWorkItem { [self] in
                 Task {
-                    state.insulinCalculated = await state.calculateInsulin()
                     await state.updateForecasts()
+                    state.insulinCalculated = await state.calculateInsulin()
                 }
             }
             if let debounce = debounce {

+ 31 - 6
Trio/Sources/Services/BolusCalculator/BolusCalculationManager.swift

@@ -4,7 +4,8 @@ import Swinject
 
 protocol BolusCalculationManager {
     func calculateInsulin(input: CalculationInput) async -> CalculationResult
-    func handleBolusCalculation(carbs: Decimal, useFattyMealCorrection: Bool, useSuperBolus: Bool) async -> CalculationResult
+    func handleBolusCalculation(carbs: Decimal, useFattyMealCorrection: Bool, useSuperBolus: Bool, minPredBG: Decimal?) async
+        -> CalculationResult
 }
 
 final class BaseBolusCalculationManager: BolusCalculationManager, Injectable {
@@ -280,7 +281,8 @@ final class BaseBolusCalculationManager: BolusCalculationManager, Injectable {
     private func prepareCalculationInput(
         carbs: Decimal,
         useFattyMealCorrection: Bool,
-        useSuperBolus: Bool
+        useSuperBolus: Bool,
+        minPredBG: Decimal?
     ) async throws -> CalculationInput {
         do {
             // Get settings
@@ -296,7 +298,6 @@ final class BaseBolusCalculationManager: BolusCalculationManager, Injectable {
             let currentISF = await getCurrentSettingValue(for: .isf)
 
             // Get max IOB and max COB
-
             let preferences = await getPreferences()
             let maxIOB = preferences.maxIOB
             let maxCOB = preferences.maxCOB
@@ -347,7 +348,7 @@ final class BaseBolusCalculationManager: BolusCalculationManager, Injectable {
                 maxBolus: maxBolus,
                 maxIOB: maxIOB,
                 maxCOB: maxCOB,
-                minPredBG: bolusVars.minPredBG
+                minPredBG: minPredBG ?? bolusVars.minPredBG
             )
         } catch {
             debug(
@@ -365,45 +366,56 @@ final class BaseBolusCalculationManager: BolusCalculationManager, Injectable {
     func calculateInsulin(input: CalculationInput) async -> CalculationResult {
         // insulin needed for the current blood glucose
         let targetDifference = input.currentBG - input.target
+        debug(.default, "Target difference: \(targetDifference)")
 
         let targetDifferenceInsulin = targetDifference / input.isf
+        debug(.default, "Target difference insulin: \(targetDifferenceInsulin)")
 
         // more or less insulin because of bg trend in the last 15 minutes
         let fifteenMinutesInsulin = input.deltaBG / input.isf
+        debug(.default, "15min insulin: \(fifteenMinutesInsulin)")
 
         // determine whole COB for which we want to dose insulin for and then determine insulin for wholeCOB
         let wholeCob = min(Decimal(input.cob) + input.carbs, input.maxCOB)
         let wholeCobInsulin = wholeCob / input.carbRatio
+        debug(.default, "Whole COB: \(wholeCob), COB insulin: \(wholeCobInsulin)")
 
         // determine how much the calculator reduces/ increases the bolus because of IOB
         let iobInsulinReduction = (-1) * input.iob
+        debug(.default, "IOB reduction: \(iobInsulinReduction)")
 
         // adding everything together
         // add a calc for the case that no fifteenMinInsulin is available
         let wholeCalc: Decimal
         if input.deltaBG != 0 {
             wholeCalc = (targetDifferenceInsulin + iobInsulinReduction + wholeCobInsulin + fifteenMinutesInsulin)
+            debug(.default, "Whole calc (with delta): \(wholeCalc)")
         } else {
             // add (rare) case that no glucose value is available -> maybe display warning?
             // if no bg is available, ?? sets its value to 0
             if input.currentBG == 0 {
                 wholeCalc = (iobInsulinReduction + wholeCobInsulin)
+                debug(.default, "Whole calc (no BG): \(wholeCalc)")
             } else {
                 wholeCalc = (targetDifferenceInsulin + iobInsulinReduction + wholeCobInsulin)
+                debug(.default, "Whole calc (no delta): \(wholeCalc)")
             }
         }
 
         // apply custom factor at the end of the calculations
         // apply custom factor if fatty meal toggle in bolus calc config settings is on and the box for fatty meals is checked (in RootView)
         var factoredInsulin = wholeCalc
+        debug(.default, "Initial factored insulin: \(factoredInsulin)")
 
         // Apply Recommended Bolus Percentage (input.fraction) and if selected apply Fatty Meal Bolus Percentage (input.fattyMealFactor)
         // If factoredInsulin is negative, though, don't apply either
         if factoredInsulin > 0 {
             factoredInsulin *= input.fraction
+            debug(.default, "After fraction (\(input.fraction)): \(factoredInsulin)")
 
             if input.useFattyMealCorrectionFactor {
                 factoredInsulin *= input.fattyMealFactor
+                debug(.default, "After fatty meal factor (\(input.fattyMealFactor)): \(factoredInsulin)")
             }
         }
 
@@ -412,24 +424,34 @@ final class BaseBolusCalculationManager: BolusCalculationManager, Injectable {
         if input.useSuperBolus {
             superBolusInsulin = input.sweetMealFactor * input.basal
             factoredInsulin += superBolusInsulin
+            debug(.default, "After super bolus (\(superBolusInsulin)): \(factoredInsulin)")
         }
 
         // the final result for recommended insulin amount
         var insulinCalculated: Decimal
         let isLoopStale = Date().timeIntervalSince(apsManager.lastLoopDate) > 15 * 60
+        debug(.default, "Loop stale: \(isLoopStale), currentBG: \(input.currentBG), minPredBG: \(input.minPredBG)")
 
         // don't recommend insulin when current glucose or minPredBG is < 54 or last sucessful loop was over 15 minutes ago
         if input.currentBG < 54 || input.minPredBG < 54 || isLoopStale {
             insulinCalculated = 0
+            debug(.default, "Insulin set to 0 due to safety check - BG < 54 or stale loop")
         } else {
             // no negative insulinCalculated
             insulinCalculated = max(factoredInsulin, 0)
+            debug(.default, "After max(0): \(insulinCalculated)")
+
             // don't exceed maxBolus
             insulinCalculated = min(insulinCalculated, input.maxBolus)
+            debug(.default, "After maxBolus (\(input.maxBolus)): \(insulinCalculated)")
+
             // don't exceed maxIOB
             insulinCalculated = min(insulinCalculated, input.maxIOB - input.iob)
+            debug(.default, "After maxIOB check (\(input.maxIOB) - \(input.iob)): \(insulinCalculated)")
+
             // round calculated recommendation to allowed bolus increment
             insulinCalculated = apsManager.roundBolus(amount: insulinCalculated)
+            debug(.default, "Final rounded insulin: \(insulinCalculated)")
         }
 
         return CalculationResult(
@@ -452,17 +474,20 @@ final class BaseBolusCalculationManager: BolusCalculationManager, Injectable {
     ///   - carbs: Amount of carbohydrates to be consumed
     ///   - useFattyMealCorrection: Whether to apply fatty meal correction
     ///   - useSuperBolus: Whether to use super bolus calculation
+    ///   - minPredBG: Minimum Predicted Glucose determined by Oref
     /// - Returns: CalculationResult containing the calculated insulin dose and details
     func handleBolusCalculation(
         carbs: Decimal,
         useFattyMealCorrection: Bool,
-        useSuperBolus: Bool
+        useSuperBolus: Bool,
+        minPredBG: Decimal? = nil
     ) async -> CalculationResult {
         do {
             let input = try await prepareCalculationInput(
                 carbs: carbs,
                 useFattyMealCorrection: useFattyMealCorrection,
-                useSuperBolus: useSuperBolus
+                useSuperBolus: useSuperBolus,
+                minPredBG: minPredBG
             )
             let result = await calculateInsulin(input: input)
             return result

+ 2 - 1
Trio/Sources/Services/WatchManager/AppleWatchManager.swift

@@ -588,7 +588,8 @@ final class BaseWatchManager: NSObject, WCSessionDelegate, Injectable, WatchMana
                     let result = await bolusCalculationManager.handleBolusCalculation(
                         carbs: Decimal(carbs),
                         useFattyMealCorrection: false,
-                        useSuperBolus: false
+                        useSuperBolus: false,
+                        minPredBG: 60 // TODO:
                     )
 
                     // Send recommendation back to watch