Predictions.swift 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import Charts
  2. import CoreData
  3. import SwiftUI
  4. import Swinject
  5. struct PredictionView: View {
  6. @Binding var predictions: Predictions?
  7. @Binding var units: GlucoseUnits
  8. @Binding var eventualBG: Int
  9. @Binding var target: Decimal
  10. var body: some View {
  11. VStack {
  12. chart()
  13. HStack {
  14. let conversion = units == .mmolL ? 0.0555 : 1
  15. Text("Eventual Glucose")
  16. Spacer()
  17. Text(
  18. (Double(eventualBG) * conversion)
  19. .formatted(.number.grouping(.never).rounded().precision(.fractionLength(units == .mmolL ? 1 : 0)))
  20. )
  21. Text(units.rawValue).foregroundStyle(.secondary)
  22. Divider()
  23. }.font(.callout)
  24. }
  25. }
  26. func chart() -> some View {
  27. // Data Source
  28. let iob = predictions?.iob ?? [Int]()
  29. let cob = predictions?.cob ?? [Int]()
  30. let uam = predictions?.uam ?? [Int]()
  31. let zt = predictions?.zt ?? [Int]()
  32. let count = max(iob.count, cob.count, uam.count, zt.count)
  33. var now = Date.now
  34. var startIndex = 0
  35. let conversion = units == .mmolL ? 0.0555 : 1
  36. // Organize the data needed for prediction chart.
  37. var data = [ChartData]()
  38. repeat {
  39. now = now.addingTimeInterval(5.minutes.timeInterval)
  40. if startIndex < count {
  41. let addedData = ChartData(
  42. date: now,
  43. iob: startIndex < iob.count ? Double(iob[startIndex]) * conversion : 0,
  44. zt: startIndex < zt.count ? Double(zt[startIndex]) * conversion : 0,
  45. cob: startIndex < cob.count ? Double(cob[startIndex]) * conversion : 0,
  46. uam: startIndex < uam.count ? Double(uam[startIndex]) * conversion : 0,
  47. id: UUID()
  48. )
  49. data.append(addedData)
  50. }
  51. startIndex += 1
  52. } while startIndex < count
  53. // Chart
  54. return Chart(data) {
  55. // Remove 0 (empty) values
  56. if $0.iob != 0 {
  57. LineMark(
  58. x: .value("Time", $0.date),
  59. y: .value("IOB", $0.iob),
  60. series: .value("IOB", "A")
  61. )
  62. .foregroundStyle(Color(.insulin))
  63. .lineStyle(StrokeStyle(lineWidth: 2))
  64. }
  65. if $0.uam != 0 {
  66. LineMark(
  67. x: .value("Time", $0.date),
  68. y: .value("UAM", $0.uam),
  69. series: .value("UAM", "B")
  70. )
  71. .foregroundStyle(Color(.UAM))
  72. .lineStyle(StrokeStyle(lineWidth: 2))
  73. }
  74. if $0.cob != 0 {
  75. LineMark(
  76. x: .value("Time", $0.date),
  77. y: .value("COB", $0.cob),
  78. series: .value("COB", "C")
  79. )
  80. .foregroundStyle(Color(.loopYellow))
  81. .lineStyle(StrokeStyle(lineWidth: 2))
  82. }
  83. if $0.zt != 0 {
  84. LineMark(
  85. x: .value("Time", $0.date),
  86. y: .value("ZT", $0.zt),
  87. series: .value("ZT", "D")
  88. )
  89. .foregroundStyle(Color(.ZT))
  90. .lineStyle(StrokeStyle(lineWidth: 2))
  91. }
  92. }
  93. .frame(minHeight: 150)
  94. .chartForegroundStyleScale([
  95. "IOB": Color(.insulin),
  96. "UAM": Color(.UAM),
  97. "COB": Color(.loopYellow),
  98. "ZT": Color(.ZT)
  99. ])
  100. .chartYAxisLabel("Glucose, " + units.rawValue, alignment: .center)
  101. .chartXAxis {
  102. AxisMarks(values: .stride(by: .hour)) { _ in
  103. AxisValueLabel(format: .dateTime.hour())
  104. }
  105. }
  106. }
  107. }