Graphs.swift 70 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605
  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. import Charts
  12. class TriangleRenderer: LineChartRenderer {
  13. let smbDataSetIndex: Int
  14. init(dataProvider: LineChartDataProvider?, animator: Animator?, viewPortHandler: ViewPortHandler?, smbDataSetIndex: Int) {
  15. self.smbDataSetIndex = smbDataSetIndex
  16. super.init(dataProvider: dataProvider!, animator: animator!, viewPortHandler: viewPortHandler!)
  17. }
  18. override func drawExtras(context: CGContext) {
  19. super.drawExtras(context: context)
  20. guard let dataProvider = dataProvider else { return }
  21. if dataProvider.lineData?.dataSets.count ?? 0 > smbDataSetIndex, let lineDataSet = dataProvider.lineData?.dataSets[smbDataSetIndex] as? LineChartDataSet {
  22. let trans = dataProvider.getTransformer(forAxis: lineDataSet.axisDependency)
  23. let phaseY = animator.phaseY
  24. for j in 0 ..< lineDataSet.entryCount {
  25. guard let e = lineDataSet.entryForIndex(j) else { continue }
  26. let pt = trans.pixelForValues(x: e.x, y: e.y * phaseY)
  27. context.saveGState()
  28. context.beginPath()
  29. context.move(to: CGPoint(x: pt.x, y: pt.y + 9))
  30. context.addLine(to: CGPoint(x: pt.x - 5, y: pt.y - 1))
  31. context.addLine(to: CGPoint(x: pt.x + 5, y: pt.y - 1))
  32. context.closePath()
  33. context.setFillColor(lineDataSet.circleColors.first!.cgColor)
  34. context.fillPath()
  35. context.restoreGState()
  36. }
  37. }
  38. }
  39. }
  40. let ScaleXMax:Float = 150.0
  41. extension MainViewController {
  42. func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) {
  43. if chartView == BGChartFull {
  44. BGChart.moveViewToX(entry.x)
  45. }
  46. if entry.data as? String == "hide"{
  47. BGChart.highlightValue(nil, callDelegate: false)
  48. }
  49. }
  50. func chartScaled(_ chartView: ChartViewBase, scaleX: CGFloat, scaleY: CGFloat) {
  51. print("Chart Scaled: \(BGChart.scaleX), \(BGChart.scaleY)")
  52. // dont store huge values
  53. var scale: Float = Float(BGChart.scaleX)
  54. if(scale > ScaleXMax ) {
  55. scale = ScaleXMax
  56. }
  57. UserDefaultsRepository.chartScaleX.value = Float(scale)
  58. }
  59. func createGraph(){
  60. // Create the BG Graph Data
  61. let bgChartEntry = [ChartDataEntry]()
  62. let maxBG: Float = UserDefaultsRepository.minBGScale.value
  63. // Setup BG line details
  64. let lineBG = LineChartDataSet(entries:bgChartEntry, label: "")
  65. lineBG.circleRadius = CGFloat(globalVariables.dotBG)
  66. lineBG.circleColors = [NSUIColor.systemGreen]
  67. lineBG.drawCircleHoleEnabled = false
  68. lineBG.axisDependency = YAxis.AxisDependency.right
  69. lineBG.highlightEnabled = true
  70. lineBG.drawValuesEnabled = false
  71. if UserDefaultsRepository.showLines.value {
  72. lineBG.lineWidth = 2
  73. } else {
  74. lineBG.lineWidth = 0
  75. }
  76. if UserDefaultsRepository.showDots.value {
  77. lineBG.drawCirclesEnabled = true
  78. } else {
  79. lineBG.drawCirclesEnabled = false
  80. }
  81. lineBG.setDrawHighlightIndicators(false)
  82. lineBG.valueFont.withSize(50)
  83. // Setup Prediction line details
  84. let predictionChartEntry = [ChartDataEntry]()
  85. let linePrediction = LineChartDataSet(entries:predictionChartEntry, label: "")
  86. linePrediction.circleRadius = CGFloat(globalVariables.dotBG)
  87. linePrediction.circleColors = [NSUIColor.systemPurple]
  88. linePrediction.colors = [NSUIColor.systemPurple]
  89. linePrediction.drawCircleHoleEnabled = false
  90. linePrediction.axisDependency = YAxis.AxisDependency.right
  91. linePrediction.highlightEnabled = true
  92. linePrediction.drawValuesEnabled = false
  93. if UserDefaultsRepository.showLines.value {
  94. linePrediction.lineWidth = 2
  95. } else {
  96. linePrediction.lineWidth = 0
  97. }
  98. if UserDefaultsRepository.showDots.value {
  99. linePrediction.drawCirclesEnabled = true
  100. } else {
  101. linePrediction.drawCirclesEnabled = false
  102. }
  103. linePrediction.setDrawHighlightIndicators(false)
  104. linePrediction.valueFont.withSize(50)
  105. // create Basal graph data
  106. let chartEntry = [ChartDataEntry]()
  107. let maxBasal = UserDefaultsRepository.minBasalScale.value
  108. let lineBasal = LineChartDataSet(entries:chartEntry, label: "")
  109. lineBasal.setDrawHighlightIndicators(false)
  110. lineBasal.setColor(NSUIColor.systemBlue, alpha: 0.5)
  111. lineBasal.lineWidth = 0
  112. lineBasal.drawFilledEnabled = true
  113. lineBasal.fillColor = NSUIColor.systemBlue
  114. lineBasal.fillAlpha = 0.5
  115. lineBasal.drawCirclesEnabled = false
  116. lineBasal.axisDependency = YAxis.AxisDependency.left
  117. lineBasal.highlightEnabled = true
  118. lineBasal.drawValuesEnabled = false
  119. lineBasal.fillFormatter = basalFillFormatter()
  120. // Boluses
  121. let chartEntryBolus = [ChartDataEntry]()
  122. let lineBolus = LineChartDataSet(entries:chartEntryBolus, label: "")
  123. lineBolus.circleRadius = CGFloat(globalVariables.dotBolus)
  124. lineBolus.circleColors = [NSUIColor.systemBlue.withAlphaComponent(0.75)]
  125. lineBolus.drawCircleHoleEnabled = false
  126. lineBolus.setDrawHighlightIndicators(false)
  127. lineBolus.setColor(NSUIColor.systemBlue, alpha: 1.0)
  128. lineBolus.lineWidth = 0
  129. lineBolus.axisDependency = YAxis.AxisDependency.right
  130. lineBolus.valueFormatter = ChartYDataValueFormatter()
  131. lineBolus.valueTextColor = NSUIColor.label
  132. lineBolus.fillColor = NSUIColor.systemBlue
  133. lineBolus.fillAlpha = 0.6
  134. lineBolus.drawCirclesEnabled = true
  135. lineBolus.drawFilledEnabled = false
  136. if UserDefaultsRepository.showValues.value {
  137. lineBolus.drawValuesEnabled = true
  138. lineBolus.highlightEnabled = false
  139. } else {
  140. lineBolus.drawValuesEnabled = false
  141. lineBolus.highlightEnabled = true
  142. }
  143. // Carbs
  144. let chartEntryCarbs = [ChartDataEntry]()
  145. let lineCarbs = LineChartDataSet(entries:chartEntryCarbs, label: "")
  146. lineCarbs.circleRadius = CGFloat(globalVariables.dotCarb)
  147. lineCarbs.circleColors = [NSUIColor.systemOrange.withAlphaComponent(0.75)]
  148. lineCarbs.drawCircleHoleEnabled = false
  149. lineCarbs.setDrawHighlightIndicators(false)
  150. lineCarbs.setColor(NSUIColor.systemBlue, alpha: 1.0)
  151. lineCarbs.lineWidth = 0
  152. lineCarbs.axisDependency = YAxis.AxisDependency.right
  153. lineCarbs.valueFormatter = ChartYDataValueFormatter()
  154. lineCarbs.valueTextColor = NSUIColor.label
  155. lineCarbs.fillColor = NSUIColor.systemOrange
  156. lineCarbs.fillAlpha = 0.6
  157. lineCarbs.drawCirclesEnabled = true
  158. lineCarbs.drawFilledEnabled = false
  159. if UserDefaultsRepository.showValues.value {
  160. lineCarbs.drawValuesEnabled = true
  161. lineCarbs.highlightEnabled = false
  162. } else {
  163. lineCarbs.drawValuesEnabled = false
  164. lineCarbs.highlightEnabled = true
  165. }
  166. // create Scheduled Basal graph data
  167. let chartBasalScheduledEntry = [ChartDataEntry]()
  168. let lineBasalScheduled = LineChartDataSet(entries:chartBasalScheduledEntry, label: "")
  169. lineBasalScheduled.setDrawHighlightIndicators(false)
  170. lineBasalScheduled.setColor(NSUIColor.systemBlue, alpha: 0.8)
  171. lineBasalScheduled.lineWidth = 2
  172. lineBasalScheduled.drawFilledEnabled = false
  173. lineBasalScheduled.drawCirclesEnabled = false
  174. lineBasalScheduled.axisDependency = YAxis.AxisDependency.left
  175. lineBasalScheduled.highlightEnabled = false
  176. lineBasalScheduled.drawValuesEnabled = false
  177. lineBasalScheduled.lineDashLengths = [10.0, 5.0]
  178. // create Override graph data
  179. let chartOverrideEntry = [ChartDataEntry]()
  180. let lineOverride = LineChartDataSet(entries:chartOverrideEntry, label: "")
  181. lineOverride.setDrawHighlightIndicators(false)
  182. lineOverride.lineWidth = 0
  183. lineOverride.drawFilledEnabled = true
  184. lineOverride.fillFormatter = OverrideFillFormatter()
  185. lineOverride.fillColor = NSUIColor.systemGreen
  186. lineOverride.fillAlpha = 0.6
  187. lineOverride.drawCirclesEnabled = false
  188. lineOverride.axisDependency = YAxis.AxisDependency.right
  189. lineOverride.highlightEnabled = true
  190. lineOverride.drawValuesEnabled = false
  191. // BG Check
  192. let chartEntryBGCheck = [ChartDataEntry]()
  193. let lineBGCheck = LineChartDataSet(entries:chartEntryBGCheck, label: "")
  194. lineBGCheck.circleRadius = CGFloat(globalVariables.dotOther)
  195. lineBGCheck.circleColors = [NSUIColor.systemRed.withAlphaComponent(0.75)]
  196. lineBGCheck.drawCircleHoleEnabled = false
  197. lineBGCheck.setDrawHighlightIndicators(false)
  198. lineBGCheck.setColor(NSUIColor.systemRed, alpha: 1.0)
  199. lineBGCheck.drawCirclesEnabled = true
  200. lineBGCheck.lineWidth = 0
  201. lineBGCheck.highlightEnabled = true
  202. lineBGCheck.axisDependency = YAxis.AxisDependency.right
  203. lineBGCheck.valueFormatter = ChartYDataValueFormatter()
  204. lineBGCheck.drawValuesEnabled = false
  205. // Suspend Pump
  206. let chartEntrySuspend = [ChartDataEntry]()
  207. let lineSuspend = LineChartDataSet(entries:chartEntrySuspend, label: "")
  208. lineSuspend.circleRadius = CGFloat(globalVariables.dotOther)
  209. lineSuspend.circleColors = [NSUIColor.systemTeal.withAlphaComponent(0.75)]
  210. lineSuspend.drawCircleHoleEnabled = false
  211. lineSuspend.setDrawHighlightIndicators(false)
  212. lineSuspend.setColor(NSUIColor.systemGray2, alpha: 1.0)
  213. lineSuspend.drawCirclesEnabled = true
  214. lineSuspend.lineWidth = 0
  215. lineSuspend.highlightEnabled = true
  216. lineSuspend.axisDependency = YAxis.AxisDependency.right
  217. lineSuspend.valueFormatter = ChartYDataValueFormatter()
  218. lineSuspend.drawValuesEnabled = false
  219. // Resume Pump
  220. let chartEntryResume = [ChartDataEntry]()
  221. let lineResume = LineChartDataSet(entries:chartEntryResume, label: "")
  222. lineResume.circleRadius = CGFloat(globalVariables.dotOther)
  223. lineResume.circleColors = [NSUIColor.systemTeal.withAlphaComponent(0.75)]
  224. lineResume.drawCircleHoleEnabled = false
  225. lineResume.setDrawHighlightIndicators(false)
  226. lineResume.setColor(NSUIColor.systemGray4, alpha: 1.0)
  227. lineResume.drawCirclesEnabled = true
  228. lineResume.lineWidth = 0
  229. lineResume.highlightEnabled = true
  230. lineResume.axisDependency = YAxis.AxisDependency.right
  231. lineResume.valueFormatter = ChartYDataValueFormatter()
  232. lineResume.drawValuesEnabled = false
  233. // Sensor Start
  234. let chartEntrySensor = [ChartDataEntry]()
  235. let lineSensor = LineChartDataSet(entries:chartEntrySensor, label: "")
  236. lineSensor.circleRadius = CGFloat(globalVariables.dotOther)
  237. lineSensor.circleColors = [NSUIColor.systemIndigo.withAlphaComponent(0.75)]
  238. lineSensor.drawCircleHoleEnabled = false
  239. lineSensor.setDrawHighlightIndicators(false)
  240. lineSensor.setColor(NSUIColor.systemGray3, alpha: 1.0)
  241. lineSensor.drawCirclesEnabled = true
  242. lineSensor.lineWidth = 0
  243. lineSensor.highlightEnabled = true
  244. lineSensor.axisDependency = YAxis.AxisDependency.right
  245. lineSensor.valueFormatter = ChartYDataValueFormatter()
  246. lineSensor.drawValuesEnabled = false
  247. // Notes
  248. let chartEntryNote = [ChartDataEntry]()
  249. let lineNote = LineChartDataSet(entries:chartEntryNote, label: "")
  250. lineNote.circleRadius = CGFloat(globalVariables.dotOther)
  251. lineNote.circleColors = [NSUIColor.systemGray.withAlphaComponent(0.75)]
  252. lineNote.drawCircleHoleEnabled = false
  253. lineNote.setDrawHighlightIndicators(false)
  254. lineNote.setColor(NSUIColor.systemGray3, alpha: 1.0)
  255. lineNote.drawCirclesEnabled = true
  256. lineNote.lineWidth = 0
  257. lineNote.highlightEnabled = true
  258. lineNote.axisDependency = YAxis.AxisDependency.right
  259. lineNote.valueFormatter = ChartYDataValueFormatter()
  260. lineNote.drawValuesEnabled = false
  261. // Setup COB Prediction line details
  262. let COBpredictionChartEntry = [ChartDataEntry]()
  263. let COBlinePrediction = LineChartDataSet(entries:COBpredictionChartEntry, label: "")
  264. COBlinePrediction.circleRadius = CGFloat(globalVariables.dotBG)
  265. COBlinePrediction.circleColors = [NSUIColor.systemPurple]
  266. COBlinePrediction.colors = [NSUIColor.systemPurple]
  267. COBlinePrediction.drawCircleHoleEnabled = false
  268. COBlinePrediction.axisDependency = YAxis.AxisDependency.right
  269. COBlinePrediction.highlightEnabled = true
  270. COBlinePrediction.drawValuesEnabled = false
  271. if UserDefaultsRepository.showLines.value {
  272. COBlinePrediction.lineWidth = 2
  273. } else {
  274. COBlinePrediction.lineWidth = 0
  275. }
  276. if UserDefaultsRepository.showDots.value {
  277. COBlinePrediction.drawCirclesEnabled = true
  278. } else {
  279. COBlinePrediction.drawCirclesEnabled = false
  280. }
  281. COBlinePrediction.setDrawHighlightIndicators(false)
  282. COBlinePrediction.valueFont.withSize(50)
  283. // Setup IOB Prediction line details
  284. let IOBpredictionChartEntry = [ChartDataEntry]()
  285. let IOBlinePrediction = LineChartDataSet(entries:IOBpredictionChartEntry, label: "")
  286. IOBlinePrediction.circleRadius = CGFloat(globalVariables.dotBG)
  287. IOBlinePrediction.circleColors = [NSUIColor.systemPurple]
  288. IOBlinePrediction.colors = [NSUIColor.systemPurple]
  289. IOBlinePrediction.drawCircleHoleEnabled = false
  290. IOBlinePrediction.axisDependency = YAxis.AxisDependency.right
  291. IOBlinePrediction.highlightEnabled = true
  292. IOBlinePrediction.drawValuesEnabled = false
  293. if UserDefaultsRepository.showLines.value {
  294. IOBlinePrediction.lineWidth = 2
  295. } else {
  296. IOBlinePrediction.lineWidth = 0
  297. }
  298. if UserDefaultsRepository.showDots.value {
  299. IOBlinePrediction.drawCirclesEnabled = true
  300. } else {
  301. IOBlinePrediction.drawCirclesEnabled = false
  302. }
  303. IOBlinePrediction.setDrawHighlightIndicators(false)
  304. IOBlinePrediction.valueFont.withSize(50)
  305. // Setup UAM Prediction line details
  306. let UAMpredictionChartEntry = [ChartDataEntry]()
  307. let UAMlinePrediction = LineChartDataSet(entries:UAMpredictionChartEntry, label: "")
  308. UAMlinePrediction.circleRadius = CGFloat(globalVariables.dotBG)
  309. UAMlinePrediction.circleColors = [NSUIColor.systemPurple]
  310. UAMlinePrediction.colors = [NSUIColor.systemPurple]
  311. UAMlinePrediction.drawCircleHoleEnabled = false
  312. UAMlinePrediction.axisDependency = YAxis.AxisDependency.right
  313. UAMlinePrediction.highlightEnabled = true
  314. UAMlinePrediction.drawValuesEnabled = false
  315. if UserDefaultsRepository.showLines.value {
  316. UAMlinePrediction.lineWidth = 2
  317. } else {
  318. UAMlinePrediction.lineWidth = 0
  319. }
  320. if UserDefaultsRepository.showDots.value {
  321. UAMlinePrediction.drawCirclesEnabled = true
  322. } else {
  323. UAMlinePrediction.drawCirclesEnabled = false
  324. }
  325. linePrediction.setDrawHighlightIndicators(false)
  326. linePrediction.valueFont.withSize(50)
  327. // Setup ZT Prediction line details
  328. let ZTpredictionChartEntry = [ChartDataEntry]()
  329. let ZTlinePrediction = LineChartDataSet(entries:ZTpredictionChartEntry, label: "")
  330. ZTlinePrediction.circleRadius = CGFloat(globalVariables.dotBG)
  331. ZTlinePrediction.circleColors = [NSUIColor.systemPurple]
  332. ZTlinePrediction.colors = [NSUIColor.systemPurple]
  333. ZTlinePrediction.drawCircleHoleEnabled = false
  334. ZTlinePrediction.axisDependency = YAxis.AxisDependency.right
  335. ZTlinePrediction.highlightEnabled = true
  336. ZTlinePrediction.drawValuesEnabled = false
  337. if UserDefaultsRepository.showLines.value {
  338. ZTlinePrediction.lineWidth = 2
  339. } else {
  340. ZTlinePrediction.lineWidth = 0
  341. }
  342. if UserDefaultsRepository.showDots.value {
  343. ZTlinePrediction.drawCirclesEnabled = true
  344. } else {
  345. ZTlinePrediction.drawCirclesEnabled = false
  346. }
  347. ZTlinePrediction.setDrawHighlightIndicators(false)
  348. ZTlinePrediction.valueFont.withSize(50)
  349. // SMB
  350. let chartEntrySmb = [ChartDataEntry]()
  351. let lineSmb = LineChartDataSet(entries: chartEntrySmb, label: "")
  352. lineSmb.circleRadius = CGFloat(globalVariables.dotBolus)
  353. lineSmb.circleColors = [NSUIColor.systemBlue.withAlphaComponent(1.0)]
  354. lineSmb.drawCircleHoleEnabled = false
  355. lineSmb.setDrawHighlightIndicators(false)
  356. lineSmb.setColor(NSUIColor.red, alpha: 1.0)
  357. lineSmb.lineWidth = 0
  358. lineSmb.axisDependency = YAxis.AxisDependency.right
  359. lineSmb.valueFormatter = ChartYDataValueFormatter()
  360. lineSmb.valueTextColor = NSUIColor.label
  361. lineSmb.drawCirclesEnabled = false
  362. lineSmb.drawFilledEnabled = false
  363. if UserDefaultsRepository.showValues.value {
  364. lineSmb.drawValuesEnabled = true
  365. lineSmb.highlightEnabled = false
  366. } else {
  367. lineSmb.drawValuesEnabled = false
  368. lineSmb.highlightEnabled = true
  369. }
  370. // Setup the chart data of all lines
  371. let data = LineChartData()
  372. data.append(lineBG) // Dataset 0
  373. data.append(linePrediction) // Dataset 1
  374. data.append(lineBasal) // Dataset 2
  375. data.append(lineBolus) // Dataset 3
  376. data.append(lineCarbs) // Dataset 4
  377. data.append(lineBasalScheduled) // Dataset 5
  378. data.append(lineOverride) // Dataset 6
  379. data.append(lineBGCheck) // Dataset 7
  380. data.append(lineSuspend) // Dataset 8
  381. data.append(lineResume) // Dataset 9
  382. data.append(lineSensor) // Dataset 10
  383. data.append(lineNote) // Dataset 11
  384. data.append(ZTlinePrediction) // Dataset 12
  385. data.append(IOBlinePrediction) // Dataset 13
  386. data.append(COBlinePrediction) // Dataset 14
  387. data.append(UAMlinePrediction) // Dataset 15
  388. data.append(lineSmb) // Dataset 16
  389. data.setValueFont(UIFont.systemFont(ofSize: 12))
  390. // Add marker popups for bolus and carbs
  391. let marker = PillMarker(color: .secondarySystemBackground, font: UIFont.boldSystemFont(ofSize: 14), textColor: .label)
  392. BGChart.marker = marker
  393. // Clear limit lines so they don't add multiples when changing the settings
  394. BGChart.rightAxis.removeAllLimitLines()
  395. //Add lower red line based on low alert value
  396. let ll = ChartLimitLine()
  397. ll.limit = Double(UserDefaultsRepository.lowLine.value)
  398. ll.lineColor = NSUIColor.systemRed.withAlphaComponent(0.5)
  399. BGChart.rightAxis.addLimitLine(ll)
  400. //Add upper yellow line based on low alert value
  401. let ul = ChartLimitLine()
  402. ul.limit = Double(UserDefaultsRepository.highLine.value)
  403. ul.lineColor = NSUIColor.systemYellow.withAlphaComponent(0.5)
  404. BGChart.rightAxis.addLimitLine(ul)
  405. // Add vertical lines as configured
  406. createVerticalLines()
  407. startGraphNowTimer()
  408. // Setup the main graph overall details
  409. BGChart.xAxis.valueFormatter = ChartXValueFormatter()
  410. BGChart.xAxis.granularity = 1800
  411. BGChart.xAxis.labelTextColor = NSUIColor.label
  412. BGChart.xAxis.labelPosition = XAxis.LabelPosition.bottom
  413. BGChart.xAxis.drawGridLinesEnabled = false
  414. BGChart.leftAxis.enabled = true
  415. BGChart.leftAxis.labelPosition = YAxis.LabelPosition.insideChart
  416. BGChart.leftAxis.axisMaximum = maxBasal
  417. BGChart.leftAxis.axisMinimum = 0
  418. BGChart.leftAxis.drawGridLinesEnabled = false
  419. BGChart.leftAxis.granularityEnabled = true
  420. BGChart.leftAxis.granularity = 0.5
  421. BGChart.rightAxis.labelTextColor = NSUIColor.label
  422. BGChart.rightAxis.labelPosition = YAxis.LabelPosition.insideChart
  423. BGChart.rightAxis.axisMinimum = 0.0
  424. BGChart.rightAxis.axisMaximum = Double(maxBG)
  425. BGChart.rightAxis.gridLineDashLengths = [5.0, 5.0]
  426. BGChart.rightAxis.drawGridLinesEnabled = false
  427. BGChart.rightAxis.valueFormatter = ChartYMMOLValueFormatter()
  428. BGChart.rightAxis.granularityEnabled = true
  429. BGChart.rightAxis.granularity = 50
  430. BGChart.maxHighlightDistance = 15.0
  431. BGChart.legend.enabled = false
  432. BGChart.scaleYEnabled = false
  433. BGChart.drawGridBackgroundEnabled = true
  434. BGChart.gridBackgroundColor = NSUIColor.secondarySystemBackground
  435. BGChart.highlightValue(nil, callDelegate: false)
  436. BGChart.data = data
  437. BGChart.setExtraOffsets(left: 5, top: 10, right: 5, bottom: 10)
  438. }
  439. func createVerticalLines() {
  440. BGChart.xAxis.removeAllLimitLines()
  441. BGChartFull.xAxis.removeAllLimitLines()
  442. createNowAndDIALines()
  443. createMidnightLines()
  444. }
  445. func createNowAndDIALines() {
  446. let ul = ChartLimitLine()
  447. ul.limit = Double(dateTimeUtils.getNowTimeIntervalUTC())
  448. ul.lineColor = NSUIColor.systemGray.withAlphaComponent(0.5)
  449. ul.lineWidth = 1
  450. BGChart.xAxis.addLimitLine(ul)
  451. if UserDefaultsRepository.show30MinLine.value {
  452. let ul2 = ChartLimitLine()
  453. ul2.limit = Double(dateTimeUtils.getNowTimeIntervalUTC().advanced(by: -30 * 60))
  454. ul2.lineColor = NSUIColor.systemBlue.withAlphaComponent(0.5)
  455. ul2.lineWidth = 1
  456. BGChart.xAxis.addLimitLine(ul2)
  457. }
  458. if UserDefaultsRepository.showDIALines.value {
  459. for i in 1..<7 {
  460. let ul = ChartLimitLine()
  461. ul.limit = Double(dateTimeUtils.getNowTimeIntervalUTC() - Double(i * 60 * 60))
  462. ul.lineColor = NSUIColor.systemGray.withAlphaComponent(0.3)
  463. let dash = 10.0 - Double(i)
  464. let space = 5.0 + Double(i)
  465. ul.lineDashLengths = [CGFloat(dash), CGFloat(space)]
  466. ul.lineWidth = 1
  467. BGChart.xAxis.addLimitLine(ul)
  468. }
  469. }
  470. if UserDefaultsRepository.show90MinLine.value {
  471. let ul3 = ChartLimitLine()
  472. ul3.limit = Double(dateTimeUtils.getNowTimeIntervalUTC().advanced(by: -90 * 60))
  473. ul3.lineColor = NSUIColor.systemOrange.withAlphaComponent(0.5)
  474. ul3.lineWidth = 1
  475. BGChart.xAxis.addLimitLine(ul3)
  476. }
  477. }
  478. func createMidnightLines() {
  479. // Draw a line at midnight: useful when showing multiple days of data
  480. if UserDefaultsRepository.showMidnightLines.value {
  481. var midnightTimeInterval = dateTimeUtils.getTimeIntervalMidnightToday()
  482. let graphHours = 24 * UserDefaultsRepository.downloadDays.value
  483. let graphStart = dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours)
  484. while midnightTimeInterval > graphStart {
  485. // Large chart
  486. let ul = ChartLimitLine()
  487. ul.limit = Double(midnightTimeInterval)
  488. ul.lineColor = NSUIColor.systemTeal.withAlphaComponent(0.5)
  489. ul.lineDashLengths = [CGFloat(2), CGFloat(5)]
  490. ul.lineWidth = 1
  491. BGChart.xAxis.addLimitLine(ul)
  492. // Small chart
  493. let sl = ChartLimitLine()
  494. sl.limit = Double(midnightTimeInterval)
  495. sl.lineColor = NSUIColor.systemTeal
  496. sl.lineDashLengths = [CGFloat(2), CGFloat(2)]
  497. sl.lineWidth = 1
  498. BGChartFull.xAxis.addLimitLine(sl)
  499. midnightTimeInterval = midnightTimeInterval.advanced(by: -24*60*60)
  500. }
  501. }
  502. }
  503. func updateBGGraphSettings() {
  504. let dataIndex = 0
  505. let dataIndexPrediction = 1
  506. let lineBG = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  507. let linePrediction = BGChart.lineData!.dataSets[dataIndexPrediction] as! LineChartDataSet
  508. if UserDefaultsRepository.showLines.value {
  509. lineBG.lineWidth = 2
  510. linePrediction.lineWidth = 2
  511. } else {
  512. lineBG.lineWidth = 0
  513. linePrediction.lineWidth = 0
  514. }
  515. if UserDefaultsRepository.showDots.value {
  516. lineBG.drawCirclesEnabled = true
  517. linePrediction.drawCirclesEnabled = true
  518. } else {
  519. lineBG.drawCirclesEnabled = false
  520. linePrediction.drawCirclesEnabled = false
  521. }
  522. BGChart.rightAxis.axisMinimum = 0
  523. // Clear limit lines so they don't add multiples when changing the settings
  524. BGChart.rightAxis.removeAllLimitLines()
  525. //Add lower red line based on low alert value
  526. let ll = ChartLimitLine()
  527. ll.limit = Double(UserDefaultsRepository.lowLine.value)
  528. ll.lineColor = NSUIColor.systemRed.withAlphaComponent(0.5)
  529. BGChart.rightAxis.addLimitLine(ll)
  530. //Add upper yellow line based on low alert value
  531. let ul = ChartLimitLine()
  532. ul.limit = Double(UserDefaultsRepository.highLine.value)
  533. ul.lineColor = NSUIColor.systemYellow.withAlphaComponent(0.5)
  534. BGChart.rightAxis.addLimitLine(ul)
  535. // Re-create vertical markers in case their settings changed
  536. createVerticalLines()
  537. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  538. BGChart.data?.notifyDataChanged()
  539. BGChart.notifyDataSetChanged()
  540. }
  541. func updateBGGraph() {
  542. if UserDefaultsRepository.debugLog.value { writeDebugLog(value: "##### Start BG Graph #####") }
  543. let dataIndex = 0
  544. let entries = bgData
  545. guard !entries.isEmpty else {
  546. return
  547. }
  548. let mainChart = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  549. let smallChart = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  550. mainChart.removeAll(keepingCapacity: false)
  551. smallChart.removeAll(keepingCapacity: false)
  552. let maxBGOffset: Float = 50
  553. var colors = [NSUIColor]()
  554. topBG = UserDefaultsRepository.minBGScale.value
  555. for i in 0..<entries.count{
  556. if Float(entries[i].sgv) > topBG - maxBGOffset {
  557. topBG = Float(entries[i].sgv) + maxBGOffset
  558. }
  559. let value = ChartDataEntry(x: Double(entries[i].date), y: Double(entries[i].sgv), data: formatPillText(line1: Localizer.toDisplayUnits(String(entries[i].sgv)), time: entries[i].date))
  560. if UserDefaultsRepository.debugLog.value { writeDebugLog(value: "BG: " + value.description) }
  561. mainChart.append(value)
  562. smallChart.append(value)
  563. if Double(entries[i].sgv) >= Double(UserDefaultsRepository.highLine.value) {
  564. colors.append(NSUIColor.systemYellow)
  565. } else if Double(entries[i].sgv) <= Double(UserDefaultsRepository.lowLine.value) {
  566. colors.append(NSUIColor.systemRed)
  567. } else {
  568. colors.append(NSUIColor.systemGreen)
  569. }
  570. }
  571. if UserDefaultsRepository.debugLog.value { writeDebugLog(value: "Total Graph BGs: " + mainChart.entries.count.description) }
  572. // Set Colors
  573. let lineBG = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  574. let lineBGSmall = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  575. lineBG.colors.removeAll()
  576. lineBG.circleColors.removeAll()
  577. lineBGSmall.colors.removeAll()
  578. lineBGSmall.circleColors.removeAll()
  579. if colors.count > 0 {
  580. for i in 0..<colors.count{
  581. mainChart.addColor(colors[i])
  582. mainChart.circleColors.append(colors[i])
  583. smallChart.addColor(colors[i])
  584. smallChart.circleColors.append(colors[i])
  585. }
  586. }
  587. if UserDefaultsRepository.debugLog.value { writeDebugLog(value: "Total Colors: " + mainChart.colors.count.description) }
  588. BGChart.rightAxis.axisMaximum = Double(calculateMaxBgGraphValue())
  589. BGChart.setVisibleXRangeMinimum(600)
  590. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  591. BGChart.data?.notifyDataChanged()
  592. BGChart.notifyDataSetChanged()
  593. BGChartFull.rightAxis.axisMaximum = Double(calculateMaxBgGraphValue())
  594. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  595. BGChartFull.data?.notifyDataChanged()
  596. BGChartFull.notifyDataSetChanged()
  597. if firstGraphLoad {
  598. var scaleX = CGFloat(UserDefaultsRepository.chartScaleX.value)
  599. print("Scale: \(scaleX)")
  600. if( scaleX > CGFloat(ScaleXMax) ) {
  601. scaleX = CGFloat(ScaleXMax)
  602. UserDefaultsRepository.chartScaleX.value = ScaleXMax
  603. }
  604. BGChart.zoom(scaleX: scaleX, scaleY: 1, x: 1, y: 1)
  605. firstGraphLoad = false
  606. }
  607. // Move to current reading everytime new readings load
  608. // Check if auto-scrolling should be performed
  609. if autoScrollPauseUntil == nil || Date() > autoScrollPauseUntil! {
  610. BGChart.moveViewToAnimated(xValue: dateTimeUtils.getNowTimeIntervalUTC() - (BGChart.visibleXRange * 0.7), yValue: 0.0, axis: .right, duration: 1, easingOption: .easeInBack)
  611. }
  612. }
  613. func updatePredictionGraph(color: UIColor? = nil) {
  614. let dataIndex = 1
  615. var mainChart = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  616. var smallChart = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  617. mainChart.clear()
  618. smallChart.clear()
  619. var colors = [NSUIColor]()
  620. let maxBGOffset: Float = 20
  621. topPredictionBG = UserDefaultsRepository.minBGScale.value
  622. for i in 0..<predictionData.count {
  623. var predictionVal = Double(predictionData[i].sgv)
  624. if Float(predictionVal) > topPredictionBG - maxBGOffset {
  625. topPredictionBG = Float(predictionVal) + maxBGOffset
  626. }
  627. if i == 0 {
  628. if UserDefaultsRepository.showDots.value {
  629. colors.append((color ?? NSUIColor.systemPurple).withAlphaComponent(0.0))
  630. } else {
  631. colors.append((color ?? NSUIColor.systemPurple).withAlphaComponent(1.0))
  632. }
  633. } else if predictionVal > 400 {
  634. colors.append(color ?? NSUIColor.systemYellow)
  635. } else if predictionVal < 0 {
  636. colors.append(color ?? NSUIColor.systemRed)
  637. } else {
  638. colors.append(color ?? NSUIColor.systemPurple)
  639. }
  640. let value = ChartDataEntry(x: predictionData[i].date, y: predictionVal, data: formatPillText(line1: Localizer.toDisplayUnits(String(predictionData[i].sgv)), time: predictionData[i].date))
  641. mainChart.addEntry(value)
  642. smallChart.addEntry(value)
  643. }
  644. smallChart.circleColors.removeAll()
  645. smallChart.colors.removeAll()
  646. mainChart.colors.removeAll()
  647. mainChart.circleColors.removeAll()
  648. if colors.count > 0 {
  649. for i in 0..<colors.count {
  650. mainChart.addColor(colors[i])
  651. mainChart.circleColors.append(colors[i])
  652. smallChart.addColor(colors[i])
  653. smallChart.circleColors.append(colors[i])
  654. }
  655. }
  656. BGChart.rightAxis.axisMaximum = Double(calculateMaxBgGraphValue())
  657. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  658. BGChart.data?.notifyDataChanged()
  659. BGChart.notifyDataSetChanged()
  660. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  661. BGChartFull.data?.notifyDataChanged()
  662. BGChartFull.notifyDataSetChanged()
  663. }
  664. func updateBasalGraph() {
  665. var dataIndex = 2
  666. BGChart.lineData?.dataSets[dataIndex].clear()
  667. BGChartFull.lineData?.dataSets[dataIndex].clear()
  668. var maxBasal = UserDefaultsRepository.minBasalScale.value
  669. var maxBasalSmall: Double = 0.0
  670. for i in 0..<basalData.count{
  671. let value = ChartDataEntry(x: Double(basalData[i].date), y: Double(basalData[i].basalRate), data: formatPillText(line1: String(basalData[i].basalRate), time: basalData[i].date))
  672. BGChart.data?.dataSets[dataIndex].addEntry(value)
  673. if UserDefaultsRepository.smallGraphTreatments.value {
  674. BGChartFull.data?.dataSets[dataIndex].addEntry(value)
  675. }
  676. if basalData[i].basalRate > maxBasal {
  677. maxBasal = basalData[i].basalRate
  678. }
  679. if basalData[i].basalRate > maxBasalSmall {
  680. maxBasalSmall = basalData[i].basalRate
  681. }
  682. }
  683. BGChart.leftAxis.axisMaximum = maxBasal
  684. BGChartFull.leftAxis.axisMaximum = maxBasalSmall
  685. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  686. BGChart.data?.notifyDataChanged()
  687. BGChart.notifyDataSetChanged()
  688. if UserDefaultsRepository.smallGraphTreatments.value {
  689. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  690. BGChartFull.data?.notifyDataChanged()
  691. BGChartFull.notifyDataSetChanged()
  692. }
  693. }
  694. func updateBasalScheduledGraph() {
  695. var dataIndex = 5
  696. BGChart.lineData?.dataSets[dataIndex].clear()
  697. BGChartFull.lineData?.dataSets[dataIndex].clear()
  698. for i in 0..<basalScheduleData.count{
  699. let value = ChartDataEntry(x: Double(basalScheduleData[i].date), y: Double(basalScheduleData[i].basalRate))
  700. BGChart.data?.dataSets[dataIndex].addEntry(value)
  701. if UserDefaultsRepository.smallGraphTreatments.value {
  702. BGChartFull.data?.dataSets[dataIndex].addEntry(value)
  703. }
  704. }
  705. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  706. BGChart.data?.notifyDataChanged()
  707. BGChart.notifyDataSetChanged()
  708. if UserDefaultsRepository.smallGraphTreatments.value {
  709. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  710. BGChartFull.data?.notifyDataChanged()
  711. BGChartFull.notifyDataSetChanged()
  712. }
  713. }
  714. func updateBolusGraph() {
  715. var dataIndex = 3
  716. var yTop: Double = 370
  717. var yBottom: Double = 345
  718. var mainChart = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  719. var smallChart = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  720. mainChart.clear()
  721. smallChart.clear()
  722. var colors = [NSUIColor]()
  723. for i in 0..<bolusData.count{
  724. let formatter = NumberFormatter()
  725. formatter.minimumFractionDigits = 0
  726. formatter.maximumFractionDigits = 2
  727. formatter.minimumIntegerDigits = 0
  728. // Check overlapping carbs to shift left if needed
  729. let bolusShift = findNextBolusTime(timeWithin: 240, needle: bolusData[i].date, haystack: bolusData, startingIndex: i)
  730. var dateTimeStamp = bolusData[i].date
  731. colors.append(NSUIColor.systemBlue.withAlphaComponent(1.0))
  732. if bolusShift {
  733. // Move it half the distance between BG readings
  734. dateTimeStamp = dateTimeStamp - 150
  735. }
  736. // skip if outside of visible area
  737. let graphHours = 24 * UserDefaultsRepository.downloadDays.value
  738. if dateTimeStamp < dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours) { continue }
  739. let dot = ChartDataEntry(x: Double(dateTimeStamp), y: Double(bolusData[i].sgv), data: formatter.string(from: NSNumber(value: bolusData[i].value)))
  740. mainChart.addEntry(dot)
  741. if UserDefaultsRepository.smallGraphTreatments.value {
  742. smallChart.addEntry(dot)
  743. }
  744. }
  745. // Set Colors
  746. let lineBolus = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  747. let lineBolusSmall = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  748. lineBolus.colors.removeAll()
  749. lineBolus.circleColors.removeAll()
  750. lineBolusSmall.colors.removeAll()
  751. lineBolusSmall.circleColors.removeAll()
  752. if colors.count > 0 {
  753. for i in 0..<colors.count{
  754. mainChart.addColor(colors[i])
  755. mainChart.circleColors.append(colors[i])
  756. smallChart.addColor(colors[i])
  757. smallChart.circleColors.append(colors[i])
  758. }
  759. }
  760. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  761. BGChart.data?.notifyDataChanged()
  762. BGChart.notifyDataSetChanged()
  763. if UserDefaultsRepository.smallGraphTreatments.value {
  764. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  765. BGChartFull.data?.notifyDataChanged()
  766. BGChartFull.notifyDataSetChanged()
  767. }
  768. }
  769. func updateSmbGraph() {
  770. var dataIndex = 16
  771. var yTop: Double = 370
  772. var yBottom: Double = 345
  773. var mainChart = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  774. var smallChart = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  775. mainChart.clear()
  776. smallChart.clear()
  777. let lightBlue = NSUIColor(red: 135/255, green: 206/255, blue: 235/255, alpha: 1.0) // Light Sky Blue
  778. var colors = [NSUIColor]()
  779. for i in 0..<smbData.count {
  780. let formatter = NumberFormatter()
  781. formatter.minimumFractionDigits = 0
  782. formatter.maximumFractionDigits = 2
  783. formatter.minimumIntegerDigits = 0
  784. let bolusShift = findNextBolusTime(timeWithin: 240, needle: smbData[i].date, haystack: smbData, startingIndex: i)
  785. var dateTimeStamp = smbData[i].date
  786. let nowTime = dateTimeUtils.getNowTimeIntervalUTC()
  787. let diffTimeHours = (nowTime - dateTimeStamp) / 60 / 60
  788. if diffTimeHours <= 1 {
  789. colors.append(lightBlue.withAlphaComponent(1.0))
  790. } else if diffTimeHours > 6 {
  791. colors.append(lightBlue.withAlphaComponent(0.25))
  792. } else {
  793. let thisAlpha = 1.0 - (0.15 * diffTimeHours)
  794. colors.append(lightBlue.withAlphaComponent(CGFloat(thisAlpha)))
  795. }
  796. if bolusShift {
  797. dateTimeStamp = dateTimeStamp - 150
  798. }
  799. let graphHours = 24 * UserDefaultsRepository.downloadDays.value
  800. if dateTimeStamp < dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours) { continue }
  801. let dot = ChartDataEntry(x: Double(dateTimeStamp), y: Double(smbData[i].sgv), data: formatter.string(from: NSNumber(value: smbData[i].value)))
  802. mainChart.addEntry(dot)
  803. if UserDefaultsRepository.smallGraphTreatments.value {
  804. smallChart.addEntry(dot)
  805. }
  806. }
  807. let smbRenderer = TriangleRenderer(dataProvider: BGChart, animator: Animator(), viewPortHandler: BGChart.viewPortHandler, smbDataSetIndex: dataIndex)
  808. BGChart.renderer = smbRenderer
  809. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  810. BGChart.data?.notifyDataChanged()
  811. BGChart.notifyDataSetChanged()
  812. if UserDefaultsRepository.smallGraphTreatments.value {
  813. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  814. BGChartFull.data?.notifyDataChanged()
  815. BGChartFull.notifyDataSetChanged()
  816. }
  817. }
  818. func updateCarbGraph() {
  819. var dataIndex = 4
  820. var mainChart = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  821. var smallChart = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  822. mainChart.clear()
  823. smallChart.clear()
  824. var colors = [NSUIColor]()
  825. for i in 0..<carbData.count{
  826. let formatter = NumberFormatter()
  827. formatter.minimumFractionDigits = 0
  828. formatter.maximumFractionDigits = 2
  829. formatter.minimumIntegerDigits = 1
  830. var valueString: String = formatter.string(from: NSNumber(value: carbData[i].value))!
  831. var hours = 3
  832. if carbData[i].absorptionTime > 0 && UserDefaultsRepository.showAbsorption.value {
  833. hours = carbData[i].absorptionTime / 60
  834. valueString += " " + String(hours) + "h"
  835. }
  836. // Check overlapping carbs to shift left if needed
  837. let carbShift = findNextCarbTime(timeWithin: 250, needle: carbData[i].date, haystack: carbData, startingIndex: i)
  838. var dateTimeStamp = carbData[i].date
  839. colors.append(NSUIColor.systemOrange.withAlphaComponent(1.0))
  840. // skip if outside of visible area
  841. let graphHours = 24 * UserDefaultsRepository.downloadDays.value
  842. if dateTimeStamp < dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours) { continue }
  843. if carbShift {
  844. dateTimeStamp = dateTimeStamp - 250
  845. }
  846. let dot = ChartDataEntry(x: Double(dateTimeStamp), y: Double(carbData[i].sgv), data: valueString)
  847. BGChart.data?.dataSets[dataIndex].addEntry(dot)
  848. if UserDefaultsRepository.smallGraphTreatments.value {
  849. BGChartFull.data?.dataSets[dataIndex].addEntry(dot)
  850. }
  851. }
  852. // Set Colors
  853. let lineCarbs = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  854. let lineCarbsSmall = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  855. lineCarbs.colors.removeAll()
  856. lineCarbs.circleColors.removeAll()
  857. lineCarbsSmall.colors.removeAll()
  858. lineCarbsSmall.circleColors.removeAll()
  859. if colors.count > 0 {
  860. for i in 0..<colors.count{
  861. mainChart.addColor(colors[i])
  862. mainChart.circleColors.append(colors[i])
  863. smallChart.addColor(colors[i])
  864. smallChart.circleColors.append(colors[i])
  865. }
  866. }
  867. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  868. BGChart.data?.notifyDataChanged()
  869. BGChart.notifyDataSetChanged()
  870. if UserDefaultsRepository.smallGraphTreatments.value {
  871. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  872. BGChartFull.data?.notifyDataChanged()
  873. BGChartFull.notifyDataSetChanged()
  874. }
  875. }
  876. func updateBGCheckGraph() {
  877. var dataIndex = 7
  878. BGChart.lineData?.dataSets[dataIndex].clear()
  879. BGChartFull.lineData?.dataSets[dataIndex].clear()
  880. for i in 0..<bgCheckData.count{
  881. let formatter = NumberFormatter()
  882. formatter.minimumFractionDigits = 0
  883. formatter.maximumFractionDigits = 2
  884. formatter.minimumIntegerDigits = 1
  885. // skip if outside of visible area
  886. let graphHours = 24 * UserDefaultsRepository.downloadDays.value
  887. if bgCheckData[i].date < dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours) { continue }
  888. let value = ChartDataEntry(x: Double(bgCheckData[i].date), y: Double(bgCheckData[i].sgv), data: formatPillText(line1: Localizer.toDisplayUnits(String(bgCheckData[i].sgv)), time: bgCheckData[i].date))
  889. BGChart.data?.dataSets[dataIndex].addEntry(value)
  890. if UserDefaultsRepository.smallGraphTreatments.value {
  891. BGChartFull.data?.dataSets[dataIndex].addEntry(value)
  892. }
  893. }
  894. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  895. BGChart.data?.notifyDataChanged()
  896. BGChart.notifyDataSetChanged()
  897. if UserDefaultsRepository.smallGraphTreatments.value {
  898. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  899. BGChartFull.data?.notifyDataChanged()
  900. BGChartFull.notifyDataSetChanged()
  901. }
  902. }
  903. func updateSuspendGraph() {
  904. var dataIndex = 8
  905. BGChart.lineData?.dataSets[dataIndex].clear()
  906. BGChartFull.lineData?.dataSets[dataIndex].clear()
  907. let thisData = suspendGraphData
  908. for i in 0..<thisData.count{
  909. // skip if outside of visible area
  910. let graphHours = 24 * UserDefaultsRepository.downloadDays.value
  911. if thisData[i].date < dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours) { continue }
  912. let value = ChartDataEntry(x: Double(thisData[i].date), y: Double(thisData[i].sgv), data: formatPillText(line1: "Suspend Pump", time: thisData[i].date))
  913. BGChart.data?.dataSets[dataIndex].addEntry(value)
  914. if UserDefaultsRepository.smallGraphTreatments.value {
  915. BGChartFull.data?.dataSets[dataIndex].addEntry(value)
  916. }
  917. }
  918. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  919. BGChart.data?.notifyDataChanged()
  920. BGChart.notifyDataSetChanged()
  921. if UserDefaultsRepository.smallGraphTreatments.value {
  922. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  923. BGChartFull.data?.notifyDataChanged()
  924. BGChartFull.notifyDataSetChanged()
  925. }
  926. }
  927. func updateResumeGraph() {
  928. var dataIndex = 9
  929. BGChart.lineData?.dataSets[dataIndex].clear()
  930. BGChartFull.lineData?.dataSets[dataIndex].clear()
  931. let thisData = resumeGraphData
  932. for i in 0..<thisData.count{
  933. // skip if outside of visible area
  934. let graphHours = 24 * UserDefaultsRepository.downloadDays.value
  935. if thisData[i].date < dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours) { continue }
  936. let value = ChartDataEntry(x: Double(thisData[i].date), y: Double(thisData[i].sgv), data: formatPillText(line1: "Resume Pump", time: thisData[i].date))
  937. BGChart.data?.dataSets[dataIndex].addEntry(value)
  938. if UserDefaultsRepository.smallGraphTreatments.value {
  939. BGChartFull.data?.dataSets[dataIndex].addEntry(value)
  940. }
  941. }
  942. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  943. BGChart.data?.notifyDataChanged()
  944. BGChart.notifyDataSetChanged()
  945. if UserDefaultsRepository.smallGraphTreatments.value {
  946. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  947. BGChartFull.data?.notifyDataChanged()
  948. BGChartFull.notifyDataSetChanged()
  949. }
  950. }
  951. func updateSensorStart() {
  952. var dataIndex = 10
  953. BGChart.lineData?.dataSets[dataIndex].clear()
  954. BGChartFull.lineData?.dataSets[dataIndex].clear()
  955. let thisData = sensorStartGraphData
  956. for i in 0..<thisData.count{
  957. // skip if outside of visible area
  958. let graphHours = 24 * UserDefaultsRepository.downloadDays.value
  959. if thisData[i].date < dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours) { continue }
  960. let value = ChartDataEntry(x: Double(thisData[i].date), y: Double(thisData[i].sgv), data: formatPillText(line1: "Start Sensor", time: thisData[i].date))
  961. BGChart.data?.dataSets[dataIndex].addEntry(value)
  962. if UserDefaultsRepository.smallGraphTreatments.value {
  963. BGChartFull.data?.dataSets[dataIndex].addEntry(value)
  964. }
  965. }
  966. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  967. BGChart.data?.notifyDataChanged()
  968. BGChart.notifyDataSetChanged()
  969. if UserDefaultsRepository.smallGraphTreatments.value {
  970. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  971. BGChartFull.data?.notifyDataChanged()
  972. BGChartFull.notifyDataSetChanged()
  973. }
  974. }
  975. func updateNotes() {
  976. var dataIndex = 11
  977. BGChart.lineData?.dataSets[dataIndex].clear()
  978. BGChartFull.lineData?.dataSets[dataIndex].clear()
  979. let thisData = noteGraphData
  980. for i in 0..<thisData.count{
  981. // skip if outside of visible area
  982. let graphHours = 24 * UserDefaultsRepository.downloadDays.value
  983. if thisData[i].date < dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours) { continue }
  984. let value = ChartDataEntry(x: Double(thisData[i].date), y: Double(thisData[i].sgv), data: formatPillText(line1: thisData[i].note, time: thisData[i].date))
  985. BGChart.data?.dataSets[dataIndex].addEntry(value)
  986. if UserDefaultsRepository.smallGraphTreatments.value {
  987. BGChartFull.data?.dataSets[dataIndex].addEntry(value)
  988. }
  989. }
  990. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  991. BGChart.data?.notifyDataChanged()
  992. BGChart.notifyDataSetChanged()
  993. if UserDefaultsRepository.smallGraphTreatments.value {
  994. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  995. BGChartFull.data?.notifyDataChanged()
  996. BGChartFull.notifyDataSetChanged()
  997. }
  998. }
  999. func createSmallBGGraph(){
  1000. let entries = bgData
  1001. var bgChartEntry = [ChartDataEntry]()
  1002. var colors = [NSUIColor]()
  1003. var maxBG: Float = UserDefaultsRepository.minBGScale.value
  1004. let lineBG = LineChartDataSet(entries:bgChartEntry, label: "")
  1005. lineBG.drawCirclesEnabled = false
  1006. //line2.setDrawHighlightIndicators(false)
  1007. lineBG.highlightEnabled = true
  1008. lineBG.drawHorizontalHighlightIndicatorEnabled = false
  1009. lineBG.drawVerticalHighlightIndicatorEnabled = false
  1010. lineBG.highlightColor = NSUIColor.label
  1011. lineBG.drawValuesEnabled = false
  1012. lineBG.lineWidth = 1.5
  1013. lineBG.axisDependency = YAxis.AxisDependency.right
  1014. // Setup Prediction line details
  1015. var predictionChartEntry = [ChartDataEntry]()
  1016. let linePrediction = LineChartDataSet(entries:predictionChartEntry, label: "")
  1017. linePrediction.drawCirclesEnabled = false
  1018. //line2.setDrawHighlightIndicators(false)
  1019. linePrediction.setColor(NSUIColor.systemPurple)
  1020. linePrediction.highlightEnabled = true
  1021. linePrediction.drawHorizontalHighlightIndicatorEnabled = false
  1022. linePrediction.drawVerticalHighlightIndicatorEnabled = false
  1023. linePrediction.highlightColor = NSUIColor.label
  1024. linePrediction.drawValuesEnabled = false
  1025. linePrediction.lineWidth = 1.5
  1026. linePrediction.axisDependency = YAxis.AxisDependency.right
  1027. // create Basal graph data
  1028. var chartEntry = [ChartDataEntry]()
  1029. var maxBasal = UserDefaultsRepository.minBasalScale.value
  1030. let lineBasal = LineChartDataSet(entries:chartEntry, label: "")
  1031. lineBasal.setDrawHighlightIndicators(false)
  1032. lineBasal.setColor(NSUIColor.systemBlue, alpha: 0.5)
  1033. lineBasal.lineWidth = 0
  1034. lineBasal.drawFilledEnabled = true
  1035. lineBasal.fillColor = NSUIColor.systemBlue
  1036. lineBasal.fillAlpha = 0.35
  1037. lineBasal.drawCirclesEnabled = false
  1038. lineBasal.axisDependency = YAxis.AxisDependency.left
  1039. lineBasal.highlightEnabled = false
  1040. lineBasal.drawValuesEnabled = false
  1041. lineBasal.fillFormatter = basalFillFormatter()
  1042. // Boluses
  1043. var chartEntryBolus = [ChartDataEntry]()
  1044. let lineBolus = LineChartDataSet(entries:chartEntryBolus, label: "")
  1045. lineBolus.circleRadius = 2
  1046. lineBolus.circleColors = [NSUIColor.systemBlue.withAlphaComponent(0.75)]
  1047. lineBolus.drawCircleHoleEnabled = false
  1048. lineBolus.setDrawHighlightIndicators(false)
  1049. lineBolus.setColor(NSUIColor.systemBlue, alpha: 1.0)
  1050. lineBolus.lineWidth = 0
  1051. lineBolus.axisDependency = YAxis.AxisDependency.right
  1052. lineBolus.valueFormatter = ChartYDataValueFormatter()
  1053. lineBolus.valueTextColor = NSUIColor.label
  1054. lineBolus.fillColor = NSUIColor.systemBlue
  1055. lineBolus.fillAlpha = 0.6
  1056. lineBolus.drawCirclesEnabled = true
  1057. lineBolus.drawFilledEnabled = false
  1058. lineBolus.drawValuesEnabled = false
  1059. lineBolus.highlightEnabled = false
  1060. // Carbs
  1061. var chartEntryCarbs = [ChartDataEntry]()
  1062. let lineCarbs = LineChartDataSet(entries:chartEntryCarbs, label: "")
  1063. lineCarbs.circleRadius = 2
  1064. lineCarbs.circleColors = [NSUIColor.systemOrange.withAlphaComponent(0.75)]
  1065. lineCarbs.drawCircleHoleEnabled = false
  1066. lineCarbs.setDrawHighlightIndicators(false)
  1067. lineCarbs.setColor(NSUIColor.systemBlue, alpha: 1.0)
  1068. lineCarbs.lineWidth = 0
  1069. lineCarbs.axisDependency = YAxis.AxisDependency.right
  1070. lineCarbs.valueFormatter = ChartYDataValueFormatter()
  1071. lineCarbs.valueTextColor = NSUIColor.label
  1072. lineCarbs.fillColor = NSUIColor.systemOrange
  1073. lineCarbs.fillAlpha = 0.6
  1074. lineCarbs.drawCirclesEnabled = true
  1075. lineCarbs.drawFilledEnabled = false
  1076. lineCarbs.drawValuesEnabled = false
  1077. lineCarbs.highlightEnabled = false
  1078. // create Scheduled Basal graph data
  1079. var chartBasalScheduledEntry = [ChartDataEntry]()
  1080. let lineBasalScheduled = LineChartDataSet(entries:chartBasalScheduledEntry, label: "")
  1081. lineBasalScheduled.setDrawHighlightIndicators(false)
  1082. lineBasalScheduled.setColor(NSUIColor.systemBlue, alpha: 0.8)
  1083. lineBasalScheduled.lineWidth = 0.5
  1084. lineBasalScheduled.drawFilledEnabled = false
  1085. lineBasalScheduled.drawCirclesEnabled = false
  1086. lineBasalScheduled.axisDependency = YAxis.AxisDependency.left
  1087. lineBasalScheduled.highlightEnabled = false
  1088. lineBasalScheduled.drawValuesEnabled = false
  1089. lineBasalScheduled.lineDashLengths = [2, 1]
  1090. // create Override graph data
  1091. var chartOverrideEntry = [ChartDataEntry]()
  1092. let lineOverride = LineChartDataSet(entries:chartOverrideEntry, label: "")
  1093. lineOverride.setDrawHighlightIndicators(false)
  1094. lineOverride.lineWidth = 0
  1095. lineOverride.drawFilledEnabled = true
  1096. lineOverride.fillFormatter = OverrideFillFormatter()
  1097. lineOverride.fillColor = NSUIColor.systemGreen
  1098. lineOverride.fillAlpha = 0.6
  1099. lineOverride.drawCirclesEnabled = false
  1100. lineOverride.axisDependency = YAxis.AxisDependency.right
  1101. lineOverride.highlightEnabled = true
  1102. lineOverride.drawValuesEnabled = false
  1103. // BG Check
  1104. var chartEntryBGCheck = [ChartDataEntry]()
  1105. let lineBGCheck = LineChartDataSet(entries:chartEntryBGCheck, label: "")
  1106. lineBGCheck.circleRadius = 2
  1107. lineBGCheck.circleColors = [NSUIColor.systemRed.withAlphaComponent(0.75)]
  1108. lineBGCheck.drawCircleHoleEnabled = false
  1109. lineBGCheck.setDrawHighlightIndicators(false)
  1110. lineBGCheck.setColor(NSUIColor.systemRed, alpha: 1.0)
  1111. lineBGCheck.drawCirclesEnabled = true
  1112. lineBGCheck.lineWidth = 0
  1113. lineBGCheck.highlightEnabled = false
  1114. lineBGCheck.axisDependency = YAxis.AxisDependency.right
  1115. lineBGCheck.valueFormatter = ChartYDataValueFormatter()
  1116. lineBGCheck.drawValuesEnabled = false
  1117. // Suspend Pump
  1118. var chartEntrySuspend = [ChartDataEntry]()
  1119. let lineSuspend = LineChartDataSet(entries:chartEntrySuspend, label: "")
  1120. lineSuspend.circleRadius = 2
  1121. lineSuspend.circleColors = [NSUIColor.systemTeal.withAlphaComponent(0.75)]
  1122. lineSuspend.drawCircleHoleEnabled = false
  1123. lineSuspend.setDrawHighlightIndicators(false)
  1124. lineSuspend.setColor(NSUIColor.systemGray2, alpha: 1.0)
  1125. lineSuspend.drawCirclesEnabled = true
  1126. lineSuspend.lineWidth = 0
  1127. lineSuspend.highlightEnabled = false
  1128. lineSuspend.axisDependency = YAxis.AxisDependency.right
  1129. lineSuspend.valueFormatter = ChartYDataValueFormatter()
  1130. lineSuspend.drawValuesEnabled = false
  1131. // Resume Pump
  1132. var chartEntryResume = [ChartDataEntry]()
  1133. let lineResume = LineChartDataSet(entries:chartEntryResume, label: "")
  1134. lineResume.circleRadius = 2
  1135. lineResume.circleColors = [NSUIColor.systemTeal.withAlphaComponent(0.75)]
  1136. lineResume.drawCircleHoleEnabled = false
  1137. lineResume.setDrawHighlightIndicators(false)
  1138. lineResume.setColor(NSUIColor.systemGray4, alpha: 1.0)
  1139. lineResume.drawCirclesEnabled = true
  1140. lineResume.lineWidth = 0
  1141. lineResume.highlightEnabled = false
  1142. lineResume.axisDependency = YAxis.AxisDependency.right
  1143. lineResume.valueFormatter = ChartYDataValueFormatter()
  1144. lineResume.drawValuesEnabled = false
  1145. // Sensor Start
  1146. var chartEntrySensor = [ChartDataEntry]()
  1147. let lineSensor = LineChartDataSet(entries:chartEntrySensor, label: "")
  1148. lineSensor.circleRadius = 2
  1149. lineSensor.circleColors = [NSUIColor.systemIndigo.withAlphaComponent(0.75)]
  1150. lineSensor.drawCircleHoleEnabled = false
  1151. lineSensor.setDrawHighlightIndicators(false)
  1152. lineSensor.setColor(NSUIColor.systemGray3, alpha: 1.0)
  1153. lineSensor.drawCirclesEnabled = true
  1154. lineSensor.lineWidth = 0
  1155. lineSensor.highlightEnabled = false
  1156. lineSensor.axisDependency = YAxis.AxisDependency.right
  1157. lineSensor.valueFormatter = ChartYDataValueFormatter()
  1158. lineSensor.drawValuesEnabled = false
  1159. // Notes
  1160. var chartEntryNote = [ChartDataEntry]()
  1161. let lineNote = LineChartDataSet(entries:chartEntryNote, label: "")
  1162. lineNote.circleRadius = 2
  1163. lineNote.circleColors = [NSUIColor.systemGray.withAlphaComponent(0.75)]
  1164. lineNote.drawCircleHoleEnabled = false
  1165. lineNote.setDrawHighlightIndicators(false)
  1166. lineNote.setColor(NSUIColor.systemGray3, alpha: 1.0)
  1167. lineNote.drawCirclesEnabled = true
  1168. lineNote.lineWidth = 0
  1169. lineNote.highlightEnabled = false
  1170. lineNote.axisDependency = YAxis.AxisDependency.right
  1171. lineNote.valueFormatter = ChartYDataValueFormatter()
  1172. lineNote.drawValuesEnabled = false
  1173. // Setup COB Prediction line details
  1174. var COBpredictionChartEntry = [ChartDataEntry]()
  1175. let COBlinePrediction = LineChartDataSet(entries:COBpredictionChartEntry, label: "")
  1176. COBlinePrediction.drawCirclesEnabled = false
  1177. COBlinePrediction.setColor(NSUIColor.systemPurple)
  1178. COBlinePrediction.highlightEnabled = true
  1179. COBlinePrediction.drawHorizontalHighlightIndicatorEnabled = false
  1180. COBlinePrediction.drawVerticalHighlightIndicatorEnabled = false
  1181. COBlinePrediction.highlightColor = NSUIColor.label
  1182. COBlinePrediction.drawValuesEnabled = false
  1183. COBlinePrediction.lineWidth = 1.5
  1184. COBlinePrediction.axisDependency = YAxis.AxisDependency.right
  1185. // Setup IOB Prediction line details
  1186. var IOBpredictionChartEntry = [ChartDataEntry]()
  1187. let IOBlinePrediction = LineChartDataSet(entries:IOBpredictionChartEntry, label: "")
  1188. IOBlinePrediction.drawCirclesEnabled = false
  1189. IOBlinePrediction.setColor(NSUIColor.systemPurple)
  1190. IOBlinePrediction.highlightEnabled = true
  1191. IOBlinePrediction.drawHorizontalHighlightIndicatorEnabled = false
  1192. IOBlinePrediction.drawVerticalHighlightIndicatorEnabled = false
  1193. IOBlinePrediction.highlightColor = NSUIColor.label
  1194. IOBlinePrediction.drawValuesEnabled = false
  1195. IOBlinePrediction.lineWidth = 1.5
  1196. IOBlinePrediction.axisDependency = YAxis.AxisDependency.right
  1197. // Setup UAM Prediction line details
  1198. var UAMpredictionChartEntry = [ChartDataEntry]()
  1199. let UAMlinePrediction = LineChartDataSet(entries:UAMpredictionChartEntry, label: "")
  1200. UAMlinePrediction.drawCirclesEnabled = false
  1201. UAMlinePrediction.setColor(NSUIColor.systemPurple)
  1202. UAMlinePrediction.highlightEnabled = true
  1203. UAMlinePrediction.drawHorizontalHighlightIndicatorEnabled = false
  1204. UAMlinePrediction.drawVerticalHighlightIndicatorEnabled = false
  1205. UAMlinePrediction.highlightColor = NSUIColor.label
  1206. UAMlinePrediction.drawValuesEnabled = false
  1207. UAMlinePrediction.lineWidth = 1.5
  1208. UAMlinePrediction.axisDependency = YAxis.AxisDependency.right
  1209. // Setup ZT Prediction line details
  1210. var ZTpredictionChartEntry = [ChartDataEntry]()
  1211. let ZTlinePrediction = LineChartDataSet(entries:ZTpredictionChartEntry, label: "")
  1212. ZTlinePrediction.drawCirclesEnabled = false
  1213. ZTlinePrediction.setColor(NSUIColor.systemPurple)
  1214. ZTlinePrediction.highlightEnabled = true
  1215. ZTlinePrediction.drawHorizontalHighlightIndicatorEnabled = false
  1216. ZTlinePrediction.drawVerticalHighlightIndicatorEnabled = false
  1217. ZTlinePrediction.highlightColor = NSUIColor.label
  1218. ZTlinePrediction.drawValuesEnabled = false
  1219. ZTlinePrediction.lineWidth = 1.5
  1220. ZTlinePrediction.axisDependency = YAxis.AxisDependency.right
  1221. // SMB
  1222. var chartEntrySmb = [ChartDataEntry]()
  1223. let lineSmb = LineChartDataSet(entries:chartEntrySmb, label: "")
  1224. lineSmb.circleRadius = 2
  1225. lineSmb.circleColors = [NSUIColor.systemBlue.withAlphaComponent(0.75)]
  1226. lineSmb.drawCircleHoleEnabled = false
  1227. lineSmb.setDrawHighlightIndicators(false)
  1228. lineSmb.setColor(NSUIColor.systemBlue, alpha: 1.0)
  1229. lineSmb.lineWidth = 0
  1230. lineSmb.axisDependency = YAxis.AxisDependency.right
  1231. lineSmb.valueFormatter = ChartYDataValueFormatter()
  1232. lineSmb.valueTextColor = NSUIColor.label
  1233. lineSmb.fillColor = NSUIColor.systemBlue
  1234. lineSmb.fillAlpha = 0.6
  1235. lineSmb.drawCirclesEnabled = true
  1236. lineSmb.drawFilledEnabled = false
  1237. lineSmb.drawValuesEnabled = false
  1238. lineSmb.highlightEnabled = false
  1239. // Setup the chart data of all lines
  1240. let data = LineChartData()
  1241. data.append(lineBG) // Dataset 0
  1242. data.append(linePrediction) // Dataset 1
  1243. data.append(lineBasal) // Dataset 2
  1244. data.append(lineBolus) // Dataset 3
  1245. data.append(lineCarbs) // Dataset 4
  1246. data.append(lineBasalScheduled) // Dataset 5
  1247. data.append(lineOverride) // Dataset 6
  1248. data.append(lineBGCheck) // Dataset 7
  1249. data.append(lineSuspend) // Dataset 8
  1250. data.append(lineResume) // Dataset 9
  1251. data.append(lineSensor) // Dataset 10
  1252. data.append(lineNote) // Dataset 11
  1253. data.append(ZTlinePrediction) // Dataset 12
  1254. data.append(IOBlinePrediction) // Dataset 13
  1255. data.append(COBlinePrediction) // Dataset 14
  1256. data.append(UAMlinePrediction) // Dataset 15
  1257. data.append(lineSmb) // Dataset 16
  1258. BGChartFull.highlightPerDragEnabled = true
  1259. BGChartFull.leftAxis.enabled = false
  1260. BGChartFull.leftAxis.axisMaximum = maxBasal
  1261. BGChartFull.leftAxis.axisMinimum = 0
  1262. BGChartFull.rightAxis.enabled = false
  1263. BGChartFull.rightAxis.axisMinimum = 0.0
  1264. BGChartFull.rightAxis.axisMaximum = Double(maxBG)
  1265. BGChartFull.xAxis.drawLabelsEnabled = false
  1266. BGChartFull.xAxis.drawGridLinesEnabled = false
  1267. BGChartFull.xAxis.drawAxisLineEnabled = false
  1268. BGChartFull.legend.enabled = false
  1269. BGChartFull.scaleYEnabled = false
  1270. BGChartFull.scaleXEnabled = false
  1271. BGChartFull.drawGridBackgroundEnabled = false
  1272. BGChartFull.data = data
  1273. }
  1274. func updateOverrideGraph() {
  1275. var dataIndex = 6
  1276. var yTop: Double = Double(calculateMaxBgGraphValue() - 5)
  1277. var yBottom: Double = Double(calculateMaxBgGraphValue() - 25)
  1278. var chart = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  1279. var smallChart = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  1280. chart.clear()
  1281. smallChart.clear()
  1282. let thisData = overrideGraphData
  1283. var colors = [NSUIColor]()
  1284. for i in 0..<thisData.count{
  1285. let thisItem = thisData[i]
  1286. let multiplier = thisItem.insulNeedsScaleFactor as! Double * 100.0
  1287. var labelText = thisItem.reason + "\r\n"
  1288. labelText += String(Int(thisItem.insulNeedsScaleFactor * 100)) + "% "
  1289. if thisItem.correctionRange.count == 2 {
  1290. labelText += String(thisItem.correctionRange[0]) + "-" + String(thisItem.correctionRange[1])
  1291. }
  1292. if thisItem.enteredBy.count > 0 {
  1293. labelText += "\r\nEntered By: " + thisItem.enteredBy
  1294. }
  1295. // Start Dot
  1296. // Shift dots 30 seconds to create an empty 0 space between consecutive temps
  1297. let preStartDot = ChartDataEntry(x: Double(thisItem.date), y: yBottom, data: labelText)
  1298. BGChart.data?.dataSets[dataIndex].addEntry(preStartDot)
  1299. if UserDefaultsRepository.smallGraphTreatments.value {
  1300. BGChartFull.data?.dataSets[dataIndex].addEntry(preStartDot)
  1301. }
  1302. let startDot = ChartDataEntry(x: Double(thisItem.date + 1), y: yTop, data: labelText)
  1303. BGChart.data?.dataSets[dataIndex].addEntry(startDot)
  1304. if UserDefaultsRepository.smallGraphTreatments.value {
  1305. BGChartFull.data?.dataSets[dataIndex].addEntry(startDot)
  1306. }
  1307. // End Dot
  1308. let endDot = ChartDataEntry(x: Double(thisItem.endDate - 2), y: yTop, data: labelText)
  1309. BGChart.data?.dataSets[dataIndex].addEntry(endDot)
  1310. if UserDefaultsRepository.smallGraphTreatments.value {
  1311. BGChartFull.data?.dataSets[dataIndex].addEntry(endDot)
  1312. }
  1313. // Post end dot
  1314. let postEndDot = ChartDataEntry(x: Double(thisItem.endDate - 1), y: yBottom, data: labelText)
  1315. BGChart.data?.dataSets[dataIndex].addEntry(postEndDot)
  1316. if UserDefaultsRepository.smallGraphTreatments.value {
  1317. BGChartFull.data?.dataSets[dataIndex].addEntry(postEndDot)
  1318. }
  1319. }
  1320. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  1321. BGChart.data?.notifyDataChanged()
  1322. BGChart.notifyDataSetChanged()
  1323. if UserDefaultsRepository.smallGraphTreatments.value {
  1324. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  1325. BGChartFull.data?.notifyDataChanged()
  1326. BGChartFull.notifyDataSetChanged()
  1327. }
  1328. }
  1329. func formatPillText(line1: String, time: TimeInterval, line2: String? = nil) -> String {
  1330. let dateFormatter = DateFormatter()
  1331. if dateTimeUtils.is24Hour() {
  1332. dateFormatter.setLocalizedDateFormatFromTemplate("HH:mm")
  1333. } else {
  1334. dateFormatter.setLocalizedDateFormatFromTemplate("hh:mm")
  1335. }
  1336. let date = Date(timeIntervalSince1970: time)
  1337. let formattedDate = dateFormatter.string(from: date)
  1338. if let line2 = line2 {
  1339. return line1 + "\r\n" + line2 + "\r\n" + formattedDate
  1340. } else {
  1341. return line1 + "\r\n" + formattedDate
  1342. }
  1343. }
  1344. func updatePredictionGraphGeneric(
  1345. dataIndex: Int,
  1346. predictionData: [ShareGlucoseData],
  1347. chartLabel: String,
  1348. color: UIColor
  1349. ) {
  1350. let mainChart = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
  1351. let smallChart = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
  1352. mainChart.clear()
  1353. smallChart.clear()
  1354. var colors = [NSUIColor]()
  1355. let maxBGOffset: Float = 20
  1356. for i in 0..<predictionData.count {
  1357. let predictionVal = Double(predictionData[i].sgv)
  1358. if Float(predictionVal) > topPredictionBG - maxBGOffset {
  1359. topPredictionBG = Float(predictionVal) + maxBGOffset
  1360. }
  1361. if i == 0 {
  1362. if UserDefaultsRepository.showDots.value {
  1363. colors.append((color).withAlphaComponent(0.0))
  1364. } else {
  1365. colors.append((color).withAlphaComponent(1.0))
  1366. }
  1367. } else {
  1368. colors.append(color)
  1369. }
  1370. let value = ChartDataEntry(
  1371. x: predictionData[i].date,
  1372. y: predictionVal,
  1373. data: formatPillText(
  1374. line1: chartLabel,
  1375. time: predictionData[i].date,
  1376. line2: Localizer.toDisplayUnits(String(predictionVal))
  1377. )
  1378. )
  1379. mainChart.addEntry(value)
  1380. smallChart.addEntry(value)
  1381. }
  1382. smallChart.circleColors.removeAll()
  1383. smallChart.colors.removeAll()
  1384. mainChart.colors.removeAll()
  1385. mainChart.circleColors.removeAll()
  1386. if colors.count > 0 {
  1387. for color in colors {
  1388. mainChart.addColor(color)
  1389. mainChart.circleColors.append(color)
  1390. smallChart.addColor(color)
  1391. smallChart.circleColors.append(color)
  1392. }
  1393. }
  1394. BGChart.rightAxis.axisMaximum = Double(calculateMaxBgGraphValue())
  1395. BGChart.data?.dataSets[dataIndex].notifyDataSetChanged()
  1396. BGChart.data?.notifyDataChanged()
  1397. BGChart.notifyDataSetChanged()
  1398. BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged()
  1399. BGChartFull.data?.notifyDataChanged()
  1400. BGChartFull.notifyDataSetChanged()
  1401. }
  1402. }