<commit_before>//
//  LoopDataManager.swift
//  Naterade
//
//  Created by <NAME> on 3/12/16.
//  Copyright © 2016 <NAME>. All rights reserved.
//

import Foundation
import CarbKit
import InsulinKit
import LoopKit
import MinimedKit


class LoopDataManager {
    static let LoopDataUpdatedNotification = "com.loudnate.Naterade.notification.LoopDataUpdated"

    enum Error: ErrorType {
        case CommunicationError
        case ConnectionError
        case MissingDataError(String)
        case StaleDataError(String)
    }

    typealias TempBasalRecommendation = (recommendedDate: NSDate, rate: Double, duration: NSTimeInterval)

    unowned let deviceDataManager: DeviceDataManager

    var dosingEnabled: Bool {
        didSet {
            NSUserDefaults.standardUserDefaults().dosingEnabled = dosingEnabled
        }
    }

    init(deviceDataManager: DeviceDataManager) {
        self.deviceDataManager = deviceDataManager

        dosingEnabled = NSUserDefaults.standardUserDefaults().dosingEnabled

        observe()
    }

    // Actions

    private func observe() {
        let center = NSNotificationCenter.defaultCenter()

        notificationObservers = [
            center.addObserverForName(DeviceDataManager.GlucoseUpdatedNotification, object: deviceDataManager, queue: nil) { (note) -> Void in
                dispatch_async(self.dataAccessQueue) {
                    self.glucoseMomentumEffect = nil
                    NSNotificationCenter.defaultCenter().postNotificationName(self.dynamicType.LoopDataUpdatedNotification, object: self)
                }
            },
            center.addObserverForName(DeviceDataManager.PumpStatusUpdatedNotification, object: deviceDataManager, queue: nil) { (note) -> Void in
                dispatch_async(self.dataAccessQueue) {
                    self.insulinEffect = nil
                    self.loop()
                }
            }
        ]

        notificationObservers.append(center.addObserverForName(CarbStore.CarbEntriesDidUpdateNotification, object: nil, queue: nil) { (note) -> Void in
            dispatch_async(self.dataAccessQueue) {
                self.carbEffect = nil

                NSNotificationCenter.defaultCenter().postNotificationName(self.dynamicType.LoopDataUpdatedNotification, object: self)
            }
        })
    }

    private func loop() {
        lastLoopError = nil

        do {
            try self.update()

            if dosingEnabled {
                setRecommendedTempBasal { (success, error) -> Void in
                    self.lastLoopError = error

                    if let error = error {
                        self.deviceDataManager.logger?.addError(error, fromSource: "TempBasal")
                    } else {
                        self.lastLoopCompleted = NSDate()
                    }

                    NSNotificationCenter.defaultCenter().postNotificationName(self.dynamicType.LoopDataUpdatedNotification, object: self)
                }

                // Delay the notification until we know the result of the temp basal
                return
            } else {
                lastLoopCompleted = NSDate()
            }
        } catch let error {
            lastLoopError = error

            // Try to troubleshoot communications errors
            if  let pumpStatusDate = deviceDataManager.latestPumpStatus?.pumpDateComponents.date where pumpStatusDate.timeIntervalSinceNow < NSTimeInterval(minutes: -15),
                let device = deviceDataManager.rileyLinkManager?.firstConnectedDevice where device.lastTuned?.timeIntervalSinceNow < NSTimeInterval(minutes: -15) {
                device.tunePumpWithCompletionHandler { (result) in
                    if let frequency = result["bestFreq"] as? NSNumber {
                        self.deviceDataManager.logger?.addError("Device auto-tuned to \(frequency.descriptionWithLocale(NSLocale.currentLocale())) MHz)", fromSource: "RileyLink")
                    } else {
                        self.deviceDataManager.logger?.addError("Device auto-tune failed", fromSource: <#T##String#>)
                    }
                }
            }
        }

        NSNotificationCenter.defaultCenter().postNotificationName(self.dynamicType.LoopDataUpdatedNotification, object: self)
    }

    // References to registered notification center observers
    private var notificationObservers: [AnyObject] = []

    deinit {<commit_msg>Placeholder<commit_after>//
//  LoopDataManager.swift
//  Naterade
//
//  Created by <NAME> on 3/12/16.
//  Copyright © 2016 <NAME>. All rights reserved.
//

import Foundation
import CarbKit
import InsulinKit
import LoopKit
import MinimedKit


class LoopDataManager {
    static let LoopDataUpdatedNotification = "com.loudnate.Naterade.notification.LoopDataUpdated"

    enum Error: ErrorType {
        case CommunicationError
        case ConnectionError
        case MissingDataError(String)
        case StaleDataError(String)
    }

    typealias TempBasalRecommendation = (recommendedDate: NSDate, rate: Double, duration: NSTimeInterval)

    unowned let deviceDataManager: DeviceDataManager

    var dosingEnabled: Bool {
        didSet {
            NSUserDefaults.standardUserDefaults().dosingEnabled = dosingEnabled
        }
    }

    init(deviceDataManager: DeviceDataManager) {
        self.deviceDataManager = deviceDataManager

        dosingEnabled = NSUserDefaults.standardUserDefaults().dosingEnabled

        observe()
    }

    // Actions

    private func observe() {
        let center = NSNotificationCenter.defaultCenter()

        notificationObservers = [
            center.addObserverForName(DeviceDataManager.GlucoseUpdatedNotification, object: deviceDataManager, queue: nil) { (note) -> Void in
                dispatch_async(self.dataAccessQueue) {
                    self.glucoseMomentumEffect = nil
                    NSNotificationCenter.defaultCenter().postNotificationName(self.dynamicType.LoopDataUpdatedNotification, object: self)
                }
            },
            center.addObserverForName(DeviceDataManager.PumpStatusUpdatedNotification, object: deviceDataManager, queue: nil) { (note) -> Void in
                dispatch_async(self.dataAccessQueue) {
                    self.insulinEffect = nil
                    self.loop()
                }
            }
        ]

        notificationObservers.append(center.addObserverForName(CarbStore.CarbEntriesDidUpdateNotification, object: nil, queue: nil) { (note) -> Void in
            dispatch_async(self.dataAccessQueue) {
                self.carbEffect = nil

                NSNotificationCenter.defaultCenter().postNotificationName(self.dynamicType.LoopDataUpdatedNotification, object: self)
            }
        })
    }

    private func loop() {
        lastLoopError = nil

        do {
            try self.update()

            if dosingEnabled {
                setRecommendedTempBasal { (success, error) -> Void in
                    self.lastLoopError = error

                    if let error = error {
                        self.deviceDataManager.logger?.addError(error, fromSource: "TempBasal")
                    } else {
                        self.lastLoopCompleted = NSDate()
                    }

                    NSNotificationCenter.defaultCenter().postNotificationName(self.dynamicType.LoopDataUpdatedNotification, object: self)
                }

                // Delay the notification until we know the result of the temp basal
                return
            } else {
                lastLoopCompleted = NSDate()
            }
        } catch let error {
            lastLoopError = error

            // Try to troubleshoot communications errors
            if  let pumpStatusDate = deviceDataManager.latestPumpStatus?.pumpDateComponents.date where pumpStatusDate.timeIntervalSinceNow < NSTimeInterval(minutes: -15),
                let device = deviceDataManager.rileyLinkManager?.firstConnectedDevice where device.lastTuned?.timeIntervalSinceNow < NSTimeInterval(minutes: -15) {
                device.tunePumpWithCompletionHandler { (result) in
                    if let frequency = result["bestFreq"] as? NSNumber {
                        self.deviceDataManager.logger?.addError("Device auto-tuned to \(frequency.descriptionWithLocale(NSLocale.currentLocale())) MHz)", fromSource: "RileyLink")
                    } else {
                        self.deviceDataManager.logger?.addError("Device auto-tune failed", fromSource: "RileyLink")
                    }
                }
            }
        }

        NSNotificationCenter.defaultCenter().postNotificationName(self.dynamicType.LoopDataUpdatedNotification, object: self)
    }

    // References to registered notification center observers
    private var notificationObservers: [AnyObject] = []

    deinit {
{'fraction_non_alphanumeric': 0.07659286037053774, 'fraction_numerical': 0.002937189335743335, 'mean_word_length': 2.1651769753307115, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1674539', 'n_tokens_mistral': 2258, 'n_tokens_neox': 2075, 'n_words': 444}