diff --git a/static/js/main.js b/static/js/main.js
index cd28deb..a5cb9c5 100644
--- a/static/js/main.js
+++ b/static/js/main.js
@@ -326,7 +326,6 @@ let reconnectionDelay = 1000; // Start with 1 second
let pingInterval = null;
let lastPingTime = Date.now();
let connectionLostTimeout = null;
-let previousBlockHeight = null; // Declare and initialize previousBlockHeight
// Server time variables for uptime calculation
let serverTimeOffset = 0;
@@ -384,31 +383,6 @@ function formatHashrateForDisplay(value, unit) {
}
}
-// Helper function: Find an exact or nearest matching label
-function findMatchingLabel(timeStr, labels, toleranceMinutes = 2) {
- // If exact match, return it
- if (labels.includes(timeStr)) {
- return timeStr;
- }
- // Parse timeStr into minutes from midnight
- const [hours, minutes] = timeStr.split(':').map(Number);
- const targetTotal = hours * 60 + minutes;
- let closestLabel = null;
- let smallestDiff = Infinity;
-
- labels.forEach(label => {
- if (!label.includes(':')) return; // skip non-time labels
- const [lh, lm] = label.split(':').map(Number);
- const labelTotal = lh * 60 + lm;
- const diff = Math.abs(targetTotal - labelTotal);
- if (diff < smallestDiff && diff <= toleranceMinutes) {
- smallestDiff = diff;
- closestLabel = label;
- }
- });
- return closestLabel; // may be null if none within tolerance
-}
-
// SSE Connection with Error Handling and Reconnection Logic
function setupEventSource() {
console.log("Setting up EventSource connection...");
@@ -713,7 +687,7 @@ function initializeChart() {
y: {
title: {
display: true,
- text: 'Hashrate (TH/s)' // Always display unit as TH/s since that's our normalized unit
+ text: 'HASHRATE (TH/S)' // Always display unit as TH/s since that's our normalized unit
},
ticks: {
color: 'white',
@@ -759,35 +733,12 @@ function initializeChart() {
},
plugins: {
tooltip: {
- // ADD THIS TOOLTIP CONFIGURATION HERE
callbacks: {
label: function (context) {
// Format tooltip values with appropriate unit
const value = context.raw;
return 'Hashrate: ' + formatHashrateForDisplay(value);
}
- },
- // New tooltip filter to prioritize block found points
- filter: function (tooltipItem) {
- // Show Block Found tooltips with higher priority
- if (tooltipItem.dataset.label === 'Block Found') {
- return true;
- }
-
- // Check if there's a block found point at this position
- const blockDataset = tooltipItem.chart.data.datasets.find(ds => ds.label === 'Block Found');
- if (blockDataset) {
- const blockPoint = blockDataset.data.find(point =>
- point.x === tooltipItem.label);
-
- if (blockPoint) {
- // If there's a block point at this position, don't show hashrate tooltip
- return false;
- }
- }
-
- // Show other tooltips
- return true;
}
},
legend: { display: false },
@@ -807,13 +758,14 @@ function initializeChart() {
shadowOffsetY: 0,
label: {
enabled: true,
- content: '24hr Avg: 0 TH/s',
+ content: '24HR AVG: 0 TH/S',
backgroundColor: 'rgba(0,0,0,0.8)',
color: '#ffd700', // Changed to match the line color
font: {
weight: 'bold',
size: 14, // Increased from 13 to 14
- family: 'var(--terminal-font)' // Use the terminal font
+ family: 'var(--terminal-font)', // Use the terminal font
+ uppercase: true // Make label text uppercase
},
padding: { top: 4, bottom: 4, left: 8, right: 8 },
borderRadius: 2,
@@ -915,12 +867,16 @@ function showCongrats(message) {
// Add timestamp to the message
const now = new Date(Date.now() + serverTimeOffset); // Use server time offset for accuracy
- const timeString = now.toLocaleTimeString('en-US', {
+ const options = {
+ year: 'numeric',
+ month: 'short',
+ day: 'numeric',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: true
- });
+ };
+ const timeString = now.toLocaleTimeString('en-US', options);
// Format the message with the timestamp
const messageWithTimestamp = `${message} [${timeString}]`;
@@ -940,11 +896,6 @@ function updateChartWithNormalizedData(chart, data) {
return;
}
try {
- // Ensure we preserve block found points across updates
- if (!data.block_found_points && latestMetrics && latestMetrics.block_found_points) {
- data.block_found_points = latestMetrics.block_found_points;
- }
-
// Always update the 24hr average line even if we don't have data points yet
const avg24hr = parseFloat(data.hashrate_24hr || 0);
const avg24hrUnit = data.hashrate_24hr_unit ? data.hashrate_24hr_unit.toLowerCase() : 'th/s';
@@ -957,67 +908,49 @@ function updateChartWithNormalizedData(chart, data) {
const annotation = chart.options.plugins.annotation.annotations.averageLine;
annotation.yMin = normalizedAvg;
annotation.yMax = normalizedAvg;
- annotation.label.content = '24hr Avg: ' + normalizedAvg.toFixed(1) + ' TH/s';
+ annotation.label.content = '24HR AVG: ' + normalizedAvg.toFixed(1) + ' TH/S';
}
- // Process block found points if they exist
- let blockFoundDataPoints = [];
- if (data.block_found_points && data.block_found_points.length > 0) {
- // Ensure block point times are formatted consistently to match chart labels
- const validLabels = new Set(chart.data.labels);
-
- blockFoundDataPoints = data.block_found_points
- .filter(point => {
- const timeStr = point.time;
- // If the time is in HH:MM:SS format, truncate seconds to match chart labels
- const formattedTime = (timeStr.length === 8 && timeStr.indexOf(':') !== -1)
- ? timeStr.substring(0, 5)
- : timeStr;
- const exists = validLabels.has(formattedTime);
- if (!exists) {
- console.warn(`Block point time ${formattedTime} not found in chart labels`);
- }
- return exists;
- })
- .map(point => {
- const val = parseFloat(point.value);
- const unit = point.unit || data.hashrate_60sec_unit || 'th/s';
- const timeStr = point.time;
- const formattedTime = (timeStr.length === 8 && timeStr.indexOf(':') !== -1)
- ? timeStr.substring(0, 5)
- : timeStr;
- return {
- x: formattedTime,
- y: normalizeHashrate(val, unit)
- };
- });
-
- // Debug logging: output the current chart labels and compare each block point time
- console.log("Chart labels after history update:", chart.data.labels);
- blockFoundDataPoints.forEach((bp, index) => {
- console.log(`Block found point ${index}: ${bp.x} vs Chart labels:`, chart.data.labels);
- });
- }
-
- // Update data points if we have any history data
+ // In updateChartWithNormalizedData function:
if (data.arrow_history && data.arrow_history.hashrate_60sec) {
console.log("History data received:", data.arrow_history.hashrate_60sec);
const historyData = data.arrow_history.hashrate_60sec;
if (historyData && historyData.length > 0) {
- const currentUnit = data.hashrate_60sec_unit ? data.hashrate_60sec_unit.toLowerCase() : 'th/s';
+ // Add day info to labels if they cross midnight
+ let prevHour = -1;
+ let dayCount = 0;
+
chart.data.labels = historyData.map(item => {
const timeStr = item.time;
+ let timeLabel;
+
if (timeStr.length === 8 && timeStr.indexOf(':') !== -1) {
- return timeStr.substring(0, 5);
+ timeLabel = timeStr.substring(0, 5); // HH:MM
+ } else {
+ timeLabel = timeStr;
}
- return timeStr;
+
+ // Check if we crossed midnight (hour decreased)
+ const hourMatch = timeLabel.match(/^(\d+):/);
+ if (hourMatch) {
+ const hour = parseInt(hourMatch[1]);
+ if (prevHour !== -1 && hour < prevHour && hour < 12) {
+ dayCount++; // We crossed midnight
+ }
+ prevHour = hour;
+ }
+
+ // Add day info for debugging
+ if (dayCount > 0) {
+ console.log(`Time ${timeLabel} considered from day+${dayCount}`);
+ }
+
+ return timeLabel;
});
chart.data.datasets[0].data = historyData.map(item => {
const val = parseFloat(item.value);
- if (item.unit) {
- return normalizeHashrate(val, item.unit);
- }
- return normalizeHashrate(val, currentUnit);
+ const unit = item.unit || 'th/s'; // Ensure unit is assigned
+ return normalizeHashrate(val, unit);
});
const values = chart.data.datasets[0].data.filter(v => !isNaN(v) && v !== null);
if (values.length > 0) {
@@ -1047,32 +980,10 @@ function updateChartWithNormalizedData(chart, data) {
}
}
- // Keep only the main dataset, then add the block found dataset, if any
- if (chart.data.datasets.length >= 1) {
- const mainDataset = chart.data.datasets[0];
- chart.data.datasets = [mainDataset];
- }
- if (blockFoundDataPoints.length > 0) {
- const blockFoundDataset = {
- label: 'Block Found',
- data: blockFoundDataPoints,
- borderColor: '#32CD32',
- backgroundColor: 'green',
- pointRadius: 9,
- pointHoverRadius: 15,
- pointStyle: 'rectRot',
- borderWidth: 2,
- showLine: false,
- order: -10,
- z: 1000
- };
- chart.data.datasets.push(blockFoundDataset);
- }
chart.update('none');
} catch (chartError) {
console.error("Error updating chart:", chartError);
}
- forceBlockPointsVisibility();
}
// Main UI update function with hashrate normalization
@@ -1085,18 +996,6 @@ function updateUI() {
try {
const data = latestMetrics;
- // Add debug logging here
- console.log("Current block height:", data.last_block_height,
- "Previous block height:", previousBlockHeight);
-
- // Check for block updates
- if (previousBlockHeight !== null && data.last_block_height !== previousBlockHeight) {
- // Block found, update the chart
- highlightBlockFound(data.last_block_height);
- }
-
- previousBlockHeight = data.last_block_height;
-
// If this is the initial load, force a reset of all arrows
if (initialLoad) {
arrowIndicator.forceApplyArrows();
@@ -1170,8 +1069,8 @@ function updateUI() {
updateElementText("daily_power_cost", "$" + numberWithCommas(data.daily_power_cost.toFixed(2)));
updateElementText("daily_profit_usd", "$" + numberWithCommas(data.daily_profit_usd.toFixed(2)));
updateElementText("monthly_profit_usd", "$" + numberWithCommas(data.monthly_profit_usd.toFixed(2)));
- updateElementText("daily_mined_sats", numberWithCommas(data.daily_mined_sats) + " sats");
- updateElementText("monthly_mined_sats", numberWithCommas(data.monthly_mined_sats) + " sats");
+ updateElementText("daily_mined_sats", numberWithCommas(data.daily_mined_sats) + " SATS");
+ updateElementText("monthly_mined_sats", numberWithCommas(data.monthly_mined_sats) + " SATS");
// Update worker count from metrics (just the number, not full worker data)
updateWorkersCount();
@@ -1184,7 +1083,7 @@ function updateUI() {
// Check for "next block" in any case format
if (payoutText && /next\s+block/i.test(payoutText)) {
- $("#est_time_to_payout").attr("style", "color: #32CD32 !important; text-shadow: 0 0 6px rgba(50, 205, 50, 0.6) !important; animation: pulse 1s infinite !important;");
+ $("#est_time_to_payout").attr("style", "color: #32CD32 !important; text-shadow: 0 0 6px rgba(50, 205, 50, 0.6) !important; animation: pulse 1s infinite !important; text-transform: uppercase !important;");
} else {
// Trim any extra whitespace
const cleanText = payoutText ? payoutText.trim() : "";
@@ -1226,13 +1125,22 @@ function updateUI() {
updateElementText("last_share", data.total_last_share || "");
// Update Estimated Earnings metrics
- updateElementText("estimated_earnings_per_day_sats", numberWithCommas(data.estimated_earnings_per_day_sats) + " sats");
- updateElementText("estimated_earnings_next_block_sats", numberWithCommas(data.estimated_earnings_next_block_sats) + " sats");
- updateElementText("estimated_rewards_in_window_sats", numberWithCommas(data.estimated_rewards_in_window_sats) + " sats");
+ updateElementText("estimated_earnings_per_day_sats", numberWithCommas(data.estimated_earnings_per_day_sats) + " SATS");
+ updateElementText("estimated_earnings_next_block_sats", numberWithCommas(data.estimated_earnings_next_block_sats) + " SATS");
+ updateElementText("estimated_rewards_in_window_sats", numberWithCommas(data.estimated_rewards_in_window_sats) + " SATS");
// Update last updated timestamp
const now = new Date(Date.now() + serverTimeOffset);
- updateElementHTML("lastUpdated", "Last Updated: " + now.toLocaleString() + "");
+ const options = {
+ year: 'numeric',
+ month: 'short',
+ day: 'numeric',
+ hour: '2-digit',
+ minute: '2-digit',
+ second: '2-digit',
+ hour12: true
+ };
+ updateElementHTML("lastUpdated", "Last Updated: " + now.toLocaleString('en-US', options) + "");
// Update chart with normalized data if it exists
if (trendChart) {
@@ -1251,292 +1159,6 @@ function updateUI() {
console.error("Error updating UI:", error);
}
}
-function highlightBlockFound(blockHeight) {
- if (!trendChart || !trendChart.data.labels || trendChart.data.labels.length === 0) {
- console.warn("Chart not initialized or no labels available");
- return;
- }
-
- if (!latestMetrics || !latestMetrics.hashrate_60sec) {
- console.warn("Cannot highlight block - latestMetrics or hashrate is not available");
- return;
- }
-
- // Get time in Los Angeles timezone
- const now = new Date(Date.now() + serverTimeOffset);
- const options = { hour12: false, hour: '2-digit', minute: '2-digit', timeZone: 'America/Los_Angeles' };
- let currentTime = now.toLocaleTimeString('en-US', options);
-
- // Ensure time format matches EXACTLY with chart.data.labels format
- if (trendChart.data.labels.length > 0) {
- // If the chart has a specific time format, adapt to it
- const sampleLabel = trendChart.data.labels[trendChart.data.labels.length - 1];
- if (sampleLabel.length === 5) { // HH:MM format
- currentTime = currentTime.length > 5 ? currentTime.substring(0, 5) : currentTime;
- }
- }
-
- console.log("Adding block point at time:", currentTime);
-
- // Find the nearest matching label
- const matchingLabel = findMatchingLabel(currentTime, trendChart.data.labels, 5); // 5 minutes tolerance
- if (!matchingLabel) {
- console.warn(`Time ${currentTime} not found in chart labels:`, trendChart.data.labels);
- return;
- }
-
- // Add the block found point to the chart data
- const blockFoundPoint = {
- time: matchingLabel, // Use the matching label
- value: latestMetrics.hashrate_60sec,
- unit: latestMetrics.hashrate_60sec_unit || 'th/s',
- flash: true,
- timestamp: new Date().toISOString() // Add a timestamp for reference
- };
-
- if (!latestMetrics.block_found_points) {
- latestMetrics.block_found_points = [];
- }
-
- latestMetrics.block_found_points.push(blockFoundPoint);
-
- // Save block found points to localStorage
- try {
- localStorage.setItem('blockFoundPoints', JSON.stringify(latestMetrics.block_found_points));
- } catch (e) {
- console.error("Error saving block found points to localStorage:", e);
- }
-
- // Update the chart with the new block found point
- updateChartWithNormalizedData(trendChart, latestMetrics);
-
- // Flash the point by animating opacity
- flashBlockFoundIndicator();
-
- // Call forceBlockPointsVisibility here
- forceBlockPointsVisibility();
-}
-
-
-// Add this function to create a continuous flashing effect
-function flashBlockFoundIndicator() {
- // Remove the flash count limit to make it indefinite
- // Store the interval ID globally so we can reference it later if needed
- if (window.blockFlashInterval) {
- clearInterval(window.blockFlashInterval);
- }
-
- // Set up continuous flashing with oscillating opacity and size
- window.blockFlashInterval = setInterval(() => {
- // Toggle visibility of the dataset
- if (trendChart && trendChart.data.datasets.length > 1) {
- // Find the block dataset
- const blockDataset = trendChart.data.datasets.find(ds => ds.label === 'Block Found');
- if (!blockDataset) return;
-
- // Create a pulsing effect using sine wave for smoother transition
- const time = Date.now() / 1000; // Time in seconds
- const opacity = 0.5 + (Math.sin(time * 3) + 1) / 2 * 0.5; // Oscillate between 0.5 and 1.0
- const size = 10 + Math.sin(time * 2) * 5; // Size oscillates between 5 and 15
-
- // Update all properties
- blockDataset.pointBackgroundColor = `rgba(50, 205, 50, ${opacity})`;
- blockDataset.borderColor = `rgba(50, 205, 50, ${opacity})`;
- blockDataset.pointRadius = size;
- blockDataset.z = 9999; // Keep z-index high
- blockDataset.order = -1; // Keep order priority high
-
- // Apply a glow effect by adjusting border properties
- blockDataset.borderWidth = 3 + Math.sin(time * 4) * 2; // Border width oscillates
-
- // Force a chart update with minimal animation
- trendChart.update('none');
-
- // At the end of updateChartWithNormalizedData after chart.update('none');
- ensureBlockPointsDisplayed();
- }
- }, 50); // Update very frequently for smoother animation
-}
-
-// Fix the forceBlockPointsVisibility function to improve how it finds point coordinates
-function forceBlockPointsVisibility() {
- // Increase the delay to give Chart.js more time to render
- setTimeout(() => {
- try {
- const canvas = document.getElementById('trendGraph');
- if (!canvas) return;
-
- canvas.parentElement.classList.add('chart-container-relative');
-
- let overlay = document.getElementById('blockPointsOverlay');
- if (!overlay) {
- overlay = document.createElement('div');
- overlay.id = 'blockPointsOverlay';
- overlay.style.position = 'absolute';
- overlay.style.top = '0';
- overlay.style.left = '0';
- overlay.style.width = '100%';
- overlay.style.height = '100%';
- overlay.style.pointerEvents = 'none';
- canvas.parentElement.appendChild(overlay);
- }
-
- // Clear previous points
- overlay.innerHTML = '';
-
- if (!latestMetrics || !latestMetrics.block_found_points ||
- !latestMetrics.block_found_points.length) return;
-
- const chart = trendChart;
- if (!chart || !chart.chartArea) return;
-
- // Add CSS animation if not already added
- if (!document.getElementById('block-marker-animation')) {
- const style = document.createElement('style');
- style.id = 'block-marker-animation';
- style.textContent = `
- @keyframes pulse-block-marker {
- 0% { transform: translate(-50%, -50%) rotate(45deg) scale(1); opacity: 1; }
- 50% { transform: translate(-50%, -50%) rotate(45deg) scale(1.3); opacity: 0.8; }
- 100% { transform: translate(-50%, -50%) rotate(45deg) scale(1); opacity: 1; }
- }
- .chart-container-relative {
- position: relative;
- }
- `;
- document.head.appendChild(style);
- }
-
- // Fixed approach: use canvas width/height and chartarea for positioning
- const chartArea = chart.chartArea;
- const xAxis = chart.scales.x;
- const yAxis = chart.scales.y;
-
- // For debugging coordinates
- console.log("Chart area:", chartArea);
- console.log("Block points:", latestMetrics.block_found_points);
-
- // For each block point, create a visible marker
- latestMetrics.block_found_points.forEach((point, index) => {
- // Find the time value in the labels array
- const timeLabel = point.time;
- const labelIndex = chart.data.labels.indexOf(timeLabel);
-
- if (labelIndex === -1) {
- console.warn(`Time "${timeLabel}" not found in chart labels:`, chart.data.labels);
- return; // Skip if not found
- }
-
- // Calculate position based on axes and chart area
- const value = parseFloat(point.value);
- const unit = point.unit || 'th/s';
- const normalizedValue = normalizeHashrate(value, unit);
-
- // Map data values to pixel positions
- const xPercent = (labelIndex) / (chart.data.labels.length - 1);
- const xPosition = chartArea.left + (xPercent * (chartArea.right - chartArea.left));
-
- // Get Y position (must be within chart boundaries)
- const yPosition = yAxis.getPixelForValue(normalizedValue);
-
- // Debug logging
- console.log(`Block point ${index}: ${timeLabel}, Label index: ${labelIndex}, X: ${xPosition}, Y: ${yPosition}`);
-
- // Create a marker element
- const marker = document.createElement('div');
- marker.className = 'block-found-marker';
- marker.style.position = 'absolute';
- marker.style.left = `${xPosition}px`;
- marker.style.top = `${yPosition}px`;
- marker.style.width = '20px'; // Larger for better visibility
- marker.style.height = '20px';
- marker.style.backgroundColor = 'green';
- marker.style.borderRadius = '2px';
- marker.style.transform = 'translate(-50%, -50%) rotate(45deg)';
- marker.style.zIndex = '9999';
- marker.style.boxShadow = '0 0 12px rgba(50, 205, 50, 0.9)';
- marker.style.animation = 'pulse-block-marker 2s infinite';
-
- // Add tooltip on hover
- marker.title = `Block found at ${timeLabel} with hashrate ${formatHashrateForDisplay(value, unit)}`;
-
- // Add it to the overlay
- overlay.appendChild(marker);
- });
-
- } catch (e) {
- console.error("Error forcing block points visibility:", e);
- }
- }, 500); // Increased delay to ensure chart is fully rendered
-}
-
-// Add this function to handle block point placement more intelligently
-function ensureBlockPointsDisplayed() {
- if (!trendChart || !latestMetrics || !latestMetrics.block_found_points) return;
- if (latestMetrics.block_found_points.length === 0) return;
- console.log("Ensuring block points displayed:", latestMetrics.block_found_points);
-
- const blockPoints = [];
- const labels = trendChart.data.labels;
- if (!labels || labels.length === 0) {
- console.warn("No labels available for placement");
- return;
- }
-
- // For each block point, try to find an exact or near match using our helper
- latestMetrics.block_found_points.forEach(point => {
- // Format the time like "HH:MM" if needed
- const formattedTime = (point.time.trim().length === 8 && point.time.indexOf(':') !== -1)
- ? point.time.trim().substring(0, 5)
- : point.time.trim();
-
- // Log the block point time and chart labels for debugging
- const validLabels = new Set(labels);
- console.log(`Comparing block point "${formattedTime}" with chart labels:`, [...validLabels].map(l => `"${l}"`));
-
- // Use our helper to find a matching label (exact or within tolerance)
- const match = findMatchingLabel(formattedTime, labels, 5); // 5 minutes tolerance
- if (match) {
- const val = parseFloat(point.value);
- const unit = point.unit || 'th/s';
- blockPoints.push({
- x: match,
- y: normalizeHashrate(val, unit)
- });
- // Update the point's time for future lookups
- point.originalTime = point.time;
- point.time = match;
- } else {
- console.warn(`No close match found for ${formattedTime}`);
- }
- });
-
- if (blockPoints.length > 0) {
- console.log("Adding block points to chart:", blockPoints);
- const blockDataset = {
- label: 'Block Found',
- data: blockPoints,
- borderColor: 'rgba(50, 205, 50, 1)', // Fully opaque
- backgroundColor: 'rgba(50, 205, 50, 1)',
- pointRadius: 12,
- pointHoverRadius: 15,
- pointStyle: 'rectRot',
- borderWidth: 3,
- showLine: false,
- order: -10,
- z: 9999
- };
-
- const existingIndex = trendChart.data.datasets.findIndex(ds => ds.label === 'Block Found');
- if (existingIndex !== -1) {
- trendChart.data.datasets[existingIndex] = blockDataset;
- } else {
- trendChart.data.datasets.push(blockDataset);
- }
- trendChart.update('none');
- setTimeout(forceBlockPointsVisibility, 100);
- }
-}
// Update unread notifications badge in navigation
function updateNotificationBadge() {
@@ -1609,138 +1231,9 @@ $(document).ready(function () {
}
};
- // You might also want to modify your cleanupBlockFoundPoints function:
- function cleanupBlockFoundPoints() {
- try {
- const savedPoints = localStorage.getItem('blockFoundPoints');
- if (savedPoints) {
- const points = JSON.parse(savedPoints);
-
- // Only keep points from the last 2 hour - this is more appropriate for chart timespan
- const now = Date.now();
- const twoHourAgo = now - (2 * 60 * 60 * 1000); // New 2 hour time limit
-
- // Filter out old or corrupted points
- const validPoints = points.filter(point => {
- // If we have a block timestamp, use it to filter by time
- if (point && point.timestamp) {
- const pointTime = new Date(point.timestamp).getTime();
- return pointTime > twoHourAgo;
- }
-
- // Fallback validation for older points without timestamps
- return point && point.time && typeof point.time === 'string' &&
- point.value && !isNaN(parseFloat(point.value));
- });
-
- // Add timestamps to any remaining points for future filtering
- const updatedPoints = validPoints.map(point => {
- if (!point.timestamp) {
- point.timestamp = new Date().toISOString();
- }
- return point;
- });
-
- if (updatedPoints.length !== points.length) {
- console.log(`Cleaned up ${points.length - updatedPoints.length} invalid or old block points`);
- localStorage.setItem('blockFoundPoints', JSON.stringify(updatedPoints));
- }
-
- return updatedPoints;
- }
- } catch (e) {
- console.error("Error cleaning up block found points:", e);
- // If there's an error, clear the storage to start fresh
- localStorage.removeItem('blockFoundPoints');
- }
- return [];
- }
-
- // Add this after your cleanupBlockFoundPoints function
- function resetBlockPoints() {
- // Clear out any old block points that might be causing issues
- console.log("Resetting block points in localStorage");
- localStorage.removeItem('blockFoundPoints');
-
- if (latestMetrics) {
- latestMetrics.block_found_points = [];
- }
- }
-
- // Add a button to reset block points (for debugging)
- function addResetBlockPointsButton() {
- const button = document.createElement('button');
- button.id = 'resetBlockPointsBtn';
- button.innerText = 'Reset Block Points';
- button.style.position = 'fixed';
- button.style.bottom = '20px';
- button.style.right = '20px';
- button.style.zIndex = '1000';
- button.style.background = '#f7931a';
- button.style.color = 'black';
- button.style.border = 'none';
- button.style.padding = '8px 16px';
- button.style.borderRadius = '4px';
- button.style.cursor = 'pointer';
- button.style.display = 'none'; // Hidden by default
-
- button.onclick = function () {
- resetBlockPoints();
- button.innerText = 'Block Points Reset';
- setTimeout(() => {
- button.innerText = 'Reset Block Points';
- }, 2000);
-
- // Refresh the chart
- if (trendChart) {
- updateChartWithNormalizedData(trendChart, latestMetrics);
- }
- };
-
- document.body.appendChild(button);
-
- // Show button on B
- document.addEventListener('keydown', function (e) {
- if (e.shiftKey && e.key === 'B') {
- button.style.display = button.style.display === 'none' ? 'block' : 'none';
- }
- });
- }
-
- // Replace your existing localStorage block points loading code with:
- try {
- const cleanedPoints = cleanupBlockFoundPoints();
- if (cleanedPoints.length > 0) {
- if (!latestMetrics) {
- latestMetrics = {};
- }
- latestMetrics.block_found_points = cleanedPoints;
- console.log(`Loaded ${cleanedPoints.length} block points from storage`);
- }
- } catch (e) {
- console.error("Error loading block found points from localStorage:", e);
- }
-
- // Inside your document ready function, add this before the chart initialization
- addResetBlockPointsButton();
-
// Initialize the chart
trendChart = initializeChart();
- // After initializing trendChart
- setTimeout(ensureBlockPointsDisplayed, 1000);
-
- // THIRD: If we have block found points, apply them to the chart
- if (latestMetrics && latestMetrics.block_found_points && latestMetrics.block_found_points.length > 0) {
- console.log("Initializing chart with block points:", latestMetrics.block_found_points);
- // Create minimal data to initialize chart with block points
- const initialData = {
- block_found_points: latestMetrics.block_found_points,
- hashrate_60sec_unit: 'th/s' // Provide default unit for normalization
- };
- updateChartWithNormalizedData(trendChart, initialData);
- }
-
// Apply any saved arrows to DOM on page load
arrowIndicator.forceApplyArrows();