Hide Long Races

Hide races with more than 5 laps unless they allow any car

// ==UserScript==
// @name         Hide Long Races
// @namespace    http://tampermonkey.net/
// @version      1.12
// @description  Hide races with more than 5 laps unless they allow any car
// @author       YoYo
// @license      MIT
// @match        https://www.torn.com/loader.php?sid=racing*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    console.log("Enhanced Race Filter script loaded.");

    function addRefreshButton() {
        if (document.getElementById("refreshRacesBtn")) return;

        let refreshBtn = document.createElement("button");
        refreshBtn.id = "refreshRacesBtn";
        refreshBtn.textContent = "Refresh Races";
        refreshBtn.style.position = "fixed";
        refreshBtn.style.top = "10px";
        refreshBtn.style.right = "10px";
        refreshBtn.style.padding = "10px";
        refreshBtn.style.background = "#333";
        refreshBtn.style.color = "white";
        refreshBtn.style.border = "none";
        refreshBtn.style.cursor = "pointer";
        refreshBtn.style.zIndex = "1000";
        refreshBtn.style.borderRadius = "5px";
        refreshBtn.onclick = () => {
            console.log("Refresh button clicked, re-filtering races...");
            filterRaces();
        };

        document.body.appendChild(refreshBtn);
    }

    function showNoRacesMessage() {
        if (document.getElementById("noRacesMsg")) return;

        let message = document.createElement("div");
        message.id = "noRacesMsg";
        message.textContent = "No races found.";
        message.style.color = "red";
        message.style.fontSize = "20px";
        message.style.textAlign = "center";
        message.style.marginTop = "20px";

        let raceContainer = document.querySelector(".custom-events-wrap");
        if (raceContainer) {
            raceContainer.appendChild(message);
        }
    }

    function hideNoRacesMessage() {
        let message = document.getElementById("noRacesMsg");
        if (message) message.remove();
    }

    function filterRaces() {
        console.log("Checking races for filtering criteria...");

        let raceElements = document.querySelectorAll(".events-list li");
        let validRaceFound = false;

        raceElements.forEach(li => {
            let hideRace = false;

            // Extract lap count
            let lapsElement = li.querySelector(".laps");
            if (lapsElement) {
                let lapsMatch = lapsElement.textContent.match(/\d+/);
                if (lapsMatch) {
                    let laps = parseInt(lapsMatch[0], 10);
                    console.log(`Race detected with ${laps} laps.`);
                    if (laps > 5) {
                        console.log(`Hiding race: More than 5 laps (${laps} laps).`);
                        hideRace = true;
                    }
                }
            }

            // Extract current and max number of drivers (should be exactly "1 / 2")
            let driversElement = li.querySelector(".drivers");
            if (driversElement) {
                let driversMatch = driversElement.textContent.match(/(\d+)\s*\/\s*(\d+)/);
                if (driversMatch) {
                    let currentDrivers = parseInt(driversMatch[1], 10);
                    let maxDrivers = parseInt(driversMatch[2], 10);
                    console.log(`Race current/max drivers: ${currentDrivers}/${maxDrivers}`);
                    if (currentDrivers !== 1 || maxDrivers !== 2) {
                        console.log(`Hiding race: Does not have exactly 1/2 drivers.`);
                        hideRace = true;
                    }
                }
            }

            // Check for password protection
            let passwordElement = li.querySelector(".password.protected");
            if (passwordElement) {
                console.log("Hiding race: Password-protected.");
                hideRace = true;
            }

            // Check for race start time (should be "waiting" for instant start)
            let startTimeElement = li.querySelector(".startTime");
            if (startTimeElement) {
                let startTime = startTimeElement.textContent.trim().toLowerCase();
                console.log(`Race start time: ${startTime}`);
                if (startTime !== "waiting") {
                    console.log("Hiding race: Not starting immediately.");
                    hideRace = true;
                }
            }

            // Check if race requires a specific car (should allow any car)
            let carElement = li.querySelector(".car");
            if (carElement) {
                let carRequirement = carElement.textContent.trim().toLowerCase();
                console.log(`Car requirement detected: "${carRequirement}"`);
                if (!carRequirement.includes("any car")) { 
                    console.log("Hiding race: Requires a specific car.");
                    hideRace = true;
                }
            }

            // Hide or keep the race
            if (hideRace) {
                li.style.display = "none";
            } else {
                li.style.display = "";
                validRaceFound = true;
            }
        });

        // Display "No races found" message if no valid races exist
        if (!validRaceFound) {
            showNoRacesMessage();
            console.log("No valid races found.");
        } else {
            hideNoRacesMessage();
        }

        console.log("Race filtering process completed.");
    }

    // Run filtering and add UI elements after page load
    window.addEventListener("load", () => {
        console.log("Page loaded, running race filter...");
        filterRaces();
        addRefreshButton();
    });

    // Mutation observer to detect dynamic updates to the race list
    const observer = new MutationObserver(() => {
        console.log("Detected changes in race list, re-checking...");
        filterRaces();
    });

    observer.observe(document.body, { childList: true, subtree: true });

    console.log("Mutation observer started, waiting for race list updates...");
})();