| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- 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"))
- }
- }
- }
|