From 47715defbcc27061c897f70332b4f80883eceacf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Mar 2026 05:50:55 +0000 Subject: [PATCH 1/2] Initial plan From 1b56d974b5b2a49ef2b6e2233d68c09e762572aa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Mar 2026 05:55:56 +0000 Subject: [PATCH 2/2] Add localStorage persistence for robot work in home.html Co-authored-by: A1L13N <193832434+A1L13N@users.noreply.github.com> --- home.html | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/home.html b/home.html index 18ca614..52582d6 100644 --- a/home.html +++ b/home.html @@ -243,6 +243,8 @@ // ========== BLOCKS ========== let blocks = []; + const STORAGE_KEY = 'robotics_playground_state'; + let lastSaveTime = 0; function generateBlocks() { blocks = []; @@ -301,6 +303,7 @@ } robot.holdingBlock = null; showMsg('Dropped!'); + saveState(); } else { // PICK for (let b of blocks) { @@ -312,6 +315,7 @@ b.held = true; robot.holdingBlock = b.id; showMsg('Grabbed! SPACE to drop'); + saveState(); break; } } @@ -355,6 +359,7 @@ } updatePartsList(); showMsg(`${type.charAt(0).toUpperCase() + type.slice(1)} added!`); + saveState(); } function removePart(type) { @@ -396,6 +401,7 @@ updatePartsList(); showMsg(`${type.charAt(0).toUpperCase() + type.slice(1)} removed!`); + saveState(); } function resetAll() { @@ -422,6 +428,7 @@ document.getElementById('detection-info').innerHTML = '
LiDAR not installed
'; document.getElementById('detection-indicator').classList.add('hidden'); updatePartsList(); + localStorage.removeItem(STORAGE_KEY); } function updatePartsList() { @@ -432,15 +439,18 @@ function updatePower() { motorPower = +document.getElementById('power-slider').value; document.getElementById('power-val').textContent = motorPower + '%'; + saveState(); } function updateTurn() { turnSpeed = +document.getElementById('turn-slider').value; document.getElementById('turn-val').textContent = turnSpeed + '°'; + saveState(); } function updateColor() { robot.color = document.getElementById('color-picker').value; + saveState(); } // ========== GAME LOOP ========== @@ -731,12 +741,18 @@ function loop() { update(); render(); + const now = Date.now(); + if (robot.parts.chassis && now - lastSaveTime > 1000) { + saveState(); + lastSaveTime = now; + } requestAnimationFrame(loop); } // ========== LIDAR DETECTION ========== let lastDetectedId = null; + loadState(); loop(); function segmentsIntersect(x1, y1, x2, y2, x3, y3, x4, y4) { @@ -832,6 +848,79 @@ indicator.classList.add('hidden'); } } + + // ========== STATE PERSISTENCE ========== + function saveState() { + try { + const state = { + robot: { + x: robot.x, + y: robot.y, + angle: robot.angle, + color: robot.color, + holdingBlock: robot.holdingBlock, + parts: { ...robot.parts }, + }, + motorPower, + turnSpeed, + blocks: blocks.map(b => ({ ...b })), + }; + localStorage.setItem(STORAGE_KEY, JSON.stringify(state)); + } catch (e) { + // localStorage may be unavailable + } + } + + function loadState() { + try { + const saved = localStorage.getItem(STORAGE_KEY); + if (!saved) return; + const state = JSON.parse(saved); + if (!state) return; + + if (state.robot) { + robot.x = typeof state.robot.x === 'number' ? Math.max(35, Math.min(canvas.width - 35, state.robot.x)) : canvas.width / 2; + robot.y = typeof state.robot.y === 'number' ? Math.max(35, Math.min(canvas.height - 35, state.robot.y)) : canvas.height / 2; + robot.angle = typeof state.robot.angle === 'number' ? state.robot.angle : 0; + robot.color = state.robot.color || '#0d9488'; + robot.holdingBlock = state.robot.holdingBlock !== undefined ? state.robot.holdingBlock : null; + if (state.robot.parts) { + robot.parts = { ...robot.parts, ...state.robot.parts }; + } + } + + if (typeof state.motorPower === 'number') { + motorPower = state.motorPower; + document.getElementById('power-slider').value = motorPower; + document.getElementById('power-val').textContent = motorPower + '%'; + } + if (typeof state.turnSpeed === 'number') { + turnSpeed = state.turnSpeed; + document.getElementById('turn-slider').value = turnSpeed; + document.getElementById('turn-val').textContent = turnSpeed + '°'; + } + + if (Array.isArray(state.blocks) && state.blocks.length > 0) { + blocks = state.blocks; + document.getElementById('block-count').textContent = blocks.length; + } + + document.getElementById('color-picker').value = robot.color; + + if (robot.parts.chassis) { + document.getElementById('start-prompt').classList.add('hidden'); + } + if (robot.parts.camera) { + document.getElementById('camera-feed').classList.remove('hidden'); + } + if (robot.parts.lidar) { + updateDetectionUI(null); + } + updatePartsList(); + } catch (e) { + // Corrupted state, ignore + } + }