document.addEventListener('DOMContentLoaded', function() { // Helper to format hashrate function formatHashrate(mhs) { if (mhs >= 1000) { return (mhs / 1000).toFixed(2) + ' GH/s'; } return parseFloat(mhs).toFixed(2) + ' MH/s'; } // Initialize Chart const ctx = document.getElementById('hashrateChart').getContext('2d'); const hashrateChart = new Chart(ctx, { type: 'line', data: { labels: [], datasets: [{ label: 'Hashrate', data: [], borderColor: '#0d6efd', backgroundColor: 'rgba(13, 110, 253, 0.1)', borderWidth: 2, fill: true, tension: 0.4 }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false }, tooltip: { callbacks: { label: function(context) { return formatHashrate(context.raw); } } } }, scales: { x: { grid: { color: '#333' }, ticks: { color: '#aaa' } }, y: { grid: { color: '#333' }, ticks: { color: '#aaa' }, beginAtZero: true } } } }); // Helper to format large numbers function formatNumber(num) { return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,'); } function updateDashboard() { fetch('/api/data') .then(response => response.json()) .then(data => { const summary = data.summary; const devs = data.devs; const pools = data.pools; // Update Top Stats if (summary) { const mhs = summary['MHS 5s'] || summary['MHS av'] || 0; // Parse unit const formatted = formatHashrate(mhs); // Check if GH/s or MH/s let unit = 'MH/s'; let val = mhs; if (formatted.includes('GH/s')) { unit = 'GH/s'; val = (mhs / 1000).toFixed(2); } else { val = parseFloat(mhs).toFixed(2); } document.getElementById('stat-mhs').innerText = val; // Note: HTML might still say MH/s in static part, need to update ID or text node of
// But simplified: const unitElem = document.querySelector('#stat-mhs').nextElementSibling; if(unitElem) unitElem.innerText = unit; document.getElementById('stat-accepted').innerText = formatNumber(summary['Accepted'] || 0); document.getElementById('stat-hw').innerText = formatNumber(summary['Hardware Errors'] || 0); } // Update Device Count if (devs) { document.getElementById('stat-devices').innerText = devs.length; } // Helper to find temp in stats if missing in devs // Cgminer 'stats' command returns specific driver info. // Structure: stats ->STATS -> list of dicts. usually one dict per device with ID keys like 'MM ID 0', etc. // Or simplified list. function getTempFallback(devId, statsData) { // Try to find matching ID in stats // This is heuristic as structure varies wildy between forks return 0; } // Update Devs Table & Max Temp let maxTemp = 0; const tbody = document.getElementById('devs-table-body'); tbody.innerHTML = ''; if (devs && devs.length > 0) { devs.forEach(dev => { let temp = dev['Temperature'] || 0; // Fallback logic could go here if we understood the STATS structure for this specific fork // For now we rely on standard API. if (temp > maxTemp) maxTemp = temp; const tr = document.createElement('tr'); tr.innerHTML = `