InsulinModelChart.swift 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. //
  2. // InsulinModelChart.swift
  3. // LoopKitUI
  4. //
  5. // Copyright © 2019 LoopKit Authors. All rights reserved.
  6. //
  7. import Foundation
  8. import LoopKit
  9. import SwiftCharts
  10. public class InsulinModelChart: GlucoseChart, ChartProviding {
  11. /// The chart points for the selected model
  12. public private(set) var selectedInsulinModelChartPoints: [ChartPoint] = [] {
  13. didSet {
  14. if let lastDate = selectedInsulinModelChartPoints.last?.x as? ChartAxisValueDate {
  15. updateEndDate(lastDate.date)
  16. }
  17. }
  18. }
  19. public private(set) var unselectedInsulinModelChartPoints: [[ChartPoint]] = [] {
  20. didSet {
  21. for points in unselectedInsulinModelChartPoints {
  22. if let lastDate = points.last?.x as? ChartAxisValueDate {
  23. updateEndDate(lastDate.date)
  24. }
  25. }
  26. }
  27. }
  28. public private(set) var endDate: Date?
  29. private func updateEndDate(_ date: Date) {
  30. if endDate == nil || date > endDate! {
  31. self.endDate = date
  32. }
  33. }
  34. }
  35. extension InsulinModelChart {
  36. public func didReceiveMemoryWarning() {
  37. }
  38. public func generate(withFrame frame: CGRect, xAxisModel: ChartAxisModel, xAxisValues: [ChartAxisValue], axisLabelSettings: ChartLabelSettings, guideLinesLayerSettings: ChartGuideLinesLayerSettings, colors: ChartColorPalette, chartSettings: ChartSettings, labelsWidthY: CGFloat, gestureRecognizer: UIGestureRecognizer?, traitCollection: UITraitCollection) -> Chart
  39. {
  40. let yAxisValues = ChartAxisValuesStaticGenerator.generateYAxisValuesWithChartPoints(glucoseDisplayRangePoints,
  41. minSegmentCount: 2,
  42. maxSegmentCount: 5,
  43. multiple: glucoseUnit.chartableIncrement / 2,
  44. axisValueGenerator: {
  45. ChartAxisValueDouble(round($0), labelSettings: axisLabelSettings)
  46. },
  47. addPaddingSegmentIfEdge: false
  48. )
  49. let yAxisModel = ChartAxisModel(axisValues: yAxisValues, lineColor: colors.axisLine, labelSpaceReservationMode: .fixed(labelsWidthY))
  50. let coordsSpace = ChartCoordsSpaceLeftBottomSingleAxis(
  51. chartSettings: chartSettings,
  52. chartFrame: frame,
  53. xModel: xAxisModel,
  54. yModel: yAxisModel
  55. )
  56. // Grid lines
  57. let gridLayer = ChartGuideLinesForValuesLayer(
  58. xAxis: coordsSpace.xAxisLayer.axis,
  59. yAxis: coordsSpace.yAxisLayer.axis,
  60. settings: guideLinesLayerSettings,
  61. axisValuesX: Array(xAxisValues.dropFirst().dropLast()),
  62. axisValuesY: yAxisValues
  63. )
  64. // Selected line
  65. var selectedLayer: ChartLayer?
  66. if selectedInsulinModelChartPoints.count > 1 {
  67. let lineModel = ChartLineModel.predictionLine(
  68. points: selectedInsulinModelChartPoints,
  69. color: colors.glucoseTint,
  70. width: 2
  71. )
  72. selectedLayer = ChartPointsLineLayer(
  73. xAxis: coordsSpace.xAxisLayer.axis,
  74. yAxis: coordsSpace.yAxisLayer.axis,
  75. lineModels: [lineModel]
  76. )
  77. }
  78. var unselectedLineModels = [ChartLineModel]()
  79. for points in unselectedInsulinModelChartPoints where points.count > 1 {
  80. unselectedLineModels.append(ChartLineModel.predictionLine(
  81. points: points,
  82. color: UIColor.secondaryLabel,
  83. width: 1
  84. ))
  85. }
  86. // Unselected lines
  87. var unselectedLayer: ChartLayer?
  88. if !unselectedLineModels.isEmpty {
  89. unselectedLayer = ChartPointsLineLayer(
  90. xAxis: coordsSpace.xAxisLayer.axis,
  91. yAxis: coordsSpace.yAxisLayer.axis,
  92. lineModels: unselectedLineModels
  93. )
  94. }
  95. let layers: [ChartLayer?] = [
  96. gridLayer,
  97. coordsSpace.xAxisLayer,
  98. coordsSpace.yAxisLayer,
  99. unselectedLayer,
  100. selectedLayer
  101. ]
  102. return Chart(
  103. frame: frame,
  104. innerFrame: coordsSpace.chartInnerFrame,
  105. settings: chartSettings,
  106. layers: layers.compactMap { $0 }
  107. )
  108. }
  109. }
  110. extension InsulinModelChart {
  111. public func setSelectedInsulinModelValues(_ values: [GlucoseValue]) {
  112. self.selectedInsulinModelChartPoints = glucosePointsFromValues(values)
  113. }
  114. public func setUnselectedInsulinModelValues(_ values: [[GlucoseValue]]) {
  115. self.unselectedInsulinModelChartPoints = values.map(glucosePointsFromValues)
  116. }
  117. }