TestingScenario.swift 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. //
  2. // TestingScenario.swift
  3. // LoopTestingKit
  4. //
  5. // Created by Michael Pangburn on 4/20/19.
  6. // Copyright © 2019 LoopKit Authors. All rights reserved.
  7. //
  8. import Foundation
  9. import LoopKit
  10. public struct TestingScenario {
  11. var dateRelativeGlucoseSamples: [DateRelativeGlucoseSample]
  12. var dateRelativeBasalEntries: [DateRelativeBasalEntry]
  13. var dateRelativeBolusEntries: [DateRelativeBolusEntry]
  14. var dateRelativeCarbEntries: [DateRelativeCarbEntry]
  15. public func instantiate(relativeTo referenceDate: Date = Date()) -> TestingScenarioInstance {
  16. let glucoseSamples = dateRelativeGlucoseSamples
  17. .map { $0.newGlucoseSample(relativeTo: referenceDate) }
  18. .filter { $0.date <= referenceDate }
  19. let basalEntries = dateRelativeBasalEntries.map { $0.newPumpEvent(relativeTo: referenceDate) }
  20. let bolusEntries = dateRelativeBolusEntries.map { $0.newPumpEvent(relativeTo: referenceDate) }
  21. let pumpEvents = (basalEntries + bolusEntries)
  22. .filter { $0.date <= referenceDate }
  23. .sorted(by: { $0.date < $1.date })
  24. let carbEntries = dateRelativeCarbEntries
  25. .filter { $0.enteredAt(relativeTo: referenceDate) <= referenceDate }
  26. .map { $0.newCarbEntry(relativeTo: referenceDate) }
  27. return TestingScenarioInstance(glucoseSamples: glucoseSamples, pumpEvents: pumpEvents, carbEntries: carbEntries)
  28. }
  29. public mutating func stepBackward(by offset: TimeInterval) {
  30. assert(offset > 0)
  31. shift(by: offset)
  32. }
  33. public mutating func stepForward(by offset: TimeInterval) {
  34. assert(offset > 0)
  35. shift(by: -offset)
  36. }
  37. public mutating func stepForward(
  38. unitsPerHour: Double,
  39. duration: TimeInterval,
  40. dateOffset: TimeInterval = 0,
  41. loopInterval: TimeInterval = 60 * 5 /* minutes */
  42. ) {
  43. precondition(duration > 0)
  44. dateRelativeBasalEntries.removeAll(where: { $0.dateOffset >= dateOffset })
  45. let basal = DateRelativeBasalEntry(unitsPerHourValue: unitsPerHour, dateOffset: dateOffset, duration: duration)
  46. dateRelativeBasalEntries.append(basal)
  47. stepForward(by: loopInterval)
  48. }
  49. mutating func shift(by offset: TimeInterval) {
  50. dateRelativeGlucoseSamples.mutateEach { $0.shift(by: offset) }
  51. dateRelativeBasalEntries.mutateEach { $0.shift(by: offset) }
  52. dateRelativeBolusEntries.mutateEach { $0.shift(by: offset) }
  53. dateRelativeCarbEntries.mutateEach { $0.shift(by: offset) }
  54. }
  55. }
  56. extension TestingScenario: Codable {
  57. public enum CodingKeys: String, CodingKey {
  58. case dateRelativeGlucoseSamples = "glucoseValues"
  59. case dateRelativeBasalEntries = "basalDoses"
  60. case dateRelativeBolusEntries = "bolusDoses"
  61. case dateRelativeCarbEntries = "carbEntries"
  62. }
  63. }
  64. extension TestingScenario {
  65. public init(source: URL) throws {
  66. let decoder = JSONDecoder()
  67. let data = try Data(contentsOf: source)
  68. self = try decoder.decode(TestingScenario.self, from: data)
  69. }
  70. }