فهرست منبع

Fix offset for cob + iob chart

polscm32 aka Marvout 1 سال پیش
والد
کامیت
74d154bdcb

+ 4 - 8
FreeAPS.xcodeproj/project.pbxproj

@@ -276,8 +276,7 @@
 		58D08B222C8DAA8E00AA37D3 /* OverrideView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D08B212C8DAA8E00AA37D3 /* OverrideView.swift */; };
 		58D08B302C8DEA7500AA37D3 /* ForecastView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D08B2F2C8DEA7500AA37D3 /* ForecastView.swift */; };
 		58D08B322C8DF88900AA37D3 /* DummyCharts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D08B312C8DF88900AA37D3 /* DummyCharts.swift */; };
-		58D08B342C8DF9A700AA37D3 /* CobChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D08B332C8DF9A700AA37D3 /* CobChart.swift */; };
-		58D08B362C8DFAC600AA37D3 /* IobChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D08B352C8DFAC600AA37D3 /* IobChart.swift */; };
+		58D08B342C8DF9A700AA37D3 /* CobIobChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D08B332C8DF9A700AA37D3 /* CobIobChart.swift */; };
 		58D08B382C8DFB6000AA37D3 /* BasalChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D08B372C8DFB6000AA37D3 /* BasalChart.swift */; };
 		58D08B3A2C8DFECD00AA37D3 /* TempTargets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D08B392C8DFECD00AA37D3 /* TempTargets.swift */; };
 		58F107742BD1A4D000B1A680 /* Determination+helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F107732BD1A4D000B1A680 /* Determination+helper.swift */; };
@@ -957,8 +956,7 @@
 		58D08B212C8DAA8E00AA37D3 /* OverrideView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverrideView.swift; sourceTree = "<group>"; };
 		58D08B2F2C8DEA7500AA37D3 /* ForecastView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForecastView.swift; sourceTree = "<group>"; };
 		58D08B312C8DF88900AA37D3 /* DummyCharts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DummyCharts.swift; sourceTree = "<group>"; };
-		58D08B332C8DF9A700AA37D3 /* CobChart.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CobChart.swift; sourceTree = "<group>"; };
-		58D08B352C8DFAC600AA37D3 /* IobChart.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IobChart.swift; sourceTree = "<group>"; };
+		58D08B332C8DF9A700AA37D3 /* CobIobChart.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CobIobChart.swift; sourceTree = "<group>"; };
 		58D08B372C8DFB6000AA37D3 /* BasalChart.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasalChart.swift; sourceTree = "<group>"; };
 		58D08B392C8DFECD00AA37D3 /* TempTargets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TempTargets.swift; sourceTree = "<group>"; };
 		58F107732BD1A4D000B1A680 /* Determination+helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Determination+helper.swift"; sourceTree = "<group>"; };
@@ -1848,8 +1846,7 @@
 				58D08B212C8DAA8E00AA37D3 /* OverrideView.swift */,
 				58D08B2F2C8DEA7500AA37D3 /* ForecastView.swift */,
 				58D08B312C8DF88900AA37D3 /* DummyCharts.swift */,
-				58D08B332C8DF9A700AA37D3 /* CobChart.swift */,
-				58D08B352C8DFAC600AA37D3 /* IobChart.swift */,
+				58D08B332C8DF9A700AA37D3 /* CobIobChart.swift */,
 				58D08B372C8DFB6000AA37D3 /* BasalChart.swift */,
 				58D08B392C8DFECD00AA37D3 /* TempTargets.swift */,
 			);
@@ -3517,7 +3514,6 @@
 				BDCD47AF2C1F3F1700F8BCD5 /* OverrideStored+helper.swift in Sources */,
 				3811DE3F25C9D4A100A708ED /* SettingsStateModel.swift in Sources */,
 				CE7CA3582A064E2F004BE681 /* ListStateView.swift in Sources */,
-				58D08B362C8DFAC600AA37D3 /* IobChart.swift in Sources */,
 				193F6CDD2A512C8F001240FD /* Loops.swift in Sources */,
 				38B4F3CB25E502E200E76A18 /* WeakObjectSet.swift in Sources */,
 				38E989DD25F5021400C0CED0 /* PumpStatus.swift in Sources */,
@@ -3559,7 +3555,7 @@
 				38A43598262E0E4900E80935 /* FetchAnnouncementsManager.swift in Sources */,
 				DD1745442C55C60E00211FAC /* AutosensSettingsDataFlow.swift in Sources */,
 				BDCAF2382C639F35002DC907 /* SettingItems.swift in Sources */,
-				58D08B342C8DF9A700AA37D3 /* CobChart.swift in Sources */,
+				58D08B342C8DF9A700AA37D3 /* CobIobChart.swift in Sources */,
 				642F76A05A4FF530463A9FD0 /* NightscoutConfigRootView.swift in Sources */,
 				BD7DA9AC2AE06EB900601B20 /* BolusCalculatorConfigRootView.swift in Sources */,
 				AD3D2CD42CD01B9EB8F26522 /* PumpConfigDataFlow.swift in Sources */,

+ 0 - 67
FreeAPS/Sources/Modules/Home/View/Chart/CobChart.swift

@@ -1,67 +0,0 @@
-import Charts
-import Foundation
-import SwiftUI
-
-extension MainChartView {
-    var cobChart: some View {
-        Chart {
-            drawCurrentTimeMarker()
-            drawCOB(dummy: false)
-
-            if #available(iOS 17, *) {
-                if let selectedCOBValue {
-                    PointMark(
-                        x: .value("Time", selectedCOBValue.deliverAt ?? now, unit: .minute),
-                        y: .value("Value", selectedCOBValue.cob)
-                    )
-                    .symbolSize(CGSize(width: 15, height: 15))
-                    .foregroundStyle(Color.orange.opacity(0.8))
-
-                    PointMark(
-                        x: .value("Time", selectedCOBValue.deliverAt ?? now, unit: .minute),
-                        y: .value("Value", selectedCOBValue.cob)
-                    )
-                    .symbolSize(CGSize(width: 6, height: 6))
-                    .foregroundStyle(Color.primary)
-                }
-            }
-        }
-        .frame(minHeight: geo.size.height * 0.12)
-        .frame(width: fullWidth(viewWidth: screenSize.width))
-        .chartXScale(domain: startMarker ... endMarker)
-        .backport.chartXSelection(value: $selection)
-        .chartXAxis { basalChartXAxis }
-        .chartYAxis { cobChartYAxis }
-        .chartYScale(domain: state.minValueCobChart ... state.maxValueCobChart)
-    }
-
-    func drawCOB(dummy: Bool) -> some ChartContent {
-        ForEach(state.enactedAndNonEnactedDeterminations) { cob in
-            let amount = Int(cob.cob)
-            let date: Date = cob.deliverAt ?? Date()
-
-            if dummy {
-                LineMark(x: .value("Time", date), y: .value("Value", amount))
-                    .foregroundStyle(Color.clear)
-                AreaMark(x: .value("Time", date), y: .value("Value", amount)).foregroundStyle(
-                    Color.clear
-                )
-            } else {
-                LineMark(x: .value("Time", date), y: .value("Value", amount))
-                    .foregroundStyle(Color.orange.gradient)
-                AreaMark(x: .value("Time", date), y: .value("Value", amount)).foregroundStyle(
-                    LinearGradient(
-                        gradient: Gradient(
-                            colors: [
-                                Color.orange.opacity(0.8),
-                                Color.orange.opacity(0.01)
-                            ]
-                        ),
-                        startPoint: .top,
-                        endPoint: .bottom
-                    )
-                )
-            }
-        }
-    }
-}

+ 109 - 0
FreeAPS/Sources/Modules/Home/View/Chart/CobIobChart.swift

@@ -0,0 +1,109 @@
+import Charts
+import Foundation
+import SwiftUI
+
+extension MainChartView {
+    var cobIobChart: some View {
+        Chart {
+            drawCurrentTimeMarker()
+            drawIOB()
+            drawCOB(dummy: false)
+
+            if let selectedCOBValue {
+                PointMark(
+                    x: .value("Time", selectedCOBValue.deliverAt ?? now, unit: .minute),
+                    y: .value("Value", selectedCOBValue.cob)
+                )
+                .symbolSize(CGSize(width: 15, height: 15))
+                .foregroundStyle(Color.orange.opacity(0.8))
+                .position(by: .value("Axis", "COB"))
+
+                PointMark(
+                    x: .value("Time", selectedCOBValue.deliverAt ?? now, unit: .minute),
+                    y: .value("Value", selectedCOBValue.cob)
+                )
+                .symbolSize(CGSize(width: 6, height: 6))
+                .foregroundStyle(Color.primary)
+                .position(by: .value("Axis", "COB"))
+            }
+
+            if let selectedIOBValue {
+                PointMark(
+                    x: .value("Time", selectedIOBValue.deliverAt ?? now, unit: .minute),
+                    y: .value("Value", Int(truncating: selectedIOBValue.iob ?? 0))
+                )
+                .symbolSize(CGSize(width: 15, height: 15))
+                .foregroundStyle(Color.darkerBlue.opacity(0.8))
+                .position(by: .value("Axis", "IOB"))
+
+                PointMark(
+                    x: .value("Time", selectedIOBValue.deliverAt ?? now, unit: .minute),
+                    y: .value("Value", Int(truncating: selectedIOBValue.iob ?? 0))
+                )
+                .symbolSize(CGSize(width: 6, height: 6))
+                .foregroundStyle(Color.primary)
+                .position(by: .value("Axis", "IOB"))
+            }
+        }
+        .chartForegroundStyleScale([
+            "COB": Color.orange,
+            "IOB": Color.darkerBlue
+        ])
+        .chartLegend(.hidden)
+        .frame(minHeight: geo.size.height * 0.12)
+        .frame(width: fullWidth(viewWidth: screenSize.width))
+        .chartXScale(domain: startMarker ... endMarker)
+        .backport.chartXSelection(value: $selection)
+        .chartXAxis { basalChartXAxis }
+        .chartYAxis { cobIobChartYAxis }
+        .chartYScale(domain: combinedYDomain())
+    }
+
+    func combinedYDomain() -> ClosedRange<Double> {
+        let minValue = min(state.minValueCobChart, state.minValueIobChart)
+        let maxValue = max(state.maxValueCobChart, state.maxValueIobChart)
+        return Double(minValue) ... Double(maxValue)
+    }
+
+    func drawCOB(dummy: Bool) -> some ChartContent {
+        ForEach(state.enactedAndNonEnactedDeterminations) { cob in
+            let amount = Int(cob.cob)
+            let date: Date = cob.deliverAt ?? Date()
+
+            if dummy {
+                LineMark(x: .value("Time", date), y: .value("Value", amount))
+                    .foregroundStyle(Color.clear)
+                    .position(by: .value("Axis", "COB"))
+                AreaMark(x: .value("Time", date), y: .value("Value", amount))
+                    .foregroundStyle(Color.clear)
+                    .position(by: .value("Axis", "COB"))
+            } else {
+                LineMark(x: .value("Time", date), y: .value("Value", amount))
+                    .foregroundStyle(by: .value("Type", "COB"))
+                    .position(by: .value("Axis", "COB"))
+                AreaMark(x: .value("Time", date), y: .value("Value", amount))
+                    .foregroundStyle(by: .value("Type", "COB"))
+                    .position(by: .value("Axis", "COB"))
+                    .opacity(0.2)
+            }
+        }
+    }
+
+    func drawIOB() -> some ChartContent {
+        ForEach(state.enactedAndNonEnactedDeterminations) { iob in
+            let rawAmount = iob.iob?.doubleValue ?? 0
+            
+            // as iob and cob share the same y axis and cob is usually >> iob we need to weigh iob visually
+            let amount: Double = rawAmount > 0 ? rawAmount * 3 : rawAmount * 4
+            let date: Date = iob.deliverAt ?? Date()
+
+            AreaMark(x: .value("Time", date), y: .value("Amount", amount))
+                .foregroundStyle(by: .value("Type", "IOB"))
+                .position(by: .value("Axis", "IOB"))
+                .opacity(0.2)
+            LineMark(x: .value("Time", date), y: .value("Amount", amount))
+                .foregroundStyle(by: .value("Type", "IOB"))
+                .position(by: .value("Axis", "IOB"))
+        }
+    }
+}

+ 1 - 1
FreeAPS/Sources/Modules/Home/View/Chart/DummyCharts.swift

@@ -72,7 +72,7 @@ extension MainChartView {
         .chartXScale(domain: startMarker ... endMarker)
         .chartXAxis { basalChartXAxis }
         .chartXAxis(.hidden)
-        .chartYAxis { cobChartYAxis }
+        .chartYAxis { cobIobChartYAxis }
         .chartYAxis(.hidden)
         .chartYScale(domain: state.minValueCobChart ... state.maxValueCobChart)
         .chartLegend(.hidden)

+ 0 - 63
FreeAPS/Sources/Modules/Home/View/Chart/IobChart.swift

@@ -1,63 +0,0 @@
-import Charts
-import Foundation
-import SwiftUI
-
-extension MainChartView {
-    var iobChart: some View {
-        VStack {
-            Chart {
-                drawIOB()
-
-                if #available(iOS 17, *) {
-                    if let selectedIOBValue {
-                        PointMark(
-                            x: .value("Time", selectedIOBValue.deliverAt ?? now, unit: .minute),
-                            y: .value("Value", Int(truncating: selectedIOBValue.iob ?? 0))
-                        )
-                        .symbolSize(CGSize(width: 15, height: 15))
-                        .foregroundStyle(Color.darkerBlue.opacity(0.8))
-
-                        PointMark(
-                            x: .value("Time", selectedIOBValue.deliverAt ?? now, unit: .minute),
-                            y: .value("Value", Int(truncating: selectedIOBValue.iob ?? 0))
-                        )
-                        .symbolSize(CGSize(width: 6, height: 6))
-                        .foregroundStyle(Color.primary)
-                    }
-                }
-            }
-            .frame(minHeight: geo.size.height * 0.12)
-            .frame(width: fullWidth(viewWidth: screenSize.width))
-            .chartXScale(domain: startMarker ... endMarker)
-            .backport.chartXSelection(value: $selection)
-            .chartXAxis { basalChartXAxis }
-            .chartYAxis { cobChartYAxis }
-            .chartYScale(domain: state.minValueIobChart ... state.maxValueIobChart)
-            .chartYAxis(.hidden)
-        }
-    }
-
-    func drawIOB() -> some ChartContent {
-        ForEach(state.enactedAndNonEnactedDeterminations) { iob in
-            let rawAmount = iob.iob?.doubleValue ?? 0
-            let amount: Double = rawAmount > 0 ? rawAmount : rawAmount * 2 // weigh negative iob with factor 2
-            let date: Date = iob.deliverAt ?? Date()
-
-            LineMark(x: .value("Time", date), y: .value("Amount", amount))
-                .foregroundStyle(Color.darkerBlue)
-            AreaMark(x: .value("Time", date), y: .value("Amount", amount))
-                .foregroundStyle(
-                    LinearGradient(
-                        gradient: Gradient(
-                            colors: [
-                                Color.darkerBlue.opacity(0.8),
-                                Color.darkerBlue.opacity(0.01)
-                            ]
-                        ),
-                        startPoint: .top,
-                        endPoint: .bottom
-                    )
-                )
-        }
-    }
-}

+ 2 - 6
FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift

@@ -81,11 +81,7 @@ struct MainChartView: View {
                             basalChart
                             mainChart
                             Spacer()
-                            ZStack {
-                                cobChart
-                                iobChart
-                            }
-
+                            cobIobChart
                         }.onChange(of: screenHours) {
                             scroller.scrollTo("MainChart", anchor: .trailing)
                         }
@@ -373,7 +369,7 @@ extension MainChartView {
         }
     }
 
-    var cobChartYAxis: some AxisContent {
+    var cobIobChartYAxis: some AxisContent {
         AxisMarks(position: .trailing) { _ in
             if displayYgridLines {
                 AxisGridLine(stroke: .init(lineWidth: 0.5, dash: [2, 3]))