CobIobChart.swift 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import Charts
  2. import Foundation
  3. import SwiftUI
  4. extension MainChartView {
  5. var cobIobChart: some View {
  6. Chart {
  7. drawCurrentTimeMarker()
  8. drawIOB()
  9. drawCOB(dummy: false)
  10. if let selectedCOBValue {
  11. PointMark(
  12. x: .value("Time", selectedCOBValue.deliverAt ?? now, unit: .minute),
  13. y: .value("Value", selectedCOBValue.cob)
  14. )
  15. .symbolSize(CGSize(width: 15, height: 15))
  16. .foregroundStyle(Color.orange.opacity(0.8))
  17. .position(by: .value("Axis", "COB"))
  18. PointMark(
  19. x: .value("Time", selectedCOBValue.deliverAt ?? now, unit: .minute),
  20. y: .value("Value", selectedCOBValue.cob)
  21. )
  22. .symbolSize(CGSize(width: 6, height: 6))
  23. .foregroundStyle(Color.primary)
  24. .position(by: .value("Axis", "COB"))
  25. }
  26. if let selectedIOBValue {
  27. let rawAmount = selectedIOBValue.iob?.doubleValue ?? 0
  28. // as iob and cob share the same y axis and cob is usually >> iob we need to weigh iob visually
  29. let amount: Double = rawAmount > 0 ? rawAmount * 5 : rawAmount * 6
  30. PointMark(
  31. x: .value("Time", selectedIOBValue.deliverAt ?? now, unit: .minute),
  32. y: .value("Value", amount)
  33. )
  34. .symbolSize(CGSize(width: 15, height: 15))
  35. .foregroundStyle(Color.darkerBlue.opacity(0.8))
  36. .position(by: .value("Axis", "IOB"))
  37. PointMark(
  38. x: .value("Time", selectedIOBValue.deliverAt ?? now, unit: .minute),
  39. y: .value("Value", amount)
  40. )
  41. .symbolSize(CGSize(width: 6, height: 6))
  42. .foregroundStyle(Color.primary)
  43. .position(by: .value("Axis", "IOB"))
  44. }
  45. }
  46. .chartForegroundStyleScale([
  47. "COB": Color.orange,
  48. "IOB": Color.darkerBlue
  49. ])
  50. .chartLegend(.hidden)
  51. .frame(minHeight: geo.size.height * 0.12)
  52. .frame(width: fullWidth(viewWidth: screenSize.width))
  53. .chartXScale(domain: startMarker ... endMarker)
  54. .backport.chartXSelection(value: $selection)
  55. .chartXAxis { basalChartXAxis }
  56. .chartYAxis { cobIobChartYAxis }
  57. .chartYScale(domain: combinedYDomain())
  58. }
  59. func combinedYDomain() -> ClosedRange<Double> {
  60. let minValue = min(state.minValueCobChart, state.minValueIobChart)
  61. let maxValue = max(state.maxValueCobChart, state.maxValueIobChart)
  62. return Double(minValue) ... Double(maxValue)
  63. }
  64. func drawCOB(dummy: Bool) -> some ChartContent {
  65. ForEach(state.enactedAndNonEnactedDeterminations) { cob in
  66. let amount = Int(cob.cob)
  67. let date: Date = cob.deliverAt ?? Date()
  68. if dummy {
  69. LineMark(x: .value("Time", date), y: .value("Value", amount))
  70. .foregroundStyle(Color.clear)
  71. .position(by: .value("Axis", "COB"))
  72. AreaMark(x: .value("Time", date), y: .value("Value", amount))
  73. .foregroundStyle(Color.clear)
  74. .position(by: .value("Axis", "COB"))
  75. } else {
  76. LineMark(x: .value("Time", date), y: .value("Value", amount))
  77. .foregroundStyle(by: .value("Type", "COB"))
  78. .position(by: .value("Axis", "COB"))
  79. AreaMark(x: .value("Time", date), y: .value("Value", amount))
  80. .foregroundStyle(by: .value("Type", "COB"))
  81. .position(by: .value("Axis", "COB"))
  82. .opacity(0.2)
  83. }
  84. }
  85. }
  86. func drawIOB() -> some ChartContent {
  87. ForEach(state.enactedAndNonEnactedDeterminations) { iob in
  88. let rawAmount = iob.iob?.doubleValue ?? 0
  89. // as iob and cob share the same y axis and cob is usually >> iob we need to weigh iob visually
  90. let amount: Double = rawAmount > 0 ? rawAmount * 5 : rawAmount * 6
  91. let date: Date = iob.deliverAt ?? Date()
  92. AreaMark(x: .value("Time", date), y: .value("Amount", amount))
  93. .foregroundStyle(by: .value("Type", "IOB"))
  94. .position(by: .value("Axis", "IOB"))
  95. .opacity(0.2)
  96. LineMark(x: .value("Time", date), y: .value("Amount", amount))
  97. .foregroundStyle(by: .value("Type", "IOB"))
  98. .position(by: .value("Axis", "IOB"))
  99. }
  100. }
  101. }