diff --git a/README.md b/README.md index 902edf1..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: @@ -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..b2bb589 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,25 @@ 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: - meetingPattern = np.random.choice(meetingPatterns) + if (hours / 3) % 0.5 == 0 and (hours / 2) % 0.5 == 0: + index = np.random.randint(len(meetingPatterns)) + meetingPattern = meetingPatterns[index] + 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 +239,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 +257,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 +344,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 +362,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 +393,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 +416,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 +430,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 +450,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 +509,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 +523,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 +535,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 +574,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 +585,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 +646,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 +681,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 +705,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 +717,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 +740,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 +840,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 +991,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 +1004,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 +1048,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 +1080,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 +1088,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 +1106,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 +1114,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..3ec5087 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.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 + ) 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): @@ -61,12 +67,12 @@ 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.BackgroundRole: + 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.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-35.pyc b/components/__pycache__/Database.cpython-35.pyc deleted file mode 100644 index ba251a5..0000000 Binary files a/components/__pycache__/Database.cpython-35.pyc and /dev/null differ diff --git a/components/__pycache__/GeneticAlgorithm.cpython-35.pyc b/components/__pycache__/GeneticAlgorithm.cpython-35.pyc deleted file mode 100644 index a868453..0000000 Binary files a/components/__pycache__/GeneticAlgorithm.cpython-35.pyc and /dev/null differ diff --git a/components/__pycache__/ImportExportHandler.cpython-35.pyc b/components/__pycache__/ImportExportHandler.cpython-35.pyc deleted file mode 100644 index fd682b1..0000000 Binary files a/components/__pycache__/ImportExportHandler.cpython-35.pyc and /dev/null differ diff --git a/components/__pycache__/ResourceTracker.cpython-35.pyc b/components/__pycache__/ResourceTracker.cpython-35.pyc deleted file mode 100644 index d139790..0000000 Binary files a/components/__pycache__/ResourceTracker.cpython-35.pyc and /dev/null differ diff --git a/components/__pycache__/ScenarioComposer.cpython-35.pyc b/components/__pycache__/ScenarioComposer.cpython-35.pyc deleted file mode 100644 index 5b26623..0000000 Binary files a/components/__pycache__/ScenarioComposer.cpython-35.pyc and /dev/null differ diff --git a/components/__pycache__/ScheduleParser.cpython-35.pyc b/components/__pycache__/ScheduleParser.cpython-35.pyc deleted file mode 100644 index eec7b9d..0000000 Binary files a/components/__pycache__/ScheduleParser.cpython-35.pyc and /dev/null differ diff --git a/components/__pycache__/Settings.cpython-35.pyc b/components/__pycache__/Settings.cpython-35.pyc deleted file mode 100644 index 9b63ef9..0000000 Binary files a/components/__pycache__/Settings.cpython-35.pyc and /dev/null differ diff --git a/components/__pycache__/TableModel.cpython-35.pyc b/components/__pycache__/TableModel.cpython-35.pyc deleted file mode 100644 index 8e00706..0000000 Binary files a/components/__pycache__/TableModel.cpython-35.pyc and /dev/null differ diff --git a/components/__pycache__/Timetable.cpython-35.pyc b/components/__pycache__/Timetable.cpython-35.pyc deleted file mode 100644 index 9c89eff..0000000 Binary files a/components/__pycache__/Timetable.cpython-35.pyc and /dev/null differ diff --git a/components/__pycache__/Utilities.cpython-35.pyc b/components/__pycache__/Utilities.cpython-35.pyc deleted file mode 100644 index 86bbc8f..0000000 Binary files a/components/__pycache__/Utilities.cpython-35.pyc and /dev/null differ diff --git a/containers/Generate.py b/containers/Generate.py index 95fe137..5b1ab90 100644 --- a/containers/Generate.py +++ b/containers/Generate.py @@ -1,5 +1,11 @@ -from PyQt5 import QtCore, QtWidgets -from components import Database as db, ResourceTracker, ScheduleParser, ScenarioComposer, GeneticAlgorithm +from PyQt6 import QtCore, QtWidgets +from components import ( + Database as db, + ResourceTracker, + ScheduleParser, + ScenarioComposer, + GeneticAlgorithm, +) from py_ui import Generate as Parent from sqlite3 import Binary from numpy import mean @@ -9,18 +15,15 @@ class Generate: def __init__(self): - self.totalResource = { - 'cpu': [], - 'memory': [] - } + self.totalResource = {"cpu": [], "memory": []} self.tick = 0 self.data = { - 'results': [], - 'rooms': [], - 'instructors': [], - 'sections': [], - 'sharings': [], - 'subjects': [] + "results": [], + "rooms": [], + "instructors": [], + "sections": [], + "sharings": [], + "subjects": [], } self.topChromosomes = [] self.meta = [] @@ -34,7 +37,11 @@ def __init__(self): self.parent = parent = Parent.Ui_Dialog() # Add parent to custom dialog parent.setupUi(dialog) - dialog.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.WindowTitleHint | QtCore.Qt.CustomizeWindowHint) + dialog.setWindowFlags( + QtCore.Qt.WindowType.Window + | QtCore.Qt.WindowType.WindowTitleHint + | QtCore.Qt.WindowType.CustomizeWindowHint + ) self.time = QtCore.QTime(0, 0) self.timer = QtCore.QTimer() self.timer.timeout.connect(self.updateTime) @@ -45,19 +52,21 @@ def __init__(self): parent.btnStop.clicked.connect(self.stopOperation) parent.chkPreview.clicked.connect(self.togglePreview) parent.cmbSection.clear() - for section, details in self.data['sections'].items(): + for section, details in self.data["sections"].items(): self.sectionKeys.append(section) parent.cmbSection.addItem(details[0]) parent.cmbSection.currentIndexChanged.connect(self.changePreview) self.startWorkers() - dialog.exec_() + dialog.exec() def togglePreview(self, state): self.preview = not state def togglePause(self): self.toggleState() - self.parent.btnPause.setText('Pause Generation' if self.running else 'Resume Generation') + self.parent.btnPause.setText( + "Pause Generation" if self.running else "Resume Generation" + ) def toggleState(self, state=None): self.running = (not self.running) if state is None else state @@ -76,16 +85,18 @@ def startWorkers(self): self.geneticAlgorithm.start() def updateStatus(self, status): - self.parent.lblStatus.setText('Status: {}'.format(status)) + self.parent.lblStatus.setText("Status: {}".format(status)) def updateDetails(self, details): - self.parent.boxGen.setTitle('Generation #{}'.format(details[0])) - self.parent.lblPopulation.setText('Population: {}'.format(details[1])) - self.parent.lblMutation.setText('Mutation Rate: {}%'.format(details[2])) - self.parent.lblFitness.setText('Average Fitness: {}%'.format(details[3])) - self.parent.lblPreviousFitness.setText('Previous Average Fitness: {}%'.format(details[4])) - self.parent.lblHighestFitness.setText('Highest Fitness: {}%'.format(details[5])) - self.parent.lblLowestFitness.setText('Lowest Fitness: {}%'.format(details[6])) + self.parent.boxGen.setTitle("Generation #{}".format(details[0])) + self.parent.lblPopulation.setText("Population: {}".format(details[1])) + self.parent.lblMutation.setText("Mutation Rate: {}%".format(details[2])) + self.parent.lblFitness.setText("Average Fitness: {}%".format(details[3])) + self.parent.lblPreviousFitness.setText( + "Previous Average Fitness: {}%".format(details[4]) + ) + self.parent.lblHighestFitness.setText("Highest Fitness: {}%".format(details[5])) + self.parent.lblLowestFitness.setText("Lowest Fitness: {}%".format(details[6])) def updateView(self, chromosomes): chromosomes.reverse() @@ -96,17 +107,26 @@ def changePreview(self, index): data = [] if not len(self.topChromosomes) or not self.preview: return False - sections = self.topChromosomes[0][0].data['sections'] + sections = self.topChromosomes[0][0].data["sections"] rawData = self.data - subjects = sections[self.sectionKeys[index]]['details'] + subjects = sections[self.sectionKeys[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][0], - 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][0], + rawData["rooms"][details[0]][0], + instructor, + ), + "instances": [ + [day, details[3], details[3] + details[4]] for day in details[2] + ], + } + ) self.loadTable(data) def loadTable(self, data=[]): @@ -118,10 +138,11 @@ def updateOperation(self, type): if type == 1: self.stopOperation() - def updateTime(self): self.time = self.time.addSecs(1) - self.parent.lblTime.setText('Elapsed Time: {}'.format(self.time.toString('hh:mm:ss'))) + self.parent.lblTime.setText( + "Elapsed Time: {}".format(self.time.toString("hh:mm:ss")) + ) def stopOperation(self): self.toggleState(False) @@ -130,25 +151,40 @@ def stopOperation(self): self.geneticAlgorithm.terminate() self.timer.stop() if len(self.topChromosomes): - self.parent.btnStop.setText('View Result') + self.parent.btnStop.setText("View Result") self.parent.btnStop.clicked.disconnect(self.stopOperation) self.parent.btnStop.clicked.connect(self.dialog.close) - self.parent.lblCPU.setText('CPU Usage: Stopped') - self.parent.lblMemory.setText('Memory Usage: Stopped') - self.parent.lblStatus.setText('Status: Stopped') - self.totalResource['cpu'] = mean(self.totalResource['cpu']) - self.totalResource['memory'] = mean(self.totalResource['memory']) - self.meta = [[chromosome[1], chromosome[0].fitnessDetails] for chromosome in - self.topChromosomes] + self.parent.lblCPU.setText("CPU Usage: Stopped") + self.parent.lblMemory.setText("Memory Usage: Stopped") + self.parent.lblStatus.setText("Status: Stopped") + self.totalResource["cpu"] = mean(self.totalResource["cpu"]) + self.totalResource["memory"] = mean(self.totalResource["memory"]) + self.meta = [ + [chromosome[1], chromosome[0].fitnessDetails] + for chromosome in self.topChromosomes + ] conn = db.getConnection() cursor = conn.cursor() - cursor.execute('INSERT INTO results (content) VALUES (?)', [Binary( - pickle.dumps({'data': [chromosome[0].data for chromosome in self.topChromosomes], - 'meta': self.meta, - 'time': self.time.toString('hh:mm:ss'), - 'resource': self.totalResource, - 'rawData': self.data}, - pickle.HIGHEST_PROTOCOL))]) + cursor.execute( + "INSERT INTO results (content) VALUES (?)", + [ + Binary( + pickle.dumps( + { + "data": [ + chromosome[0].data + for chromosome in self.topChromosomes + ], + "meta": self.meta, + "time": self.time.toString("hh:mm:ss"), + "resource": self.totalResource, + "rawData": self.data, + }, + pickle.HIGHEST_PROTOCOL, + ) + ) + ], + ) conn.commit() conn.close() else: @@ -159,10 +195,12 @@ def updateResource(self, resource): if self.tick == 3: self.tick = 0 else: - self.totalResource['cpu'].append(resource[0]) - self.totalResource['memory'].append(resource[1][1]) - self.parent.lblCPU.setText('CPU Usage: {}%'.format(resource[0])) - self.parent.lblMemory.setText('Memory Usage: {}% - {} MB'.format(resource[1][0], resource[1][1])) + self.totalResource["cpu"].append(resource[0]) + self.totalResource["memory"].append(resource[1][1]) + self.parent.lblCPU.setText("CPU Usage: {}%".format(resource[0])) + self.parent.lblMemory.setText( + "Memory Usage: {}% - {} MB".format(resource[1][0], resource[1][1]) + ) class ResourceTrackerWorker(QtCore.QThread): @@ -177,11 +215,14 @@ def __del__(self): self.wait() def run(self): - while (self.runThread): + while self.runThread: self.sleep(1) if self.running is True: cpu = ResourceTracker.getCPUUsage() memory = ResourceTracker.getMemoryUsage() - memory = [ResourceTracker.getMemoryPercentage(memory), ResourceTracker.byteToMegabyte(memory[0])] + memory = [ + ResourceTracker.getMemoryPercentage(memory), + ResourceTracker.byteToMegabyte(memory[0]), + ] self.signal.emit([cpu, memory]) return True diff --git a/containers/Instructor.py b/containers/Instructor.py index 8653815..33d7656 100644 --- a/containers/Instructor.py +++ b/containers/Instructor.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 Instructor as Parent import json @@ -18,18 +18,22 @@ 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, hours, schedule FROM instructors WHERE id = ?', [self.id]) + cursor.execute( + "SELECT name, hours, schedule FROM instructors WHERE id = ?", [self.id] + ) result = cursor.fetchone() conn.close() self.parent.lineEditName.setText(str(result[0])) self.parent.lineEditHours.setText(str(result[1])) # Generate timetable from custom schedule - self.table = Timetable.Timetable(self.parent.tableSchedule, json.loads(result[2])) + self.table = Timetable.Timetable( + self.parent.tableSchedule, json.loads(result[2]) + ) def finish(self): # Verification of input @@ -38,7 +42,7 @@ def finish(self): name = self.parent.lineEditName.text() try: hours = int(self.parent.lineEditHours.text()) - if hours <= 0 or hours > 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-35.pyc b/containers/__pycache__/Generate.cpython-35.pyc deleted file mode 100644 index daa9e00..0000000 Binary files a/containers/__pycache__/Generate.cpython-35.pyc and /dev/null differ diff --git a/containers/__pycache__/Instructor.cpython-35.pyc b/containers/__pycache__/Instructor.cpython-35.pyc deleted file mode 100644 index 0350f0f..0000000 Binary files a/containers/__pycache__/Instructor.cpython-35.pyc and /dev/null differ diff --git a/containers/__pycache__/Main.cpython-35.pyc b/containers/__pycache__/Main.cpython-35.pyc deleted file mode 100644 index 41ac89c..0000000 Binary files a/containers/__pycache__/Main.cpython-35.pyc and /dev/null differ diff --git a/containers/__pycache__/ResultViewer.cpython-35.pyc b/containers/__pycache__/ResultViewer.cpython-35.pyc deleted file mode 100644 index f046915..0000000 Binary files a/containers/__pycache__/ResultViewer.cpython-35.pyc and /dev/null differ diff --git a/containers/__pycache__/Room.cpython-35.pyc b/containers/__pycache__/Room.cpython-35.pyc deleted file mode 100644 index 0c96b33..0000000 Binary files a/containers/__pycache__/Room.cpython-35.pyc and /dev/null differ diff --git a/containers/__pycache__/Section.cpython-35.pyc b/containers/__pycache__/Section.cpython-35.pyc deleted file mode 100644 index 0f3492c..0000000 Binary files a/containers/__pycache__/Section.cpython-35.pyc and /dev/null differ diff --git a/containers/__pycache__/Share.cpython-35.pyc b/containers/__pycache__/Share.cpython-35.pyc deleted file mode 100644 index b95f8b4..0000000 Binary files a/containers/__pycache__/Share.cpython-35.pyc and /dev/null differ diff --git a/containers/__pycache__/Subject.cpython-35.pyc b/containers/__pycache__/Subject.cpython-35.pyc deleted file mode 100644 index b7ceb36..0000000 Binary files a/containers/__pycache__/Subject.cpython-35.pyc and /dev/null differ 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-35.pyc b/py_ui/__pycache__/Generate.cpython-35.pyc deleted file mode 100644 index e645d80..0000000 Binary files a/py_ui/__pycache__/Generate.cpython-35.pyc and /dev/null differ diff --git a/py_ui/__pycache__/Instructor.cpython-35.pyc b/py_ui/__pycache__/Instructor.cpython-35.pyc deleted file mode 100644 index 62aba28..0000000 Binary files a/py_ui/__pycache__/Instructor.cpython-35.pyc and /dev/null differ diff --git a/py_ui/__pycache__/Main.cpython-35.pyc b/py_ui/__pycache__/Main.cpython-35.pyc deleted file mode 100644 index 0f6cdc5..0000000 Binary files a/py_ui/__pycache__/Main.cpython-35.pyc and /dev/null differ diff --git a/py_ui/__pycache__/Result.cpython-35.pyc b/py_ui/__pycache__/Result.cpython-35.pyc deleted file mode 100644 index 4bdd8e4..0000000 Binary files a/py_ui/__pycache__/Result.cpython-35.pyc and /dev/null differ diff --git a/py_ui/__pycache__/Room.cpython-35.pyc b/py_ui/__pycache__/Room.cpython-35.pyc deleted file mode 100644 index 468d8ef..0000000 Binary files a/py_ui/__pycache__/Room.cpython-35.pyc and /dev/null differ diff --git a/py_ui/__pycache__/Section.cpython-35.pyc b/py_ui/__pycache__/Section.cpython-35.pyc deleted file mode 100644 index bd0be6a..0000000 Binary files a/py_ui/__pycache__/Section.cpython-35.pyc and /dev/null differ diff --git a/py_ui/__pycache__/Share.cpython-35.pyc b/py_ui/__pycache__/Share.cpython-35.pyc deleted file mode 100644 index dbb4500..0000000 Binary files a/py_ui/__pycache__/Share.cpython-35.pyc and /dev/null differ diff --git a/py_ui/__pycache__/Subject.cpython-35.pyc b/py_ui/__pycache__/Subject.cpython-35.pyc deleted file mode 100644 index f87294e..0000000 Binary files a/py_ui/__pycache__/Subject.cpython-35.pyc and /dev/null differ 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 diff --git a/settings.json b/settings.json index 886caeb..62f731f 100644 --- a/settings.json +++ b/settings.json @@ -1 +1 @@ -{"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