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