Filters.swift 7.34 KB
Newer Older
1
2
3
4
5
6
7
8
9
//
//  Filters.swift
//  WhatsOpen
//
//  Created by Zach Knox on 5/7/17.
//  Copyright © 2017 SRCT. All rights reserved.
//

import Foundation
10
import RealmSwift
11
12
13

//This may be a stupid way to handle filters, but it should work; at least for now

Zach Knox's avatar
Zach Knox committed
14
class Filters {
Zac Wood's avatar
Zac Wood committed
15
16
17
    var showOpen = true
    var showClosed = true
    var sortBy = SortMethod.alphabetical
Zach Knox's avatar
Zach Knox committed
18
    var openFirst = true
19
	
Zach Knox's avatar
Zach Knox committed
20
	var showAlerts = ["Informational":true, "Minor Alerts":true, "Major Alerts":true]
Zac Wood's avatar
Zac Wood committed
21
22
    
    var onlyFromLocations = [String: Bool]() // Locations to show, could simply use Location objects instead if you wanted
23
24
25
    var onlyFromCategories = [String: Bool]() // same as above, but for Categories, not Locations
	var onlyFromCampuses = [String: Bool]() // and for campuses
	
Zac Wood's avatar
Zac Wood committed
26
    init() {
Zach Knox's avatar
Zach Knox committed
27
        //nothing to do here
Zac Wood's avatar
Zac Wood committed
28
29
    }
    
30
    func applyFiltersOnFacilities(_ facilities: List<Facility>) -> List<Facility> {
Zac Wood's avatar
Zac Wood committed
31
32
33
34
35
        //TODO: Add checks for onlyFromLocations and onlyFromCategories here before doing the rest
        
        let specifiedFacilities = List<Facility>()
        // facility must be within both a specified location and category
        for f in facilities {
Zach Knox's avatar
Zach Knox committed
36
            if  onlyFromLocations[(f.facilityLocation?.building)!.lowercased()] == true && onlyFromCategories[(f.category?.categoryName)!.lowercased()] == true {
Zac Wood's avatar
Zac Wood committed
37
38
39
40
41
                specifiedFacilities.append(f)
            }
        }
        
        let (open, closed) = separateOpenAndClosed(specifiedFacilities)
Zach Knox's avatar
Zach Knox committed
42
        
43
        // This switch statement figures out what sort method is being used, and will sort accordingly
44
45
46
        switch sortBy {
        case .alphabetical:
            if(openFirst) {
47
                var returning = List<Facility>()
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
                if(showOpen) {
                    returning += sortAlphabetically(open)
                }
                if(showClosed) {
                    returning += sortAlphabetically(closed)
                }
                return returning
            }
            else {
                if(showOpen && showClosed) {
                    return sortAlphabetically(facilities)
                }
                else if(showOpen) {
                    return sortAlphabetically(open)
                }
                else if(showClosed) {
                    return sortAlphabetically(closed)
                }
                else {
67
                    return List<Facility>()
68
69
70
71
                }
            }
        case .reverseAlphabetical:
            if(openFirst) {
72
                var returning = List<Facility>()
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
                if(showOpen) {
                    returning += sortAlphabetically(open, reverse: true)
                }
                if(showClosed) {
                    returning += sortAlphabetically(closed, reverse: true)
                }
                return returning
            }
            else {
                if(showOpen && showClosed) {
                    return sortAlphabetically(facilities, reverse: true)
                }
                else if(showOpen) {
                    return sortAlphabetically(open, reverse: true)
                }
                else if(showClosed) {
                    return sortAlphabetically(closed, reverse: true)
                }
                else {
92
                    return List<Facility>()
93
94
95
96
                }
            }
        case .byLocation:
            if(openFirst) {
97
                var returning = List<Facility>()
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
                if(showOpen) {
                    returning += sortByLocation(open)
                }
                if(showClosed) {
                    returning += sortByLocation(closed)
                }
                return returning
            }
            else {
                if(showOpen && showClosed) {
                    return sortByLocation(facilities)
                }
                else if(showOpen) {
                    return sortByLocation(open)
                }
                else if(showClosed) {
                    return sortByLocation(closed)
                }
                else {
117
                    return List<Facility>()
118
119
120
                }
            }
        }
Zach Knox's avatar
Zach Knox committed
121
    }
Zac Wood's avatar
Zac Wood committed
122
    
Zach Knox's avatar
Zach Knox committed
123
    // Takes in array of Facilities, separates them into those open and closed, returning a tuple of 2 arrays
124
    private func separateOpenAndClosed(_ facilities: List<Facility>) -> (open: List<Facility>, closed: List<Facility>) {
Zac Wood's avatar
Zac Wood committed
125
126
127
128
129
130
        let open = List<Facility>()
        let closed = List<Facility>()
        facilities.forEach {
            Utilities.isOpen(facility: $0) ? open.append($0) : closed.append($0)
        }
        return (open, closed)
Zach Knox's avatar
Zach Knox committed
131
    }
Zac Wood's avatar
Zac Wood committed
132
133
    
    //TODO
Zach Knox's avatar
Zach Knox committed
134
    // Sorts items in the given Facility array by name alphabetically (reverse if told)
135
    private func sortAlphabetically(_ facilities: List<Facility>, reverse: Bool = false) -> List<Facility> {
Zac Wood's avatar
Zac Wood committed
136
137
        // Convert to a swift array because the realm sorting method crashes the list object for some reason?
        var facilitiesArray = facilities.asArray()
138
139
140
141
142
143
144
		if !reverse {
			facilitiesArray.sort { $0.facilityName < $1.facilityName }

		}
		else {
			facilitiesArray.sort { $0.facilityName > $1.facilityName }
		}
Zac Wood's avatar
Zac Wood committed
145
        return facilitiesArray.asRealmList()
Zach Knox's avatar
Zach Knox committed
146
    }
Zac Wood's avatar
Zac Wood committed
147
148
    
    //TODO
Zach Knox's avatar
Zach Knox committed
149
    // Sorts Facilities by their given location's name, and within those sorts A->Z
150
    private func sortByLocation(_ facilities: List<Facility>) -> List<Facility> {
Zac Wood's avatar
Zac Wood committed
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
        var facilitiesArray = facilities.asArray()
        facilitiesArray.sort { (facility, nextFacility) in
            guard let location = facility.facilityLocation else { return true }
            guard let nextLocation = nextFacility.facilityLocation else { return false }
            return location.building < nextLocation.building
        }
        return facilitiesArray.asRealmList()
    }
    
    func setShowOpen(_ to: Bool) -> Bool {
        showOpen = to
        return true
    }
    
    func setShowClosed(_ to: Bool) -> Bool {
        showClosed = to
        return true
    }
    
    func setOpenFirst(_ to: Bool) -> Bool {
        openFirst = to
        return true
    }
    
    func setCategory(_ category: String?, to: Bool) -> Bool{
        if(category != nil) {
            onlyFromCategories[category!] = to
            return true
        }
        else {
            return false
        }
    }
    
    func setLocation(_ location: String?, to: Bool) -> Bool{
        if(location != nil) {
            onlyFromLocations[location!] = to
            return true
        }
        else {
            return false
        }
Zach Knox's avatar
Zach Knox committed
193
194
195
    }
    
    
196
197
198
199
}

//Is this a viable way to do this?
enum SortMethod {
Zac Wood's avatar
Zac Wood committed
200
201
202
    case alphabetical //A -> Z
    case reverseAlphabetical //Z -> A
    case byLocation // A -> Z Locations, w/ A -> Z Facilities inside
Zach Knox's avatar
Zach Knox committed
203
    //case openLongest //Places things open longest on top; if only showing closed, shows opening soonest
Zac Wood's avatar
Zac Wood committed
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
    //case openShortest //Places things closing soonest on top; if only showing closed, shows opening furthest from now
    
    
    static var count = 3 // REMEMBER TO CHANGE THIS IF YOU ADD MORE CASES
    
    
    //We should figure out how we want to allow sorting
}

extension Array where Element: RealmCollectionValue {
    func asRealmList() -> List<Element> {
        return self.reduce(into: List<Element>()) { (list, element) in
            list.append(element)
        }
    }
219
}
Zac Wood's avatar
Zac Wood committed
220
221
222
223
224
225
226
227
228

extension List {
    func asArray() -> [Element] {
        return self.reduce(into: [Element]()) { (array, element) in
            array.append(element)
        }
    }
}