OC Success Chance 2.0

Calculates OC Success Chance

当前为 2025-02-14 提交的版本,查看 最新版本

// ==UserScript==
// @name         OC Success Chance 2.0
// @namespace    http://tampermonkey.net/
// @version      2.0.6
// @description  Calculates OC Success Chance
// @author       Allenone [2033011]
// @match        https://www.torn.com/factions.php?step=your*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=torn.com
// @connect      tornprobability.com
// @grant        GM.xmlHttpRequest
// @grant        GM_info
// ==/UserScript==

(function () {
    'use strict';
    const ocs = new Map();
    let observer;

    // Minimal error logging function
    function logError(message, data = null) {
        console.error(`[OC Success Chance] ${message}`, data);
    }

    // Wait for an element to appear in the DOM
    function waitForElement(selector, timeout = 10000) {
        return new Promise((resolve, reject) => {
            const startTime = Date.now();
            const checkInterval = setInterval(() => {
                const element = document.querySelector(selector);
                if (element) {
                    clearInterval(checkInterval);
                    resolve(element);
                } else if (Date.now() - startTime > timeout) {
                    clearInterval(checkInterval);
                    reject(new Error(`Timeout waiting for element: ${selector}`));
                }
            }, 500);
        });
    }

    // Extract success chances from each OC element individually.
    function extractSuccessChances() {
        const ocElements = document.querySelectorAll('.wrapper___U2Ap7');
        if (!ocElements.length) {
            return;
        }

        for (let element of ocElements) {
            // Skip if already processed
            if (element.dataset.ocProcessed) {
                continue;
            }

            const reactFiberKey = Object.keys(element).find(key => key.startsWith("__reactFiber$"));
            if (!reactFiberKey) {
                logError('React fiber key not found for element:', element);
                continue;
            }

            let ocName = element.querySelector('.panelTitle___aoGuV')?.innerText || "Unknown";
            let slots = element.querySelectorAll('.wrapper___Lpz_D');

            const successChances = {};
            for (let slot of slots) {
                const slotFiberKey = Object.keys(slot).find(key => key.startsWith("__reactFiber$"));
                if (!slotFiberKey) {
                    logError('Slot fiber key not found for slot:', slot);
                    continue;
                }

                try {
                    let fiberNode = slot[slotFiberKey];
                    let key = fiberNode.return.key; // e.g., slot-P1, slot-P2, etc.
                    let chanceText = slot.querySelector('.successChance___ddHsR')?.innerText;
                    if (key && chanceText) {
                        successChances[key] = parseFloat(chanceText.replace('%', ''));
                    }
                } catch (error) {
                    logError('Error accessing React properties:', error);
                }
            }

            if (Object.keys(successChances).length > 0) {
                // Process this element’s OC data and mark it processed.
                processOC(element, ocName, successChances);
                element.dataset.ocProcessed = true;
            }
        }
    }

    // Process OC data and calculate success chance for a specific element.
    async function processOC(element, ocName, successChances) {
        if (ocName === 'Blast From The Past') {
            try {
                const success = await BFTP(
                    successChances['slot-P1'],
                    successChances['slot-P2'],
                    successChances['slot-P3'],
                    successChances['slot-P4'],
                    successChances['slot-P5'],
                    successChances['slot-P6']
                );
                if (success.successChance) {
                    ocs.set(ocName, success.successChance);
                    injectSuccessChance(element, success.successChance);
                }
            } catch (error) {
                logError('Error processing Blast From The Past:', error);
            }
        } else if (ocName === 'Break The Bank') {
            try {
                const success = await BTB(
                    successChances['slot-P1'],
                    successChances['slot-P2'],
                    successChances['slot-P3'],
                    successChances['slot-P4'],
                    successChances['slot-P5'],
                    successChances['slot-P6']
                );
                if (success.successChance) {
                    ocs.set(ocName, success.successChance);
                    injectSuccessChance(element, success.successChance);
                }
            } catch (error) {
                logError('Error processing Break The Bank:', error);
            }
        } else {
            // If unsupported, do nothing.
            return;
        }
    }

    // Inject success chance into the specific OC element.
    function injectSuccessChance(element, successChance) {
        const title = element.querySelector('.panelTitle___aoGuV');
        if (title && !element.querySelector('.success-chance')) {
            const successChanceElement = document.createElement('p');
            successChanceElement.innerText = `Success Chance: ${(successChance * 100).toFixed(2)}%`;
            successChanceElement.classList.add('success-chance');
            title.after(successChanceElement);
        }
    }

    // API call for Blast From The Past
    async function BFTP(p1, p2, p3, p4, p5, p6) {
        return new Promise((resolve, reject) => {
            GM.xmlHttpRequest({
                method: 'POST',
                url: 'https://tornprobability.com:3000/BlastFromThePast',
                headers: {
                    'Content-Type': 'application/json'
                },
                data: JSON.stringify({
                    Picklock1: p1,
                    Hacker1: p2,
                    Engineer1: p3,
                    Bomber1: p4,
                    Muscle1: p5,
                    Picklock2: p6
                }),
                onload: (response) => {
                    try {
                        const data = JSON.parse(response.responseText);
                        resolve(data);
                    } catch (err) {
                        logError('Error parsing BFTP response:', err);
                        reject(err);
                    }
                },
                onerror: (err) => {
                    logError('BFTP request failed:', err);
                    reject(err);
                }
            });
        });
    }

    // API call for Break The Bank
    async function BTB(p1, p2, p3, p4, p5, p6) {
        return new Promise((resolve, reject) => {
            GM.xmlHttpRequest({
                method: 'POST',
                url: 'https://tornprobability.com:3000/BreakTheBank',
                headers: {
                    'Content-Type': 'application/json'
                },
                data: JSON.stringify({
                    Robber1: p1,
                    Muscle1: p2,
                    Muscle2: p3,
                    Thief1: p4,
                    Muscle3: p5,
                    Thief2: p6
                }),
                onload: (response) => {
                    try {
                        const data = JSON.parse(response.responseText);
                        resolve(data);
                    } catch (err) {
                        logError('Error parsing BTB response:', err);
                        reject(err);
                    }
                },
                onerror: (err) => {
                    logError('BTB request failed:', err);
                    reject(err);
                }
            });
        });
    }

    // Observe DOM changes and extract success chances.
    function observeDOM() {
        const targetNode = document.querySelector('#faction-crimes-root');
        if (!targetNode) {
            logError('Faction crimes root not found for observation');
            return;
        }
        observer = new MutationObserver(() => {
            extractSuccessChances();
        });
        observer.observe(targetNode, { childList: true, subtree: true });
    }

    // Initialize the script.
    async function init() {
        try {
            await waitForElement('#faction-crimes-root');
            await waitForElement('.wrapper___U2Ap7');
            observeDOM();
            extractSuccessChances();
        } catch (error) {
            logError('Error during initialization:', error);
        }
    }

    init();
})();

QingJ © 2025

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