Torn Custom Race Organizer

Debugging: Move 1-lap races with 1/2 drivers to top and highlight when new race data is loaded

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Torn Custom Race Organizer 
// @namespace    https://greasyfork.org
// @license      MIT
// @version      2.9
// @description  Debugging: Move 1-lap races with 1/2 drivers to top and highlight when new race data is loaded
// @author       yoyoYossarian and ChatGPT
// @match        https://www.torn.com/loader.php?sid=racing*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    console.log("[Torn Custom Race Organizer] Script is running...");

    // Function to rearrange races
    function rearrangeRaces() {
        console.log("[Torn Custom Race Organizer] Attempting to rearrange races...");

        const eventList = document.querySelector('ul.events-list');
        if (!eventList) {
            console.warn("[Torn Custom Race Organizer] No event list found.");
            return;
        }

        const races = Array.from(eventList.children);
        console.log(`[Torn Custom Race Organizer] Found ${races.length} races in the list.`);

        const priorityRaces = [];

        races.forEach((race, index) => {
            const trackElement = race.querySelector('li.track');
            const lapsElement = trackElement?.querySelector('span.laps');
            const driversElement = race.querySelector('li.drivers');

            if (trackElement && lapsElement && driversElement) {
                const laps = lapsElement.textContent.trim();
                const driverCountText = driversElement.textContent.replace(/\s+/g, ' ').trim();
                const match = driverCountText.match(/(\d+)\s*\/\s*(\d+)/);
                const currentDrivers = match ? parseInt(match[1], 10) : null;
                const maxDrivers = match ? parseInt(match[2], 10) : null;

                console.log(`[Torn Custom Race Organizer] Race ${index + 1}: Laps=${laps}, Drivers=${currentDrivers}/${maxDrivers}`);

                if (laps.includes("1 lap") && currentDrivers === 1 && maxDrivers === 2) {
                    race.style.backgroundColor = 'rgba(152, 251, 152, 0.5)'; // Highlight
                    priorityRaces.push(race);
                    console.log(`[Torn Custom Race Organizer] Highlighting and prioritizing race ${index + 1}`);
                }
            } else {
                console.warn(`[Torn Custom Race Organizer] Could not extract race info for race ${index + 1}`);
            }
        });

        if (priorityRaces.length > 0) {
            console.log(`[Torn Custom Race Organizer] Moving ${priorityRaces.length} priority races to the top.`);
            priorityRaces.forEach((race) => eventList.prepend(race));
        } else {
            console.log("[Torn Custom Race Organizer] No priority races found.");
        }

        console.log(`[Torn Custom Race Organizer] Rearrangement complete at ${new Date().toLocaleTimeString()}`);
    }

    // Function to monitor network requests for new race data
    function monitorNetworkRequests() {
        console.log("[Torn Custom Race Organizer] Monitoring network requests for race updates...");

        // Intercept XMLHttpRequests (XHR)
        const originalXHR = window.XMLHttpRequest.prototype.open;
        window.XMLHttpRequest.prototype.open = function (method, url) {
            if (url.includes("loader.php?sid=racing&tab=customrace")) {
                console.log(`[Torn Custom Race Organizer] Detected XHR request for race updates: ${url}`);
                setTimeout(() => {
                    console.log("[Torn Custom Race Organizer] Running rearrangeRaces() after XHR request.");
                    rearrangeRaces();
                }, 1000); // Delay to allow Torn to update the UI
            }
            return originalXHR.apply(this, arguments);
        };

        // Intercept Fetch API calls (modern alternative to XHR)
        const originalFetch = window.fetch;
        window.fetch = function (url, options) {
            if (typeof url === "string" && url.includes("loader.php?sid=racing&tab=customrace")) {
                console.log(`[Torn Custom Race Organizer] Detected Fetch request for race updates: ${url}`);
                setTimeout(() => {
                    console.log("[Torn Custom Race Organizer] Running rearrangeRaces() after Fetch request.");
                    rearrangeRaces();
                }, 1000);
            }
            return originalFetch.apply(this, arguments);
        };
    }

    // Initial setup: Wait for the event list and monitor network requests
    function waitForElement(selector, callback) {
        console.log(`[Torn Custom Race Organizer] Waiting for ${selector} to appear...`);
        const checkInterval = setInterval(() => {
            const element = document.querySelector(selector);
            if (element) {
                clearInterval(checkInterval);
                console.log(`[Torn Custom Race Organizer] Found ${selector}!`);
                callback(element);
            }
        }, 100);
    }

    waitForElement('ul.events-list', (element) => {
        console.log('[Torn Custom Race Organizer] Event list detected! Running initial sorting.');
        rearrangeRaces();
        monitorNetworkRequests();
    });

})();