switched server from js to py
This commit is contained in:
parent
c87f8d8383
commit
7afc48fd6c
10 changed files with 594 additions and 862 deletions
406
down.html
Normal file
406
down.html
Normal file
|
|
@ -0,0 +1,406 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>503 Service Unavailable</title>
|
||||
<style>
|
||||
/* --- Clean, Modern Dark Theme (GitHub/VSCode style) --- */
|
||||
:root {
|
||||
--bg-color: #0d1117;
|
||||
--card-bg: #161b22;
|
||||
--border: #30363d;
|
||||
--text-main: #c9d1d9;
|
||||
--text-sub: #8b949e;
|
||||
--accent: #58a6ff;
|
||||
--error: #f85149;
|
||||
--success: #3fb950;
|
||||
--font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
|
||||
--font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: var(--bg-color);
|
||||
color: var(--text-main);
|
||||
font-family: var(--font-ui);
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* --- 1. Boot Screen Overlay --- */
|
||||
#boot-screen {
|
||||
position: fixed;
|
||||
top: 0; left: 0; width: 100%; height: 100%;
|
||||
background-color: #000;
|
||||
color: #ccc;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 14px;
|
||||
padding: 40px;
|
||||
box-sizing: border-box;
|
||||
z-index: 1000;
|
||||
display: flex; /* Flex to keep log at bottom? No, top down is fine */
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.log-line {
|
||||
margin-bottom: 4px;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.log-green { color: var(--success); }
|
||||
.log-red { color: var(--error); }
|
||||
|
||||
.cursor-blink {
|
||||
display: inline-block;
|
||||
width: 8px;
|
||||
height: 15px;
|
||||
background: #ccc;
|
||||
animation: blink 1s step-end infinite;
|
||||
vertical-align: middle;
|
||||
}
|
||||
@keyframes blink { 50% { opacity: 0; } }
|
||||
|
||||
/* --- 2. Main UI (Hidden initially) --- */
|
||||
#main-ui {
|
||||
display: none; /* Hidden until boot finishes */
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
opacity: 0;
|
||||
transition: opacity 1s ease;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: var(--card-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
padding: 32px;
|
||||
box-shadow: 0 8px 24px rgba(0,0,0,0.2);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 { margin: 0 0 10px 0; font-size: 24px; color: var(--text-main); }
|
||||
p { color: var(--text-sub); line-height: 1.5; margin-bottom: 24px; }
|
||||
|
||||
.error-code {
|
||||
display: inline-block;
|
||||
background: rgba(248, 81, 73, 0.15);
|
||||
color: var(--error);
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 12px;
|
||||
margin-bottom: 20px;
|
||||
border: 1px solid rgba(248, 81, 73, 0.4);
|
||||
}
|
||||
|
||||
/* --- Game/Terminal Container --- */
|
||||
.terminal-box {
|
||||
background: #000; /* Deep black for contrast */
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
margin-top: 20px;
|
||||
position: relative;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.terminal-header {
|
||||
background: #21262d;
|
||||
padding: 6px 12px;
|
||||
font-size: 11px;
|
||||
color: var(--text-sub);
|
||||
border-bottom: 1px solid var(--border);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
canvas {
|
||||
display: block;
|
||||
width: 100%; /* Responsive */
|
||||
background: #0d1117;
|
||||
}
|
||||
|
||||
/* --- Vim Status Bar --- */
|
||||
.vim-status {
|
||||
background: var(--accent);
|
||||
color: #fff;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 11px;
|
||||
padding: 4px 10px;
|
||||
display: none; /* Hidden by default for normal users */
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.hint-text {
|
||||
font-size: 12px;
|
||||
color: #444;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="boot-screen">
|
||||
<div id="log-container"></div>
|
||||
<div id="boot-prompt" style="margin-top: 20px; display:none;">
|
||||
[root@server ~]# <span style="color:white">System Halted. Press <strong style="color: #fff; border-bottom: 1px solid #fff;">ENTER</strong> to view logs.</span><span class="cursor-blink"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="main-ui">
|
||||
<div class="card">
|
||||
<h1>Service Temporarily Unavailable</h1>
|
||||
<div class="error-code">HTTP 503 - UPSTREAM_TIMEOUT</div>
|
||||
<p>
|
||||
The server is currently unable to handle the request due to a temporary overload or scheduled maintenance.
|
||||
</p>
|
||||
|
||||
<div class="terminal-box">
|
||||
<div class="terminal-header">
|
||||
<span>root@server: ~/diagnostics</span>
|
||||
<span>/bin/zsh</span>
|
||||
</div>
|
||||
|
||||
<canvas id="gameCanvas" width="540" height="300"></canvas>
|
||||
|
||||
<div class="vim-status" id="vim-bar">
|
||||
<span style="font-weight:bold;">-- INSERT --</span>
|
||||
<span id="coord">10, 10</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hint-text">Waiting for connection...</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
/* ------------------------------------------------
|
||||
1. BOOT SEQUENCE LOGIC
|
||||
------------------------------------------------ */
|
||||
const logContainer = document.getElementById('log-container');
|
||||
const bootPrompt = document.getElementById('boot-prompt');
|
||||
const bootScreen = document.getElementById('boot-screen');
|
||||
const mainUI = document.getElementById('main-ui');
|
||||
|
||||
const logs = [
|
||||
"Initializing kernel...",
|
||||
"[ <span class='log-green'>OK</span> ] Started System Logging Service.",
|
||||
"[ <span class='log-green'>OK</span> ] Mounted /boot/efi.",
|
||||
"[ <span class='log-green'>OK</span> ] Reached target System Initialization.",
|
||||
"[ <span class='log-green'>OK</span> ] Listening on Port 80.",
|
||||
"[ <span class='log-green'>OK</span> ] Listening on Port 443.",
|
||||
"Starting nginx service...",
|
||||
"[ <span class='log-red'>FAILED</span> ] Failed to start Application Server.",
|
||||
"[ <span class='log-red'>ERROR</span> ] Connection refused on 127.0.0.1:8080",
|
||||
"[ <span class='log-red'>CRITICAL</span> ] HTTP 503 Service Unavailable"
|
||||
];
|
||||
|
||||
let lineIndex = 0;
|
||||
|
||||
function addLog() {
|
||||
if (lineIndex < logs.length) {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'log-line';
|
||||
div.innerHTML = logs[lineIndex];
|
||||
logContainer.appendChild(div);
|
||||
lineIndex++;
|
||||
// Random typing speed
|
||||
setTimeout(addLog, Math.random() * 200 + 50);
|
||||
} else {
|
||||
// Done logging, show prompt
|
||||
bootPrompt.style.display = 'block';
|
||||
document.addEventListener('keydown', checkEnter);
|
||||
}
|
||||
}
|
||||
|
||||
function checkEnter(e) {
|
||||
if (e.key === 'Enter') {
|
||||
document.removeEventListener('keydown', checkEnter);
|
||||
bootScreen.style.display = 'none';
|
||||
mainUI.style.display = 'block';
|
||||
|
||||
// Trigger fade in
|
||||
setTimeout(() => {
|
||||
mainUI.style.opacity = '1';
|
||||
startGame(); // Start game ONLY after visible
|
||||
}, 50);
|
||||
}
|
||||
}
|
||||
|
||||
// Start Boot
|
||||
setTimeout(addLog, 500);
|
||||
|
||||
|
||||
/* ------------------------------------------------
|
||||
2. SNAKE GAME LOGIC
|
||||
------------------------------------------------ */
|
||||
const canvas = document.getElementById('gameCanvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
const vimBar = document.getElementById('vim-bar');
|
||||
const coordSpan = document.getElementById('coord');
|
||||
|
||||
// Config
|
||||
const gridSize = 20;
|
||||
let tileCountX = Math.floor(canvas.width / gridSize);
|
||||
let tileCountY = Math.floor(canvas.height / gridSize);
|
||||
|
||||
let snake = [{x: 10, y: 10}];
|
||||
let food = {x: 15, y: 15};
|
||||
let dx = 0;
|
||||
let dy = 0;
|
||||
let score = 0;
|
||||
let gameRunning = false;
|
||||
let gameSpeed = 100; // ms
|
||||
let lastTime = 0;
|
||||
|
||||
// Vim Detection
|
||||
let isVimUser = false;
|
||||
|
||||
function startGame() {
|
||||
// Re-calculate grid in case of weird sizing
|
||||
tileCountX = Math.floor(canvas.width / gridSize);
|
||||
tileCountY = Math.floor(canvas.height / gridSize);
|
||||
|
||||
spawnFood();
|
||||
requestAnimationFrame(gameLoop);
|
||||
}
|
||||
|
||||
function gameLoop(currentTime) {
|
||||
window.requestAnimationFrame(gameLoop);
|
||||
|
||||
const secondsSinceLastRender = (currentTime - lastTime) / 1000;
|
||||
if (secondsSinceLastRender < (gameSpeed / 1000)) return;
|
||||
|
||||
lastTime = currentTime;
|
||||
|
||||
update();
|
||||
draw();
|
||||
}
|
||||
|
||||
function update() {
|
||||
if (!gameRunning) return;
|
||||
|
||||
const head = { x: snake[0].x + dx, y: snake[0].y + dy };
|
||||
|
||||
// Wrap logic (Toroidal world)
|
||||
if (head.x < 0) head.x = tileCountX - 1;
|
||||
if (head.x >= tileCountX) head.x = 0;
|
||||
if (head.y < 0) head.y = tileCountY - 1;
|
||||
if (head.y >= tileCountY) head.y = 0;
|
||||
|
||||
// Self Collision
|
||||
for (let i = 0; i < snake.length; i++) {
|
||||
if (head.x === snake[i].x && head.y === snake[i].y) {
|
||||
resetGame();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
snake.unshift(head);
|
||||
|
||||
// Eat Food
|
||||
if (head.x === food.x && head.y === food.y) {
|
||||
score++;
|
||||
spawnFood();
|
||||
// Speed up slightly
|
||||
if(gameSpeed > 50) gameSpeed -= 2;
|
||||
} else {
|
||||
snake.pop();
|
||||
}
|
||||
|
||||
// Update Vim Coords
|
||||
if (isVimUser) {
|
||||
coordSpan.innerText = `${head.y + 1}, ${head.x + 1}`;
|
||||
}
|
||||
}
|
||||
|
||||
function draw() {
|
||||
// Clear
|
||||
ctx.fillStyle = '#0d1117';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Draw Snake
|
||||
ctx.fillStyle = '#3fb950'; // GitHub Green
|
||||
snake.forEach((part, index) => {
|
||||
if (index === 0) ctx.fillStyle = '#7ee787'; // Lighter head
|
||||
else ctx.fillStyle = '#3fb950';
|
||||
|
||||
ctx.fillRect(part.x * gridSize + 1, part.y * gridSize + 1, gridSize - 2, gridSize - 2);
|
||||
});
|
||||
|
||||
// Draw Food
|
||||
ctx.fillStyle = '#f85149'; // GitHub Red
|
||||
ctx.fillRect(food.x * gridSize + 1, food.y * gridSize + 1, gridSize - 2, gridSize - 2);
|
||||
|
||||
// Draw "Paused" Text if not running
|
||||
if (!gameRunning) {
|
||||
ctx.fillStyle = '#8b949e';
|
||||
ctx.font = '14px monospace';
|
||||
ctx.fillText("Press Arrow Keys to Start", 20, 30);
|
||||
}
|
||||
}
|
||||
|
||||
function spawnFood() {
|
||||
food.x = Math.floor(Math.random() * tileCountX);
|
||||
food.y = Math.floor(Math.random() * tileCountY);
|
||||
// Ensure food doesn't spawn on snake
|
||||
snake.forEach(part => {
|
||||
if(part.x === food.x && part.y === food.y) spawnFood();
|
||||
});
|
||||
}
|
||||
|
||||
function resetGame() {
|
||||
snake = [{x: 10, y: 10}];
|
||||
dx = 0; dy = 0;
|
||||
gameRunning = false;
|
||||
gameSpeed = 100;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------
|
||||
3. CONTROLS
|
||||
------------------------------------------------ */
|
||||
document.addEventListener('keydown', (e) => {
|
||||
// Only capture keys if Main UI is visible
|
||||
if (mainUI.style.display === 'none') return;
|
||||
|
||||
const keys = ["ArrowUp","ArrowDown","ArrowLeft","ArrowRight","h","j","k","l","w","a","s","d"];
|
||||
if (keys.includes(e.key)) {
|
||||
e.preventDefault(); // Stop scrolling
|
||||
if (!gameRunning) gameRunning = true;
|
||||
}
|
||||
|
||||
// Check for Vim usage
|
||||
if (["h","j","k","l"].includes(e.key)) {
|
||||
isVimUser = true;
|
||||
vimBar.style.display = 'flex'; // REVEAL THE NERD UI
|
||||
}
|
||||
|
||||
const goingUp = dy === -1;
|
||||
const goingDown = dy === 1;
|
||||
const goingRight = dx === 1;
|
||||
const goingLeft = dx === -1;
|
||||
|
||||
switch(e.key) {
|
||||
// Standard
|
||||
case 'ArrowLeft': case 'a': if (!goingRight) { dx = -1; dy = 0; } break;
|
||||
case 'ArrowUp': case 'w': if (!goingDown) { dx = 0; dy = -1; } break;
|
||||
case 'ArrowRight': case 'd': if (!goingLeft) { dx = 1; dy = 0; } break;
|
||||
case 'ArrowDown': case 's': if (!goingUp) { dx = 0; dy = 1; } break;
|
||||
|
||||
// Vim
|
||||
case 'h': if (!goingRight) { dx = -1; dy = 0; } break;
|
||||
case 'j': if (!goingUp) { dx = 0; dy = 1; } break; // Down
|
||||
case 'k': if (!goingDown) { dx = 0; dy = -1; } break; // Up
|
||||
case 'l': if (!goingLeft) { dx = 1; dy = 0; } break;
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue