canvasapp/schedules.py

206 lines
6.8 KiB
Python

# schedule.py
#
# experimenting with manipulating and querying the schedule of courses
import json, re, sys, os
from datetime import datetime
from fast_autocomplete import AutoComplete
columns, rows = os.get_terminal_size()
course_types = {'in-person':'IP','hybrid':'H','online':'O','online live':'OL'}
def course_to_string(crs):
if len(crs['teacher'].split()) == 3:
crs['teacher'] = crs['teacher'].split()[0] + " " + crs['teacher'].split()[2]
# crn type loc days start end cred num/cap code name teacher date
lengths = [5, 3, 7, 5, 6, 6, 4, 9, 13, 35, 25,10]
items = [ crs[x] for x in 'crn,type,loc,days,time_start,time_end,cred,act,cap,code,name,teacher,date'.split(',')]
items[1] = course_types[ items[1] ]
if items[2] in ["ONLINE", "ONLINE LIVE"]: items[2] = ''
items[6] = items[6][0:3]
items[7] = f"{items[7]}/{items[8]}"
if int(crs['wl_act']) != 0: items[7] += f"+{crs['wl_act']}"
items.pop(8)
result = " ".join(f"{str(val):{width}}" for val, width in zip(items, lengths))
return result
def parse_days(str_days):
# return a list with actual day of week names
days = []
if 'M' in str_days:
days.append('monday')
if 'T' in str_days:
days.append('tuesday')
if 'W' in str_days:
days.append('wednesday')
if 'R' in str_days:
days.append('thursday')
if 'F' in str_days:
days.append('friday')
if 'S' in str_days:
days.append('saturday')
return days
def parse_courses(filename):
with open(filename) as f:
courses = json.load(f)
depts, crns, codes, coursenames, locations, teachers, days, now = {}, {}, {}, {}, {}, {}, {}, datetime.now()
weekdays = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']
for course in courses:
#print(course)
dept = course['code'].split()[0]
depts.setdefault(dept, []).append(course)
# Add course to teachers dict
course['teacher'] = re.sub(r'\s+', ' ', course['teacher'])
teachers.setdefault(course['teacher'], []).append(course)
# add course to codes, crns, coursenames dict
codes.setdefault(course['code'], []).append(course)
crns.setdefault(course['crn'], []).append(course)
coursenames.setdefault(course['name'], []).append(course)
if course['type'] != 'in-person': continue
# Add course to locations dict
locations.setdefault(course['loc'], []).append(course)
# Add course to days dict
for day in parse_days(course['days']):
days.setdefault(day, []).append(course)
# Check if course is happening now
if course['time_start'] == '': continue
if course['time_end'] == '': continue
start_time = datetime.strptime(course['time_start'], '%H:%M')
end_time = datetime.strptime(course['time_end'], '%H:%M')
#if start_time.time() <= now.time() <= end_time.time():
# print(f"{course['code']} is happening now in {course['loc']}")
return depts,crns, codes, coursenames, locations, teachers, days
def write_at(row, col, text):
sys.stdout.write(f"\033[{row};{col}H{text}")
sys.stdout.flush()
def write_search_results(res,maximum=8):
height = max(len(res),maximum)
while len(res)<height:
res.append('')
for i,L in enumerate(res):
write_at(rows - i-1, 1, f"{L} ")
write_at(rows,0,'')
def write_cleared_search_results(maximum=8):
for i in range(maximum):
write_at(rows - i, 1, f" ")
write_at(rows,0,'')
examples = 0
if examples:
# Get schedule for a specific room on a specific day
room = 'HU 104'
day = 'monday'
print(f"\nSchedule for {room} on {day}:")
for course in locations[room]:
if day in parse_days(course['days']):
print(" " + course_to_string(course))
# Get weekly schedule for a specific teacher
teacher = 'Kimberly J Smith'
print(f"\nWeekly schedule for {teacher}:")
for course in teachers[teacher]:
print(" " + course_to_string(course))
def interactive(allkeys):
import sys
def getch():
# Unix
if sys.platform != 'win32':
import tty, termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(fd)
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
# Windows
else:
import msvcrt
return msvcrt.getch().decode('utf-8')
words = { x:{} for x in allkeys.keys() }
autocomplete = AutoComplete(words=words)
# get search term
query = ''
results = []
while True:
char = getch()
#print(repr(char))
#print("\n\n\n\n\n\n\n\n")
if char == '\x08':
query = query[:-1]
elif char == '\r':
if query == 'quit': return False
break
else:
query += char
results = [x[0] for x in autocomplete.search(word=query, max_cost=3, size=5)]
print(query+" ",end='',flush=True)
write_search_results(results)
write_cleared_search_results()
print()
print()
for (keyset,dataset) in [(deptkeys,depts),(teacherkeys,teachers), (locationkeys,locations),(coursenameskeys,coursenames),(codeskeys,codes),(crnskeys,crns)]:
if results[0] in keyset:
real_key = keyset[results[0]]
if real_key in dataset.keys():
print(f"\nWeekly schedule for {real_key}:")
for course in dataset[real_key]:
print(" " + course_to_string(course))
while True:
# Read in schedule
depts, crns, codes, coursenames, locations, teachers, days = parse_courses('cache/sample_semester.json')
deptkeys = { x.lower():x for x in depts.keys() }
teacherkeys = { x.lower():x for x in teachers.keys() }
locationkeys = { x.lower():x for x in locations.keys() }
coursenameskeys = { x.lower():x for x in coursenames.keys() }
codeskeys = { x.lower():x for x in codes.keys() }
crnskeys = { x.lower():x for x in crns.keys() }
lname_first = [x.split() for x in teachers.keys() ]
d_lnf = { x[-1].lower() + ", " + ' '.join(x[:-1]).lower(): ' '.join(x) for x in lname_first }
teacherkeys.update(d_lnf)
allkeys = {}
allkeys.update(deptkeys)
allkeys.update(teacherkeys)
allkeys.update(locationkeys)
allkeys.update(coursenameskeys)
allkeys.update(codeskeys)
allkeys.update(crnskeys)
print("\nEnter your query or 'quit': ")
if interactive(allkeys) == False: break