Skip to content

Commit a927001

Browse files
marionbarkerbjorkertps2
authored
Glucose Based Partial Application Factor (#1988)
* Add Dosing Strategy: automaticBolusSlidingScale * Reverse order of two new constants * revert to dev for dosing strategy selection * revert to dev for dosing strategy selection * Rename to effectiveBolusApplicationFactor, change to flag inside existing automaticBolus case * Add applyLinearRamp slider to Dosing Strategy * Update constants * Modify explanation seen by user * missed one phrase * Update explanation seen by user, modify font * Enable swapping of original and replacment protocols, minimize LoopKit changes * Restore to dev branch version prior to pr1988_update merge * Restore to dev branch version prior to update for PR 1988 * Updates per requested changes for Loop PR 1988 * Renaming, adjusting views, logging * Wording change * Logging error fixed * dead code * missed rename * dark mode fix * Updated algorithm experiments view and glucose based partial application view * Put algorithm experiments behind feature flag --------- Co-authored-by: Jonas Björkert <jonas@bjorkert.se> Co-authored-by: Pete Schwamb <pete@schwamb.net>
1 parent daca18f commit a927001

9 files changed

+283
-4
lines changed

Common/FeatureFlags.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ struct FeatureFlagConfiguration: Decodable {
3939
let adultChildInsulinModelSelectionEnabled: Bool
4040
let profileExpirationSettingsViewEnabled: Bool
4141
let missedMealNotifications: Bool
42+
let allowAlgorithmExperiments: Bool
4243

4344

4445
fileprivate init() {
@@ -229,6 +230,11 @@ struct FeatureFlagConfiguration: Decodable {
229230
self.missedMealNotifications = true
230231
#endif
231232

233+
#if ALLOW_ALGORITHM_EXPERIMENTS
234+
self.allowAlgorithmExperiments = true
235+
#else
236+
self.allowAlgorithmExperiments = false
237+
#endif
232238
}
233239
}
234240

@@ -263,7 +269,8 @@ extension FeatureFlagConfiguration : CustomDebugStringConvertible {
263269
"* dynamicCarbAbsorptionEnabled: \(dynamicCarbAbsorptionEnabled)",
264270
"* adultChildInsulinModelSelectionEnabled: \(adultChildInsulinModelSelectionEnabled)",
265271
"* profileExpirationSettingsViewEnabled: \(profileExpirationSettingsViewEnabled)",
266-
"* missedMealNotifications: \(missedMealNotifications)"
272+
"* missedMealNotifications: \(missedMealNotifications)",
273+
"* allowAlgorithmExperiments: \(allowAlgorithmExperiments)"
267274
].joined(separator: "\n")
268275
}
269276
}

Loop.xcodeproj/project.pbxproj

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,11 @@
518518
C1FB428D21791D2500FAB378 /* PumpManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C3B6F620BBCAA30026CAFA /* PumpManager.swift */; };
519519
C1FB428F217921D600FAB378 /* PumpManagerUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1FB428E217921D600FAB378 /* PumpManagerUI.swift */; };
520520
C1FB4290217922A100FAB378 /* PumpManagerUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1FB428E217921D600FAB378 /* PumpManagerUI.swift */; };
521+
DDC389F62A2B61750066E2E8 /* ApplicationFactorStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC389F52A2B61750066E2E8 /* ApplicationFactorStrategy.swift */; };
522+
DDC389F82A2B620B0066E2E8 /* GlucoseBasedApplicationFactorStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC389F72A2B620B0066E2E8 /* GlucoseBasedApplicationFactorStrategy.swift */; };
523+
DDC389FA2A2B62470066E2E8 /* ConstantApplicationFactorStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC389F92A2B62470066E2E8 /* ConstantApplicationFactorStrategy.swift */; };
524+
DDC389FC2A2BC6670066E2E8 /* SettingsView+algorithmExperimentsSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC389FB2A2BC6670066E2E8 /* SettingsView+algorithmExperimentsSection.swift */; };
525+
DDC389FE2A2C4C830066E2E8 /* GlucoseBasedApplicationFactorSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC389FD2A2C4C830066E2E8 /* GlucoseBasedApplicationFactorSelectionView.swift */; };
521526
E90909D124E34AC500F963D2 /* high_and_rising_with_cob_momentum_effect.json in Resources */ = {isa = PBXBuildFile; fileRef = E90909CC24E34AC500F963D2 /* high_and_rising_with_cob_momentum_effect.json */; };
522527
E90909D224E34AC500F963D2 /* high_and_rising_with_cob_insulin_effect.json in Resources */ = {isa = PBXBuildFile; fileRef = E90909CD24E34AC500F963D2 /* high_and_rising_with_cob_insulin_effect.json */; };
523528
E90909D324E34AC500F963D2 /* high_and_rising_with_cob_predicted_glucose.json in Resources */ = {isa = PBXBuildFile; fileRef = E90909CE24E34AC500F963D2 /* high_and_rising_with_cob_predicted_glucose.json */; };
@@ -1687,6 +1692,11 @@
16871692
C1FF3D4B29C786A900BDC1EC /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/Localizable.strings; sourceTree = "<group>"; };
16881693
C1FF3D4C29C786A900BDC1EC /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/Localizable.strings; sourceTree = "<group>"; };
16891694
C1FF3D4D29C786A900BDC1EC /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/InfoPlist.strings; sourceTree = "<group>"; };
1695+
DDC389F52A2B61750066E2E8 /* ApplicationFactorStrategy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationFactorStrategy.swift; sourceTree = "<group>"; };
1696+
DDC389F72A2B620B0066E2E8 /* GlucoseBasedApplicationFactorStrategy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseBasedApplicationFactorStrategy.swift; sourceTree = "<group>"; };
1697+
DDC389F92A2B62470066E2E8 /* ConstantApplicationFactorStrategy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConstantApplicationFactorStrategy.swift; sourceTree = "<group>"; };
1698+
DDC389FB2A2BC6670066E2E8 /* SettingsView+algorithmExperimentsSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SettingsView+algorithmExperimentsSection.swift"; sourceTree = "<group>"; };
1699+
DDC389FD2A2C4C830066E2E8 /* GlucoseBasedApplicationFactorSelectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseBasedApplicationFactorSelectionView.swift; sourceTree = "<group>"; };
16901700
E90909CC24E34AC500F963D2 /* high_and_rising_with_cob_momentum_effect.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = high_and_rising_with_cob_momentum_effect.json; sourceTree = "<group>"; };
16911701
E90909CD24E34AC500F963D2 /* high_and_rising_with_cob_insulin_effect.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = high_and_rising_with_cob_insulin_effect.json; sourceTree = "<group>"; };
16921702
E90909CE24E34AC500F963D2 /* high_and_rising_with_cob_predicted_glucose.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = high_and_rising_with_cob_predicted_glucose.json; sourceTree = "<group>"; };
@@ -2314,6 +2324,7 @@
23142324
isa = PBXGroup;
23152325
children = (
23162326
A98556842493F901000FD662 /* AlertStore+SimulatedCoreData.swift */,
2327+
DDC389FB2A2BC6670066E2E8 /* SettingsView+algorithmExperimentsSection.swift */,
23172328
C1D289B422F90A52003FFBD9 /* BasalDeliveryState.swift */,
23182329
A9F703722489BC8500C98AD8 /* CarbStore+SimulatedCoreData.swift */,
23192330
C17824991E1999FA00D9D25C /* CaseCountable.swift */,
@@ -2400,6 +2411,7 @@
24002411
43F64DD81D9C92C900D24DC6 /* TitleSubtitleTableViewCell.swift */,
24012412
4311FB9A1F37FE1B00D4C0A7 /* TitleSubtitleTextFieldTableViewCell.swift */,
24022413
C1AF062229426300002C1B19 /* ManualGlucoseEntryRow.swift */,
2414+
DDC389FD2A2C4C830066E2E8 /* GlucoseBasedApplicationFactorSelectionView.swift */,
24032415
);
24042416
path = Views;
24052417
sourceTree = "<group>";
@@ -2441,6 +2453,9 @@
24412453
C1F2075B26D6F9B0007AB7EB /* ProfileExpirationAlerter.swift */,
24422454
A96DAC2B2838F31200D94E38 /* SharedLogging.swift */,
24432455
7E69CFFB2A16A77E00203CBD /* ResetLoopManager.swift */,
2456+
DDC389F52A2B61750066E2E8 /* ApplicationFactorStrategy.swift */,
2457+
DDC389F72A2B620B0066E2E8 /* GlucoseBasedApplicationFactorStrategy.swift */,
2458+
DDC389F92A2B62470066E2E8 /* ConstantApplicationFactorStrategy.swift */,
24442459
);
24452460
path = Managers;
24462461
sourceTree = "<group>";
@@ -3872,6 +3887,7 @@
38723887
C1201E2C23ECDBD0002DA84A /* WatchContextRequestUserInfo.swift in Sources */,
38733888
1D49795824E7289700948F05 /* ServicesViewModel.swift in Sources */,
38743889
1D4A3E2D2478628500FD601B /* StoredAlert+CoreDataClass.swift in Sources */,
3890+
DDC389FA2A2B62470066E2E8 /* ConstantApplicationFactorStrategy.swift in Sources */,
38753891
892D7C5123B54A15008A9656 /* CarbEntryViewController.swift in Sources */,
38763892
B4E202302661063E009421B5 /* AutomaticDosingStatus.swift in Sources */,
38773893
C191D2A125B3ACAA00C26C0B /* DosingStrategySelectionView.swift in Sources */,
@@ -3903,6 +3919,7 @@
39033919
1DB619AC270BAD3D006C9D07 /* VersionUpdateViewModel.swift in Sources */,
39043920
A9C62D882331703100535612 /* Service.swift in Sources */,
39053921
89CAB36324C8FE96009EE3CE /* PredictedGlucoseChartView.swift in Sources */,
3922+
DDC389F82A2B620B0066E2E8 /* GlucoseBasedApplicationFactorStrategy.swift in Sources */,
39063923
4F6663941E905FD2009E74FC /* ChartColorPalette+Loop.swift in Sources */,
39073924
A9F703732489BC8500C98AD8 /* CarbStore+SimulatedCoreData.swift in Sources */,
39083925
4328E0351CFC0AE100E199AA /* WatchDataManager.swift in Sources */,
@@ -3933,6 +3950,7 @@
39333950
E9B080B1253BDA6300BAD8F8 /* UserDefaults+LoopIntents.swift in Sources */,
39343951
C1AF062329426300002C1B19 /* ManualGlucoseEntryRow.swift in Sources */,
39353952
C148CEE724FD91BD00711B3B /* DeliveryUncertaintyAlertManager.swift in Sources */,
3953+
DDC389FC2A2BC6670066E2E8 /* SettingsView+algorithmExperimentsSection.swift in Sources */,
39363954
1D12D3B92548EFDD00B53E8B /* main.swift in Sources */,
39373955
435400341C9F878D00D5819C /* SetBolusUserInfo.swift in Sources */,
39383956
A9DCF32A25B0FABF00C89088 /* LoopUIColorPalette+Default.swift in Sources */,
@@ -3967,13 +3985,15 @@
39673985
A97F250825E056D500F0EE19 /* OnboardingManager.swift in Sources */,
39683986
438D42F91D7C88BC003244B0 /* PredictionInputEffect.swift in Sources */,
39693987
892A5D692230C41D008961AB /* RangeReplaceableCollection.swift in Sources */,
3988+
DDC389F62A2B61750066E2E8 /* ApplicationFactorStrategy.swift in Sources */,
39703989
4F70C2101DE8FAC5006380B7 /* ExtensionDataManager.swift in Sources */,
39713990
43DFB62320D4CAE7008A7BAE /* PumpManager.swift in Sources */,
39723991
A9FB75F1252BE320004C7D3F /* BolusDosingDecision.swift in Sources */,
39733992
892A5D59222F0A27008961AB /* Debug.swift in Sources */,
39743993
431A8C401EC6E8AB00823B9C /* CircleMaskView.swift in Sources */,
39753994
1D05219D2469F1F5000EBBDE /* AlertStore.swift in Sources */,
39763995
439897371CD2F80600223065 /* AnalyticsServicesManager.swift in Sources */,
3996+
DDC389FE2A2C4C830066E2E8 /* GlucoseBasedApplicationFactorSelectionView.swift in Sources */,
39773997
A9C62D842331700E00535612 /* DiagnosticLog+Subsystem.swift in Sources */,
39783998
895FE0952201234000FCF18A /* OverrideSelectionViewController.swift in Sources */,
39793999
C1EF747228D6A44A00C8C083 /* CrashRecoveryManager.swift in Sources */,
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//
2+
// SettingsView+algorithmExperimentsSection.swift
3+
// Loop
4+
//
5+
// Created by Jonas Björkert on 2023-06-03.
6+
// Copyright © 2023 LoopKit Authors. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import SwiftUI
11+
import LoopKit
12+
import LoopKitUI
13+
14+
extension SettingsView {
15+
internal var algorithmExperimentsSection: some View {
16+
NavigationLink(NSLocalizedString("Algorithm Experiments", comment: "The title of the Algorithm Experiments section in settings")) {
17+
ExperimentsSettingsView(automaticDosingStrategy: viewModel.automaticDosingStrategy)
18+
}
19+
}
20+
}
21+
22+
public struct ExperimentRow: View {
23+
var name: String
24+
var enabled: Bool
25+
26+
public var body: some View {
27+
HStack {
28+
Text(name)
29+
.foregroundColor(.primary)
30+
Spacer()
31+
Text(enabled ? "On" : "Off")
32+
.foregroundColor(enabled ? .red : .secondary)
33+
}
34+
}
35+
}
36+
37+
public struct ExperimentsSettingsView: View {
38+
@State private var isGlucoseBasedApplicationFactorEnabled = UserDefaults.standard.glucoseBasedApplicationFactorEnabled
39+
var automaticDosingStrategy: AutomaticDosingStrategy
40+
41+
public var body: some View {
42+
VStack(alignment: .center, spacing: 12) {
43+
VStack {
44+
Text("⚠️").font(.largeTitle)
45+
Text("Caution")
46+
}
47+
Divider()
48+
VStack(alignment: .leading, spacing: 12) {
49+
Text(NSLocalizedString("Algorithm Experiments are optional modifications to the Loop Algorithm. These modifications are less tested than the standard Loop algorithm, so please use carefully.", comment: "Algorithm Experiments description."))
50+
Text(NSLocalizedString("In future versions of Loop these experiments may change, end up as standard parts of the Loop Algorithm, or be removed from Loop entirely. Please follow along in the Loop Zulip chat to stay informed of possible changes to these features.", comment: "Algorithm Experiments description second paragraph."))
51+
}
52+
.foregroundColor(.secondary)
53+
54+
Divider()
55+
NavigationLink(destination: GlucoseBasedApplicationFactorSelectionView(isGlucoseBasedApplicationFactorEnabled: $isGlucoseBasedApplicationFactorEnabled, automaticDosingStrategy: automaticDosingStrategy)) {
56+
ExperimentRow(name: "Glucose Based Partial Application", enabled: isGlucoseBasedApplicationFactorEnabled && automaticDosingStrategy == .automaticBolus)
57+
}
58+
.padding()
59+
.background(Color(UIColor.secondarySystemBackground))
60+
.foregroundColor(.accentColor)
61+
.cornerRadius(10)
62+
Spacer()
63+
}
64+
.padding()
65+
.navigationTitle(NSLocalizedString("Algorithm Experiments", comment: "Navigation title for algorithms experiments screen"))
66+
}
67+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//
2+
// ApplicationFactorStrategy.swift
3+
// Loop
4+
//
5+
// Created by Jonas Björkert on 2023-06-03.
6+
// Copyright © 2023 LoopKit Authors. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import HealthKit
11+
import LoopKit
12+
import LoopCore
13+
14+
protocol ApplicationFactorStrategy {
15+
func calculateDosingFactor(
16+
for glucose: HKQuantity,
17+
correctionRangeSchedule: GlucoseRangeSchedule,
18+
settings: LoopSettings
19+
) -> Double
20+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//
2+
// ConstantDosingStrategy.swift
3+
// Loop
4+
//
5+
// Created by Jonas Björkert on 2023-06-03.
6+
// Copyright © 2023 LoopKit Authors. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import HealthKit
11+
import LoopKit
12+
import LoopCore
13+
14+
struct ConstantApplicationFactorStrategy: ApplicationFactorStrategy {
15+
func calculateDosingFactor(
16+
for glucose: HKQuantity,
17+
correctionRangeSchedule: GlucoseRangeSchedule,
18+
settings: LoopSettings
19+
) -> Double {
20+
// The original strategy uses a constant dosing factor.
21+
return LoopConstants.bolusPartialApplicationFactor
22+
}
23+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//
2+
// GlucoseBasedApplicationFactorStrategy.swift
3+
// Loop
4+
//
5+
// Created by Jonas Björkert on 2023-06-03.
6+
// Copyright © 2023 LoopKit Authors. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import HealthKit
11+
import LoopKit
12+
import LoopCore
13+
14+
struct GlucoseBasedApplicationFactorStrategy: ApplicationFactorStrategy {
15+
static let minPartialApplicationFactor = 0.20 // min fraction of correction when glucose > minGlucoseSlidingScale
16+
static let maxPartialApplicationFactor = 0.80 // max fraction of correction when glucose > maxGlucoseSlidingScale
17+
// set minGlucoseSlidingScale based on user setting for correction range
18+
// use mg/dL for calculations
19+
static let minGlucoseDeltaSlidingScale = 10.0 // mg/dL
20+
static let maxGlucoseSlidingScale = 200.0 // mg/dL
21+
22+
func calculateDosingFactor(
23+
for glucose: HKQuantity,
24+
correctionRangeSchedule: GlucoseRangeSchedule,
25+
settings: LoopSettings
26+
) -> Double {
27+
// Calculate current glucose and lower bound target
28+
let currentGlucose = glucose.doubleValue(for: .milligramsPerDeciliter)
29+
let correctionRange = correctionRangeSchedule.quantityRange(at: Date())
30+
let lowerBoundTarget = correctionRange.lowerBound.doubleValue(for: .milligramsPerDeciliter)
31+
32+
// Calculate minimum glucose sliding scale and scaling fraction
33+
let minGlucoseSlidingScale = GlucoseBasedApplicationFactorStrategy.minGlucoseDeltaSlidingScale + lowerBoundTarget
34+
let scalingFraction = (GlucoseBasedApplicationFactorStrategy.maxPartialApplicationFactor - GlucoseBasedApplicationFactorStrategy.minPartialApplicationFactor) / (GlucoseBasedApplicationFactorStrategy.maxGlucoseSlidingScale - minGlucoseSlidingScale)
35+
let scalingGlucose = max(currentGlucose - minGlucoseSlidingScale, 0.0)
36+
37+
// Calculate effectiveBolusApplicationFactor
38+
let effectiveBolusApplicationFactor = min(GlucoseBasedApplicationFactorStrategy.minPartialApplicationFactor + scalingGlucose * scalingFraction, GlucoseBasedApplicationFactorStrategy.maxPartialApplicationFactor)
39+
40+
return effectiveBolusApplicationFactor
41+
}
42+
}
43+
44+
extension UserDefaults {
45+
private enum Key: String {
46+
case GlucoseBasedApplicationFactorEnabled = "com.loopkit.algorithmExperiments.glucoseBasedApplicationFactorEnabled"
47+
}
48+
49+
var glucoseBasedApplicationFactorEnabled: Bool {
50+
get {
51+
bool(forKey: Key.GlucoseBasedApplicationFactorEnabled.rawValue) as Bool
52+
}
53+
set {
54+
set(newValue, forKey: Key.GlucoseBasedApplicationFactorEnabled.rawValue)
55+
}
56+
}
57+
}

Loop/Managers/LoopDataManager.swift

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1698,7 +1698,23 @@ extension LoopDataManager {
16981698
return self.delegate?.roundBolusVolume(units: units) ?? units
16991699
}
17001700

1701-
let maxAutomaticBolus = min(iobHeadroom, maxBolus! * LoopConstants.bolusPartialApplicationFactor)
1701+
// Create dosing strategy based on user setting
1702+
let applicationFactorStrategy: ApplicationFactorStrategy = UserDefaults.standard.glucoseBasedApplicationFactorEnabled
1703+
? GlucoseBasedApplicationFactorStrategy()
1704+
: ConstantApplicationFactorStrategy()
1705+
1706+
let correctionRangeSchedule = settings.effectiveGlucoseTargetRangeSchedule()
1707+
1708+
let effectiveBolusApplicationFactor = applicationFactorStrategy.calculateDosingFactor(
1709+
for: glucose.quantity,
1710+
correctionRangeSchedule: correctionRangeSchedule!,
1711+
settings: settings
1712+
)
1713+
1714+
self.logger.debug(" *** Glucose: %{public}@, effectiveBolusApplicationFactor: %.2f", glucose.quantity.description, effectiveBolusApplicationFactor)
1715+
1716+
// If a user customizes maxPartialApplicationFactor > 1; this respects maxBolus
1717+
let maxAutomaticBolus = min(iobHeadroom, maxBolus! * min(effectiveBolusApplicationFactor, 1.0))
17021718

17031719
dosingRecommendation = predictedGlucose.recommendedAutomaticDose(
17041720
to: glucoseTargetRange!,
@@ -1708,7 +1724,7 @@ extension LoopDataManager {
17081724
model: doseStore.insulinModelProvider.model(for: pumpInsulinType),
17091725
basalRates: basalRateSchedule!,
17101726
maxAutomaticBolus: maxAutomaticBolus,
1711-
partialApplicationFactor: LoopConstants.bolusPartialApplicationFactor * self.timeBasedDoseApplicationFactor,
1727+
partialApplicationFactor: effectiveBolusApplicationFactor * self.timeBasedDoseApplicationFactor,
17121728
lastTempBasal: lastTempBasal,
17131729
volumeRounder: volumeRounder,
17141730
rateRounder: rateRounder,
@@ -2128,6 +2144,7 @@ extension LoopDataManager {
21282144
"insulinOnBoard: \(String(describing: manager.insulinOnBoard))",
21292145
"error: \(String(describing: state.error))",
21302146
"overrideInUserDefaults: \(String(describing: UserDefaults.appGroup?.intentExtensionOverrideToSet))",
2147+
"glucoseBasedApplicationFactorEnabled: \(UserDefaults.standard.glucoseBasedApplicationFactorEnabled)",
21312148
"",
21322149
String(reflecting: self.retrospectiveCorrection),
21332150
"",

0 commit comments

Comments
 (0)