您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Optimized OC success chance calculator
当前为
// ==UserScript== // @name OC Success Chance 2.0 // @namespace http://tampermonkey.net/ // @version 2.0.7 // @description Optimized OC success chance calculator // @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; let processing = false; const debounceDelay = 300; // Centralized error handling const logError = (message, error) => { console.error(`[OC Success] ${message}`, error?.message || error); }; // Debounce function for performance function debounce(func, wait) { let timeout; return (...args) => { clearTimeout(timeout); timeout = setTimeout(() => func.apply(this, args), wait); }; } // Generic API caller async function callOCAPI(endpoint, data) { return new Promise((resolve, reject) => { GM.xmlHttpRequest({ method: 'POST', url: `https://tornprobability.com:3000/${endpoint}`, headers: {'Content-Type': 'application/json'}, data: JSON.stringify(data), onload: (response) => { try { resolve(JSON.parse(response.responseText)); } catch (err) { logError('API parse error', err); reject(err); } }, onerror: (err) => { logError('API request failed', err); reject(err); } }); }); } // Process individual OC element async function processOCElement(element) { const ocName = element.querySelector('.panelTitle___aoGuV')?.textContent; if (!ocName || !['Blast From The Past', 'Break The Bank'].includes(ocName)) return; const slots = element.querySelectorAll('.wrapper___Lpz_D'); const successChances = {}; for (const slot of slots) { try { const fiberKey = Object.keys(slot).find(k => k.startsWith('__reactFiber$')); const key = slot[fiberKey]?.return?.key; const chanceText = slot.querySelector('.successChance___ddHsR')?.textContent; if (key && chanceText) { successChances[key] = parseFloat(chanceText.replace('%', '')); } } catch (error) { logError('Slot processing error', error); } } if (Object.keys(successChances).length === 0) return; try { const endpoint = ocName.replace(/ /g, ''); const { successChance } = await callOCAPI(endpoint, successChances); if (successChance) { ocs.set(ocName, successChance); injectSuccessChance(element, successChance); } } catch (error) { logError('OC processing failed', error); } } // Inject success display function injectSuccessChance(element, chance) { const existing = element.querySelector('.oc-success-chance'); if (existing) { existing.textContent = `Success: ${(chance * 100).toFixed(2)}%`; return; } const display = document.createElement('div'); display.className = 'oc-success-chance'; display.textContent = `Success: ${(chance * 100).toFixed(2)}%`; element.querySelector('.panelTitle___aoGuV')?.after(display); } // Main processing function const processOCs = debounce(() => { if (processing) return; processing = true; requestIdleCallback(() => { try { document.querySelectorAll('.wrapper___U2Ap7:not(.oc-processed)').forEach(async element => { element.classList.add('oc-processed'); await processOCElement(element); }); } catch (error) { logError('Main processing error', error); } finally { processing = false; } }); }, debounceDelay); // MutationObserver setup function initObserver() { if (observer) observer.disconnect(); observer = new MutationObserver(processOCs); observer.observe(document.querySelector('#faction-crimes-root') || document.body, { childList: true, subtree: true, attributes: false, characterData: false }); } // Initialization function initialize() { initObserver(); processOCs(); // Re-process when OC tabs change document.querySelector('.buttonsContainer___aClaa')?.addEventListener('click', () => { document.querySelectorAll('.wrapper___U2Ap7.oc-processed').forEach(el => { el.classList.remove('oc-processed'); }); processOCs(); }); } // Start script if (document.readyState === 'complete') { initialize(); } else { window.addEventListener('load', initialize); } })();