CalibrationsStateModel.swift 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import CoreData
  2. import Observation
  3. import SwiftDate
  4. import SwiftUI
  5. extension Calibrations {
  6. @Observable final class StateModel: BaseStateModel<Provider> {
  7. @ObservationIgnored @Injected() var glucoseStorage: GlucoseStorage!
  8. @ObservationIgnored @Injected() var calibrationService: CalibrationService!
  9. var slope: Double = 1
  10. var intercept: Double = 1
  11. var newCalibration: Decimal = 0
  12. var calibrations: [Calibration] = []
  13. var calibrate: (Int) -> Double = { Double($0) }
  14. var items: [Item] = []
  15. var units: GlucoseUnits = .mgdL
  16. let backgroundContext = CoreDataStack.shared.newTaskContext()
  17. private let viewContext = CoreDataStack.shared.persistentContainer.viewContext
  18. override func subscribe() {
  19. units = settingsManager.settings.units
  20. calibrate = calibrationService.calibrate
  21. setupCalibrations()
  22. }
  23. private func setupCalibrations() {
  24. slope = calibrationService.slope
  25. intercept = calibrationService.intercept
  26. calibrations = calibrationService.calibrations
  27. items = calibrations.map {
  28. Item(calibration: $0)
  29. }
  30. }
  31. /// - Returns: An array of NSManagedObjectIDs for glucose readings.
  32. private func fetchGlucose() async -> [NSManagedObjectID] {
  33. let results = await CoreDataStack.shared.fetchEntitiesAsync(
  34. ofType: GlucoseStored.self,
  35. onContext: backgroundContext,
  36. predicate: NSPredicate.predicateFor20MinAgo,
  37. key: "date",
  38. ascending: false,
  39. fetchLimit: 1 /// We only need the last value
  40. )
  41. return await backgroundContext.perform {
  42. guard let glucoseResults = results as? [GlucoseStored] else {
  43. return []
  44. }
  45. return glucoseResults.map(\.objectID)
  46. }
  47. }
  48. @MainActor func addCalibration() async {
  49. defer {
  50. UIApplication.shared.endEditing()
  51. setupCalibrations()
  52. }
  53. var glucose = newCalibration
  54. if units == .mmolL {
  55. glucose = newCalibration.asMgdL
  56. }
  57. let glucoseValuesIds = await fetchGlucose()
  58. let glucoseObjects: [GlucoseStored] = await CoreDataStack.shared
  59. .getNSManagedObject(with: glucoseValuesIds, context: viewContext)
  60. if let lastGlucose = glucoseObjects.first {
  61. let unfiltered = lastGlucose.glucose
  62. let calibration = Calibration(x: Double(unfiltered), y: Double(glucose))
  63. calibrationService.addCalibration(calibration)
  64. } else {
  65. info(.service, "Glucose is stale for calibration")
  66. return
  67. }
  68. }
  69. func removeLast() {
  70. calibrationService.removeLast()
  71. setupCalibrations()
  72. }
  73. func removeAll() {
  74. calibrationService.removeAllCalibrations()
  75. setupCalibrations()
  76. }
  77. func removeAtIndex(_ index: Int) {
  78. let calibration = calibrations[index]
  79. calibrationService.removeCalibration(calibration)
  80. setupCalibrations()
  81. }
  82. }
  83. }