Skip to content

Commit 512f50d

Browse files
authored
Fix mmol unit conversion for missed meal detection (#1990)
* Fix unit handling for mmol/L users * Fix merge conflict
1 parent d7e107d commit 512f50d

File tree

2 files changed

+41
-12
lines changed

2 files changed

+41
-12
lines changed

Loop/Managers/Missed Meal Detection/MealDetectionManager.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ enum MissedMealStatus: Equatable {
1919

2020
class MealDetectionManager {
2121
private let log = OSLog(category: "MealDetectionManager")
22+
// All math for meal detection occurs in mg/dL, with settings being converted if in mmol/L
23+
private let unit = HKUnit.milligramsPerDeciliter
2224

2325
public var carbRatioScheduleApplyingOverrideHistory: CarbRatioSchedule?
2426
public var insulinSensitivityScheduleApplyingOverrideHistory: InsulinSensitivitySchedule?
@@ -76,7 +78,6 @@ class MealDetectionManager {
7678
/// Compute how much of the ICE effect we can't explain via our entered carbs
7779
/// Effect caching inspired by `LoopMath.predictGlucose`
7880
var effectValueCache: [Date: Double] = [:]
79-
let unit = HKUnit.milligramsPerDeciliter
8081

8182
/// Carb effects are cumulative, so we have to subtract the previous effect value
8283
var previousEffectValue: Double = filteredCarbEffects.first?.quantity.doubleValue(for: unit) ?? 0
@@ -195,7 +196,7 @@ class MealDetectionManager {
195196
private func effectThreshold(mealStart: Date, carbsInGrams: Double) -> Double? {
196197
guard
197198
let carbRatio = carbRatioScheduleApplyingOverrideHistory?.value(at: mealStart),
198-
let insulinSensitivity = insulinSensitivityScheduleApplyingOverrideHistory?.value(at: mealStart)
199+
let insulinSensitivity = insulinSensitivityScheduleApplyingOverrideHistory?.value(for: unit, at: mealStart)
199200
else {
200201
return nil
201202
}

LoopTests/Managers/MealDetectionManagerTests.swift

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ enum MissedMealTestType {
3333
case dynamicCarbAutofill
3434
/// Test case for purely testing the notifications (not the algorithm)
3535
case notificationTest
36+
/// Test case for testing the algorithm with settings in mmol/L
37+
case mmolUser
3638
}
3739

3840
extension MissedMealTestType {
@@ -48,7 +50,7 @@ extension MissedMealTestType {
4850
return "noisy_cgm_counteraction_effect"
4951
case .manyMeals, .missedMealWithCOB:
5052
return "realistic_report_counteraction_effect"
51-
case .dynamicCarbAutofill:
53+
case .dynamicCarbAutofill, .mmolUser:
5254
return "dynamic_autofill_counteraction_effect"
5355
}
5456
}
@@ -65,7 +67,7 @@ extension MissedMealTestType {
6567
return Self.dateFormatter.date(from: "2022-10-19T19:50:15")!
6668
case .manyMeals:
6769
return Self.dateFormatter.date(from: "2022-10-19T21:50:15")!
68-
case .dynamicCarbAutofill:
70+
case .dynamicCarbAutofill, .mmolUser:
6971
return Self.dateFormatter.date(from: "2022-10-17T07:51:09")!
7072
}
7173
}
@@ -78,7 +80,7 @@ extension MissedMealTestType {
7880
return Self.dateFormatter.date(from: "2022-10-19T19:00:00")
7981
case .manyMeals:
8082
return Self.dateFormatter.date(from: "2022-10-19T20:40:00 ")
81-
case .dynamicCarbAutofill:
83+
case .dynamicCarbAutofill, .mmolUser:
8284
return Self.dateFormatter.date(from: "2022-10-17T07:20:00")!
8385
default:
8486
return nil
@@ -136,13 +138,26 @@ extension MissedMealTestType {
136138
}
137139

138140
var insulinSensitivitySchedule: InsulinSensitivitySchedule {
139-
InsulinSensitivitySchedule(
140-
unit: HKUnit.milligramsPerDeciliter,
141-
dailyItems: [
142-
RepeatingScheduleValue(startTime: 0.0, value: 50.0)
143-
],
144-
timeZone: .utcTimeZone
145-
)!
141+
let value = 50.0
142+
switch self {
143+
case .mmolUser:
144+
return InsulinSensitivitySchedule(
145+
unit: HKUnit.millimolesPerLiter,
146+
dailyItems: [
147+
RepeatingScheduleValue(startTime: 0.0,
148+
value: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: value).doubleValue(for: .millimolesPerLiter))
149+
],
150+
timeZone: .utcTimeZone
151+
)!
152+
default:
153+
return InsulinSensitivitySchedule(
154+
unit: HKUnit.milligramsPerDeciliter,
155+
dailyItems: [
156+
RepeatingScheduleValue(startTime: 0.0, value: value)
157+
],
158+
timeZone: .utcTimeZone
159+
)!
160+
}
146161
}
147162
}
148163

@@ -335,6 +350,19 @@ class MealDetectionManagerTests: XCTestCase {
335350
updateGroup.wait()
336351
}
337352

353+
func testMMOLUser() {
354+
let testType = MissedMealTestType.mmolUser
355+
let counteractionEffects = setUp(for: testType)
356+
357+
let updateGroup = DispatchGroup()
358+
updateGroup.enter()
359+
mealDetectionManager.hasMissedMeal(insulinCounteractionEffects: counteractionEffects, carbEffects: mealDetectionCarbEffects(using: counteractionEffects)) { status in
360+
XCTAssertEqual(status, .hasMissedMeal(startTime: testType.missedMealDate!, carbAmount: 25))
361+
updateGroup.leave()
362+
}
363+
updateGroup.wait()
364+
}
365+
338366
// MARK: - Notification Tests
339367
func testNoMissedMealLastNotificationTime() {
340368
setUp(for: .notificationTest)

0 commit comments

Comments
 (0)