Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: implement duplicate schedule checking in schedule generator #974

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 30 additions & 5 deletions src/components/ScheduleGenerate/ScheduleGenerateModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ export default defineComponent({
);
},
generateSchedules() {
const output: {
const outputs: {
semester: string;
schedule: Map<Course, Timeslot[]>;
fulfilledRequirements: Map<string, Requirement[]>;
Expand All @@ -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(
Expand Down Expand Up @@ -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();
Expand Down
21 changes: 6 additions & 15 deletions src/schedule-generator/algorithm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,28 +29,20 @@
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;
Expand All @@ -61,35 +53,34 @@
}
}
});

return { semester, schedule, fulfilledRequirements, totalCredits };
}

static prettyPrintSchedule(output: GeneratedScheduleOutput): void {
console.log('************************');

Check warning on line 60 in src/schedule-generator/algorithm.ts

View workflow job for this annotation

GitHub Actions / check

Unexpected console statement
console.log(`Generated Schedule for ${output.semester}:`);

Check warning on line 61 in src/schedule-generator/algorithm.ts

View workflow job for this annotation

GitHub Actions / check

Unexpected console statement
output.schedule.forEach((timeslots, course) => {
const fulfilledReqs = output.fulfilledRequirements
.get(course.code)
?.map(req => req.name)
.join(', ');

console.log(`- ${course.code} (${fulfilledReqs}, ${course.credits} credits)`);

Check warning on line 68 in src/schedule-generator/algorithm.ts

View workflow job for this annotation

GitHub Actions / check

Unexpected console statement

timeslots.forEach(timeslot => {
if (timeslot.daysOfTheWeek && timeslot.daysOfTheWeek.length > 0) {
console.log(

Check warning on line 72 in src/schedule-generator/algorithm.ts

View workflow job for this annotation

GitHub Actions / check

Unexpected console statement
`\tTime Slot: ${timeslot.start} – ${timeslot.end}. Days: ${timeslot.daysOfTheWeek.join(
', '
)}`
);
} else {
console.log(`\tTime Slot: ${timeslot.start} – ${timeslot.end}. Days: not specified`);

Check warning on line 78 in src/schedule-generator/algorithm.ts

View workflow job for this annotation

GitHub Actions / check

Unexpected console statement
}
});
});
console.log();

Check warning on line 82 in src/schedule-generator/algorithm.ts

View workflow job for this annotation

GitHub Actions / check

Unexpected console statement
console.log(`Total Credits in the Schedule: ${output.totalCredits}`);

Check warning on line 83 in src/schedule-generator/algorithm.ts

View workflow job for this annotation

GitHub Actions / check

Unexpected console statement
}

private static isTimeslotOccupied(
Expand Down
Loading