diff --git a/src/main/java/org/example/se302/controller/CoursesController.java b/src/main/java/org/example/se302/controller/CoursesController.java index cbd7a47..ee3bc74 100644 --- a/src/main/java/org/example/se302/controller/CoursesController.java +++ b/src/main/java/org/example/se302/controller/CoursesController.java @@ -15,20 +15,33 @@ import org.example.se302.service.DataManager; */ public class CoursesController { - @FXML private TextField searchField; - @FXML private Label resultCountLabel; - @FXML private TableView coursesTable; - @FXML private TableColumn courseCodeColumn; - @FXML private TableColumn studentCountColumn; - @FXML private TableColumn classroomColumn; - @FXML private TableColumn examDateColumn; - @FXML private TableColumn actionColumn; + @FXML + private TextField searchField; + @FXML + private Label resultCountLabel; + @FXML + private TableView coursesTable; + @FXML + private TableColumn courseCodeColumn; + @FXML + private TableColumn studentCountColumn; + @FXML + private TableColumn classroomColumn; + @FXML + private TableColumn examDateColumn; + @FXML + private TableColumn actionColumn; - @FXML private VBox studentListPanel; - @FXML private Label studentListTitleLabel; - @FXML private TableView enrolledStudentsTable; - @FXML private TableColumn enrolledStudentIdColumn; - @FXML private Label enrolledCountLabel; + @FXML + private VBox studentListPanel; + @FXML + private Label studentListTitleLabel; + @FXML + private TableView enrolledStudentsTable; + @FXML + private TableColumn enrolledStudentIdColumn; + @FXML + private Label enrolledCountLabel; private DataManager dataManager; private FilteredList filteredCourses; @@ -38,11 +51,10 @@ public class CoursesController { dataManager = DataManager.getInstance(); // Set up table columns - courseCodeColumn.setCellValueFactory(cellData -> - new SimpleStringProperty(cellData.getValue().getCourseCode())); + courseCodeColumn.setCellValueFactory(cellData -> new SimpleStringProperty(cellData.getValue().getCourseCode())); - studentCountColumn.setCellValueFactory(cellData -> - new SimpleIntegerProperty(cellData.getValue().getEnrolledStudentsCount())); + studentCountColumn.setCellValueFactory( + cellData -> new SimpleIntegerProperty(cellData.getValue().getEnrolledStudentsCount())); classroomColumn.setCellValueFactory(cellData -> { String classroom = cellData.getValue().getAssignedClassroom(); @@ -50,8 +62,12 @@ public class CoursesController { }); examDateColumn.setCellValueFactory(cellData -> { - String examDate = cellData.getValue().getExamDateTime(); - return new SimpleStringProperty(examDate != null ? examDate : "Not Scheduled"); + Course course = cellData.getValue(); + if (course.isScheduled()) { + return new SimpleStringProperty("Day " + (course.getExamDay() + 1) + + ", Slot " + (course.getExamTimeSlot() + 1)); + } + return new SimpleStringProperty("Not Scheduled"); }); // Add "View Students" button to action column @@ -73,8 +89,7 @@ public class CoursesController { }); // Set up enrolled students table column - enrolledStudentIdColumn.setCellValueFactory(cellData -> - new SimpleStringProperty(cellData.getValue())); + enrolledStudentIdColumn.setCellValueFactory(cellData -> new SimpleStringProperty(cellData.getValue())); // Set up filtered list filteredCourses = new FilteredList<>(dataManager.getCourses(), p -> true); @@ -106,14 +121,13 @@ public class CoursesController { filteredCourses.setPredicate(course -> true); } else { String lowerCaseFilter = searchText.toLowerCase().trim(); - filteredCourses.setPredicate(course -> - course.getCourseCode().toLowerCase().contains(lowerCaseFilter) - ); + filteredCourses.setPredicate(course -> course.getCourseCode().toLowerCase().contains(lowerCaseFilter)); } } private void showEnrolledStudents(Course course) { - if (course == null) return; + if (course == null) + return; studentListTitleLabel.setText("Students Enrolled in " + course.getCourseCode()); enrolledStudentsTable.setItems(FXCollections.observableArrayList(course.getEnrolledStudents())); diff --git a/src/main/java/org/example/se302/controller/ScheduleClassroomController.java b/src/main/java/org/example/se302/controller/ScheduleClassroomController.java index 445a4b5..379cb87 100644 --- a/src/main/java/org/example/se302/controller/ScheduleClassroomController.java +++ b/src/main/java/org/example/se302/controller/ScheduleClassroomController.java @@ -150,78 +150,62 @@ public class ScheduleClassroomController { ScheduleConfiguration config = dataManager.getActiveConfiguration(); ObservableList entries = FXCollections.observableArrayList(); - int totalSlots = 0; int usedSlots = 0; int totalStudents = 0; - // Find all courses scheduled in this classroom for (Course course : dataManager.getCourses()) { - if (course.isScheduled() && - selected.getClassroomId().equals(course.getAssignedClassroom())) { + if (!course.isScheduled() || !selected.getClassroomId().equals(course.getAssignedClassroom())) + continue; - int dayIndex = course.getExamDay(); - int slotIndex = course.getExamTimeSlot(); + int dayIndex = course.getExamDay(); + int slotIndex = course.getExamTimeSlot(); + int studentCount = course.getEnrolledStudentsCount(); + int utilization = selected.getCapacity() > 0 + ? (studentCount * 100) / selected.getCapacity() + : 0; - // Format date - String dateStr; - if (config != null && config.getStartDate() != null) { - LocalDate examDate = config.getStartDate().plusDays(dayIndex); - dateStr = examDate.format(DateTimeFormatter.ofPattern("dd/MM/yyyy")); - } else { - dateStr = "Day " + (dayIndex + 1); - } + entries.add(new ClassroomSlotEntry( + formatDate(config, dayIndex), + formatTime(config, dayIndex, slotIndex), + course.getCourseCode(), studentCount, utilization + "%", + utilization, dayIndex, slotIndex)); - // Format time - String timeStr; - if (config != null) { - TimeSlot timeSlot = config.getTimeSlot(dayIndex, slotIndex); - if (timeSlot != null) { - timeStr = timeSlot.getStartTime() + " - " + timeSlot.getEndTime(); - } else { - timeStr = "Slot " + (slotIndex + 1); - } - } else { - timeStr = "Slot " + (slotIndex + 1); - } - - // Calculate utilization - int studentCount = course.getEnrolledStudentsCount(); - int capacity = selected.getCapacity(); - int utilizationPercent = capacity > 0 ? (studentCount * 100) / capacity : 0; - String utilizationStr = utilizationPercent + "%"; - - entries.add(new ClassroomSlotEntry( - dateStr, timeStr, course.getCourseCode(), - studentCount, utilizationStr, utilizationPercent, - dayIndex, slotIndex)); - - usedSlots++; - totalStudents += studentCount; - } + usedSlots++; + totalStudents += studentCount; } - // Calculate total possible slots - if (config != null) { - totalSlots = config.getNumDays() * config.getSlotsPerDay(); - } - - // Sort by day then slot entries.sort(Comparator.comparingInt(ClassroomSlotEntry::getDayIndex) .thenComparingInt(ClassroomSlotEntry::getSlotIndex)); - scheduleTable.setItems(entries); - // Update overall utilization label + int totalSlots = config != null ? config.getNumDays() * config.getSlotsPerDay() : 0; if (totalSlots > 0) { - int overallUtilization = (usedSlots * 100) / totalSlots; + int overallUtil = (usedSlots * 100) / totalSlots; utilizationLabel.setText(String.format( "Overall Utilization: %d%% (%d/%d slots used, %d total students)", - overallUtilization, usedSlots, totalSlots, totalStudents)); + overallUtil, usedSlots, totalSlots, totalStudents)); } else { utilizationLabel.setText("Overall Utilization: 0% (No schedule data available)"); } } + private String formatDate(ScheduleConfiguration config, int dayIndex) { + if (config != null && config.getStartDate() != null) { + LocalDate examDate = config.getStartDate().plusDays(dayIndex); + return examDate.format(DateTimeFormatter.ofPattern("dd/MM/yyyy")); + } + return "Day " + (dayIndex + 1); + } + + private String formatTime(ScheduleConfiguration config, int dayIndex, int slotIndex) { + if (config != null) { + TimeSlot slot = config.getTimeSlot(dayIndex, slotIndex); + if (slot != null) + return slot.getStartTime() + " - " + slot.getEndTime(); + } + return "Slot " + (slotIndex + 1); + } + // Helper class for table entries public static class ClassroomSlotEntry { private final String date; diff --git a/src/main/java/org/example/se302/controller/ScheduleCourseController.java b/src/main/java/org/example/se302/controller/ScheduleCourseController.java index 533aa56..be28bbe 100644 --- a/src/main/java/org/example/se302/controller/ScheduleCourseController.java +++ b/src/main/java/org/example/se302/controller/ScheduleCourseController.java @@ -151,53 +151,48 @@ public class ScheduleCourseController { ObservableList entries = FXCollections.observableArrayList(); for (Course course : dataManager.getCourses()) { - String courseCode = course.getCourseCode(); - int enrolled = course.getEnrolledStudentsCount(); - String dateStr = "Not Scheduled"; String timeStr = "-"; String classroomStr = "-"; int dayIndex = Integer.MAX_VALUE; int slotIndex = Integer.MAX_VALUE; - // Check if this course has been scheduled if (course.isScheduled()) { dayIndex = course.getExamDay(); slotIndex = course.getExamTimeSlot(); classroomStr = course.getAssignedClassroom(); - - // Format date using configuration's start date - if (config != null && config.getStartDate() != null) { - LocalDate examDate = config.getStartDate().plusDays(dayIndex); - dateStr = examDate.format(DateTimeFormatter.ofPattern("dd/MM/yyyy (EEEE)")); - } else { - dateStr = "Day " + (dayIndex + 1); - } - - // Format time using configuration's time slots - if (config != null) { - TimeSlot timeSlot = config.getTimeSlot(dayIndex, slotIndex); - if (timeSlot != null) { - timeStr = timeSlot.getStartTime() + " - " + timeSlot.getEndTime(); - } else { - timeStr = "Slot " + (slotIndex + 1); - } - } else { - timeStr = "Slot " + (slotIndex + 1); - } + dateStr = formatDate(config, dayIndex); + timeStr = formatTime(config, dayIndex, slotIndex); } - entries.add(new CourseScheduleEntry(courseCode, enrolled, dateStr, timeStr, classroomStr, + entries.add(new CourseScheduleEntry(course.getCourseCode(), + course.getEnrolledStudentsCount(), dateStr, timeStr, classroomStr, dayIndex, slotIndex)); } - // Sort by day first, then by slot entries.sort(Comparator.comparingInt(CourseScheduleEntry::getDayIndex) .thenComparingInt(CourseScheduleEntry::getSlotIndex)); - courseScheduleTable.setItems(entries); } + private String formatDate(ScheduleConfiguration config, int dayIndex) { + if (config != null && config.getStartDate() != null) { + LocalDate examDate = config.getStartDate().plusDays(dayIndex); + return examDate.format(DateTimeFormatter.ofPattern("dd/MM/yyyy (EEEE)")); + } + return "Day " + (dayIndex + 1); + } + + private String formatTime(ScheduleConfiguration config, int dayIndex, int slotIndex) { + if (config != null) { + TimeSlot slot = config.getTimeSlot(dayIndex, slotIndex); + if (slot != null) { + return slot.getStartTime() + " - " + slot.getEndTime(); + } + } + return "Slot " + (slotIndex + 1); + } + // Helper class for table entries public static class CourseScheduleEntry { private final String courseCode; diff --git a/src/main/java/org/example/se302/controller/ScheduleStudentController.java b/src/main/java/org/example/se302/controller/ScheduleStudentController.java index de3a6df..8b2d49a 100644 --- a/src/main/java/org/example/se302/controller/ScheduleStudentController.java +++ b/src/main/java/org/example/se302/controller/ScheduleStudentController.java @@ -105,77 +105,58 @@ public class ScheduleStudentController { for (String courseCode : student.getEnrolledCourses()) { Course course = dataManager.getCourse(courseCode); - if (course != null) { - String dateStr = "Not Scheduled"; - String timeStr = "-"; - String classroom = "-"; - int dayIndex = -1; - int slotIndex = -1; + if (course == null) + continue; - if (course.isScheduled()) { - dayIndex = course.getExamDay(); - slotIndex = course.getExamTimeSlot(); - classroom = course.getAssignedClassroom(); + String dateStr = "Not Scheduled"; + String timeStr = "-"; + String classroom = "-"; + int dayIndex = -1, slotIndex = -1; - if (config != null) { - TimeSlot slot = config.getTimeSlot(dayIndex, slotIndex); - if (slot != null) { - dateStr = slot.getDate().toString(); // YYYY-MM-DD - timeStr = slot.getStartTime().toString() + " - " + slot.getEndTime().toString(); - } else { - dateStr = "Day " + (dayIndex + 1); - timeStr = "Slot " + (slotIndex + 1); - } - } else { - // Fallback if no config saved - dateStr = "Day " + (dayIndex + 1); - timeStr = "Slot " + (slotIndex + 1); - } + if (course.isScheduled()) { + dayIndex = course.getExamDay(); + slotIndex = course.getExamTimeSlot(); + classroom = course.getAssignedClassroom(); + + TimeSlot slot = config != null ? config.getTimeSlot(dayIndex, slotIndex) : null; + if (slot != null) { + dateStr = slot.getDate().toString(); + timeStr = slot.getStartTime() + " - " + slot.getEndTime(); + } else { + dateStr = "Day " + (dayIndex + 1); + timeStr = "Slot " + (slotIndex + 1); } - - entries.add(new CourseScheduleEntry(courseCode, dateStr, timeStr, classroom, dayIndex, slotIndex)); } + + entries.add(new CourseScheduleEntry(courseCode, dateStr, timeStr, classroom, dayIndex, slotIndex)); } - // Sort by day and time entries.sort(Comparator.comparingInt(CourseScheduleEntry::getDayIndex) .thenComparingInt(CourseScheduleEntry::getSlotIndex)); - - // Analyze for highlights analyzeSchedule(entries); - scheduleTable.setItems(FXCollections.observableArrayList(entries)); } private void analyzeSchedule(List entries) { - if (entries.isEmpty()) - return; - for (int i = 0; i < entries.size(); i++) { CourseScheduleEntry current = entries.get(i); if (current.getDayIndex() == -1) - continue; // Skip unscheduled + continue; - // Check for multiple exams on same day - int examsOnDay = 0; + // Check for multiple exams and conflicts on same day for (CourseScheduleEntry other : entries) { if (other.getDayIndex() == current.getDayIndex() && other.getDayIndex() != -1) { - examsOnDay++; + current.isMultipleExamsOnDay = true; if (other.getSlotIndex() == current.getSlotIndex() && other != current) { current.hasConflictWarning = true; } } } - if (examsOnDay > 1) { - current.isMultipleExamsOnDay = true; - } - // Check for consecutive days (look at previous scheduled exam) - // Since list is sorted, we can look at previous entry if it exists + // Check for consecutive days with previous exam if (i > 0) { CourseScheduleEntry prev = entries.get(i - 1); - if (prev.getDayIndex() != -1 && - current.getDayIndex() == prev.getDayIndex() + 1) { + if (prev.getDayIndex() != -1 && current.getDayIndex() == prev.getDayIndex() + 1) { current.isConsecutiveDay = true; } } diff --git a/src/main/java/org/example/se302/model/Course.java b/src/main/java/org/example/se302/model/Course.java index 48250c4..8bc4246 100644 --- a/src/main/java/org/example/se302/model/Course.java +++ b/src/main/java/org/example/se302/model/Course.java @@ -4,72 +4,40 @@ import java.util.ArrayList; import java.util.List; /** - * Represents a course in the exam scheduling system. - * Contains course information and exam scheduling details. + * Represents a course with exam scheduling details. */ public class Course { private String courseCode; private List enrolledStudents; - - // Exam schedule fields (index-based) - private int examDay; // -1 if not scheduled, 0-based day index - private int examTimeSlot; // -1 if not scheduled, 0-based slot index - private String assignedClassroom; // null if not scheduled - - // Legacy field for backward compatibility - private String examDateTime; // null if not scheduled (string format) + private int examDay = -1; + private int examTimeSlot = -1; + private String assignedClassroom; public Course(String courseCode) { this.courseCode = courseCode; this.enrolledStudents = new ArrayList<>(); - this.examDay = -1; - this.examTimeSlot = -1; - this.assignedClassroom = null; - this.examDateTime = null; } - /** - * Checks if this course has been scheduled for an exam. - */ public boolean isScheduled() { return examDay >= 0 && examTimeSlot >= 0 && assignedClassroom != null; } - /** - * Clears the exam schedule for this course. - */ public void clearSchedule() { this.examDay = -1; this.examTimeSlot = -1; this.assignedClassroom = null; - this.examDateTime = null; } - /** - * Sets the complete exam schedule. - * - * @param day Day index (0-based) - * @param timeSlot Time slot index (0-based) - * @param classroomId Classroom ID - */ public void setExamSchedule(int day, int timeSlot, String classroomId) { this.examDay = day; this.examTimeSlot = timeSlot; this.assignedClassroom = classroomId; } - /** - * Gets a unique key for this course's time slot. - */ public String getTimeSlotKey() { - if (!isScheduled()) { - return null; - } - return "D" + examDay + "_S" + examTimeSlot; + return isScheduled() ? "D" + examDay + "_S" + examTimeSlot : null; } - // Basic getters and setters - public String getCourseCode() { return courseCode; } @@ -82,14 +50,13 @@ public class Course { return enrolledStudents; } - public void setEnrolledStudents(List enrolledStudents) { - this.enrolledStudents = enrolledStudents; + public void setEnrolledStudents(List students) { + this.enrolledStudents = students; } public void addStudent(String studentId) { - if (!enrolledStudents.contains(studentId)) { + if (!enrolledStudents.contains(studentId)) enrolledStudents.add(studentId); - } } public void removeStudent(String studentId) { @@ -100,8 +67,6 @@ public class Course { return enrolledStudents.size(); } - // Schedule field getters and setters - public int getExamDay() { return examDay; } @@ -114,24 +79,16 @@ public class Course { return examTimeSlot; } - public void setExamTimeSlot(int examTimeSlot) { - this.examTimeSlot = examTimeSlot; + public void setExamTimeSlot(int slot) { + this.examTimeSlot = slot; } public String getAssignedClassroom() { return assignedClassroom; } - public void setAssignedClassroom(String assignedClassroom) { - this.assignedClassroom = assignedClassroom; - } - - public String getExamDateTime() { - return examDateTime; - } - - public void setExamDateTime(String examDateTime) { - this.examDateTime = examDateTime; + public void setAssignedClassroom(String classroom) { + this.assignedClassroom = classroom; } @Override