OverrideProfilesStateModel.swift 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. import CoreData
  2. import SwiftUI
  3. extension OverrideProfilesConfig {
  4. final class StateModel: BaseStateModel<Provider> {
  5. @Injected() var storage: TempTargetsStorage!
  6. @Injected() var apsManager: APSManager!
  7. @Published var percentageProfiles: Double = 100
  8. @Published var isEnabled = false
  9. @Published var _indefinite = true
  10. @Published var durationProfile: Decimal = 0
  11. @Published var target: Decimal = 0
  12. @Published var override_target: Bool = false
  13. @Published var smbIsOff: Bool = false
  14. @Published var id: String = ""
  15. @Published var profileName: String = ""
  16. @Published var isPreset: Bool = false
  17. @Published var presetsProfiles: [OverridePresets] = []
  18. @Published var selection: OverridePresets?
  19. @Published var advancedSettings: Bool = false
  20. @Published var isfAndCr: Bool = true
  21. @Published var isf: Bool = true
  22. @Published var cr: Bool = true
  23. @Published var smbIsAlwaysOff: Bool = false
  24. @Published var start: Decimal = 0
  25. @Published var end: Decimal = 23
  26. @Published var smbMinutes: Decimal = 0
  27. @Published var uamMinutes: Decimal = 0
  28. @Published var defaultSmbMinutes: Decimal = 0
  29. @Published var defaultUamMinutes: Decimal = 0
  30. @Published var selectedTab: Tab = .profiles
  31. var units: GlucoseUnits = .mmolL
  32. // temp target stuff
  33. @Published var low: Decimal = 0
  34. // @Published var target: Decimal = 0
  35. @Published var high: Decimal = 0
  36. @Published var durationTT: Decimal = 0
  37. @Published var date = Date()
  38. @Published var newPresetName = ""
  39. @Published var presetsTT: [TempTarget] = []
  40. @Published var percentageTT = 100.0
  41. @Published var maxValue: Decimal = 1.2
  42. @Published var viewPercantage = false
  43. @Published var hbt: Double = 160
  44. @Published var didSaveSettings: Bool = false
  45. override func subscribe() {
  46. units = settingsManager.settings.units
  47. defaultSmbMinutes = settingsManager.preferences.maxSMBBasalMinutes
  48. defaultUamMinutes = settingsManager.preferences.maxUAMSMBBasalMinutes
  49. presetsProfiles = [OverridePresets(context: coredataContext)]
  50. presetsTT = storage.presets()
  51. maxValue = settingsManager.preferences.autosensMax
  52. }
  53. let coredataContext = CoreDataStack.shared.backgroundContext
  54. func saveSettings() {
  55. coredataContext.perform { [self] in
  56. let saveOverride = Override(context: self.coredataContext)
  57. saveOverride.duration = self.durationProfile as NSDecimalNumber
  58. saveOverride.indefinite = self._indefinite
  59. saveOverride.percentage = self.percentageProfiles
  60. saveOverride.enabled = true
  61. saveOverride.smbIsOff = self.smbIsOff
  62. if self.isPreset {
  63. saveOverride.isPreset = true
  64. saveOverride.id = id
  65. } else { saveOverride.isPreset = false }
  66. saveOverride.date = Date()
  67. if override_target {
  68. if units == .mmolL {
  69. target = target.asMgdL
  70. }
  71. saveOverride.target = target as NSDecimalNumber
  72. } else { saveOverride.target = 0 }
  73. if advancedSettings {
  74. saveOverride.advancedSettings = true
  75. if !isfAndCr {
  76. saveOverride.isfAndCr = false
  77. saveOverride.isf = isf
  78. saveOverride.cr = cr
  79. } else { saveOverride.isfAndCr = true }
  80. if smbIsAlwaysOff {
  81. saveOverride.smbIsAlwaysOff = true
  82. saveOverride.start = start as NSDecimalNumber
  83. saveOverride.end = end as NSDecimalNumber
  84. } else { saveOverride.smbIsAlwaysOff = false }
  85. saveOverride.smbMinutes = smbMinutes as NSDecimalNumber
  86. saveOverride.uamMinutes = uamMinutes as NSDecimalNumber
  87. }
  88. if self.coredataContext.hasChanges {
  89. try? self.coredataContext.save()
  90. }
  91. }
  92. }
  93. func savePreset() {
  94. coredataContext.perform { [self] in
  95. let saveOverride = OverridePresets(context: self.coredataContext)
  96. saveOverride.duration = self.durationProfile as NSDecimalNumber
  97. saveOverride.indefinite = self._indefinite
  98. saveOverride.percentage = self.percentageProfiles
  99. saveOverride.smbIsOff = self.smbIsOff
  100. saveOverride.name = self.profileName
  101. id = UUID().uuidString
  102. self.isPreset.toggle()
  103. saveOverride.id = id
  104. saveOverride.date = Date()
  105. if override_target {
  106. saveOverride.target = (
  107. units == .mmolL
  108. ? target.asMgdL
  109. : target
  110. ) as NSDecimalNumber
  111. } else { saveOverride.target = 0 }
  112. if advancedSettings {
  113. saveOverride.advancedSettings = true
  114. if !isfAndCr {
  115. saveOverride.isfAndCr = false
  116. saveOverride.isf = isf
  117. saveOverride.cr = cr
  118. } else { saveOverride.isfAndCr = true }
  119. if smbIsAlwaysOff {
  120. saveOverride.smbIsAlwaysOff = true
  121. saveOverride.start = start as NSDecimalNumber
  122. saveOverride.end = end as NSDecimalNumber
  123. } else { smbIsAlwaysOff = false }
  124. saveOverride.smbMinutes = smbMinutes as NSDecimalNumber
  125. saveOverride.uamMinutes = uamMinutes as NSDecimalNumber
  126. }
  127. if self.coredataContext.hasChanges {
  128. try? self.coredataContext.save()
  129. }
  130. }
  131. }
  132. func selectProfile(id_: String) {
  133. guard id_ != "" else { return }
  134. coredataContext.performAndWait {
  135. var profileArray = [OverridePresets]()
  136. let requestProfiles = OverridePresets.fetchRequest() as NSFetchRequest<OverridePresets>
  137. try? profileArray = coredataContext.fetch(requestProfiles)
  138. guard let profile = profileArray.filter({ $0.id == id_ }).first else { return }
  139. let saveOverride = Override(context: self.coredataContext)
  140. saveOverride.duration = (profile.duration ?? 0) as NSDecimalNumber
  141. saveOverride.indefinite = profile.indefinite
  142. saveOverride.percentage = profile.percentage
  143. saveOverride.enabled = true
  144. saveOverride.smbIsOff = profile.smbIsOff
  145. saveOverride.isPreset = true
  146. saveOverride.date = Date()
  147. saveOverride.target = profile.target
  148. saveOverride.id = id_
  149. if profile.advancedSettings {
  150. saveOverride.advancedSettings = true
  151. if !isfAndCr {
  152. saveOverride.isfAndCr = false
  153. saveOverride.isf = profile.isf
  154. saveOverride.cr = profile.cr
  155. } else { saveOverride.isfAndCr = true }
  156. if profile.smbIsAlwaysOff {
  157. saveOverride.smbIsAlwaysOff = true
  158. saveOverride.start = profile.start
  159. saveOverride.end = profile.end
  160. } else { saveOverride.smbIsAlwaysOff = false }
  161. saveOverride.smbMinutes = (profile.smbMinutes ?? 0) as NSDecimalNumber
  162. saveOverride.uamMinutes = (profile.uamMinutes ?? 0) as NSDecimalNumber
  163. }
  164. if self.coredataContext.hasChanges {
  165. try? self.coredataContext.save()
  166. }
  167. }
  168. }
  169. func savedSettings() {
  170. coredataContext.performAndWait {
  171. var overrideArray = [Override]()
  172. let requestEnabled = Override.fetchRequest() as NSFetchRequest<Override>
  173. let sortIsEnabled = NSSortDescriptor(key: "date", ascending: false)
  174. requestEnabled.sortDescriptors = [sortIsEnabled]
  175. // requestEnabled.fetchLimit = 1
  176. try? overrideArray = coredataContext.fetch(requestEnabled)
  177. isEnabled = overrideArray.first?.enabled ?? false
  178. percentageProfiles = overrideArray.first?.percentage ?? 100
  179. _indefinite = overrideArray.first?.indefinite ?? true
  180. durationProfile = (overrideArray.first?.duration ?? 0) as Decimal
  181. smbIsOff = overrideArray.first?.smbIsOff ?? false
  182. advancedSettings = overrideArray.first?.advancedSettings ?? false
  183. isfAndCr = overrideArray.first?.isfAndCr ?? true
  184. smbIsAlwaysOff = overrideArray.first?.smbIsAlwaysOff ?? false
  185. if advancedSettings {
  186. if !isfAndCr {
  187. isf = overrideArray.first?.isf ?? false
  188. cr = overrideArray.first?.cr ?? false
  189. }
  190. if smbIsAlwaysOff {
  191. start = (overrideArray.first?.start ?? 0) as Decimal
  192. end = (overrideArray.first?.end ?? 0) as Decimal
  193. }
  194. if (overrideArray[0].smbMinutes as Decimal?) != nil {
  195. smbMinutes = (overrideArray.first?.smbMinutes ?? 30) as Decimal
  196. }
  197. if (overrideArray[0].uamMinutes as Decimal?) != nil {
  198. uamMinutes = (overrideArray.first?.uamMinutes ?? 30) as Decimal
  199. }
  200. }
  201. let overrideTarget = (overrideArray.first?.target ?? 0) as Decimal
  202. var newDuration = Double(durationProfile)
  203. if isEnabled {
  204. let duration = overrideArray.first?.duration ?? 0
  205. let addedMinutes = Int(duration as Decimal)
  206. let date = overrideArray.first?.date ?? Date()
  207. if date.addingTimeInterval(addedMinutes.minutes.timeInterval) < Date(), !_indefinite {
  208. isEnabled = false
  209. }
  210. newDuration = Date().distance(to: date.addingTimeInterval(addedMinutes.minutes.timeInterval)).minutes
  211. if overrideTarget != 0 {
  212. override_target = true
  213. target = units == .mmolL ? overrideTarget.asMmolL : overrideTarget
  214. }
  215. }
  216. if newDuration < 0 { newDuration = 0 } else { durationProfile = Decimal(newDuration) }
  217. if !isEnabled {
  218. _indefinite = true
  219. percentageProfiles = 100
  220. durationProfile = 0
  221. target = 0
  222. override_target = false
  223. smbIsOff = false
  224. advancedSettings = false
  225. smbMinutes = defaultSmbMinutes
  226. uamMinutes = defaultUamMinutes
  227. }
  228. }
  229. }
  230. func cancelProfile() {
  231. _indefinite = true
  232. isEnabled = false
  233. percentageProfiles = 100
  234. durationProfile = 0
  235. target = 0
  236. override_target = false
  237. smbIsOff = false
  238. advancedSettings = false
  239. coredataContext.perform { [self] in
  240. let profiles = Override(context: self.coredataContext)
  241. profiles.enabled = false
  242. profiles.date = Date()
  243. if self.coredataContext.hasChanges {
  244. try? self.coredataContext.save()
  245. }
  246. }
  247. smbMinutes = defaultSmbMinutes
  248. uamMinutes = defaultUamMinutes
  249. }
  250. // MARK: TEMP TARGET
  251. func enact() {
  252. guard durationTT > 0 else {
  253. return
  254. }
  255. var lowTarget = low
  256. if viewPercantage {
  257. lowTarget = Decimal(round(Double(computeTarget())))
  258. coredataContext.performAndWait {
  259. let saveToCoreData = TempTargets(context: self.coredataContext)
  260. saveToCoreData.id = UUID().uuidString
  261. saveToCoreData.active = true
  262. saveToCoreData.hbt = hbt
  263. saveToCoreData.date = Date()
  264. saveToCoreData.duration = durationTT as NSDecimalNumber
  265. saveToCoreData.startDate = Date()
  266. try? self.coredataContext.save()
  267. }
  268. didSaveSettings = true
  269. } else {
  270. coredataContext.performAndWait {
  271. let saveToCoreData = TempTargets(context: coredataContext)
  272. saveToCoreData.active = false
  273. saveToCoreData.date = Date()
  274. if self.coredataContext.hasChanges {
  275. try? coredataContext.save()
  276. }
  277. }
  278. }
  279. var highTarget = lowTarget
  280. if units == .mmolL, !viewPercantage {
  281. lowTarget = Decimal(round(Double(lowTarget.asMgdL)))
  282. highTarget = lowTarget
  283. }
  284. let entry = TempTarget(
  285. name: TempTarget.custom,
  286. createdAt: date,
  287. targetTop: highTarget,
  288. targetBottom: lowTarget,
  289. duration: durationTT,
  290. enteredBy: TempTarget.manual,
  291. reason: TempTarget.custom
  292. )
  293. storage.storeTempTargets([entry])
  294. showModal(for: nil)
  295. }
  296. func cancel() {
  297. storage.storeTempTargets([TempTarget.cancel(at: Date())])
  298. showModal(for: nil)
  299. coredataContext.performAndWait {
  300. let saveToCoreData = TempTargets(context: self.coredataContext)
  301. saveToCoreData.active = false
  302. saveToCoreData.date = Date()
  303. if self.coredataContext.hasChanges {
  304. try? self.coredataContext.save()
  305. }
  306. let setHBT = TempTargetsSlider(context: self.coredataContext)
  307. setHBT.enabled = false
  308. setHBT.date = Date()
  309. if self.coredataContext.hasChanges {
  310. try? self.coredataContext.save()
  311. }
  312. }
  313. }
  314. func save() {
  315. guard durationTT > 0 else {
  316. return
  317. }
  318. var lowTarget = low
  319. if viewPercantage {
  320. lowTarget = Decimal(round(Double(computeTarget())))
  321. didSaveSettings = true
  322. }
  323. var highTarget = lowTarget
  324. if units == .mmolL, !viewPercantage {
  325. lowTarget = Decimal(round(Double(lowTarget.asMgdL)))
  326. highTarget = lowTarget
  327. }
  328. let entry = TempTarget(
  329. name: newPresetName.isEmpty ? TempTarget.custom : newPresetName,
  330. createdAt: Date(),
  331. targetTop: highTarget,
  332. targetBottom: lowTarget,
  333. duration: durationTT,
  334. enteredBy: TempTarget.manual,
  335. reason: newPresetName.isEmpty ? TempTarget.custom : newPresetName
  336. )
  337. presetsTT.append(entry)
  338. storage.storePresets(presetsTT)
  339. if viewPercantage {
  340. let id = entry.id
  341. coredataContext.performAndWait {
  342. let saveToCoreData = TempTargetsSlider(context: self.coredataContext)
  343. saveToCoreData.id = id
  344. saveToCoreData.isPreset = true
  345. saveToCoreData.enabled = true
  346. saveToCoreData.hbt = hbt
  347. saveToCoreData.date = Date()
  348. saveToCoreData.duration = durationTT as NSDecimalNumber
  349. if self.coredataContext.hasChanges {
  350. try? self.coredataContext.save()
  351. }
  352. }
  353. }
  354. }
  355. func enactPreset(id: String) {
  356. if var preset = presetsTT.first(where: { $0.id == id }) {
  357. preset.createdAt = Date()
  358. storage.storeTempTargets([preset])
  359. showModal(for: nil)
  360. coredataContext.performAndWait {
  361. var tempTargetsArray = [TempTargetsSlider]()
  362. let requestTempTargets = TempTargetsSlider.fetchRequest() as NSFetchRequest<TempTargetsSlider>
  363. let sortTT = NSSortDescriptor(key: "date", ascending: false)
  364. requestTempTargets.sortDescriptors = [sortTT]
  365. try? tempTargetsArray = coredataContext.fetch(requestTempTargets)
  366. let whichID = tempTargetsArray.first(where: { $0.id == id })
  367. if whichID != nil {
  368. let saveToCoreData = TempTargets(context: self.coredataContext)
  369. saveToCoreData.active = true
  370. saveToCoreData.date = Date()
  371. saveToCoreData.hbt = whichID?.hbt ?? 160
  372. // saveToCoreData.id = id
  373. saveToCoreData.startDate = Date()
  374. saveToCoreData.duration = whichID?.duration ?? 0
  375. if self.coredataContext.hasChanges {
  376. try? self.coredataContext.save()
  377. }
  378. } else {
  379. let saveToCoreData = TempTargets(context: self.coredataContext)
  380. saveToCoreData.active = false
  381. saveToCoreData.date = Date()
  382. if self.coredataContext.hasChanges {
  383. try? self.coredataContext.save()
  384. }
  385. }
  386. }
  387. }
  388. }
  389. func removePreset(id: String) {
  390. presetsTT = presetsTT.filter { $0.id != id }
  391. storage.storePresets(presetsTT)
  392. }
  393. func computeTarget() -> Decimal {
  394. var ratio = Decimal(percentageTT / 100)
  395. let c = Decimal(hbt - 100)
  396. var target = (c / ratio) - c + 100
  397. if c * (c + target - 100) <= 0 {
  398. ratio = maxValue
  399. target = (c / ratio) - c + 100
  400. }
  401. return Decimal(Double(target))
  402. }
  403. }
  404. }