mirror of
https://github.com/sabazadam/Se302.git
synced 2025-12-31 12:21:22 +00:00
Modify Classroom and Course Schedule views to show generated schedule
This commit is contained in:
@@ -236,13 +236,13 @@ public class ExamEditDialog extends Dialog<ExamEditDialog.EditResult> {
|
|||||||
validationPanel.setStyle("-fx-background-color: #e8f5e9; -fx-background-radius: 5;");
|
validationPanel.setStyle("-fx-background-color: #e8f5e9; -fx-background-radius: 5;");
|
||||||
updateButtonStates(true, false);
|
updateButtonStates(true, false);
|
||||||
} else if (currentValidation.hasHardViolations()) {
|
} else if (currentValidation.hasHardViolations()) {
|
||||||
validationStatusLabel.setText("❌ Constraint violations found");
|
validationStatusLabel.setText("Constraint violations found!");
|
||||||
validationStatusLabel.setTextFill(Color.web("#e74c3c"));
|
validationStatusLabel.setTextFill(Color.web("#e74c3c"));
|
||||||
violationDetails.setText(currentValidation.getFormattedMessage());
|
violationDetails.setText(currentValidation.getFormattedMessage());
|
||||||
validationPanel.setStyle("-fx-background-color: #ffebee; -fx-background-radius: 5;");
|
validationPanel.setStyle("-fx-background-color: #ffebee; -fx-background-radius: 5;");
|
||||||
updateButtonStates(false, true);
|
updateButtonStates(false, true);
|
||||||
} else {
|
} else {
|
||||||
validationStatusLabel.setText("⚠️ Warnings found");
|
validationStatusLabel.setText("Warnings found!");
|
||||||
validationStatusLabel.setTextFill(Color.web("#f39c12"));
|
validationStatusLabel.setTextFill(Color.web("#f39c12"));
|
||||||
violationDetails.setText(currentValidation.getFormattedMessage());
|
violationDetails.setText(currentValidation.getFormattedMessage());
|
||||||
validationPanel.setStyle("-fx-background-color: #fff3e0; -fx-background-radius: 5;");
|
validationPanel.setStyle("-fx-background-color: #fff3e0; -fx-background-radius: 5;");
|
||||||
|
|||||||
@@ -11,14 +11,13 @@ import javafx.scene.control.TableColumn;
|
|||||||
import javafx.scene.control.TableRow;
|
import javafx.scene.control.TableRow;
|
||||||
import javafx.scene.control.TableView;
|
import javafx.scene.control.TableView;
|
||||||
import org.example.se302.model.Classroom;
|
import org.example.se302.model.Classroom;
|
||||||
import org.example.se302.model.ExamAssignment;
|
import org.example.se302.model.Course;
|
||||||
import org.example.se302.model.ScheduleConfiguration;
|
import org.example.se302.model.ScheduleConfiguration;
|
||||||
import org.example.se302.service.DataManager;
|
import org.example.se302.service.DataManager;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller for the Classroom Schedule view.
|
* Controller for the Classroom Schedule view.
|
||||||
@@ -47,10 +46,6 @@ public class ScheduleClassroomController {
|
|||||||
|
|
||||||
private DataManager dataManager;
|
private DataManager dataManager;
|
||||||
|
|
||||||
// Reference to the current schedule state (set by parent controller)
|
|
||||||
private Map<String, ExamAssignment> currentAssignments;
|
|
||||||
private ScheduleConfiguration configuration;
|
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
dataManager = DataManager.getInstance();
|
dataManager = DataManager.getInstance();
|
||||||
@@ -112,15 +107,35 @@ public class ScheduleClassroomController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// Refresh when tab is selected - find TabPane once scene is available
|
||||||
* Sets the current schedule assignments. Called by parent controller after
|
scheduleTable.sceneProperty().addListener((obs, oldScene, newScene) -> {
|
||||||
* schedule generation.
|
if (newScene != null) {
|
||||||
*/
|
// Find parent TabPane and listen for selection changes
|
||||||
public void setScheduleData(Map<String, ExamAssignment> assignments, ScheduleConfiguration config) {
|
javafx.scene.Parent parent = scheduleTable.getParent();
|
||||||
this.currentAssignments = assignments;
|
while (parent != null) {
|
||||||
this.configuration = config;
|
if (parent.getParent() instanceof javafx.scene.control.TabPane) {
|
||||||
|
javafx.scene.control.TabPane tabPane = (javafx.scene.control.TabPane) parent
|
||||||
|
.getParent();
|
||||||
|
// Find which tab contains our content
|
||||||
|
for (javafx.scene.control.Tab tab : tabPane.getTabs()) {
|
||||||
|
if (tab.getContent() == parent) {
|
||||||
|
tab.selectedProperty().addListener(
|
||||||
|
(o, wasSelected, isSelected) -> {
|
||||||
|
if (isSelected && classroomComboBox
|
||||||
|
.getValue() != null) {
|
||||||
|
onShowSchedule();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
parent = parent.getParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
@@ -132,52 +147,52 @@ public class ScheduleClassroomController {
|
|||||||
selectedClassroomLabel.setText("Schedule for: " + selected.getClassroomId() +
|
selectedClassroomLabel.setText("Schedule for: " + selected.getClassroomId() +
|
||||||
" (Capacity: " + selected.getCapacity() + ")");
|
" (Capacity: " + selected.getCapacity() + ")");
|
||||||
|
|
||||||
|
ScheduleConfiguration config = dataManager.getActiveConfiguration();
|
||||||
ObservableList<ClassroomSlotEntry> entries = FXCollections.observableArrayList();
|
ObservableList<ClassroomSlotEntry> entries = FXCollections.observableArrayList();
|
||||||
int totalSlots = 0;
|
int totalSlots = 0;
|
||||||
int usedSlots = 0;
|
int usedSlots = 0;
|
||||||
int totalStudents = 0;
|
int totalStudents = 0;
|
||||||
|
|
||||||
// If we have assignments, filter by this classroom
|
// Find all courses scheduled in this classroom
|
||||||
if (currentAssignments != null && !currentAssignments.isEmpty()) {
|
for (Course course : dataManager.getCourses()) {
|
||||||
for (ExamAssignment assignment : currentAssignments.values()) {
|
if (course.isScheduled() &&
|
||||||
if (assignment.isAssigned() &&
|
selected.getClassroomId().equals(course.getAssignedClassroom())) {
|
||||||
selected.getClassroomId().equals(assignment.getClassroomId())) {
|
|
||||||
|
|
||||||
// Format date
|
int dayIndex = course.getExamDay();
|
||||||
String dateStr;
|
int slotIndex = course.getExamTimeSlot();
|
||||||
if (configuration != null && configuration.getStartDate() != null) {
|
|
||||||
LocalDate examDate = configuration.getStartDate()
|
|
||||||
.plusDays(assignment.getDay());
|
|
||||||
dateStr = examDate.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
|
|
||||||
} else {
|
|
||||||
dateStr = "Day " + (assignment.getDay() + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format time
|
// Format date
|
||||||
String timeStr = "Slot " + (assignment.getTimeSlotIndex() + 1);
|
String dateStr;
|
||||||
|
if (config != null && config.getStartDate() != null) {
|
||||||
// Calculate utilization percentage for this slot
|
LocalDate examDate = config.getStartDate().plusDays(dayIndex);
|
||||||
int studentCount = assignment.getStudentCount();
|
dateStr = examDate.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
|
||||||
int capacity = selected.getCapacity();
|
} else {
|
||||||
int utilizationPercent = capacity > 0 ? (studentCount * 100) / capacity : 0;
|
dateStr = "Day " + (dayIndex + 1);
|
||||||
String utilizationStr = utilizationPercent + "%";
|
|
||||||
|
|
||||||
entries.add(new ClassroomSlotEntry(
|
|
||||||
dateStr, timeStr, assignment.getCourseCode(),
|
|
||||||
studentCount, utilizationStr, utilizationPercent,
|
|
||||||
assignment.getDay(), assignment.getTimeSlotIndex()));
|
|
||||||
|
|
||||||
usedSlots++;
|
|
||||||
totalStudents += studentCount;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate total possible slots
|
String timeStr = "Slot " + (slotIndex + 1);
|
||||||
if (configuration != null) {
|
|
||||||
totalSlots = configuration.getNumDays() * configuration.getSlotsPerDay();
|
// 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate total possible slots
|
||||||
|
if (config != null) {
|
||||||
|
totalSlots = config.getNumDays() * config.getSlotsPerDay();
|
||||||
|
}
|
||||||
|
|
||||||
// Sort by day then slot
|
// Sort by day then slot
|
||||||
entries.sort(Comparator.comparingInt(ClassroomSlotEntry::getDayIndex)
|
entries.sort(Comparator.comparingInt(ClassroomSlotEntry::getDayIndex)
|
||||||
.thenComparingInt(ClassroomSlotEntry::getSlotIndex));
|
.thenComparingInt(ClassroomSlotEntry::getSlotIndex));
|
||||||
|
|||||||
@@ -9,14 +9,12 @@ import javafx.scene.control.TableColumn;
|
|||||||
import javafx.scene.control.TableRow;
|
import javafx.scene.control.TableRow;
|
||||||
import javafx.scene.control.TableView;
|
import javafx.scene.control.TableView;
|
||||||
import org.example.se302.model.Course;
|
import org.example.se302.model.Course;
|
||||||
import org.example.se302.model.ExamAssignment;
|
|
||||||
import org.example.se302.model.ScheduleConfiguration;
|
import org.example.se302.model.ScheduleConfiguration;
|
||||||
import org.example.se302.service.DataManager;
|
import org.example.se302.service.DataManager;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
// Color palette for days (pastel colors for readability)
|
// Color palette for days (pastel colors for readability)
|
||||||
// Day 0 = Light Blue, Day 1 = Light Green, Day 2 = Light Yellow, etc.
|
// Day 0 = Light Blue, Day 1 = Light Green, Day 2 = Light Yellow, etc.
|
||||||
@@ -43,11 +41,6 @@ public class ScheduleCourseController {
|
|||||||
|
|
||||||
private DataManager dataManager;
|
private DataManager dataManager;
|
||||||
|
|
||||||
// Reference to the current schedule state (set by parent controller or loaded
|
|
||||||
// from DB)
|
|
||||||
private Map<String, ExamAssignment> currentAssignments;
|
|
||||||
private ScheduleConfiguration configuration;
|
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
dataManager = DataManager.getInstance();
|
dataManager = DataManager.getInstance();
|
||||||
@@ -122,19 +115,38 @@ public class ScheduleCourseController {
|
|||||||
// Listen for data changes
|
// Listen for data changes
|
||||||
dataManager.getCourses().addListener(
|
dataManager.getCourses().addListener(
|
||||||
(javafx.collections.ListChangeListener<Course>) c -> loadScheduleData());
|
(javafx.collections.ListChangeListener<Course>) c -> loadScheduleData());
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// Refresh when tab is selected - find TabPane once scene is available
|
||||||
* Sets the current schedule assignments. Called by parent controller after
|
courseScheduleTable.sceneProperty().addListener((obs, oldScene, newScene) -> {
|
||||||
* schedule generation.
|
if (newScene != null) {
|
||||||
*/
|
loadScheduleData();
|
||||||
public void setScheduleData(Map<String, ExamAssignment> assignments, ScheduleConfiguration config) {
|
// Find parent TabPane and listen for selection changes
|
||||||
this.currentAssignments = assignments;
|
javafx.scene.Parent parent = courseScheduleTable.getParent();
|
||||||
this.configuration = config;
|
while (parent != null) {
|
||||||
loadScheduleData();
|
if (parent.getParent() instanceof javafx.scene.control.TabPane) {
|
||||||
|
javafx.scene.control.TabPane tabPane = (javafx.scene.control.TabPane) parent
|
||||||
|
.getParent();
|
||||||
|
// Find which tab contains our content
|
||||||
|
for (javafx.scene.control.Tab tab : tabPane.getTabs()) {
|
||||||
|
if (tab.getContent() == parent) {
|
||||||
|
tab.selectedProperty().addListener(
|
||||||
|
(o, wasSelected, isSelected) -> {
|
||||||
|
if (isSelected)
|
||||||
|
loadScheduleData();
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
parent = parent.getParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadScheduleData() {
|
private void loadScheduleData() {
|
||||||
|
ScheduleConfiguration config = dataManager.getActiveConfiguration();
|
||||||
ObservableList<CourseScheduleEntry> entries = FXCollections.observableArrayList();
|
ObservableList<CourseScheduleEntry> entries = FXCollections.observableArrayList();
|
||||||
|
|
||||||
for (Course course : dataManager.getCourses()) {
|
for (Course course : dataManager.getCourses()) {
|
||||||
@@ -144,33 +156,24 @@ public class ScheduleCourseController {
|
|||||||
String dateStr = "Not Scheduled";
|
String dateStr = "Not Scheduled";
|
||||||
String timeStr = "-";
|
String timeStr = "-";
|
||||||
String classroomStr = "-";
|
String classroomStr = "-";
|
||||||
int dayIndex = Integer.MAX_VALUE; // For sorting unscheduled items last
|
int dayIndex = Integer.MAX_VALUE;
|
||||||
int slotIndex = Integer.MAX_VALUE;
|
int slotIndex = Integer.MAX_VALUE;
|
||||||
|
|
||||||
// Check if we have an assignment for this course
|
// Check if this course has been scheduled
|
||||||
if (currentAssignments != null && currentAssignments.containsKey(courseCode)) {
|
if (course.isScheduled()) {
|
||||||
ExamAssignment assignment = currentAssignments.get(courseCode);
|
dayIndex = course.getExamDay();
|
||||||
|
slotIndex = course.getExamTimeSlot();
|
||||||
|
classroomStr = course.getAssignedClassroom();
|
||||||
|
|
||||||
if (assignment.isAssigned()) {
|
// Format date using configuration's start date
|
||||||
dayIndex = assignment.getDay();
|
if (config != null && config.getStartDate() != null) {
|
||||||
slotIndex = assignment.getTimeSlotIndex();
|
LocalDate examDate = config.getStartDate().plusDays(dayIndex);
|
||||||
|
dateStr = examDate.format(DateTimeFormatter.ofPattern("dd/MM/yyyy (EEEE)"));
|
||||||
// Format date based on configuration start date + day offset
|
} else {
|
||||||
if (configuration != null && configuration.getStartDate() != null) {
|
dateStr = "Day " + (dayIndex + 1);
|
||||||
LocalDate examDate = configuration.getStartDate().plusDays(dayIndex);
|
|
||||||
dateStr = examDate.format(
|
|
||||||
DateTimeFormatter.ofPattern("dd/MM/yyyy (EEEE)"));
|
|
||||||
} else {
|
|
||||||
dateStr = "Day " + (dayIndex + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format time slot
|
|
||||||
timeStr = "Slot " + (slotIndex + 1);
|
|
||||||
|
|
||||||
// Classroom
|
|
||||||
classroomStr = assignment.getClassroomId() != null ? assignment.getClassroomId()
|
|
||||||
: "-";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
timeStr = "Slot " + (slotIndex + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
entries.add(new CourseScheduleEntry(courseCode, enrolled, dateStr, timeStr, classroomStr,
|
entries.add(new CourseScheduleEntry(courseCode, enrolled, dateStr, timeStr, classroomStr,
|
||||||
|
|||||||
Reference in New Issue
Block a user