🏆Daily Score & Power Ranking Enhanced ⭐ClopoStars⭐

A humble script to enhance the Daily Score and Power Ranking tables on ClopoStars.com, making them more insightful and user-friendly. Shared with care to add ease and clarity. Use at your own risk—I’m not responsible for issues, data loss, or account troubles. This script is made with good intentions, never to harm or invade anyone’s space. Tinker wisely, stay safe, and may your scores always shine bright!

// ==UserScript==
// @name         🏆Daily Score & Power Ranking Enhanced ⭐ClopoStars⭐
// @namespace    http://tampermonkey.net/
// @version      2.6
// @description  A humble script to enhance the Daily Score and Power Ranking tables on ClopoStars.com, making them more insightful and user-friendly. Shared with care to add ease and clarity. Use at your own risk—I’m not responsible for issues, data loss, or account troubles. This script is made with good intentions, never to harm or invade anyone’s space. Tinker wisely, stay safe, and may your scores always shine bright!
// @author       ChatGPT-4-turbo
// @match        *://clopostars.com/allies/cards
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    console.log('🚀 Stable Suzi GJ Loaded');

    function createHeaderCell(text) {
        const header = document.createElement('th');
        header.textContent = text;
        header.style.textAlign = 'center';
        header.style.padding = '10px';
        header.style.fontWeight = 'bold';
        return header;
    }

    function createStyledCell(content, color = '#808080') {
        const cell = document.createElement('td');
        cell.textContent = content;
        cell.style.textAlign = 'center';
        cell.style.fontWeight = 'bold';
        if (color) cell.style.color = color;
        return cell;
    }

    function calculateCappedScore(row, index) {
    const getValue = (index) => parseInt(row.querySelector(`td:nth-child(${index})`)?.textContent.replace(/,/g, '')) || 0;

    const groundPoints = Math.min(Math.floor(getValue(5) / 600000000), 100);
    const airPoints = Math.min(Math.floor(getValue(6) / 50000), 100);
    const bhPoints = Math.min(getValue(7) * 2, 200); // 🥇 BH cap
    const shPoints = Math.min(getValue(8) * 4, 200); // ✈️ SH cap
    const chPoints = Math.min(getValue(9) * 8, 200); // 🏆 CH cap
    const rhPoints = getValue(10) * 10;
    const mercPoints = getValue(11) * 10;
    const phPoints = getValue(12) * 10;

    return groundPoints + airPoints + bhPoints + shPoints + chPoints + rhPoints + mercPoints + phPoints;
    }

    function calculateImpact(score, power) { // Unified Calculation Function
        if (power === '0' && score > 0) return '+∞';
        if (power === '0' && score === 0) return '0';
        if (!power || power === 'N/A') return 'N/A';
        return (score / parseFloat(power)).toFixed(2);
    }

    function modifyDailyScoresTable(playerStats) {
        const dailyScoresTable = document.querySelector('table');
        const headerRow = dailyScoresTable.querySelector('thead tr');

        // Update "Rank" header to "Tier Level"
        const rankHeader = headerRow.querySelector('th:nth-child(1)');
        if (rankHeader) rankHeader.textContent = 'Tier Level';

        // Dynamic Header Management
        const headersToInsert = ['Wild Impact', 'Capped Score', 'Capped Impact'];
        const totalScoreHeader = [...headerRow.querySelectorAll('th')].find(th => th.textContent.trim() === 'Total Score');

        if (totalScoreHeader) {
            totalScoreHeader.textContent = 'Wild Score';
            headersToInsert.reverse().forEach(header => {
                headerRow.insertBefore(createHeaderCell(header), totalScoreHeader);
            });
        }

        // Helper function for creating plain (unstyled) cells
        const createPlainCell = (content) => {
            const cell = document.createElement('td');
            cell.textContent = content;
            cell.style.textAlign = 'center'; // Keep alignment consistent
            return cell;
        };

        // Process Player Rows
        dailyScoresTable.querySelectorAll('tbody tr').forEach(row => {
            const playerName = row.querySelector('td:nth-child(3)')?.innerText.trim().toLowerCase().replace(/\s+/g, '');
            const stats = playerStats[playerName] || { tier: 'N/A', color: '#808080', power: 'N/A' };

            const insertCell = (value, refIndex) => {
                const cell = createPlainCell(value); // Use plain cell for values
                row.insertBefore(cell, row.querySelector(`td:nth-child(${refIndex})`));
            };

            // Insert Tier Level (keeps the styling for Tier Level only)
            row.replaceChild(createStyledCell(stats.tier, stats.color), row.querySelector('td:nth-child(1)'));

            // Insert Capped Impact & Capped Score (unstyled)
            const cappedScore = calculateCappedScore(row);
            insertCell(calculateImpact(cappedScore, stats.power), 4);
            insertCell(cappedScore, 5);

            // Insert Wild Impact (unstyled)
            const wildScore = parseInt(row.querySelector('td:nth-child(6)')?.textContent.replace(/,/g, '')) || 0;
            insertCell(calculateImpact(wildScore, stats.power), 6);
        });
    }

    function getPlayerStats(rankingTable) { // Modified Function
        const playerStats = {};
        rankingTable.querySelectorAll('tbody tr').forEach(row => {
            const playerName = row.querySelector('td:nth-child(3)')?.innerText.trim().toLowerCase().replace(/\s+/g, '');
            const tier = row.querySelector('td:nth-child(1)')?.innerText.trim();
            const color = row.querySelector('td:nth-child(1)')?.style.color;
            const power = row.querySelector('td:nth-child(4)')?.innerText.trim();

            if (playerName) {
                playerStats[playerName] = { tier, color, power: power || 'N/A' };
            }
        });
        return playerStats;
    }

    function modifyPowerRankingTable(rankingTable) {
        const rows = rankingTable.querySelectorAll('tbody tr');
        const totalPlayers = rows.length;
        const headerRow = rankingTable.querySelector('thead tr');

        const rankHeader = headerRow.querySelector('th:nth-child(1)');
        if (rankHeader) {
            rankHeader.textContent = 'Tier Level';
        }

        rows.forEach((row, index) => {
            const rank = index + 1;
            const percentage = (rank / totalPlayers) * 100;

            let tier = 'T5';
            let color = '#808080';

            if (percentage <= 4.64) { tier = 'T1'; color = '#FFD700'; }
            else if (percentage <= 18.64) { tier = 'T2'; color = '#C0C0C0'; }
            else if (percentage <= 39.09) { tier = 'T3'; color = '#CD7F32'; }
            else if (percentage <= 66.86) { tier = 'T4'; color = '#1E90FF'; }

            const tierCell = createStyledCell(tier, color);
            row.replaceChild(tierCell, row.querySelector('td:nth-child(1)'));
        });
    }

	function waitForPowerRankingLoad(callback) {
        const tables = document.querySelectorAll('table');
        if (tables.length < 2) {
            setTimeout(() => waitForPowerRankingLoad(callback), 500);
            return;
        }

        const rankingTable = tables[1];
        const tbody = rankingTable.querySelector('tbody');

        if (!tbody || tbody.children.length === 0) {
            setTimeout(() => waitForPowerRankingLoad(callback), 500);
            return;
        }

        modifyPowerRankingTable(rankingTable);
        callback(rankingTable);
    }

    // Function to enable sorting with the new descending-first logic
    function enableSorting() {
        const table = document.querySelector('table'); // Selects the Daily Score table
        if (!table) return;

        let lastSortedColumn = null;
        let lastSortDirection = 'desc'; // Default sorting order is descending

        table.querySelectorAll('th').forEach((header, index) => {
            if (['Capped Impact', 'Capped Score', 'Wild Impact', 'Wild Score'].includes(header.textContent.trim())) {
                header.style.cursor = 'pointer';
                header.addEventListener('click', () => {
                    const isSameColumn = lastSortedColumn === index;

                    if (isSameColumn) {
                        // Only switch to ascending if the same column is clicked twice in a row
                        lastSortDirection = lastSortDirection === 'desc' ? 'asc' : 'desc';
                    } else {
                        // New column clicked, reset sorting to descending
                        lastSortDirection = 'desc';
                        lastSortedColumn = index;
                    }

                    sortTableByColumn(table, index, lastSortDirection);
                    updateSortingIndicator(header, lastSortDirection);
                });
            }
        });
    }

    // Function to sort the table by the clicked column
    function sortTableByColumn(table, columnIndex, direction) {
        const tbody = table.querySelector('tbody');
        const rows = Array.from(tbody.querySelectorAll('tr'));

        rows.sort((rowA, rowB) => {
            const cellA = rowA.children[columnIndex]?.textContent.trim().replace(/,/g, '');
            const cellB = rowB.children[columnIndex]?.textContent.trim().replace(/,/g, '');

            const valueA = parseFloat(cellA) || (cellA === 'N/A' ? -Infinity : 0);
            const valueB = parseFloat(cellB) || (cellB === 'N/A' ? -Infinity : 0);

            return direction === 'asc' ? valueA - valueB : valueB - valueA;
        });

        rows.forEach(row => tbody.appendChild(row));
    }

    // Function to update sorting indicators and highlight sorted column
    function updateSortingIndicator(header, direction) {
        // Ensure each header retains its original text
        document.querySelectorAll('th').forEach(th => {
            if (!th.dataset.originalText) {
                th.dataset.originalText = th.textContent.trim();
            }
            th.innerHTML = th.dataset.originalText.replace(/▲|▼/g, ''); // Reset text
            th.style.color = ''; // Reset header color
        });

        // Change the text color of the sorted column to gold
        header.style.color = '#FFD700';

        // Create sorting arrow at the beginning of the header
        const arrow = document.createElement('span');
        arrow.textContent = direction === 'asc' ? '▲' : '▼';
        arrow.style.color = '#FFD700'; // Gold color for visibility
        arrow.style.fontWeight = 'bold';
        arrow.style.marginRight = '4px'; // Reduce space between arrow and text

        // Insert the arrow at the beginning of the header text
        header.innerHTML = ''; // Clear existing content
        header.appendChild(arrow);
        header.appendChild(document.createTextNode(header.dataset.originalText)); // Restore header text
    }

    // Call enableSorting() after modifying the table
    function startScript() {
        waitForPowerRankingLoad((rankingTable) => {
            const playerStats = getPlayerStats(rankingTable);
            modifyDailyScoresTable(playerStats);
            enableSorting();// Ensure sorting is enabled only after the table is updated
        });
    }

    function observeUrlChanges() {
        let lastUrl = location.href;
        new MutationObserver(() => {
            const currentUrl = location.href;
            if (currentUrl !== lastUrl) {
                lastUrl = currentUrl;
                if (/https:\/\/clopostars\.com\/allies\/cards/.test(currentUrl)) {
                    startScript();
                }
            }
        }).observe(document, { subtree: true, childList: true });
    }

    if (document.readyState === 'complete' || document.readyState === 'interactive') {
        startScript();
        observeUrlChanges();
    } else {
        document.addEventListener('DOMContentLoaded', () => {
            startScript();
            observeUrlChanges();
        });
    }
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址