ISFEditorStateModel.swift 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import CoreData
  2. import SwiftUI
  3. extension ISFEditor {
  4. final class StateModel: BaseStateModel<Provider> {
  5. @Injected() var determinationStorage: DeterminationStorage!
  6. @Published var items: [Item] = []
  7. private(set) var autosensISF: Decimal?
  8. private(set) var autosensRatio: Decimal = 0
  9. @Published var autotune: Autotune?
  10. @Published var determinationsFromPersistence: [OrefDetermination] = []
  11. let context = CoreDataStack.shared.newTaskContext()
  12. let viewContext = CoreDataStack.shared.persistentContainer.viewContext
  13. let timeValues = stride(from: 0.0, to: 1.days.timeInterval, by: 30.minutes.timeInterval).map { $0 }
  14. var rateValues: [Decimal] {
  15. stride(from: 9, to: 540.01, by: 1.0).map { Decimal($0) }
  16. }
  17. var canAdd: Bool {
  18. guard let lastItem = items.last else { return true }
  19. return lastItem.timeIndex < timeValues.count - 1
  20. }
  21. private(set) var units: GlucoseUnits = .mgdL
  22. override func subscribe() {
  23. units = settingsManager.settings.units
  24. let profile = provider.profile
  25. items = profile.sensitivities.map { value in
  26. let timeIndex = timeValues.firstIndex(of: Double(value.offset * 60)) ?? 0
  27. let rateIndex = rateValues.firstIndex(of: value.sensitivity) ?? 0
  28. return Item(rateIndex: rateIndex, timeIndex: timeIndex)
  29. }
  30. autotune = provider.autotune
  31. if let newISF = provider.autosense.newisf {
  32. switch units {
  33. case .mgdL:
  34. autosensISF = newISF
  35. case .mmolL:
  36. autosensISF = newISF * GlucoseUnits.exchangeRate
  37. }
  38. }
  39. autosensRatio = provider.autosense.ratio
  40. setupDeterminationsArray()
  41. }
  42. func add() {
  43. var time = 0
  44. var rate = 0
  45. if let last = items.last {
  46. time = last.timeIndex + 1
  47. rate = last.rateIndex
  48. }
  49. let newItem = Item(rateIndex: rate, timeIndex: time)
  50. items.append(newItem)
  51. }
  52. func save() {
  53. let sensitivities = items.map { item -> InsulinSensitivityEntry in
  54. let fotmatter = DateFormatter()
  55. fotmatter.timeZone = TimeZone(secondsFromGMT: 0)
  56. fotmatter.dateFormat = "HH:mm:ss"
  57. let date = Date(timeIntervalSince1970: self.timeValues[item.timeIndex])
  58. let minutes = Int(date.timeIntervalSince1970 / 60)
  59. let rate = self.rateValues[item.rateIndex]
  60. return InsulinSensitivityEntry(sensitivity: rate, offset: minutes, start: fotmatter.string(from: date))
  61. }
  62. let profile = InsulinSensitivities(
  63. units: units,
  64. userPrefferedUnits: settingsManager.settings.units,
  65. sensitivities: sensitivities
  66. )
  67. provider.saveProfile(profile)
  68. }
  69. func validate() {
  70. DispatchQueue.main.async {
  71. let uniq = Array(Set(self.items))
  72. let sorted = uniq.sorted { $0.timeIndex < $1.timeIndex }
  73. sorted.first?.timeIndex = 0
  74. self.items = sorted
  75. if self.items.isEmpty {
  76. self.units = self.settingsManager.settings.units
  77. }
  78. }
  79. }
  80. private func setupDeterminationsArray() {
  81. Task {
  82. let ids = await determinationStorage.fetchLastDeterminationObjectID(
  83. predicate: NSPredicate.enactedDetermination
  84. )
  85. await updateDeterminationsArray(with: ids)
  86. }
  87. }
  88. @MainActor private func updateDeterminationsArray(with IDs: [NSManagedObjectID]) {
  89. do {
  90. let objects = try IDs.compactMap { id in
  91. try viewContext.existingObject(with: id) as? OrefDetermination
  92. }
  93. determinationsFromPersistence = objects
  94. } catch {
  95. debugPrint(
  96. "Home State: \(#function) \(DebuggingIdentifiers.failed) error while updating the glucose array: \(error.localizedDescription)"
  97. )
  98. }
  99. }
  100. }
  101. }
  102. extension ISFEditor.StateModel: SettingsObserver {
  103. func settingsDidChange(_: FreeAPSSettings) {
  104. units = settingsManager.settings.units
  105. }
  106. }