From 8dd0918be4d349004c1b7a2effb13c747f636990 Mon Sep 17 00:00:00 2001 From: RandomCyberCoder Date: Wed, 13 May 2026 12:17:57 -0700 Subject: [PATCH 01/17] semster course config update --- .../src/main/resources/constants/semester-configurations.tsv | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/hello-world/src/main/resources/constants/semester-configurations.tsv b/java/hello-world/src/main/resources/constants/semester-configurations.tsv index 15974048..a9194fed 100644 --- a/java/hello-world/src/main/resources/constants/semester-configurations.tsv +++ b/java/hello-world/src/main/resources/constants/semester-configurations.tsv @@ -36,6 +36,7 @@ csc3760 2-0-1 csc3780 3-1-0 csc4036 2-0-1 csc4037 2-0-1 +csc4040 2-0-1 csc4091 1-0-0 csc4092 various csc4093 various @@ -104,7 +105,7 @@ csc4993 Lecture_only csc5092 Lecture_only csc5100 3-0-0 csc5113 3-0-0 -csc5170 Lecture_only +csc5170 2-0-1 csc5201 3-0-0 csc5210 3-0-0 csc5220 3-0-0 From 4f586348e841dce6da5eab97d025a97b810c2de3 Mon Sep 17 00:00:00 2001 From: RandomCyberCoder Date: Wed, 13 May 2026 12:19:10 -0700 Subject: [PATCH 02/17] facutly member's meeting time block out added back in --- .../domain/teacher/Faculty.java | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/domain/teacher/Faculty.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/domain/teacher/Faculty.java index 619abd9a..0cee4327 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/domain/teacher/Faculty.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/domain/teacher/Faculty.java @@ -35,7 +35,7 @@ public class Faculty extends Teacher{ final int NUM_BLOCKS_FULL_HOUR = 2; List facultyTimes; DateTimeFormatter formatter = DateTimeFormatter.ofPattern("h:mma"); - final EnumSet FACULTY_DAYS = EnumSet.of(Days.MONDAY, Days.WEDNESDAY, Days.FRIDAY); + EnumSet facultyDays = EnumSet.of(Days.MONDAY, Days.WEDNESDAY, Days.FRIDAY); try{ //set special bits for testing @@ -45,27 +45,26 @@ public class Faculty extends Teacher{ EnumSet.of(Days.MONDAY, Days.WEDNESDAY, Days.FRIDAY)); FACULTY_CONFLICT.or(temp); } -// /*CSC faculty times*/ -// if(ScheduleConfig.getDepartment().equalsIgnoreCase("csc")){ -// facultyTimes = List.of( -// LocalTime.parse("1:00PM", formatter), -// LocalTime.parse("2:00PM", formatter) -// ); -// } -// else{ -// /*CPE faculty times*/ -// facultyTimes = List.of( -// LocalTime.parse("12:00PM", formatter), -// LocalTime.parse("1:00PM", formatter), -// LocalTime.parse("2:00PM", formatter) -// ); -// } -// -// /*create the BitSet for faculty conflict*/ -// for(LocalTime localTime: facultyTimes) { -// BitSet temp = BitSetHelper.timeSlotBitSet(localTime, NUM_BLOCKS_FULL_HOUR, FACULTY_DAYS); -// FACULTY_CONFLICT.or(temp); -// } + /*CSC faculty times*/ + if(ScheduleConfig.getDepartment().equalsIgnoreCase("csc")){ + facultyTimes = List.of( + LocalTime.parse("11:00AM", formatter) + ); + facultyDays = EnumSet.of(Days.TUESDAY); + } + else{ + /*CPE faculty times*/ + facultyTimes = List.of( + LocalTime.parse("11:00AM", formatter) + ); + facultyDays = EnumSet.of(Days.WEDNESDAY); + } + + /*create the BitSet for faculty conflict*/ + for(LocalTime localTime: facultyTimes) { + BitSet temp = BitSetHelper.timeSlotBitSet(localTime, NUM_BLOCKS_FULL_HOUR, facultyDays); + FACULTY_CONFLICT.or(temp); + } } catch (Exception e){ Faculty.LOGGER.error("Problem creating BitSet mask for the faculty tenure conflict."); From f7e69efbfa150a36df8b10bb2b8a4d5d0e933c20 Mon Sep 17 00:00:00 2001 From: RandomCyberCoder Date: Wed, 13 May 2026 16:54:02 -0700 Subject: [PATCH 03/17] deleted old files that aren't used --- .../constants/future_times_to_add.csv | 70 ----- .../constants/oldTimesForDisconnected.csv | 192 -------------- .../constants/possibleTimes_V2.csv | 244 ------------------ 3 files changed, 506 deletions(-) delete mode 100644 java/hello-world/src/main/java/org/acme/schooltimetabling/constants/future_times_to_add.csv delete mode 100644 java/hello-world/src/main/java/org/acme/schooltimetabling/constants/oldTimesForDisconnected.csv delete mode 100644 java/hello-world/src/main/java/org/acme/schooltimetabling/constants/possibleTimes_V2.csv diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/constants/future_times_to_add.csv b/java/hello-world/src/main/java/org/acme/schooltimetabling/constants/future_times_to_add.csv deleted file mode 100644 index ac4744fd..00000000 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/constants/future_times_to_add.csv +++ /dev/null @@ -1,70 +0,0 @@ -//these are for the lecture-activity times for the lecture if we cant schedule the lecture and activity back to back -MWF, 7:10am-8:00am, 1 -MWF, 8:10am-9:00am, 1 -MWF, 9:10am-10:00am, 1 -MWF, 10:10am-11:00am, 1 -MWF, 11:10am-12:00pm, 1 -MWF, 12:10pm-1:00pm, 1 -MWF, 1:10pm-2:00pm, 1 -MWF, 2:10pm-3:00pm, 1 -MWF, 3:10pm-4:00pm, 1 -MWF, 4:10pm-5:00pm, 1 -MWF, 5:10pm-6:00pm, 1 -MWF, 6:10pm-7:00pm, 1 -MWF, 7:10pm-8:00pm, 1 -MWF, 8:10pm-9:00pm, 1 - -//these are the activity times for friday -F, 7:10am-9:00am, 2 -F, 8:10am-10:00am, 2 -F, 9:10am-11:00am, 2 -F, 10:10am-12:00pm, 2 -F, 11:10am-1:00pm, 2 -F, 12:10pm-2:00pm, 2 -F, 1:10pm-3:00pm, 2 -F, 2:10pm-4:00pm, 2 -F, 3:10pm-5:00pm, 2 -F, 4:10pm-6:00pm, 2 -F, 5:10pm-7:00pm, 2 -F, 6:10pm-8:00pm, 2 -F, 7:10pm-9:00pm, 2 - - -/// -Days, Time, Hours -TR, 8:00am-11:00am, 1.5 -TR, 12:00pm-3:00pm, 1.5 -TR, 1:30pm-4:30pm, 1.5 -TR, 3:00pm-6:00pm, 1.5 -TR, 4:00pm-7:00pm, 1.5 -TR, 4:30pm-7:30pm, 1.5 -TR, 5:00pm-8:00pm, 1.5 -TR, 5:30pm-8:30pm, 1.5 -TR, 6:00pm-9:00pm, 1.5 -TR, 6:30pm-9:30pm, 1.5 -TR, 7:00pm-10:00pm, 1.5 - -TR, 1:10pm-4:10pm, 3 -TR, 3:10pm-6:10pm, 3 -TR, 4:10pm-7:10pm, 3 -TR, 4:40pm-7:40pm, 3 -TR, 5:10pm-8:10pm, 3 -TR, 5:40pm-8:40pm, 3 -TR, 6:10pm-9:10pm, 3 -TR, 6:40pm-9:40pm, 3 -TR, 7:10pm-10:10pm, 3 -TR, 7:40pm-10:40pm, 3 -TR, 8:10pm-11:10pm, 3 -TR, 8:40pm-11:40pm, 3 -TR, 1:10pm-4:10pm, 3 -TR, 3:10pm-6:10pm, 3 -TR, 4:10pm-7:10pm, 3 -TR, 4:40pm-7:40pm, 3 -TR, 5:10pm-8:10pm, 3 -TR, 5:40pm-8:40pm, 3 -TR, 6:10pm-9:10pm, 3 -TR, 6:40pm-9:40pm, 3 -TR, 7:10pm-10:10pm, 3 -TR, 7:40pm-10:40pm, 3 -TR, 8:10pm-11:10pm, 3 -TR, 8:40pm-11:40pm, 3 diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/constants/oldTimesForDisconnected.csv b/java/hello-world/src/main/java/org/acme/schooltimetabling/constants/oldTimesForDisconnected.csv deleted file mode 100644 index a3c29f46..00000000 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/constants/oldTimesForDisconnected.csv +++ /dev/null @@ -1,192 +0,0 @@ -days, time_start, time_end, lecture_hours, total_hours, days2, time_start2, time_end2, lecture_hours2, total_hours2 -MWF, 7:00AM, 9:00AM, 1, 2,,,,, -MWF, 8:00AM, 10:00AM, 1, 2,,,,, -MWF, 9:00AM, 11:00AM, 1, 2,,,,, -MWF, 10:00AM, 12:00PM, 1, 2,,,,, -MWF, 11:00AM, 1:00PM, 1, 2,,,,, -MWF, 12:00PM, 2:00PM, 1, 2,,,,, -MWF, 1:00PM, 3:00PM, 1, 2,,,,, -MWF, 2:00PM, 4:00PM, 1, 2,,,,, -MWF, 3:00PM, 5:00PM, 1, 2,,,,, -MWF, 4:00PM, 6:00PM, 1, 2,,,,, -MWF, 5:00PM, 7:00PM, 1, 2,,,,, -MWF, 6:00PM, 8:00PM, 1, 2,,,,, -MWF, 7:00PM, 9:00PM, 1, 2,,,,, -TR, 8:00AM, 11:00AM, 1.5, 3,,,,, -TR, 12:00PM, 3:00PM, 1.5, 3,,,,, -TR, 1:30PM, 4:30PM, 1.5, 3,,,,, -TR, 3:00PM, 6:00PM, 1.5, 3,,,,, -TR, 4:00PM, 7:00PM, 1.5, 3,,,,, -TR, 4:30PM, 7:30PM, 1.5, 3,,,,, -TR, 5:00PM, 8:00PM, 1.5, 3,,,,, -TR, 5:30PM, 8:30PM, 1.5, 3,,,,, -TR, 6:00PM, 9:00PM, 1.5, 3,,,,, -MTWR, 7:00AM, 8:00AM, 1, 1,,,,, -MTWR, 8:00AM, 9:00AM, 1, 1,,,,, -MTWR, 9:00AM, 10:00AM, 1, 1,,,,, -MTWR, 10:00AM, 11:00AM, 1, 1,,,,, -MTWR, 11:00AM, 12:00PM, 1, 1,,,,, -MTWR, 12:00PM, 1:00PM, 1, 1,,,,, -MTWR, 1:00PM, 2:00PM, 1, 1,,,,, -MTWR, 2:00PM, 3:00PM, 1, 1,,,,, -MTWR, 3:00PM, 4:00PM, 1, 1,,,,, -MWF, 7:00AM, 8:00AM, 1, 1,,,,, -MWF, 8:00AM, 9:00AM, 1, 1,,,,, -MWF, 9:00AM, 10:00AM, 1, 1,,,,, -MWF, 10:00AM, 11:00AM, 1, 1,,,,, -MWF, 11:00AM, 12:00PM, 1, 1,,,,, -MWF, 12:00PM, 1:00PM, 1, 1,,,,, -MWF, 1:00PM, 2:00PM, 1, 1,,,,, -MWF, 2:00PM, 3:00PM, 1, 1,,,,, -MWF, 3:00PM, 4:00PM, 1, 1,,,,, -MWF, 4:00PM, 5:00PM, 1, 1,,,,, -MWF, 5:00PM, 6:00PM, 1, 1,,,,, -MWF, 6:00PM, 7:00PM, 1, 1,,,,, -TR, 8:00AM, 9:30AM, 1.5, 1.5,,,,, -TR, 12:00PM, 1:30PM, 1.5, 1.5,,,,, -TR, 1:30PM, 3:00PM, 1.5, 1.5,,,,, -TR, 3:00PM, 4:30PM, 1.5, 1.5,,,,, -TR, 4:00PM, 5:30PM, 1.5, 1.5,,,,, -TR, 4:30PM, 6:00PM, 1.5, 1.5,,,,, -TR, 5:00PM, 6:30PM, 1.5, 1.5,,,,, -TR, 5:30PM, 7:00PM, 1.5, 1.5,,,,, -TR, 6:00PM, 7:30PM, 1.5, 1.5,,,,, -TR, 8:00AM, 9:30AM, 1.5, 1.5,,,,, -TR, 12:00PM, 1:30PM, 1.5, 1.5,,,,, -TR, 1:30PM, 3:00PM, 1.5, 1.5,,,,, -TR, 3:00PM, 4:30PM, 1.5, 1.5,,,,, -TR, 4:00PM, 5:30PM, 1.5, 1.5,,,,, -TR, 4:30PM, 6:00PM, 1.5, 1.5,,,,, -TR, 5:00PM, 6:30PM, 1.5, 1.5,,,,, -TR, 5:30PM, 7:00PM, 1.5, 1.5,,,,, -TR, 6:00PM, 7:30PM, 1.5, 1.5,,,,, -M, 8:00AM, 11:00AM, 3, 3,,,,, -M, 9:00AM, 12:00PM, 3, 3,,,,, -M, 10:00AM, 1:00PM, 3, 3,,,,, -M, 11:00AM, 2:00PM, 3, 3,,,,, -M, 12:00PM, 3:00PM, 3, 3,,,,, -M, 1:00PM, 4:00PM, 3, 3,,,,, -M, 2:00PM, 5:00PM, 3, 3,,,,, -M, 3:00PM, 6:00PM, 3, 3,,,,, -M, 4:00PM, 7:00PM, 3, 3,,,,, -W, 8:00AM, 11:00AM, 3, 3,,,,, -W, 9:00AM, 12:00PM, 3, 3,,,,, -W, 10:00AM, 1:00PM, 3, 3,,,,, -W, 11:00AM, 2:00PM, 3, 3,,,,, -W, 12:00PM, 3:00PM, 3, 3,,,,, -W, 1:00PM, 4:00PM, 3, 3,,,,, -W, 2:00PM, 5:00PM, 3, 3,,,,, -W, 3:00PM, 6:00PM, 3, 3,,,,, -W, 4:00PM, 7:00PM, 3, 3,,,,, -F, 8:00AM, 11:00AM, 3, 3,,,,, -F, 9:00AM, 12:00PM, 3, 3,,,,, -F, 10:00AM, 1:00PM, 3, 3,,,,, -F, 11:00AM, 2:00PM, 3, 3,,,,, -F, 12:00PM, 3:00PM, 3, 3,,,,, -F, 1:00PM, 4:00PM, 3, 3,,,,, -F, 2:00PM, 5:00PM, 3, 3,,,,, -F, 3:00PM, 6:00PM, 3, 3,,,,, -F, 4:00PM, 7:00PM, 3, 3,,,,, -T, 8:00AM, 11:00AM, 3, 3,,,,, -T, 9:00AM, 12:00PM, 3, 3,,,,, -T, 10:00AM, 1:00PM, 3, 3,,,,, -T, 11:00AM, 2:00PM, 3, 3,,,,, -T, 12:00PM, 3:00PM, 3, 3,,,,, -T, 1:00PM, 4:00PM, 3, 3,,,,, -T, 2:00PM, 5:00PM, 3, 3,,,,, -T, 3:00PM, 6:00PM, 3, 3,,,,, -T, 4:00PM, 7:00PM, 3, 3,,,,, -R, 8:00AM, 11:00AM, 3, 3,,,,, -R, 9:00AM, 12:00PM, 3, 3,,,,, -R, 10:00AM, 1:00PM, 3, 3,,,,, -R, 11:00AM, 2:00PM, 3, 3,,,,, -R, 12:00PM, 3:00PM, 3, 3,,,,, -R, 1:00PM, 4:00PM, 3, 3,,,,, -R, 2:00PM, 5:00PM, 3, 3,,,,, -R, 3:00PM, 6:00PM, 3, 3,,,,, -R, 4:00PM, 7:00PM, 3, 3,,,,, -M, 8:00AM, 9:00AM, 1, 1,,,,, -M, 9:00AM, 10:00AM, 1, 1,,,,, -M, 10:00AM, 11:00AM, 1, 1,,,,, -M, 11:00AM, 12:00PM, 1, 1,,,,, -M, 12:00PM, 1:00PM, 1, 1,,,,, -M, 1:00PM, 2:00PM, 1, 1,,,,, -M, 2:00PM, 3:00PM, 1, 1,,,,, -M, 3:00PM, 4:00PM, 1, 1,,,,, -M, 4:00PM, 5:00PM, 1, 1,,,,, -M, 5:00PM, 6:00PM, 1, 1,,,,, -M, 6:00PM, 7:00PM, 1, 1,,,,, -T, 8:00AM, 9:00AM, 1, 1,,,,, -T, 9:00AM, 10:00AM, 1, 1,,,,, -T, 10:00AM, 11:00AM, 1, 1,,,,, -T, 11:00AM, 12:00PM, 1, 1,,,,, -T, 12:00PM, 1:00PM, 1, 1,,,,, -T, 1:00PM, 2:00PM, 1, 1,,,,, -T, 2:00PM, 3:00PM, 1, 1,,,,, -T, 3:00PM, 4:00PM, 1, 1,,,,, -T, 4:00PM, 5:00PM, 1, 1,,,,, -T, 5:00PM, 6:00PM, 1, 1,,,,, -T, 6:00PM, 7:00PM, 1, 1,,,,, -W, 8:00AM, 9:00AM, 1, 1,,,,, -W, 9:00AM, 10:00AM, 1, 1,,,,, -W, 10:00AM, 11:00AM, 1, 1,,,,, -W, 11:00AM, 12:00PM, 1, 1,,,,, -W, 12:00PM, 1:00PM, 1, 1,,,,, -W, 1:00PM, 2:00PM, 1, 1,,,,, -W, 2:00PM, 3:00PM, 1, 1,,,,, -W, 3:00PM, 4:00PM, 1, 1,,,,, -W, 4:00PM, 5:00PM, 1, 1,,,,, -W, 5:00PM, 6:00PM, 1, 1,,,,, -W, 6:00PM, 7:00PM, 1, 1,,,,, -R, 8:00AM, 9:00AM, 1, 1,,,,, -R, 9:00AM, 10:00AM, 1, 1,,,,, -R, 10:00AM, 11:00AM, 1, 1,,,,, -R, 11:00AM, 12:00PM, 1, 1,,,,, -R, 12:00PM, 1:00PM, 1, 1,,,,, -R, 1:00PM, 2:00PM, 1, 1,,,,, -R, 2:00PM, 3:00PM, 1, 1,,,,, -R, 3:00PM, 4:00PM, 1, 1,,,,, -R, 4:00PM, 5:00PM, 1, 1,,,,, -R, 5:00PM, 6:00PM, 1, 1,,,,, -R, 6:00PM, 7:00PM, 1, 1,,,,, -F, 8:00AM, 9:00AM, 1, 1,,,,, -F, 9:00AM, 10:00AM, 1, 1,,,,, -F, 10:00AM, 11:00AM, 1, 1,,,,, -F, 11:00AM, 12:00PM, 1, 1,,,,, -F, 12:00PM, 1:00PM, 1, 1,,,,, -F, 1:00PM, 2:00PM, 1, 1,,,,, -F, 2:00PM, 3:00PM, 1, 1,,,,, -F, 3:00PM, 4:00PM, 1, 1,,,,, -F, 4:00PM, 5:00PM, 1, 1,,,,, -F, 5:00PM, 6:00PM, 1, 1,,,,, -F, 6:00PM, 7:00PM, 1, 1,,,,, -M, 8:00AM, 2:00PM, 6, 6,,,,, -M, 9:00AM, 3:00PM, 6, 6,,,,, -M, 10:00AM, 4:00PM, 6, 6,,,,, -M, 11:00AM, 5:00PM, 6, 6,,,,, -M, 12:00PM, 6:00PM, 6, 6,,,,, -M, 1:00PM, 7:00PM, 6, 6,,,,, -T, 8:00AM, 2:00PM, 6, 6,,,,, -T, 9:00AM, 3:00PM, 6, 6,,,,, -T, 10:00AM, 4:00PM, 6, 6,,,,, -T, 11:00AM, 5:00PM, 6, 6,,,,, -T, 12:00PM, 6:00PM, 6, 6,,,,, -T, 1:00PM, 7:00PM, 6, 6,,,,, -W, 8:00AM, 2:00PM, 6, 6,,,,, -W, 9:00AM, 3:00PM, 6, 6,,,,, -W, 10:00AM, 4:00PM, 6, 6,,,,, -W, 11:00AM, 5:00PM, 6, 6,,,,, -W, 12:00PM, 6:00PM, 6, 6,,,,, -W, 1:00PM, 7:00PM, 6, 6,,,,, -R, 8:00AM, 2:00PM, 6, 6,,,,, -R, 9:00AM, 3:00PM, 6, 6,,,,, -R, 10:00AM, 4:00PM, 6, 6,,,,, -R, 11:00AM, 5:00PM, 6, 6,,,,, -R, 12:00PM, 6:00PM, 6, 6,,,,, -R, 1:00PM, 7:00PM, 6, 6,,,,, -F, 8:00AM, 2:00PM, 6, 6,,,,, -F, 9:00AM, 3:00PM, 6, 6,,,,, -F, 10:00AM, 4:00PM, 6, 6,,,,, -F, 11:00AM, 5:00PM, 6, 6,,,,, -F, 12:00PM, 6:00PM, 6, 6,,,,, -F, 1:00PM, 7:00PM, 6, 6,,,,, \ No newline at end of file diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/constants/possibleTimes_V2.csv b/java/hello-world/src/main/java/org/acme/schooltimetabling/constants/possibleTimes_V2.csv deleted file mode 100644 index 8912b689..00000000 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/constants/possibleTimes_V2.csv +++ /dev/null @@ -1,244 +0,0 @@ -days, time_start, time_end, lecture_hours, total_hours, days2, time_start2, time_end2, lecture_hours2, total_hours2 -MWF, 7:00AM, 9:00AM, 1, 2, , , , , -MWF, 8:00AM, 10:00AM, 1, 2, , , , , -MWF, 9:00AM, 11:00AM, 1, 2, , , , , -MWF, 10:00AM, 12:00PM, 1, 2, , , , , -MWF, 11:00AM, 1:00PM, 1, 2, , , , , -MWF, 12:00PM, 2:00PM, 1, 2, , , , , -MWF, 1:00PM, 3:00PM, 1, 2, , , , , -MWF, 2:00PM, 4:00PM, 1, 2, , , , , -MWF, 3:00PM, 5:00PM, 1, 2, , , , , -MWF, 4:00PM, 6:00PM, 1, 2, , , , , -MWF, 5:00PM, 7:00PM, 1, 2, , , , , -MWF, 6:00PM, 8:00PM, 1, 2, , , , , -MWF, 7:00PM, 9:00PM, 1, 2, , , , , -MW, 7:00AM, 9:00AM, 1, 2, , , , , -MW, 8:00AM, 10:00AM, 1, 2, , , , , -MW, 9:00AM, 11:00AM, 1, 2, , , , , -MW, 10:00AM, 12:00PM, 1, 2, , , , , -MW, 11:00AM, 1:00PM, 1, 2, , , , , -MW, 12:00PM, 2:00PM, 1, 2, , , , , -MW, 1:00PM, 3:00PM, 1, 2, , , , , -MW, 2:00PM, 4:00PM, 1, 2, , , , , -MW, 3:00PM, 5:00PM, 1, 2, , , , , -MW, 4:00PM, 6:00PM, 1, 2, , , , , -MW, 5:00PM, 7:00PM, 1, 2, , , , , -MW, 6:00PM, 8:00PM, 1, 2, , , , , -MW, 7:00PM, 9:00PM, 1, 2, , , , , - -//hour lunch break -MW, 9:00AM, 12:00AM, 1, 3, , , , , - - -//this is for lec and activity on different times -MW, 7:00AM, 8:00AM, 1, 1, F, 7:00AM, 9:00AM, 0, 2 -MW, 8:00AM, 9:00AM, 1, 1, F, 8:00AM, 10:AM, 0, 2 -MW, 9:00AM, 10:00AM, 1, 1, , , , , -MW, 10:00AM, 11:00PM, 1, 1, , , , , -MW, 11:00AM, 12:00PM, 1, 1, , , , , -MW, 12:00PM, 1:00PM, 1, 1, , , , , -MW, 1:00PM, 2:00PM, 1, 1, , , , , -MW, 2:00PM, 3:00PM, 1, 1, , , , , -MW, 3:00PM, 4:00PM, 1, 1, , , , , -MW, 4:00PM, 5:00PM, 1, 1, , , , , -MW, 5:00PM, 6:00PM, 1, 1, , , , , -MW, 6:00PM, 7:00PM, 1, 1, , , , , -MW, 7:00PM, 8:00PM, 1, 1, , , , , - -MTWR, 7:00AM, 8:00AM, 1, 1, , , , , -MTWR, 8:00AM, 9:00AM, 1, 1, , , , , -MTWR, 9:00AM, 10:00AM, 1, 1, , , , , -MTWR, 10:00AM, 11:00AM, 1, 1, , , , , -MTWR, 11:00AM, 12:00PM, 1, 1, , , , , -MTWR, 12:00PM, 1:00PM, 1, 1, , , , , -MTWR, 1:00PM, 2:00PM, 1, 1, , , , , -MTWR, 2:00PM, 3:00PM, 1, 1, , , , , -MTWR, 3:00PM, 4:00PM, 1, 1, , , , , -MTWR, 4:00PM, 5:00PM, 1, 1, , , , , -MTWR, 5:00PM, 6:00PM, 1, 1, , , , , -MTWR, 6:00PM, 7:00PM, 1, 1, , , , , -MTWR, 7:00PM, 8:00PM, 1, 1, , , , , -MTWR, 8:00PM, 9:00PM, 1, 1, , , , , - - - -TR, 8:00AM, 11:00AM, 1.5, 3, , , , , -TR, 12:00PM, 3:00PM, 1.5, 3, , , , , - -//can take into account university hour -TR, 9:30AM, 1:30PM, 1.5, 4, , , , , - - -USE FOR CSC WHILE AUTO GENERATION IS BEING DONE ----------------------------------------------------------------------------------------------------------------------------------- -days, time_start, time_end, lecture_hours, total_hours, days2, time_start2, time_end2, lecture_hours2, total_hours2 -MWF, 7:00AM, 9:00AM, 1, 2,,,,, -MWF, 8:00AM, 10:00AM, 1, 2,,,,, -MWF, 9:00AM, 11:00AM, 1, 2,,,,, -MWF, 10:00AM, 12:00PM, 1, 2,,,,, -MWF, 11:00AM, 1:00PM, 1, 2,,,,, -MWF, 12:00PM, 2:00PM, 1, 2,,,,, -MWF, 1:00PM, 3:00PM, 1, 2,,,,, -MWF, 2:00PM, 4:00PM, 1, 2,,,,, -MWF, 3:00PM, 5:00PM, 1, 2,,,,, -MWF, 4:00PM, 6:00PM, 1, 2,,,,, -MWF, 5:00PM, 7:00PM, 1, 2,,,,, -MWF, 6:00PM, 8:00PM, 1, 2,,,,, -MWF, 7:00PM, 9:00PM, 1, 2,,,,, -TR, 8:00AM, 11:00AM, 1.5, 3,,,,, -TR, 12:00PM, 3:00PM, 1.5, 3,,,,, -TR, 1:30PM, 4:30PM, 1.5, 3,,,,, -TR, 3:00PM, 6:00PM, 1.5, 3,,,,, -TR, 4:00PM, 7:00PM, 1.5, 3,,,,, -TR, 4:30PM, 7:30PM, 1.5, 3,,,,, -TR, 5:00PM, 8:00PM, 1.5, 3,,,,, -TR, 5:30PM, 8:30PM, 1.5, 3,,,,, -TR, 6:00PM, 9:00PM, 1.5, 3,,,,, -TR, 6:30PM, 9:30PM, 1.5, 3,,,,, -TR, 7:00PM, 10:00PM, 1.5, 3,,,,, -MTWR, 7:00AM, 8:00AM, 1, 1,,,,, -MTWR, 8:00AM, 9:00AM, 1, 1,,,,, -MTWR, 9:00AM, 10:00AM, 1, 1,,,,, -MTWR, 10:00AM, 11:00AM, 1, 1,,,,, -MTWR, 11:00AM, 12:00PM, 1, 1,,,,, -MTWR, 12:00PM, 1:00PM, 1, 1,,,,, -MTWR, 1:00PM, 2:00PM, 1, 1,,,,, -MTWR, 2:00PM, 3:00PM, 1, 1,,,,, -MTWR, 3:00PM, 4:00PM, 1, 1,,,,, -MTWR, 4:00PM, 5:00PM, 1, 1,,,,, -MTWR, 5:00PM, 6:00PM, 1, 1,,,,, -MTWR, 6:00PM, 7:00PM, 1, 1,,,,, -MTWR, 7:00PM, 8:00PM, 1, 1,,,,, -MTWR, 8:00PM, 9:00PM, 1, 1,,,,, -TR, 7:00AM, 9:00AM, 2, 2,,,,, -TR, 9:00AM, 11:00AM, 2, 2,,,,, -TR, 12:00PM, 2:00PM, 2, 2,,,,, -TR, 2:00PM, 4:00PM, 2, 2,,,,, -TR, 4:00PM, 6:00PM, 2, 2,,,,, -TR, 5:00PM, 7:00PM, 2, 2,,,,, -TR, 6:00PM, 8:00PM, 2, 2,,,,, -TR, 7:00PM, 9:00PM, 2, 2,,,,, -TR, 8:00PM, 10:00PM, 2, 2,,,,, -MW, 7:00AM, 9:00AM, 1, 2,,,,, -MW, 8:00AM, 10:00AM, 1, 2,,,,, -MW, 9:00AM, 11:00AM, 1, 2,,,,, -MW, 10:00AM, 12:00PM, 1, 2,,,,, -MW, 11:00AM, 1:00PM, 1, 2,,,,, -MW, 12:00PM, 2:00PM, 1, 2,,,,, -MW, 1:00PM, 3:00PM, 1, 2,,,,, -MW, 2:00PM, 4:00PM, 1, 2,,,,, -MW, 3:00PM, 5:00PM, 1, 2,,,,, -MW, 4:00PM, 6:00PM, 1, 2,,,,, -MW, 5:00PM, 7:00PM, 1, 2,,,,, -MW, 6:00PM, 8:00PM, 1, 2,,,,, -MW, 7:00PM, 9:00PM, 1, 2,,,,, -WF, 7:00AM, 9:00AM, 1, 2,,,,, -WF, 8:00AM, 10:00AM, 1, 2,,,,, -WF, 9:00AM, 11:00AM, 1, 2,,,,, -WF, 10:00AM, 12:00PM, 1, 2,,,,, -WF, 11:00AM, 1:00PM, 1, 2,,,,, -WF, 12:00PM, 2:00PM, 1, 2,,,,, -WF, 1:00PM, 3:00PM, 1, 2,,,,, -WF, 2:00PM, 4:00PM, 1, 2,,,,, -WF, 3:00PM, 5:00PM, 1, 2,,,,, -WF, 4:00PM, 6:00PM, 1, 2,,,,, -WF, 5:00PM, 7:00PM, 1, 2,,,,, -WF, 6:00PM, 8:00PM, 1, 2,,,,, -WF, 7:00PM, 9:00PM, 1, 2,,,,, -TR, 7:00AM, 9:00AM, 1, 2,,,,, -TR, 8:00AM, 10:00AM, 1, 2,,,,, -TR, 9:00AM, 11:00AM, 1, 2,,,,, -TR, 10:00AM, 12:00PM, 1, 2,,,,, -TR, 11:00AM, 1:00PM, 1, 2,,,,, -TR, 12:00PM, 2:00PM, 1, 2,,,,, -TR, 1:00PM, 3:00PM, 1, 2,,,,, -TR, 2:00PM, 4:00PM, 1, 2,,,,, -TR, 3:00PM, 5:00PM, 1, 2,,,,, -TR, 4:00PM, 6:00PM, 1, 2,,,,, -TR, 5:00PM, 7:00PM, 1, 2,,,,, -TR, 6:00PM, 8:00PM, 1, 2,,,,, -TR, 7:00PM, 9:00PM, 1, 2,,,,, - - -FOR CPE -------------------------------------------------------------------------------- -days, time_start, time_end, lecture_hours, total_hours, days2, time_start2, time_end2, lecture_hours2, total_hours2 -MWF, 7:00AM, 9:00AM, 1, 2,,,,, -MWF, 8:00AM, 10:00AM, 1, 2,,,,, -MWF, 9:00AM, 11:00AM, 1, 2,,,,, -MWF, 10:00AM, 12:00PM, 1, 2,,,,, -MWF, 11:00AM, 1:00PM, 1, 2,,,,, -MWF, 12:00PM, 2:00PM, 1, 2,,,,, -MWF, 1:00PM, 3:00PM, 1, 2,,,,, -MWF, 2:00PM, 4:00PM, 1, 2,,,,, -MWF, 3:00PM, 5:00PM, 1, 2,,,,, -MWF, 4:00PM, 6:00PM, 1, 2,,,,, -MWF, 5:00PM, 7:00PM, 1, 2,,,,, -MWF, 6:00PM, 8:00PM, 1, 2,,,,, -MWF, 7:00PM, 9:00PM, 1, 2,,,,, -TR, 8:00AM, 11:00AM, 1.5, 3,,,,, -TR, 12:00PM, 3:00PM, 1.5, 3,,,,, -TR, 1:30PM, 4:30PM, 1.5, 3,,,,, -TR, 3:00PM, 6:00PM, 1.5, 3,,,,, -TR, 4:00PM, 7:00PM, 1.5, 3,,,,, -TR, 4:30PM, 7:30PM, 1.5, 3,,,,, -TR, 5:00PM, 8:00PM, 1.5, 3,,,,, -TR, 5:30PM, 8:30PM, 1.5, 3,,,,, -TR, 6:00PM, 9:00PM, 1.5, 3,,,,, -MTWR, 7:00AM, 8:00AM, 1, 1,,,,, -MTWR, 8:00AM, 9:00AM, 1, 1,,,,, -MTWR, 9:00AM, 10:00AM, 1, 1,,,,, -MTWR, 10:00AM, 11:00AM, 1, 1,,,,, -MTWR, 11:00AM, 12:00PM, 1, 1,,,,, -MTWR, 12:00PM, 1:00PM, 1, 1,,,,, -MTWR, 1:00PM, 2:00PM, 1, 1,,,,, -MTWR, 2:00PM, 3:00PM, 1, 1,,,,, -MTWR, 3:00PM, 4:00PM, 1, 1,,,,, -MWF, 7:00AM, 8:00AM, 1, 1, F, 8:00AM, 11:00AM, 3, 3 -MWF, 7:00AM, 8:00AM, 1, 1, W, 8:00AM, 11:00AM, 3, 3 -MWF, 7:00AM, 8:00AM, 1, 1, M, 8:00AM, 11:00AM, 3, 3 -MWF, 7:00AM, 8:00AM, 1, 1, F, 8:00AM, 10:00AM, 2, 2 -MWF, 7:00AM, 8:00AM, 1, 1, W, 8:00AM, 10:00AM, 2, 2 -MWF, 7:00AM, 8:00AM, 1, 1, M, 8:00AM, 10:00AM, 2, 2 -MWF, 8:00AM, 9:00AM, 1, 1, M, 9:00AM, 12:00PM, 3, 3 -MWF, 8:00AM, 9:00AM, 1, 1, W, 9:00AM, 12:00PM, 3, 3 -MWF, 8:00AM, 9:00AM, 1, 1, F, 9:00AM, 12:00PM, 3, 3 -MWF, 9:00AM, 10:00AM, 1, 1, W, 10:00AM, 1:00PM, 3, 3 -MWF, 10:00AM, 11:00AM, 1, 1, W, 11:00AM, 2:00PM, 3, 3 -MWF, 10:00AM, 11:00AM, 1, 1, W, 11:00AM, 1:00PM, 2, 2 -MWF, 10:00AM, 11:00AM, 1, 1, M, 11:00AM, 2:00PM, 3, 3 -MWF, 10:00AM, 11:00AM, 1, 1, F, 11:00AM, 2:00PM, 3, 3 -MWF, 11:00AM, 12:00PM, 1, 1, W, 12:00PM, 3:00PM, 3, 3 -MWF, 12:00PM, 1:00PM, 1, 1, F, 1:00PM, 4:00PM, 3, 3 -MWF, 1:00PM, 2:00PM, 1, 1, F, 2:00PM, 5:00PM, 3, 3 -MWF, 1:00PM, 2:00PM, 1, 1, W, 2:00PM, 5:00PM, 3, 3 -MWF, 1:00PM, 2:00PM, 1, 1, M, 2:00PM, 5:00PM, 3, 3 -MWF, 2:00PM, 3:00PM, 1, 1, M, 3:00PM, 6:00PM, 3, 3 -MWF, 3:00PM, 4:00PM, 1, 1, M, 4:00PM, 7:00PM, 3, 3 -MWF, 4:00PM, 5:00PM, 1, 1, W, 5:00PM, 8:00PM, 3, 3 -MWF, 5:00PM, 6:00PM, 1, 1, F, 6:00PM, 9:00PM, 3, 3 -MWF, 6:00PM, 7:00PM, 1, 1, F, 7:00PM, 10:00PM, 3, 3 -TR, 8:00AM, 9:30AM, 1.5, 1.5, T, 9:30AM, 11:30AM, 2, 2 -TR, 12:00PM, 1:30PM, 1.5, 1.5, T, 1:30PM, 3:30PM, 2, 2 -TR, 1:30PM, 3:00PM, 1.5, 1.5, T, 3:00PM, 5:00PM, 2, 2 -TR, 3:00PM, 4:30PM, 1.5, 1.5, T, 4:30PM, 6:30PM, 2, 2 -TR, 4:00PM, 5:30PM, 1.5, 1.5, T, 5:30PM, 7:30PM, 2, 2 -TR, 4:30PM, 6:00PM, 1.5, 1.5, T, 6:00PM, 8:00PM, 2, 2 -TR, 5:00PM, 6:30PM, 1.5, 1.5, T, 6:30PM, 8:30PM, 2, 2 -TR, 5:30PM, 7:00PM, 1.5, 1.5, T, 7:00PM, 9:00PM, 2, 2 -TR, 6:00PM, 7:30PM, 1.5, 1.5, T, 7:30PM, 9:30PM, 2, 2 -TR, 8:00AM, 9:30AM, 1.5, 1.5, T, 9:30AM, 12:30PM, 3, 3 -TR, 12:00PM, 1:30PM, 1.5, 1.5, T, 1:30PM, 4:30PM, 3, 3 -TR, 1:30PM, 3:00PM, 1.5, 1.5, T, 3:00PM, 6:00PM, 3, 3 -TR, 3:00PM, 4:30PM, 1.5, 1.5, T, 4:30PM, 7:30PM, 3, 3 -TR, 4:00PM, 5:30PM, 1.5, 1.5, T, 5:30PM, 8:30PM, 3, 3 -TR, 4:30PM, 6:00PM, 1.5, 1.5, T, 6:00PM, 9:00PM, 3, 3 -TR, 5:00PM, 6:30PM, 1.5, 1.5, T, 6:30PM, 9:30PM, 3, 3 -TR, 5:30PM, 7:00PM, 1.5, 1.5, T, 7:00PM, 10:00PM, 3, 3 -TR, 6:00PM, 7:30PM, 1.5, 1.5, T, 7:30PM, 10:30PM, 3, 3 -M, 7:00AM, 8:00AM, 1, 1, M, 8:00AM, 2:00PM, 6, 6 -M, 8:00AM, 9:00AM, 1, 1, M, 9:00AM, 3:00PM, 6, 6 -M, 9:00AM, 10:00AM, 1, 1, M, 10:00AM, 4:00PM, 6, 6 -M, 10:00AM, 11:00AM, 1, 1, M, 11:00AM, 5:00PM, 6, 6 -TR, 8:00AM, 9:30AM, 1.5, 1.5, R, 2:00PM, 5:00PM, 3, 3 -TR, 9:30AM, 11:00AM, 1.5, 1.5, T, 2:00PM, 5:00PM, 3, 3 From d4f858f3e1669769edc69f59bc26334233336da9 Mon Sep 17 00:00:00 2001 From: RandomCyberCoder Date: Thu, 14 May 2026 11:49:30 -0700 Subject: [PATCH 04/17] updated formatter constant name --- .../java/org/acme/schooltimetabling/constants/Constants.java | 2 +- .../org/acme/schooltimetabling/domain/lesson/Lesson.java | 5 ++--- .../acme/schooltimetabling/helperClasses/BitSetHelper.java | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/constants/Constants.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/constants/Constants.java index 40529b95..bc698a18 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/constants/Constants.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/constants/Constants.java @@ -27,7 +27,7 @@ public class Constants { /** * Global time formatter */ - public static final DateTimeFormatter TIME_FMT = DateTimeFormatter.ofPattern("h:mma"); + public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("h:mma"); /** * Set to True for testing. Helps by pass some checks * */ diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/domain/lesson/Lesson.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/domain/lesson/Lesson.java index 19334090..533ab121 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/domain/lesson/Lesson.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/domain/lesson/Lesson.java @@ -14,7 +14,6 @@ import org.slf4j.LoggerFactory; import java.time.LocalTime; -import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.BitSet; import java.util.List; @@ -313,8 +312,8 @@ public List> toJson(){ LocalTime endTime = BASE_TIME.plusMinutes((end + 1) * 30L); res.add(Map.of( "day", day.name(), - "start", startTime.format(Constants.TIME_FMT), - "end", endTime.format(Constants.TIME_FMT) + "start", startTime.format(Constants.TIME_FORMATTER), + "end", endTime.format(Constants.TIME_FORMATTER) )); start = dayBits.nextSetBit(end + 1); } diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/BitSetHelper.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/BitSetHelper.java index 8fb87738..32d28ccc 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/BitSetHelper.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/BitSetHelper.java @@ -194,8 +194,8 @@ public static BitSet timeJsonToBs(Map time) { if (time == null || time.get("day") == null || time.get("start") == null || time.get("end") == null) { throw new IllegalArgumentException("Time map must contain day, start, and end"); } - LocalTime start = LocalTime.parse(time.get("start"), Constants.TIME_FMT); - LocalTime end = LocalTime.parse(time.get("end"), Constants.TIME_FMT); + LocalTime start = LocalTime.parse(time.get("start"), Constants.TIME_FORMATTER); + LocalTime end = LocalTime.parse(time.get("end"), Constants.TIME_FORMATTER); LocalTime earliest = LocalTime.of(7, 0); LocalTime latest = LocalTime.of(22, 0); if (start.isBefore(earliest) || end.isAfter(latest) || !end.isAfter(start)) { From 3d0375f91a59b59240f9522893ceb6c852a4edbb Mon Sep 17 00:00:00 2001 From: RandomCyberCoder Date: Thu, 14 May 2026 11:50:53 -0700 Subject: [PATCH 05/17] default times prototypes, singletons, and registry created --- .../DefaultTimes/DefaultTime.java | 16 ++++ .../DefaultTimes/DefaultTimeAll.java | 77 +++++++++++++++++++ .../DefaultTimes/DefaultTimeEvening.java | 77 +++++++++++++++++++ .../DefaultTimes/DefaultTimeMorning.java | 77 +++++++++++++++++++ .../DefaultTimes/DefaultTimeRegistry.java | 25 ++++++ 5 files changed, 272 insertions(+) create mode 100644 java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTime.java create mode 100644 java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeAll.java create mode 100644 java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeEvening.java create mode 100644 java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeMorning.java create mode 100644 java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeRegistry.java diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTime.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTime.java new file mode 100644 index 00000000..b3613892 --- /dev/null +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTime.java @@ -0,0 +1,16 @@ +package org.acme.schooltimetabling.DefaultTimes; + +import java.util.BitSet; + +/** + * All classes that inherit this class will be a part of a prototype pattern; + * Each class should be implemented as a singleton + * When implementing this class, the classes should make sure that the preference, acceptable, and conflict + * {@link BitSet}s cover the whole time span of + * 7AM-10PM for MTWRF + */ +public interface DefaultTime { + BitSet getPreference(); + BitSet getAcceptable(); + BitSet getConflict(); +} diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeAll.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeAll.java new file mode 100644 index 00000000..1e84cc7a --- /dev/null +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeAll.java @@ -0,0 +1,77 @@ +package org.acme.schooltimetabling.DefaultTimes; + +import org.acme.schooltimetabling.constants.Constants; +import org.acme.schooltimetabling.constants.Days; +import org.acme.schooltimetabling.helperClasses.BitSetHelper; + +import java.util.BitSet; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.util.EnumSet; +import java.util.List; + +public class DefaultTimeAll implements DefaultTime{ + private static final DefaultTimeAll INSTANCE; + private BitSet conflict; + private BitSet acceptable; + private BitSet preference; + + static { + INSTANCE = new DefaultTimeAll(); + INSTANCE.conflict = new BitSet(); + INSTANCE.acceptable = new BitSet(); + INSTANCE.preference = new BitSet(); + + final int NUM_BLOCKS_FULL_HOUR = 2; + final DateTimeFormatter FORMATTER = Constants.TIME_FORMATTER; + EnumSet defaultDays = EnumSet.allOf(Days.class); + + List acceptableTimes = List.of( + LocalTime.parse("8:00AM", FORMATTER), + LocalTime.parse("9:00AM", FORMATTER), + LocalTime.parse("10:00AM", FORMATTER), + LocalTime.parse("11:00AM", FORMATTER), + LocalTime.parse("12:00PM", FORMATTER), + LocalTime.parse("1:00PM", FORMATTER), + LocalTime.parse("2:00PM", FORMATTER), + LocalTime.parse("3:00PM", FORMATTER), + LocalTime.parse("4:00PM", FORMATTER), + LocalTime.parse("5:00PM", FORMATTER) + ); + for(LocalTime localTime : acceptableTimes) { + INSTANCE.acceptable.or(BitSetHelper.timeSlotBitSet(localTime, NUM_BLOCKS_FULL_HOUR, defaultDays)); + } + + List conflictTimes = List.of( + LocalTime.parse("7:00AM", FORMATTER), + LocalTime.parse("6:00PM", FORMATTER), + LocalTime.parse("7:00PM", FORMATTER), + LocalTime.parse("8:00PM", FORMATTER), + LocalTime.parse("9:00PM", FORMATTER) + ); + for(LocalTime localTime : conflictTimes) { + INSTANCE.conflict.or(BitSetHelper.timeSlotBitSet(localTime, NUM_BLOCKS_FULL_HOUR, defaultDays)); + } + } + + private DefaultTimeAll(){} + + public static DefaultTimeAll getInstance(){ + return INSTANCE; + } + + @Override + public BitSet getPreference(){ + return (BitSet) preference.clone(); + } + + @Override + public BitSet getAcceptable() { + return (BitSet) acceptable.clone(); + } + + @Override + public BitSet getConflict() { + return (BitSet) conflict.clone(); + } +} diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeEvening.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeEvening.java new file mode 100644 index 00000000..32722318 --- /dev/null +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeEvening.java @@ -0,0 +1,77 @@ +package org.acme.schooltimetabling.DefaultTimes; + +import org.acme.schooltimetabling.constants.Constants; +import org.acme.schooltimetabling.constants.Days; +import org.acme.schooltimetabling.helperClasses.BitSetHelper; + +import java.util.BitSet; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.util.EnumSet; +import java.util.List; + +public class DefaultTimeEvening implements DefaultTime{ + private static final DefaultTimeEvening INSTANCE; + private BitSet conflict; + private BitSet acceptable; + private BitSet preference; + + static { + INSTANCE = new DefaultTimeEvening(); + INSTANCE.conflict = new BitSet(); + INSTANCE.acceptable = new BitSet(); + INSTANCE.preference = new BitSet(); + + final int NUM_BLOCKS_FULL_HOUR = 2; + DateTimeFormatter FORMATTER = Constants.TIME_FORMATTER; + EnumSet defaultDays = EnumSet.allOf(Days.class); + + List acceptableTimes = List.of( + LocalTime.parse("1:00PM", FORMATTER), + LocalTime.parse("2:00PM", FORMATTER), + LocalTime.parse("3:00PM", FORMATTER), + LocalTime.parse("4:00PM", FORMATTER), + LocalTime.parse("5:00PM", FORMATTER) + ); + for (LocalTime localTime : acceptableTimes) { + INSTANCE.acceptable.or(BitSetHelper.timeSlotBitSet(localTime, NUM_BLOCKS_FULL_HOUR, defaultDays)); + } + + List conflictTimes = List.of( + LocalTime.parse("7:00AM", FORMATTER), + LocalTime.parse("8:00AM", FORMATTER), + LocalTime.parse("9:00AM", FORMATTER), + LocalTime.parse("10:00AM", FORMATTER), + LocalTime.parse("11:00AM", FORMATTER), + LocalTime.parse("12:00PM", FORMATTER), + LocalTime.parse("6:00PM", FORMATTER), + LocalTime.parse("7:00PM", FORMATTER), + LocalTime.parse("8:00PM", FORMATTER), + LocalTime.parse("9:00PM", FORMATTER) + ); + for (LocalTime localTime : conflictTimes) { + INSTANCE.conflict.or(BitSetHelper.timeSlotBitSet(localTime, NUM_BLOCKS_FULL_HOUR, defaultDays)); + } + } + + private DefaultTimeEvening() {} + + public static DefaultTimeEvening getInstance() { + return INSTANCE; + } + + @Override + public BitSet getPreference() { + return (BitSet) preference.clone(); + } + + @Override + public BitSet getAcceptable() { + return (BitSet) acceptable.clone(); + } + + @Override + public BitSet getConflict() { + return null; + } +} diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeMorning.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeMorning.java new file mode 100644 index 00000000..db0c3bbc --- /dev/null +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeMorning.java @@ -0,0 +1,77 @@ +package org.acme.schooltimetabling.DefaultTimes; + +import org.acme.schooltimetabling.constants.Constants; +import org.acme.schooltimetabling.constants.Days; +import org.acme.schooltimetabling.helperClasses.BitSetHelper; + +import java.util.BitSet; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.util.EnumSet; +import java.util.List; + +public class DefaultTimeMorning implements DefaultTime { + private static final DefaultTimeMorning INSTANCE; + private BitSet conflict; + private BitSet acceptable; + private BitSet preference; + + static { + INSTANCE = new DefaultTimeMorning(); + INSTANCE.conflict = new BitSet(); + INSTANCE.acceptable = new BitSet(); + INSTANCE.preference = new BitSet(); + + final int NUM_BLOCKS_FULL_HOUR = 2; + DateTimeFormatter FORMATTER = Constants.TIME_FORMATTER; + EnumSet defaultDays = EnumSet.allOf(Days.class); + + List acceptableTimes = List.of( + LocalTime.parse("8:00AM", FORMATTER), + LocalTime.parse("9:00AM", FORMATTER), + LocalTime.parse("10:00AM", FORMATTER), + LocalTime.parse("11:00AM", FORMATTER), + LocalTime.parse("12:00PM", FORMATTER) + ); + for (LocalTime localTime : acceptableTimes) { + INSTANCE.acceptable.or(BitSetHelper.timeSlotBitSet(localTime, NUM_BLOCKS_FULL_HOUR, defaultDays)); + } + + List conflictTimes = List.of( + LocalTime.parse("7:00AM", FORMATTER), + LocalTime.parse("1:00PM", FORMATTER), + LocalTime.parse("2:00PM", FORMATTER), + LocalTime.parse("3:00PM", FORMATTER), + LocalTime.parse("4:00PM", FORMATTER), + LocalTime.parse("5:00PM", FORMATTER), + LocalTime.parse("6:00PM", FORMATTER), + LocalTime.parse("7:00PM", FORMATTER), + LocalTime.parse("8:00PM", FORMATTER), + LocalTime.parse("9:00PM", FORMATTER) + ); + for (LocalTime localTime : conflictTimes) { + INSTANCE.conflict.or(BitSetHelper.timeSlotBitSet(localTime, NUM_BLOCKS_FULL_HOUR, defaultDays)); + } + } + + private DefaultTimeMorning() {} + + public static DefaultTimeMorning getInstance() { + return INSTANCE; + } + + @Override + public BitSet getConflict() { + return (BitSet) conflict.clone(); + } + + @Override + public BitSet getAcceptable() { + return (BitSet) acceptable.clone(); + } + + @Override + public BitSet getPreference() { + return (BitSet) preference.clone(); + } +} diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeRegistry.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeRegistry.java new file mode 100644 index 00000000..37d3b729 --- /dev/null +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeRegistry.java @@ -0,0 +1,25 @@ +package org.acme.schooltimetabling.DefaultTimes; + +import java.util.List; +import java.util.Random; +import java.util.function.Supplier; + +public class DefaultTimeRegistry { + private static final List> defaultTimes = List.of( + DefaultTimeAll::getInstance +// , DefaultTimeMorning::getInstance +// , DefaultTimeEvening::getInstance + ); + private static final Random RANDOM = new Random(); + + /** + * get a random default time. Then you can get the preferences, acceptable, and conflict times for this + * default time schedule + * @return Default time schedule allowing you to copy bitsets + */ + public static DefaultTime getRandomDefault(){ + int size = defaultTimes.size(); + int choice = RANDOM.nextInt(size); + return defaultTimes.get(choice).get(); + } +} From 671129a602f08845d455ba65b7909ed2684d9902 Mon Sep 17 00:00:00 2001 From: RandomCyberCoder Date: Thu, 14 May 2026 12:14:39 -0700 Subject: [PATCH 06/17] lesson generator updated to use default schedules when needed --- .../Generators/LessonGenerator.java | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/LessonGenerator.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/LessonGenerator.java index 6e14fcdf..b2ef77c1 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/LessonGenerator.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/LessonGenerator.java @@ -1,5 +1,7 @@ package org.acme.schooltimetabling.helperClasses.Generators; +import org.acme.schooltimetabling.DefaultTimes.DefaultTime; +import org.acme.schooltimetabling.DefaultTimes.DefaultTimeRegistry; import org.acme.schooltimetabling.constants.Constants; import org.acme.schooltimetabling.constants.Preference; import org.acme.schooltimetabling.domain.lesson.Lesson; @@ -168,26 +170,29 @@ private static Lesson generateLesson(Map teacherHashMap, Mapteacher name; if no associated object - * exists, then one is created, but with no conflict, preference, or acceptable times + * exists, then one is created, using a default schedule from {@link DefaultTimeRegistry} * * @param teacherHashMap map with a canon name as a key and teacher object as a value * @param teacherName canon teacher name * @return teacher object for given teacher name - * @see LessonGenerator#noSurveyTeacher(String) + * @see LessonGenerator#noSurveyTeacher(String, DefaultTime) */ private static Teacher getTeacher(Map teacherHashMap, String teacherName){ /*checking if we can find the teacher; skip teacher if we can't * find their teacher object*/ Teacher teacher = teacherHashMap.get(teacherName); if(teacher == null){ + DefaultTime defaultTime = DefaultTimeRegistry.getRandomDefault(); + if(Constants.DEBUG){ LOGGER.warn(String.format("Couldn't find a teacher object for '%s'. Most likely due to them not having" + " a survey filled out or old noncanon-canon mapping is used;" + - "Creating one for them with now with no conflict, pref, or acceptable times.", teacherName)); + "Creating one for them with now using the default time %s.", teacherName, + defaultTime.getClass().getSimpleName())); } //create teacher object - teacher = noSurveyTeacher(teacherName); + teacher = noSurveyTeacher(teacherName, defaultTime); //add prescheduled times if possible if(PRESCHED_TIMES.containsKey(teacherName)){ @@ -310,15 +315,16 @@ private static boolean skipCourse(String modifier, String name, String config){ /** * This function is used to create a teacher object during lesson creation if a teacher object can't be found - * for the name. It will return a faculty object if the person is found to be a faculty member. Note that the object - * returned will have empty conflict, preferences, and acceptable BitSets. + * for the name. It will return a faculty object if the person is found to be a faculty member. The object returned + * will have a copy of the preference, acceptable, and conflict {@link BitSet} as the {@link DefaultTime} prototype + * object * * @param name name of teacher. Assumes it's in canon name format (i.e. <last name>, <rest of name>) * @return a teacher object; or faculty if found to be a faculty member * @see Teacher * @see Faculty */ - private static Teacher noSurveyTeacher(String name){ + private static Teacher noSurveyTeacher(String name, DefaultTime defaultTime){ final int LAST_NAME_POS = 0; String[] nameFragments = name.split(","); @@ -329,7 +335,10 @@ private static Teacher noSurveyTeacher(String name){ Preference.NEUTRAL); } - return new Teacher(TeacherGenerator.getNextTeacherID(), name, new BitSet(), new BitSet(), new BitSet(), + return new Teacher(TeacherGenerator.getNextTeacherID(), name, + defaultTime.getPreference(), + defaultTime.getAcceptable(), + defaultTime.getConflict(), Preference.NEUTRAL); } From 37dd411253ce12c443ec362169fe0c9b842a4ee2 Mon Sep 17 00:00:00 2001 From: RandomCyberCoder Date: Fri, 15 May 2026 00:51:40 -0700 Subject: [PATCH 07/17] old surveys if no other option. confg/defaults updated --- .../schooltimetabling/DefaultTimes/DefaultTimeAll.java | 2 +- .../helperClasses/Generators/TeacherGenerator.java | 7 +++++++ java/hello-world/src/main/resources/solverConfig.xml | 10 +++++----- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeAll.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeAll.java index 1e84cc7a..b31324b3 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeAll.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeAll.java @@ -27,6 +27,7 @@ public class DefaultTimeAll implements DefaultTime{ EnumSet defaultDays = EnumSet.allOf(Days.class); List acceptableTimes = List.of( + LocalTime.parse("7:00AM", FORMATTER), LocalTime.parse("8:00AM", FORMATTER), LocalTime.parse("9:00AM", FORMATTER), LocalTime.parse("10:00AM", FORMATTER), @@ -43,7 +44,6 @@ public class DefaultTimeAll implements DefaultTime{ } List conflictTimes = List.of( - LocalTime.parse("7:00AM", FORMATTER), LocalTime.parse("6:00PM", FORMATTER), LocalTime.parse("7:00PM", FORMATTER), LocalTime.parse("8:00PM", FORMATTER), diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/TeacherGenerator.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/TeacherGenerator.java index bf7d3a50..aaaf7be0 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/TeacherGenerator.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/TeacherGenerator.java @@ -175,6 +175,13 @@ public static HashMap generateTeachers(List - + 1 2hard/10medium/20soft @@ -60,16 +60,16 @@ OR - 20 + 30 0hard/1medium/*soft - - - + 1 + + 3 3hard/5medium/5soft From 6c06d313afc93e17a4f1d3c5e859f975ad3a0436 Mon Sep 17 00:00:00 2001 From: RandomCyberCoder Date: Fri, 15 May 2026 12:39:59 -0700 Subject: [PATCH 08/17] prescheduling done, but needs more checks --- .../acme/schooltimetabling/domain/Room.java | 16 ++ .../helperClasses/BitSetHelper.java | 15 ++ .../Generators/LessonGenerator.java | 8 +- .../Generators/RoomGenerator.java | 25 ++- .../Generators/TeacherGenerator.java | 21 +-- .../helperClasses/ParseInput.java | 14 +- .../helperClasses/PrescheduleObject.java | 149 ++++++++++++++++++ .../helperClasses/ResultSaver.java | 11 +- 8 files changed, 236 insertions(+), 23 deletions(-) create mode 100644 java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/PrescheduleObject.java diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/domain/Room.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/domain/Room.java index 85c96d39..28708c91 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/domain/Room.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/domain/Room.java @@ -2,6 +2,8 @@ import ai.timefold.solver.core.api.domain.lookup.PlanningId; +import java.util.BitSet; + public class Room { @PlanningId @@ -12,12 +14,18 @@ public class Room { * of what is needed for scheduling. Anything else is for debugging * but even that could be found in the hashmaps that have been created*/ private int ID; + + private BitSet prescheduled; + + public static boolean hasPrescheduled = false; + public Room() { } public Room(String id, String name) { this.id = id; this.name = name; + this.prescheduled = new BitSet(); } public Room(String id, String name, int ID){ @@ -46,4 +54,12 @@ public String getName() { public int getID() { return ID; } + + public BitSet getPrescheduled(){ + return (BitSet) prescheduled.clone(); + } + + public void prescheduleUpdate(BitSet addBitset){ + if(addBitset != null) this.prescheduled.or(addBitset); + } } diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/BitSetHelper.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/BitSetHelper.java index 32d28ccc..ebdff419 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/BitSetHelper.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/BitSetHelper.java @@ -1,6 +1,7 @@ package org.acme.schooltimetabling.helperClasses; import org.acme.schooltimetabling.constants.Constants; import org.acme.schooltimetabling.constants.Days; +import org.acme.schooltimetabling.helperClasses.PrescheduleObject.PrescheduledWindow; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -212,4 +213,18 @@ public static BitSet timeJsonToBs(Map time) { bitSet.set(dayOffset + startBlock, dayOffset + endBlock); return bitSet; } + + public static BitSet timeJsonToBs(PrescheduledWindow time) { + if (time == null) { + throw new IllegalArgumentException("Time window must not be null"); + } + + Map mappedTime = Map.of( + "day", time.getDay(), + "start", time.getStart(), + "end", time.getEnd() + ); + + return timeJsonToBs(mappedTime); + } } diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/LessonGenerator.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/LessonGenerator.java index b2ef77c1..6e8d923f 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/LessonGenerator.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/LessonGenerator.java @@ -7,6 +7,7 @@ import org.acme.schooltimetabling.domain.lesson.Lesson; import org.acme.schooltimetabling.domain.teacher.Faculty; import org.acme.schooltimetabling.helperClasses.ParseInput; +import org.acme.schooltimetabling.helperClasses.PrescheduleObject; import org.acme.schooltimetabling.helperClasses.ScheduleConfig; import org.acme.schooltimetabling.helperClasses.ScheduleFormat; import org.acme.schooltimetabling.domain.teacher.Teacher; @@ -21,7 +22,8 @@ public class LessonGenerator extends Generator{ public static boolean OLD_studio_detected = false; public static boolean proper_studio_detected = false; private static final Logger LOGGER = LoggerFactory.getLogger(LessonGenerator.class); - private static final Map>> PRESCHED_TIMES = ParseInput.readPrescheduledFile(); + private static final PrescheduleObject PRESCHED_TIMES = ScheduleConfig.getPrescheduledFileName() != null ? + ParseInput.readPrescheduledFile() : null; /** * Keeps track of the next available section number available for a course */ @@ -195,12 +197,12 @@ private static Teacher getTeacher(Map teacherHashMap, String te teacher = noSurveyTeacher(teacherName, defaultTime); //add prescheduled times if possible - if(PRESCHED_TIMES.containsKey(teacherName)){ + if(PRESCHED_TIMES != null && PRESCHED_TIMES.getTeachers().containsKey(teacherName)){ LOGGER.info(String.format("Found a prescheduled time for '%s'. Adding the time to their conflict bitset.", teacherName)); try { - BitSet addConflict = TeacherGenerator.createPreschedBs(PRESCHED_TIMES.get(teacherName)); + BitSet addConflict = TeacherGenerator.createPreschedBs(PRESCHED_TIMES.getTeachers().get(teacherName)); teacher.getAcceptable().andNot(addConflict); teacher.getPreferences().andNot(addConflict); teacher.getConflict().or(addConflict); diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/RoomGenerator.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/RoomGenerator.java index 36ba8251..472914ea 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/RoomGenerator.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/RoomGenerator.java @@ -2,10 +2,22 @@ import org.acme.schooltimetabling.constants.Constants; import org.acme.schooltimetabling.domain.Room; +import org.acme.schooltimetabling.helperClasses.BitSetHelper; +import org.acme.schooltimetabling.helperClasses.ParseInput; +import org.acme.schooltimetabling.helperClasses.PrescheduleObject; +import org.acme.schooltimetabling.helperClasses.ScheduleConfig; +import org.apache.commons.math3.random.BitsStreamGenerator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.ArrayList; +import java.util.BitSet; public class RoomGenerator extends Generator{ + private static final PrescheduleObject PRESCHED_TIMES = ScheduleConfig.getPrescheduledFileName() != null ? + ParseInput.readPrescheduledFile() : null; + private static final Logger LOGGER = LoggerFactory.getLogger(RoomGenerator.class); + /** * Generates a list of rooms that are specified in the {@link Constants#POSSIBLE_ROOMS Constants.POSSIBLE_ROOMS} * constant. This includes all lab rooms and a special room used for lecture only courses @@ -32,7 +44,18 @@ public static ArrayList generateRooms(){ */ private static Room generateRoom(String roomName){ int roomID = Constants.ROOM_TO_ID_BIMAP.get(roomName); - return new Room(String.valueOf(roomID), roomName, roomID); + Room room = new Room(String.valueOf(roomID), roomName, roomID); + + //check for prescheduling + if(PRESCHED_TIMES != null && PRESCHED_TIMES.getRooms().containsKey(roomName)){ + LOGGER.info("Found prescheduling times for room '{}'. Using prescheduling times.", roomName); + for(PrescheduleObject.PrescheduledWindow prescheduledWindow: PRESCHED_TIMES.getRooms().get(roomName)){ + BitSet preBs = BitSetHelper.timeJsonToBs(prescheduledWindow); + room.prescheduleUpdate(preBs); + } + } + + return room; } } diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/TeacherGenerator.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/TeacherGenerator.java index aaaf7be0..20c3ec7f 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/TeacherGenerator.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/TeacherGenerator.java @@ -4,18 +4,16 @@ import org.acme.schooltimetabling.apiCalls.surveyEndpoint.SurveyRecord; import org.acme.schooltimetabling.apiCalls.teacherEndpoint.TeacherRecord; import org.acme.schooltimetabling.constants.Constants; -import org.acme.schooltimetabling.constants.Days; import org.acme.schooltimetabling.constants.Preference; import org.acme.schooltimetabling.domain.teacher.Faculty; import org.acme.schooltimetabling.helperClasses.BitSetHelper; +import org.acme.schooltimetabling.helperClasses.PrescheduleObject; import org.acme.schooltimetabling.domain.teacher.Teacher; import org.acme.schooltimetabling.helperClasses.ParseInput; import org.acme.schooltimetabling.helperClasses.ScheduleConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.time.LocalTime; -import java.time.format.DateTimeFormatter; import java.util.*; public class TeacherGenerator extends Generator{ @@ -97,8 +95,10 @@ public static Map teacherGenDriver(){ if(ScheduleConfig.getPrescheduledFileName() != null){ LOGGER.info("Reading in prescheduled time file"); - Map>> preschedTimes = ParseInput.readPrescheduledFile(); - if(!preschedTimes.isEmpty()) prescheduleUpdate(teacherMap, preschedTimes); + PrescheduleObject preschedTimes = ParseInput.readPrescheduledFile(); + if(preschedTimes.hasTeachers()) { + prescheduleUpdate(teacherMap, preschedTimes.getTeachers()); + } } return teacherMap; @@ -268,10 +268,11 @@ private static Teacher generateTeacher(HashMap surveyEntry){ } - private static void prescheduleUpdate(Map teacherMap, Map>> presched){ - Iterator>>> iterator = presched.entrySet().iterator(); + private static void prescheduleUpdate(Map teacherMap, + Map> presched){ + Iterator>> iterator = presched.entrySet().iterator(); while (iterator.hasNext()) { - Map.Entry>> entry = iterator.next(); + Map.Entry> entry = iterator.next(); String name = entry.getKey(); Teacher teacher = teacherMap.get(name); if (teacher == null){ @@ -302,9 +303,9 @@ private static void prescheduleUpdate(Map teacherMap, Map> timeJson){ + public static BitSet createPreschedBs(List timeJson){ BitSet bs = new BitSet(); - for(Map time: timeJson){ + for(PrescheduleObject.PrescheduledWindow time: timeJson){ bs.or(BitSetHelper.timeJsonToBs(time)); } diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/ParseInput.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/ParseInput.java index acd4700e..52ef8539 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/ParseInput.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/ParseInput.java @@ -218,18 +218,20 @@ public static Set getFaculty(String file) { return faculty; } - public static Map>> readPrescheduledFile(){ + public static PrescheduleObject readPrescheduledFile(){ String filePath = "input/" + ScheduleConfig.getPrescheduledFileName(); try(InputStream inputStream = getResourceAsStream(filePath)){ ObjectMapper mapper = new ObjectMapper(); - - return mapper.readValue(inputStream, new TypeReference<>() {}); + PrescheduleObject prescheduleObject = mapper.readValue(inputStream, PrescheduleObject.class); + prescheduleObject.validate(); + return prescheduleObject; } catch (Exception e) { ParseInput.LOGGER.error("ERROR reading file containing teachers prescheduled times. Skipping inclusion of " + - "these times."); - return new HashMap<>(); + "these times. System existing..."); + e.printStackTrace(); + System.exit(1); + throw new IllegalStateException("Failed to read prescheduled file", e); } } - } diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/PrescheduleObject.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/PrescheduleObject.java new file mode 100644 index 00000000..7c7d86ca --- /dev/null +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/PrescheduleObject.java @@ -0,0 +1,149 @@ +package org.acme.schooltimetabling.helperClasses; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class PrescheduleObject { + + private Map> teachers = new LinkedHashMap<>(); + private Map> rooms = new LinkedHashMap<>(); + + public PrescheduleObject() { + } + + @JsonProperty("teachers") + public Map> getTeachers() { + return teachers; + } + + public void setTeachers(Map> teachers) { + this.teachers = teachers; + } + + @JsonProperty("rooms") + public Map> getRooms() { + return rooms; + } + + public void setRooms(Map> rooms) { + this.rooms = rooms; + } + + public boolean hasTeachers() { + return teachers != null; + } + + public boolean hasRooms() { + return rooms != null; + } + + /** + * Checks to make sure that the JSON object has all the fields that are necessary + */ + public void validate() { + if (!hasTeachers()) { + throw new IllegalStateException("PrescheduleObject must contain at least one teacher entry."); + } + if (!hasRooms()) { + throw new IllegalStateException("PrescheduleObject must contain at least one room entry."); + } + + validateWindows("teacher", teachers); + validateWindows("room", rooms); + } + + private void validateWindows(String category, Map> entries) { + for (Map.Entry> entry : entries.entrySet()) { + if (entry.getValue() == null || entry.getValue().isEmpty()) { + throw new IllegalStateException("PrescheduleObject contains no windows for " + category + " '" + + entry.getKey() + "'."); + } + for (PrescheduledWindow window : entry.getValue()) { + if (window == null) { + throw new IllegalStateException("PrescheduleObject contains a null window for " + category + " '" + + entry.getKey() + "'."); + } + window.validate(category, entry.getKey()); + } + } + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static class PrescheduledWindow { + @JsonProperty("start") + private String start; + @JsonProperty("day") + private String day; + @JsonProperty("end") + private String end; + + public PrescheduledWindow() { + } + + public PrescheduledWindow(String start, String day, String end) { + this.start = start; + this.day = day; + this.end = end; + } + + public void setStart(String start) { + this.start = start; + } + + public void setDay(String day) { + this.day = day; + } + + public void setEnd(String end) { + this.end = end; + } + + public String getStart() { + return start; + } + + public String getDay() { + return day; + } + + public String getEnd() { + return end; + } + + public void validate(String category, String ownerName) { + if (start == null || start.isBlank()) { + throw new IllegalStateException("Missing start for " + category + " '" + ownerName + "'."); + } + if (day == null || day.isBlank()) { + throw new IllegalStateException("Missing day for " + category + " '" + ownerName + "'."); + } + if (end == null || end.isBlank()) { + throw new IllegalStateException("Missing end for " + category + " '" + ownerName + "'."); + } + } + } + + public static PrescheduleObject empty() { + return new PrescheduleObject(); + } + + /** + * Add a new Prescheduled Window for a teacher + */ + public void addTeacherWindow(String teacherName, PrescheduledWindow window) { + teachers.computeIfAbsent(teacherName, ignored -> new ArrayList<>()).add(window); + } + + /** + * Add a new Prescheduled Window for a room + */ + public void addRoomWindow(String roomName, PrescheduledWindow window) { + rooms.computeIfAbsent(roomName, ignored -> new ArrayList<>()).add(window); + } +} diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/ResultSaver.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/ResultSaver.java index 659946a6..ccf57811 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/ResultSaver.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/ResultSaver.java @@ -527,14 +527,19 @@ public void teacherTimesToJson() throws IOException { //we only consider lessons that don't violate any hard constraints as actually being scheduled List lsWithNoHard = extracted.getKey(); - Map>> res = new HashMap<>(); + Map>> teachers = new LinkedHashMap<>(); + Map>> rooms = new LinkedHashMap<>(); for(Lesson lesson: lsWithNoHard){ final String teacherName = lesson.getTeacherObj().getName(); - if(!res.containsKey(teacherName)) res.put(teacherName, new ArrayList<>()); - List> teacherMap = res.get(teacherName); + if(!teachers.containsKey(teacherName)) teachers.put(teacherName, new ArrayList<>()); + List> teacherMap = teachers.get(teacherName); teacherMap.addAll(lesson.toJson()); } + Map res = new LinkedHashMap<>(); + res.put("teachers", teachers); + res.put("rooms", rooms); + Scanner retryScanner = new Scanner(System.in); boolean retryAllowed = true; From 800af340dc83cda63db4a6357ef2bb1ccae5a0d8 Mon Sep 17 00:00:00 2001 From: RandomCyberCoder Date: Fri, 15 May 2026 12:45:54 -0700 Subject: [PATCH 09/17] updated preschedule example file --- generated/scheduled_times_dump.example.json | 151 +++++++++++--------- 1 file changed, 81 insertions(+), 70 deletions(-) diff --git a/generated/scheduled_times_dump.example.json b/generated/scheduled_times_dump.example.json index c8a6180d..0e757824 100644 --- a/generated/scheduled_times_dump.example.json +++ b/generated/scheduled_times_dump.example.json @@ -1,71 +1,82 @@ { - "LastName, FirstName": [ - { - "start": "10:00AM", - "day": "MONDAY", - "end": "12:00PM" - }, - { - "start": "10:00AM", - "day": "WEDNESDAY", - "end": "12:00PM" - }, - { - "start": "10:00AM", - "day": "FRIDAY", - "end": "12:00PM" - }, - { - "start": "4:00PM", - "day": "MONDAY", - "end": "6:00PM" - }, - { - "start": "4:00PM", - "day": "WEDNESDAY", - "end": "6:00PM" - }, - { - "start": "4:00PM", - "day": "FRIDAY", - "end": "6:00PM" - }, - { - "start": "12:00PM", - "day": "MONDAY", - "end": "2:00PM" - }, - { - "start": "12:00PM", - "day": "WEDNESDAY", - "end": "2:00PM" - }, - { - "start": "12:00PM", - "day": "FRIDAY", - "end": "2:00PM" - } - ], - "LastName2, FirstName2": [ - { - "start": "9:00AM", - "day": "MONDAY", - "end": "10:30AM" - }, - { - "start": "9:00AM", - "day": "WEDNESDAY", - "end": "10:30AM" - }, - { - "start": "11:00AM", - "day": "MONDAY", - "end": "1:00PM" - }, - { - "start": "11:00AM", - "day": "WEDNESDAY", - "end": "1:00PM" - } - ] -} \ No newline at end of file + "teachers": { + "LastName, FirstName": [ + { + "start": "10:00AM", + "day": "MONDAY", + "end": "12:00PM" + }, + { + "start": "10:00AM", + "day": "WEDNESDAY", + "end": "12:00PM" + }, + { + "start": "10:00AM", + "day": "FRIDAY", + "end": "12:00PM" + }, + { + "start": "4:00PM", + "day": "MONDAY", + "end": "6:00PM" + }, + { + "start": "4:00PM", + "day": "WEDNESDAY", + "end": "6:00PM" + }, + { + "start": "4:00PM", + "day": "FRIDAY", + "end": "6:00PM" + }, + { + "start": "12:00PM", + "day": "MONDAY", + "end": "2:00PM" + }, + { + "start": "12:00PM", + "day": "WEDNESDAY", + "end": "2:00PM" + }, + { + "start": "12:00PM", + "day": "FRIDAY", + "end": "2:00PM" + } + ], + "LastName2, FirstName2": [ + { + "start": "9:00AM", + "day": "MONDAY", + "end": "10:30AM" + }, + { + "start": "9:00AM", + "day": "WEDNESDAY", + "end": "10:30AM" + }, + { + "start": "11:00AM", + "day": "MONDAY", + "end": "1:00PM" + }, + { + "start": "11:00AM", + "day": "WEDNESDAY", + "end": "1:00PM" + } + ] + }, + "rooms": { + "Room 101": [ + { + "start": "8:00AM", + "day": "TUESDAY", + "end": "9:30AM" + } + ] + } +} From a810b39f895c22ee8e3832cd3c9337a797b23884 Mon Sep 17 00:00:00 2001 From: RandomCyberCoder Date: Fri, 15 May 2026 12:51:32 -0700 Subject: [PATCH 10/17] updated package name --- .../org/acme/schooltimetabling/DefaultTimes/DefaultTime.java | 2 +- .../acme/schooltimetabling/DefaultTimes/DefaultTimeAll.java | 2 +- .../schooltimetabling/DefaultTimes/DefaultTimeEvening.java | 2 +- .../schooltimetabling/DefaultTimes/DefaultTimeMorning.java | 2 +- .../schooltimetabling/DefaultTimes/DefaultTimeRegistry.java | 2 +- .../helperClasses/Generators/LessonGenerator.java | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTime.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTime.java index b3613892..0db7e690 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTime.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTime.java @@ -1,4 +1,4 @@ -package org.acme.schooltimetabling.DefaultTimes; +package org.acme.schooltimetabling.defaultTimes; import java.util.BitSet; diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeAll.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeAll.java index b31324b3..d4d02d93 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeAll.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeAll.java @@ -1,4 +1,4 @@ -package org.acme.schooltimetabling.DefaultTimes; +package org.acme.schooltimetabling.defaultTimes; import org.acme.schooltimetabling.constants.Constants; import org.acme.schooltimetabling.constants.Days; diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeEvening.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeEvening.java index 32722318..dd0867f6 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeEvening.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeEvening.java @@ -1,4 +1,4 @@ -package org.acme.schooltimetabling.DefaultTimes; +package org.acme.schooltimetabling.defaultTimes; import org.acme.schooltimetabling.constants.Constants; import org.acme.schooltimetabling.constants.Days; diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeMorning.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeMorning.java index db0c3bbc..2f6230c0 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeMorning.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeMorning.java @@ -1,4 +1,4 @@ -package org.acme.schooltimetabling.DefaultTimes; +package org.acme.schooltimetabling.defaultTimes; import org.acme.schooltimetabling.constants.Constants; import org.acme.schooltimetabling.constants.Days; diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeRegistry.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeRegistry.java index 37d3b729..6c3b3bd2 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeRegistry.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeRegistry.java @@ -1,4 +1,4 @@ -package org.acme.schooltimetabling.DefaultTimes; +package org.acme.schooltimetabling.defaultTimes; import java.util.List; import java.util.Random; diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/LessonGenerator.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/LessonGenerator.java index 6e8d923f..5bea7712 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/LessonGenerator.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/LessonGenerator.java @@ -1,7 +1,7 @@ package org.acme.schooltimetabling.helperClasses.Generators; -import org.acme.schooltimetabling.DefaultTimes.DefaultTime; -import org.acme.schooltimetabling.DefaultTimes.DefaultTimeRegistry; +import org.acme.schooltimetabling.defaultTimes.DefaultTime; +import org.acme.schooltimetabling.defaultTimes.DefaultTimeRegistry; import org.acme.schooltimetabling.constants.Constants; import org.acme.schooltimetabling.constants.Preference; import org.acme.schooltimetabling.domain.lesson.Lesson; From 96acf5d0474681954626aa68596113ec68aab0c8 Mon Sep 17 00:00:00 2001 From: RandomCyberCoder Date: Fri, 15 May 2026 13:21:05 -0700 Subject: [PATCH 11/17] added in the room prescheduling constraint --- .../Generators/RoomGenerator.java | 2 ++ .../solver/TimetableConstraintProvider.java | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/RoomGenerator.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/RoomGenerator.java index 472914ea..34a706c0 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/RoomGenerator.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/RoomGenerator.java @@ -48,6 +48,8 @@ private static Room generateRoom(String roomName){ //check for prescheduling if(PRESCHED_TIMES != null && PRESCHED_TIMES.getRooms().containsKey(roomName)){ + //mark this var so that we know to include the prescheduling room constraint + Room.hasPrescheduled = true; LOGGER.info("Found prescheduling times for room '{}'. Using prescheduling times.", roomName); for(PrescheduleObject.PrescheduledWindow prescheduledWindow: PRESCHED_TIMES.getRooms().get(roomName)){ BitSet preBs = BitSetHelper.timeJsonToBs(prescheduledWindow); diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/solver/TimetableConstraintProvider.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/solver/TimetableConstraintProvider.java index cc69c2c6..b82ff2a6 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/solver/TimetableConstraintProvider.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/solver/TimetableConstraintProvider.java @@ -90,6 +90,12 @@ else if(AGGRESSIVE_CHOICE.equals("NONE")){ System.exit(1); } + //add in the room prescheduling conflict constraint only if we prescheduled rooms detected + if(Room.hasPrescheduled){ + LOGGER.info("At least on room has been found to be prescheduled. Including the room prescheduling constraint."); + solver_constraints.add(roomPreschedule(constraintFactory)); + } + return solver_constraints.toArray(Constraint[]::new); } @@ -599,4 +605,23 @@ Constraint outBestTime(ConstraintFactory constraintFactory){ .asConstraint("Penalize time out of preferred time interval"); } + //--------------------- NEW COSNTRAINT FOR THE ROOM PRESCHEDULING ---------------// + Constraint roomPreschedule(ConstraintFactory constraintFactory){ + return constraintFactory.forEach(Lesson.class) + .filter(lesson -> { + //skip lessons that are in the lecture only room + //take into account only lessons that have a room that has prescheduling times + if(Objects.equals(lesson.getRoom().getName(), Constants.LEC_ONLY) + || !lesson.getRoom().getPrescheduled().isEmpty() ) return false; + + //penalize lessons that are scheduled in a rooms prescheduled time + BitSet prescheduled = lesson.getRoom().getPrescheduled(); + + return prescheduled.intersects(lesson.getTimeslot().getLectureBitSet()) || + prescheduled.intersects(lesson.getTimeslot().getLabActBitSet()); + }) + .penalize(HardMediumSoftScore.ONE_SOFT) + .asConstraint("Penalize a lesson "); + } + } From 80293303184e1e9be1bc090217bf16a26adc1ee6 Mon Sep 17 00:00:00 2001 From: RandomCyberCoder Date: Mon, 18 May 2026 12:54:16 -0700 Subject: [PATCH 12/17] updating default times for better scheduling --- .../DefaultTimes/DefaultTimeAll.java | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeAll.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeAll.java index d4d02d93..c2ddaf64 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeAll.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/DefaultTimes/DefaultTimeAll.java @@ -26,18 +26,28 @@ public class DefaultTimeAll implements DefaultTime{ final DateTimeFormatter FORMATTER = Constants.TIME_FORMATTER; EnumSet defaultDays = EnumSet.allOf(Days.class); - List acceptableTimes = List.of( + //I'm trying to set preferred times outside of prime time to help solver push more lectures into this time. + List preferredTimes = List.of( LocalTime.parse("7:00AM", FORMATTER), LocalTime.parse("8:00AM", FORMATTER), + LocalTime.parse("3:00PM", FORMATTER), + LocalTime.parse("4:00PM", FORMATTER), + LocalTime.parse("5:00PM", FORMATTER) + + ); + + for(LocalTime localTime : preferredTimes){ + INSTANCE.preference.or(BitSetHelper.timeSlotBitSet(localTime, NUM_BLOCKS_FULL_HOUR, defaultDays)); + } + + + List acceptableTimes = List.of( LocalTime.parse("9:00AM", FORMATTER), LocalTime.parse("10:00AM", FORMATTER), LocalTime.parse("11:00AM", FORMATTER), LocalTime.parse("12:00PM", FORMATTER), LocalTime.parse("1:00PM", FORMATTER), - LocalTime.parse("2:00PM", FORMATTER), - LocalTime.parse("3:00PM", FORMATTER), - LocalTime.parse("4:00PM", FORMATTER), - LocalTime.parse("5:00PM", FORMATTER) + LocalTime.parse("2:00PM", FORMATTER) ); for(LocalTime localTime : acceptableTimes) { INSTANCE.acceptable.or(BitSetHelper.timeSlotBitSet(localTime, NUM_BLOCKS_FULL_HOUR, defaultDays)); From 2fec938a3e2d091e0da34d63bde2d4514cd9a618 Mon Sep 17 00:00:00 2001 From: RandomCyberCoder Date: Mon, 18 May 2026 12:58:59 -0700 Subject: [PATCH 13/17] faculty meeting times updated --- .../org/acme/schooltimetabling/domain/teacher/Faculty.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/domain/teacher/Faculty.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/domain/teacher/Faculty.java index 0cee4327..8e8fe107 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/domain/teacher/Faculty.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/domain/teacher/Faculty.java @@ -35,14 +35,14 @@ public class Faculty extends Teacher{ final int NUM_BLOCKS_FULL_HOUR = 2; List facultyTimes; DateTimeFormatter formatter = DateTimeFormatter.ofPattern("h:mma"); - EnumSet facultyDays = EnumSet.of(Days.MONDAY, Days.WEDNESDAY, Days.FRIDAY); + EnumSet facultyDays; try{ //set special bits for testing if(Constants.TESTING){ LocalTime localTime = LocalTime.parse("9:00PM", formatter); BitSet temp = BitSetHelper.timeSlotBitSet(localTime, NUM_BLOCKS_FULL_HOUR, - EnumSet.of(Days.MONDAY, Days.WEDNESDAY, Days.FRIDAY)); + EnumSet.of(Days.MONDAY, Days.TUESDAY, Days.WEDNESDAY, Days.THURSDAY)); FACULTY_CONFLICT.or(temp); } /*CSC faculty times*/ From 0616413663161db9ee013fe3efb9ae720c940d93 Mon Sep 17 00:00:00 2001 From: RandomCyberCoder Date: Mon, 18 May 2026 13:05:53 -0700 Subject: [PATCH 14/17] fixed facutly default survey --- .../Generators/LessonGenerator.java | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/LessonGenerator.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/LessonGenerator.java index 5bea7712..d967f415 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/LessonGenerator.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/LessonGenerator.java @@ -329,19 +329,24 @@ private static boolean skipCourse(String modifier, String name, String config){ private static Teacher noSurveyTeacher(String name, DefaultTime defaultTime){ final int LAST_NAME_POS = 0; String[] nameFragments = name.split(","); + boolean isFaculty = Constants.FACULTY_LAST_NAMES.contains(nameFragments[LAST_NAME_POS]); - if(Constants.FACULTY_LAST_NAMES.contains(nameFragments[LAST_NAME_POS])){ - LOGGER.info(String.format("Found teacher '%s' to be a faculty member. Promoting Teacher obj to Faculty" + if(isFaculty){ + LOGGER.info(String.format("Found teacher '%s' to be a faculty member. Promoting to Faculty" , name)); - return new Faculty(TeacherGenerator.getNextTeacherID(), name, new BitSet(), new BitSet(), new BitSet(), + return new Faculty(TeacherGenerator.getNextTeacherID(), name, + defaultTime.getPreference(), + defaultTime.getAcceptable(), + defaultTime.getConflict(), + Preference.NEUTRAL); + } + else{ + return new Teacher(TeacherGenerator.getNextTeacherID(), name, + defaultTime.getPreference(), + defaultTime.getAcceptable(), + defaultTime.getConflict(), Preference.NEUTRAL); } - - return new Teacher(TeacherGenerator.getNextTeacherID(), name, - defaultTime.getPreference(), - defaultTime.getAcceptable(), - defaultTime.getConflict(), - Preference.NEUTRAL); } From 98e0dd3bf04eb1d5bfbae1cbe83f2cbed9747587 Mon Sep 17 00:00:00 2001 From: RandomCyberCoder Date: Mon, 18 May 2026 13:06:33 -0700 Subject: [PATCH 15/17] updated Room constructor --- .../src/main/java/org/acme/schooltimetabling/domain/Room.java | 1 + 1 file changed, 1 insertion(+) diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/domain/Room.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/domain/Room.java index 28708c91..21a08374 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/domain/Room.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/domain/Room.java @@ -32,6 +32,7 @@ public Room(String id, String name, int ID){ this.id = id; this.name = name; this.ID = ID; + this.prescheduled = new BitSet(); } @Override From 0f04ac6a9fe0d272210e518fd6afa668939cc9c5 Mon Sep 17 00:00:00 2001 From: RandomCyberCoder Date: Mon, 18 May 2026 13:39:14 -0700 Subject: [PATCH 16/17] fixed the usage of old surveys as a fall back --- .../Generators/TeacherGenerator.java | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/TeacherGenerator.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/TeacherGenerator.java index 20c3ec7f..0dfa4cb6 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/TeacherGenerator.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/TeacherGenerator.java @@ -108,7 +108,9 @@ public static Map teacherGenDriver(){ /** * Returns a hashmap of the teacher's canon name mapped to their teacher's object. If the person is a faculty * member the teacher object will actually be a Faculty object. The function will try to bleed an old survey - * if the professor chooses. If a professor bleeds forward in the old survey, the teacher is skipped + * if the professor chooses. If a professor bleeds forward in the old survey, the teacher is skipped. + * + * If a teacher has no survey for the current quarter, then we will try to use the survey from the previous quarter * * @param curQuarterSurvey current quarter survey file path assuming it's in src directory * @param prevQuarterSurvey prev quarter survey file path assuming it's in src directory @@ -117,9 +119,10 @@ public static Map teacherGenDriver(){ * */ public static HashMap generateTeachers(List> curQuarterSurvey, List> prevQuarterSurvey){ - /* This Hash map will map the teacher's name to the teacher's object */ + /* This Hash map will map the teacher's CANON name to their teacher object */ HashMap teacherHashMap = new HashMap<> (); final String BLEED_FORWARD_STRING = "Yes, use the same as last term"; + final String BLEED_FORWARD_KEY = "use_old"; /*we will use a hashmap to keep track of who want to bleed forward for * easy lookup*/ @@ -130,7 +133,7 @@ public static HashMap generateTeachers(List generateTeachers(List surveyEntry : prevQuarterSurvey){ String instructorName = surveyEntry.get("name").strip(); + final String canonName = Constants.TEACHER_NAME_TO_CANON.get(instructorName); + /*Check if the instructor wanted to bleed forward*/ if(teacherBleed.containsKey(instructorName)){ LOGGER.info(String.format("Trying to use %s's old survey", instructorName)); /*If the instructor choose to bleed forward in the previous survey * we will be forced to skip them :( */ - if(BLEED_FORWARD_STRING.equals(surveyEntry.get("use_old"))){ + if(BLEED_FORWARD_STRING.equals(surveyEntry.get(BLEED_FORWARD_KEY))){ LOGGER.warn(String.format("Previous survey also bleeds forward. SKIPPING %s", instructorName)); continue; } @@ -171,16 +176,19 @@ public static HashMap generateTeachers(List Date: Mon, 18 May 2026 15:21:23 -0700 Subject: [PATCH 17/17] updated room prescheduling, and update a random log --- .../Generators/TeacherGenerator.java | 2 +- .../solver/TimetableConstraintProvider.java | 45 ++++++++------- .../solver/ConstraintTestHelper.java | 48 ++++++++++++---- .../solver/TestConstraints.java | 57 +++++++++++++++++-- 4 files changed, 114 insertions(+), 38 deletions(-) diff --git a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/TeacherGenerator.java b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/TeacherGenerator.java index 0dfa4cb6..42378a84 100644 --- a/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/TeacherGenerator.java +++ b/java/hello-world/src/main/java/org/acme/schooltimetabling/helperClasses/Generators/TeacherGenerator.java @@ -161,7 +161,7 @@ public static HashMap generateTeachers(List { + //skip lessons that are in the lecture only room + //take into account only lessons that have a room that has prescheduling times + if(Constants.LEC_ONLY.equals(lesson.getRoom().getName()) || + lesson.getRoom().getPrescheduled().isEmpty()) return false; + + //penalize lessons that are scheduled in a rooms prescheduled time + BitSet prescheduled = lesson.getRoom().getPrescheduled(); + + //studio course both// non studio only lab + return prescheduled.intersects(lesson.getTimeslot().getLabActBitSet()) || + (lesson.isStudio() && prescheduled.intersects(lesson.getTimeslot().getLectureBitSet())); + }) + .penalize(HardMediumSoftScore.ONE_HARD) + .asConstraint("Penalize a lesson "); + } + //-------------------------------------- Medium Constraints -------------------------------------- Constraint prefTime(ConstraintFactory constraintFactory){ @@ -604,24 +627,4 @@ Constraint outBestTime(ConstraintFactory constraintFactory){ .penalize(HardMediumSoftScore.ONE_SOFT) .asConstraint("Penalize time out of preferred time interval"); } - - //--------------------- NEW COSNTRAINT FOR THE ROOM PRESCHEDULING ---------------// - Constraint roomPreschedule(ConstraintFactory constraintFactory){ - return constraintFactory.forEach(Lesson.class) - .filter(lesson -> { - //skip lessons that are in the lecture only room - //take into account only lessons that have a room that has prescheduling times - if(Objects.equals(lesson.getRoom().getName(), Constants.LEC_ONLY) - || !lesson.getRoom().getPrescheduled().isEmpty() ) return false; - - //penalize lessons that are scheduled in a rooms prescheduled time - BitSet prescheduled = lesson.getRoom().getPrescheduled(); - - return prescheduled.intersects(lesson.getTimeslot().getLectureBitSet()) || - prescheduled.intersects(lesson.getTimeslot().getLabActBitSet()); - }) - .penalize(HardMediumSoftScore.ONE_SOFT) - .asConstraint("Penalize a lesson "); - } - } diff --git a/java/hello-world/src/test/java/org/acme/schooltimetabling/solver/ConstraintTestHelper.java b/java/hello-world/src/test/java/org/acme/schooltimetabling/solver/ConstraintTestHelper.java index 9486384e..774db5f6 100644 --- a/java/hello-world/src/test/java/org/acme/schooltimetabling/solver/ConstraintTestHelper.java +++ b/java/hello-world/src/test/java/org/acme/schooltimetabling/solver/ConstraintTestHelper.java @@ -5,8 +5,10 @@ import org.acme.schooltimetabling.domain.Room; import org.acme.schooltimetabling.domain.Timeslot; import org.acme.schooltimetabling.domain.teacher.Teacher; +import org.acme.schooltimetabling.helperClasses.BitSetHelper; import org.glassfish.jaxb.runtime.v2.runtime.reflect.opt.Const; +import java.time.LocalTime; import java.util.BitSet; import java.util.EnumSet; import java.util.Set; @@ -22,12 +24,16 @@ public class ConstraintTestHelper { /** * Test: room name; will be used by a specific course {@link #TEST_L_W_LAB_SPECIFIC} */ - public final static String TEST_LAB_ROOM_SPECIFIC = "LabRoom"; + public final static String TEST_NAME_LAB_ROOM_SPECIFIC = "LabRoom"; /** * Test: name of lab room not assigned to an course specifically */ - public final static String TEST_RANDOM_LAB_ROOM = "Random lab room"; - public final static Set TEST_SET_LAB_ROOMS = Set.of(TEST_LAB_ROOM_SPECIFIC); + public final static String TEST_NAME_RANDOM_LAB_ROOM = "Random lab room"; + /** + * Test: name of prescheduled ROOM + */ + public final static String TEST_NAME_PRESCHEDULED_ROOM = "Room Prescheduled"; + public final static Set TEST_SET_LAB_ROOMS = Set.of(TEST_NAME_LAB_ROOM_SPECIFIC); /** * Test: name of a course that has a specific lab*/ public final static String TEST_L_W_LAB_SPECIFIC = "Lab/Act course"; @@ -39,28 +45,48 @@ public class ConstraintTestHelper { * Room that is used for a course specifically and can also be used by an lab */ public static Room TEST_ROOM_SPECIFIC; + /** + * Room prescheduled + */ + public static Room TEST_ROOM_PRESCHEDULED; public static String NON_STUDIO_SPECIFIC = "non studio course with a specific room"; static{ - Constants.POSSIBLE_ROOMS.add(TEST_LAB_ROOM_SPECIFIC); - Constants.ROOM_TO_ID_BIMAP.put(TEST_LAB_ROOM_SPECIFIC, 1000); + //add rooms to those that are possible + Constants.POSSIBLE_ROOMS.add(TEST_NAME_LAB_ROOM_SPECIFIC); + Constants.ROOM_TO_ID_BIMAP.put(TEST_NAME_LAB_ROOM_SPECIFIC, 1000); - Constants.POSSIBLE_ROOMS.add(TEST_RANDOM_LAB_ROOM); - Constants.ROOM_TO_ID_BIMAP.put(TEST_RANDOM_LAB_ROOM, 1001); + Constants.POSSIBLE_ROOMS.add(TEST_NAME_RANDOM_LAB_ROOM); + Constants.ROOM_TO_ID_BIMAP.put(TEST_NAME_RANDOM_LAB_ROOM, 1001); + Constants.POSSIBLE_ROOMS.add(TEST_NAME_PRESCHEDULED_ROOM); + Constants.ROOM_TO_ID_BIMAP.put(TEST_NAME_PRESCHEDULED_ROOM, 1002); + + //add course names to their ID Constants.COURSE_ID_BIMAP.put(DUMMY_STUDIO, 2000); Constants.COURSE_ID_BIMAP.put(NON_STUDIO_SPECIFIC, 2001); + //add which lessons are studios Constants.STUDIO_STYLE_COURSES.add(DUMMY_STUDIO); Constants.STUDIO_STYLE_COURSES.add(TEST_L_W_LAB_SPECIFIC); + //add mapping for which courses can be in certain rooms Constants.COURSE_TO_ROOMS.put(TEST_L_W_LAB_SPECIFIC, TEST_SET_LAB_ROOMS); Constants.COURSE_TO_ROOMS.put(NON_STUDIO_SPECIFIC, TEST_SET_LAB_ROOMS); - TEST_ROOM_RANDO_LAB = new Room(Integer.toString(Constants.ROOM_TO_ID_BIMAP.get(TEST_RANDOM_LAB_ROOM)), - TEST_RANDOM_LAB_ROOM, Constants.ROOM_TO_ID_BIMAP.get(TEST_RANDOM_LAB_ROOM)); - TEST_ROOM_SPECIFIC = new Room(Integer.toString(Constants.ROOM_TO_ID_BIMAP.get(TEST_LAB_ROOM_SPECIFIC)), - TEST_LAB_ROOM_SPECIFIC, Constants.ROOM_TO_ID_BIMAP.get(TEST_LAB_ROOM_SPECIFIC)); + //create the room objects + TEST_ROOM_RANDO_LAB = new Room(Integer.toString(Constants.ROOM_TO_ID_BIMAP.get(TEST_NAME_RANDOM_LAB_ROOM)), + TEST_NAME_RANDOM_LAB_ROOM, Constants.ROOM_TO_ID_BIMAP.get(TEST_NAME_RANDOM_LAB_ROOM)); + TEST_ROOM_SPECIFIC = new Room(Integer.toString(Constants.ROOM_TO_ID_BIMAP.get(TEST_NAME_LAB_ROOM_SPECIFIC)), + TEST_NAME_LAB_ROOM_SPECIFIC, Constants.ROOM_TO_ID_BIMAP.get(TEST_NAME_LAB_ROOM_SPECIFIC)); + TEST_ROOM_PRESCHEDULED = new Room(Integer.toString(Constants.ROOM_TO_ID_BIMAP.get(TEST_NAME_LAB_ROOM_SPECIFIC)), + TEST_NAME_LAB_ROOM_SPECIFIC, Constants.ROOM_TO_ID_BIMAP.get(TEST_NAME_LAB_ROOM_SPECIFIC)); + + //let's preschedule a room + EnumSet MWF = EnumSet.of(Days.MONDAY, Days.WEDNESDAY, Days.FRIDAY); + BitSet roomBlocked = BitSetHelper.timeSlotBitSet(LocalTime.parse("9:00AM", Constants.TIME_FORMATTER), 2, MWF); + TEST_ROOM_PRESCHEDULED.prescheduleUpdate(roomBlocked); + Constants.TESTING = true; } diff --git a/java/hello-world/src/test/java/org/acme/schooltimetabling/solver/TestConstraints.java b/java/hello-world/src/test/java/org/acme/schooltimetabling/solver/TestConstraints.java index c4c310ad..129ec181 100644 --- a/java/hello-world/src/test/java/org/acme/schooltimetabling/solver/TestConstraints.java +++ b/java/hello-world/src/test/java/org/acme/schooltimetabling/solver/TestConstraints.java @@ -12,14 +12,11 @@ import org.acme.schooltimetabling.helperClasses.BitSetHelper; import org.acme.schooltimetabling.helperClasses.Generators.LessonGenerator; import org.acme.schooltimetabling.helperClasses.ScheduleConfig; -import org.glassfish.jaxb.runtime.v2.runtime.reflect.opt.Const; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import ai.timefold.solver.test.api.score.stream.ConstraintVerifier; -import java.sql.Time; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.util.BitSet; @@ -342,7 +339,7 @@ void noPenLessonRoomCheck(){ Lesson lesson2 = Lesson.test_buildLesson("1", 1, "some only lec course", "", "", "1-0-0", 1111, ConstraintTestHelper.DUMMY_TEACHER, ConstraintTestHelper.DUMMY_TS, LEC_ONLY_ROOM); - Lesson lsLabOnly = Lesson.test_buildLesson("2", 1, ConstraintTestHelper.TEST_RANDOM_LAB_ROOM, + Lesson lsLabOnly = Lesson.test_buildLesson("2", 1, ConstraintTestHelper.TEST_NAME_RANDOM_LAB_ROOM, "noName", "", "0-0-1", 1, ConstraintTestHelper.DUMMY_TEACHER, ConstraintTestHelper.DUMMY_TS, ConstraintTestHelper.DUMMY_ROOM); @@ -710,6 +707,56 @@ void penalizeDislikedHourGap() { likedGap1, likedGap2) .penalizesBy(2); } -} + @Test + @DisplayName("Penalty: room prescheduling blocks lab and studio lecture") + void roomPrescheduleConflict() { + EnumSet MWF = EnumSet.of(Days.MONDAY, Days.WEDNESDAY, Days.FRIDAY); + + BitSet blockedLessonBits = BitSetHelper.timeSlotBitSet(LocalTime.parse("9:00AM", formatter), 2, MWF); + BitSet blockedLessonBits2 = BitSetHelper.timeSlotBitSet(LocalTime.parse("8:00AM", formatter), 2, MWF); + Timeslot blockedTimeslot = Timeslot.test_lecLabBitAndDays(1, blockedLessonBits, ConstraintTestHelper.EMPTY_BS, + MWF, ConstraintTestHelper.NO_DAYS); + Timeslot blockedTimeslot_LecLab = Timeslot.test_lecLabBitAndDays(2, blockedLessonBits2, blockedLessonBits, + MWF, MWF); + + Lesson blockedLessonLab = Lesson.test_buildLesson("room-blocked-lab", 2, "", "", "", + "3-1-0", 1, ConstraintTestHelper.DUMMY_TEACHER,blockedTimeslot_LecLab, + ConstraintTestHelper.TEST_ROOM_PRESCHEDULED); + Lesson blockedStudio = Lesson.test_buildLesson("room-blocked-studio", 3, ConstraintTestHelper.DUMMY_STUDIO, + "", "", "1-0-0", Constants.COURSE_ID_BIMAP.get(ConstraintTestHelper.DUMMY_STUDIO), + ConstraintTestHelper.DUMMY_TEACHER, blockedTimeslot, ConstraintTestHelper.TEST_ROOM_PRESCHEDULED); + + constraintVerifier.verifyThat(TimetableConstraintProvider::roomPreschedule) + .given(blockedLessonLab, blockedStudio) + .penalizesBy(2); + } + + @Test + @DisplayName("No Penalty: room prescheduling skip branches") + void noRoomPrescheduleConflict() { + EnumSet MWF = EnumSet.of(Days.MONDAY, Days.WEDNESDAY, Days.FRIDAY); + + BitSet roomBlocked = BitSetHelper.timeSlotBitSet(LocalTime.parse("9:00AM", formatter), 2, MWF); + BitSet bs_10AM = BitSetHelper.timeSlotBitSet(LocalTime.parse("10:00AM", formatter), 2, MWF); + + Timeslot blockedTimeslot = Timeslot.test_lecLabBitAndDays(2, roomBlocked, ConstraintTestHelper.EMPTY_BS, + MWF, ConstraintTestHelper.NO_DAYS); + Timeslot ts_9AM_10AM_MWF = Timeslot.test_lecLabBitAndDays(2, roomBlocked, bs_10AM, MWF, MWF); + Timeslot ts_10AM_MWF = Timeslot.test_lecLabBitAndDays(2, bs_10AM, ConstraintTestHelper.EMPTY_BS, MWF, + ConstraintTestHelper.NO_DAYS); + Lesson openLessonLec = Lesson.test_buildLesson("room-open-lec", 1, "", "", "", + "3-1-0", 1, ConstraintTestHelper.DUMMY_TEACHER, ts_9AM_10AM_MWF, + ConstraintTestHelper.TEST_ROOM_PRESCHEDULED); + Lesson lecOnlyRoomLesson = Lesson.test_buildLesson("room-lec-only", 3, "", "", "", + "1-0-0", 1, ConstraintTestHelper.DUMMY_TEACHER, blockedTimeslot, + ConstraintTestHelper.TEST_ROOM_PRESCHEDULED); + Lesson emptyRoomLesson = Lesson.test_buildLesson("room-empty", 4, "", "", "", + "1-0-0", 1, ConstraintTestHelper.DUMMY_TEACHER, blockedTimeslot, ConstraintTestHelper.DUMMY_ROOM); + + constraintVerifier.verifyThat(TimetableConstraintProvider::roomPreschedule) + .given(openLessonLec, lecOnlyRoomLesson, emptyRoomLesson) + .penalizesBy(0); + } +}