From 5c24ada7bea1fc0477b5b60c4bce2554d5523d4e Mon Sep 17 00:00:00 2001 From: m-jishnu Date: Wed, 7 Feb 2024 23:15:21 +0530 Subject: [PATCH 1/4] update to pyqt6 --- README.md | 2 +- components/GeneticAlgorithm.py | 608 ++++++++++++------ components/ImportExportHandler.py | 2 +- components/ScheduleParser.py | 40 +- components/TableModel.py | 14 +- components/Timetable.py | 68 +- .../__pycache__/Database.cpython-312.pyc | Bin 0 -> 3506 bytes .../GeneticAlgorithm.cpython-312.pyc | Bin 0 -> 49636 bytes .../ImportExportHandler.cpython-312.pyc | Bin 0 -> 3598 bytes .../ResourceTracker.cpython-312.pyc | Bin 0 -> 1171 bytes .../ScenarioComposer.cpython-312.pyc | Bin 0 -> 5062 bytes .../ScheduleParser.cpython-312.pyc | Bin 0 -> 6020 bytes .../__pycache__/Settings.cpython-312.pyc | Bin 0 -> 1946 bytes .../__pycache__/TableModel.cpython-312.pyc | Bin 0 -> 3027 bytes .../__pycache__/Timetable.cpython-312.pyc | Bin 0 -> 5710 bytes .../__pycache__/Utilities.cpython-312.pyc | Bin 0 -> 1870 bytes containers/Generate.py | 149 +++-- containers/Instructor.py | 60 +- containers/Main.py | 171 +++-- containers/ResultViewer.py | 307 ++++++--- containers/Room.py | 55 +- containers/Section.py | 138 ++-- containers/Share.py | 79 ++- containers/Subject.py | 115 ++-- .../__pycache__/Generate.cpython-312.pyc | Bin 0 -> 15366 bytes .../__pycache__/Instructor.cpython-312.pyc | Bin 0 -> 10589 bytes containers/__pycache__/Main.cpython-312.pyc | Bin 0 -> 23118 bytes .../__pycache__/ResultViewer.cpython-312.pyc | Bin 0 -> 17029 bytes containers/__pycache__/Room.cpython-312.pyc | Bin 0 -> 10306 bytes .../__pycache__/Section.cpython-312.pyc | Bin 0 -> 20332 bytes containers/__pycache__/Share.cpython-312.pyc | Bin 0 -> 8324 bytes .../__pycache__/Subject.cpython-312.pyc | Bin 0 -> 15405 bytes main.py | 6 +- py_ui/Generate.py | 50 +- py_ui/Instructor.py | 32 +- py_ui/Main.py | 257 ++++---- py_ui/Result.py | 58 +- py_ui/Room.py | 30 +- py_ui/Section.py | 39 +- py_ui/Share.py | 18 +- py_ui/Subject.py | 52 +- py_ui/__pycache__/Generate.cpython-312.pyc | Bin 0 -> 11596 bytes py_ui/__pycache__/Instructor.cpython-312.pyc | Bin 0 -> 5718 bytes py_ui/__pycache__/Main.cpython-312.pyc | Bin 0 -> 52121 bytes py_ui/__pycache__/Result.cpython-312.pyc | Bin 0 -> 14354 bytes py_ui/__pycache__/Room.cpython-312.pyc | Bin 0 -> 5531 bytes py_ui/__pycache__/Section.cpython-312.pyc | Bin 0 -> 6721 bytes py_ui/__pycache__/Share.cpython-312.pyc | Bin 0 -> 2981 bytes py_ui/__pycache__/Subject.cpython-312.pyc | Bin 0 -> 9961 bytes settings.json | 23 +- 50 files changed, 1489 insertions(+), 884 deletions(-) create mode 100644 components/__pycache__/Database.cpython-312.pyc create mode 100644 components/__pycache__/GeneticAlgorithm.cpython-312.pyc create mode 100644 components/__pycache__/ImportExportHandler.cpython-312.pyc create mode 100644 components/__pycache__/ResourceTracker.cpython-312.pyc create mode 100644 components/__pycache__/ScenarioComposer.cpython-312.pyc create mode 100644 components/__pycache__/ScheduleParser.cpython-312.pyc create mode 100644 components/__pycache__/Settings.cpython-312.pyc create mode 100644 components/__pycache__/TableModel.cpython-312.pyc create mode 100644 components/__pycache__/Timetable.cpython-312.pyc create mode 100644 components/__pycache__/Utilities.cpython-312.pyc create mode 100644 containers/__pycache__/Generate.cpython-312.pyc create mode 100644 containers/__pycache__/Instructor.cpython-312.pyc create mode 100644 containers/__pycache__/Main.cpython-312.pyc create mode 100644 containers/__pycache__/ResultViewer.cpython-312.pyc create mode 100644 containers/__pycache__/Room.cpython-312.pyc create mode 100644 containers/__pycache__/Section.cpython-312.pyc create mode 100644 containers/__pycache__/Share.cpython-312.pyc create mode 100644 containers/__pycache__/Subject.cpython-312.pyc create mode 100644 py_ui/__pycache__/Generate.cpython-312.pyc create mode 100644 py_ui/__pycache__/Instructor.cpython-312.pyc create mode 100644 py_ui/__pycache__/Main.cpython-312.pyc create mode 100644 py_ui/__pycache__/Result.cpython-312.pyc create mode 100644 py_ui/__pycache__/Room.cpython-312.pyc create mode 100644 py_ui/__pycache__/Section.cpython-312.pyc create mode 100644 py_ui/__pycache__/Share.cpython-312.pyc create mode 100644 py_ui/__pycache__/Subject.cpython-312.pyc diff --git a/README.md b/README.md index 902edf1..a7584aa 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ A research on creation of metaheuristic university class timetable scheduling so ### Dependencies: 1. Numpy -2. PyQT5 +2. PyQt6 3. psutil ### Educational Documentation diff --git a/components/GeneticAlgorithm.py b/components/GeneticAlgorithm.py index acd8e90..d83e2f6 100644 --- a/components/GeneticAlgorithm.py +++ b/components/GeneticAlgorithm.py @@ -1,4 +1,4 @@ -from PyQt5 import QtCore +from PyQt6 import QtCore from components import Settings from operator import itemgetter from collections import Counter @@ -23,16 +23,16 @@ def __init__(self, data): self.running = True self.chromosomes = [] self.data = { - 'rooms': [], - 'instructors': [], - 'sections': [], - 'sharings': [], - 'subjects': [] + "rooms": [], + "instructors": [], + "sections": [], + "sharings": [], + "subjects": [], } self.stayInRoomAssignments = {} - self.tournamentSize = .04 - self.elitePercent = .05 - self.mutationRate = .10 + self.tournamentSize = 0.04 + self.elitePercent = 0.05 + self.mutationRate = 0.10 self.lowVariety = 55 self.highestFitness = 0 self.lowestFitness = 100 @@ -43,24 +43,26 @@ def __init__(self, data): self.tempSections = None self.data = data self.settings = Settings.getSettings() - self.stopWhenMaxFitnessAt = self.settings['maximum_fitness'] + self.stopWhenMaxFitnessAt = self.settings["maximum_fitness"] super().__init__() def initialization(self): # Generate population based on minimum population - self.generateChromosome(self.settings['minimum_population']) + self.generateChromosome(self.settings["minimum_population"]) def generateChromosome(self, quantity): for i in range(quantity): - self.statusSignal.emit('Creating #{} of {} Chromosomes'.format(i, quantity)) + self.statusSignal.emit("Creating #{} of {} Chromosomes".format(i, quantity)) self.tempChromosome = Chromosome(self.data) # {id: [[subjectIds](, stay|roomId = False)]} - self.tempSections = sections = {key: [value[2], value[3]] for (key, value) in - copy.deepcopy(self.data['sections']).items()} + self.tempSections = sections = { + key: [value[2], value[3]] + for (key, value) in copy.deepcopy(self.data["sections"]).items() + } # {id: [subjectId, [sections]]} - self.tempSharings = sharings = copy.deepcopy(self.data['sharings']) + self.tempSharings = sharings = copy.deepcopy(self.data["sharings"]) # [roomIds] - self.rooms = rooms = list(self.data['rooms'].keys()) + self.rooms = rooms = list(self.data["rooms"].keys()) # Distributed Room selection for staying sections if not len(self.stayInRoomAssignments): selectedRooms = [] @@ -71,9 +73,9 @@ def generateChromosome(self, quantity): while not room: attempts += 1 candidate = np.random.choice(rooms) - if attempts == self.settings['generation_tolerance']: + if attempts == self.settings["generation_tolerance"]: room = candidate - if self.data['rooms'][candidate][1] == 'lec': + if self.data["rooms"][candidate][1] == "lec": if candidate not in selectedRooms: selectedRooms.append(copy.deepcopy(candidate)) room = candidate @@ -94,9 +96,11 @@ def generateSubjectPlacementsForSharings(self, sharings): sharingOrder = list(sharings.keys()) np.random.shuffle(sharingOrder) for sharing in sharingOrder: - result = self.generateSubjectPlacement(sharings[sharing][1], sharings[sharing][0], sharing) + result = self.generateSubjectPlacement( + sharings[sharing][1], sharings[sharing][0], sharing + ) if not result: - self.tempChromosome.data['unplaced']['sharings'].append(sharing) + self.tempChromosome.data["unplaced"]["sharings"].append(sharing) # {id: [[subjectIds](, stay|roomId = False)]} def generateSubjectPlacementsForSections(self, sections): @@ -109,9 +113,13 @@ def generateSubjectPlacementsForSections(self, sections): if not len(subjectList): continue subjectToPlace = np.random.randint(0, len(subjectList)) - result = self.generateSubjectPlacement([section], subjectList[subjectToPlace]) + result = self.generateSubjectPlacement( + [section], subjectList[subjectToPlace] + ) if not result: - self.tempChromosome.data['unplaced']['sections'][section].append(subjectList[subjectToPlace]) + self.tempChromosome.data["unplaced"]["sections"][section].append( + subjectList[subjectToPlace] + ) sections[section][0].pop(subjectToPlace) # Section = [id], Subject = int (id) @@ -120,9 +128,12 @@ def generateSubjectPlacement(self, section, subject, sharing=False): generationAttempt = 0 error = None - stayInRoom = False if section[0] not in self.stayInRoomAssignments.keys() else self.stayInRoomAssignments[ - section[0]] - subjectDetails = self.data['subjects'][subject] + stayInRoom = ( + False + if section[0] not in self.stayInRoomAssignments.keys() + else self.stayInRoomAssignments[section[0]] + ) + subjectDetails = self.data["subjects"][subject] room = stayInRoom if stayInRoom else None # [[day/s], startingTimeSlot, length] @@ -132,14 +143,18 @@ def generateSubjectPlacement(self, section, subject, sharing=False): while generating: # Control generation to avoid impossible combinations generationAttempt += 1 - if generationAttempt > self.settings['generation_tolerance']: + if generationAttempt > self.settings["generation_tolerance"]: generating = False return False # Allow random meeting patterns if generation is taking long - forceRandomMeeting = True if generationAttempt > self.settings['generation_tolerance'] / 2 else False + forceRandomMeeting = ( + True + if generationAttempt > self.settings["generation_tolerance"] / 2 + else False + ) # First time generation if not error: - if not stayInRoom or (stayInRoom and subjectDetails[6] == 'lab'): + if not stayInRoom or (stayInRoom and subjectDetails[6] == "lab"): room = self.selectRoom(subject) if len(subjectDetails[4]) > 1: instructor = self.selectInstructor(subject) @@ -154,7 +169,9 @@ def generateSubjectPlacement(self, section, subject, sharing=False): if np.random.randint(0, 2): error = 3 elif error == 1: - if not stayInRoom or (stayInRoom and subjectDetails[6] == 'lab'): + if not stayInRoom or ( + stayInRoom and subjectDetails[6] == "lab" + ): room = self.selectRoom(subject) else: error = 3 @@ -179,13 +196,13 @@ def selectRoom(self, subject): room = None while not room: candidate = np.random.choice(self.rooms) - if self.data['subjects'][subject][6] == self.data['rooms'][candidate][1]: + if self.data["subjects"][subject][6] == self.data["rooms"][candidate][1]: room = candidate return room def selectInstructor(self, subject): instructor = None - subjectInstructors = self.data['subjects'][subject][4] + subjectInstructors = self.data["subjects"][subject][4] while not instructor and len(subjectInstructors): instructor = np.random.choice(subjectInstructors) return instructor @@ -194,19 +211,24 @@ def selectTimeDetails(self, subject, forceRandomMeeting): meetingPatterns = [[0, 2, 4], [1, 3]] days = [0, 1, 2, 3, 4, 5] np.random.shuffle(days) - hours = self.data['subjects'][subject][1] + hours = self.data["subjects"][subject][1] # Check if hours can be splitted with minimum session of 1 hour or 2 timeslot - if hours > 1.5 and ((hours / 3) % .5 == 0 or (hours / 2) % .5 == 0) and self.data['subjects'][subject][5]: + if ( + hours > 1.5 + and ((hours / 3) % 0.5 == 0 or (hours / 2) % 0.5 == 0) + and self.data["subjects"][subject][5] + ): # If hours is divisible by two and three - if (hours / 3) % .5 == 0 and (hours / 2) % .5 == 0: + if (hours / 3) % 0.5 == 0 and (hours / 2) % 0.5 == 0: meetingPattern = np.random.choice(meetingPatterns) + if len(meetingPattern) == 3: meetingPattern = days[0:3] if forceRandomMeeting else meetingPattern hours = hours / 3 else: meetingPattern = days[0:2] if forceRandomMeeting else meetingPattern hours = hours / 2 - elif (hours / 3) % .5 == 0: + elif (hours / 3) % 0.5 == 0: meetingPattern = days[0:3] if forceRandomMeeting else meetingPatterns[0] hours = hours / 3 else: @@ -216,11 +238,11 @@ def selectTimeDetails(self, subject, forceRandomMeeting): else: meetingPattern = [np.random.randint(0, 6)] # To convert hours into timetable timeslots - hours = hours / .5 + hours = hours / 0.5 startingTimeslot = False # Starting slot selection - startingTime = self.settings['starting_time'] - endingTime = self.settings['ending_time'] + startingTime = self.settings["starting_time"] + endingTime = self.settings["ending_time"] while not startingTimeslot: candidate = np.random.randint(0, endingTime - startingTime + 1) # Validate if subject will not overpass operation time @@ -234,46 +256,79 @@ def evaluate(self): self.lowestFitness = 100 self.highestFitness = 0 for index, chromosome in enumerate(self.chromosomes): - self.statusSignal.emit('Evaluating #{} of {} Chromosomes'.format(index + 1, len(self.chromosomes))) + self.statusSignal.emit( + "Evaluating #{} of {} Chromosomes".format( + index + 1, len(self.chromosomes) + ) + ) chromosome.fitness = self.evaluateAll(chromosome) totalChromosomeFitness += chromosome.fitness self.averageFitness = totalChromosomeFitness / len(self.chromosomes) - self.highestFitness = chromosome.fitness if chromosome.fitness > self.highestFitness else self.highestFitness - self.lowestFitness = chromosome.fitness if chromosome.fitness < self.lowestFitness else self.lowestFitness - chromosomeFitness = sorted(enumerate(map(lambda chromosome: chromosome.fitness, self.chromosomes)), - key=itemgetter(1)) + self.highestFitness = ( + chromosome.fitness + if chromosome.fitness > self.highestFitness + else self.highestFitness + ) + self.lowestFitness = ( + chromosome.fitness + if chromosome.fitness < self.lowestFitness + else self.lowestFitness + ) + chromosomeFitness = sorted( + enumerate(map(lambda chromosome: chromosome.fitness, self.chromosomes)), + key=itemgetter(1), + ) # Emit top five chromosomes self.dataSignal.emit( - list(map(lambda chromosome: [self.chromosomes[chromosome[0]], chromosome[1]], chromosomeFitness[-5:]))) + list( + map( + lambda chromosome: [self.chromosomes[chromosome[0]], chromosome[1]], + chromosomeFitness[-5:], + ) + ) + ) # Evaluation weight depends on settings def evaluateAll(self, chromosome): subjectPlacement = self.evaluateSubjectPlacements(chromosome) - lunchBreak = self.evaluateLunchBreak(chromosome) if self.settings['lunchbreak'] else 100 + lunchBreak = ( + self.evaluateLunchBreak(chromosome) if self.settings["lunchbreak"] else 100 + ) studentRest = self.evaluateStudentRest(chromosome) instructorRest = self.evaluateInstructorRest(chromosome) idleTime = self.evaluateStudentIdleTime(chromosome) meetingPattern = self.evaluateMeetingPattern(chromosome) instructorLoad = self.evaluateInstructorLoad(chromosome) - chromosome.fitnessDetails = copy.deepcopy([subjectPlacement, lunchBreak, studentRest, instructorRest, idleTime, - meetingPattern, instructorLoad]) - matrix = self.settings['evaluation_matrix'] + chromosome.fitnessDetails = copy.deepcopy( + [ + subjectPlacement, + lunchBreak, + studentRest, + instructorRest, + idleTime, + meetingPattern, + instructorLoad, + ] + ) + matrix = self.settings["evaluation_matrix"] return round( - (subjectPlacement * matrix['subject_placement'] / 100) + - (lunchBreak * matrix['lunch_break'] / 100) + - (studentRest * matrix['student_rest'] / 100) + - (instructorRest * matrix['instructor_rest'] / 100) + - (idleTime * matrix['idle_time'] / 100) + - (meetingPattern * matrix['meeting_pattern'] / 100) + - (instructorLoad * matrix['instructor_load'] / 100), - 2 + (subjectPlacement * matrix["subject_placement"] / 100) + + (lunchBreak * matrix["lunch_break"] / 100) + + (studentRest * matrix["student_rest"] / 100) + + (instructorRest * matrix["instructor_rest"] / 100) + + (idleTime * matrix["idle_time"] / 100) + + (meetingPattern * matrix["meeting_pattern"] / 100) + + (instructorLoad * matrix["instructor_load"] / 100), + 2, ) # = ((subjects - unplacedSubjects) / subjects) * 100 def evaluateSubjectPlacements(self, chromosome): - sections = copy.deepcopy({key: value[2] for key, value in self.data['sections'].items()}) - sharings = self.data['sharings'] - chromosomeUnplacedData = chromosome.data['unplaced'] + sections = copy.deepcopy( + {key: value[2] for key, value in self.data["sections"].items()} + ) + sharings = self.data["sharings"] + chromosomeUnplacedData = chromosome.data["unplaced"] # Number of subjects that are in sharing sharingSubjects = 0 # Remove section subjects that are shared @@ -288,11 +343,17 @@ def evaluateSubjectPlacements(self, chromosome): totalSubjects = sectionSubjects + sharingSubjects # Number of shared subjects that are not placed unplacedSharingSubjects = 0 - for sharing in chromosomeUnplacedData['sharings']: + for sharing in chromosomeUnplacedData["sharings"]: # Sharing subjects is increased based on number of sections sharing the subject unplacedSharingSubjects += len(sharings[sharing][1]) # Length of unplaced section subjects - unplacedSectionSubjects = len(list(itertools.chain.from_iterable(chromosomeUnplacedData['sections'].values()))) + unplacedSectionSubjects = len( + list( + itertools.chain.from_iterable( + chromosomeUnplacedData["sections"].values() + ) + ) + ) totalUnplacedSubjects = unplacedSharingSubjects + unplacedSectionSubjects return round(((totalSubjects - totalUnplacedSubjects) / totalSubjects) * 100, 2) @@ -300,9 +361,9 @@ def evaluateSubjectPlacements(self, chromosome): def evaluateLunchBreak(self, chromosome): sectionDays = 0 noLunchDays = 0 - for section in chromosome.data['sections'].values(): + for section in chromosome.data["sections"].values(): # [roomId, instructorId, [day / s], startingTS, length] - details = section['details'] + details = section["details"] # A temporary map for days and lunch period # {day: [22, 23, 24, 25]} # TS 22-25 : 11 AM - 1 PM @@ -331,10 +392,10 @@ def evaluateLunchBreak(self, chromosome): def evaluateStudentRest(self, chromosome): sectionDays = 0 noRestDays = 0 - for section in chromosome.data['sections'].values(): + for section in chromosome.data["sections"].values(): # Sections week week = {day: [] for day in range(6)} - for subject in section['details'].values(): + for subject in section["details"].values(): if not len(subject): continue # Add section subject timeslots to sections week @@ -354,8 +415,12 @@ def evaluateStudentRest(self, chromosome): if hasViolated: continue # Compare consecutive timeslot to section's day timeslot - if [timeslot for timeslot in range(day[threeHours - 6], day[threeHours - 6] + 6)] == day[ - threeHours - 6: threeHours]: + if [ + timeslot + for timeslot in range( + day[threeHours - 6], day[threeHours - 6] + 6 + ) + ] == day[threeHours - 6 : threeHours]: hasViolated = True noRestDays += 1 return round(((sectionDays - noRestDays) / sectionDays) * 100, 2) @@ -364,7 +429,7 @@ def evaluateStudentRest(self, chromosome): def evaluateInstructorRest(self, chromosome): instructorTeachingDays = 0 noRestDays = 0 - for instructor in chromosome.data['instructors'].values(): + for instructor in chromosome.data["instructors"].values(): # Instructor week week = {day: [] for day in range(6)} for timeslot, timeslotRow in enumerate(instructor): @@ -384,35 +449,50 @@ def evaluateInstructorRest(self, chromosome): if hasViolated: continue # Compare consecutive timeslot to section's day timeslot - if [timeslot for timeslot in range(day[threeHours - 6], day[threeHours - 6] + 6)] == day[ - threeHours - 6: threeHours]: + if [ + timeslot + for timeslot in range( + day[threeHours - 6], day[threeHours - 6] + 6 + ) + ] == day[threeHours - 6 : threeHours]: hasViolated = True noRestDays += 1 if not instructorTeachingDays: return 100.00 - return round(((instructorTeachingDays - noRestDays) / instructorTeachingDays) * 100, 2) + return round( + ((instructorTeachingDays - noRestDays) / instructorTeachingDays) * 100, 2 + ) # = ((sectionDays - idleDays) / sectionDays) * 100 def evaluateStudentIdleTime(self, chromosome): sectionDays = 0 idleDays = 0 - for section in chromosome.data['sections'].values(): + for section in chromosome.data["sections"].values(): week = {day: [] for day in range(6)} - for subject in section['details'].values(): + for subject in section["details"].values(): if not len(subject): continue # Add section subject timeslots to sections week for day in subject[2]: - week[day].append([timeslot for timeslot in range(subject[3], subject[3] + subject[4])]) + week[day].append( + [ + timeslot + for timeslot in range(subject[3], subject[3] + subject[4]) + ] + ) week[day].sort() for day in week.values(): if not len(day): continue sectionDays += 1 # For every 6 TS that the day occupies, there is 1 TS allowable break - allowedBreaks = round((len(list(itertools.chain.from_iterable(day))) / 6), 2) + allowedBreaks = round( + (len(list(itertools.chain.from_iterable(day))) / 6), 2 + ) # If the decimal of allowed breaks is greater than .6, consider it as an addition - if (allowedBreaks > 1 and allowedBreaks % 1 > 0.60) or allowedBreaks % 1 > .80: + if ( + allowedBreaks > 1 and allowedBreaks % 1 > 0.60 + ) or allowedBreaks % 1 > 0.80: allowedBreaks += 1 for index, timeslots in enumerate(day): if index == len(day) - 1 or allowedBreaks < 0: @@ -428,8 +508,8 @@ def evaluateStudentIdleTime(self, chromosome): def evaluateMeetingPattern(self, chromosome): placedSubjects = 0 badPattern = 0 - for section in chromosome.data['sections'].values(): - for subject in section['details'].values(): + for section in chromosome.data["sections"].values(): + for subject in section["details"].values(): if not len(subject) or len(subject[2]) == 1: continue placedSubjects += 1 @@ -442,10 +522,10 @@ def evaluateInstructorLoad(self, chromosome): activeInstructors = {} activeSubjects = [] # Get list of active subjects - for section in self.data['sections'].values(): + for section in self.data["sections"].values(): activeSubjects += section[2] - subjects = self.data['subjects'] - sharings = self.data['sharings'] + subjects = self.data["subjects"] + sharings = self.data["sharings"] # Get list of active instructors and their potential load for subject in activeSubjects: # Exclude subjects that have less than 1 candidate instructor @@ -454,16 +534,18 @@ def evaluateInstructorLoad(self, chromosome): for instructor in subjects[subject][4]: if instructor not in activeInstructors.keys(): activeInstructors[instructor] = [0, 0] - activeInstructors[instructor][0] += int(subjects[subject][1] / .5) + activeInstructors[instructor][0] += int(subjects[subject][1] / 0.5) # Remove load from instructors that is duplicated due to sharing for sharing in sharings.values(): subject = subjects[sharing[0]] if len(subject[4]) <= 1: continue for instructor in subject[4]: - activeInstructors[instructor][0] -= int(subject[1] / .5) * (len(sharing[1]) - 1) + activeInstructors[instructor][0] -= int(subject[1] / 0.5) * ( + len(sharing[1]) - 1 + ) # Fill up active instructors with actual load - for instructor, details in chromosome.data['instructors'].items(): + for instructor, details in chromosome.data["instructors"].items(): for timeslotRow in details: for day in timeslotRow: if day and instructor in activeInstructors.keys(): @@ -491,8 +573,10 @@ def getFitnessDeviation(self): fitnesses = [chromosome.fitness for chromosome in self.chromosomes] mean = np.mean(fitnesses) sigmas = [int(fitness - mean) for fitness in fitnesses] - sigmaInstances = {sigma: (instance / populationCount) * 100 for sigma, instance in - dict(Counter(sigmas)).items()} + sigmaInstances = { + sigma: (instance / populationCount) * 100 + for sigma, instance in dict(Counter(sigmas)).items() + } return [sigmas, sigmaInstances] def alignPopulation(self, sigmas, sigmaInstances): @@ -500,42 +584,60 @@ def alignPopulation(self, sigmas, sigmaInstances): sigmaStartingInstance = list(sigmaInstances.values())[0] if sigmaStartingInstance > self.lowVariety: # Add the excess percentage of instances on first sigma to population - generate = int((int(sigmaStartingInstance - self.lowVariety) / 100) * populationCount) - while generate + populationCount > self.settings['maximum_population']: + generate = int( + (int(sigmaStartingInstance - self.lowVariety) / 100) * populationCount + ) + while generate + populationCount > self.settings["maximum_population"]: generate -= 1 self.generateChromosome(generate) else: # Remove the excess percentage of instances on first sigma to population sortedSigmas = sorted(enumerate(sigmas), key=itemgetter(1)) - remove = int((int(self.lowVariety - sigmaStartingInstance) / 100) * populationCount) - while populationCount - remove < self.settings['minimum_population']: + remove = int( + (int(self.lowVariety - sigmaStartingInstance) / 100) * populationCount + ) + while populationCount - remove < self.settings["minimum_population"]: remove -= 1 remove = [sortedSigmas[index][0] for index in range(remove)] - self.chromosomes = [chromosome for index, chromosome in enumerate(self.chromosomes) if index not in remove] + self.chromosomes = [ + chromosome + for index, chromosome in enumerate(self.chromosomes) + if index not in remove + ] # Increase mutation rate for low performing generations and decrease for good performance def adjustMutationRate(self): - if (self.averageFitness - self.pastAverageFitness < 0) or ( - abs(self.averageFitness - self.pastAverageFitness) <= self.settings[ - 'mutation_rate_adjustment_trigger']) and not self.mutationRate >= 100: - self.mutationRate += .05 - elif self.mutationRate > .10: - self.mutationRate -= .05 + if ( + (self.averageFitness - self.pastAverageFitness < 0) + or ( + abs(self.averageFitness - self.pastAverageFitness) + <= self.settings["mutation_rate_adjustment_trigger"] + ) + and not self.mutationRate >= 100 + ): + self.mutationRate += 0.05 + elif self.mutationRate > 0.10: + self.mutationRate -= 0.05 self.mutationRate = round(self.mutationRate, 2) # Selects top 5% of population and performs tournament to generate remaining candidates def selection(self): population = len(self.chromosomes) - chromosomeFitness = [self.chromosomes[chromosome].fitness for chromosome in range(len(self.chromosomes))] + chromosomeFitness = [ + self.chromosomes[chromosome].fitness + for chromosome in range(len(self.chromosomes)) + ] # Select number of elites that will ensure there will be even offspring to be generated eliteCount = round(population * self.elitePercent) if population % 2 == 0: eliteCount = eliteCount if eliteCount % 2 == 0 else eliteCount + 1 else: eliteCount = eliteCount if eliteCount % 2 != 0 else eliteCount + 1 - self.statusSignal.emit('Selecting {} Elites'.format(eliteCount)) + self.statusSignal.emit("Selecting {} Elites".format(eliteCount)) sortedFitness = sorted(enumerate(chromosomeFitness), key=itemgetter(1)) - elites = list(map(lambda chromosome: chromosome[0], sortedFitness[eliteCount * -1:])) + elites = list( + map(lambda chromosome: chromosome[0], sortedFitness[eliteCount * -1 :]) + ) matingPool = [] matingPoolSize = int((population - eliteCount) / 2) tournamentSize = int(self.tournamentSize * population) @@ -543,7 +645,9 @@ def selection(self): tournamentSize = 25 # Fill mating pool with couples selected by multiple tournaments for i in range(matingPoolSize): - self.statusSignal.emit('Creating #{} of {} Couples'.format(i + 1, matingPoolSize)) + self.statusSignal.emit( + "Creating #{} of {} Couples".format(i + 1, matingPoolSize) + ) couple = [] while len(couple) != 2: winner = self.createTournament(tournamentSize, chromosomeFitness) @@ -576,15 +680,23 @@ def crossover(self): self.offsprings = [] for couple in self.matingPool: self.statusSignal.emit( - 'Creating #{} of {} Offsprings'.format(offspringCount, len(self.chromosomes) - len(self.elites))) + "Creating #{} of {} Offsprings".format( + offspringCount, len(self.chromosomes) - len(self.elites) + ) + ) self.offsprings.append(self.createOffspring(couple)) offspringCount += 1 couple.reverse() self.statusSignal.emit( - 'Creating #{} of {} Offsprings'.format(offspringCount, len(self.chromosomes) - len(self.elites))) + "Creating #{} of {} Offsprings".format( + offspringCount, len(self.chromosomes) - len(self.elites) + ) + ) self.offsprings.append(self.createOffspring(couple)) offspringCount += 1 - self.elites = list(map(lambda elite: copy.deepcopy(self.chromosomes[elite]), self.elites)) + self.elites = list( + map(lambda elite: copy.deepcopy(self.chromosomes[elite]), self.elites) + ) self.chromosomes = self.offsprings + self.elites # Returns a chromosome containing a mix of parents genes @@ -592,12 +704,9 @@ def createOffspring(self, parent): self.tempChromosome = offspring = Chromosome(self.data) parentA = self.chromosomes[parent[0]] parentB = self.chromosomes[parent[1]] - parentAShareables = { - 'sharings': {}, - 'sections': {} - } + parentAShareables = {"sharings": {}, "sections": {}} # Parent A shall provide half of its genes - parentASharings = parentA.data['sharings'] + parentASharings = parentA.data["sharings"] if len(parentASharings) > 1: # Amount of sharings to get sharingCarve = round(len(parentASharings) / 3) @@ -607,16 +716,21 @@ def createOffspring(self, parent): # Take note that index does not mean it is the key of the sharings # [{sharingId: details}] sharings = [id for id in parentASharings.keys()] - for sharing in sharings[startingPoint:startingPoint + sharingCarve]: - parentAShareables['sharings'][sharing] = parentASharings[sharing] + for sharing in sharings[startingPoint : startingPoint + sharingCarve]: + parentAShareables["sharings"][sharing] = parentASharings[sharing] # Raw list of parent A sections with reduced subjects from sharings parentASections = {} - for section, value in copy.deepcopy(parentA.data['sections']).items(): - parentASections[section] = value['details'] - for sharing in self.data['sharings'].values(): + for section, value in copy.deepcopy(parentA.data["sections"]).items(): + parentASections[section] = value["details"] + for sharing in self.data["sharings"].values(): for section in sharing[1]: parentASections[section].pop(sharing[0]) - parentASections = {key: value for key, value in filter(lambda item: len(item[1]) > 1, parentASections.items())} + parentASections = { + key: value + for key, value in filter( + lambda item: len(item[1]) > 1, parentASections.items() + ) + } # Calculate the shareables of each section for section, values in parentASections.items(): # Amount of section subjects to share @@ -625,74 +739,97 @@ def createOffspring(self, parent): startingPoint = int(len(values) / 2) - (sectionCarve - 1) subjects = [id for id in values.keys()] for index in range(startingPoint, startingPoint + sectionCarve): - if section not in parentAShareables['sections']: - parentAShareables['sections'][section] = {} - parentAShareables['sections'][section][subjects[index]] = values[subjects[index]] - parentBShareables = { - 'sharings': {}, - 'sections': {} - } + if section not in parentAShareables["sections"]: + parentAShareables["sections"][section] = {} + parentAShareables["sections"][section][subjects[index]] = values[ + subjects[index] + ] + parentBShareables = {"sharings": {}, "sections": {}} # Add remaining sharings from parent B - for id, sharing in parentB.data['sharings'].items(): - if id not in parentAShareables['sharings'].keys(): - parentBShareables['sharings'][id] = sharing + for id, sharing in parentB.data["sharings"].items(): + if id not in parentAShareables["sharings"].keys(): + parentBShareables["sharings"][id] = sharing # Create list of parent B sections parentBSections = {} - for section, value in copy.deepcopy(parentB.data['sections']).items(): - parentBSections[section] = value['details'] - for sharing in self.data['sharings'].values(): + for section, value in copy.deepcopy(parentB.data["sections"]).items(): + parentBSections[section] = value["details"] + for sharing in self.data["sharings"].values(): for section in sharing[1]: parentBSections[section].pop(sharing[0]) # Create list of subjects that are not in parent A shareables for section in parentBSections: - parentBShareables['sections'][section] = {} + parentBShareables["sections"][section] = {} for id, subject in parentBSections[section].items(): - if not (id in list(parentAShareables['sections'][section].keys())): - parentBShareables['sections'][section][id] = subject + if id not in list(parentAShareables["sections"][section].keys()): + parentBShareables["sections"][section][id] = subject # List of unplaced sharings with or without data unplacedSharings = {} # Insert parent A sharings into chromosome - sharings = self.data['sharings'] - for id, sharing in parentAShareables['sharings'].items(): + sharings = self.data["sharings"] + for id, sharing in parentAShareables["sharings"].items(): if not len(sharing): unplacedSharings[id] = [] continue - offspring.insertSchedule([sharing[0], sharings[id][1], sharings[id][0], sharing[1], *sharing[2:5], id]) + offspring.insertSchedule( + [ + sharing[0], + sharings[id][1], + sharings[id][0], + sharing[1], + *sharing[2:5], + id, + ] + ) # Add parent B subjects in random manner - parentBSharings = list(parentBShareables['sharings'].keys()) + parentBSharings = list(parentBShareables["sharings"].keys()) np.random.shuffle(parentBSharings) for id in parentBSharings: - sharing = parentBShareables['sharings'][id] + sharing = parentBShareables["sharings"][id] if not len(sharing): unplacedSharings[id] = [] continue - if offspring.insertSchedule([sharing[0], sharings[id][1], sharings[id][0], sharing[1], *sharing[2:5], id]): + if offspring.insertSchedule( + [ + sharing[0], + sharings[id][1], + sharings[id][0], + sharing[1], + *sharing[2:5], + id, + ] + ): unplacedSharings[id] = sharing # List of unplaced subjects with or without data unplacedSectionSubjects = {} # Insert parent A section subjects into chromosome - for section, subjects in parentAShareables['sections'].items(): + for section, subjects in parentAShareables["sections"].items(): if section not in unplacedSectionSubjects.keys(): unplacedSectionSubjects[section] = {} for subject, details in subjects.items(): if not len(details): unplacedSectionSubjects[section][subject] = [] continue - if offspring.insertSchedule([details[0], [section], subject, details[1], *details[2:5]]): + if offspring.insertSchedule( + [details[0], [section], subject, details[1], *details[2:5]] + ): unplacedSectionSubjects[section][subject] = details # Insert parent B section subjects into chromosome - for section, subjects in parentBShareables['sections'].items(): + for section, subjects in parentBShareables["sections"].items(): if section not in unplacedSectionSubjects.keys(): unplacedSectionSubjects[section] = {} for subject, details in subjects.items(): if not len(details): unplacedSectionSubjects[section][subject] = [] continue - if offspring.insertSchedule([details[0], [section], subject, details[1], *details[2:5]]): + if offspring.insertSchedule( + [details[0], [section], subject, details[1], *details[2:5]] + ): unplacedSectionSubjects[section][subject] = details # Attempt to insert unplaced sharings for sharing in copy.deepcopy(unplacedSharings).keys(): - if self.generateSubjectPlacement(sharings[sharing][1], sharings[sharing][0], sharing): + if self.generateSubjectPlacement( + sharings[sharing][1], sharings[sharing][0], sharing + ): unplacedSharings.pop(sharing) # Attempt to insert unplaced section subjects for section, subjects in copy.deepcopy(unplacedSectionSubjects).items(): @@ -702,88 +839,120 @@ def createOffspring(self, parent): return offspring def mutation(self): - sharings = self.data['sharings'] - sections = self.data['sections'] + sharings = self.data["sharings"] + sections = self.data["sections"] mutationCandidates = { - 'sections': {}, - 'sharings': [key for key in sharings.keys()] + "sections": {}, + "sharings": [key for key in sharings.keys()], } # Prepare clean list of subject placement with consideration for sharing for section, data in copy.deepcopy(sections).items(): - mutationCandidates['sections'][section] = data[2] + mutationCandidates["sections"][section] = data[2] for sharing in sharings.values(): for section in sharing[1]: - mutationCandidates['sections'][section].remove(sharing[0]) - if not len(mutationCandidates['sharings']): - mutationCandidates.pop('sharings') - for section in copy.deepcopy(mutationCandidates['sections']): - if not len(mutationCandidates['sections'][section]): - mutationCandidates['sections'].pop(section) + mutationCandidates["sections"][section].remove(sharing[0]) + if not len(mutationCandidates["sharings"]): + mutationCandidates.pop("sharings") + for section in copy.deepcopy(mutationCandidates["sections"]): + if not len(mutationCandidates["sections"][section]): + mutationCandidates["sections"].pop(section) # Randomly select chromosomes to mutate for index, chromosome in enumerate(copy.deepcopy(self.chromosomes)): if np.random.randint(100) > (self.mutationRate * 100) - 1: continue - self.statusSignal.emit('Mutating Chromosome #{}'.format(index + 1)) + self.statusSignal.emit("Mutating Chromosome #{}".format(index + 1)) self.tempChromosome = Chromosome(self.data) # Select a gene to mutate mutating = np.random.choice(list(mutationCandidates.keys())) - if mutating == 'sections': - section = np.random.choice(list(mutationCandidates['sections'].keys())) - mutating = ['sections', section, np.random.choice(mutationCandidates['sections'][section])] + if mutating == "sections": + section = np.random.choice(list(mutationCandidates["sections"].keys())) + mutating = [ + "sections", + section, + np.random.choice(mutationCandidates["sections"][section]), + ] else: - mutating = ['sharing', np.random.choice(mutationCandidates['sharings'])] + mutating = ["sharing", np.random.choice(mutationCandidates["sharings"])] # Replicate chromosome except the mutating gene - for sharing in mutationCandidates['sharings'] if 'sharings' in mutationCandidates else []: - if mutating[0] == 'sharing' and sharing == mutating[1]: + for sharing in ( + mutationCandidates["sharings"] + if "sharings" in mutationCandidates + else [] + ): + if mutating[0] == "sharing" and sharing == mutating[1]: continue - details = chromosome.data['sharings'][sharing] + details = chromosome.data["sharings"][sharing] if len(details): self.tempChromosome.insertSchedule( - [details[0], sharings[sharing][1], sharings[sharing][0], details[1], *details[2:5], sharing]) - for section, subjects in mutationCandidates['sections'].items(): + [ + details[0], + sharings[sharing][1], + sharings[sharing][0], + details[1], + *details[2:5], + sharing, + ] + ) + for section, subjects in mutationCandidates["sections"].items(): for subject in subjects: - if mutating[0] == 'sections' and mutating[1] == section and mutating[2] == subject: + if ( + mutating[0] == "sections" + and mutating[1] == section + and mutating[2] == subject + ): continue - details = chromosome.data['sections'][section]['details'][subject] + details = chromosome.data["sections"][section]["details"][subject] if len(details): - self.tempChromosome.insertSchedule([details[0], [section], subject, details[1], *details[2:5]]) + self.tempChromosome.insertSchedule( + [details[0], [section], subject, details[1], *details[2:5]] + ) # Generate mutation - if mutating[0] == 'sharing': - self.generateSubjectPlacement(sharings[mutating[1]][1], sharings[mutating[1]][0], mutating[1]) + if mutating[0] == "sharing": + self.generateSubjectPlacement( + sharings[mutating[1]][1], sharings[mutating[1]][0], mutating[1] + ) else: self.generateSubjectPlacement([mutating[1]], mutating[2]) self.chromosomes[index] = copy.deepcopy(self.tempChromosome) def run(self): - self.statusSignal.emit('Initializing') + self.statusSignal.emit("Initializing") self.initialization() generation = 0 runThread = True - while (runThread): + while runThread: if self.running: generation += 1 - self.statusSignal.emit('Preparing Evaluation') + self.statusSignal.emit("Preparing Evaluation") self.evaluate() self.detailsSignal.emit( - [generation, len(self.chromosomes), int(self.mutationRate * 100), round(self.averageFitness, 2), - round(self.pastAverageFitness, 2), self.highestFitness, self.lowestFitness]) - if self.highestFitness >= self.settings['maximum_fitness']: - self.statusSignal.emit('Reached the Highest Fitness') + [ + generation, + len(self.chromosomes), + int(self.mutationRate * 100), + round(self.averageFitness, 2), + round(self.pastAverageFitness, 2), + self.highestFitness, + self.lowestFitness, + ] + ) + if self.highestFitness >= self.settings["maximum_fitness"]: + self.statusSignal.emit("Reached the Highest Fitness") self.operationSignal.emit(1) self.running = runThread = False break - if self.settings['maximum_generations'] < generation - 1: - self.statusSignal.emit('Hit Maximum Generations') + if self.settings["maximum_generations"] < generation - 1: + self.statusSignal.emit("Hit Maximum Generations") self.operationSignal.emit(1) self.running = runThread = False break - self.statusSignal.emit('Tweaking Environment') + self.statusSignal.emit("Tweaking Environment") self.adapt() - self.statusSignal.emit('Preparing Selection') + self.statusSignal.emit("Preparing Selection") self.selection() - self.statusSignal.emit('Preparing Crossover') + self.statusSignal.emit("Preparing Crossover") self.crossover() - self.statusSignal.emit('Preparing Mutation') + self.statusSignal.emit("Preparing Mutation") self.mutation() @@ -821,14 +990,11 @@ def __init__(self, data): self.fitness = 0 self.fitnessDetails = [] self.data = { - 'sections': {}, - 'sharings': {}, - 'instructors': {}, - 'rooms': {}, - 'unplaced': { - 'sharings': [], - 'sections': {} - } + "sections": {}, + "sharings": {}, + "instructors": {}, + "rooms": {}, + "unplaced": {"sharings": [], "sections": {}}, } self.rawData = data self.settings = Settings.getSettings() @@ -837,33 +1003,41 @@ def __init__(self, data): def buildChromosome(self): rawData = self.rawData # {id: {details: [subject: []], schedule: [days]}} - sections = rawData['sections'] + sections = rawData["sections"] for section in sections: - self.data['sections'][section] = {'details': {}, 'schedule': []} - self.data['sections'][section]['details'] = {key: [] for key in sections[section][2]} + self.data["sections"][section] = {"details": {}, "schedule": []} + self.data["sections"][section]["details"] = { + key: [] for key in sections[section][2] + } sectionTimetable = [] for timeslotRow in sections[section][1]: - sectionTimetable.append([None if day == 'Available' else False for day in timeslotRow]) - self.data['sections'][section]['schedule'] = sectionTimetable - self.data['unplaced']['sections'][section] = [] + sectionTimetable.append( + [None if day == "Available" else False for day in timeslotRow] + ) + self.data["sections"][section]["schedule"] = sectionTimetable + self.data["unplaced"]["sections"][section] = [] # {id: [subjectId: [details]]} - sharings = rawData['sharings'] + sharings = rawData["sharings"] for sharing in sharings: - self.data['sharings'][sharing] = [] + self.data["sharings"][sharing] = [] # {id: [days]} - instructors = rawData['instructors'] + instructors = rawData["instructors"] for instructor in instructors: instructorTimetable = [] for timeslotRow in instructors[instructor][2]: - instructorTimetable.append([None if day == 'Available' else False for day in timeslotRow]) - self.data['instructors'][instructor] = instructorTimetable + instructorTimetable.append( + [None if day == "Available" else False for day in timeslotRow] + ) + self.data["instructors"][instructor] = instructorTimetable # {id: [days]} - rooms = rawData['rooms'] + rooms = rawData["rooms"] for room in rooms: roomTimetable = [] for timeslotRow in rooms[room][2]: - roomTimetable.append([None if day == 'Available' else False for day in timeslotRow]) - self.data['rooms'][room] = roomTimetable + roomTimetable.append( + [None if day == "Available" else False for day in timeslotRow] + ) + self.data["rooms"][room] = roomTimetable # [roomId, [sectionId], subjectId, instructorID, [day/s], startingTS, length(, sharingId)] def insertSchedule(self, schedule): @@ -873,19 +1047,25 @@ def insertSchedule(self, schedule): return isValid data = self.data # [roomId, instructorId, [day/s], startingTS, length] - subjectDetails = [schedule[0], schedule[3], schedule[4], schedule[5], schedule[6]] + subjectDetails = [ + schedule[0], + schedule[3], + schedule[4], + schedule[5], + schedule[6], + ] # Check if schedule is for sharing if len(schedule) > 7: - data['sharings'][schedule[-1]] = subjectDetails + data["sharings"][schedule[-1]] = subjectDetails # Insert details into section data for section in schedule[1]: - data['sections'][section]['details'][schedule[2]] = subjectDetails + data["sections"][section]["details"][schedule[2]] = subjectDetails # Update instructor and room timetable for timeslot in range(schedule[5], schedule[5] + schedule[6]): for day in schedule[4]: if schedule[3]: - data['instructors'][schedule[3]][timeslot][day] = schedule[1] - data['rooms'][schedule[0]][timeslot][day] = schedule[1] + data["instructors"][schedule[3]][timeslot][day] = schedule[1] + data["rooms"][schedule[0]][timeslot][day] = schedule[1] # False signifies no error in insertion return False @@ -899,7 +1079,7 @@ def validateSchedule(self, schedule): return True def isRoomTimeslotAvailable(self, schedule): - room = self.data['rooms'][schedule[0]] + room = self.data["rooms"][schedule[0]] for timeslotRow in range(schedule[5], schedule[5] + schedule[6]): for day in schedule[4]: if room[timeslotRow][day] is not None: @@ -907,8 +1087,8 @@ def isRoomTimeslotAvailable(self, schedule): return True def isSectionTimeslotAvailable(self, schedule): - rooms = self.data['rooms'] - sections = self.data['sections'] + rooms = self.data["rooms"] + sections = self.data["sections"] # Check for each room if on the given subject range, the section has class for room in rooms: for timeslotRow in range(schedule[5], schedule[5] + schedule[6]): @@ -925,7 +1105,7 @@ def isSectionTimeslotAvailable(self, schedule): for section in schedule[1]: for timeslotRow in range(schedule[5], schedule[5] + schedule[6]): for day in schedule[4]: - if sections[section]['schedule'][timeslotRow][day] is not None: + if sections[section]["schedule"][timeslotRow][day] is not None: return False return True @@ -933,13 +1113,13 @@ def isInstructorTimeslotAvailable(self, schedule): # Pass if no instructor is set if not schedule[3]: return True - instructor = self.data['instructors'][schedule[3]] + instructor = self.data["instructors"][schedule[3]] for timeslotRow in range(schedule[5], schedule[5] + schedule[6]): for day in schedule[4]: if instructor[timeslotRow][day] is not None: return False # Check if instructor can still teach - maxLoad = self.rawData['instructors'][schedule[3]][1] * 2 + maxLoad = self.rawData["instructors"][schedule[3]][1] * 2 for timeslotRow in instructor: for day in timeslotRow: if day: diff --git a/components/ImportExportHandler.py b/components/ImportExportHandler.py index 08bd928..c4abbe7 100644 --- a/components/ImportExportHandler.py +++ b/components/ImportExportHandler.py @@ -1,4 +1,4 @@ -from PyQt5 import QtWidgets +from PyQt6 import QtWidgets from components import Database as db import csv diff --git a/components/ScheduleParser.py b/components/ScheduleParser.py index 87e7049..dfc54bd 100644 --- a/components/ScheduleParser.py +++ b/components/ScheduleParser.py @@ -1,4 +1,4 @@ -from PyQt5 import QtCore, QtWidgets, QtGui +from PyQt6 import QtCore, QtWidgets, QtGui from components import Settings, TableModel, Utilities import json @@ -12,20 +12,24 @@ class ScheduleParser: # table = QTableView, data = [] def __init__(self, table, data): self.table = table - header = [['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']] - with open('timeslots.json') as json_file: - self.timeslots = timeslots = json.load(json_file)['timeslots'] + header = [["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]] + with open("timeslots.json") as json_file: + self.timeslots = timeslots = json.load(json_file)["timeslots"] self.settings = settings = Settings.getSettings() - header.append(timeslots[settings['starting_time']:settings['ending_time'] + 1]) + header.append( + timeslots[settings["starting_time"] : settings["ending_time"] + 1] + ) temporaryData = [] - for i in range(settings['ending_time'] + 1 - settings['starting_time']): - temporaryData.append(['', '', '', '', '', '']) + for i in range(settings["ending_time"] + 1 - settings["starting_time"]): + temporaryData.append(["", "", "", "", "", ""]) self.model = ScheduleParserModel(header, temporaryData) table.setModel(self.model) table.setFocusPolicy(QtCore.Qt.NoFocus) table.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) - # table.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Fixed) - table.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Fixed) + # table.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.Fixed) + table.verticalHeader().setSectionResizeMode( + QtWidgets.QHeaderView.ResizeMode.Fixed + ) self.parseData(data) # data = [{'color': None, 'text': '', 'instances': [[day, startingTS, endingTS]]}] @@ -33,17 +37,19 @@ def parseData(self, data): view = self.table model = self.model for entry in data: - entry['color'] = Utilities.colorGenerator() - for instance in entry['instances']: + entry["color"] = Utilities.colorGenerator() + for instance in entry["instances"]: index = model.index(instance[1], instance[0]) view.setSpan(instance[1], instance[0], instance[2] - instance[1], 1) - item = QtGui.QStandardItem(entry['text']) - item.setBackground(QtGui.QBrush(QtGui.QColor(*entry['color']))) - item.setForeground(QtGui.QBrush(QtGui.QColor(*Utilities.textColor(entry['color'])))) + item = QtGui.QStandardItem(entry["text"]) + item.setBackground(QtGui.QBrush(QtGui.QColor(*entry["color"]))) + item.setForeground( + QtGui.QBrush(QtGui.QColor(*Utilities.textColor(entry["color"]))) + ) model.setData(index, item) def subjectGenerator(self): - print(self.settings['starting_time']) + print(self.settings["starting_time"]) class ScheduleParserModel(TableModel.TableModel): @@ -63,10 +69,10 @@ def data(self, index, role): return QtCore.QVariant() elif role == QtCore.Qt.TextAlignmentRole: return QtCore.Qt.AlignCenter - elif role == QtCore.Qt.BackgroundRole: + elif role == QtCore.Qt.ItemDataRole.BackgroundRole: return self.data[index.row()][index.column()].background() elif role == QtCore.Qt.ForegroundRole: return self.data[index.row()][index.column()].foreground() - elif role != QtCore.Qt.DisplayRole: + elif role != QtCore.Qt.ItemDataRole.DisplayRole: return QtCore.QVariant() return self.data[index.row()][index.column()].text() diff --git a/components/TableModel.py b/components/TableModel.py index 36e6682..3d089d5 100644 --- a/components/TableModel.py +++ b/components/TableModel.py @@ -1,4 +1,4 @@ -from PyQt5 import QtCore +from PyQt6 import QtCore # Standard table model requires 2D header and complete dataset @@ -11,7 +11,7 @@ def __init__(self, header, data): def data(self, index, role): if not index.isValid(): return QtCore.QVariant() - elif role != QtCore.Qt.DisplayRole: + elif role != QtCore.Qt.ItemDataRole.DisplayRole: return QtCore.QVariant() return self.data[index.row()][index.column()] @@ -22,9 +22,15 @@ def columnCount(self, parent=None, *args, **kwargs): return len(self.data[0]) def headerData(self, p_int, Qt_Orientation, role=None): - if Qt_Orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole: + if ( + Qt_Orientation == QtCore.Qt.Orientation.Horizontal + and role == QtCore.Qt.ItemDataRole.DisplayRole + ): return QtCore.QVariant(self.header[0][p_int]) - elif Qt_Orientation == QtCore.Qt.Vertical and role == QtCore.Qt.DisplayRole: + elif ( + Qt_Orientation == QtCore.Qt.Orientation.Vertical + and role == QtCore.Qt.ItemDataRole.DisplayRole + ): return QtCore.QVariant(self.header[1][p_int]) return QtCore.QVariant() diff --git a/components/Timetable.py b/components/Timetable.py index c82c4f1..4d35849 100644 --- a/components/Timetable.py +++ b/components/Timetable.py @@ -1,4 +1,4 @@ -from PyQt5 import QtCore, QtWidgets, QtGui +from PyQt6 import QtCore, QtWidgets, QtGui from components import Settings, TableModel import json @@ -7,20 +7,35 @@ class Timetable: def __init__(self, table, data=False): self.table = table - header = [['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']] - with open('timeslots.json') as json_file: - timeslots = json.load(json_file)['timeslots'] + header = [["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]] + with open("timeslots.json") as json_file: + timeslots = json.load(json_file)["timeslots"] settings = Settings.getSettings() - header.append(timeslots[settings['starting_time']:settings['ending_time'] + 1]) + header.append( + timeslots[settings["starting_time"] : settings["ending_time"] + 1] + ) self.data = data if not data: self.data = [] - for i in range(settings['ending_time'] + 1 - settings['starting_time']): - self.data.append(['Available', 'Available', 'Available', 'Available', 'Available', 'Available']) + for i in range(settings["ending_time"] + 1 - settings["starting_time"]): + self.data.append( + [ + "Available", + "Available", + "Available", + "Available", + "Available", + "Available", + ] + ) self.model = TimetableModel(header, self.data) table.setModel(self.model) - table.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Fixed) - table.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Fixed) + table.horizontalHeader().setSectionResizeMode( + QtWidgets.QHeaderView.ResizeMode.Fixed + ) + table.verticalHeader().setSectionResizeMode( + QtWidgets.QHeaderView.ResizeMode.Fixed + ) table.clicked.connect(self.toggleCells) table.horizontalHeader().sectionClicked.connect(self.toggleCells) table.verticalHeader().sectionClicked.connect(self.toggleCells) @@ -30,11 +45,19 @@ def __init__(self, table, data=False): def toggleCells(self): indexes = self.table.selectionModel().selectedIndexes() for i in indexes: - value = 'Available' if self.data[i.row()][i.column()] == 'Unavailable' else 'Unavailable' - if value == 'Available': - self.table.setStyleSheet('selection-background-color: rgb(46, 204, 113); selection-color: black;') + value = ( + "Available" + if self.data[i.row()][i.column()] == "Unavailable" + else "Unavailable" + ) + if value == "Available": + self.table.setStyleSheet( + "selection-background-color: rgb(46, 204, 113); selection-color: black;" + ) else: - self.table.setStyleSheet('selection-background-color: rgb(231, 76, 60); selection-color: black;') + self.table.setStyleSheet( + "selection-background-color: rgb(231, 76, 60); selection-color: black;" + ) self.model.setData(i, value) def getData(self): @@ -49,12 +72,12 @@ def __init__(self, header, data): def data(self, index, role): if not index.isValid(): return QtCore.QVariant() - elif role == QtCore.Qt.BackgroundRole: - if self.data[index.row()][index.column()] == 'Available': + elif role == QtCore.Qt.ItemDataRole.BackgroundRole: + if self.data[index.row()][index.column()] == "Available": return QtGui.QBrush(QtGui.QColor(46, 204, 113)) else: return QtGui.QBrush(QtGui.QColor(231, 76, 60)) - elif role != QtCore.Qt.DisplayRole: + elif role != QtCore.Qt.ItemDataRole.DisplayRole: return QtCore.QVariant() return self.data[index.row()][index.column()] @@ -62,6 +85,15 @@ def data(self, index, role): def generateRawTable(): settings = Settings.getSettings() data = [] - for i in range(settings['ending_time'] + 1 - settings['starting_time']): - data.append(['Available', 'Available', 'Available', 'Available', 'Available', 'Available']) + for i in range(settings["ending_time"] + 1 - settings["starting_time"]): + data.append( + [ + "Available", + "Available", + "Available", + "Available", + "Available", + "Available", + ] + ) return data diff --git a/components/__pycache__/Database.cpython-312.pyc b/components/__pycache__/Database.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..021e06bfa5a153faeea9ad8986ea41f49cf349a1 GIT binary patch literal 3506 zcmd5;&2Jk;6yII1KkCRSX+xBjP>oPavLdQlaX~<-9B0!wu{Xuus9!E-vpbD9*j_WU zu5gJ_A_by|LyqNNKov*e)W3jBq~>55Zk)JT%`IGbv%B6niJcEM2UglQGjHC!nR)Lw zGrvD#u_y=M=fA$h|3d9=)@Xl%SJ}A&mFJwn8GMm@$Qi;K_mDRNAO%AN8L076@E>NZ z=-v>g2!Le&&Tk-|b2jg2K`gaBw-rzt{0pzY&Mk9G!HzDk`ob&g{4&23KHP5zZ4W#L z7UvFI_#On9p|5v8j2Bk;TA(IML1j0zsL|`j!n5hDoRSkNDr+T-rZRJBM87VYHqMtc zYGZ=#P0JY>*|iG3HEL@MMLde)%A{j{Yt$@Ln^bk%B6M_0l|s$1JNUz9Shvb$tlQ0y zUM18b%`pB3>s1>!BTulc7pyXF2KAyvu@q>E%$TsvH$w!|YSE@F!U&<=dx?*8^Ar=B zn=xsjTt(?zx=KwwcL$fTZR+vjqD4%*P?|5BPr=NzYl)&pX;v>_qguoyr(2~8%vQE( zZc>9CXcS+s)S6K+(7(!JyILXrFqsHHod&VO{ndA2^Y+H=pFVokcXeg55gXWiwDIW2 z$176}F}kj-Dq9yHZ;M|vViz~_8~InUE36~3KC?QrmTH7!E8jKF4>tPF?|?6^J8}qM z;w+J42z9{-)B}cC7mZ*&XoTt^BU}%6N7V9uM0LU3a$q0kx><P9bGZMe_Y*R?VUgbfYnU079mL zl8P$dku&ISCYg?B9-vwI!FY#-bC^{5zUsJB=2NN8-hu^3!gs+YJZM2Z^rD_VG~EWg zqlvk>lpI(5Y0#uR6`xP3=q5@`%Zb^2>qf{Ml~mB!jd65S>R9q#UHZgPYr`iD6S1rk z-8a#j28i7@y|@0q2+j{D3=XX>EWtH+w()TR1i(%CiSNXhZW%{}&%jhCX2mwGa_<;- zLcb>l4fClnV)zn~Gbym;F9d+|%|UAkRw%yx2nM)`?Z){3VMggdA!N)O`j+3&vQ zh&RQfH>bQVfgjnxV9-QrZlddvx6KlUM3*XP5?(VknU?*RATgiG$cmb0%B&hs-}RU2 z9Uv)07%wFuCfHj~A|QacS*4O`6UL;a2w}w1rD(%C!5R?6jyodnFvI2rug7^2Jl)%# zu6+y+s=d5<>cO_PiJII3h8&?ai0xd+ZNyV8)Ms|)V(pfEsps; zZX>cjyE?m;_UPmHDZ-ZBoimO@&&fGsmXidR?MT92c7Nua3EW`C7O|ahNjlt$h($ literal 0 HcmV?d00001 diff --git a/components/__pycache__/GeneticAlgorithm.cpython-312.pyc b/components/__pycache__/GeneticAlgorithm.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f74fd7c7ebd007fa76636d36104c71ca65e2f857 GIT binary patch literal 49636 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 literal 0 HcmV?d00001 diff --git a/components/__pycache__/ScenarioComposer.cpython-312.pyc b/components/__pycache__/ScenarioComposer.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e57cc38f8bae7541175f98f90456662896baf891 GIT binary patch literal 5062 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 literal 0 HcmV?d00001 diff --git a/components/__pycache__/Settings.cpython-312.pyc b/components/__pycache__/Settings.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7f5e6388d715c1cc3ff588d47c9ca0b698167411 GIT binary patch literal 1946 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 E3+aJ1-v9sr literal 0 HcmV?d00001 diff --git a/components/__pycache__/Timetable.cpython-312.pyc b/components/__pycache__/Timetable.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..220207502ac5df62c38bee6acee88d5e4e70cfe9 GIT binary patch literal 5710 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 100 or hours % .5 != 0: + if hours <= 0 or hours > 100 or hours % 0.5 != 0: return False except: return False @@ -53,9 +57,14 @@ def insertInstructor(data): conn = db.getConnection() cursor = conn.cursor() if len(data) > 3: - cursor.execute('UPDATE instructors SET name = ?, hours = ?, schedule = ? WHERE id = ?', data) + cursor.execute( + "UPDATE instructors SET name = ?, hours = ?, schedule = ? WHERE id = ?", + data, + ) else: - cursor.execute('INSERT INTO instructors (name, hours, schedule) VALUES (?, ?, ?)', data) + cursor.execute( + "INSERT INTO instructors (name, hours, schedule) VALUES (?, ?, ?)", data + ) conn.commit() conn.close() return True @@ -65,7 +74,9 @@ class Tree: def __init__(self, tree): self.tree = tree self.model = model = QtGui.QStandardItemModel() - model.setHorizontalHeaderLabels(['ID', 'Available', 'Name', 'Hours', 'Operation']) + model.setHorizontalHeaderLabels( + ["ID", "Available", "Name", "Hours", "Operation"] + ) tree.setModel(model) tree.setColumnHidden(0, True) model.itemChanged.connect(lambda item: self.toggleAvailability(item)) @@ -74,10 +85,12 @@ def __init__(self, tree): def toggleAvailability(self, item): # Get ID of toggled instructor id = self.model.data(self.model.index(item.row(), 0)) - newValue = 1 if item.checkState() == 2 else 0 + newValue = 1 if item.checkState() == QtCore.Qt.CheckState.Checked else 0 conn = db.getConnection() cursor = conn.cursor() - cursor.execute('UPDATE instructors SET active = ? WHERE id = ?', [newValue, id]) + cursor.execute( + "UPDATE instructors SET active = ? WHERE id = ?", [newValue, id] + ) conn.commit() conn.close() @@ -86,7 +99,7 @@ def display(self): self.model.removeRows(0, self.model.rowCount()) conn = db.getConnection() cursor = conn.cursor() - cursor.execute('SELECT id, active, hours, name FROM instructors') + cursor.execute("SELECT id, active, hours, name FROM instructors") result = cursor.fetchall() conn.close() for instr in result: @@ -96,7 +109,11 @@ def display(self): # Availability Item availability = QtGui.QStandardItem() availability.setCheckable(True) - availability.setCheckState(2 if instr[1] == 1 else 0) + availability.setCheckState( + QtCore.Qt.CheckState.Checked + if instr[1] == 1 + else QtCore.Qt.CheckState.Unchecked + ) availability.setEditable(False) # Hours Item hours = QtGui.QStandardItem(str(instr[2])) @@ -111,9 +128,9 @@ def display(self): self.model.appendRow([id, availability, name, hours, edit]) # Create a widget group for edit and delete buttons frameEdit = QtWidgets.QFrame() - btnEdit = QtWidgets.QPushButton('Edit', frameEdit) + btnEdit = QtWidgets.QPushButton("Edit", frameEdit) btnEdit.clicked.connect(lambda state, id=instr[0]: self.edit(id)) - btnDelete = QtWidgets.QPushButton('Delete', frameEdit) + btnDelete = QtWidgets.QPushButton("Delete", frameEdit) btnDelete.clicked.connect(lambda state, id=instr[0]: self.delete(id)) frameLayout = QtWidgets.QHBoxLayout(frameEdit) frameLayout.setContentsMargins(0, 0, 0, 0) @@ -129,16 +146,19 @@ def edit(self, id): def delete(self, id): # Show confirm model confirm = QtWidgets.QMessageBox() - confirm.setIcon(QtWidgets.QMessageBox.Warning) - confirm.setText('Are you sure you want to delete this entry?') - confirm.setWindowTitle('Confirm Delete') - confirm.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) - result = confirm.exec_() + confirm.setIcon(QtWidgets.QMessageBox.Icon.Warning) + confirm.setText("Are you sure you want to delete this entry?") + confirm.setWindowTitle("Confirm Delete") + confirm.setStandardButtons( + QtWidgets.QMessageBox.StandardButton.Yes + | QtWidgets.QMessageBox.StandardButton.Yes + ) + result = confirm.exec() # 16384 == Confirm if result == 16384: conn = db.getConnection() cursor = conn.cursor() - cursor.execute('DELETE FROM instructors WHERE id = ?', [id]) + cursor.execute("DELETE FROM instructors WHERE id = ?", [id]) conn.commit() conn.close() self.display() diff --git a/containers/Main.py b/containers/Main.py index 9fcf883..6542689 100644 --- a/containers/Main.py +++ b/containers/Main.py @@ -1,10 +1,11 @@ -from PyQt5 import QtCore +from PyQt6 import QtCore from containers import Generate, Instructor, ResultViewer, Room, Subject, Section from components import Settings, Database, Timetable, ImportExportHandler as ioHandler from py_ui import Main import json import gc + class MainWindow(Main.Ui_MainWindow): def __init__(self, parent): super().__init__() @@ -72,16 +73,16 @@ def checkContents(self): conn = Database.getConnection() cursor = conn.cursor() disabled = False - cursor.execute('SELECT id FROM rooms LIMIT 1') + cursor.execute("SELECT id FROM rooms LIMIT 1") if cursor.fetchone(): disabled = True - cursor.execute('SELECT id FROM instructors LIMIT 1') + cursor.execute("SELECT id FROM instructors LIMIT 1") if cursor.fetchone(): disabled = True - cursor.execute('SELECT id FROM sections LIMIT 1') + cursor.execute("SELECT id FROM sections LIMIT 1") if cursor.fetchone(): disabled = True - cursor.execute('SELECT id FROM subjects LIMIT 1') + cursor.execute("SELECT id FROM subjects LIMIT 1") if cursor.fetchone(): disabled = True self.timeStarting.setDisabled(disabled) @@ -100,17 +101,19 @@ def openGenerate(self): self.openResult() def importInstructors(self): - instructors = ioHandler.getCSVFile('instructors') + instructors = ioHandler.getCSVFile("instructors") if instructors: instructors.pop(0) instructors.pop(0) blankSchedule = json.dumps(Timetable.generateRawTable()) for instructor in instructors: - Instructor.Instructor.insertInstructor([instructor[0], float(instructor[1]), blankSchedule]) + Instructor.Instructor.insertInstructor( + [instructor[0], float(instructor[1]), blankSchedule] + ) self.tabListener(0) def importRooms(self): - rooms = ioHandler.getCSVFile('rooms') + rooms = ioHandler.getCSVFile("rooms") if rooms: rooms.pop(0) rooms.pop(0) @@ -120,13 +123,22 @@ def importRooms(self): self.tabListener(1) def importSubjects(self): - subjects = ioHandler.getCSVFile('subjects') + subjects = ioHandler.getCSVFile("subjects") if subjects: subjects.pop(0) subjects.pop(0) for subject in subjects: Subject.Subject.insertSubject( - [subject[1], float(subject[3]), subject[0], '', json.dumps([]), int(subject[4]), subject[2]]) + [ + subject[1], + float(subject[3]), + subject[0], + "", + json.dumps([]), + int(subject[4]), + subject[2], + ] + ) self.tabListener(2) def saveAs(self): @@ -138,88 +150,127 @@ def load(self): self.tabListener(0) def loadSettings(self): - self.timeStarting.setTime(QtCore.QTime(int(self.settings['starting_time'] / 2), 0)) - self.timeEnding.setTime(QtCore.QTime(int(self.settings['ending_time'] / 2) + 1, 0)) - if self.settings['lunchbreak']: + self.timeStarting.setTime( + QtCore.QTime(int(self.settings["starting_time"] / 2), 0) + ) + self.timeEnding.setTime( + QtCore.QTime(int(self.settings["ending_time"] / 2) + 1, 0) + ) + if self.settings["lunchbreak"]: self.radioLunchYes.setChecked(True) else: self.radioLunchNo.setChecked(True) - self.editMinPop.setValue(self.settings['minimum_population']) - self.editMaxPop.setValue(self.settings['maximum_population']) - self.editMaxGen.setValue(self.settings['maximum_generations']) - self.editMaxCreation.setValue(self.settings['generation_tolerance']) - self.editMut.setValue(self.settings['mutation_rate_adjustment_trigger']) - self.editMaxFit.setValue(self.settings['maximum_fitness']) - self.editElite.setValue(int(self.settings['elite_percent'] * 100)) - self.editDev.setValue(self.settings['deviation_tolerance']) - self.matrix = matrix = self.settings['evaluation_matrix'] - self.editSbj.setValue(matrix['subject_placement']) - self.editLun.setValue(matrix['lunch_break']) - self.editSec.setValue(matrix['student_rest']) - self.editIdle.setValue(matrix['idle_time']) - self.editInstrRest.setValue(matrix['instructor_rest']) - self.editInstrLoad.setValue(matrix['instructor_load']) - self.editMeet.setValue(matrix['meeting_pattern']) + self.editMinPop.setValue(self.settings["minimum_population"]) + self.editMaxPop.setValue(self.settings["maximum_population"]) + self.editMaxGen.setValue(self.settings["maximum_generations"]) + self.editMaxCreation.setValue(self.settings["generation_tolerance"]) + self.editMut.setValue(self.settings["mutation_rate_adjustment_trigger"]) + self.editMaxFit.setValue(self.settings["maximum_fitness"]) + self.editElite.setValue(int(self.settings["elite_percent"] * 100)) + self.editDev.setValue(self.settings["deviation_tolerance"]) + self.matrix = matrix = self.settings["evaluation_matrix"] + self.editSbj.setValue(matrix["subject_placement"]) + self.editLun.setValue(matrix["lunch_break"]) + self.editSec.setValue(matrix["student_rest"]) + self.editIdle.setValue(matrix["idle_time"]) + self.editInstrRest.setValue(matrix["instructor_rest"]) + self.editInstrLoad.setValue(matrix["instructor_load"]) + self.editMeet.setValue(matrix["meeting_pattern"]) self.matrixSum = sum(matrix.values()) - self.lblTotal.setText('Total: {}%'.format(self.matrixSum)) + self.lblTotal.setText("Total: {}%".format(self.matrixSum)) # Handle Settings def handleSettings(self): self.timeStarting.timeChanged.connect(self.handleStartingTime) self.timeEnding.timeChanged.connect(self.handleEndingTime) - self.radioLunchYes.toggled.connect(lambda state: self.updateSettings('lunchbreak', state)) + self.radioLunchYes.toggled.connect( + lambda state: self.updateSettings("lunchbreak", state) + ) self.editMinPop.valueChanged.connect(self.handleMinPop) self.editMaxPop.valueChanged.connect(self.handleMaxPop) - self.editMaxGen.valueChanged.connect(lambda value: self.updateSettings('maximum_generations', value)) - self.editMaxCreation.valueChanged.connect(lambda value: self.updateSettings('generation_tolerance', value)) + self.editMaxGen.valueChanged.connect( + lambda value: self.updateSettings("maximum_generations", value) + ) + self.editMaxCreation.valueChanged.connect( + lambda value: self.updateSettings("generation_tolerance", value) + ) self.editMut.valueChanged.connect( - lambda value: self.updateSettings('mutation_rate_adjustment_trigger', round(value, 2))) - self.editMaxFit.valueChanged.connect(lambda value: self.updateSettings('maximum_fitness', value)) - self.editElite.valueChanged.connect(lambda value: self.updateSettings('elite_percent', round(value / 100, 2))) - self.editDev.valueChanged.connect(lambda value: self.updateSettings('deviation_tolerance', value)) - self.editSbj.valueChanged.connect(lambda value: self.handleMatrix('subject_placement', value, self.editSbj)) - self.editLun.valueChanged.connect(lambda value: self.handleMatrix('lunch_break', value, self.editLun)) - self.editSec.valueChanged.connect(lambda value: self.handleMatrix('student_rest', value, self.editSec)) - self.editIdle.valueChanged.connect(lambda value: self.handleMatrix('idle_time', value, self.editIdle)) + lambda value: self.updateSettings( + "mutation_rate_adjustment_trigger", round(value, 2) + ) + ) + self.editMaxFit.valueChanged.connect( + lambda value: self.updateSettings("maximum_fitness", value) + ) + self.editElite.valueChanged.connect( + lambda value: self.updateSettings("elite_percent", round(value / 100, 2)) + ) + self.editDev.valueChanged.connect( + lambda value: self.updateSettings("deviation_tolerance", value) + ) + self.editSbj.valueChanged.connect( + lambda value: self.handleMatrix("subject_placement", value, self.editSbj) + ) + self.editLun.valueChanged.connect( + lambda value: self.handleMatrix("lunch_break", value, self.editLun) + ) + self.editSec.valueChanged.connect( + lambda value: self.handleMatrix("student_rest", value, self.editSec) + ) + self.editIdle.valueChanged.connect( + lambda value: self.handleMatrix("idle_time", value, self.editIdle) + ) self.editInstrRest.valueChanged.connect( - lambda value: self.handleMatrix('instructor_rest', value, self.editInstrRest)) + lambda value: self.handleMatrix( + "instructor_rest", value, self.editInstrRest + ) + ) self.editInstrLoad.valueChanged.connect( - lambda value: self.handleMatrix('instructor_load', value, self.editInstrLoad)) - self.editMeet.valueChanged.connect(lambda value: self.handleMatrix('meeting_pattern', value, self.editMeet)) + lambda value: self.handleMatrix( + "instructor_load", value, self.editInstrLoad + ) + ) + self.editMeet.valueChanged.connect( + lambda value: self.handleMatrix("meeting_pattern", value, self.editMeet) + ) def handleStartingTime(self, time): - if time.hour() * 2 >= self.settings['ending_time']: - self.timeStarting.setTime(QtCore.QTime(int(self.settings['starting_time'] / 2), 0)) + if time.hour() * 2 >= self.settings["ending_time"]: + self.timeStarting.setTime( + QtCore.QTime(int(self.settings["starting_time"] / 2), 0) + ) else: - self.updateSettings('starting_time', time.hour() * 2) + self.updateSettings("starting_time", time.hour() * 2) def handleEndingTime(self, time): - if (time.hour() * 2) - 1 <= self.settings['starting_time']: - self.timeEnding.setTime(QtCore.QTime(int(self.settings['ending_time'] / 2) + 1, 0)) + if (time.hour() * 2) - 1 <= self.settings["starting_time"]: + self.timeEnding.setTime( + QtCore.QTime(int(self.settings["ending_time"] / 2) + 1, 0) + ) else: - self.updateSettings('ending_time', (time.hour() * 2) - 1) + self.updateSettings("ending_time", (time.hour() * 2) - 1) def handleMinPop(self, value): - if value > self.settings['maximum_population']: - self.editMinPop.setValue(self.settings['minimum_population']) + if value > self.settings["maximum_population"]: + self.editMinPop.setValue(self.settings["minimum_population"]) else: - self.updateSettings('minimum_population', value) + self.updateSettings("minimum_population", value) def handleMaxPop(self, value): - if value < self.settings['minimum_population']: - self.editMaxPop.setValue(self.settings['maximum_population']) + if value < self.settings["minimum_population"]: + self.editMaxPop.setValue(self.settings["maximum_population"]) else: - self.updateSettings('maximum_population', value) + self.updateSettings("maximum_population", value) def handleMatrix(self, key, value, obj): difference = self.matrix[key] - value if self.matrixSum - difference > 100: obj.setValue(self.matrix[key]) else: - self.updateSettings('evaluation_matrix', value, key) - self.matrixSum = sum(self.settings['evaluation_matrix'].values()) - self.matrix = self.settings['evaluation_matrix'] - self.lblTotal.setText('Total: {}%'.format(self.matrixSum)) + self.updateSettings("evaluation_matrix", value, key) + self.matrixSum = sum(self.settings["evaluation_matrix"].values()) + self.matrix = self.settings["evaluation_matrix"] + self.lblTotal.setText("Total: {}%".format(self.matrixSum)) def updateSettings(self, key, value, secondKey=False): Settings.setSettings(key, value, secondKey) diff --git a/containers/ResultViewer.py b/containers/ResultViewer.py index 6f1df95..f3c07a7 100644 --- a/containers/ResultViewer.py +++ b/containers/ResultViewer.py @@ -1,4 +1,4 @@ -from PyQt5 import QtWidgets +from PyQt6 import QtWidgets from components import Settings, Database as db, ScheduleParser from py_ui import Result as Parent import pickle @@ -17,39 +17,49 @@ def __init__(self): self.table = self.parent.tableResult self.run = True self.settings = Settings.getSettings() - self.result = { 'data': [] } + self.result = {"data": []} self.getLastResult() if self.run: self.parseResultDetails() self.connectWidgets() self.updateTable(0) - dialog.exec_() + dialog.exec() def getLastResult(self): conn = db.getConnection() cursor = conn.cursor() - cursor.execute('SELECT content FROM results WHERE id = (SELECT MAX(id) FROM results)') + cursor.execute( + "SELECT content FROM results WHERE id = (SELECT MAX(id) FROM results)" + ) result = cursor.fetchone() conn.close() if result: self.result = pickle.loads(result[0]) else: messageBox = QtWidgets.QMessageBox() - messageBox.setWindowTitle('No Data') - messageBox.setIcon(QtWidgets.QMessageBox.Information) - messageBox.setText('You haven\'t generated a solution yet!') - messageBox.setStandardButtons(QtWidgets.QMessageBox.Ok) - messageBox.exec_() + messageBox.setWindowTitle("No Data") + messageBox.setIcon(QtWidgets.QMessageBox.Icon.Information) + messageBox.setText("You haven't generated a solution yet!") + messageBox.setStandardButtons(QtWidgets.QMessageBox.StandardButton.Ok) + messageBox.exec() self.run = False def parseResultDetails(self): - if not len(self.result['data']): + if not len(self.result["data"]): return False result = self.result - self.rawData = copy.deepcopy(result['rawData']) - self.parent.lblTime.setText('Generation Time: {}'.format(result['time'])) - self.parent.lblCPU.setText('Average CPU Usage: {}%'.format(round(result['resource']['cpu']), 2)) - self.parent.lblMemory.setText('Average Mem Usage: {} MB'.format(round(result['resource']['memory']), 2)) + self.rawData = copy.deepcopy(result["rawData"]) + self.parent.lblTime.setText("Generation Time: {}".format(result["time"])) + self.parent.lblCPU.setText( + "Average CPU Usage: {}%".format( + round(result["resource"]["cpu"]), + ) + ) + self.parent.lblMemory.setText( + "Average Mem Usage: {} MB".format( + round(result["resource"]["memory"]), + ) + ) self.updateEntries(0) self.updateDetails(0) @@ -61,15 +71,15 @@ def connectWidgets(self): def updateDetails(self, index): parent = self.parent - meta = self.result['meta'][index] - parent.lblFit.setText('Total Fitness: {}%'.format(meta[0])) - parent.lblSbj.setText('Subject Placement: {}%'.format(meta[1][0])) - parent.lblSecRest.setText('Section Rest: {}%'.format(meta[1][2])) - parent.lblSecIdle.setText('Section Idle Time: {}%'.format(meta[1][4])) - parent.lblInstrRest.setText('Instructor Rest: {}%'.format(meta[1][3])) - parent.lblInstrLoad.setText('Instructor Load: {}%'.format(meta[1][6])) - parent.lblLunch.setText('Lunch Break: {}%'.format(meta[1][1])) - parent.lblMeet.setText('Meeting Pattern: {}%'.format(meta[1][5])) + meta = self.result["meta"][index] + parent.lblFit.setText("Total Fitness: {}%".format(meta[0])) + parent.lblSbj.setText("Subject Placement: {}%".format(meta[1][0])) + parent.lblSecRest.setText("Section Rest: {}%".format(meta[1][2])) + parent.lblSecIdle.setText("Section Idle Time: {}%".format(meta[1][4])) + parent.lblInstrRest.setText("Instructor Rest: {}%".format(meta[1][3])) + parent.lblInstrLoad.setText("Instructor Load: {}%".format(meta[1][6])) + parent.lblLunch.setText("Lunch Break: {}%".format(meta[1][1])) + parent.lblMeet.setText("Meeting Pattern: {}%".format(meta[1][5])) parent.cmbCategory.setCurrentIndex(0) parent.cmbEntry.setCurrentIndex(0) self.updateEntries(0) @@ -77,11 +87,11 @@ def updateDetails(self, index): def updateEntries(self, index): if index == 0: - key = 'sections' + key = "sections" elif index == 1: - key = 'rooms' + key = "rooms" else: - key = 'instructors' + key = "instructors" self.entryKeys = [] self.changingKeys = True self.parent.cmbEntry.clear() @@ -94,50 +104,92 @@ def updateEntries(self, index): def updateTable(self, index): if self.changingKeys: return False - chromosome = self.result['data'][self.parent.cmbChromosome.currentIndex()] + chromosome = self.result["data"][self.parent.cmbChromosome.currentIndex()] category = self.parent.cmbCategory.currentIndex() # {secId: {'details': {sbjId: [roomId, instructorId, [day/s], startingTS, length]}}} - sections = chromosome['sections'] + sections = chromosome["sections"] rawData = self.rawData data = [] # Section if category == 0: - subjects = sections[self.entryKeys[index]]['details'] + subjects = sections[self.entryKeys[index]]["details"] for subject, details in subjects.items(): if not len(details): continue - instructor = '' if not details[1] else rawData['instructors'][details[1]][0] - data.append({'color': None, 'text': '{} \n {} \n {}'.format(rawData['subjects'][subject][2], - rawData['rooms'][details[0]][0], - instructor), - 'instances': [[day, details[3], details[3] + details[4]] for day in details[2]]}) + instructor = ( + "" if not details[1] else rawData["instructors"][details[1]][0] + ) + data.append( + { + "color": None, + "text": "{} \n {} \n {}".format( + rawData["subjects"][subject][2], + rawData["rooms"][details[0]][0], + instructor, + ), + "instances": [ + [day, details[3], details[3] + details[4]] + for day in details[2] + ], + } + ) # Room elif category == 1: for section, details in sections.items(): - for subject, subjectDetail in details['details'].items(): + for subject, subjectDetail in details["details"].items(): if not len(subjectDetail): continue if subjectDetail[0] != self.entryKeys[index]: continue - instructor = '' if not subjectDetail[1] else rawData['instructors'][subjectDetail[1]][0] - data.append({'color': None, 'text': '{} \n {} \n {}'.format(rawData['subjects'][subject][2], - rawData['sections'][section][0], - instructor), - 'instances': [[day, subjectDetail[3], subjectDetail[3] + subjectDetail[4]] for day in - subjectDetail[2]]}) + instructor = ( + "" + if not subjectDetail[1] + else rawData["instructors"][subjectDetail[1]][0] + ) + data.append( + { + "color": None, + "text": "{} \n {} \n {}".format( + rawData["subjects"][subject][2], + rawData["sections"][section][0], + instructor, + ), + "instances": [ + [ + day, + subjectDetail[3], + subjectDetail[3] + subjectDetail[4], + ] + for day in subjectDetail[2] + ], + } + ) # Instructor else: for section, details in sections.items(): - for subject, subjectDetail in details['details'].items(): + for subject, subjectDetail in details["details"].items(): if not len(subjectDetail): continue if subjectDetail[1] != self.entryKeys[index]: continue - data.append({'color': None, 'text': '{} \n {} \n {}'.format(rawData['subjects'][subject][2], - rawData['rooms'][subjectDetail[0]][0], - rawData['sections'][section][0]), - 'instances': [[day, subjectDetail[3], subjectDetail[3] + subjectDetail[4]] for day in - subjectDetail[2]]}) + data.append( + { + "color": None, + "text": "{} \n {} \n {}".format( + rawData["subjects"][subject][2], + rawData["rooms"][subjectDetail[0]][0], + rawData["sections"][section][0], + ), + "instances": [ + [ + day, + subjectDetail[3], + subjectDetail[3] + subjectDetail[4], + ] + for day in subjectDetail[2] + ], + } + ) self.loadTable(data) def loadTable(self, data=[]): @@ -146,72 +198,137 @@ def loadTable(self, data=[]): ScheduleParser.ScheduleParser(self.table, data) def export(self): - directory = QtWidgets.QFileDialog().getExistingDirectory(None, 'Select Directory for Export') + directory = QtWidgets.QFileDialog().getExistingDirectory( + None, "Select Directory for Export" + ) if not directory: return False - with open('timeslots.json') as json_file: - timeslots = json.load(json_file)['timeslots'] - fieldnames = ['Time', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'] + with open("timeslots.json") as json_file: + timeslots = json.load(json_file)["timeslots"] + fieldnames = [ + "Time", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + ] rawData = self.rawData - chromosome = self.result['data'][self.parent.cmbChromosome.currentIndex()] + chromosome = self.result["data"][self.parent.cmbChromosome.currentIndex()] # Create schedule for sections - with open('{}/sections_schedule.csv'.format(directory), 'w', newline='') as file: - writer = csv.writer(file, dialect='excel') - for section, subjects in chromosome['sections'].items(): - writer.writerow([self.rawData['sections'][section][0]]) + with open( + "{}/sections_schedule.csv".format(directory), "w", newline="" + ) as file: + writer = csv.writer(file, dialect="excel") + for section, subjects in chromosome["sections"].items(): + writer.writerow([self.rawData["sections"][section][0]]) writer.writerow(fieldnames) - schedule = [['' for j in range(6)] for i in - range(self.settings['ending_time'] - self.settings['starting_time'] + 1)] - for subject, details in subjects['details'].items(): + schedule = [ + ["" for j in range(6)] + for i in range( + self.settings["ending_time"] + - self.settings["starting_time"] + + 1 + ) + ] + for subject, details in subjects["details"].items(): if not len(details): continue - instructor = '' if not details[1] else rawData['instructors'][details[1]][0] + instructor = ( + "" if not details[1] else rawData["instructors"][details[1]][0] + ) for timeslot in range(details[3], details[3] + details[4]): for day in details[2]: - schedule[timeslot][day] = '{} - {} - {}'.format(rawData['subjects'][subject][2], - rawData['rooms'][details[0]][0], - instructor) - for timeslot in range(self.settings['starting_time'], self.settings['ending_time'] + 1): - writer.writerow([timeslots[timeslot], *schedule[timeslot - self.settings['starting_time']]]) - writer.writerow(['']) + schedule[timeslot][day] = "{} - {} - {}".format( + rawData["subjects"][subject][2], + rawData["rooms"][details[0]][0], + instructor, + ) + for timeslot in range( + self.settings["starting_time"], self.settings["ending_time"] + 1 + ): + writer.writerow( + [ + timeslots[timeslot], + *schedule[timeslot - self.settings["starting_time"]], + ] + ) + writer.writerow([""]) # Create schedule for instructors - with open('{}/instructors_schedule.csv'.format(directory), 'w', newline='') as file: - writer = csv.writer(file, dialect='excel') - for instructor in rawData['instructors'].keys(): - writer.writerow([rawData['instructors'][instructor][0]]) + with open( + "{}/instructors_schedule.csv".format(directory), "w", newline="" + ) as file: + writer = csv.writer(file, dialect="excel") + for instructor in rawData["instructors"].keys(): + writer.writerow([rawData["instructors"][instructor][0]]) writer.writerow(fieldnames) - schedule = [['' for j in range(6)] for i in - range(self.settings['ending_time'] - self.settings['starting_time'] + 1)] - for section, subjects in chromosome['sections'].items(): - for subject, details in subjects['details'].items(): + schedule = [ + ["" for j in range(6)] + for i in range( + self.settings["ending_time"] + - self.settings["starting_time"] + + 1 + ) + ] + for section, subjects in chromosome["sections"].items(): + for subject, details in subjects["details"].items(): if not len(details) or details[1] != instructor: continue for timeslot in range(details[3], details[3] + details[4]): for day in details[2]: - schedule[timeslot][day] = '{} - {} - {}'.format(rawData['subjects'][subject][2], - rawData['rooms'][details[0]][0], - rawData['sections'][section][0]) - for timeslot in range(self.settings['starting_time'], self.settings['ending_time'] + 1): - writer.writerow([timeslots[timeslot], *schedule[timeslot - self.settings['starting_time']]]) - writer.writerow(['']) + schedule[timeslot][day] = "{} - {} - {}".format( + rawData["subjects"][subject][2], + rawData["rooms"][details[0]][0], + rawData["sections"][section][0], + ) + for timeslot in range( + self.settings["starting_time"], self.settings["ending_time"] + 1 + ): + writer.writerow( + [ + timeslots[timeslot], + *schedule[timeslot - self.settings["starting_time"]], + ] + ) + writer.writerow([""]) # Create schedule for rooms - with open('{}/rooms_schedule.csv'.format(directory), 'w', newline='') as file: - writer = csv.writer(file, dialect='excel') - for room in rawData['rooms'].keys(): - writer.writerow([rawData['rooms'][room][0]]) + with open("{}/rooms_schedule.csv".format(directory), "w", newline="") as file: + writer = csv.writer(file, dialect="excel") + for room in rawData["rooms"].keys(): + writer.writerow([rawData["rooms"][room][0]]) writer.writerow(fieldnames) - schedule = [['' for j in range(6)] for i in - range(self.settings['ending_time'] - self.settings['starting_time'] + 1)] - for section, subjects in chromosome['sections'].items(): - for subject, details in subjects['details'].items(): + schedule = [ + ["" for j in range(6)] + for i in range( + self.settings["ending_time"] + - self.settings["starting_time"] + + 1 + ) + ] + for section, subjects in chromosome["sections"].items(): + for subject, details in subjects["details"].items(): if not len(details) or details[0] != room: continue - instructor = '' if not details[1] else rawData['instructors'][details[1]][0] + instructor = ( + "" + if not details[1] + else rawData["instructors"][details[1]][0] + ) for timeslot in range(details[3], details[3] + details[4]): for day in details[2]: - schedule[timeslot][day] = '{} - {} - {}'.format(rawData['subjects'][subject][2], - rawData['sections'][section][0], - instructor) - for timeslot in range(self.settings['starting_time'], self.settings['ending_time'] + 1): - writer.writerow([timeslots[timeslot], *schedule[timeslot - self.settings['starting_time']]]) - writer.writerow(['']) + schedule[timeslot][day] = "{} - {} - {}".format( + rawData["subjects"][subject][2], + rawData["sections"][section][0], + instructor, + ) + for timeslot in range( + self.settings["starting_time"], self.settings["ending_time"] + 1 + ): + writer.writerow( + [ + timeslots[timeslot], + *schedule[timeslot - self.settings["starting_time"]], + ] + ) + writer.writerow([""]) diff --git a/containers/Room.py b/containers/Room.py index 5a7bddb..50e98be 100644 --- a/containers/Room.py +++ b/containers/Room.py @@ -1,4 +1,4 @@ -from PyQt5 import QtWidgets, QtGui +from PyQt6 import QtWidgets, QtGui, QtCore from components import Database as db, Timetable from py_ui import Room as Parent import json @@ -20,17 +20,19 @@ def __init__(self, id): self.table = Timetable.Timetable(parent.tableSchedule) parent.btnFinish.clicked.connect(self.finish) parent.btnCancel.clicked.connect(self.dialog.close) - dialog.exec_() + dialog.exec() def fillForm(self): conn = db.getConnection() cursor = conn.cursor() - cursor.execute('SELECT name, schedule, type FROM rooms WHERE id = ?', [self.id]) + cursor.execute("SELECT name, schedule, type FROM rooms WHERE id = ?", [self.id]) result = cursor.fetchone() conn.close() self.parent.lineEditName.setText(str(result[0])) - self.table = Timetable.Timetable(self.parent.tableSchedule, json.loads(result[1])) - if result[2] == 'lec': + self.table = Timetable.Timetable( + self.parent.tableSchedule, json.loads(result[1]) + ) + if result[2] == "lec": self.parent.radioLec.setChecked(True) else: self.parent.radioLab.setChecked(True) @@ -39,7 +41,7 @@ def finish(self): if not self.parent.lineEditName.text(): return False name = self.parent.lineEditName.text() - type = 'lec' if self.parent.radioLec.isChecked() else 'lab' + type = "lec" if self.parent.radioLec.isChecked() else "lab" data = [name, json.dumps(self.table.getData()), type, self.id] if not self.id: data.pop() @@ -51,9 +53,13 @@ def insertRoom(data): conn = db.getConnection() cursor = conn.cursor() if len(data) > 3: - cursor.execute('UPDATE rooms SET name = ?, schedule = ?, type = ? WHERE id = ?', data) + cursor.execute( + "UPDATE rooms SET name = ?, schedule = ?, type = ? WHERE id = ?", data + ) else: - cursor.execute('INSERT INTO rooms (name, schedule, type) VALUES (?, ?, ?)', data) + cursor.execute( + "INSERT INTO rooms (name, schedule, type) VALUES (?, ?, ?)", data + ) conn.commit() conn.close() @@ -62,7 +68,7 @@ class Tree: def __init__(self, tree): self.tree = tree self.model = model = QtGui.QStandardItemModel() - model.setHorizontalHeaderLabels(['ID', 'Available', 'Name', 'Operation']) + model.setHorizontalHeaderLabels(["ID", "Available", "Name", "Operation"]) tree.setModel(model) tree.setColumnHidden(0, True) model.itemChanged.connect(lambda item: self.toggleAvailability(item)) @@ -70,10 +76,10 @@ def __init__(self, tree): def toggleAvailability(self, item): id = self.model.data(self.model.index(item.row(), 0)) - newValue = 1 if item.checkState() == 2 else 0 + newValue = 1 if item.checkState() == QtCore.Qt.CheckState.Checked else 0 conn = db.getConnection() cursor = conn.cursor() - cursor.execute('UPDATE rooms SET active = ? WHERE id = ?', [newValue, id]) + cursor.execute("UPDATE rooms SET active = ? WHERE id = ?", [newValue, id]) conn.commit() conn.close() @@ -81,7 +87,7 @@ def display(self): self.model.removeRows(0, self.model.rowCount()) conn = db.getConnection() cursor = conn.cursor() - cursor.execute('SELECT id, active, name FROM rooms') + cursor.execute("SELECT id, active, name FROM rooms") result = cursor.fetchall() conn.close() for entry in result: @@ -89,7 +95,11 @@ def display(self): id.setEditable(False) availability = QtGui.QStandardItem() availability.setCheckable(True) - availability.setCheckState(2 if entry[1] == 1 else 0) + availability.setCheckState( + QtCore.Qt.CheckState.Checked + if entry[1] == 1 + else QtCore.Qt.CheckState.Unchecked + ) availability.setEditable(False) name = QtGui.QStandardItem(entry[2]) name.setEditable(False) @@ -97,9 +107,9 @@ def display(self): edit.setEditable(False) self.model.appendRow([id, availability, name, edit]) frameEdit = QtWidgets.QFrame() - btnEdit = QtWidgets.QPushButton('Edit', frameEdit) + btnEdit = QtWidgets.QPushButton("Edit", frameEdit) btnEdit.clicked.connect(lambda state, id=entry[0]: self.edit(id)) - btnDelete = QtWidgets.QPushButton('Delete', frameEdit) + btnDelete = QtWidgets.QPushButton("Delete", frameEdit) btnDelete.clicked.connect(lambda state, id=entry[0]: self.delete(id)) frameLayout = QtWidgets.QHBoxLayout(frameEdit) frameLayout.setContentsMargins(0, 0, 0, 0) @@ -113,15 +123,18 @@ def edit(self, id): def delete(self, id): confirm = QtWidgets.QMessageBox() - confirm.setIcon(QtWidgets.QMessageBox.Warning) - confirm.setText('Are you sure you want to delete this entry?') - confirm.setWindowTitle('Confirm Delete') - confirm.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) - result = confirm.exec_() + confirm.setIcon(QtWidgets.QMessageBox.Icon.Warning) + confirm.setText("Are you sure you want to delete this entry?") + confirm.setWindowTitle("Confirm Delete") + confirm.setStandardButtons( + QtWidgets.QMessageBox.StandardButton.Yes + | QtWidgets.QMessageBox.StandardButton.No + ) + result = confirm.exec() if result == 16384: conn = db.getConnection() cursor = conn.cursor() - cursor.execute('DELETE FROM rooms WHERE id = ?', [id]) + cursor.execute("DELETE FROM rooms WHERE id = ?", [id]) conn.commit() conn.close() self.display() diff --git a/containers/Section.py b/containers/Section.py index a3b8787..9d59453 100644 --- a/containers/Section.py +++ b/containers/Section.py @@ -1,4 +1,4 @@ -from PyQt5 import QtWidgets, QtGui +from PyQt6 import QtWidgets, QtGui, QtCore from containers import Share from components import Database as db, Timetable from py_ui import Section as Parent @@ -24,13 +24,15 @@ def __init__(self, id): self.setupSubjects() parent.btnFinish.clicked.connect(self.finish) parent.btnCancel.clicked.connect(self.dialog.close) - dialog.exec_() + dialog.exec() def setupSubjects(self): # Setup subjects tree view self.tree = tree = self.parent.treeSubjects self.model = model = QtGui.QStandardItemModel() - model.setHorizontalHeaderLabels(['ID', 'Available', 'Shared', 'Subject Code', 'Subject Name', 'Share ID']) + model.setHorizontalHeaderLabels( + ["ID", "Available", "Shared", "Subject Code", "Subject Name", "Share ID"] + ) tree.setModel(model) tree.setColumnHidden(0, True) tree.setColumnHidden(5, True) @@ -38,7 +40,7 @@ def setupSubjects(self): conn = db.getConnection() cursor = conn.cursor() # Get subjects for listing - cursor.execute('SELECT id, name, code FROM subjects') + cursor.execute("SELECT id, name, code FROM subjects") subjects = cursor.fetchall() # Subjects that the current section have currentSubjects = [] @@ -46,18 +48,23 @@ def setupSubjects(self): # [(sharing_id, subject_id, sections [str of list - load using json.loads])] sharedSubjects = [] if self.id: - cursor.execute('SELECT subjects FROM sections WHERE id = ?', [self.id]) + cursor.execute("SELECT subjects FROM sections WHERE id = ?", [self.id]) # Convert result into list of int - currentSubjects = list(map(lambda id: int(id), json.loads(cursor.fetchall()[0][0]))) + currentSubjects = list( + map(lambda id: int(id), json.loads(cursor.fetchall()[0][0])) + ) # Get active sharing by subject for id in currentSubjects: - cursor.execute('SELECT id, subjectId, sections FROM sharings WHERE subjectId = ? AND final = 1', [id]) + cursor.execute( + "SELECT id, subjectId, sections FROM sharings WHERE subjectId = ? AND final = 1", + [id], + ) sharedSubjects.append(cursor.fetchone()) sharedSubjects = [sharing for sharing in sharedSubjects if sharing] # Get section names # {id: name} sectionNames = [] - cursor.execute('SELECT id, name FROM sections WHERE active = 1') + cursor.execute("SELECT id, name FROM sections WHERE active = 1") sectionNames = dict(cursor.fetchall()) conn.close() for subject in subjects: @@ -66,8 +73,12 @@ def setupSubjects(self): availability = QtGui.QStandardItem() availability.setCheckable(True) availability.setEditable(False) - availability.setCheckState(2 if subject[0] in currentSubjects else 0) - shared = QtGui.QStandardItem('') + availability.setCheckState( + QtCore.Qt.CheckState.Checked + if subject[0] in currentSubjects + else QtCore.Qt.CheckState.Unchecked + ) + shared = QtGui.QStandardItem("") shared.setCheckable(True) shared.setEditable(False) shareId = QtGui.QStandardItem() @@ -79,9 +90,11 @@ def setupSubjects(self): if self.id not in sectionList: continue sectionList.remove(self.id) - sectionList = ', '.join(list(map(lambda id: sectionNames[id], sectionList))) + sectionList = ", ".join( + list(map(lambda id: sectionNames[id], sectionList)) + ) shared.setText(sectionList) - shared.setCheckState(2) + shared.setCheckState(QtCore.Qt.CheckState.Checked) shareId.setText(str(sharing[0])) code = QtGui.QStandardItem(subject[2]) code.setEditable(False) @@ -94,36 +107,55 @@ def toggleSharing(self, item): if item.column() == 2: subjectId = self.model.data(self.model.index(item.row(), 0)) shareToggle = self.model.item(item.row(), 2).checkState() - if shareToggle == 2 and not self.model.item(item.row(), 2).text(): + if ( + shareToggle == QtCore.Qt.CheckState.Checked + and not self.model.item(item.row(), 2).text() + ): shareData = Share.Share(subjectId, self.id).getShareData() if not shareData[0]: - self.model.item(item.row(), 2).setCheckState(0) + self.model.item(item.row(), 2).setCheckState( + QtCore.Qt.CheckState.Unchecked + ) return False shareId = shareData[0] self.shareId.append(shareId) self.model.item(item.row(), 5).setText(str(shareId)) self.model.item(item.row(), 2).setText(shareData[1]) - self.model.item(item.row(), 1).setCheckState(2) + self.model.item(item.row(), 1).setCheckState( + QtCore.Qt.CheckState.Checked + ) elif shareToggle == 0 and self.model.item(item.row(), 2).text(): if int(self.model.item(item.row(), 5).text()) in self.shareId: self.shareId.remove(int(self.model.item(item.row(), 5).text())) else: - self.removeShareId.append(int(self.model.item(item.row(), 5).text())) - self.model.item(item.row(), 5).setText('') - self.model.item(item.row(), 2).setText('') + self.removeShareId.append( + int(self.model.item(item.row(), 5).text()) + ) + self.model.item(item.row(), 5).setText("") + self.model.item(item.row(), 2).setText("") elif item.column() == 1: - if self.model.item(item.row(), 1).checkState() == 0 and self.model.item(item.row(), 5).text(): - self.model.item(item.row(), 2).setCheckState(0) + if ( + self.model.item(item.row(), 1).checkState() + == QtCore.Qt.CheckState.Unchecked + and self.model.item(item.row(), 5).text() + ): + self.model.item(item.row(), 2).setCheckState( + QtCore.Qt.CheckState.Unchecked + ) def fillForm(self): conn = db.getConnection() cursor = conn.cursor() - cursor.execute('SELECT name, schedule, stay FROM sections WHERE id = ?', [self.id]) + cursor.execute( + "SELECT name, schedule, stay FROM sections WHERE id = ?", [self.id] + ) result = cursor.fetchone() conn.close() self.parent.lineEditName.setText(str(result[0])) self.parent.checkStay.setChecked(result[2]) - self.table = Timetable.Timetable(self.parent.tableSchedule, json.loads(result[1])) + self.table = Timetable.Timetable( + self.parent.tableSchedule, json.loads(result[1]) + ) def finish(self): if not self.parent.lineEditName.text(): @@ -133,29 +165,36 @@ def finish(self): schedule = json.dumps(self.table.getData()) subjects = [] for row in range(self.model.rowCount()): - if self.model.item(row, 1).checkState() == 2: + if self.model.item(row, 1).checkState() == QtCore.Qt.CheckState.Checked: subjects.append(self.model.item(row, 0).text()) subjects = json.dumps(subjects) conn = db.getConnection() cursor = conn.cursor() if self.removeShareId: for id in self.removeShareId: - cursor.execute('SELECT sections FROM sharings WHERE id = ?', [id]) + cursor.execute("SELECT sections FROM sharings WHERE id = ?", [id]) result = list(map(int, json.loads(cursor.fetchone()[0]))) if len(result) > 2: result.remove(self.id) - cursor.execute('UPDATE sharings SET sections = ? WHERE id = ?', [json.dumps(result), id]) + cursor.execute( + "UPDATE sharings SET sections = ? WHERE id = ?", + [json.dumps(result), id], + ) else: - cursor.execute('UPDATE sharings SET final = 0 WHERE id = ?', [id]) + cursor.execute("UPDATE sharings SET final = 0 WHERE id = ?", [id]) if self.shareId: for id in self.shareId: - cursor.execute('UPDATE sharings SET final = 1 WHERE id = ?', [id]) + cursor.execute("UPDATE sharings SET final = 1 WHERE id = ?", [id]) if self.id: - cursor.execute('UPDATE sections SET name = ?, schedule = ?, subjects = ?, stay = ? WHERE id = ?', - [name, schedule, subjects, stay, self.id]) + cursor.execute( + "UPDATE sections SET name = ?, schedule = ?, subjects = ?, stay = ? WHERE id = ?", + [name, schedule, subjects, stay, self.id], + ) else: - cursor.execute('INSERT INTO sections (name, schedule, subjects, stay) VALUES (?, ?, ?, ?)', - [name, schedule, subjects, stay]) + cursor.execute( + "INSERT INTO sections (name, schedule, subjects, stay) VALUES (?, ?, ?, ?)", + [name, schedule, subjects, stay], + ) conn.commit() conn.close() self.dialog.close() @@ -165,7 +204,9 @@ class Tree: def __init__(self, tree): self.tree = tree self.model = model = QtGui.QStandardItemModel() - model.setHorizontalHeaderLabels(['ID', 'Available', 'Name', 'Stay in Room', 'Operation']) + model.setHorizontalHeaderLabels( + ["ID", "Available", "Name", "Stay in Room", "Operation"] + ) tree.setModel(model) tree.setColumnHidden(0, True) model.itemChanged.connect(lambda item: self.toggleAvailability(item)) @@ -173,10 +214,10 @@ def __init__(self, tree): def toggleAvailability(self, item): id = self.model.data(self.model.index(item.row(), 0)) - newValue = 1 if item.checkState() == 2 else 0 + newValue = 1 if item.checkState() == QtCore.Qt.CheckState.Checked else 0 conn = db.getConnection() cursor = conn.cursor() - cursor.execute('UPDATE sections SET active = ? WHERE id = ?', [newValue, id]) + cursor.execute("UPDATE sections SET active = ? WHERE id = ?", [newValue, id]) conn.commit() conn.close() @@ -184,7 +225,7 @@ def display(self): self.model.removeRows(0, self.model.rowCount()) conn = db.getConnection() cursor = conn.cursor() - cursor.execute('SELECT id, active, name, stay FROM sections') + cursor.execute("SELECT id, active, name, stay FROM sections") result = cursor.fetchall() conn.close() for instr in result: @@ -192,19 +233,23 @@ def display(self): id.setEditable(False) availability = QtGui.QStandardItem() availability.setCheckable(True) - availability.setCheckState(2 if instr[1] == 1 else 0) + availability.setCheckState( + QtCore.Qt.CheckState.Checked + if instr[1] == 1 + else QtCore.Qt.CheckState.Unchecked + ) availability.setEditable(False) name = QtGui.QStandardItem(instr[2]) - stay = QtGui.QStandardItem('TRUE' if instr[3] == 1 else 'FALSE') + stay = QtGui.QStandardItem("TRUE" if instr[3] == 1 else "FALSE") stay.setEditable(False) name.setEditable(False) edit = QtGui.QStandardItem() edit.setEditable(False) self.model.appendRow([id, availability, name, stay, edit]) frameEdit = QtWidgets.QFrame() - btnEdit = QtWidgets.QPushButton('Edit', frameEdit) + btnEdit = QtWidgets.QPushButton("Edit", frameEdit) btnEdit.clicked.connect(lambda state, id=instr[0]: self.edit(id)) - btnDelete = QtWidgets.QPushButton('Delete', frameEdit) + btnDelete = QtWidgets.QPushButton("Delete", frameEdit) btnDelete.clicked.connect(lambda state, id=instr[0]: self.delete(id)) frameLayout = QtWidgets.QHBoxLayout(frameEdit) frameLayout.setContentsMargins(0, 0, 0, 0) @@ -218,15 +263,18 @@ def edit(self, id): def delete(self, id): confirm = QtWidgets.QMessageBox() - confirm.setIcon(QtWidgets.QMessageBox.Warning) - confirm.setText('Are you sure you want to delete this entry?') - confirm.setWindowTitle('Confirm Delete') - confirm.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) - result = confirm.exec_() + confirm.setIcon(QtWidgets.QMessageBox.Icon.Warning) + confirm.setText("Are you sure you want to delete this entry?") + confirm.setWindowTitle("Confirm Delete") + confirm.setStandardButtons( + QtWidgets.QMessageBox.StandardButton.Yes + | QtWidgets.QMessageBox.StandardButton.No + ) + result = confirm.exec() if result == 16384: conn = db.getConnection() cursor = conn.cursor() - cursor.execute('DELETE FROM sections WHERE id = ?', [id]) + cursor.execute("DELETE FROM sections WHERE id = ?", [id]) conn.commit() conn.close() self.display() diff --git a/containers/Share.py b/containers/Share.py index bb53587..b8c45fd 100644 --- a/containers/Share.py +++ b/containers/Share.py @@ -1,4 +1,4 @@ -from PyQt5 import QtWidgets, QtGui +from PyQt6 import QtWidgets, QtGui from components import Database as db from py_ui import Share as Parent import json @@ -19,7 +19,7 @@ def __init__(self, subject_id, section_id): self.setSharings() parent.btnFinish.clicked.connect(self.finish) parent.btnCancel.clicked.connect(self.dialog.close) - dialog.exec_() + dialog.exec() def getShareData(self): return tuple([self.shareId, self.shareMembersText]) @@ -27,7 +27,7 @@ def getShareData(self): def setSharings(self): self.tree = tree = self.parent.treeSections self.model = model = QtGui.QStandardItemModel() - model.setHorizontalHeaderLabels(['ID', 'Sections', 'SectionID']) + model.setHorizontalHeaderLabels(["ID", "Sections", "SectionID"]) tree.setModel(model) tree.setColumnHidden(0, True) tree.setColumnHidden(2, True) @@ -36,21 +36,43 @@ def setSharings(self): cursor = conn.cursor() # Get sections with mutual subjects if self.section_id: - cursor.execute('SELECT id, name, subjects FROM sections WHERE active = 1 AND id != ?', [self.section_id]) + cursor.execute( + "SELECT id, name, subjects FROM sections WHERE active = 1 AND id != ?", + [self.section_id], + ) else: - cursor.execute('SELECT id, name, subjects FROM sections WHERE active = 1') + cursor.execute("SELECT id, name, subjects FROM sections WHERE active = 1") sections = cursor.fetchall() - cursor.execute('SELECT id, sections FROM sharings WHERE subjectId = ? AND final = 1', [self.id]) + cursor.execute( + "SELECT id, sections FROM sharings WHERE subjectId = ? AND final = 1", + [self.id], + ) sharings = cursor.fetchall() - sharedSections = list(set([section for sectionGroup in list( - map(lambda sharing: list(map(lambda id: int(id), json.loads(sharing[1]))), sharings)) for section in - sectionGroup])) + sharedSections = list( + set( + [ + section + for sectionGroup in list( + map( + lambda sharing: list( + map(lambda id: int(id), json.loads(sharing[1])) + ), + sharings, + ) + ) + for section in sectionGroup + ] + ) + ) sharings = dict(sharings) conn.close() sectionDict = {} for section in sections: sectionDict[section[0]] = section[1] - if self.id not in list(map(lambda id: int(id), json.loads(section[2]))) or section[0] in sharedSections: + if ( + self.id not in list(map(lambda id: int(id), json.loads(section[2]))) + or section[0] in sharedSections + ): continue id = QtGui.QStandardItem() id.setEditable(False) @@ -64,9 +86,11 @@ def setSharings(self): if self.section_id in sectionIDList: continue id = QtGui.QStandardItem(str(key)) - sectionList = QtGui.QStandardItem(', '.join(list(map(lambda id: sectionDict[id], sectionIDList)))) + sectionList = QtGui.QStandardItem( + ", ".join(list(map(lambda id: sectionDict[id], sectionIDList))) + ) sectionList.setEditable(False) - sectionID = QtGui.QStandardItem(','.join(map(str, sectionIDList))) + sectionID = QtGui.QStandardItem(",".join(map(str, sectionIDList))) self.model.appendRow([id, sectionList, sectionID]) def finish(self): @@ -77,15 +101,36 @@ def finish(self): conn = db.getConnection() cursor = conn.cursor() if not shareId: - cursor.execute('INSERT INTO sharings (subjectId, sections) VALUES (?, ?)', [self.id, json.dumps( - [self.section_id, self.model.item(self.tree.selectedIndexes()[0].row(), 2).text()])]) + cursor.execute( + "INSERT INTO sharings (subjectId, sections) VALUES (?, ?)", + [ + self.id, + json.dumps( + [ + self.section_id, + self.model.item( + self.tree.selectedIndexes()[0].row(), 2 + ).text(), + ] + ), + ], + ) self.shareId = cursor.lastrowid else: - subjectID = self.model.item(self.tree.selectedIndexes()[0].row(), 2).text().split(',') + subjectID = ( + self.model.item(self.tree.selectedIndexes()[0].row(), 2) + .text() + .split(",") + ) subjectID.append(self.section_id) - cursor.execute('UPDATE sharings SET sections = ? WHERE id = ?', [json.dumps(subjectID), shareId]) + cursor.execute( + "UPDATE sharings SET sections = ? WHERE id = ?", + [json.dumps(subjectID), shareId], + ) self.shareId = shareId conn.commit() conn.close() - self.shareMembersText = self.model.item(self.tree.selectedIndexes()[0].row(), 1).text() + self.shareMembersText = self.model.item( + self.tree.selectedIndexes()[0].row(), 1 + ).text() self.dialog.close() diff --git a/containers/Subject.py b/containers/Subject.py index b34305e..11b3c04 100644 --- a/containers/Subject.py +++ b/containers/Subject.py @@ -1,4 +1,4 @@ -from PyQt5 import QtWidgets, QtGui +from PyQt6 import QtWidgets, QtGui, QtCore from components import Database as db from py_ui import Subject as Parent import json @@ -20,12 +20,15 @@ def __init__(self, id): self.setupInstructors() parent.btnFinish.clicked.connect(self.finish) parent.btnCancel.clicked.connect(self.dialog.close) - dialog.exec_() + dialog.exec() def fillForm(self): conn = db.getConnection() cursor = conn.cursor() - cursor.execute('SELECT name, hours, code, description, divisible, type FROM subjects WHERE id = ?', [self.id]) + cursor.execute( + "SELECT name, hours, code, description, divisible, type FROM subjects WHERE id = ?", + [self.id], + ) result = cursor.fetchone() conn.close() self.parent.lineEditName.setText(str(result[0])) @@ -36,9 +39,9 @@ def fillForm(self): self.parent.radioYes.setChecked(True) else: self.parent.radioNo.setChecked(True) - if result[5] == 'lec': + if result[5] == "lec": self.parent.radioLec.setChecked(True) - elif result[5] == 'lab': + elif result[5] == "lab": self.parent.radioLab.setChecked(True) else: self.parent.radioAny.setChecked(True) @@ -46,24 +49,30 @@ def fillForm(self): def setupInstructors(self): self.tree = tree = self.parent.treeSchedule self.model = model = QtGui.QStandardItemModel() - model.setHorizontalHeaderLabels(['ID', 'Available', 'Name']) + model.setHorizontalHeaderLabels(["ID", "Available", "Name"]) tree.setModel(model) tree.setColumnHidden(0, True) conn = db.getConnection() cursor = conn.cursor() - cursor.execute('SELECT id, name FROM instructors WHERE active = 1') + cursor.execute("SELECT id, name FROM instructors WHERE active = 1") instructors = cursor.fetchall() subjectAssignments = [] if self.id: - cursor.execute('SELECT instructors FROM subjects WHERE id = ?', [self.id]) - subjectAssignments = list(map(lambda id: int(id), json.loads(cursor.fetchone()[0]))) + cursor.execute("SELECT instructors FROM subjects WHERE id = ?", [self.id]) + subjectAssignments = list( + map(lambda id: int(id), json.loads(cursor.fetchone()[0])) + ) conn.close() for entry in instructors: id = QtGui.QStandardItem(str(entry[0])) id.setEditable(False) availability = QtGui.QStandardItem() availability.setCheckable(True) - availability.setCheckState(2 if entry[0] in subjectAssignments else 0) + availability.setCheckState( + QtCore.Qt.CheckState.Checked + if entry[0] in subjectAssignments + else QtCore.Qt.CheckState.Unchecked + ) availability.setEditable(False) name = QtGui.QStandardItem(str(entry[1])) name.setEditable(False) @@ -74,13 +83,16 @@ def finish(self): return False if not self.parent.lineEditCode.text(): return False - if not self.parent.lineEditHours.text() or float(self.parent.lineEditHours.text()) < 0 or float( - self.parent.lineEditHours.text()) > 12 or not ( - float(self.parent.lineEditHours.text()) / .5).is_integer(): + if ( + not self.parent.lineEditHours.text() + or float(self.parent.lineEditHours.text()) < 0 + or float(self.parent.lineEditHours.text()) > 12 + or not (float(self.parent.lineEditHours.text()) / 0.5).is_integer() + ): return False instructors = [] for row in range(0, self.model.rowCount()): - if self.model.item(row, 1).checkState() == 0: + if self.model.item(row, 1).checkState() == QtCore.Qt.CheckState.Unchecked: continue instructors.append(self.model.item(row, 0).text()) name = self.parent.lineEditName.text() @@ -89,12 +101,21 @@ def finish(self): description = self.parent.lineEditDescription.text() divisible = 1 if self.parent.radioYes.isChecked() else 0 if self.parent.radioLec.isChecked(): - type = 'lec' + type = "lec" elif self.parent.radioLab.isChecked(): - type = 'lab' + type = "lab" else: - type = 'any' - data = [name, hours, code, description, json.dumps(instructors), divisible, type, self.id] + type = "any" + data = [ + name, + hours, + code, + description, + json.dumps(instructors), + divisible, + type, + self.id, + ] if not self.id: data.pop() self.insertSubject(data) @@ -106,12 +127,14 @@ def insertSubject(data): cursor = conn.cursor() if len(data) > 7: cursor.execute( - 'UPDATE subjects SET name = ?, hours = ?, code = ?, description = ?, instructors = ?, divisible = ?, type = ? WHERE id = ?', - data) + "UPDATE subjects SET name = ?, hours = ?, code = ?, description = ?, instructors = ?, divisible = ?, type = ? WHERE id = ?", + data, + ) else: cursor.execute( - 'INSERT INTO subjects (name, hours, code, description, instructors, divisible, type) VALUES (?, ?, ?, ?, ?, ?, ?)', - data) + "INSERT INTO subjects (name, hours, code, description, instructors, divisible, type) VALUES (?, ?, ?, ?, ?, ?, ?)", + data, + ) conn.commit() conn.close() @@ -120,7 +143,9 @@ class Tree: def __init__(self, tree): self.tree = tree self.model = model = QtGui.QStandardItemModel() - model.setHorizontalHeaderLabels(['ID', 'Code', 'Name', 'Type', 'Instructors', 'Operation']) + model.setHorizontalHeaderLabels( + ["ID", "Code", "Name", "Type", "Instructors", "Operation"] + ) tree.setModel(model) tree.setColumnHidden(0, True) self.display() @@ -129,9 +154,9 @@ def display(self): self.model.removeRows(0, self.model.rowCount()) conn = db.getConnection() cursor = conn.cursor() - cursor.execute('SELECT id, code, name, type, instructors FROM subjects') + cursor.execute("SELECT id, code, name, type, instructors FROM subjects") result = cursor.fetchall() - cursor.execute('SELECT id, name FROM instructors WHERE active = 1') + cursor.execute("SELECT id, name FROM instructors WHERE active = 1") instructorList = dict(cursor.fetchall()) conn.close() for entry in result: @@ -144,23 +169,34 @@ def display(self): type = QtGui.QStandardItem(entry[3].upper()) type.setEditable(False) instructorID = list( - set(map(lambda id: int(id), json.loads(entry[4]))).intersection(set(instructorList.keys()))) + set(map(lambda id: int(id), json.loads(entry[4]))).intersection( + set(instructorList.keys()) + ) + ) if len(instructorID) > 3: - instructorText = ', '.join(list(map(lambda id: instructorList[id], instructorID[0:3]))) + ' and ' + str( - len(instructorID) - 3) + ' more' + instructorText = ( + ", ".join( + list(map(lambda id: instructorList[id], instructorID[0:3])) + ) + + " and " + + str(len(instructorID) - 3) + + " more" + ) elif len(instructorID) > 0: - instructorText = ', '.join(list(map(lambda id: instructorList[id], instructorID))) + instructorText = ", ".join( + list(map(lambda id: instructorList[id], instructorID)) + ) else: - instructorText = '' + instructorText = "" instructors = QtGui.QStandardItem(instructorText) instructors.setEditable(False) edit = QtGui.QStandardItem() edit.setEditable(False) self.model.appendRow([id, code, name, type, instructors, edit]) frameEdit = QtWidgets.QFrame() - btnEdit = QtWidgets.QPushButton('Edit', frameEdit) + btnEdit = QtWidgets.QPushButton("Edit", frameEdit) btnEdit.clicked.connect(lambda state, id=entry[0]: self.edit(id)) - btnDelete = QtWidgets.QPushButton('Delete', frameEdit) + btnDelete = QtWidgets.QPushButton("Delete", frameEdit) btnDelete.clicked.connect(lambda state, id=entry[0]: self.delete(id)) frameLayout = QtWidgets.QHBoxLayout(frameEdit) frameLayout.setContentsMargins(0, 0, 0, 0) @@ -174,15 +210,18 @@ def edit(self, id): def delete(self, id): confirm = QtWidgets.QMessageBox() - confirm.setIcon(QtWidgets.QMessageBox.Warning) - confirm.setText('Are you sure you want to delete this entry?') - confirm.setWindowTitle('Confirm Delete') - confirm.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) - result = confirm.exec_() + confirm.setIcon(QtWidgets.QMessageBox.Icon.Warning) + confirm.setText("Are you sure you want to delete this entry?") + confirm.setWindowTitle("Confirm Delete") + confirm.setStandardButtons( + QtWidgets.QMessageBox.StandardButton.Yes + | QtWidgets.QMessageBox.StandardButton.No + ) + result = confirm.exec() if result == 16384: conn = db.getConnection() cursor = conn.cursor() - cursor.execute('DELETE FROM subjects WHERE id = ?', [id]) + cursor.execute("DELETE FROM subjects WHERE id = ?", [id]) conn.commit() conn.close() self.display() diff --git a/containers/__pycache__/Generate.cpython-312.pyc b/containers/__pycache__/Generate.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4b98dbd30d71d2ddf09fba909bf4d64606b641f1 GIT binary patch literal 15366 zcmcILX>1f%npJ(dy1Tl4v~3K=cH_H^IgA|+bH!jV<}eTpWE?V{##J%h>BFgN2i!5E ztOo7cSrDL^5kwnJO#Z}7Mv9~TF&?cnOSD=|qLo(EbTidk)~C=i>4PhWStYpuwI6o_qkn9Y$aTHo`>N z5jJWWv9S1UiCCky5qs1z;)s@vltj4^F6ta{5}GyQin>R50^1^>g)cV+A+l;{_hRJ%R^fui%BaR49eGY|0iWmvCLj*t~v}0F2Z1rMx_NXOw5W$fDTTsb z3K{7~S@0@5&4$YjJcaV;OgPsbr7}#|XTTJiWVi57|vZ>5lt3Kqda*#NA>T1v?))kAScO4k8O zEc`8_1chkHe&*GE408c^;8ojIJJgcn4>Tu~f5m_)G;Mok ze_y3}jda>BSg=P%+3PRb7+5Q_@qXJVN1;`A!gna$NR1X?Oa+ol&qK#gxRq#>qmV(L zVglR{2w>~j#H8kkiqW__ku!V~NmzgUpdCvBqxAlZYpR5h~0z8_4I^HJbopUh^j6 z69+Fz@n~F*M@1Q>GGI$4B=OCVcv*92n>!{>$r1;(X{DegP^piKg65c% zjvbzw5H*JmYo%FSC=n5lgrHjA!AUt0kA{+>P9aG9>ETdR#9>10ARm%u$1h1M!6ZJJ z&`QSQu^3F6=FTx!o&qHMntOgKppt0aTgP@Q^844kV?iPFqNX9 zxfAj6aa4;47U*YSUNsN&ZQ|qv>OQb!nrrOR>!-343rj)@WItVF(TivFmDTKH5itlI z4kbibeMfL&LW~JoNl*|50i*fGCMBHG!I&UkId~};8;ABiV+5eJ^JE<7;}R%su%_Y_ zaSS$=O%@}sY1~*=SCf!y=2nC3Dy>9-Zz6eL*Z6?#wwy;g9+dgAUbL%pdRWr8h&M(%i%~Y+))YfHc*6IJh@|0A$ko35W zY1n{yYcrMAh{&v|g@lL9h^<-jHL1QH#n+SaZJ*&XzFO6{QSog|`8L59$KQ0$I#sSl z;cD*Iq`AhWhIX}KtJ1J_(Uxx5`;glURk?4y_GLqh+OS1w*ph1KddPL@$S*kWP4BGt z)|+XrKErucu1?|VmiUUBgR_Gw?^k%g%C{+e+mg5PW@t8~dK(pQqw3wJc(;9JWj)tBb@wxK3zEou^j%*1quik$3`=jvT!oIs^T`IRu z;nt~Kqrx@L^?bPh-u^V#ouiR)Rbv0LlTuZyRt1!*fL??5X6bCH$~7olgUYojT-&@& zZQrT1?@V*MU_>}Nm8(~{dX;NcxYoIZ+O|t++m+^e$#~Z)+**~}pl};hE}(FM`DV3a zkJ7Ox&F#&jW9?~fL&o3yq4S<|zC-c9p!#CFC_riC>_tH;5%TPTDKKFT=?BuwI+QFU z+|HjJCos5VIf$6asF;TWb27^s&)_r>ZX@l0rnC~^`@`augwz9H_gONTGLAAkiMs$y zRu)ep^4C6~$f%XV6ymbt)xZ2mbUx(kzqVSOu1wDW zNy&TE?x*%;C)E?Ekin zjZM2s?RXZ80__`^!5&I7Q(>V-Gt)df9vE5fSV7J*T9c86D-4)IVe6b#um7`a_pi+P%)Wo)n$t5@u2oTuIqUw? zPnm=!lje{^cS7Nu0qo6Qa2zaCq_6+(#x0!RkFmSe1;U$c)bK3yh&N}WVNm= z(W4XlbyZArp`xB8WtG))sGFC@sb-lamg?nl3a4}y8qVjbhu}L|mE)<zmi${)f1l#- zd(ixgz^8$f|2S4uM=~Op(5q0nZ3?$-p-1iRSGxPt+@U=BMupp`a@`8oz0j}r99DV` zr@4VVdb`54tK3$F+qzKs(}qt#qv*?{7E1r4%J!pa?pPkZN#UAuoGM>vq8pBg+z0?f zWMvjwgiL$Jd@T?{4h&dmhl>Mf8P*Y4+9tn+K66Hi;ab!tJ-|_h66%;(k0k_U#92etP zU;yY-N(`e*MH&aH<^j%Q3_<5UZottIXfF83_ExLF%;>~`Zcm=pLtwNH+qq+KWy$%n|CYCyB7x@^!@B;s(B#I9Rb#_ zb34O0eb~{fcJwJ7eGl3`+wf^es^dhO8_MM~OyGy@d(`%WO8dbF1E2MMdNkF3GR>XJ zf8e->C9n<8E8nvDo!VZ;Idd z6s;08UOjprkr%5Rim->9`_;|Il+DLJ8+bT;_Vc5u&F9nH%ehL?xKX)Ih3kB{>43Uv zP}wy2S=+;x&V1gH+I032cWxyE$IU_*_|E}A1LvD9$^_;m!A$)&Zi+z3&E*6(jXFbU1e(WaR%S3mWX1s%ISfNzv;Bj=r%tI+X-boIpsz8x5%+BXl)NXmV?O zzSoQjQTLeP`7GFk7okYfms6DVO^8aD2n6{>h;Rq`s3}ypRNwf1^xf$Eu~hv|Lvg~b zdAH~N-S6&JYrB-%F12=_QoAoz`{E<6Z{-T1sXnEY z?3S)8+!Xv(_NKsbwIpx6C3I{ud%a@1M6hF>vPE#jJkvJ)27+QqYvcytDhIcOIg`!k zl>k@eX1fb&a$@OeBAoTv02~o#P&=v9sC}BFm*_xqBfg)x=^V3+gAeIdxKF+6oOS|* zh^M^NgE^D%H*URcxn5<1+*h4~_dP2eA9yuEZZ|Zm5S)^cTj-u=jCGG19_BouP~hywVat1Tp-@^rV_Pb%xYeWj zS`}Ywy0mRR@$vMJr!&5qjBkyOoO?s@1?D#>zE0KGrTDrQIuzet@Bmj--wE6f%#?s* z_-?Ie%7J-wh7qg>Nao{gB1q{-O7tH|5{D%#=C3S#RZ%ulm;IAMDAL)nuAF z=DR-VeYXM_{9dJ-vSg+E?89^CmF|~kj)G_N=CRphU({{LtnXBz?)BZ7nua--QnPV> zK&k0jIIYy|KuihvUFO#;l;2-xU>l#5*y^eu^UO*191Asm9{!!x(pa4tIC|H2cYH4R zZg{?JVZ;57h0BX?e3AtD_RE?B%b4SUgZ}EoBX0d4m)($s z`1}86q`NERHmx}VG@;f*$2q=}&7!2Jtetelw$#$*W_pgIT|=>_cn8X%GtIrg91;E0#8 zMqU3PPWL?TBl$+FD$O-4an&kEY%Afz@V)Rt^CND@N}i7$CeynW0F=rC`+7SZta2D) zj`ss88;l8>f+2$8NX|Ssr13tU3N>2-Zp;dXBLFp7lN(NvmtYpCGEM;u%3XS^>z!T1 z|6Z@~^^bV}V=Kc~=^fAS5KbTI_`d`2Jp00MDi`@sZBS8BFk5>w6+^I?i5T-;Vk#bT zteCQ7n&M6h*z{>mmK}-&CuC9Z<5eN5>3`xbUFwZSdu2ILB5i`slS?|d#*=mZx&)M7 z%u7^gomp~;_?ZOW+OF`;Y=iPER1PeC0|@d7h+usxYwir*9#kt^l**R5V5+hmFN1Pg zq3(!5RXD@fXYWab4@37tYU@s=b?4%`RBL~VKVRf4H_$()mT9(#MgrYaTP&IG~uwxYqW6-=&dzGZ^etR+%8F=o127i4~2}B zp0ukL(8+fgcnam{`1WrX#Tu#LN}yCDA%QolB!tnJD+B~ujKDFA3ZZc}4P=2YbHNsw|b_qZM&(Ptd8!cr&+=jp_rewvzQ)m5WW$3f);xEPRANxc{iW3&?@xU31u*_TB`DsI zT9!6KfQH+TN?Q_b&FP+7D+sx2m1{l+Jybjaxq6b${1a<<7eLri}A7o7&Fvc90Ut7 z$2bApT}Iy6A;=9Iyg2ACFEdpY#4B;AQTDx>@~peLR;huw)&vq4)C1~zaWHeunb}B! z!%Rso?(H*M`}1$B(8wqX(3(CnGDEp9eVo}@HhKW|7^mA~x*H2K7;+-%&6758#gbfG zC}{xY--K?l69)pEgpN7FadmGNVdsB`IKs}y5qb|I>L&Ohzy)^o1wbU%6xr1v_K0}- z6m$P0M7poQ`Hu6}=~?d$C)n6Gcg^m)%f7QOQ?qua|HdHf_B=+Q@|_CbIsfuP@ct`l z-mt~*A{S73!lk&y@=x50eV=&KJYK=;mj}k{zlTlTYE!S$)VsJ7E<$#vnhGvLjBDQv z-=^}L6@K&ll|}acTZ>)yzq@$lGxle1eb)7}@22=6!%)<{DdqTZGZu`BqobN@bTk^r zUjhNlkB+`E8I0%@={Ss;Jb{x?tJB3RYD&_#G5QWh7cuI`=o&@>Mri-)5)-HOK0|yC zy7v!lJMt?XR0ZUhAiBmZTQ=IOmq%FEzG2y6v%8+~R{IOfE~mY9xtg^fWS1RI`+0V` z+G;<*F1u>%b&q?PdjAu~YTvo+vOpmY3N7=UcK?$Ltjq4wo5PmI;4c@@Aja_I97KNu z9EJWS$-;vM{$l&q(lwcvrvX8II21$ksV+kb#ZA)IHn1RmNw;?}M72H_zjy=?|yHP^w){=#p- zE(b%2VpoV(GCC@V5qKS3w_5)Q`B&IIRC%%|Y}R?hy|QoUXC!@lIV%y&_`LKZ;OLmE zC=|InY(-@F6fBdBB<1-lO`I2WrFCU7#qF`JKe))m^FT z?pxNSwe9NK9m?7rskOUqIlioHQY&{Tl{*$4smlFJ__a-`+_tcNal@Omd8E@8jAgG>~SSiR!Melz$4vYfQ#dKXXp?)GMC)yKkmEt#2QO$$5JqQ&#!*;8PoGuU&Sq_R8Nm+;+XY zq=G<|W&A>d21d-3ZX11o#gin@>8x!=M)4EGpTOuCM1SJ;=z?jV^w02#K1_09 z``F5|?0+y#zqdG8%hwD>UWRS?4YTeyO!coB&#xKx?;UShSl3q!#!sj1)okV6!|xBh MJM=XJAZg)$0ntMy-2eap literal 0 HcmV?d00001 diff --git a/containers/__pycache__/Instructor.cpython-312.pyc b/containers/__pycache__/Instructor.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..daccac74327805ff19cb69a5cdc5257900aeb173 GIT binary patch literal 10589 zcmb_ie{2(ZcAv4w_ShcBNt}Q~65^0RVh99S7Iry)Y#<5AE(rt@SiEd=-pr8L>)6?u z@j`q~g-)n-wou?!71`>fWqT)WB39b$U*%M(<)^?3x?e{F& zh#{w1=72J~SjNm!LFZT4AZS&bBjWi8JIRTHVjB@pBqNG_L_D70xu8X%d&6S*ov^?u z&e6y;2k96WBo)_SToC!>gqYxmC$xFAxG*WPx(o7m2#yGmED^G>Wi1d>tQBG# zXJ@Hv#Jxh_kYm;swDUA%C-fn(%3AoX{x6BcrO7lgj^%0)u~rRHefRVN`07Jn!9K;7 za~9F5H;SsKq35)3SueX@H)l;-qh38{eAAYDKo-BoS{HeR@r_ zR!}=tCI?Qu%QE`q% z#`UTht;iv8Vsd6IqR^Kju~>hCpXMDnhDW{5XD6mOHW}j-o0?Ue?}+jKNIW7;DUOL) zWa3?pg+wAA=O#qOeo3prM#sbP2`;ACCSnQT4~o0OO#~^061dnUo`LcCDva<#2zWmO z5WYP#aq!}p!12Px*I|NqGB9*;C@DlHF80JG6MRIRnjVWs-iP{#ID0%676hF-{vwbd zh9hz8YjEGLnOTJ%9|xku@$roU}J$4X15+_GD0*`00K`-t8P zMebXdp0sS0Te_u|?rh7RNAw=8Fi%(AteUU7^?r`t{42L7&s5(WnjgAx>Ki+;sZDO^ zk{Y@e&&fM`q@6w4hGUuD>#su(nf6PxU#0^R9gyixiSAsi`@C_fF-O0=POTg~CcE**|T;%^e3WtM=Cco0I zod(g`02!U1^zWK8Y|wie-xtncHJ?GmVl|jaq%~G(BB#WnoHCP5utKVA{=$iaOf2r! zED^K~rw*R&JK1-9G!PF@b6tU{M3NV}0z!eu1N~=C4Fw`a@Dc*&2l~$R1tM(VaNsD9 zgMNj#>MKkIYZMFnj^Y7iJg%{SBoSBa6EI?eR~*RiNs&`o9V81UPD~|$I~$>=%Jd2o z18(hOBjPZSqM#5O<*tZ|6_8W$=yd}~pel}d6#WVn6<`uuED>e}9uGK3@whVzg(8UG zhDkfm3CWmPlqx(5a~^L<9jF?F@Rtx>C04vOvbRO@wq(7n87f~>f2Z+wV}IC0PSUh0O3Uy1YK}WpcW8OD5wl(LSa2YAds`j z@|D9t{=1GeM>+|yC{orK(?qnaN1e{nb0Dr*%e%lpf(KI8cY7g4LyAhlu0YKJxC*cm zCn`%8u_&IRh)5M-4dz@&h0&>io+j$cBn66+X^l_~Dn(IT8D!|9QWaEqPb)&&s?Vsl zFjIMu-ztJJ>MYR)s@Vl%mb_xUKwKt4K=f-|&O)C_t>5FL!77zw`5+W1l&ErPBrft@ zkmq+|p^Z&W&u9#(I6xqvTC8!tbtW;RRD($2c+r4g4f~O{BLAX5Qf#U~QYaSsSMV>2 zw^WTW#4b(MK#mt=h^`Wky}p}2n*WjP?U1}3vbRg}cICXg@;-n5`HHM}SB83Ou{j%7 z>NYM=AG<$t%l$!Z2dRazyJ!FWt;N3O<4bSc-}7bH zq5Q_Cr&eO;;ioiFQ-6#5>FCFyk3x&o=dLA}+<8#yJech~lx;qIU;LZPzqtI!djfNkufk(YQMfO^qHfJqC1wWJ9H_~W%}w1WF@v;z1q z@}EAAp&r1Eet~)bMw)H-D_nl6Z|rn$&nN&@33Q$9(@+kftAKP`vWRw2Q3i0S*9M2r z_MI6G3=WT;DjTcQ6fT2-b3G@=`pyPAVFLUg91S}7b|8pHZCyhnYmAHY9gqcROiWKl zL=^&qR{jUrq+4$%;5tAB*1+l&$fO!eE;}r&jDbLm5yAvSSBWQUf!2zySbOeB9Z4WvWYLw@=GSj-qS+y|gA0vvA^WVd`hCX<(YCvo<{XmS?}sBX zbbKh(uqwkS)qyyq5|qnlKOYLe)tg^{~d zj^3&^M|_fL)LXM#PUh$#loQN6bE8US$ubTqYN4OO8Lp{?7P$lHErc~RLK7nu5Td9@ z>b(sFVT-1yev5zuNiz=AZ?@>tM={d}P5G&4UgO*A~6vN>DY7A=~R##}78-qMyyO9|go(RFn`n5Sq;8sq5mkOY{C)Ue93{1&KB zb*}-f;Rz8uF^H&vG7t@V)my5g48~QuEG5_VcNwse94;t=Z;7Skoc*?(+*v7c@7IymL_6Iryc2@b;dE?`7y0+mnYM&=0rV|HBgYD}~=1jK)@_q7hLK znP&CBVG|LUKv+YzGDJ-niv`h_qqmZ21y`F-^Esz1qHNsYmjDhQf*eb`c8 zvBk`rT$};@MkX+(*8_lBdx=|?w>g5Cqt<6XvB+|1iY3cDD1|*=oAGp^LK5rGq0=>I zPutB{lckK2poIx@0&O;=jkT$wrCls~r=x-AcRGq}TM?qjQWYWI_C3Zyysijk)SHSZ zqs96=RdyP7)6;OI9p+;2|2qflrK5D@IXX@MZX*`Y*O_*{Xrwjx4-M;zkhZ1mX*%sl zJ11==YulkWi=y#e5sH+!M57(PG*twaPP=rzo^z+&(cKjdARB$@`7)hHE|IFr=)C4M zrOa$bSILY_n)#kHy4RR-p9!rlowhko+7m^4sUold&-m{iYIG1lZg`@vYU$EA?bb(H zvjt=y~L?D`aiz|3gCoa!z(aU*P3K*QmpD;LeM z=iIpcqbip3Z7>;+q$m_RUdz-q#0ww%43*qss*)EC6+%VKDvo0Y z3c5Id8ZxQPDg+l)+vm0LYtTl(mqbuq!Fe+Ki`j>@e>HbiQ^6H`FBjv)ay#vJAlnY= zIt<4HPH0N?cOvzVN=SWB_xFvzY@1)`>vod((X~hke1D>5~a4~2`paP}lJbKR1vG})fsz1PJ z9D6&*;;I$~Z+6b`%nTQ2fi&&K&_2@7qxt3@Ih_=yjwMAAEH{Kl%^Y!$3>-^bIT@Z! zBt@lGHDBT)JSYl7VSW<46EGgjYVYK#siIUtn?cn63WXsU3LJ?DZ-$=6qvSy?5uE;- zGRK59b5b?zcw{9Wd6H+bq4N@wh|5-f~02YI$3BC#C zDW>!qhM`300kaV<-DAz~QE<(L@78^~>61-z>prP;c(rJDAipIxk9d~eDBv$wM~FJ+G9nJRS2EWDg!TAwrqTnvbb zfCk+GaVjDN0EPJ3qp2!*g}xNwrvn-qM2Odb6WV*>xf>n^)_vFx)@l&w9vR{UAw0yjb&sG1oq|$TUZ7Yna01^1 zz0L67@Na1BU2t-!{tf)=8eEtPmIihTl|GILjGc08$fjyG=+Y4W6C!vdsBM&MJEYo< zY;7>($kX1N-g)m&oto&B{d*<DZ%x;ORAjeT%*#aA!;+9Y3F*0&W9qrTzJTesi(@a;^0;mP7rW6y(Q5BBAl zfx=_>^&w0EkX#2)tiE}2{^X6}ryhc7RD~}*Q}D0BiuoRlj$wp1l^@0k1*fV=@VHfc zFGc~3)ISjD#}r0`@DuQ$@GZh=+xTpQ%U1u)zr%LqS%|dQHm=gOHf=VwdC;TSPS1{r z`_)UN`iC|DmJ8l{X5eogKuO~9th94ShoxehnH^6?G;xmVuKJ3qj#fbxc(ApHmLvQP zXos>+*a6W~D@l^SCbmn&_Fogb|DD+OZ-o0d_M>Fo*91hr>9xE?l8w&@jMXLnA6q<{ AS^xk5 literal 0 HcmV?d00001 diff --git a/containers/__pycache__/Main.cpython-312.pyc b/containers/__pycache__/Main.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..667fe74e284c72990ed369e8342bc9b7a69feefd GIT binary patch literal 23118 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 literal 0 HcmV?d00001 diff --git a/containers/__pycache__/Room.cpython-312.pyc b/containers/__pycache__/Room.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c9505a114c19b0a89618e06e7f91793704b8c888 GIT binary patch literal 10306 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 literal 0 HcmV?d00001 diff --git a/main.py b/main.py index 5f8a226..f34d5f5 100644 --- a/main.py +++ b/main.py @@ -1,14 +1,14 @@ -from PyQt5 import QtWidgets +from PyQt6 import QtWidgets from components import Database as db from containers import Main import sys # Entry point for application -if __name__ == '__main__': +if __name__ == "__main__": if not db.checkSetup(): db.setup() app = QtWidgets.QApplication(sys.argv) parent = QtWidgets.QMainWindow() Main.MainWindow(parent) parent.show() - sys.exit(app.exec_()) + sys.exit(app.exec()) diff --git a/py_ui/Generate.py b/py_ui/Generate.py index 0792397..b141eb9 100644 --- a/py_ui/Generate.py +++ b/py_ui/Generate.py @@ -1,12 +1,12 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'generate.ui' +# Form implementation generated from reading ui file 'qt_ui\generate.ui' # -# Created by: PyQt5 UI code generator 5.6 +# Created by: PyQt6 UI code generator 6.6.1 # -# WARNING! All changes made in this file will be lost! +# WARNING: Any manual changes made to this file will be lost when pyuic6 is +# run again. Do not edit this file unless you know what you are doing. + -from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets class Ui_Dialog(object): @@ -20,11 +20,11 @@ def setupUi(self, Dialog): self.verticalLayout_2.setObjectName("verticalLayout_2") self.horizontalLayout_2 = QtWidgets.QHBoxLayout() self.horizontalLayout_2.setObjectName("horizontalLayout_2") - self.groupBox_3 = QtWidgets.QGroupBox(Dialog) + self.groupBox_3 = QtWidgets.QGroupBox(parent=Dialog) self.groupBox_3.setObjectName("groupBox_3") self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.groupBox_3) self.horizontalLayout_5.setObjectName("horizontalLayout_5") - self.cmbSection = QtWidgets.QComboBox(self.groupBox_3) + self.cmbSection = QtWidgets.QComboBox(parent=self.groupBox_3) self.cmbSection.setObjectName("cmbSection") self.cmbSection.addItem("") self.cmbSection.addItem("") @@ -32,67 +32,67 @@ def setupUi(self, Dialog): self.cmbSection.addItem("") self.cmbSection.addItem("") self.horizontalLayout_5.addWidget(self.cmbSection) - self.chkPreview = QtWidgets.QCheckBox(self.groupBox_3) + self.chkPreview = QtWidgets.QCheckBox(parent=self.groupBox_3) self.chkPreview.setObjectName("chkPreview") self.horizontalLayout_5.addWidget(self.chkPreview) self.horizontalLayout_2.addWidget(self.groupBox_3) - self.groupBox_4 = QtWidgets.QGroupBox(Dialog) + self.groupBox_4 = QtWidgets.QGroupBox(parent=Dialog) self.groupBox_4.setObjectName("groupBox_4") self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.groupBox_4) self.horizontalLayout_4.setObjectName("horizontalLayout_4") - self.btnPause = QtWidgets.QPushButton(self.groupBox_4) + self.btnPause = QtWidgets.QPushButton(parent=self.groupBox_4) self.btnPause.setObjectName("btnPause") self.horizontalLayout_4.addWidget(self.btnPause) - self.btnStop = QtWidgets.QPushButton(self.groupBox_4) + self.btnStop = QtWidgets.QPushButton(parent=self.groupBox_4) self.btnStop.setObjectName("btnStop") self.horizontalLayout_4.addWidget(self.btnStop) self.horizontalLayout_2.addWidget(self.groupBox_4) self.verticalLayout_2.addLayout(self.horizontalLayout_2) self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") - self.boxGen = QtWidgets.QGroupBox(Dialog) + self.boxGen = QtWidgets.QGroupBox(parent=Dialog) self.boxGen.setObjectName("boxGen") self.gridLayout = QtWidgets.QGridLayout(self.boxGen) self.gridLayout.setObjectName("gridLayout") - self.lblFitness = QtWidgets.QLabel(self.boxGen) + self.lblFitness = QtWidgets.QLabel(parent=self.boxGen) self.lblFitness.setObjectName("lblFitness") self.gridLayout.addWidget(self.lblFitness, 2, 0, 1, 1) - self.lblPreviousFitness = QtWidgets.QLabel(self.boxGen) + self.lblPreviousFitness = QtWidgets.QLabel(parent=self.boxGen) self.lblPreviousFitness.setObjectName("lblPreviousFitness") self.gridLayout.addWidget(self.lblPreviousFitness, 2, 1, 1, 1) - self.lblPopulation = QtWidgets.QLabel(self.boxGen) + self.lblPopulation = QtWidgets.QLabel(parent=self.boxGen) self.lblPopulation.setObjectName("lblPopulation") self.gridLayout.addWidget(self.lblPopulation, 1, 0, 1, 1) - self.lblMutation = QtWidgets.QLabel(self.boxGen) + self.lblMutation = QtWidgets.QLabel(parent=self.boxGen) self.lblMutation.setObjectName("lblMutation") self.gridLayout.addWidget(self.lblMutation, 1, 1, 1, 1) - self.lblHighestFitness = QtWidgets.QLabel(self.boxGen) + self.lblHighestFitness = QtWidgets.QLabel(parent=self.boxGen) self.lblHighestFitness.setObjectName("lblHighestFitness") self.gridLayout.addWidget(self.lblHighestFitness, 3, 0, 1, 1) - self.lblLowestFitness = QtWidgets.QLabel(self.boxGen) + self.lblLowestFitness = QtWidgets.QLabel(parent=self.boxGen) self.lblLowestFitness.setObjectName("lblLowestFitness") self.gridLayout.addWidget(self.lblLowestFitness, 3, 1, 1, 1) self.horizontalLayout.addWidget(self.boxGen) - self.groupBox = QtWidgets.QGroupBox(Dialog) + self.groupBox = QtWidgets.QGroupBox(parent=Dialog) self.groupBox.setObjectName("groupBox") self.gridLayout_2 = QtWidgets.QGridLayout(self.groupBox) self.gridLayout_2.setObjectName("gridLayout_2") - self.lblCPU = QtWidgets.QLabel(self.groupBox) + self.lblCPU = QtWidgets.QLabel(parent=self.groupBox) self.lblCPU.setObjectName("lblCPU") self.gridLayout_2.addWidget(self.lblCPU, 2, 0, 1, 1) - self.lblTime = QtWidgets.QLabel(self.groupBox) + self.lblTime = QtWidgets.QLabel(parent=self.groupBox) self.lblTime.setObjectName("lblTime") self.gridLayout_2.addWidget(self.lblTime, 0, 0, 1, 2) - self.lblMemory = QtWidgets.QLabel(self.groupBox) + self.lblMemory = QtWidgets.QLabel(parent=self.groupBox) self.lblMemory.setObjectName("lblMemory") self.gridLayout_2.addWidget(self.lblMemory, 2, 1, 1, 1) - self.lblStatus = QtWidgets.QLabel(self.groupBox) + self.lblStatus = QtWidgets.QLabel(parent=self.groupBox) self.lblStatus.setObjectName("lblStatus") self.gridLayout_2.addWidget(self.lblStatus, 1, 0, 1, 2) self.horizontalLayout.addWidget(self.groupBox) self.verticalLayout_2.addLayout(self.horizontalLayout) self.verticalLayout_5.addLayout(self.verticalLayout_2) - self.tableSchedule = QtWidgets.QTableView(Dialog) + self.tableSchedule = QtWidgets.QTableView(parent=Dialog) self.tableSchedule.setObjectName("tableSchedule") self.verticalLayout_5.addWidget(self.tableSchedule) diff --git a/py_ui/Instructor.py b/py_ui/Instructor.py index aa9aca2..8c4b459 100644 --- a/py_ui/Instructor.py +++ b/py_ui/Instructor.py @@ -1,54 +1,54 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'instructor.ui' +# Form implementation generated from reading ui file 'qt_ui\instructor.ui' # -# Created by: PyQt5 UI code generator 5.6 +# Created by: PyQt6 UI code generator 6.6.1 # -# WARNING! All changes made in this file will be lost! +# WARNING: Any manual changes made to this file will be lost when pyuic6 is +# run again. Do not edit this file unless you know what you are doing. + -from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets class Ui_Dialog(object): def setupUi(self, Dialog): Dialog.setObjectName("Dialog") Dialog.resize(716, 553) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Minimum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(Dialog.sizePolicy().hasHeightForWidth()) Dialog.setSizePolicy(sizePolicy) Dialog.setMinimumSize(QtCore.QSize(716, 553)) Dialog.setMaximumSize(QtCore.QSize(716, 553)) - Dialog.setFocusPolicy(QtCore.Qt.NoFocus) + Dialog.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus) Dialog.setModal(False) self.verticalLayout = QtWidgets.QVBoxLayout(Dialog) self.verticalLayout.setObjectName("verticalLayout") self.gridLayout = QtWidgets.QGridLayout() - self.gridLayout.setSizeConstraint(QtWidgets.QLayout.SetMinimumSize) + self.gridLayout.setSizeConstraint(QtWidgets.QLayout.SizeConstraint.SetMinimumSize) self.gridLayout.setObjectName("gridLayout") - self.lblName = QtWidgets.QLabel(Dialog) + self.lblName = QtWidgets.QLabel(parent=Dialog) self.lblName.setObjectName("lblName") self.gridLayout.addWidget(self.lblName, 0, 0, 1, 1) - self.lineEditName = QtWidgets.QLineEdit(Dialog) + self.lineEditName = QtWidgets.QLineEdit(parent=Dialog) self.lineEditName.setObjectName("lineEditName") self.gridLayout.addWidget(self.lineEditName, 0, 1, 1, 1) - self.lblHours = QtWidgets.QLabel(Dialog) + self.lblHours = QtWidgets.QLabel(parent=Dialog) self.lblHours.setObjectName("lblHours") self.gridLayout.addWidget(self.lblHours, 0, 2, 1, 1) - self.lineEditHours = QtWidgets.QLineEdit(Dialog) + self.lineEditHours = QtWidgets.QLineEdit(parent=Dialog) self.lineEditHours.setObjectName("lineEditHours") self.gridLayout.addWidget(self.lineEditHours, 0, 3, 1, 1) self.verticalLayout.addLayout(self.gridLayout) - self.tableSchedule = QtWidgets.QTableView(Dialog) + self.tableSchedule = QtWidgets.QTableView(parent=Dialog) self.tableSchedule.setObjectName("tableSchedule") self.verticalLayout.addWidget(self.tableSchedule) self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") - self.btnFinish = QtWidgets.QPushButton(Dialog) + self.btnFinish = QtWidgets.QPushButton(parent=Dialog) self.btnFinish.setObjectName("btnFinish") self.horizontalLayout.addWidget(self.btnFinish) - self.btnCancel = QtWidgets.QPushButton(Dialog) + self.btnCancel = QtWidgets.QPushButton(parent=Dialog) self.btnCancel.setObjectName("btnCancel") self.horizontalLayout.addWidget(self.btnCancel) self.verticalLayout.addLayout(self.horizontalLayout) diff --git a/py_ui/Main.py b/py_ui/Main.py index a555b4b..2efeb20 100644 --- a/py_ui/Main.py +++ b/py_ui/Main.py @@ -1,146 +1,141 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'main.ui' +# Form implementation generated from reading ui file 'qt_ui\main.ui' # -# Created by: PyQt5 UI code generator 5.6 +# Created by: PyQt6 UI code generator 6.6.1 # -# WARNING! All changes made in this file will be lost! +# WARNING: Any manual changes made to this file will be lost when pyuic6 is +# run again. Do not edit this file unless you know what you are doing. + -from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") - MainWindow.setWindowModality(QtCore.Qt.NonModal) + MainWindow.setWindowModality(QtCore.Qt.WindowModality.NonModal) MainWindow.resize(800, 600) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Maximum, QtWidgets.QSizePolicy.Policy.Maximum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth()) MainWindow.setSizePolicy(sizePolicy) MainWindow.setMinimumSize(QtCore.QSize(800, 600)) MainWindow.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.centralwidget = QtWidgets.QWidget(MainWindow) + self.centralwidget = QtWidgets.QWidget(parent=MainWindow) self.centralwidget.setMinimumSize(QtCore.QSize(711, 526)) self.centralwidget.setObjectName("centralwidget") self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.verticalLayout.setSpacing(0) self.verticalLayout.setObjectName("verticalLayout") - self.tabWidget = QtWidgets.QTabWidget(self.centralwidget) + self.tabWidget = QtWidgets.QTabWidget(parent=self.centralwidget) font = QtGui.QFont() font.setBold(False) font.setWeight(50) self.tabWidget.setFont(font) self.tabWidget.setStyleSheet("") - self.tabWidget.setTabPosition(QtWidgets.QTabWidget.North) - self.tabWidget.setTabShape(QtWidgets.QTabWidget.Rounded) + self.tabWidget.setTabPosition(QtWidgets.QTabWidget.TabPosition.North) + self.tabWidget.setTabShape(QtWidgets.QTabWidget.TabShape.Rounded) self.tabWidget.setObjectName("tabWidget") self.tabInstructors = QtWidgets.QWidget() self.tabInstructors.setObjectName("tabInstructors") self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.tabInstructors) - self.verticalLayout_2.setContentsMargins(9, 9, 9, 9) self.verticalLayout_2.setObjectName("verticalLayout_2") - self.groupBox = QtWidgets.QGroupBox(self.tabInstructors) + self.groupBox = QtWidgets.QGroupBox(parent=self.tabInstructors) self.groupBox.setObjectName("groupBox") self.horizontalLayout = QtWidgets.QHBoxLayout(self.groupBox) self.horizontalLayout.setObjectName("horizontalLayout") - self.btnInstrAdd = QtWidgets.QPushButton(self.groupBox) + self.btnInstrAdd = QtWidgets.QPushButton(parent=self.groupBox) self.btnInstrAdd.setObjectName("btnInstrAdd") self.horizontalLayout.addWidget(self.btnInstrAdd) - self.btnInstrImport = QtWidgets.QPushButton(self.groupBox) + self.btnInstrImport = QtWidgets.QPushButton(parent=self.groupBox) self.btnInstrImport.setObjectName("btnInstrImport") self.horizontalLayout.addWidget(self.btnInstrImport) self.verticalLayout_2.addWidget(self.groupBox) - self.treeInstr = QtWidgets.QTreeView(self.tabInstructors) + self.treeInstr = QtWidgets.QTreeView(parent=self.tabInstructors) self.treeInstr.setObjectName("treeInstr") self.verticalLayout_2.addWidget(self.treeInstr) self.tabWidget.addTab(self.tabInstructors, "") self.tabRooms = QtWidgets.QWidget() self.tabRooms.setObjectName("tabRooms") self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.tabRooms) - self.verticalLayout_3.setContentsMargins(9, 9, 9, 9) self.verticalLayout_3.setObjectName("verticalLayout_3") - self.groupBox_2 = QtWidgets.QGroupBox(self.tabRooms) + self.groupBox_2 = QtWidgets.QGroupBox(parent=self.tabRooms) self.groupBox_2.setObjectName("groupBox_2") self.horizontalLayout_7 = QtWidgets.QHBoxLayout(self.groupBox_2) self.horizontalLayout_7.setObjectName("horizontalLayout_7") - self.btnRoomAdd = QtWidgets.QPushButton(self.groupBox_2) + self.btnRoomAdd = QtWidgets.QPushButton(parent=self.groupBox_2) self.btnRoomAdd.setObjectName("btnRoomAdd") self.horizontalLayout_7.addWidget(self.btnRoomAdd) - self.btnRoomImport = QtWidgets.QPushButton(self.groupBox_2) + self.btnRoomImport = QtWidgets.QPushButton(parent=self.groupBox_2) self.btnRoomImport.setObjectName("btnRoomImport") self.horizontalLayout_7.addWidget(self.btnRoomImport) self.verticalLayout_3.addWidget(self.groupBox_2) - self.treeRoom = QtWidgets.QTreeView(self.tabRooms) + self.treeRoom = QtWidgets.QTreeView(parent=self.tabRooms) self.treeRoom.setObjectName("treeRoom") self.verticalLayout_3.addWidget(self.treeRoom) self.tabWidget.addTab(self.tabRooms, "") self.tabSubjects = QtWidgets.QWidget() self.tabSubjects.setObjectName("tabSubjects") self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.tabSubjects) - self.verticalLayout_4.setContentsMargins(9, 9, 9, 9) self.verticalLayout_4.setObjectName("verticalLayout_4") - self.groupBox_3 = QtWidgets.QGroupBox(self.tabSubjects) + self.groupBox_3 = QtWidgets.QGroupBox(parent=self.tabSubjects) self.groupBox_3.setObjectName("groupBox_3") self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.groupBox_3) self.horizontalLayout_2.setObjectName("horizontalLayout_2") - self.btnSubjAdd = QtWidgets.QPushButton(self.groupBox_3) + self.btnSubjAdd = QtWidgets.QPushButton(parent=self.groupBox_3) self.btnSubjAdd.setObjectName("btnSubjAdd") self.horizontalLayout_2.addWidget(self.btnSubjAdd) - self.btnSubjImport = QtWidgets.QPushButton(self.groupBox_3) + self.btnSubjImport = QtWidgets.QPushButton(parent=self.groupBox_3) self.btnSubjImport.setObjectName("btnSubjImport") self.horizontalLayout_2.addWidget(self.btnSubjImport) self.verticalLayout_4.addWidget(self.groupBox_3) - self.treeSubj = QtWidgets.QTreeView(self.tabSubjects) + self.treeSubj = QtWidgets.QTreeView(parent=self.tabSubjects) self.treeSubj.setObjectName("treeSubj") self.verticalLayout_4.addWidget(self.treeSubj) self.tabWidget.addTab(self.tabSubjects, "") self.tabSections = QtWidgets.QWidget() self.tabSections.setObjectName("tabSections") self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.tabSections) - self.verticalLayout_5.setContentsMargins(9, 9, 9, 9) self.verticalLayout_5.setObjectName("verticalLayout_5") - self.groupBox_4 = QtWidgets.QGroupBox(self.tabSections) + self.groupBox_4 = QtWidgets.QGroupBox(parent=self.tabSections) self.groupBox_4.setObjectName("groupBox_4") self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.groupBox_4) self.horizontalLayout_3.setObjectName("horizontalLayout_3") - self.btnSecAdd = QtWidgets.QPushButton(self.groupBox_4) + self.btnSecAdd = QtWidgets.QPushButton(parent=self.groupBox_4) self.btnSecAdd.setObjectName("btnSecAdd") self.horizontalLayout_3.addWidget(self.btnSecAdd) self.verticalLayout_5.addWidget(self.groupBox_4) - self.treeSec = QtWidgets.QTreeView(self.tabSections) + self.treeSec = QtWidgets.QTreeView(parent=self.tabSections) self.treeSec.setObjectName("treeSec") self.verticalLayout_5.addWidget(self.treeSec) self.tabWidget.addTab(self.tabSections, "") self.tabScenario = QtWidgets.QWidget() - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.tabScenario.sizePolicy().hasHeightForWidth()) self.tabScenario.setSizePolicy(sizePolicy) self.tabScenario.setObjectName("tabScenario") self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.tabScenario) - self.verticalLayout_6.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint) - self.verticalLayout_6.setContentsMargins(9, 9, 9, 9) + self.verticalLayout_6.setSizeConstraint(QtWidgets.QLayout.SizeConstraint.SetDefaultConstraint) self.verticalLayout_6.setObjectName("verticalLayout_6") - self.groupBox_5 = QtWidgets.QGroupBox(self.tabScenario) + self.groupBox_5 = QtWidgets.QGroupBox(parent=self.tabScenario) self.groupBox_5.setObjectName("groupBox_5") self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.groupBox_5) self.horizontalLayout_4.setObjectName("horizontalLayout_4") - self.btnScenGenerate = QtWidgets.QPushButton(self.groupBox_5) + self.btnScenGenerate = QtWidgets.QPushButton(parent=self.groupBox_5) self.btnScenGenerate.setObjectName("btnScenGenerate") self.horizontalLayout_4.addWidget(self.btnScenGenerate) - self.btnScenResult = QtWidgets.QPushButton(self.groupBox_5) + self.btnScenResult = QtWidgets.QPushButton(parent=self.groupBox_5) self.btnScenResult.setObjectName("btnScenResult") self.horizontalLayout_4.addWidget(self.btnScenResult) self.verticalLayout_6.addWidget(self.groupBox_5) - self.groupBox_6 = QtWidgets.QGroupBox(self.tabScenario) + self.groupBox_6 = QtWidgets.QGroupBox(parent=self.tabScenario) self.groupBox_6.setObjectName("groupBox_6") self.gridLayout_2 = QtWidgets.QGridLayout(self.groupBox_6) self.gridLayout_2.setObjectName("gridLayout_2") - self.groupBox_7 = QtWidgets.QGroupBox(self.groupBox_6) + self.groupBox_7 = QtWidgets.QGroupBox(parent=self.groupBox_6) self.groupBox_7.setStyleSheet("border: none") self.groupBox_7.setTitle("") self.groupBox_7.setFlat(False) @@ -151,250 +146,250 @@ def setupUi(self, MainWindow): self.horizontalLayout_5.setContentsMargins(0, 0, 0, 0) self.horizontalLayout_5.setSpacing(10) self.horizontalLayout_5.setObjectName("horizontalLayout_5") - self.radioLunchYes = QtWidgets.QRadioButton(self.groupBox_7) + self.radioLunchYes = QtWidgets.QRadioButton(parent=self.groupBox_7) self.radioLunchYes.setChecked(True) self.radioLunchYes.setObjectName("radioLunchYes") self.horizontalLayout_5.addWidget(self.radioLunchYes) - self.radioLunchNo = QtWidgets.QRadioButton(self.groupBox_7) + self.radioLunchNo = QtWidgets.QRadioButton(parent=self.groupBox_7) self.radioLunchNo.setObjectName("radioLunchNo") self.horizontalLayout_5.addWidget(self.radioLunchNo) self.gridLayout_2.addWidget(self.groupBox_7, 2, 1, 1, 1) - self.label_6 = QtWidgets.QLabel(self.groupBox_6) + self.label_6 = QtWidgets.QLabel(parent=self.groupBox_6) self.label_6.setObjectName("label_6") self.gridLayout_2.addWidget(self.label_6, 2, 0, 1, 1) - self.label_4 = QtWidgets.QLabel(self.groupBox_6) + self.label_4 = QtWidgets.QLabel(parent=self.groupBox_6) self.label_4.setObjectName("label_4") self.gridLayout_2.addWidget(self.label_4, 0, 0, 1, 1) - self.timeStarting = QtWidgets.QTimeEdit(self.groupBox_6) - self.timeStarting.setCurrentSection(QtWidgets.QDateTimeEdit.HourSection) + self.timeStarting = QtWidgets.QTimeEdit(parent=self.groupBox_6) + self.timeStarting.setCurrentSection(QtWidgets.QDateTimeEdit.Section.HourSection) self.timeStarting.setTime(QtCore.QTime(8, 0, 0)) self.timeStarting.setObjectName("timeStarting") self.gridLayout_2.addWidget(self.timeStarting, 0, 1, 1, 1) - spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) self.gridLayout_2.addItem(spacerItem, 0, 2, 1, 1) - self.label_5 = QtWidgets.QLabel(self.groupBox_6) + self.label_5 = QtWidgets.QLabel(parent=self.groupBox_6) self.label_5.setObjectName("label_5") self.gridLayout_2.addWidget(self.label_5, 1, 0, 1, 1) - self.timeEnding = QtWidgets.QTimeEdit(self.groupBox_6) + self.timeEnding = QtWidgets.QTimeEdit(parent=self.groupBox_6) self.timeEnding.setCalendarPopup(True) self.timeEnding.setTime(QtCore.QTime(18, 0, 0)) self.timeEnding.setObjectName("timeEnding") self.gridLayout_2.addWidget(self.timeEnding, 1, 1, 1, 1) self.verticalLayout_6.addWidget(self.groupBox_6) - self.groupBox_8 = QtWidgets.QGroupBox(self.tabScenario) + self.groupBox_8 = QtWidgets.QGroupBox(parent=self.tabScenario) self.groupBox_8.setObjectName("groupBox_8") self.gridLayout_3 = QtWidgets.QGridLayout(self.groupBox_8) self.gridLayout_3.setObjectName("gridLayout_3") - self.label_20 = QtWidgets.QLabel(self.groupBox_8) + self.label_20 = QtWidgets.QLabel(parent=self.groupBox_8) self.label_20.setObjectName("label_20") self.gridLayout_3.addWidget(self.label_20, 2, 3, 1, 1) - self.label_21 = QtWidgets.QLabel(self.groupBox_8) + self.label_21 = QtWidgets.QLabel(parent=self.groupBox_8) self.label_21.setObjectName("label_21") self.gridLayout_3.addWidget(self.label_21, 3, 3, 1, 1) - self.editDev = QtWidgets.QSpinBox(self.groupBox_8) + self.editDev = QtWidgets.QSpinBox(parent=self.groupBox_8) self.editDev.setMaximum(100) self.editDev.setProperty("value", 55) self.editDev.setObjectName("editDev") self.gridLayout_3.addWidget(self.editDev, 3, 5, 1, 1) - self.editMaxPop = QtWidgets.QSpinBox(self.groupBox_8) + self.editMaxPop = QtWidgets.QSpinBox(parent=self.groupBox_8) self.editMaxPop.setMinimum(50) self.editMaxPop.setMaximum(10000) self.editMaxPop.setProperty("value", 100) self.editMaxPop.setObjectName("editMaxPop") self.gridLayout_3.addWidget(self.editMaxPop, 1, 1, 1, 1) - self.label_12 = QtWidgets.QLabel(self.groupBox_8) + self.label_12 = QtWidgets.QLabel(parent=self.groupBox_8) self.label_12.setObjectName("label_12") self.gridLayout_3.addWidget(self.label_12, 1, 3, 1, 1) - self.editElite = QtWidgets.QSpinBox(self.groupBox_8) + self.editElite = QtWidgets.QSpinBox(parent=self.groupBox_8) self.editElite.setMaximum(100) self.editElite.setProperty("value", 5) self.editElite.setObjectName("editElite") self.gridLayout_3.addWidget(self.editElite, 2, 5, 1, 1) - spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) self.gridLayout_3.addItem(spacerItem1, 0, 7, 1, 1) - self.editMaxGen = QtWidgets.QSpinBox(self.groupBox_8) + self.editMaxGen = QtWidgets.QSpinBox(parent=self.groupBox_8) self.editMaxGen.setMinimum(50) self.editMaxGen.setMaximum(10000) self.editMaxGen.setObjectName("editMaxGen") self.gridLayout_3.addWidget(self.editMaxGen, 2, 1, 1, 1) - self.editMaxFit = QtWidgets.QSpinBox(self.groupBox_8) + self.editMaxFit = QtWidgets.QSpinBox(parent=self.groupBox_8) self.editMaxFit.setMaximum(100) self.editMaxFit.setProperty("value", 90) self.editMaxFit.setObjectName("editMaxFit") self.gridLayout_3.addWidget(self.editMaxFit, 1, 5, 1, 1) - self.label_11 = QtWidgets.QLabel(self.groupBox_8) + self.label_11 = QtWidgets.QLabel(parent=self.groupBox_8) self.label_11.setObjectName("label_11") self.gridLayout_3.addWidget(self.label_11, 0, 3, 1, 1) - self.label_10 = QtWidgets.QLabel(self.groupBox_8) + self.label_10 = QtWidgets.QLabel(parent=self.groupBox_8) self.label_10.setObjectName("label_10") self.gridLayout_3.addWidget(self.label_10, 3, 0, 1, 1) - self.label_9 = QtWidgets.QLabel(self.groupBox_8) + self.label_9 = QtWidgets.QLabel(parent=self.groupBox_8) self.label_9.setObjectName("label_9") self.gridLayout_3.addWidget(self.label_9, 2, 0, 1, 1) - self.editMaxCreation = QtWidgets.QSpinBox(self.groupBox_8) + self.editMaxCreation = QtWidgets.QSpinBox(parent=self.groupBox_8) self.editMaxCreation.setMinimum(1500) self.editMaxCreation.setMaximum(30000) self.editMaxCreation.setObjectName("editMaxCreation") self.gridLayout_3.addWidget(self.editMaxCreation, 3, 1, 1, 1) - self.label_7 = QtWidgets.QLabel(self.groupBox_8) + self.label_7 = QtWidgets.QLabel(parent=self.groupBox_8) self.label_7.setObjectName("label_7") self.gridLayout_3.addWidget(self.label_7, 0, 0, 1, 1) - self.label_8 = QtWidgets.QLabel(self.groupBox_8) + self.label_8 = QtWidgets.QLabel(parent=self.groupBox_8) self.label_8.setObjectName("label_8") self.gridLayout_3.addWidget(self.label_8, 1, 0, 1, 1) - self.editMinPop = QtWidgets.QSpinBox(self.groupBox_8) + self.editMinPop = QtWidgets.QSpinBox(parent=self.groupBox_8) self.editMinPop.setMinimum(50) self.editMinPop.setMaximum(10000) self.editMinPop.setObjectName("editMinPop") self.gridLayout_3.addWidget(self.editMinPop, 0, 1, 1, 1) - spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) self.gridLayout_3.addItem(spacerItem2, 0, 11, 1, 1) - spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) self.gridLayout_3.addItem(spacerItem3, 0, 10, 1, 1) - spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) self.gridLayout_3.addItem(spacerItem4, 0, 2, 1, 1) - spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) self.gridLayout_3.addItem(spacerItem5, 0, 9, 1, 1) - spacerItem6 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + spacerItem6 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) self.gridLayout_3.addItem(spacerItem6, 0, 8, 1, 1) - self.editMut = QtWidgets.QDoubleSpinBox(self.groupBox_8) + self.editMut = QtWidgets.QDoubleSpinBox(parent=self.groupBox_8) self.editMut.setMaximum(100.0) self.editMut.setSingleStep(0.01) self.editMut.setProperty("value", 0.08) self.editMut.setObjectName("editMut") self.gridLayout_3.addWidget(self.editMut, 0, 5, 1, 1) self.verticalLayout_6.addWidget(self.groupBox_8) - self.groupBox_9 = QtWidgets.QGroupBox(self.tabScenario) + self.groupBox_9 = QtWidgets.QGroupBox(parent=self.tabScenario) self.groupBox_9.setObjectName("groupBox_9") self.gridLayout_4 = QtWidgets.QGridLayout(self.groupBox_9) self.gridLayout_4.setObjectName("gridLayout_4") - self.label_15 = QtWidgets.QLabel(self.groupBox_9) + self.label_15 = QtWidgets.QLabel(parent=self.groupBox_9) self.label_15.setObjectName("label_15") self.gridLayout_4.addWidget(self.label_15, 2, 0, 1, 1) - self.label_18 = QtWidgets.QLabel(self.groupBox_9) + self.label_18 = QtWidgets.QLabel(parent=self.groupBox_9) self.label_18.setObjectName("label_18") self.gridLayout_4.addWidget(self.label_18, 3, 0, 1, 1) - self.label_19 = QtWidgets.QLabel(self.groupBox_9) + self.label_19 = QtWidgets.QLabel(parent=self.groupBox_9) self.label_19.setObjectName("label_19") self.gridLayout_4.addWidget(self.label_19, 5, 0, 1, 1) - self.label_17 = QtWidgets.QLabel(self.groupBox_9) + self.label_17 = QtWidgets.QLabel(parent=self.groupBox_9) self.label_17.setObjectName("label_17") self.gridLayout_4.addWidget(self.label_17, 7, 0, 1, 1) - self.label_16 = QtWidgets.QLabel(self.groupBox_9) + self.label_16 = QtWidgets.QLabel(parent=self.groupBox_9) self.label_16.setObjectName("label_16") self.gridLayout_4.addWidget(self.label_16, 4, 0, 1, 1) - self.editSbj = QtWidgets.QSpinBox(self.groupBox_9) + self.editSbj = QtWidgets.QSpinBox(parent=self.groupBox_9) self.editSbj.setMaximum(100) self.editSbj.setProperty("value", 70) self.editSbj.setObjectName("editSbj") self.gridLayout_4.addWidget(self.editSbj, 0, 1, 1, 1) - self.label_13 = QtWidgets.QLabel(self.groupBox_9) + self.label_13 = QtWidgets.QLabel(parent=self.groupBox_9) self.label_13.setObjectName("label_13") self.gridLayout_4.addWidget(self.label_13, 0, 0, 1, 1) - self.label_14 = QtWidgets.QLabel(self.groupBox_9) + self.label_14 = QtWidgets.QLabel(parent=self.groupBox_9) self.label_14.setObjectName("label_14") self.gridLayout_4.addWidget(self.label_14, 1, 0, 1, 1) - spacerItem7 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + spacerItem7 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) self.gridLayout_4.addItem(spacerItem7, 0, 2, 1, 1) - self.editLun = QtWidgets.QSpinBox(self.groupBox_9) + self.editLun = QtWidgets.QSpinBox(parent=self.groupBox_9) self.editLun.setMaximum(100) self.editLun.setProperty("value", 5) self.editLun.setObjectName("editLun") self.gridLayout_4.addWidget(self.editLun, 1, 1, 1, 1) - self.editSec = QtWidgets.QSpinBox(self.groupBox_9) + self.editSec = QtWidgets.QSpinBox(parent=self.groupBox_9) self.editSec.setMaximum(100) self.editSec.setProperty("value", 5) self.editSec.setObjectName("editSec") self.gridLayout_4.addWidget(self.editSec, 2, 1, 1, 1) - self.editInstrRest = QtWidgets.QSpinBox(self.groupBox_9) + self.editInstrRest = QtWidgets.QSpinBox(parent=self.groupBox_9) self.editInstrRest.setMaximum(100) self.editInstrRest.setProperty("value", 5) self.editInstrRest.setObjectName("editInstrRest") self.gridLayout_4.addWidget(self.editInstrRest, 4, 1, 1, 1) - self.editInstrLoad = QtWidgets.QSpinBox(self.groupBox_9) + self.editInstrLoad = QtWidgets.QSpinBox(parent=self.groupBox_9) self.editInstrLoad.setMaximum(100) self.editInstrLoad.setProperty("value", 5) self.editInstrLoad.setObjectName("editInstrLoad") self.gridLayout_4.addWidget(self.editInstrLoad, 5, 1, 1, 1) - self.editIdle = QtWidgets.QSpinBox(self.groupBox_9) + self.editIdle = QtWidgets.QSpinBox(parent=self.groupBox_9) self.editIdle.setMaximum(100) self.editIdle.setProperty("value", 5) self.editIdle.setObjectName("editIdle") self.gridLayout_4.addWidget(self.editIdle, 3, 1, 1, 1) - self.editMeet = QtWidgets.QSpinBox(self.groupBox_9) + self.editMeet = QtWidgets.QSpinBox(parent=self.groupBox_9) self.editMeet.setMaximum(100) self.editMeet.setProperty("value", 5) self.editMeet.setObjectName("editMeet") self.gridLayout_4.addWidget(self.editMeet, 7, 1, 1, 1) - self.lblTotal = QtWidgets.QLabel(self.groupBox_9) + self.lblTotal = QtWidgets.QLabel(parent=self.groupBox_9) self.lblTotal.setObjectName("lblTotal") self.gridLayout_4.addWidget(self.lblTotal, 8, 0, 1, 1) self.verticalLayout_6.addWidget(self.groupBox_9) - spacerItem8 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + spacerItem8 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding) self.verticalLayout_6.addItem(spacerItem8) self.tabWidget.addTab(self.tabScenario, "") self.verticalLayout.addWidget(self.tabWidget) MainWindow.setCentralWidget(self.centralwidget) - self.menubar = QtWidgets.QMenuBar(MainWindow) + self.menubar = QtWidgets.QMenuBar(parent=MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21)) self.menubar.setObjectName("menubar") - self.menuFile = QtWidgets.QMenu(self.menubar) + self.menuFile = QtWidgets.QMenu(parent=self.menubar) self.menuFile.setObjectName("menuFile") - self.menuHelp = QtWidgets.QMenu(self.menubar) + self.menuHelp = QtWidgets.QMenu(parent=self.menubar) self.menuHelp.setObjectName("menuHelp") MainWindow.setMenuBar(self.menubar) - self.statusbar = QtWidgets.QStatusBar(MainWindow) + self.statusbar = QtWidgets.QStatusBar(parent=MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) - self.actionNew = QtWidgets.QAction(MainWindow) + self.actionNew = QtGui.QAction(parent=MainWindow) self.actionNew.setObjectName("actionNew") - self.actionOpen = QtWidgets.QAction(MainWindow) + self.actionOpen = QtGui.QAction(parent=MainWindow) self.actionOpen.setObjectName("actionOpen") - self.actionSave = QtWidgets.QAction(MainWindow) + self.actionSave = QtGui.QAction(parent=MainWindow) self.actionSave.setObjectName("actionSave") - self.actionSave_As = QtWidgets.QAction(MainWindow) + self.actionSave_As = QtGui.QAction(parent=MainWindow) self.actionSave_As.setObjectName("actionSave_As") - self.actionSettings = QtWidgets.QAction(MainWindow) + self.actionSettings = QtGui.QAction(parent=MainWindow) self.actionSettings.setObjectName("actionSettings") - self.actionExit = QtWidgets.QAction(MainWindow) + self.actionExit = QtGui.QAction(parent=MainWindow) self.actionExit.setObjectName("actionExit") - self.actionAdd_Instructor = QtWidgets.QAction(MainWindow) + self.actionAdd_Instructor = QtGui.QAction(parent=MainWindow) self.actionAdd_Instructor.setObjectName("actionAdd_Instructor") - self.actionView_Instructors = QtWidgets.QAction(MainWindow) + self.actionView_Instructors = QtGui.QAction(parent=MainWindow) self.actionView_Instructors.setObjectName("actionView_Instructors") - self.actionAdd_Room = QtWidgets.QAction(MainWindow) + self.actionAdd_Room = QtGui.QAction(parent=MainWindow) self.actionAdd_Room.setObjectName("actionAdd_Room") - self.actionView_Rooms = QtWidgets.QAction(MainWindow) + self.actionView_Rooms = QtGui.QAction(parent=MainWindow) self.actionView_Rooms.setObjectName("actionView_Rooms") - self.actionAdd_Subject = QtWidgets.QAction(MainWindow) + self.actionAdd_Subject = QtGui.QAction(parent=MainWindow) self.actionAdd_Subject.setObjectName("actionAdd_Subject") - self.actionView_Subjects = QtWidgets.QAction(MainWindow) + self.actionView_Subjects = QtGui.QAction(parent=MainWindow) self.actionView_Subjects.setObjectName("actionView_Subjects") - self.actionAdd_Sections = QtWidgets.QAction(MainWindow) + self.actionAdd_Sections = QtGui.QAction(parent=MainWindow) self.actionAdd_Sections.setObjectName("actionAdd_Sections") - self.actionView_Sections = QtWidgets.QAction(MainWindow) + self.actionView_Sections = QtGui.QAction(parent=MainWindow) self.actionView_Sections.setObjectName("actionView_Sections") - self.actionImport = QtWidgets.QAction(MainWindow) + self.actionImport = QtGui.QAction(parent=MainWindow) self.actionImport.setObjectName("actionImport") - self.actionExport = QtWidgets.QAction(MainWindow) + self.actionExport = QtGui.QAction(parent=MainWindow) self.actionExport.setObjectName("actionExport") - self.actionView_Results = QtWidgets.QAction(MainWindow) + self.actionView_Results = QtGui.QAction(parent=MainWindow) self.actionView_Results.setObjectName("actionView_Results") - self.actionGenerate = QtWidgets.QAction(MainWindow) + self.actionGenerate = QtGui.QAction(parent=MainWindow) self.actionGenerate.setObjectName("actionGenerate") - self.actionImport_2 = QtWidgets.QAction(MainWindow) + self.actionImport_2 = QtGui.QAction(parent=MainWindow) self.actionImport_2.setObjectName("actionImport_2") - self.actionExport_2 = QtWidgets.QAction(MainWindow) + self.actionExport_2 = QtGui.QAction(parent=MainWindow) self.actionExport_2.setObjectName("actionExport_2") - self.actionScenario_Summary = QtWidgets.QAction(MainWindow) + self.actionScenario_Summary = QtGui.QAction(parent=MainWindow) self.actionScenario_Summary.setObjectName("actionScenario_Summary") - self.actionGenerate_2 = QtWidgets.QAction(MainWindow) + self.actionGenerate_2 = QtGui.QAction(parent=MainWindow) self.actionGenerate_2.setObjectName("actionGenerate_2") - self.actionView_Results_2 = QtWidgets.QAction(MainWindow) + self.actionView_Results_2 = QtGui.QAction(parent=MainWindow) self.actionView_Results_2.setObjectName("actionView_Results_2") - self.actionInstructions = QtWidgets.QAction(MainWindow) + self.actionInstructions = QtGui.QAction(parent=MainWindow) self.actionInstructions.setObjectName("actionInstructions") - self.actionAbout = QtWidgets.QAction(MainWindow) + self.actionAbout = QtGui.QAction(parent=MainWindow) self.actionAbout.setObjectName("actionAbout") self.menuFile.addAction(self.actionNew) self.menuFile.addAction(self.actionOpen) @@ -452,41 +447,33 @@ def retranslateUi(self, MainWindow): self.label_21.setText(_translate("MainWindow", "Deviation Tolerance")) self.label_12.setToolTip(_translate("MainWindow", "Stops the generation when a chromosome meets this.")) self.label_12.setText(_translate("MainWindow", "Maximum Fitness")) - self.label_11.setToolTip(_translate("MainWindow", - "

Triggers mutation rate change when the difference of average fitness falls to the specificied level.

")) + self.label_11.setToolTip(_translate("MainWindow", "

Triggers mutation rate change when the difference of average fitness falls to the specificied level.

")) self.label_11.setText(_translate("MainWindow", "Mutation Rate Adjustment Trigger")) self.label_10.setToolTip(_translate("MainWindow", "Maximum attempts for creating a valid chromosome.")) self.label_10.setText(_translate("MainWindow", "Maximum Creation Attempts")) - self.label_9.setToolTip( - _translate("MainWindow", "Maximum amount of generations to be performed on solution generation.")) + self.label_9.setToolTip(_translate("MainWindow", "Maximum amount of generations to be performed on solution generation.")) self.label_9.setText(_translate("MainWindow", "Maximum Generations")) - self.label_7.setToolTip( - _translate("MainWindow", "Starting point and lowest population count of the genetic algorithm.")) + self.label_7.setToolTip(_translate("MainWindow", "Starting point and lowest population count of the genetic algorithm.")) self.label_7.setText(_translate("MainWindow", "Minimum Population Count")) self.label_8.setToolTip(_translate("MainWindow", "Highest population count of the genetic algorithm.")) self.label_8.setText(_translate("MainWindow", "Maximum Population Count")) self.groupBox_9.setTitle(_translate("MainWindow", "Evaluation Matrix")) - self.label_15.setToolTip(_translate("MainWindow", - "The weight of section rest (There must be a rest for every consecutive 3 hours of session)")) + self.label_15.setToolTip(_translate("MainWindow", "The weight of section rest (There must be a rest for every consecutive 3 hours of session)")) self.label_15.setText(_translate("MainWindow", "Section Rest")) self.label_18.setToolTip(_translate("MainWindow", "The weight of sections having less idle time.")) self.label_18.setText(_translate("MainWindow", "Section Idle Time")) - self.label_19.setToolTip( - _translate("MainWindow", "The weight of having all instructors have normalized teaching load.")) + self.label_19.setToolTip(_translate("MainWindow", "The weight of having all instructors have normalized teaching load.")) self.label_19.setText(_translate("MainWindow", "Instructor Load Balance")) - self.label_17.setToolTip( - _translate("MainWindow", "The weight of having correct meeting patterns for subject placement.")) + self.label_17.setToolTip(_translate("MainWindow", "The weight of having correct meeting patterns for subject placement.")) self.label_17.setText(_translate("MainWindow", "Meeting Pattern")) - self.label_16.setToolTip(_translate("MainWindow", - "The weight of instructor rest (There must be a rest for every consecutive 3 hours of session)")) + self.label_16.setToolTip(_translate("MainWindow", "The weight of instructor rest (There must be a rest for every consecutive 3 hours of session)")) self.label_16.setText(_translate("MainWindow", "Instructor Rest")) self.label_13.setToolTip(_translate("MainWindow", "The weight of having all subjects placed.")) self.label_13.setText(_translate("MainWindow", "Subject Placement")) self.label_14.setToolTip(_translate("MainWindow", "The weight of having a lunch break.")) self.label_14.setText(_translate("MainWindow", "Lunch Break")) - self.lblTotal.setText(_translate("MainWindow", "Total: ")) - self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabScenario), - _translate("MainWindow", "Scenario Manager")) + self.lblTotal.setText(_translate("MainWindow", "TextLabel")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabScenario), _translate("MainWindow", "Scenario Manager")) self.menuFile.setTitle(_translate("MainWindow", "File")) self.menuHelp.setTitle(_translate("MainWindow", "Help")) self.actionNew.setText(_translate("MainWindow", "New")) diff --git a/py_ui/Result.py b/py_ui/Result.py index f858903..579ae51 100644 --- a/py_ui/Result.py +++ b/py_ui/Result.py @@ -1,12 +1,12 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'result2.ui' +# Form implementation generated from reading ui file 'qt_ui\result.ui' # -# Created by: PyQt5 UI code generator 5.6 +# Created by: PyQt6 UI code generator 6.6.1 # -# WARNING! All changes made in this file will be lost! +# WARNING: Any manual changes made to this file will be lost when pyuic6 is +# run again. Do not edit this file unless you know what you are doing. + -from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets class Ui_Dialog(object): @@ -21,11 +21,11 @@ def setupUi(self, Dialog): self.horizontalLayout.setObjectName("horizontalLayout") self.horizontalLayout_2 = QtWidgets.QHBoxLayout() self.horizontalLayout_2.setObjectName("horizontalLayout_2") - self.groupBox_3 = QtWidgets.QGroupBox(Dialog) + self.groupBox_3 = QtWidgets.QGroupBox(parent=Dialog) self.groupBox_3.setObjectName("groupBox_3") self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.groupBox_3) self.verticalLayout_4.setObjectName("verticalLayout_4") - self.cmbChromosome = QtWidgets.QComboBox(self.groupBox_3) + self.cmbChromosome = QtWidgets.QComboBox(parent=self.groupBox_3) self.cmbChromosome.setObjectName("cmbChromosome") self.cmbChromosome.addItem("") self.cmbChromosome.addItem("") @@ -34,31 +34,31 @@ def setupUi(self, Dialog): self.cmbChromosome.addItem("") self.verticalLayout_4.addWidget(self.cmbChromosome) self.horizontalLayout_2.addWidget(self.groupBox_3) - self.groupBox = QtWidgets.QGroupBox(Dialog) + self.groupBox = QtWidgets.QGroupBox(parent=Dialog) self.groupBox.setObjectName("groupBox") self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.groupBox) self.verticalLayout_3.setObjectName("verticalLayout_3") - self.cmbCategory = QtWidgets.QComboBox(self.groupBox) + self.cmbCategory = QtWidgets.QComboBox(parent=self.groupBox) self.cmbCategory.setObjectName("cmbCategory") self.cmbCategory.addItem("") self.cmbCategory.addItem("") self.cmbCategory.addItem("") self.verticalLayout_3.addWidget(self.cmbCategory) self.horizontalLayout_2.addWidget(self.groupBox) - self.groupBox_2 = QtWidgets.QGroupBox(Dialog) + self.groupBox_2 = QtWidgets.QGroupBox(parent=Dialog) self.groupBox_2.setObjectName("groupBox_2") self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.groupBox_2) self.verticalLayout_2.setObjectName("verticalLayout_2") - self.cmbEntry = QtWidgets.QComboBox(self.groupBox_2) + self.cmbEntry = QtWidgets.QComboBox(parent=self.groupBox_2) self.cmbEntry.setObjectName("cmbEntry") self.verticalLayout_2.addWidget(self.cmbEntry) self.horizontalLayout_2.addWidget(self.groupBox_2) self.horizontalLayout.addLayout(self.horizontalLayout_2) - self.groupBox_6 = QtWidgets.QGroupBox(Dialog) + self.groupBox_6 = QtWidgets.QGroupBox(parent=Dialog) self.groupBox_6.setObjectName("groupBox_6") self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.groupBox_6) self.horizontalLayout_3.setObjectName("horizontalLayout_3") - self.btnExport = QtWidgets.QPushButton(self.groupBox_6) + self.btnExport = QtWidgets.QPushButton(parent=self.groupBox_6) self.btnExport.setObjectName("btnExport") self.horizontalLayout_3.addWidget(self.btnExport) self.horizontalLayout.addWidget(self.groupBox_6) @@ -67,53 +67,53 @@ def setupUi(self, Dialog): self.horizontalLayout_4.setObjectName("horizontalLayout_4") self.verticalLayout_7 = QtWidgets.QVBoxLayout() self.verticalLayout_7.setObjectName("verticalLayout_7") - self.groupBox_4 = QtWidgets.QGroupBox(Dialog) + self.groupBox_4 = QtWidgets.QGroupBox(parent=Dialog) self.groupBox_4.setObjectName("groupBox_4") self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.groupBox_4) self.verticalLayout_5.setObjectName("verticalLayout_5") - self.lblFit = QtWidgets.QLabel(self.groupBox_4) + self.lblFit = QtWidgets.QLabel(parent=self.groupBox_4) self.lblFit.setObjectName("lblFit") self.verticalLayout_5.addWidget(self.lblFit) - self.lblSbj = QtWidgets.QLabel(self.groupBox_4) + self.lblSbj = QtWidgets.QLabel(parent=self.groupBox_4) self.lblSbj.setObjectName("lblSbj") self.verticalLayout_5.addWidget(self.lblSbj) - self.lblSecRest = QtWidgets.QLabel(self.groupBox_4) + self.lblSecRest = QtWidgets.QLabel(parent=self.groupBox_4) self.lblSecRest.setObjectName("lblSecRest") self.verticalLayout_5.addWidget(self.lblSecRest) - self.lblSecIdle = QtWidgets.QLabel(self.groupBox_4) + self.lblSecIdle = QtWidgets.QLabel(parent=self.groupBox_4) self.lblSecIdle.setObjectName("lblSecIdle") self.verticalLayout_5.addWidget(self.lblSecIdle) - self.lblInstrRest = QtWidgets.QLabel(self.groupBox_4) + self.lblInstrRest = QtWidgets.QLabel(parent=self.groupBox_4) self.lblInstrRest.setObjectName("lblInstrRest") self.verticalLayout_5.addWidget(self.lblInstrRest) - self.lblInstrLoad = QtWidgets.QLabel(self.groupBox_4) + self.lblInstrLoad = QtWidgets.QLabel(parent=self.groupBox_4) self.lblInstrLoad.setObjectName("lblInstrLoad") self.verticalLayout_5.addWidget(self.lblInstrLoad) - self.lblLunch = QtWidgets.QLabel(self.groupBox_4) + self.lblLunch = QtWidgets.QLabel(parent=self.groupBox_4) self.lblLunch.setObjectName("lblLunch") self.verticalLayout_5.addWidget(self.lblLunch) - self.lblMeet = QtWidgets.QLabel(self.groupBox_4) + self.lblMeet = QtWidgets.QLabel(parent=self.groupBox_4) self.lblMeet.setObjectName("lblMeet") self.verticalLayout_5.addWidget(self.lblMeet) self.verticalLayout_7.addWidget(self.groupBox_4) - self.groupProblems = QtWidgets.QGroupBox(Dialog) + self.groupProblems = QtWidgets.QGroupBox(parent=Dialog) self.groupProblems.setObjectName("groupProblems") self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.groupProblems) self.verticalLayout_6.setObjectName("verticalLayout_6") - self.lblTime = QtWidgets.QLabel(self.groupProblems) + self.lblTime = QtWidgets.QLabel(parent=self.groupProblems) self.lblTime.setObjectName("lblTime") self.verticalLayout_6.addWidget(self.lblTime) - self.lblCPU = QtWidgets.QLabel(self.groupProblems) + self.lblCPU = QtWidgets.QLabel(parent=self.groupProblems) self.lblCPU.setObjectName("lblCPU") self.verticalLayout_6.addWidget(self.lblCPU) - self.lblMemory = QtWidgets.QLabel(self.groupProblems) + self.lblMemory = QtWidgets.QLabel(parent=self.groupProblems) self.lblMemory.setObjectName("lblMemory") self.verticalLayout_6.addWidget(self.lblMemory) - spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding) self.verticalLayout_6.addItem(spacerItem) self.verticalLayout_7.addWidget(self.groupProblems) self.horizontalLayout_4.addLayout(self.verticalLayout_7) - self.tableResult = QtWidgets.QTableView(Dialog) + self.tableResult = QtWidgets.QTableView(parent=Dialog) self.tableResult.setMinimumSize(QtCore.QSize(698, 300)) self.tableResult.setMaximumSize(QtCore.QSize(698, 3000)) self.tableResult.setObjectName("tableResult") diff --git a/py_ui/Room.py b/py_ui/Room.py index cbf923f..9278bbe 100644 --- a/py_ui/Room.py +++ b/py_ui/Room.py @@ -1,12 +1,12 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'room.ui' +# Form implementation generated from reading ui file 'qt_ui\room.ui' # -# Created by: PyQt5 UI code generator 5.6 +# Created by: PyQt6 UI code generator 6.6.1 # -# WARNING! All changes made in this file will be lost! +# WARNING: Any manual changes made to this file will be lost when pyuic6 is +# run again. Do not edit this file unless you know what you are doing. + -from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets class Ui_Dialog(object): @@ -18,35 +18,35 @@ def setupUi(self, Dialog): self.verticalLayout = QtWidgets.QVBoxLayout(Dialog) self.verticalLayout.setObjectName("verticalLayout") self.gridLayout = QtWidgets.QGridLayout() - self.gridLayout.setSizeConstraint(QtWidgets.QLayout.SetMinimumSize) + self.gridLayout.setSizeConstraint(QtWidgets.QLayout.SizeConstraint.SetMinimumSize) self.gridLayout.setObjectName("gridLayout") - self.lblName = QtWidgets.QLabel(Dialog) + self.lblName = QtWidgets.QLabel(parent=Dialog) self.lblName.setObjectName("lblName") self.gridLayout.addWidget(self.lblName, 0, 0, 1, 1) - self.lineEditName = QtWidgets.QLineEdit(Dialog) + self.lineEditName = QtWidgets.QLineEdit(parent=Dialog) self.lineEditName.setObjectName("lineEditName") self.gridLayout.addWidget(self.lineEditName, 0, 1, 1, 1) - self.groupBox = QtWidgets.QGroupBox(Dialog) + self.groupBox = QtWidgets.QGroupBox(parent=Dialog) self.groupBox.setObjectName("groupBox") self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.groupBox) self.horizontalLayout_2.setObjectName("horizontalLayout_2") - self.radioLec = QtWidgets.QRadioButton(self.groupBox) + self.radioLec = QtWidgets.QRadioButton(parent=self.groupBox) self.radioLec.setObjectName("radioLec") self.horizontalLayout_2.addWidget(self.radioLec) - self.radioLab = QtWidgets.QRadioButton(self.groupBox) + self.radioLab = QtWidgets.QRadioButton(parent=self.groupBox) self.radioLab.setObjectName("radioLab") self.horizontalLayout_2.addWidget(self.radioLab) self.gridLayout.addWidget(self.groupBox, 0, 2, 1, 1) self.verticalLayout.addLayout(self.gridLayout) - self.tableSchedule = QtWidgets.QTableView(Dialog) + self.tableSchedule = QtWidgets.QTableView(parent=Dialog) self.tableSchedule.setObjectName("tableSchedule") self.verticalLayout.addWidget(self.tableSchedule) self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") - self.btnFinish = QtWidgets.QPushButton(Dialog) + self.btnFinish = QtWidgets.QPushButton(parent=Dialog) self.btnFinish.setObjectName("btnFinish") self.horizontalLayout.addWidget(self.btnFinish) - self.btnCancel = QtWidgets.QPushButton(Dialog) + self.btnCancel = QtWidgets.QPushButton(parent=Dialog) self.btnCancel.setObjectName("btnCancel") self.horizontalLayout.addWidget(self.btnCancel) self.verticalLayout.addLayout(self.horizontalLayout) diff --git a/py_ui/Section.py b/py_ui/Section.py index 42c644a..345b1c3 100644 --- a/py_ui/Section.py +++ b/py_ui/Section.py @@ -1,62 +1,61 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'section2.ui' +# Form implementation generated from reading ui file 'qt_ui\section.ui' # -# Created by: PyQt5 UI code generator 5.6 +# Created by: PyQt6 UI code generator 6.6.1 # -# WARNING! All changes made in this file will be lost! +# WARNING: Any manual changes made to this file will be lost when pyuic6 is +# run again. Do not edit this file unless you know what you are doing. + -from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets class Ui_Dialog(object): def setupUi(self, Dialog): Dialog.setObjectName("Dialog") Dialog.resize(716, 553) - Dialog.setMinimumSize(QtCore.QSize(731, 553)) # 553 + Dialog.setMinimumSize(QtCore.QSize(716, 553)) self.verticalLayout_2 = QtWidgets.QVBoxLayout(Dialog) self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) self.verticalLayout_2.setSpacing(0) self.verticalLayout_2.setObjectName("verticalLayout_2") - self.scrollArea = QtWidgets.QScrollArea(Dialog) + self.scrollArea = QtWidgets.QScrollArea(parent=Dialog) self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName("scrollArea") self.scrollAreaWidgetContents = QtWidgets.QWidget() - self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 697, 759)) # 697 + self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 697, 759)) self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents") - self.scrollAreaWidgetContents.setContentsMargins(9, 9, 9, 9) self.verticalLayout = QtWidgets.QVBoxLayout(self.scrollAreaWidgetContents) - self.verticalLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint) - self.verticalLayout.setContentsMargins(0, 9, 0, 0) + self.verticalLayout.setSizeConstraint(QtWidgets.QLayout.SizeConstraint.SetDefaultConstraint) + self.verticalLayout.setContentsMargins(-1, 9, -1, -1) self.verticalLayout.setObjectName("verticalLayout") self.gridLayout = QtWidgets.QGridLayout() - self.gridLayout.setSizeConstraint(QtWidgets.QLayout.SetMinimumSize) + self.gridLayout.setSizeConstraint(QtWidgets.QLayout.SizeConstraint.SetMinimumSize) self.gridLayout.setObjectName("gridLayout") - self.lblName = QtWidgets.QLabel(self.scrollAreaWidgetContents) + self.lblName = QtWidgets.QLabel(parent=self.scrollAreaWidgetContents) self.lblName.setObjectName("lblName") self.gridLayout.addWidget(self.lblName, 1, 0, 1, 1) - self.lineEditName = QtWidgets.QLineEdit(self.scrollAreaWidgetContents) + self.lineEditName = QtWidgets.QLineEdit(parent=self.scrollAreaWidgetContents) self.lineEditName.setObjectName("lineEditName") self.gridLayout.addWidget(self.lineEditName, 1, 1, 1, 1) - self.checkStay = QtWidgets.QCheckBox(self.scrollAreaWidgetContents) + self.checkStay = QtWidgets.QCheckBox(parent=self.scrollAreaWidgetContents) self.checkStay.setObjectName("checkStay") self.gridLayout.addWidget(self.checkStay, 1, 2, 1, 1) self.verticalLayout.addLayout(self.gridLayout) - self.treeSubjects = QtWidgets.QTreeView(self.scrollAreaWidgetContents) + self.treeSubjects = QtWidgets.QTreeView(parent=self.scrollAreaWidgetContents) self.treeSubjects.setMinimumSize(QtCore.QSize(0, 200)) self.treeSubjects.setHeaderHidden(False) self.treeSubjects.setObjectName("treeSubjects") self.verticalLayout.addWidget(self.treeSubjects) - self.tableSchedule = QtWidgets.QTableView(self.scrollAreaWidgetContents) + self.tableSchedule = QtWidgets.QTableView(parent=self.scrollAreaWidgetContents) self.tableSchedule.setMinimumSize(QtCore.QSize(0, 476)) self.tableSchedule.setObjectName("tableSchedule") self.verticalLayout.addWidget(self.tableSchedule) self.horizontalLayout_2 = QtWidgets.QHBoxLayout() self.horizontalLayout_2.setObjectName("horizontalLayout_2") - self.btnFinish = QtWidgets.QPushButton(self.scrollAreaWidgetContents) + self.btnFinish = QtWidgets.QPushButton(parent=self.scrollAreaWidgetContents) self.btnFinish.setObjectName("btnFinish") self.horizontalLayout_2.addWidget(self.btnFinish) - self.btnCancel = QtWidgets.QPushButton(self.scrollAreaWidgetContents) + self.btnCancel = QtWidgets.QPushButton(parent=self.scrollAreaWidgetContents) self.btnCancel.setObjectName("btnCancel") self.horizontalLayout_2.addWidget(self.btnCancel) self.verticalLayout.addLayout(self.horizontalLayout_2) diff --git a/py_ui/Share.py b/py_ui/Share.py index 1fb6e75..b76cc6f 100644 --- a/py_ui/Share.py +++ b/py_ui/Share.py @@ -1,12 +1,12 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'share.ui' +# Form implementation generated from reading ui file 'qt_ui\share.ui' # -# Created by: PyQt5 UI code generator 5.6 +# Created by: PyQt6 UI code generator 6.6.1 # -# WARNING! All changes made in this file will be lost! +# WARNING: Any manual changes made to this file will be lost when pyuic6 is +# run again. Do not edit this file unless you know what you are doing. + -from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets class Ui_Dialog(object): @@ -17,15 +17,15 @@ def setupUi(self, Dialog): Dialog.setMaximumSize(QtCore.QSize(400, 300)) self.verticalLayout = QtWidgets.QVBoxLayout(Dialog) self.verticalLayout.setObjectName("verticalLayout") - self.treeSections = QtWidgets.QTreeView(Dialog) + self.treeSections = QtWidgets.QTreeView(parent=Dialog) self.treeSections.setObjectName("treeSections") self.verticalLayout.addWidget(self.treeSections) self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") - self.btnFinish = QtWidgets.QPushButton(Dialog) + self.btnFinish = QtWidgets.QPushButton(parent=Dialog) self.btnFinish.setObjectName("btnFinish") self.horizontalLayout.addWidget(self.btnFinish) - self.btnCancel = QtWidgets.QPushButton(Dialog) + self.btnCancel = QtWidgets.QPushButton(parent=Dialog) self.btnCancel.setObjectName("btnCancel") self.horizontalLayout.addWidget(self.btnCancel) self.verticalLayout.addLayout(self.horizontalLayout) diff --git a/py_ui/Subject.py b/py_ui/Subject.py index bdfaf4b..d79f576 100644 --- a/py_ui/Subject.py +++ b/py_ui/Subject.py @@ -1,12 +1,12 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'subject.ui' +# Form implementation generated from reading ui file 'qt_ui\subject.ui' # -# Created by: PyQt5 UI code generator 5.6 +# Created by: PyQt6 UI code generator 6.6.1 # -# WARNING! All changes made in this file will be lost! +# WARNING: Any manual changes made to this file will be lost when pyuic6 is +# run again. Do not edit this file unless you know what you are doing. + -from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets class Ui_Dialog(object): @@ -18,22 +18,22 @@ def setupUi(self, Dialog): self.verticalLayout = QtWidgets.QVBoxLayout(Dialog) self.verticalLayout.setObjectName("verticalLayout") self.gridLayout = QtWidgets.QGridLayout() - self.gridLayout.setSizeConstraint(QtWidgets.QLayout.SetMinimumSize) + self.gridLayout.setSizeConstraint(QtWidgets.QLayout.SizeConstraint.SetMinimumSize) self.gridLayout.setObjectName("gridLayout") - self.lineEditName = QtWidgets.QLineEdit(Dialog) + self.lineEditName = QtWidgets.QLineEdit(parent=Dialog) self.lineEditName.setObjectName("lineEditName") self.gridLayout.addWidget(self.lineEditName, 0, 1, 1, 1) - self.lineEditHours = QtWidgets.QLineEdit(Dialog) + self.lineEditHours = QtWidgets.QLineEdit(parent=Dialog) self.lineEditHours.setObjectName("lineEditHours") self.gridLayout.addWidget(self.lineEditHours, 0, 4, 1, 1) - self.lblHours = QtWidgets.QLabel(Dialog) + self.lblHours = QtWidgets.QLabel(parent=Dialog) self.lblHours.setObjectName("lblHours") self.gridLayout.addWidget(self.lblHours, 0, 3, 1, 1) - self.lblName = QtWidgets.QLabel(Dialog) + self.lblName = QtWidgets.QLabel(parent=Dialog) self.lblName.setObjectName("lblName") self.gridLayout.addWidget(self.lblName, 0, 0, 1, 1) - self.groupBox_2 = QtWidgets.QGroupBox(Dialog) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + self.groupBox_2 = QtWidgets.QGroupBox(parent=Dialog) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.groupBox_2.sizePolicy().hasHeightForWidth()) @@ -41,49 +41,49 @@ def setupUi(self, Dialog): self.groupBox_2.setObjectName("groupBox_2") self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.groupBox_2) self.horizontalLayout_2.setObjectName("horizontalLayout_2") - self.radioYes = QtWidgets.QRadioButton(self.groupBox_2) + self.radioYes = QtWidgets.QRadioButton(parent=self.groupBox_2) self.radioYes.setObjectName("radioYes") self.horizontalLayout_2.addWidget(self.radioYes) - self.radioNo = QtWidgets.QRadioButton(self.groupBox_2) + self.radioNo = QtWidgets.QRadioButton(parent=self.groupBox_2) self.radioNo.setObjectName("radioNo") self.horizontalLayout_2.addWidget(self.radioNo) self.gridLayout.addWidget(self.groupBox_2, 2, 0, 1, 2) - self.groupBox = QtWidgets.QGroupBox(Dialog) + self.groupBox = QtWidgets.QGroupBox(parent=Dialog) self.groupBox.setObjectName("groupBox") self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.groupBox) self.horizontalLayout_3.setObjectName("horizontalLayout_3") - self.radioAny = QtWidgets.QRadioButton(self.groupBox) + self.radioAny = QtWidgets.QRadioButton(parent=self.groupBox) self.radioAny.setObjectName("radioAny") self.horizontalLayout_3.addWidget(self.radioAny) - self.radioLec = QtWidgets.QRadioButton(self.groupBox) + self.radioLec = QtWidgets.QRadioButton(parent=self.groupBox) self.radioLec.setObjectName("radioLec") self.horizontalLayout_3.addWidget(self.radioLec) - self.radioLab = QtWidgets.QRadioButton(self.groupBox) + self.radioLab = QtWidgets.QRadioButton(parent=self.groupBox) self.radioLab.setObjectName("radioLab") self.horizontalLayout_3.addWidget(self.radioLab) self.gridLayout.addWidget(self.groupBox, 2, 3, 1, 2) - self.lblCode = QtWidgets.QLabel(Dialog) + self.lblCode = QtWidgets.QLabel(parent=Dialog) self.lblCode.setObjectName("lblCode") self.gridLayout.addWidget(self.lblCode, 1, 0, 1, 1) - self.lblDesc = QtWidgets.QLabel(Dialog) + self.lblDesc = QtWidgets.QLabel(parent=Dialog) self.lblDesc.setObjectName("lblDesc") self.gridLayout.addWidget(self.lblDesc, 1, 3, 1, 1) - self.lineEditCode = QtWidgets.QLineEdit(Dialog) + self.lineEditCode = QtWidgets.QLineEdit(parent=Dialog) self.lineEditCode.setObjectName("lineEditCode") self.gridLayout.addWidget(self.lineEditCode, 1, 1, 1, 1) - self.lineEditDescription = QtWidgets.QLineEdit(Dialog) + self.lineEditDescription = QtWidgets.QLineEdit(parent=Dialog) self.lineEditDescription.setObjectName("lineEditDescription") self.gridLayout.addWidget(self.lineEditDescription, 1, 4, 1, 1) self.verticalLayout.addLayout(self.gridLayout) - self.treeSchedule = QtWidgets.QTreeView(Dialog) + self.treeSchedule = QtWidgets.QTreeView(parent=Dialog) self.treeSchedule.setObjectName("treeSchedule") self.verticalLayout.addWidget(self.treeSchedule) self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") - self.btnFinish = QtWidgets.QPushButton(Dialog) + self.btnFinish = QtWidgets.QPushButton(parent=Dialog) self.btnFinish.setObjectName("btnFinish") self.horizontalLayout.addWidget(self.btnFinish) - self.btnCancel = QtWidgets.QPushButton(Dialog) + self.btnCancel = QtWidgets.QPushButton(parent=Dialog) self.btnCancel.setObjectName("btnCancel") self.horizontalLayout.addWidget(self.btnCancel) self.verticalLayout.addLayout(self.horizontalLayout) diff --git a/py_ui/__pycache__/Generate.cpython-312.pyc b/py_ui/__pycache__/Generate.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..72e46e0eb202b2bf19e471454f937a37729a327c GIT binary patch literal 11596 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 F{uh$O5<&m~ literal 0 HcmV?d00001 diff --git a/py_ui/__pycache__/Main.cpython-312.pyc b/py_ui/__pycache__/Main.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..74c9515a3227ee180b5fcec1f519648b403c4858 GIT binary patch literal 52121 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 literal 0 HcmV?d00001 diff --git a/py_ui/__pycache__/Result.cpython-312.pyc b/py_ui/__pycache__/Result.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c9cdd2d6f195c0316a7bbb9dda2747be37ec0b80 GIT binary patch literal 14354 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 oZ|2miz`zxzhQI3n>F0U=KP?NB{r; literal 0 HcmV?d00001 diff --git a/py_ui/__pycache__/Section.cpython-312.pyc b/py_ui/__pycache__/Section.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2d9dd530ed73415e3dd28bc1a03e8dedfcf179f5 GIT binary patch literal 6721 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 literal 0 HcmV?d00001 diff --git a/py_ui/__pycache__/Share.cpython-312.pyc b/py_ui/__pycache__/Share.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0f38fcf255da5eb71dc400ee599b79928189fa1d GIT binary patch literal 2981 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 SzkM;6YvxPee>j|)%Krm-uZ)HO literal 0 HcmV?d00001 diff --git a/settings.json b/settings.json index 886caeb..082a7e8 100644 --- a/settings.json +++ b/settings.json @@ -1 +1,22 @@ -{"maximum_generations": 50, "minimum_population": 50, "elite_percent": 0.05, "ending_time": 35, "generation_tolerance": 1500, "deviation_tolerance": 55, "lunchbreak": true, "starting_time": 12, "evaluation_matrix": {"instructor_load": 0, "idle_time": 50, "instructor_rest": 0, "student_rest": 0, "lunch_break": 10, "meeting_pattern": 0, "subject_placement": 40}, "mutation_rate_adjustment_trigger": 0.08, "maximum_population": 100, "maximum_fitness": 100} \ No newline at end of file +{ + "maximum_generations": 50, + "minimum_population": 50, + "elite_percent": 0.05, + "ending_time": 35, + "generation_tolerance": 1500, + "deviation_tolerance": 52, + "lunchbreak": true, + "starting_time": 12, + "evaluation_matrix": { + "instructor_load": 0, + "idle_time": 50, + "instructor_rest": 0, + "student_rest": 0, + "lunch_break": 10, + "meeting_pattern": 0, + "subject_placement": 40 + }, + "mutation_rate_adjustment_trigger": 0.08, + "maximum_population": 100, + "maximum_fitness": 100 +} \ No newline at end of file From 4606cae43f43355af8a066664c70262fc9112dc1 Mon Sep 17 00:00:00 2001 From: m-jishnu Date: Thu, 8 Feb 2024 00:28:21 +0530 Subject: [PATCH 2/4] update to numpy1.26 --- components/GeneticAlgorithm.py | 3 ++- components/ScheduleParser.py | 10 ++++---- .../__pycache__/Database.cpython-312.pyc | Bin 3506 -> 0 bytes .../__pycache__/Database.cpython-35.pyc | Bin 2929 -> 0 bytes .../GeneticAlgorithm.cpython-312.pyc | Bin 49636 -> 0 bytes .../GeneticAlgorithm.cpython-35.pyc | Bin 30340 -> 0 bytes .../ImportExportHandler.cpython-312.pyc | Bin 3598 -> 0 bytes .../ImportExportHandler.cpython-35.pyc | Bin 2366 -> 0 bytes .../ResourceTracker.cpython-312.pyc | Bin 1171 -> 0 bytes .../ResourceTracker.cpython-35.pyc | Bin 852 -> 0 bytes .../ScenarioComposer.cpython-312.pyc | Bin 5062 -> 0 bytes .../ScenarioComposer.cpython-35.pyc | Bin 3531 -> 0 bytes .../ScheduleParser.cpython-312.pyc | Bin 6020 -> 0 bytes .../__pycache__/ScheduleParser.cpython-35.pyc | Bin 3340 -> 0 bytes .../__pycache__/Settings.cpython-312.pyc | Bin 1946 -> 0 bytes .../__pycache__/Settings.cpython-35.pyc | Bin 1325 -> 0 bytes .../__pycache__/TableModel.cpython-312.pyc | Bin 3027 -> 0 bytes .../__pycache__/TableModel.cpython-35.pyc | Bin 1774 -> 0 bytes .../__pycache__/Timetable.cpython-312.pyc | Bin 5710 -> 0 bytes .../__pycache__/Timetable.cpython-35.pyc | Bin 3164 -> 0 bytes .../__pycache__/Utilities.cpython-312.pyc | Bin 1870 -> 0 bytes .../__pycache__/Utilities.cpython-35.pyc | Bin 1020 -> 0 bytes .../__pycache__/Generate.cpython-312.pyc | Bin 15366 -> 0 bytes .../__pycache__/Generate.cpython-35.pyc | Bin 8322 -> 0 bytes .../__pycache__/Instructor.cpython-312.pyc | Bin 10589 -> 0 bytes .../__pycache__/Instructor.cpython-35.pyc | Bin 5605 -> 0 bytes containers/__pycache__/Main.cpython-312.pyc | Bin 23118 -> 0 bytes containers/__pycache__/Main.cpython-35.pyc | Bin 12096 -> 0 bytes .../__pycache__/ResultViewer.cpython-312.pyc | Bin 17029 -> 0 bytes .../__pycache__/ResultViewer.cpython-35.pyc | Bin 9302 -> 0 bytes containers/__pycache__/Room.cpython-312.pyc | Bin 10306 -> 0 bytes containers/__pycache__/Room.cpython-35.pyc | Bin 5427 -> 0 bytes .../__pycache__/Section.cpython-312.pyc | Bin 20332 -> 0 bytes containers/__pycache__/Section.cpython-35.pyc | Bin 9488 -> 0 bytes containers/__pycache__/Share.cpython-312.pyc | Bin 8324 -> 0 bytes containers/__pycache__/Share.cpython-35.pyc | Bin 4433 -> 0 bytes .../__pycache__/Subject.cpython-312.pyc | Bin 15405 -> 0 bytes containers/__pycache__/Subject.cpython-35.pyc | Bin 7653 -> 0 bytes py_ui/__pycache__/Generate.cpython-312.pyc | Bin 11596 -> 0 bytes py_ui/__pycache__/Generate.cpython-35.pyc | Bin 4443 -> 0 bytes py_ui/__pycache__/Instructor.cpython-312.pyc | Bin 5718 -> 0 bytes py_ui/__pycache__/Instructor.cpython-35.pyc | Bin 2499 -> 0 bytes py_ui/__pycache__/Main.cpython-312.pyc | Bin 52121 -> 0 bytes py_ui/__pycache__/Main.cpython-35.pyc | Bin 17967 -> 0 bytes py_ui/__pycache__/Result.cpython-312.pyc | Bin 14354 -> 0 bytes py_ui/__pycache__/Result.cpython-35.pyc | Bin 5209 -> 0 bytes py_ui/__pycache__/Room.cpython-312.pyc | Bin 5531 -> 0 bytes py_ui/__pycache__/Room.cpython-35.pyc | Bin 2395 -> 0 bytes py_ui/__pycache__/Section.cpython-312.pyc | Bin 6721 -> 0 bytes py_ui/__pycache__/Section.cpython-35.pyc | Bin 2799 -> 0 bytes py_ui/__pycache__/Share.cpython-312.pyc | Bin 2981 -> 0 bytes py_ui/__pycache__/Share.cpython-35.pyc | Bin 1537 -> 0 bytes py_ui/__pycache__/Subject.cpython-312.pyc | Bin 9961 -> 0 bytes py_ui/__pycache__/Subject.cpython-35.pyc | Bin 3859 -> 0 bytes settings.json | 23 +----------------- 55 files changed, 8 insertions(+), 28 deletions(-) delete mode 100644 components/__pycache__/Database.cpython-312.pyc delete mode 100644 components/__pycache__/Database.cpython-35.pyc delete mode 100644 components/__pycache__/GeneticAlgorithm.cpython-312.pyc delete mode 100644 components/__pycache__/GeneticAlgorithm.cpython-35.pyc delete mode 100644 components/__pycache__/ImportExportHandler.cpython-312.pyc delete mode 100644 components/__pycache__/ImportExportHandler.cpython-35.pyc delete mode 100644 components/__pycache__/ResourceTracker.cpython-312.pyc delete mode 100644 components/__pycache__/ResourceTracker.cpython-35.pyc delete mode 100644 components/__pycache__/ScenarioComposer.cpython-312.pyc delete mode 100644 components/__pycache__/ScenarioComposer.cpython-35.pyc delete mode 100644 components/__pycache__/ScheduleParser.cpython-312.pyc delete mode 100644 components/__pycache__/ScheduleParser.cpython-35.pyc delete mode 100644 components/__pycache__/Settings.cpython-312.pyc delete mode 100644 components/__pycache__/Settings.cpython-35.pyc delete mode 100644 components/__pycache__/TableModel.cpython-312.pyc delete mode 100644 components/__pycache__/TableModel.cpython-35.pyc delete mode 100644 components/__pycache__/Timetable.cpython-312.pyc delete mode 100644 components/__pycache__/Timetable.cpython-35.pyc delete mode 100644 components/__pycache__/Utilities.cpython-312.pyc delete mode 100644 components/__pycache__/Utilities.cpython-35.pyc delete mode 100644 containers/__pycache__/Generate.cpython-312.pyc delete mode 100644 containers/__pycache__/Generate.cpython-35.pyc delete mode 100644 containers/__pycache__/Instructor.cpython-312.pyc delete mode 100644 containers/__pycache__/Instructor.cpython-35.pyc delete mode 100644 containers/__pycache__/Main.cpython-312.pyc delete mode 100644 containers/__pycache__/Main.cpython-35.pyc delete mode 100644 containers/__pycache__/ResultViewer.cpython-312.pyc delete mode 100644 containers/__pycache__/ResultViewer.cpython-35.pyc delete mode 100644 containers/__pycache__/Room.cpython-312.pyc delete mode 100644 containers/__pycache__/Room.cpython-35.pyc delete mode 100644 containers/__pycache__/Section.cpython-312.pyc delete mode 100644 containers/__pycache__/Section.cpython-35.pyc delete mode 100644 containers/__pycache__/Share.cpython-312.pyc delete mode 100644 containers/__pycache__/Share.cpython-35.pyc delete mode 100644 containers/__pycache__/Subject.cpython-312.pyc delete mode 100644 containers/__pycache__/Subject.cpython-35.pyc delete mode 100644 py_ui/__pycache__/Generate.cpython-312.pyc delete mode 100644 py_ui/__pycache__/Generate.cpython-35.pyc delete mode 100644 py_ui/__pycache__/Instructor.cpython-312.pyc delete mode 100644 py_ui/__pycache__/Instructor.cpython-35.pyc delete mode 100644 py_ui/__pycache__/Main.cpython-312.pyc delete mode 100644 py_ui/__pycache__/Main.cpython-35.pyc delete mode 100644 py_ui/__pycache__/Result.cpython-312.pyc delete mode 100644 py_ui/__pycache__/Result.cpython-35.pyc delete mode 100644 py_ui/__pycache__/Room.cpython-312.pyc delete mode 100644 py_ui/__pycache__/Room.cpython-35.pyc delete mode 100644 py_ui/__pycache__/Section.cpython-312.pyc delete mode 100644 py_ui/__pycache__/Section.cpython-35.pyc delete mode 100644 py_ui/__pycache__/Share.cpython-312.pyc delete mode 100644 py_ui/__pycache__/Share.cpython-35.pyc delete mode 100644 py_ui/__pycache__/Subject.cpython-312.pyc delete mode 100644 py_ui/__pycache__/Subject.cpython-35.pyc diff --git a/components/GeneticAlgorithm.py b/components/GeneticAlgorithm.py index d83e2f6..b2bb589 100644 --- a/components/GeneticAlgorithm.py +++ b/components/GeneticAlgorithm.py @@ -220,7 +220,8 @@ def selectTimeDetails(self, subject, forceRandomMeeting): ): # If hours is divisible by two and three if (hours / 3) % 0.5 == 0 and (hours / 2) % 0.5 == 0: - meetingPattern = np.random.choice(meetingPatterns) + index = np.random.randint(len(meetingPatterns)) + meetingPattern = meetingPatterns[index] if len(meetingPattern) == 3: meetingPattern = days[0:3] if forceRandomMeeting else meetingPattern diff --git a/components/ScheduleParser.py b/components/ScheduleParser.py index dfc54bd..3ec5087 100644 --- a/components/ScheduleParser.py +++ b/components/ScheduleParser.py @@ -24,8 +24,8 @@ def __init__(self, table, data): temporaryData.append(["", "", "", "", "", ""]) self.model = ScheduleParserModel(header, temporaryData) table.setModel(self.model) - table.setFocusPolicy(QtCore.Qt.NoFocus) - table.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) + table.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus) + table.setSelectionMode(QtWidgets.QAbstractItemView.SelectionMode.NoSelection) # table.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.Fixed) table.verticalHeader().setSectionResizeMode( QtWidgets.QHeaderView.ResizeMode.Fixed @@ -67,11 +67,11 @@ def setData(self, index, value, role=None): def data(self, index, role): if not index.isValid() or not self.data[index.row()][index.column()]: return QtCore.QVariant() - elif role == QtCore.Qt.TextAlignmentRole: - return QtCore.Qt.AlignCenter + elif role == QtCore.Qt.ItemDataRole.TextAlignmentRole: + return QtCore.Qt.AlignmentFlag.AlignCenter elif role == QtCore.Qt.ItemDataRole.BackgroundRole: return self.data[index.row()][index.column()].background() - elif role == QtCore.Qt.ForegroundRole: + elif role == QtCore.Qt.ItemDataRole.ForegroundRole: return self.data[index.row()][index.column()].foreground() elif role != QtCore.Qt.ItemDataRole.DisplayRole: return QtCore.QVariant() diff --git a/components/__pycache__/Database.cpython-312.pyc b/components/__pycache__/Database.cpython-312.pyc deleted file mode 100644 index 021e06bfa5a153faeea9ad8986ea41f49cf349a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3506 zcmd5;&2Jk;6yII1KkCRSX+xBjP>oPavLdQlaX~<-9B0!wu{Xuus9!E-vpbD9*j_WU zu5gJ_A_by|LyqNNKov*e)W3jBq~>55Zk)JT%`IGbv%B6niJcEM2UglQGjHC!nR)Lw zGrvD#u_y=M=fA$h|3d9=)@Xl%SJ}A&mFJwn8GMm@$Qi;K_mDRNAO%AN8L076@E>NZ z=-v>g2!Le&&Tk-|b2jg2K`gaBw-rzt{0pzY&Mk9G!HzDk`ob&g{4&23KHP5zZ4W#L z7UvFI_#On9p|5v8j2Bk;TA(IML1j0zsL|`j!n5hDoRSkNDr+T-rZRJBM87VYHqMtc zYGZ=#P0JY>*|iG3HEL@MMLde)%A{j{Yt$@Ln^bk%B6M_0l|s$1JNUz9Shvb$tlQ0y zUM18b%`pB3>s1>!BTulc7pyXF2KAyvu@q>E%$TsvH$w!|YSE@F!U&<=dx?*8^Ar=B zn=xsjTt(?zx=KwwcL$fTZR+vjqD4%*P?|5BPr=NzYl)&pX;v>_qguoyr(2~8%vQE( zZc>9CXcS+s)S6K+(7(!JyILXrFqsHHod&VO{ndA2^Y+H=pFVokcXeg55gXWiwDIW2 z$176}F}kj-Dq9yHZ;M|vViz~_8~InUE36~3KC?QrmTH7!E8jKF4>tPF?|?6^J8}qM z;w+J42z9{-)B}cC7mZ*&XoTt^BU}%6N7V9uM0LU3a$q0kx><P9bGZMe_Y*R?VUgbfYnU079mL zl8P$dku&ISCYg?B9-vwI!FY#-bC^{5zUsJB=2NN8-hu^3!gs+YJZM2Z^rD_VG~EWg zqlvk>lpI(5Y0#uR6`xP3=q5@`%Zb^2>qf{Ml~mB!jd65S>R9q#UHZgPYr`iD6S1rk z-8a#j28i7@y|@0q2+j{D3=XX>EWtH+w()TR1i(%CiSNXhZW%{}&%jhCX2mwGa_<;- zLcb>l4fClnV)zn~Gbym;F9d+|%|UAkRw%yx2nM)`?Z){3VMggdA!N)O`j+3&vQ zh&RQfH>bQVfgjnxV9-QrZlddvx6KlUM3*XP5?(VknU?*RATgiG$cmb0%B&hs-}RU2 z9Uv)07%wFuCfHj~A|QacS*4O`6UL;a2w}w1rD(%C!5R?6jyodnFvI2rug7^2Jl)%# zu6+y+s=d5<>cO_PiJII3h8&?ai0xd+ZNyV8)Ms|)V(pfEsps; zZX>cjyE?m;_UPmHDZ-ZBoimO@&&fGsmXidR?MT92c7Nua3EW`C7O|ahNjlt$h($ diff --git a/components/__pycache__/Database.cpython-35.pyc b/components/__pycache__/Database.cpython-35.pyc deleted file mode 100644 index ba251a585f4162824062e5fc9e6084502987623f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2929 zcmd5;PjA~c6sIg(_8fa1hHdDP*d-NE6z#UtwhnV_rZMWsfu!`0VZcx%Hc?_r9!VEV z7N0uoo9wVpun(}~PP^*5)4sxX=_4h}svBnsnnPuic<+&XB;W5x@_p89*8lwDufczH zg#Jc_uLSb682Sy^xm$m$K zDAH>i3b&yW2pxkD4ZYIP9HDbiOXw9sa}Awq=os99sv%7(Wz|qpohnk+&S6S~PHKo* zazPHP#W5?^nQ`dxd%?lkjzfB+?c&IrP`qvTcQOBA911#`cwA71pY9NwU~xL74>yH( zFs7ThWpz~dhnr!<1)KRIW_)woHI1a24*oK!`f(IdUnGVx4SSp0_A2cZ5-+FuX%Ic0oE0-uhD9m-EcJRLr2!GGk$ zGv-r}9RG+0qbFYs{dh73*OB1Ejt9&2IK4MLP3q9@pEy*^rg9ek5mZRKr8TrBlsc5M z#x}s_%Le(?pyVk03d$uYK>X(l?KxmkMstPsydt5VE41g;3@HF(fs~HU^`ZjEWf(#W zK(|zkqEby2;DCZ!lWa(V29$wJIk4X68bWoPeQlexT!P)!R*&HBHn#dMCeON#>)-;0 z_)b0m<1oNo%O#J9jrZ*CZp(g-ACu>I3q2HNT=L9S?yUV@uh@D7;PBjqoN%=Vm#EFg z6tDH+`67Ht@m9azBP}bR26xDIYrp5>2e`dM+K=B@H^$khu7&U1zl$H3g(WX#^BZOM zZeKA>ERHAqjfvhhK=Mqj-}-wIoL{aO96mcZhQofd@kt2;#O>w47y0GK!6o4fDEC=7 z6=58$k8zRuYdIK%FGC)}#dlpAE(c!7#NuAwrb5oy1y6svDinYNZ2D%Q_w7XI=JmK>OmS*xFbd?{~3IowWt>% zvwfP`7RO-KoZ*(4KUwrnxw2x-f|puV8kAO$dZMJlWfF4>M2?|SNz8_^VSEU`x=}SC zp;`Xw8f!qGJgJcb@}#B-N-?Q%%u=2_n59CnWFoe@jOHN~?KH!K%Vq>UxO9v(Cf%Cl kbhyl@)C!cf;6u4o`>B09iDeG(9UL#jB?=9_vC-Ij4R*MY{Qv*} diff --git a/components/__pycache__/GeneticAlgorithm.cpython-312.pyc b/components/__pycache__/GeneticAlgorithm.cpython-312.pyc deleted file mode 100644 index f74fd7c7ebd007fa76636d36104c71ca65e2f857..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49636 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%0A|IyoXGIn_F`RDtjjgt?G~Ct>I;!VNh_OsQblIe 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 bSG#Gn9m{K+jk*poBW6V1t{QjFKVhi!_ diff --git a/components/__pycache__/ResourceTracker.cpython-312.pyc b/components/__pycache__/ResourceTracker.cpython-312.pyc deleted file mode 100644 index 6d9bec3fc67afd1c9137316d048fbf7b9684b453..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1171 zcmaJ=&1(}u6rb5_($-B%(^gQll2TEEQm{p6(^`-o1R?218V@BH*4;7Pnq=e5ZXv~k z2QQv%Ppv3eZcr@LlzY?0y1K%AXPI8GTNZ&*a05R8SMm8 zML^_tKw@$-7VD_H(1TtCP#Si_~~?} zSP+bh;$urJ)!bCJn019^6d$n~b1dUwrEGJ{S*jLl)(V7KPGh>F3z0XLnCVs+FB*2W zZr32CD9$rsyO4f?>&6SlhwBYrD>G+$wonjynQO& zDc%YGbMRGgNcdY|Y>@xMcQCgc%dyZp)jMr7q-eS8bT72R7?WNF*O}YobB9rZJ|A0F zB;_1mB^~2fiQh5HZG#EnE4J`sKt$a#eXYu>HgA-y+H>3QUa`32>XlO9)%5Ar1rfG;;!oVLxQUSug6NIxtUt*hFf&BzbF$e<02dhK{-==Bxe!QLwG*~^UENhT=iMQ zkv}`Evl|@?c9xZOwD>iM!`C?JEK}}rB5iz2S*@o%DesoHz@7a diff --git a/components/__pycache__/ResourceTracker.cpython-35.pyc b/components/__pycache__/ResourceTracker.cpython-35.pyc deleted file mode 100644 index d1397904b30cb0cc0bf23790aba33e903569cd9a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 852 zcmZ9K&5qMR497kB>TbUPfsj@!9v}xea6|}!3gWU`RdmZCiWHTZp`@F3qL~D#61Va) zJO@v}HCIl31y0zGQo5vx=O0hU{@Kps(Wrm#=dZ*GfZuR(d8l9G;iWt-sRMrbO4HO3aOr@wpC z1F}KvHBss6Dld|OEbFY)R_bl_18ji1Z2nwLUZe}BtxMl2sf+ZjcDI!&)Aw)i&gQ1Z zBdF%`i&ojk=czQC(rht`OFwAG+c$P8Z?%0^?wY|$SCiRd;g%~M5*tB+uo2oj@IE>i z{wazUzVcx0!yc%FbwC2kxuCtUds%s0oaN#oOF@#}%o?ekYdqtc2=kY@N(LLfF?N^b z+s`H$f6Z-GFN>^o{wuy!#MzAT;5DCN_H*=g?4%`Sq>EN+9;Z}+ z*(G8zjX%u+?t>lRZY=DOmn8VKtMvb=$K<>**Lt-iMe(|%Yu9xglq9Spu@O de-e&AH7@7u<;JMG(66Y8u8(FYhW;?1-(S-Cp`HK$ diff --git a/components/__pycache__/ScenarioComposer.cpython-312.pyc b/components/__pycache__/ScenarioComposer.cpython-312.pyc deleted file mode 100644 index e57cc38f8bae7541175f98f90456662896baf891..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5062 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 diff --git a/components/__pycache__/ScheduleParser.cpython-35.pyc b/components/__pycache__/ScheduleParser.cpython-35.pyc deleted file mode 100644 index eec7b9dc3c851fd972dc010666cd58e4a17b6908..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3340 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 d4R)dc*;IL0EVPaWxI zZ|7#`W@dl0vp+XB))Sy_fBKQF2!#BGlQO~Fp<+J_3q&Cb)kuoQDJ33qf+(J8qIeli z`bv5g!;06P#JyQxOn8cu7`6Sw=1`imM1>+)a;bO>#?Rq5jKrxz;+`3Do+@-&jC=7% zai3DBc&BMxfYAq|A4UPjIvD*hiZkRYjR!_ZOtkAy%jYz9GOaKzQF6rj3BKb~90c|? zT_C0-MmFosky{Y(N=ZUV&XXfj**lV>Fk82kCCl_w%x4QmW`c2Blq6MGO-ZtSifqcZ zf1Jq*CJ{Y@zJ)a^^#Kze=ON>4i+X~Im8Q;x7p=H;M?^Z(*zLVMs+(i))IhusA zn#w6On$7iu)x=0?;RvMKTu*coU8|y`SS5gI(!uR!`Ndwy^XvbWB!ipR;|yX7y(}%q z)aq(9y;@_0@H)_l1?)Q27?m|u;g|_q93GXqD(j~088+?U2PR7$1H62i)|lOJOf@Dn zIg1k)D_)+yV*3+mEtAq?UXH%nf~qU*s_o;TWuQ$!5Z?x)vt%+|1)lW^<8k@+K!!h2VPdkc+CUyUxDoj;q8bX$?`e5BWk^sY7bZdM9~=d!ce zJCUW<#n!t!tx(r}_E3AEeWP2U1FPZzjtNVw?;uRjGZYrz0tRKaj*=WnR_ei5q?OY5 zQr?z5wpU}i6VkHJ4ctE=a{##QllcY1_Fue$W4VUh6xbppY$%=4%}tOm3wOYejP1Yx z@u3~J_b>F#_kD4FRcwFReJoAK{deJIYxfn3u-FJ9<~hYNO1=|WJFqH88{AEGeQl}O zvkG|xmm#Zg_s;PAz@t#-s@UoJjDD60-!bjQzunUGY@BViQeLYdYn9%`Hz95Y`wXO{~)GR=fL_k-Oo8w$nrs3dN*L&?K5d&59zlqZ09x$8n^y++-k0$7RUKe*y zv7BN7=gi?@c()rq<|li=&J~+mW?csrG~k zXm6&yZP=75>~M6l3fT2-!`4$Dq|Q zxE35NY;V5jUkWS+^3fhE+LMp=Thact?ft*I2iN`m4-Y>${N1GogWq>qdk#Gc_pJu| zUa~b{bquTp2mXt#C!xsPjoBMp7TOOG#g;vgW+`4IYJn3vP5FiemdaG#P8SGC>?2iF z)))XeSguuicFlK>>jAJFKOOUPY-P?#%Ukg64PbTy_Ku-(S--#(+s9I> zS%Lz`?X!i;vX)`B_P@?xrnC7wDmK3)>w=}mabOj_s1S}8-Z?nqn+wbaZg(xj=3`%W zTVltZ%u;SKclWv__7ucmUW~%+BrmpGV*4F-|IA~tyATRHC!pJA>+u4n%P9sIuzE>K zrSVn-??Fkrl#w;}i*pxp1KkZy@IA=7k-ZJfZY*8Q5=_%1DMooCNDVBc_uT%9Tg8## zW1xxW)8v`QE42SvF9-*V+o;e{^iyGX(cd8K{-;e4nq3!B-?=M(k{vb=x)*`)@X>RI z$>oH(ktfIaGI1B-3HU-Ba6=j7hhU1n7;V7*@KQ>DA<<`I7j3@Xl5gs^n!5iYFmcxY E3+aJ1-v9sr diff --git a/components/__pycache__/TableModel.cpython-35.pyc b/components/__pycache__/TableModel.cpython-35.pyc deleted file mode 100644 index 8e00706f265f94c21bfd6e7cd1e3e286d85b2004..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1774 zcmZux&2HO95S}F|lKQh=&3VHDWa25+TrZa48QqiX7`7~-dBJBlYZU-_!nAFfcg(O z^w%f^{uz`2GX^OGb}T#)KD@zYA0&fw4{m%&eGmamlFnN+frQy`Y(}+`IZfA(zf$x$ zDiX*YdQUz06W|5v`1jxsTtR2fAATeaKy*NaAR>5!2vEm=45I6%xQ^2vh`yUfZaM%l zbkmqTPm(R$d&Zxa@<}aZnXggM+rvR`{Ur(ma0778NV01Wt^qQX%qfV6T(OfRupPaa zOJ(CME2_d|nGFOt+=ge83#k&{23nRcRD?cNhyv;8W?5cxt+VVe`0sf1-Sk&2m7e}6 za#>D~q`olqe0ux{|JkHos9d5p$V_~!00d;7_i<4(_W0TAPQ^?*>vA!x5?{q+(BX=B0SKX7=w6UA^N z@zfoBwLz)7w6IU&9*Nt`*nUHz14Jj+fc9I=w2tJ&3qABEOd}lnH44hU;|E*&!UJ^( z*Zz9NU#-xAz|n~9htRPK9Q=)K=uTdKV0-CYy|eW;wvA7$sY&8DB)oM@M6Qz57D7vV zk84#d>&oy_ZR3KXgt|^k<5Q_jk@GTXa+r4J*qY?T~hYRZrpmjRy>` zLE_-2XGy3A1edB_?U10Nv3;uW(HXB^N?`*zE6gfpMU`kfzw>e-KN@JHrJ*Rlz;o|f zC}5wlJ+|C!MY%ebbm^9>_)Ow0*UPe5Efyu|gDm@P!OLdH-9rsVVox2A_>=^FX2W&D zRF@W9Bm1b){iP|u0o&~iqHQ04k)j=U&Hj8fHs8ABr+ec^&$UrJHye=d;KqBSk#8Fx OHbB3p`f+`*6Z{W4-d|P# diff --git a/components/__pycache__/Timetable.cpython-312.pyc b/components/__pycache__/Timetable.cpython-312.pyc deleted file mode 100644 index 220207502ac5df62c38bee6acee88d5e4e70cfe9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5710 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
pv2 zRAf&bmFNhT)u_dPb!tToTKRo}T39QN3Ql*0!03NbAJ)K>3cc7OQ+4Ym3nn5iV$tT; zSLqllhz1o_5H-)fFq?%x{TuC=8k>>N#bL7aI`4SUaGiBGk-wX4^k9z6JPj6Tus9ny z_d^3qG+1^*-kHtKg`EHYfn3O21}->-D=cAfMj#y8@#nT}`O7Sg!k4!4Xe2c=wH+Cy zIa__SKT@ut%;BwVspZC0Q7$5>IUa+%rIz!$VAptQUnQv?Ud$eQD=sD0E1- zr6B{}R<$&)qr14Dsd${FCQLq;VI-A(2V))CGjWzalsX=}7*Pyi+i2%=9>?;zEp5dw zWMt=`No=P#TVClUaqj>Fm0p&nkYgJr>-Q76A(KRR=XEZ6V=}AuBu=A^{Wyub3+;P* z+NiK+?vISgQom|FEt4l|8M;-A4JhyDHrCh^!ILNszDH^ zu?Yf>UVR0GL`}Ra7Q`jd6qmu5(JqTC;=EWCE&P@p9WR}TnTqJ~3G?Gkn#%-#!Uu;5 zUf~d5a8WGi#qT&?HotyO$1Z+2@DcuqeL_fsbK%}XVmc_0`W2_A6p6{D4TK&(x&Lq~ z9PwIo@sci{>T;PxOhOug4^5a=Kn$mY#*lNII0|WF5WgCm=sU(~L+080N$c0A#taD8}bcpl~V} zW@unkaC2y=fXUI&@x`_;oXPlOL(b^56(j(*^D4%40ffZ(+=;Hq=(b;G6sO@(27#>y z0g}KdVZIpzPe);rkEm;`fw!SX!Fn`S$w?pv9;&mrjgEOe*4;(yM*8@%Z6AY8(n zRT>oqyo=rrjN=c~Vb4Y3H||hTkkN@6$pH)wg&o`^fcso{2Q^1=sd0A=+y`*qL5b>o zZw%KAL^D?BW9ce8W1_D?2SrkUIc*C(_IAx3zq;+>`3?Kv&9_XRGWidaUo-g_#BbV4 ztRII-94UsGt+pSBDh^X)3vFZP@6R&8!wfl@bG2fD>IM^!SCrfL)kyE-e}i*`ZEVK+ zFbQAsg2`dok_$8IDHd`9KZiV)c@s@@_8|mTT`VE%t`>fb|GF42pE)>IiKAxl5=B8LG=5WM^d-&|R47ju31p_$dIs2IS26c>_y}?&B z1TYS@g)>}Xwn(k~`t(zm$sI2EruY4KdUv`(JHQ6#U9|`u>KqfkH@cHTPGa~ejs|s! z$wd&j&}ZK5jkDAl|JlX9Or;8qd>B4=SKm)CN!LNxnPs^0vQVGn%Wv4yZ(g>|`|hM& y;m=R7eo`TG3pfX;^GqsC*mq9CDb>!)>{(m=IL|ttaH4a1SH%U<^p>x*&V2`a*|%Z< diff --git a/components/__pycache__/Utilities.cpython-312.pyc b/components/__pycache__/Utilities.cpython-312.pyc deleted file mode 100644 index 0cd0935146d0c2c5f972133e37b44133b8d1a081..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1870 zcmcIkO>7%Q6n?YowI}{*nzR*8kg5uSgd0?F)FN5}QsgQ~Eww~Us@5{HoSl_3iM{L2 zt`P|wdgvhqL~}sIhC@??gri)1sYE0YJx1b^bbUyda^iw-p}F+}Z#FgwEl5NWBkecy zX6AkG%{OoMr&ufu*xtGOgAq{yew9YIg*t=nFBO1AV8BQTva(l7qzqYw08?*3R%HRi zfT1yM=0$)7BF-pa1X*x}>@b|ix%Y4-8!AGU8g%+dH^gp_9?JC5UAsGCAx2j)zHD7S z0{i1ID1!m?KR6R+({s>lSeQlj!4dJ5@z4KvSm~H7Iv2sS#rDDZ&q^O+y$9w1cKE;? zA=dXa2dWS?=xzlpkWYsKFiU1hqQ5PbNGFIF6a|x6Wqq$uK{T+kVfzNcA~>Cz1eoqr z)!xmFFr^#&|JYenGmuczLWXYtfsjyyOwJ3*%(>|-!?w)l@s-rM+=OiiJ9mNGQ)czV zrQD^e&Gp<{hG{rlA1xIv!JVn{gvsB>ZQPknl?t|<(WeYnEg2%GTjh#n8m43CCLCVk z4ma#mm09nQZj~${X+*)XgpluF!_R&N;W|8w_TNh1OxKb%-Hkr?&Dgi;JLzV!sk_gg z`+n@l^lEx7xu&}#M&ORf{52hraQ-P>LZO* zlPr%lGs|yp44(ZibFXjp@;!Yuw=sBOjcp8!uV21;KYsP&v+Du#e%?g%rSfP#UoLPn zpKnW%+QSmoBz%FuA7Xy|bBx*c6OGA*tOO=O-cmc9c|wZeC+Umun2wY!SxIk- z7jQwUV?Tqqr4mAZhS)D~{85mQcgZ74h()%75Qxstx$3}!SpP!ulPlX0*5dPI^T@Gz zx=9b;>b==p3)hs};d*#!c*%C-LoNE!lMAmkM(@1dRNeUL7CrOi;=g*GZX9*vr&{#o zjz?Xq@!I5VUguxUG)C)Ib14!=4H3s<-$P z#Q)&G@aWm&;LVHk3j{CvszWp^0h{hOuc+y+dR5)mTCK*L&tC^ko9H{OjVky9tn9uZ zl9+;KM1v)_XeKCvX_1gN$qK!P0a7LD7+xU-UZbf+`cRzzB;}BFX(8z7MM;Aijj_Qc z<E6?l%At({cgMD!k%_T;pkB;lPF+&HMr6}tZW~U6HNpcTcQru zf6TFs!|hXz4pI3V(6zLMPf_DAVVr*=&8Hjq^|*I9Jj;~MhL2>RX2T`r=7Yz4_I(Z?!QdXy*T?2Mz5&^2Jd z+3?`6jb*ew0eNR`Q3uM}Ol`EZLhb9!tKbeeZp0DL6(Jr) z%J+*ZS~gaN2n#n;c^<~&tZ+tYs$!`tI0io?^H>(uRHLzLB1~|j#Jw9Oaz0c1Vkx@` Y@Wi(5RXp1hyTTD2aRaL(ZW-)|KV)>m1^@s6 diff --git a/containers/__pycache__/Generate.cpython-312.pyc b/containers/__pycache__/Generate.cpython-312.pyc deleted file mode 100644 index 4b98dbd30d71d2ddf09fba909bf4d64606b641f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15366 zcmcILX>1f%npJ(dy1Tl4v~3K=cH_H^IgA|+bH!jV<}eTpWE?V{##J%h>BFgN2i!5E ztOo7cSrDL^5kwnJO#Z}7Mv9~TF&?cnOSD=|qLo(EbTidk)~C=i>4PhWStYpuwI6o_qkn9Y$aTHo`>N z5jJWWv9S1UiCCky5qs1z;)s@vltj4^F6ta{5}GyQin>R50^1^>g)cV+A+l;{_hRJ%R^fui%BaR49eGY|0iWmvCLj*t~v}0F2Z1rMx_NXOw5W$fDTTsb z3K{7~S@0@5&4$YjJcaV;OgPsbr7}#|XTTJiWVi57|vZ>5lt3Kqda*#NA>T1v?))kAScO4k8O zEc`8_1chkHe&*GE408c^;8ojIJJgcn4>Tu~f5m_)G;Mok ze_y3}jda>BSg=P%+3PRb7+5Q_@qXJVN1;`A!gna$NR1X?Oa+ol&qK#gxRq#>qmV(L zVglR{2w>~j#H8kkiqW__ku!V~NmzgUpdCvBqxAlZYpR5h~0z8_4I^HJbopUh^j6 z69+Fz@n~F*M@1Q>GGI$4B=OCVcv*92n>!{>$r1;(X{DegP^piKg65c% zjvbzw5H*JmYo%FSC=n5lgrHjA!AUt0kA{+>P9aG9>ETdR#9>10ARm%u$1h1M!6ZJJ z&`QSQu^3F6=FTx!o&qHMntOgKppt0aTgP@Q^844kV?iPFqNX9 zxfAj6aa4;47U*YSUNsN&ZQ|qv>OQb!nrrOR>!-343rj)@WItVF(TivFmDTKH5itlI z4kbibeMfL&LW~JoNl*|50i*fGCMBHG!I&UkId~};8;ABiV+5eJ^JE<7;}R%su%_Y_ zaSS$=O%@}sY1~*=SCf!y=2nC3Dy>9-Zz6eL*Z6?#wwy;g9+dgAUbL%pdRWr8h&M(%i%~Y+))YfHc*6IJh@|0A$ko35W zY1n{yYcrMAh{&v|g@lL9h^<-jHL1QH#n+SaZJ*&XzFO6{QSog|`8L59$KQ0$I#sSl z;cD*Iq`AhWhIX}KtJ1J_(Uxx5`;glURk?4y_GLqh+OS1w*ph1KddPL@$S*kWP4BGt z)|+XrKErucu1?|VmiUUBgR_Gw?^k%g%C{+e+mg5PW@t8~dK(pQqw3wJc(;9JWj)tBb@wxK3zEou^j%*1quik$3`=jvT!oIs^T`IRu z;nt~Kqrx@L^?bPh-u^V#ouiR)Rbv0LlTuZyRt1!*fL??5X6bCH$~7olgUYojT-&@& zZQrT1?@V*MU_>}Nm8(~{dX;NcxYoIZ+O|t++m+^e$#~Z)+**~}pl};hE}(FM`DV3a zkJ7Ox&F#&jW9?~fL&o3yq4S<|zC-c9p!#CFC_riC>_tH;5%TPTDKKFT=?BuwI+QFU z+|HjJCos5VIf$6asF;TWb27^s&)_r>ZX@l0rnC~^`@`augwz9H_gONTGLAAkiMs$y zRu)ep^4C6~$f%XV6ymbt)xZ2mbUx(kzqVSOu1wDW zNy&TE?x*%;C)E?Ekin zjZM2s?RXZ80__`^!5&I7Q(>V-Gt)df9vE5fSV7J*T9c86D-4)IVe6b#um7`a_pi+P%)Wo)n$t5@u2oTuIqUw? zPnm=!lje{^cS7Nu0qo6Qa2zaCq_6+(#x0!RkFmSe1;U$c)bK3yh&N}WVNm= z(W4XlbyZArp`xB8WtG))sGFC@sb-lamg?nl3a4}y8qVjbhu}L|mE)<zmi${)f1l#- zd(ixgz^8$f|2S4uM=~Op(5q0nZ3?$-p-1iRSGxPt+@U=BMupp`a@`8oz0j}r99DV` zr@4VVdb`54tK3$F+qzKs(}qt#qv*?{7E1r4%J!pa?pPkZN#UAuoGM>vq8pBg+z0?f zWMvjwgiL$Jd@T?{4h&dmhl>Mf8P*Y4+9tn+K66Hi;ab!tJ-|_h66%;(k0k_U#92etP zU;yY-N(`e*MH&aH<^j%Q3_<5UZottIXfF83_ExLF%;>~`Zcm=pLtwNH+qq+KWy$%n|CYCyB7x@^!@B;s(B#I9Rb#_ zb34O0eb~{fcJwJ7eGl3`+wf^es^dhO8_MM~OyGy@d(`%WO8dbF1E2MMdNkF3GR>XJ zf8e->C9n<8E8nvDo!VZ;Idd z6s;08UOjprkr%5Rim->9`_;|Il+DLJ8+bT;_Vc5u&F9nH%ehL?xKX)Ih3kB{>43Uv zP}wy2S=+;x&V1gH+I032cWxyE$IU_*_|E}A1LvD9$^_;m!A$)&Zi+z3&E*6(jXFbU1e(WaR%S3mWX1s%ISfNzv;Bj=r%tI+X-boIpsz8x5%+BXl)NXmV?O zzSoQjQTLeP`7GFk7okYfms6DVO^8aD2n6{>h;Rq`s3}ypRNwf1^xf$Eu~hv|Lvg~b zdAH~N-S6&JYrB-%F12=_QoAoz`{E<6Z{-T1sXnEY z?3S)8+!Xv(_NKsbwIpx6C3I{ud%a@1M6hF>vPE#jJkvJ)27+QqYvcytDhIcOIg`!k zl>k@eX1fb&a$@OeBAoTv02~o#P&=v9sC}BFm*_xqBfg)x=^V3+gAeIdxKF+6oOS|* zh^M^NgE^D%H*URcxn5<1+*h4~_dP2eA9yuEZZ|Zm5S)^cTj-u=jCGG19_BouP~hywVat1Tp-@^rV_Pb%xYeWj zS`}Ywy0mRR@$vMJr!&5qjBkyOoO?s@1?D#>zE0KGrTDrQIuzet@Bmj--wE6f%#?s* z_-?Ie%7J-wh7qg>Nao{gB1q{-O7tH|5{D%#=C3S#RZ%ulm;IAMDAL)nuAF z=DR-VeYXM_{9dJ-vSg+E?89^CmF|~kj)G_N=CRphU({{LtnXBz?)BZ7nua--QnPV> zK&k0jIIYy|KuihvUFO#;l;2-xU>l#5*y^eu^UO*191Asm9{!!x(pa4tIC|H2cYH4R zZg{?JVZ;57h0BX?e3AtD_RE?B%b4SUgZ}EoBX0d4m)($s z`1}86q`NERHmx}VG@;f*$2q=}&7!2Jtetelw$#$*W_pgIT|=>_cn8X%GtIrg91;E0#8 zMqU3PPWL?TBl$+FD$O-4an&kEY%Afz@V)Rt^CND@N}i7$CeynW0F=rC`+7SZta2D) zj`ss88;l8>f+2$8NX|Ssr13tU3N>2-Zp;dXBLFp7lN(NvmtYpCGEM;u%3XS^>z!T1 z|6Z@~^^bV}V=Kc~=^fAS5KbTI_`d`2Jp00MDi`@sZBS8BFk5>w6+^I?i5T-;Vk#bT zteCQ7n&M6h*z{>mmK}-&CuC9Z<5eN5>3`xbUFwZSdu2ILB5i`slS?|d#*=mZx&)M7 z%u7^gomp~;_?ZOW+OF`;Y=iPER1PeC0|@d7h+usxYwir*9#kt^l**R5V5+hmFN1Pg zq3(!5RXD@fXYWab4@37tYU@s=b?4%`RBL~VKVRf4H_$()mT9(#MgrYaTP&IG~uwxYqW6-=&dzGZ^etR+%8F=o127i4~2}B zp0ukL(8+fgcnam{`1WrX#Tu#LN}yCDA%QolB!tnJD+B~ujKDFA3ZZc}4P=2YbHNsw|b_qZM&(Ptd8!cr&+=jp_rewvzQ)m5WW$3f);xEPRANxc{iW3&?@xU31u*_TB`DsI zT9!6KfQH+TN?Q_b&FP+7D+sx2m1{l+Jybjaxq6b${1a<<7eLri}A7o7&Fvc90Ut7 z$2bApT}Iy6A;=9Iyg2ACFEdpY#4B;AQTDx>@~peLR;huw)&vq4)C1~zaWHeunb}B! z!%Rso?(H*M`}1$B(8wqX(3(CnGDEp9eVo}@HhKW|7^mA~x*H2K7;+-%&6758#gbfG zC}{xY--K?l69)pEgpN7FadmGNVdsB`IKs}y5qb|I>L&Ohzy)^o1wbU%6xr1v_K0}- z6m$P0M7poQ`Hu6}=~?d$C)n6Gcg^m)%f7QOQ?qua|HdHf_B=+Q@|_CbIsfuP@ct`l z-mt~*A{S73!lk&y@=x50eV=&KJYK=;mj}k{zlTlTYE!S$)VsJ7E<$#vnhGvLjBDQv z-=^}L6@K&ll|}acTZ>)yzq@$lGxle1eb)7}@22=6!%)<{DdqTZGZu`BqobN@bTk^r zUjhNlkB+`E8I0%@={Ss;Jb{x?tJB3RYD&_#G5QWh7cuI`=o&@>Mri-)5)-HOK0|yC zy7v!lJMt?XR0ZUhAiBmZTQ=IOmq%FEzG2y6v%8+~R{IOfE~mY9xtg^fWS1RI`+0V` z+G;<*F1u>%b&q?PdjAu~YTvo+vOpmY3N7=UcK?$Ltjq4wo5PmI;4c@@Aja_I97KNu z9EJWS$-;vM{$l&q(lwcvrvX8II21$ksV+kb#ZA)IHn1RmNw;?}M72H_zjy=?|yHP^w){=#p- zE(b%2VpoV(GCC@V5qKS3w_5)Q`B&IIRC%%|Y}R?hy|QoUXC!@lIV%y&_`LKZ;OLmE zC=|InY(-@F6fBdBB<1-lO`I2WrFCU7#qF`JKe))m^FT z?pxNSwe9NK9m?7rskOUqIlioHQY&{Tl{*$4smlFJ__a-`+_tcNal@Omd8E@8jAgG>~SSiR!Melz$4vYfQ#dKXXp?)GMC)yKkmEt#2QO$$5JqQ&#!*;8PoGuU&Sq_R8Nm+;+XY zq=G<|W&A>d21d-3ZX11o#gin@>8x!=M)4EGpTOuCM1SJ;=z?jV^w02#K1_09 z``F5|?0+y#zqdG8%hwD>UWRS?4YTeyO!coB&#xKx?;UShSl3q!#!sj1)okV6!|xBh MJM=XJAZg)$0ntMy-2eap diff --git a/containers/__pycache__/Generate.cpython-35.pyc b/containers/__pycache__/Generate.cpython-35.pyc deleted file mode 100644 index daa9e0001170dafc85cfaf028b5efc05f7c7fbe5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8322 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 E1GTE=2LJ#7 diff --git a/containers/__pycache__/Instructor.cpython-312.pyc b/containers/__pycache__/Instructor.cpython-312.pyc deleted file mode 100644 index daccac74327805ff19cb69a5cdc5257900aeb173..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10589 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 AS^xk5 diff --git a/containers/__pycache__/Instructor.cpython-35.pyc b/containers/__pycache__/Instructor.cpython-35.pyc deleted file mode 100644 index 0350f0f44ea541d152529c58b98b6d1876679c1d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5605 zcmb7ITW=f36`olx@1!hCu@dEGHc4v}4V*S@S|mt(i7u83Ted7YZWeBdHFr!cz1(GH zhp|OSC<+&8f&Pj@_E$prDpIPE1^7r22{DqwlVaou&k>SZ9TAnp$Q52$j4Hyb*w&JW zs$x_VUftGR5jBL@5Z8mU2rA-Nm{<`{u}Te1RT0#Kp%opQ^0B8;%spk?P8a&TYZ{d{LL=2jus{84mdpS zfLq}TIFDBn0X{C5T`@Z+?xiYXcE+c;Kh9gn0UNr4#rjUZhl_98W(6tz9kK%{4ut3l zVWb#3;;9fW)l1^g5yln6@~o*M4ol*oB!*RSfPqp-%+SDo+VK}C?s*L`X;M9UdzW#xX9K(uA`MD=@JH*-@JJ=9ffpzD;ikbN!m z%lP{D^_7qA-%XWH@2>@zdw*4>k4!SYfBhOhy`5yD`wAsKQtz|(?_*ozhcQh!0?VcG zepc)Ca1hh$)v#>(5;7s{a?x3oZCR1+(mA;#m*sTv*sNkkU(#s&5eDcT7z4jY!9aqN z9{dmzD_{WmL(D^0#Qt-jMDOlRMx3P9-trG^FPdZmLJ;67e5tzDXGbebEwV|~uR?cA(XO%uyOmtQy z!A^`~kpe=>^!E~ogdUxRo3$c{Xe|iM7LJk;+IH0wla-*|S-a@lpaU}Q^cl>|++m7M z%2DD6sh+1(xEid64#Jv#lZq9s(n(|(J2ra-&3XoFH zm7B;tS8XeTfed)~znq4d#{icI?n2OD#{#ZH6I|QM++D5I%y%I9)1l}){RJ{Wm6>z1`mM3jcy0CE`HraL8=I zB!fYu@}dUejCH-Z6e0_&V6c1~-#{{0pE-Mcy*Z%0{BYDY*pEhVlcYZ}<;Xlx8(_ z@mTK+N-Ie;8O0l65UAK|(m_}D{CJ=Oy?`yUY7nO5$lr%Pkh#%UDZ54)L9VzHBaiS( zJt<*Ukbfax2P@4ZpSDljYlaQNg^RR;l>QbOu{b`K&QSpAfKW;#Jb(g%##56GL8Hr! zuojNcSICUS>~z4ru=W8{4qb5o<5Q)Phky?325^B!5SJqcSdAPLjIijS68z5sC*>^$ zfPM|<(yt<$zV`wa^ZO?JQW1G|PViN?X`hOiBrAt;pq^wUojmp$@H_gCAUya9C+Ucp zNdJ(wWGhjz&wiO2NUgnEtR8>nM-%m8YWf7@eu88L;are!=0+dH^fC+Ld6dpjPQs&& zO0>WQ;N7AeB7p$%vbE-TI~WTqhuj6U4j$wKHHK>Ds)~vgf%W{X*Z<^i5@J~W*?g0 zu2Q&^hlo%>AKH#IZ@|cm_16 zEe;S?vGYb;%b%w%9uloD(-HW|Y^B8&y3;FSxXd?wl}>LrmtXu`++!E2ZPjJ^UhZgz z!Mh!+7&CX94BKmsPX(fjZA6=Xk~uM7gKYF26-iyRO0vgwAEMk=FGtsOiWu zULi#1Nlf2lMabFhd7{lKt143F$c+6j$EbjLF{kTjVszHm(~mJJj?sOM8NzF5HA=oz zcaq28XE4M{GJ&6Y3N_>rg&##Wq9|ddtbM``=(o}4HNoxlj%47x77;yB4%ga6jS0xB z`{S{S1MJPQvRBz&*W{Bnw{K6umy&C+Y6UCoBBdWA6VB_*j%^N!+Rn0U!Sptc zUv{X3qs?=P`2;chcdu#H0nR$hKJfNziD@=e6nS@oW;<1ilRxA34Df%zURdGdHS zG|((kfWis0s*-x8&sFL9TZG`kKl<9xb1|m(1Q065B9{K}})<2@`$CPo5LH+_Cgmp{P(#PO;M4%s{<0?|x zK!!c)twyWcay7NX?JwWn-!>ocQ?h%SH4smY@!JQuK@)84Q_ycnS$VwQn}innv>Hd# bywGVo!&9~~(q;0&dHW@(;Jj>=7C-zCjDCVF diff --git a/containers/__pycache__/Main.cpython-312.pyc b/containers/__pycache__/Main.cpython-312.pyc deleted file mode 100644 index 667fe74e284c72990ed369e8342bc9b7a69feefd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23118 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 diff --git a/containers/__pycache__/ResultViewer.cpython-35.pyc b/containers/__pycache__/ResultViewer.cpython-35.pyc deleted file mode 100644 index f0469152ba95804aab8f098dce20ed00f9741014..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9302 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 diff --git a/containers/__pycache__/Room.cpython-312.pyc b/containers/__pycache__/Room.cpython-312.pyc deleted file mode 100644 index c9505a114c19b0a89618e06e7f91793704b8c888..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10306 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 qH-+J0XB1e_(`Gz|aa9U%ZWXqn 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 diff --git a/containers/__pycache__/Share.cpython-312.pyc b/containers/__pycache__/Share.cpython-312.pyc deleted file mode 100644 index 3297388258c8aa3cbee1b2e830f08289b487482e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8324 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 Ab^rhX diff --git a/containers/__pycache__/Subject.cpython-312.pyc b/containers/__pycache__/Subject.cpython-312.pyc deleted file mode 100644 index f4d3dba400174ab122f8bfb932431cdd1ffcd115..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15405 zcmcIrYj6`+mTtXUR_kHQHu6(4Heg|1#=J=Y2lFr(gTW31A;k!{FcPxlbhiO}8n&i(H(OgZ%hvuF8fm7zy`I`sZT3h0@!Fc*`L*ZV z)>TVFwjr6h3AgX_+=uQx=R4D;eg$FhhemlX(6^NK7$2!y97E zpy8}x(0JB3XgX^$V3{#y9<-dblC&vi8)VPgN!lDMIa^|64l%st2E$wL8#QWYSyE<$ zGB#W07%>O!-(rKHNwxP#rz8A8SQ1rBk924_qFQ^T{Rtr)G^lJxND5sDiI}#X8om$> z_e%$zmw%vmFExWSw?@kWTvya{3pZ-&?!w&C>dXDFOyN321c zV1sNwC4^O`%)jURpmd5!8j{R;EGI$2S`wmk$7lh3Dd}t2C);w&DA{SFDES3wPW$Hd zveLRSQ_>W5)13ZI8t)sloPmKB9=(R9qF$QPzq}!@SGit8Q_J=;2%aPpT|wLHUpjx7 z4->7@%V{d7-W08-rTRBotEXuy>Zd9F3)BO8j;8X~wUUp z*U(b^tFL#22^zb5gXO9*!V7pFR9jC+Bos>ws8&AnJrNSZaY?oJMb6WzA+5+JhNa=5 zzKF^SAwH7m3iqoeP_+M2xc_pP&y=1Ciz<6D5{n&72!pDJbm@$Xk}%vaB?M8mUy$Ml zBk_oMNwxLIBBZCSKM{|^Wm2sdwHj=+KNRl|$5cyyEFp$fbNE`gKWJ9XVmNkDz(Xr= z7~z2w@#F^}{PB4Iu5*22SP;)0fdS&ffn(>64U3WfbM3K#gbWV zyHaLX&TL7u%`cbyyTdupd2St>ICk^+Jj*F;oy^vySwFN?Sf9-L6gD8U0flXr+2+~u zpVi!}NwZs*s8xcy$J7G%* z^o)%el7^^7E6a_u^~R(ziY%@m@W7#>xTOVQz(Dyl+-76cQBV!pEM*gn>|DH_a0A!N z^{>jYqzc+M39KC13cYvqyXXj&w5R?p#@+HpFum3YKAkd6EjxnwwMHn$CyVg)yfs)B z8NtL`u|`-8zj?7=qr_(%+#K78Qhfk1>0ycyUlAm{iN z8OgUKh3w^9VlE>GLl-is_V`H9EYx9@8AY1Vf=R0o7KdX}R!Rx=P%0qe(S-^X zn0V~O5NyzOX2D&mxc#!*pK>>ho99a_rfP22d|WqfMV1Z1W1c%d?<~D_dgAnW=L?I; zUh;%x%6wD)+x}GPN^Hg5Dw!y`$zcLGe6ED}!aMu+T>HH<_v_Q_j%$w-Xzah=;%+~7?rg;A~GP_1$H_GhBUzp|&K4|^2^XINKyLaAEI@$2yPLy9q zCypvyK;{Ap*CKN*vmL+XTEC{{ewp(t+*+AiJG&*#Z6e(!c1~L!JL(qeJMZ*Pwojay zUiH}NU#v}*e!;jx0Jb_$-XSI?^6q^&k$|(AC=?WiVzQ5*>#R&1Ge}waR!pK%c}03< zCFK~(#Uj#c0Q8=}&Be-wWihxRiifix@J8OGOHwJzxuZppH=Q9t{7c~LF>}&f3}5qR zoi9TRyp;tZJA!3^8MDGp7vcEA=|!kpinq^23R0F2OAT~r-g<+P8fh+Cgu}vkOQ7ch znVX$&@ z0nyt!x}J8)X|%Yc&f|>86_H~+N0^zb2_&-^_!M)`(0$LKnj&%Oo`DEv5f4y+NV`9> zZ^S}_7x>Vg(X~{MD%1=&yb(+EhhpL$NN8UBm4K=z=p65?PW zBkCm~9Hx4lYQ~%Z44hHRdQM59I3E)DPANQi45T|~lY`__1%n?3g>V#=zS!Y#hz|>0 zp$p*{=&n$uwRJ;ken-4YC30O@hl6O~BNU5iSi~HQhyXJNLqn=L zDgtDbK16!1n9c%nMlL4!7^D2@6S`<;>5h<^`f1N7z^|J~hpb}Kb) za!uPKwhfeH`((#L-Abiyt6aA=Rk!^SyB!KkCi~`Dr@|t_c-*`{&2}ItaZWfV!)dk_ z(h6HEv$fMbGv+kAYB}KaXvL8O^Vrb^q!-oG}o|D6Hsb4$Tb^MHJiq}<~g6jt&+J_GkltBA-UBuxB6?ZZ@TpMjz|7h+1vWU z#FVa>vfs8Vo+jDTqV}w+Y6i7>3UMaII9${N#>en z`hetu*Qa<_%ih&L6=%23mEPO&*;vZEb-V+Bl)}}@T)~7YFByth+m;@^C1U?C1ICvfSw3N9(G>o8O07w^xD4HhHNJR;6ybQ2HjQ`o_n=W?%{XKs+`sPvCnPM>ZerCV$_XNmikkD>N0&j#p zd_|)%r9y#h2lMVv08TANA#1RqV=-Vt;w`lIQl?`mYfyP*12JlK1%asehMT9rFx5~{ z1=&T`U3}KY?5wjYgHAEKFImWT^CR77 zAZbxdh1mIWFP$oZ%m+2|68Z%Ow8mfWB~Vd7wNAhvLN$fJMpH+SqkyXizzBvRVKX*B zWTILw0%8Mv6%oPmFNFuff@%>$arh#30z*&Y>i)zqI7rM9K$U6<0bDvb6MB(SA4aFK zy;Z|uLK~KNvBVw`GkA>{kp$cgp&M%~{P5tAsDUlhP+~}R0z3-~QU*zB4iD6(gC!cI zJA=JUFeBkzOo7b_ELav|s8by|COXxgHPOL(!9=H;d2nSCY)zqCKtt*RTA)T<6ufEv zm>wt-yFfGnWOI9O{b=GxihGUhUZc3z$?kP&_l9||Z_$dcJ>^r5+YZGOls!SkvqAQ3 zNP9LdxXUMdr{1~!j#9BfuGpaAlvKsmlzZEQ(#P&yOVyV>cJE#&ubOVU+j6Hxscw_2 z+mz}Za`lc>^{!O;?g#yHdAs60CVP*iy~hDC%~$%y9RPQxOQ$>T9=UTwsof~oZcNp- zro5YyBa=T$Au6mOg`Qi7CJsF*wR=j&%}>g4 zkyk&wik7&;6NhgeA;7#^W~-;cs};!F5vydj>bGpo%Lo#+Hi96ZK_XYpEM|10cYk?@ zlWqvn)m7erNJ#L4VxDz{!=Rafn1sq(0~0S>q!ma;y%orK2koza=`4Y(E#sU54rcED z)&^ZiNBT~5wD%s+P3Wf%XhwL@r<-d&wOT47}am)py`jpc&>~_BQ3w=Jt;`a;&?9c61%% zww*t(mYhEiW(V*xLz+8({=MN)Osf&lOi4Te0-`>`dsR*ZO+V5<7?v(2cmWr7PcwUH zE5#E+-iTmAL>t5n=9$rLseHDw(z5y4rh3b^XZs96OYM`l4UDzysnKPrcy6L8GCS>w z3G~c{3~pqeH$lbn13B)qZ>^EWodrh->z`Agh^Q zaEFA07$KMt4rA1b(GiGL8y^veVxbW@>*zz$EjIaQ9S_Z@6L)_DeT#4lio~}e0s&p_ zLo>?KMiiAh_`+laml3g5EM`c-GtEtKAGuy;)rheOtDc5q_+#eBrBlpAaX5{w3IcCf zr0r6w4WJJU21aM+OLaoeSoJ*zJtWoh?iWUXG zAC`ic@X|i|m(Ci*hzYz1CgMdf>%R7AkrxIMA~_P0X5N4qItu-QDrG6=oyqmzEIkHL z&hznu7sUF#DU!DV**V&hw(m{RhO3X_ohk@)U$dj3U!{n@DsM;d{*j>jmUO=o&w`g} z6>Sk+O;h?8_ROC5Yh+F~okKA%l0MQzX|zSBMN@_AptR_B%&seax~j$72ng!ri~28e zd}xhyobl3&2HtT4{1&`{w^e814;_bod2STC=qIrF=%Xe2nZ)+I6XUUx_>Q9OHOSWd znzMD`Y$;5m^P^uF%gDRON|rh0CE50lq+{9hfufv*Vz-k1Qe#|_TaMBqToTpPf&hxW zm8k2EBsXBCvjtw+MjJ-6{yAEb^K#0W)2@i>&3lqgx`Sh`q^qbmZ?{gDrYPUJXc%YU z+?3wPQSz4=u`FjqchdbGNAxZ-ViAuajF$mHW1gg^n70m2Jo)cF3ULU)i#^eHEu9-D zU6j(IE!=tw_>JGn?X9Jw=&UISa9$8J6a;#n^!+k`e8_ka%ex8u7~Mu)f8Z@dl|l0v zYOi(H1#-Z9{?i@dO&Cmbwh71rgeHjcZ2lGssNIjPPCAUl{NdGwUcOwtWelQ0_I5bZRB0QVM zr*Y=X;So`|f)(ayA`%yVfDLhp@COVB1yDp)N6(32@zPtvk_2iAKI;+C$pOWO-%4ET z3XLR&CGY{02X_)We~*QP0k|NlJ;d|c-$W3NM0G)%&Nv^wrWLA|2xfw1n$nVWE(<$w zh<7l;+bhH|LOZ1(K!nq$kHX=ZL(WaahkC*pZ1)$~&VCUmk7rl4!K-kRz~|xG!B8Ef zTARHv0Ubnqr}slJ4CIA<+NHh$b)#G^zqv!Yz&`ySs7{&=uf49G4$YK*Uj1pc(y&Et z*ph14mS(pv?^!;cW>3t6PgZ}0N8ajbF6V`+y6KB|6L%7+`i-foP2;Z2fbd4IqUJf% zV&C(Mj$-P$of)3(`Se=KyQ$D?oAvF!YKza`|MdOTn(Zm?j+aQ)_`&o2m-}Vk+AlhO zcI4iXx#0&rUtUYC+m|YDPkG)_JjZ3v@rCjg(=Nr=BKulWzV)f{4d4wgEqiV<*Sf~L zUX(B%@8laPcVMRVvAgN(a^FX?I)*F4ST-g9`-zZ@6o=VRNcvx?-X>bs06)q zMg3EosiOV`%dDvWq;Wcys&1JL$<-TEm7AX0%@wWS&W0uqOGW)t@Phkac$l(^$#d}Z zai-^S>FW80Ri9UVTD4H_`^1~7+x4I;Rn?g)KY~8`vfF64S=lt{TB!Cb)$8Tz^|SF* z^_$~IiAA?j<{D=Xq`9@(JxqC<3pWK#oL~#p9y89YoZ)9X=9(TjzUqC{a3swgUGOz1 zzGm6iobs(5?_8+#E0ryBWy|crxz1GOp7BHToEM$y3WtNu^}$ogAEcYQ(%do9alPzY zKYQtcJ>`3Ayb~;~3Rfp{b=qS9ZS&KsPo%k?h3ZD7dLwMfoE;3`ndy`FldZF%xzf4z zG`Ec`sX^u%X4b%x^jt8_t;0ohPIP9T1oVD>_S3VUotxYFJMPV=rwwozg#g@*mjni~ zl;^u3$~DmHA_6cE6U8b zqd2m~*+kwSMHM$LENh-vW~QF(VA(_zIc7ol4phnuNI-TJj6->AMyXQ}=)u6pro4%G z%rEJRV=?c0wg)~x#dA{-vh`@*$SUi4Bi@`eX|4) z(So4YkD%qy(mmSJE`$RhWx=kVNn8!ZrGS)x*Yt==0@9_37$6U>_Kv#X+55$aFc{F} zT!h&N+u6_o5Awk=u=umRpjVUmj-F#-Q49@)L9~ZJu@GUr>Ew zSA57j72jsrw^{M+l6~4=IFZ^%z5{9YAT(9jdYP?%%%nw@KzU zDclyB+p^$Vp|~1lSEJ(EEW0)r<1#x$T81^WMH{s`hs6$Mx{s9$vZkeYkhQ zTcLOxWp883y9$IxMHRX@KYn-oVD?qnp0CQjGN-u%$bI2G{LNz-S#lFze0gqlO>}+K z{lv*|ntQAp+#}au#li?iXdTg92DqsN9tpTh0_rq`TWdS_K4vjO_9^0>Ll*&SS@EoV zi)GKVn89dS@tpNov@uA_Ag5YRjPyv`$nnweD6&EDZzl$a;BPAc58}Hn?blWOZ$I|f9a?I diff --git a/containers/__pycache__/Subject.cpython-35.pyc b/containers/__pycache__/Subject.cpython-35.pyc deleted file mode 100644 index b7ceb36e832a71adb5d4d719eec4ae26667beca2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7653 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 diff --git a/py_ui/__pycache__/Generate.cpython-312.pyc b/py_ui/__pycache__/Generate.cpython-312.pyc deleted file mode 100644 index 72e46e0eb202b2bf19e471454f937a37729a327c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11596 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 F{uh$O5<&m~ diff --git a/py_ui/__pycache__/Instructor.cpython-35.pyc b/py_ui/__pycache__/Instructor.cpython-35.pyc deleted file mode 100644 index 62aba286341a70879c8e6afd8407c95632faac2a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2499 zcmaJ@%~Bgj5T4b)kOTj?fJ4U0dcFF9> zMie=bQ!aUqJVx%h=#&)XS~3!fn8*Nfpyx&8_;F# zye`>lJCa-%ZM8cTx@xP}!aw6G?&5;v$-!U)zIY7?XJ`owgC(#HM!*8t10#Tq;{x-G zV5Fq0N5Xw3ydXO3A_P8p_)73?!xuk=*_Flmw25nrSvVm`0K3jHOXXNU&kXGsl0gw= zKj+vLNK0sxRAExiPAUXlW!H@LCy*uvYN(h@>P$6Qe-gK0Y$k%K{}N1-pvn3(DM$-9 zjEd;#1GEd1E5_W1Nc#_IhoyAIEP8|DITFvY{s*+RdDj2XV1g2GAuQ!o>7xwn0_iQ# zib_`F!R`NQ3ha<)-4hM#0Dd8Od5d2TkQ-$)`KMiSR#Ph`v6M>Q2!qf zmI+{)02=QDEE52vCEda}ke`s=9BE**Kh5lFg=8y)IhA5U^v$kTQl-z51gw(ADrroo z;>Q`xHCnMoE1D@LXc)}3dzIRx)F!2Il|Xn?rFMz~zL^cJrmQDp;}+KC=dAxlGKUk_ zX}9)u$($(hCmbo!1|lsuOFMem@4G&Hz@RWBN@J_eK{b9iMbT5+PG742{t9q)!9TAGSr*XLL zgnb%L0HpHM;}jgD4Q)kyAa8{0*0q`%d{401bu%=K(0c zNG)}g4{J|W!tDYlbt&*!A-sAo$^3d5vuC>zPYHKs=YVPrmTTTLc3scGFg<=f_;b? zJQn<&oJLvAesSwv({K)kac^s=R20e?1Zg3=0a2G;7zdu>M*{R-apjqm>X~j7hLGD% z5UF@;gw+Hsr4aMrjl?@%&I0+JN$eW`Y;AvYaujnJpFH=WI8L7N_(v6;pX_eJ>vo_3 zyBtPTWbW~oC+8z~C{A8tV1`{4$@TM*Ek-g~HBaBX)q?*s zz@4&Yf#PWK9@-*a3s#vm$-I?oSeMPTZ>^6l-sxXhzT4=+uRs)>Z0K61A;BPz-Np1p z=u*kmT44QRBB0im2uc|NG_qTbaz;Q6FVU!E1kh8A23-#2eG0ptxQ&`FU{)@tHs5+8 zz!F%ZW9^j8X?05Dqgpj3KW*c$fz9)CIFz0eQK+kF_Nnk+i_nkW9SRk2Q;C?8Lw=!5 z-KBNY&dbLToUuP{3PQDDNE_uVK)!`9#RrWcm$s@iG?W1ZV^UkGR9oit@^q|&OZERDISb$^%aFf;^jw| bl`chei_xn40CnX% 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 diff --git a/py_ui/__pycache__/Main.cpython-35.pyc b/py_ui/__pycache__/Main.cpython-35.pyc deleted file mode 100644 index 0f6cdc5a2e37ce56b4dc7d96fa9a09a031823be7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17967 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 TgF61TiQ^lpkvw{vZb$zMATdhd diff --git a/py_ui/__pycache__/Room.cpython-312.pyc b/py_ui/__pycache__/Room.cpython-312.pyc deleted file mode 100644 index db686a60e1fafde6a43ecc4da59406f0c11c02ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5531 zcmbtY%}*Rh7Vn-f3d{_Kgz#Y)28_YOX9xjo<6s*S+iTfuCN}wCkw(LG8+z0;O}cv= z4`QVpe6XdJoLg)u(&Ce`h?LpWvWH~Q!~U*Y&q>xPgP_-}_elv618cfgeZSy@Z_D)j4s#?}vhs>kYE ze1-s42nqadd6dTzWp674U?zfpw~Xt^kO))=>DZRjGKf&LuSBS_c8tmp>Q#{RFwxFL z2u1rXZ-!f3((`VM%N(aNgknZ0Kz**T)IxM6Z0MG$Po4ofqmSx59?FR^2D z@-Pw`UqJAy7wUJ*JCf%ryzghARD1s#kpT1oLerk^-rK(*i4Ve>#;~lHW7T!qf3B~ldnQ3Q^=+M3CO+0kL(Q>2RM z{BN&&iHBf+p3t;sdi@%;^^3e_;8!92|9hITmQ_ga(HRhmRx5ByhRA5t9rwU45w;R?}NpR^nZ-+Kgs+iO5I(b!I zOl3tCRJa$oXs{b)DJQ-sNID+3(VD8{H|CYQcFVe=N}EbfCy>dvY^0_HNx3ej36)xX zfsyR6o?4Z~o9T5?$jhRAyjIt)U)6J$rJSU#JLEztmloytDLbr*`fpb=V%jwyQbkSL z6zvEM-vIG!K6?|MRX;WoOkmpOrS5t>TqfAZ5+8!o?tE2TroqS+F9IqqN$q9;#Rv;Z zPSe$tgyWGYhbvOUh}^7l080DosZ~){aZPI1rv$;R?4icLUJjqy(b3 zw8N?hlgVjvN*9+Tkh&r2DL15cOIpe0AhtJUMc3vFc!lFWJD`d3Z56&AI1MjeEcWx_ z!nu_tO;oj&Yp_DOeC)=`jl3qMSFVUT5q8xjc?~v$zMfsmNwCi}NiQtODNQ2_uC8np zl6h(614YS>Z4~S}h;)8qN!o1ozG247LpXriI;`jC+z%*Xp)Lb;J^I*01Mu`P{2=^A z`q89`dK_N2fx5rC{YUw+yfaz!??>M@(bSQQQgqOYP8!k4;^qD5?EQd=PW*rxEp);_ zCoB{;?WB{!4hj z?=m(AF$Qxz2I{fUsDVbGkIkEC!ND6d+Q*8*pR<3;n(gnhF)NgDYfipIi6$x(oka|M6M2Rg^4I7x{GK%iW+5Oy;x)vx zd^ByMz7l?;+&SYF-MRfenmT|Nj;p#s!1)Iss0VPR0XGOb7I0by9|tup6Q~)0$KU(l zPQkkypnM;<1=kpYkK8L%Wkv5BoyuqMv0T&27~b7P6^8dMO_ehE*sW=0i~!RQR-QlF zk029+aZB)$xrCS)jLP^W7@dUp4y0oz&Lk*%!O3tqLvXYarKaz5S^4Tp( zmqj;;;v8{HysNu;65%I@>19OK%W-kP`X)@%^|K-A0c&^{$6_&c0&_>YR_nCUI(@&vODT^tJMG2k{U}Zo_{DaPbDW?aFYln@zgO=SIbNd%iay@lISu)y2fvCQ1D_fW)Y<*$J0_Yt%s9Uvy=bCKnBg2A9@N$S9-?uW z@jaSTCt(VU@t}>8$sACO^%mWS67jFI*=o&p1cV4HJHERs4rv zCJm?Kd)&W#L&52Tk9icl;7VftVmxFA-!CNeX=jO5d=RKku@zFBip@b$akWd~e@5qB oZ|2miz`zxzhQI3n>F0U=KP?NB{r; diff --git a/py_ui/__pycache__/Room.cpython-35.pyc b/py_ui/__pycache__/Room.cpython-35.pyc deleted file mode 100644 index 468d8eff2a2fdde25cc3e3af0a656feee55078d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2395 zcmZ`*OLOBy5FS~U-*)^+vI!(4JgUI3>|v{*3TlhmO?C-~Y*@ufw#wxym23^k7+Er- z5gVt%Df}0T|Gwuo0GgT8eOx}y9NIVOS zlw|dkInSBvhvyT7zz_bG;N6EeGEG9R4Kh`mxG{)<3k3;aHwC>e5Mh!jV5;2!H5Ih( zV~7%&mJt-Bt_g7}I8H0d27~}?phT72fMsCU6uU;Ib%OK;nKm^(C;=55vofVt4t7Q9 zttg37UZb5byfVS3g3pbmt#)z%T_x950N@SoU7OSZ-KBO8pqB$!RRF6BpqBZ#mQa)3 zudC&{5~^oH5AF(WsO5$dYGkf}l6Ga||MWJM-lo!9MlI9Z%%C8U8fsPTs+9{%ayV}( zsO2`^&TVu{@wSwil?)S3RAX*s?yaSVx~(*}l}0;bzmvn%$;hKTFn-LY?j;C~@ z&6hZh*cFv6Aio6hSv(uSnkyrgjdRU&FEd^d9jM!9;I!T)FKfy{wr^fRN(Vp@VLuEa z!Ce*zS+@1Q^z1?u*zIJ!vmdPrVHa+6bVK8So*&{GCd zFR5^K2xWH?1_8u!;D;jGTi}WI3$hqd|2vM&^H;(@fuFyh?0-2rjVO;sFFZJh(Q_Jo zFT(lg;2Av5AdLBh!c3i~bM|;NUpO%v9f#rU(R?Ax5XX3a%5ZzpF$~0L8f{|}zFqiT zG1g(k*-ma;gEhXrWZZ!n%Je{9OQ-8zp=n%ovK!!0VlBG~p!X9zb9EE^1``1d5c+?C z{8Yf|n407|y4-!Q(wNi$Z^;Ear4rhB^~5r^6bgV#r+)@`WrVMN~>EsG&=v zZR2hHY(Dp)@C6G4SKCO@H60~& TAE2x}(SCe|9U#K~vt|AR9(@sL diff --git a/py_ui/__pycache__/Section.cpython-312.pyc b/py_ui/__pycache__/Section.cpython-312.pyc deleted file mode 100644 index 2d9dd530ed73415e3dd28bc1a03e8dedfcf179f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6721 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 diff --git a/py_ui/__pycache__/Section.cpython-35.pyc b/py_ui/__pycache__/Section.cpython-35.pyc deleted file mode 100644 index bd0be6ab960bca9df6f44d2bb750e3b0ad65e8ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2799 zcmZ`*OLH4V5T4c3dRej@D{*4-A_R+ofmA_J6a^$s;v5o_jqIdK<*Kc*txZ<>i={XWwB+p78=Zfx5`N0_$~) zr|@OnyeippGZI`CZMik}RmGN1eeZzFct8WvUk;rw@y6?DI3p$yg9+Rq0R#9z0&MCR zm{$ZzNmX`z=Z^0N(ZPTq=tuuccsKFJodRR8EH>1WII);Tf`$axNzTYQCi83vOgvgk z17(p7OXLgT6=P1B+F_Xu7l=E1P71&X(O=9M!K$naRm zJR0l-v4eS04_{=%rjE0fl7p|xz@JiL1ORHYGGYZs`cSONv=HGU4J7;}jlaZ(ZAR8* zHawGIKx^g;3_a^~zA%6cF(#>6Nu%v(w9X9L*$fR@IB8-X$hl-@Ng%6QT-Ae`vrgv| zgJ`5`+n8&!N#fuuF{W``)4X~WR5C&}kB;=Cz z>u3+k}VMgiMZ<{_1|QGp2=`7(eBhe^eijN{FDj%!-HHqU_t zm~y}d%yStB;x?GqGR(KqwY;v;u4|9g%>4E|<+>Kv^`P?^ESwDN`v3WLwO?2JU3lHE zo2jzQUe8oGEALFBNDrVPoF0H1$(gh0c)!br@1-(IORu}OtxBeJ_`jiM_+4uLKqD+v z4%PaG3+WHs;DI}d#?raDqpI;hL_u&%aM%BtM*odQottV+W!sEG$wL{RRtRTt9!FIV zgzp(lRSx!pZFj^^HDf*SLw?uuC8<yg%dv8T)_2 zPc@{wAMhTAd*gts_F*LaV}vk`TvhgEc+U_0_)vE@-EhEz?uKf_Tz;joG-XNf*gxiK z5$cB+J{pgDkOlFhe(OH!DN{B3$?fQ+nS>~lrVW>L-Va@I;D>R)3SIBW9r)ovzh?Kc z+=&Hv^vT2I>oKv?9QtM3Xar@hU&Dwk9*wvZlYY^Dj46v6ku4E00s~m2DGE z|4fg|JN%hD4k(_~T(h^btcyBfEMnZu9C1xOaQAs28f2`vo@XM#ef1z&6@hCKCVP|C z1=AO;bZD}g6?+GZ^Tg*b#4=3%Cc?bWU5|_VzUT2!RqY*`rXF#IoNM;|X&zUM=FvDl zygimO3PlGRah9MefJy>t2;{>JX4Rfu`; zOwg710~7D#-#=e$e!90Ca}n>|^{^B6?(q1zjE?rUZsBoy(O3*PdU{VePj2oVO`Ng6 z*8{R2g&Ri`RYpAHqg|h}6{DUoW;LvqwQ9BTw(!^1ZPU7{wJTOf>znxBvR3e3nroLK zt!a<6w`?_&k)&x^%jPfFu#T6qD}N)2BD?zY2!uAMzWTpMN1}-0!q2g9b9DBHdG^YD zQs7#jmc#-Z7E=SXQ$uOSkbM|XA;xDw=79@%>aj3mz{h|w=yFrq)=QuYv?|ASI@p)} z@bcp*8mUrpI7`XNte7L$vgym|*3nUbIz*{gm2BztA${tHUi4zemjO2$m)2#6zm$4! zPWMkYFE)@36F}9;K=f`f%?D(^f#xpWn2rdu>U!B$v2@30r%9jNf7{)nT5y~Yb8;M2 zb(~Q|RS5mM<9t1K17i^%0#C!wP|{Wunzx7^QO2}*b*uh~Ak8+u?~0Emw){w^L(u99 cU4KfEE?Roje*vn6&rBSjQz40|ey!#I1?JsxGXMYp diff --git a/py_ui/__pycache__/Share.cpython-312.pyc b/py_ui/__pycache__/Share.cpython-312.pyc deleted file mode 100644 index 0f38fcf255da5eb71dc400ee599b79928189fa1d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2981 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 SzkM;6YvxPee>j|)%Krm-uZ)HO diff --git a/py_ui/__pycache__/Subject.cpython-35.pyc b/py_ui/__pycache__/Subject.cpython-35.pyc deleted file mode 100644 index f87294e731ea78aee9223ebd07630fd68fa9e4e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3859 zcmaJ^OH&(15T4ch2}0swY+|sDZDc#ff!L`^xndr+;b0RK0j^L~REu_uRu)=ic4S+W zb0R+@e;}30kH|fjT<4k-e<8V~yJvT`AQ4I1n(4>a^XTd6oy_MmzyI;q{%@0v{mnw3 z7_?X5ai0LO;AgNFW5)*DH`sB6?MK*gly~~0E9F21dhQI_y#B70sMgzz{Ylr zS#fZZQ0ZN}_S`mG&QTp9@Dqh60na)-?!R%yJ{hb@lQ=b)fgOSbu+xa{N0^MVCScNR zfa@#9hY4hYHIoPmTAvuJrI0pL39KZuQr_=0uDyl<#z=3B0AMsYckNOGj4=erTmUGBMo=Pv5&>if z0ZIgr`yYUD0vIQNbCcF17$*RK7XB0_LL-=@C7beS^Gd$~oAgtJeTuN=G@{V#pmR0c zxkm0MS#t*WqWKw8e;I nC|1*ohJ9<2KEDwjjq%oTKg>&15uCx^Z6VCUtL;QXxPF zBR$=lm)YGSyIW*8HfVP%U_rQOs7YoOY4KqHi)`4+%@gK4VU_~NdRFt;$64JbrQ4)5 z9w_Nq1xj~F=?*DP1VaHMJ(N3_+1(|(yJR;xXm|HAy9KgaAiJqSyM=%itj0X8h7QF3 zYJ?-XOqgZDyfO$-rWn2$h+%+x1aOZ4rUwD;5x~Wx5I&6e3E(~fTpa|s@0}ujp#2RE z13Vyr2Ly0!5a0m;gikXbc1TK}lU;@^Ft8tnj@Kf|76}v1h?gP2NN??8U^MF|vqxm{ zh%DeddAaV35atqTERn|b023@U=F(83WinbOBk<)7BrsYISiyuI1*|VU=LY8R$E^9p z@5B93EzfPKguWl_KjDI~%Rtn~doHA1H(RgFp3{{ob0lobYv)>ao4>GZxn&-6VZa@7 zhD7Ck{-)Cv?pX|Zsn%gjcca)%LKm$N&*^s7oR767RctuIK5^R8_XfO_FfH5pp1UeZ ztu5yaFE5qy?S@z_dseIMp4WQC>we2TBWVC?U${wteUU`wkCCFAbg1rzap6n>A8B z=MajESKjW4G}@+3%hJ_`$YMVMhKIZ*^3V~Zqyhf)UWo$svozXmr)AfBD!ncETP_5* z)HsY{GuX*0tedPiR1vs)UM%@M9PcK#j~eo&Bfz z<{!j$l+U6(TiNcq4bR6MvTqJ{J+ijVW@7kdCnoCpfy(-q7b{m4A+H$13*2CC` zf-mOs)?0xUn0O52S0+~A@1JMuUmxtcT(}1>EQq25h{Jc%=^SjV!mn0^Q&s2CqG+t` zEgf`vwXS_o?NXRM?DSL;mZ{s>wQ=*@Uw|+pZxoDa_!i-R)R+W{t=XaUI%wyO8ITu@ z3GXRUtK?Z+6Uc`d#mV`r@gS3VLs?<|Gj&Ja) KaPh91iT(#Zqe86! diff --git a/settings.json b/settings.json index 082a7e8..62f731f 100644 --- a/settings.json +++ b/settings.json @@ -1,22 +1 @@ -{ - "maximum_generations": 50, - "minimum_population": 50, - "elite_percent": 0.05, - "ending_time": 35, - "generation_tolerance": 1500, - "deviation_tolerance": 52, - "lunchbreak": true, - "starting_time": 12, - "evaluation_matrix": { - "instructor_load": 0, - "idle_time": 50, - "instructor_rest": 0, - "student_rest": 0, - "lunch_break": 10, - "meeting_pattern": 0, - "subject_placement": 40 - }, - "mutation_rate_adjustment_trigger": 0.08, - "maximum_population": 100, - "maximum_fitness": 100 -} \ No newline at end of file +{"maximum_generations": 50, "minimum_population": 50, "elite_percent": 0.05, "ending_time": 35, "generation_tolerance": 1500, "deviation_tolerance": 52, "lunchbreak": true, "starting_time": 12, "evaluation_matrix": {"instructor_load": 0, "idle_time": 50, "instructor_rest": 0, "student_rest": 0, "lunch_break": 10, "meeting_pattern": 0, "subject_placement": 40}, "mutation_rate_adjustment_trigger": 0.08, "maximum_population": 100, "maximum_fitness": 100} \ No newline at end of file From ec2a7137c5e749836f914e47236a97cde237a786 Mon Sep 17 00:00:00 2001 From: Jishnu M <83004520+mjishnu@users.noreply.github.com> Date: Wed, 29 May 2024 18:42:15 +0530 Subject: [PATCH 3/4] add requirement.txt --- requirements.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..049a4e4 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +psutil +numpy +pyqt6 \ No newline at end of file From 382dcd755e80c0f987f4359dbbd509bcbf949a08 Mon Sep 17 00:00:00 2001 From: Jishnu M <83004520+mjishnu@users.noreply.github.com> Date: Wed, 29 May 2024 18:44:14 +0530 Subject: [PATCH 4/4] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a7584aa..58b7252 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ A research on creation of metaheuristic university class timetable scheduling so ### Installation: 1. Clone repository. -3. Ensure all dependencies are installed. +3. Run `pip install -r requirements.txt` 2. Run `python main.py` on project directory. ### Usage: