Kaynağa Gözat

Add Predictions to both bolus views.
Prevent force unwrapping of nil values.

Jon Mårtensson 2 yıl önce
ebeveyn
işleme
ec02ba749d

+ 4 - 0
FreeAPS.xcodeproj/project.pbxproj

@@ -19,6 +19,7 @@
 		190EBCC829FF13AA00BA767D /* StatConfigStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 190EBCC729FF13AA00BA767D /* StatConfigStateModel.swift */; };
 		190EBCCB29FF13CB00BA767D /* StatConfigRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 190EBCCA29FF13CB00BA767D /* StatConfigRootView.swift */; };
 		191F62682AD6B05A004D7911 /* NightscoutSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191F62672AD6B05A004D7911 /* NightscoutSettings.swift */; };
+		19229B962AFBB84800CD91CA /* Predictions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19229B952AFBB84800CD91CA /* Predictions.swift */; };
 		1927C8E62744606D00347C69 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1927C8E82744606D00347C69 /* InfoPlist.strings */; };
 		1935364028496F7D001E0B16 /* Oref2_variables.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1935363F28496F7D001E0B16 /* Oref2_variables.swift */; };
 		193F6CDD2A512C8F001240FD /* Loops.swift in Sources */ = {isa = PBXBuildFile; fileRef = 193F6CDC2A512C8F001240FD /* Loops.swift */; };
@@ -508,6 +509,7 @@
 		190EBCCA29FF13CB00BA767D /* StatConfigRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatConfigRootView.swift; sourceTree = "<group>"; };
 		1918333A26ADA46800F45722 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Localizable.strings; sourceTree = "<group>"; };
 		191F62672AD6B05A004D7911 /* NightscoutSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightscoutSettings.swift; sourceTree = "<group>"; };
+		19229B952AFBB84800CD91CA /* Predictions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Predictions.swift; sourceTree = "<group>"; };
 		1927C8E92744611700347C69 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/InfoPlist.strings; sourceTree = "<group>"; };
 		1927C8EA2744611800347C69 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/InfoPlist.strings; sourceTree = "<group>"; };
 		1927C8EB2744611900347C69 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
@@ -2084,6 +2086,7 @@
 				10A0C32B0DAB52726EF9B6D9 /* BolusRootView.swift */,
 				BDFD165B2AE40688007F0DDA /* DefaultBolusCalcRootView.swift */,
 				BDFD16592AE40438007F0DDA /* AlternativeBolusCalcRootView.swift */,
+				19229B952AFBB84800CD91CA /* Predictions.swift */,
 			);
 			path = View;
 			sourceTree = "<group>";
@@ -2830,6 +2833,7 @@
 				1967DFBE29D052C200759F30 /* Icons.swift in Sources */,
 				38E8754F275556FA00975559 /* WatchManager.swift in Sources */,
 				A228DF96647338139F152B15 /* PreferencesEditorDataFlow.swift in Sources */,
+				19229B962AFBB84800CD91CA /* Predictions.swift in Sources */,
 				389ECE052601144100D86C4F /* ConcurrentMap.swift in Sources */,
 				CE7CA3562A064973004BE681 /* StateIntentRequest.swift in Sources */,
 				E4984C5262A90469788754BB /* PreferencesEditorProvider.swift in Sources */,

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

@@ -13,6 +13,7 @@ extension Bolus {
         @Injected() var nsManager: NightscoutManager!
 
         @Published var suggestion: Suggestion?
+        @Published var predictions: Predictions?
         @Published var amount: Decimal = 0
         @Published var insulinRecommended: Decimal = 0
         @Published var insulinRequired: Decimal = 0
@@ -89,6 +90,12 @@ extension Bolus {
                         }
                     }.store(in: &lifetime)
             }
+            if let notNilSugguestion = provider.suggestion {
+                suggestion = notNilSugguestion
+                if let notNilPredictions = suggestion?.predictions {
+                    predictions = notNilPredictions
+                }
+            }
         }
 
         func getDeltaBG() {

+ 6 - 75
FreeAPS/Sources/Modules/Bolus/View/AlternativeBolusCalcRootView.swift

@@ -58,7 +58,7 @@ extension Bolus {
         var body: some View {
             Form {
                 Section {
-                    chart()
+                    predictionChart
                 } header: {
                     Text("Predictions")
                 }
@@ -194,81 +194,12 @@ extension Bolus {
             }
         }
 
-        func chart() -> some View {
-            // Data Source
-            let iob = state.provider.suggestion?.predictions?.iob ?? [Int]()
-            let cob = state.provider.suggestion?.predictions?.cob ?? [Int]()
-            let uam = state.provider.suggestion?.predictions?.uam ?? [Int]()
-            let zt = state.provider.suggestion?.predictions?.zt ?? [Int]()
-            let count = max(iob.count, cob.count, uam.count, zt.count)
-            var now = Date.now
-            var startIndex = 0
-            let conversion = state.units == .mmolL ? 0.0555 : 1
-            // Organize the data needed for prediction chart.
-            var data = [ChartData]()
-            repeat {
-                now = now.addingTimeInterval(5.minutes.timeInterval)
-                if startIndex < count {
-                    let addedData = ChartData(
-                        date: now,
-                        iob: startIndex < iob.count ? Double(iob[startIndex]) * conversion : 0,
-                        zt: startIndex < zt.count ? Double(zt[startIndex]) * conversion : 0,
-                        cob: startIndex < cob.count ? Double(cob[startIndex]) * conversion : 0,
-                        uam: startIndex < uam.count ? Double(uam[startIndex]) * conversion : 0,
-                        id: UUID()
-                    )
-                    data.append(addedData)
-                }
-                startIndex += 1
-            } while startIndex < count
-            // Chart
-            return Chart(data) { item in
-                // Remove 0 (empty) values
-                if item.iob != 0 {
-                    LineMark(
-                        x: .value("Time", item.date),
-                        y: .value("IOB", item.iob),
-                        series: .value("IOB", "A")
-                    )
-                    .foregroundStyle(Color(.insulin))
-                    .lineStyle(StrokeStyle(lineWidth: 2))
-                }
-                if item.uam != 0 {
-                    LineMark(
-                        x: .value("Time", item.date),
-                        y: .value("UAM", item.uam),
-                        series: .value("UAM", "B")
-                    )
-                    .foregroundStyle(Color(.UAM))
-                    .lineStyle(StrokeStyle(lineWidth: 2))
-                }
-                if item.cob != 0 {
-                    LineMark(
-                        x: .value("Time", item.date),
-                        y: .value("COB", item.cob),
-                        series: .value("COB", "C")
-                    )
-                    .foregroundStyle(Color(.loopYellow))
-                    .lineStyle(StrokeStyle(lineWidth: 2))
-                }
-                if item.zt != 0 {
-                    LineMark(
-                        x: .value("Time", item.date),
-                        y: .value("ZT", item.zt),
-                        series: .value("ZT", "D")
-                    )
-                    .foregroundStyle(Color(.ZT))
-                    .lineStyle(StrokeStyle(lineWidth: 2))
-                }
+        var predictionChart: some View {
+            ZStack {
+                PredictionView(
+                    predictions: $state.predictions, units: $state.units
+                )
             }
-            .frame(minHeight: 150)
-            .chartForegroundStyleScale([
-                "IOB": Color(.insulin),
-                "UAM": Color(.UAM),
-                "COB": Color(.loopYellow),
-                "ZT": Color(.ZT)
-            ])
-            .chartYAxisLabel("Glucose (" + state.units.rawValue + ")")
         }
 
         // Pop-up

+ 15 - 0
FreeAPS/Sources/Modules/Bolus/View/DefaultBolusCalcRootView.swift

@@ -1,3 +1,4 @@
+import Charts
 import CoreData
 import SwiftUI
 import Swinject
@@ -36,6 +37,12 @@ extension Bolus {
 
         var body: some View {
             Form {
+                Section {
+                    predictionChart
+                } header: {
+                    Text("Predictions")
+                }
+
                 if fetch {
                     Section {
                         mealEntries
@@ -156,6 +163,14 @@ extension Bolus {
             }
         }
 
+        var predictionChart: some View {
+            ZStack {
+                PredictionView(
+                    predictions: $state.predictions, units: $state.units
+                )
+            }
+        }
+
         var changed: Bool {
             ((meal.first?.carbs ?? 0) > 0) || ((meal.first?.fat ?? 0) > 0) || ((meal.first?.protein ?? 0) > 0)
         }

+ 90 - 0
FreeAPS/Sources/Modules/Bolus/View/Predictions.swift

@@ -0,0 +1,90 @@
+import Charts
+import CoreData
+import SwiftUI
+import Swinject
+
+struct PredictionView: View {
+    @Binding var predictions: Predictions?
+    @Binding var units: GlucoseUnits
+
+    var body: some View {
+        chart()
+    }
+
+    func chart() -> some View {
+        // Data Source
+        let iob = predictions?.iob ?? [Int]()
+        let cob = predictions?.cob ?? [Int]()
+        let uam = predictions?.uam ?? [Int]()
+        let zt = predictions?.zt ?? [Int]()
+        let count = max(iob.count, cob.count, uam.count, zt.count)
+        var now = Date.now
+        var startIndex = 0
+        let conversion = units == .mmolL ? 0.0555 : 1
+        // Organize the data needed for prediction chart.
+        var data = [ChartData]()
+        repeat {
+            now = now.addingTimeInterval(5.minutes.timeInterval)
+            if startIndex < count {
+                let addedData = ChartData(
+                    date: now,
+                    iob: startIndex < iob.count ? Double(iob[startIndex]) * conversion : 0,
+                    zt: startIndex < zt.count ? Double(zt[startIndex]) * conversion : 0,
+                    cob: startIndex < cob.count ? Double(cob[startIndex]) * conversion : 0,
+                    uam: startIndex < uam.count ? Double(uam[startIndex]) * conversion : 0,
+                    id: UUID()
+                )
+                data.append(addedData)
+            }
+            startIndex += 1
+        } while startIndex < count
+        // Chart
+        return Chart(data) { item in
+            // Remove 0 (empty) values
+            if item.iob != 0 {
+                LineMark(
+                    x: .value("Time", item.date),
+                    y: .value("IOB", item.iob),
+                    series: .value("IOB", "A")
+                )
+                .foregroundStyle(Color(.insulin))
+                .lineStyle(StrokeStyle(lineWidth: 2))
+            }
+            if item.uam != 0 {
+                LineMark(
+                    x: .value("Time", item.date),
+                    y: .value("UAM", item.uam),
+                    series: .value("UAM", "B")
+                )
+                .foregroundStyle(Color(.UAM))
+                .lineStyle(StrokeStyle(lineWidth: 2))
+            }
+            if item.cob != 0 {
+                LineMark(
+                    x: .value("Time", item.date),
+                    y: .value("COB", item.cob),
+                    series: .value("COB", "C")
+                )
+                .foregroundStyle(Color(.loopYellow))
+                .lineStyle(StrokeStyle(lineWidth: 2))
+            }
+            if item.zt != 0 {
+                LineMark(
+                    x: .value("Time", item.date),
+                    y: .value("ZT", item.zt),
+                    series: .value("ZT", "D")
+                )
+                .foregroundStyle(Color(.ZT))
+                .lineStyle(StrokeStyle(lineWidth: 2))
+            }
+        }
+        .frame(minHeight: 150)
+        .chartForegroundStyleScale([
+            "IOB": Color(.insulin),
+            "UAM": Color(.UAM),
+            "COB": Color(.loopYellow),
+            "ZT": Color(.ZT)
+        ])
+        .chartYAxisLabel("Glucose (" + units.rawValue + ")")
+    }
+}