اولویت ثبت با نفر اول • سهمیه ۱ نوبت سانتریفوژها و هود با کد دانشجویی ۱۳ رقمی • آزادی رزرو همزمان سایر دستگاهها
این فایل index.html به صورت خودکار به api.php متصل میشود، ساعت رسمی تهران را از سرور شما میخواند و تمام نوبتها را با قفل اتمیک (flock) ذخیره میکند.
api.php (در کنار index.html روی سرور قرار دهید):
<?php
// Central Biology Lab Booking Backend (api.php)
// Enforces Asia/Tehran Anti-Cheat Server Time, Strict 13-Digit Student ID (e.g. 1404111198032) & Atomic File Locking (flock)
date_default_timezone_set('Asia/Tehran');
header('Content-Type: application/json; charset=utf-8');
function normalizeStudentIdServer($str) {
$persian = ['۰','۱','۲','۳','۴','۵','۶','۷','۸','۹','٠','١','٢','٣','٤','٥','٦','٧','٨','٩'];
$english = ['0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9'];
$clean = str_replace($persian, $english, (string)$str);
return preg_replace('/[^\d]/', '', $clean);
}
$dbFile = __DIR__ . '/lab_bookings_v4.json';
$fp = fopen($dbFile, 'c+');
if (!flock($fp, LOCK_EX)) {
http_response_code(503);
echo json_encode(['error' => 'سرور مشغول است، مجدداً تلاش کنید.'], JSON_UNESCAPED_UNICODE);
exit;
}
$raw = stream_get_contents($fp);
$state = $raw ? json_decode($raw, true) : [];
if (!is_array($state)) $state = ['days' => [], 'blacklist' => [], 'rules' => [], 'deviceMeta' => []];
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$state['serverTimeMs'] = round(microtime(true) * 1000);
$state['serverIso'] = date('c');
echo json_encode($state, JSON_UNESCAPED_UNICODE);
flock($fp, LOCK_UN);
fclose($fp);
exit;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$input = json_decode(file_get_contents('php://input'), true);
if (isset($input['fullState']) && is_array($input['fullState'])) {
$state['days'] = $input['fullState']['days'] ?? $state['days'];
$state['blacklist'] = $input['fullState']['blacklist'] ?? $state['blacklist'];
$state['rules'] = $input['fullState']['rules'] ?? $state['rules'];
$state['deviceMeta'] = $input['fullState']['deviceMeta'] ?? $state['deviceMeta'];
}
ftruncate($fp, 0);
rewind($fp);
fwrite($fp, json_encode($state, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
fflush($fp);
$state['serverTimeMs'] = round(microtime(true) * 1000);
echo json_encode($state, JSON_UNESCAPED_UNICODE);
}
flock($fp, LOCK_UN);
fclose($fp);
?>