Преглед изворни кода

Refactor storePumpEvents func

polscm32 пре 1 година
родитељ
комит
32f00d764e

+ 10 - 0
Model/CoreDataStack.swift

@@ -46,6 +46,16 @@ class CoreDataStack: ObservableObject {
         CoreDataStack(inMemory: true)
     }
 
+    // Used for Canvas Preview
+    static var preview: CoreDataStack = {
+        let stack = CoreDataStack(inMemory: true)
+        let context = stack.persistentContainer.viewContext
+
+        let pumpHistory = PumpEventStored.makePreviewEvents(count: 10, provider: stack)
+
+        return stack
+    }()
+
     /// A persistent container to set up the Core Data Stack
     lazy var persistentContainer: NSPersistentContainer = {
         let container = NSPersistentContainer(name: "TrioCoreDataPersistentContainer")

+ 16 - 0
Model/Helper/PumpEvent+helper.swift

@@ -12,6 +12,22 @@ extension PumpEventStored {
         }
         return request
     }
+
+    // Preview
+    @discardableResult static func makePreviewEvents(count: Int, provider: CoreDataStack) -> [PumpEventStored] {
+        let context = provider.persistentContainer.viewContext
+        let events = (0 ..< count).map { index -> PumpEventStored in
+            let event = PumpEventStored(context: context)
+            event.timestamp = Date.now.addingTimeInterval(Double(index) * 60)
+            event.type = "Mock Data"
+//            event.amount = 1.0
+//            event.isExternal = false
+//            event.isSMB = false
+//            event.duration = 0
+            return event
+        }
+        return events
+    }
 }
 
 public extension PumpEventStored {

+ 122 - 158
Trio/Sources/APS/Storage/PumpHistoryStorage.swift

@@ -49,164 +49,7 @@ final class BasePumpHistoryStorage: PumpHistoryStorage, Injectable {
     func storePumpEvents(_ events: [NewPumpEvent]) async {
         await context.perform {
             for event in events {
-                let existingEvents: [PumpEventStored] = CoreDataStack.shared.fetchEntities(
-                    ofType: PumpEventStored.self,
-                    onContext: self.context,
-                    predicate: NSPredicate.duplicateInLastHour(event.date),
-                    key: "timestamp",
-                    ascending: false,
-                    batchSize: 50
-                ) as? [PumpEventStored] ?? []
-
-                switch event.type {
-                case .bolus:
-
-                    guard let dose = event.dose else { continue }
-                    let amount = self.roundDose(
-                        dose.unitsInDeliverableIncrements,
-                        toIncrement: Double(self.settings.preferences.bolusIncrement)
-                    )
-
-                    guard existingEvents.isEmpty else {
-                        // Duplicate found, do not store the event
-                        print("Duplicate event found with timestamp: \(event.date)")
-
-                        if let existingEvent = existingEvents.first(where: { $0.type == EventType.bolus.rawValue }) {
-                            if existingEvent.timestamp == event.date {
-                                if let existingAmount = existingEvent.bolus?.amount, amount < existingAmount as Decimal {
-                                    // Update existing event with new smaller value
-                                    existingEvent.bolus?.amount = amount as NSDecimalNumber
-                                    existingEvent.bolus?.isSMB = dose.automatic ?? true
-                                    existingEvent.isUploadedToNS = false
-                                    existingEvent.isUploadedToHealth = false
-                                    existingEvent.isUploadedToTidepool = false
-
-                                    print("Updated existing event with smaller value: \(amount)")
-                                }
-                            }
-                        }
-                        continue
-                    }
-
-                    let newPumpEvent = PumpEventStored(context: self.context)
-                    newPumpEvent.id = UUID().uuidString
-                    newPumpEvent.timestamp = event.date
-                    newPumpEvent.type = PumpEvent.bolus.rawValue
-                    newPumpEvent.isUploadedToNS = false
-                    newPumpEvent.isUploadedToHealth = false
-                    newPumpEvent.isUploadedToTidepool = false
-
-                    let newBolusEntry = BolusStored(context: self.context)
-                    newBolusEntry.pumpEvent = newPumpEvent
-                    newBolusEntry.amount = NSDecimalNumber(decimal: amount)
-                    newBolusEntry.isExternal = dose.manuallyEntered
-                    newBolusEntry.isSMB = dose.automatic ?? true
-
-                case .tempBasal:
-                    guard let dose = event.dose else { continue }
-
-                    guard existingEvents.isEmpty else {
-                        // Duplicate found, do not store the event
-                        print("Duplicate event found with timestamp: \(event.date)")
-                        continue
-                    }
-
-                    let rate = Decimal(dose.unitsPerHour)
-                    let minutes = (dose.endDate - dose.startDate).timeInterval / 60
-                    let delivered = dose.deliveredUnits
-                    let date = event.date
-
-                    let isCancel = delivered != nil
-                    guard !isCancel else { continue }
-
-                    let newPumpEvent = PumpEventStored(context: self.context)
-                    newPumpEvent.id = UUID().uuidString
-                    newPumpEvent.timestamp = date
-                    newPumpEvent.type = PumpEvent.tempBasal.rawValue
-                    newPumpEvent.isUploadedToNS = false
-                    newPumpEvent.isUploadedToHealth = false
-                    newPumpEvent.isUploadedToTidepool = false
-
-                    let newTempBasal = TempBasalStored(context: self.context)
-                    newTempBasal.pumpEvent = newPumpEvent
-                    newTempBasal.duration = Int16(round(minutes))
-                    newTempBasal.rate = rate as NSDecimalNumber
-                    newTempBasal.tempType = TempType.absolute.rawValue
-
-                case .suspend:
-                    guard existingEvents.isEmpty else {
-                        // Duplicate found, do not store the event
-                        print("Duplicate event found with timestamp: \(event.date)")
-                        continue
-                    }
-                    let newPumpEvent = PumpEventStored(context: self.context)
-                    newPumpEvent.id = UUID().uuidString
-                    newPumpEvent.timestamp = event.date
-                    newPumpEvent.type = PumpEvent.pumpSuspend.rawValue
-                    newPumpEvent.isUploadedToNS = false
-                    newPumpEvent.isUploadedToHealth = false
-                    newPumpEvent.isUploadedToTidepool = false
-
-                case .resume:
-                    guard existingEvents.isEmpty else {
-                        // Duplicate found, do not store the event
-                        print("Duplicate event found with timestamp: \(event.date)")
-                        continue
-                    }
-                    let newPumpEvent = PumpEventStored(context: self.context)
-                    newPumpEvent.id = UUID().uuidString
-                    newPumpEvent.timestamp = event.date
-                    newPumpEvent.type = PumpEvent.pumpResume.rawValue
-                    newPumpEvent.isUploadedToNS = false
-                    newPumpEvent.isUploadedToHealth = false
-                    newPumpEvent.isUploadedToTidepool = false
-
-                case .rewind:
-                    guard existingEvents.isEmpty else {
-                        // Duplicate found, do not store the event
-                        print("Duplicate event found with timestamp: \(event.date)")
-                        continue
-                    }
-                    let newPumpEvent = PumpEventStored(context: self.context)
-                    newPumpEvent.id = UUID().uuidString
-                    newPumpEvent.timestamp = event.date
-                    newPumpEvent.type = PumpEvent.rewind.rawValue
-                    newPumpEvent.isUploadedToNS = false
-                    newPumpEvent.isUploadedToHealth = false
-                    newPumpEvent.isUploadedToTidepool = false
-
-                case .prime:
-                    guard existingEvents.isEmpty else {
-                        // Duplicate found, do not store the event
-                        print("Duplicate event found with timestamp: \(event.date)")
-                        continue
-                    }
-                    let newPumpEvent = PumpEventStored(context: self.context)
-                    newPumpEvent.id = UUID().uuidString
-                    newPumpEvent.timestamp = event.date
-                    newPumpEvent.type = PumpEvent.prime.rawValue
-                    newPumpEvent.isUploadedToNS = false
-                    newPumpEvent.isUploadedToHealth = false
-                    newPumpEvent.isUploadedToTidepool = false
-
-                case .alarm:
-                    guard existingEvents.isEmpty else {
-                        // Duplicate found, do not store the event
-                        print("Duplicate event found with timestamp: \(event.date)")
-                        continue
-                    }
-                    let newPumpEvent = PumpEventStored(context: self.context)
-                    newPumpEvent.id = UUID().uuidString
-                    newPumpEvent.timestamp = event.date
-                    newPumpEvent.type = PumpEvent.pumpAlarm.rawValue
-                    newPumpEvent.isUploadedToNS = false
-                    newPumpEvent.isUploadedToHealth = false
-                    newPumpEvent.isUploadedToTidepool = false
-                    newPumpEvent.note = event.title
-
-                default:
-                    continue
-                }
+                self.createPumpEvent(event)
             }
 
             do {
@@ -221,6 +64,127 @@ final class BasePumpHistoryStorage: PumpHistoryStorage, Injectable {
         }
     }
 
+    private func createPumpEvent(_ event: NewPumpEvent) {
+        // Check for duplicates
+        let existingEvents = findExistingEvents(for: event.date)
+
+        // for bolus events, update if there is a duplicate
+        if event.type == .bolus {
+            if handleExistingBolusEvent(event, existingEvents: existingEvents) {
+                return
+            }
+            // for all other events, do not save if there is a duplicate
+        } else if !existingEvents.isEmpty {
+            return
+        }
+
+        // If there is no duplicate or no bolus update necessary, create new event
+        let pumpEvent = PumpEventStored(context: context)
+        pumpEvent.id = UUID().uuidString
+        pumpEvent.timestamp = event.date
+        pumpEvent.isUploadedToNS = false
+        pumpEvent.isUploadedToHealth = false
+        pumpEvent.isUploadedToTidepool = false
+
+        switch event.type {
+        case .bolus:
+            createBolusEvent(event, pumpEvent: pumpEvent)
+            pumpEvent.type = PumpEvent.bolus.rawValue
+        case .tempBasal:
+            createTempBasalEvent(event, pumpEvent: pumpEvent)
+            pumpEvent.type = PumpEvent.tempBasal.rawValue
+        case .suspend:
+            pumpEvent.type = PumpEvent.pumpSuspend.rawValue
+        case .resume:
+            pumpEvent.type = PumpEvent.pumpResume.rawValue
+        case .rewind:
+            pumpEvent.type = PumpEvent.rewind.rawValue
+        case .prime:
+            pumpEvent.type = PumpEvent.prime.rawValue
+        case .alarm:
+            pumpEvent.type = PumpEvent.pumpAlarm.rawValue
+            pumpEvent.note = event.title
+        default:
+            return
+        }
+    }
+
+    private func findExistingEvents(for date: Date) -> [PumpEventStored] {
+        CoreDataStack.shared.fetchEntities(
+            ofType: PumpEventStored.self,
+            onContext: context,
+            predicate: NSPredicate.duplicateInLastHour(date),
+            key: "timestamp",
+            ascending: false,
+            batchSize: 50
+        ) as? [PumpEventStored] ?? []
+    }
+
+    private func handleExistingBolusEvent(_ event: NewPumpEvent, existingEvents: [PumpEventStored]) -> Bool {
+        guard let dose = event.dose,
+              let existingEvent = existingEvents.first(where: { $0.type == EventType.bolus.rawValue })
+        else {
+            return false
+        }
+
+        let amount = roundDose(
+            dose.unitsInDeliverableIncrements,
+            toIncrement: Double(settings.preferences.bolusIncrement)
+        )
+
+        guard let existingAmount = existingEvent.bolus?.amount else {
+            return false
+        }
+
+        // if the amount is the same, do not save again
+        if amount == existingAmount as Decimal {
+            return true
+        }
+
+        // if the new amount is smaller, update the existing event
+        if amount < existingAmount as Decimal {
+            existingEvent.bolus?.amount = amount as NSDecimalNumber
+            existingEvent.bolus?.isSMB = dose.automatic ?? true
+            existingEvent.isUploadedToNS = false
+            existingEvent.isUploadedToHealth = false
+            existingEvent.isUploadedToTidepool = false
+            return true
+        }
+
+        return false
+    }
+
+    private func createTempBasalEvent(_ event: NewPumpEvent, pumpEvent: PumpEventStored) {
+        guard let dose = event.dose else { return }
+
+        let rate = Decimal(dose.unitsPerHour)
+        let minutes = (dose.endDate - dose.startDate).timeInterval / 60
+
+        let isCancel = dose.deliveredUnits != nil
+        guard !isCancel else { return }
+
+        let tempBasal = TempBasalStored(context: context)
+        tempBasal.rate = rate as NSDecimalNumber
+        tempBasal.duration = Int16(round(minutes))
+        tempBasal.tempType = TempType.absolute.rawValue
+        tempBasal.pumpEvent = pumpEvent
+    }
+
+    private func createBolusEvent(_ event: NewPumpEvent, pumpEvent: PumpEventStored) {
+        guard let dose = event.dose else { return }
+
+        let amount = roundDose(
+            dose.unitsInDeliverableIncrements,
+            toIncrement: Double(settings.preferences.bolusIncrement)
+        )
+
+        let bolus = BolusStored(context: context)
+        bolus.amount = NSDecimalNumber(decimal: amount)
+        bolus.isExternal = dose.manuallyEntered
+        bolus.isSMB = dose.automatic ?? true
+        bolus.pumpEvent = pumpEvent
+    }
+
     func storeExternalInsulinEvent(amount: Decimal, timestamp: Date) async {
         debug(.default, "External insulin saved")
         await context.perform {