Spaces:
Runtime error
Runtime error
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Simulator</title> | |
</head> | |
<body> | |
<canvas id="displayCanvas" width="512" height="512"></canvas> | |
<script> | |
const canvas = document.getElementById('displayCanvas'); | |
const ctx = canvas.getContext('2d'); | |
let socket; | |
let isConnected = false; | |
let reconnectAttempts = 0; | |
const MAX_RECONNECT_DELAY = 30000; // Maximum delay between reconnection attempts (30 seconds) | |
let isProcessing = false; | |
function connect() { | |
socket = new WebSocket(`wss://${window.location.host}/ws`); | |
socket.onopen = function(event) { | |
console.log("WebSocket connection established"); | |
isConnected = true; | |
reconnectAttempts = 0; | |
//startHeartbeat(); | |
}; | |
socket.onclose = function(event) { | |
console.log("WebSocket connection closed. Attempting to reconnect..."); | |
isConnected = false; | |
clearInterval(heartbeatInterval); | |
scheduleReconnection(); | |
}; | |
socket.onerror = function(error) { | |
console.error("WebSocket error:", error); | |
}; | |
socket.onmessage = function (event) { | |
const data = JSON.parse(event.data); | |
if (data.type === "heartbeat_response") { | |
console.log("Heartbeat response received"); | |
} else if (data.image) { | |
const img = new Image(); | |
img.onload = function() { | |
ctx.drawImage(img, 0, 0, canvas.width, canvas.height); | |
isProcessing = false; // Allow new inputs after drawing the image | |
}; | |
img.src = 'data:image/png;base64,' + data.image; | |
} | |
}; | |
} | |
function scheduleReconnection() { | |
const delay = Math.min(1000 * Math.pow(2, reconnectAttempts), MAX_RECONNECT_DELAY); | |
console.log(`Scheduling reconnection in ${delay}ms`); | |
setTimeout(connect, delay); | |
reconnectAttempts++; | |
} | |
let heartbeatInterval; | |
function startHeartbeat() { | |
heartbeatInterval = setInterval(() => { | |
if (isConnected) { | |
try { | |
socket.send(JSON.stringify({ type: "heartbeat" })); | |
console.error("finished sending heartbeat:", error); | |
} catch (error) { | |
console.error("Error sending heartbeat:", error); | |
} | |
} | |
}, 1000); // Send heartbeat every 15 seconds | |
} | |
// Initial connection | |
connect(); | |
let lastSentPosition = null; | |
let lastSentTime = 0; | |
const SEND_INTERVAL = 50; // Send updates every 50ms | |
function sendMousePosition(x, y, forceUpdate = false) { | |
const currentTime = Date.now(); | |
if (isConnected && !isProcessing && (forceUpdate || !lastSentPosition || currentTime - lastSentTime >= SEND_INTERVAL)) { | |
try { | |
socket.send(JSON.stringify({ | |
"action_type": "move", | |
"mouse_position": [x, y] | |
})); | |
lastSentPosition = { x, y }; | |
lastSentTime = currentTime; | |
} catch (error) { | |
console.error("Error sending mouse position:", error); | |
} | |
} | |
} | |
// Capture mouse movements and clicks | |
canvas.addEventListener("mousemove", function (event) { | |
if (!isConnected || isProcessing) return; | |
let rect = canvas.getBoundingClientRect(); | |
let x = event.clientX - rect.left; | |
let y = event.clientY - rect.top; | |
// Client-side prediction | |
ctx.beginPath(); | |
ctx.moveTo(lastSentPosition ? lastSentPosition.x : x, lastSentPosition ? lastSentPosition.y : y); | |
ctx.lineTo(x, y); | |
ctx.stroke(); | |
sendMousePosition(x, y); | |
}); | |
canvas.addEventListener("click", function (event) { | |
if (!isConnected || isProcessing) return; | |
let rect = canvas.getBoundingClientRect(); | |
let x = event.clientX - rect.left; | |
let y = event.clientY - rect.top; | |
isProcessing = false; | |
try { | |
socket.send(JSON.stringify({ | |
"action_type": "left_click", | |
"mouse_position": [x, y] | |
})); | |
} catch (error) { | |
console.error("Error sending click action:", error); | |
} | |
}); | |
// Graceful disconnection | |
window.addEventListener('beforeunload', function (e) { | |
if (isConnected) { | |
try { | |
//socket.send(JSON.stringify({ type: "disconnect" })); | |
//socket.close(); | |
} catch (error) { | |
console.error("Error during disconnection:", error); | |
} | |
} | |
}); | |
</script> | |
</body> | |
</html> |