|
|
@@ -60,7 +60,8 @@ import Testing
|
|
|
maxBolus: maxBolus,
|
|
|
maxIOB: maxIOB,
|
|
|
maxCOB: maxCOB,
|
|
|
- minPredBG: minPredBG
|
|
|
+ minPredBG: minPredBG,
|
|
|
+ lastLoopDate: Date()
|
|
|
)
|
|
|
|
|
|
// STEP 3: Calculate insulin
|
|
|
@@ -173,7 +174,8 @@ import Testing
|
|
|
maxBolus: maxBolus,
|
|
|
maxIOB: maxIOB,
|
|
|
maxCOB: maxCOB,
|
|
|
- minPredBG: minPredBG
|
|
|
+ minPredBG: minPredBG,
|
|
|
+ lastLoopDate: Date()
|
|
|
)
|
|
|
|
|
|
// STEP 3: Calculate insulin with fatty meal enabled
|
|
|
@@ -198,7 +200,8 @@ import Testing
|
|
|
maxBolus: maxBolus,
|
|
|
maxIOB: maxIOB,
|
|
|
maxCOB: maxCOB,
|
|
|
- minPredBG: minPredBG
|
|
|
+ minPredBG: minPredBG,
|
|
|
+ lastLoopDate: Date()
|
|
|
)
|
|
|
let standardResult = await calculator.calculateInsulin(input: standardInput)
|
|
|
|
|
|
@@ -262,7 +265,8 @@ import Testing
|
|
|
maxBolus: maxBolus,
|
|
|
maxIOB: maxIOB,
|
|
|
maxCOB: maxCOB,
|
|
|
- minPredBG: minPredBG
|
|
|
+ minPredBG: minPredBG,
|
|
|
+ lastLoopDate: Date()
|
|
|
)
|
|
|
|
|
|
// STEP 3: Calculate insulin with super bolus enabled
|
|
|
@@ -287,7 +291,8 @@ import Testing
|
|
|
maxBolus: maxBolus,
|
|
|
maxIOB: maxIOB,
|
|
|
maxCOB: maxCOB,
|
|
|
- minPredBG: minPredBG
|
|
|
+ minPredBG: minPredBG,
|
|
|
+ lastLoopDate: Date()
|
|
|
)
|
|
|
let standardResult = await calculator.calculateInsulin(input: standardInput)
|
|
|
|
|
|
@@ -330,6 +335,145 @@ import Testing
|
|
|
)
|
|
|
}
|
|
|
|
|
|
+ @Test("Calculate insulin with low glucose forecast (minPredBG < 54)") func testMinPredBGGuardBolusCalculation() async throws {
|
|
|
+ // STEP 1: Setup test scenario
|
|
|
+ // We need to provide a CalculationInput struct
|
|
|
+ let carbs: Decimal = 80
|
|
|
+ let currentBG: Decimal = 180 // 80 points above target, should result in 2U correction
|
|
|
+ let deltaBG: Decimal = 5 // Rising trend, should add small correction
|
|
|
+ let target: Decimal = 100
|
|
|
+ let isf: Decimal = 40
|
|
|
+ let carbRatio: Decimal = 10 // Should result in 8U for carbs
|
|
|
+ let iob: Decimal = 1.0 // Should subtract from final result
|
|
|
+ let cob: Int16 = 20
|
|
|
+ let useFattyMealCorrectionFactor: Bool = false
|
|
|
+ let useSuperBolus: Bool = false
|
|
|
+ let fattyMealFactor: Decimal = 0.8
|
|
|
+ let sweetMealFactor: Decimal = 2
|
|
|
+ let basal: Decimal = 1.5 // Will be added to insulin calculation when super bolus is enabled
|
|
|
+ let fraction: Decimal = 0.8
|
|
|
+ let maxBolus: Decimal = 10
|
|
|
+ let maxIOB: Decimal = 15.0
|
|
|
+ let maxCOB: Decimal = 120.0
|
|
|
+ let minPredBG: Decimal = 45.0 // Severe Hypo forecasted
|
|
|
+
|
|
|
+ // STEP 2: Create calculation input with severe hypo forecasted minPredBG
|
|
|
+ let input = CalculationInput(
|
|
|
+ carbs: carbs,
|
|
|
+ currentBG: currentBG,
|
|
|
+ deltaBG: deltaBG,
|
|
|
+ target: target,
|
|
|
+ isf: isf,
|
|
|
+ carbRatio: carbRatio,
|
|
|
+ iob: iob,
|
|
|
+ cob: cob,
|
|
|
+ useFattyMealCorrectionFactor: useFattyMealCorrectionFactor,
|
|
|
+ fattyMealFactor: fattyMealFactor,
|
|
|
+ useSuperBolus: useSuperBolus,
|
|
|
+ sweetMealFactor: sweetMealFactor,
|
|
|
+ basal: basal,
|
|
|
+ fraction: fraction,
|
|
|
+ maxBolus: maxBolus,
|
|
|
+ maxIOB: maxIOB,
|
|
|
+ maxCOB: maxCOB,
|
|
|
+ minPredBG: minPredBG,
|
|
|
+ lastLoopDate: Date()
|
|
|
+ )
|
|
|
+
|
|
|
+ // STEP 3: Calculate insulin with super bolus enabled
|
|
|
+ let minPredBGResult = await calculator.calculateInsulin(input: input)
|
|
|
+
|
|
|
+ // STEP 4: Calculate insulin with super bolus disabled for comparison
|
|
|
+ let standardInput = CalculationInput(
|
|
|
+ carbs: carbs,
|
|
|
+ currentBG: currentBG,
|
|
|
+ deltaBG: deltaBG,
|
|
|
+ target: target,
|
|
|
+ isf: isf,
|
|
|
+ carbRatio: carbRatio,
|
|
|
+ iob: iob,
|
|
|
+ cob: cob,
|
|
|
+ useFattyMealCorrectionFactor: useFattyMealCorrectionFactor,
|
|
|
+ fattyMealFactor: fattyMealFactor,
|
|
|
+ useSuperBolus: false, // Disabled for comparison
|
|
|
+ sweetMealFactor: sweetMealFactor,
|
|
|
+ basal: basal,
|
|
|
+ fraction: fraction,
|
|
|
+ maxBolus: maxBolus,
|
|
|
+ maxIOB: maxIOB,
|
|
|
+ maxCOB: maxCOB,
|
|
|
+ minPredBG: 80,
|
|
|
+ lastLoopDate: Date()
|
|
|
+ )
|
|
|
+ let standardResult = await calculator.calculateInsulin(input: standardInput)
|
|
|
+
|
|
|
+ // STEP 5: Verify results
|
|
|
+ #expect(minPredBGResult.insulinCalculated == 0, "Severe Hypo forecasted; insulin calculated set to 0 U for safety!")
|
|
|
+
|
|
|
+ #expect(
|
|
|
+ standardResult.insulinCalculated > minPredBGResult.insulinCalculated,
|
|
|
+ """
|
|
|
+ Super bolus calculation incorrect
|
|
|
+ Expected super bolus calculation to be higher than standard
|
|
|
+ MinPred <54 bolus: \(minPredBGResult.insulinCalculated) U
|
|
|
+ Standard: \(standardResult.insulinCalculated) U
|
|
|
+ Difference: \(standardResult.insulinCalculated - minPredBGResult.insulinCalculated) U
|
|
|
+ """
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test("Calculate insulin with stale loop (longer than 15min ago)") func testStaleLoopBolusCalculation() async throws {
|
|
|
+ // STEP 1: Setup test scenario
|
|
|
+ // We need to provide a CalculationInput struct
|
|
|
+ let carbs: Decimal = 80
|
|
|
+ let currentBG: Decimal = 180 // 80 points above target, should result in 2U correction
|
|
|
+ let deltaBG: Decimal = 5 // Rising trend, should add small correction
|
|
|
+ let target: Decimal = 100
|
|
|
+ let isf: Decimal = 40
|
|
|
+ let carbRatio: Decimal = 10 // Should result in 8U for carbs
|
|
|
+ let iob: Decimal = 1.0 // Should subtract from final result
|
|
|
+ let cob: Int16 = 20
|
|
|
+ let useFattyMealCorrectionFactor: Bool = false
|
|
|
+ let useSuperBolus: Bool = false
|
|
|
+ let fattyMealFactor: Decimal = 0.8
|
|
|
+ let sweetMealFactor: Decimal = 2
|
|
|
+ let basal: Decimal = 1.5 // Will be added to insulin calculation when super bolus is enabled
|
|
|
+ let fraction: Decimal = 0.8
|
|
|
+ let maxBolus: Decimal = 10
|
|
|
+ let maxIOB: Decimal = 15.0
|
|
|
+ let maxCOB: Decimal = 120.0
|
|
|
+ let minPredBG: Decimal = 80
|
|
|
+
|
|
|
+ // STEP 2: Create calculation input with severe hypo forecasted minPredBG
|
|
|
+ let input = CalculationInput(
|
|
|
+ carbs: carbs,
|
|
|
+ currentBG: currentBG,
|
|
|
+ deltaBG: deltaBG,
|
|
|
+ target: target,
|
|
|
+ isf: isf,
|
|
|
+ carbRatio: carbRatio,
|
|
|
+ iob: iob,
|
|
|
+ cob: cob,
|
|
|
+ useFattyMealCorrectionFactor: useFattyMealCorrectionFactor,
|
|
|
+ fattyMealFactor: fattyMealFactor,
|
|
|
+ useSuperBolus: useSuperBolus,
|
|
|
+ sweetMealFactor: sweetMealFactor,
|
|
|
+ basal: basal,
|
|
|
+ fraction: fraction,
|
|
|
+ maxBolus: maxBolus,
|
|
|
+ maxIOB: maxIOB,
|
|
|
+ maxCOB: maxCOB,
|
|
|
+ minPredBG: minPredBG,
|
|
|
+ lastLoopDate: Date().addingTimeInterval(TimeInterval(-15 * 60)) // 15min ago
|
|
|
+ )
|
|
|
+
|
|
|
+ // STEP 3: Calculate insulin with super bolus enabled
|
|
|
+ let result = await calculator.calculateInsulin(input: input)
|
|
|
+
|
|
|
+ // STEP 4: Verify results
|
|
|
+ #expect(result.insulinCalculated == 0, "Loop is stale; insulin calculated set to 0 U for safety!")
|
|
|
+ }
|
|
|
+
|
|
|
@Test("Calculate insulin with zero carbs") func testZeroCarbsCalculation() async throws {
|
|
|
// Given
|
|
|
let carbs: Decimal = 0
|
|
|
@@ -339,6 +483,7 @@ import Testing
|
|
|
carbs: carbs,
|
|
|
useFattyMealCorrection: false,
|
|
|
useSuperBolus: false,
|
|
|
+ lastLoopDate: Date(),
|
|
|
minPredBG: nil
|
|
|
)
|
|
|
|