@@ -1127,12 +1127,111 @@ extension LoopDataManager: CarbEntryViewModelDelegate {
11271127 var defaultAbsorptionTimes : DefaultAbsorptionTimes {
11281128 LoopCoreConstants . defaultCarbAbsorptionTimes
11291129 }
1130-
11311130 func getGlucoseSamples( start: Date ? , end: Date ? ) async throws -> [ StoredGlucoseSample ] {
11321131 try await glucoseStore. getGlucoseSamples ( start: start, end: end)
11331132 }
11341133}
11351134
1135+ extension LoopDataManager : FavoriteFoodInsightsViewModelDelegate {
1136+ func selectedFavoriteFoodLastEaten( _ favoriteFood: StoredFavoriteFood ) async throws -> Date ? {
1137+ try await carbStore. getCarbEntries ( start: nil , end: nil , dateAscending: false , fetchLimit: 1 , with: favoriteFood. id) . first? . startDate
1138+ }
1139+
1140+
1141+ func getFavoriteFoodCarbEntries( _ favoriteFood: StoredFavoriteFood ) async throws -> [ LoopKit . StoredCarbEntry ] {
1142+ try await carbStore. getCarbEntries ( start: nil , end: nil , dateAscending: false , fetchLimit: nil , with: favoriteFood. id)
1143+ }
1144+
1145+ func getHistoricalChartsData( start: Date , end: Date ) async throws -> HistoricalChartsData {
1146+ // Need to get insulin data from any active doses that might affect this time range
1147+ var dosesStart = start. addingTimeInterval ( - InsulinMath. defaultInsulinActivityDuration)
1148+ let doses = try await doseStore. getNormalizedDoseEntries (
1149+ start: dosesStart,
1150+ end: end
1151+ ) . map { $0. simpleDose ( with: insulinModel ( for: $0. insulinType) ) }
1152+
1153+ dosesStart = doses. map { $0. startDate } . min ( ) ?? dosesStart
1154+
1155+ let basal = try await settingsProvider. getBasalHistory ( startDate: dosesStart, endDate: end)
1156+
1157+ let carbEntries = try await carbStore. getCarbEntries ( start: start, end: end)
1158+
1159+ let carbRatio = try await settingsProvider. getCarbRatioHistory ( startDate: start, endDate: end)
1160+
1161+ let glucose = try await glucoseStore. getGlucoseSamples ( start: start, end: end)
1162+
1163+ let sensitivityStart = min ( start, dosesStart)
1164+
1165+ let sensitivity = try await settingsProvider. getInsulinSensitivityHistory ( startDate: sensitivityStart, endDate: end)
1166+
1167+ let overrides = temporaryPresetsManager. overrideHistory. getOverrideHistory ( startDate: sensitivityStart, endDate: end)
1168+
1169+ guard !sensitivity. isEmpty else {
1170+ throw LoopError . configurationError ( . insulinSensitivitySchedule)
1171+ }
1172+
1173+ let sensitivityWithOverrides = overrides. applySensitivity ( over: sensitivity)
1174+
1175+ guard !basal. isEmpty else {
1176+ throw LoopError . configurationError ( . basalRateSchedule)
1177+ }
1178+ let basalWithOverrides = overrides. applyBasal ( over: basal)
1179+
1180+ guard !carbRatio. isEmpty else {
1181+ throw LoopError . configurationError ( . carbRatioSchedule)
1182+ }
1183+ let carbRatioWithOverrides = overrides. applyCarbRatio ( over: carbRatio)
1184+
1185+ let carbModel : CarbAbsorptionModel = FeatureFlags . nonlinearCarbModelEnabled ? . piecewiseLinear : . linear
1186+
1187+ // Overlay basal history on basal doses, splitting doses to get amount delivered relative to basal
1188+ let annotatedDoses = doses. annotated ( with: basalWithOverrides)
1189+
1190+ let insulinEffects = annotatedDoses. glucoseEffects (
1191+ insulinSensitivityHistory: sensitivityWithOverrides,
1192+ from: start. addingTimeInterval ( - CarbMath. maximumAbsorptionTimeInterval) . dateFlooredToTimeInterval ( GlucoseMath . defaultDelta) ,
1193+ to: nil )
1194+
1195+ // ICE
1196+ let insulinCounteractionEffects = glucose. counteractionEffects ( to: insulinEffects)
1197+
1198+ // Carb Effects
1199+ let carbStatus = carbEntries. map (
1200+ to: insulinCounteractionEffects,
1201+ carbRatio: carbRatioWithOverrides,
1202+ insulinSensitivity: sensitivityWithOverrides
1203+ )
1204+
1205+ let carbEffects = carbStatus. dynamicGlucoseEffects (
1206+ from: end,
1207+ to: end. addingTimeInterval ( InsulinMath . defaultInsulinActivityDuration) ,
1208+ carbRatios: carbRatioWithOverrides,
1209+ insulinSensitivities: sensitivityWithOverrides,
1210+ absorptionModel: carbModel. model
1211+ )
1212+
1213+ let carbAbsorptionReview = CarbAbsorptionReview (
1214+ carbEntries: carbEntries,
1215+ carbStatuses: carbStatus,
1216+ effectsVelocities: insulinCounteractionEffects,
1217+ carbEffects: carbEffects
1218+ )
1219+
1220+ let trimmedDoses = annotatedDoses. filterDateRange ( start, end)
1221+ let trimmedIOBValues = annotatedDoses. insulinOnBoardTimeline ( ) . filterDateRange ( start, end)
1222+
1223+ let historicalChartsData = HistoricalChartsData (
1224+ glucoseValues: glucose,
1225+ carbEntries: carbEntries,
1226+ doses: trimmedDoses,
1227+ iobValues: trimmedIOBValues,
1228+ carbAbsorptionReview: carbAbsorptionReview
1229+ )
1230+
1231+ return historicalChartsData
1232+ }
1233+ }
1234+
11361235extension LoopDataManager : ManualDoseViewModelDelegate {
11371236 var pumpInsulinType : InsulinType ? {
11381237 deliveryDelegate? . pumpInsulinType
0 commit comments