Greasy Fork

[银河奶牛]箱子期望显示

银河奶牛箱子期望显示

目前为 2024-07-03 提交的版本。查看 最新版本

// ==UserScript==
// @name         [银河奶牛]箱子期望显示
// @namespace    http://tampermonkey.net/
// @version      0.24
// @description  银河奶牛箱子期望显示
// @author       Truth_Light
// @license      Truth_Light
// @match        https://www.milkywayidle.com/*
// @match        https://test.milkywayidle.com/*
// ==/UserScript==

(function() {
    'use strict';

    const itemSelector = '.ItemDictionary_drop__24I5f';
    const iconSelector = '.Icon_icon__2LtL_ use';
    const chestNameSelector = '#root > div > div > div.Modal_modalContainer__3B80m > div.Modal_modal__1Jiep > div.ItemDictionary_modalContent__WvEBY > div.ItemDictionary_itemAndDescription__28_he > div.Item_itemContainer__x7kH1 > div > div > div > div > svg > use';
    const resultDisplaySelector = '.ItemDictionary_openToLoot__1krnv';

    let timer = null;
    let chestList = {};
    let specialItemPrices = {
        'Coin': { ask: 1, bid: 1 }, // 默认的特殊物品价值,包括ask和bid价值
        'Cowbell': { ask: 33000, bid: 30000 },
    };

    function initObserver() {
        const observer = new MutationObserver((mutations) => {
            mutations.forEach(() => {
                processItems();
            });
        });

        const config = { attributes: true, childList: true, subtree: true };
        const targetNode = document.body;
        observer.observe(targetNode, config);
    }

    function processItems() {
        const modalContainer = document.querySelector(".Modal_modalContainer__3B80m");
        if (!modalContainer) return; // 如果不存在 Modal_modalContainer__3B80m 元素,则直接返回

        clearTimeout(timer);
        timer = setTimeout(() => {
            const chestNameElem = document.querySelector(chestNameSelector);
            if (!chestNameElem) return;

            const chestNameRaw = chestNameElem.getAttribute('href').split('#').pop() || "Unknown Chest";
            const chestName = formatItemName(chestNameRaw);

            const items = document.querySelectorAll(itemSelector);

            const itemDataList = [];
            let totalAskValue = 0;
            let totalBidValue = 0;

            items.forEach(item => {
                const quantityRangeElem = item.querySelector('div:first-child');
                const quantityRangeText = quantityRangeElem.textContent.trim();
                const quantityRange = parseQuantityRange(quantityRangeText);

                const iconElem = item.querySelector(iconSelector);
                if (!iconElem) return;
                const itemNameRaw = iconElem.getAttribute('href').split('#').pop();//提取链接最后的物品名称
                const itemName = formatItemName(itemNameRaw);//对提取的物品名称进行格式化处理

                let probabilityElem = item.querySelector('div:nth-child(3)');//提取物品的概率
                let probabilityText = probabilityElem ? probabilityElem.textContent.trim() : '';
                probabilityText = probabilityText.replace('~', '');

                let probability;
                if (probabilityText === '') {
                    probability = 1.0; // 如果概率文本为空,则假定掉落率为100%
                } else {
                    probability = parseProbability(probabilityText);
                }

                let expectedOutput = 0;
                if (quantityRange.min === quantityRange.max) {
                    expectedOutput = quantityRange.min * probability;
                } else {
                    const average = (quantityRange.min + quantityRange.max) / 2;
                    expectedOutput = average * probability;
                }

                let itemAskValue = 0;
                let itemBidValue = 0;
                let priceColor = '#E7E7E7';

                if (chestList[itemName]) {
                    // 如果是箱子,直接使用chestList中的价格信息
                    itemAskValue = chestList[itemName].totalAskValue;
                    itemBidValue = chestList[itemName].totalBidValue;
                } else {
                    if (specialItemPrices[itemName]) {
                        itemAskValue = specialItemPrices[itemName].ask;
                        itemBidValue = specialItemPrices[itemName].bid;
                    } else {
                        const marketDataStr = localStorage.getItem('MWITools_marketAPI_json');
                        if (marketDataStr) {
                            try {
                                const marketData = JSON.parse(marketDataStr);
                                if (marketData && marketData.market && marketData.market[itemName]) {
                                    itemAskValue = marketData.market[itemName].ask;
                                    itemBidValue = marketData.market[itemName].bid;

                                    if (itemAskValue === -1 && itemBidValue !== -1) {
                                        itemAskValue = itemBidValue;
                                    }

                                    if (itemAskValue === -1 && itemBidValue === -1) {
                                        priceColor = 'yellow';
                                    } else if (itemAskValue === -1) {
                                        priceColor = '#D95961';
                                    } else if (itemBidValue === -1) {
                                        priceColor = '#2FC4A7';
                                    }
                                } else {
                                    console.error(`未找到物品 ${itemName} 的价格信息`);
                                    priceColor = 'yellow';
                                }

                            } catch (error) {
                                console.error(`解析 MWITools_marketAPI_json 数据时出错:`, error);
                            }
                        } else {
                            console.error('未找到 MWITools_marketAPI_json 的本地存储数据');
                        }
                    }
                }

                const itemTotalAskValue = expectedOutput * itemAskValue;
                const itemTotalBidValue = expectedOutput * itemBidValue;

                totalAskValue += itemTotalAskValue;
                totalBidValue += itemTotalBidValue;

                const itemData = {
                    itemName,
                    quantityRange: `${quantityRange.min}-${quantityRange.max}`,
                    probability: probability * 100,
                    expectedOutput: expectedOutput.toFixed(2),
                    itemAskValue,
                    itemBidValue,
                    itemTotalAskValue: itemTotalAskValue.toFixed(2),
                    itemTotalBidValue: itemTotalBidValue.toFixed(2),
                    priceColor
                };

                itemDataList.push(itemData);

                const itemNameElem = item.querySelector('.Item_name__2C42x');
                if (itemNameElem) {
                    if (priceColor) {
                        itemNameElem.style.color = priceColor;
                    }
                }

            });

            if (itemDataList.length > 0) {
                chestList[chestName] = {
                    items: itemDataList,
                    totalAskValue: totalAskValue.toFixed(2),
                    totalBidValue: totalBidValue.toFixed(2)
                };
                saveChestList();
                displayResult(document.body, totalAskValue, totalBidValue);
            }
        }, 200); // 200ms 延迟
    }

    function saveChestList() {
        localStorage.setItem('chestList', JSON.stringify(chestList));
    }

    function loadChestList() {
        const savedChestList = localStorage.getItem('chestList');
        chestList = savedChestList ? JSON.parse(savedChestList) : {};
    }

    function formatItemName(itemNameRaw) {
        let formattedName = itemNameRaw.replace('#', '').replace(/_/g, ' ').replace(/\b\w/g, char => char.toUpperCase());

        if (formattedName.includes(' ')) {
            const words = formattedName.split(' ');
            let firstWord = words[0];
            const restOfName = words.slice(1).join(' ');
            if (firstWord.endsWith('s') && !firstWord.endsWith("'s")) {
                firstWord = `${firstWord.slice(0, -1)}'${firstWord.slice(-1)}`;
            }
            formattedName = `${firstWord}${restOfName ? " " + restOfName : ""}`;
        }

        return formattedName;
    }





    function parseQuantityRange(rangeText) {
        const parts = rangeText.split('-').map(str => parseInt(str.trim().replace(',', ''), 10));
        if (parts.length === 1) {
            return { min: parts[0], max: parts[0] };
        } else {
            return { min: parts[0], max: parts[1] };
        }
    }

    function parseProbability(probabilityText) {
        const probPercentage = parseFloat(probabilityText.replace('%', ''));
        return probPercentage / 100;
    }

    function formatPrice(value) {
        if (value >= 1000000) {
            return (value / 1000000).toFixed(1) + 'M';
        } else if (value >= 1000) {
            return (value / 1000).toFixed(1) + 'K';
        } else {
            return value.toString();
        }
    }

    function displayResult(container, totalExpectedOutputASK, totalExpectedOutputBID) {
        const formattedASK = formatPrice(totalExpectedOutputASK);
        const formattedBID = formatPrice(totalExpectedOutputBID);

        const dropListContainer = container.querySelector(resultDisplaySelector);

        // 继续执行其他操作
        const previousResults = dropListContainer.querySelectorAll('.resultDiv');
        previousResults.forEach(result => result.remove());

        // 创建期望产出(最低买入价计算)元素
        const minPriceOutput = document.createElement('div');
        minPriceOutput.className = 'resultDiv';
        minPriceOutput.textContent = `期望产出 (最低买入价计算): ${formattedASK}`;
        minPriceOutput.style.color = 'gold';
        minPriceOutput.style.fontSize = '14px';
        minPriceOutput.style.fontWeight = '400';
        minPriceOutput.style.paddingTop = '10px';

        // 创建期望产出(最高收购价计算)元素
        const maxPriceOutput = document.createElement('div');
        maxPriceOutput.className = 'resultDiv';
        maxPriceOutput.textContent = `期望产出 (最高收购价计算): ${formattedBID}`;
        maxPriceOutput.style.color = 'gold';
        maxPriceOutput.style.fontSize = '14px';
        maxPriceOutput.style.fontWeight = '400';
        maxPriceOutput.style.paddingTop = '10px';

        // 插入新创建的元素到掉落物表的最后一个物品后面
        dropListContainer.appendChild(minPriceOutput);
        dropListContainer.appendChild(maxPriceOutput);
    }

    // 初始化时加载已保存的箱子列表
    loadChestList();
    console.log(chestList);
    // 初始化
    initObserver();

})();