/home/techb158/workloadmatch.com/Manager/Generate_Schedule.php (34743B)
| Date | Slot | Time | Course ID |
|---|---|---|---|
| {$row['Date']} | Slot {$row['Time_Slot']} | {$row['Time_From']} - {$row['Time_To']} | {$row['Course_ID']} |
"; print_r($selectedCourses); echo ""; echo "
"; print_r($courseSessions); echo ""; echo "
"; print_r($priorityCourses); echo ""; if (empty($selectedCourses)) { echo "No courses selected."; exit; } // Fetch group time slot config $stmt = $mysqli->prepare("SELECT Time_Slot, Time_From, Time_To, class_days, Weekend_Class, Group_Name FROM manager_group_name WHERE Group_ID = ?"); $stmt->bind_param("i", $Group_ID); $stmt->execute(); $group = $stmt->get_result()->fetch_assoc(); if (!$group) { echo "Group info not found."; exit; } $classDays = explode(',', $group['class_days']); $weekend = $group['Weekend_Class']; $groupName = $group['Group_Name']; // Remove Saturday if not allowed if (!$weekend && in_array('Saturday', $classDays)) { $classDays = array_filter($classDays, fn($day) => $day !== 'Saturday'); } // Extract working window and slot labels $slotLabels = explode(',', $group['Time_Slot']); $managerStart = new DateTime(trim($group['Time_From'])); $managerEnd = new DateTime(trim($group['Time_To'])); $managerDuration = $managerEnd->diff($managerStart); $dayHours = $managerDuration->h + ($managerDuration->i / 60); $slotCount = count($slotLabels); $sessionLength = $slotCount > 0 ? $dayHours / $slotCount : 3; $courseSessions = []; $courseQuery = $mysqli->query("SELECT Course_ID, Course_Time FROM Courses WHERE Program_ID = $Program_ID"); while ($row = $courseQuery->fetch_assoc()) { $courseID = $row['Course_ID']; $courseHours = $row['Course_Time']; $courseSessions[$courseID] = ceil($courseHours / $sessionLength); } $timeFrom = []; $timeTo = []; foreach ($slotLabels as $label) { $label = trim($label); $stmt = $mysqli->prepare("SELECT Time_From, Time_To FROM time_slot_programs WHERE Time_Slot = ?"); $stmt->bind_param("s", $label); $stmt->execute(); $result = $stmt->get_result(); $validSlotFound = false; while ($row = $result->fetch_assoc()) { $slotStart = new DateTime($row['Time_From']); $slotEnd = new DateTime($row['Time_To']); if ($slotStart >= $managerStart && $slotEnd <= $managerEnd) { $timeFrom[] = $slotStart->format("H:i:s"); $timeTo[] = $slotEnd->format("H:i:s"); $validSlotFound = true; break; } } if (!$validSlotFound) { if (count($slotLabels) === 1) { echo "
âš No matching slot found for '$label', using full manager time range.
"; $timeFrom[] = $managerStart->format("H:i:s"); $timeTo[] = $managerEnd->format("H:i:s"); } else { echo "⌠No valid time_slot_programs found for label '$label' within the manager range {$managerStart->format('H:i')}-{$managerEnd->format('H:i')}
"; } } } $sessionLength = 0; foreach ($timeFrom as $i => $from) { $fromTime = new DateTime($from); $toTime = new DateTime($timeTo[$i]); $sessionLength += ($toTime->getTimestamp() - $fromTime->getTimestamp()) / 3600; } $slotCount = count($timeFrom); $sessionLength = $slotCount > 0 ? $sessionLength / $slotCount : 3; $courseSessions = []; if (empty($courseSessions)) { $courseQuery = $mysqli->query("SELECT Course_ID, Course_Time FROM Courses WHERE Program_ID = $Program_ID"); while ($row = $courseQuery->fetch_assoc()) { $courseID = $row['Course_ID']; $courseHours = $row['Course_Time']; $courseSessions[$courseID] = ceil($courseHours / $sessionLength); } } // Get holidays $holidayDates = []; $res = $mysqli->query("SELECT Event_Start, Event_End FROM Events WHERE Calendar_Year = YEAR('$Start_Date')"); while ($row = $res->fetch_assoc()) { $start = new DateTime($row['Event_Start']); $end = new DateTime($row['Event_End']); while ($start <= $end) { $holidayDates[] = $start->format('Y-m-d'); $start->modify('+1 day'); } } // Get retake dates $retakeDates = []; $retakeStmt = $mysqli->prepare("SELECT Retake_Date FROM retake_records WHERE Program_ID = ? AND Group_ID = ?"); $retakeStmt->bind_param("ii", $Program_ID, $Group_ID); $retakeStmt->execute(); $retakes = $retakeStmt->get_result(); while ($row = $retakes->fetch_assoc()) { $retakeDates[] = $row['Retake_Date']; } // Build valid schedule days (excluding July) $cur = new DateTime($Start_Date); $validDates = []; $totalSessionsNeeded = array_sum($courseSessions); $sessionsPerDay = count($slotLabels); $daysRequired = ceil($totalSessionsNeeded / $sessionsPerDay); $added = 0; while ($added < $daysRequired) { $day = $cur->format('l'); $dateStr = $cur->format('Y-m-d'); $month = (int) $cur->format('m'); if ($month === 7) { $cur->modify('+1 day'); continue; } if (in_array($day, $classDays) && !in_array($dateStr, $holidayDates) && !in_array($dateStr, $retakeDates)) { $validDates[] = $dateStr; $added++; } $cur->modify('+1 day'); } // Output valid dates echo ""; print_r($validDates); echo ""; // Output valid dates //echo "
"; print_r($validDates); echo ""; $totalSessionsNeeded = array_sum($courseSessions); $availableDays = count($validDates); // Estimate sessions per day (based on number of slots) $sessionsPerDay = count($slotLabels); // Calculate how many days are needed to finish all sessions $daysRequired = ceil($totalSessionsNeeded / $sessionsPerDay); // Get expected end date $expectedEndDate = $validDates[$daysRequired - 1] ?? end($validDates); // fallback to last available if out of bounds echo "
$expectedEndDate (" . (new DateTime($expectedEndDate))->format('l') . ")
"; // Sort by course priority usort($selectedCourses, function ($a, $b) use ($priorityCourses) { $priorityA = $priorityCourses[$a] ?? PHP_INT_MAX; $priorityB = $priorityCourses[$b] ?? PHP_INT_MAX; return $priorityA <=> $priorityB; }); echo ""; print_r($selectedCourses); echo ""; // Prepare for fair scheduling (one course per slot) // Initialize $schedule = []; $remainingSessions = []; foreach ($selectedCourses as $courseID) { $remainingSessions[$courseID] = $courseSessions[$courseID] ?? 0; } // Queue of all courses $courseQueue = $selectedCourses; $currentCourses = [ 0 => null, // Slot 1 (e.g. Morning) 1 => null // Slot 2 (e.g. Afternoon) ]; // Assign initial two courses // Assign initial courses to slots without repeating $courseQueueCopy = $selectedCourses; $assignedCourses = []; foreach ([0, 1] as $slotIndex) { foreach ($courseQueueCopy as $courseID) { if (!in_array($courseID, $assignedCourses) && $remainingSessions[$courseID] > 0) { $currentCourses[$slotIndex] = $courseID; $assignedCourses[] = $courseID; break; } } } // Fetch all course names into array $courseNames = []; $courseRes = $mysqli->query("SELECT Course_ID, Course_Name FROM Courses"); while ($row = $courseRes->fetch_assoc()) { $courseNames[$row['Course_ID']] = $row['Course_Name']; } foreach ($validDates as $date) { $totalSessions = $courseSessions; // Copy of original sessions foreach ([0, 1] as $slotIndex) { $from = $timeFrom[$slotIndex] ?? null; $to = $timeTo[$slotIndex] ?? null; if (!$from || !$to || !$currentCourses[$slotIndex]) continue; $courseID = $currentCourses[$slotIndex]; $courseName = $courseNames[$courseID] ?? "Course #$courseID"; // Schedule the session $schedule[] = [ 'Date' => $date, 'Slot' => "Slot " . ($slotIndex + 1), 'Time' => format_time_slot_range($slotLabels[$slotIndex], $from, $to, (new DateTime($date))->format('l')), 'Course_ID' => $courseID ]; // Session info $scheduledSoFar = $totalSessions[$courseID] - $remainingSessions[$courseID] + 1; $total = $totalSessions[$courseID]; echo "
✅ Scheduled $courseName (Course ID: $courseID) on $date (Slot " . ($slotIndex + 1) . ") - Session $scheduledSoFar of $total
"; // Decrease remaining $remainingSessions[$courseID]--; // If finished, pull a new course if ($remainingSessions[$courseID] <= 0) { $currentCourses[$slotIndex] = null; while (!empty($courseQueue)) { $nextCourse = array_shift($courseQueue); if ($remainingSessions[$nextCourse] > 0) { $currentCourses[$slotIndex] = $nextCourse; break; } } } } // Stop if both slots are out of courses if (!$currentCourses[0] && !$currentCourses[1]) break; } // 🔠Identify last scheduled session for each course $lastSessions = []; foreach ($schedule as $index => $entry) { $courseID = $entry['Course_ID']; $lastSessions[$courseID] = $index; // keeps overwriting until the last index } echo ""; print_r($schedule); echo ""; echo "
Group: " . htmlspecialchars($groupName) . "
"; if (!empty($schedule)) { // Collect all displayed dates: scheduled, holidays, and retakes $displayDates = []; // 1. From scheduled sessions foreach ($schedule as $row) { $displayDates[$row['Date']][] = $row; // grouped by date } // 2. Add holidays (if no course scheduled on them) foreach ($holidayDates as $hDate) { if (!isset($displayDates[$hDate])) { $displayDates[$hDate] = []; // will be handled below } } // 3. Add retakes foreach ($retakeDates as $rDate) { if (!isset($displayDates[$rDate])) { $displayDates[$rDate] = []; // will be handled below } } // Sort the dates chronologically ksort($displayDates); echo "| Date | Slot | Time | Course |
|---|---|---|---|
| $date | $label | ||
| (" . (new DateTime($row['Date']))->format('l') . ") {$row['Date']} | {$slotName} | {$row['Time']} | {$courseName}" . ($isExam ? " (Exam Day)" : "") . " |
🚫 No schedule generated - check if valid time slots, sessions, or dates are missing.
"; } } /* if ($_SERVER['REQUEST_METHOD'] === 'POST') { $Program_ID = intval($_POST['Program_ID']); $Group_ID = intval($_POST['Group_ID']); $Start_Date = $_POST['Start_Date']; //$End_Date = $_POST['End_Date']; $Divide_Evenly = isset($_POST['Divide_Evenly']); $selectedCourses = $_POST['Selected_Courses'] ?? []; $courseSessions = $_POST['Course_Sessions'] ?? []; $priorityCourses = $_POST['Priority_Course'] ?? []; echo ""; print_r($selectedCourses); echo ""; echo "
"; print_r($courseSessions); echo ""; echo "
"; print_r($priorityCourses); echo ""; if (empty($selectedCourses)) { echo "No courses selected."; exit; } // Fetch group time slot config $stmt = $mysqli->prepare("SELECT Time_Slot, Time_From, Time_To, class_days, Weekend_Class, Group_Name FROM manager_group_name WHERE Group_ID = ?"); $stmt->bind_param("i", $Group_ID); $stmt->execute(); $group = $stmt->get_result()->fetch_assoc(); if (!$group) { echo "Group info not found."; exit; } $classDays = explode(',', $group['class_days']); $weekend = $group['Weekend_Class']; $groupName = $group['Group_Name']; // Remove Saturday if not allowed if (!$weekend && in_array('Saturday', $classDays)) { $classDays = array_filter($classDays, fn($day) => $day !== 'Saturday'); } // Extract working window and slot labels $slotLabels = explode(',', $group['Time_Slot']); $managerStart = new DateTime(trim($group['Time_From'])); $managerEnd = new DateTime(trim($group['Time_To'])); // Calculate session length in hours from group's full day $managerStart = new DateTime(trim($group['Time_From'])); $managerEnd = new DateTime(trim($group['Time_To'])); $managerDuration = $managerEnd->diff($managerStart); $dayHours = $managerDuration->h + ($managerDuration->i / 60); // Count number of time slots (based on Time_Slot labels) $slotCount = count($slotLabels); $sessionLength = $slotCount > 0 ? $dayHours / $slotCount : 3; // fallback 3 if division fails // Fetch course hours and calculate suggested session count $courseSessions = []; // overwrite or generate if not already provided $courseQuery = $mysqli->query("SELECT Course_ID, Course_Time FROM Courses WHERE Program_ID = $Program_ID"); while ($row = $courseQuery->fetch_assoc()) { $courseID = $row['Course_ID']; $courseHours = $row['Course_Time']; $courseSessions[$courseID] = ceil($courseHours / $sessionLength); } $timeFrom = []; $timeTo = []; foreach ($slotLabels as $label) { $label = trim($label); $stmt = $mysqli->prepare("SELECT Time_From, Time_To FROM time_slot_programs WHERE Time_Slot = ?"); $stmt->bind_param("s", $label); $stmt->execute(); $result = $stmt->get_result(); $validSlotFound = false; while ($row = $result->fetch_assoc()) { $slotStart = new DateTime($row['Time_From']); $slotEnd = new DateTime($row['Time_To']); // ✅ Check if the slot fits within the group's available range if ($slotStart >= $managerStart && $slotEnd <= $managerEnd) { $timeFrom[] = $slotStart->format("H:i:s"); $timeTo[] = $slotEnd->format("H:i:s"); $validSlotFound = true; break; // pick the first valid one } } if (!$validSlotFound) { // ✅ Fallback only if the group has ONE slot if (count($slotLabels) === 1) { echo "
âš No matching slot found for '$label', using full manager time range.
"; $timeFrom[] = $managerStart->format("H:i:s"); $timeTo[] = $managerEnd->format("H:i:s"); } else { echo "⌠No valid time_slot_programs found for label '$label' within the manager range {$managerStart->format('H:i')}-{$managerEnd->format('H:i')}
"; } } } // 🔄 Calculate accurate session length based on selected slot durations $sessionLength = 0; foreach ($timeFrom as $i => $from) { $fromTime = new DateTime($from); $toTime = new DateTime($timeTo[$i]); $sessionLength += ($toTime->getTimestamp() - $fromTime->getTimestamp()) / 3600; } $slotCount = count($timeFrom); $sessionLength = $slotCount > 0 ? $sessionLength / $slotCount : 3; // Fetch course hours and calculate suggested session count $courseSessions = []; if (empty($courseSessions)) { $courseQuery = $mysqli->query("SELECT Course_ID, Course_Time FROM Courses WHERE Program_ID = $Program_ID"); while ($row = $courseQuery->fetch_assoc()) { $courseID = $row['Course_ID']; $courseHours = $row['Course_Time']; $courseSessions[$courseID] = ceil($courseHours / $sessionLength); } } echo "Time From: "; print_r($timeFrom); echo ""; echo "
Time To: "; print_r($timeTo); echo ""; echo "
"; print_r($classDays); echo ""; // Get holidays $holidayDates = []; $res = $mysqli->query("SELECT Event_Start, Event_End FROM Events WHERE Calendar_Year = YEAR('$Start_Date')"); while ($row = $res->fetch_assoc()) { $start = new DateTime($row['Event_Start']); $end = new DateTime($row['Event_End']); while ($start <= $end) { $holidayDates[] = $start->format('Y-m-d'); $start->modify('+1 day'); } } echo "
"; print_r($holidayDates); echo ""; // Get retake dates $retakeDates = []; $retakeStmt = $mysqli->prepare("SELECT Retake_Date FROM retake_records WHERE Program_ID = ? AND Group_ID = ?"); $retakeStmt->bind_param("ii", $Program_ID, $Group_ID); $retakeStmt->execute(); $retakes = $retakeStmt->get_result(); while ($row = $retakes->fetch_assoc()) { $retakeDates[] = $row['Retake_Date']; } echo "
"; print_r($retakeDates); echo ""; // Build valid schedule days //$validDates = []; $cur = new DateTime($Start_Date); $validDates = []; $totalSessionsNeeded = array_sum($courseSessions); $sessionsPerDay = count($slotLabels); $daysRequired = ceil($totalSessionsNeeded / $sessionsPerDay); $added = 0; while ($added < $daysRequired) { $day = $cur->format('l'); $dateStr = $cur->format('Y-m-d'); if (in_array($day, $classDays) && !in_array($dateStr, $holidayDates) && !in_array($dateStr, $retakeDates)) { $validDates[] = $dateStr; $added++; } $cur->modify('+1 day'); } // Suggest the end date $expectedEndDate = end($validDates); echo "
$expectedEndDate (" . (new DateTime($expectedEndDate))->format('l') . ")
"; $end = new DateTime($End_Date); while ($cur <= $end) { $day = $cur->format('l'); $dateStr = $cur->format('Y-m-d'); if (in_array($day, $classDays) && !in_array($dateStr, $holidayDates) && !in_array($dateStr, $retakeDates)) { $validDates[] = $dateStr; } $cur->modify('+1 day'); } echo ""; print_r($validDates); echo ""; $totalSessionsNeeded = array_sum($courseSessions); $availableDays = count($validDates); // Estimate sessions per day (based on number of slots) $sessionsPerDay = count($slotLabels); // Calculate how many days are needed to finish all sessions $daysRequired = ceil($totalSessionsNeeded / $sessionsPerDay); // Get expected end date $expectedEndDate = $validDates[$daysRequired - 1] ?? end($validDates); // fallback to last available if out of bounds echo "
$expectedEndDate (" . (new DateTime($expectedEndDate))->format('l') . ")
"; // Sort by course priority usort($selectedCourses, function ($a, $b) use ($priorityCourses) { $priorityA = $priorityCourses[$a] ?? PHP_INT_MAX; $priorityB = $priorityCourses[$b] ?? PHP_INT_MAX; return $priorityA <=> $priorityB; }); echo ""; print_r($selectedCourses); echo ""; // Prepare for fair scheduling (one course per slot) // Initialize $schedule = []; $remainingSessions = []; foreach ($selectedCourses as $courseID) { $remainingSessions[$courseID] = $courseSessions[$courseID] ?? 0; } // Queue of all courses $courseQueue = $selectedCourses; $currentCourses = [ 0 => null, // Slot 1 (e.g. Morning) 1 => null // Slot 2 (e.g. Afternoon) ]; // Assign initial two courses // Assign initial courses to slots without repeating $courseQueueCopy = $selectedCourses; $assignedCourses = []; foreach ([0, 1] as $slotIndex) { foreach ($courseQueueCopy as $courseID) { if (!in_array($courseID, $assignedCourses) && $remainingSessions[$courseID] > 0) { $currentCourses[$slotIndex] = $courseID; $assignedCourses[] = $courseID; break; } } } // Fetch all course names into array $courseNames = []; $courseRes = $mysqli->query("SELECT Course_ID, Course_Name FROM Courses"); while ($row = $courseRes->fetch_assoc()) { $courseNames[$row['Course_ID']] = $row['Course_Name']; } foreach ($validDates as $date) { $totalSessions = $courseSessions; // Copy of original sessions foreach ([0, 1] as $slotIndex) { $from = $timeFrom[$slotIndex] ?? null; $to = $timeTo[$slotIndex] ?? null; if (!$from || !$to || !$currentCourses[$slotIndex]) continue; $courseID = $currentCourses[$slotIndex]; $courseName = $courseNames[$courseID] ?? "Course #$courseID"; // Schedule the session $schedule[] = [ 'Date' => $date, 'Slot' => "Slot " . ($slotIndex + 1), 'Time' => format_time_slot_range($slotLabels[$slotIndex], $from, $to, (new DateTime($date))->format('l')), 'Course_ID' => $courseID ]; // Session info $scheduledSoFar = $totalSessions[$courseID] - $remainingSessions[$courseID] + 1; $total = $totalSessions[$courseID]; echo "
✅ Scheduled $courseName (Course ID: $courseID) on $date (Slot " . ($slotIndex + 1) . ") - Session $scheduledSoFar of $total
"; // Decrease remaining $remainingSessions[$courseID]--; // If finished, pull a new course if ($remainingSessions[$courseID] <= 0) { $currentCourses[$slotIndex] = null; while (!empty($courseQueue)) { $nextCourse = array_shift($courseQueue); if ($remainingSessions[$nextCourse] > 0) { $currentCourses[$slotIndex] = $nextCourse; break; } } } } // Stop if both slots are out of courses if (!$currentCourses[0] && !$currentCourses[1]) break; } // 🔠Identify last scheduled session for each course $lastSessions = []; foreach ($schedule as $index => $entry) { $courseID = $entry['Course_ID']; $lastSessions[$courseID] = $index; // keeps overwriting until the last index } echo ""; print_r($schedule); echo ""; echo "
Group: " . htmlspecialchars($groupName) . "
"; if (!empty($schedule)) { // Collect all displayed dates: scheduled, holidays, and retakes $displayDates = []; // 1. From scheduled sessions foreach ($schedule as $row) { $displayDates[$row['Date']][] = $row; // grouped by date } // 2. Add holidays (if no course scheduled on them) foreach ($holidayDates as $hDate) { if (!isset($displayDates[$hDate])) { $displayDates[$hDate] = []; // will be handled below } } // 3. Add retakes foreach ($retakeDates as $rDate) { if (!isset($displayDates[$rDate])) { $displayDates[$rDate] = []; // will be handled below } } // Sort the dates chronologically ksort($displayDates); echo "| Date | Slot | Time | Course |
|---|---|---|---|
| $date | $label | ||
| (" . (new DateTime($row['Date']))->format('l') . ") {$row['Date']} | {$slotName} | {$row['Time']} | {$courseName}" . ($isExam ? " (Exam Day)" : "") . " |
🚫 No schedule generated - check if valid time slots, sessions, or dates are missing.
"; } } */ ?>