@@ -276,18 +276,27 @@ final class LoopDataManager: ObservableObject {
276
276
277
277
func fetchData(
278
278
for baseTime: Date = Date ( ) ,
279
- disablingPreMeal: Bool = false
279
+ disablingPreMeal: Bool = false ,
280
+ ensureDosingCoverageStart: Date ? = nil
280
281
) async throws -> StoredDataAlgorithmInput {
281
282
// Need to fetch doses back as far as t - (DIA + DCA) for Dynamic carbs
282
283
let dosesInputHistory = CarbMath . maximumAbsorptionTimeInterval + InsulinMath. defaultInsulinActivityDuration
283
284
284
285
var dosesStart = baseTime. addingTimeInterval ( - dosesInputHistory)
286
+
287
+ // Ensure dosing data goes back before ensureDosingCoverageStart, if specified
288
+ if let ensureDosingCoverageStart {
289
+ dosesStart = min ( ensureDosingCoverageStart, dosesStart)
290
+ }
291
+
285
292
let doses = try await doseStore. getNormalizedDoseEntries (
286
293
start: dosesStart,
287
294
end: baseTime
288
295
)
289
296
290
- dosesStart = doses. map { $0. startDate } . min ( ) ?? dosesStart
297
+ // Doses that were included because they cover dosesStart might have a start time earlier than dosesStart
298
+ // This moves the start time back to ensure basal covers
299
+ dosesStart = min ( dosesStart, doses. map { $0. startDate } . min ( ) ?? dosesStart)
291
300
292
301
let basal = try await settingsProvider. getBasalHistory ( startDate: dosesStart, endDate: baseTime)
293
302
@@ -411,7 +420,9 @@ final class LoopDataManager: ObservableObject {
411
420
func updateDisplayState( ) async {
412
421
var newState = AlgorithmDisplayState ( )
413
422
do {
414
- var input = try await fetchData ( for: now ( ) )
423
+ let midnight = Calendar . current. startOfDay ( for: Date ( ) )
424
+
425
+ var input = try await fetchData ( for: now ( ) , ensureDosingCoverageStart: midnight)
415
426
input. recommendationType = . manualBolus
416
427
newState. input = input
417
428
newState. output = LoopAlgorithm . run ( input: input)
@@ -598,6 +609,24 @@ final class LoopDataManager: ObservableObject {
598
609
}
599
610
}
600
611
612
+ public func totalDeliveredToday( ) async -> InsulinValue ?
613
+ {
614
+ guard let data = displayState. input else {
615
+ return nil
616
+ }
617
+
618
+ let now = data. predictionStart
619
+ let midnight = Calendar . current. startOfDay ( for: now)
620
+
621
+ let annotatedDoses = data. doses. annotated ( with: data. basal, fillBasalGaps: true )
622
+ let trimmed = annotatedDoses. map { $0. trimmed ( from: midnight, to: now) }
623
+
624
+ return InsulinValue (
625
+ startDate: midnight,
626
+ value: trimmed. reduce ( 0.0 ) { $0 + $1. volume }
627
+ )
628
+ }
629
+
601
630
var iobValues : [ InsulinValue ] {
602
631
dosesRelativeToBasal. insulinOnBoardTimeline ( )
603
632
}
@@ -1123,7 +1152,7 @@ extension LoopDataManager: SimpleBolusViewModelDelegate {
1123
1152
1124
1153
}
1125
1154
1126
- extension LoopDataManager : BolusEntryViewModelDelegate {
1155
+ extension LoopDataManager : BolusEntryViewModelDelegate {
1127
1156
func saveGlucose( sample: LoopKit . NewGlucoseSample ) async throws -> LoopKit . StoredGlucoseSample {
1128
1157
let storedSamples = try await addGlucose ( [ sample] )
1129
1158
return storedSamples. first!
0 commit comments