Graphs.swift 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240
  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. let ScaleXMax:Float = 150.0
  12. extension MainViewController {
  13. func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) {
  14. if chartView == BGChartFull {
  15. BGChart.moveViewToX(entry.x)
  16. }
  17. if entry.data as? String == "hide"{
  18. BGChart.highlightValue(nil, callDelegate: false)
  19. }
  20. }
  21. func chartScaled(_ chartView: ChartViewBase, scaleX: CGFloat, scaleY: CGFloat) {
  22. print("Chart Scaled: \(BGChart.scaleX), \(BGChart.scaleY)")
  23. // dont store huge values
  24. var scale: Float = Float(BGChart.scaleX)
  25. if(scale > ScaleXMax ) {
  26. scale = ScaleXMax
  27. }
  28. UserDefaultsRepository.chartScaleX.value = Float(scale)
  29. }
  30. func createGraph(){
  31. self.BGChart.clear()
  32. // Create the BG Graph Data
  33. let entries = bgData
  34. var bgChartEntry = [ChartDataEntry]()
  35. var colors = [NSUIColor]()
  36. var maxBG: Float = UserDefaultsRepository.minBGScale.value
  37. // Setup BG line details
  38. let lineBG = LineChartDataSet(entries:bgChartEntry, label: "")
  39. lineBG.circleRadius = CGFloat(globalVariables.dotBG)
  40. lineBG.circleColors = [NSUIColor.systemGreen]
  41. lineBG.drawCircleHoleEnabled = false
  42. lineBG.axisDependency = YAxis.AxisDependency.right
  43. lineBG.highlightEnabled = true
  44. lineBG.drawValuesEnabled = false
  45. if UserDefaultsRepository.showLines.value {
  46. lineBG.lineWidth = 2
  47. } else {
  48. lineBG.lineWidth = 0
  49. }
  50. if UserDefaultsRepository.showDots.value {
  51. lineBG.drawCirclesEnabled = true
  52. } else {
  53. lineBG.drawCirclesEnabled = false
  54. }
  55. lineBG.setDrawHighlightIndicators(false)
  56. lineBG.valueFont.withSize(50)
  57. // Setup Prediction line details
  58. var predictionChartEntry = [ChartDataEntry]()
  59. let linePrediction = LineChartDataSet(entries:predictionChartEntry, label: "")
  60. linePrediction.circleRadius = CGFloat(globalVariables.dotBG)
  61. linePrediction.circleColors = [NSUIColor.systemPurple]
  62. linePrediction.colors = [NSUIColor.systemPurple]
  63. linePrediction.drawCircleHoleEnabled = false
  64. linePrediction.axisDependency = YAxis.AxisDependency.right
  65. linePrediction.highlightEnabled = true
  66. linePrediction.drawValuesEnabled = false
  67. if UserDefaultsRepository.showLines.value {
  68. linePrediction.lineWidth = 2
  69. } else {
  70. linePrediction.lineWidth = 0
  71. }
  72. if UserDefaultsRepository.showDots.value {
  73. linePrediction.drawCirclesEnabled = true
  74. } else {
  75. linePrediction.drawCirclesEnabled = false
  76. }
  77. linePrediction.setDrawHighlightIndicators(false)
  78. linePrediction.valueFont.withSize(50)
  79. // create Basal graph data
  80. var chartEntry = [ChartDataEntry]()
  81. var maxBasal = UserDefaultsRepository.minBasalScale.value
  82. let lineBasal = LineChartDataSet(entries:chartEntry, label: "")
  83. lineBasal.setDrawHighlightIndicators(false)
  84. lineBasal.setColor(NSUIColor.systemBlue, alpha: 0.5)
  85. lineBasal.lineWidth = 0
  86. lineBasal.drawFilledEnabled = true
  87. lineBasal.fillColor = NSUIColor.systemBlue
  88. lineBasal.fillAlpha = 0.5
  89. lineBasal.drawCirclesEnabled = false
  90. lineBasal.axisDependency = YAxis.AxisDependency.left
  91. lineBasal.highlightEnabled = true
  92. lineBasal.drawValuesEnabled = false
  93. lineBasal.fillFormatter = basalFillFormatter()
  94. // Boluses
  95. var chartEntryBolus = [ChartDataEntry]()
  96. let lineBolus = LineChartDataSet(entries:chartEntryBolus, label: "")
  97. lineBolus.circleRadius = CGFloat(globalVariables.dotBolus)
  98. lineBolus.circleColors = [NSUIColor.systemBlue.withAlphaComponent(0.75)]
  99. lineBolus.drawCircleHoleEnabled = false
  100. lineBolus.setDrawHighlightIndicators(false)
  101. lineBolus.setColor(NSUIColor.systemBlue, alpha: 1.0)
  102. lineBolus.lineWidth = 0
  103. lineBolus.axisDependency = YAxis.AxisDependency.right
  104. lineBolus.valueFormatter = ChartYDataValueFormatter()
  105. lineBolus.valueTextColor = NSUIColor.label
  106. lineBolus.fillColor = NSUIColor.systemBlue
  107. lineBolus.fillAlpha = 0.6
  108. lineBolus.drawCirclesEnabled = true
  109. lineBolus.drawFilledEnabled = false
  110. if UserDefaultsRepository.showValues.value {
  111. lineBolus.drawValuesEnabled = true
  112. lineBolus.highlightEnabled = false
  113. } else {
  114. lineBolus.drawValuesEnabled = false
  115. lineBolus.highlightEnabled = true
  116. }
  117. // Carbs
  118. var chartEntryCarbs = [ChartDataEntry]()
  119. let lineCarbs = LineChartDataSet(entries:chartEntryCarbs, label: "")
  120. lineCarbs.circleRadius = CGFloat(globalVariables.dotCarb)
  121. lineCarbs.circleColors = [NSUIColor.systemOrange.withAlphaComponent(0.75)]
  122. lineCarbs.drawCircleHoleEnabled = false
  123. lineCarbs.setDrawHighlightIndicators(false)
  124. lineCarbs.setColor(NSUIColor.systemBlue, alpha: 1.0)
  125. lineCarbs.lineWidth = 0
  126. lineCarbs.axisDependency = YAxis.AxisDependency.right
  127. lineCarbs.valueFormatter = ChartYDataValueFormatter()
  128. lineCarbs.valueTextColor = NSUIColor.label
  129. lineCarbs.fillColor = NSUIColor.systemOrange
  130. lineCarbs.fillAlpha = 0.6
  131. lineCarbs.drawCirclesEnabled = true
  132. lineCarbs.drawFilledEnabled = false
  133. if UserDefaultsRepository.showValues.value {
  134. lineCarbs.drawValuesEnabled = true
  135. lineCarbs.highlightEnabled = false
  136. } else {
  137. lineCarbs.drawValuesEnabled = false
  138. lineCarbs.highlightEnabled = true
  139. }
  140. // create Scheduled Basal graph data
  141. var chartBasalScheduledEntry = [ChartDataEntry]()
  142. let lineBasalScheduled = LineChartDataSet(entries:chartBasalScheduledEntry, label: "")
  143. lineBasalScheduled.setDrawHighlightIndicators(false)
  144. lineBasalScheduled.setColor(NSUIColor.systemBlue, alpha: 0.8)
  145. lineBasalScheduled.lineWidth = 2
  146. lineBasalScheduled.drawFilledEnabled = false
  147. lineBasalScheduled.drawCirclesEnabled = false
  148. lineBasalScheduled.axisDependency = YAxis.AxisDependency.left
  149. lineBasalScheduled.highlightEnabled = false
  150. lineBasalScheduled.drawValuesEnabled = false
  151. lineBasalScheduled.lineDashLengths = [10.0, 5.0]
  152. // create Override graph data
  153. var chartOverrideEntry = [ChartDataEntry]()
  154. let lineOverride = LineChartDataSet(entries:chartOverrideEntry, label: "")
  155. lineOverride.setDrawHighlightIndicators(false)
  156. lineOverride.lineWidth = 0
  157. lineOverride.drawFilledEnabled = true
  158. lineOverride.fillFormatter = OverrideFillFormatter()
  159. lineOverride.fillColor = NSUIColor.systemGreen
  160. lineOverride.fillAlpha = 0.6
  161. lineOverride.drawCirclesEnabled = false
  162. lineOverride.axisDependency = YAxis.AxisDependency.right
  163. lineOverride.highlightEnabled = true
  164. lineOverride.drawValuesEnabled = false
  165. // lineOverride.circleColors = [NSUIColor.systemGreen.withAlphaComponent(0.75)]
  166. // lineOverride.valueFormatter = ChartYDataValueFormatter()
  167. // lineOverride.drawCircleHoleEnabled = false
  168. // BG Check
  169. var chartEntryBGCheck = [ChartDataEntry]()
  170. let lineBGCheck = LineChartDataSet(entries:chartEntryBGCheck, label: "")
  171. lineBGCheck.circleRadius = CGFloat(globalVariables.dotOther)
  172. lineBGCheck.circleColors = [NSUIColor.systemRed.withAlphaComponent(0.75)]
  173. lineBGCheck.drawCircleHoleEnabled = false
  174. lineBGCheck.setDrawHighlightIndicators(false)
  175. lineBGCheck.setColor(NSUIColor.systemRed, alpha: 1.0)
  176. lineBGCheck.drawCirclesEnabled = true
  177. lineBGCheck.lineWidth = 0
  178. lineBGCheck.highlightEnabled = true
  179. lineBGCheck.axisDependency = YAxis.AxisDependency.right
  180. lineBGCheck.valueFormatter = ChartYDataValueFormatter()
  181. lineBGCheck.drawValuesEnabled = false
  182. // Suspend Pump
  183. var chartEntrySuspend = [ChartDataEntry]()
  184. let lineSuspend = LineChartDataSet(entries:chartEntrySuspend, label: "")
  185. lineSuspend.circleRadius = CGFloat(globalVariables.dotOther)
  186. lineSuspend.circleColors = [NSUIColor.systemTeal.withAlphaComponent(0.75)]
  187. lineSuspend.drawCircleHoleEnabled = false
  188. lineSuspend.setDrawHighlightIndicators(false)
  189. lineSuspend.setColor(NSUIColor.systemGray2, alpha: 1.0)
  190. lineSuspend.drawCirclesEnabled = true
  191. lineSuspend.lineWidth = 0
  192. lineSuspend.highlightEnabled = true
  193. lineSuspend.axisDependency = YAxis.AxisDependency.right
  194. lineSuspend.valueFormatter = ChartYDataValueFormatter()
  195. lineSuspend.drawValuesEnabled = false
  196. // Resume Pump
  197. var chartEntryResume = [ChartDataEntry]()
  198. let lineResume = LineChartDataSet(entries:chartEntryResume, label: "")
  199. lineResume.circleRadius = CGFloat(globalVariables.dotOther)
  200. lineResume.circleColors = [NSUIColor.systemTeal.withAlphaComponent(0.75)]
  201. lineResume.drawCircleHoleEnabled = false
  202. lineResume.setDrawHighlightIndicators(false)
  203. lineResume.setColor(NSUIColor.systemGray4, alpha: 1.0)
  204. lineResume.drawCirclesEnabled = true
  205. lineResume.lineWidth = 0
  206. lineResume.highlightEnabled = true
  207. lineResume.axisDependency = YAxis.AxisDependency.right
  208. lineResume.valueFormatter = ChartYDataValueFormatter()
  209. lineResume.drawValuesEnabled = false
  210. // Sensor Start
  211. var chartEntrySensor = [ChartDataEntry]()
  212. let lineSensor = LineChartDataSet(entries:chartEntrySensor, label: "")
  213. lineSensor.circleRadius = CGFloat(globalVariables.dotOther)
  214. lineSensor.circleColors = [NSUIColor.systemIndigo.withAlphaComponent(0.75)]
  215. lineSensor.drawCircleHoleEnabled = false
  216. lineSensor.setDrawHighlightIndicators(false)
  217. lineSensor.setColor(NSUIColor.systemGray3, alpha: 1.0)
  218. lineSensor.drawCirclesEnabled = true
  219. lineSensor.lineWidth = 0
  220. lineSensor.highlightEnabled = true
  221. lineSensor.axisDependency = YAxis.AxisDependency.right
  222. lineSensor.valueFormatter = ChartYDataValueFormatter()
  223. lineSensor.drawValuesEnabled = false
  224. // Notes
  225. var chartEntryNote = [ChartDataEntry]()
  226. let lineNote = LineChartDataSet(entries:chartEntryNote, label: "")
  227. lineNote.circleRadius = CGFloat(globalVariables.dotOther)
  228. lineNote.circleColors = [NSUIColor.systemGray.withAlphaComponent(0.75)]
  229. lineNote.drawCircleHoleEnabled = false
  230. lineNote.setDrawHighlightIndicators(false)
  231. lineNote.setColor(NSUIColor.systemGray3, alpha: 1.0)
  232. lineNote.drawCirclesEnabled = true
  233. lineNote.lineWidth = 0
  234. lineNote.highlightEnabled = true
  235. lineNote.axisDependency = YAxis.AxisDependency.right
  236. lineNote.valueFormatter = ChartYDataValueFormatter()
  237. lineNote.drawValuesEnabled = false
  238. // Setup the chart data of all lines
  239. let data = LineChartData()
  240. data.addDataSet(lineBG) // Dataset 0
  241. data.addDataSet(linePrediction) // Dataset 1
  242. data.addDataSet(lineBasal) // Dataset 2
  243. data.addDataSet(lineBolus) // Dataset 3
  244. data.addDataSet(lineCarbs) // Dataset 4
  245. data.addDataSet(lineBasalScheduled) // Dataset 5
  246. data.addDataSet(lineOverride) // Dataset 6
  247. data.addDataSet(lineBGCheck) // Dataset 7
  248. data.addDataSet(lineSuspend) // Dataset 8
  249. data.addDataSet(lineResume) // Dataset 9
  250. data.addDataSet(lineSensor) // Dataset 10
  251. data.addDataSet(lineNote) // Dataset 11
  252. data.setValueFont(UIFont.systemFont(ofSize: 12))
  253. // Add marker popups for bolus and carbs
  254. let marker = PillMarker(color: .secondarySystemBackground, font: UIFont.boldSystemFont(ofSize: 14), textColor: .label)
  255. BGChart.marker = marker
  256. // Clear limit lines so they don't add multiples when changing the settings
  257. BGChart.rightAxis.removeAllLimitLines()
  258. //Add lower red line based on low alert value
  259. let ll = ChartLimitLine()
  260. ll.limit = Double(UserDefaultsRepository.lowLine.value)
  261. ll.lineColor = NSUIColor.systemRed.withAlphaComponent(0.5)
  262. BGChart.rightAxis.addLimitLine(ll)
  263. //Add upper yellow line based on low alert value
  264. let ul = ChartLimitLine()
  265. ul.limit = Double(UserDefaultsRepository.highLine.value)
  266. ul.lineColor = NSUIColor.systemYellow.withAlphaComponent(0.5)
  267. BGChart.rightAxis.addLimitLine(ul)
  268. // Add Now Line
  269. createNowAndDIALines()
  270. createMidnightLines()
  271. startGraphNowTimer()
  272. // Setup the main graph overall details
  273. BGChart.xAxis.valueFormatter = ChartXValueFormatter()
  274. BGChart.xAxis.granularity = 1800
  275. BGChart.xAxis.labelTextColor = NSUIColor.label
  276. BGChart.xAxis.labelPosition = XAxis.LabelPosition.bottom
  277. BGChart.xAxis.drawGridLinesEnabled = false
  278. BGChart.leftAxis.enabled = true
  279. BGChart.leftAxis.labelPosition = YAxis.LabelPosition.insideChart
  280. BGChart.leftAxis.axisMaximum = maxBasal
  281. BGChart.leftAxis.axisMinimum = 0
  282. BGChart.leftAxis.drawGridLinesEnabled = false
  283. BGChart.leftAxis.granularityEnabled = true
  284. BGChart.leftAxis.granularity = 0.5
  285. BGChart.rightAxis.labelTextColor = NSUIColor.label
  286. BGChart.rightAxis.labelPosition = YAxis.LabelPosition.insideChart
  287. BGChart.rightAxis.axisMinimum = 0.0
  288. BGChart.rightAxis.axisMaximum = Double(maxBG)
  289. BGChart.rightAxis.gridLineDashLengths = [5.0, 5.0]
  290. BGChart.rightAxis.drawGridLinesEnabled = false
  291. BGChart.rightAxis.valueFormatter = ChartYMMOLValueFormatter()
  292. BGChart.rightAxis.granularityEnabled = true
  293. BGChart.rightAxis.granularity = 50
  294. BGChart.maxHighlightDistance = 15.0
  295. BGChart.legend.enabled = false
  296. BGChart.scaleYEnabled = false
  297. BGChart.drawGridBackgroundEnabled = true
  298. BGChart.gridBackgroundColor = NSUIColor.secondarySystemBackground
  299. BGChart.highlightValue(nil, callDelegate: false)
  300. BGChart.data = data
  301. BGChart.setExtraOffsets(left: 10, top: 10, right: 10, bottom: 10)
  302. }
  303. func createNowAndDIALines() {
  304. BGChart.xAxis.removeAllLimitLines()
  305. let ul = ChartLimitLine()
  306. ul.limit = Double(dateTimeUtils.getNowTimeIntervalUTC())
  307. ul.lineColor = NSUIColor.systemGray.withAlphaComponent(0.5)
  308. ul.lineWidth = 1
  309. BGChart.xAxis.addLimitLine(ul)
  310. if UserDefaultsRepository.showDIALines.value {
  311. for i in 1..<7 {
  312. let ul = ChartLimitLine()
  313. ul.limit = Double(dateTimeUtils.getNowTimeIntervalUTC() - Double(i * 60 * 60))
  314. ul.lineColor = NSUIColor.systemGray.withAlphaComponent(0.3)
  315. let dash = 10.0 - Double(i)
  316. let space = 5.0 + Double(i)
  317. ul.lineDashLengths = [CGFloat(dash), CGFloat(space)]
  318. ul.lineWidth = 1
  319. BGChart.xAxis.addLimitLine(ul)
  320. }
  321. }
  322. }
  323. func createMidnightLines() {
  324. // Draw a line at midnight: useful when showing multiple days of data
  325. if UserDefaultsRepository.showMidnightLines.value {
  326. var midnightTimeInterval = dateTimeUtils.getTimeIntervalMidnightToday()
  327. let graphHours = 24 * UserDefaultsRepository.downloadDays.value
  328. let graphStart = dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours)
  329. while midnightTimeInterval > graphStart {
  330. let ul = ChartLimitLine()
  331. ul.limit = Double(midnightTimeInterval)
  332. ul.lineColor = NSUIColor.systemIndigo.withAlphaComponent(0.5)
  333. ul.lineDashLengths = [CGFloat(2), CGFloat(5)]
  334. ul.lineWidth = 1
  335. BGChart.xAxis.addLimitLine(ul)
  336. midnightTimeInterval = midnightTimeInterval.advanced(by: -24*60*60)
  337. }
  338. }
  339. }
  340. func updateBGGraphSettings() {
  341. let dataIndex = 0
  342. let dataIndexPrediction = 1
  343. let lineBG = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  344. let linePrediction = BGChart.lineData!.dataSets[dataIndexPrediction] as! LineChartDataSet
  345. if UserDefaultsRepository.showLines.value {
  346. lineBG.lineWidth = 2
  347. linePrediction.lineWidth = 2
  348. } else {
  349. lineBG.lineWidth = 0
  350. linePrediction.lineWidth = 0
  351. }
  352. if UserDefaultsRepository.showDots.value {
  353. lineBG.drawCirclesEnabled = true
  354. linePrediction.drawCirclesEnabled = true
  355. } else {
  356. lineBG.drawCirclesEnabled = false
  357. linePrediction.drawCirclesEnabled = false
  358. }
  359. BGChart.rightAxis.axisMinimum = 0
  360. // Clear limit lines so they don't add multiples when changing the settings
  361. BGChart.rightAxis.removeAllLimitLines()
  362. //Add lower red line based on low alert value
  363. let ll = ChartLimitLine()
  364. ll.limit = Double(UserDefaultsRepository.lowLine.value)
  365. ll.lineColor = NSUIColor.systemRed.withAlphaComponent(0.5)
  366. BGChart.rightAxis.addLimitLine(ll)
  367. //Add upper yellow line based on low alert value
  368. let ul = ChartLimitLine()
  369. ul.limit = Double(UserDefaultsRepository.highLine.value)
  370. ul.lineColor = NSUIColor.systemYellow.withAlphaComponent(0.5)
  371. BGChart.rightAxis.addLimitLine(ul)
  372. // Re-create vertical markers in case their settings changed
  373. BGChart.xAxis.removeAllLimitLines()
  374. createNowAndDIALines()
  375. createMidnightLines()
  376. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  377. BGChart.data?.notifyDataChanged()
  378. BGChart.notifyDataSetChanged()
  379. }
  380. func updateBGGraph() {
  381. if UserDefaultsRepository.debugLog.value { writeDebugLog(value: "##### Start BG Graph #####") }
  382. let dataIndex = 0
  383. let entries = bgData
  384. if entries.count < 1 { return }
  385. var mainChart = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  386. var smallChart = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  387. mainChart.clear()
  388. smallChart.clear()
  389. var maxBGOffset: Float = 50
  390. var colors = [NSUIColor]()
  391. for i in 0..<entries.count{
  392. if Float(entries[i].sgv) > topBG - maxBGOffset {
  393. topBG = Float(entries[i].sgv) + maxBGOffset
  394. }
  395. let value = ChartDataEntry(x: Double(entries[i].date), y: Double(entries[i].sgv), data: formatPillText(line1: bgUnits.toDisplayUnits(String(entries[i].sgv)), time: entries[i].date))
  396. if UserDefaultsRepository.debugLog.value { writeDebugLog(value: "BG: " + value.description) }
  397. mainChart.addEntry(value)
  398. smallChart.addEntry(value)
  399. if Double(entries[i].sgv) >= Double(UserDefaultsRepository.highLine.value) {
  400. colors.append(NSUIColor.systemYellow)
  401. } else if Double(entries[i].sgv) <= Double(UserDefaultsRepository.lowLine.value) {
  402. colors.append(NSUIColor.systemRed)
  403. } else {
  404. colors.append(NSUIColor.systemGreen)
  405. }
  406. }
  407. if UserDefaultsRepository.debugLog.value { writeDebugLog(value: "Total Graph BGs: " + mainChart.entries.count.description) }
  408. // Set Colors
  409. let lineBG = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  410. let lineBGSmall = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  411. lineBG.colors.removeAll()
  412. lineBG.circleColors.removeAll()
  413. lineBGSmall.colors.removeAll()
  414. lineBGSmall.circleColors.removeAll()
  415. if colors.count > 0 {
  416. for i in 0..<colors.count{
  417. mainChart.addColor(colors[i])
  418. mainChart.circleColors.append(colors[i])
  419. smallChart.addColor(colors[i])
  420. smallChart.circleColors.append(colors[i])
  421. }
  422. }
  423. if UserDefaultsRepository.debugLog.value { writeDebugLog(value: "Total Colors: " + mainChart.colors.count.description) }
  424. BGChart.rightAxis.axisMaximum = Double(topBG)
  425. BGChart.setVisibleXRangeMinimum(600)
  426. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  427. BGChart.data?.notifyDataChanged()
  428. BGChart.notifyDataSetChanged()
  429. BGChartFull.rightAxis.axisMaximum = Double(topBG)
  430. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  431. BGChartFull.data?.notifyDataChanged()
  432. BGChartFull.notifyDataSetChanged()
  433. if firstGraphLoad {
  434. var scaleX = CGFloat(UserDefaultsRepository.chartScaleX.value)
  435. print("Scale: \(scaleX)")
  436. if( scaleX > CGFloat(ScaleXMax) ) {
  437. scaleX = CGFloat(ScaleXMax)
  438. UserDefaultsRepository.chartScaleX.value = ScaleXMax
  439. }
  440. BGChart.zoom(scaleX: scaleX, scaleY: 1, x: 1, y: 1)
  441. firstGraphLoad = false
  442. }
  443. // Move to current reading everytime new readings load
  444. BGChart.moveViewToAnimated(xValue: dateTimeUtils.getNowTimeIntervalUTC() - (BGChart.visibleXRange * 0.7), yValue: 0.0, axis: .right, duration: 1, easingOption: .easeInBack)
  445. }
  446. func updatePredictionGraph() {
  447. let dataIndex = 1
  448. var mainChart = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  449. var smallChart = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  450. mainChart.clear()
  451. smallChart.clear()
  452. if UserDefaultsRepository.debugLog.value { self.writeDebugLog(value: "Graph: print prediction") }
  453. var colors = [NSUIColor]()
  454. let maxBGOffset: Float = 20
  455. for i in 0..<predictionData.count {
  456. var predictionVal = Double(predictionData[i].sgv)
  457. if Float(predictionVal) > topBG - maxBGOffset {
  458. topBG = Float(predictionVal) + maxBGOffset
  459. }
  460. if i == 0 {
  461. if UserDefaultsRepository.showDots.value {
  462. colors.append(NSUIColor.systemPurple.withAlphaComponent(0.0))
  463. } else {
  464. colors.append(NSUIColor.systemPurple.withAlphaComponent(1.0))
  465. }
  466. } else if predictionVal > 400 {
  467. predictionVal = 400
  468. colors.append(NSUIColor.systemYellow)
  469. } else if predictionVal < 0 {
  470. predictionVal = 0
  471. colors.append(NSUIColor.systemRed)
  472. } else {
  473. colors.append(NSUIColor.systemPurple)
  474. }
  475. let value = ChartDataEntry(x: predictionData[i].date, y: predictionVal, data: formatPillText(line1: bgUnits.toDisplayUnits(String(predictionData[i].sgv)), time: predictionData[i].date))
  476. mainChart.addEntry(value)
  477. smallChart.addEntry(value)
  478. }
  479. smallChart.circleColors.removeAll()
  480. smallChart.colors.removeAll()
  481. mainChart.colors.removeAll()
  482. mainChart.circleColors.removeAll()
  483. if colors.count > 0 {
  484. if UserDefaultsRepository.debugLog.value { self.writeDebugLog(value: "Graph: prediction colors") }
  485. for i in 0..<colors.count{
  486. mainChart.addColor(colors[i])
  487. mainChart.circleColors.append(colors[i])
  488. smallChart.addColor(colors[i])
  489. smallChart.circleColors.append(colors[i])
  490. }
  491. }
  492. BGChart.rightAxis.axisMaximum = Double(topBG)
  493. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  494. BGChart.data?.notifyDataChanged()
  495. BGChart.notifyDataSetChanged()
  496. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  497. BGChartFull.data?.notifyDataChanged()
  498. BGChartFull.notifyDataSetChanged()
  499. }
  500. func updateBasalGraph() {
  501. var dataIndex = 2
  502. BGChart.lineData?.dataSets[dataIndex].clear()
  503. BGChartFull.lineData?.dataSets[dataIndex].clear()
  504. var maxBasal = UserDefaultsRepository.minBasalScale.value
  505. var maxBasalSmall: Double = 0.0
  506. for i in 0..<basalData.count{
  507. let value = ChartDataEntry(x: Double(basalData[i].date), y: Double(basalData[i].basalRate), data: formatPillText(line1: String(basalData[i].basalRate), time: basalData[i].date))
  508. BGChart.data?.dataSets[dataIndex].addEntry(value)
  509. if UserDefaultsRepository.smallGraphTreatments.value {
  510. BGChartFull.data?.dataSets[dataIndex].addEntry(value)
  511. }
  512. if basalData[i].basalRate > maxBasal {
  513. maxBasal = basalData[i].basalRate
  514. }
  515. if basalData[i].basalRate > maxBasalSmall {
  516. maxBasalSmall = basalData[i].basalRate
  517. }
  518. }
  519. BGChart.leftAxis.axisMaximum = maxBasal
  520. BGChartFull.leftAxis.axisMaximum = maxBasalSmall
  521. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  522. BGChart.data?.notifyDataChanged()
  523. BGChart.notifyDataSetChanged()
  524. if UserDefaultsRepository.smallGraphTreatments.value {
  525. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  526. BGChartFull.data?.notifyDataChanged()
  527. BGChartFull.notifyDataSetChanged()
  528. }
  529. }
  530. func updateBasalScheduledGraph() {
  531. var dataIndex = 5
  532. BGChart.lineData?.dataSets[dataIndex].clear()
  533. BGChartFull.lineData?.dataSets[dataIndex].clear()
  534. for i in 0..<basalScheduleData.count{
  535. let value = ChartDataEntry(x: Double(basalScheduleData[i].date), y: Double(basalScheduleData[i].basalRate))
  536. BGChart.data?.dataSets[dataIndex].addEntry(value)
  537. if UserDefaultsRepository.smallGraphTreatments.value {
  538. BGChartFull.data?.dataSets[dataIndex].addEntry(value)
  539. }
  540. }
  541. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  542. BGChart.data?.notifyDataChanged()
  543. BGChart.notifyDataSetChanged()
  544. if UserDefaultsRepository.smallGraphTreatments.value {
  545. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  546. BGChartFull.data?.notifyDataChanged()
  547. BGChartFull.notifyDataSetChanged()
  548. }
  549. }
  550. func updateBolusGraph() {
  551. var dataIndex = 3
  552. var yTop: Double = 370
  553. var yBottom: Double = 345
  554. var mainChart = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  555. var smallChart = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  556. mainChart.clear()
  557. smallChart.clear()
  558. var colors = [NSUIColor]()
  559. for i in 0..<bolusData.count{
  560. let formatter = NumberFormatter()
  561. formatter.minimumFractionDigits = 0
  562. formatter.maximumFractionDigits = 2
  563. formatter.minimumIntegerDigits = 0
  564. // Check overlapping carbs to shift left if needed
  565. let bolusShift = findNextBolusTime(timeWithin: 240, needle: bolusData[i].date, haystack: bolusData, startingIndex: i)
  566. var dateTimeStamp = bolusData[i].date
  567. // Alpha colors for DIA
  568. let nowTime = dateTimeUtils.getNowTimeIntervalUTC()
  569. let diffTimeHours = (nowTime - dateTimeStamp) / 60 / 60
  570. if diffTimeHours <= 1 {
  571. colors.append(NSUIColor.systemBlue.withAlphaComponent(1.0))
  572. } else if diffTimeHours > 6 {
  573. colors.append(NSUIColor.systemBlue.withAlphaComponent(0.25))
  574. } else {
  575. let thisAlpha = 1.0 - (0.15 * diffTimeHours)
  576. colors.append(NSUIColor.systemBlue.withAlphaComponent(CGFloat(thisAlpha)))
  577. }
  578. if bolusShift {
  579. // Move it half the distance between BG readings
  580. dateTimeStamp = dateTimeStamp - 150
  581. }
  582. // skip if outside of visible area
  583. let graphHours = 24 * UserDefaultsRepository.downloadDays.value
  584. if dateTimeStamp < dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours) { continue }
  585. let dot = ChartDataEntry(x: Double(dateTimeStamp), y: Double(bolusData[i].sgv), data: formatter.string(from: NSNumber(value: bolusData[i].value)))
  586. mainChart.addEntry(dot)
  587. if UserDefaultsRepository.smallGraphTreatments.value {
  588. smallChart.addEntry(dot)
  589. }
  590. }
  591. // Set Colors
  592. let lineBolus = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  593. let lineBolusSmall = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  594. lineBolus.colors.removeAll()
  595. lineBolus.circleColors.removeAll()
  596. lineBolusSmall.colors.removeAll()
  597. lineBolusSmall.circleColors.removeAll()
  598. if colors.count > 0 {
  599. for i in 0..<colors.count{
  600. mainChart.addColor(colors[i])
  601. mainChart.circleColors.append(colors[i])
  602. smallChart.addColor(colors[i])
  603. smallChart.circleColors.append(colors[i])
  604. }
  605. }
  606. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  607. BGChart.data?.notifyDataChanged()
  608. BGChart.notifyDataSetChanged()
  609. if UserDefaultsRepository.smallGraphTreatments.value {
  610. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  611. BGChartFull.data?.notifyDataChanged()
  612. BGChartFull.notifyDataSetChanged()
  613. }
  614. }
  615. func updateCarbGraph() {
  616. var dataIndex = 4
  617. var mainChart = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  618. var smallChart = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  619. mainChart.clear()
  620. smallChart.clear()
  621. var colors = [NSUIColor]()
  622. for i in 0..<carbData.count{
  623. let formatter = NumberFormatter()
  624. formatter.minimumFractionDigits = 0
  625. formatter.maximumFractionDigits = 2
  626. formatter.minimumIntegerDigits = 1
  627. var valueString: String = formatter.string(from: NSNumber(value: carbData[i].value))!
  628. var hours = 3
  629. if carbData[i].absorptionTime > 0 && UserDefaultsRepository.showAbsorption.value {
  630. hours = carbData[i].absorptionTime / 60
  631. valueString += " " + String(hours) + "h"
  632. }
  633. // Check overlapping carbs to shift left if needed
  634. let carbShift = findNextCarbTime(timeWithin: 250, needle: carbData[i].date, haystack: carbData, startingIndex: i)
  635. var dateTimeStamp = carbData[i].date
  636. // Alpha colors for DIA
  637. let nowTime = dateTimeUtils.getNowTimeIntervalUTC()
  638. let diffTimeHours = (nowTime - dateTimeStamp) / 60 / 60
  639. if diffTimeHours <= 0.5 {
  640. colors.append(NSUIColor.systemOrange.withAlphaComponent(1.0))
  641. } else if diffTimeHours > Double(hours) {
  642. colors.append(NSUIColor.systemOrange.withAlphaComponent(0.25))
  643. } else {
  644. let thisAlpha = 1.0 - ((0.75 / Double(hours)) * diffTimeHours)
  645. colors.append(NSUIColor.systemOrange.withAlphaComponent(CGFloat(thisAlpha)))
  646. }
  647. // skip if outside of visible area
  648. let graphHours = 24 * UserDefaultsRepository.downloadDays.value
  649. if dateTimeStamp < dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours) { continue }
  650. if carbShift {
  651. dateTimeStamp = dateTimeStamp - 250
  652. }
  653. let dot = ChartDataEntry(x: Double(dateTimeStamp), y: Double(carbData[i].sgv), data: valueString)
  654. BGChart.data?.dataSets[dataIndex].addEntry(dot)
  655. if UserDefaultsRepository.smallGraphTreatments.value {
  656. BGChartFull.data?.dataSets[dataIndex].addEntry(dot)
  657. }
  658. }
  659. // Set Colors
  660. let lineCarbs = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  661. let lineCarbsSmall = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  662. lineCarbs.colors.removeAll()
  663. lineCarbs.circleColors.removeAll()
  664. lineCarbsSmall.colors.removeAll()
  665. lineCarbsSmall.circleColors.removeAll()
  666. if colors.count > 0 {
  667. for i in 0..<colors.count{
  668. mainChart.addColor(colors[i])
  669. mainChart.circleColors.append(colors[i])
  670. smallChart.addColor(colors[i])
  671. smallChart.circleColors.append(colors[i])
  672. }
  673. }
  674. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  675. BGChart.data?.notifyDataChanged()
  676. BGChart.notifyDataSetChanged()
  677. if UserDefaultsRepository.smallGraphTreatments.value {
  678. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  679. BGChartFull.data?.notifyDataChanged()
  680. BGChartFull.notifyDataSetChanged()
  681. }
  682. }
  683. func updateBGCheckGraph() {
  684. var dataIndex = 7
  685. BGChart.lineData?.dataSets[dataIndex].clear()
  686. BGChartFull.lineData?.dataSets[dataIndex].clear()
  687. for i in 0..<bgCheckData.count{
  688. let formatter = NumberFormatter()
  689. formatter.minimumFractionDigits = 0
  690. formatter.maximumFractionDigits = 2
  691. formatter.minimumIntegerDigits = 1
  692. // skip if outside of visible area
  693. let graphHours = 24 * UserDefaultsRepository.downloadDays.value
  694. if bgCheckData[i].date < dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours) { continue }
  695. let value = ChartDataEntry(x: Double(bgCheckData[i].date), y: Double(bgCheckData[i].sgv), data: formatPillText(line1: bgUnits.toDisplayUnits(String(bgCheckData[i].sgv)), time: bgCheckData[i].date))
  696. BGChart.data?.dataSets[dataIndex].addEntry(value)
  697. if UserDefaultsRepository.smallGraphTreatments.value {
  698. BGChartFull.data?.dataSets[dataIndex].addEntry(value)
  699. }
  700. }
  701. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  702. BGChart.data?.notifyDataChanged()
  703. BGChart.notifyDataSetChanged()
  704. if UserDefaultsRepository.smallGraphTreatments.value {
  705. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  706. BGChartFull.data?.notifyDataChanged()
  707. BGChartFull.notifyDataSetChanged()
  708. }
  709. }
  710. func updateSuspendGraph() {
  711. var dataIndex = 8
  712. BGChart.lineData?.dataSets[dataIndex].clear()
  713. BGChartFull.lineData?.dataSets[dataIndex].clear()
  714. let thisData = suspendGraphData
  715. for i in 0..<thisData.count{
  716. // skip if outside of visible area
  717. let graphHours = 24 * UserDefaultsRepository.downloadDays.value
  718. if thisData[i].date < dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours) { continue }
  719. let value = ChartDataEntry(x: Double(thisData[i].date), y: Double(thisData[i].sgv), data: formatPillText(line1: "Suspend Pump", time: thisData[i].date))
  720. BGChart.data?.dataSets[dataIndex].addEntry(value)
  721. if UserDefaultsRepository.smallGraphTreatments.value {
  722. BGChartFull.data?.dataSets[dataIndex].addEntry(value)
  723. }
  724. }
  725. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  726. BGChart.data?.notifyDataChanged()
  727. BGChart.notifyDataSetChanged()
  728. if UserDefaultsRepository.smallGraphTreatments.value {
  729. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  730. BGChartFull.data?.notifyDataChanged()
  731. BGChartFull.notifyDataSetChanged()
  732. }
  733. }
  734. func updateResumeGraph() {
  735. var dataIndex = 9
  736. BGChart.lineData?.dataSets[dataIndex].clear()
  737. BGChartFull.lineData?.dataSets[dataIndex].clear()
  738. let thisData = resumeGraphData
  739. for i in 0..<thisData.count{
  740. // skip if outside of visible area
  741. let graphHours = 24 * UserDefaultsRepository.downloadDays.value
  742. if thisData[i].date < dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours) { continue }
  743. let value = ChartDataEntry(x: Double(thisData[i].date), y: Double(thisData[i].sgv), data: formatPillText(line1: "Resume Pump", time: thisData[i].date))
  744. BGChart.data?.dataSets[dataIndex].addEntry(value)
  745. if UserDefaultsRepository.smallGraphTreatments.value {
  746. BGChartFull.data?.dataSets[dataIndex].addEntry(value)
  747. }
  748. }
  749. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  750. BGChart.data?.notifyDataChanged()
  751. BGChart.notifyDataSetChanged()
  752. if UserDefaultsRepository.smallGraphTreatments.value {
  753. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  754. BGChartFull.data?.notifyDataChanged()
  755. BGChartFull.notifyDataSetChanged()
  756. }
  757. }
  758. func updateSensorStart() {
  759. var dataIndex = 10
  760. BGChart.lineData?.dataSets[dataIndex].clear()
  761. BGChartFull.lineData?.dataSets[dataIndex].clear()
  762. let thisData = sensorStartGraphData
  763. for i in 0..<thisData.count{
  764. // skip if outside of visible area
  765. let graphHours = 24 * UserDefaultsRepository.downloadDays.value
  766. if thisData[i].date < dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours) { continue }
  767. let value = ChartDataEntry(x: Double(thisData[i].date), y: Double(thisData[i].sgv), data: formatPillText(line1: "Start Sensor", time: thisData[i].date))
  768. BGChart.data?.dataSets[dataIndex].addEntry(value)
  769. if UserDefaultsRepository.smallGraphTreatments.value {
  770. BGChartFull.data?.dataSets[dataIndex].addEntry(value)
  771. }
  772. }
  773. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  774. BGChart.data?.notifyDataChanged()
  775. BGChart.notifyDataSetChanged()
  776. if UserDefaultsRepository.smallGraphTreatments.value {
  777. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  778. BGChartFull.data?.notifyDataChanged()
  779. BGChartFull.notifyDataSetChanged()
  780. }
  781. }
  782. func updateNotes() {
  783. var dataIndex = 11
  784. BGChart.lineData?.dataSets[dataIndex].clear()
  785. BGChartFull.lineData?.dataSets[dataIndex].clear()
  786. let thisData = noteGraphData
  787. for i in 0..<thisData.count{
  788. // skip if outside of visible area
  789. let graphHours = 24 * UserDefaultsRepository.downloadDays.value
  790. if thisData[i].date < dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours) { continue }
  791. let value = ChartDataEntry(x: Double(thisData[i].date), y: Double(thisData[i].sgv), data: formatPillText(line1: thisData[i].note, time: thisData[i].date))
  792. BGChart.data?.dataSets[dataIndex].addEntry(value)
  793. if UserDefaultsRepository.smallGraphTreatments.value {
  794. BGChartFull.data?.dataSets[dataIndex].addEntry(value)
  795. }
  796. }
  797. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  798. BGChart.data?.notifyDataChanged()
  799. BGChart.notifyDataSetChanged()
  800. if UserDefaultsRepository.smallGraphTreatments.value {
  801. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  802. BGChartFull.data?.notifyDataChanged()
  803. BGChartFull.notifyDataSetChanged()
  804. }
  805. }
  806. func createSmallBGGraph(){
  807. let entries = bgData
  808. var bgChartEntry = [ChartDataEntry]()
  809. var colors = [NSUIColor]()
  810. var maxBG: Float = UserDefaultsRepository.minBGScale.value
  811. let lineBG = LineChartDataSet(entries:bgChartEntry, label: "")
  812. lineBG.drawCirclesEnabled = false
  813. //line2.setDrawHighlightIndicators(false)
  814. lineBG.highlightEnabled = true
  815. lineBG.drawHorizontalHighlightIndicatorEnabled = false
  816. lineBG.drawVerticalHighlightIndicatorEnabled = false
  817. lineBG.highlightColor = NSUIColor.label
  818. lineBG.drawValuesEnabled = false
  819. lineBG.lineWidth = 1.5
  820. lineBG.axisDependency = YAxis.AxisDependency.right
  821. // Setup Prediction line details
  822. var predictionChartEntry = [ChartDataEntry]()
  823. let linePrediction = LineChartDataSet(entries:predictionChartEntry, label: "")
  824. linePrediction.drawCirclesEnabled = false
  825. //line2.setDrawHighlightIndicators(false)
  826. linePrediction.setColor(NSUIColor.systemPurple)
  827. linePrediction.highlightEnabled = true
  828. linePrediction.drawHorizontalHighlightIndicatorEnabled = false
  829. linePrediction.drawVerticalHighlightIndicatorEnabled = false
  830. linePrediction.highlightColor = NSUIColor.label
  831. linePrediction.drawValuesEnabled = false
  832. linePrediction.lineWidth = 1.5
  833. linePrediction.axisDependency = YAxis.AxisDependency.right
  834. // create Basal graph data
  835. var chartEntry = [ChartDataEntry]()
  836. var maxBasal = UserDefaultsRepository.minBasalScale.value
  837. let lineBasal = LineChartDataSet(entries:chartEntry, label: "")
  838. lineBasal.setDrawHighlightIndicators(false)
  839. lineBasal.setColor(NSUIColor.systemBlue, alpha: 0.5)
  840. lineBasal.lineWidth = 0
  841. lineBasal.drawFilledEnabled = true
  842. lineBasal.fillColor = NSUIColor.systemBlue
  843. lineBasal.fillAlpha = 0.35
  844. lineBasal.drawCirclesEnabled = false
  845. lineBasal.axisDependency = YAxis.AxisDependency.left
  846. lineBasal.highlightEnabled = false
  847. lineBasal.drawValuesEnabled = false
  848. lineBasal.fillFormatter = basalFillFormatter()
  849. // Boluses
  850. var chartEntryBolus = [ChartDataEntry]()
  851. let lineBolus = LineChartDataSet(entries:chartEntryBolus, label: "")
  852. lineBolus.circleRadius = 2
  853. lineBolus.circleColors = [NSUIColor.systemBlue.withAlphaComponent(0.75)]
  854. lineBolus.drawCircleHoleEnabled = false
  855. lineBolus.setDrawHighlightIndicators(false)
  856. lineBolus.setColor(NSUIColor.systemBlue, alpha: 1.0)
  857. lineBolus.lineWidth = 0
  858. lineBolus.axisDependency = YAxis.AxisDependency.right
  859. lineBolus.valueFormatter = ChartYDataValueFormatter()
  860. lineBolus.valueTextColor = NSUIColor.label
  861. lineBolus.fillColor = NSUIColor.systemBlue
  862. lineBolus.fillAlpha = 0.6
  863. lineBolus.drawCirclesEnabled = true
  864. lineBolus.drawFilledEnabled = false
  865. lineBolus.drawValuesEnabled = false
  866. lineBolus.highlightEnabled = false
  867. // Carbs
  868. var chartEntryCarbs = [ChartDataEntry]()
  869. let lineCarbs = LineChartDataSet(entries:chartEntryCarbs, label: "")
  870. lineCarbs.circleRadius = 2
  871. lineCarbs.circleColors = [NSUIColor.systemOrange.withAlphaComponent(0.75)]
  872. lineCarbs.drawCircleHoleEnabled = false
  873. lineCarbs.setDrawHighlightIndicators(false)
  874. lineCarbs.setColor(NSUIColor.systemBlue, alpha: 1.0)
  875. lineCarbs.lineWidth = 0
  876. lineCarbs.axisDependency = YAxis.AxisDependency.right
  877. lineCarbs.valueFormatter = ChartYDataValueFormatter()
  878. lineCarbs.valueTextColor = NSUIColor.label
  879. lineCarbs.fillColor = NSUIColor.systemOrange
  880. lineCarbs.fillAlpha = 0.6
  881. lineCarbs.drawCirclesEnabled = true
  882. lineCarbs.drawFilledEnabled = false
  883. lineCarbs.drawValuesEnabled = false
  884. lineCarbs.highlightEnabled = false
  885. // create Scheduled Basal graph data
  886. var chartBasalScheduledEntry = [ChartDataEntry]()
  887. let lineBasalScheduled = LineChartDataSet(entries:chartBasalScheduledEntry, label: "")
  888. lineBasalScheduled.setDrawHighlightIndicators(false)
  889. lineBasalScheduled.setColor(NSUIColor.systemBlue, alpha: 0.8)
  890. lineBasalScheduled.lineWidth = 0.5
  891. lineBasalScheduled.drawFilledEnabled = false
  892. lineBasalScheduled.drawCirclesEnabled = false
  893. lineBasalScheduled.axisDependency = YAxis.AxisDependency.left
  894. lineBasalScheduled.highlightEnabled = false
  895. lineBasalScheduled.drawValuesEnabled = false
  896. lineBasalScheduled.lineDashLengths = [2, 1]
  897. // create Override graph data
  898. var chartOverrideEntry = [ChartDataEntry]()
  899. let lineOverride = LineChartDataSet(entries:chartOverrideEntry, label: "")
  900. lineOverride.setDrawHighlightIndicators(false)
  901. lineOverride.lineWidth = 0
  902. lineOverride.drawFilledEnabled = true
  903. lineOverride.fillFormatter = OverrideFillFormatter()
  904. lineOverride.fillColor = NSUIColor.systemGreen
  905. lineOverride.fillAlpha = 0.6
  906. lineOverride.drawCirclesEnabled = false
  907. lineOverride.axisDependency = YAxis.AxisDependency.right
  908. lineOverride.highlightEnabled = true
  909. lineOverride.drawValuesEnabled = false
  910. // BG Check
  911. var chartEntryBGCheck = [ChartDataEntry]()
  912. let lineBGCheck = LineChartDataSet(entries:chartEntryBGCheck, label: "")
  913. lineBGCheck.circleRadius = 2
  914. lineBGCheck.circleColors = [NSUIColor.systemRed.withAlphaComponent(0.75)]
  915. lineBGCheck.drawCircleHoleEnabled = false
  916. lineBGCheck.setDrawHighlightIndicators(false)
  917. lineBGCheck.setColor(NSUIColor.systemRed, alpha: 1.0)
  918. lineBGCheck.drawCirclesEnabled = true
  919. lineBGCheck.lineWidth = 0
  920. lineBGCheck.highlightEnabled = false
  921. lineBGCheck.axisDependency = YAxis.AxisDependency.right
  922. lineBGCheck.valueFormatter = ChartYDataValueFormatter()
  923. lineBGCheck.drawValuesEnabled = false
  924. // Suspend Pump
  925. var chartEntrySuspend = [ChartDataEntry]()
  926. let lineSuspend = LineChartDataSet(entries:chartEntrySuspend, label: "")
  927. lineSuspend.circleRadius = 2
  928. lineSuspend.circleColors = [NSUIColor.systemTeal.withAlphaComponent(0.75)]
  929. lineSuspend.drawCircleHoleEnabled = false
  930. lineSuspend.setDrawHighlightIndicators(false)
  931. lineSuspend.setColor(NSUIColor.systemGray2, alpha: 1.0)
  932. lineSuspend.drawCirclesEnabled = true
  933. lineSuspend.lineWidth = 0
  934. lineSuspend.highlightEnabled = false
  935. lineSuspend.axisDependency = YAxis.AxisDependency.right
  936. lineSuspend.valueFormatter = ChartYDataValueFormatter()
  937. lineSuspend.drawValuesEnabled = false
  938. // Resume Pump
  939. var chartEntryResume = [ChartDataEntry]()
  940. let lineResume = LineChartDataSet(entries:chartEntryResume, label: "")
  941. lineResume.circleRadius = 2
  942. lineResume.circleColors = [NSUIColor.systemTeal.withAlphaComponent(0.75)]
  943. lineResume.drawCircleHoleEnabled = false
  944. lineResume.setDrawHighlightIndicators(false)
  945. lineResume.setColor(NSUIColor.systemGray4, alpha: 1.0)
  946. lineResume.drawCirclesEnabled = true
  947. lineResume.lineWidth = 0
  948. lineResume.highlightEnabled = false
  949. lineResume.axisDependency = YAxis.AxisDependency.right
  950. lineResume.valueFormatter = ChartYDataValueFormatter()
  951. lineResume.drawValuesEnabled = false
  952. // Sensor Start
  953. var chartEntrySensor = [ChartDataEntry]()
  954. let lineSensor = LineChartDataSet(entries:chartEntrySensor, label: "")
  955. lineSensor.circleRadius = 2
  956. lineSensor.circleColors = [NSUIColor.systemIndigo.withAlphaComponent(0.75)]
  957. lineSensor.drawCircleHoleEnabled = false
  958. lineSensor.setDrawHighlightIndicators(false)
  959. lineSensor.setColor(NSUIColor.systemGray3, alpha: 1.0)
  960. lineSensor.drawCirclesEnabled = true
  961. lineSensor.lineWidth = 0
  962. lineSensor.highlightEnabled = false
  963. lineSensor.axisDependency = YAxis.AxisDependency.right
  964. lineSensor.valueFormatter = ChartYDataValueFormatter()
  965. lineSensor.drawValuesEnabled = false
  966. // Notes
  967. var chartEntryNote = [ChartDataEntry]()
  968. let lineNote = LineChartDataSet(entries:chartEntryNote, label: "")
  969. lineNote.circleRadius = 2
  970. lineNote.circleColors = [NSUIColor.systemGray.withAlphaComponent(0.75)]
  971. lineNote.drawCircleHoleEnabled = false
  972. lineNote.setDrawHighlightIndicators(false)
  973. lineNote.setColor(NSUIColor.systemGray3, alpha: 1.0)
  974. lineNote.drawCirclesEnabled = true
  975. lineNote.lineWidth = 0
  976. lineNote.highlightEnabled = false
  977. lineNote.axisDependency = YAxis.AxisDependency.right
  978. lineNote.valueFormatter = ChartYDataValueFormatter()
  979. lineNote.drawValuesEnabled = false
  980. // Setup the chart data of all lines
  981. let data = LineChartData()
  982. data.addDataSet(lineBG) // Dataset 0
  983. data.addDataSet(linePrediction) // Dataset 1
  984. data.addDataSet(lineBasal) // Dataset 2
  985. data.addDataSet(lineBolus) // Dataset 3
  986. data.addDataSet(lineCarbs) // Dataset 4
  987. data.addDataSet(lineBasalScheduled) // Dataset 5
  988. data.addDataSet(lineOverride) // Dataset 6
  989. data.addDataSet(lineBGCheck) // Dataset 7
  990. data.addDataSet(lineSuspend) // Dataset 8
  991. data.addDataSet(lineResume) // Dataset 9
  992. data.addDataSet(lineSensor) // Dataset 10
  993. data.addDataSet(lineNote) // Dataset 11
  994. BGChartFull.highlightPerDragEnabled = true
  995. BGChartFull.leftAxis.enabled = false
  996. BGChartFull.leftAxis.axisMaximum = maxBasal
  997. BGChartFull.leftAxis.axisMinimum = 0
  998. BGChartFull.rightAxis.enabled = false
  999. BGChartFull.rightAxis.axisMinimum = 0.0
  1000. BGChartFull.rightAxis.axisMaximum = Double(maxBG)
  1001. BGChartFull.xAxis.enabled = false
  1002. BGChartFull.legend.enabled = false
  1003. BGChartFull.scaleYEnabled = false
  1004. BGChartFull.scaleXEnabled = false
  1005. BGChartFull.drawGridBackgroundEnabled = false
  1006. BGChartFull.data = data
  1007. }
  1008. func updateOverrideGraph() {
  1009. var dataIndex = 6
  1010. var yTop: Double = Double(topBG - 5)
  1011. var yBottom: Double = Double(topBG - 25)
  1012. var chart = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  1013. var smallChart = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  1014. chart.clear()
  1015. smallChart.clear()
  1016. let thisData = overrideGraphData
  1017. var colors = [NSUIColor]()
  1018. for i in 0..<thisData.count{
  1019. let thisItem = thisData[i]
  1020. let multiplier = thisItem.insulNeedsScaleFactor as! Double * 100.0
  1021. var labelText = thisItem.reason + "\r\n"
  1022. labelText += String(Int(thisItem.insulNeedsScaleFactor * 100)) + "% "
  1023. if thisItem.correctionRange.count == 2 {
  1024. labelText += String(thisItem.correctionRange[0]) + "-" + String(thisItem.correctionRange[1])
  1025. }
  1026. if thisItem.enteredBy.count > 0 {
  1027. labelText += "\r\nEntered By: " + thisItem.enteredBy
  1028. }
  1029. // Start Dot
  1030. // Shift dots 30 seconds to create an empty 0 space between consecutive temps
  1031. let preStartDot = ChartDataEntry(x: Double(thisItem.date), y: yBottom, data: labelText)
  1032. BGChart.data?.dataSets[dataIndex].addEntry(preStartDot)
  1033. if UserDefaultsRepository.smallGraphTreatments.value {
  1034. BGChartFull.data?.dataSets[dataIndex].addEntry(preStartDot)
  1035. }
  1036. let startDot = ChartDataEntry(x: Double(thisItem.date + 1), y: yTop, data: labelText)
  1037. BGChart.data?.dataSets[dataIndex].addEntry(startDot)
  1038. if UserDefaultsRepository.smallGraphTreatments.value {
  1039. BGChartFull.data?.dataSets[dataIndex].addEntry(startDot)
  1040. }
  1041. // End Dot
  1042. let endDot = ChartDataEntry(x: Double(thisItem.endDate - 2), y: yTop, data: labelText)
  1043. BGChart.data?.dataSets[dataIndex].addEntry(endDot)
  1044. if UserDefaultsRepository.smallGraphTreatments.value {
  1045. BGChartFull.data?.dataSets[dataIndex].addEntry(endDot)
  1046. }
  1047. // Post end dot
  1048. let postEndDot = ChartDataEntry(x: Double(thisItem.endDate - 1), y: yBottom, data: labelText)
  1049. BGChart.data?.dataSets[dataIndex].addEntry(postEndDot)
  1050. if UserDefaultsRepository.smallGraphTreatments.value {
  1051. BGChartFull.data?.dataSets[dataIndex].addEntry(postEndDot)
  1052. }
  1053. }
  1054. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  1055. BGChart.data?.notifyDataChanged()
  1056. BGChart.notifyDataSetChanged()
  1057. if UserDefaultsRepository.smallGraphTreatments.value {
  1058. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  1059. BGChartFull.data?.notifyDataChanged()
  1060. BGChartFull.notifyDataSetChanged()
  1061. }
  1062. }
  1063. func formatPillText(line1: String, time: TimeInterval) -> String {
  1064. let dateFormatter = DateFormatter()
  1065. //let timezoneOffset = TimeZone.current.secondsFromGMT()
  1066. //let epochTimezoneOffset = value + Double(timezoneOffset)
  1067. if dateTimeUtils.is24Hour() {
  1068. dateFormatter.setLocalizedDateFormatFromTemplate("HH:mm")
  1069. } else {
  1070. dateFormatter.setLocalizedDateFormatFromTemplate("hh:mm")
  1071. }
  1072. //let date = Date(timeIntervalSince1970: epochTimezoneOffset)
  1073. let date = Date(timeIntervalSince1970: time)
  1074. let formattedDate = dateFormatter.string(from: date)
  1075. return line1 + "\r\n" + formattedDate
  1076. }
  1077. }