Просмотр исходного кода

remove readings entity, use new glucose entity where necessary

polscm32 2 лет назад
Родитель
Сommit
d50da16d1e

+ 1 - 2
FreeAPS/Sources/APS/APSManager.swift

@@ -765,8 +765,7 @@ final class BaseAPSManager: APSManager, Injectable {
         return Double(sorted[length / 2])
     }
 
-    private func tir(_ array: [GlucoseStored]) -> (TIR: Double, hypos: Double, hypers: Double, normal_: Double) {
-        let glucose = array
+    private func tir(_ glucose: [GlucoseStored]) -> (TIR: Double, hypos: Double, hypers: Double, normal_: Double) {
         let justGlucoseArray = glucose.compactMap({ each in Int(each.glucose as Int16) })
         let totalReadings = justGlucoseArray.count
         let highLimit = settingsManager.settings.high

+ 0 - 1
FreeAPS/Sources/Modules/Bolus/BolusDataFlow.swift

@@ -5,5 +5,4 @@ enum Bolus {
 protocol BolusProvider: Provider {
     var suggestion: Suggestion? { get }
     func pumpSettings() -> PumpSettings
-    func fetchGlucose() -> [Readings]
 }

+ 0 - 7
FreeAPS/Sources/Modules/Bolus/BolusProvider.swift

@@ -1,7 +1,5 @@
 extension Bolus {
     final class Provider: BaseProvider, BolusProvider {
-        let coreDataStorage = CoreDataStorage()
-
         var suggestion: Suggestion? {
             storage.retrieve(OpenAPS.Enact.suggested, as: Suggestion.self)
         }
@@ -17,10 +15,5 @@ extension Bolus {
                 ?? [BasalProfileEntry](from: OpenAPS.defaults(for: OpenAPS.Settings.basalProfile))
                 ?? []
         }
-
-        func fetchGlucose() -> [Readings] {
-            let fetchGlucose = coreDataStorage.fetchGlucose(interval: DateFilter().twoHours)
-            return fetchGlucose
-        }
     }
 }

+ 7 - 2
FreeAPS/Sources/Modules/DataTable/DataTableStateModel.swift

@@ -200,7 +200,7 @@ extension DataTable {
             provider.deleteGlucose(id: id)
 
             let fetchRequest: NSFetchRequest<NSFetchRequestResult>
-            fetchRequest = NSFetchRequest(entityName: "Readings")
+            fetchRequest = NSFetchRequest(entityName: "GlucoseStored")
             fetchRequest.predicate = NSPredicate(format: "id == %@", id)
             let deleteRequest = NSBatchDeleteRequest(
                 fetchRequest: fetchRequest
@@ -214,7 +214,12 @@ extension DataTable {
                         into: [coredataContext]
                     )
                 }
-            } catch { /* To do: handle any thrown errors. */ }
+                debugPrint("Data Table State: \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) deleted glucose")
+            } catch {
+                debugPrint(
+                    "Data Table State: \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to delete glucose"
+                )
+            }
 
             // Deletes Manual Glucose
             if (glucose.glucose.type ?? "") == GlucoseType.manual.rawValue {

+ 7 - 5
FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift

@@ -85,6 +85,8 @@ struct MainChartView: View {
     @State private var maxValue: Decimal = 270
     @State private var selection: Date? = nil
 
+    private let now = Date.now
+
     @Environment(\.colorScheme) var colorScheme
     @Environment(\.calendar) var calendar
 
@@ -142,11 +144,11 @@ struct MainChartView: View {
         units == .mgdL ? 30 : 1.66
     }
 
-    private var selectedGlucose: BloodGlucose? {
+    private var selectedGlucose: GlucoseStored? {
         if let selection = selection {
             let lowerBound = selection.addingTimeInterval(-120)
             let upperBound = selection.addingTimeInterval(120)
-            return glucose.first { $0.dateString >= lowerBound && $0.dateString <= upperBound }
+            return glucoseFromPersistence.first { $0.date ?? now >= lowerBound && $0.date ?? now <= upperBound }
         } else {
             return nil
         }
@@ -236,7 +238,7 @@ extension MainChartView {
 
                 /// show glucose value when hovering over it
                 if let selectedGlucose {
-                    RuleMark(x: .value("Selection", selectedGlucose.dateString, unit: .minute))
+                    RuleMark(x: .value("Selection", selectedGlucose.date ?? now, unit: .minute))
                         .foregroundStyle(Color.tabBar)
                         .offset(yStart: 70)
                         .lineStyle(.init(lineWidth: 2, dash: [5]))
@@ -279,10 +281,10 @@ extension MainChartView {
     }
 
     @ViewBuilder var selectionPopover: some View {
-        if let sgv = selectedGlucose?.sgv {
+        if let sgv = selectedGlucose?.glucose {
             let glucoseToShow = Decimal(sgv) * conversionFactor
             VStack {
-                Text(selectedGlucose?.dateString.formatted(.dateTime.hour().minute(.twoDigits)) ?? "")
+                Text(selectedGlucose?.date?.formatted(.dateTime.hour().minute(.twoDigits)) ?? "")
                 HStack {
                     Text(glucoseToShow.formatted(.number.precision(units == .mmolL ? .fractionLength(1) : .fractionLength(0))))
                         .fontWeight(.bold)

+ 6 - 11
FreeAPS/Sources/Modules/Stat/View/ChartsView.swift

@@ -4,7 +4,7 @@ import SwiftDate
 import SwiftUI
 
 struct ChartsView: View {
-    @FetchRequest var fetchRequest: FetchedResults<Readings>
+    @FetchRequest var glucose: FetchedResults<GlucoseStored>
 
     @Binding var highLimit: Decimal
     @Binding var lowLimit: Decimal
@@ -40,7 +40,7 @@ struct ChartsView: View {
         _ units: Binding<GlucoseUnits>,
         _ overrideUnit: Binding<Bool>,
         _ standing: Binding<Bool>
-    ) { _fetchRequest = FetchRequest<Readings>(
+    ) { _glucose = FetchRequest<GlucoseStored>(
         sortDescriptors: [NSSortDescriptor(key: "date", ascending: false)],
         predicate: NSPredicate(format: "glucose > 0 AND date > %@", filter)
     )
@@ -55,13 +55,12 @@ struct ChartsView: View {
         // Be aware of the low/lowLimit difference. lowLimit/highLimit is always in mg/dl, whereas low/high is configurable in settings
         let low = lowLimit * (units == .mmolL ? Decimal(conversionFactor) : 1)
         let high = highLimit * (units == .mmolL ? Decimal(conversionFactor) : 1)
-        let readings = fetchRequest
-        let count = readings.count
+        let count = glucose.count
         // The symbol size when fewer readings are larger
         let sizeOfDataPoints: CGFloat = count < 20 ? 50 : count < 50 ? 35 : count > 2000 ? 5 : 15
 
         return Chart {
-            ForEach(readings.filter({ $0.glucose > Int(highLimit) }), id: \.date) { item in
+            ForEach(glucose.filter({ $0.glucose > Int(highLimit) }), id: \.date) { item in
                 PointMark(
                     x: .value("Date", item.date ?? Date()),
                     y: .value("High", Double(item.glucose) * (units == .mmolL ? self.conversionFactor : 1))
@@ -70,7 +69,7 @@ struct ChartsView: View {
                 .symbolSize(sizeOfDataPoints)
             }
             ForEach(
-                readings
+                glucose
                     .filter({
                         $0.glucose >= Int(lowLimit) && $0
                             .glucose <= Int(highLimit) }),
@@ -83,7 +82,7 @@ struct ChartsView: View {
                 .foregroundStyle(.green)
                 .symbolSize(sizeOfDataPoints)
             }
-            ForEach(readings.filter({ $0.glucose < Int(lowLimit) }), id: \.date) { item in
+            ForEach(glucose.filter({ $0.glucose < Int(lowLimit) }), id: \.date) { item in
                 PointMark(
                     x: .value("Date", item.date ?? Date()),
                     y: .value("Low", Double(item.glucose) * (units == .mmolL ? conversionFactor : 1))
@@ -207,7 +206,6 @@ struct ChartsView: View {
 
     var groupedGlucose: some View {
         VStack(alignment: .leading, spacing: 20) {
-            let glucose = fetchRequest
             let mapGlucose = glucose.compactMap({ each in each.glucose })
             if !mapGlucose.isEmpty {
                 let mapGlucoseAcuteLow = mapGlucose.filter({ $0 < Int16(3.3 / 0.0555) })
@@ -237,7 +235,6 @@ struct ChartsView: View {
 
     var groupedGlucoseStatsLaying: some View {
         HStack {
-            let glucose = fetchRequest
             let mapGlucose = glucose.compactMap({ each in each.glucose })
             if !mapGlucose.isEmpty {
                 let mapGlucoseLow = mapGlucose.filter({ $0 < Int16(3.3 / 0.0555) })
@@ -271,8 +268,6 @@ struct ChartsView: View {
         let hypoLimit = Int(lowLimit)
         let hyperLimit = Int(highLimit)
 
-        let glucose = fetchRequest
-
         let justGlucoseArray = glucose.compactMap({ each in Int(each.glucose as Int16) })
         let totalReadings = justGlucoseArray.count
 

+ 2 - 6
FreeAPS/Sources/Modules/Stat/View/StatsView.swift

@@ -4,7 +4,7 @@ import SwiftUI
 
 struct StatsView: View {
     @FetchRequest var fetchRequest: FetchedResults<LoopStatRecord>
-    @FetchRequest var fetchRequestReadings: FetchedResults<Readings>
+    @FetchRequest var glucose: FetchedResults<GlucoseStored>
 
     @State var headline: Color = .secondary
 
@@ -37,7 +37,7 @@ struct StatsView: View {
             predicate: NSPredicate(format: "interval > 0 AND start > %@", filter)
         )
 
-        _fetchRequestReadings = FetchRequest<Readings>(
+        _glucose = FetchRequest<GlucoseStored>(
             sortDescriptors: [NSSortDescriptor(key: "date", ascending: false)],
             predicate: NSPredicate(format: "glucose > 0 AND date > %@", filter)
         )
@@ -130,7 +130,6 @@ struct StatsView: View {
             let useUnit: GlucoseUnits = (units == .mmolL && overrideUnit) ? .mgdL :
                 (units == .mgdL && overrideUnit || units == .mmolL) ? .mmolL : .mgdL
             let hba1cs = glucoseStats()
-            let glucose = fetchRequestReadings
             // First date
             let previous = glucose.last?.date ?? Date()
             // Last date (recent)
@@ -173,7 +172,6 @@ struct StatsView: View {
         HStack(spacing: 30) {
             let bgs = glucoseStats()
 
-            let glucose = fetchRequestReadings
             // First date
             let previous = glucose.last?.date ?? Date()
             // Last date (recent)
@@ -212,7 +210,6 @@ struct StatsView: View {
     private func glucoseStats()
         -> (ifcc: Double, ngsp: Double, average: Double, median: Double, sd: Double, cv: Double, readings: Double)
     {
-        let glucose = fetchRequestReadings
         // First date
         let previous = glucose.last?.date ?? Date()
         // Last date (recent)
@@ -264,7 +261,6 @@ struct StatsView: View {
     }
 
     private func tir() -> [(decimal: Decimal, string: String)] {
-        let glucose = fetchRequestReadings
         let justGlucoseArray = glucose.compactMap({ each in Int(each.glucose as Int16) })
         let totalReadings = justGlucoseArray.count
 

+ 17 - 6
FreeAPS/Sources/Services/LiveActivity/LiveActivityBridge.swift

@@ -25,7 +25,7 @@ extension LiveActivityAttributes.ContentState {
         new bg: BloodGlucose,
         prev: BloodGlucose?,
         mmol: Bool,
-        chart: [Readings],
+        chart: [GlucoseStored],
         settings: FreeAPSSettings,
         suggestion: Suggestion
     ) {
@@ -284,10 +284,8 @@ extension LiveActivityBridge: GlucoseObserver {
             self.latestGlucose = glucose.last
         }
 
-        // fetch glucose for chart from Core Data
-        let coreDataStorage = CoreDataStorage()
-        let sixHoursAgo = Calendar.current.date(byAdding: .hour, value: -6, to: Date()) ?? Date()
-        let fetchGlucose = coreDataStorage.fetchGlucose(interval: sixHoursAgo as NSDate)
+        // fetch glucose for the last 6 hours for the LA chart from Core Data
+        let fetchedGlucose = fetchGlucose()
 
         guard let bg = glucose.last else {
             return
@@ -298,7 +296,7 @@ extension LiveActivityBridge: GlucoseObserver {
                 new: bg,
                 prev: latestGlucose,
                 mmol: settings.units == .mmolL,
-                chart: fetchGlucose,
+                chart: fetchedGlucose,
                 settings: settings,
                 suggestion: suggestion
             )
@@ -310,4 +308,17 @@ extension LiveActivityBridge: GlucoseObserver {
             }
         }
     }
+
+    private func fetchGlucose() -> [GlucoseStored] {
+        let context = CoreDataStack.shared.persistentContainer.viewContext
+        do {
+            let fetchedGlucose = try context.fetch(GlucoseStored.fetch(NSPredicate.predicateForSixHoursAgo))
+            debugPrint("LA Bridge: \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to fetch glucose")
+
+            return fetchedGlucose
+        } catch {
+            debugPrint("LA Bridge: \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to fetch glucose")
+            return []
+        }
+    }
 }

+ 19 - 7
FreeAPS/Sources/Services/WatchManager/WatchManager.swift

@@ -18,6 +18,7 @@ final class BaseWatchManager: NSObject, WatchManager, Injectable {
     @Injected() private var garmin: GarminManager!
 
     let coreDataStorage = CoreDataStorage()
+    let context = CoreDataStack.shared.persistentContainer.viewContext
 
     private var lifetime = Lifetime()
 
@@ -53,15 +54,26 @@ final class BaseWatchManager: NSObject, WatchManager, Injectable {
         configureState()
     }
 
+    private func fetchGlucose() -> [GlucoseStored] {
+        do {
+            let fetchedReadings = try context.fetch(GlucoseStored.fetch(NSPredicate.predicateFor120MinAgo))
+            debugPrint("Watch Manager: \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) fetched glucose")
+            return fetchedReadings
+        } catch {
+            debugPrint("Watch Manager: \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to fetch glucose")
+            return []
+        }
+    }
+
     private func configureState() {
         processQueue.async {
-            let readings = self.coreDataStorage.fetchGlucose(interval: DateFilter().twoHours)
-            let glucoseValues = self.glucoseText(readings)
+            let fetchedReadings = self.fetchGlucose()
+            let glucoseValues = self.glucoseText(fetchedReadings)
             self.state.glucose = glucoseValues.glucose
             self.state.trend = glucoseValues.trend
             self.state.delta = glucoseValues.delta
-            self.state.trendRaw = readings.first?.direction ?? "↔︎"
-            self.state.glucoseDate = readings.first?.date ?? .distantPast
+            self.state.trendRaw = fetchedReadings.first?.direction ?? "↔︎"
+            self.state.glucoseDate = fetchedReadings.first?.date ?? .distantPast
             self.state.lastLoopDate = self.enactedSuggestion?.recieved == true ? self.enactedSuggestion?.deliverAt : self
                 .apsManager.lastLoopDate
             self.state.lastLoopDateInterval = self.state.lastLoopDate.map {
@@ -90,7 +102,7 @@ final class BaseWatchManager: NSObject, WatchManager, Injectable {
                         0
                     ))
             } else {
-                let recommended = self.newBolusCalc(delta: readings, suggestion: self.suggestion)
+                let recommended = self.newBolusCalc(delta: fetchedReadings, suggestion: self.suggestion)
                 self.state.bolusRecommended = self.apsManager
                     .roundBolus(amount: max(recommended, 0))
             }
@@ -151,7 +163,7 @@ final class BaseWatchManager: NSObject, WatchManager, Injectable {
         }
     }
 
-    private func glucoseText(_ glucose: [Readings]) -> (glucose: String, trend: String, delta: String) {
+    private func glucoseText(_ glucose: [GlucoseStored]) -> (glucose: String, trend: String, delta: String) {
         let glucoseValue = glucose.first?.glucose ?? 0
 
         guard !glucose.isEmpty else { return ("--", "--", "--") }
@@ -203,7 +215,7 @@ final class BaseWatchManager: NSObject, WatchManager, Injectable {
         )!
     }
 
-    private func newBolusCalc(delta: [Readings], suggestion _: Suggestion?) -> Decimal {
+    private func newBolusCalc(delta: [GlucoseStored], suggestion _: Suggestion?) -> Decimal {
         var conversion: Decimal = 1
         // Settings
         if settingsManager.settings.units == .mmolL {

+ 0 - 6
Model/Core_Data.xcdatamodeld/Core_Data.xcdatamodel/contents

@@ -158,12 +158,6 @@
         <attribute name="enteredBy" optional="YES" attributeType="String"/>
         <attribute name="protein" optional="YES" attributeType="Decimal" defaultValueString="0.0"/>
     </entity>
-    <entity name="Readings" representedClassName="Readings" syncable="YES" codeGenerationType="class">
-        <attribute name="date" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
-        <attribute name="direction" optional="YES" attributeType="String"/>
-        <attribute name="glucose" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
-        <attribute name="id" optional="YES" attributeType="String"/>
-    </entity>
     <entity name="StatsData" representedClassName="StatsData" syncable="YES" codeGenerationType="class">
         <attribute name="lastrun" attributeType="Date" defaultDateTimeInterval="704497620" usesScalarValueType="NO"/>
     </entity>

+ 18 - 0
Model/NSPredicates.swift

@@ -10,6 +10,14 @@ extension Date {
         Calendar.current.date(byAdding: .minute, value: -30, to: Date())!
     }
 
+    static var twoHoursAgo: Date {
+        Calendar.current.date(byAdding: .hour, value: -2, to: Date())!
+    }
+
+    static var sixHoursAgo: Date {
+        Calendar.current.date(byAdding: .hour, value: -6, to: Date())!
+    }
+
     static var oneWeekAgo: Date {
         Calendar.current.date(byAdding: .day, value: -7, to: Date())!
     }
@@ -38,6 +46,16 @@ extension NSPredicate {
         return NSPredicate(format: "date >= %@", date as NSDate)
     }
 
+    static var predicateFor120MinAgo: NSPredicate {
+        let date = Date.twoHoursAgo
+        return NSPredicate(format: "date >= %@", date as NSDate)
+    }
+
+    static var predicateForSixHoursAgo: NSPredicate {
+        let date = Date.sixHoursAgo
+        return NSPredicate(format: "date >= %@", date as NSDate)
+    }
+
     static var predicateForOneWeek: NSPredicate {
         let date = Date.oneWeekAgo
         return NSPredicate(format: "date >= %@", date as NSDate)