Просмотр исходного кода

Merge pull request #400 from loopandlearn/override-crash-fix

Fix for crashes related to overrides
Marion Barker 1 год назад
Родитель
Сommit
3cba25ffa6
1 измененных файлов с 54 добавлено и 53 удалено
  1. 54 53
      LoopFollow/Controllers/Nightscout/Treatments/Overrides.swift

+ 54 - 53
LoopFollow/Controllers/Nightscout/Treatments/Overrides.swift

@@ -10,79 +10,80 @@ import Foundation
 import UIKit
 
 extension MainViewController {
-    // NS Override Response Processor
-    func processNSOverrides(entries: [[String:AnyObject]]) {
+
+    func processNSOverrides(entries: [[String: AnyObject]]) {
         overrideGraphData.removeAll()
-        var activeOverrideNote: String? = nil
+        var activeOverrideNote: String?
+
+        let sorted = entries.sorted { lhs, rhs in
+            guard
+                let ls = (lhs["timestamp"] as? String) ?? (lhs["created_at"] as? String),
+                let rs = (rhs["timestamp"] as? String) ?? (rhs["created_at"] as? String),
+                let ld = NightscoutUtils.parseDate(ls),
+                let rd = NightscoutUtils.parseDate(rs)
+            else { return false }
+            return ld < rd
+        }
 
         let now = Date().timeIntervalSince1970
-        let predictionLoadHours = UserDefaultsRepository.predictionToLoad.value
-        let predictionLoadSeconds = predictionLoadHours * 3600
-        let maxEndDate = now + predictionLoadSeconds
+        let maxEndDate = now + UserDefaultsRepository.predictionToLoad.value * 3600
+        let graphHorizon = dateTimeUtils.getTimeIntervalNHoursAgo(N: 24 * UserDefaultsRepository.downloadDays.value)
 
-        entries.reversed().enumerated().forEach { (index, currentEntry) in
-            guard let dateStr = currentEntry["timestamp"] as? String ?? currentEntry["created_at"] as? String else { return }
-            guard let parsedDate = NightscoutUtils.parseDate(dateStr) else { return }
+        for i in 0..<sorted.count {
+            let e = sorted[i]
 
-            var dateTimeStamp = parsedDate.timeIntervalSince1970
-            let graphHours = 24 * UserDefaultsRepository.downloadDays.value
-            if dateTimeStamp < dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours) {
-                dateTimeStamp = dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours)
-            }
-            
-            let multiplier = currentEntry["insulinNeedsScaleFactor"] as? Double ?? 1.0
-            
-            var duration: Double = 5.0
-            if let _ = currentEntry["durationType"] as? String, index == entries.count - 1 {
-                duration = dateTimeUtils.getNowTimeIntervalUTC() - dateTimeStamp + (60 * 60)
-            } else {
-                duration = (currentEntry["duration"] as? Double ?? 5.0) * 60
-            }
-            
-            if duration < 300 { return }
-
-            let reason = currentEntry["reason"] as? String ?? ""
+            guard
+                let dateStr = (e["timestamp"] as? String) ?? (e["created_at"] as? String),
+                let startDate = NightscoutUtils.parseDate(dateStr)
+            else { continue }
 
-            guard let enteredBy = currentEntry["enteredBy"] as? String else {
-                return
-            }
+            let start = max(startDate.timeIntervalSince1970, graphHorizon)
+            var end   = start + (e["duration"] as? Double ?? 5) * 60   // seconds
 
-            var range: [Int] = []
-            if let ranges = currentEntry["correctionRange"] as? [Int], ranges.count == 2 {
-                range = ranges
-            } else {
-                let low = currentEntry["targetBottom"] as? Int
-                let high = currentEntry["targetTop"] as? Int
-                if (low == nil && high != nil) || (low != nil && high == nil) { return }
-                range = [low ?? 0, high ?? 0]
+            if i + 1 < sorted.count,
+               let nextDateStr = (sorted[i + 1]["timestamp"] as? String) ?? (sorted[i + 1]["created_at"] as? String),
+               let nextStart   = NightscoutUtils.parseDate(nextDateStr)?
+                .timeIntervalSince1970
+            {
+                end = min(end, nextStart - 60) // avoid overlapping overrides
             }
 
-            // Limit displayed override duration to 'Hours of Prediction' after current time
-            var endDate = dateTimeStamp + duration
-            if endDate > maxEndDate {
-                endDate = maxEndDate
-                duration = endDate - dateTimeStamp
-            }
+            end = min(end, maxEndDate)
 
-            if dateTimeStamp <= now && now < endDate {
-                activeOverrideNote = currentEntry["notes"] as? String ?? currentEntry["reason"] as? String
-            }
+            if end - start < 300 { continue } // skip short overrides
 
-            let dot = DataStructs.overrideStruct(insulNeedsScaleFactor: multiplier, date: dateTimeStamp, endDate: endDate, duration: duration, correctionRange: range, enteredBy: enteredBy, reason: reason, sgv: -20)
+            let dot = DataStructs.overrideStruct(
+                insulNeedsScaleFactor: e["insulinNeedsScaleFactor"] as? Double ?? 1,
+                date:         start,
+                endDate:      end,
+                duration:     end - start,
+                correctionRange: {
+                    if let r = e["correctionRange"] as? [Int], r.count == 2 {
+                        return r
+                    }
+                    let lo = e["targetBottom"] as? Int ?? 0
+                    let hi = e["targetTop"]    as? Int ?? 0
+                    return [lo, hi]
+                }(),
+                enteredBy:    e["enteredBy"] as? String ?? "unknown",
+                reason:       e["reason"]    as? String ?? "",
+                sgv:          -20
+            )
             overrideGraphData.append(dot)
+
+            if now >= start, now < end {
+                activeOverrideNote = e["notes"] as? String ?? e["reason"] as? String
+            }
         }
-        
-        Observable.shared.override.value = activeOverrideNote
 
+        Observable.shared.override.value = activeOverrideNote
         if ObservableUserDefaults.shared.device.value == "Trio" {
-            if let note = activeOverrideNote
-            {
+            if let note = activeOverrideNote {
                 infoManager.updateInfoData(type: .override, value: note)
             } else {
                 infoManager.clearInfoData(type: .override)
             }
         }
-
         if UserDefaultsRepository.graphOtherTreatments.value {
             updateOverrideGraph()
         }