97 KiB
EXAM SCHEDULING SYSTEM - MEMORY BANK
Project: Exam Planner Desktop Application Course: SE302 - Software Engineering Team: Team 3, Section 1 Date Started: November 26, 2025 Technology Stack: Java 17+, JavaFX, SQLite, Maven
TABLE OF CONTENTS
- Project Overview
- Team Members & Roles
- Requirements Summary
- Database Schema
- Architecture & Design Patterns
- Algorithm Design
- Constraints & Business Rules
- User Interface Design
- API Contracts Between Layers
- Testing Strategy
- Development Workflow
- Key Technical Decisions
PROJECT OVERVIEW
What We're Building
A Windows desktop application that automatically generates exam schedules for educational institutions by solving a constraint satisfaction problem (CSP). The system assigns exams to classrooms across time slots while respecting hard constraints like student availability and classroom capacity.
Core Value Proposition
- Automates a complex, time-consuming manual scheduling process
- Guarantees all hard constraints are satisfied (no scheduling conflicts)
- Optimizes according to configurable strategies (minimize days, balance distribution, etc.)
- Provides multiple views (by classroom, student, course, day)
- Enables manual adjustments with real-time constraint validation
Target Users
Student Affairs staff at educational institutions who need to:
- Schedule exams for 50-500+ students across 10-50+ courses
- Manage classroom allocation based on capacity
- Ensure no student conflicts (consecutive exams, max 2 per day)
- Export schedules for distribution
Key Success Metrics
- Performance: Generate schedule for 50 courses/500 students in <10 seconds
- Reliability: 100% compliance with hard constraints (no violations allowed)
- Usability: New users can generate first schedule within 30 minutes
- Accuracy: Zero data corruption, all imports validated
TEAM MEMBERS & ROLES
Team Roster
| Name | Student ID | Role Specialty | Primary Responsibilities |
|---|---|---|---|
| Kerem Bozdag | 20200602012 | Database & Data Layer | SQLite schema, DAO pattern, CSV import/export, data validation |
| Milena Larissa Ünal | 20230602107 | Algorithm Specialist | CSP backtracking solver, constraint validation, optimization strategies |
| Rabia Tülay Gokdag | 20210602029 | UI/FXML Specialist | JavaFX views, FXML layouts, Scene Builder, UI components |
| Mehmet Sefa Keskin | 20230602047 | Controller Layer | MVC controllers, event handling, UI-business logic integration |
| Feyza Gereme | 20230602028 | Testing & QA | JUnit tests, integration testing, CI/CD setup, test automation |
| Emin Arslan | 20230602007 | Documentation & Integration | JavaDoc, user manual, code reviews, feature integration |
Collaboration Model
- Specialist ownership with cross-functional support
- Weekly integration meetings to sync work across layers
- Pull Request reviews required from at least one other team member
- Pair programming sessions for complex integration points (UI-Algorithm, Database-Algorithm)
REQUIREMENTS SUMMARY
Functional Requirements
FR1: Data Import from CSV
- Import 4 types of CSV files:
- Student IDs - List of all students (one per line)
- Course Codes - List of all courses (one per line)
- Classroom Capacities - Format:
ClassroomID;Capacity(e.g.,Classroom_01;40) - Attendance Lists - Student-Course enrollment mapping
- Validation requirements:
- Detect and reject duplicate entries
- Validate file format before processing
- Show line numbers for errors
- User feedback:
- Progress indicator during import
- Summary report (X students imported, Y duplicates rejected)
FR2: Configuration of Exam Period
- User can specify:
- Number of exam days (e.g., 5 days)
- Number of time slots per day (e.g., 4 slots)
- Total slots = Days × Slots (e.g., 5 × 4 = 20 exam slots)
- Validation: Must have enough slots for all courses
FR3: Optimization Strategy Selection
- User chooses one strategy before generation:
- Minimize Days Used - Pack exams into fewest days possible
- Balance Distribution - Spread exams evenly across all days
- Minimize Classrooms - Use fewest classrooms possible
- Balance Classrooms Per Day - Even classroom usage across days
- Strategy affects solver's variable/value ordering heuristics
FR4: Automatic Schedule Generation
- Algorithm: Backtracking CSP solver with constraint propagation
- Performance targets:
- Small datasets (50 courses, 500 students): <10 seconds
- Medium datasets (100 courses, 1000 students): <2 minutes
- Large datasets: May take several minutes (show progress)
- User experience:
- Progress indicator with percentage complete
- "Cancel" button to abort long-running generations
- Success/failure notification with details
FR5: Multi-View Schedule Display
Four distinct view modes:
-
Classroom View
- Shows: Which exams are in which classrooms
- Columns: Classroom ID, Day, Time Slot, Course Code, Student Count
-
Student View
- Shows: Personal exam schedule for each student
- Columns: Student ID, Course Code, Day, Time Slot, Classroom
- Filterable by student ID
-
Course View
- Shows: Exact time and classroom for each course exam
- Columns: Course Code, Day, Time Slot, Classroom, Enrolled Count
-
Day View
- Shows: All exams scheduled for each day/time slot
- Grid format: Days (rows) × Time Slots (columns)
- Cell contents: Course codes in that slot
FR6: Export to CSV and Excel
- CSV Export: Simple comma-separated format for each view
- Excel Export:
- Multi-sheet workbook (one sheet per view)
- Formatted headers, borders, column widths
- Ready for printing
- User can choose export format and destination folder
FR7: Manual Schedule Adjustments
- Allowed operations:
- Move exam to different time slot
- Move exam to different classroom
- Swap two exams
- Constraint validation:
- System checks all constraints before applying change
- If any constraint would be violated, reject change
- Show specific error message explaining which constraint prevents the change
- Limitations: Cannot change student enrollments or classroom capacities
FR8: Database Persistence (SQLite)
- Local storage: All data persisted in local SQLite file
- Saved data:
- Imported student/course/classroom data
- Generated schedules with metadata (creation date, optimization strategy)
- User configuration settings
- Operations:
- Save current schedule
- Load previously saved schedule
- Delete old schedules
FR10: Conflict Detection and Reporting
- When no solution exists:
- Identify which constraints cannot be satisfied
- Report specific conflicts:
- Student X has 3 exams on Day Y (violates max 2 per day)
- Course Z has 50 students but max classroom capacity is 40
- Students A, B, C have consecutive exam conflicts
- Recommendations:
- Extend exam period (add more days/slots)
- Add classrooms with higher capacity
- Reduce course enrollments
- Alternative: Release consecutive exam constraint (not recommended)
FR12: Schedule History
- View previous schedules with metadata:
- Creation date and time
- Optimization strategy used
- Number of days/slots configured
- Course/student counts
- Operations:
- Load and view any historical schedule
- Compare different schedule versions
- Export historical schedules
Non-Functional Requirements
NFR1: Usability
- Learning curve: New users can generate first schedule within 30 minutes
- Interface clarity: Intuitive labels, clear navigation, logical workflow
- Help system: Built-in user manual with screenshots and examples
- Error messages: Clear, actionable, non-technical language
NFR2: Error Messaging Standards
- Format: "[Context] Problem detected: [Specific issue]. [Suggested fix]"
- Examples:
- ✅ GOOD: "Import failed: Duplicate student ID 'Std_ID_123' found on lines 45 and 67. Remove duplicate entry and try again."
- ❌ BAD: "Error: Duplicate key violation in students table"
- Guidelines:
- Always include line numbers for file import errors
- Suggest specific corrective actions
- Avoid technical jargon (no SQL errors, stack traces to users)
NFR3: Performance
- Small datasets: <10 seconds for 50 courses, 500 students
- Responsiveness: UI remains responsive during generation (background thread)
- Database queries: Optimized with proper indexes (<100ms for typical queries)
NFR4: Reliability
- No crashes: Graceful error handling for all edge cases
- Data integrity: ACID transactions for all database operations
- Validation: All user inputs validated before processing
- Backup: Export capability serves as backup mechanism
NFR6: Maintainability
- Code organization: Clear package structure following MVC pattern
- Naming conventions: Java standard conventions (camelCase, PascalCase)
- Documentation: JavaDoc for all public methods and classes
- Comments: Explain "why" for complex algorithms, not obvious "what"
- Extensibility: Easy to add new optimization strategies, export formats, constraints
DATABASE SCHEMA
Entity-Relationship Model
┌─────────────┐ ┌──────────────┐ ┌──────────────┐
│ Student │ │ Enrollment │ │ Course │
├─────────────┤ ├──────────────┤ ├──────────────┤
│ student_id │◄───────►│ student_id │◄───────►│ course_code │
│ │ (M:N) │ course_code │ (M:N)│ │
└─────────────┘ └──────────────┘ └──────────────┘
│
│ (1:M)
▼
┌──────────────┐ ┌─────────────────┐
│ Classroom │◄────────│ ExamAssignment │
├──────────────┤ (1:M) ├─────────────────┤
│ classroom_id │ │ exam_id │
│ capacity │ │ course_code │
└──────────────┘ │ classroom_id │
│ day │
│ time_slot │
┌──────────────┐ │ schedule_id │
│ Schedule │◄────────│ │
├──────────────┤ (1:M) └─────────────────┘
│ schedule_id │
│ created_date │
│ strategy │
│ num_days │
│ slots_per_day│
└──────────────┘
Table Definitions (SQLite)
1. students
CREATE TABLE students (
student_id TEXT PRIMARY KEY NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
- Purpose: Store all student records
- Sample data: Std_ID_001, Std_ID_002, ..., Std_ID_250
2. courses
CREATE TABLE courses (
course_code TEXT PRIMARY KEY NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
- Purpose: Store all course records
- Sample data: CourseCode_01, CourseCode_02, ..., CourseCode_20
3. classrooms
CREATE TABLE classrooms (
classroom_id TEXT PRIMARY KEY NOT NULL,
capacity INTEGER NOT NULL CHECK(capacity > 0),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
- Purpose: Store classroom information with seating capacity
- Sample data: Classroom_01 (capacity: 40), Classroom_02 (capacity: 40), etc.
- Validation: Capacity must be positive integer
4. enrollments
CREATE TABLE enrollments (
enrollment_id INTEGER PRIMARY KEY AUTOINCREMENT,
student_id TEXT NOT NULL,
course_code TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (student_id) REFERENCES students(student_id) ON DELETE CASCADE,
FOREIGN KEY (course_code) REFERENCES courses(course_code) ON DELETE CASCADE,
UNIQUE(student_id, course_code)
);
CREATE INDEX idx_enrollments_student ON enrollments(student_id);
CREATE INDEX idx_enrollments_course ON enrollments(course_code);
- Purpose: Many-to-many relationship between students and courses
- Uniqueness: One enrollment record per student-course pair
- Indexes: Fast lookups for "which courses for student X" and "which students in course Y"
5. schedules
CREATE TABLE schedules (
schedule_id INTEGER PRIMARY KEY AUTOINCREMENT,
created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
optimization_strategy TEXT NOT NULL,
num_days INTEGER NOT NULL CHECK(num_days > 0),
slots_per_day INTEGER NOT NULL CHECK(slots_per_day > 0),
status TEXT DEFAULT 'generated' CHECK(status IN ('generated', 'saved', 'archived'))
);
- Purpose: Store metadata for each generated schedule
- Optimization strategies: 'minimize_days', 'balance_distribution', 'minimize_classrooms', 'balance_classrooms'
- Status values:
- 'generated' - Just created
- 'saved' - User explicitly saved
- 'archived' - Old schedule kept for history
6. exam_assignments
CREATE TABLE exam_assignments (
exam_id INTEGER PRIMARY KEY AUTOINCREMENT,
schedule_id INTEGER NOT NULL,
course_code TEXT NOT NULL,
classroom_id TEXT NOT NULL,
day INTEGER NOT NULL CHECK(day > 0),
time_slot INTEGER NOT NULL CHECK(time_slot > 0),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (schedule_id) REFERENCES schedules(schedule_id) ON DELETE CASCADE,
FOREIGN KEY (course_code) REFERENCES courses(course_code) ON DELETE CASCADE,
FOREIGN KEY (classroom_id) REFERENCES classrooms(classroom_id) ON DELETE CASCADE,
UNIQUE(schedule_id, course_code),
UNIQUE(schedule_id, classroom_id, day, time_slot)
);
CREATE INDEX idx_assignments_schedule ON exam_assignments(schedule_id);
CREATE INDEX idx_assignments_course ON exam_assignments(course_code);
CREATE INDEX idx_assignments_classroom_time ON exam_assignments(classroom_id, day, time_slot);
- Purpose: Store exam scheduling assignments (which course in which room at what time)
- Uniqueness constraints:
- Each course appears once per schedule
- Each classroom-day-timeslot combination used once per schedule
- Indexes: Fast lookups for schedule queries, course lookups, and classroom availability checks
Sample Data Statistics
Based on provided sample data:
- Students: 250 (Std_ID_001 to Std_ID_250)
- Courses: 20 (CourseCode_01 to CourseCode_20)
- Classrooms: 10 (Classroom_01 to Classroom_10, each capacity 40)
- Average enrollments per course: ~40 students
- Total enrollment records: ~800 (20 courses × ~40 students)
Database File Location
- Development:
./data/exam_scheduler.db - Production: User's Documents folder or configurable path
- Backup: Auto-export to CSV on schedule save
ARCHITECTURE & DESIGN PATTERNS
Overall Architecture: MVC (Model-View-Controller)
┌─────────────────────────────────────────────────────────────┐
│ VIEW LAYER │
│ (JavaFX FXML + Scene Builder) │
│ │
│ • ImportView.fxml • ScheduleView.fxml │
│ • ConfigurationView.fxml • ClassroomView.fxml │
│ • StudentView.fxml • CourseView.fxml │
│ • DayView.fxml • ExportView.fxml │
└──────────────────┬──────────────────────────────────────────┘
│ User Events (button clicks, etc.)
▼
┌─────────────────────────────────────────────────────────────┐
│ CONTROLLER LAYER │
│ (JavaFX Controllers) │
│ │
│ • ImportController • ScheduleController │
│ • ConfigurationController • ViewControllers │
│ • ExportController • MainController │
└──────────────────┬──────────────────────────────────────────┘
│ Method calls
▼
┌─────────────────────────────────────────────────────────────┐
│ BUSINESS LOGIC LAYER │
│ (Service Classes) │
│ │
│ • ScheduleService • ImportService │
│ • CSPSolver • ExportService │
│ • ConstraintValidator • ConfigurationService │
│ • OptimizationStrategy • ConflictDetector │
└──────────────────┬──────────────────────────────────────────┘
│ Data operations
▼
┌─────────────────────────────────────────────────────────────┐
│ DATA ACCESS LAYER │
│ (DAO Pattern) │
│ │
│ • StudentDAO • ScheduleDAO │
│ • CourseDAO • ExamAssignmentDAO │
│ • ClassroomDAO • EnrollmentDAO │
│ • DatabaseConnection • TransactionManager │
└──────────────────┬──────────────────────────────────────────┘
│ SQL queries
▼
┌─────────────────────────────────────────────────────────────┐
│ DATA LAYER │
│ (SQLite Database) │
│ │
│ exam_scheduler.db │
└─────────────────────────────────────────────────────────────┘
Package Structure
src/main/java/
├── com.se302.examscheduler/
│ ├── model/ # Domain Models (POJOs)
│ │ ├── Student.java
│ │ ├── Course.java
│ │ ├── Classroom.java
│ │ ├── Enrollment.java
│ │ ├── Schedule.java
│ │ ├── ExamAssignment.java
│ │ └── ScheduleConfiguration.java
│ │
│ ├── dao/ # Data Access Objects
│ │ ├── StudentDAO.java
│ │ ├── CourseDAO.java
│ │ ├── ClassroomDAO.java
│ │ ├── EnrollmentDAO.java
│ │ ├── ScheduleDAO.java
│ │ ├── ExamAssignmentDAO.java
│ │ └── DatabaseConnection.java
│ │
│ ├── service/ # Business Logic
│ │ ├── ScheduleService.java
│ │ ├── ImportService.java
│ │ ├── ExportService.java
│ │ ├── ConfigurationService.java
│ │ └── ValidationService.java
│ │
│ ├── algorithm/ # CSP Solver
│ │ ├── CSPSolver.java
│ │ ├── ConstraintValidator.java
│ │ ├── ConflictDetector.java
│ │ ├── strategy/
│ │ │ ├── OptimizationStrategy.java (interface)
│ │ │ ├── MinimizeDaysStrategy.java
│ │ │ ├── BalanceDistributionStrategy.java
│ │ │ ├── MinimizeClassroomsStrategy.java
│ │ │ └── BalanceClassroomsStrategy.java
│ │ └── heuristics/
│ │ ├── VariableOrderingHeuristic.java
│ │ └── ValueOrderingHeuristic.java
│ │
│ ├── controller/ # JavaFX Controllers
│ │ ├── MainController.java
│ │ ├── ImportController.java
│ │ ├── ConfigurationController.java
│ │ ├── ScheduleController.java
│ │ ├── ClassroomViewController.java
│ │ ├── StudentViewController.java
│ │ ├── CourseViewController.java
│ │ ├── DayViewController.java
│ │ └── ExportController.java
│ │
│ ├── util/ # Utility Classes
│ │ ├── CSVParser.java
│ │ ├── ExcelExporter.java
│ │ ├── ValidationUtil.java
│ │ └── ProgressTracker.java
│ │
│ └── Main.java # Application Entry Point
│
src/main/resources/
├── fxml/ # FXML Layout Files
│ ├── MainWindow.fxml
│ ├── ImportView.fxml
│ ├── ConfigurationView.fxml
│ ├── ScheduleView.fxml
│ ├── ClassroomView.fxml
│ ├── StudentView.fxml
│ ├── CourseView.fxml
│ ├── DayView.fxml
│ └── ExportView.fxml
│
├── css/ # Stylesheets
│ └── styles.css
│
├── images/ # Icons and images
│
└── database/
└── schema.sql # Database initialization script
src/test/java/
├── com.se302.examscheduler/
│ ├── dao/ # DAO Tests
│ ├── service/ # Service Tests
│ ├── algorithm/ # Algorithm Tests
│ └── integration/ # Integration Tests
Design Patterns Used
1. DAO (Data Access Object) Pattern
- Purpose: Separate data access logic from business logic
- Implementation: One DAO class per entity (StudentDAO, CourseDAO, etc.)
- Benefits: Easy to mock for testing, can swap database implementations
2. Strategy Pattern (Optimization Strategies)
- Purpose: Allow different scheduling optimization algorithms to be swapped at runtime
- Implementation:
OptimizationStrategyinterface with concrete implementations - Benefits: Easy to add new strategies without modifying solver code
3. Singleton Pattern (Database Connection)
- Purpose: Ensure only one database connection pool exists
- Implementation:
DatabaseConnection.getInstance() - Benefits: Resource efficiency, consistent connection management
4. Observer Pattern (Progress Tracking)
- Purpose: UI observes long-running algorithm execution
- Implementation:
ProgressTrackerwith listeners, JavaFXTask<T> - Benefits: Responsive UI, can show progress and allow cancellation
5. Factory Pattern (DAO Creation)
- Purpose: Centralize DAO instance creation
- Implementation:
DAOFactoryclass - Benefits: Easier testing, dependency injection
ALGORITHM DESIGN
Backtracking CSP Solver Architecture
Problem Definition (CSP Formulation)
Variables:
- Each course is a variable that needs assignment
- Example:
CourseCode_01,CourseCode_02, ...,CourseCode_20
Domain (Possible Values):
- Each variable can be assigned to a {Classroom, Day, TimeSlot} triple
- Example domain for a course with 35 students:
{(Classroom_01, 1, 1), (Classroom_01, 1, 2), ..., (Classroom_02, 1, 1), (Classroom_02, 1, 2), ..., (Classroom_10, 5, 4)} - Domain is pre-filtered to remove impossible assignments (e.g., classroom too small)
Constraints:
- No consecutive exams for any student (Hard)
- Max 2 exams per student per day (Hard)
- Classroom capacity must not be exceeded (Hard)
- Each course scheduled exactly once (Implicit in CSP formulation)
- No classroom double-booking (Implicit - each {classroom, day, slot} used once)
Backtracking Algorithm Pseudocode
function BACKTRACK-CSP(assignment, csp):
if assignment is complete:
return assignment
var = SELECT-UNASSIGNED-VARIABLE(csp, assignment)
for each value in ORDER-DOMAIN-VALUES(var, assignment, csp):
if value is consistent with assignment (satisfies all constraints):
add {var = value} to assignment
# Constraint propagation (forward checking)
inferences = INFER(csp, var, value)
if inferences ≠ failure:
add inferences to assignment
result = BACKTRACK-CSP(assignment, csp)
if result ≠ failure:
return result
remove {var = value} and inferences from assignment
return failure
Heuristic 1: Variable Ordering (SELECT-UNASSIGNED-VARIABLE)
Strategy: Minimum Remaining Values (MRV)
- Select the course with the fewest valid domain values remaining
- Rationale: Fail fast on difficult assignments, prune search space early
- Tie-breaking: Choose course with most students (harder to place)
public Course selectUnassignedVariable(Assignment assignment) {
Course minCourse = null;
int minDomainSize = Integer.MAX_VALUE;
for (Course course : unassignedCourses) {
int domainSize = calculateValidDomainSize(course, assignment);
if (domainSize < minDomainSize) {
minDomainSize = domainSize;
minCourse = course;
}
}
return minCourse;
}
Heuristic 2: Value Ordering (ORDER-DOMAIN-VALUES)
Strategy: Least Constraining Value
- Select the {classroom, day, slot} that leaves most flexibility for remaining courses
- Rationale: Maximize future options, avoid dead-ends
Optimization Strategy Influence:
- Minimize Days: Prefer earlier days, earlier slots
- Balance Distribution: Prefer days/slots with fewer assignments
- Minimize Classrooms: Prefer already-used classrooms
- Balance Classrooms: Prefer classrooms with fewer assignments
public List<Assignment> orderDomainValues(Course course, OptimizationStrategy strategy) {
List<Assignment> domain = getValidAssignments(course);
// Sort based on optimization strategy
domain.sort((a1, a2) -> strategy.compareAssignments(a1, a2));
return domain;
}
Constraint Checking Functions
1. No Consecutive Exams Constraint
public boolean checkNoConsecutiveExams(Course course, int day, int slot, Assignment assignment) {
Set<Student> enrolledStudents = getEnrolledStudents(course);
for (Student student : enrolledStudents) {
// Check if student has exam in previous slot
if (slot > 1 && hasExamInSlot(student, day, slot - 1, assignment)) {
return false;
}
// Check if student has exam in next slot
if (slot < slotsPerDay && hasExamInSlot(student, day, slot + 1, assignment)) {
return false;
}
// Check boundary with previous day
if (slot == 1 && day > 1 && hasExamInSlot(student, day - 1, slotsPerDay, assignment)) {
return false;
}
// Check boundary with next day
if (slot == slotsPerDay && day < numDays && hasExamInSlot(student, day + 1, 1, assignment)) {
return false;
}
}
return true;
}
2. Max 2 Exams Per Day Constraint
public boolean checkMaxTwoExamsPerDay(Course course, int day, Assignment assignment) {
Set<Student> enrolledStudents = getEnrolledStudents(course);
for (Student student : enrolledStudents) {
int examsOnDay = countExamsForStudentOnDay(student, day, assignment);
if (examsOnDay >= 2) {
return false; // Would cause student to have 3+ exams on this day
}
}
return true;
}
3. Classroom Capacity Constraint
public boolean checkClassroomCapacity(Course course, Classroom classroom) {
int enrolledCount = getEnrolledStudentCount(course);
return enrolledCount <= classroom.getCapacity();
}
Forward Checking (Constraint Propagation)
After assigning a course, reduce domains of unassigned courses:
- Remove {classroom, day, slot} if it's now occupied
- Remove consecutive slots for students in this course
- Remove same-day slots if students already have 2 exams that day
public Map<Course, Set<Assignment>> forwardCheck(Course assigned, Assignment value) {
Map<Course, Set<Assignment>> removedValues = new HashMap<>();
Set<Student> students = getEnrolledStudents(assigned);
for (Course unassigned : unassignedCourses) {
Set<Assignment> toRemove = new HashSet<>();
Set<Student> unassignedStudents = getEnrolledStudents(unassigned);
// If courses share students, check constraints
Set<Student> overlap = intersection(students, unassignedStudents);
if (!overlap.isEmpty()) {
for (Assignment a : getDomain(unassigned)) {
if (violatesConstraintWith(a, value, overlap)) {
toRemove.add(a);
}
}
}
if (!toRemove.isEmpty()) {
removedValues.put(unassigned, toRemove);
getDomain(unassigned).removeAll(toRemove);
}
}
return removedValues;
}
Conflict Detection (When No Solution Exists)
If backtracking exhausts all possibilities without finding a solution:
public ConflictReport analyzeFailure() {
ConflictReport report = new ConflictReport();
// Find students with too many courses for available slots
for (Student student : students) {
int courseCount = getEnrolledCourseCount(student);
int maxPossibleExams = numDays * 2; // Max 2 per day
if (courseCount > maxPossibleExams) {
report.addConflict(student, "Enrolled in " + courseCount +
" courses but only " + maxPossibleExams + " slots available");
}
}
// Find courses with insufficient classroom capacity
for (Course course : courses) {
int enrolledCount = getEnrolledStudentCount(course);
int maxCapacity = getMaxClassroomCapacity();
if (enrolledCount > maxCapacity) {
report.addConflict(course, "Enrolled count " + enrolledCount +
" exceeds max classroom capacity " + maxCapacity);
}
}
// Find groups of students with too many overlapping enrollments
// (complex graph analysis - detect cliques in conflict graph)
return report;
}
Performance Optimizations
-
Pre-compute enrollment mappings:
Map<Course, Set<Student>>- students in each courseMap<Student, Set<Course>>- courses for each student- Avoids repeated database queries during backtracking
-
Domain pre-filtering:
- Eliminate classroom assignments where capacity < enrolled count
- Reduce domain size before backtracking starts
-
Early termination checks:
- If any course has empty domain, fail immediately
- If student has more courses than max possible slots, fail immediately
-
Memoization:
- Cache constraint check results for repeated {student, day, slot} combinations
-
Parallel domain evaluation:
- Use Java streams to evaluate constraint checks in parallel
- Useful for large student sets
Progress Tracking
public class CSPSolver {
private ProgressTracker progressTracker;
private volatile boolean cancelled = false;
public Schedule solve(ScheduleConfiguration config) {
int totalCourses = courses.size();
int assignedCourses = 0;
while (assignedCourses < totalCourses && !cancelled) {
// Backtracking logic
assignedCourses++;
progressTracker.updateProgress(assignedCourses, totalCourses);
}
if (cancelled) {
throw new CancelledException();
}
return buildSchedule(assignment);
}
public void cancel() {
this.cancelled = true;
}
}
CONSTRAINTS & BUSINESS RULES
Hard Constraints (CANNOT be violated)
Constraint 1: No Consecutive Exams for Students
Definition: If a student has an exam in time slot N, they CANNOT have another exam in time slot N+1 (immediately following).
Rationale: Students need break time between exams to rest, review, and travel between exam locations.
Edge Cases:
- Day boundaries: If a student has an exam in the last slot of Day 1, they CAN have an exam in the first slot of Day 2 (not considered consecutive because of overnight break)
- UPDATE: Actually, slots are numbered sequentially across days, so slot 4 of Day 1 and slot 1 of Day 2 ARE consecutive. Need to check this in implementation.
- First/last slots: No previous/next slot to check
Validation Logic:
public boolean validateNoConsecutiveExams(Student student, int day, int slot, Assignment assignment) {
// Calculate absolute slot number (for sequential numbering across days)
int absoluteSlot = (day - 1) * slotsPerDay + slot;
// Check previous slot
if (absoluteSlot > 1) {
int prevDay = (absoluteSlot - 2) / slotsPerDay + 1;
int prevSlot = (absoluteSlot - 2) % slotsPerDay + 1;
if (hasExam(student, prevDay, prevSlot, assignment)) {
return false;
}
}
// Check next slot
int totalSlots = numDays * slotsPerDay;
if (absoluteSlot < totalSlots) {
int nextDay = absoluteSlot / slotsPerDay + 1;
int nextSlot = absoluteSlot % slotsPerDay + 1;
if (hasExam(student, nextDay, nextSlot, assignment)) {
return false;
}
}
return true;
}
Error Message Template: "Cannot assign [Course] to [Day] [Slot]: Student [StudentID] already has an exam in the consecutive slot [Day] [Slot]."
Constraint 2: Maximum 2 Exams Per Student Per Day
Definition: A student cannot have more than 2 exams on any single day.
Rationale: More than 2 exams per day is excessively stressful and reduces exam quality/fairness.
Edge Cases:
- Student enrolled in only 1-2 courses total: Always satisfiable
- Student enrolled in 10+ courses over 5 days: May be impossible to satisfy both this constraint and consecutive constraint
Validation Logic:
public boolean validateMaxTwoExamsPerDay(Student student, int day, Assignment assignment) {
int examsOnDay = 0;
for (int slot = 1; slot <= slotsPerDay; slot++) {
if (hasExam(student, day, slot, assignment)) {
examsOnDay++;
}
}
return examsOnDay < 2; // Currently has 0 or 1, so can add one more
}
Error Message Template: "Cannot assign [Course] to [Day]: Student [StudentID] already has 2 exams on this day."
Constraint 3: Classroom Capacity Must Not Be Exceeded
Definition: The number of students enrolled in a course (who will take the exam) cannot exceed the seating capacity of the assigned classroom.
Rationale: Physical limitation - cannot fit more students than seats available.
Edge Cases:
- Course with 0 students enrolled: Can be assigned to any classroom (but shouldn't appear in schedule at all)
- Multiple classrooms needed: Current design doesn't support splitting one exam across multiple classrooms (would need extension)
Validation Logic:
public boolean validateClassroomCapacity(Course course, Classroom classroom) {
int enrolledCount = getEnrolledStudentCount(course);
return enrolledCount <= classroom.getCapacity();
}
Error Message Template: "Cannot assign [Course] to [Classroom]: Course has [X] students but classroom capacity is only [Y]."
Constraint 4: Each Course Scheduled Exactly Once (Implicit)
Definition: Every course must appear in the schedule exactly one time (one exam per course).
Rationale: Business requirement - each course needs one exam during the exam period.
Implementation:
- CSP formulation ensures this (each course is a variable assigned exactly one value)
- Database uniqueness constraint:
UNIQUE(schedule_id, course_code)
Constraint 5: No Classroom Double-Booking (Implicit)
Definition: A classroom cannot host two exams at the same time (same day + time slot).
Rationale: Physical limitation - one room can only hold one exam at a time.
Implementation:
- CSP domain ensures each {classroom, day, slot} used at most once
- Database uniqueness constraint:
UNIQUE(schedule_id, classroom_id, day, time_slot)
Soft Constraints (Optimization Objectives)
These are preferences, not requirements. They guide the solver's heuristics but can be violated if necessary.
Soft Constraint 1: Minimize Days Used
- Objective: Pack exams into as few days as possible
- Heuristic: Prefer earlier days when ordering domain values
- Use case: Shorter exam period, reduce facility costs
Soft Constraint 2: Balance Distribution Across Days
- Objective: Spread exams evenly across all available days
- Heuristic: Prefer days with fewer assigned exams
- Use case: Reduce student stress, balance proctoring workload
Soft Constraint 3: Minimize Classrooms Used
- Objective: Use as few different classrooms as possible
- Heuristic: Prefer already-assigned classrooms
- Use case: Reduce setup costs, centralize exam locations
Soft Constraint 4: Balance Classrooms Per Day
- Objective: Use similar number of classrooms each day
- Heuristic: Prefer days with fewer classrooms in use
- Use case: Balance proctoring staff assignments
Business Rules
Rule 1: Data Import Validation
- No duplicate student IDs in imported file
- No duplicate course codes in imported file
- No duplicate classroom IDs in imported file
- Enrollment records must reference existing students and courses
- Classroom capacity must be positive integer
- CSV files must have correct format (specific delimiters, expected columns)
Rule 2: Configuration Validation
- Number of days must be positive integer (1-30 reasonable range)
- Number of slots per day must be positive integer (1-6 reasonable range)
- Total available slots (days × slots) must be ≥ number of courses
- At least one classroom must exist
- At least one student must exist
- At least one course must exist
Rule 3: Schedule Generation Preconditions
- All required data imported (students, courses, classrooms, enrollments)
- Configuration set (days, slots, optimization strategy)
- Database connection available
Rule 4: Manual Edit Validation
- Can only edit existing schedules (cannot edit during generation)
- All hard constraints must still be satisfied after edit
- Cannot change student enrollments via manual edit (data integrity)
- Cannot change classroom capacity via manual edit
Rule 5: Export Requirements
- Schedule must be fully generated (all courses assigned)
- User must specify output file path and format (CSV or Excel)
- File path must be writable
USER INTERFACE DESIGN
Main Window Layout
┌────────────────────────────────────────────────────────────────┐
│ Exam Scheduler [_] [□] [X] │
├────────────────────────────────────────────────────────────────┤
│ File Edit View Help │
├────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌────────────────────────────────────┐ │
│ │ │ │ │ │
│ │ NAVIGATION │ │ CONTENT AREA │ │
│ │ PANEL │ │ │ │
│ │ │ │ (Dynamic - changes based on │ │
│ │ • Import Data │ │ selected navigation item) │ │
│ │ • Configure │ │ │ │
│ │ • Generate │ │ │ │
│ │ • View Schedule │ │ │ │
│ │ • Export │ │ │ │
│ │ • History │ │ │ │
│ │ │ │ │ │
│ │ │ │ │ │
│ └─────────────────┘ └────────────────────────────────────┘ │
│ │
├────────────────────────────────────────────────────────────────┤
│ Status: Ready │
└────────────────────────────────────────────────────────────────┘
View 1: Import Data View
Purpose: Import CSV files with validation feedback
Layout:
Import Data
───────────────────────────────────────────────────────
Students File: [/path/to/students.csv ] [Browse...]
Courses File: [/path/to/courses.csv ] [Browse...]
Classrooms File: [/path/to/classrooms.csv ] [Browse...]
Enrollments File: [/path/to/enrollments.csv ] [Browse...]
[Import All] [Clear]
Import Results:
┌─────────────────────────────────────────────────────┐
│ ✓ Students: 250 imported, 0 duplicates rejected │
│ ✓ Courses: 20 imported, 0 duplicates rejected │
│ ✓ Classrooms: 10 imported, 0 duplicates rejected │
│ ✓ Enrollments: 800 imported, 0 errors │
└─────────────────────────────────────────────────────┘
Key Components:
- File path text fields (read-only)
- Browse buttons (open file dialog)
- Import All button (validates and imports all files)
- Results text area (shows success/error messages with line numbers)
View 2: Configuration View
Purpose: Set exam period parameters and optimization strategy
Layout:
Schedule Configuration
───────────────────────────────────────────────────────
Exam Period:
Number of Days: [5 ] days
Time Slots Per Day: [4 ] slots
Total Available Slots: 20 slots
Total Courses: 20 courses
✓ Sufficient slots available
Optimization Strategy:
○ Minimize Days Used
● Balance Distribution Across Days
○ Minimize Classrooms Needed
○ Balance Classrooms Per Day
[Save Configuration]
Key Components:
- Number spinners for days and slots (with validation)
- Calculated field for total slots
- Radio buttons for optimization strategy selection
- Save button (enables Generate view)
View 3: Generate Schedule View
Purpose: Run scheduling algorithm with progress feedback
Layout:
Generate Schedule
───────────────────────────────────────────────────────
Configuration:
Exam Period: 5 days × 4 slots = 20 total slots
Strategy: Balance Distribution Across Days
Courses: 20
Students: 250
[ ]
Generating schedule...
12 / 20 courses assigned (60%)
Estimated time remaining: 8 seconds
[Cancel]
Recent Generations:
┌─────────────────────────────────────────────────────┐
│ 2025-11-26 10:30 - Balance Distribution - Success │
│ 2025-11-26 09:15 - Minimize Days - Success │
└─────────────────────────────────────────────────────┘
Key Components:
- Configuration summary (read-only)
- Progress bar (animated during generation)
- Status text (updates in real-time)
- Cancel button (aborts generation)
- Recent generations list (clickable to load previous schedules)
Success State:
✓ Schedule Generated Successfully!
All 20 courses assigned
All constraints satisfied
Generation time: 3.2 seconds
[View Schedule] [Export]
Failure State:
✗ Schedule Generation Failed
Unable to satisfy all constraints.
Conflicts detected:
• Student Std_ID_042 enrolled in 15 courses (max 10 possible)
• CourseCode_15 has 55 students (max classroom capacity: 40)
Recommendations:
• Extend exam period to 7 days
• Add classroom with capacity ≥55
• Reduce enrollments for affected students
[View Conflicts] [Adjust Configuration]
View 4: Schedule Views (4 Sub-Views)
4A: Classroom View
Purpose: Show which exams are in which classrooms
Layout:
Schedule - Classroom View
───────────────────────────────────────────────────────
Filter: [All Classrooms ▼] Day: [All Days ▼]
┌────────────┬─────┬──────┬────────────┬─────────────┐
│ Classroom │ Day │ Slot │ Course │ Students │
├────────────┼─────┼──────┼────────────┼─────────────┤
│ Room_01 │ 1 │ 1 │ Course_01 │ 40 │
│ Room_01 │ 1 │ 2 │ Course_05 │ 38 │
│ Room_01 │ 2 │ 1 │ Course_12 │ 40 │
│ Room_02 │ 1 │ 1 │ Course_02 │ 35 │
│ ... │ ... │ ... │ ... │ ... │
└────────────┴─────┴──────┴────────────┴─────────────┘
[Export View] [Edit]
4B: Student View
Purpose: Show personal exam schedule for each student
Layout:
Schedule - Student View
───────────────────────────────────────────────────────
Search Student: [Std_ID_042 ] [Search]
┌─────────────┬────────────┬─────┬──────┬────────────┐
│ Student ID │ Course │ Day │ Slot │ Classroom │
├─────────────┼────────────┼─────┼──────┼────────────┤
│ Std_ID_042 │ Course_01 │ 1 │ 1 │ Room_01 │
│ Std_ID_042 │ Course_07 │ 1 │ 3 │ Room_03 │
│ Std_ID_042 │ Course_12 │ 2 │ 1 │ Room_01 │
│ Std_ID_042 │ Course_18 │ 3 │ 2 │ Room_05 │
└─────────────┴────────────┴─────┴──────┴────────────┘
[Export Student Schedule]
4C: Course View
Purpose: Show exam details for each course
Layout:
Schedule - Course View
───────────────────────────────────────────────────────
Sort by: [Course Code ▼]
┌────────────┬─────┬──────┬────────────┬─────────────┐
│ Course │ Day │ Slot │ Classroom │ Enrolled │
├────────────┼─────┼──────┼────────────┼─────────────┤
│ Course_01 │ 1 │ 1 │ Room_01 │ 40 │
│ Course_02 │ 1 │ 1 │ Room_02 │ 35 │
│ Course_03 │ 1 │ 2 │ Room_04 │ 38 │
│ Course_04 │ 1 │ 3 │ Room_02 │ 42 │
│ ... │ ... │ ... │ ... │ ... │
└────────────┴─────┴──────┴────────────┴─────────────┘
[Export View]
4D: Day View (Grid Layout)
Purpose: Visual grid showing all exams by day and time slot
Layout:
Schedule - Day View
───────────────────────────────────────────────────────
┌──────┬──────────────┬──────────────┬──────────────┬──────────────┐
│ │ Slot 1 │ Slot 2 │ Slot 3 │ Slot 4 │
├──────┼──────────────┼──────────────┼──────────────┼──────────────┤
│ Day 1│ Course_01 │ Course_05 │ Course_07 │ Course_11 │
│ │ (Room_01) │ (Room_01) │ (Room_03) │ (Room_02) │
│ │ 40 students │ 38 students │ 35 students │ 40 students │
│ │ │ │ │ │
│ │ Course_02 │ Course_06 │ Course_08 │ Course_12 │
│ │ (Room_02) │ (Room_04) │ (Room_05) │ (Room_06) │
│ │ 35 students │ 40 students │ 38 students │ 42 students │
├──────┼──────────────┼──────────────┼──────────────┼──────────────┤
│ Day 2│ ... │ ... │ ... │ ... │
└──────┴──────────────┴──────────────┴──────────────┴──────────────┘
[Export View]
View 5: Export View
Purpose: Export schedule to CSV or Excel
Layout:
Export Schedule
───────────────────────────────────────────────────────
Export Format:
○ CSV (Comma-Separated Values)
● Excel (.xlsx)
Views to Export:
☑ Classroom View
☑ Student View
☑ Course View
☑ Day View
(Excel will create separate sheet for each view)
Output Location:
[C:\Users\Student\Documents\exam_schedule.xlsx] [Browse...]
[Export] [Cancel]
Export Status:
┌─────────────────────────────────────────────────────┐
│ ✓ Export completed successfully! │
│ File saved to: C:\Users\Student\Documents\... │
│ File size: 24 KB │
└─────────────────────────────────────────────────────┘
View 6: History View
Purpose: View and load previously generated schedules
Layout:
Schedule History
───────────────────────────────────────────────────────
┌─────────────┬──────────────────┬─────────┬──────────┬────────┐
│ Date/Time │ Strategy │ Days │ Courses │ Status │
├─────────────┼──────────────────┼─────────┼──────────┼────────┤
│ 11/26 10:30 │ Balance Distrib. │ 5×4=20 │ 20 │ Saved │
│ 11/26 09:15 │ Minimize Days │ 5×4=20 │ 20 │ Saved │
│ 11/25 14:22 │ Minimize Rooms │ 6×3=18 │ 18 │ Saved │
│ ... │ ... │ ... │ ... │ ... │
└─────────────┴──────────────────┴─────────┴──────────┴────────┘
[Load Selected] [Delete] [Export]
UI/UX Guidelines
Color Scheme
- Primary: Blue (#2196F3) for action buttons, links
- Success: Green (#4CAF50) for success messages, checkmarks
- Error: Red (#F44336) for error messages, warnings
- Neutral: Gray (#9E9E9E) for disabled elements, borders
- Background: Light gray (#FAFAFA) for content areas
Typography
- Font: System default (Segoe UI on Windows)
- Headers: 18pt bold
- Body text: 12pt regular
- Labels: 11pt regular
Interaction Patterns
- Buttons: Hover state (darker shade), click state (pressed effect)
- Tables: Row hover highlight, sortable columns (click header)
- Forms: Validation on blur (lose focus), red border for invalid fields
- Progress: Animated progress bar, percentage text, time remaining estimate
Accessibility
- Keyboard navigation: Tab order follows logical flow, Enter activates buttons
- Tooltips: Hover over fields shows help text
- Error messages: Red border + icon + text description
- Focus indicators: Visible blue outline on focused elements
API CONTRACTS BETWEEN LAYERS
Controller → Service Layer Contracts
ImportService Interface
public interface ImportService {
/**
* Import students from CSV file
* @param filePath Absolute path to CSV file
* @return ImportResult with success/failure counts and error messages
* @throws FileNotFoundException if file doesn't exist
* @throws InvalidFormatException if CSV format is incorrect
*/
ImportResult importStudents(String filePath)
throws FileNotFoundException, InvalidFormatException;
/**
* Import courses from CSV file
*/
ImportResult importCourses(String filePath)
throws FileNotFoundException, InvalidFormatException;
/**
* Import classrooms from CSV file
* Format: ClassroomID;Capacity
*/
ImportResult importClassrooms(String filePath)
throws FileNotFoundException, InvalidFormatException;
/**
* Import enrollments (student-course mappings) from CSV file
*/
ImportResult importEnrollments(String filePath)
throws FileNotFoundException, InvalidFormatException;
/**
* Validate all imported data for consistency
* @return ValidationResult with list of issues found
*/
ValidationResult validateImportedData();
}
public class ImportResult {
private int successCount;
private int errorCount;
private List<ImportError> errors;
private boolean success;
public static class ImportError {
private int lineNumber;
private String message;
private String rawLine;
}
}
ScheduleService Interface
public interface ScheduleService {
/**
* Generate schedule using CSP solver
* @param config Schedule configuration (days, slots, strategy)
* @param progressTracker Callback for progress updates
* @return Generated Schedule object
* @throws NoSolutionException if constraints cannot be satisfied
* @throws CancelledException if user cancels during generation
*/
Schedule generateSchedule(ScheduleConfiguration config, ProgressTracker progressTracker)
throws NoSolutionException, CancelledException;
/**
* Validate manual edit against constraints
* @param scheduleId ID of schedule to modify
* @param courseCode Course to move
* @param newDay New day assignment
* @param newSlot New time slot assignment
* @param newClassroom New classroom assignment
* @return ValidationResult indicating if change is valid
*/
ValidationResult validateEdit(
int scheduleId,
String courseCode,
int newDay,
int newSlot,
String newClassroom
);
/**
* Apply manual edit to schedule
* @throws ConstraintViolationException if edit violates constraints
*/
void applyEdit(int scheduleId, ExamAssignment newAssignment)
throws ConstraintViolationException;
/**
* Save current schedule to database
* @return Saved schedule ID
*/
int saveSchedule(Schedule schedule);
/**
* Load schedule from database
*/
Schedule loadSchedule(int scheduleId)
throws ScheduleNotFoundException;
/**
* Get all saved schedules (metadata only)
*/
List<ScheduleMetadata> getScheduleHistory();
/**
* Delete schedule from database
*/
void deleteSchedule(int scheduleId);
}
public class ScheduleConfiguration {
private int numDays;
private int slotsPerDay;
private OptimizationStrategy strategy;
}
public enum OptimizationStrategy {
MINIMIZE_DAYS,
BALANCE_DISTRIBUTION,
MINIMIZE_CLASSROOMS,
BALANCE_CLASSROOMS
}
ExportService Interface
public interface ExportService {
/**
* Export schedule to CSV files (one file per view)
* @param schedule Schedule to export
* @param outputDirectory Directory to save CSV files
* @param views Which views to export (CLASSROOM, STUDENT, COURSE, DAY)
* @return ExportResult with file paths and success status
*/
ExportResult exportToCSV(
Schedule schedule,
String outputDirectory,
Set<ViewType> views
) throws IOException;
/**
* Export schedule to Excel workbook (one sheet per view)
* @param schedule Schedule to export
* @param outputFilePath Path to save .xlsx file
* @param views Which views to export
* @return ExportResult with file path and success status
*/
ExportResult exportToExcel(
Schedule schedule,
String outputFilePath,
Set<ViewType> views
) throws IOException;
}
public enum ViewType {
CLASSROOM,
STUDENT,
COURSE,
DAY
}
public class ExportResult {
private boolean success;
private List<String> filePaths;
private String message;
private long fileSizeBytes;
}
Service → DAO Layer Contracts
StudentDAO Interface
public interface StudentDAO {
/**
* Insert single student
*/
void insert(Student student) throws SQLException;
/**
* Batch insert multiple students (more efficient)
*/
void insertBatch(List<Student> students) throws SQLException;
/**
* Get student by ID
*/
Optional<Student> findById(String studentId);
/**
* Get all students
*/
List<Student> findAll();
/**
* Check if student exists
*/
boolean exists(String studentId);
/**
* Delete all students (for re-import)
*/
void deleteAll() throws SQLException;
/**
* Get students enrolled in specific course
*/
List<Student> findByCourse(String courseCode);
}
CourseDAO Interface
public interface CourseDAO {
void insert(Course course) throws SQLException;
void insertBatch(List<Course> courses) throws SQLException;
Optional<Course> findById(String courseCode);
List<Course> findAll();
boolean exists(String courseCode);
void deleteAll() throws SQLException;
/**
* Get enrollment count for course
*/
int getEnrollmentCount(String courseCode);
}
EnrollmentDAO Interface
public interface EnrollmentDAO {
void insert(Enrollment enrollment) throws SQLException;
void insertBatch(List<Enrollment> enrollments) throws SQLException;
/**
* Get all courses for a student
*/
List<Course> getCoursesForStudent(String studentId);
/**
* Get all students for a course
*/
List<Student> getStudentsForCourse(String courseCode);
/**
* Check if enrollment exists
*/
boolean exists(String studentId, String courseCode);
/**
* Get total enrollment count
*/
int getTotalEnrollmentCount();
void deleteAll() throws SQLException;
}
ScheduleDAO Interface
public interface ScheduleDAO {
/**
* Insert new schedule (returns generated ID)
*/
int insert(Schedule schedule) throws SQLException;
/**
* Update existing schedule
*/
void update(Schedule schedule) throws SQLException;
/**
* Get schedule by ID (includes all exam assignments)
*/
Optional<Schedule> findById(int scheduleId);
/**
* Get all schedules (metadata only, no assignments)
*/
List<ScheduleMetadata> findAllMetadata();
/**
* Delete schedule and all associated assignments (cascade)
*/
void delete(int scheduleId) throws SQLException;
}
ExamAssignmentDAO Interface
public interface ExamAssignmentDAO {
/**
* Insert single assignment
*/
void insert(ExamAssignment assignment) throws SQLException;
/**
* Batch insert all assignments for a schedule
*/
void insertBatch(List<ExamAssignment> assignments) throws SQLException;
/**
* Get all assignments for a schedule
*/
List<ExamAssignment> findBySchedule(int scheduleId);
/**
* Get assignment for specific course in a schedule
*/
Optional<ExamAssignment> findByCourse(int scheduleId, String courseCode);
/**
* Update single assignment (for manual edits)
*/
void update(ExamAssignment assignment) throws SQLException;
/**
* Delete all assignments for a schedule
*/
void deleteBySchedule(int scheduleId) throws SQLException;
/**
* Check if classroom-day-slot is occupied in schedule
*/
boolean isSlotOccupied(int scheduleId, String classroomId, int day, int slot);
}
Service → Algorithm Layer Contracts
CSPSolver Interface
public interface CSPSolver {
/**
* Solve CSP to generate schedule
* @param courses List of courses to schedule
* @param classrooms Available classrooms
* @param enrollments Student-course enrollment data
* @param config Exam period configuration
* @param strategy Optimization strategy to use
* @param progressTracker Progress callback
* @return Map of course → {classroom, day, slot} assignments
* @throws NoSolutionException if no valid schedule exists
* @throws CancelledException if solve() is cancelled
*/
Map<Course, ExamAssignment> solve(
List<Course> courses,
List<Classroom> classrooms,
List<Enrollment> enrollments,
ScheduleConfiguration config,
OptimizationStrategy strategy,
ProgressTracker progressTracker
) throws NoSolutionException, CancelledException;
/**
* Cancel ongoing solve operation
*/
void cancel();
}
ConstraintValidator Interface
public interface ConstraintValidator {
/**
* Check if assignment satisfies all constraints
* @param course Course being assigned
* @param classroom Classroom to assign to
* @param day Day to assign to
* @param slot Time slot to assign to
* @param currentAssignment Partial assignment so far
* @param enrollments Enrollment data
* @return true if assignment is valid
*/
boolean isValid(
Course course,
Classroom classroom,
int day,
int slot,
Map<Course, ExamAssignment> currentAssignment,
List<Enrollment> enrollments
);
/**
* Get detailed constraint violations for an assignment
* @return List of violated constraints with explanations
*/
List<ConstraintViolation> getViolations(
Course course,
Classroom classroom,
int day,
int slot,
Map<Course, ExamAssignment> currentAssignment,
List<Enrollment> enrollments
);
}
public class ConstraintViolation {
private ConstraintType type;
private String message;
private List<String> affectedStudents; // For student-related violations
}
public enum ConstraintType {
CONSECUTIVE_EXAMS,
MAX_TWO_PER_DAY,
CLASSROOM_CAPACITY,
CLASSROOM_DOUBLE_BOOKING
}
ConflictDetector Interface
public interface ConflictDetector {
/**
* Analyze why no solution exists
* @return Report detailing conflicts and recommendations
*/
ConflictReport analyzeFailure(
List<Course> courses,
List<Classroom> classrooms,
List<Enrollment> enrollments,
ScheduleConfiguration config
);
}
public class ConflictReport {
private List<StudentConflict> studentConflicts;
private List<CourseConflict> courseConflicts;
private List<String> recommendations;
}
public class StudentConflict {
private Student student;
private String description; // "Enrolled in 15 courses, max 10 possible with constraints"
private int courseCount;
private int maxPossible;
}
public class CourseConflict {
private Course course;
private String description; // "55 students enrolled, max classroom capacity 40"
private int enrolledCount;
private int maxCapacity;
}
TESTING STRATEGY
Unit Testing
DAO Layer Tests
Framework: JUnit 5
Database: In-memory SQLite (:memory:)
Coverage targets: >90%
Test categories:
- CRUD operations: Insert, update, delete, select
- Batch operations: Batch insert performance and correctness
- Transactions: Rollback on error, commit on success
- Uniqueness constraints: Duplicate prevention
- Foreign key constraints: Referential integrity
- Index usage: Query performance
Example test:
@Test
public void testBatchInsertStudents_ShouldInsertAllStudents() {
// Arrange
List<Student> students = createTestStudents(100);
StudentDAO dao = new StudentDAOImpl(testConnection);
// Act
dao.insertBatch(students);
// Assert
assertEquals(100, dao.findAll().size());
assertTrue(dao.exists("Std_ID_001"));
}
@Test
public void testInsertDuplicateStudent_ShouldThrowException() {
// Arrange
StudentDAO dao = new StudentDAOImpl(testConnection);
Student student = new Student("Std_ID_001");
dao.insert(student);
// Act & Assert
assertThrows(SQLException.class, () -> dao.insert(student));
}
Algorithm Layer Tests
Framework: JUnit 5 Test data: Small synthetic datasets with known solutions
Test categories:
- Constraint validation: Each constraint checked individually
- Simple solvable cases: 3-5 courses with obvious solution
- Unsolvable cases: Known conflicts (student with 15 courses, etc.)
- Edge cases:
- Single course
- All students in one course
- Minimum/maximum capacity classrooms
- Consecutive slots at day boundaries
- Optimization strategies: Verify strategy affects solution
- Performance: Small dataset (<10 courses) solves in <1 second
Example tests:
@Test
public void testNoConsecutiveExams_StudentWithTwoCourses_ShouldNotBeInConsecutiveSlots() {
// Arrange
CSPSolver solver = new BacktrackingSolver();
Student student = new Student("S1");
Course course1 = new Course("C1");
Course course2 = new Course("C2");
Enrollment e1 = new Enrollment(student, course1);
Enrollment e2 = new Enrollment(student, course2);
Classroom classroom = new Classroom("R1", 50);
ScheduleConfiguration config = new ScheduleConfiguration(2, 2); // 2 days, 2 slots
// Act
Map<Course, ExamAssignment> solution = solver.solve(
Arrays.asList(course1, course2),
Arrays.asList(classroom),
Arrays.asList(e1, e2),
config,
OptimizationStrategy.MINIMIZE_DAYS,
null
);
// Assert
assertNotNull(solution);
ExamAssignment a1 = solution.get(course1);
ExamAssignment a2 = solution.get(course2);
assertFalse(areConsecutive(a1, a2), "Courses should not be in consecutive slots");
}
@Test
public void testUnsolvableCase_StudentWith15Courses_ShouldThrowNoSolutionException() {
// Arrange: Student enrolled in 15 courses, only 5 days × 2 slots = 10 possible
CSPSolver solver = new BacktrackingSolver();
Student student = createStudentWithNCourses(15);
ScheduleConfiguration config = new ScheduleConfiguration(5, 2); // Only 10 slots
// Act & Assert
assertThrows(NoSolutionException.class, () ->
solver.solve(courses, classrooms, enrollments, config, strategy, null)
);
}
Service Layer Tests
Framework: JUnit 5 + Mockito Mocking: Mock DAO and Algorithm layers
Test categories:
- Business logic validation: Configuration validation, data consistency checks
- Transaction handling: Rollback on failure, commit on success
- Error propagation: Service catches and wraps DAO/algorithm exceptions appropriately
- Null handling: Graceful handling of null inputs
Example test:
@Test
public void testGenerateSchedule_WithValidConfig_ShouldReturnSchedule() {
// Arrange
ScheduleService service = new ScheduleServiceImpl(mockDAO, mockSolver);
ScheduleConfiguration config = new ScheduleConfiguration(5, 4, OptimizationStrategy.BALANCE_DISTRIBUTION);
when(mockDAO.findAllCourses()).thenReturn(createTestCourses(20));
when(mockDAO.findAllClassrooms()).thenReturn(createTestClassrooms(10));
when(mockDAO.findAllEnrollments()).thenReturn(createTestEnrollments());
when(mockSolver.solve(any(), any(), any(), any(), any(), any())).thenReturn(createValidSolution());
// Act
Schedule schedule = service.generateSchedule(config, null);
// Assert
assertNotNull(schedule);
assertEquals(20, schedule.getAssignments().size());
verify(mockDAO, times(1)).saveSchedule(any());
}
Integration Testing
Database Integration Tests
Setup: Real SQLite file (not in-memory) Cleanup: Delete database file after each test class
Test categories:
- End-to-end import: CSV → Database → Verify
- Schedule generation → save → load: Full round-trip
- Manual edit → validation → save: Edit workflow
- Concurrent access: Multiple connections (if applicable)
Example test:
@Test
public void testFullImportWorkflow_ShouldPersistAllData() {
// Arrange
ImportService importService = new ImportServiceImpl(realDAO);
String studentsFile = "src/test/resources/test_students.csv";
String coursesFile = "src/test/resources/test_courses.csv";
String classroomsFile = "src/test/resources/test_classrooms.csv";
String enrollmentsFile = "src/test/resources/test_enrollments.csv";
// Act
ImportResult r1 = importService.importStudents(studentsFile);
ImportResult r2 = importService.importCourses(coursesFile);
ImportResult r3 = importService.importClassrooms(classroomsFile);
ImportResult r4 = importService.importEnrollments(enrollmentsFile);
// Assert
assertTrue(r1.isSuccess());
assertTrue(r2.isSuccess());
assertTrue(r3.isSuccess());
assertTrue(r4.isSuccess());
// Verify data persisted
assertEquals(250, realDAO.findAllStudents().size());
assertEquals(20, realDAO.findAllCourses().size());
assertEquals(10, realDAO.findAllClassrooms().size());
assertEquals(800, realDAO.getTotalEnrollmentCount());
}
UI Integration Tests
Framework: TestFX (JavaFX testing framework) Approach: Simulate user interactions
Test categories:
- Navigation: Click navigation items, verify view changes
- Import workflow: Select files, click import, verify results
- Generation workflow: Configure, generate, view schedule
- Export workflow: Select format, export, verify file created
Example test:
@Test
public void testImportWorkflow_UserSelectsFilesAndImports_ShouldShowSuccessMessage(FxRobot robot) {
// Arrange: Start application
// Act
robot.clickOn("#importNavButton");
robot.clickOn("#browseStudentsButton");
// (File dialog interaction - may need mocking)
robot.clickOn("#importAllButton");
// Assert
verifyThat("#importResultsText", hasText(containsString("250 imported")));
}
Performance Testing
Benchmark Tests
Framework: JMH (Java Microbenchmark Harness) or simple timing
Test categories:
- Small dataset: 50 courses, 500 students (target: <10 seconds)
- Medium dataset: 100 courses, 1000 students (target: <2 minutes)
- Large dataset: 200 courses, 2000 students (acceptance: <10 minutes)
- Database queries: All common queries <100ms
Example test:
@Test
public void testSmallDatasetPerformance_ShouldCompleteUnder10Seconds() {
// Arrange
CSPSolver solver = new BacktrackingSolver();
List<Course> courses = createTestCourses(50);
List<Student> students = createTestStudents(500);
List<Enrollment> enrollments = createRandomEnrollments(students, courses, 10); // 10 courses per student avg
List<Classroom> classrooms = createTestClassrooms(15);
ScheduleConfiguration config = new ScheduleConfiguration(10, 4); // 40 slots
// Act
long startTime = System.currentTimeMillis();
Map<Course, ExamAssignment> solution = solver.solve(courses, classrooms, enrollments, config, OptimizationStrategy.BALANCE_DISTRIBUTION, null);
long endTime = System.currentTimeMillis();
// Assert
assertNotNull(solution);
long duration = endTime - startTime;
assertTrue(duration < 10000, "Solving took " + duration + "ms, expected <10000ms");
}
Test Data Management
Test Fixtures
Location: src/test/resources/
Files:
test_students_10.csv- 10 studentstest_students_100.csv- 100 studentstest_students_250.csv- 250 students (matches sample data)test_courses_5.csv- 5 coursestest_courses_20.csv- 20 courses (matches sample data)test_classrooms_small.csv- 3 classrooms, capacity 20test_classrooms_medium.csv- 10 classrooms, capacity 40 (matches sample data)test_enrollments_simple.csv- Simple enrollment pattern for easy testingtest_enrollments_complex.csv- Complex pattern to stress-test solver
Test Data Builders
Use builder pattern for creating test objects:
public class TestDataBuilder {
public static List<Student> createStudents(int count) {
List<Student> students = new ArrayList<>();
for (int i = 1; i <= count; i++) {
students.add(new Student(String.format("Std_ID_%03d", i)));
}
return students;
}
public static List<Course> createCourses(int count) {
List<Course> courses = new ArrayList<>();
for (int i = 1; i <= count; i++) {
courses.add(new Course(String.format("Course_%02d", i)));
}
return courses;
}
// ... similar methods for classrooms, enrollments
}
Continuous Integration Testing
Platform: GitHub Actions
Workflow:
- On every push to feature branch: Run unit tests
- On PR to
develop: Run unit + integration tests - On merge to
develop: Run full test suite + performance tests - On merge to
main: Run all tests + generate coverage report
Coverage Requirements:
- Overall: >70% code coverage
- Critical paths (algorithm, constraints): >90% coverage
- DAO layer: >85% coverage
Example GitHub Actions workflow:
name: Java CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
- name: Build with Maven
run: mvn clean compile
- name: Run tests
run: mvn test
- name: Generate coverage report
run: mvn jacoco:report
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
DEVELOPMENT WORKFLOW
Git Branching Strategy
Branch structure:
main
└── develop
├── feature/database-schema
├── feature/csv-import
├── feature/csp-solver
├── feature/ui-main-window
├── feature/classroom-view
└── bugfix/constraint-validation-issue
Branch naming conventions:
feature/short-description- New featuresbugfix/issue-description- Bug fixeshotfix/critical-issue- Urgent production fixes (from main)refactor/component-name- Code refactoringtest/component-name- Test additions
Workflow:
-
Create feature branch from
develop:git checkout develop git pull origin develop git checkout -b feature/csv-import -
Work on feature with regular commits:
git add . git commit -m "Add CSV parser for student data" git push origin feature/csv-import -
Create Pull Request to
develop:- Title: Brief description (e.g., "Add CSV import functionality")
- Description: Detailed changes, testing done, screenshots (for UI)
- Assign reviewer (at least one other team member)
- Link to any related issues/tasks
-
Code Review:
- Reviewer checks code quality, test coverage, documentation
- Leaves comments for improvements
- Approves when satisfied
-
Merge to develop:
- Use "Squash and Merge" for clean history
- Delete feature branch after merge
-
Release to main:
- When develop is stable and ready for release
- Create PR from
developtomain - Requires approval from Documentation & Integration Lead
- Tag release with version number (e.g.,
v1.0.0)
Commit Message Guidelines
Format:
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat: New featurefix: Bug fixrefactor: Code refactoring (no functional change)test: Adding or updating testsdocs: Documentation changesstyle: Code style changes (formatting, no logic change)chore: Build process, dependency updates
Examples:
feat(import): Add CSV import for student data
Implemented CSVParser utility class to read student IDs from CSV file.
Includes validation for duplicates and empty lines.
Closes #15
fix(csp-solver): Correct consecutive exam constraint checking
Previous implementation didn't handle day boundaries correctly.
Now checks if last slot of day N and first slot of day N+1 are consecutive.
Fixes #42
Pull Request Template
Create .github/PULL_REQUEST_TEMPLATE.md:
## Description
<!-- Brief description of changes -->
## Type of Change
- [ ] New feature
- [ ] Bug fix
- [ ] Refactoring
- [ ] Documentation
- [ ] Testing
## Changes Made
<!-- List of specific changes -->
-
-
-
## Testing Done
<!-- How did you test these changes? -->
-
-
## Screenshots (if applicable)
<!-- For UI changes -->
## Checklist
- [ ] Code follows Java naming conventions
- [ ] Added JavaDoc for public methods
- [ ] Added unit tests (or not applicable)
- [ ] All tests pass locally
- [ ] No new compiler warnings
- [ ] Updated documentation (if needed)
## Related Issues
<!-- Link to issues: Closes #123, Fixes #456 -->
Code Review Checklist
For reviewers:
Code Quality
- Follows Java naming conventions (camelCase for variables, PascalCase for classes)
- No magic numbers (use named constants)
- Meaningful variable/method names
- Appropriate use of access modifiers (private, public, protected)
- No code duplication
Functionality
- Code does what PR description says
- Edge cases handled
- Error handling appropriate (try-catch where needed)
- No obvious bugs
Architecture
- Follows MVC pattern (code in correct layer)
- No tight coupling (DAO doesn't call UI, etc.)
- Uses appropriate design patterns
Testing
- Unit tests added for new methods
- Tests cover edge cases
- All existing tests still pass
Documentation
- JavaDoc added for public methods
- Complex algorithms have explanatory comments
- README updated if needed
Performance
- No obvious performance issues (e.g., nested loops with O(n²) that could be O(n))
- Database queries are efficient (use indexes)
Weekly Development Cycle
Monday:
- Team standup (15 min): What did you do last week? What will you do this week? Any blockers?
- Integration review: Discuss PRs that need merging, resolve conflicts
Wednesday:
- Mid-week check-in (30 min): Progress update, pair programming sessions scheduled
Friday:
- End-of-week review (30 min): Demo completed features, retrospective (what went well, what to improve)
- Planning for next week: Assign new tasks based on roadmap
Development Environment Setup
Required tools:
- Java JDK 17+ (download from Oracle or adopt OpenJDK)
- Maven or Gradle (build tool)
- IDE: IntelliJ IDEA (recommended) or Eclipse
- Git (version control)
- Scene Builder (for FXML visual editing)
- SQLite Browser (for database inspection)
Setup steps:
# Clone repository
git clone https://github.com/your-team/exam-scheduler.git
cd exam-scheduler
# Checkout develop branch
git checkout develop
# Build project
mvn clean install
# Run tests
mvn test
# Run application
mvn javafx:run
IDE configuration:
- Install Checkstyle plugin (for code style enforcement)
- Configure Java 17 as project SDK
- Enable "Optimize imports on the fly"
- Set code formatter to Java standard style
KEY TECHNICAL DECISIONS
Decision Log
Decision 1: Why Backtracking CSP Solver?
Context: Need to choose scheduling algorithm approach.
Options considered:
- Greedy heuristic (fast but may not find solution)
- Genetic algorithm (good for optimization but probabilistic)
- Integer Linear Programming (optimal but complex to implement)
- Backtracking CSP solver (systematic, guaranteed to find solution if one exists)
Decision: Backtracking CSP solver with constraint propagation
Rationale:
- Correctness: Guarantees finding solution or proving none exists
- Constraint handling: Natural fit for hard constraints
- Extensibility: Easy to add new constraints or optimization strategies
- Performance: With good heuristics (MRV, least constraining value), performs well on small-medium datasets
- Understandable: Algorithm is well-documented and teachable
Trade-offs:
- May be slower than greedy for very large datasets (acceptable given requirements)
- Not guaranteed to find optimal solution (finds valid solution, optimizes via heuristics)
Decision 2: Why SQLite?
Context: Need to choose database for local persistence.
Options considered:
- Flat files (CSV/JSON)
- Embedded H2 database
- SQLite
- MySQL/PostgreSQL (external server)
Decision: SQLite
Rationale:
- Zero configuration: No server setup, no connection strings, just a file
- Cross-platform: Works on Windows, Mac, Linux
- Lightweight: Small footprint, fast for small-medium datasets
- ACID transactions: Full database features (transactions, foreign keys, indexes)
- No dependencies: No external process needed
- Easy backup: Just copy the .db file
Trade-offs:
- Not suitable for concurrent multi-user access (but this is single-user desktop app)
- Limited scalability compared to server databases (but dataset sizes are small)
Decision 3: Why JavaFX with FXML + MVC?
Context: Need to choose UI framework and architecture.
Options considered:
- Swing (older Java UI framework)
- JavaFX with pure Java code
- JavaFX with FXML + MVC
- JavaFX with FXML + MVVM
Decision: JavaFX with FXML + MVC
Rationale:
- Modern: JavaFX is the modern Java UI framework (Swing is legacy)
- Separation of concerns: FXML separates UI layout from logic
- Visual design: Scene Builder provides WYSIWYG editor for FXML
- MVC familiarity: Team likely familiar with MVC pattern from coursework
- Testability: Can test controllers independently of views
Trade-offs:
- MVVM might be more testable, but MVC is simpler for team to learn
- Pure Java code (no FXML) might be more flexible, but FXML provides better separation
Decision 4: Why Maven (or Gradle)?
Context: Need to choose build tool.
Options considered:
- Manual compilation (javac)
- Ant
- Maven
- Gradle
Decision: Maven (or Gradle, team can choose)
Rationale:
- Dependency management: Automatically downloads libraries (SQLite JDBC, JUnit, etc.)
- Standardized structure: Convention over configuration
- Build lifecycle: Compile, test, package (JAR), run all automated
- CI/CD integration: Easy to integrate with GitHub Actions
- Plugin ecosystem: JavaFX plugin, testing plugins, coverage plugins
Trade-offs:
- Adds complexity compared to manual compilation
- Gradle is more flexible but has steeper learning curve
Decision 5: Why Feature Branching (Not Trunk-Based Development)?
Context: Need to choose Git workflow for team of 6.
Options considered:
- Everyone commits to main (chaos)
- Trunk-based development (frequent merges to main)
- Git Flow (complex with release branches)
- Feature branching with develop branch
Decision: Feature branching with main and develop branches
Rationale:
- Isolation: Each feature developed independently without breaking others
- Code review: PRs enable peer review before merging
- Stable main: Main branch always has working code
- Learning: Teaches industry-standard Git workflow
- Flexibility: Can work on multiple features in parallel
Trade-offs:
- More complex than trunk-based development
- Risk of long-lived branches and merge conflicts (mitigated by frequent integration)
Decision 6: Test Coverage Target: 70%
Context: Need to set realistic test coverage goal.
Options considered:
- No specific target (risky)
- 50% coverage (too low for quality)
- 70% coverage (balanced)
- 90%+ coverage (too time-consuming)
Decision: 70% overall coverage, 90% for critical paths (algorithm, constraints)
Rationale:
- Balanced: Provides confidence without excessive test maintenance
- Focus on critical: Algorithm correctness is most important
- Achievable: Team of 6 can reach this in 10-week timeline
- Industry standard: 70% is common target for projects
Trade-offs:
- Not 100% coverage (but diminishing returns after 70%)
- Some UI code may be hard to test (acceptable)
Decision 7: Progress Tracking via JavaFX Task
Context: Need to show progress during long-running schedule generation.
Options considered:
- No progress indication (bad UX)
- Custom threading with callbacks
- JavaFX Task with progress updates
- Background service with polling
Decision: JavaFX Task with ProgressTracker callback
Rationale:
- Built-in: JavaFX Task provides progress, cancellation, error handling
- Thread-safe: Updates UI from background thread safely
- Cancellable: User can cancel long-running operations
- Standard pattern: Well-documented JavaFX approach
Implementation:
public class ScheduleGenerationTask extends Task<Schedule> {
@Override
protected Schedule call() throws Exception {
updateMessage("Initializing solver...");
updateProgress(0, 100);
// Solver updates progress via callback
Schedule schedule = solver.solve(..., (current, total) -> {
updateProgress(current, total);
updateMessage("Assigned " + current + " / " + total + " courses");
});
return schedule;
}
}
Decision 8: CSV Format for Import (Not JSON/XML)
Context: Sample data provided in CSV format.
Options considered:
- CSV (simple text format)
- JSON (structured data)
- XML (verbose but structured)
- Excel (.xlsx) directly
Decision: CSV for import, both CSV and Excel for export
Rationale:
- Simplicity: CSV is easiest to create/edit for users (Excel, Google Sheets, text editor)
- Sample data: Already provided in CSV format
- Lightweight: No XML/JSON parsing libraries needed
- Universal: All spreadsheet programs support CSV
Trade-offs:
- Less structured than JSON/XML (but data is simple enough)
- Encoding issues possible (mitigated by using UTF-8)
GLOSSARY
Terms used throughout project:
- CSP (Constraint Satisfaction Problem): A problem where variables must be assigned values subject to constraints
- Backtracking: Algorithm that tries assignments and "backs up" when constraints are violated
- Domain: Set of possible values a variable can take
- Hard Constraint: Constraint that CANNOT be violated (vs soft constraint = preference)
- Forward Checking: Constraint propagation technique that reduces domains after each assignment
- Heuristic: Rule of thumb to guide search (e.g., MRV, least constraining value)
- MRV (Minimum Remaining Values): Choose variable with fewest valid domain values
- DAO (Data Access Object): Design pattern separating data access from business logic
- POJO (Plain Old Java Object): Simple Java class with no special requirements
- FXML: JavaFX XML-based language for describing UI layouts
- MVC (Model-View-Controller): Architecture pattern separating data, UI, and logic
- JDBC (Java Database Connectivity): Java API for database operations
- ORM (Object-Relational Mapping): Mapping between objects and database tables
- ACID (Atomicity, Consistency, Isolation, Durability): Database transaction properties
- PR (Pull Request): Request to merge code changes into a branch
- CI/CD (Continuous Integration/Continuous Deployment): Automated testing and deployment
- Enrollment: Student-course relationship (which students are in which courses)
- Assignment (in CSP context): Mapping of variable to value (course → {classroom, day, slot})
- Slot: Time period for an exam (e.g., Slot 1 = 9:00-11:00 AM)
- Optimization Strategy: Preference for how to schedule (minimize days, balance load, etc.)
VERSION HISTORY
| Version | Date | Author | Changes |
|---|---|---|---|
| 1.0 | 2025-11-26 | Claude Code | Initial memory bank creation |
CONTACT & RESOURCES
Team Communication:
- Primary channel: [Specify - WhatsApp group, Discord, Slack, etc.]
- Code repository: [GitHub URL once created]
- Documentation: This memory bank + inline JavaDoc
External Resources:
- JavaFX Documentation: https://openjfx.io/javadoc/17/
- SQLite Documentation: https://www.sqlite.org/docs.html
- JUnit 5 User Guide: https://junit.org/junit5/docs/current/user-guide/
- Constraint Satisfaction (AI textbook): Russell & Norvig, Chapter 6
Course Materials:
- SE302 course website: [URL from instructor]
- Professor contact: [Email]
- Office hours: [Schedule]
NOTES & ASSUMPTIONS
Assumptions made:
- Exams are single-session (no multi-part exams spanning multiple slots)
- All students in a course take exam at same time (no separate sections)
- One exam per course (no midterm + final during same exam period)
- Classrooms are generic (no special equipment requirements)
- All exams have same duration (fit in one time slot)
- Students are physically able to take 2 exams per day (no disability accommodations modeled)
- Desktop application for single user (Student Affairs staff person), not multi-user
- Windows OS is primary target (but Java ensures cross-platform compatibility)
- Exam period is contiguous (no gaps, e.g., no exams on weekends if those days aren't configured)
- Consecutive = immediately following slot number (whether same day or across day boundary)
Open questions:
- [To be filled in during development as questions arise]
END OF MEMORY BANK
This memory bank should be treated as a living document. Update it as:
- Decisions are made
- Requirements are clarified
- Implementation details are finalized
- Issues are discovered and resolved
All team members should review this document at start of project and reference it throughout development.