|
|
@@ -7,44 +7,46 @@
|
|
|
//
|
|
|
|
|
|
import Foundation
|
|
|
+
|
|
|
extension MainViewController {
|
|
|
// NS Temp Basal Response Processor
|
|
|
func processNSBasals(entries: [[String:AnyObject]]) {
|
|
|
infoManager.clearInfoData(type: .basal)
|
|
|
|
|
|
- if UserDefaultsRepository.debugLog.value { self.writeDebugLog(value: "Process: Basal") }
|
|
|
- // due to temp basal durations, we're going to destroy the array and load everything each cycle for the time being.
|
|
|
basalData.removeAll()
|
|
|
-
|
|
|
+
|
|
|
var lastEndDot = 0.0
|
|
|
-
|
|
|
+
|
|
|
+ let isoFormatter = ISO8601DateFormatter()
|
|
|
+ isoFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
|
|
|
+
|
|
|
var tempArray = entries
|
|
|
tempArray.reverse()
|
|
|
+
|
|
|
for i in 0..<tempArray.count {
|
|
|
let currentEntry = tempArray[i] as [String : AnyObject]?
|
|
|
- var basalDate: String
|
|
|
- if currentEntry?["timestamp"] != nil {
|
|
|
- basalDate = currentEntry?["timestamp"] as! String
|
|
|
- } else if currentEntry?["created_at"] != nil {
|
|
|
- basalDate = currentEntry?["created_at"] as! String
|
|
|
+
|
|
|
+ var basalDateStr: String
|
|
|
+ if let ts = currentEntry?["timestamp"] as? String {
|
|
|
+ basalDateStr = ts
|
|
|
+ } else if let ca = currentEntry?["created_at"] as? String {
|
|
|
+ basalDateStr = ca
|
|
|
} else {
|
|
|
continue
|
|
|
}
|
|
|
- var strippedZone = String(basalDate.dropLast())
|
|
|
- strippedZone = strippedZone.replacingOccurrences(of: "\\.\\d+", with: "", options: .regularExpression)
|
|
|
- let dateFormatter = DateFormatter()
|
|
|
- dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
|
|
|
- dateFormatter.locale = Locale(identifier: "en_US")
|
|
|
- dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
|
|
|
- guard let dateString = dateFormatter.date(from: strippedZone) else { continue }
|
|
|
- let dateTimeStamp = dateString.timeIntervalSince1970
|
|
|
+
|
|
|
+ guard let dateParsed = isoFormatter.date(from: basalDateStr) else {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ let dateTimeStamp = dateParsed.timeIntervalSince1970
|
|
|
+
|
|
|
guard let basalRate = currentEntry?["absolute"] as? Double else {
|
|
|
- if UserDefaultsRepository.debugLog.value { self.writeDebugLog(value: "ERROR: Null Basal entry")}
|
|
|
+ if UserDefaultsRepository.debugLog.value {
|
|
|
+ self.writeDebugLog(value: "ERROR: Null Basal entry")
|
|
|
+ }
|
|
|
continue
|
|
|
}
|
|
|
-
|
|
|
- let midnightTime = dateTimeUtils.getTimeIntervalMidnightToday()
|
|
|
- // Setting end dots
|
|
|
+
|
|
|
var duration = 0.0
|
|
|
if let durationValue = currentEntry?["duration"] as? Double {
|
|
|
duration = durationValue
|
|
|
@@ -52,42 +54,38 @@ extension MainViewController {
|
|
|
print("No Duration Found")
|
|
|
}
|
|
|
|
|
|
- // This adds scheduled basal wherever there is a break between temps. can't check the prior ending on the first item. it is 24 hours old, so it isn't important for display anyway
|
|
|
+ // *** Check for any gap since the previous entry
|
|
|
if i > 0 {
|
|
|
let priorEntry = tempArray[i - 1] as [String : AnyObject]?
|
|
|
- var priorBasalDate: String
|
|
|
- if priorEntry?["timestamp"] != nil {
|
|
|
- priorBasalDate = priorEntry?["timestamp"] as! String
|
|
|
- } else if currentEntry?["created_at"] != nil {
|
|
|
- priorBasalDate = priorEntry?["created_at"] as! String
|
|
|
+
|
|
|
+ var priorBasalDateStr: String
|
|
|
+ if let ts = priorEntry?["timestamp"] as? String {
|
|
|
+ priorBasalDateStr = ts
|
|
|
+ } else if let ca = priorEntry?["created_at"] as? String {
|
|
|
+ priorBasalDateStr = ca
|
|
|
} else {
|
|
|
continue
|
|
|
}
|
|
|
- var priorStrippedZone = String(priorBasalDate.dropLast())
|
|
|
- priorStrippedZone = priorStrippedZone.replacingOccurrences(of: "\\.\\d+", with: "", options: .regularExpression)
|
|
|
- let priorDateFormatter = DateFormatter()
|
|
|
- priorDateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
|
|
|
- priorDateFormatter.locale = Locale(identifier: "en_US")
|
|
|
- priorDateFormatter.timeZone = TimeZone(abbreviation: "UTC")
|
|
|
- guard let priorDateString = dateFormatter.date(from: priorStrippedZone) else { continue }
|
|
|
- let priorDateTimeStamp = priorDateString.timeIntervalSince1970
|
|
|
+
|
|
|
+ guard let priorDateParsed = isoFormatter.date(from: priorBasalDateStr) else {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ let priorDateTimeStamp = priorDateParsed.timeIntervalSince1970
|
|
|
let priorDuration = priorEntry?["duration"] as? Double ?? 0.0
|
|
|
+
|
|
|
// if difference between time stamps is greater than the duration of the last entry, there is a gap. Give a 15 second leeway on the timestamp
|
|
|
- if Double( dateTimeStamp - priorDateTimeStamp ) > Double( (priorDuration * 60) + 15 ) {
|
|
|
-
|
|
|
+ if Double(dateTimeStamp - priorDateTimeStamp) > Double((priorDuration * 60) + 15) {
|
|
|
+
|
|
|
var scheduled = 0.0
|
|
|
- var midGap = false
|
|
|
+ let midGap = false
|
|
|
var midGapTime: TimeInterval = 0
|
|
|
var midGapValue: Double = 0
|
|
|
- // cycle through basal profiles.
|
|
|
- // TODO figure out how to deal with profile changes that happen mid-gap
|
|
|
+
|
|
|
for b in 0..<self.basalScheduleData.count {
|
|
|
-
|
|
|
- if (priorDateTimeStamp + (priorDuration * 60)) >= basalScheduleData[b].date {
|
|
|
+ let priorEnd = priorDateTimeStamp + (priorDuration * 60)
|
|
|
+ if priorEnd >= basalScheduleData[b].date {
|
|
|
scheduled = basalScheduleData[b].basalRate
|
|
|
-
|
|
|
- // deal with mid-gap scheduled basal change
|
|
|
- // don't do it on the last scheudled basal entry
|
|
|
+
|
|
|
if b < self.basalScheduleData.count - 1 {
|
|
|
if dateTimeStamp > self.basalScheduleData[b + 1].date {
|
|
|
// midGap = true
|
|
|
@@ -96,106 +94,106 @@ extension MainViewController {
|
|
|
midGapValue = self.basalScheduleData[b + 1].basalRate
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// Make the starting dot at the last ending dot
|
|
|
- let startDot = basalGraphStruct(basalRate: scheduled, date: Double(priorDateTimeStamp + (priorDuration * 60)))
|
|
|
+ let startDot = basalGraphStruct(
|
|
|
+ basalRate: scheduled,
|
|
|
+ date: priorDateTimeStamp + (priorDuration * 60)
|
|
|
+ )
|
|
|
basalData.append(startDot)
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
if midGap {
|
|
|
- // Make the ending dot at the new scheduled basal
|
|
|
- let endDot1 = basalGraphStruct(basalRate: scheduled, date: Double(midGapTime))
|
|
|
+ // Make the ending dot at the old scheduled basal
|
|
|
+ let endDot1 = basalGraphStruct(basalRate: scheduled, date: midGapTime)
|
|
|
basalData.append(endDot1)
|
|
|
// Make the starting dot at the scheduled Time
|
|
|
- let startDot2 = basalGraphStruct(basalRate: midGapValue, date: Double(midGapTime))
|
|
|
+ let startDot2 = basalGraphStruct(basalRate: midGapValue, date: midGapTime)
|
|
|
basalData.append(startDot2)
|
|
|
// Make the ending dot at the new basal value
|
|
|
- let endDot2 = basalGraphStruct(basalRate: midGapValue, date: Double(dateTimeStamp))
|
|
|
+ let endDot2 = basalGraphStruct(basalRate: midGapValue, date: dateTimeStamp)
|
|
|
basalData.append(endDot2)
|
|
|
-
|
|
|
} else {
|
|
|
// Make the ending dot at the new starting dot
|
|
|
- let endDot = basalGraphStruct(basalRate: scheduled, date: Double(dateTimeStamp))
|
|
|
+ let endDot = basalGraphStruct(basalRate: scheduled, date: dateTimeStamp)
|
|
|
basalData.append(endDot)
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// Make the starting dot
|
|
|
- let startDot = basalGraphStruct(basalRate: basalRate, date: Double(dateTimeStamp))
|
|
|
+ let startDot = basalGraphStruct(basalRate: basalRate, date: dateTimeStamp)
|
|
|
basalData.append(startDot)
|
|
|
-
|
|
|
+
|
|
|
// Make the ending dot
|
|
|
- // If it's the last one and has no duration, extend it for 30 minutes past the start. Otherwise set ending at duration
|
|
|
- // duration is already set to 0 if there is no duration set on it.
|
|
|
- //if i == tempArray.count - 1 && dateTimeStamp + duration <= dateTimeUtils.getNowTimeIntervalUTC() {
|
|
|
if i == tempArray.count - 1 && duration == 0.0 {
|
|
|
+ // If it's the last one and has no duration
|
|
|
lastEndDot = dateTimeStamp + (30 * 60)
|
|
|
} else {
|
|
|
lastEndDot = dateTimeStamp + (duration * 60)
|
|
|
}
|
|
|
- latestBasal = Localizer.formatToLocalizedString(basalRate, maxFractionDigits: 2, minFractionDigits: 0)
|
|
|
+ latestBasal = Localizer.formatToLocalizedString(basalRate,
|
|
|
+ maxFractionDigits: 2,
|
|
|
+ minFractionDigits: 0)
|
|
|
|
|
|
- // Double check for overlaps of incorrectly ended TBRs and sent it to end when the next one starts if it finds a discrepancy
|
|
|
+ // *** Overlap check for next entry
|
|
|
if i < tempArray.count - 1 {
|
|
|
let nextEntry = tempArray[i + 1] as [String : AnyObject]?
|
|
|
- var nextBasalDate: String
|
|
|
- if nextEntry?["timestamp"] != nil {
|
|
|
- nextBasalDate = nextEntry?["timestamp"] as! String
|
|
|
- } else if currentEntry?["created_at"] != nil {
|
|
|
- nextBasalDate = nextEntry?["created_at"] as! String
|
|
|
+ var nextBasalDateStr: String
|
|
|
+ if let ts = nextEntry?["timestamp"] as? String {
|
|
|
+ nextBasalDateStr = ts
|
|
|
+ } else if let ca = nextEntry?["created_at"] as? String {
|
|
|
+ nextBasalDateStr = ca
|
|
|
} else {
|
|
|
continue
|
|
|
}
|
|
|
- var nextStrippedZone = String(nextBasalDate.dropLast())
|
|
|
- nextStrippedZone = nextStrippedZone.replacingOccurrences(of: "\\.\\d+", with: "", options: .regularExpression)
|
|
|
- let nextDateFormatter = DateFormatter()
|
|
|
- nextDateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
|
|
|
- nextDateFormatter.locale = Locale(identifier: "en_US")
|
|
|
- nextDateFormatter.timeZone = TimeZone(abbreviation: "UTC")
|
|
|
- guard let nextDateString = dateFormatter.date(from: nextStrippedZone) else { continue }
|
|
|
- let nextDateTimeStamp = nextDateString.timeIntervalSince1970
|
|
|
+
|
|
|
+ guard let nextDateParsed = isoFormatter.date(from: nextBasalDateStr) else {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ let nextDateTimeStamp = nextDateParsed.timeIntervalSince1970
|
|
|
if nextDateTimeStamp < (dateTimeStamp + (duration * 60)) {
|
|
|
lastEndDot = nextDateTimeStamp
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- let endDot = basalGraphStruct(basalRate: basalRate, date: Double(lastEndDot))
|
|
|
+
|
|
|
+ let endDot = basalGraphStruct(basalRate: basalRate, date: lastEndDot)
|
|
|
basalData.append(endDot)
|
|
|
-
|
|
|
-
|
|
|
}
|
|
|
-
|
|
|
- // If last basal was prior to right now, we need to create one last scheduled entry
|
|
|
+
|
|
|
+ // If last basal was prior to right now, we need to create one last scheduled entry
|
|
|
if lastEndDot <= dateTimeUtils.getNowTimeIntervalUTC() {
|
|
|
var scheduled = 0.0
|
|
|
- // cycle through basal profiles.
|
|
|
- // TODO figure out how to deal with profile changes that happen mid-gap
|
|
|
for b in 0..<self.basalProfile.count {
|
|
|
- let scheduleTimeYesterday = self.basalProfile[b].timeAsSeconds + dateTimeUtils.getTimeIntervalMidnightYesterday()
|
|
|
- let scheduleTimeToday = self.basalProfile[b].timeAsSeconds + dateTimeUtils.getTimeIntervalMidnightToday()
|
|
|
- // check the prior temp ending to the profile seconds from midnight
|
|
|
+ let scheduleTimeToday = self.basalProfile[b].timeAsSeconds
|
|
|
+ + dateTimeUtils.getTimeIntervalMidnightToday()
|
|
|
if lastEndDot >= scheduleTimeToday {
|
|
|
scheduled = basalProfile[b].value
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- latestBasal = Localizer.formatToLocalizedString(scheduled, maxFractionDigits: 2, minFractionDigits: 0)
|
|
|
+
|
|
|
+ latestBasal = Localizer.formatToLocalizedString(
|
|
|
+ scheduled,
|
|
|
+ maxFractionDigits: 2,
|
|
|
+ minFractionDigits: 0
|
|
|
+ )
|
|
|
+
|
|
|
// Make the starting dot at the last ending dot
|
|
|
- let startDot = basalGraphStruct(basalRate: scheduled, date: Double(lastEndDot))
|
|
|
+ let startDot = basalGraphStruct(
|
|
|
+ basalRate: scheduled,
|
|
|
+ date: lastEndDot
|
|
|
+ )
|
|
|
basalData.append(startDot)
|
|
|
-
|
|
|
+
|
|
|
// Make the ending dot 10 minutes after now
|
|
|
- let endDot = basalGraphStruct(basalRate: scheduled, date: Double(Date().timeIntervalSince1970 + (60 * 10)))
|
|
|
+ let endDot = basalGraphStruct(
|
|
|
+ basalRate: scheduled,
|
|
|
+ date: Date().timeIntervalSince1970 + (60 * 10)
|
|
|
+ )
|
|
|
basalData.append(endDot)
|
|
|
-
|
|
|
}
|
|
|
+
|
|
|
if UserDefaultsRepository.graphBasal.value {
|
|
|
updateBasalGraph()
|
|
|
}
|