pcrclan

Add additional information to ranking list entries.

// ==UserScript==
// @name         pcrclan
// @namespace    pcrclan
// @version      1.0
// @description  Add additional information to ranking list entries.
// @author       You
// @match        https://game.bilibili.com/tool/pcr/chart
// @match        https://game.bilibili.com/tool/pcr/rank
// @match        https://game.bilibili.com/tool/pcr/search
// @icon         https://www.google.com/s2/favicons?sz=64&domain=bilibili.com
// @grant        none
// @require      https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js
// ==/UserScript==

(function() {
    'use strict';

    const rankingListContainerSelector = '.chart-rank-list';
    let isDataLoading = false; // 标志变量记录数据是否正在加载

    function debounce(func, wait, immediate) {
        let timeout;
        return function() {
            const context = this,
                args = arguments;
            const later = function() {
                timeout = null;
                if (!immediate) func.apply(context, args);
            };
            const callNow = immediate && !timeout;
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
            if (callNow) func.apply(context, args);
        };
    }

    function getScoreFromText(txtDiv) {
        try {
            const scoreText = txtDiv.find('div:contains("分数:")').text();
            const scoreMatch = scoreText.match(/分数:(\d+)/);
            if (scoreMatch && scoreMatch[1]) {
                return parseInt(scoreMatch[1], 10);
            } else {
                console.error('无法从文本中提取分数:', scoreText);
                return null;
            }
        } catch (e) {
            console.error('Error getting score:', e);
            return null;
        }
    }

    function calculateWeekAndRemainingHP(score) {
        let week = [1, 1]; // 初始周目
        let remainingHp = 0;
        let currentHP = 6000000;
        const lap_num = [3, 10, 30, 38, 999];
        const hp = [
            [6000000, 8000000, 10000000, 12000000, 15000000],
            [6000000, 8000000, 10000000, 12000000, 15000000],
            [12000000, 14000000, 17000000, 19000000, 22000000],
            [22000000, 23000000, 27000000, 29000000, 31000000],
            [145000000, 150000000, 175000000, 195000000, 210000000]
        ];
        const multiple = [
            [1.2, 1.2, 1.3, 1.4, 1.5],
            [1.6, 1.6, 1.8, 1.9, 2],
            [2, 2, 2.4, 2.4, 2.6],
            [3.5, 3.5, 3.7, 3.8, 4],
            [3.5, 3.5, 3.7, 3.8, 4]
        ];

        while (score >= 0) {
            let lapIndex = lap_num.findIndex(lap => week[0] <= lap);

            let kingIndex = week[1] - 1;
            currentHP = hp[lapIndex][kingIndex];
            let currentMultiple = multiple[lapIndex][kingIndex];

            if (score - currentHP * currentMultiple < 0) {
                remainingHp = Math.round(currentHP - score / currentMultiple); // 四舍五入
                break;
            }
            score -= currentHP * currentMultiple;

            if (++week[1] > 5) {
                week[1] = 1;
                week[0]++;
            }
        }

        return { week: week, remainingHp: remainingHp, currentHP: currentHP };
    }

    function modifyRankingList() {
        const rankingListContainer = $(rankingListContainerSelector);

        if (rankingListContainer.length > 0) {
            rankingListContainer.find('.week-info').remove();
            rankingListContainer.find('.remainingHp-info').remove();

            rankingListContainer.find('ul li').each((index, element) => {
                const $element = $(element);
                const boxDiv = $element.find('.box');

                if (boxDiv.length > 0) {
                    const txtDiv = boxDiv.find('.txt');

                    if (txtDiv.length > 0) {
                        const score = getScoreFromText(txtDiv);

                        if (score !== null) {
                            const result = calculateWeekAndRemainingHP(score);
                            const remainingHpElement = $('<div class="remainingHp-info">血量:' + result.remainingHp + ' / ' + result.currentHP + '</div>');
                            const weekElement = $('<div class="week-info"><div>周目:' + result.week.join('-') + '</div></div>');

                            txtDiv.append(remainingHpElement);
                            boxDiv.append(weekElement);
                        }
                    }
                }
            });

            console.log('Ranking list modified successfully.');
        } else {
            console.error('Ranking list container not found.');
        }
    }

    function addRefreshButton() {
        const button = $('<button id="refresh-button" style="position: fixed; top: 10px; right: 10px; color: #5f96f0; font-size: 0.6875rem; padding: 0 0.9375rem; height: 1.625rem; border-radius: 1.625rem; cursor: pointer; background: #fff; border: none;">刷新计算</button>');
        $('body').prepend(button);

        $('#refresh-button').on('click', () => {
            modifyRankingList();
        });
    }

    $(document).ready(() => {
        // 在文档加载完成时立即执行一次
        modifyRankingList();

        // 添加刷新按钮
        addRefreshButton();

        const observerCallback = function(mutationsList, observer) {
            mutationsList.forEach(function(mutation) {
                if (mutation.type === 'childList') {
                    mutation.addedNodes.forEach(node => {
                        if (node instanceof Element && node.classList.contains('jq-loading')) {
                            console.log('Loading indicator added:', node);
                            isDataLoading = true; // 设置标志为 true 表示数据正在加载
                        }
                    });
                    mutation.removedNodes.forEach(node => {
                        if (node instanceof Element && node.classList.contains('jq-loading')) {
                            console.log('Loading indicator removed:', node);
                            if (isDataLoading) {
                                isDataLoading = false; // 数据加载完成,设置标志为 false
                                modifyRankingList(); // 触发更新逻辑
                            }
                        }
                    });
                }
            });
        };

        const observer = new MutationObserver(debounce(observerCallback, 10));
        observer.observe(document.body, { childList: true, subtree: true });

        // 使用定时器检查 .jq-loading 的状态
        const checkLoadingStatus = setInterval(() => {
            if ($('.jq-loading').length > 0) {
                console.log('Loading indicator detected in the document.');
                isDataLoading = true;
            } else if (isDataLoading) {
                console.log('Loading indicator removed by checking status.');
                isDataLoading = false;
                modifyRankingList(); // 触发更新逻辑
            }
        }, 500); // 每500毫秒检查一次

        // 清除定时器
        window.addEventListener('beforeunload', () => {
            clearInterval(checkLoadingStatus);
            observer.disconnect();
        });

        // 检查初始状态
        if ($('.jq-loading').length > 0) {
            console.log('Initial loading indicator found, setting isDataLoading to true');
            isDataLoading = true;
        }
    });
})();