PHP Code Editor
<?php /** * Chess Engine Master - Smart Skip & High Success Rate * Debian 10 / PHP 7.3 / Apache2 */ // BOOSTER: Mencegah Error 500 pada file besar ini_set('memory_limit', '512M'); set_time_limit(300); $assets = 'assets/'; $engines = 'engines/'; $files = [ 'jquery.min.js' => ['url' => 'https://ajax.googleapis.com', 'size' => 50000], 'chess.min.js' => ['url' => 'https://cdnjs.cloudflare.com', 'size' => 10000], 'chessboard.min.js' => ['url' => 'https://cdnjs.cloudflare.com', 'size' => 10000], 'chessboard.min.css' => ['url' => 'https://cdnjs.cloudflare.com', 'size' => 2000], 'stockfish.js' => ['url' => 'https://cdn.jsdelivr.net', 'size' => 50000], 'stockfish.wasm' => ['url' => 'https://cdn.jsdelivr.net', 'size' => 500000] ]; // Helper: Cek apakah file sudah ada dan valid (bukan HTML error) function is_file_valid($name, $min_size) { global $assets, $engines; $path = (strpos($name, 'stockfish') !== false ? $engines : $assets) . $name; if (!file_exists($path)) return false; // Cek ukuran & pastikan bukan diawali tag HTML '<' if (filesize($path) < $min_size) return false; $handle = fopen($path, 'r'); $first_char = fgetc($handle); fclose($handle); return $first_char !== '<'; } // API: Handle Download dengan Auto-Skip Logic if (isset($_GET['action']) && $_GET['action'] === 'install') { header('Content-Type: application/json'); $name = $_GET['file']; if (!isset($files[$name])) exit; // JIKA FILE SUDAH ADA & VALID -> SKIP if (is_file_valid($name, $files[$name]['size'])) { echo json_encode(['status' => 'exists', 'size' => filesize((strpos($name, 'stockfish') !== false ? $engines : $assets) . $name)]); exit; } $dir = (strpos($name, 'stockfish') !== false) ? $engines : $assets; if (!file_exists($dir)) @mkdir($dir, 0777, true); // Proses Download dengan cURL (Metode Paling Berhasil) $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $files[$name]['url']); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_TIMEOUT, 60); $data = curl_exec($ch); $info = curl_getinfo($ch); curl_close($ch); if ($info['http_code'] === 200 && $data && strlen($data) >= $files[$name]['size']) { file_put_contents($dir . $name, $data); echo json_encode(['status' => 'ok', 'size' => strlen($data)]); } else { http_response_code(500); echo json_encode(['status' => 'error']); } exit; } // Cek kesiapan untuk memunculkan Papan Catur $is_ready = true; foreach ($files as $n => $m) { if (!is_file_valid($n, $m['size'])) $is_ready = false; } ?> <!DOCTYPE html> <html lang="id"> <head> <meta charset="UTF-8"> <title>Chess Master - Smart Installer</title> <script src="https://cdn.tailwindcss.com"></script> <?php if ($is_ready): ?> <link rel="stylesheet" href="assets/chessboard.min.css"> <script src="assets/jquery.min.js"></script> <script src="assets/chess.min.js"></script> <script src="assets/chessboard.min.js"></script> <?php endif; ?> </head> <body class="bg-[#0d1117] text-slate-300 min-h-screen flex items-center justify-center p-4 font-mono text-sm"> <?php if (!$is_ready): ?> <div class="max-w-md w-full bg-[#161b22] border border-slate-800 p-8 rounded-2xl shadow-2xl"> <h2 class="text-blue-500 font-bold mb-2 uppercase tracking-tighter">Smart Batch Installer</h2> <p class="text-[10px] text-slate-500 mb-6 italic">Fitur: Auto-Skip & Integrity Check</p> <div class="space-y-2 mb-6"> <?php foreach ($files as $n => $m): ?> <div class="flex justify-between text-[11px] p-2 bg-black/40 rounded border border-slate-800/50"> <span><?php echo $n; ?></span> <span id="st-<?php echo str_replace('.','-',$n); ?>" class="text-slate-600 italic">Checking...</span> </div> <?php endforeach; ?> </div> <div class="bg-black rounded-full h-1.5 overflow-hidden mb-6"> <div id="pb" class="bg-blue-600 h-full w-0 transition-all duration-500"></div> </div> <div id="log" class="bg-black/60 p-3 rounded text-[9px] h-32 overflow-y-auto mb-6 border border-slate-800 text-emerald-500 scrollbar-hide"> > Menunggu instruksi... </div> <button onclick="runInstall()" id="btn" class="w-full bg-blue-600 hover:bg-blue-500 py-3 rounded-xl font-bold text-white transition">PROSES DOWNLOAD</button> </div> <script> async function runInstall() { const files = <?php echo json_encode(array_keys($files)); ?>; const log = document.getElementById('log'); document.getElementById('btn').disabled = true; for(let i=0; i<files.length; i++) { const f = files[i]; const id = f.replace(/\./g, '-'); const st = document.getElementById('st-'+id); log.innerHTML += `<div>> Memproses ${f}...</div>`; st.innerText = "Checking..."; try { const res = await fetch(`?action=install&file=${f}`); const data = await res.json(); if (data.status === 'exists') { st.innerText = "EXISTING"; st.className = "text-blue-400 font-bold"; log.innerHTML += `<div class="text-blue-400"> SKIP: ${f} sudah ada.</div>`; } else if (data.status === 'ok') { st.innerText = "DOWNLOADED"; st.className = "text-emerald-500 font-bold"; log.innerHTML += `<div class="text-emerald-500"> DONE: ${f} berhasil.</div>`; } else { throw new Error(); } } catch (e) { st.innerText = "FAILED"; st.className = "text-red-500 font-bold"; log.innerHTML += `<div class="text-red-400"> ERR: ${f} gagal (Lanjut berikutnya).</div>`; } document.getElementById('pb').style.width = ((i+1)/files.length*100) + '%'; log.scrollTop = log.scrollHeight; } log.innerHTML += `<div class="text-blue-400 mt-2">> Refreshing...</div>`; setTimeout(() => location.reload(), 2000); } </script> <?php else: ?> <!-- UI GAMEPLAY TETAP SAMA --> <div class="max-w-5xl w-full grid md:grid-cols-12 gap-8"> <div class="md:col-span-8 bg-[#161b22] p-4 rounded-3xl border border-slate-800 shadow-2xl"> <div id="board" class="w-full"></div> </div> <div class="md:col-span-4 bg-[#161b22] p-6 rounded-3xl border border-slate-800 shadow-xl"> <h1 class="text-2xl font-black text-blue-500 italic mb-4 uppercase">Stockfish Pro</h1> <div id="game-log" class="bg-black/50 p-4 rounded-xl text-[10px] font-mono text-emerald-400 h-64 overflow-y-auto border border-slate-800"> > Sistem Ready.<br>> Giliran Putih. </div> <button onclick="location.reload()" class="w-full mt-6 bg-slate-800 py-3 rounded-xl font-bold">RESET</button> </div> </div> <script> $(function() { const game = new Chess(); const engine = new Worker('engines/stockfish.js'); engine.onmessage = (e) => { if (e.data.includes('bestmove')) { const m = e.data.split(' '); game.move({ from: m.substring(0,2), to: m.substring(2,4), promotion: 'q' }); board.position(game.fen()); $('#game-log').append(`<div class="text-blue-400">> AI: ${m}</div>`).scrollTop(9999); } }; const board = Chessboard('board', { draggable: true, position: 'start', onDrop: (s, t) => { const m = game.move({ from: s, to: t, promotion: 'q' }); if (m === null) return 'snapback'; $('#game-log').append(`<div>> User: ${s}${t}</div>`); engine.postMessage(`position fen ${game.fen()}`); engine.postMessage('go depth 13'); } }); }); </script> <?php endif; ?> </body> </html>
Run Code
<?php /** * Chess Engine Master - Smart Skip & High Success Rate * Debian 10 / PHP 7.3 / Apache2 */ // BOOSTER: Mencegah Error 500 pada file besar ini_set('memory_limit', '512M'); set_time_limit(300); $assets = 'assets/'; $engines = 'engines/'; $files = [ 'jquery.min.js' => ['url' => 'https://ajax.googleapis.com', 'size' => 50000], 'chess.min.js' => ['url' => 'https://cdnjs.cloudflare.com', 'size' => 10000], 'chessboard.min.js' => ['url' => 'https://cdnjs.cloudflare.com', 'size' => 10000], 'chessboard.min.css' => ['url' => 'https://cdnjs.cloudflare.com', 'size' => 2000], 'stockfish.js' => ['url' => 'https://cdn.jsdelivr.net', 'size' => 50000], 'stockfish.wasm' => ['url' => 'https://cdn.jsdelivr.net', 'size' => 500000] ]; // Helper: Cek apakah file sudah ada dan valid (bukan HTML error) function is_file_valid($name, $min_size) { global $assets, $engines; $path = (strpos($name, 'stockfish') !== false ? $engines : $assets) . $name; if (!file_exists($path)) return false; // Cek ukuran & pastikan bukan diawali tag HTML '<' if (filesize($path) < $min_size) return false; $handle = fopen($path, 'r'); $first_char = fgetc($handle); fclose($handle); return $first_char !== '<'; } // API: Handle Download dengan Auto-Skip Logic if (isset($_GET['action']) && $_GET['action'] === 'install') { header('Content-Type: application/json'); $name = $_GET['file']; if (!isset($files[$name])) exit; // JIKA FILE SUDAH ADA & VALID -> SKIP if (is_file_valid($name, $files[$name]['size'])) { echo json_encode(['status' => 'exists', 'size' => filesize((strpos($name, 'stockfish') !== false ? $engines : $assets) . $name)]); exit; } $dir = (strpos($name, 'stockfish') !== false) ? $engines : $assets; if (!file_exists($dir)) @mkdir($dir, 0777, true); // Proses Download dengan cURL (Metode Paling Berhasil) $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $files[$name]['url']); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_TIMEOUT, 60); $data = curl_exec($ch); $info = curl_getinfo($ch); curl_close($ch); if ($info['http_code'] === 200 && $data && strlen($data) >= $files[$name]['size']) { file_put_contents($dir . $name, $data); echo json_encode(['status' => 'ok', 'size' => strlen($data)]); } else { http_response_code(500); echo json_encode(['status' => 'error']); } exit; } // Cek kesiapan untuk memunculkan Papan Catur $is_ready = true; foreach ($files as $n => $m) { if (!is_file_valid($n, $m['size'])) $is_ready = false; } ?> <!DOCTYPE html> <html lang="id"> <head> <meta charset="UTF-8"> <title>Chess Master - Smart Installer</title> <script src="https://cdn.tailwindcss.com"></script> <?php if ($is_ready): ?> <link rel="stylesheet" href="assets/chessboard.min.css"> <script src="assets/jquery.min.js"></script> <script src="assets/chess.min.js"></script> <script src="assets/chessboard.min.js"></script> <?php endif; ?> </head> <body class="bg-[#0d1117] text-slate-300 min-h-screen flex items-center justify-center p-4 font-mono text-sm"> <?php if (!$is_ready): ?> <div class="max-w-md w-full bg-[#161b22] border border-slate-800 p-8 rounded-2xl shadow-2xl"> <h2 class="text-blue-500 font-bold mb-2 uppercase tracking-tighter">Smart Batch Installer</h2> <p class="text-[10px] text-slate-500 mb-6 italic">Fitur: Auto-Skip & Integrity Check</p> <div class="space-y-2 mb-6"> <?php foreach ($files as $n => $m): ?> <div class="flex justify-between text-[11px] p-2 bg-black/40 rounded border border-slate-800/50"> <span><?php echo $n; ?></span> <span id="st-<?php echo str_replace('.','-',$n); ?>" class="text-slate-600 italic">Checking...</span> </div> <?php endforeach; ?> </div> <div class="bg-black rounded-full h-1.5 overflow-hidden mb-6"> <div id="pb" class="bg-blue-600 h-full w-0 transition-all duration-500"></div> </div> <div id="log" class="bg-black/60 p-3 rounded text-[9px] h-32 overflow-y-auto mb-6 border border-slate-800 text-emerald-500 scrollbar-hide"> > Menunggu instruksi... </div> <button onclick="runInstall()" id="btn" class="w-full bg-blue-600 hover:bg-blue-500 py-3 rounded-xl font-bold text-white transition">PROSES DOWNLOAD</button> </div> <script> async function runInstall() { const files = <?php echo json_encode(array_keys($files)); ?>; const log = document.getElementById('log'); document.getElementById('btn').disabled = true; for(let i=0; i<files.length; i++) { const f = files[i]; const id = f.replace(/\./g, '-'); const st = document.getElementById('st-'+id); log.innerHTML += `<div>> Memproses ${f}...</div>`; st.innerText = "Checking..."; try { const res = await fetch(`?action=install&file=${f}`); const data = await res.json(); if (data.status === 'exists') { st.innerText = "EXISTING"; st.className = "text-blue-400 font-bold"; log.innerHTML += `<div class="text-blue-400"> SKIP: ${f} sudah ada.</div>`; } else if (data.status === 'ok') { st.innerText = "DOWNLOADED"; st.className = "text-emerald-500 font-bold"; log.innerHTML += `<div class="text-emerald-500"> DONE: ${f} berhasil.</div>`; } else { throw new Error(); } } catch (e) { st.innerText = "FAILED"; st.className = "text-red-500 font-bold"; log.innerHTML += `<div class="text-red-400"> ERR: ${f} gagal (Lanjut berikutnya).</div>`; } document.getElementById('pb').style.width = ((i+1)/files.length*100) + '%'; log.scrollTop = log.scrollHeight; } log.innerHTML += `<div class="text-blue-400 mt-2">> Refreshing...</div>`; setTimeout(() => location.reload(), 2000); } </script> <?php else: ?> <!-- UI GAMEPLAY TETAP SAMA --> <div class="max-w-5xl w-full grid md:grid-cols-12 gap-8"> <div class="md:col-span-8 bg-[#161b22] p-4 rounded-3xl border border-slate-800 shadow-2xl"> <div id="board" class="w-full"></div> </div> <div class="md:col-span-4 bg-[#161b22] p-6 rounded-3xl border border-slate-800 shadow-xl"> <h1 class="text-2xl font-black text-blue-500 italic mb-4 uppercase">Stockfish Pro</h1> <div id="game-log" class="bg-black/50 p-4 rounded-xl text-[10px] font-mono text-emerald-400 h-64 overflow-y-auto border border-slate-800"> > Sistem Ready.<br>> Giliran Putih. </div> <button onclick="location.reload()" class="w-full mt-6 bg-slate-800 py-3 rounded-xl font-bold">RESET</button> </div> </div> <script> $(function() { const game = new Chess(); const engine = new Worker('engines/stockfish.js'); engine.onmessage = (e) => { if (e.data.includes('bestmove')) { const m = e.data.split(' '); game.move({ from: m.substring(0,2), to: m.substring(2,4), promotion: 'q' }); board.position(game.fen()); $('#game-log').append(`<div class="text-blue-400">> AI: ${m}</div>`).scrollTop(9999); } }; const board = Chessboard('board', { draggable: true, position: 'start', onDrop: (s, t) => { const m = game.move({ from: s, to: t, promotion: 'q' }); if (m === null) return 'snapback'; $('#game-log').append(`<div>> User: ${s}${t}</div>`); engine.postMessage(`position fen ${game.fen()}`); engine.postMessage('go depth 13'); } }); }); </script> <?php endif; ?> </body> </html>
Run Code New Tab
Result