| 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 {
- func setupBolusStats() {
- Task {
- let stats = await fetchBolusStats()
- await MainActor.run {
- self.bolusStats = stats
- }
- }
- }
- /// Fetches and processes bolus statistics for a specific date range
- /// - Returns: Array of BolusStats containing daily bolus statistics
- func fetchBolusStats() async -> [BolusStats] {
- let calendar = Calendar.current
- // Fetch bolus records from Core Data
- let results = await CoreDataStack.shared.fetchEntitiesAsync(
- ofType: BolusStored.self,
- onContext: bolusTaskContext,
- predicate: NSPredicate.pumpHistoryForStats,
- key: "pumpEvent.timestamp",
- ascending: true,
- batchSize: 100
- )
- return await bolusTaskContext.perform {
- guard let fetchedResults = results as? [BolusStored] else { return [] }
- // Group boluses by day
- let groupedByDay = Dictionary(grouping: fetchedResults) { bolus -> Date in
- guard let timestamp = bolus.pumpEvent?.timestamp else { return Date() }
- return calendar.startOfDay(for: timestamp)
- }
- // Calculate daily totals
- return groupedByDay.map { date, boluses -> BolusStats in
- // Calculate total manual boluses (excluding SMB and external)
- let manualBolus = boluses
- .filter { !($0.isExternal || $0.isSMB) }
- .reduce(0.0) { $0 + (($1.amount as? Decimal) ?? 0).doubleValue }
- // Calculate total SMB
- let smb = boluses
- .filter { $0.isSMB }
- .reduce(0.0) { $0 + (($1.amount as? Decimal) ?? 0).doubleValue }
- // Calculate total external boluses
- let external = boluses
- .filter { $0.isExternal }
- .reduce(0.0) { $0 + (($1.amount as? Decimal) ?? 0).doubleValue }
- return BolusStats(
- date: date,
- manualBolus: manualBolus,
- smb: smb,
- external: external
- )
- }
- }
- }
- func calculateAverageBolus(from startDate: Date, to endDate: Date) -> (manual: Double, smb: Double, external: Double) {
- let visibleStats = bolusStats.filter { stat in
- stat.date >= startDate && stat.date <= endDate
- }
- guard !visibleStats.isEmpty else { return (0, 0, 0) }
- let count = Double(visibleStats.count)
- let manualSum = visibleStats.reduce(0.0) { $0 + $1.manualBolus }
- let smbSum = visibleStats.reduce(0.0) { $0 + $1.smb }
- let externalSum = visibleStats.reduce(0.0) { $0 + $1.external }
- return (
- manualSum / count,
- smbSum / count,
- externalSum / count
- )
- }
- }
- /// Extension to convert Decimal to Double
- private extension Decimal {
- var doubleValue: Double {
- NSDecimalNumber(decimal: self).doubleValue
- }
- }
|