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

		}
		else {
			facilitiesArray.sort { $0.facilityName > $1.facilityName }
		}
Zac Wood's avatar
Zac Wood committed
142
        return facilitiesArray.asRealmList()
Zach Knox's avatar
Zach Knox committed
143
    }
Zac Wood's avatar
Zac Wood committed
144
145
    
    //TODO
Zach Knox's avatar
Zach Knox committed
146
    // Sorts Facilities by their given location's name, and within those sorts A->Z
147
    private func sortByLocation(_ facilities: List<Facility>) -> List<Facility> {
Zac Wood's avatar
Zac Wood committed
148
149
150
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
        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
190
191
192
    }
    
    
193
194
195
196
}

//Is this a viable way to do this?
enum SortMethod {
Zac Wood's avatar
Zac Wood committed
197
198
199
    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
200
    //case openLongest //Places things open longest on top; if only showing closed, shows opening soonest
Zac Wood's avatar
Zac Wood committed
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
    //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)
        }
    }
216
}
Zac Wood's avatar
Zac Wood committed
217
218
219
220
221
222
223
224
225

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