fix step 2, finish step 3

This commit is contained in:
SowinskiBraeden committed 2022-04-08 13:42:04 -07:00
1 parent d6115844f2
commit 90cf967701
3 files changed
+77 -61

No files matched your search

-1
View File
@@ -1 +0,0 @@
{}
+15 -3
View File
@@ -1,5 +1,17 @@
test_string = "XAT--12C-S" # test_string = "XAT--12C-S"
print(bool([i for i in ["XAT--12A-S", "XAT--12B-S"] if(i in test_string)])) # print(bool([i for i in ["XAT--12A-S", "XAT--12B-S"] if(i in test_string)]))
print(test_string[len(test_string)-1]) # print(test_string[len(test_string)-1])
myFirstDict = {
"den": {},
"ten": {},
"ben": {}
}
query = "ten"
if query in myFirstDict: print(True)
for i in range(10): print(i)
+62 -57
View File
@@ -3,6 +3,7 @@ import sys
import json import json
import math import math
import random import random
from xml.etree.ElementTree import TreeBuilder
from courses import mockCourses, activeCourses from courses import mockCourses, activeCourses
from mockStudents import generateMockStudents, getSampleStudents from mockStudents import generateMockStudents, getSampleStudents
from generateCourses import getSampleCourses from generateCourses import getSampleCourses
@@ -370,11 +371,7 @@ def generateScheduleV3(students, courses):
if courses[code]["Requests"] > minReq and courses[code]["CrsNo"] not in activeCourses: if courses[code]["Requests"] > minReq and courses[code]["CrsNo"] not in activeCourses:
activeCourses[code] = courses[code] activeCourses[code] = courses[code]
# Step 2 - Generate class list without timetable # Step 2 - Generate empty classes
# Step 2 part A
existingClasses = []
selectedCourses = {}
emptyClasses = {} # List of all classes with how many students should be entered during generation emptyClasses = {} # List of all classes with how many students should be entered during generation
# calculate # of times to run class # calculate # of times to run class
for i in range(len(activeCourses)): for i in range(len(activeCourses)):
@@ -383,11 +380,9 @@ def generateScheduleV3(students, courses):
classRunCount = math.floor(activeCourses[index]["Requests"] / median) classRunCount = math.floor(activeCourses[index]["Requests"] / median)
remaining = activeCourses[index]["Requests"] % median remaining = activeCourses[index]["Requests"] % median
if classRunCount >= 1: existingClasses.append(index)
# Put # of classRunCount classes in emptyClasses # Put # of classRunCount classes in emptyClasses
for j in range(classRunCount): for j in range(classRunCount):
emptyClasses[index][f"{activeCourses[index]['Description']}-{j}"] = { emptyClasses[index][f"{index}-{j}"] = {
"CrsNo": index, "CrsNo": index,
"Description": activeCourses[index]["Description"], "Description": activeCourses[index]["Description"],
"expectedLen": median # Number of students expected in this class / may be altered "expectedLen": median # Number of students expected in this class / may be altered
@@ -396,15 +391,27 @@ def generateScheduleV3(students, courses):
# If remaining fit in open slots in existing classes # If remaining fit in open slots in existing classes
if remaining <= classRunCount * (classCap - median): if remaining <= classRunCount * (classCap - median):
# Equally disperse remaining into existing classes # Equally disperse remaining into existing classes
while remaining > 0:
for j in range(classRunCount): for j in range(classRunCount):
if remaining == 0: break if remaining == 0: break
emptyClasses[index][f"{activeCourses[index]['Description']}-{j}"]["expectedLen"] += 1 emptyClasses[index][f"{index}-{j}"]["expectedLen"] += 1
remaining -= 1 remaining -= 1
# Else if the remaining can create a class elif remaining >= minReq and classRunCount == 0:
elif remaining >= minReq:
# Create a class using remaining # Create a class using remaining
emptyClasses[index][f"{activeCourses[index]['Description']}-{classRunCount}"] = { emptyClasses[index][f"{index}-{classRunCount}"] = {
"CrsNo": index,
"Description": activeCourses[index]["Description"],
"expectedLen": remaining
}
classRunCount += 1
# Else if the remaining can create a class
elif remaining >= minReq and classRunCount > 0:
# Create a class using remaining
emptyClasses[index][f"{index}-{classRunCount}"] = {
"CrsNo": index, "CrsNo": index,
"Description": activeCourses[index]["Description"], "Description": activeCourses[index]["Description"],
"expectedLen": remaining "expectedLen": remaining
@@ -413,10 +420,10 @@ def generateScheduleV3(students, courses):
classRunCount += 1 classRunCount += 1
# Equalize (level) class expectedLen's # Equalize (level) class expectedLen's
expectedLengths = [emptyClasses[index][f"{activeCourses[index]['Description']}-{j}"]["expectedLen"] for j in range(classRunCount)] expectedLengths = [emptyClasses[index][f"{index}-{j}"]["expectedLen"] for j in range(classRunCount)]
newExpectedLens = equal(expectedLengths) newExpectedLens = equal(expectedLengths)
for j in range(len(newExpectedLens)): for j in range(len(newExpectedLens)):
emptyClasses[index][f"{activeCourses[index]['Description']}-{j}"]["expectedLen"] = newExpectedLens[j] emptyClasses[index][f"{index}-{j}"]["expectedLen"] = newExpectedLens[j]
# Else if we can't fit remaining in open slots in existing classes # Else if we can't fit remaining in open slots in existing classes
# and it is unable to create its own class, # and it is unable to create its own class,
@@ -424,12 +431,12 @@ def generateScheduleV3(students, courses):
elif minReq - remaining < classRunCount * (median - minReq): elif minReq - remaining < classRunCount * (median - minReq):
# Take 1 from each class till min requirment met # Take 1 from each class till min requirment met
for j in range(classRunCount): for j in range(classRunCount):
emptyClasses[index][f"{activeCourses[index]['Description']}-{j}"]["expectedLen"] -= 1 emptyClasses[index][f"{index}-{j}"]["expectedLen"] -= 1
remaining += 1 remaining += 1
if remaining == minReq: break if remaining == minReq: break
# Create a class using remaining # Create a class using remaining
emptyClasses[index][f"{activeCourses[index]['Description']}-{classRunCount}"] = { emptyClasses[index][f"{index}-{classRunCount}"] = {
"CrsNo": index, "CrsNo": index,
"Description": activeCourses[index]["Description"], "Description": activeCourses[index]["Description"],
"expectedLen": remaining "expectedLen": remaining
@@ -438,10 +445,10 @@ def generateScheduleV3(students, courses):
classRunCount += 1 classRunCount += 1
# Equalize (level) class expectedLen's # Equalize (level) class expectedLen's
expectedLengths = [emptyClasses[index][f"{activeCourses[index]['Description']}-{j}"]["expectedLen"] for j in range(classRunCount)] expectedLengths = [emptyClasses[index][f"{index}-{j}"]["expectedLen"] for j in range(classRunCount)]
newExpectedLens = equal(expectedLengths) newExpectedLens = equal(expectedLengths)
for j in range(len(newExpectedLens)): for j in range(len(newExpectedLens)):
emptyClasses[index][f"{activeCourses[index]['Description']}-{j}"]["expectedLen"] = newExpectedLens[j] emptyClasses[index][f"{index}-{j}"]["expectedLen"] = newExpectedLens[j]
else: else:
# In the case that the remaining requests are unable to be resolved # In the case that the remaining requests are unable to be resolved
@@ -449,45 +456,46 @@ def generateScheduleV3(students, courses):
# Will need to be ignored so later we can fold them into their alternative # Will need to be ignored so later we can fold them into their alternative
# choices # choices
for j in range(classRunCount): for j in range(classRunCount):
if emptyClasses[index][f"{activeCourses[index]['Description']}-{j}"]["expectedLen"] < classCap and remaining > 0: if emptyClasses[index][f"{index}-{j}"]["expectedLen"] < classCap and remaining > 0:
emptyClasses[index][f"{activeCourses[index]['Description']}-{j}"]["expectedLen"] += 1 emptyClasses[index][f"{index}-{j}"]["expectedLen"] += 1
remaining -= 1 remaining -= 1
# Step 2 part B # Step 3 Fill emptyClasses with Students
selectedCourses = {}
tempStudents = students tempStudents = students
while len(tempStudents) > 0: while len(tempStudents) > 0:
student = tempStudents[random.randint(0, len(students)-1)] student = tempStudents[random.randint(0, len(students)-1)]
altOffset = 0
alternates = [request for request in student["requests"] if request["alt"]] alternates = [request for request in student["requests"] if request["alt"]]
altOffset = None
if len(alternates) > 0: altOffset = 0
for request in (request for request in student["requests"] if not request["alt"] and request not in ["XAT--12A-S", "XAT--12B-S"]): for request in (request for request in student["requests"] if not request["alt"] and request not in ["XAT--12A-S", "XAT--12B-S"]):
course = request["CrsNo"] course = request["CrsNo"]
if course in existingClasses: getAvailableCourse = True
done = False while getAvailableCourse:
while not done: if course in emptyClasses:
breakCname = False # if course exists, get first available class
for cname in emptyClasses[course]: for cname in emptyClasses[course]:
if breakCname: break
if cname in selectedCourses: if cname in selectedCourses:
if len(selectedCourses[cname]["students"]) < emptyClasses[course][cname]["expectedLen"]: if len(selectedCourses[cname]["students"]) < emptyClasses[course][cname]["expectedLen"]:
# Class exists and there is room # Class exists with room for student
selectedCourses[cname]["students"].append(student["Pupil #"]) selectedCourses[cname]["students"].append(student["Pupil #"])
done = True getAvailableCourse = False
breakCname = True break
elif len(selectedCourses[cname]["students"]) == emptyClasses[course][cname]["expectedLen"]: elif len(selectedCourses[cname]["students"]) == emptyClasses[course][cname]["expectedLen"]:
# Class exists and there no room # If class is full, and is last class of that course
if cname[len(cname)-1] == f"{len(emptyClasses[course])-1}":
# If this is the last class in that course, fold student to alternate if altOffset is not None and altOffset <= len(alternates)-1:
if cname[len(cname)-1] == str((len(emptyClasses[course])-1)): # Use alternate
for i in range(len(alternates)): course = alternates[altOffset]["CrsNo"]
if i == altOffset: altOffset += 1
if i < len(alternates)-1: break
done = True # force stop to move to next class
else: else:
course = alternates[i] # Force break loop, ignore and let an admin
altOffset += 1 # Change offset in case we need another alternate # handle options to solve for missing class
breakCname = True getAvailableCourse = False
break
elif cname not in selectedCourses: elif cname not in selectedCourses:
selectedCourses[cname] = { selectedCourses[cname] = {
@@ -495,28 +503,25 @@ def generateScheduleV3(students, courses):
"CrsNo": course, "CrsNo": course,
"Description": courses[course]["Description"] "Description": courses[course]["Description"]
} }
done = True getAvailableCourse = False
breakCname = True break
elif course not in emptyClasses:
if altOffset is not None and altOffset <= len(alternates)-1:
# Use alternate
course = alternates[altOffset]["CrsNo"]
altOffset += 1
else: else:
#use alternate # Force break loop, ignore and let an admin
print("use alternate") # handle options to solve for missing class
getAvailableCourse = False
tempStudents.remove(student) tempStudents.remove(student)
# for course in selectedCourses: # Step 4 - Attempt to fit classes into timetable
# print("Class: ", selectedCourses[course]["Description"])
# print("Students: ", len(selectedCourses[course]["students"]), "\n")
# print("==============================")
# print("Total: ", len(selectedCourses))
with open("classes.json", "w") as outfile:
json.dump(selectedCourses, outfile, indent=2)
# Step 3 - Attempt to fit classes into timetable # Step 5 - Evaluate, move classes or students to fix
# Step 4 - Evaluate, move classes or students to fix
return [] return []
if __name__ == '__main__': if __name__ == '__main__':