-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Expand file tree
/
Copy pathTargetsEditorStateModel.swift
More file actions
139 lines (116 loc) · 5.29 KB
/
TargetsEditorStateModel.swift
File metadata and controls
139 lines (116 loc) · 5.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import SwiftUI
extension TargetsEditor {
final class StateModel: BaseStateModel<Provider> {
@Injected() private var nightscout: NightscoutManager!
@Injected() private var tidepoolManager: TidepoolManager!
@Injected() private var broadcaster: Broadcaster!
@Published var items: [Item] = []
@Published var initialItems: [Item] = []
@Published var therapyItems: [TherapySettingItem] = []
@Published var shouldDisplaySaving: Bool = false
let timeValues = stride(from: 0.0, to: 1.days.timeInterval, by: 30.minutes.timeInterval).map { $0 }
var rateValues: [Decimal] {
let settingsProvider = PickerSettingsProvider.shared
let glucoseSetting = PickerSetting(value: 110, step: 1, min: 72, max: 180, type: .glucose)
return settingsProvider.generatePickerValues(from: glucoseSetting, units: units)
}
var canAdd: Bool {
guard let lastItem = items.last else { return true }
return lastItem.timeIndex < timeValues.count - 1
}
var hasChanges: Bool {
initialItems != items
}
private(set) var units: GlucoseUnits = .mgdL
// Convert items to TherapySettingItem format
func getTherapyItems() -> [TherapySettingItem] {
items.map { item in
TherapySettingItem(
time: timeValues[item.timeIndex],
value: rateValues[item.lowIndex]
)
}
}
// Update items from TherapySettingItem format
func updateFromTherapyItems(_ therapyItems: [TherapySettingItem]) {
items = therapyItems.map { therapyItem in
let timeIndex = timeValues.firstIndex(where: { abs($0 - therapyItem.time) < 1 }) ?? 0
let lowIndex = rateValues.firstIndex(of: therapyItem.value) ?? 0
return Item(lowIndex: lowIndex, highIndex: lowIndex, timeIndex: timeIndex)
}
}
override func subscribe() {
units = settingsManager.settings.units
let profile = provider.profile
items = profile.targets.map { value in
let timeIndex = timeValues.firstIndex(of: Double(value.offset * 60)) ?? 0
let lowIndex = rateValues.firstIndex(of: value.low) ?? 0
let highIndex = rateValues.firstIndex(of: value.high) ?? 0
return Item(lowIndex: lowIndex, highIndex: highIndex, timeIndex: timeIndex)
}
initialItems = items.map { Item(lowIndex: $0.lowIndex, highIndex: $0.highIndex, timeIndex: $0.timeIndex) }
}
func add() {
var time = 0
var low = 0
var high = 0
if let last = items.last {
time = last.timeIndex + 1
low = last.lowIndex
high = low
}
let newItem = Item(lowIndex: low, highIndex: high, timeIndex: time)
items.append(newItem)
}
func save() {
guard hasChanges else { return }
shouldDisplaySaving.toggle()
let targets = items.map { item -> BGTargetEntry in
let formatter = DateFormatter()
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "HH:mm:ss"
let date = Date(timeIntervalSince1970: self.timeValues[item.timeIndex])
let minutes = Int(date.timeIntervalSince1970 / 60)
let low = self.rateValues[item.lowIndex]
let high = low
return BGTargetEntry(low: low, high: high, start: formatter.string(from: date), offset: minutes)
}
let profile = BGTargets(units: .mgdL, userPreferredUnits: .mgdL, targets: targets)
provider.saveProfile(profile)
initialItems = items.map { Item(lowIndex: $0.lowIndex, highIndex: $0.highIndex, timeIndex: $0.timeIndex) }
DispatchQueue.main.async {
self.broadcaster.notify(BGTargetsObserver.self, on: .main) {
$0.bgTargetsDidChange(profile)
}
}
Task.detached(priority: .low) {
do {
debug(.nightscout, "Attempting to upload targets to Nightscout")
try await self.nightscout.uploadProfiles()
} catch {
debug(
.default,
"\(DebuggingIdentifiers.failed) failed to upload targets to Nightscout: \(error)"
)
}
}
Task.detached(priority: .low) {
await self.tidepoolManager.uploadSettings()
}
}
func validate() {
DispatchQueue.main.async {
let uniq = Array(Set(self.items))
let sorted = uniq.sorted { $0.timeIndex < $1.timeIndex }
.map { item -> Item in
Item(lowIndex: item.lowIndex, highIndex: item.highIndex, timeIndex: item.timeIndex)
}
sorted.first?.timeIndex = 0
self.items = sorted
if self.items.isEmpty {
self.units = self.settingsManager.settings.units
}
}
}
}
}