-
Notifications
You must be signed in to change notification settings - Fork 3
/
DataStore.swift
107 lines (85 loc) · 2.74 KB
/
DataStore.swift
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
//
// DataStore.swift
// SmogWatch WatchKit Extension
//
// Created by Kuba Suder on 22.12.2018.
// Copyright © 2018 Kuba Suder. Licensed under WTFPL license.
//
import Foundation
private let savedPointsKey = "SavedPoints"
private let lastUpdateDateKey = "LastUpdateDate"
private let selectedChannelIdKey = "SelectedChannelId"
private let pointsLimit = 8
struct DataPoint {
let date: Date
let value: Double
}
struct Station: Codable {
let channelId: Int
let name: String
let lat: Double
let lng: Double
}
class DataStore {
let defaults = UserDefaults.standard
static let dataLoadedNotification = Notification.Name("DataLoadedNotification")
lazy var stations: [Station] = loadStations()
var selectedChannelId: Int? {
get {
return defaults.object(forKey: selectedChannelIdKey) as? Int
}
set {
if newValue != selectedChannelId {
defaults.set(newValue, forKey: selectedChannelIdKey)
invalidateData()
}
}
}
func invalidateData() {
defaults.removeObject(forKey: savedPointsKey)
defaults.removeObject(forKey: lastUpdateDateKey)
}
var hasEnoughPoints: Bool {
points.count >= pointsLimit
}
var currentLevel: Double? {
points.last?.value
}
var lastMeasurementDate: Date? {
points.last?.date
}
var lastUpdateDate: Date? {
get {
return defaults.object(forKey: lastUpdateDateKey) as? Date
}
set {
defaults.set(newValue, forKey: lastUpdateDateKey)
}
}
var points: [DataPoint] {
guard let tuples = defaults.object(forKey: savedPointsKey) as? [[Any]] else {
return []
}
return tuples.compactMap { t in
if t.count == 2, let date = t[0] as? Date, let value = t[1] as? Double {
return DataPoint(date: date, value: value)
} else {
return nil
}
}
}
func addPoints(_ newPoints: [DataPoint]) {
var pointMap: [Date:DataPoint] = [:]
self.points.forEach { p in pointMap[p.date] = p }
newPoints.forEach { p in pointMap[p.date] = p }
let allPoints = pointMap.keys.sorted().map { date in pointMap[date]! }
let recentPoints = Array(allPoints.suffix(pointsLimit))
let encodedData = recentPoints.map { p in [p.date, p.value ]}
defaults.set(encodedData, forKey: savedPointsKey)
}
func loadStations() -> [Station] {
let stationsFile = Bundle.main.url(forResource: "Stations", withExtension: "plist")!
let data = try! Data(contentsOf: stationsFile)
return try! PropertyListDecoder().decode([Station].self, from: data)
}
}