DoseStore.swift 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. //
  2. // DoseStore.swift
  3. // Loop
  4. //
  5. // Created by Nate Racklyeft on 7/31/16.
  6. // Copyright © 2016 Nathan Racklyeft. All rights reserved.
  7. //
  8. import LoopKit
  9. // Bridges support for MinimedKit data types
  10. extension Collection where Element == TimestampedHistoryEvent {
  11. func pumpEvents(from model: PumpModel) -> [NewPumpEvent] {
  12. var events: [NewPumpEvent] = []
  13. var lastTempBasalAmount: DoseEntry?
  14. var lastSuspend: DoseEntry?
  15. // Always assume the sequence may have started rewound. LoopKit will ignore unmatched resume events.
  16. var isRewound = true
  17. var title: String
  18. let now = Date()
  19. for event in self {
  20. var dose: DoseEntry?
  21. var eventType: LoopKit.PumpEventType?
  22. switch event.pumpEvent {
  23. case let bolus as BolusNormalPumpEvent:
  24. let bolusEndDate: Date
  25. if let lastSuspend = lastSuspend, bolus.programmed != bolus.amount, lastSuspend.startDate > event.date {
  26. bolusEndDate = lastSuspend.startDate
  27. } else if bolus.duration > 0 {
  28. bolusEndDate = event.date.addingTimeInterval(bolus.duration)
  29. } else {
  30. bolusEndDate = event.date.addingTimeInterval(model.bolusDeliveryTime(units: bolus.amount))
  31. }
  32. dose = DoseEntry(type: .bolus, startDate: event.date, endDate: bolusEndDate, value: bolus.programmed, unit: .units, deliveredUnits: bolus.amount)
  33. case is SuspendPumpEvent:
  34. dose = DoseEntry(suspendDate: event.date)
  35. lastSuspend = dose
  36. case is ResumePumpEvent:
  37. dose = DoseEntry(resumeDate: event.date)
  38. case let temp as TempBasalPumpEvent:
  39. if case .Absolute = temp.rateType {
  40. lastTempBasalAmount = DoseEntry(type: .tempBasal, startDate: event.date, value: temp.rate, unit: .unitsPerHour)
  41. }
  42. case let temp as TempBasalDurationPumpEvent:
  43. if let amount = lastTempBasalAmount, amount.startDate == event.date {
  44. dose = DoseEntry(
  45. type: .tempBasal,
  46. startDate: event.date,
  47. endDate: event.date.addingTimeInterval(TimeInterval(minutes: Double(temp.duration))),
  48. value: amount.unitsPerHour,
  49. unit: .unitsPerHour
  50. )
  51. }
  52. case let basal as BasalProfileStartPumpEvent:
  53. dose = DoseEntry(
  54. type: .basal,
  55. startDate: event.date,
  56. // Use the maximum-possible duration for a basal entry; its true duration will be reconciled against other entries.
  57. endDate: event.date.addingTimeInterval(.hours(24)),
  58. value: basal.scheduleEntry.rate,
  59. unit: .unitsPerHour
  60. )
  61. case is RewindPumpEvent:
  62. eventType = .rewind
  63. /*
  64. No insulin is delivered between the beginning of a rewind until the suggested fixed prime is delivered or cancelled.
  65. If the fixed prime is cancelled, it is never recorded in history. It is possible to cancel a fixed prime and perform one manually some time later, but basal delivery will have resumed during that period.
  66. We take the conservative approach and assume delivery is paused only between the Rewind and the first Prime event.
  67. */
  68. dose = DoseEntry(suspendDate: event.date)
  69. isRewound = true
  70. case is PrimePumpEvent:
  71. eventType = .prime
  72. if isRewound {
  73. isRewound = false
  74. dose = DoseEntry(resumeDate: event.date)
  75. }
  76. case let alarm as PumpAlarmPumpEvent:
  77. eventType = .alarm
  78. if case .noDelivery = alarm.alarmType {
  79. dose = DoseEntry(suspendDate: event.date)
  80. }
  81. break
  82. case let alarm as ClearAlarmPumpEvent:
  83. eventType = .alarmClear
  84. if case .noDelivery = alarm.alarmType {
  85. dose = DoseEntry(resumeDate: event.date)
  86. }
  87. break
  88. default:
  89. break
  90. }
  91. title = String(describing: event.pumpEvent)
  92. events.append(NewPumpEvent(date: event.date, dose: dose, isMutable: event.isMutable(atDate: now, forPump: model), raw: event.pumpEvent.rawData, title: title, type: eventType))
  93. }
  94. return events
  95. }
  96. }