ini / static /app.js
favoredone's picture
Upload 9 files
bd6de9f verified
// Configuration
const API_BASE_URL = '/api'; // Use relative URL
const UPDATE_INTERVAL = 1000; // 1 second
const DEBUG = true; // Enable debug logging
// Debug logger
function debug(message, data = null) {
if (DEBUG) {
if (data) {
console.log(`[Debug] ${message}`, data);
} else {
console.log(`[Debug] ${message}`);
}
}
}
// Chart configuration
const chartConfig = {
hashrate: {
data: {
labels: [],
datasets: [{
label: 'Hashrate (KH/s)',
data: [],
borderColor: '#2ecc71',
tension: 0.4,
fill: false
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
grid: {
color: 'rgba(255, 255, 255, 0.1)'
}
},
x: {
grid: {
color: 'rgba(255, 255, 255, 0.1)'
}
}
},
plugins: {
legend: {
display: false
}
}
}
},
totalHashes: {
data: {
labels: [],
datasets: [{
label: 'Total Hashes',
data: [],
borderColor: '#3498db',
tension: 0.4,
fill: false
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
grid: {
color: 'rgba(255, 255, 255, 0.1)'
}
},
x: {
grid: {
color: 'rgba(255, 255, 255, 0.1)'
}
}
},
plugins: {
legend: {
display: false
}
}
}
}
};
// DOM Elements
const elements = {
startButton: document.getElementById('startButton'),
stopButton: document.getElementById('stopButton'),
statusText: document.getElementById('statusText'),
statusDot: document.querySelector('.status-dot'),
lastUpdate: document.getElementById('lastUpdate'),
hashrateValue: document.getElementById('hashrateValue'),
totalHashesValue: document.getElementById('totalHashesValue'),
blocksFoundValue: document.getElementById('blocksFoundValue'),
difficultyValue: document.getElementById('difficultyValue'),
bestHashValue: document.getElementById('bestHashValue'),
hashrateChart: document.getElementById('hashrateChart').getContext('2d'),
totalHashesChart: document.getElementById('totalHashesChart').getContext('2d')
};
// Initialize charts
const charts = {
hashrate: new Chart(elements.hashrateChart, chartConfig.hashrate),
totalHashes: new Chart(elements.totalHashesChart, chartConfig.totalHashes)
};
// Helper functions
function formatNumber(num) {
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
function updateLastUpdateTime() {
const now = new Date();
elements.lastUpdate.textContent = now.toLocaleTimeString();
}
function updateStatusIndicator(status) {
elements.statusText.textContent = status;
elements.statusDot.classList.toggle('active', status === 'Running');
}
function updateCharts(hashrate, totalHashes) {
const timestamp = new Date().toLocaleTimeString();
// Update hashrate chart
if (chartConfig.hashrate.data.labels.length > 20) {
chartConfig.hashrate.data.labels.shift();
chartConfig.hashrate.data.datasets[0].data.shift();
}
chartConfig.hashrate.data.labels.push(timestamp);
chartConfig.hashrate.data.datasets[0].data.push(hashrate);
charts.hashrate.update();
// Update total hashes chart
if (chartConfig.totalHashes.data.labels.length > 20) {
chartConfig.totalHashes.data.labels.shift();
chartConfig.totalHashes.data.datasets[0].data.shift();
}
chartConfig.totalHashes.data.labels.push(timestamp);
chartConfig.totalHashes.data.datasets[0].data.push(totalHashes);
charts.totalHashes.update();
}
// API functions
async function fetchStatus() {
try {
debug('Fetching status...');
const response = await fetch(`${API_BASE_URL}/status`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
debug('Received status data:', data);
// Update UI
elements.hashrateValue.textContent = data.hashrate.toFixed(2);
elements.totalHashesValue.textContent = formatNumber(data.total_hashes);
elements.blocksFoundValue.textContent = data.blocks_found;
elements.difficultyValue.textContent = formatNumber(data.difficulty);
elements.bestHashValue.textContent = data.best_hash || 'None';
updateStatusIndicator(data.status);
updateLastUpdateTime();
updateCharts(data.hashrate, data.total_hashes);
debug('UI updated successfully');
} catch (error) {
console.error('Error fetching status:', error);
updateStatusIndicator('Error');
// Show error in UI
elements.hashrateValue.textContent = 'ERR';
elements.totalHashesValue.textContent = 'ERR';
elements.blocksFoundValue.textContent = 'ERR';
elements.difficultyValue.textContent = 'ERR';
elements.bestHashValue.textContent = 'Error fetching data';
}
}
async function startMining() {
try {
debug('Starting mining...');
elements.startButton.disabled = true;
const response = await fetch(`${API_BASE_URL}/start`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
debug('Mining started:', data);
alert(data.message);
} catch (error) {
console.error('Error starting mining:', error);
alert('Failed to start mining: ' + error.message);
} finally {
elements.startButton.disabled = false;
}
}
async function stopMining() {
try {
debug('Stopping mining...');
elements.stopButton.disabled = true;
const response = await fetch(`${API_BASE_URL}/stop`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
debug('Mining stopped:', data);
alert(data.message);
} catch (error) {
console.error('Error stopping mining:', error);
alert('Failed to stop mining: ' + error.message);
} finally {
elements.stopButton.disabled = false;
}
}
// Event listeners
elements.startButton.addEventListener('click', startMining);
elements.stopButton.addEventListener('click', stopMining);
// Start periodic updates
setInterval(fetchStatus, UPDATE_INTERVAL);
// Initial status fetch
fetchStatus();