<commit_before>//
//  ServerConfiguration.swift
//  Nightscouter
//
//  Created by <NAME> on 1/11/16.
//  Copyright © 2016 Nothingonline. All rights reserved.
//

import Foundation

public struct ServerConfiguration: Codable, CustomStringConvertible {
    public let status: String
    public let version: String
    public let name: String
    public let serverTime: String
    public let apiEnabled: Bool
    public let careportalEnabled: Bool
    public let boluscalcEnabled: Bool
    public let settings: Settings?
    
    public var description: String {
        var dict = [String: Any]()
        
        dict["status"] = status
        dict["apiEnabled"] = apiEnabled
        dict["serverTime"] = serverTime
        dict["careportalEnabled"] = careportalEnabled
        dict["boluscalcEnabled"] = boluscalcEnabled
        dict["settings"] = settings
        dict["version"] = version
        dict["name"] = name
        
        return dict.description
    }
    
    public init() {
        self.status = "okToTest"
        self.version = "0.0.0test"
        self.name = "NightscoutTest"
        self.serverTime = "2016-01-13T15:04:59.059Z"
        self.apiEnabled = true
        self.careportalEnabled = false
        self.boluscalcEnabled = false
        
        let placeholderAlarm1: [Double] = [15, 30, 45, 60]
        let placeholderAlarm2: [Double] = [30, 60, 90, 120]
        
        let alrm = Alarm(urgentHigh: true, urgentHighMins: placeholderAlarm2, high: true, highMins: placeholderAlarm2, low: true, lowMins: placeholderAlarm1, urgentLow: true, urgentLowMins: placeholderAlarm1, warnMins: placeholderAlarm2)
        let timeAgo = TimeAgoAlert(warn: true, warnMins: 60.0 * 10, urgent: true, urgentMins: 60.0 * 15)
        let plugins: [Plugin] = [Plugin.delta, Plugin.rawbg]

        let thre = Thresholds(bgHigh: 300, bgLow: 70, bgTargetBottom: 60, bgTargetTop: 250)
        
        let s = Settings(units: .mgdl, showRawbg: .never, customTitle: "NightscoutDefault", alarmUrgentHigh: true, alarmUrgentHighMins: alrm.urgentLowMins, alarmHigh: alrm.urgentHigh, alarmHighMins: alrm.warnMins, alarmLow: alrm.low, alarmLowMins: alrm.lowMins, alarmUrgentLow: alrm.urgentLow, alarmUrgentLowMins: alrm.urgentLowMins, alarmWarnMins: alrm.warnMins, alarmTimeagoWarn: timeAgo.warn, alarmTimeagoWarnMins: timeAgo.urgentMins, alarmTimeagoUrgent: timeAgo.urgent, alarmTimeagoUrgentMins: timeAgo.urgentMins, thresholds: thre, enable: plugins)
        self.settings = s

    }
    
    public init(status: String, version: String, name: String, serverTime: String, api: Bool, carePortal: Bool, boluscalc: Bool, settings: Settings?, head: String) {
        self.status = status
        self.version = version
        self.name = name
        self.serverTime = serverTime
        self.apiEnabled = api
        self.careportalEnabled = carePortal
        self.boluscalcEnabled = boluscalc
        self.settings = settings
    }
}

extension ServerConfiguration: Equatable { }
public func ==(lhs: ServerConfiguration, rhs: ServerConfiguration) -> Bool {
    return lhs.status == rhs.status &&
        lhs.version == rhs.version &&
        lhs.name == rhs.name &&
        lhs.serverTime == rhs.serverTime &&
        lhs.apiEnabled == rhs.apiEnabled &&
        lhs.careportalEnabled == rhs.careportalEnabled &&
        lhs.boluscalcEnabled == rhs.boluscalcEnabled &&
        lhs.settings == rhs.settings
}

extension ServerConfiguration {
    public var displayName: String {
        if let settings = settings {
            return settings.customTitle
        } else {
            return name
        }
    }
    
    public var displayRawData: Bool {
        if let settings = settings {
            let rawEnabled = settings.enable.contains(Plugin.rawbg)
            if rawEnabled {
                switch settings.showRawbg {
                case .noise:
                    return true
                case .always:
                    return true
                case .never:
                    return false
                }
                
            }
        }
        return false
        
    }
    
    public var displayUnits: GlucoseUnit {
        if let settings = settings {
            return settings.units
        }
        return .mgdl
    }
}

public struct Settings: Codable {
    public let units: GlucoseUnit

    public let showRawbg: RawBGMode
    public let customTitle: String

    public var alarms: Alarm {
        return Alarm(urgentHigh: alarmUrgentHigh, urgentHighMins: alarmUrgentHighMins, high: alarmHigh, highMins: alarmHighMins, low: alarmLow, lowMins: alarmLowMins, urgentLow: alarmUrgentLow, urgentLowMins: alarmUrgentLowMins, warnMins: alarmWarnMins)
    }
    
    public let alarmUrgentHigh: Bool
    public let alarmUrgentHighMins: [Double]
    public let alarmHigh: Bool
    public let alarmHighMins: [Double]
    public let alarmLow: Bool
    public let alarmLowMins: [Double]
    public let alarmUrgentLow: Bool
    public let alarmUrgentLowMins: [Double]
    public let alarmWarnMins: [Double]
    public let alarmTimeagoWarn: Bool
    public var alarmTimeagoWarnMins: Double = 15
    public let alarmTimeagoUrgent: Bool
    public var alarmTimeagoUrgentMins: Double = 30
    
    public var timeAgo: TimeAgoAlert {
        return TimeAgoAlert(warn: alarmTimeagoWarn, warnMins: TimeInterval(alarmTimeagoWarnMins * 10), urgent: alarmTimeagoUrgent, urgentMins: TimeInterval(alarmTimeagoUrgentMins * 10))
    }

    public let thresholds: Thresholds
    public let enable: [Plugin]
    
}

extension Settings {
    public init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
       
        units = try values.decode(GlucoseUnit.self, forKey: .units)
        showRawbg = try values.decode(RawBGMode.self, forKey: .showRawbg)
        customTitle = try values.decode(String.self, forKey: .customTitle)
        
        alarmUrgentHigh = try values.decode(Bool.self, forKey: .alarmUrgentHigh)
        alarmUrgentHighMins = try values.decode([Double].self, forKey: .alarmUrgentHighMins)
        alarmHigh = try values.decode(Bool.self, forKey: .alarmHigh)
        alarmHighMins = try values.decode([Double].self, forKey: .alarmHighMins)
        alarmLow = try values.decode(Bool.self, forKey: .alarmLow)
        alarmLowMins = try values.decode([Double].self, forKey: .alarmLowMins)
        alarmUrgentLow = try values.decode(Bool.self, forKey: .alarmUrgentLow)
        alarmUrgentLowMins  = try values.decode([Double].self, forKey: .alarmUrgentLowMins)
        alarmWarnMins = try values.decode([Double].self, forKey: .alarmWarnMins)
        alarmTimeagoWarn = try values.decode(Bool.self, forKey: .alarmTimeagoWarn)
        alarmTimeagoWarnMins  = 15//try values.decodeIfPresent(Double.self, forKey: .alarmTimeagoWarnMins) ?? 15
        alarmTimeagoUrgent = try values.decode(Bool.self, forKey: .alarmTimeagoUrgent)
        alarmTimeagoUrgentMins  = 30//try values.decodeIfPresent(Double.self, forKey: .alarmTimeagoUrgentMins) ?? 30<commit_msg>more robust handling of time ago string<commit_after>//
//  ServerConfiguration.swift
//  Nightscouter
//
//  Created by <NAME> on 1/11/16.
//  Copyright © 2016 Nothingonline. All rights reserved.
//

import Foundation

public struct ServerConfiguration: Codable, CustomStringConvertible {
    public let status: String
    public let version: String
    public let name: String
    public let serverTime: String
    public let apiEnabled: Bool
    public let careportalEnabled: Bool
    public let boluscalcEnabled: Bool
    public let settings: Settings?
    
    public var description: String {
        var dict = [String: Any]()
        
        dict["status"] = status
        dict["apiEnabled"] = apiEnabled
        dict["serverTime"] = serverTime
        dict["careportalEnabled"] = careportalEnabled
        dict["boluscalcEnabled"] = boluscalcEnabled
        dict["settings"] = settings
        dict["version"] = version
        dict["name"] = name
        
        return dict.description
    }
    
    public init() {
        self.status = "okToTest"
        self.version = "0.0.0test"
        self.name = "NightscoutTest"
        self.serverTime = "2016-01-13T15:04:59.059Z"
        self.apiEnabled = true
        self.careportalEnabled = false
        self.boluscalcEnabled = false
        
        let placeholderAlarm1: [Double] = [15, 30, 45, 60]
        let placeholderAlarm2: [Double] = [30, 60, 90, 120]
        
        let alrm = Alarm(urgentHigh: true, urgentHighMins: placeholderAlarm2, high: true, highMins: placeholderAlarm2, low: true, lowMins: placeholderAlarm1, urgentLow: true, urgentLowMins: placeholderAlarm1, warnMins: placeholderAlarm2)
        let timeAgo = TimeAgoAlert(warn: true, warnMins: 60.0 * 10, urgent: true, urgentMins: 60.0 * 15)
        let plugins: [Plugin] = [Plugin.delta, Plugin.rawbg]

        let thre = Thresholds(bgHigh: 300, bgLow: 70, bgTargetBottom: 60, bgTargetTop: 250)
        
        let s = Settings(units: .mgdl, showRawbg: .never, customTitle: "NightscoutDefault", alarmUrgentHigh: true, alarmUrgentHighMins: alrm.urgentLowMins, alarmHigh: alrm.urgentHigh, alarmHighMins: alrm.warnMins, alarmLow: alrm.low, alarmLowMins: alrm.lowMins, alarmUrgentLow: alrm.urgentLow, alarmUrgentLowMins: alrm.urgentLowMins, alarmWarnMins: alrm.warnMins, alarmTimeagoWarn: timeAgo.warn, alarmTimeagoWarnMins: timeAgo.urgentMins, alarmTimeagoUrgent: timeAgo.urgent, alarmTimeagoUrgentMins: timeAgo.urgentMins, thresholds: thre, enable: plugins)
        self.settings = s

    }
    
    public init(status: String, version: String, name: String, serverTime: String, api: Bool, carePortal: Bool, boluscalc: Bool, settings: Settings?, head: String) {
        self.status = status
        self.version = version
        self.name = name
        self.serverTime = serverTime
        self.apiEnabled = api
        self.careportalEnabled = carePortal
        self.boluscalcEnabled = boluscalc
        self.settings = settings
    }
}

extension ServerConfiguration: Equatable { }
public func ==(lhs: ServerConfiguration, rhs: ServerConfiguration) -> Bool {
    return lhs.status == rhs.status &&
        lhs.version == rhs.version &&
        lhs.name == rhs.name &&
        lhs.serverTime == rhs.serverTime &&
        lhs.apiEnabled == rhs.apiEnabled &&
        lhs.careportalEnabled == rhs.careportalEnabled &&
        lhs.boluscalcEnabled == rhs.boluscalcEnabled &&
        lhs.settings == rhs.settings
}

extension ServerConfiguration {
    public var displayName: String {
        if let settings = settings {
            return settings.customTitle
        } else {
            return name
        }
    }
    
    public var displayRawData: Bool {
        if let settings = settings {
            let rawEnabled = settings.enable.contains(Plugin.rawbg)
            if rawEnabled {
                switch settings.showRawbg {
                case .noise:
                    return true
                case .always:
                    return true
                case .never:
                    return false
                }
                
            }
        }
        return false
        
    }
    
    public var displayUnits: GlucoseUnit {
        if let settings = settings {
            return settings.units
        }
        return .mgdl
    }
}

public struct Settings: Codable {
    public let units: GlucoseUnit

    public let showRawbg: RawBGMode
    public let customTitle: String

    public var alarms: Alarm {
        return Alarm(urgentHigh: alarmUrgentHigh, urgentHighMins: alarmUrgentHighMins, high: alarmHigh, highMins: alarmHighMins, low: alarmLow, lowMins: alarmLowMins, urgentLow: alarmUrgentLow, urgentLowMins: alarmUrgentLowMins, warnMins: alarmWarnMins)
    }
    
    public let alarmUrgentHigh: Bool
    public let alarmUrgentHighMins: [Double]
    public let alarmHigh: Bool
    public let alarmHighMins: [Double]
    public let alarmLow: Bool
    public let alarmLowMins: [Double]
    public let alarmUrgentLow: Bool
    public let alarmUrgentLowMins: [Double]
    public let alarmWarnMins: [Double]
    public let alarmTimeagoWarn: Bool
    public var alarmTimeagoWarnMins: Double = 15
    public let alarmTimeagoUrgent: Bool
    public var alarmTimeagoUrgentMins: Double = 30
    
    public var timeAgo: TimeAgoAlert {
        return TimeAgoAlert(warn: alarmTimeagoWarn, warnMins: TimeInterval(alarmTimeagoWarnMins * 10), urgent: alarmTimeagoUrgent, urgentMins: TimeInterval(alarmTimeagoUrgentMins * 10))
    }

    public let thresholds: Thresholds
    public let enable: [Plugin]
    
}

extension Settings {
    public init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
       
        units = try values.decode(GlucoseUnit.self, forKey: .units)
        showRawbg = try values.decode(RawBGMode.self, forKey: .showRawbg)
        customTitle = try values.decode(String.self, forKey: .customTitle)
        
        alarmUrgentHigh = try values.decode(Bool.self, forKey: .alarmUrgentHigh)
        alarmUrgentHighMins = try values.decode([Double].self, forKey: .alarmUrgentHighMins)
        alarmHigh = try values.decode(Bool.self, forKey: .alarmHigh)
        alarmHighMins = try values.decode([Double].self, forKey: .alarmHighMins)
        alarmLow = try values.decode(Bool.self, forKey: .alarmLow)
        alarmLowMins = try values.decode([Double].self, forKey: .alarmLowMins)
        alarmUrgentLow = try values.decode(Bool.self, forKey: .alarmUrgentLow)
        alarmUrgentLowMins  = try values.decode([Double].self, forKey: .alarmUrgentLowMins)
        alarmWarnMins = try values.decode([Double].self, forKey: .alarmWarnMins)
        alarmTimeagoWarn = try values.decode(Bool.self, forKey: .alarmTimeagoWarn)
        alarmTimeagoUrgent = try values.decode(Bool.self, forKey: .alarmTimeagoUrgent)
        
        do {
            alarmTimeagoWarnMins = try values.decode(Double.self, forKey: .alarmTimeagoWarnMins) * 10
        } catch {
            alarmTimeagoWarnMins = 15
        }
        
        do {
            alarmTimeagoUrgentMins = try values.decode(Double.self, forKey: .alarmTimeagoUrgentMins) * 10
        } catch {
            alarmTimeagoUrgentMins = 30
        }
{'fraction_non_alphanumeric': 0.08726712424709343, 'fraction_numerical': 0.012466732035299062, 'mean_word_length': 2.709794751883606, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, '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': '3505002', 'n_tokens_mistral': 4463, 'n_tokens_neox': 4252, 'n_words': 1063}