'Mon','tue'=>'Tue','wed'=>'Wed','thu'=>'Thu','fri'=>'Fri','sat'=>'Sat','sun'=>'Sun']; /* ---- Clear the router timetable cache so a newly-verified train shows up at once ---- */ function vq_clear_cache(): void { $f = sys_get_temp_dir() . '/trainchain_tt_v3.ser'; if (is_file($f)) @unlink($f); if (function_exists('apcu_delete')) @apcu_delete('tt_v3'); } /* ---- Handle save (POST), then redirect (PRG) ---- */ $flash = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['train_no'])) { $no = preg_replace('/\D/', '', (string) $_POST['train_no']); $days = (array) ($_POST['days'] ?? []); if ($no === '') { $flash = 'err:Invalid train number.'; } else { $mask = ''; foreach ($ORDER as $d) $mask .= in_array($d, $days, true) ? '1' : '0'; if (!preg_match('/^[01]{7}$/', $mask) || $mask === '0000000') { $flash = 'err:Pick at least one running day for train ' . $no . '.'; } else { $st = db()->prepare( "UPDATE trains SET run_days = ?, data_source = 'manual', refreshed_at = NOW() WHERE train_no = ?" ); $st->execute([$mask, $no]); vq_clear_cache(); $flash = 'ok:Train ' . $no . ' set to ' . $mask . ' and added to routing.'; } } $qs = http_build_query(array_filter([ 'f' => $_GET['f'] ?? null, 'q' => $_GET['q'] ?? null, 'p' => $_GET['p'] ?? null, ])); header('Location: /admin/verify_queue.php' . ($qs ? '?' . $qs : '') . '#m' . $no); // pass flash via session so it survives the redirect $_SESSION['vq_flash'] = $flash; exit; } if (!empty($_SESSION['vq_flash'])) { $flash = $_SESSION['vq_flash']; unset($_SESSION['vq_flash']); } /* ---- Filters / paging ---- */ $f = $_GET['f'] ?? 'untried'; // untried | noschedule | all $q = trim((string) ($_GET['q'] ?? '')); $page = max(1, (int) ($_GET['p'] ?? 1)); $per = 50; $off = ($page - 1) * $per; $where = ['run_days IS NULL']; $args = []; if ($f === 'untried') $where[] = 'data_source IS NULL'; elseif ($f === 'noschedule') $where[] = "data_source = 'no_schedule'"; if ($q !== '') { $where[] = '(train_no LIKE ? OR train_name LIKE ?)'; $args[] = "%$q%"; $args[] = "%$q%"; } $wsql = implode(' AND ', $where); $total = (int) (function () use ($wsql, $args) { $s = db()->prepare("SELECT COUNT(*) FROM trains WHERE $wsql"); $s->execute($args); return $s->fetchColumn(); })(); $pages = max(1, (int) ceil($total / $per)); $rows = (function () use ($wsql, $args, $per, $off) { $s = db()->prepare( "SELECT train_no, train_name, source_code, dest_code, data_source FROM trains WHERE $wsql ORDER BY train_no LIMIT $per OFFSET $off" ); $s->execute($args); return $s->fetchAll(); })(); /* ---- Counters for the header ---- */ $c = db()->query( "SELECT SUM(run_days IS NOT NULL) AS verified, SUM(run_days IS NULL AND data_source IS NULL) AS untried, SUM(data_source = 'no_schedule') AS noschedule, COUNT(*) AS total FROM trains" )->fetch(); $page_title = 'Verify queue'; require APP_DIR . '/header.php'; ?>
Only trains with a verified running-days mask appear in journey results. Commit a mask below to add a train to routing.
Verified (routing)
Untried
No API schedule
Total trains
Tip: use AI run-days to look up a train's days, then tick them here and Save.
Nothing pending in this view. 🎉