/home/techb158/workloadmatch.com/workloadmatch.com/BackUp/Manager
Edit: /home/techb158/workloadmatch.com/workloadmatch.com/BackUp/Manager/ajax_course_group_Backup.php (17270B)
prepare("SELECT Time_Slot, Time_From, Time_To, class_days, Weekend_Class FROM Manager_Group_Name WHERE Group_ID = ?");
$stmt->bind_param("i", $groupID);
$stmt->execute();
return $stmt->get_result()->fetch_assoc();
}
// Fetch slot times
function fetch_slot_times($mysqli, $slotLabels, $managerStart, $managerEnd) {
$timeFrom = [];
$timeTo = [];
foreach ($slotLabels as $label) {
$stmt = $mysqli->prepare("SELECT Time_From, Time_To FROM Time_Slot_Programs WHERE Time_Slot = ?");
$stmt->bind_param("s", $label);
$stmt->execute();
$res = $stmt->get_result();
if ($row = $res->fetch_assoc()) {
$timeFrom[] = $row['Time_From'];
$timeTo[] = $row['Time_To'];
} else {
$timeFrom[] = $managerStart->format('H:i:s');
$timeTo[] = $managerEnd->format('H:i:s');
}
}
return [$timeFrom, $timeTo];
}
// Fetch holidays
function get_holidays($mysqli, $startDate) {
$holidays = [];
$res = $mysqli->query("SELECT Event_Start, Event_End FROM Events WHERE Calendar_Year = YEAR('$startDate')");
while ($row = $res->fetch_assoc()) {
$start = new DateTime($row['Event_Start']);
$end = new DateTime($row['Event_End']);
while ($start <= $end) {
$holidays[] = $start->format('Y-m-d');
$start->modify('+1 day');
}
}
return $holidays;
}
// Fetch retake dates
function get_retake_dates($mysqli, $programID, $groupID) {
$retakes = [];
$stmt = $mysqli->prepare("SELECT Retake_Date FROM Retake_Records WHERE Program_ID = ? AND Group_ID = ?");
$stmt->bind_param("ii", $programID, $groupID);
$stmt->execute();
$res = $stmt->get_result();
while ($row = $res->fetch_assoc()) {
$retakes[] = $row['Retake_Date'];
}
return $retakes;
}
// Generate all valid class dates, excluding holidays, retakes, and July
function generate_valid_dates($Start_Date, $End_Date, $classDays, $holidayDates, $retakeDates) {
$validDates = [];
$cur = new DateTime($Start_Date);
$end = $End_Date ? new DateTime($End_Date) : null;
while (!$end || $cur <= $end) {
$day = $cur->format('l');
$dateStr = $cur->format('Y-m-d');
$month = (int)$cur->format('m');
if ($month === 7 || !in_array($day, $classDays)) {
$cur->modify('+1 day');
continue;
}
if (in_array($dateStr, $holidayDates)) {
$validDates[] = ['Date' => $dateStr, 'Type' => 'Holiday'];
} elseif (in_array($dateStr, $retakeDates)) {
$validDates[] = ['Date' => $dateStr, 'Type' => 'Retake'];
} else {
$validDates[] = ['Date' => $dateStr, 'Type' => 'Class'];
}
$cur->modify('+1 day');
if ($end === null && count($validDates) > 500) break;
}
return $validDates;
}
// Calculate the average duration of one session
function calculate_session_length($timeFrom, $timeTo) {
$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);
return $slotCount > 0 ? $sessionLength / $slotCount : 3;
}
// Calculate the number of sessions required for each course
function calculate_course_sessions($mysqli, $Program_ID, $sessionLength) {
$courseSessions = [];
$res = $mysqli->query("SELECT Course_ID, Course_Time FROM Courses WHERE Program_ID = $Program_ID");
while ($row = $res->fetch_assoc()) {
$courseID = $row['Course_ID'];
$courseHours = $row['Course_Time'];
$courseSessions[$courseID] = ceil($courseHours / $sessionLength);
}
return $courseSessions;
}
// --- MAIN LOGIC --- //
/*
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$saturdayDate = $_POST['date'] ?? '';
$programID = intval($_POST['Program_ID'] ?? 0);
$groupID = intval($_POST['Group_ID'] ?? 0);
$startDate = $_POST['Start_Date'] ?? '';
$selectedCourses = json_decode(urldecode($_POST['Selected_Courses'] ?? '[]'), true);
$priorityCourses = json_decode(urldecode($_POST['Priority_Course'] ?? '{}'), true);
if (!$programID || !$groupID || !$saturdayDate || !$startDate || empty($selectedCourses)) {
echo json_encode(['status' => 'error', 'message' => 'Missing required fields.']);
exit;
}
$group = get_group_info($mysqli, $groupID);
if (!$group) {
echo json_encode(['status' => 'error', 'message' => 'Group not found.']);
exit;
}
$classDays = array_map('trim', explode(',', $group['class_days']));
$slotLabels = array_map('trim', explode(',', $group['Time_Slot']));
$managerStart = new DateTime($group['Time_From']);
$managerEnd = new DateTime($group['Time_To']);
list($timeFrom, $timeTo) = fetch_slot_times($mysqli, $slotLabels, $managerStart, $managerEnd);
$holidayDates = get_holidays($mysqli, $startDate);
$retakeDates = get_retake_dates($mysqli, $programID, $groupID);
// 🧹 Find the next valid weekday (limit to 20 days)
$cur = new DateTime($saturdayDate);
$cur->modify('+1 day');
$replacementDate = null;
$attempts = 0;
while ($attempts < 20) {
$day = $cur->format('l');
$dateStr = $cur->format('Y-m-d');
if ($day !== 'Saturday' && in_array($day, $classDays) && !in_array($dateStr, $holidayDates) && !in_array($dateStr, $retakeDates)) {
$replacementDate = $dateStr;
break;
}
$cur->modify('+1 day');
$attempts++;
}
if (!$replacementDate) {
echo json_encode(['status' => 'error', 'message' => 'No available weekday found within 20 days.']);
exit;
}
// 🎯 Sort courses by priority
usort($selectedCourses, function($a, $b) use ($priorityCourses) {
return ($priorityCourses[$a] ?? PHP_INT_MAX) <=> ($priorityCourses[$b] ?? PHP_INT_MAX);
});
$courseID = $selectedCourses[0];
// Fetch course name
$res = $mysqli->query("SELECT Course_Name FROM Courses WHERE Course_ID = $courseID");
$courseData = $res->fetch_assoc();
$courseName = $courseData ? $courseData['Course_Name'] : "Course ID $courseID";
// 🎨 Prepare new HTML row
$dayName = (new DateTime($replacementDate))->format('l');
$slotName = format_time_slot_label($slotLabels[0] ?? 'Morning', $dayName);
$timeRange = format_time_slot_range($slotLabels[0] ?? 'Morning', $timeFrom[0] ?? '08:30', $timeTo[0] ?? '12:30', $dayName);
$newRowHtml = "
| ($dayName) $replacementDate |
$slotName |
$timeRange |
$courseName |
- |
";
echo json_encode([
'status' => 'success',
'original' => $saturdayDate,
'replacement' => $replacementDate,
'newRowHtml' => $newRowHtml
]);
exit;
}
*/
// Handle AJAX request
// Handle AJAX request
// MAIN START
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$Program_ID = intval($_POST['Program_ID']);
$Group_ID = intval($_POST['Group_ID']);
$Start_Date = $_POST['Start_Date'];
$Removed_Date = $_POST['date'];
$selectedCourses = json_decode($_POST['Selected_Courses'], true) ?? [];
$priorityCourses = json_decode($_POST['Priority_Course'], true) ?? [];
$group = get_group_info($mysqli, $Group_ID);
if (!$group) {
echo json_encode(['status' => 'error', 'message' => 'Group not found']);
exit;
}
$classDays = explode(',', $group['class_days']);
$slotLabels = explode(',', $group['Time_Slot']);
$managerStart = new DateTime(trim($group['Time_From']));
$managerEnd = new DateTime(trim($group['Time_To']));
list($timeFrom, $timeTo) = fetch_slot_times($mysqli, $slotLabels, $managerStart, $managerEnd);
$sessionLength = calculate_session_length($timeFrom, $timeTo);
$holidayDates = get_holidays($mysqli, $Start_Date);
$retakeDates = get_retake_dates($mysqli, $Program_ID, $Group_ID);
// Generate valid dates
$validDates = generate_valid_dates($Start_Date, null, $classDays, $holidayDates, $retakeDates);
// Remove the deleted Saturday
$validDates = array_filter($validDates, function($d) use ($Removed_Date) {
return $d['Date'] !== $Removed_Date;
});
$validDates = array_values($validDates);
// Reorder courses by priority
if (!empty($priorityCourses)) {
usort($selectedCourses, function($a, $b) use ($priorityCourses) {
return ($priorityCourses[$a] ?? PHP_INT_MAX) <=> ($priorityCourses[$b] ?? PHP_INT_MAX);
});
}
$courseNames = [];
$res = $mysqli->query("SELECT Course_ID, Course_Name FROM Courses WHERE Program_ID = $Program_ID");
while ($row = $res->fetch_assoc()) {
$courseNames[$row['Course_ID']] = $row['Course_Name'];
}
$courseSessions = calculate_course_sessions($mysqli, $Program_ID, $sessionLength);
$remainingSessions = [];
foreach ($selectedCourses as $courseID) {
$remainingSessions[$courseID] = $courseSessions[$courseID] ?? 0;
}
// Build schedule
$html = '
';
$html .= '| Date | Slot | Time | Course | Action |
';
$currentCourse = reset($selectedCourses);
$slotCount = count($slotLabels);
$slotIndex = 0;
foreach ($validDates as $entry) {
$date = $entry['Date'];
$dayName = (new DateTime($date))->format('l');
$type = $entry['Type'];
if ($type == 'Holiday') {
$html .= "| {$date} (Holiday) |
";
continue;
}
if ($type == 'Retake') {
$html .= "| {$date} (Retake Day) |
";
continue;
}
if (!$currentCourse) break;
$slotLabel = format_time_slot_label($slotLabels[$slotIndex % $slotCount], $dayName);
$timeRange = format_time_slot_range($slotLabels[$slotIndex % $slotCount], $timeFrom[$slotIndex % $slotCount], $timeTo[$slotIndex % $slotCount], $dayName);
$examTag = ($remainingSessions[$currentCourse] == 1) ? ' (Exam Day)' : '';
$action = ($dayName === 'Saturday' && !$examTag) ? "" : "-";
$html .= "";
$html .= "| ($dayName) $date | $slotLabel | $timeRange | {$courseNames[$currentCourse]}$examTag | $action | ";
$html .= "
";
$remainingSessions[$currentCourse]--;
if ($remainingSessions[$currentCourse] <= 0) {
$currentCourse = next($selectedCourses);
}
$slotIndex++;
}
$html .= '
';
echo json_encode([
'status' => 'success',
'html' => $html
]);
exit;
}
// ------------------- Functions -------------------
function generateSchedule($mysqli, $Program_ID, $Group_ID, $Start_Date, $Removed_Date, $selectedCourses, $priorityCourses) {
// Get group info
$group = get_group_info($mysqli, $Group_ID);
if (!$group) {
return '
Error: Group not found.
';
}
$classDays = explode(',', $group['class_days']);
$slotLabels = explode(',', $group['Time_Slot']);
$managerStart = new DateTime(trim($group['Time_From']));
$managerEnd = new DateTime(trim($group['Time_To']));
list($timeFrom, $timeTo) = fetch_slot_times($mysqli, $slotLabels, $managerStart, $managerEnd);
$sessionLength = calculate_session_length($timeFrom, $timeTo);
// Courses & sessions
$courseSessions = calculate_course_sessions($mysqli, $Program_ID, $sessionLength);
// Load holidays & retakes
$holidayDates = get_holidays($mysqli, $Start_Date);
$retakeDates = get_retake_dates($mysqli, $Program_ID, $Group_ID);
// Generate valid dates
$validDates = generate_valid_dates($Start_Date, null, $classDays, $holidayDates, $retakeDates);
// Remove the Saturday we want to delete
$validDates = array_filter($validDates, function($date) use ($Removed_Date) {
return $date !== $Removed_Date;
});
$validDates = array_values($validDates); // Re-index after filtering
// Sort courses by priority
if (!empty($priorityCourses)) {
usort($selectedCourses, function ($a, $b) use ($priorityCourses) {
$priorityA = $priorityCourses[$a] ?? PHP_INT_MAX;
$priorityB = $priorityCourses[$b] ?? PHP_INT_MAX;
return $priorityA <=> $priorityB;
});
}
// Initialize scheduling
$schedule = [];
$remainingSessions = [];
foreach ($selectedCourses as $courseID) {
$remainingSessions[$courseID] = $courseSessions[$courseID] ?? 0;
}
// Course Names
$courseNames = [];
$res = $mysqli->query("SELECT Course_ID, Course_Name FROM Courses");
while ($row = $res->fetch_assoc()) {
$courseNames[$row['Course_ID']] = $row['Course_Name'];
}
// Main loop: assign courses
$courseQueue = $selectedCourses;
$currentCourses = [0 => null, 1 => null]; // Morning and Evening
foreach ([0, 1] as $slotIndex) {
foreach ($courseQueue as $courseID) {
if ($remainingSessions[$courseID] > 0) {
$currentCourses[$slotIndex] = $courseID;
break;
}
}
}
$examTag = ' (Exam Day)';
// Build schedule
$examDates = [];
foreach ($validDates as $date) {
$weekday = (new DateTime($date))->format('l');
foreach ([0, 1] as $slotIndex) {
$from = $timeFrom[$slotIndex] ?? null;
$to = $timeTo[$slotIndex] ?? null;
if (!$from || !$to || !$currentCourses[$slotIndex]) {
continue;
}
$courseID = $currentCourses[$slotIndex];
$isExam = false;
if (isset($remainingSessions[$courseID]) && $remainingSessions[$courseID] == 1) {
$isExam = true; // last session becomes exam
}
$schedule[] = [
'Date' => $date,
'Day' => $weekday,
'Slot' => $slotLabels[$slotIndex] ?? 'Unknown Slot',
'Time' => format_time_slot_range($slotLabels[$slotIndex], $from, $to, $weekday),
'Course_Name' => $courseNames[$courseID] ?? 'Unknown',
'IsExam' => $isExam
];
// Reduce sessions
$remainingSessions[$courseID]--;
if ($remainingSessions[$courseID] <= 0) {
$currentCourses[$slotIndex] = null;
while (!empty($courseQueue)) {
$nextCourseID = array_shift($courseQueue);
if ($remainingSessions[$nextCourseID] > 0) {
$currentCourses[$slotIndex] = $nextCourseID;
break;
}
}
}
}
if (!$currentCourses[0] && !$currentCourses[1]) {
break;
}
}
// Render HTML
$html = "
";
$html .= "
";
$html .= "| Date | Slot | Time | Course | Action |
";
foreach ($schedule as $row) {
$formattedDate = "(" . $row['Day'] . ") " . $row['Date'];
$examLabel = $row['IsExam'] ? $examTag : '';
$action = (stripos($row['Day'], 'Saturday') !== false) ? "🧹 Replace" : "-";
$html .= "";
$html .= "| {$formattedDate} | ";
$html .= "{$row['Slot']} | ";
$html .= "{$row['Time']} | ";
$html .= "{$row['Course_Name']}{$examLabel} | ";
$html .= "{$action} | ";
$html .= "
";
}
$html .= "
";
return $html;
}
// ❌ Fallback if not POST
http_response_code(405);
echo json_encode(['status' => 'error', 'message' => 'Invalid request method.']);
exit;
?>