Skip to content

Commit

Permalink
Use LoopAlgorithm basal overlay for computing total delivery (#700)
Browse files Browse the repository at this point in the history
  • Loading branch information
ps2 authored Sep 11, 2024
1 parent d640b55 commit b6f2594
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 12 deletions.
37 changes: 33 additions & 4 deletions Loop/Managers/LoopDataManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -276,18 +276,27 @@ final class LoopDataManager: ObservableObject {

func fetchData(
for baseTime: Date = Date(),
disablingPreMeal: Bool = false
disablingPreMeal: Bool = false,
ensureDosingCoverageStart: Date? = nil
) async throws -> StoredDataAlgorithmInput {
// Need to fetch doses back as far as t - (DIA + DCA) for Dynamic carbs
let dosesInputHistory = CarbMath.maximumAbsorptionTimeInterval + InsulinMath.defaultInsulinActivityDuration

var dosesStart = baseTime.addingTimeInterval(-dosesInputHistory)

// Ensure dosing data goes back before ensureDosingCoverageStart, if specified
if let ensureDosingCoverageStart {
dosesStart = min(ensureDosingCoverageStart, dosesStart)
}

let doses = try await doseStore.getNormalizedDoseEntries(
start: dosesStart,
end: baseTime
)

dosesStart = doses.map { $0.startDate }.min() ?? dosesStart
// Doses that were included because they cover dosesStart might have a start time earlier than dosesStart
// This moves the start time back to ensure basal covers
dosesStart = min(dosesStart, doses.map { $0.startDate }.min() ?? dosesStart)

let basal = try await settingsProvider.getBasalHistory(startDate: dosesStart, endDate: baseTime)

Expand Down Expand Up @@ -411,7 +420,9 @@ final class LoopDataManager: ObservableObject {
func updateDisplayState() async {
var newState = AlgorithmDisplayState()
do {
var input = try await fetchData(for: now())
let midnight = Calendar.current.startOfDay(for: Date())

var input = try await fetchData(for: now(), ensureDosingCoverageStart: midnight)
input.recommendationType = .manualBolus
newState.input = input
newState.output = LoopAlgorithm.run(input: input)
Expand Down Expand Up @@ -598,6 +609,24 @@ final class LoopDataManager: ObservableObject {
}
}

public func totalDeliveredToday() async -> InsulinValue?
{
guard let data = displayState.input else {
return nil
}

let now = data.predictionStart
let midnight = Calendar.current.startOfDay(for: now)

let annotatedDoses = data.doses.annotated(with: data.basal, fillBasalGaps: true)
let trimmed = annotatedDoses.map { $0.trimmed(from: midnight, to: now)}

return InsulinValue(
startDate: midnight,
value: trimmed.reduce(0.0) { $0 + $1.volume }
)
}

var iobValues: [InsulinValue] {
dosesRelativeToBasal.insulinOnBoardTimeline()
}
Expand Down Expand Up @@ -1123,7 +1152,7 @@ extension LoopDataManager: SimpleBolusViewModelDelegate {

}

extension LoopDataManager: BolusEntryViewModelDelegate {
extension LoopDataManager: BolusEntryViewModelDelegate {
func saveGlucose(sample: LoopKit.NewGlucoseSample) async throws -> LoopKit.StoredGlucoseSample {
let storedSamples = try await addGlucose([sample])
return storedSamples.first!
Expand Down
2 changes: 0 additions & 2 deletions Loop/Managers/Store Protocols/DoseStoreProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ protocol DoseStoreProtocol: AnyObject {

var lastReservoirValue: ReservoirValue? { get }

func getTotalUnitsDelivered(since startDate: Date) async throws -> InsulinValue

var lastAddedPumpData: Date { get }
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,9 +320,7 @@ public final class InsulinDeliveryTableViewController: UITableViewController {
private func updateTotal() {
Task { @MainActor in
if case .display = state {
let midnight = Calendar.current.startOfDay(for: Date())

if let result = try? await doseStore?.getTotalUnitsDelivered(since: midnight) {
if let result = await loopDataManager.totalDeliveredToday() {
self.totalValueLabel.text = NumberFormatter.localizedString(from: NSNumber(value: result.value), number: .none)
self.totalDateLabel.text = String(format: NSLocalizedString("com.loudnate.InsulinKit.totalDateLabel", value: "since %1$@", comment: "The format string describing the starting date of a total value. The first format argument is the localized date."), DateFormatter.localizedString(from: result.startDate, dateStyle: .none, timeStyle: .short))
} else {
Expand Down
2 changes: 1 addition & 1 deletion Loop/View Controllers/StatusTableViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ final class StatusTableViewController: LoopChartsTableViewController {
doseEntries = loopManager.dosesRelativeToBasal.trimmed(from: startDate)

iobValues = loopManager.iobValues.filterDateRange(startDate, nil)
totalDelivery = try? await loopManager.doseStore.getTotalUnitsDelivered(since: Calendar.current.startOfDay(for: Date())).value
totalDelivery = await loopManager.totalDeliveredToday()?.value
}

updatePresetModeAvailability(automaticDosingEnabled: automaticDosingEnabled)
Expand Down
4 changes: 2 additions & 2 deletions Loop/View Models/BolusEntryViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ protocol BolusEntryViewModelDelegate: AnyObject {
var mostRecentGlucoseDataDate: Date? { get }
var mostRecentPumpDataDate: Date? { get }

func fetchData(for baseTime: Date, disablingPreMeal: Bool) async throws -> StoredDataAlgorithmInput
func fetchData(for baseTime: Date, disablingPreMeal: Bool, ensureDosingCoverageStart: Date?) async throws -> StoredDataAlgorithmInput
func effectiveGlucoseTargetRangeSchedule(presumingMealEntry: Bool) -> GlucoseRangeSchedule?

func addCarbEntry(_ carbEntry: NewCarbEntry, replacing replacingEntry: StoredCarbEntry?) async throws -> StoredCarbEntry
Expand Down Expand Up @@ -515,7 +515,7 @@ final class BolusEntryViewModel: ObservableObject {

do {
let startDate = now()
var input = try await delegate.fetchData(for: startDate, disablingPreMeal: potentialCarbEntry != nil)
var input = try await delegate.fetchData(for: startDate, disablingPreMeal: potentialCarbEntry != nil, ensureDosingCoverageStart: nil)

let insulinModel = delegate.insulinModel(for: deliveryDelegate?.pumpInsulinType)

Expand Down

0 comments on commit b6f2594

Please sign in to comment.