@@ -23,7 +23,21 @@ public struct LoopSettings: Equatable {
2323
2424 public var overridePresets : [ TemporaryScheduleOverridePreset ] = [ ]
2525
26- public var scheduleOverride : TemporaryScheduleOverride ?
26+ public var scheduleOverride : TemporaryScheduleOverride ? {
27+ didSet {
28+ if let newValue = scheduleOverride, newValue. context == . preMeal {
29+ preconditionFailure ( " The `scheduleOverride` field should not be used for a pre-meal target range override; use `preMealOverride` instead " )
30+ }
31+ }
32+ }
33+
34+ public var preMealOverride : TemporaryScheduleOverride ? {
35+ didSet {
36+ if let newValue = preMealOverride, newValue. context != . preMeal || newValue. settings. insulinNeedsScaleFactor != nil {
37+ preconditionFailure ( " The `preMealOverride` field should be used only for a pre-meal target range override " )
38+ }
39+ }
40+ }
2741
2842 public var maximumBasalRatePerHour : Double ?
2943
@@ -106,26 +120,37 @@ public struct LoopSettings: Equatable {
106120
107121extension LoopSettings {
108122 public var glucoseTargetRangeScheduleApplyingOverrideIfActive : GlucoseRangeSchedule ? {
109- if let override = scheduleOverride, override. isActive ( ) {
110- return glucoseTargetRangeSchedule? . applyingOverride ( override)
123+ let currentEffectiveOverride : TemporaryScheduleOverride ?
124+ switch ( preMealOverride, scheduleOverride) {
125+ case ( let preMealOverride? , nil ) :
126+ currentEffectiveOverride = preMealOverride
127+ case ( nil , let scheduleOverride? ) :
128+ currentEffectiveOverride = scheduleOverride
129+ case ( let preMealOverride? , let scheduleOverride? ) :
130+ currentEffectiveOverride = preMealOverride. endDate > Date ( )
131+ ? preMealOverride
132+ : scheduleOverride
133+ case ( nil , nil ) :
134+ currentEffectiveOverride = nil
135+ }
136+
137+ if let effectiveOverride = currentEffectiveOverride {
138+ return glucoseTargetRangeSchedule? . applyingOverride ( effectiveOverride)
111139 } else {
112140 return glucoseTargetRangeSchedule
113141 }
114142 }
115143
116144 public func scheduleOverrideEnabled( at date: Date = Date ( ) ) -> Bool {
117- guard let override = scheduleOverride else { return false }
118- return override. isActive ( at: date)
145+ return scheduleOverride? . isActive ( at: date) == true
119146 }
120147
121148 public func nonPreMealOverrideEnabled( at date: Date = Date ( ) ) -> Bool {
122- guard let override = scheduleOverride else { return false }
123- return override. context != . preMeal && override. isActive ( at: date)
149+ return scheduleOverride? . isActive ( at: date) == true
124150 }
125151
126152 public func preMealTargetEnabled( at date: Date = Date ( ) ) -> Bool {
127- guard let override = scheduleOverride else { return false }
128- return override. context == . preMeal && override. isActive ( at: date)
153+ return preMealOverride? . isActive ( at: date) == true
129154 }
130155
131156 public func futureOverrideEnabled( relativeTo date: Date = Date ( ) ) -> Bool {
@@ -134,16 +159,16 @@ extension LoopSettings {
134159 }
135160
136161 public mutating func enablePreMealOverride( at date: Date = Date ( ) , for duration: TimeInterval ) {
137- scheduleOverride = preMealOverride ( beginningAt: date, for: duration)
162+ preMealOverride = makePreMealOverride ( beginningAt: date, for: duration)
138163 }
139164
140- public func preMealOverride ( beginningAt date: Date = Date ( ) , for duration: TimeInterval ) -> TemporaryScheduleOverride ? {
141- guard let premealTargetRange = preMealTargetRange, let unit = glucoseUnit else {
165+ private func makePreMealOverride ( beginningAt date: Date = Date ( ) , for duration: TimeInterval ) -> TemporaryScheduleOverride ? {
166+ guard let preMealTargetRange = preMealTargetRange, let unit = glucoseUnit else {
142167 return nil
143168 }
144169 return TemporaryScheduleOverride (
145170 context: . preMeal,
146- settings: TemporaryScheduleOverrideSettings ( unit: unit, targetRange: premealTargetRange ) ,
171+ settings: TemporaryScheduleOverrideSettings ( unit: unit, targetRange: preMealTargetRange ) ,
147172 startDate: date,
148173 duration: . finite( duration) ,
149174 enactTrigger: . local,
@@ -153,6 +178,7 @@ extension LoopSettings {
153178
154179 public mutating func enableLegacyWorkoutOverride( at date: Date = Date ( ) , for duration: TimeInterval ) {
155180 scheduleOverride = legacyWorkoutOverride ( beginningAt: date, for: duration)
181+ preMealOverride = nil
156182 }
157183
158184 public func legacyWorkoutOverride( beginningAt date: Date = Date ( ) , for duration: TimeInterval ) -> TemporaryScheduleOverride ? {
@@ -170,6 +196,11 @@ extension LoopSettings {
170196 }
171197
172198 public mutating func clearOverride( matching context: TemporaryScheduleOverride . Context ? = nil ) {
199+ if context == . preMeal {
200+ preMealOverride = nil
201+ return
202+ }
203+
173204 guard let override = scheduleOverride else { return }
174205 if let context = context {
175206 if override. context == context {
@@ -223,6 +254,10 @@ extension LoopSettings: RawRepresentable {
223254 self . overridePresets = rawPresets. compactMap ( TemporaryScheduleOverridePreset . init ( rawValue: ) )
224255 }
225256
257+ if let rawPreMealOverride = rawValue [ " preMealOverride " ] as? TemporaryScheduleOverride . RawValue {
258+ self . preMealOverride = TemporaryScheduleOverride ( rawValue: rawPreMealOverride)
259+ }
260+
226261 if let rawOverride = rawValue [ " scheduleOverride " ] as? TemporaryScheduleOverride . RawValue {
227262 self . scheduleOverride = TemporaryScheduleOverride ( rawValue: rawOverride)
228263 }
@@ -246,6 +281,7 @@ extension LoopSettings: RawRepresentable {
246281 raw [ " glucoseTargetRangeSchedule " ] = glucoseTargetRangeSchedule? . rawValue
247282 raw [ " preMealTargetRange " ] = preMealTargetRange? . rawValue
248283 raw [ " legacyWorkoutTargetRange " ] = legacyWorkoutTargetRange? . rawValue
284+ raw [ " preMealOverride " ] = preMealOverride? . rawValue
249285 raw [ " scheduleOverride " ] = scheduleOverride? . rawValue
250286 raw [ " maximumBasalRatePerHour " ] = maximumBasalRatePerHour
251287 raw [ " maximumBolus " ] = maximumBolus
0 commit comments