o
    -š…jR4  ã                   @   s  d dl Z d dlZej d d¡ d dlmZmZ e  ¡ ZedƒZ	e	 
e¡\ZZZerGedƒ er3eeƒ edƒ er>edƒ nedƒ e d ¡ er\ed	ƒ edƒ eed
ƒƒ e d ¡ d dlZd dlZd dlZej ej ej e¡¡¡ d dlmZ dd„ Zedkr‰eƒ  dS dS )é    Nz/opt/ngon/apps)ÚAuthManagerÚgenerate_login_page_htmlÚperformance_30zContent-Type: application/jsonÚ z6{"success": false, "error": "Authentication required"}z{"success": true}zContent-Type: text/htmlzPerformance 30-Day)Úget_performance_datac                  C   sÊ   t dƒ} | r|  d¡stdƒ tdƒ d S | d }| dd¡}tdƒ td|› d|› d	|d
 › d|d › dt |d ¡› dt |d ¡› dt |d ¡› dt |d ¡› dt |d ¡› d|› d�ƒ d S )Né   ÚsuccesszContent-Type: text/html
zA<html><body><h1>Error loading performance data</h1></body></html>ÚdataÚdayszü
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="refresh" content="300">
        <title>Performance Monitoring (zê Days)</title>
        <link rel="stylesheet" href="styles.css">  <!-- Link to your existing styles -->
        <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    </head>
    <body>

        <h1>Performance Monitoring (a   Days)</h1>

        <!-- Bar chart for total current hashrate -->
        <div>
            <canvas id="totalHashrateBar"></canvas>
        </div>

        <!-- Container for total hashrate chart -->
        <div class="chart-container">
            <canvas id="totalHashrateLineChart"></canvas>
        </div>

        <!-- Container for individual containers chart -->
        <div class="chart-container">
            <canvas id="containerLineChart"></canvas>
        </div>

        <!-- List of current container hashrates displayed in a grid, grouped by site -->
        <div class="hashrate-grid-container">
            <div class="hashrate-grid" id="containerHashrateList"></div>
        </div>

        <!-- Regional pool hashrates (post-2026-08-01 two-worker cutover) -->
        <h2 style="text-align: center; color: #e0e0e0;">Current Pool Hashrates</h2>
        <div class="hashrate-grid-container">
            <div class="hashrate-grid" id="poolHashrateList"></div>
        </div>

        <script>
            const totalHashrateCurrent = Útotal_hashrate_currentz;
            const maxPH = Úmax_phz0;
            const containersHashrateCurrent = Úcontainers_hashrate_currentz,;
            const containersHashrate30d = Úcontainers_hashrate_30dz';
            const totalHashrate30d = Útotal_hashrate_30dz+;
            const maxPotentialHashrate = Úmax_potential_hashratez#;
            const poolRegional = Úpool_regionalz;
            const days = u&  ;


            // Function to format ISO time strings to just the date (YYYY-MM-DD)
            function formatDate(isoString) {
                const date = new Date(isoString);
                return date.toISOString().split('T')[0];  // Returns just the date part (YYYY-MM-DD)
            }

            // Render the total current hashrate bar chart
            const totalHashrateCtx = document.getElementById('totalHashrateBar').getContext('2d');
            new Chart(totalHashrateCtx, {
                type: 'bar',
                data: {
                    labels: [''],
                    datasets: [{
                        label: '',
                        data: [totalHashrateCurrent],
                        backgroundColor: ['rgba(255, 102, 0, 0.2)'],
                        borderColor: ['rgba(255, 102, 0, 1)'],
                        borderWidth: 1
                    }]
                },
                options: {
                    indexAxis: 'y',
                    scales: {
                        x: {
                            min: 0,
                            max: maxPH
                        }
                    },
                    plugins: {
                        legend: { display: false }
                    },
                    maintainAspectRatio: false
                }
            });

            // Render individual container hashrates grouped by site in a grid layout
            // Site cards are ours-only: after the 2026-08-01 two-worker cutover the
            // pool only knows ND vs TX, so pool hashrate lives in its own grid below.
            const containerList = document.getElementById('containerHashrateList');
            Object.keys(containersHashrateCurrent).sort().forEach(site => {
                const hashrate = containersHashrateCurrent[site] || 0;
                const maxPotential = maxPotentialHashrate[site] || 0; // Get max potential hashrate for the site or default to 0

                const siteContainer = document.createElement('div');
                siteContainer.className = 'site-group';
                siteContainer.innerHTML = `
                    <h3 style="text-align: center;">${site} 
                    <br>(${maxPotential.toFixed(2)})<br></h3>
                    <span class="hashrate-value">${hashrate.toFixed(2)} PH</span>`;
                containerList.appendChild(siteContainer);
            });

            // One card per Foundry regional sub-account (ND / TX) with our own
            // measured hashrate alongside, plus a roll-up of the retired per-site
            // sub-accounts that stubborn miners are still hashing into.
            const poolList = document.getElementById('poolHashrateList');
            (poolRegional.regions || []).forEach(region => {
                const oursPh = region.ours_ph || 0;
                let deltaHtml = '';
                if (oursPh > 0 && region.ok) {
                    const deltaPct = ((region.ph - oursPh) / oursPh) * 100;
                    const color = Math.abs(deltaPct) > 5 ? '#ffaa00' : '#888';
                    deltaHtml = `<span style="color:${color};font-size:11px;">${deltaPct >= 0 ? '+' : ''}${deltaPct.toFixed(1)}% vs ours</span><br>`;
                }
                const el = document.createElement('div');
                el.className = 'site-group';
                el.innerHTML = `
                    <h3 style="text-align: center;">${region.region} Pool
                    <br>(${region.workers.toLocaleString()} workers)<br></h3>
                    <span class="hashrate-value">${region.ok ? region.ph.toFixed(2) + ' PH' : 'unavailable'}</span><br>
                    <span class="pool-hashrate">Ours: ${oursPh.toFixed(2)} PH</span><br>
                    ${deltaHtml}`;
                poolList.appendChild(el);
            });

            // Stragglers that never took the regional pool config â€” should trend to zero.
            const legacy = poolRegional.legacy || { ph: 0, workers: 0, accounts: [] };
            const legacyBreakdown = (legacy.accounts || []).length
                ? legacy.accounts.map(a => `${a.label}: ${a.ph.toFixed(2)} PH (${a.workers})`).join('<br>')
                : 'All miners on regional workers';
            const legacyEl = document.createElement('div');
            legacyEl.className = 'site-group';
            legacyEl.innerHTML = `
                <h3 style="text-align: center;">Other Subaccounts
                <br>(${legacy.workers.toLocaleString()} workers)<br></h3>
                <span class="hashrate-value" style="color:${(legacy.ph > 0 || legacy.workers > 0) ? '#ffaa00' : '#888'};">${legacy.ph.toFixed(2)} PH</span><br>
                <span class="pool-hashrate">${legacyBreakdown}</span>`;
            poolList.appendChild(legacyEl);

            // Render the individual container line chart grouped by site
            const containerLineCtx = document.getElementById('containerLineChart').getContext('2d');
            const containerLabels = Object.values(containersHashrate30d)[0].map(entry => formatDate(entry.time));  // Format date
            const containerDatasets = Object.keys(containersHashrate30d).sort().map((site, idx) => {
                const data = containersHashrate30d[site].map(entry => entry.value);
                const color = `hsl(${idx * 30}, 70%, 50%)`;  // Different color for each line
                return {
                    label: site,
                    data: data,
                    fill: false,
                    tension: 0.1,
                    borderColor: color,
                    backgroundColor: color
                };
            });

            new Chart(containerLineCtx, {
                type: 'line',
                data: {
                    labels: containerLabels,  // Use formatted date labels
                    datasets: containerDatasets
                },
                options: {
                    plugins: {
                        legend: {
                            display: true,
                            labels: {
                                usePointStyle: true,
                                pointStyle: 'line',
                                color: 'white',  // Set legend text color to white
                                font: {
                                    size: 14  // Set legend text size to 14
                                }
                            }
                        }
                    },
                    tooltip: {
                        callbacks: {
                            labelColor: function(context) {
                                return {
                                    borderColor: context.dataset.borderColor,
                                    backgroundColor: context.dataset.backgroundColor
                                };
                            }
                        },
                        borderWidth: 1
                    },
                    maintainAspectRatio: false,
                    responsive: true
                }
            });

            // Render the total hashrate line chart
            const totalLineCtx = document.getElementById('totalHashrateLineChart').getContext('2d');
            const totalLabels = totalHashrate30d.map(entry => formatDate(entry.time));  // Format date
            const totalData = totalHashrate30d.map(entry => entry.value);
            const color = `rgba(75, 192, 192, 1)`;  // Set chart color

            new Chart(totalLineCtx, {
                type: 'line',
                data: {
                    labels: totalLabels,  // Use formatted date labels
                    datasets: [{
                        label: `Overall Hashrate (${days} Days)`,
                        data: totalData,
                        borderColor: color,
                        backgroundColor: color,
                        fill: false,
                        tension: 0.1
                    }]
                },
                options: {
                    plugins: {
                        legend: {
                            display: true,
                            labels: {
                                usePointStyle: true,
                                pointStyle: 'line',
                                color: 'white',  // Set legend text color to white
                                font: {
                                    size: 14  // Set legend text size to 14
                                }
                            }
                        }
                    },
                    tooltip: {
                        callbacks: {
                            labelColor: function(context) {
                                return {
                                    borderColor: context.dataset.borderColor,
                                    backgroundColor: context.dataset.backgroundColor
                                };
                            }
                        },
                        backgroundColor: function(context) {
                            // Sets the tooltip background to match the line color
                            return context.tooltipItems[0].dataset.borderColor;
                        },
                        borderColor: function(context) {
                            // Sets the tooltip border to match the line color
                            return context.tooltipItems[0].dataset.borderColor;
                        },
                        borderWidth: 1
                    },
                    maintainAspectRatio: false,
                    responsive: true
                }
            });
        </script>

    </body>
    </html>
    )r   ÚgetÚprintÚjsonÚdumps)Úapi_responser	   r
   © r   ú+/var/www/html/ngon/status/performance_30.pyÚ
print_html%   s:   ùó*Ö+Õ,Ô-Ó.Ò/Ñ0Ð1Ïr   Ú__main__)ÚcgiÚsysÚpathÚinsertÚmanagers.auth_managerr   r   ÚFieldStorageÚ_formÚ_authÚrequire_authÚ_auth_requiredÚ_should_exitÚ_headersr   Úexitr   ÚosÚappendÚdirnameÚabspathÚ__file__Úperformance_data_cgir   r   Ú__name__r   r   r   r   Ú<module>   s>   


  
ÿ