update work on test schedule generator

This commit is contained in:
SowinskiBraeden committed 2022-02-22 13:44:46 -08:00
1 parent 1ae16739a8
commit 10716d5a48
1 file changed
+125 -103
+125 -103
View File
@@ -6,10 +6,6 @@ import json
from prettytable import PrettyTable from prettytable import PrettyTable
from courses import courses, activeCourses from courses import courses, activeCourses
# FIXME: Student is assigned multiple classes per block
# FIXME: Classes are ran more than they should be according to ln 124 count
# FIXME: Student List around 240 causes "No more room in school for classes" problem
''' '''
I will be using python to test and I will be using python to test and
develop course selection / schedule develop course selection / schedule
@@ -18,81 +14,95 @@ from courses import courses, activeCourses
this is honestly terrible code but this is honestly terrible code but
this is not an easy task for me to this is not an easy task for me to
do do
Block 1-4 is first semester while
block 5-8 is second semester
''' '''
''' '''
schedule example: schedule example:
schedule: { schedule: {
"semester1": { "block1": "className",
"block1": "className", "block2": "className",
"block2": "className", "block3": "className",
"block3": "className", "block4": "className"
"block4": "className" "block5": "className",
}, "block6": "className",
"semester2": { "block7": "className",
"block1": "className", "block8": "className"
"block2": "className",
"block3": "className",
"block4": "className"
}
} }
''' '''
''' '''
running example: running example:
running: { running: {
"semester1": { "block1": {classCode:{"className":name,"students":[student Name]},classCode:{"className":name,"students":[student Name]}},
"block1": {classCode:{"className":name,"students":[student Name]},classCode:{"className":name,"students":[student Name]}}, "block2": {classCode:{"className":name,"students":[student Name]},classCode:{"className":name,"students":[student Name]}},
"block2": {classCode:{"className":name,"students":[student Name]},classCode:{"className":name,"students":[student Name]}}, "block3": {classCode:{"className":name,"students":[student Name]},classCode:{"className":name,"students":[student Name]}},
"block3": {classCode:{"className":name,"students":[student Name]},classCode:{"className":name,"students":[student Name]}}, "block4": {classCode:{"className":name,"students":[student Name]},classCode:{"className":name,"students":[student Name]}},
"block4": {classCode:{"className":name,"students":[student Name]},classCode:{"className":name,"students":[student Name]}} "block5": {classCode:{"className":name,"students":[student Name]},classCode:{"className":name,"students":[student Name]}},
}, "block6": {classCode:{"className":name,"students":[student Name]},classCode:{"className":name,"students":[student Name]}},
"semester2": { "block7": {classCode:{"className":name,"students":[student Name]},classCode:{"className":name,"students":[student Name]}},
"block1": {classCode:{"className":name,"students":[student Name]},classCode:{"className":name,"students":[student Name]}}, "block8": {classCode:{"className":name,"students":[student Name]},classCode:{"className":name,"students":[student Name]}}
"block2": {classCode:{"className":name,"students":[student Name]},classCode:{"className":name,"students":[student Name]}},
"block3": {classCode:{"className":name,"students":[student Name]},classCode:{"className":name,"students":[student Name]}},
"block4": {classCode:{"className":name,"students":[student Name]},classCode:{"className":name,"students":[student Name]}}
]
} }
''' '''
minReq, classCap, blockClassLimit = 18, 30, 24 # Error 1: No classes in schedule can fit this student
# Error 2: No more room in schedule for another class
# Error 3: No more alternatives
err1, err2, err3 = 0,0,0
minReq, classCap, blockClassLimit = 18, 30, 15
mockStudents = [] mockStudents = []
running = { running = {
"semester1": { "block1": {},
"block1": {}, "block2": {},
"block2": {}, "block3": {},
"block3": {}, "block4": {},
"block4": {} "block5": {},
}, "block6": {},
"semester2": { "block7": {},
"block1": {}, "block8": {}
"block2": {},
"block3": {},
"block4": {}
}
} }
# Generate n students for mock data # Generate n students for mock data
def generateMockStudents(n): def generateMockStudents(n):
newStudent = {
"name": "Braeden Sowinski",
"requests": [], # list of class codes
"schedule": {
"block1": "",
"block2": "",
"block3": "",
"block4": "",
"block5": "",
"block6": "",
"block7": "",
"block8": ""
}
}
# Get list of random class choices with no repeats
# 8 primary choices, 2 secondary choices
courseSelection = random.sample(range(0, len(courses)), 10)
for courseNum in courseSelection:
newStudent["requests"].append(list(courses)[courseNum])
mockStudents.append(newStudent)
for _ in range(n): for _ in range(n):
newStudent = { newStudent = {
"name": names.get_full_name(), "name": names.get_full_name(),
"requests": [], # list of class codes "requests": [], # list of class codes
"schedule": { "schedule": {
"semester1": { "block1": "",
"block1": "", "block2": "",
"block2": "", "block3": "",
"block3": "", "block4": "",
"block4": "" "block5": "",
}, "block6": "",
"semester2": { "block7": "",
"block1": "", "block8": ""
"block2": "",
"block3": "",
"block4": ""
}
} }
} }
# Get list of random class choices with no repeats # Get list of random class choices with no repeats
@@ -104,25 +114,26 @@ def generateMockStudents(n):
def generateSchedule(): def generateSchedule():
global err1, err2, err3
# Collect data and calculate schedules # Collect data and calculate schedules
for student in mockStudents: for student in mockStudents:
# Tally class request # Tally class request
for request in student["requests"]: for request in student["requests"]:
courses[request]["totalrequests"] += 1 courses[request]["totalrequests"] += 1
courses[request]["studentindexes"].append(mockStudents.index(student)) courses[request]["studentindexes"].append(mockStudents.index(student))
# Add course to active list if enough requests # Add course to active list if enough requests
if courses[request]["totalrequests"] > minReq and courses[request]["code"] not in activeCourses: activeCourses[courses[request]["code"]] = courses[request] if courses[request]["totalrequests"] > minReq and courses[request]["code"] not in activeCourses: activeCourses[courses[request]["code"]] = courses[request]
# This is just for data testing/visualizations # This is just for data testing/visualizations
# calculate # of times to run class # calculate # of times to run class
t = PrettyTable(["Class Name", "Class Runcount"]) # t = PrettyTable(["Class Name", "Class Runcount"])
for i in range(len(activeCourses)): # for i in range(len(activeCourses)):
classRunCount = math.floor(activeCourses[list(activeCourses)[i]]["totalrequests"] / classCap) # classRunCount = math.floor(activeCourses[list(activeCourses)[i]]["totalrequests"] / classCap)
# If there is 18+ requests left, 1 more class could be run # # If there is 18+ requests left, 1 more class could be run
if (activeCourses[list(activeCourses)[i]]["totalrequests"] % classCap) > minReq: classRunCount += 1 # if (activeCourses[list(activeCourses)[i]]["totalrequests"] % classCap) > minReq: classRunCount += 1
activeCourses[list(activeCourses)[i]]["classRunCount"] = classRunCount # activeCourses[list(activeCourses)[i]]["classRunCount"] = classRunCount
t.add_row([activeCourses[list(activeCourses)[i]]["code"], classRunCount]) # t.add_row([activeCourses[list(activeCourses)[i]]["code"], classRunCount])
print(t) # print(t)
for student in mockStudents: for student in mockStudents:
alternateOffset = len(student["requests"])-8 alternateOffset = len(student["requests"])-8
@@ -133,79 +144,90 @@ def generateSchedule():
# If class is allowed to run # If class is allowed to run
if currentCourse in activeCourses: if currentCourse in activeCourses:
blockIndex = 1 blockIndex = 1
semesterIndex = 1
getFreeBlock = True getFreeBlock = True
while getFreeBlock: while getFreeBlock:
block = f"block{blockIndex}" block = f"block{blockIndex}"
semester = f"semester{semesterIndex}" if currentCourse in running[block]:
if currentCourse in running[semester][block]: if student["schedule"][block] == "": # Add student to class
if student["schedule"][semester][block] == "": # Add student to class if len(running[block][currentCourse]["students"]) < classCap:
if len(running[semester][block][currentCourse]["students"]) < classCap: running[block][currentCourse]["students"].append(student["name"])
running[semester][block][currentCourse]["students"].append(student["name"]) student["schedule"][block] = courses[currentCourse]["name"]
student["schedule"][semester][block] = courses[currentCourse]["name"]
getFreeBlock = False getFreeBlock = False
else: # Find next available class or create new one else: # Find next available class or create new one
if semesterIndex == 2 and blockIndex == 4: if blockIndex == 8: # No available classes
# No available classes # print(f"\nError 1: No more available classes for student {student['name']}")
print("No more available classes") err1 += 1
getFreeBlock = False getFreeBlock = False
elif blockIndex == 4:
blockIndex = 1
semesterIndex += 1
else: blockIndex += 1 else: blockIndex += 1
else: else:
if semesterIndex == 2 and blockIndex == 4: if blockIndex == 8: # No available classes
# No available classes # print(f"\nError 1: No more available classes for student {student['name']}")
print("No more available classes for that student --------------------") err1 += 1
# Resort to alternative # Resort to alternative
getFreeBlock = False getFreeBlock = False
elif blockIndex == 4:
blockIndex = 1
semesterIndex += 1
else: blockIndex += 1 else: blockIndex += 1
else: else:
if semesterIndex == 2 and blockIndex == 4: if blockIndex == 8:
# Class does not exists # Class does not exists
# Create new class in first available slot # Create new class in first available slot
blockNum = 1 blockNum = 1
semesterNum = 1
while True: while True:
newBlock = f"block{blockNum}" newBlock = f"block{blockNum}"
newSemester = f"semester{semesterNum}" if currentCourse not in running[newBlock] and len(running[newBlock]) < blockClassLimit:
if currentCourse not in running[newSemester][newBlock] and len(running[newSemester][newBlock]) < blockClassLimit: if student["schedule"][newBlock] == "":
running[newSemester][newBlock][currentCourse] = { running[newBlock][currentCourse] = {
"name": courses[currentCourse]["name"], "name": courses[currentCourse]["name"],
"students": [student["name"]] "students": [student["name"]]
} }
student["schedule"][newSemester][newBlock] = courses[currentCourse]["name"] student["schedule"][newBlock] = courses[currentCourse]["name"]
break break
else:
if blockNum == 8:
# No available classes
# print(f"\nError 1: No more available classes for student {student['name']}")
err1 += 1
# TODO: Resort to alternative
break
else: blockNum += 1
else: else:
if semesterNum == 2 and blockNum == 4: if blockNum == 8:
# No room in school for more classes # No room in school for more classes
print("No room in school for more classes") # print(f"\nError 2: No more room in school for another class")
err2 += 1
break break
elif blockNum == 4:
blockNum = 1
semesterNum += 1
else: blockNum += 1 else: blockNum += 1
break break
elif blockIndex == 4: # 4th Block (final block)
blockIndex = 1
semesterIndex += 1
else: blockIndex += 1 else: blockIndex += 1
break break
elif currentCourse not in activeCourses: elif currentCourse not in activeCourses:
if alternateOffset == 0: if alternateOffset == 0:
# TODO: No more alternatives, solve problem # TODO: No more alternatives, solve problem
print("No more alternatives, solve this problem somehow") # print("Error 3: No more alternatives")
err3 += 1
# How to solve?
generate = False generate = False
currentCourse = student["requests"][len(student["requests"])-alternateOffset] currentCourse = student["requests"][len(student["requests"])-alternateOffset]
alternateOffset -= 1 alternateOffset -= 1
if __name__ == '__main__': if __name__ == '__main__':
generateMockStudents(200) generateMockStudents(400)
generateSchedule() generateSchedule()
print(f"Error 1: x{err1}")
print(f"Error 2: x{err2}")
print(f"Error 3: x{err3}")
print("\n\n")
### Displays the number of students in each class
# for block in running:
# print(f"\nBlock: {block}")
# print("=====================")
# for cl in running[block]:
# name = running[block][cl]["name"]
# students = len(running[block][cl]["students"])
# print(f"Class: {name} | Students: {students}")
with open("schedule.json", "w") as outfile: with open("schedule.json", "w") as outfile:
json.dump(running, outfile, indent=2) json.dump(running, outfile, indent=2)