TempTargetsStorage.swift 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import Foundation
  2. import SwiftDate
  3. import Swinject
  4. protocol TempTargetsObserver {
  5. func tempTargetsDidUpdate(_ targers: [TempTarget])
  6. }
  7. protocol TempTargetsStorage {
  8. func storeTempTargets(_ targets: [TempTarget])
  9. func syncDate() -> Date
  10. func recent() -> [TempTarget]
  11. func nightscoutTretmentsNotUploaded() -> [NigtscoutTreatment]
  12. func storePresets(_ targets: [TempTarget])
  13. func presets() -> [TempTarget]
  14. func current() -> TempTarget?
  15. }
  16. final class BaseTempTargetsStorage: TempTargetsStorage, Injectable {
  17. private let processQueue = DispatchQueue(label: "BaseTempTargetsStorage.processQueue")
  18. @Injected() private var storage: FileStorage!
  19. @Injected() private var broadcaster: Broadcaster!
  20. init(resolver: Resolver) {
  21. injectServices(resolver)
  22. }
  23. func storeTempTargets(_ targets: [TempTarget]) {
  24. storeTempTargets(targets, isPresets: false)
  25. }
  26. private func storeTempTargets(_ targets: [TempTarget], isPresets: Bool) {
  27. processQueue.sync {
  28. var targets = targets
  29. if !isPresets {
  30. if current() != nil, let newActive = targets.last(where: {
  31. $0.createdAt.addingTimeInterval(Int($0.duration).minutes.timeInterval) > Date()
  32. && $0.createdAt <= Date()
  33. }) {
  34. // cancel current
  35. targets += [TempTarget.cancel(at: newActive.createdAt.addingTimeInterval(-1))]
  36. }
  37. }
  38. let file = isPresets ? OpenAPS.FreeAPS.tempTargetsPresets : OpenAPS.Settings.tempTargets
  39. var uniqEvents: [TempTarget] = []
  40. self.storage.transaction { storage in
  41. storage.append(targets, to: file, uniqBy: \.createdAt)
  42. uniqEvents = storage.retrieve(file, as: [TempTarget].self)?
  43. .filter {
  44. guard !isPresets else { return true }
  45. return $0.createdAt.addingTimeInterval(1.days.timeInterval) > Date()
  46. }
  47. .sorted { $0.createdAt > $1.createdAt } ?? []
  48. storage.save(Array(uniqEvents), as: file)
  49. }
  50. broadcaster.notify(TempTargetsObserver.self, on: processQueue) {
  51. $0.tempTargetsDidUpdate(uniqEvents)
  52. }
  53. }
  54. }
  55. func syncDate() -> Date {
  56. Date().addingTimeInterval(-1.days.timeInterval)
  57. }
  58. func recent() -> [TempTarget] {
  59. storage.retrieve(OpenAPS.Settings.tempTargets, as: [TempTarget].self)?.reversed() ?? []
  60. }
  61. func current() -> TempTarget? {
  62. guard let currentTarget = recent()
  63. .last(where: {
  64. $0.createdAt.addingTimeInterval(Int($0.duration).minutes.timeInterval) > Date()
  65. && $0.createdAt <= Date()
  66. })
  67. else {
  68. return nil
  69. }
  70. if let cancel = recent().last(where: { $0.createdAt <= Date() }), cancel.duration == 0 {
  71. return nil
  72. }
  73. return currentTarget
  74. }
  75. func nightscoutTretmentsNotUploaded() -> [NigtscoutTreatment] {
  76. let uploaded = storage.retrieve(OpenAPS.Nightscout.uploadedTempTargets, as: [NigtscoutTreatment].self) ?? []
  77. let eventsManual = recent().filter { $0.enteredBy == TempTarget.manual }
  78. let treatments = eventsManual.map {
  79. NigtscoutTreatment(
  80. duration: Int($0.duration),
  81. rawDuration: nil,
  82. rawRate: nil,
  83. absolute: nil,
  84. rate: nil,
  85. eventType: .nsTempTarget,
  86. createdAt: $0.createdAt,
  87. enteredBy: TempTarget.manual,
  88. bolus: nil,
  89. insulin: nil,
  90. notes: nil,
  91. carbs: nil,
  92. targetTop: $0.targetTop,
  93. targetBottom: $0.targetBottom
  94. )
  95. }
  96. return Array(Set(treatments).subtracting(Set(uploaded)))
  97. }
  98. func storePresets(_ targets: [TempTarget]) {
  99. storage.remove(OpenAPS.FreeAPS.tempTargetsPresets)
  100. storeTempTargets(targets, isPresets: true)
  101. }
  102. func presets() -> [TempTarget] {
  103. storage.retrieve(OpenAPS.FreeAPS.tempTargetsPresets, as: [TempTarget].self)?.reversed() ?? []
  104. }
  105. }