// // TestingScenario.swift // LoopTestingKit // // Created by Michael Pangburn on 4/20/19. // Copyright © 2019 LoopKit Authors. All rights reserved. // import Foundation import LoopKit public struct TestingScenario { var dateRelativeGlucoseSamples: [DateRelativeGlucoseSample] var dateRelativeBasalEntries: [DateRelativeBasalEntry] var dateRelativeBolusEntries: [DateRelativeBolusEntry] var dateRelativeCarbEntries: [DateRelativeCarbEntry] public func instantiate(relativeTo referenceDate: Date = Date()) -> TestingScenarioInstance { let glucoseSamples = dateRelativeGlucoseSamples .map { $0.newGlucoseSample(relativeTo: referenceDate) } .filter { $0.date <= referenceDate } let basalEntries = dateRelativeBasalEntries.map { $0.newPumpEvent(relativeTo: referenceDate) } let bolusEntries = dateRelativeBolusEntries.map { $0.newPumpEvent(relativeTo: referenceDate) } let pumpEvents = (basalEntries + bolusEntries) .filter { $0.date <= referenceDate } .sorted(by: { $0.date < $1.date }) let carbEntries = dateRelativeCarbEntries .filter { $0.enteredAt(relativeTo: referenceDate) <= referenceDate } .map { $0.newCarbEntry(relativeTo: referenceDate) } return TestingScenarioInstance(glucoseSamples: glucoseSamples, pumpEvents: pumpEvents, carbEntries: carbEntries) } public mutating func stepBackward(by offset: TimeInterval) { assert(offset > 0) shift(by: offset) } public mutating func stepForward(by offset: TimeInterval) { assert(offset > 0) shift(by: -offset) } public mutating func stepForward( unitsPerHour: Double, duration: TimeInterval, dateOffset: TimeInterval = 0, loopInterval: TimeInterval = 60 * 5 /* minutes */ ) { precondition(duration > 0) dateRelativeBasalEntries.removeAll(where: { $0.dateOffset >= dateOffset }) let basal = DateRelativeBasalEntry(unitsPerHourValue: unitsPerHour, dateOffset: dateOffset, duration: duration) dateRelativeBasalEntries.append(basal) stepForward(by: loopInterval) } mutating func shift(by offset: TimeInterval) { dateRelativeGlucoseSamples.mutateEach { $0.shift(by: offset) } dateRelativeBasalEntries.mutateEach { $0.shift(by: offset) } dateRelativeBolusEntries.mutateEach { $0.shift(by: offset) } dateRelativeCarbEntries.mutateEach { $0.shift(by: offset) } } } extension TestingScenario: Codable { public enum CodingKeys: String, CodingKey { case dateRelativeGlucoseSamples = "glucoseValues" case dateRelativeBasalEntries = "basalDoses" case dateRelativeBolusEntries = "bolusDoses" case dateRelativeCarbEntries = "carbEntries" } } extension TestingScenario { public init(source: URL) throws { let decoder = JSONDecoder() let data = try Data(contentsOf: source) self = try decoder.decode(TestingScenario.self, from: data) } }