finish step 5, being step 6
This commit is contained in:
1 parent
9a09218f86
commit
2ea40bfe6f
3 files changed
+54
-29
No files matched your search
@@ -38,7 +38,7 @@ from util.generateCourses import getSampleCourses
|
||||
}
|
||||
'''
|
||||
|
||||
minReq, median, classCap, blockClassLimit = 18, 24, 30, 26
|
||||
minReq, median, classCap = 18, 24, 30
|
||||
mockStudents = []
|
||||
activeCourses = {}
|
||||
running = {
|
||||
@@ -60,7 +60,7 @@ running = {
|
||||
# It starts by trying to get all classes full and give all students a full class list.
|
||||
# Then it starts to attempt to fit all classes into a timetable, making corretions along
|
||||
# the way. Corrections being moving a students class
|
||||
def generateScheduleV3(students: list, courses: dict) -> dict[str, dict]:
|
||||
def generateScheduleV3(students: list, courses: dict, blockClassLimit: int=40, studentsDir: str="../output/students.json") -> dict[str, dict]:
|
||||
def equal(l): # Used to equalize list of numbers
|
||||
q,r = divmod(sum(l),len(l))
|
||||
return [q+1]*r + [q]*(len(l)-r)
|
||||
@@ -80,7 +80,7 @@ def generateScheduleV3(students: list, courses: dict) -> dict[str, dict]:
|
||||
# Step 2 - Generate empty classes
|
||||
allClassRunCounts = []
|
||||
courseRunInfo = {} # Generated now, used in step 4
|
||||
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 step 3
|
||||
# calculate # of times to run class
|
||||
for i in range(len(activeCourses)):
|
||||
index = list(activeCourses)[i]
|
||||
@@ -164,16 +164,15 @@ def generateScheduleV3(students: list, courses: dict) -> dict[str, dict]:
|
||||
}
|
||||
allClassRunCounts.append(classRunCount)
|
||||
|
||||
|
||||
# Step 3 Fill emptyClasses with Students
|
||||
selectedCourses = {}
|
||||
tempStudents = students
|
||||
tempStudents = list(students)
|
||||
|
||||
while len(tempStudents) > 0:
|
||||
student = tempStudents[random.randint(0, len(students)-1)]
|
||||
student = tempStudents[random.randint(0, len(tempStudents)-1)]
|
||||
|
||||
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["CrsNo"] not in ["XAT--12A-S", "XAT--12B-S"]):
|
||||
course = request["CrsNo"]
|
||||
getAvailableCourse = True
|
||||
@@ -184,16 +183,19 @@ def generateScheduleV3(students: list, courses: dict) -> dict[str, dict]:
|
||||
if cname in selectedCourses:
|
||||
if len(selectedCourses[cname]["students"]) < emptyClasses[course][cname]["expectedLen"]:
|
||||
# Class exists with room for student
|
||||
selectedCourses[cname]["students"].append(student["Pupil #"])
|
||||
selectedCourses[cname]["students"].append({
|
||||
"Pupil #": student["Pupil #"],
|
||||
"index": student["studentIndex"]
|
||||
})
|
||||
getAvailableCourse = False
|
||||
break
|
||||
elif len(selectedCourses[cname]["students"]) == emptyClasses[course][cname]["expectedLen"]:
|
||||
# If class is full, and is last class of that course
|
||||
if cname[len(cname)-1] == f"{len(emptyClasses[course])-1}":
|
||||
if altOffset is not None and altOffset <= len(alternates)-1:
|
||||
if len(alternates) > 0:
|
||||
# Use alternate
|
||||
course = alternates[altOffset]["CrsNo"]
|
||||
altOffset += 1
|
||||
course = alternates[0]["CrsNo"]
|
||||
alternates.remove(course)
|
||||
break
|
||||
else:
|
||||
# Force break loop, ignore and let an admin
|
||||
@@ -202,7 +204,10 @@ def generateScheduleV3(students: list, courses: dict) -> dict[str, dict]:
|
||||
break
|
||||
elif cname not in selectedCourses:
|
||||
selectedCourses[cname] = {
|
||||
"students": [student["Pupil #"]],
|
||||
"students": [{
|
||||
"Pupil #": student["Pupil #"],
|
||||
"index": student["studentIndex"]
|
||||
}],
|
||||
"CrsNo": course,
|
||||
"Description": courses[course]["Description"]
|
||||
}
|
||||
@@ -210,18 +215,20 @@ def generateScheduleV3(students: list, courses: dict) -> dict[str, dict]:
|
||||
break
|
||||
|
||||
elif course not in emptyClasses:
|
||||
if altOffset is not None and altOffset <= len(alternates)-1:
|
||||
if len(alternates) > 0:
|
||||
# Use alternate
|
||||
course = alternates[altOffset]["CrsNo"]
|
||||
altOffset += 1
|
||||
course = alternates[0]["CrsNo"]
|
||||
alternates.remove(course)
|
||||
else:
|
||||
# Force break loop, ignore and let an admin
|
||||
# handle options to solve for missing class
|
||||
getAvailableCourse = False
|
||||
|
||||
students[student["studentIndex"]]["remainingAlts"] = alternates
|
||||
tempStudents.remove(student)
|
||||
|
||||
# Step 4 - Attempt to fit classes into timetable
|
||||
|
||||
# Step 4 - Attempt to fit classes into timetable
|
||||
def stepIndex(offset: int, stepType: int) -> int:
|
||||
# stepType 0 is for stepping between first and second semester
|
||||
if stepType == 0:
|
||||
@@ -264,7 +271,7 @@ def generateScheduleV3(students: list, courses: dict) -> dict[str, dict]:
|
||||
while not classInserted:
|
||||
|
||||
blockIndex += offset
|
||||
if len(running[list(running)[blockIndex]]) < 40:
|
||||
if len(running[list(running)[blockIndex]]) < blockClassLimit:
|
||||
running[list(running)[blockIndex]][cname] = {
|
||||
"CrsNo": course,
|
||||
"Description": emptyClasses[course][cname]["Description"],
|
||||
@@ -303,7 +310,7 @@ def generateScheduleV3(students: list, courses: dict) -> dict[str, dict]:
|
||||
running[f"block{leastBlock+offset}"][course] = {
|
||||
"CrsNo": course,
|
||||
"Description": emptyClasses[course][cname]["Description"],
|
||||
"Students": selectedCourses[cname]["students"],
|
||||
"students": selectedCourses[cname]["students"],
|
||||
}
|
||||
|
||||
allClassRunCounts[index] -= 1
|
||||
@@ -313,11 +320,25 @@ def generateScheduleV3(students: list, courses: dict) -> dict[str, dict]:
|
||||
allClassRunCounts.remove(allClassRunCounts[index])
|
||||
courseRunInfo.pop(list(courseRunInfo)[index])
|
||||
|
||||
|
||||
# Step 5 - Fill student schedule
|
||||
for block in running:
|
||||
for cname in running[block]:
|
||||
for student in running[block][cname]["students"]:
|
||||
students[student["index"]]["schedule"][block].append(cname)
|
||||
|
||||
with open(studentsDir, "w") as outfile:
|
||||
json.dump(students, outfile, indent=2)
|
||||
|
||||
|
||||
# Step 6 - Evaluate, move classes or students to fix
|
||||
for student in students:
|
||||
for block in student["schedule"]:
|
||||
pass
|
||||
|
||||
return running
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Processing...")
|
||||
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ if __name__ == '__main__':
|
||||
samplemockCourses = getSampleCourses("./sample_data/course_selection_data.csv", True)
|
||||
timetable = {}
|
||||
timetable["Version"] = 3
|
||||
timetable["timetable"] = generateScheduleV3(sampleStudents, samplemockCourses)
|
||||
timetable["timetable"] = generateScheduleV3(sampleStudents, samplemockCourses, 40, "./output/students.json")
|
||||
|
||||
else:
|
||||
print("Invalid argument")
|
||||
|
||||
+14
-10
@@ -51,6 +51,7 @@ def getSampleStudents(data_dir: str, log: bool = False) -> list[dict]:
|
||||
"Description": row["Description"],
|
||||
"alt": alternate
|
||||
})
|
||||
if row["CrsNo"] in ["XAT--12A-S", "XAT--12B-S"]: mockStudents[student["studentIndex"]]["expectedClasses"] -= 1
|
||||
else:
|
||||
newStudent = {
|
||||
"Pupil #": row["Pupil #"],
|
||||
@@ -60,19 +61,22 @@ def getSampleStudents(data_dir: str, log: bool = False) -> list[dict]:
|
||||
"alt": alternate
|
||||
}],
|
||||
"schedule": {
|
||||
"block1": "",
|
||||
"block2": "",
|
||||
"block3": "",
|
||||
"block4": "",
|
||||
"block5": "",
|
||||
"block6": "",
|
||||
"block7": "",
|
||||
"block8": "",
|
||||
"block9": "",
|
||||
"block10": ""
|
||||
"block1": [],
|
||||
"block2": [],
|
||||
"block3": [],
|
||||
"block4": [],
|
||||
"block5": [],
|
||||
"block6": [],
|
||||
"block7": [],
|
||||
"block8": [],
|
||||
"block9": [],
|
||||
"block10": []
|
||||
},
|
||||
"expectedClasses": 8,
|
||||
"remainingAlts": [],
|
||||
"studentIndex": len(mockStudents)
|
||||
}
|
||||
if row["CrsNo"] in ["XAT--12A-S", "XAT--12B-S"]: mockStudents[student["studentIndex"]]["expectedClasses"] -= 1
|
||||
mockStudents.append(newStudent)
|
||||
|
||||
if log:
|
||||
|
||||
Reference in new issue
Block a user