Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Magrav-Bitcoin Mining Control System</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| .gauge-container { | |
| position: relative; | |
| width: 100%; | |
| height: 0; | |
| padding-bottom: 50%; | |
| } | |
| .gauge { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| } | |
| .alert-flash { | |
| animation: flash 2s infinite; | |
| } | |
| @keyframes flash { | |
| 0% { opacity: 1; } | |
| 50% { opacity: 0.5; } | |
| 100% { opacity: 1; } | |
| } | |
| .chart-container { | |
| position: relative; | |
| height: 300px; | |
| width: 100%; | |
| } | |
| .system-status { | |
| transition: all 0.3s ease; | |
| } | |
| .emergency-active { | |
| animation: pulse 1s infinite; | |
| } | |
| @keyframes pulse { | |
| 0% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.7); } | |
| 70% { box-shadow: 0 0 0 10px rgba(239, 68, 68, 0); } | |
| 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0); } | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-900 text-gray-100 min-h-screen"> | |
| <div class="container mx-auto px-4 py-8"> | |
| <!-- Header --> | |
| <div class="flex flex-col md:flex-row justify-between items-start md:items-center mb-8"> | |
| <div> | |
| <h1 class="text-3xl md:text-4xl font-bold mb-2"> | |
| <i class="fas fa-bolt text-yellow-400 mr-2"></i> | |
| Magrav-Bitcoin Mining Control System | |
| </h1> | |
| <p class="text-gray-400">Experimental Power Integration Monitoring</p> | |
| </div> | |
| <div class="mt-4 md:mt-0 flex items-center"> | |
| <div id="systemStatus" class="system-status px-4 py-2 rounded-full flex items-center | |
| bg-gray-800 border border-gray-700"> | |
| <span class="w-3 h-3 rounded-full bg-red-500 mr-2"></span> | |
| <span>System Offline</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- System Stats --> | |
| <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8"> | |
| <!-- Magrav Output --> | |
| <div class="bg-gray-800 rounded-xl p-6 border border-gray-700"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-lg font-semibold"> | |
| <i class="fas fa-atom text-red-400 mr-2"></i> | |
| Magrav Output | |
| </h3> | |
| <span class="text-xs bg-gray-700 px-2 py-1 rounded">Experimental</span> | |
| </div> | |
| <div class="flex items-end justify-between"> | |
| <div> | |
| <div class="text-3xl font-bold text-red-400" id="magravOutput">0</div> | |
| <div class="text-gray-400 text-sm">Watts</div> | |
| </div> | |
| <div class="gauge-container"> | |
| <canvas id="magravGauge" class="gauge"></canvas> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Battery Status --> | |
| <div class="bg-gray-800 rounded-xl p-6 border border-gray-700"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-lg font-semibold"> | |
| <i class="fas fa-battery-three-quarters text-green-400 mr-2"></i> | |
| Battery Status | |
| </h3> | |
| <span class="text-xs bg-gray-700 px-2 py-1 rounded">48V LiFePO4</span> | |
| </div> | |
| <div class="flex items-end justify-between"> | |
| <div> | |
| <div class="text-3xl font-bold text-green-400" id="batteryCapacity">0</div> | |
| <div class="text-gray-400 text-sm" id="batteryVoltage">0.0V</div> | |
| </div> | |
| <div class="gauge-container"> | |
| <canvas id="batteryGauge" class="gauge"></canvas> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- DC Output --> | |
| <div class="bg-gray-800 rounded-xl p-6 border border-gray-700"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-lg font-semibold"> | |
| <i class="fas fa-plug text-blue-400 mr-2"></i> | |
| DC Output | |
| </h3> | |
| <span class="text-xs bg-gray-700 px-2 py-1 rounded">12V Target</span> | |
| </div> | |
| <div class="flex items-end justify-between"> | |
| <div> | |
| <div class="text-3xl font-bold text-blue-400" id="dcVoltage">0.00</div> | |
| <div class="text-gray-400 text-sm">Volts</div> | |
| </div> | |
| <div class="gauge-container"> | |
| <canvas id="voltageGauge" class="gauge"></canvas> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Mining Power --> | |
| <div class="bg-gray-800 rounded-xl p-6 border border-gray-700"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-lg font-semibold"> | |
| <i class="fas fa-microchip text-orange-400 mr-2"></i> | |
| Mining Power | |
| </h3> | |
| <span class="text-xs bg-gray-700 px-2 py-1 rounded">500W Test Rig</span> | |
| </div> | |
| <div class="flex items-end justify-between"> | |
| <div> | |
| <div class="text-3xl font-bold text-orange-400" id="minerPower">0</div> | |
| <div class="text-gray-400 text-sm" id="gridPower">Grid: 0W</div> | |
| </div> | |
| <div class="gauge-container"> | |
| <canvas id="minerGauge" class="gauge"></canvas> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Control Panel --> | |
| <div class="bg-gray-800 rounded-xl p-6 border border-gray-700 mb-8"> | |
| <h3 class="text-xl font-semibold mb-6"> | |
| <i class="fas fa-sliders-h text-gray-400 mr-2"></i> | |
| System Controls | |
| </h3> | |
| <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-6"> | |
| <!-- System Toggle --> | |
| <button id="systemToggle" | |
| class="px-6 py-3 rounded-lg font-semibold bg-gray-700 hover:bg-gray-600 text-white transition-colors flex items-center justify-center"> | |
| <i class="fas fa-power-off mr-2"></i> | |
| Power ON | |
| </button> | |
| <!-- Mining Toggle --> | |
| <button id="miningToggle" disabled | |
| class="px-6 py-3 rounded-lg font-semibold bg-gray-700 text-gray-400 transition-colors flex items-center justify-center cursor-not-allowed"> | |
| <i class="fas fa-digging mr-2"></i> | |
| Mining OFF | |
| </button> | |
| <!-- Emergency Stop --> | |
| <button id="emergencyStop" | |
| class="px-6 py-3 rounded-lg font-semibold bg-red-600 hover:bg-red-700 text-white transition-colors flex items-center justify-center"> | |
| <i class="fas fa-exclamation-triangle mr-2"></i> | |
| Emergency Stop | |
| </button> | |
| <!-- Reset System --> | |
| <button id="resetSystem" disabled | |
| class="px-6 py-3 rounded-lg font-semibold bg-blue-600 text-blue-200 transition-colors flex items-center justify-center cursor-not-allowed"> | |
| <i class="fas fa-sync-alt mr-2"></i> | |
| Reset System | |
| </button> | |
| </div> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-6"> | |
| <!-- Power Flow Chart --> | |
| <div class="bg-gray-900 rounded-lg p-4 border border-gray-700"> | |
| <h4 class="text-lg font-semibold mb-4"> | |
| <i class="fas fa-exchange-alt text-purple-400 mr-2"></i> | |
| Power Flow | |
| </h4> | |
| <div class="chart-container"> | |
| <canvas id="powerFlowChart"></canvas> | |
| </div> | |
| </div> | |
| <!-- System Health Chart --> | |
| <div class="bg-gray-900 rounded-lg p-4 border border-gray-700"> | |
| <h4 class="text-lg font-semibold mb-4"> | |
| <i class="fas fa-heartbeat text-green-400 mr-2"></i> | |
| System Health | |
| </h4> | |
| <div class="chart-container"> | |
| <canvas id="healthChart"></canvas> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Alerts and Statistics --> | |
| <div class="grid grid-cols-1 lg:grid-cols-2 gap-8"> | |
| <!-- Alerts Panel --> | |
| <div class="bg-gray-800 rounded-xl p-6 border border-gray-700"> | |
| <h3 class="text-xl font-semibold mb-4 flex items-center"> | |
| <i class="fas fa-exclamation-circle text-yellow-400 mr-2"></i> | |
| System Alerts | |
| </h3> | |
| <div class="space-y-2 max-h-64 overflow-y-auto pr-2" id="alertsContainer"> | |
| <div class="p-3 rounded-lg bg-gray-900 border-l-4 border-gray-500"> | |
| <div class="flex justify-between items-start"> | |
| <span class="text-sm">System initialized and ready</span> | |
| <span class="text-xs text-gray-400">Just now</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Statistics Panel --> | |
| <div class="bg-gray-800 rounded-xl p-6 border border-gray-700"> | |
| <h3 class="text-xl font-semibold mb-4 flex items-center"> | |
| <i class="fas fa-chart-line text-blue-400 mr-2"></i> | |
| Experiment Statistics | |
| </h3> | |
| <div class="space-y-4 mb-6"> | |
| <div class="flex justify-between items-center"> | |
| <span class="text-gray-300"> | |
| <i class="fas fa-bolt text-yellow-400 mr-2"></i> | |
| Total Energy from Magrav: | |
| </span> | |
| <span class="font-semibold text-green-400" id="totalEnergy">0.000 kWh</span> | |
| </div> | |
| <div class="flex justify-between items-center"> | |
| <span class="text-gray-300"> | |
| <i class="fas fa-dollar-sign text-green-400 mr-2"></i> | |
| Theoretical Cost Savings: | |
| </span> | |
| <span class="font-semibold text-green-400" id="costSavings">$0.00</span> | |
| </div> | |
| <div class="flex justify-between items-center"> | |
| <span class="text-gray-300"> | |
| <i class="fas fa-tachometer-alt text-blue-400 mr-2"></i> | |
| System Efficiency: | |
| </span> | |
| <span class="font-semibold text-blue-400" id="systemEfficiency">0%</span> | |
| </div> | |
| <div class="flex justify-between items-center"> | |
| <span class="text-gray-300"> | |
| <i class="fas fa-plug text-orange-400 mr-2"></i> | |
| Grid Dependence: | |
| </span> | |
| <span class="font-semibold text-orange-400" id="gridDependence">0%</span> | |
| </div> | |
| </div> | |
| <div class="p-4 bg-yellow-900 rounded-lg border border-yellow-700"> | |
| <h4 class="font-semibold text-yellow-300 mb-2 flex items-center"> | |
| <i class="fas fa-exclamation-triangle mr-2"></i> | |
| Experimental Notice | |
| </h4> | |
| <p class="text-sm text-yellow-200"> | |
| This system is for research purposes only. Real-world performance may vary significantly from simulated results. | |
| Always follow proper electrical safety procedures when working with experimental power systems. | |
| </p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // System Configuration | |
| const CONFIG = { | |
| MAGRAV_MAX_OUTPUT: 2000, // 2kW claimed max | |
| BATTERY_NOMINAL_VOLTAGE: 48.0, | |
| BATTERY_CAPACITY: 10000, // 10kWh | |
| DC_VOLTAGE_TARGET: 12.0, | |
| DC_VOLTAGE_TOLERANCE: 0.6, // ±5% | |
| MINER_POWER_RATING: 500, // 500W GPU rig | |
| GRID_RATE: 0.12, // $0.12/kWh | |
| SAFETY_THRESHOLDS: { | |
| OVERVOLTAGE: 12.6, | |
| UNDERVOLTAGE: 11.4, | |
| OVERTEMPERATURE: 75 | |
| } | |
| }; | |
| // System State | |
| let systemState = { | |
| systemEnabled: false, | |
| emergencyStop: false, | |
| miningEnabled: false, | |
| magravOutput: 0, | |
| batteryVoltage: 44.0, | |
| batteryCapacity: 20, | |
| dcVoltage: 0, | |
| minerPower: 0, | |
| gridPower: 0 | |
| }; | |
| // Performance Data | |
| let performanceData = []; | |
| let alerts = []; | |
| let totalEnergy = 0; | |
| let costSavings = 0; | |
| let updateInterval; | |
| let alertId = 0; | |
| // DOM Elements | |
| const systemStatusEl = document.getElementById('systemStatus'); | |
| const systemToggleBtn = document.getElementById('systemToggle'); | |
| const miningToggleBtn = document.getElementById('miningToggle'); | |
| const emergencyStopBtn = document.getElementById('emergencyStop'); | |
| const resetSystemBtn = document.getElementById('resetSystem'); | |
| const alertsContainer = document.getElementById('alertsContainer'); | |
| // Gauge Charts | |
| const magravGauge = createGauge('magravGauge', 'Magrav Output', 'W', 0, CONFIG.MAGRAV_MAX_OUTPUT, 'red'); | |
| const batteryGauge = createGauge('batteryGauge', 'Battery', '%', 0, 100, 'green'); | |
| const voltageGauge = createGauge('voltageGauge', 'DC Voltage', 'V', 10, 14, 'blue'); | |
| const minerGauge = createGauge('minerGauge', 'Miner Power', 'W', 0, CONFIG.MINER_POWER_RATING, 'orange'); | |
| // Line Charts | |
| const powerFlowChart = createLineChart('powerFlowChart', ['Magrav Output', 'Miner Power', 'Grid Power'], ['#EF4444', '#F97316', '#3B82F6']); | |
| const healthChart = createLineChart('healthChart', ['Battery %', 'DC Voltage'], ['#10B981', '#8B5CF6']); | |
| // Initialize system | |
| updateUI(); | |
| addAlert('info', 'System initialized and ready'); | |
| // Event Listeners | |
| systemToggleBtn.addEventListener('click', toggleSystem); | |
| miningToggleBtn.addEventListener('click', toggleMining); | |
| emergencyStopBtn.addEventListener('click', emergencyStop); | |
| resetSystemBtn.addEventListener('click', resetSystem); | |
| // System Functions | |
| function toggleSystem() { | |
| if (systemState.emergencyStop) return; | |
| systemState.systemEnabled = !systemState.systemEnabled; | |
| systemState.miningEnabled = false; | |
| if (systemState.systemEnabled) { | |
| startSystem(); | |
| addAlert('info', 'System powered ON'); | |
| } else { | |
| stopSystem(); | |
| addAlert('info', 'System powered OFF'); | |
| } | |
| updateUI(); | |
| } | |
| function toggleMining() { | |
| if (systemState.dcVoltage < CONFIG.SAFETY_THRESHOLDS.UNDERVOLTAGE) { | |
| addAlert('error', 'Cannot enable mining - DC voltage too low'); | |
| return; | |
| } | |
| systemState.miningEnabled = !systemState.miningEnabled; | |
| if (systemState.miningEnabled) { | |
| addAlert('info', 'Mining enabled'); | |
| } else { | |
| addAlert('info', 'Mining disabled'); | |
| } | |
| updateUI(); | |
| } | |
| function emergencyStop() { | |
| systemState.emergencyStop = true; | |
| systemState.systemEnabled = false; | |
| systemState.miningEnabled = false; | |
| clearInterval(updateInterval); | |
| addAlert('error', 'EMERGENCY STOP ACTIVATED'); | |
| updateUI(); | |
| } | |
| function resetSystem() { | |
| systemState.emergencyStop = false; | |
| addAlert('info', 'System reset completed'); | |
| updateUI(); | |
| } | |
| function startSystem() { | |
| // Initialize performance data | |
| performanceData = []; | |
| // Start update loop | |
| updateInterval = setInterval(updateSystem, 1000); | |
| } | |
| function stopSystem() { | |
| clearInterval(updateInterval); | |
| } | |
| function updateSystem() { | |
| if (systemState.emergencyStop) return; | |
| // Simulate Magrav output | |
| systemState.magravOutput = simulateMagravOutput(); | |
| // Calculate mining power | |
| systemState.minerPower = calculateMinerPower(); | |
| // Update battery state | |
| const batteryState = updateBatteryState(systemState.magravOutput, systemState.minerPower); | |
| systemState.batteryCapacity = batteryState.capacity; | |
| systemState.batteryVoltage = batteryState.voltage; | |
| // Calculate DC output | |
| systemState.dcVoltage = calculateDCOutput(systemState.batteryVoltage, systemState.minerPower); | |
| // Calculate grid power | |
| systemState.gridPower = Math.max(0, systemState.minerPower - systemState.magravOutput); | |
| // Update totals | |
| totalEnergy += systemState.magravOutput / 3600000; // Convert to kWh | |
| costSavings += (systemState.magravOutput * CONFIG.GRID_RATE) / 3600000; | |
| // Add data point | |
| const dataPoint = { | |
| timestamp: new Date().toLocaleTimeString(), | |
| magravOutput: systemState.magravOutput, | |
| minerPower: systemState.minerPower, | |
| batteryCapacity: systemState.batteryCapacity, | |
| dcVoltage: systemState.dcVoltage, | |
| gridPower: systemState.gridPower | |
| }; | |
| performanceData.push(dataPoint); | |
| if (performanceData.length > 15) { | |
| performanceData.shift(); | |
| } | |
| // Check safety conditions | |
| checkSafetyConditions(); | |
| // Update UI | |
| updateUI(); | |
| } | |
| function simulateMagravOutput() { | |
| if (!systemState.systemEnabled) return 0; | |
| // Simulate erratic/experimental behavior | |
| const baseOutput = CONFIG.MAGRAV_MAX_OUTPUT * 0.3; // 30% of claimed | |
| const variation = Math.sin(Date.now() / 10000) * 200; | |
| const noise = (Math.random() - 0.5) * 300; | |
| return Math.max(0, baseOutput + variation + noise); | |
| } | |
| function updateBatteryState(magravInput, minerLoad) { | |
| const currentCapacity = systemState.batteryCapacity; | |
| const chargeRate = magravInput / CONFIG.BATTERY_CAPACITY * 100; | |
| const dischargeRate = minerLoad / CONFIG.BATTERY_CAPACITY * 100; | |
| const netChange = chargeRate - dischargeRate; | |
| const newCapacity = Math.max(0, Math.min(100, currentCapacity + netChange * 0.1)); | |
| const voltage = 44.0 + (newCapacity / 100) * 8.0; // 44V to 52V range | |
| return { capacity: newCapacity, voltage }; | |
| } | |
| function calculateDCOutput(batteryVoltage, load) { | |
| if (batteryVoltage < 44.0) return 0; // Undervoltage cutoff | |
| const efficiency = 0.95; // 95% efficiency | |
| const regulation = CONFIG.DC_VOLTAGE_TARGET; | |
| const loadEffect = load > 400 ? -0.1 : 0; // Voltage drop under heavy load | |
| return regulation + loadEffect; | |
| } | |
| function calculateMinerPower() { | |
| if (!systemState.miningEnabled || systemState.dcVoltage < CONFIG.SAFETY_THRESHOLDS.UNDERVOLTAGE) { | |
| return 0; | |
| } | |
| const basePower = CONFIG.MINER_POWER_RATING; | |
| const voltageEffect = (systemState.dcVoltage - 12.0) / 12.0 * 50; | |
| return basePower + voltageEffect; | |
| } | |
| function checkSafetyConditions() { | |
| const { dcVoltage, batteryVoltage } = systemState; | |
| if (dcVoltage > CONFIG.SAFETY_THRESHOLDS.OVERVOLTAGE) { | |
| addAlert('error', 'DC Overvoltage detected! System shutdown initiated.'); | |
| systemState.emergencyStop = true; | |
| systemState.miningEnabled = false; | |
| systemState.systemEnabled = false; | |
| stopSystem(); | |
| return false; | |
| } | |
| if (dcVoltage < CONFIG.SAFETY_THRESHOLDS.UNDERVOLTAGE && systemState.miningEnabled) { | |
| addAlert('warning', 'DC Undervoltage - Mining disabled for protection.'); | |
| systemState.miningEnabled = false; | |
| } | |
| if (batteryVoltage < 44.0) { | |
| addAlert('warning', 'Battery critically low - System protection activated.'); | |
| systemState.miningEnabled = false; | |
| } | |
| return true; | |
| } | |
| function addAlert(type, message) { | |
| const alert = { | |
| id: alertId++, | |
| type, | |
| message, | |
| timestamp: new Date().toLocaleTimeString() | |
| }; | |
| alerts.unshift(alert); | |
| if (alerts.length > 10) { | |
| alerts.pop(); | |
| } | |
| // Create alert element | |
| const alertEl = document.createElement('div'); | |
| alertEl.className = `p-3 rounded-lg border-l-4 mb-2 ${ | |
| type === 'error' ? 'bg-red-900 border-red-500' : | |
| type === 'warning' ? 'bg-yellow-900 border-yellow-500' : | |
| 'bg-blue-900 border-blue-500' | |
| }`; | |
| alertEl.innerHTML = ` | |
| <div class="flex justify-between items-start"> | |
| <span class="text-sm">${message}</span> | |
| <span class="text-xs text-gray-400">${alert.timestamp}</span> | |
| </div> | |
| `; | |
| alertsContainer.insertBefore(alertEl, alertsContainer.firstChild); | |
| // Flash alert | |
| if (type === 'error') { | |
| alertEl.classList.add('alert-flash'); | |
| } | |
| } | |
| function updateUI() { | |
| // Update status display | |
| if (systemState.emergencyStop) { | |
| systemStatusEl.innerHTML = ` | |
| <span class="w-3 h-3 rounded-full bg-red-500 mr-2 animate-pulse"></span> | |
| <span>EMERGENCY STOP</span> | |
| `; | |
| systemStatusEl.classList.add('emergency-active'); | |
| } else if (systemState.systemEnabled) { | |
| systemStatusEl.innerHTML = ` | |
| <span class="w-3 h-3 rounded-full bg-green-500 mr-2"></span> | |
| <span>System Online</span> | |
| `; | |
| systemStatusEl.classList.remove('emergency-active'); | |
| } else { | |
| systemStatusEl.innerHTML = ` | |
| <span class="w-3 h-3 rounded-full bg-red-500 mr-2"></span> | |
| <span>System Offline</span> | |
| `; | |
| systemStatusEl.classList.remove('emergency-active'); | |
| } | |
| // Update control buttons | |
| systemToggleBtn.innerHTML = ` | |
| <i class="fas fa-power-off mr-2"></i> | |
| ${systemState.systemEnabled ? 'Power OFF' : 'Power ON'} | |
| `; | |
| systemToggleBtn.className = systemState.systemEnabled ? | |
| 'px-6 py-3 rounded-lg font-semibold bg-green-600 hover:bg-green-700 text-white transition-colors flex items-center justify-center' : | |
| 'px-6 py-3 rounded-lg font-semibold bg-gray-700 hover:bg-gray-600 text-white transition-colors flex items-center justify-center'; | |
| miningToggleBtn.disabled = !systemState.systemEnabled || systemState.emergencyStop; | |
| miningToggleBtn.innerHTML = ` | |
| <i class="fas fa-digging mr-2"></i> | |
| ${systemState.miningEnabled ? 'Mining OFF' : 'Mining ON'} | |
| `; | |
| miningToggleBtn.className = systemState.miningEnabled ? | |
| 'px-6 py-3 rounded-lg font-semibold bg-orange-600 hover:bg-orange-700 text-white transition-colors flex items-center justify-center' : | |
| 'px-6 py-3 rounded-lg font-semibold bg-gray-700 hover:bg-gray-600 text-white transition-colors flex items-center justify-center'; | |
| if (miningToggleBtn.disabled) { | |
| miningToggleBtn.className = 'px-6 py-3 rounded-lg font-semibold bg-gray-700 text-gray-400 transition-colors flex items-center justify-center cursor-not-allowed'; | |
| } | |
| resetSystemBtn.disabled = !systemState.emergencyStop; | |
| if (resetSystemBtn.disabled) { | |
| resetSystemBtn.className = 'px-6 py-3 rounded-lg font-semibold bg-blue-600 text-blue-200 transition-colors flex items-center justify-center cursor-not-allowed'; | |
| } else { | |
| resetSystemBtn.className = 'px-6 py-3 rounded-lg font-semibold bg-blue-600 hover:bg-blue-700 text-white transition-colors flex items-center justify-center'; | |
| } | |
| // Update numeric displays | |
| document.getElementById('magravOutput').textContent = systemState.magravOutput.toFixed(1); | |
| document.getElementById('batteryCapacity').textContent = systemState.batteryCapacity.toFixed(1); | |
| document.getElementById('batteryVoltage').textContent = systemState.batteryVoltage.toFixed(1) + 'V'; | |
| document.getElementById('dcVoltage').textContent = systemState.dcVoltage.toFixed(2); | |
| document.getElementById('minerPower').textContent = systemState.minerPower.toFixed(1); | |
| document.getElementById('gridPower').textContent = `Grid: ${systemState.gridPower.toFixed(1)}W`; | |
| // Update statistics | |
| document.getElementById('totalEnergy').textContent = totalEnergy.toFixed(3) + ' kWh'; | |
| document.getElementById('costSavings').textContent = '$' + costSavings.toFixed(2); | |
| const efficiency = systemState.magravOutput > 0 ? | |
| ((systemState.minerPower / systemState.magravOutput) * 100).toFixed(1) : 0; | |
| document.getElementById('systemEfficiency').textContent = efficiency + '%'; | |
| const gridDependence = systemState.minerPower > 0 ? | |
| ((systemState.gridPower / systemState.minerPower) * 100).toFixed(1) : 0; | |
| document.getElementById('gridDependence').textContent = gridDependence + '%'; | |
| // Update gauges | |
| updateGauge(magravGauge, systemState.magravOutput); | |
| updateGauge(batteryGauge, systemState.batteryCapacity); | |
| updateGauge(voltageGauge, systemState.dcVoltage); | |
| updateGauge(minerGauge, systemState.minerPower); | |
| // Update line charts | |
| updateLineChart(powerFlowChart, performanceData, ['magravOutput', 'minerPower', 'gridPower']); | |
| updateLineChart(healthChart, performanceData, ['batteryCapacity', 'dcVoltage']); | |
| } | |
| // Chart Functions | |
| function createGauge(canvasId, label, unit, min, max, color) { | |
| const canvas = document.getElementById(canvasId); | |
| const ctx = canvas.getContext('2d'); | |
| return { | |
| ctx, | |
| label, | |
| unit, | |
| min, | |
| max, | |
| color, | |
| value: 0 | |
| }; | |
| } | |
| function updateGauge(gauge, value) { | |
| const { ctx, label, unit, min, max, color } = gauge; | |
| const width = ctx.canvas.width; | |
| const height = ctx.canvas.height; | |
| // Clear canvas | |
| ctx.clearRect(0, 0, width, height); | |
| // Draw gauge background | |
| ctx.beginPath(); | |
| ctx.arc(width / 2, height / 2, Math.min(width, height) / 2 - 10, 0.75 * Math.PI, 2.25 * Math.PI); | |
| ctx.lineWidth = 20; | |
| ctx.strokeStyle = '#374151'; | |
| ctx.stroke(); | |
| // Calculate angle for value | |
| const normalizedValue = Math.min(Math.max(value, min), max); | |
| const angle = 0.75 * Math.PI + (1.5 * Math.PI * (normalizedValue - min) / (max - min)); | |
| // Draw gauge value | |
| ctx.beginPath(); | |
| ctx.arc(width / 2, height / 2, Math.min(width, height) / 2 - 10, 0.75 * Math.PI, angle); | |
| ctx.lineWidth = 20; | |
| ctx.strokeStyle = color; | |
| ctx.stroke(); | |
| // Draw gauge center | |
| ctx.fillStyle = '#1F2937'; | |
| ctx.beginPath(); | |
| ctx.arc(width / 2, height / 2, Math.min(width, height) / 2 - 30, 0, 2 * Math.PI); | |
| ctx.fill(); | |
| // Draw value text | |
| ctx.fillStyle = '#F3F4F6'; | |
| ctx.font = 'bold ' + (Math.min(width, height) / 5) + 'px Arial'; | |
| ctx.textAlign = 'center'; | |
| ctx.textBaseline = 'middle'; | |
| ctx.fillText(normalizedValue.toFixed(1), width / 2, height / 2); | |
| // Draw unit text | |
| ctx.fillStyle = '#9CA3AF'; | |
| ctx.font = (Math.min(width, height) / 8) + 'px Arial'; | |
| ctx.fillText(unit, width / 2, height / 2 + (Math.min(width, height) / 6)); | |
| } | |
| function createLineChart(canvasId, datasets, colors) { | |
| const canvas = document.getElementById(canvasId); | |
| const ctx = canvas.getContext('2d'); | |
| return new Chart(ctx, { | |
| type: 'line', | |
| data: { | |
| labels: [], | |
| datasets: datasets.map((label, i) => ({ | |
| label, | |
| data: [], | |
| borderColor: colors[i], | |
| backgroundColor: colors[i] + '20', | |
| borderWidth: 2, | |
| tension: 0.3, | |
| fill: true | |
| })) | |
| }, | |
| options: { | |
| responsive: true, | |
| maintainAspectRatio: false, | |
| scales: { | |
| x: { | |
| grid: { | |
| color: '#374151' | |
| }, | |
| ticks: { | |
| color: '#9CA3AF' | |
| } | |
| }, | |
| y: { | |
| grid: { | |
| color: '#374151' | |
| }, | |
| ticks: { | |
| color: '#9CA3AF' | |
| } | |
| } | |
| }, | |
| plugins: { | |
| legend: { | |
| labels: { | |
| color: '#F3F4F6' | |
| } | |
| } | |
| }, | |
| interaction: { | |
| intersect: false, | |
| mode: 'index' | |
| } | |
| } | |
| }); | |
| } | |
| function updateLineChart(chart, data, fields) { | |
| chart.data.labels = data.map(item => item.timestamp); | |
| fields.forEach((field, i) => { | |
| chart.data.datasets[i].data = data.map(item => item[field]); | |
| }); | |
| chart.update(); | |
| } | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Gaslighttheghost/bitmin" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |