OverrideProfilesStateModel.swift 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  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.persistentContainer.newBackgroundContext()
  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. do {
  89. try CoreDataStack.shared.saveContext()
  90. } catch {
  91. print(error.localizedDescription)
  92. }
  93. }
  94. }
  95. func savePreset() {
  96. coredataContext.perform { [self] in
  97. let saveOverride = OverridePresets(context: self.coredataContext)
  98. saveOverride.duration = self.durationProfile as NSDecimalNumber
  99. saveOverride.indefinite = self._indefinite
  100. saveOverride.percentage = self.percentageProfiles
  101. saveOverride.smbIsOff = self.smbIsOff
  102. saveOverride.name = self.profileName
  103. id = UUID().uuidString
  104. self.isPreset.toggle()
  105. saveOverride.id = id
  106. saveOverride.date = Date()
  107. if override_target {
  108. saveOverride.target = (
  109. units == .mmolL
  110. ? target.asMgdL
  111. : target
  112. ) as NSDecimalNumber
  113. } else { saveOverride.target = 0 }
  114. if advancedSettings {
  115. saveOverride.advancedSettings = true
  116. if !isfAndCr {
  117. saveOverride.isfAndCr = false
  118. saveOverride.isf = isf
  119. saveOverride.cr = cr
  120. } else { saveOverride.isfAndCr = true }
  121. if smbIsAlwaysOff {
  122. saveOverride.smbIsAlwaysOff = true
  123. saveOverride.start = start as NSDecimalNumber
  124. saveOverride.end = end as NSDecimalNumber
  125. } else { smbIsAlwaysOff = false }
  126. saveOverride.smbMinutes = smbMinutes as NSDecimalNumber
  127. saveOverride.uamMinutes = uamMinutes as NSDecimalNumber
  128. }
  129. do {
  130. try CoreDataStack.shared.saveContext()
  131. } catch {
  132. print(error.localizedDescription)
  133. }
  134. }
  135. }
  136. func selectProfile(id_: String) {
  137. guard id_ != "" else { return }
  138. coredataContext.performAndWait {
  139. var profileArray = [OverridePresets]()
  140. let requestProfiles = OverridePresets.fetchRequest() as NSFetchRequest<OverridePresets>
  141. try? profileArray = coredataContext.fetch(requestProfiles)
  142. guard let profile = profileArray.filter({ $0.id == id_ }).first else { return }
  143. let saveOverride = Override(context: self.coredataContext)
  144. saveOverride.duration = (profile.duration ?? 0) as NSDecimalNumber
  145. saveOverride.indefinite = profile.indefinite
  146. saveOverride.percentage = profile.percentage
  147. saveOverride.enabled = true
  148. saveOverride.smbIsOff = profile.smbIsOff
  149. saveOverride.isPreset = true
  150. saveOverride.date = Date()
  151. saveOverride.target = profile.target
  152. saveOverride.id = id_
  153. if profile.advancedSettings {
  154. saveOverride.advancedSettings = true
  155. if !isfAndCr {
  156. saveOverride.isfAndCr = false
  157. saveOverride.isf = profile.isf
  158. saveOverride.cr = profile.cr
  159. } else { saveOverride.isfAndCr = true }
  160. if profile.smbIsAlwaysOff {
  161. saveOverride.smbIsAlwaysOff = true
  162. saveOverride.start = profile.start
  163. saveOverride.end = profile.end
  164. } else { saveOverride.smbIsAlwaysOff = false }
  165. saveOverride.smbMinutes = (profile.smbMinutes ?? 0) as NSDecimalNumber
  166. saveOverride.uamMinutes = (profile.uamMinutes ?? 0) as NSDecimalNumber
  167. }
  168. do {
  169. try CoreDataStack.shared.saveContext()
  170. } catch {
  171. print(error.localizedDescription)
  172. }
  173. }
  174. }
  175. func savedSettings() {
  176. coredataContext.performAndWait {
  177. var overrideArray = [Override]()
  178. let requestEnabled = Override.fetchRequest() as NSFetchRequest<Override>
  179. let sortIsEnabled = NSSortDescriptor(key: "date", ascending: false)
  180. requestEnabled.sortDescriptors = [sortIsEnabled]
  181. // requestEnabled.fetchLimit = 1
  182. try? overrideArray = coredataContext.fetch(requestEnabled)
  183. isEnabled = overrideArray.first?.enabled ?? false
  184. percentageProfiles = overrideArray.first?.percentage ?? 100
  185. _indefinite = overrideArray.first?.indefinite ?? true
  186. durationProfile = (overrideArray.first?.duration ?? 0) as Decimal
  187. smbIsOff = overrideArray.first?.smbIsOff ?? false
  188. advancedSettings = overrideArray.first?.advancedSettings ?? false
  189. isfAndCr = overrideArray.first?.isfAndCr ?? true
  190. smbIsAlwaysOff = overrideArray.first?.smbIsAlwaysOff ?? false
  191. if advancedSettings {
  192. if !isfAndCr {
  193. isf = overrideArray.first?.isf ?? false
  194. cr = overrideArray.first?.cr ?? false
  195. }
  196. if smbIsAlwaysOff {
  197. start = (overrideArray.first?.start ?? 0) as Decimal
  198. end = (overrideArray.first?.end ?? 0) as Decimal
  199. }
  200. if (overrideArray[0].smbMinutes as Decimal?) != nil {
  201. smbMinutes = (overrideArray.first?.smbMinutes ?? 30) as Decimal
  202. }
  203. if (overrideArray[0].uamMinutes as Decimal?) != nil {
  204. uamMinutes = (overrideArray.first?.uamMinutes ?? 30) as Decimal
  205. }
  206. }
  207. let overrideTarget = (overrideArray.first?.target ?? 0) as Decimal
  208. var newDuration = Double(durationProfile)
  209. if isEnabled {
  210. let duration = overrideArray.first?.duration ?? 0
  211. let addedMinutes = Int(duration as Decimal)
  212. let date = overrideArray.first?.date ?? Date()
  213. if date.addingTimeInterval(addedMinutes.minutes.timeInterval) < Date(), !_indefinite {
  214. isEnabled = false
  215. }
  216. newDuration = Date().distance(to: date.addingTimeInterval(addedMinutes.minutes.timeInterval)).minutes
  217. if overrideTarget != 0 {
  218. override_target = true
  219. target = units == .mmolL ? overrideTarget.asMmolL : overrideTarget
  220. }
  221. }
  222. if newDuration < 0 { newDuration = 0 } else { durationProfile = Decimal(newDuration) }
  223. if !isEnabled {
  224. _indefinite = true
  225. percentageProfiles = 100
  226. durationProfile = 0
  227. target = 0
  228. override_target = false
  229. smbIsOff = false
  230. advancedSettings = false
  231. smbMinutes = defaultSmbMinutes
  232. uamMinutes = defaultUamMinutes
  233. }
  234. }
  235. }
  236. func cancelProfile() {
  237. _indefinite = true
  238. isEnabled = false
  239. percentageProfiles = 100
  240. durationProfile = 0
  241. target = 0
  242. override_target = false
  243. smbIsOff = false
  244. advancedSettings = false
  245. coredataContext.perform { [self] in
  246. let profiles = Override(context: self.coredataContext)
  247. profiles.enabled = false
  248. profiles.date = Date()
  249. do {
  250. try CoreDataStack.shared.saveContext()
  251. } catch {
  252. print(error.localizedDescription)
  253. }
  254. }
  255. smbMinutes = defaultSmbMinutes
  256. uamMinutes = defaultUamMinutes
  257. }
  258. // MARK: TEMP TARGET
  259. func enact() {
  260. guard durationTT > 0 else {
  261. return
  262. }
  263. var lowTarget = low
  264. if viewPercantage {
  265. lowTarget = Decimal(round(Double(computeTarget())))
  266. coredataContext.performAndWait {
  267. let saveToCoreData = TempTargets(context: self.coredataContext)
  268. saveToCoreData.id = UUID().uuidString
  269. saveToCoreData.active = true
  270. saveToCoreData.hbt = hbt
  271. saveToCoreData.date = Date()
  272. saveToCoreData.duration = durationTT as NSDecimalNumber
  273. saveToCoreData.startDate = Date()
  274. try? self.coredataContext.save()
  275. }
  276. didSaveSettings = true
  277. } else {
  278. coredataContext.performAndWait {
  279. let saveToCoreData = TempTargets(context: coredataContext)
  280. saveToCoreData.active = false
  281. saveToCoreData.date = Date()
  282. do {
  283. try CoreDataStack.shared.saveContext()
  284. } catch {
  285. print(error.localizedDescription)
  286. }
  287. }
  288. }
  289. var highTarget = lowTarget
  290. if units == .mmolL, !viewPercantage {
  291. lowTarget = Decimal(round(Double(lowTarget.asMgdL)))
  292. highTarget = lowTarget
  293. }
  294. let entry = TempTarget(
  295. name: TempTarget.custom,
  296. createdAt: date,
  297. targetTop: highTarget,
  298. targetBottom: lowTarget,
  299. duration: durationTT,
  300. enteredBy: TempTarget.manual,
  301. reason: TempTarget.custom
  302. )
  303. storage.storeTempTargets([entry])
  304. showModal(for: nil)
  305. }
  306. func cancel() {
  307. storage.storeTempTargets([TempTarget.cancel(at: Date())])
  308. showModal(for: nil)
  309. coredataContext.performAndWait {
  310. let saveToCoreData = TempTargets(context: self.coredataContext)
  311. saveToCoreData.active = false
  312. saveToCoreData.date = Date()
  313. do {
  314. try CoreDataStack.shared.saveContext()
  315. } catch {
  316. print(error.localizedDescription)
  317. }
  318. let setHBT = TempTargetsSlider(context: self.coredataContext)
  319. setHBT.enabled = false
  320. setHBT.date = Date()
  321. do {
  322. try CoreDataStack.shared.saveContext()
  323. } catch {
  324. print(error.localizedDescription)
  325. }
  326. }
  327. }
  328. func save() {
  329. guard durationTT > 0 else {
  330. return
  331. }
  332. var lowTarget = low
  333. if viewPercantage {
  334. lowTarget = Decimal(round(Double(computeTarget())))
  335. didSaveSettings = true
  336. }
  337. var highTarget = lowTarget
  338. if units == .mmolL, !viewPercantage {
  339. lowTarget = Decimal(round(Double(lowTarget.asMgdL)))
  340. highTarget = lowTarget
  341. }
  342. let entry = TempTarget(
  343. name: newPresetName.isEmpty ? TempTarget.custom : newPresetName,
  344. createdAt: Date(),
  345. targetTop: highTarget,
  346. targetBottom: lowTarget,
  347. duration: durationTT,
  348. enteredBy: TempTarget.manual,
  349. reason: newPresetName.isEmpty ? TempTarget.custom : newPresetName
  350. )
  351. presetsTT.append(entry)
  352. storage.storePresets(presetsTT)
  353. if viewPercantage {
  354. let id = entry.id
  355. coredataContext.performAndWait {
  356. let saveToCoreData = TempTargetsSlider(context: self.coredataContext)
  357. saveToCoreData.id = id
  358. saveToCoreData.isPreset = true
  359. saveToCoreData.enabled = true
  360. saveToCoreData.hbt = hbt
  361. saveToCoreData.date = Date()
  362. saveToCoreData.duration = durationTT as NSDecimalNumber
  363. do {
  364. try CoreDataStack.shared.saveContext()
  365. } catch {
  366. print(error.localizedDescription)
  367. }
  368. }
  369. }
  370. }
  371. func enactPreset(id: String) {
  372. if var preset = presetsTT.first(where: { $0.id == id }) {
  373. preset.createdAt = Date()
  374. storage.storeTempTargets([preset])
  375. showModal(for: nil)
  376. coredataContext.performAndWait {
  377. var tempTargetsArray = [TempTargetsSlider]()
  378. let requestTempTargets = TempTargetsSlider.fetchRequest() as NSFetchRequest<TempTargetsSlider>
  379. let sortTT = NSSortDescriptor(key: "date", ascending: false)
  380. requestTempTargets.sortDescriptors = [sortTT]
  381. try? tempTargetsArray = coredataContext.fetch(requestTempTargets)
  382. let whichID = tempTargetsArray.first(where: { $0.id == id })
  383. if whichID != nil {
  384. let saveToCoreData = TempTargets(context: self.coredataContext)
  385. saveToCoreData.active = true
  386. saveToCoreData.date = Date()
  387. saveToCoreData.hbt = whichID?.hbt ?? 160
  388. // saveToCoreData.id = id
  389. saveToCoreData.startDate = Date()
  390. saveToCoreData.duration = whichID?.duration ?? 0
  391. do {
  392. try CoreDataStack.shared.saveContext()
  393. } catch {
  394. print(error.localizedDescription)
  395. }
  396. } else {
  397. let saveToCoreData = TempTargets(context: self.coredataContext)
  398. saveToCoreData.active = false
  399. saveToCoreData.date = Date()
  400. do {
  401. try CoreDataStack.shared.saveContext()
  402. } catch {
  403. print(error.localizedDescription)
  404. }
  405. }
  406. }
  407. }
  408. }
  409. func removePreset(id: String) {
  410. presetsTT = presetsTT.filter { $0.id != id }
  411. storage.storePresets(presetsTT)
  412. }
  413. func computeTarget() -> Decimal {
  414. var ratio = Decimal(percentageTT / 100)
  415. let c = Decimal(hbt - 100)
  416. var target = (c / ratio) - c + 100
  417. if c * (c + target - 100) <= 0 {
  418. ratio = maxValue
  419. target = (c / ratio) - c + 100
  420. }
  421. return Decimal(Double(target))
  422. }
  423. }
  424. }