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];