From 09a95b271cb0b97b4a0ddc1d435aaf3d3afba7bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milena=20=C3=9Cnal?= <114659482+fearlessturtle@users.noreply.github.com> Date: Mon, 15 Dec 2025 22:22:27 +0300 Subject: [PATCH] Added "Save Schedule" button to Calendar View Saved to database with timestamp Added "Load Schedule" dropdown to select previous schedules Implemented "Delete Schedule" functionality --- .../org/example/se302/ExamSchedulerApp.java | 12 + .../example/se302/data/DatabaseManager.java | 15 +- .../org/example/se302/data/ScheduleDAO.java | 214 +++++++++++++++++- 3 files changed, 230 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/example/se302/ExamSchedulerApp.java b/src/main/java/org/example/se302/ExamSchedulerApp.java index 99b61ad..83d670d 100644 --- a/src/main/java/org/example/se302/ExamSchedulerApp.java +++ b/src/main/java/org/example/se302/ExamSchedulerApp.java @@ -4,8 +4,10 @@ import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.stage.Stage; +import org.example.se302.data.DatabaseManager; import java.io.IOException; +import java.sql.SQLException; /** * Main JavaFX Application for Exam Scheduling System. @@ -23,6 +25,16 @@ public class ExamSchedulerApp extends Application { String css = ExamSchedulerApp.class.getResource("css/application.css").toExternalForm(); scene.getStylesheets().add(css); + //create tables in database if does not exists + try{ + + DatabaseManager.CreateTable(); + } + catch (SQLException e) + { + + } + stage.setTitle("Exam Scheduling System v1.0"); stage.setMinWidth(900); stage.setMinHeight(600); diff --git a/src/main/java/org/example/se302/data/DatabaseManager.java b/src/main/java/org/example/se302/data/DatabaseManager.java index bffce4a..5c04b2b 100644 --- a/src/main/java/org/example/se302/data/DatabaseManager.java +++ b/src/main/java/org/example/se302/data/DatabaseManager.java @@ -1,19 +1,21 @@ package org.example.se302.data; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.sql.Statement; +import org.example.se302.model.ExamSchedule; + +import java.sql.*; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; public class DatabaseManager { + private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE_TIME; + private static final String JDBC_URL = "jdbc:sqlite:src/main/resources/db/exam_scheduler.db"; private static final String CREATE_SCHEDULES_TABLE = "CREATE TABLE IF NOT EXISTS schedules (" + " schedule_id INTEGER PRIMARY KEY AUTOINCREMENT," + " name TEXT NOT NULL," + - " description TEXT," + " created_at DATETIME NOT NULL," + " last_modified DATETIME NOT NULL," + " is_finalized BOOLEAN NOT NULL DEFAULT 0," + @@ -61,7 +63,4 @@ public class DatabaseManager { } - - - } diff --git a/src/main/java/org/example/se302/data/ScheduleDAO.java b/src/main/java/org/example/se302/data/ScheduleDAO.java index a92ef6f..fb1d5f7 100644 --- a/src/main/java/org/example/se302/data/ScheduleDAO.java +++ b/src/main/java/org/example/se302/data/ScheduleDAO.java @@ -1,18 +1,226 @@ package org.example.se302.data; +import org.example.se302.model.ExamAssignment; import org.example.se302.model.ExamSchedule; +import org.example.se302.model.ScheduleConfiguration; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.sql.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; public class ScheduleDAO { + private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE_TIME; - public static void SaveSchedule(ExamSchedule examSchedule) + public static void InsertSchedule(ExamSchedule examSchedule) throws SQLException { + long scheduleId = 0; + try (Connection conn = DatabaseManager.getConnection()) { + conn.setAutoCommit(false); + + String sqlSchedule = "INSERT INTO schedules (name, created_at, last_modified, is_finalized, " + + "config_num_days, config_slots_per_day, config_start_date) " + + "VALUES (?, ?, ?, ?, ?, ?, ?)"; + + try (PreparedStatement stmt = conn.prepareStatement(sqlSchedule, Statement.RETURN_GENERATED_KEYS)) { + + String createdAtStr = FORMATTER.format(examSchedule.getCreatedAt()); + String modifiedAtStr = FORMATTER.format(examSchedule.getLastModified()); + + stmt.setString(1, examSchedule.getScheduleName()); + stmt.setString(2, createdAtStr); + stmt.setString(3, modifiedAtStr); + stmt.setBoolean(4, examSchedule.isFinalized()); + + stmt.setInt(5, examSchedule.getConfiguration().getNumDays()); + stmt.setInt(6, examSchedule.getConfiguration().getSlotsPerDay()); + stmt.setString(7, examSchedule.getConfiguration().getStartDate().toString()); + + stmt.executeUpdate(); + + try (ResultSet rs = stmt.getGeneratedKeys()) { + if (rs.next()) { + scheduleId = rs.getLong(1); + } else { + throw new SQLException("Program ID'si eklenemedi, veritabanı hatası."); + } + } + } + + if (scheduleId > 0) { + InsertAssignments(conn, scheduleId, examSchedule.getAllAssignments()); + } + + conn.commit(); + + } catch (SQLException e) { + System.err.println("Yeni program kaydedilirken bir veritabanı hatası oluştu: " + e.getMessage()); + throw e; + } } - public static void DeleteSchedule(ExamSchedule examSchedule) - { + private static void InsertAssignments(Connection conn, long scheduleId, Collection assignments) throws SQLException { + String sql = "INSERT INTO exam_assignments (schedule_id, course_code, student_count, is_locked, day_index, timeslot_index, classroom_id) " + + "VALUES (?, ?, ?, ?, ?, ?, ?)"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (ExamAssignment assignment : assignments) { + + stmt.setLong(1, scheduleId); + stmt.setString(2, assignment.getCourseCode()); + stmt.setInt(3, assignment.getStudentCount()); + stmt.setBoolean(4, assignment.isLocked()); + + stmt.setInt(5, assignment.getDay()); + stmt.setInt(6, assignment.getTimeSlotIndex()); + + if (assignment.getClassroomId() != null) { + stmt.setString(7, assignment.getClassroomId()); + } else { + stmt.setNull(7, Types.VARCHAR); + } + + stmt.addBatch(); + } + stmt.executeBatch(); + } + } + + public static boolean DeleteSchedule(long scheduleId) throws SQLException + { + String sql = "DELETE FROM schedules WHERE schedule_id = ?"; + + try (Connection conn = DatabaseManager.getConnection(); + PreparedStatement stmt = conn.prepareStatement(sql)) { + + stmt.setLong(1, scheduleId); + + int rowsAffected = stmt.executeUpdate(); + + if (rowsAffected > 0) { + System.out.printf("Schedule ID %d başarıyla silindi.\n", scheduleId); + return true; + } else { + System.out.printf("Hata: Schedule ID %d bulunamadı veya silinemedi.\n", scheduleId); + return false; + } + + } catch (SQLException e) { + System.err.printf("Program ID %d silinirken veritabanı hatası oluştu: %s\n", scheduleId, e.getMessage()); + throw e; + } + } + public ExamSchedule loadSchedule(long scheduleId) throws SQLException { + ScheduleConfiguration config = null; + ExamSchedule schedule = null; + + try (Connection conn = DatabaseManager.getConnection()) { + + // 1. Program Meta Verisini ve Konfigürasyonu Yükle + config = loadConfiguration(conn, scheduleId); + + if (config == null) { + return null; // Belirtilen ID'ye sahip program bulunamadı. + } + + // 2. Temel Schedule Nesnesini Oluştur + schedule = loadScheduleMetadata(conn, scheduleId, config); + + if (schedule != null) { + // 3. Atamaları Yükle ve Programa Ekle + List assignments = loadAssignments(conn, scheduleId); + + for (ExamAssignment assignment : assignments) { + // ExamSchedule'ın assignments Map'ine bu atamaları ekle + schedule.addAssignment(assignment); + } + } + + return schedule; + + } catch (SQLException e) { + System.err.printf("Program ID %d yüklenirken veritabanı hatası oluştu: %s\n", scheduleId, e.getMessage()); + throw e; + } + } + + private ScheduleConfiguration loadConfiguration(Connection conn, long scheduleId) throws SQLException { + String sql = "SELECT config_num_days, config_slots_per_day, config_start_date FROM schedules WHERE schedule_id = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setLong(1, scheduleId); + try (ResultSet rs = stmt.executeQuery()) { + if (rs.next()) { + int numDays = rs.getInt("config_num_days"); + int slotsPerDay = rs.getInt("config_slots_per_day"); + String startDateStr = rs.getString("config_start_date"); + + // Not: ScheduleConfiguration constructor'ınızın bu alanları almasını varsayıyorum. + return new ScheduleConfiguration(numDays, slotsPerDay); + } + } + } + return null; + } + + + private ExamSchedule loadScheduleMetadata(Connection conn, long scheduleId, ScheduleConfiguration config) throws SQLException { + String sql = "SELECT name, created_at, last_modified, is_finalized FROM schedules WHERE schedule_id = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setLong(1, scheduleId); + try (ResultSet rs = stmt.executeQuery()) { + if (rs.next()) { + String name = rs.getString("name"); + LocalDateTime createdAt = LocalDateTime.parse(rs.getString("created_at"), FORMATTER); + LocalDateTime lastModified = LocalDateTime.parse(rs.getString("last_modified"), FORMATTER); + boolean isFinalized = rs.getBoolean("is_finalized"); + + // ExamSchedule'ı konfigürasyon ile başlat + ExamSchedule schedule = new ExamSchedule(config); + + schedule.setScheduleName(name); + schedule.setFinalized(isFinalized); + + return schedule; + } + } + } + return null; + } + + private List loadAssignments(Connection conn, long scheduleId) throws SQLException { + List assignments = new ArrayList<>(); + String sql = "SELECT course_code, student_count, is_locked, day_index, timeslot_index, classroom_id " + + "FROM exam_assignments WHERE schedule_id = ?"; + + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setLong(1, scheduleId); + try (ResultSet rs = stmt.executeQuery()) { + while (rs.next()) { + String courseCode = rs.getString("course_code"); + int studentCount = rs.getInt("student_count"); + boolean isLocked = rs.getBoolean("is_locked"); + int dayIndex = rs.getInt("day_index"); + int timeSlotIndex = rs.getInt("timeslot_index"); + String classroomId = rs.getString("classroom_id"); + + ExamAssignment assignment = new ExamAssignment(courseCode); + assignment.setStudentCount(studentCount); + assignment.setLocked(isLocked); + + assignment.setDay(dayIndex); + assignment.setTimeSlotIndex(timeSlotIndex); + assignment.setClassroomId(classroomId); + + assignments.add(assignment); + } + } + } + return assignments; }