From 8253af4f12471fd6f4163b08d73de8a906f26d11 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sat, 6 Dec 2025 20:25:06 +0000 Subject: [PATCH] best version so far --- teacher_timetable.php | 132 ++++++++++++++++++++---------------------- timetable.php | 12 +++- 2 files changed, 74 insertions(+), 70 deletions(-) diff --git a/teacher_timetable.php b/teacher_timetable.php index 979bffb..7264403 100644 --- a/teacher_timetable.php +++ b/teacher_timetable.php @@ -205,85 +205,81 @@ error_log("Final teacher_timetable_by_period structure: " . print_r($teacher_tim 0) { + $prev_period_id = $non_break_periods[$period_idx - 1]['id']; + foreach($timeslots as $ts) { + if ($ts['id'] === $prev_period_id) { + $last_period_end_time = $ts['end_time']; + break; + } + } + } + + foreach ($timeslots as $ts) { + if ($ts['is_break'] && $ts['start_time'] >= $last_period_end_time && $ts['start_time'] < $timeslot_info['start_time']) { + $break_html .= ''; + $break_html .= '' . htmlspecialchars($ts['name']) . '
' . date("g:i A", strtotime($ts['start_time'])) . ' - ' . date("g:i A", strtotime($ts['end_time'])) . ''; + $break_html .= 'Break'; + $break_html .= ''; + } + } + echo $break_html; ?> -
- - +
+ - - - Break - - + $day): ?> + 0) { - $lesson_above = $teacher_timetable_by_period[$day_idx][$period_idx - 1] ?? null; - if ($lesson_above && !empty($lesson_above['is_double'])) { - // This logic needs to be robust. The simplest way is to check if the lesson in the previous period on the same day was a double. - // However, the data structure might not be perfect. Let's check if the lesson ID matches. - $current_lesson = $teacher_timetable_by_period[$day_idx][$period_idx] ?? null; - if ($current_lesson && $lesson_above['id'] === $current_lesson['id']) { - $skip_cell = true; - } - } - } - - // A better approach for skipping: check the lesson itself. - // The `get_timetable_from_db` in `timetable.php` duplicates the lesson entry for the second slot. Let's mimic that here for consistency. - // We need to rebuild the array first. - $lesson = $teacher_timetable_by_period[$day_idx][$period_idx] ?? null; - - // More reliable skip logic based on the logic from timetable.php - $lesson_above = ($period_idx > 0) ? ($teacher_timetable_by_period[$day_idx][$period_idx - 1] ?? null) : null; - if ($lesson_above && !empty($lesson_above['is_double']) && ($lesson_above['id'] ?? 'a') === ($lesson['id'] ?? 'b')) { - // If the lesson above was a double and has the same ID as the current one, skip this cell. - continue; - } - - $rowspan = 1; - if ($lesson && !empty($lesson['is_double'])) { - // Check if the next timeslot is not a break to prevent rowspan over a break row - $is_next_slot_a_break = false; - $current_timeslot_index = -1; - - $timeslots_values = array_values($timeslots); - foreach ($timeslots_values as $index => $ts) { - if ($ts['id'] === $timeslot['id']) { - $current_timeslot_index = $index; - break; + if ($lesson) { + // If it's an array of lessons (co-teaching), display them all + $lessons_to_display = is_array($lesson) && !isset($lesson['id']) ? $lesson : [$lesson]; + foreach ($lessons_to_display as $single_lesson) { + if ($single_lesson) { // Check not null + echo '
'; + echo '' . htmlspecialchars($single_lesson['lesson_display_name']) . '
'; + echo '' . htmlspecialchars($single_lesson['class_name']) . ''; + echo '
'; } } - - if ($current_timeslot_index !== -1 && isset($timeslots_values[$current_timeslot_index + 1])) { - $next_timeslot = $timeslots_values[$current_timeslot_index + 1]; - if ($next_timeslot['is_break']) { - $is_next_slot_a_break = true; - } - } - - if (!$is_next_slot_a_break) { - $rowspan = 2; - } } ?> - - -
-
- -
- - - - - + + - + = $last_timeslot_end_time) { + $final_break_html .= ''; + $final_break_html .= '' . htmlspecialchars($ts['name']) . '
' . date("g:i A", strtotime($ts['start_time'])) . ' - ' . date("g:i A", strtotime($ts['end_time'])) . ''; + $final_break_html .= 'Break'; + $final_break_html .= ''; + } + } + echo $final_break_html; + ?> diff --git a/timetable.php b/timetable.php index b5e8023..7b42185 100644 --- a/timetable.php +++ b/timetable.php @@ -119,16 +119,21 @@ function generate_timetable($data, $days_of_week) { // 4. Placement $lessons_placed = 0; $lessons_failed = 0; + $period_popularity = array_fill(0, $periods_per_day, 0); foreach ($lessons_to_schedule as $index => $lesson) { $lesson_label = $lesson['display_name'] . (is_array($lesson['class_id']) ? ' for ' . count($lesson['class_id']) . ' classes' : ' for class ' . $lesson['class_id']); error_log("generate_timetable: Attempting to place lesson #" . ($index + 1) . ": " . $lesson_label); - $best_slot = find_best_slot_for_lesson($lesson, $class_timetables, $teacher_timetables, $days_of_week, $periods_per_day, $data['workloads'], $data['timeslots']); + $best_slot = find_best_slot_for_lesson($lesson, $class_timetables, $teacher_timetables, $days_of_week, $periods_per_day, $data['workloads'], $data['timeslots'], $period_popularity); if ($best_slot) { $lessons_placed++; $day = $best_slot['day']; $period = $best_slot['period']; + $period_popularity[$period]++; + if ($lesson['is_double']) { + $period_popularity[$period + 1]++; + } error_log("generate_timetable: Found best slot for lesson #" . ($index + 1) . " at Day $day, Period $period."); if ($lesson['type'] === 'single') { @@ -190,7 +195,7 @@ function generate_timetable($data, $days_of_week) { return $class_timetables; } -function find_best_slot_for_lesson($lesson, &$class_timetables, &$teacher_timetables, $days_of_week, $periods_per_day, $workloads, $all_timeslots) { +function find_best_slot_for_lesson($lesson, &$class_timetables, &$teacher_timetables, $days_of_week, $periods_per_day, $workloads, $all_timeslots, $period_popularity) { $best_slot = null; $best_score = -1; @@ -305,6 +310,9 @@ function find_best_slot_for_lesson($lesson, &$class_timetables, &$teacher_timeta } } + // Rule 4: Penalize placing in a timeslot that is already popular across all classes + $current_score -= $period_popularity[$period] * 5; + if ($current_score > $best_score) { $best_score = $current_score; $best_slot = ['day' => $day, 'period' => $period];