// // BasalSchedule.swift // RileyLink // // Created by Pete Schwamb on 5/6/17. // Copyright © 2017 Pete Schwamb. All rights reserved. // import Foundation public struct BasalScheduleEntry { public let index: Int public let timeOffset: TimeInterval public let rate: Double // U/hour public init(index: Int, timeOffset: TimeInterval, rate: Double) { self.index = index self.timeOffset = timeOffset self.rate = rate } } public struct BasalSchedule { public let entries: [BasalScheduleEntry] public init(entries: [BasalScheduleEntry]) { self.entries = entries } } extension BasalSchedule { static let rawValueLength = 192 public typealias RawValue = Data public init?(rawValue: RawValue) { var entries = [BasalScheduleEntry]() for tuple in sequence(first: (index: 0, offset: 0), next: { (index: $0.index + 1, $0.offset + 3) }) { let beginOfRange = tuple.offset let endOfRange = beginOfRange + 3 guard endOfRange < rawValue.count else { break } if let entry = BasalScheduleEntry( index: tuple.index, rawValue: rawValue[beginOfRange..= entry.timeOffset { // Stop if the new timeOffset isn't greater than the last one break } entries.append(entry) } else { // Stop if we can't decode the entry break } } guard entries.count > 0 else { return nil } self.init(entries: entries) } public var rawValue: RawValue { var buffer = Data(count: BasalSchedule.rawValueLength) var byteIndex = 0 for rawEntry in entries.map({ $0.rawValue }) { buffer.replaceSubrange(byteIndex..<(byteIndex + rawEntry.count), with: rawEntry) byteIndex += rawEntry.count } // Send the special "empty" code to clear a schedule if entries.count == 0 { buffer[2] = 0x3f } return buffer } } private extension BasalScheduleEntry { static let rawValueLength = 3 typealias RawValue = Data init?(index: Int, rawValue: RawValue) { guard rawValue.count == BasalScheduleEntry.rawValueLength else { return nil } let rawRate = rawValue[rawValue.startIndex..