OverrideProfilesStateModel.swift 18 KB

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