update to latest

This commit is contained in:
SowinskiBraeden committed 2022-06-21 20:16:58 -07:00
1 parent cb7298077d
commit 27d84c3c99
5 files changed
+65 -51

No files matched your search

+1
View File
@@ -1,3 +1,4 @@
#! python
import json import json
f = open('./output/students.json') f = open('./output/students.json')
+38 -44
View File
@@ -1,6 +1,5 @@
#!/usr/bin/env python3 #! python
import json import json
import math
import random import random
from inspect import currentframe from inspect import currentframe
@@ -22,7 +21,6 @@ from util.generateCourses import getSampleCourses
... ...
} }
running example: running example:
running: { running: {
"block1": { "block1": {
@@ -43,23 +41,17 @@ def getLineNumber(): return currentframe().f_back.f_lineno
# Takes in information to create or add a new conflict # Takes in information to create or add a new conflict
# Returns if the particular student has a previous error # Returns if the particular student has a previous error
def newConflict(pupilNum: str, email: str, type: str, code: str, description: str, logs: dict) -> bool: def newConflict(pupilNum: str, email: str, conflictType: str, code: str, description: str, logs: dict) -> bool:
exists = True if pupilNum in logs else False exists = True if pupilNum in logs else False
if exists: logs[pupilNum].append({ log = {
"Pupil #": pupilNum, "Pupil #": pupilNum,
"Email": email, "Email": email,
"Type": type, "Type": conflictType,
"Code": code, "Code": code,
"Conflict": description "Conflict": description
}) }
else: if exists: logs[pupilNum].append(log)
logs[pupilNum] = [{ else: logs[pupilNum] = [log]
"Pupil #": pupilNum,
"Email": email,
"Type": type,
"Code": code,
"Conflict": description
}]
return exists return exists
minReq, median, classCap = 18, 24, 30 minReq, median, classCap = 18, 24, 30
@@ -79,7 +71,7 @@ running = {
# These are the codes for Flex (spare) blocks # These are the codes for Flex (spare) blocks
# Semester 1 and 2 # Semester 1 and 2
flex = ["XAT--12A-S", "XAT--12B-S"] flex = ("XAT--12A-S", "XAT--12B-S")
# V3 differs a lot by V1/2 as it does not focus on fitting the classes # V3 differs a lot by V1/2 as it does not focus on fitting the classes
# into the time table first. # into the time table first.
@@ -118,7 +110,7 @@ def generateScheduleV3(
for i in range(len(activeCourses)): for i in range(len(activeCourses)):
index = list(activeCourses)[i] index = list(activeCourses)[i]
if index not in emptyClasses: emptyClasses[index] = {} if index not in emptyClasses: emptyClasses[index] = {}
classRunCount = math.floor(activeCourses[index]["Requests"] / median) classRunCount = activeCourses[index]["Requests"] // median
remaining = activeCourses[index]["Requests"] % median remaining = activeCourses[index]["Requests"] % median
# Put # of classRunCount classes in emptyClasses # Put # of classRunCount classes in emptyClasses
@@ -269,14 +261,10 @@ def generateScheduleV3(
# Step 4 - Attempt to fit classes into timetable # Step 4 - Attempt to fit classes into timetable
def stepIndex(offset: int, stepType: int) -> int: def stepIndex(offset: int, stepType: int) -> int:
# stepType 0 is for stepping between first and second semester # stepType 0 is for stepping between first and second semester
if stepType == 0: if stepType == 0: return 5 if offset == 0 or offset == -4 else -4
if offset == 0 or offset == -4: return 5
else: return -4
# stepType 1 is for stepping between second and first semester # stepType 1 is for stepping between second and first semester
elif stepType == 1: elif stepType == 1: return -5 if offset == 0 or offset == 6 else 6
if offset == 0 or offset == 6: return -5
else: return 6
# Return Error if code is altered to cause error # Return Error if code is altered to cause error
else: raise SystemExit(f"Invalid 'stepType' in func 'stepIndex' line {getLineNumber()}") else: raise SystemExit(f"Invalid 'stepType' in func 'stepIndex' line {getLineNumber()}")
@@ -289,12 +277,13 @@ def generateScheduleV3(
# Tally first and second semester # Tally first and second semester
sem1, sem2 = 0, 0 sem1, sem2 = 0, 0
sem1List, sem2List = {}, {} sem1List, sem2List = {}, {}
for i in range(1, 6): for i in range(1, 11):
sem1 += len(running[f"block{i}"]) if i <= 5:
sem1List[f"block{i}"] = running[f"block{i}"] sem1 += len(running[f"block{i}"])
for i in range(5, 11): sem1List[f"block{i}"] = running[f"block{i}"]
sem2 += len(running[f"block{i}"]) elif i > 5:
sem2List[f"block{i}"] = running[f"block{i}"] sem2 += len(running[f"block{i}"])
sem2List[f"block{i}"] = running[f"block{i}"]
# If there is more than one class Running # If there is more than one class Running
if allClassRunCounts[index] > 1: if allClassRunCounts[index] > 1:
@@ -330,16 +319,15 @@ def generateScheduleV3(
semBlocks = [] semBlocks = []
offset = 1 offset = 1
# If sem1 is less than or equal to sem2, add to sem1
if sem1 <= sem2: if sem1 <= sem2:
for block in sem1List: for block in sem1List:
semBlocks.append(len(block)) semBlocks.append(len(block))
# If sem1 is less than or equal to sem2, add to sem1
if sem1 <= sem2: [semBlocks.append(len(block)) for block in sem1List]
# If sem2 is less than sem1, add to sem2 # If sem2 is less than sem1, add to sem2
elif sem1 > sem2: elif sem1 > sem2: [semBlocks.append(len(block)) for block in sem2List]
offset = 5
for block in sem2List:
semBlocks.append(len(block))
# Get block with least classes # Get block with least classes
leastBlock = semBlocks.index(min(semBlocks)) leastBlock = semBlocks.index(min(semBlocks))
@@ -403,14 +391,14 @@ def generateScheduleV3(
# Check if conflicts have been resolved # Check if conflicts have been resolved
blocks = [student["schedule"][block] for block in student["schedule"]] blocks = [student["schedule"][block] for block in student["schedule"]]
# If there is exceptions, make them look normal in blocks # If there is exceptions, make them look normal in blocks
# list to ginore them when looking for clashes, and not to # list to ignore them when looking for clashes, and not to
# accidently overwrite while evaluating other classes # accidently overwrite while evaluating other classes
if len(exceptions) > 0: if len(exceptions) > 0:
for i in range(len(blocks)): for i in range(len(blocks)):
if i in exceptions: blocks[i] = ['EXPT'] if i in exceptions: blocks[i] = ['EXPT']
conflicts = sum(1 for b in blocks if len(b)>1) conflicts = sum(1 for b in blocks if len(b)>1)
if conflicts == 0: hasConflicts = False if conflicts == 0: break
elif conflicts > 0: elif conflicts > 0:
@@ -586,14 +574,20 @@ def generateScheduleV3(
} }
} }
# Update Student records
with open(studentsDir, "w") as outfile:
json.dump(students, outfile, indent=2)
# Log Conflict to records # Log Conflict to records
with open(conflictsDir, "w") as outfile: with open(conflictsDir, "w") as outfile:
json.dump(finalConflictLogs, outfile, indent=2) json.dump(finalConflictLogs, outfile, indent=2)
for student in students:
for block in student["schedule"]:
if len(student["schedule"][block]) == 0:
if int(block[len(block)-1]) <= 5: student["schedule"][block].append(flex[0])
elif int(block[len(block)-1]) > 5: student["schedule"][block].append(flex[1])
# Update Student records
with open(studentsDir, "w") as outfile:
json.dump(students, outfile, indent=2)
return running return running
if __name__ == '__main__': if __name__ == '__main__':
+23 -4
View File
@@ -1,6 +1,9 @@
#!/usr/bin/python3 #! python
from prettytable import PrettyTable from prettytable import PrettyTable
from typing import Tuple from typing import Tuple
from time import time, sleep
import itertools
import threading
import json import json
import sys import sys
@@ -11,6 +14,15 @@ from util.generateCourses import getSampleCourses
# Import Algorithm # Import Algorithm
from scheduleGenerator.generator import generateScheduleV3 from scheduleGenerator.generator import generateScheduleV3
done = False
def processing():
for c in itertools.cycle(['|', '/', '-', '\\']):
if done: break
sys.stdout.write(f'\rProcessing {c}')
sys.stdout.flush()
sleep(0.1)
def errorOutput(students) -> Tuple[PrettyTable, dict, dict]: def errorOutput(students) -> Tuple[PrettyTable, dict, dict]:
# Error Table calulation / output # Error Table calulation / output
f = open('./output/conflicts.json') f = open('./output/conflicts.json')
@@ -34,7 +46,11 @@ def errorOutput(students) -> Tuple[PrettyTable, dict, dict]:
if __name__ == '__main__': if __name__ == '__main__':
if len(sys.argv) == 1: if len(sys.argv) == 1:
print("Processing...\n") print()
st = time() # Start time
t = threading.Thread(target=processing)
t.start() # Start animation
sampleStudents = getSampleStudents("./sample_data/course_selection_data.csv", True) sampleStudents = getSampleStudents("./sample_data/course_selection_data.csv", True)
samplemockCourses = getSampleCourses("./sample_data/course_selection_data.csv", True) samplemockCourses = getSampleCourses("./sample_data/course_selection_data.csv", True)
@@ -42,6 +58,11 @@ if __name__ == '__main__':
timetable["Version"] = 3 timetable["Version"] = 3
timetable["timetable"] = generateScheduleV3(sampleStudents, samplemockCourses, 40, "./output/students.json", "./output/conflicts.json") timetable["timetable"] = generateScheduleV3(sampleStudents, samplemockCourses, 40, "./output/students.json", "./output/conflicts.json")
done = True # End Animation
et = time() # End time
elapsed_time = round((et - st), 3) # Execution time
print(f'\n\nDone - Finished in {elapsed_time} seconds\n')
errors, _, _ = errorOutput(sampleStudents) errors, _, _ = errorOutput(sampleStudents)
print(errors) print(errors)
@@ -69,5 +90,3 @@ if __name__ == '__main__':
with open("./output/timetable.json", "w") as outfile: with open("./output/timetable.json", "w") as outfile:
json.dump(timetable, outfile, indent=2) json.dump(timetable, outfile, indent=2)
print("\nDone")
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env python3 #! python
import json import json
import csv import csv
+2 -2
View File
@@ -1,8 +1,8 @@
#!/usr/bin/env python3 #! python
import json import json
import csv import csv
flex= ["XAT--12A-S", "XAT--12B-S"] flex= ("XAT--12A-S", "XAT--12B-S")
mockStudents: list[dict] = [] mockStudents: list[dict] = []