Filters.swift 7.09 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
135
136
        // Convert to a swift array because the realm sorting method crashes the list object for some reason?
        var facilitiesArray = facilities.asArray()
        facilitiesArray.sort { $0.facilityName < $1.facilityName }
        return facilitiesArray.asRealmList()
Zach Knox's avatar
Zach Knox committed
137
    }
Zac Wood's avatar
Zac Wood committed
138
139
    
    //TODO
Zach Knox's avatar
Zach Knox committed
140
    // Sorts Facilities by their given location's name, and within those sorts A->Z
141
    private func sortByLocation(_ facilities: List<Facility>) -> List<Facility> {
Zac Wood's avatar
Zac Wood committed
142
143
144
145
146
147
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
        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
184
185
186
    }
    
    
187
188
189
190
}

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

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