diff --git a/src/components/ScheduleGenerate/ScheduleGenerateModal.vue b/src/components/ScheduleGenerate/ScheduleGenerateModal.vue index 84bb966d2..ea49ea67b 100644 --- a/src/components/ScheduleGenerate/ScheduleGenerateModal.vue +++ b/src/components/ScheduleGenerate/ScheduleGenerateModal.vue @@ -168,7 +168,7 @@ export default defineComponent({ ); }, generateSchedules() { - const output: { + const outputs: { semester: string; schedule: Map; fulfilledRequirements: Map; @@ -191,7 +191,31 @@ export default defineComponent({ ); } - for (let i = 0; i < 5; i += 1) { + /** Checks if two `GeneratedScheduleOutput` objects `first` and `second` are equal. Outputs + * are equal if all three of the following conditions are true: outputs are in the same + * semester, they contain the same courses in the same order, and they have the same total credits. + */ + function isEqual(first: GeneratedScheduleOutput, second: GeneratedScheduleOutput) { + if (first.totalCredits !== second.totalCredits || first.semester !== second.semester) { + return false; + } + + const firstScheduleEntries = Array.from(first.schedule.entries()); + const secondScheduleEntries = Array.from(first.schedule.entries()); + if (firstScheduleEntries.length !== secondScheduleEntries.length) { + return false; + } + for (let i = 0; i < firstScheduleEntries.length; i += 1) { + if (firstScheduleEntries[i][0].code !== secondScheduleEntries[i][0].code) { + return false; + } + } + + return true; + } + + const startTime = Date.now(); + while (outputs.length < 5 && Date.now() - startTime < 1000) { const courses = this.courses.map( course => new Course( @@ -311,10 +335,11 @@ export default defineComponent({ momentary.fulfilledRequirements = newFullfilledReqs; momentary.totalCredits += deltaCredits; - output.push(momentary); + if (outputs.every(output => !isEqual(output, momentary))) { + outputs.push(momentary); + } } - - this.generatedScheduleOutputs = output; + this.generatedScheduleOutputs = outputs; }, regenerateSchedule() { this.generateSchedules(); diff --git a/src/schedule-generator/algorithm.ts b/src/schedule-generator/algorithm.ts index dc693ba4f..360e87944 100644 --- a/src/schedule-generator/algorithm.ts +++ b/src/schedule-generator/algorithm.ts @@ -29,28 +29,20 @@ export default class ScheduleGenerator { let performAdditionFlag = true; const onlyCourseRequirement = course.requirements[0].name ?? 'nonsense-requirement'; - // New logic: must be free for *all* time slots. if ( actualFulfilledRequirements.has(onlyCourseRequirement) || fulfilledRequirements.has(course.code) || creditLimit - course.credits < 0 ) { performAdditionFlag = false; - } else { - for (const timeslot of course.timeslots) { - if (ScheduleGenerator.isTimeslotOccupied(schedule, timeslot)) { - performAdditionFlag = false; - } - } } - course.timeslots.forEach(timeslot => { - if (ScheduleGenerator.isTimeslotOccupied(schedule, timeslot)) { - performAdditionFlag = false; - } - }); - - if (performAdditionFlag) { + if ( + performAdditionFlag && + course.timeslots.some( + timeslot => !ScheduleGenerator.isTimeslotOccupied(schedule, timeslot) + ) + ) { ScheduleGenerator.addToSchedule(schedule, course, course.timeslots); creditLimit -= course.credits; totalCredits += course.credits; @@ -61,7 +53,6 @@ export default class ScheduleGenerator { } } }); - return { semester, schedule, fulfilledRequirements, totalCredits }; }