Graphs.swift 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. //
  2. // Graphs.swift
  3. // LoopFollow
  4. //
  5. // Created by Jon Fawcett on 6/16/20.
  6. // Copyright © 2020 Jon Fawcett. All rights reserved.
  7. //
  8. import Foundation
  9. import Charts
  10. import UIKit
  11. extension MainViewController {
  12. func createGraph(){
  13. self.BGChart.clear()
  14. // Create the BG Graph Data
  15. let entries = bgData
  16. var bgChartEntry = [ChartDataEntry]()
  17. var colors = [NSUIColor]()
  18. var maxBG: Int = 250
  19. if bgData.count > 0 {
  20. for i in 0..<entries.count{
  21. var dateString = String(entries[i].date).prefix(10)
  22. let dateSecondsOnly = Double(String(dateString))!
  23. if entries[i].sgv > maxBG - 40 {
  24. maxBG = entries[i].sgv + 40
  25. }
  26. let value = ChartDataEntry(x: Double(entries[i].date), y: Double(entries[i].sgv))
  27. bgChartEntry.append(value)
  28. if Double(entries[i].sgv) >= Double(UserDefaultsRepository.highLine.value) {
  29. colors.append(NSUIColor.systemYellow)
  30. } else if Double(entries[i].sgv) <= Double(UserDefaultsRepository.lowLine.value) {
  31. colors.append(NSUIColor.systemRed)
  32. } else {
  33. colors.append(NSUIColor.systemGreen)
  34. }
  35. }
  36. }
  37. // Add Prediction Data
  38. if predictionData.count > 0 && bgData.count > 0 && UserDefaultsRepository.graphPrediction.value {
  39. var startingTime = bgChartEntry[bgChartEntry.count - 1].x + 300
  40. var i = 0
  41. // Add 1 hour of predictions
  42. while i < 12 {
  43. var predictionVal = Double(predictionData[i])
  44. // Below can be turned on to prevent out of range on the graph if desired.
  45. // It currently just drops them out of view
  46. if predictionVal > 400 {
  47. // predictionVal = 400
  48. } else if predictionVal < 0 {
  49. // predictionVal = 0
  50. }
  51. let value = ChartDataEntry(x: startingTime + 5, y: predictionVal)
  52. bgChartEntry.append(value)
  53. colors.append(NSUIColor.systemPurple)
  54. startingTime += 300
  55. i += 1
  56. }
  57. }
  58. // Setup BG line details
  59. let lineBG = LineChartDataSet(entries:bgChartEntry, label: "")
  60. lineBG.circleRadius = 3
  61. lineBG.circleColors = [NSUIColor.systemGreen]
  62. lineBG.drawCircleHoleEnabled = false
  63. lineBG.axisDependency = YAxis.AxisDependency.right
  64. lineBG.highlightEnabled = false
  65. lineBG.drawValuesEnabled = false
  66. if UserDefaultsRepository.showLines.value {
  67. lineBG.lineWidth = 2
  68. } else {
  69. lineBG.lineWidth = 0
  70. }
  71. if UserDefaultsRepository.showDots.value {
  72. lineBG.drawCirclesEnabled = true
  73. } else {
  74. lineBG.drawCirclesEnabled = false
  75. }
  76. lineBG.setDrawHighlightIndicators(false)
  77. lineBG.valueFont.withSize(50)
  78. if colors.count > 0 {
  79. for i in 1..<colors.count{
  80. lineBG.addColor(colors[i])
  81. lineBG.circleColors.append(colors[i])
  82. }
  83. }
  84. // create Basal graph data
  85. var chartEntry = [ChartDataEntry]()
  86. var maxBasal = 1.0
  87. if basalData.count > 0 && UserDefaultsRepository.graphBasal.value {
  88. for i in 0..<basalData.count{
  89. let value = ChartDataEntry(x: Double(basalData[i].date), y: Double(basalData[i].basalRate))
  90. chartEntry.append(value)
  91. if basalData[i].basalRate > maxBasal {
  92. maxBasal = basalData[i].basalRate
  93. }
  94. }
  95. }
  96. // Setup Basal line details
  97. let lineBasal = LineChartDataSet(entries:chartEntry, label: "")
  98. lineBasal.setDrawHighlightIndicators(false)
  99. lineBasal.setColor(NSUIColor.systemBlue, alpha: 0.5)
  100. lineBasal.lineWidth = 0
  101. lineBasal.drawFilledEnabled = true
  102. lineBasal.fillColor = NSUIColor.systemBlue.withAlphaComponent(0.8)
  103. lineBasal.drawCirclesEnabled = false
  104. lineBasal.axisDependency = YAxis.AxisDependency.left
  105. lineBasal.highlightEnabled = false
  106. lineBasal.drawValuesEnabled = false
  107. // Boluses
  108. var chartEntryBolus = [ChartDataEntry]()
  109. if bolusData.count > 0 && UserDefaultsRepository.graphBolus.value {
  110. for i in 0..<bolusData.count{
  111. let value = ChartDataEntry(x: Double(bolusData[i].date), y: Double(bolusData[i].sgv + 10), data: String(bolusData[i].value))
  112. chartEntryBolus.append(value)
  113. }
  114. }
  115. let lineBolus = LineChartDataSet(entries:chartEntryBolus, label: "")
  116. lineBolus.circleRadius = 7
  117. lineBolus.circleColors = [NSUIColor.systemBlue.withAlphaComponent(0.75)]
  118. lineBolus.drawCircleHoleEnabled = false
  119. lineBolus.setDrawHighlightIndicators(false)
  120. lineBolus.setColor(NSUIColor.systemBlue, alpha: 1.0)
  121. lineBolus.drawCirclesEnabled = true
  122. lineBolus.lineWidth = 0
  123. lineBolus.axisDependency = YAxis.AxisDependency.right
  124. lineBolus.valueFormatter = ChartYDataValueFormatter()
  125. lineBolus.drawValuesEnabled = true
  126. lineBolus.valueTextColor = NSUIColor.label
  127. // Carbs
  128. var chartEntryCarbs = [ChartDataEntry]()
  129. if carbData.count > 0 && UserDefaultsRepository.graphCarbs.value {
  130. for i in 0..<carbData.count{
  131. let value = ChartDataEntry(x: Double(carbData[i].date), y: Double(carbData[i].sgv + 30), data: String(carbData[i].value))
  132. chartEntryCarbs.append(value)
  133. }
  134. }
  135. let lineCarbs = LineChartDataSet(entries:chartEntryCarbs, label: "")
  136. lineCarbs.circleRadius = 7
  137. lineCarbs.circleColors = [NSUIColor.systemOrange.withAlphaComponent(0.75)]
  138. lineCarbs.drawCircleHoleEnabled = false
  139. lineCarbs.setDrawHighlightIndicators(false)
  140. lineCarbs.setColor(NSUIColor.systemBlue, alpha: 1.0)
  141. lineCarbs.drawCirclesEnabled = true
  142. lineCarbs.lineWidth = 0
  143. lineCarbs.axisDependency = YAxis.AxisDependency.right
  144. lineCarbs.valueFormatter = ChartYDataValueFormatter()
  145. lineCarbs.drawValuesEnabled = true
  146. lineCarbs.valueTextColor = NSUIColor.label
  147. // Setup the chart data of all lines
  148. let data = LineChartData()
  149. data.addDataSet(lineBG)
  150. data.addDataSet(lineBasal)
  151. data.addDataSet(lineBolus)
  152. data.addDataSet(lineCarbs)
  153. data.setValueFont(UIFont.systemFont(ofSize: 12))
  154. // Add marker popups for bolus and carbs
  155. // Changed to display values
  156. //let marker = PillMarker(color: .secondarySystemBackground, font: UIFont.boldSystemFont(ofSize: 14), textColor: .label)
  157. //BGChart.marker = marker
  158. // Clear limit lines so they don't add multiples when changing the settings
  159. BGChart.rightAxis.removeAllLimitLines()
  160. //Add lower red line based on low alert value
  161. let ll = ChartLimitLine()
  162. ll.limit = Double(UserDefaultsRepository.lowLine.value)
  163. ll.lineColor = NSUIColor.systemRed.withAlphaComponent(0.5)
  164. BGChart.rightAxis.addLimitLine(ll)
  165. //Add upper yellow line based on low alert value
  166. let ul = ChartLimitLine()
  167. ul.limit = Double(UserDefaultsRepository.highLine.value)
  168. ul.lineColor = NSUIColor.systemYellow.withAlphaComponent(0.5)
  169. BGChart.rightAxis.addLimitLine(ul)
  170. // Setup the main graph overall details
  171. BGChart.xAxis.valueFormatter = ChartXValueFormatter()
  172. BGChart.xAxis.granularity = 1800
  173. BGChart.xAxis.labelTextColor = NSUIColor.label
  174. BGChart.xAxis.labelPosition = XAxis.LabelPosition.bottom
  175. BGChart.leftAxis.enabled = true
  176. BGChart.leftAxis.labelPosition = YAxis.LabelPosition.insideChart
  177. BGChart.leftAxis.axisMaximum = maxBasal
  178. BGChart.leftAxis.axisMinimum = 0.0
  179. BGChart.leftAxis.drawGridLinesEnabled = false
  180. BGChart.rightAxis.labelTextColor = NSUIColor.label
  181. BGChart.rightAxis.labelPosition = YAxis.LabelPosition.insideChart
  182. BGChart.rightAxis.axisMinimum = 40
  183. BGChart.rightAxis.axisMaximum = Double(maxBG)
  184. BGChart.legend.enabled = false
  185. BGChart.scaleYEnabled = false
  186. BGChart.drawGridBackgroundEnabled = false
  187. //BGChart.gridBackgroundColor = NSUIColor.secondarySystemBackground
  188. BGChart.data = data
  189. // This must be called after the data is loaded
  190. BGChart.setExtraOffsets(left: 10, top: 10, right: 10, bottom: 10)
  191. BGChart.setVisibleXRangeMinimum(10)
  192. if firstGraphLoad {
  193. BGChart.zoom(scaleX: 18, scaleY: 1, x: 1, y: 1)
  194. firstGraphLoad = false
  195. }
  196. if minAgoBG < 1 {
  197. BGChart.moveViewToAnimated(xValue: dateTimeUtils.getNowTimeIntervalUTC() - (BGChart.visibleXRange * 0.7), yValue: 0.0, axis: .right, duration: 1, easingOption: .easeInBack)
  198. }
  199. if bgData.count > 0 {
  200. createSmallBGGraph(bgChartEntry: bgChartEntry, colors: colors)
  201. }
  202. }
  203. func createSmallBGGraph(bgChartEntry: [ChartDataEntry], colors: [NSUIColor]){
  204. //24 Hour Small Graph
  205. let line2 = LineChartDataSet(entries:bgChartEntry, label: "Number")
  206. line2.drawCirclesEnabled = false
  207. line2.setDrawHighlightIndicators(false)
  208. line2.lineWidth = 1
  209. for i in 1..<colors.count{
  210. line2.addColor(colors[i])
  211. line2.circleColors.append(colors[i])
  212. }
  213. let data2 = LineChartData()
  214. data2.addDataSet(line2)
  215. BGChartFull.leftAxis.enabled = false
  216. BGChartFull.rightAxis.enabled = false
  217. BGChartFull.xAxis.enabled = false
  218. BGChartFull.legend.enabled = false
  219. BGChartFull.scaleYEnabled = false
  220. BGChartFull.scaleXEnabled = false
  221. BGChartFull.drawGridBackgroundEnabled = false
  222. BGChartFull.data = data2
  223. }
  224. }