Jon Mårtensson пре 2 година
родитељ
комит
25686ca373

+ 4 - 4
FreeAPS.xcodeproj/project.pbxproj

@@ -40,7 +40,7 @@
 		19D466A529AA2BD4004D5F33 /* FPUConfigProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19D466A429AA2BD4004D5F33 /* FPUConfigProvider.swift */; };
 		19D466A729AA2C22004D5F33 /* FPUConfigStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19D466A629AA2C22004D5F33 /* FPUConfigStateModel.swift */; };
 		19D466AA29AA3099004D5F33 /* FPUConfigRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19D466A929AA3099004D5F33 /* FPUConfigRootView.swift */; };
-		19D4E4EB29FC6A9F00351451 /* TIRforChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19D4E4EA29FC6A9F00351451 /* TIRforChart.swift */; };
+		19D4E4EB29FC6A9F00351451 /* Charts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19D4E4EA29FC6A9F00351451 /* Charts.swift */; };
 		19DA48E829CD339B00EEA1E7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 19DA487F29CD2B8400EEA1E7 /* Assets.xcassets */; };
 		19DA48E929CD339C00EEA1E7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 19DA487F29CD2B8400EEA1E7 /* Assets.xcassets */; };
 		19DA48EA29CD339C00EEA1E7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 19DA487F29CD2B8400EEA1E7 /* Assets.xcassets */; };
@@ -568,7 +568,7 @@
 		19D466A429AA2BD4004D5F33 /* FPUConfigProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FPUConfigProvider.swift; sourceTree = "<group>"; };
 		19D466A629AA2C22004D5F33 /* FPUConfigStateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FPUConfigStateModel.swift; sourceTree = "<group>"; };
 		19D466A929AA3099004D5F33 /* FPUConfigRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FPUConfigRootView.swift; sourceTree = "<group>"; };
-		19D4E4EA29FC6A9F00351451 /* TIRforChart.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TIRforChart.swift; sourceTree = "<group>"; };
+		19D4E4EA29FC6A9F00351451 /* Charts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Charts.swift; sourceTree = "<group>"; };
 		19DA487F29CD2B8400EEA1E7 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
 		19DC677E29CA675700FD9EC4 /* OverrideProfilesDataFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverrideProfilesDataFlow.swift; sourceTree = "<group>"; };
 		19DC678029CA676A00FD9EC4 /* OverrideProfilesProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverrideProfilesProvider.swift; sourceTree = "<group>"; };
@@ -1655,7 +1655,7 @@
 				FE41E4D529463EE20047FD55 /* NightscoutPreferences.swift */,
 				191F62672AD6B05A004D7911 /* NightscoutSettings.swift */,
 				1967DFBD29D052C200759F30 /* Icons.swift */,
-				19D4E4EA29FC6A9F00351451 /* TIRforChart.swift */,
+				19D4E4EA29FC6A9F00351451 /* Charts.swift */,
 				19A910352A24D6D700C8951B /* DateFilter.swift */,
 				193F6CDC2A512C8F001240FD /* Loops.swift */,
 				CC6C406D2ACDD69E009B8058 /* RawFetchedProfile.swift */,
@@ -2862,7 +2862,7 @@
 				0CEA2EA070AB041AF3E3745B /* BolusRootView.swift in Sources */,
 				1967DFC029D053AC00759F30 /* IconSelection.swift in Sources */,
 				BDFD165C2AE40688007F0DDA /* DefaultBolusCalcRootView.swift in Sources */,
-				19D4E4EB29FC6A9F00351451 /* TIRforChart.swift in Sources */,
+				19D4E4EB29FC6A9F00351451 /* Charts.swift in Sources */,
 				FEFFA7A22929FE49007B8193 /* UIDevice+Extensions.swift in Sources */,
 				F90692D3274B9A130037068D /* AppleHealthKitRootView.swift in Sources */,
 				3862CC1F273FDC9200BF832C /* CalibrationsChart.swift in Sources */,

+ 17 - 0
FreeAPS/Sources/Models/Charts.swift

@@ -0,0 +1,17 @@
+
+import Foundation
+
+struct ShapeModel: Identifiable {
+    var type: String
+    var percent: Decimal
+    var id = UUID()
+}
+
+struct ChartData: Identifiable {
+    var date: Date
+    var iob: Double
+    var zt: Double
+    var cob: Double
+    var uam: Double
+    var id = UUID()
+}

+ 0 - 8
FreeAPS/Sources/Models/TIRforChart.swift

@@ -1,8 +0,0 @@
-
-import Foundation
-
-struct ShapeModel: Identifiable {
-    var type: String
-    var percent: Decimal
-    var id = UUID()
-}

+ 85 - 0
FreeAPS/Sources/Modules/Bolus/View/AlternativeBolusCalcRootView.swift

@@ -1,3 +1,4 @@
+import Charts
 import CoreData
 import SwiftUI
 import Swinject
@@ -56,6 +57,13 @@ extension Bolus {
 
         var body: some View {
             Form {
+                Section {
+                    chart()
+                } header: {
+                    Text("Predictions")
+                }
+
+                Section {}
                 if fetch {
                     Section {
                         mealEntries
@@ -186,6 +194,83 @@ 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))
+                }
+            }
+            .frame(minHeight: 150)
+            .chartForegroundStyleScale([
+                "IOB": Color(.insulin),
+                "UAM": Color(.UAM),
+                "COB": Color(.loopYellow),
+                "ZT": Color(.ZT)
+            ])
+            .chartYAxisLabel("Glucose (" + state.units.rawValue + ")")
+        }
+
         // Pop-up
         var bolusInfoAlternativeCalculator: some View {
             VStack {