-
Notifications
You must be signed in to change notification settings - Fork 0
/
timetable.py
194 lines (134 loc) · 4.83 KB
/
timetable.py
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
140
141
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
184
185
186
187
188
189
190
191
192
193
194
import exTime
import copy
# Data structures and functions used to parse html page and store in TimetableEntry classes.
# Structures
class TimetableEntry:
def __init__(self, day, start, end, venue):
self.day = day
self.start = start
self.end = end
self.venue = venue
# Functions
def getFilteredTimetable(day, time, timetable):
""" Filter the timetable based on day and time.
Args:
day: The day to return from the timetable. EG "Monday"
time: The time string to use as a filter. EG "14:24"
timetable: The list of TimetableEntry to apply the filter proccess
Returns:
A list of TimetableEntry that match the day and are in session during the given time
"""
matchingDateTimetable = []
# Discard all entries that do not match the day
for entry in timetable:
if entry.day == day:
matchingDateTimetable.append(entry)
finalTimetable = []
# Discard all entries that do not match the time range
for entry in matchingDateTimetable:
# Convert strings to minutes
start = exTime.convertTimeStringToMinutes(entry.start[:-3])
end = exTime.convertTimeStringToMinutes(entry.end[:-3])
timeMins = exTime.convertTimeStringToMinutes(time)
# If timeMins is in the range of entry, then the venue is active and we add it to the final timetable
if timeMins in range(start, end):
finalTimetable.append(entry)
###DEBUG_S
### print(str(timeMins) + ' is in range of ' + '[' + str(start) + ', ' + str(end) + ']')
### else:
### print('Dropping: ' + str(timeMins) + ' not in [' + str(start) + ', ' + str(end) + ']')
###DEBUG_E
###DEBUG_S
###print('Classes running at ' + time)
###for entry in finalTimetable:
### print(entry.start + ' -> ' + entry.end + '\t' + entry.day + '\t\t' + entry.venue)
###DEBUG_E
return finalTimetable
def getEmptyVenuesFromURL(url, day, time):
# TODO: Error handling
htmlRequest = requests.get(url)
timeTableObject = timetable.getTimetableFromHTML(htmlRequest.text)
venueList = timetable.getVenueList(timeTableObject)
filteredTimetable = timetable.getFilteredTimetable(day, time, timeTableObject)
emptyVenues = timetable.getEmptyVenues(filteredTimetable, venueList)
emptyVenues.sort()
return emptyVenues
def getEmptyVenuesFromFullTimetable(day, time, fullTimetable):
venueList = getVenueList(fullTimetable)
activeTimetable = getFilteredTimetable(day, time, fullTimetable)
empty = getEmptyVenues(activeTimetable, venueList)
return empty
def getEmptyVenues(timetable, venueList):
""" Return a list of empty venues
Args:
timetable: A list of TimetableEntry to search in
venueList: A list containing all valid venues
Returns:
Returns a list of all venues that are empty
"""
# Creates a deep copy of the list
empty = venueList[:]
# Remove venues from the empty list if they exist in the timetable
for entry in timetable:
if entry.venue in empty:
empty.remove(entry.venue)
###DEBUG_S
###print('Dropping: ' + entry.venue)
###print('\t' + entry.day + ' ' + entry.start + ' -> ' + entry.end)
###print('----')
###DEBUG_E
return empty
def getVenueList(timetable):
""" Return a list of all unique venues from the timetable
Args:
timetable: A list of TimetableEntry to scrape venues from
"""
venueList = []
# Add all unique venues from the timetable to the venue list
for entry in timetable:
if not entry.venue in venueList:
venueList.append(entry.venue)
return venueList
def getTimetableEntry(text):
""" Attempt to extract a TimetableEntry from a formatted line of HTML
Args:
text: A line of HTML to parse.
Index
Returns:
If the HTML line was a valid timetable entry:
A TimetableEntry object containing the relevant iformation
Else
A TimetableEntry object with all values set to -1
"""
# HTML Format:
# <tr><td>4/SOR 420/G01/B/L1</td><td>S2</td><td>Monday</td><td>12:30:00</td><td>14:30:00</td><td>Regsgebou/Law building 1-31</td></tr>
# Some constants describing the index of data after splitting at '>'
LENGTH = 15
OPEN_TAG_INDEX = 0
CLOSE_TAG_INDEX = 13
DAY_INDEX = 6
START_TIME_INDEX = 8
END_TIME_INDEX = 10
VENUE_INDEX = 12
entry = TimetableEntry(-1, -1, -1, -1)
rawData = text.split('>')
# Validate the data to make sure it is what we are looking for
if len(rawData) == LENGTH:
if rawData[OPEN_TAG_INDEX] == '<tr' and rawData[CLOSE_TAG_INDEX] == '</tr':
# Add info to array and strip the left over tags
entry = TimetableEntry(rawData[DAY_INDEX].strip('</td'), rawData[START_TIME_INDEX].strip('</td'), rawData[END_TIME_INDEX].strip('</td'), rawData[VENUE_INDEX].strip('</td'))
return entry
def getTimetableFromHTML(text):
""" Parse a HTML file and return a list of Timetable Entry
Args:
text: The HTML timetable
Returns:
A list of TimetableEntry objects
"""
timetable = []
rawData = text.split('\r\n')
for line in rawData:
entry = getTimetableEntry(line)
if entry.day != -1:
timetable.append(entry)
return timetable