Graphs.swift 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  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 {
  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. for i in 1..<colors.count{
  79. lineBG.addColor(colors[i])
  80. lineBG.circleColors.append(colors[i])
  81. }
  82. // create Basal graph data
  83. var chartEntry = [ChartDataEntry]()
  84. var maxBasal = 1.0
  85. if basalData.count > 0 {
  86. for i in 0..<basalData.count{
  87. let value = ChartDataEntry(x: Double(basalData[i].date), y: Double(basalData[i].basalRate))
  88. chartEntry.append(value)
  89. if basalData[i].basalRate > maxBasal {
  90. maxBasal = basalData[i].basalRate
  91. }
  92. }
  93. }
  94. // Setup Basal line details
  95. let lineBasal = LineChartDataSet(entries:chartEntry, label: "")
  96. lineBasal.setDrawHighlightIndicators(false)
  97. lineBasal.setColor(NSUIColor.systemBlue, alpha: 0.5)
  98. lineBasal.lineWidth = 0
  99. lineBasal.drawFilledEnabled = true
  100. lineBasal.fillColor = NSUIColor.systemBlue.withAlphaComponent(0.8)
  101. lineBasal.drawCirclesEnabled = false
  102. lineBasal.axisDependency = YAxis.AxisDependency.left
  103. lineBasal.highlightEnabled = false
  104. lineBasal.drawValuesEnabled = false
  105. // Boluses
  106. var chartEntryBolus = [ChartDataEntry]()
  107. if bolusData.count > 0 {
  108. for i in 0..<bolusData.count{
  109. let value = ChartDataEntry(x: Double(bolusData[i].date), y: Double(bolusData[i].sgv + 10), data: String(bolusData[i].value))
  110. chartEntryBolus.append(value)
  111. }
  112. }
  113. let lineBolus = LineChartDataSet(entries:chartEntryBolus, label: "")
  114. lineBolus.circleRadius = 7
  115. lineBolus.circleColors = [NSUIColor.systemBlue.withAlphaComponent(0.75)]
  116. lineBolus.drawCircleHoleEnabled = false
  117. lineBolus.setDrawHighlightIndicators(false)
  118. lineBolus.setColor(NSUIColor.systemBlue, alpha: 1.0)
  119. lineBolus.drawCirclesEnabled = true
  120. lineBolus.lineWidth = 0
  121. lineBolus.axisDependency = YAxis.AxisDependency.right
  122. lineBolus.valueFormatter = ChartYDataValueFormatter()
  123. lineBolus.drawValuesEnabled = true
  124. lineBolus.valueTextColor = NSUIColor.label
  125. // Carbs
  126. var chartEntryCarbs = [ChartDataEntry]()
  127. if carbData.count > 0 {
  128. for i in 0..<carbData.count{
  129. let value = ChartDataEntry(x: Double(carbData[i].date), y: Double(carbData[i].sgv + 30), data: String(carbData[i].value))
  130. chartEntryCarbs.append(value)
  131. }
  132. }
  133. let lineCarbs = LineChartDataSet(entries:chartEntryCarbs, label: "")
  134. lineCarbs.circleRadius = 7
  135. lineCarbs.circleColors = [NSUIColor.systemOrange.withAlphaComponent(0.75)]
  136. lineCarbs.drawCircleHoleEnabled = false
  137. lineCarbs.setDrawHighlightIndicators(false)
  138. lineCarbs.setColor(NSUIColor.systemBlue, alpha: 1.0)
  139. lineCarbs.drawCirclesEnabled = true
  140. lineCarbs.lineWidth = 0
  141. lineCarbs.axisDependency = YAxis.AxisDependency.right
  142. lineCarbs.valueFormatter = ChartYDataValueFormatter()
  143. lineCarbs.drawValuesEnabled = true
  144. lineCarbs.valueTextColor = NSUIColor.label
  145. // Setup the chart data of all lines
  146. let data = LineChartData()
  147. data.addDataSet(lineBG)
  148. data.addDataSet(lineBasal)
  149. data.addDataSet(lineBolus)
  150. data.addDataSet(lineCarbs)
  151. data.setValueFont(UIFont.systemFont(ofSize: 12))
  152. // Add marker popups for bolus and carbs
  153. // Changed to display values
  154. //let marker = PillMarker(color: .secondarySystemBackground, font: UIFont.boldSystemFont(ofSize: 14), textColor: .label)
  155. //BGChart.marker = marker
  156. // Clear limit lines so they don't add multiples when changing the settings
  157. BGChart.rightAxis.removeAllLimitLines()
  158. //Add lower red line based on low alert value
  159. let ll = ChartLimitLine()
  160. ll.limit = Double(UserDefaultsRepository.lowLine.value)
  161. ll.lineColor = NSUIColor.systemRed.withAlphaComponent(0.5)
  162. BGChart.rightAxis.addLimitLine(ll)
  163. //Add upper yellow line based on low alert value
  164. let ul = ChartLimitLine()
  165. ul.limit = Double(UserDefaultsRepository.highLine.value)
  166. ul.lineColor = NSUIColor.systemYellow.withAlphaComponent(0.5)
  167. BGChart.rightAxis.addLimitLine(ul)
  168. // Setup the main graph overall details
  169. BGChart.xAxis.valueFormatter = ChartXValueFormatter()
  170. BGChart.xAxis.granularity = 1800
  171. BGChart.xAxis.labelTextColor = NSUIColor.label
  172. BGChart.xAxis.labelPosition = XAxis.LabelPosition.bottom
  173. BGChart.leftAxis.enabled = true
  174. BGChart.leftAxis.labelPosition = YAxis.LabelPosition.insideChart
  175. BGChart.leftAxis.axisMaximum = maxBasal
  176. BGChart.leftAxis.axisMinimum = 0.0
  177. BGChart.leftAxis.drawGridLinesEnabled = false
  178. BGChart.rightAxis.labelTextColor = NSUIColor.label
  179. BGChart.rightAxis.labelPosition = YAxis.LabelPosition.insideChart
  180. BGChart.rightAxis.axisMinimum = 40
  181. BGChart.rightAxis.axisMaximum = Double(maxBG)
  182. BGChart.legend.enabled = false
  183. BGChart.scaleYEnabled = false
  184. BGChart.drawGridBackgroundEnabled = false
  185. //BGChart.gridBackgroundColor = NSUIColor.secondarySystemBackground
  186. BGChart.data = data
  187. // This must be called after the data is loaded
  188. BGChart.setExtraOffsets(left: 10, top: 10, right: 10, bottom: 10)
  189. BGChart.setVisibleXRangeMinimum(10)
  190. if firstGraphLoad {
  191. BGChart.zoom(scaleX: 18, scaleY: 1, x: 1, y: 1)
  192. firstGraphLoad = false
  193. }
  194. if minAgoBG < 1 {
  195. BGChart.moveViewToAnimated(xValue: dateTimeUtils.getNowTimeIntervalUTC() - (BGChart.visibleXRange * 0.7), yValue: 0.0, axis: .right, duration: 1, easingOption: .easeInBack)
  196. }
  197. if bgData.count > 0 {
  198. createSmallBGGraph(bgChartEntry: bgChartEntry, colors: colors)
  199. }
  200. }
  201. func createSmallBGGraph(bgChartEntry: [ChartDataEntry], colors: [NSUIColor]){
  202. //24 Hour Small Graph
  203. let line2 = LineChartDataSet(entries:bgChartEntry, label: "Number")
  204. line2.drawCirclesEnabled = false
  205. line2.setDrawHighlightIndicators(false)
  206. line2.lineWidth = 1
  207. for i in 1..<colors.count{
  208. line2.addColor(colors[i])
  209. line2.circleColors.append(colors[i])
  210. }
  211. let data2 = LineChartData()
  212. data2.addDataSet(line2)
  213. BGChartFull.leftAxis.enabled = false
  214. BGChartFull.rightAxis.enabled = false
  215. BGChartFull.xAxis.enabled = false
  216. BGChartFull.legend.enabled = false
  217. BGChartFull.scaleYEnabled = false
  218. BGChartFull.scaleXEnabled = false
  219. BGChartFull.drawGridBackgroundEnabled = false
  220. BGChartFull.data = data2
  221. }
  222. }