| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- import CoreData
- import Foundation
- /// Represents statistical data about bolus insulin delivery for a specific day
- struct BolusStats: Identifiable {
- let id = UUID()
- /// The date representing this time period
- let date: Date
- /// Total amount of manual boluses (excluding SMB and external)
- let manualBolus: Double
- /// Total amount of Super Micro Boluses (SMB)
- let smb: Double
- /// Total amount of external boluses (e.g., from pump directly)
- let external: Double
- }
- extension Stat.StateModel {
- /// Updates the bolus statistics for the currently selected time period
- func updateBolusStats() {
- Task {
- let stats = await fetchBolusStats(days: requestedDaysTDD, endDate: requestedEndDayTDD)
- await MainActor.run {
- self.bolusStats = stats
- }
- }
- }
- /// Fetches and processes bolus statistics for a specific date range
- /// - Parameters:
- /// - days: Number of days to fetch
- /// - endDate: The end date of the range
- /// - Returns: Array of BolusStats containing daily bolus statistics
- func fetchBolusStats(days: Int, endDate: Date) async -> [BolusStats] {
- let calendar = Calendar.current
- let endDate = calendar.startOfDay(for: endDate)
- let startDate = calendar.date(byAdding: .day, value: -(days - 1), to: endDate)!
- // Fetch bolus records from Core Data
- let results = await CoreDataStack.shared.fetchEntitiesAsync(
- ofType: BolusStored.self,
- onContext: bolusTaskContext,
- predicate: NSPredicate(
- format: "pumpEvent.timestamp >= %@ AND pumpEvent.timestamp < %@",
- startDate as NSDate,
- calendar.date(byAdding: .day, value: 1, to: endDate)! as NSDate
- ),
- key: "pumpEvent.timestamp",
- ascending: false,
- batchSize: 100
- )
- return await bolusTaskContext.perform {
- guard let fetchedResults = results as? [BolusStored] else { return [] }
- // Group entries by day
- let groupedEntries = Dictionary(grouping: fetchedResults) { entry in
- calendar.startOfDay(for: entry.pumpEvent?.timestamp ?? Date())
- }
- // Create array of all dates in the range
- var dates: [Date] = []
- var currentDate = startDate
- while currentDate <= endDate {
- dates.append(calendar.startOfDay(for: currentDate))
- currentDate = calendar.date(byAdding: .day, value: 1, to: currentDate)!
- }
- // Calculate statistics for each day
- return dates.map { date in
- let dayEntries = groupedEntries[date, default: []]
- // Calculate total manual boluses (excluding SMB and external)
- let manualBolus = dayEntries
- .filter { !($0.isExternal || $0.isSMB) }
- .reduce(0.0) { $0 + (($1.amount as? Decimal) ?? 0).doubleValue }
- // Calculate total SMB
- let smb = dayEntries
- .filter { $0.isSMB }
- .reduce(0.0) { $0 + (($1.amount as? Decimal) ?? 0).doubleValue }
- // Calculate total external boluses
- let external = dayEntries
- .filter { $0.isExternal }
- .reduce(0.0) { $0 + (($1.amount as? Decimal) ?? 0).doubleValue }
- return BolusStats(
- date: date,
- manualBolus: manualBolus,
- smb: smb,
- external: external
- )
- }.sorted { $0.date < $1.date }
- }
- }
- }
- /// Extension to convert Decimal to Double
- private extension Decimal {
- var doubleValue: Double {
- NSDecimalNumber(decimal: self).doubleValue
- }
- }
|