// // Graphs.swift // LoopFollow // // Created by Jon Fawcett on 6/16/20. // Copyright © 2020 Jon Fawcett. All rights reserved. // import Foundation import Charts import UIKit let ScaleXMax:Float = 150.0 extension MainViewController { func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) { if chartView == BGChartFull { BGChart.moveViewToX(entry.x) } if entry.data as? String == "hide"{ BGChart.highlightValue(nil, callDelegate: false) } } func chartScaled(_ chartView: ChartViewBase, scaleX: CGFloat, scaleY: CGFloat) { print("Chart Scaled: \(BGChart.scaleX), \(BGChart.scaleY)") // dont store huge values var scale: Float = Float(BGChart.scaleX) if(scale > ScaleXMax ) { scale = ScaleXMax } UserDefaultsRepository.chartScaleX.value = Float(scale) } func createGraph(){ self.BGChart.clear() // Create the BG Graph Data let entries = bgData var bgChartEntry = [ChartDataEntry]() var colors = [NSUIColor]() var maxBG: Float = UserDefaultsRepository.minBGScale.value // Setup BG line details let lineBG = LineChartDataSet(entries:bgChartEntry, label: "") lineBG.circleRadius = CGFloat(globalVariables.dotBG) lineBG.circleColors = [NSUIColor.systemGreen] lineBG.drawCircleHoleEnabled = false lineBG.axisDependency = YAxis.AxisDependency.right lineBG.highlightEnabled = true lineBG.drawValuesEnabled = false if UserDefaultsRepository.showLines.value { lineBG.lineWidth = 2 } else { lineBG.lineWidth = 0 } if UserDefaultsRepository.showDots.value { lineBG.drawCirclesEnabled = true } else { lineBG.drawCirclesEnabled = false } lineBG.setDrawHighlightIndicators(false) lineBG.valueFont.withSize(50) // Setup Prediction line details var predictionChartEntry = [ChartDataEntry]() let linePrediction = LineChartDataSet(entries:predictionChartEntry, label: "") linePrediction.circleRadius = CGFloat(globalVariables.dotBG) linePrediction.circleColors = [NSUIColor.systemPurple] linePrediction.colors = [NSUIColor.systemPurple] linePrediction.drawCircleHoleEnabled = false linePrediction.axisDependency = YAxis.AxisDependency.right linePrediction.highlightEnabled = true linePrediction.drawValuesEnabled = false if UserDefaultsRepository.showLines.value { linePrediction.lineWidth = 2 } else { linePrediction.lineWidth = 0 } if UserDefaultsRepository.showDots.value { linePrediction.drawCirclesEnabled = true } else { linePrediction.drawCirclesEnabled = false } linePrediction.setDrawHighlightIndicators(false) linePrediction.valueFont.withSize(50) // create Basal graph data var chartEntry = [ChartDataEntry]() var maxBasal = UserDefaultsRepository.minBasalScale.value let lineBasal = LineChartDataSet(entries:chartEntry, label: "") lineBasal.setDrawHighlightIndicators(false) lineBasal.setColor(NSUIColor.systemBlue, alpha: 0.5) lineBasal.lineWidth = 0 lineBasal.drawFilledEnabled = true lineBasal.fillColor = NSUIColor.systemBlue lineBasal.fillAlpha = 0.5 lineBasal.drawCirclesEnabled = false lineBasal.axisDependency = YAxis.AxisDependency.left lineBasal.highlightEnabled = true lineBasal.drawValuesEnabled = false lineBasal.fillFormatter = basalFillFormatter() // Boluses var chartEntryBolus = [ChartDataEntry]() let lineBolus = LineChartDataSet(entries:chartEntryBolus, label: "") lineBolus.circleRadius = CGFloat(globalVariables.dotBolus) lineBolus.circleColors = [NSUIColor.systemBlue.withAlphaComponent(0.75)] lineBolus.drawCircleHoleEnabled = false lineBolus.setDrawHighlightIndicators(false) lineBolus.setColor(NSUIColor.systemBlue, alpha: 1.0) lineBolus.lineWidth = 0 lineBolus.axisDependency = YAxis.AxisDependency.right lineBolus.valueFormatter = ChartYDataValueFormatter() lineBolus.valueTextColor = NSUIColor.label lineBolus.fillColor = NSUIColor.systemBlue lineBolus.fillAlpha = 0.6 lineBolus.drawCirclesEnabled = true lineBolus.drawFilledEnabled = false if UserDefaultsRepository.showValues.value { lineBolus.drawValuesEnabled = true lineBolus.highlightEnabled = false } else { lineBolus.drawValuesEnabled = false lineBolus.highlightEnabled = true } // Carbs var chartEntryCarbs = [ChartDataEntry]() let lineCarbs = LineChartDataSet(entries:chartEntryCarbs, label: "") lineCarbs.circleRadius = CGFloat(globalVariables.dotCarb) lineCarbs.circleColors = [NSUIColor.systemOrange.withAlphaComponent(0.75)] lineCarbs.drawCircleHoleEnabled = false lineCarbs.setDrawHighlightIndicators(false) lineCarbs.setColor(NSUIColor.systemBlue, alpha: 1.0) lineCarbs.lineWidth = 0 lineCarbs.axisDependency = YAxis.AxisDependency.right lineCarbs.valueFormatter = ChartYDataValueFormatter() lineCarbs.valueTextColor = NSUIColor.label lineCarbs.fillColor = NSUIColor.systemOrange lineCarbs.fillAlpha = 0.6 lineCarbs.drawCirclesEnabled = true lineCarbs.drawFilledEnabled = false if UserDefaultsRepository.showValues.value { lineCarbs.drawValuesEnabled = true lineCarbs.highlightEnabled = false } else { lineCarbs.drawValuesEnabled = false lineCarbs.highlightEnabled = true } // create Scheduled Basal graph data var chartBasalScheduledEntry = [ChartDataEntry]() let lineBasalScheduled = LineChartDataSet(entries:chartBasalScheduledEntry, label: "") lineBasalScheduled.setDrawHighlightIndicators(false) lineBasalScheduled.setColor(NSUIColor.systemBlue, alpha: 0.8) lineBasalScheduled.lineWidth = 2 lineBasalScheduled.drawFilledEnabled = false lineBasalScheduled.drawCirclesEnabled = false lineBasalScheduled.axisDependency = YAxis.AxisDependency.left lineBasalScheduled.highlightEnabled = false lineBasalScheduled.drawValuesEnabled = false lineBasalScheduled.lineDashLengths = [10.0, 5.0] // create Override graph data var chartOverrideEntry = [ChartDataEntry]() let lineOverride = LineChartDataSet(entries:chartOverrideEntry, label: "") lineOverride.setDrawHighlightIndicators(false) lineOverride.lineWidth = 0 lineOverride.drawFilledEnabled = true lineOverride.fillFormatter = OverrideFillFormatter() lineOverride.fillColor = NSUIColor.systemGreen lineOverride.fillAlpha = 0.6 lineOverride.drawCirclesEnabled = false lineOverride.axisDependency = YAxis.AxisDependency.right lineOverride.highlightEnabled = true lineOverride.drawValuesEnabled = false // lineOverride.circleColors = [NSUIColor.systemGreen.withAlphaComponent(0.75)] // lineOverride.valueFormatter = ChartYDataValueFormatter() // lineOverride.drawCircleHoleEnabled = false // BG Check var chartEntryBGCheck = [ChartDataEntry]() let lineBGCheck = LineChartDataSet(entries:chartEntryBGCheck, label: "") lineBGCheck.circleRadius = CGFloat(globalVariables.dotOther) lineBGCheck.circleColors = [NSUIColor.systemRed.withAlphaComponent(0.75)] lineBGCheck.drawCircleHoleEnabled = false lineBGCheck.setDrawHighlightIndicators(false) lineBGCheck.setColor(NSUIColor.systemRed, alpha: 1.0) lineBGCheck.drawCirclesEnabled = true lineBGCheck.lineWidth = 0 lineBGCheck.highlightEnabled = true lineBGCheck.axisDependency = YAxis.AxisDependency.right lineBGCheck.valueFormatter = ChartYDataValueFormatter() lineBGCheck.drawValuesEnabled = false // Suspend Pump var chartEntrySuspend = [ChartDataEntry]() let lineSuspend = LineChartDataSet(entries:chartEntrySuspend, label: "") lineSuspend.circleRadius = CGFloat(globalVariables.dotOther) lineSuspend.circleColors = [NSUIColor.systemTeal.withAlphaComponent(0.75)] lineSuspend.drawCircleHoleEnabled = false lineSuspend.setDrawHighlightIndicators(false) lineSuspend.setColor(NSUIColor.systemGray2, alpha: 1.0) lineSuspend.drawCirclesEnabled = true lineSuspend.lineWidth = 0 lineSuspend.highlightEnabled = true lineSuspend.axisDependency = YAxis.AxisDependency.right lineSuspend.valueFormatter = ChartYDataValueFormatter() lineSuspend.drawValuesEnabled = false // Resume Pump var chartEntryResume = [ChartDataEntry]() let lineResume = LineChartDataSet(entries:chartEntryResume, label: "") lineResume.circleRadius = CGFloat(globalVariables.dotOther) lineResume.circleColors = [NSUIColor.systemTeal.withAlphaComponent(0.75)] lineResume.drawCircleHoleEnabled = false lineResume.setDrawHighlightIndicators(false) lineResume.setColor(NSUIColor.systemGray4, alpha: 1.0) lineResume.drawCirclesEnabled = true lineResume.lineWidth = 0 lineResume.highlightEnabled = true lineResume.axisDependency = YAxis.AxisDependency.right lineResume.valueFormatter = ChartYDataValueFormatter() lineResume.drawValuesEnabled = false // Sensor Start var chartEntrySensor = [ChartDataEntry]() let lineSensor = LineChartDataSet(entries:chartEntrySensor, label: "") lineSensor.circleRadius = CGFloat(globalVariables.dotOther) lineSensor.circleColors = [NSUIColor.systemIndigo.withAlphaComponent(0.75)] lineSensor.drawCircleHoleEnabled = false lineSensor.setDrawHighlightIndicators(false) lineSensor.setColor(NSUIColor.systemGray3, alpha: 1.0) lineSensor.drawCirclesEnabled = true lineSensor.lineWidth = 0 lineSensor.highlightEnabled = true lineSensor.axisDependency = YAxis.AxisDependency.right lineSensor.valueFormatter = ChartYDataValueFormatter() lineSensor.drawValuesEnabled = false // Notes var chartEntryNote = [ChartDataEntry]() let lineNote = LineChartDataSet(entries:chartEntryNote, label: "") lineNote.circleRadius = CGFloat(globalVariables.dotOther) lineNote.circleColors = [NSUIColor.systemGray.withAlphaComponent(0.75)] lineNote.drawCircleHoleEnabled = false lineNote.setDrawHighlightIndicators(false) lineNote.setColor(NSUIColor.systemGray3, alpha: 1.0) lineNote.drawCirclesEnabled = true lineNote.lineWidth = 0 lineNote.highlightEnabled = true lineNote.axisDependency = YAxis.AxisDependency.right lineNote.valueFormatter = ChartYDataValueFormatter() lineNote.drawValuesEnabled = false // Setup the chart data of all lines let data = LineChartData() data.append(lineBG) // Dataset 0 data.append(linePrediction) // Dataset 1 data.append(lineBasal) // Dataset 2 data.append(lineBolus) // Dataset 3 data.append(lineCarbs) // Dataset 4 data.append(lineBasalScheduled) // Dataset 5 data.append(lineOverride) // Dataset 6 data.append(lineBGCheck) // Dataset 7 data.append(lineSuspend) // Dataset 8 data.append(lineResume) // Dataset 9 data.append(lineSensor) // Dataset 10 data.append(lineNote) // Dataset 11 data.setValueFont(UIFont.systemFont(ofSize: 12)) // Add marker popups for bolus and carbs let marker = PillMarker(color: .secondarySystemBackground, font: UIFont.boldSystemFont(ofSize: 14), textColor: .label) BGChart.marker = marker // Clear limit lines so they don't add multiples when changing the settings BGChart.rightAxis.removeAllLimitLines() //Add lower red line based on low alert value let ll = ChartLimitLine() ll.limit = Double(UserDefaultsRepository.lowLine.value) ll.lineColor = NSUIColor.systemRed.withAlphaComponent(0.5) BGChart.rightAxis.addLimitLine(ll) //Add upper yellow line based on low alert value let ul = ChartLimitLine() ul.limit = Double(UserDefaultsRepository.highLine.value) ul.lineColor = NSUIColor.systemYellow.withAlphaComponent(0.5) BGChart.rightAxis.addLimitLine(ul) // Add vertical lines as configured createVerticalLines() startGraphNowTimer() // Setup the main graph overall details BGChart.xAxis.valueFormatter = ChartXValueFormatter() BGChart.xAxis.granularity = 1800 BGChart.xAxis.labelTextColor = NSUIColor.label BGChart.xAxis.labelPosition = XAxis.LabelPosition.bottom BGChart.xAxis.drawGridLinesEnabled = false BGChart.leftAxis.enabled = true BGChart.leftAxis.labelPosition = YAxis.LabelPosition.insideChart BGChart.leftAxis.axisMaximum = maxBasal BGChart.leftAxis.axisMinimum = 0 BGChart.leftAxis.drawGridLinesEnabled = false BGChart.leftAxis.granularityEnabled = true BGChart.leftAxis.granularity = 0.5 BGChart.rightAxis.labelTextColor = NSUIColor.label BGChart.rightAxis.labelPosition = YAxis.LabelPosition.insideChart BGChart.rightAxis.axisMinimum = 0.0 BGChart.rightAxis.axisMaximum = Double(maxBG) BGChart.rightAxis.gridLineDashLengths = [5.0, 5.0] BGChart.rightAxis.drawGridLinesEnabled = false BGChart.rightAxis.valueFormatter = ChartYMMOLValueFormatter() BGChart.rightAxis.granularityEnabled = true BGChart.rightAxis.granularity = 50 BGChart.maxHighlightDistance = 15.0 BGChart.legend.enabled = false BGChart.scaleYEnabled = false BGChart.drawGridBackgroundEnabled = true BGChart.gridBackgroundColor = NSUIColor.secondarySystemBackground BGChart.highlightValue(nil, callDelegate: false) BGChart.data = data BGChart.setExtraOffsets(left: 5, top: 10, right: 5, bottom: 10) } func createVerticalLines() { BGChart.xAxis.removeAllLimitLines() BGChartFull.xAxis.removeAllLimitLines() createNowAndDIALines() createMidnightLines() } func createNowAndDIALines() { let ul = ChartLimitLine() ul.limit = Double(dateTimeUtils.getNowTimeIntervalUTC()) ul.lineColor = NSUIColor.systemGray.withAlphaComponent(0.5) ul.lineWidth = 1 BGChart.xAxis.addLimitLine(ul) if UserDefaultsRepository.show30MinLine.value { let ul2 = ChartLimitLine() ul2.limit = Double(dateTimeUtils.getNowTimeIntervalUTC().advanced(by: -30 * 60)) ul2.lineColor = NSUIColor.systemBlue.withAlphaComponent(0.5) ul2.lineWidth = 1 BGChart.xAxis.addLimitLine(ul2) } if UserDefaultsRepository.showDIALines.value { for i in 1..<7 { let ul = ChartLimitLine() ul.limit = Double(dateTimeUtils.getNowTimeIntervalUTC() - Double(i * 60 * 60)) ul.lineColor = NSUIColor.systemGray.withAlphaComponent(0.3) let dash = 10.0 - Double(i) let space = 5.0 + Double(i) ul.lineDashLengths = [CGFloat(dash), CGFloat(space)] ul.lineWidth = 1 BGChart.xAxis.addLimitLine(ul) } } if UserDefaultsRepository.show90MinLine.value { let ul3 = ChartLimitLine() ul3.limit = Double(dateTimeUtils.getNowTimeIntervalUTC().advanced(by: -90 * 60)) ul3.lineColor = NSUIColor.systemOrange.withAlphaComponent(0.5) ul3.lineWidth = 1 BGChart.xAxis.addLimitLine(ul3) } } func createMidnightLines() { // Draw a line at midnight: useful when showing multiple days of data if UserDefaultsRepository.showMidnightLines.value { var midnightTimeInterval = dateTimeUtils.getTimeIntervalMidnightToday() let graphHours = 24 * UserDefaultsRepository.downloadDays.value let graphStart = dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours) while midnightTimeInterval > graphStart { // Large chart let ul = ChartLimitLine() ul.limit = Double(midnightTimeInterval) ul.lineColor = NSUIColor.systemTeal.withAlphaComponent(0.5) ul.lineDashLengths = [CGFloat(2), CGFloat(5)] ul.lineWidth = 1 BGChart.xAxis.addLimitLine(ul) // Small chart let sl = ChartLimitLine() sl.limit = Double(midnightTimeInterval) sl.lineColor = NSUIColor.systemTeal sl.lineDashLengths = [CGFloat(2), CGFloat(2)] sl.lineWidth = 1 BGChartFull.xAxis.addLimitLine(sl) midnightTimeInterval = midnightTimeInterval.advanced(by: -24*60*60) } } } func updateBGGraphSettings() { let dataIndex = 0 let dataIndexPrediction = 1 let lineBG = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet let linePrediction = BGChart.lineData!.dataSets[dataIndexPrediction] as! LineChartDataSet if UserDefaultsRepository.showLines.value { lineBG.lineWidth = 2 linePrediction.lineWidth = 2 } else { lineBG.lineWidth = 0 linePrediction.lineWidth = 0 } if UserDefaultsRepository.showDots.value { lineBG.drawCirclesEnabled = true linePrediction.drawCirclesEnabled = true } else { lineBG.drawCirclesEnabled = false linePrediction.drawCirclesEnabled = false } BGChart.rightAxis.axisMinimum = 0 // Clear limit lines so they don't add multiples when changing the settings BGChart.rightAxis.removeAllLimitLines() //Add lower red line based on low alert value let ll = ChartLimitLine() ll.limit = Double(UserDefaultsRepository.lowLine.value) ll.lineColor = NSUIColor.systemRed.withAlphaComponent(0.5) BGChart.rightAxis.addLimitLine(ll) //Add upper yellow line based on low alert value let ul = ChartLimitLine() ul.limit = Double(UserDefaultsRepository.highLine.value) ul.lineColor = NSUIColor.systemYellow.withAlphaComponent(0.5) BGChart.rightAxis.addLimitLine(ul) // Re-create vertical markers in case their settings changed createVerticalLines() BGChart.data?.dataSets[dataIndex].notifyDataSetChanged() BGChart.data?.notifyDataChanged() BGChart.notifyDataSetChanged() } func updateBGGraph() { if UserDefaultsRepository.debugLog.value { writeDebugLog(value: "##### Start BG Graph #####") } let dataIndex = 0 let entries = bgData if entries.count < 1 { return } var mainChart = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet var smallChart = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet mainChart.clear() smallChart.clear() var maxBGOffset: Float = 50 var colors = [NSUIColor]() for i in 0.. topBG - maxBGOffset { topBG = Float(entries[i].sgv) + maxBGOffset } 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)) if UserDefaultsRepository.debugLog.value { writeDebugLog(value: "BG: " + value.description) } mainChart.addEntry(value) smallChart.addEntry(value) if Double(entries[i].sgv) >= Double(UserDefaultsRepository.highLine.value) { colors.append(NSUIColor.systemYellow) } else if Double(entries[i].sgv) <= Double(UserDefaultsRepository.lowLine.value) { colors.append(NSUIColor.systemRed) } else { colors.append(NSUIColor.systemGreen) } } if (predictionData.count < 1) { let value = ChartDataEntry(x: Double(entries[entries.count-1].date+1200), y: 0) mainChart.addEntry(value) colors.append(NSUIColor.systemGray.withAlphaComponent(0.0)) } if UserDefaultsRepository.debugLog.value { writeDebugLog(value: "Total Graph BGs: " + mainChart.entries.count.description) } // Set Colors let lineBG = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet let lineBGSmall = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet lineBG.colors.removeAll() lineBG.circleColors.removeAll() lineBGSmall.colors.removeAll() lineBGSmall.circleColors.removeAll() if colors.count > 0 { for i in 0.. CGFloat(ScaleXMax) ) { scaleX = CGFloat(ScaleXMax) UserDefaultsRepository.chartScaleX.value = ScaleXMax } BGChart.zoom(scaleX: scaleX, scaleY: 1, x: 1, y: 1) firstGraphLoad = false } // Move to current reading everytime new readings load BGChart.moveViewToAnimated(xValue: dateTimeUtils.getNowTimeIntervalUTC() - (BGChart.visibleXRange * 0.7), yValue: 0.0, axis: .right, duration: 1, easingOption: .easeInBack) } func updatePredictionGraph(color: UIColor? = nil) { let dataIndex = 1 var mainChart = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet var smallChart = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet mainChart.clear() smallChart.clear() var colors = [NSUIColor]() let maxBGOffset: Float = 20 for i in 0.. topBG - maxBGOffset { topBG = Float(predictionVal) + maxBGOffset } if i == 0 { if UserDefaultsRepository.showDots.value { colors.append((color ?? NSUIColor.systemPurple).withAlphaComponent(0.0)) } else { colors.append((color ?? NSUIColor.systemPurple).withAlphaComponent(1.0)) } } else if predictionVal > 400 { colors.append(color ?? NSUIColor.systemYellow) } else if predictionVal < 0 { colors.append(color ?? NSUIColor.systemRed) } else { colors.append(color ?? NSUIColor.systemPurple) } let value = ChartDataEntry(x: predictionData[i].date, y: predictionVal, data: formatPillText(line1: bgUnits.toDisplayUnits(String(predictionData[i].sgv)), time: predictionData[i].date)) mainChart.addEntry(value) smallChart.addEntry(value) } smallChart.circleColors.removeAll() smallChart.colors.removeAll() mainChart.colors.removeAll() mainChart.circleColors.removeAll() if colors.count > 0 { for i in 0.. maxBasal { maxBasal = basalData[i].basalRate } if basalData[i].basalRate > maxBasalSmall { maxBasalSmall = basalData[i].basalRate } } BGChart.leftAxis.axisMaximum = maxBasal BGChartFull.leftAxis.axisMaximum = maxBasalSmall BGChart.data?.dataSets[dataIndex].notifyDataSetChanged() BGChart.data?.notifyDataChanged() BGChart.notifyDataSetChanged() if UserDefaultsRepository.smallGraphTreatments.value { BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged() BGChartFull.data?.notifyDataChanged() BGChartFull.notifyDataSetChanged() } } func updateBasalScheduledGraph() { var dataIndex = 5 BGChart.lineData?.dataSets[dataIndex].clear() BGChartFull.lineData?.dataSets[dataIndex].clear() for i in 0.. 6 { colors.append(NSUIColor.systemBlue.withAlphaComponent(0.25)) } else { let thisAlpha = 1.0 - (0.15 * diffTimeHours) colors.append(NSUIColor.systemBlue.withAlphaComponent(CGFloat(thisAlpha))) } if bolusShift { // Move it half the distance between BG readings dateTimeStamp = dateTimeStamp - 150 } // skip if outside of visible area let graphHours = 24 * UserDefaultsRepository.downloadDays.value if dateTimeStamp < dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours) { continue } let dot = ChartDataEntry(x: Double(dateTimeStamp), y: Double(bolusData[i].sgv), data: formatter.string(from: NSNumber(value: bolusData[i].value))) mainChart.addEntry(dot) if UserDefaultsRepository.smallGraphTreatments.value { smallChart.addEntry(dot) } } // Set Colors let lineBolus = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet let lineBolusSmall = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet lineBolus.colors.removeAll() lineBolus.circleColors.removeAll() lineBolusSmall.colors.removeAll() lineBolusSmall.circleColors.removeAll() if colors.count > 0 { for i in 0.. 0 && UserDefaultsRepository.showAbsorption.value { hours = carbData[i].absorptionTime / 60 valueString += " " + String(hours) + "h" } // Check overlapping carbs to shift left if needed let carbShift = findNextCarbTime(timeWithin: 250, needle: carbData[i].date, haystack: carbData, startingIndex: i) var dateTimeStamp = carbData[i].date // Alpha colors for DIA let nowTime = dateTimeUtils.getNowTimeIntervalUTC() let diffTimeHours = (nowTime - dateTimeStamp) / 60 / 60 if diffTimeHours <= 0.5 { colors.append(NSUIColor.systemOrange.withAlphaComponent(1.0)) } else if diffTimeHours > Double(hours) { colors.append(NSUIColor.systemOrange.withAlphaComponent(0.25)) } else { let thisAlpha = 1.0 - ((0.75 / Double(hours)) * diffTimeHours) colors.append(NSUIColor.systemOrange.withAlphaComponent(CGFloat(thisAlpha))) } // skip if outside of visible area let graphHours = 24 * UserDefaultsRepository.downloadDays.value if dateTimeStamp < dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours) { continue } if carbShift { dateTimeStamp = dateTimeStamp - 250 } let dot = ChartDataEntry(x: Double(dateTimeStamp), y: Double(carbData[i].sgv), data: valueString) BGChart.data?.dataSets[dataIndex].addEntry(dot) if UserDefaultsRepository.smallGraphTreatments.value { BGChartFull.data?.dataSets[dataIndex].addEntry(dot) } } // Set Colors let lineCarbs = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet let lineCarbsSmall = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet lineCarbs.colors.removeAll() lineCarbs.circleColors.removeAll() lineCarbsSmall.colors.removeAll() lineCarbsSmall.circleColors.removeAll() if colors.count > 0 { for i in 0.. 0 { labelText += "\r\nEntered By: " + thisItem.enteredBy } // Start Dot // Shift dots 30 seconds to create an empty 0 space between consecutive temps let preStartDot = ChartDataEntry(x: Double(thisItem.date), y: yBottom, data: labelText) BGChart.data?.dataSets[dataIndex].addEntry(preStartDot) if UserDefaultsRepository.smallGraphTreatments.value { BGChartFull.data?.dataSets[dataIndex].addEntry(preStartDot) } let startDot = ChartDataEntry(x: Double(thisItem.date + 1), y: yTop, data: labelText) BGChart.data?.dataSets[dataIndex].addEntry(startDot) if UserDefaultsRepository.smallGraphTreatments.value { BGChartFull.data?.dataSets[dataIndex].addEntry(startDot) } // End Dot let endDot = ChartDataEntry(x: Double(thisItem.endDate - 2), y: yTop, data: labelText) BGChart.data?.dataSets[dataIndex].addEntry(endDot) if UserDefaultsRepository.smallGraphTreatments.value { BGChartFull.data?.dataSets[dataIndex].addEntry(endDot) } // Post end dot let postEndDot = ChartDataEntry(x: Double(thisItem.endDate - 1), y: yBottom, data: labelText) BGChart.data?.dataSets[dataIndex].addEntry(postEndDot) if UserDefaultsRepository.smallGraphTreatments.value { BGChartFull.data?.dataSets[dataIndex].addEntry(postEndDot) } } BGChart.data?.dataSets[dataIndex].notifyDataSetChanged() BGChart.data?.notifyDataChanged() BGChart.notifyDataSetChanged() if UserDefaultsRepository.smallGraphTreatments.value { BGChartFull.data?.dataSets[dataIndex].notifyDataSetChanged() BGChartFull.data?.notifyDataChanged() BGChartFull.notifyDataSetChanged() } } func formatPillText(line1: String, time: TimeInterval) -> String { let dateFormatter = DateFormatter() //let timezoneOffset = TimeZone.current.secondsFromGMT() //let epochTimezoneOffset = value + Double(timezoneOffset) if dateTimeUtils.is24Hour() { dateFormatter.setLocalizedDateFormatFromTemplate("HH:mm") } else { dateFormatter.setLocalizedDateFormatFromTemplate("hh:mm") } //let date = Date(timeIntervalSince1970: epochTimezoneOffset) let date = Date(timeIntervalSince1970: time) let formattedDate = dateFormatter.string(from: date) return line1 + "\r\n" + formattedDate } }