Skip to content

Instantly share code, notes, and snippets.

@kellylougheed
Last active November 5, 2019 23:34
Show Gist options
  • Save kellylougheed/5646b721fd6f682413c150372c54e678 to your computer and use it in GitHub Desktop.
Save kellylougheed/5646b721fd6f682413c150372c54e678 to your computer and use it in GitHub Desktop.
Process CSV files of course requests to produce rosters
import csv, operator, random
# Set enrollment limits per day
# Course-specific limits should be set inside the functions make_roster_tues and make_roster_thurs
TUES_LIMIT = 13
THURS_LIMIT = 12
'''
When generating rosters, manually double-check:
* Enrollment for PAWS, Math Cafe, Digital Literacy
* That Study Buddies participants have an endorsement
* That X-Block leaders are in the X-Block they're leading
* That Science Fair participants have a free on Thurs
* LEFTOVER STUDENTS -- Manually place if few, adjust limits if a lot
Files needed:
* signups-tues.csv
* signups-thurs.csv
(These files are identical and are used for tracking Tues and Thurs enrollment.)
* rosters-tues.csv
* rosters-thurs.csv
(Initially empty, to hold all the rosters.)
'''
'''
PART ONE: INVITATION ONLY & OTHER SPECIAL WORKSHOPS
'''
'''
These functions take in a workshop name and create a roster for that workshop. No functionality for limiting number of students in each X-Block.
Special cases are: Science Fair, PAWS, 6th Grade Math Cafe, 7th Grade Math Cafe, Digital Literacy, MS Play
STOP: Check if enrollment is low enough to include: So You Want To Lead an X-Block, Study Buddies
'''
def handle_special_case_tues(workshop):
remaining_students = []
with open('signups-tues.csv', mode='r') as signups_file, open('rosters-tues.csv', mode='a') as rosters_file:
signups = csv.reader(signups_file, delimiter=',')
rosters = csv.writer(rosters_file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
rosters.writerow([workshop])
for row in signups:
if workshop in row[5]:
rosters.writerow(row)
else:
remaining_students.append(row)
signups_file.close()
rosters_file.close()
# Delete students now on roster from sign-ups
update_roster_tues(remaining_students)
# Give Science Fair students a free period on Thursday
if workshop == "Science Fair":
with open('signups-thurs.csv', mode='w') as signups_file:
signups = csv.writer(signups_file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
signups.writerows(remaining_students)
signups_file.close()
def handle_special_case_thurs(workshop):
remaining_students = []
with open('signups-thurs.csv', mode='r+') as signups_file, open('rosters-thurs.csv', mode='a') as rosters_file:
signups = csv.reader(signups_file, delimiter=',')
rosters = csv.writer(rosters_file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
rosters.writerow([workshop])
for row in signups:
if workshop in row[6]:
rosters.writerow(row)
else:
remaining_students.append(row)
signups_file.close()
rosters_file.close()
# Delete students now on roster from sign-ups
update_roster_thurs(remaining_students)
def update_roster_tues(remaining_students):
with open('signups-tues.csv', mode='w') as signups_file:
signups = csv.writer(signups_file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
signups.writerows(remaining_students)
signups_file.close()
def update_roster_thurs(remaining_students):
with open('signups-thurs.csv', mode='w') as signups_file:
signups = csv.writer(signups_file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
signups.writerows(remaining_students)
signups_file.close()
'''
PART TWO: REGULAR WORKSHOPS
'''
# CHANGE EACH SERIES: keywords for regular workshops
workshops_tues = ["Wing", "Change", "Digital Crafts", "Dimension", "Robots", "Write", "Rotten", "Journal"]
workshops_thurs = ["Lead", "Baking", "Choreography", "Climate", "ProCRAFTination", "Spot", "Pup", "Gaming", "Knitting", "Seasonal", "Album", "Bullet", "Math"]
# Returns number of requests for a workshop on Tues
def count_requests_tues(workshop):
with open('signups-tues.csv', mode='r') as signups_file:
signups = csv.reader(signups_file, delimiter=',')
requests = 0
for row in signups:
if workshop in row[5]:
requests += 1
signups_file.close()
return requests
# Returns number of requests for a workshop on Thurs
def count_requests_thurs(workshop):
with open('signups-thurs.csv', mode='r') as signups_file:
signups = csv.reader(signups_file, delimiter=',')
requests = 0
for row in signups:
if workshop in row[6]:
requests += 1
signups_file.close()
return requests
# Arguments: list of workshops, string "T" for Tuesday or "TR" for Thursday
def get_counts(workshops, day):
counts = {}
for workshop in workshops:
if day == "T":
counts[workshop] = count_requests_tues(workshop)
elif day == "TR":
counts[workshop] = count_requests_thurs(workshop)
return counts
# Create dictionaries of counts
tues_counts = get_counts(workshops_tues, "T")
thurs_counts = get_counts(workshops_thurs, "TR")
# Convert dictionaries into list of ordered tuples
sorted_tues = sorted(tues_counts.items(), key=operator.itemgetter(1))
sorted_thurs = sorted(thurs_counts.items(), key=operator.itemgetter(1))
def make_roster_tues(workshop):
students_enrolled = []
remaining_students = []
with open('signups-tues.csv', mode='r+') as signups_file, open('rosters-tues.csv', mode='a') as rosters_file:
signups = csv.reader(signups_file, delimiter=',')
rosters = csv.writer(rosters_file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
# Write workshop title
rosters.writerow([workshop])
# Set limit
limit = TUES_LIMIT
if workshop == "Digital Crafts":
limit = 10
if workshop == "Dimension":
limit = 12
# Loop through to check for students who didn't request other workshops
for row in signups:
enroll = False
if workshop in row[5]:
enroll = True
for pair in sorted_tues:
if pair[0] in row[5]:
enroll = False
break
if enroll and len(students_enrolled) < limit:
rosters.writerow(row)
students_enrolled.append(row)
signups_file.close()
rosters_file.close()
# If still room, let students in randomly
for i in range(2):
with open('signups-tues.csv', mode='r+') as signups_file, open('rosters-tues.csv', mode='a') as rosters_file:
signups = csv.reader(signups_file, delimiter=',')
rosters = csv.writer(rosters_file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
for row in signups:
if row not in students_enrolled and workshop in row[5]:
rand = random.randint(0, 1)
if rand == 0 and len(students_enrolled) < limit:
rosters.writerow(row)
students_enrolled.append(row)
signups_file.close()
rosters_file.close()
with open('signups-tues.csv', mode='r+') as signups_file:
signups = csv.reader(signups_file, delimiter=',')
# Make list of remaining students to update sign-ups
for row in signups:
if row not in students_enrolled:
remaining_students.append(row)
signups_file.close()
# Delete students now on roster from sign-ups
update_roster_tues(remaining_students)
def make_roster_thurs(workshop):
students_enrolled = []
remaining_students = []
with open('signups-thurs.csv', mode='r+') as signups_file, open('rosters-thurs.csv', mode='a') as rosters_file:
signups = csv.reader(signups_file, delimiter=',')
rosters = csv.writer(rosters_file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
# Write workshop title
rosters.writerow([workshop])
# Set limit
limit = THURS_LIMIT
if workshop == "Climate":
limit = 8
# Loop through to check for students who didn't request other workshops
# Thursday: Also check for X-Block leaders
for row in signups:
enroll = False
if workshop in row[6]:
enroll = True
for pair in sorted_tues:
if pair[0] in row[6]:
enroll = False
break
# Fast-track leaders to enrollment in their own X-Block
# Student-Led: "Baking", "Choreography", "Climate", "ProCRAFTination", "Spot", "Pup", "Gaming"
leader = False
if workshop == "Choreography" and "curry" in row[1]:
leader = True
elif workshop == "Baking" and ("wachler" in row[1] or "lundberg" in row[1] or "chu" in row[1]):
leader = True
elif workshop == "Climate" and "stephen" in row[1]:
leader = True
elif workshop == "ProCRAFTination" and ("morris" in row[1] or "keston" in row[1]):
leader = True
elif workshop == "Spot" and ("alvarez" in row[1] or "ritchie" in row[1]):
leader = True
elif workshop == "Pup" and ("entin" in row[1] or "frank" in row[1]):
leader = True
elif workshop == "Gaming" and ("arsan" in row[1] or "lazarus" in row[1]):
leader = True
if leader:
rosters.writerow(row)
students_enrolled.append(row)
elif enroll and len(students_enrolled) < limit:
rosters.writerow(row)
students_enrolled.append(row)
signups_file.close()
rosters_file.close()
# If still room, let students in randomly
for i in range(2):
with open('signups-thurs.csv', mode='r+') as signups_file, open('rosters-thurs.csv', mode='a') as rosters_file:
signups = csv.reader(signups_file, delimiter=',')
rosters = csv.writer(rosters_file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
for row in signups:
if row not in students_enrolled and workshop in row[6]:
rand = random.randint(0, 1)
if rand == 0 and len(students_enrolled) < limit:
rosters.writerow(row)
students_enrolled.append(row)
signups_file.close()
rosters_file.close()
with open('signups-thurs.csv', mode='r+') as signups_file:
signups = csv.reader(signups_file, delimiter=',')
# Make list of remaining students to update sign-ups
for row in signups:
if row not in students_enrolled:
remaining_students.append(row)
signups_file.close()
# Delete students now on roster from sign-ups
update_roster_thurs(remaining_students)
special_cases = {
"Tues": ["Science Fair", "Digital Literacy", "PAWS", "7th Grade Math Cafe", "6th Grade Math Cafe", "Study Buddies"],
"Thurs": ["PAWS", "Play", "Lead"]
}
'''
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ROSTERS GENERATED HERE: COMMENT OUT IF NEEDED
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
'''
for workshop in special_cases["Tues"]:
handle_special_case_tues(workshop)
for workshop in special_cases["Thurs"]:
handle_special_case_thurs(workshop)
# STOP: Cross-reference generated rosters with the official ones. Manually make corrections.
'''
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ROSTERS GENERATED HERE: COMMENT OUT IF NEEDED
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
'''
# Feed each workshop name into roster-making function
# As you go, delete workshop tuples to remove them from consideration
# TUESDAY
for i in range(len(sorted_tues)):
make_roster_tues(sorted_tues[i][0])
sorted_tues[i] = ('XXDONEXX', 'XXDONEXX')
# THURSDAY
for i in range(len(sorted_thurs)):
make_roster_thurs(sorted_thurs[i][0])
sorted_thurs[i] = ('XXDONEXX', 'XXDONEXX')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment