Graphs.swift 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209
  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. startGraphNowTimer()
  271. // Setup the main graph overall details
  272. BGChart.xAxis.valueFormatter = ChartXValueFormatter()
  273. BGChart.xAxis.granularity = 1800
  274. BGChart.xAxis.labelTextColor = NSUIColor.label
  275. BGChart.xAxis.labelPosition = XAxis.LabelPosition.bottom
  276. BGChart.xAxis.drawGridLinesEnabled = false
  277. BGChart.leftAxis.enabled = true
  278. BGChart.leftAxis.labelPosition = YAxis.LabelPosition.insideChart
  279. BGChart.leftAxis.axisMaximum = maxBasal
  280. BGChart.leftAxis.axisMinimum = 0
  281. BGChart.leftAxis.drawGridLinesEnabled = false
  282. BGChart.leftAxis.granularityEnabled = true
  283. BGChart.leftAxis.granularity = 0.5
  284. BGChart.rightAxis.labelTextColor = NSUIColor.label
  285. BGChart.rightAxis.labelPosition = YAxis.LabelPosition.insideChart
  286. BGChart.rightAxis.axisMinimum = 0.0
  287. BGChart.rightAxis.axisMaximum = Double(maxBG)
  288. BGChart.rightAxis.gridLineDashLengths = [5.0, 5.0]
  289. BGChart.rightAxis.drawGridLinesEnabled = false
  290. BGChart.rightAxis.valueFormatter = ChartYMMOLValueFormatter()
  291. BGChart.rightAxis.granularityEnabled = true
  292. BGChart.rightAxis.granularity = 50
  293. BGChart.maxHighlightDistance = 15.0
  294. BGChart.legend.enabled = false
  295. BGChart.scaleYEnabled = false
  296. BGChart.drawGridBackgroundEnabled = true
  297. BGChart.gridBackgroundColor = NSUIColor.secondarySystemBackground
  298. BGChart.highlightValue(nil, callDelegate: false)
  299. BGChart.data = data
  300. BGChart.setExtraOffsets(left: 10, top: 10, right: 10, bottom: 10)
  301. }
  302. func createNowAndDIALines() {
  303. BGChart.xAxis.removeAllLimitLines()
  304. let ul = ChartLimitLine()
  305. ul.limit = Double(dateTimeUtils.getNowTimeIntervalUTC())
  306. ul.lineColor = NSUIColor.systemGray.withAlphaComponent(0.5)
  307. ul.lineWidth = 1
  308. BGChart.xAxis.addLimitLine(ul)
  309. if UserDefaultsRepository.showDIALines.value {
  310. for i in 1..<7 {
  311. let ul = ChartLimitLine()
  312. ul.limit = Double(dateTimeUtils.getNowTimeIntervalUTC() - Double(i * 60 * 60))
  313. ul.lineColor = NSUIColor.systemGray.withAlphaComponent(0.3)
  314. let dash = 10.0 - Double(i)
  315. let space = 5.0 + Double(i)
  316. ul.lineDashLengths = [CGFloat(dash), CGFloat(space)]
  317. ul.lineWidth = 1
  318. BGChart.xAxis.addLimitLine(ul)
  319. }
  320. }
  321. }
  322. func updateBGGraphSettings() {
  323. let dataIndex = 0
  324. let dataIndexPrediction = 1
  325. let lineBG = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  326. let linePrediction = BGChart.lineData!.dataSets[dataIndexPrediction] as! LineChartDataSet
  327. if UserDefaultsRepository.showLines.value {
  328. lineBG.lineWidth = 2
  329. linePrediction.lineWidth = 2
  330. } else {
  331. lineBG.lineWidth = 0
  332. linePrediction.lineWidth = 0
  333. }
  334. if UserDefaultsRepository.showDots.value {
  335. lineBG.drawCirclesEnabled = true
  336. linePrediction.drawCirclesEnabled = true
  337. } else {
  338. lineBG.drawCirclesEnabled = false
  339. linePrediction.drawCirclesEnabled = false
  340. }
  341. BGChart.rightAxis.axisMinimum = 0
  342. // Clear limit lines so they don't add multiples when changing the settings
  343. BGChart.rightAxis.removeAllLimitLines()
  344. //Add lower red line based on low alert value
  345. let ll = ChartLimitLine()
  346. ll.limit = Double(UserDefaultsRepository.lowLine.value)
  347. ll.lineColor = NSUIColor.systemRed.withAlphaComponent(0.5)
  348. BGChart.rightAxis.addLimitLine(ll)
  349. //Add upper yellow line based on low alert value
  350. let ul = ChartLimitLine()
  351. ul.limit = Double(UserDefaultsRepository.highLine.value)
  352. ul.lineColor = NSUIColor.systemYellow.withAlphaComponent(0.5)
  353. BGChart.rightAxis.addLimitLine(ul)
  354. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  355. BGChart.data?.notifyDataChanged()
  356. BGChart.notifyDataSetChanged()
  357. }
  358. func updateBGGraph() {
  359. if UserDefaultsRepository.debugLog.value { writeDebugLog(value: "##### Start BG Graph #####") }
  360. let dataIndex = 0
  361. let entries = bgData
  362. if entries.count < 1 { return }
  363. var mainChart = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  364. var smallChart = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  365. mainChart.clear()
  366. smallChart.clear()
  367. var maxBGOffset: Float = 50
  368. var colors = [NSUIColor]()
  369. for i in 0..<entries.count{
  370. if Float(entries[i].sgv) > topBG - maxBGOffset {
  371. topBG = Float(entries[i].sgv) + maxBGOffset
  372. }
  373. 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))
  374. if UserDefaultsRepository.debugLog.value { writeDebugLog(value: "BG: " + value.description) }
  375. mainChart.addEntry(value)
  376. smallChart.addEntry(value)
  377. if Double(entries[i].sgv) >= Double(UserDefaultsRepository.highLine.value) {
  378. colors.append(NSUIColor.systemYellow)
  379. } else if Double(entries[i].sgv) <= Double(UserDefaultsRepository.lowLine.value) {
  380. colors.append(NSUIColor.systemRed)
  381. } else {
  382. colors.append(NSUIColor.systemGreen)
  383. }
  384. }
  385. if UserDefaultsRepository.debugLog.value { writeDebugLog(value: "Total Graph BGs: " + mainChart.entries.count.description) }
  386. // Set Colors
  387. let lineBG = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  388. let lineBGSmall = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  389. lineBG.colors.removeAll()
  390. lineBG.circleColors.removeAll()
  391. lineBGSmall.colors.removeAll()
  392. lineBGSmall.circleColors.removeAll()
  393. if colors.count > 0 {
  394. for i in 0..<colors.count{
  395. mainChart.addColor(colors[i])
  396. mainChart.circleColors.append(colors[i])
  397. smallChart.addColor(colors[i])
  398. smallChart.circleColors.append(colors[i])
  399. }
  400. }
  401. if UserDefaultsRepository.debugLog.value { writeDebugLog(value: "Total Colors: " + mainChart.colors.count.description) }
  402. BGChart.rightAxis.axisMaximum = Double(topBG)
  403. BGChart.setVisibleXRangeMinimum(600)
  404. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  405. BGChart.data?.notifyDataChanged()
  406. BGChart.notifyDataSetChanged()
  407. BGChartFull.rightAxis.axisMaximum = Double(topBG)
  408. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  409. BGChartFull.data?.notifyDataChanged()
  410. BGChartFull.notifyDataSetChanged()
  411. if firstGraphLoad {
  412. var scaleX = CGFloat(UserDefaultsRepository.chartScaleX.value)
  413. print("Scale: \(scaleX)")
  414. if( scaleX > CGFloat(ScaleXMax) ) {
  415. scaleX = CGFloat(ScaleXMax)
  416. UserDefaultsRepository.chartScaleX.value = ScaleXMax
  417. }
  418. BGChart.zoom(scaleX: scaleX, scaleY: 1, x: 1, y: 1)
  419. firstGraphLoad = false
  420. }
  421. // Move to current reading everytime new readings load
  422. BGChart.moveViewToAnimated(xValue: dateTimeUtils.getNowTimeIntervalUTC() - (BGChart.visibleXRange * 0.7), yValue: 0.0, axis: .right, duration: 1, easingOption: .easeInBack)
  423. }
  424. func updatePredictionGraph() {
  425. let dataIndex = 1
  426. var mainChart = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  427. var smallChart = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  428. mainChart.clear()
  429. smallChart.clear()
  430. if UserDefaultsRepository.debugLog.value { self.writeDebugLog(value: "Graph: print prediction") }
  431. var colors = [NSUIColor]()
  432. let maxBGOffset: Float = 20
  433. for i in 0..<predictionData.count {
  434. var predictionVal = Double(predictionData[i].sgv)
  435. if Float(predictionVal) > topBG - maxBGOffset {
  436. topBG = Float(predictionVal) + maxBGOffset
  437. }
  438. if i == 0 {
  439. if UserDefaultsRepository.showDots.value {
  440. colors.append(NSUIColor.systemPurple.withAlphaComponent(0.0))
  441. } else {
  442. colors.append(NSUIColor.systemPurple.withAlphaComponent(1.0))
  443. }
  444. } else if predictionVal > 400 {
  445. predictionVal = 400
  446. colors.append(NSUIColor.systemYellow)
  447. } else if predictionVal < 0 {
  448. predictionVal = 0
  449. colors.append(NSUIColor.systemRed)
  450. } else {
  451. colors.append(NSUIColor.systemPurple)
  452. }
  453. let value = ChartDataEntry(x: predictionData[i].date, y: predictionVal, data: formatPillText(line1: bgUnits.toDisplayUnits(String(predictionData[i].sgv)), time: predictionData[i].date))
  454. mainChart.addEntry(value)
  455. smallChart.addEntry(value)
  456. }
  457. smallChart.circleColors.removeAll()
  458. smallChart.colors.removeAll()
  459. mainChart.colors.removeAll()
  460. mainChart.circleColors.removeAll()
  461. if colors.count > 0 {
  462. if UserDefaultsRepository.debugLog.value { self.writeDebugLog(value: "Graph: prediction colors") }
  463. for i in 0..<colors.count{
  464. mainChart.addColor(colors[i])
  465. mainChart.circleColors.append(colors[i])
  466. smallChart.addColor(colors[i])
  467. smallChart.circleColors.append(colors[i])
  468. }
  469. }
  470. BGChart.rightAxis.axisMaximum = Double(topBG)
  471. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  472. BGChart.data?.notifyDataChanged()
  473. BGChart.notifyDataSetChanged()
  474. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  475. BGChartFull.data?.notifyDataChanged()
  476. BGChartFull.notifyDataSetChanged()
  477. }
  478. func updateBasalGraph() {
  479. var dataIndex = 2
  480. BGChart.lineData?.dataSets[dataIndex].clear()
  481. BGChartFull.lineData?.dataSets[dataIndex].clear()
  482. var maxBasal = UserDefaultsRepository.minBasalScale.value
  483. var maxBasalSmall: Double = 0.0
  484. for i in 0..<basalData.count{
  485. let value = ChartDataEntry(x: Double(basalData[i].date), y: Double(basalData[i].basalRate), data: formatPillText(line1: String(basalData[i].basalRate), time: basalData[i].date))
  486. BGChart.data?.dataSets[dataIndex].addEntry(value)
  487. if UserDefaultsRepository.smallGraphTreatments.value {
  488. BGChartFull.data?.dataSets[dataIndex].addEntry(value)
  489. }
  490. if basalData[i].basalRate > maxBasal {
  491. maxBasal = basalData[i].basalRate
  492. }
  493. if basalData[i].basalRate > maxBasalSmall {
  494. maxBasalSmall = basalData[i].basalRate
  495. }
  496. }
  497. BGChart.leftAxis.axisMaximum = maxBasal
  498. BGChartFull.leftAxis.axisMaximum = maxBasalSmall
  499. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  500. BGChart.data?.notifyDataChanged()
  501. BGChart.notifyDataSetChanged()
  502. if UserDefaultsRepository.smallGraphTreatments.value {
  503. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  504. BGChartFull.data?.notifyDataChanged()
  505. BGChartFull.notifyDataSetChanged()
  506. }
  507. }
  508. func updateBasalScheduledGraph() {
  509. var dataIndex = 5
  510. BGChart.lineData?.dataSets[dataIndex].clear()
  511. BGChartFull.lineData?.dataSets[dataIndex].clear()
  512. for i in 0..<basalScheduleData.count{
  513. let value = ChartDataEntry(x: Double(basalScheduleData[i].date), y: Double(basalScheduleData[i].basalRate))
  514. BGChart.data?.dataSets[dataIndex].addEntry(value)
  515. if UserDefaultsRepository.smallGraphTreatments.value {
  516. BGChartFull.data?.dataSets[dataIndex].addEntry(value)
  517. }
  518. }
  519. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  520. BGChart.data?.notifyDataChanged()
  521. BGChart.notifyDataSetChanged()
  522. if UserDefaultsRepository.smallGraphTreatments.value {
  523. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  524. BGChartFull.data?.notifyDataChanged()
  525. BGChartFull.notifyDataSetChanged()
  526. }
  527. }
  528. func updateBolusGraph() {
  529. var dataIndex = 3
  530. var yTop: Double = 370
  531. var yBottom: Double = 345
  532. var mainChart = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  533. var smallChart = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  534. mainChart.clear()
  535. smallChart.clear()
  536. var colors = [NSUIColor]()
  537. for i in 0..<bolusData.count{
  538. let formatter = NumberFormatter()
  539. formatter.minimumFractionDigits = 0
  540. formatter.maximumFractionDigits = 2
  541. formatter.minimumIntegerDigits = 0
  542. // Check overlapping carbs to shift left if needed
  543. let bolusShift = findNextBolusTime(timeWithin: 240, needle: bolusData[i].date, haystack: bolusData, startingIndex: i)
  544. var dateTimeStamp = bolusData[i].date
  545. // Alpha colors for DIA
  546. let nowTime = dateTimeUtils.getNowTimeIntervalUTC()
  547. let diffTimeHours = (nowTime - dateTimeStamp) / 60 / 60
  548. if diffTimeHours <= 1 {
  549. colors.append(NSUIColor.systemBlue.withAlphaComponent(1.0))
  550. } else if diffTimeHours > 6 {
  551. colors.append(NSUIColor.systemBlue.withAlphaComponent(0.25))
  552. } else {
  553. let thisAlpha = 1.0 - (0.15 * diffTimeHours)
  554. colors.append(NSUIColor.systemBlue.withAlphaComponent(CGFloat(thisAlpha)))
  555. }
  556. if bolusShift {
  557. // Move it half the distance between BG readings
  558. dateTimeStamp = dateTimeStamp - 150
  559. }
  560. // skip if > 24 hours old
  561. if dateTimeStamp < dateTimeUtils.getTimeInterval24HoursAgo() { continue }
  562. let dot = ChartDataEntry(x: Double(dateTimeStamp), y: Double(bolusData[i].sgv), data: formatter.string(from: NSNumber(value: bolusData[i].value)))
  563. mainChart.addEntry(dot)
  564. if UserDefaultsRepository.smallGraphTreatments.value {
  565. smallChart.addEntry(dot)
  566. }
  567. }
  568. // Set Colors
  569. let lineBolus = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  570. let lineBolusSmall = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  571. lineBolus.colors.removeAll()
  572. lineBolus.circleColors.removeAll()
  573. lineBolusSmall.colors.removeAll()
  574. lineBolusSmall.circleColors.removeAll()
  575. if colors.count > 0 {
  576. for i in 0..<colors.count{
  577. mainChart.addColor(colors[i])
  578. mainChart.circleColors.append(colors[i])
  579. smallChart.addColor(colors[i])
  580. smallChart.circleColors.append(colors[i])
  581. }
  582. }
  583. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  584. BGChart.data?.notifyDataChanged()
  585. BGChart.notifyDataSetChanged()
  586. if UserDefaultsRepository.smallGraphTreatments.value {
  587. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  588. BGChartFull.data?.notifyDataChanged()
  589. BGChartFull.notifyDataSetChanged()
  590. }
  591. }
  592. func updateCarbGraph() {
  593. var dataIndex = 4
  594. var mainChart = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  595. var smallChart = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  596. mainChart.clear()
  597. smallChart.clear()
  598. var colors = [NSUIColor]()
  599. for i in 0..<carbData.count{
  600. let formatter = NumberFormatter()
  601. formatter.minimumFractionDigits = 0
  602. formatter.maximumFractionDigits = 2
  603. formatter.minimumIntegerDigits = 1
  604. var valueString: String = formatter.string(from: NSNumber(value: carbData[i].value))!
  605. var hours = 3
  606. if carbData[i].absorptionTime > 0 && UserDefaultsRepository.showAbsorption.value {
  607. hours = carbData[i].absorptionTime / 60
  608. valueString += " " + String(hours) + "h"
  609. }
  610. // Check overlapping carbs to shift left if needed
  611. let carbShift = findNextCarbTime(timeWithin: 250, needle: carbData[i].date, haystack: carbData, startingIndex: i)
  612. var dateTimeStamp = carbData[i].date
  613. // Alpha colors for DIA
  614. let nowTime = dateTimeUtils.getNowTimeIntervalUTC()
  615. let diffTimeHours = (nowTime - dateTimeStamp) / 60 / 60
  616. if diffTimeHours <= 0.5 {
  617. colors.append(NSUIColor.systemOrange.withAlphaComponent(1.0))
  618. } else if diffTimeHours > Double(hours) {
  619. colors.append(NSUIColor.systemOrange.withAlphaComponent(0.25))
  620. } else {
  621. let thisAlpha = 1.0 - ((0.75 / Double(hours)) * diffTimeHours)
  622. colors.append(NSUIColor.systemOrange.withAlphaComponent(CGFloat(thisAlpha)))
  623. }
  624. // skip if > 24 hours old
  625. if dateTimeStamp < dateTimeUtils.getTimeInterval24HoursAgo() { continue }
  626. if carbShift {
  627. dateTimeStamp = dateTimeStamp - 250
  628. }
  629. let dot = ChartDataEntry(x: Double(dateTimeStamp), y: Double(carbData[i].sgv), data: valueString)
  630. BGChart.data?.dataSets[dataIndex].addEntry(dot)
  631. if UserDefaultsRepository.smallGraphTreatments.value {
  632. BGChartFull.data?.dataSets[dataIndex].addEntry(dot)
  633. }
  634. }
  635. // Set Colors
  636. let lineCarbs = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  637. let lineCarbsSmall = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  638. lineCarbs.colors.removeAll()
  639. lineCarbs.circleColors.removeAll()
  640. lineCarbsSmall.colors.removeAll()
  641. lineCarbsSmall.circleColors.removeAll()
  642. if colors.count > 0 {
  643. for i in 0..<colors.count{
  644. mainChart.addColor(colors[i])
  645. mainChart.circleColors.append(colors[i])
  646. smallChart.addColor(colors[i])
  647. smallChart.circleColors.append(colors[i])
  648. }
  649. }
  650. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  651. BGChart.data?.notifyDataChanged()
  652. BGChart.notifyDataSetChanged()
  653. if UserDefaultsRepository.smallGraphTreatments.value {
  654. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  655. BGChartFull.data?.notifyDataChanged()
  656. BGChartFull.notifyDataSetChanged()
  657. }
  658. }
  659. func updateBGCheckGraph() {
  660. var dataIndex = 7
  661. BGChart.lineData?.dataSets[dataIndex].clear()
  662. BGChartFull.lineData?.dataSets[dataIndex].clear()
  663. for i in 0..<bgCheckData.count{
  664. let formatter = NumberFormatter()
  665. formatter.minimumFractionDigits = 0
  666. formatter.maximumFractionDigits = 2
  667. formatter.minimumIntegerDigits = 1
  668. // skip if > 24 hours old
  669. if bgCheckData[i].date < dateTimeUtils.getTimeInterval24HoursAgo() { continue }
  670. 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))
  671. BGChart.data?.dataSets[dataIndex].addEntry(value)
  672. if UserDefaultsRepository.smallGraphTreatments.value {
  673. BGChartFull.data?.dataSets[dataIndex].addEntry(value)
  674. }
  675. }
  676. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  677. BGChart.data?.notifyDataChanged()
  678. BGChart.notifyDataSetChanged()
  679. if UserDefaultsRepository.smallGraphTreatments.value {
  680. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  681. BGChartFull.data?.notifyDataChanged()
  682. BGChartFull.notifyDataSetChanged()
  683. }
  684. }
  685. func updateSuspendGraph() {
  686. var dataIndex = 8
  687. BGChart.lineData?.dataSets[dataIndex].clear()
  688. BGChartFull.lineData?.dataSets[dataIndex].clear()
  689. let thisData = suspendGraphData
  690. for i in 0..<thisData.count{
  691. // skip if > 24 hours old
  692. if thisData[i].date < dateTimeUtils.getTimeInterval24HoursAgo() { continue }
  693. let value = ChartDataEntry(x: Double(thisData[i].date), y: Double(thisData[i].sgv), data: formatPillText(line1: "Suspend Pump", time: thisData[i].date))
  694. BGChart.data?.dataSets[dataIndex].addEntry(value)
  695. if UserDefaultsRepository.smallGraphTreatments.value {
  696. BGChartFull.data?.dataSets[dataIndex].addEntry(value)
  697. }
  698. }
  699. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  700. BGChart.data?.notifyDataChanged()
  701. BGChart.notifyDataSetChanged()
  702. if UserDefaultsRepository.smallGraphTreatments.value {
  703. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  704. BGChartFull.data?.notifyDataChanged()
  705. BGChartFull.notifyDataSetChanged()
  706. }
  707. }
  708. func updateResumeGraph() {
  709. var dataIndex = 9
  710. BGChart.lineData?.dataSets[dataIndex].clear()
  711. BGChartFull.lineData?.dataSets[dataIndex].clear()
  712. let thisData = resumeGraphData
  713. for i in 0..<thisData.count{
  714. // skip if > 24 hours old
  715. if thisData[i].date < dateTimeUtils.getTimeInterval24HoursAgo() { continue }
  716. let value = ChartDataEntry(x: Double(thisData[i].date), y: Double(thisData[i].sgv), data: formatPillText(line1: "Resume Pump", time: thisData[i].date))
  717. BGChart.data?.dataSets[dataIndex].addEntry(value)
  718. if UserDefaultsRepository.smallGraphTreatments.value {
  719. BGChartFull.data?.dataSets[dataIndex].addEntry(value)
  720. }
  721. }
  722. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  723. BGChart.data?.notifyDataChanged()
  724. BGChart.notifyDataSetChanged()
  725. if UserDefaultsRepository.smallGraphTreatments.value {
  726. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  727. BGChartFull.data?.notifyDataChanged()
  728. BGChartFull.notifyDataSetChanged()
  729. }
  730. }
  731. func updateSensorStart() {
  732. var dataIndex = 10
  733. BGChart.lineData?.dataSets[dataIndex].clear()
  734. BGChartFull.lineData?.dataSets[dataIndex].clear()
  735. let thisData = sensorStartGraphData
  736. for i in 0..<thisData.count{
  737. // skip if > 24 hours old
  738. if thisData[i].date < dateTimeUtils.getTimeInterval24HoursAgo() { continue }
  739. let value = ChartDataEntry(x: Double(thisData[i].date), y: Double(thisData[i].sgv), data: formatPillText(line1: "Start Sensor", time: thisData[i].date))
  740. BGChart.data?.dataSets[dataIndex].addEntry(value)
  741. if UserDefaultsRepository.smallGraphTreatments.value {
  742. BGChartFull.data?.dataSets[dataIndex].addEntry(value)
  743. }
  744. }
  745. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  746. BGChart.data?.notifyDataChanged()
  747. BGChart.notifyDataSetChanged()
  748. if UserDefaultsRepository.smallGraphTreatments.value {
  749. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  750. BGChartFull.data?.notifyDataChanged()
  751. BGChartFull.notifyDataSetChanged()
  752. }
  753. }
  754. func updateNotes() {
  755. var dataIndex = 11
  756. BGChart.lineData?.dataSets[dataIndex].clear()
  757. BGChartFull.lineData?.dataSets[dataIndex].clear()
  758. let thisData = noteGraphData
  759. for i in 0..<thisData.count{
  760. // skip if > 24 hours old
  761. if thisData[i].date < dateTimeUtils.getTimeInterval24HoursAgo() { continue }
  762. let value = ChartDataEntry(x: Double(thisData[i].date), y: Double(thisData[i].sgv), data: formatPillText(line1: thisData[i].note, time: thisData[i].date))
  763. BGChart.data?.dataSets[dataIndex].addEntry(value)
  764. if UserDefaultsRepository.smallGraphTreatments.value {
  765. BGChartFull.data?.dataSets[dataIndex].addEntry(value)
  766. }
  767. }
  768. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  769. BGChart.data?.notifyDataChanged()
  770. BGChart.notifyDataSetChanged()
  771. if UserDefaultsRepository.smallGraphTreatments.value {
  772. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  773. BGChartFull.data?.notifyDataChanged()
  774. BGChartFull.notifyDataSetChanged()
  775. }
  776. }
  777. func createSmallBGGraph(){
  778. let entries = bgData
  779. var bgChartEntry = [ChartDataEntry]()
  780. var colors = [NSUIColor]()
  781. var maxBG: Float = UserDefaultsRepository.minBGScale.value
  782. let lineBG = LineChartDataSet(entries:bgChartEntry, label: "")
  783. lineBG.drawCirclesEnabled = false
  784. //line2.setDrawHighlightIndicators(false)
  785. lineBG.highlightEnabled = true
  786. lineBG.drawHorizontalHighlightIndicatorEnabled = false
  787. lineBG.drawVerticalHighlightIndicatorEnabled = false
  788. lineBG.highlightColor = NSUIColor.label
  789. lineBG.drawValuesEnabled = false
  790. lineBG.lineWidth = 1.5
  791. lineBG.axisDependency = YAxis.AxisDependency.right
  792. // Setup Prediction line details
  793. var predictionChartEntry = [ChartDataEntry]()
  794. let linePrediction = LineChartDataSet(entries:predictionChartEntry, label: "")
  795. linePrediction.drawCirclesEnabled = false
  796. //line2.setDrawHighlightIndicators(false)
  797. linePrediction.setColor(NSUIColor.systemPurple)
  798. linePrediction.highlightEnabled = true
  799. linePrediction.drawHorizontalHighlightIndicatorEnabled = false
  800. linePrediction.drawVerticalHighlightIndicatorEnabled = false
  801. linePrediction.highlightColor = NSUIColor.label
  802. linePrediction.drawValuesEnabled = false
  803. linePrediction.lineWidth = 1.5
  804. linePrediction.axisDependency = YAxis.AxisDependency.right
  805. // create Basal graph data
  806. var chartEntry = [ChartDataEntry]()
  807. var maxBasal = UserDefaultsRepository.minBasalScale.value
  808. let lineBasal = LineChartDataSet(entries:chartEntry, label: "")
  809. lineBasal.setDrawHighlightIndicators(false)
  810. lineBasal.setColor(NSUIColor.systemBlue, alpha: 0.5)
  811. lineBasal.lineWidth = 0
  812. lineBasal.drawFilledEnabled = true
  813. lineBasal.fillColor = NSUIColor.systemBlue
  814. lineBasal.fillAlpha = 0.35
  815. lineBasal.drawCirclesEnabled = false
  816. lineBasal.axisDependency = YAxis.AxisDependency.left
  817. lineBasal.highlightEnabled = false
  818. lineBasal.drawValuesEnabled = false
  819. lineBasal.fillFormatter = basalFillFormatter()
  820. // Boluses
  821. var chartEntryBolus = [ChartDataEntry]()
  822. let lineBolus = LineChartDataSet(entries:chartEntryBolus, label: "")
  823. lineBolus.circleRadius = 2
  824. lineBolus.circleColors = [NSUIColor.systemBlue.withAlphaComponent(0.75)]
  825. lineBolus.drawCircleHoleEnabled = false
  826. lineBolus.setDrawHighlightIndicators(false)
  827. lineBolus.setColor(NSUIColor.systemBlue, alpha: 1.0)
  828. lineBolus.lineWidth = 0
  829. lineBolus.axisDependency = YAxis.AxisDependency.right
  830. lineBolus.valueFormatter = ChartYDataValueFormatter()
  831. lineBolus.valueTextColor = NSUIColor.label
  832. lineBolus.fillColor = NSUIColor.systemBlue
  833. lineBolus.fillAlpha = 0.6
  834. lineBolus.drawCirclesEnabled = true
  835. lineBolus.drawFilledEnabled = false
  836. lineBolus.drawValuesEnabled = false
  837. lineBolus.highlightEnabled = false
  838. // Carbs
  839. var chartEntryCarbs = [ChartDataEntry]()
  840. let lineCarbs = LineChartDataSet(entries:chartEntryCarbs, label: "")
  841. lineCarbs.circleRadius = 2
  842. lineCarbs.circleColors = [NSUIColor.systemOrange.withAlphaComponent(0.75)]
  843. lineCarbs.drawCircleHoleEnabled = false
  844. lineCarbs.setDrawHighlightIndicators(false)
  845. lineCarbs.setColor(NSUIColor.systemBlue, alpha: 1.0)
  846. lineCarbs.lineWidth = 0
  847. lineCarbs.axisDependency = YAxis.AxisDependency.right
  848. lineCarbs.valueFormatter = ChartYDataValueFormatter()
  849. lineCarbs.valueTextColor = NSUIColor.label
  850. lineCarbs.fillColor = NSUIColor.systemOrange
  851. lineCarbs.fillAlpha = 0.6
  852. lineCarbs.drawCirclesEnabled = true
  853. lineCarbs.drawFilledEnabled = false
  854. lineCarbs.drawValuesEnabled = false
  855. lineCarbs.highlightEnabled = false
  856. // create Scheduled Basal graph data
  857. var chartBasalScheduledEntry = [ChartDataEntry]()
  858. let lineBasalScheduled = LineChartDataSet(entries:chartBasalScheduledEntry, label: "")
  859. lineBasalScheduled.setDrawHighlightIndicators(false)
  860. lineBasalScheduled.setColor(NSUIColor.systemBlue, alpha: 0.8)
  861. lineBasalScheduled.lineWidth = 0.5
  862. lineBasalScheduled.drawFilledEnabled = false
  863. lineBasalScheduled.drawCirclesEnabled = false
  864. lineBasalScheduled.axisDependency = YAxis.AxisDependency.left
  865. lineBasalScheduled.highlightEnabled = false
  866. lineBasalScheduled.drawValuesEnabled = false
  867. lineBasalScheduled.lineDashLengths = [2, 1]
  868. // create Override graph data
  869. var chartOverrideEntry = [ChartDataEntry]()
  870. let lineOverride = LineChartDataSet(entries:chartOverrideEntry, label: "")
  871. lineOverride.setDrawHighlightIndicators(false)
  872. lineOverride.lineWidth = 0
  873. lineOverride.drawFilledEnabled = true
  874. lineOverride.fillFormatter = OverrideFillFormatter()
  875. lineOverride.fillColor = NSUIColor.systemGreen
  876. lineOverride.fillAlpha = 0.6
  877. lineOverride.drawCirclesEnabled = false
  878. lineOverride.axisDependency = YAxis.AxisDependency.right
  879. lineOverride.highlightEnabled = true
  880. lineOverride.drawValuesEnabled = false
  881. // BG Check
  882. var chartEntryBGCheck = [ChartDataEntry]()
  883. let lineBGCheck = LineChartDataSet(entries:chartEntryBGCheck, label: "")
  884. lineBGCheck.circleRadius = 2
  885. lineBGCheck.circleColors = [NSUIColor.systemRed.withAlphaComponent(0.75)]
  886. lineBGCheck.drawCircleHoleEnabled = false
  887. lineBGCheck.setDrawHighlightIndicators(false)
  888. lineBGCheck.setColor(NSUIColor.systemRed, alpha: 1.0)
  889. lineBGCheck.drawCirclesEnabled = true
  890. lineBGCheck.lineWidth = 0
  891. lineBGCheck.highlightEnabled = false
  892. lineBGCheck.axisDependency = YAxis.AxisDependency.right
  893. lineBGCheck.valueFormatter = ChartYDataValueFormatter()
  894. lineBGCheck.drawValuesEnabled = false
  895. // Suspend Pump
  896. var chartEntrySuspend = [ChartDataEntry]()
  897. let lineSuspend = LineChartDataSet(entries:chartEntrySuspend, label: "")
  898. lineSuspend.circleRadius = 2
  899. lineSuspend.circleColors = [NSUIColor.systemTeal.withAlphaComponent(0.75)]
  900. lineSuspend.drawCircleHoleEnabled = false
  901. lineSuspend.setDrawHighlightIndicators(false)
  902. lineSuspend.setColor(NSUIColor.systemGray2, alpha: 1.0)
  903. lineSuspend.drawCirclesEnabled = true
  904. lineSuspend.lineWidth = 0
  905. lineSuspend.highlightEnabled = false
  906. lineSuspend.axisDependency = YAxis.AxisDependency.right
  907. lineSuspend.valueFormatter = ChartYDataValueFormatter()
  908. lineSuspend.drawValuesEnabled = false
  909. // Resume Pump
  910. var chartEntryResume = [ChartDataEntry]()
  911. let lineResume = LineChartDataSet(entries:chartEntryResume, label: "")
  912. lineResume.circleRadius = 2
  913. lineResume.circleColors = [NSUIColor.systemTeal.withAlphaComponent(0.75)]
  914. lineResume.drawCircleHoleEnabled = false
  915. lineResume.setDrawHighlightIndicators(false)
  916. lineResume.setColor(NSUIColor.systemGray4, alpha: 1.0)
  917. lineResume.drawCirclesEnabled = true
  918. lineResume.lineWidth = 0
  919. lineResume.highlightEnabled = false
  920. lineResume.axisDependency = YAxis.AxisDependency.right
  921. lineResume.valueFormatter = ChartYDataValueFormatter()
  922. lineResume.drawValuesEnabled = false
  923. // Sensor Start
  924. var chartEntrySensor = [ChartDataEntry]()
  925. let lineSensor = LineChartDataSet(entries:chartEntrySensor, label: "")
  926. lineSensor.circleRadius = 2
  927. lineSensor.circleColors = [NSUIColor.systemIndigo.withAlphaComponent(0.75)]
  928. lineSensor.drawCircleHoleEnabled = false
  929. lineSensor.setDrawHighlightIndicators(false)
  930. lineSensor.setColor(NSUIColor.systemGray3, alpha: 1.0)
  931. lineSensor.drawCirclesEnabled = true
  932. lineSensor.lineWidth = 0
  933. lineSensor.highlightEnabled = false
  934. lineSensor.axisDependency = YAxis.AxisDependency.right
  935. lineSensor.valueFormatter = ChartYDataValueFormatter()
  936. lineSensor.drawValuesEnabled = false
  937. // Notes
  938. var chartEntryNote = [ChartDataEntry]()
  939. let lineNote = LineChartDataSet(entries:chartEntryNote, label: "")
  940. lineNote.circleRadius = 2
  941. lineNote.circleColors = [NSUIColor.systemGray.withAlphaComponent(0.75)]
  942. lineNote.drawCircleHoleEnabled = false
  943. lineNote.setDrawHighlightIndicators(false)
  944. lineNote.setColor(NSUIColor.systemGray3, alpha: 1.0)
  945. lineNote.drawCirclesEnabled = true
  946. lineNote.lineWidth = 0
  947. lineNote.highlightEnabled = false
  948. lineNote.axisDependency = YAxis.AxisDependency.right
  949. lineNote.valueFormatter = ChartYDataValueFormatter()
  950. lineNote.drawValuesEnabled = false
  951. // Setup the chart data of all lines
  952. let data = LineChartData()
  953. data.addDataSet(lineBG) // Dataset 0
  954. data.addDataSet(linePrediction) // Dataset 1
  955. data.addDataSet(lineBasal) // Dataset 2
  956. data.addDataSet(lineBolus) // Dataset 3
  957. data.addDataSet(lineCarbs) // Dataset 4
  958. data.addDataSet(lineBasalScheduled) // Dataset 5
  959. data.addDataSet(lineOverride) // Dataset 6
  960. data.addDataSet(lineBGCheck) // Dataset 7
  961. data.addDataSet(lineSuspend) // Dataset 8
  962. data.addDataSet(lineResume) // Dataset 9
  963. data.addDataSet(lineSensor) // Dataset 10
  964. data.addDataSet(lineNote) // Dataset 11
  965. BGChartFull.highlightPerDragEnabled = true
  966. BGChartFull.leftAxis.enabled = false
  967. BGChartFull.leftAxis.axisMaximum = maxBasal
  968. BGChartFull.leftAxis.axisMinimum = 0
  969. BGChartFull.rightAxis.enabled = false
  970. BGChartFull.rightAxis.axisMinimum = 0.0
  971. BGChartFull.rightAxis.axisMaximum = Double(maxBG)
  972. BGChartFull.xAxis.enabled = false
  973. BGChartFull.legend.enabled = false
  974. BGChartFull.scaleYEnabled = false
  975. BGChartFull.scaleXEnabled = false
  976. BGChartFull.drawGridBackgroundEnabled = false
  977. BGChartFull.data = data
  978. }
  979. func updateOverrideGraph() {
  980. var dataIndex = 6
  981. var yTop: Double = Double(topBG - 5)
  982. var yBottom: Double = Double(topBG - 25)
  983. var chart = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  984. var smallChart = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  985. chart.clear()
  986. smallChart.clear()
  987. let thisData = overrideGraphData
  988. var colors = [NSUIColor]()
  989. for i in 0..<thisData.count{
  990. let thisItem = thisData[i]
  991. let multiplier = thisItem.insulNeedsScaleFactor as! Double * 100.0
  992. var labelText = thisItem.reason + "\r\n"
  993. labelText += String(Int(thisItem.insulNeedsScaleFactor * 100)) + "% "
  994. if thisItem.correctionRange.count == 2 {
  995. labelText += String(thisItem.correctionRange[0]) + "-" + String(thisItem.correctionRange[1])
  996. }
  997. if thisItem.enteredBy.count > 0 {
  998. labelText += "\r\nEntered By: " + thisItem.enteredBy
  999. }
  1000. // Start Dot
  1001. // Shift dots 30 seconds to create an empty 0 space between consecutive temps
  1002. let preStartDot = ChartDataEntry(x: Double(thisItem.date), y: yBottom, data: labelText)
  1003. BGChart.data?.dataSets[dataIndex].addEntry(preStartDot)
  1004. if UserDefaultsRepository.smallGraphTreatments.value {
  1005. BGChartFull.data?.dataSets[dataIndex].addEntry(preStartDot)
  1006. }
  1007. let startDot = ChartDataEntry(x: Double(thisItem.date + 1), y: yTop, data: labelText)
  1008. BGChart.data?.dataSets[dataIndex].addEntry(startDot)
  1009. if UserDefaultsRepository.smallGraphTreatments.value {
  1010. BGChartFull.data?.dataSets[dataIndex].addEntry(startDot)
  1011. }
  1012. // End Dot
  1013. let endDot = ChartDataEntry(x: Double(thisItem.endDate - 2), y: yTop, data: labelText)
  1014. BGChart.data?.dataSets[dataIndex].addEntry(endDot)
  1015. if UserDefaultsRepository.smallGraphTreatments.value {
  1016. BGChartFull.data?.dataSets[dataIndex].addEntry(endDot)
  1017. }
  1018. // Post end dot
  1019. let postEndDot = ChartDataEntry(x: Double(thisItem.endDate - 1), y: yBottom, data: labelText)
  1020. BGChart.data?.dataSets[dataIndex].addEntry(postEndDot)
  1021. if UserDefaultsRepository.smallGraphTreatments.value {
  1022. BGChartFull.data?.dataSets[dataIndex].addEntry(postEndDot)
  1023. }
  1024. }
  1025. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  1026. BGChart.data?.notifyDataChanged()
  1027. BGChart.notifyDataSetChanged()
  1028. if UserDefaultsRepository.smallGraphTreatments.value {
  1029. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  1030. BGChartFull.data?.notifyDataChanged()
  1031. BGChartFull.notifyDataSetChanged()
  1032. }
  1033. }
  1034. func formatPillText(line1: String, time: TimeInterval) -> String {
  1035. let dateFormatter = DateFormatter()
  1036. //let timezoneOffset = TimeZone.current.secondsFromGMT()
  1037. //let epochTimezoneOffset = value + Double(timezoneOffset)
  1038. if dateTimeUtils.is24Hour() {
  1039. dateFormatter.setLocalizedDateFormatFromTemplate("HH:mm")
  1040. } else {
  1041. dateFormatter.setLocalizedDateFormatFromTemplate("hh:mm")
  1042. }
  1043. //let date = Date(timeIntervalSince1970: epochTimezoneOffset)
  1044. let date = Date(timeIntervalSince1970: time)
  1045. let formattedDate = dateFormatter.string(from: date)
  1046. return line1 + "\r\n" + formattedDate
  1047. }
  1048. }