/home/techb158/workloadmatch.com/Manager/Inc
Edit: /home/techb158/workloadmatch.com/Manager/Inc/ConflictResolver.php (4920B)
db = $db;
$this->engine = new ScheduleEngine($db);
}
public function findReplacementForSaturday(int $programId, int $groupId, string $saturdayDate, int $maxDays = 20): ?array {
$group = $this->engine->getGroupInfo($groupId);
if (!$group) return null;
$classDays = explode(',', $group['class_days']);
$holidays = $this->engine->getHolidays($saturdayDate);
$retakes = $this->engine->getRetakeDates($programId, $groupId);
$cur = new DateTime($saturdayDate);
$attempts = 0;
while ($attempts < $maxDays) {
$cur->modify('+1 day');
$day = $cur->format('l');
$dateStr = $cur->format('Y-m-d');
$month = (int)$cur->format('m');
$attempts++;
if ($month === 7) continue;
if ($day === 'Saturday') continue;
if (!in_array($day, $classDays, true)) continue;
if (in_array($dateStr, $holidays, true)) continue;
if (in_array($dateStr, $retakes, true)) continue;
$courseOnDate = $this->getCourseOnDate($groupId, $dateStr);
if ($courseOnDate) continue;
return [
'date' => $dateStr,
'day' => $day,
'gap' => $attempts,
];
}
return null;
}
public function findReplacementUsingAI(int $programId, int $groupId, string $saturdayDate, ?ProviderInterface $provider, array $selectedCourses = []): ?array {
$group = $this->engine->getGroupInfo($groupId);
if (!$group) return $this->findReplacementForSaturday($programId, $groupId, $saturdayDate);
if (!$provider) return $this->findReplacementForSaturday($programId, $groupId, $saturdayDate);
try {
$systemPrompt = "You are a schedule conflict resolution assistant. Find the best replacement date for a cancelled Saturday class. Respond only with JSON.";
$classDays = explode(',', $group['class_days']);
$holidays = $this->engine->getHolidays($saturdayDate);
$retakes = $this->engine->getRetakeDates($programId, $groupId);
$userPrompt = json_encode([
'problem' => "Find replacement date for Saturday $saturdayDate",
'class_days' => $classDays,
'holidays' => $holidays,
'retake_dates' => $retakes,
'exclude_month' => 7,
'max_days_ahead' => 20,
'courses' => $selectedCourses,
]);
$response = $provider->sendPrompt($systemPrompt, $userPrompt);
$date = $response['date'] ?? $response['replacement_date'] ?? null;
if ($date) {
$dt = new DateTime($date);
return [
'date' => $date,
'day' => $dt->format('l'),
'gap' => (int)$dt->diff(new DateTime($saturdayDate))->format('%a'),
'ai' => true,
];
}
} catch (Throwable $e) {
error_log("ConflictResolver AI failed: " . $e->getMessage());
}
return $this->findReplacementForSaturday($programId, $groupId, $saturdayDate);
}
public function suggestScheduleSwap(int $scheduleId1, int $scheduleId2): ?array {
$stmt = $this->db->prepare("
SELECT s1.*, s2.*
FROM schedule_course_for_group s1, schedule_course_for_group s2
WHERE s1.Schedule_ID = ? AND s2.Schedule_ID = ?
");
$stmt->bind_param('ii', $scheduleId1, $scheduleId2);
$stmt->execute();
$result = $stmt->get_result();
$rows = $result->fetch_all(MYSQLI_ASSOC);
$stmt->close();
if (count($rows) < 2) return null;
return [
'swap1' => [
'schedule_id' => $scheduleId1,
'new_date' => $rows[1]['Start_Date'],
],
'swap2' => [
'schedule_id' => $scheduleId2,
'new_date' => $rows[0]['Start_Date'],
],
];
}
private function getCourseOnDate(int $groupId, string $date): ?array {
$stmt = $this->db->prepare("
SELECT scfg.Schedule_ID, c.Course_Name
FROM schedule_course_for_group scfg
JOIN Courses c ON scfg.Course_ID = c.Course_ID
WHERE scfg.Group_ID = ? AND scfg.Start_Date = ?
LIMIT 1
");
$stmt->bind_param('is', $groupId, $date);
$stmt->execute();
$result = $stmt->get_result()->fetch_assoc();
$stmt->close();
return $result ?: null;
}
}