double lesson sorted, now electives

This commit is contained in:
Flatlogic Bot 2025-12-02 17:16:35 +00:00
parent 1295752cb1
commit debb478acf
3 changed files with 67 additions and 12 deletions

View File

@ -0,0 +1,8 @@
CREATE TABLE IF NOT EXISTS schedule_teachers (
id INT AUTO_INCREMENT PRIMARY KEY,
schedule_id INT NOT NULL,
teacher_id INT NOT NULL,
FOREIGN KEY (schedule_id) REFERENCES schedules(id) ON DELETE CASCADE,
FOREIGN KEY (teacher_id) REFERENCES teachers(id) ON DELETE CASCADE,
UNIQUE KEY (schedule_id, teacher_id)
);

View File

@ -5,7 +5,9 @@ require_once 'db/config.php';
// --- Database Fetch Functions --- // --- Database Fetch Functions ---
function get_teachers($pdo, $school_id) { function get_teachers($pdo, $school_id) {
return $pdo->prepare("SELECT * FROM teachers WHERE school_id = ? ORDER BY name")->execute([$school_id])->fetchAll(PDO::FETCH_ASSOC); $stmt = $pdo->prepare("SELECT * FROM teachers WHERE school_id = ? ORDER BY name");
$stmt->execute([$school_id]);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
} }
function get_timeslots($pdo) { function get_timeslots($pdo) {
@ -24,7 +26,8 @@ function get_teacher_schedule($pdo, $teacher_id, $school_id) {
s.is_horizontal_elective s.is_horizontal_elective
FROM schedules s FROM schedules s
JOIN classes c ON s.class_id = c.id JOIN classes c ON s.class_id = c.id
WHERE s.teacher_id = :teacher_id AND s.school_id = :school_id JOIN schedule_teachers st ON s.id = st.schedule_id
WHERE st.teacher_id = :teacher_id AND c.school_id = :school_id
"); ");
$stmt->execute([':teacher_id' => $teacher_id, ':school_id' => $school_id]); $stmt->execute([':teacher_id' => $teacher_id, ':school_id' => $school_id]);
return $stmt->fetchAll(PDO::FETCH_ASSOC); return $stmt->fetchAll(PDO::FETCH_ASSOC);

View File

@ -290,7 +290,8 @@ function generate_timetable($workloads, $classes, $days_of_week, $periods_per_da
'teacher_name' => count($teachers_to_place) > 1 ? 'Multiple' : $lesson['component_lessons'][0]['teacher_name'], 'teacher_name' => count($teachers_to_place) > 1 ? 'Multiple' : $lesson['component_lessons'][0]['teacher_name'],
'is_double' => $is_double, 'is_double' => $is_double,
'is_elective' => $lesson['type'] === 'elective', 'is_elective' => $lesson['type'] === 'elective',
'is_horizontal_elective' => $lesson['type'] === 'horizontal_elective' 'is_horizontal_elective' => $lesson['type'] === 'horizontal_elective',
'component_lessons' => $lesson['component_lessons']
]; ];
if ($is_double) { if ($is_double) {
@ -314,31 +315,56 @@ function generate_timetable($workloads, $classes, $days_of_week, $periods_per_da
// --- Timetable Persistence --- // --- Timetable Persistence ---
function save_timetable($pdo, $class_timetables, $timeslots) { function save_timetable($pdo, $class_timetables, $timeslots) {
$pdo->exec('TRUNCATE TABLE schedules'); $pdo->exec('TRUNCATE TABLE schedules');
$pdo->exec('TRUNCATE TABLE schedule_teachers');
$stmt = $pdo->prepare( $stmt = $pdo->prepare(
'INSERT INTO schedules (class_id, day_of_week, timeslot_id, subject_id, teacher_id, lesson_display_name, teacher_display_name, is_double, is_elective, is_horizontal_elective) ' . 'INSERT INTO schedules (class_id, day_of_week, timeslot_id, subject_id, lesson_display_name, teacher_display_name, is_double, is_elective, is_horizontal_elective) ' .
'VALUES (:class_id, :day_of_week, :timeslot_id, :subject_id, :teacher_id, :lesson_display_name, :teacher_display_name, :is_double, :is_elective, :is_horizontal_elective)' 'VALUES (:class_id, :day_of_week, :timeslot_id, :subject_id, :lesson_display_name, :teacher_display_name, :is_double, :is_elective, :is_horizontal_elective)'
);
$teacher_stmt = $pdo->prepare(
'INSERT INTO schedule_teachers (schedule_id, teacher_id) VALUES (:schedule_id, :teacher_id)'
); );
$lesson_periods = array_values(array_filter($timeslots, function($ts) { return !$ts['is_break']; })); $lesson_periods = array_values(array_filter($timeslots, function($ts) { return !$ts['is_break']; }));
foreach ($class_timetables as $class_id => $day_schedule) { foreach ($class_timetables as $class_id => $day_schedule) {
foreach ($day_schedule as $day_idx => $period_schedule) { foreach ($day_schedule as $day_idx => $period_schedule) {
$processed_periods = [];
foreach ($period_schedule as $period_idx => $lesson) { foreach ($period_schedule as $period_idx => $lesson) {
if ($lesson) { if ($lesson && !in_array($period_idx, $processed_periods)) {
if (!isset($lesson_periods[$period_idx])) continue; if (!isset($lesson_periods[$period_idx])) continue;
$timeslot_id = $lesson_periods[$period_idx]['id']; $timeslot_id = $lesson_periods[$period_idx]['id'];
$stmt->execute([ $stmt->execute([
':class_id' => $class_id, ':class_id' => $class_id,
':day_of_week' => $day_idx, ':day_of_week' => $day_idx,
':timeslot_id' => $timeslot_id, ':timeslot_id' => $timeslot_id,
':subject_id' => $lesson['subject_id'], ':subject_id' => $lesson['subject_id'],
':teacher_id' => $lesson['teacher_id'],
':lesson_display_name' => $lesson['subject_name'], ':lesson_display_name' => $lesson['subject_name'],
':teacher_display_name' => $lesson['teacher_name'], ':teacher_display_name' => $lesson['teacher_name'],
':is_double' => (int)$lesson['is_double'], ':is_double' => (int)$lesson['is_double'],
':is_elective' => (int)$lesson['is_elective'], ':is_elective' => (int)$lesson['is_elective'],
':is_horizontal_elective' => (int)$lesson['is_horizontal_elective'] ':is_horizontal_elective' => (int)$lesson['is_horizontal_elective']
]); ]);
$schedule_id = $pdo->lastInsertId();
if (!empty($lesson['component_lessons'])) {
$teacher_ids = array_unique(array_column($lesson['component_lessons'], 'teacher_id'));
foreach ($teacher_ids as $teacher_id) {
if ($teacher_id) {
$teacher_stmt->execute([
':schedule_id' => $schedule_id,
':teacher_id' => $teacher_id
]);
}
}
}
$processed_periods[] = $period_idx;
if ($lesson['is_double']) {
$processed_periods[] = $period_idx + 1;
}
} }
} }
} }
@ -350,6 +376,11 @@ function get_timetable_from_db($pdo, $classes, $timeslots) {
$saved_lessons = $stmt->fetchAll(PDO::FETCH_ASSOC); $saved_lessons = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (empty($saved_lessons)) return []; if (empty($saved_lessons)) return [];
// Get teacher associations
$schedule_teachers_stmt = $pdo->query('SELECT st.schedule_id, t.name, t.id FROM schedule_teachers st JOIN teachers t ON st.teacher_id = t.id');
$schedule_teachers = $schedule_teachers_stmt->fetchAll(PDO::FETCH_GROUP | PDO::FETCH_ASSOC);
$days_of_week = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']; $days_of_week = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'];
$periods = array_filter($timeslots, function($ts) { return !$ts['is_break']; }); $periods = array_filter($timeslots, function($ts) { return !$ts['is_break']; });
$periods_per_day = count($periods); $periods_per_day = count($periods);
@ -373,16 +404,29 @@ function get_timetable_from_db($pdo, $classes, $timeslots) {
if (!isset($timeslot_id_to_period_idx[$timeslot_id]) || !isset($class_timetables[$class_id])) continue; if (!isset($timeslot_id_to_period_idx[$timeslot_id]) || !isset($class_timetables[$class_id])) continue;
$period_idx = $timeslot_id_to_period_idx[$timeslot_id]; $period_idx = $timeslot_id_to_period_idx[$timeslot_id];
$class_timetables[$class_id][$day_idx][$period_idx] = [ $teachers_for_lesson = $schedule_teachers[$lesson['id']] ?? [];
$teacher_name = $lesson['teacher_display_name'];
if (count($teachers_for_lesson) > 1) {
$teacher_name = 'Multiple';
} elseif (count($teachers_for_lesson) === 1) {
$teacher_name = $teachers_for_lesson[0]['name'];
}
$lesson_data = [
'id' => $lesson['id'], 'id' => $lesson['id'],
'subject_id' => $lesson['subject_id'], 'subject_id' => $lesson['subject_id'],
'teacher_id' => $lesson['teacher_id'],
'subject_name' => $lesson['lesson_display_name'], 'subject_name' => $lesson['lesson_display_name'],
'teacher_name' => $lesson['teacher_display_name'], 'teacher_name' => $teacher_name,
'is_double' => (bool)$lesson['is_double'], 'is_double' => (bool)$lesson['is_double'],
'is_elective' => (bool)$lesson['is_elective'], 'is_elective' => (bool)$lesson['is_elective'],
'is_horizontal_elective' => (bool)$lesson['is_horizontal_elective'] 'is_horizontal_elective' => (bool)$lesson['is_horizontal_elective']
]; ];
$class_timetables[$class_id][$day_idx][$period_idx] = $lesson_data;
if ($lesson_data['is_double'] && isset($class_timetables[$class_id][$day_idx][$period_idx + 1])) {
$class_timetables[$class_id][$day_idx][$period_idx + 1] = $lesson_data;
}
} }
return $class_timetables; return $class_timetables;
} }