Skip to content

Instantly share code, notes, and snippets.

@jordangarcia
Created June 19, 2025 02:33
Show Gist options
  • Save jordangarcia/eab9eaadb692f0300890fdd3604dab38 to your computer and use it in GitHub Desktop.
Save jordangarcia/eab9eaadb692f0300890fdd3604dab38 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>80x80 Pixel Weight Physics Simulation</title>
<style>
body {
margin: 0;
padding: 20px;
background: #1a1a1a;
color: white;
font-family: 'Courier New', monospace;
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
}
.container {
background: #2a2a2a;
border-radius: 15px;
padding: 30px;
box-shadow: 0 10px 30px rgba(0,0,0,0.5);
max-width: 900px;
width: 100%;
}
.title {
text-align: center;
font-size: 24px;
margin-bottom: 20px;
color: #4CAF50;
}
.input-section {
background: #3a3a3a;
padding: 20px;
border-radius: 10px;
margin-bottom: 20px;
}
.pixel-grid {
display: grid;
grid-template-columns: repeat(80, 4px);
grid-template-rows: repeat(80, 4px);
gap: 0.5px;
background: #666;
padding: 5px;
border-radius: 5px;
margin: 10px auto;
width: fit-content;
max-height: 400px;
overflow: auto;
}
.pixel {
width: 4px;
height: 4px;
background: #000;
cursor: pointer;
transition: background 0.1s;
}
.pixel.light {
background: #fff;
}
.simulation-area {
position: relative;
height: 400px;
background: linear-gradient(135deg, #333, #555);
border-radius: 10px;
overflow: hidden;
margin: 20px 0;
border: 2px solid #666;
}
.ground {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 20px;
background: #8B4513;
border-top: 2px solid #A0522D;
}
.fulcrum {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 0;
border-left: 20px solid transparent;
border-right: 20px solid transparent;
border-bottom: 30px solid #666;
}
.balance-beam {
position: absolute;
bottom: 50px;
left: 50%;
width: 300px;
height: 8px;
background: #888;
transform-origin: center;
transform: translateX(-50%);
border-radius: 4px;
transition: transform 0.3s ease;
}
.image-container {
position: absolute;
bottom: 58px;
left: 50%;
transform: translateX(-50%);
width: 128px;
height: 128px;
background: #f0f0f0;
border-radius: 15px;
display: flex;
align-items: center;
justify-content: center;
transition: transform 0.3s ease;
border: 2px solid #ccc;
padding: 10px;
}
.preview-grid {
display: grid;
grid-template-columns: repeat(80, 1.5px);
grid-template-rows: repeat(80, 1.5px);
gap: 0;
width: 120px;
height: 120px;
}
.preview-pixel {
width: 1.5px;
height: 1.5px;
background: #000;
}
.preview-pixel.light {
background: #fff;
}
.controls {
display: flex;
flex-wrap: wrap;
gap: 10px;
justify-content: center;
margin: 20px 0;
}
.btn {
background: #4CAF50;
color: white;
border: none;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
font-size: 14px;
transition: background 0.3s;
}
.btn:hover {
background: #45a049;
}
.btn.secondary {
background: #666;
}
.btn.secondary:hover {
background: #777;
}
.stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 15px;
margin: 20px 0;
}
.stat-box {
background: #3a3a3a;
padding: 15px;
border-radius: 8px;
border-left: 4px solid #4CAF50;
}
.stat-label {
font-size: 12px;
color: #aaa;
margin-bottom: 5px;
}
.stat-value {
font-size: 18px;
font-weight: bold;
color: #4CAF50;
}
.result {
font-size: 18px;
font-weight: bold;
text-align: center;
padding: 15px;
border-radius: 8px;
margin: 10px 0;
}
.left-heavy { background: #ff4444; }
.right-heavy { background: #4444ff; }
.balanced { background: #44ff44; color: black; }
.json-status {
padding: 10px;
border-radius: 5px;
margin-top: 10px;
font-size: 14px;
}
.json-success {
background: #2d5a2d;
color: #90ee90;
border: 1px solid #4CAF50;
}
.json-error {
background: #5a2d2d;
color: #ff9090;
border: 1px solid #ff4444;
}
.json-examples {
background: #3a3a3a;
padding: 15px;
border-radius: 5px;
margin-top: 10px;
font-family: monospace;
font-size: 12px;
max-height: 200px;
overflow-y: auto;
}
.weight-visualization {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
margin: 20px 0;
}
.weight-side {
background: #3a3a3a;
padding: 15px;
border-radius: 8px;
text-align: center;
}
.weight-bar {
height: 20px;
background: #666;
border-radius: 10px;
margin: 10px 0;
overflow: hidden;
}
.weight-fill {
height: 100%;
transition: width 0.3s ease;
}
.left-fill { background: #ff4444; }
.right-fill { background: #4444ff; }
</style>
</head>
<body>
<div class="container">
<div class="title">🎯 80Γ—80 Pixel Weight Physics Simulation</div>
<div class="input-section">
<h3>🎨 Pixel Editor</h3>
<p>Click pixels to toggle between black (1g) and white (0g). Create any pattern!</p>
<div class="pixel-grid" id="pixelGrid"></div>
<div class="controls">
<button class="btn secondary" onclick="clearGrid()">πŸ—‘οΈ Clear All</button>
<button class="btn secondary" onclick="shiftLeft()">⬅️ Shift Left</button>
<button class="btn secondary" onclick="shiftRight()">➑️ Shift Right</button>
</div>
<div style="margin-top: 20px;">
<h4>πŸ“‹ JSON Array Input</h4>
<p>Paste a 2D JSON array: 80 rows Γ— 80 columns. Format: [[0,1,0,...],[1,0,1,...],...] (0=black/1g, 1=white/0g)</p>
<textarea id="jsonInput" placeholder="[[0,0,0,1,0,0,0,0,0,0,1,1,1,0,0,0,...],[0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,...],...]"
style="width: 100%; height: 120px; background: #4a4a4a; color: white; border: 1px solid #666; border-radius: 5px; padding: 10px; font-family: monospace; font-size: 12px; resize: vertical;"></textarea>
<div style="display: flex; gap: 10px; margin-top: 10px;">
<button class="btn" onclick="loadFromJSON()">πŸ“₯ Load from JSON</button>
<button class="btn secondary" onclick="exportToJSON()">πŸ“€ Export to JSON</button>
</div>
<div id="jsonStatus" style="margin-top: 10px; padding: 10px; border-radius: 5px; display: none;"></div>
</div>
</div>
<div class="simulation-area">
<div class="ground"></div>
<div class="fulcrum"></div>
<div class="balance-beam" id="balanceBeam"></div>
<div class="image-container" id="imageContainer">
<div class="preview-grid" id="previewGrid"></div>
</div>
</div>
<div class="controls">
<button class="btn" onclick="startSimulation()">🎯 Run Physics Simulation</button>
<button class="btn secondary" onclick="resetSimulation()">πŸ”„ Reset Physics</button>
</div>
<div class="weight-visualization">
<div class="weight-side">
<h4>⬅️ LEFT SIDE</h4>
<div class="weight-bar">
<div class="weight-fill left-fill" id="leftBar"></div>
</div>
<div id="leftWeight">0g</div>
</div>
<div class="weight-side">
<h4>RIGHT SIDE ➑️</h4>
<div class="weight-bar">
<div class="weight-fill right-fill" id="rightBar"></div>
</div>
<div id="rightWeight">0g</div>
</div>
</div>
<div class="stats">
<div class="stat-box">
<div class="stat-label">TOTAL BLACK PIXELS</div>
<div class="stat-value" id="blackPixels">6400</div>
</div>
<div class="stat-box">
<div class="stat-label">TOTAL WHITE PIXELS</div>
<div class="stat-value" id="whitePixels">0</div>
</div>
<div class="stat-box">
<div class="stat-label">TOTAL WEIGHT</div>
<div class="stat-value" id="totalWeight">6400g</div>
</div>
<div class="stat-box">
<div class="stat-label">BALANCE DIFFERENCE</div>
<div class="stat-value" id="weightDiff">0g</div>
</div>
<div class="stat-box">
<div class="stat-label">CENTER OF MASS</div>
<div class="stat-value" id="centerOfMass">40.0</div>
</div>
</div>
<div id="result" class="result" style="display: none;"></div>
<div class="analysis">
<h3>πŸ”¬ Physics Analysis</h3>
<p><strong>Simulation Method:</strong> Each pixel in the 32Γ—32 grid represents weight. The simulation calculates the center of mass and determines tipping direction.</p>
<p><strong>Weight System:</strong></p>
<ul>
<li>Dark pixels = 1 gram each</li>
<li>Light pixels = 0.1 gram each</li>
<li>Total possible weight: 5760g (all dark) to 640g (all light)</li>
<li>Center line divides at pixel column 40</li>
</ul>
<p><strong>Physics Calculation:</strong></p>
<ul>
<li>Weight Γ— Distance from center = Torque</li>
<li>Left torque vs Right torque determines tipping</li>
<li>Center of mass calculated as weighted average position</li>
</ul>
</div>
</div>
<script>
// 80x80 pixel array (0 = black/1g, 1 = white/0g)
let pixelArray = new Array(80).fill(0).map(() => new Array(80).fill(0));
let simulationData = {
leftWeight: 0,
rightWeight: 0,
totalWeight: 0,
centerOfMass: 40,
isRunning: false
};
function initializeGrid() {
const grid = document.getElementById('pixelGrid');
const previewGrid = document.getElementById('previewGrid');
grid.innerHTML = '';
previewGrid.innerHTML = '';
for (let row = 0; row < 80; row++) {
for (let col = 0; col < 80; col++) {
// Main grid pixel
const pixel = document.createElement('div');
pixel.className = 'pixel';
pixel.dataset.row = row;
pixel.dataset.col = col;
pixel.onclick = () => togglePixel(row, col);
grid.appendChild(pixel);
// Preview grid pixel
const previewPixel = document.createElement('div');
previewPixel.className = 'preview-pixel';
previewPixel.dataset.row = row;
previewPixel.dataset.col = col;
previewGrid.appendChild(previewPixel);
}
}
updateDisplay();
}
function togglePixel(row, col) {
pixelArray[row][col] = pixelArray[row][col] === 0 ? 1 : 0;
updatePixelDisplay();
calculateWeightDistribution();
updateDisplay();
}
function updatePixelDisplay() {
const pixels = document.querySelectorAll('.pixel');
const previewPixels = document.querySelectorAll('.preview-pixel');
pixels.forEach(pixel => {
const row = parseInt(pixel.dataset.row);
const col = parseInt(pixel.dataset.col);
pixel.className = pixelArray[row][col] === 1 ? 'pixel light' : 'pixel';
});
previewPixels.forEach(pixel => {
const row = parseInt(pixel.dataset.row);
const col = parseInt(pixel.dataset.col);
pixel.className = pixelArray[row][col] === 1 ? 'preview-pixel light' : 'preview-pixel';
});
}
function calculateWeightDistribution() {
let leftWeight = 0;
let rightWeight = 0;
let totalMoment = 0;
let totalWeight = 0;
let blackPixels = 0;
let whitePixels = 0;
for (let row = 0; row < 80; row++) {
for (let col = 0; col < 80; col++) {
const pixelWeight = pixelArray[row][col] === 0 ? 1.0 : 0.0; // 0=black=1g, 1=white=0g
const distanceFromCenter = col - 39.5; // Center is at 39.5
totalWeight += pixelWeight;
totalMoment += pixelWeight * col;
if (pixelArray[row][col] === 0) {
blackPixels++;
} else {
whitePixels++;
}
if (col < 40) {
leftWeight += pixelWeight;
} else {
rightWeight += pixelWeight;
}
}
}
simulationData.leftWeight = leftWeight;
simulationData.rightWeight = rightWeight;
simulationData.totalWeight = totalWeight;
simulationData.centerOfMass = totalWeight > 0 ? totalMoment / totalWeight : 40;
simulationData.blackPixels = blackPixels;
simulationData.whitePixels = whitePixels;
return simulationData;
}
function updateDisplay() {
const data = simulationData;
document.getElementById('leftWeight').textContent = data.leftWeight.toFixed(1) + 'g';
document.getElementById('rightWeight').textContent = data.rightWeight.toFixed(1) + 'g';
document.getElementById('totalWeight').textContent = data.totalWeight.toFixed(1) + 'g';
document.getElementById('weightDiff').textContent = Math.abs(data.rightWeight - data.leftWeight).toFixed(1) + 'g';
document.getElementById('centerOfMass').textContent = data.centerOfMass.toFixed(1);
document.getElementById('blackPixels').textContent = data.blackPixels || 0;
document.getElementById('whitePixels').textContent = data.whitePixels || 0;
// Update weight bars
const maxWeight = Math.max(data.leftWeight, data.rightWeight);
const leftPercent = maxWeight > 0 ? (data.leftWeight / maxWeight) * 100 : 0;
const rightPercent = maxWeight > 0 ? (data.rightWeight / maxWeight) * 100 : 0;
document.getElementById('leftBar').style.width = leftPercent + '%';
document.getElementById('rightBar').style.width = rightPercent + '%';
}
function startSimulation() {
if (simulationData.isRunning) return;
calculateWeightDistribution();
simulationData.isRunning = true;
const data = simulationData;
const weightDiff = data.rightWeight - data.leftWeight;
const centerOffset = data.centerOfMass - 40;
// Calculate tilt angle based on center of mass offset
const maxTilt = 20; // degrees
const tiltAngle = centerOffset * 2; // Amplify for visibility
const balanceBeam = document.getElementById('balanceBeam');
const imageContainer = document.getElementById('imageContainer');
balanceBeam.style.transform = `translateX(-50%) rotate(${tiltAngle}deg)`;
imageContainer.style.transform = `translateX(-50%) rotate(${tiltAngle}deg)`;
// Show result
const resultDiv = document.getElementById('result');
resultDiv.style.display = 'block';
if (Math.abs(centerOffset) < 0.5) {
resultDiv.textContent = 'βš–οΈ PERFECTLY BALANCED! Center of mass is at the center.';
resultDiv.className = 'result balanced';
} else if (centerOffset < 0) {
resultDiv.textContent = `⬅️ TIPS LEFT! Center of mass at ${data.centerOfMass.toFixed(1)} (${Math.abs(centerOffset).toFixed(1)} pixels left of center)`;
resultDiv.className = 'result left-heavy';
} else {
resultDiv.textContent = `➑️ TIPS RIGHT! Center of mass at ${data.centerOfMass.toFixed(1)} (${centerOffset.toFixed(1)} pixels right of center)`;
resultDiv.className = 'result right-heavy';
}
setTimeout(() => {
simulationData.isRunning = false;
}, 500);
}
function resetSimulation() {
document.getElementById('balanceBeam').style.transform = 'translateX(-50%) rotate(0deg)';
document.getElementById('imageContainer').style.transform = 'translateX(-50%) rotate(0deg)';
document.getElementById('result').style.display = 'none';
}
function shiftLeft() {
const newPixelArray = new Array(80).fill(0).map(() => new Array(80).fill(0));
for (let row = 0; row < 80; row++) {
for (let col = 0; col < 80; col++) {
if (col < 79) {
// Shift everything left by 1, fill rightmost column with white (1)
newPixelArray[row][col] = pixelArray[row][col + 1];
} else {
// Fill the rightmost column with white (1) - weightless
newPixelArray[row][col] = 1;
}
}
}
pixelArray = newPixelArray;
updatePixelDisplay();
calculateWeightDistribution();
updateDisplay();
resetSimulation();
}
function shiftRight() {
const newPixelArray = new Array(80).fill(0).map(() => new Array(80).fill(0));
for (let row = 0; row < 80; row++) {
for (let col = 0; col < 80; col++) {
if (col > 0) {
// Shift everything right by 1, fill leftmost column with white (1)
newPixelArray[row][col] = pixelArray[row][col - 1];
} else {
// Fill the leftmost column with white (1) - weightless
newPixelArray[row][col] = 1;
}
}
}
pixelArray = newPixelArray;
updatePixelDisplay();
calculateWeightDistribution();
updateDisplay();
resetSimulation();
}
function clearGrid() {
pixelArray = new Array(80).fill(0).map(() => new Array(80).fill(0));
updatePixelDisplay();
calculateWeightDistribution();
updateDisplay();
resetSimulation();
}
function fillRandom() {
for (let row = 0; row < 80; row++) {
for (let col = 0; col < 80; col++) {
pixelArray[row][col] = Math.random() < 0.3 ? 1 : 0;
}
}
updatePixelDisplay();
calculateWeightDistribution();
updateDisplay();
resetSimulation();
}
function loadSampleG() {
clearGrid();
// Create a larger G pattern for 80x80 grid (black pixels = weight)
const gPattern = [
// Horizontal top line
[20,20],[20,21],[20,22],[20,23],[20,24],[20,25],[20,26],[20,27],[20,28],[20,29],[20,30],[20,31],[20,32],[20,33],[20,34],[20,35],[20,36],[20,37],[20,38],[20,39],
// Left vertical line
[21,20],[22,20],[23,20],[24,20],[25,20],[26,20],[27,20],[28,20],[29,20],[30,20],[31,20],[32,20],[33,20],[34,20],[35,20],[36,20],[37,20],[38,20],[39,20],[40,20],
[41,20],[42,20],[43,20],[44,20],[45,20],[46,20],[47,20],[48,20],[49,20],[50,20],[51,20],[52,20],[53,20],[54,20],[55,20],[56,20],[57,20],[58,20],[59,20],
// Middle horizontal line
[40,20],[40,21],[40,22],[40,23],[40,24],[40,25],[40,26],[40,27],[40,28],[40,29],[40,30],[40,31],[40,32],[40,33],[40,34],
// Right vertical line (middle to bottom)
[41,34],[42,34],[43,34],[44,34],[45,34],[46,34],[47,34],[48,34],[49,34],[50,34],[51,34],[52,34],[53,34],[54,34],[55,34],[56,34],[57,34],[58,34],[59,34],
// Bottom horizontal line
[59,20],[59,21],[59,22],[59,23],[59,24],[59,25],[59,26],[59,27],[59,28],[59,29],[59,30],[59,31],[59,32],[59,33],[59,34],[59,35],[59,36],[59,37],[59,38],[59,39]
];
// Start with all white (weightless)
for (let row = 0; row < 80; row++) {
for (let col = 0; col < 80; col++) {
pixelArray[row][col] = 1; // 1 = white = 0g
}
}
// Add black G pattern (weight)
gPattern.forEach(([row, col]) => {
if (row < 80 && col < 80) {
pixelArray[row][col] = 0; // 0 = black = 1g
}
});
// Add a larger dot below
for (let row = 65; row < 70; row++) {
for (let col = 27; col < 32; col++) {
pixelArray[row][col] = 0; // 0 = black = 1g
}
}
updatePixelDisplay();
calculateWeightDistribution();
updateDisplay();
resetSimulation();
}
function loadSamplePattern() {
clearGrid();
// Start with all white (weightless)
for (let row = 0; row < 80; row++) {
for (let col = 0; col < 80; col++) {
pixelArray[row][col] = 1; // 1 = white = 0g
}
}
// Create an interesting asymmetric pattern for 80x80 (add black weight)
for (let row = 10; row < 70; row++) {
for (let col = 10; col < 70; col++) {
if ((row + col) % 5 === 0 && col > 40) {
pixelArray[row][col] = 0; // 0 = black = 1g
}
if (row === 40 && col < 30) {
pixelArray[row][col] = 0; // 0 = black = 1g
}
if (col === 20 && row > 50) {
pixelArray[row][col] = 0; // 0 = black = 1g
}
}
}
updatePixelDisplay();
calculateWeightDistribution();
updateDisplay();
resetSimulation();
}
function loadFromJSON() {
const jsonInput = document.getElementById('jsonInput');
const statusDiv = document.getElementById('jsonStatus');
try {
const input = jsonInput.value.trim();
if (!input) {
showStatus('Please enter a JSON array', 'error');
return;
}
let pixelData = JSON.parse(input);
// Validate the data - should be 2D array
if (!Array.isArray(pixelData)) {
showStatus('Input must be an array', 'error');
return;
}
if (pixelData.length !== 80) {
showStatus(`Array must have exactly 80 rows. Found ${pixelData.length} rows.`, 'error');
return;
}
// Validate each row
for (let row = 0; row < 80; row++) {
if (!Array.isArray(pixelData[row])) {
showStatus(`Row ${row} must be an array`, 'error');
return;
}
if (pixelData[row].length !== 80) {
showStatus(`Row ${row} must have exactly 80 elements. Found ${pixelData[row].length} elements.`, 'error');
return;
}
// Validate each element in this row
for (let col = 0; col < 80; col++) {
if (pixelData[row][col] !== 0 && pixelData[row][col] !== 1) {
showStatus(`Element at row ${row}, column ${col} must be 0 or 1. Found: ${pixelData[row][col]}`, 'error');
return;
}
}
}
// Data is valid, update the pixel array
pixelArray = pixelData;
updatePixelDisplay();
calculateWeightDistribution();
updateDisplay();
resetSimulation();
showStatus('βœ… Successfully loaded 2D pixel pattern! (0=black/1g, 1=white/0g)', 'success');
} catch (error) {
showStatus(`JSON Parse Error: ${error.message}`, 'error');
}
}
function exportToJSON() {
// Export the 2D array directly
const jsonString = JSON.stringify(pixelArray, null, 2);
document.getElementById('jsonInput').value = jsonString;
showStatus('βœ… Current pattern exported as 2D JSON array (0=black/1g, 1=white/0g)', 'success');
}
function showJSONExamples() {
const statusDiv = document.getElementById('jsonStatus');
// Create example patterns as 2D arrays
const emptyPattern = new Array(80).fill(0).map(() => new Array(80).fill(0));
const solidPattern = new Array(80).fill(0).map(() => new Array(80).fill(1));
const checkerboard = new Array(80).fill(0).map((_, row) =>
new Array(80).fill(0).map((_, col) => (row + col) % 2)
);
const verticalSplit = new Array(80).fill(0).map(() =>
new Array(80).fill(0).map((_, col) => col < 40 ? 1 : 0)
);
const horizontalSplit = new Array(80).fill(0).map((_, row) =>
new Array(80).fill(0).map(() => row < 40 ? 1 : 0)
);
const examples = `
<strong>πŸ“– 2D JSON Array Examples:</strong>
<strong>1. All Light (empty pattern):</strong>
${JSON.stringify(emptyPattern).substring(0, 100)}...
<strong>2. All Dark (solid pattern):</strong>
${JSON.stringify(solidPattern).substring(0, 100)}...
<strong>3. Checkerboard Pattern:</strong>
${JSON.stringify(checkerboard).substring(0, 100)}...
<strong>4. Vertical Split (left dark, right light):</strong>
${JSON.stringify(verticalSplit).substring(0, 100)}...
<strong>5. Horizontal Split (top dark, bottom light):</strong>
${JSON.stringify(horizontalSplit).substring(0, 100)}...
<strong>6. Simple Cross Pattern:</strong>
${JSON.stringify(new Array(80).fill(0).map((_, row) =>
new Array(80).fill(0).map((_, col) => (row === 40 || col === 40) ? 1 : 0)
)).substring(0, 100)}...
<strong>Format:</strong> Array of 80 arrays, each containing 80 values (0 or 1)
<strong>Structure:</strong> [row0, row1, row2, ..., row79]
<strong>Each row:</strong> [col0, col1, col2, ..., col79]
<strong>Example structure:</strong>
[
[0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,...],
[0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,...],
...
]
`;
statusDiv.innerHTML = examples;
statusDiv.className = 'json-status json-examples';
statusDiv.style.display = 'block';
}
function showStatus(message, type) {
const statusDiv = document.getElementById('jsonStatus');
statusDiv.textContent = message;
statusDiv.className = `json-status json-${type}`;
statusDiv.style.display = 'block';
if (type === 'success') {
setTimeout(() => {
statusDiv.style.display = 'none';
}, 3000);
}
}
async function loadDefaultData() {
try {
showStatus('πŸ”„ Loading default pattern...', 'success');
const response = await fetch('https://gist.githubusercontent.com/jordangarcia/1d7827bd1bca863080acc708740acd92/raw/1ca27386382ce51599aad5f65e235a88773c6480/logo.json');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
// Validate the data structure
if (!Array.isArray(data)) {
throw new Error('Data must be an array');
}
if (data.length !== 80) {
throw new Error(`Array must have exactly 80 rows. Found ${data.length} rows.`);
}
// Validate each row
for (let row = 0; row < 80; row++) {
if (!Array.isArray(data[row])) {
throw new Error(`Row ${row} must be an array`);
}
if (data[row].length !== 80) {
throw new Error(`Row ${row} must have exactly 80 elements. Found ${data[row].length} elements.`);
}
// Validate each element in this row
for (let col = 0; col < 80; col++) {
if (data[row][col] !== 0 && data[row][col] !== 1) {
throw new Error(`Element at row ${row}, column ${col} must be 0 or 1. Found: ${data[row][col]}`);
}
}
}
// Data is valid, update the pixel array
pixelArray = data;
updatePixelDisplay();
calculateWeightDistribution();
updateDisplay();
resetSimulation();
showStatus('βœ… Default pattern loaded successfully!', 'success');
} catch (error) {
console.error('Error loading default data:', error);
showStatus(`❌ Error loading default pattern: ${error.message}`, 'error');
// Fall back to empty grid
calculateWeightDistribution();
updateDisplay();
}
}
// Initialize the application
initializeGrid();
loadDefaultData();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment