From 48fa7eaee3ac44ec158783d7cb3b46e9949103f7 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Mon, 17 Apr 2017 19:39:53 -0500 Subject: [PATCH 1/3] do not forecast out beyond dia --- Loop/Managers/LoopDataManager.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Loop/Managers/LoopDataManager.swift b/Loop/Managers/LoopDataManager.swift index ccdebef422..57622a292d 100644 --- a/Loop/Managers/LoopDataManager.swift +++ b/Loop/Managers/LoopDataManager.swift @@ -383,6 +383,10 @@ final class LoopDataManager { throw LoopError.missingDataError(details: "Glucose data not available", recovery: "Check your CGM data source") } + guard let insulinActionDuration = self.doseStore.insulinActionDuration else { + throw LoopError.configurationError("Missing insulin action duration.") + } + if glucoseChange == nil { updateGroup.enter() glucoseStore.getRecentGlucoseChange { (values, error) in @@ -417,7 +421,7 @@ final class LoopDataManager { self.logger.addError(error, fromSource: "CarbStore") self.carbEffect = nil } else { - self.carbEffect = effects + self.carbEffect = effects.filterDateRange(effectStartDate, Date.init(timeIntervalSinceNow: insulinActionDuration)) } updateGroup.leave() From d047bc6c426b952303128ace904d715f0c7f7d97 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Thu, 20 Apr 2017 22:27:51 -0500 Subject: [PATCH 2/3] allow forecast to go beyond dia, but dosing decisions should only use eventual bg no further out than dia. --- Loop/Managers/DoseMath.swift | 12 ++++++++---- Loop/Managers/LoopDataManager.swift | 21 +++++++++++---------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/Loop/Managers/DoseMath.swift b/Loop/Managers/DoseMath.swift index cb224a271f..2bcda6c277 100644 --- a/Loop/Managers/DoseMath.swift +++ b/Loop/Managers/DoseMath.swift @@ -62,13 +62,15 @@ struct DoseMath { glucoseTargetRange: GlucoseRangeSchedule, insulinSensitivity: InsulinSensitivitySchedule, basalRateSchedule: BasalRateSchedule, - minimumBGGuard: GlucoseThreshold + minimumBGGuard: GlucoseThreshold, + insulinActionDuration: TimeInterval ) -> (rate: Double, duration: TimeInterval)? { guard glucose.count > 1 else { return nil } - let eventualGlucose = glucose.last! + let eventualGlucose = glucose.filter { $0.startDate < date.addingTimeInterval(insulinActionDuration) }.last! + let minGlucose = glucose.min { $0.quantity < $1.quantity }! let eventualGlucoseTargets = glucoseTargetRange.value(at: eventualGlucose.startDate) @@ -151,13 +153,15 @@ struct DoseMath { insulinSensitivity: InsulinSensitivitySchedule, basalRateSchedule: BasalRateSchedule, pendingInsulin: Double, - minimumBGGuard: GlucoseThreshold + minimumBGGuard: GlucoseThreshold, + insulinActionDuration: TimeInterval ) -> BolusRecommendation { guard glucose.count > 1 else { return BolusRecommendation(amount: 0, pendingInsulin: pendingInsulin) } - let eventualGlucose = glucose.last! + let eventualGlucose = glucose.filter { $0.startDate < date.addingTimeInterval(insulinActionDuration) }.last! + let minGlucose = glucose.min { $0.quantity < $1.quantity }! let eventualGlucoseTargets = glucoseTargetRange.value(at: eventualGlucose.startDate) diff --git a/Loop/Managers/LoopDataManager.swift b/Loop/Managers/LoopDataManager.swift index 57622a292d..e57e2d8f8d 100644 --- a/Loop/Managers/LoopDataManager.swift +++ b/Loop/Managers/LoopDataManager.swift @@ -383,10 +383,6 @@ final class LoopDataManager { throw LoopError.missingDataError(details: "Glucose data not available", recovery: "Check your CGM data source") } - guard let insulinActionDuration = self.doseStore.insulinActionDuration else { - throw LoopError.configurationError("Missing insulin action duration.") - } - if glucoseChange == nil { updateGroup.enter() glucoseStore.getRecentGlucoseChange { (values, error) in @@ -421,7 +417,7 @@ final class LoopDataManager { self.logger.addError(error, fromSource: "CarbStore") self.carbEffect = nil } else { - self.carbEffect = effects.filterDateRange(effectStartDate, Date.init(timeIntervalSinceNow: insulinActionDuration)) + self.carbEffect = effects } updateGroup.leave() @@ -794,7 +790,8 @@ final class LoopDataManager { maxBasal = settings.maximumBasalRatePerHour, let glucoseTargetRange = settings.glucoseTargetRangeSchedule, let insulinSensitivity = insulinSensitivitySchedule, - let basalRates = basalRateSchedule + let basalRates = basalRateSchedule, + let insulinActionDuration = insulinActionDuration else { error = LoopError.configurationError("Check settings") throw error! @@ -809,7 +806,8 @@ final class LoopDataManager { glucoseTargetRange: glucoseTargetRange, insulinSensitivity: insulinSensitivity, basalRateSchedule: basalRates, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) else { recommendedTempBasal = nil @@ -830,7 +828,8 @@ final class LoopDataManager { let maxBolus = settings.maximumBolus, let glucoseTargetRange = settings.glucoseTargetRangeSchedule, let insulinSensitivity = insulinSensitivitySchedule, - let basalRates = basalRateSchedule + let basalRates = basalRateSchedule, + let insulinActionDuration = insulinActionDuration else { throw LoopError.configurationError("Check Settings") } @@ -853,7 +852,8 @@ final class LoopDataManager { insulinSensitivity: insulinSensitivity, basalRateSchedule: basalRates, pendingInsulin: pendingInsulin, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) let recommendationWithoutMomentum = DoseMath.recommendBolusFromPredictedGlucose(glucoseWithoutMomentum, @@ -862,7 +862,8 @@ final class LoopDataManager { insulinSensitivity: insulinSensitivity, basalRateSchedule: basalRates, pendingInsulin: pendingInsulin, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) if recommendationWithMomentum.amount > recommendationWithoutMomentum.amount { From a0567c1af05406628e8d0e0b648a668017858b27 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Thu, 20 Apr 2017 23:25:37 -0500 Subject: [PATCH 3/3] Adding tests for bg rising past dia --- DoseMathTests/DoseMathTests.swift | 151 ++++++++++++++---- .../Fixtures/far_future_high_bg_forecast.json | 16 ++ ...end_temp_basal_very_low_end_in_range.json} | 0 Loop.xcodeproj/project.pbxproj | 12 +- Loop/Managers/DoseMath.swift | 4 +- 5 files changed, 142 insertions(+), 41 deletions(-) create mode 100644 DoseMathTests/Fixtures/far_future_high_bg_forecast.json rename DoseMathTests/Fixtures/{recommend_tamp_basal_very_low_end_in_range.json => recommend_temp_basal_very_low_end_in_range.json} (100%) diff --git a/DoseMathTests/DoseMathTests.swift b/DoseMathTests/DoseMathTests.swift index 80b62d6826..ea584a9ff1 100644 --- a/DoseMathTests/DoseMathTests.swift +++ b/DoseMathTests/DoseMathTests.swift @@ -92,6 +92,10 @@ class RecommendTempBasalTests: XCTestCase { return GlucoseThreshold(unit: HKUnit.milligramsPerDeciliterUnit(), value: 55) } + var insulinActionDuration: TimeInterval { + return TimeInterval(hours: 4) + } + func testNoChange() { let glucose = loadGlucoseValueFixture("recommend_temp_basal_no_change_glucose") @@ -102,7 +106,8 @@ class RecommendTempBasalTests: XCTestCase { glucoseTargetRange: glucoseTargetRange, insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertNil(dose) @@ -118,7 +123,8 @@ class RecommendTempBasalTests: XCTestCase { glucoseTargetRange: glucoseTargetRange, insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertNil(dose) @@ -139,7 +145,8 @@ class RecommendTempBasalTests: XCTestCase { glucoseTargetRange: glucoseTargetRange, insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertEqual(0, dose!.rate) @@ -156,7 +163,8 @@ class RecommendTempBasalTests: XCTestCase { glucoseTargetRange: glucoseTargetRange, insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertNil(dose) @@ -176,7 +184,8 @@ class RecommendTempBasalTests: XCTestCase { glucoseTargetRange: glucoseTargetRange, insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertEqual(0, dose!.rate) @@ -202,7 +211,8 @@ class RecommendTempBasalTests: XCTestCase { glucoseTargetRange: glucoseTargetRange, insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertEqual(0, dose!.rate) @@ -216,7 +226,8 @@ class RecommendTempBasalTests: XCTestCase { glucoseTargetRange: glucoseTargetRange, insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertNil(dose) @@ -236,7 +247,8 @@ class RecommendTempBasalTests: XCTestCase { glucoseTargetRange: glucoseTargetRange, insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertEqual(0, dose!.rate) @@ -253,7 +265,8 @@ class RecommendTempBasalTests: XCTestCase { glucoseTargetRange: glucoseTargetRange, insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertEqual(0, dose!.rate) @@ -271,7 +284,8 @@ class RecommendTempBasalTests: XCTestCase { glucoseTargetRange: glucoseTargetRange, insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertNil(dose) @@ -291,7 +305,8 @@ class RecommendTempBasalTests: XCTestCase { glucoseTargetRange: glucoseTargetRange, insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertEqual(0, dose!.rate) @@ -308,7 +323,8 @@ class RecommendTempBasalTests: XCTestCase { glucoseTargetRange: glucoseTargetRange, insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertEqual(3.0, dose!.rate) @@ -325,7 +341,8 @@ class RecommendTempBasalTests: XCTestCase { glucoseTargetRange: glucoseTargetRange, insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertEqualWithAccuracy(1.425, dose!.rate, accuracy: 1.0 / 40.0) @@ -342,7 +359,8 @@ class RecommendTempBasalTests: XCTestCase { glucoseTargetRange: glucoseTargetRange, insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertEqualWithAccuracy(1.475, dose!.rate, accuracy: 1.0 / 40.0) @@ -359,7 +377,8 @@ class RecommendTempBasalTests: XCTestCase { glucoseTargetRange: glucoseTargetRange, insulinSensitivity: self.insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertEqual(3.0, dose!.rate) @@ -375,7 +394,8 @@ class RecommendTempBasalTests: XCTestCase { glucoseTargetRange: glucoseTargetRange, insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertEqualWithAccuracy(2.975, dose!.rate, accuracy: 1.0 / 40.0) @@ -383,7 +403,7 @@ class RecommendTempBasalTests: XCTestCase { } func testVeryLowAndRising() { - let glucose = loadGlucoseValueFixture("recommend_tamp_basal_very_low_end_in_range") + let glucose = loadGlucoseValueFixture("recommend_temp_basal_very_low_end_in_range") let dose = DoseMath.recommendTempBasalFromPredictedGlucose(glucose, atDate: glucose.first!.startDate, @@ -392,13 +412,31 @@ class RecommendTempBasalTests: XCTestCase { glucoseTargetRange: glucoseTargetRange, insulinSensitivity: self.insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertEqual(0.0, dose!.rate) XCTAssertEqual(TimeInterval(minutes: 30), dose!.duration) } + func testRiseAfterDIA() { + let glucose = loadGlucoseValueFixture("far_future_high_bg_forecast") + + let dose = DoseMath.recommendTempBasalFromPredictedGlucose(glucose, + atDate: glucose.first!.startDate, + lastTempBasal: nil, + maxBasalRate: maxBasalRate, + glucoseTargetRange: glucoseTargetRange, + insulinSensitivity: self.insulinSensitivitySchedule, + basalRateSchedule: basalRateSchedule, + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration + ) + + XCTAssertNil(dose) + } + func testNoInputGlucose() { let dose = DoseMath.recommendTempBasalFromPredictedGlucose([], @@ -407,7 +445,8 @@ class RecommendTempBasalTests: XCTestCase { glucoseTargetRange: glucoseTargetRange, insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertNil(dose) @@ -457,6 +496,10 @@ class RecommendBolusTests: XCTestCase { return GlucoseThreshold(unit: HKUnit.milligramsPerDeciliterUnit(), value: 55) } + var insulinActionDuration: TimeInterval { + return TimeInterval(hours: 4) + } + func testNoChange() { let glucose = loadGlucoseValueFixture("recommend_temp_basal_no_change_glucose") @@ -467,7 +510,8 @@ class RecommendBolusTests: XCTestCase { insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, pendingInsulin: 0, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertEqual(0, dose.amount) @@ -483,7 +527,9 @@ class RecommendBolusTests: XCTestCase { insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, pendingInsulin: 0, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration + ) XCTAssertEqual(0, dose.amount) @@ -499,7 +545,9 @@ class RecommendBolusTests: XCTestCase { insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, pendingInsulin: 0, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration + ) XCTAssertEqual(0, dose.amount) @@ -515,7 +563,9 @@ class RecommendBolusTests: XCTestCase { insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, pendingInsulin: 0, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration + ) XCTAssertEqual(0, dose.amount) @@ -531,7 +581,9 @@ class RecommendBolusTests: XCTestCase { insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, pendingInsulin: 0, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration + ) XCTAssertEqual(1.325, dose.amount) @@ -556,7 +608,8 @@ class RecommendBolusTests: XCTestCase { insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, pendingInsulin: 0, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertEqual(1.325, dose.amount) @@ -574,7 +627,8 @@ class RecommendBolusTests: XCTestCase { insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, pendingInsulin: 1, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertEqual(0.325, dose.amount) @@ -590,7 +644,8 @@ class RecommendBolusTests: XCTestCase { insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, pendingInsulin: 0, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertEqual(0, dose.amount) @@ -606,7 +661,8 @@ class RecommendBolusTests: XCTestCase { insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, pendingInsulin: 0, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertEqualWithAccuracy(1.333, dose.amount, accuracy: 1.0 / 40.0) @@ -622,7 +678,8 @@ class RecommendBolusTests: XCTestCase { insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, pendingInsulin: 0, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertEqualWithAccuracy(0.067, dose.amount, accuracy: 1.0 / 40.0) @@ -638,7 +695,8 @@ class RecommendBolusTests: XCTestCase { insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, pendingInsulin: 0, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertEqualWithAccuracy(0.083, dose.amount, accuracy: 1.0 / 40.0) @@ -652,7 +710,8 @@ class RecommendBolusTests: XCTestCase { insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, pendingInsulin: 0.8, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertEqualWithAccuracy(0, dose.amount, accuracy: 1e-13) @@ -664,7 +723,8 @@ class RecommendBolusTests: XCTestCase { insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, pendingInsulin: 0, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertEqualWithAccuracy(0.083, dose.amount, accuracy: 1.0 / 40.0) @@ -680,7 +740,8 @@ class RecommendBolusTests: XCTestCase { insulinSensitivity: self.insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, pendingInsulin: 0, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertEqual(1.0, dose.amount) @@ -695,12 +756,31 @@ class RecommendBolusTests: XCTestCase { insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, pendingInsulin: 0, - minimumBGGuard: minimumBGGuard + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration ) XCTAssertEqualWithAccuracy(1.0, dose.amount, accuracy: 1.0 / 40.0) } + func testRiseAfterDIA() { + let glucose = loadGlucoseValueFixture("far_future_high_bg_forecast") + + let dose = DoseMath.recommendBolusFromPredictedGlucose(glucose, + atDate: glucose.first!.startDate, + maxBolus: maxBolus, + glucoseTargetRange: glucoseTargetRange, + insulinSensitivity: self.insulinSensitivitySchedule, + basalRateSchedule: basalRateSchedule, + pendingInsulin: 0, + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration + ) + + XCTAssertEqual(0.0, dose.amount) + } + + func testNoInputGlucose() { let dose = DoseMath.recommendBolusFromPredictedGlucose([], maxBolus: 4, @@ -708,7 +788,8 @@ class RecommendBolusTests: XCTestCase { insulinSensitivity: insulinSensitivitySchedule, basalRateSchedule: basalRateSchedule, pendingInsulin: 0, - minimumBGGuard: minimumBGGuard) + minimumBGGuard: minimumBGGuard, + insulinActionDuration: insulinActionDuration) XCTAssertEqual(0, dose.amount) } diff --git a/DoseMathTests/Fixtures/far_future_high_bg_forecast.json b/DoseMathTests/Fixtures/far_future_high_bg_forecast.json new file mode 100644 index 0000000000..27555e5d87 --- /dev/null +++ b/DoseMathTests/Fixtures/far_future_high_bg_forecast.json @@ -0,0 +1,16 @@ + [ + {"date": "2015-07-19T16:30:00", "amount": 90}, + {"date": "2015-07-19T17:00:00", "amount": 90}, + {"date": "2015-07-19T17:30:00", "amount": 90}, + {"date": "2015-07-19T18:00:00", "amount": 90}, + {"date": "2015-07-19T18:30:00", "amount": 95}, + {"date": "2015-07-19T19:00:00", "amount": 100}, + {"date": "2015-07-19T19:30:00", "amount": 105}, + {"date": "2015-07-19T20:00:00", "amount": 110}, + {"date": "2015-07-19T20:30:00", "amount": 115}, + {"date": "2015-07-19T21:00:00", "amount": 118}, + {"date": "2015-07-19T21:30:00", "amount": 120}, + {"date": "2015-07-19T21:30:00", "amount": 140}, + {"date": "2015-07-19T21:30:00", "amount": 160}, + {"date": "2015-07-19T21:30:00", "amount": 180} + ] diff --git a/DoseMathTests/Fixtures/recommend_tamp_basal_very_low_end_in_range.json b/DoseMathTests/Fixtures/recommend_temp_basal_very_low_end_in_range.json similarity index 100% rename from DoseMathTests/Fixtures/recommend_tamp_basal_very_low_end_in_range.json rename to DoseMathTests/Fixtures/recommend_temp_basal_very_low_end_in_range.json diff --git a/Loop.xcodeproj/project.pbxproj b/Loop.xcodeproj/project.pbxproj index c045be8ac9..55670b0036 100644 --- a/Loop.xcodeproj/project.pbxproj +++ b/Loop.xcodeproj/project.pbxproj @@ -216,9 +216,10 @@ 4FF4D1011E18375000846527 /* WatchContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FF4D0FF1E18374700846527 /* WatchContext.swift */; }; 540DED971E14C75F002B2491 /* EnliteSensorDisplayable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 540DED961E14C75F002B2491 /* EnliteSensorDisplayable.swift */; }; C10428971D17BAD400DD539A /* NightscoutUploadKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C10428961D17BAD400DD539A /* NightscoutUploadKit.framework */; }; + C10B28461EA9BA5E006EA1FC /* far_future_high_bg_forecast.json in Resources */ = {isa = PBXBuildFile; fileRef = C10B28451EA9BA5E006EA1FC /* far_future_high_bg_forecast.json */; }; C11C87DD1E21E53500BB71D3 /* GlucoseThreshold.swift in Sources */ = {isa = PBXBuildFile; fileRef = C178249D1E19B62300D9D25C /* GlucoseThreshold.swift */; }; C11C87DE1E21EAAD00BB71D3 /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F526D5E1DF2459000A04910 /* HKUnit.swift */; }; - C12F21A71DFA79CB00748193 /* recommend_tamp_basal_very_low_end_in_range.json in Resources */ = {isa = PBXBuildFile; fileRef = C12F21A61DFA79CB00748193 /* recommend_tamp_basal_very_low_end_in_range.json */; }; + C12F21A71DFA79CB00748193 /* recommend_temp_basal_very_low_end_in_range.json in Resources */ = {isa = PBXBuildFile; fileRef = C12F21A61DFA79CB00748193 /* recommend_temp_basal_very_low_end_in_range.json */; }; C13BAD941E8009B000050CB5 /* NumberFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43BFF0B31E45C1BE00FF19A9 /* NumberFormatter.swift */; }; C15713821DAC6983005BC4D2 /* MealBolusNightscoutTreatment.swift in Sources */ = {isa = PBXBuildFile; fileRef = C15713811DAC6983005BC4D2 /* MealBolusNightscoutTreatment.swift */; }; C178249A1E1999FA00D9D25C /* CaseCountable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C17824991E1999FA00D9D25C /* CaseCountable.swift */; }; @@ -540,7 +541,8 @@ 4FF4D0FF1E18374700846527 /* WatchContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WatchContext.swift; sourceTree = ""; }; 540DED961E14C75F002B2491 /* EnliteSensorDisplayable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnliteSensorDisplayable.swift; sourceTree = ""; }; C10428961D17BAD400DD539A /* NightscoutUploadKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NightscoutUploadKit.framework; path = Carthage/Build/iOS/NightscoutUploadKit.framework; sourceTree = ""; }; - C12F21A61DFA79CB00748193 /* recommend_tamp_basal_very_low_end_in_range.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = recommend_tamp_basal_very_low_end_in_range.json; sourceTree = ""; }; + C10B28451EA9BA5E006EA1FC /* far_future_high_bg_forecast.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = far_future_high_bg_forecast.json; sourceTree = ""; }; + C12F21A61DFA79CB00748193 /* recommend_temp_basal_very_low_end_in_range.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = recommend_temp_basal_very_low_end_in_range.json; sourceTree = ""; }; C15713811DAC6983005BC4D2 /* MealBolusNightscoutTreatment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MealBolusNightscoutTreatment.swift; sourceTree = ""; }; C17824991E1999FA00D9D25C /* CaseCountable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaseCountable.swift; sourceTree = ""; }; C178249D1E19B62300D9D25C /* GlucoseThreshold.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlucoseThreshold.swift; sourceTree = ""; }; @@ -811,9 +813,10 @@ 43E2D8E91D20C0DB004DA55F /* recommend_temp_basal_start_high_end_low.json */, 43E2D8EA1D20C0DB004DA55F /* recommend_temp_basal_start_low_end_high.json */, 43E2D8EB1D20C0DB004DA55F /* recommend_temp_basal_start_low_end_in_range.json */, - C12F21A61DFA79CB00748193 /* recommend_tamp_basal_very_low_end_in_range.json */, + C12F21A61DFA79CB00748193 /* recommend_temp_basal_very_low_end_in_range.json */, C17824A21E19EAB600D9D25C /* recommend_temp_basal_start_very_low_end_high.json */, C1C6591B1E1B1FDA0025CC58 /* recommend_temp_basal_dropping_then_rising.json */, + C10B28451EA9BA5E006EA1FC /* far_future_high_bg_forecast.json */, ); path = Fixtures; sourceTree = ""; @@ -1348,12 +1351,13 @@ 43E2D8EF1D20C0DB004DA55F /* recommend_temp_basal_high_and_falling.json in Resources */, 43E2D8ED1D20C0DB004DA55F /* recommend_temp_basal_correct_low_at_min.json in Resources */, 43E2D8F01D20C0DB004DA55F /* recommend_temp_basal_high_and_rising.json in Resources */, - C12F21A71DFA79CB00748193 /* recommend_tamp_basal_very_low_end_in_range.json in Resources */, + C12F21A71DFA79CB00748193 /* recommend_temp_basal_very_low_end_in_range.json in Resources */, 43E2D8F11D20C0DB004DA55F /* recommend_temp_basal_in_range_and_rising.json in Resources */, 43E2D8EE1D20C0DB004DA55F /* recommend_temp_basal_flat_and_high.json in Resources */, C1C6591C1E1B1FDA0025CC58 /* recommend_temp_basal_dropping_then_rising.json in Resources */, 43E2D8F31D20C0DB004DA55F /* recommend_temp_basal_start_high_end_in_range.json in Resources */, 43E2D8F51D20C0DB004DA55F /* recommend_temp_basal_start_low_end_high.json in Resources */, + C10B28461EA9BA5E006EA1FC /* far_future_high_bg_forecast.json in Resources */, 43E2D8EC1D20C0DB004DA55F /* read_selected_basal_profile.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Loop/Managers/DoseMath.swift b/Loop/Managers/DoseMath.swift index 2bcda6c277..1c146b4317 100644 --- a/Loop/Managers/DoseMath.swift +++ b/Loop/Managers/DoseMath.swift @@ -69,7 +69,7 @@ struct DoseMath { return nil } - let eventualGlucose = glucose.filter { $0.startDate < date.addingTimeInterval(insulinActionDuration) }.last! + let eventualGlucose = glucose.filter { $0.startDate <= date.addingTimeInterval(insulinActionDuration) }.last! let minGlucose = glucose.min { $0.quantity < $1.quantity }! @@ -160,7 +160,7 @@ struct DoseMath { return BolusRecommendation(amount: 0, pendingInsulin: pendingInsulin) } - let eventualGlucose = glucose.filter { $0.startDate < date.addingTimeInterval(insulinActionDuration) }.last! + let eventualGlucose = glucose.filter { $0.startDate <= date.addingTimeInterval(insulinActionDuration) }.last! let minGlucose = glucose.min { $0.quantity < $1.quantity }!