| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- import Foundation
- import SwiftDate
- import Swinject
- protocol GlucoseStorage {
- func storeGlucose(_ glucose: [BloodGlucose])
- func recent() -> [BloodGlucose]
- func syncDate() -> Date
- func filterTooFrequentGlucose(_ glucose: [BloodGlucose], at: Date) -> [BloodGlucose]
- func lastGlucoseDate() -> Date
- func isGlucoseFresh() -> Bool
- func isGlucoseNotFlat() -> Bool
- }
- final class BaseGlucoseStorage: GlucoseStorage, Injectable {
- private let processQueue = DispatchQueue(label: "BaseGlucoseStorage.processQueue")
- @Injected() private var storage: FileStorage!
- @Injected() private var broadcaster: Broadcaster!
- private enum Config {
- static let filterTime: TimeInterval = 4.75 * 60
- }
- init(resolver: Resolver) {
- injectServices(resolver)
- }
- func storeGlucose(_ glucose: [BloodGlucose]) {
- processQueue.sync {
- let file = OpenAPS.Monitor.glucose
- self.storage.transaction { storage in
- storage.append(glucose, to: file, uniqBy: \.dateString)
- let uniqEvents = storage.retrieve(file, as: [BloodGlucose].self)?
- .filter { $0.dateString.addingTimeInterval(1.days.timeInterval) > Date() }
- .sorted { $0.dateString > $1.dateString } ?? []
- let glucose = Array(uniqEvents)
- storage.save(glucose, as: file)
- DispatchQueue.main.async {
- self.broadcaster.notify(GlucoseObserver.self, on: .main) {
- $0.glucoseDidUpdate(glucose.reversed())
- }
- }
- }
- }
- }
- func syncDate() -> Date {
- guard let events = storage.retrieve(OpenAPS.Monitor.glucose, as: [BloodGlucose].self),
- let recent = events.first
- else {
- return Date().addingTimeInterval(-1.days.timeInterval)
- }
- return recent.dateString
- }
- func recent() -> [BloodGlucose] {
- storage.retrieve(OpenAPS.Monitor.glucose, as: [BloodGlucose].self)?.reversed() ?? []
- }
- func lastGlucoseDate() -> Date {
- recent().last?.dateString ?? .distantPast
- }
- func isGlucoseFresh() -> Bool {
- Date().timeIntervalSince(lastGlucoseDate()) <= Config.filterTime
- }
- func filterTooFrequentGlucose(_ glucose: [BloodGlucose], at date: Date) -> [BloodGlucose] {
- var lastDate = date
- var filtered: [BloodGlucose] = []
- for entry in glucose.reversed() {
- guard entry.dateString.addingTimeInterval(-Config.filterTime) > lastDate else {
- continue
- }
- filtered.append(entry)
- lastDate = entry.dateString
- }
- return filtered
- }
- func isGlucoseNotFlat() -> Bool {
- let last3 = recent().suffix(3)
- guard last3.count == 3 else { return true }
- return Array(last3.compactMap { $0.filtered ?? Decimal($0.sgv ?? 0) }.uniqued()).count > 1
- }
- }
- protocol GlucoseObserver {
- func glucoseDidUpdate(_ glucose: [BloodGlucose])
- }
|