CarbsStorage.swift 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import CoreData
  2. import Foundation
  3. import SwiftDate
  4. import Swinject
  5. protocol CarbsObserver {
  6. func carbsDidUpdate(_ carbs: [CarbsEntry])
  7. }
  8. protocol CarbsStorage {
  9. func storeCarbs(_ carbs: [CarbsEntry])
  10. func syncDate() -> Date
  11. func recent() -> [CarbsEntry]
  12. func nightscoutTretmentsNotUploaded() -> [NigtscoutTreatment]
  13. func deleteCarbs(at date: Date)
  14. }
  15. final class BaseCarbsStorage: CarbsStorage, Injectable {
  16. private let processQueue = DispatchQueue(label: "BaseCarbsStorage.processQueue")
  17. @Injected() private var storage: FileStorage!
  18. @Injected() private var broadcaster: Broadcaster!
  19. let coredataContext = CoreDataStack.shared.persistentContainer.viewContext
  20. init(resolver: Resolver) {
  21. injectServices(resolver)
  22. }
  23. func storeCarbs(_ carbs: [CarbsEntry]) {
  24. processQueue.sync {
  25. let file = OpenAPS.Monitor.carbHistory
  26. var uniqEvents: [CarbsEntry] = []
  27. self.storage.transaction { storage in
  28. storage.append(carbs, to: file, uniqBy: \.createdAt)
  29. uniqEvents = storage.retrieve(file, as: [CarbsEntry].self)?
  30. .filter { $0.createdAt.addingTimeInterval(1.days.timeInterval) > Date() }
  31. .sorted { $0.createdAt > $1.createdAt } ?? []
  32. storage.save(Array(uniqEvents), as: file)
  33. }
  34. // MARK: Save to CoreData. TEST
  35. var cbs: Decimal = 0
  36. var carbDate = Date()
  37. if carbs.isNotEmpty {
  38. cbs = carbs[0].carbs
  39. carbDate = carbs[0].createdAt
  40. }
  41. if cbs != 0 {
  42. let carbDataForStats = Carbohydrates(context: coredataContext)
  43. carbDataForStats.date = carbDate
  44. carbDataForStats.carbs = cbs as NSDecimalNumber
  45. try? coredataContext.save()
  46. }
  47. broadcaster.notify(CarbsObserver.self, on: processQueue) {
  48. $0.carbsDidUpdate(uniqEvents)
  49. }
  50. }
  51. }
  52. func syncDate() -> Date {
  53. Date().addingTimeInterval(-1.days.timeInterval)
  54. }
  55. func recent() -> [CarbsEntry] {
  56. storage.retrieve(OpenAPS.Monitor.carbHistory, as: [CarbsEntry].self)?.reversed() ?? []
  57. }
  58. func deleteCarbs(at date: Date) {
  59. processQueue.sync {
  60. var allValues = storage.retrieve(OpenAPS.Monitor.carbHistory, as: [CarbsEntry].self) ?? []
  61. guard let entryIndex = allValues.firstIndex(where: { $0.createdAt == date }) else {
  62. return
  63. }
  64. allValues.remove(at: entryIndex)
  65. storage.save(allValues, as: OpenAPS.Monitor.carbHistory)
  66. broadcaster.notify(CarbsObserver.self, on: processQueue) {
  67. $0.carbsDidUpdate(allValues)
  68. }
  69. }
  70. }
  71. func nightscoutTretmentsNotUploaded() -> [NigtscoutTreatment] {
  72. let uploaded = storage.retrieve(OpenAPS.Nightscout.uploadedPumphistory, as: [NigtscoutTreatment].self) ?? []
  73. let eventsManual = recent().filter { $0.enteredBy == CarbsEntry.manual }
  74. let treatments = eventsManual.map {
  75. NigtscoutTreatment(
  76. duration: nil,
  77. rawDuration: nil,
  78. rawRate: nil,
  79. absolute: nil,
  80. rate: nil,
  81. eventType: .nsCarbCorrection,
  82. createdAt: $0.createdAt,
  83. enteredBy: CarbsEntry.manual,
  84. bolus: nil,
  85. insulin: nil,
  86. notes: nil,
  87. carbs: $0.carbs,
  88. targetTop: nil,
  89. targetBottom: nil
  90. )
  91. }
  92. return Array(Set(treatments).subtracting(Set(uploaded)))
  93. }
  94. }