Nitro Type Top Racer/Team Badges

OPTIMIZED - Instant loading, shared cache, eliminates delays and visual shifts. Adds top racer and team badges with proper bot filtering and display name handling

安裝腳本?
作者推薦腳本

您可能也會喜歡 Nitro Type Flag Check StarTrack+NTL:Legacy

安裝腳本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Nitro Type Top Racer/Team Badges
// @namespace    http://tampermonkey.net/
// @version      3.2.0
// @description  OPTIMIZED - Instant loading, shared cache, eliminates delays and visual shifts. Adds top racer and team badges with proper bot filtering and display name handling
// @match        https://www.nitrotype.com/team/*
// @match        https://www.nitrotype.com/friends
// @match        https://www.nitrotype.com/leagues
// @match        https://www.nitrotype.com/racer/*
// @match        https://www.nitrotype.com/garage*
// @grant        GM_xmlhttpRequest
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_deleteValue
// @connect      ntstartrack.org
// @connect      nitrotype.com
// @license      MIT
// ==/UserScript==
 
(function() {
    'use strict';
 
    // ===== SHARED OPTIMIZATION LAYER (Optional - enhances performance with Leaderboard script) =====
    window.NTShared = window.NTShared || {
        cache: {
            individual: { data: null, timestamp: 0, expiresAt: 0 },
            team: { data: null, timestamp: 0, expiresAt: 0 },
            isbot: new Map()
        },

        setCache(type, data, expiresAt) {
            this.cache[type].data = data;
            this.cache[type].timestamp = Date.now();
            this.cache[type].expiresAt = expiresAt || (Date.now() + 3600000);
            window.dispatchEvent(new CustomEvent('nt-cache-updated', {
                detail: { type, data, expiresAt }
            }));
        },

        getCache(type) {
        const cached = this.cache[type];
        if (!cached.data) return null;

        if (Date.now() < cached.expiresAt) {
                return cached.data;
            }
            return null;
        },

        getBotStatus(username) {
            return this.cache.isbot.get(username.toLowerCase());
        },

        setBotStatus(username, status) {
            this.cache.isbot.set(username.toLowerCase(), status);
        }
    };

    // Icon loading coordination - ensures all badges load simultaneously
    window.NTIconQueue = window.NTIconQueue || {
        pending: [],
        isProcessing: false,

        add(fn) {
            this.pending.push(fn);
            if (!this.isProcessing) {
                this.flush();
            }
        },

        flush() {
            if (this.pending.length === 0) return;

            this.isProcessing = true;
            requestAnimationFrame(() => {
                // Execute all pending icon additions in one frame
                this.pending.forEach(fn => fn());
                this.pending = [];
                this.isProcessing = false;
            });
        }
    };

    const SCRIPT_VERSION = '3.2.0';
    
    // Clear old caches if script version changed (fixes display name issues from older versions)
    const lastVersion = GM_getValue('script_version');
    if (lastVersion !== SCRIPT_VERSION) {
        GM_deleteValue('individual_leaderboard_cache');
        GM_deleteValue('team_leaderboard_cache');
        GM_setValue('script_version', SCRIPT_VERSION);
    }
 
    const BADGE_TIERS = {
        individual: [
            { rank: 3, img: 'https://www.nitrotype.com/dist/site/images/badges/profile-racer-top3.png', label: 'Top 3' },
            { rank: 10, img: 'https://www.nitrotype.com/dist/site/images/badges/profile-racer-top10.png', label: 'Top 10' },
            { rank: 50, img: 'https://www.nitrotype.com/dist/site/images/badges/profile-racer-top50.png', label: 'Top 50' },
            { rank: 100, img: 'https://www.nitrotype.com/dist/site/images/badges/profile-racer-top100.png', label: 'Top 100' },
            { rank: 300, img: 'https://www.nitrotype.com/dist/site/images/badges/profile-racer-top300.png', label: 'Top 300' }
        ],
        team: [
            { rank: 3, img: 'https://www.nitrotype.com/dist/site/images/badges/profile-team-top3.png', label: 'Top 3' },
            { rank: 10, img: 'https://www.nitrotype.com/dist/site/images/badges/profile-team-top10.png', label: 'Top 10' },
            { rank: 50, img: 'https://www.nitrotype.com/dist/site/images/badges/profile-team-top50.png', label: 'Top 50' }
        ]
    };
 
    const usernameCache = {
        data: {},
        get: function(displayName) {
        if (!displayName) return null;
            return this.data[displayName.toLowerCase()];
        },
        set: function(displayName, username) {
        if (!displayName || !username) return;
            this.data[displayName.toLowerCase()] = username.toLowerCase();
        },
        has: function(displayName) {
        if (!displayName) return false;
            return displayName.toLowerCase() in this.data;
        }
    };
 
    const resolutionQueue = {
        team: new Map(),
        friends: new Set(),
        leagues: new Set(),
        timers: {}
    };
 
    function getToken() {
        let token = GM_getValue('nt_token');
        if (!token) {
            token = localStorage.getItem("player_token");
        if (token) {
                GM_setValue('nt_token', token);
            }
        }
        return token;
    }
 
    function getTokenAndRetry(callback) {
        const token = localStorage.getItem("player_token");
        if (token) {
            GM_setValue('nt_token', token);
            callback();
        }
    }
 
    function getUsernameFromToken() {
        const token = getToken();
        if (!token) return null;
 
        try {
        const base64Url = token.split('.')[1];
        const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
        const jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) {
                return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
            }).join(''));
        const parts = JSON.parse(jsonPayload);
            return parts.username || parts.sub;
        } catch (e) {
            console.error('[BADGE] Error decoding token:', e);
            return null;
        }
    }
 
    function getCTMidnight() {
        const now = new Date();
        const ctOffset = -6 * 60;
        const utc = now.getTime() + (now.getTimezoneOffset() * 60000);
        const ctTime = new Date(utc + (ctOffset * 60000));
        ctTime.setHours(0, 0, 0, 0);
        return ctTime;
    }
 
    function getNextCTMidnight() {
        const midnight = getCTMidnight();
        midnight.setDate(midnight.getDate() + 1);
        return midnight;
    }
 
    function get7DaysBeforeCTMidnight() {
        const midnight = getCTMidnight();
        midnight.setDate(midnight.getDate() - 7);
        return midnight;
    }
 
    function formatDateForAPI(date) {
        const year = date.getFullYear();
        const month = String(date.getMonth() + 1).padStart(2, '0');
        const day = String(date.getDate()).padStart(2, '0');
        return `${year}-${month}-${day} 00:00:00`;
    }
 
    function fetchIndividualLeaderboard(callback) {
        // Check shared cache first (from Leaderboard script)
        if (window.NTShared && window.NTShared.getCache) {
        const sharedData = window.NTShared.getCache('individual');
        if (sharedData) {
                console.log('[BADGE] ✓ Using shared individual cache (instant, no API call!)');
                const individualMap = {};
                let currentRank = 0;

                sharedData.forEach((entry) => {
                    const username = (entry.Username || entry.username || '').toLowerCase();
                    if (!username || entry.bot === 1) return;
                    individualMap[username] = currentRank++;
                });

                callback(individualMap);
                return;
            }
        }

        const cacheKey = 'individual_leaderboard_cache';
        const cached = GM_getValue(cacheKey);
 
        if (cached && cached.expiresAt && Date.now() < cached.expiresAt) {
            callback(cached.data);
            return;
        }
 
        const endTime = getCTMidnight();
        const startTime = get7DaysBeforeCTMidnight();
        const nextMidnight = getNextCTMidnight();
 
        const startStr = encodeURIComponent(formatDateForAPI(startTime));
        const endStr = encodeURIComponent(formatDateForAPI(endTime));
 
        const url = `https://ntstartrack.org/api/individual-leaderboard?start_time=${startStr}&end_time=${endStr}`;
 
        GM_xmlhttpRequest({
            method: "GET",
            url: url,
            onload: function(response) {
                if (response.status === 200) {
                    try {
                        const data = JSON.parse(response.responseText);
 
                        const individualMap = {};
                        let currentRank = 0;
 
                        // ✅ FIX: Properly filter bots and assign sequential ranks
                        data.forEach((entry) => {
                            const username = (entry.Username || entry.username || '').toLowerCase();
                            if (!username) return;
 
                            // Skip bots completely
                            if (entry.bot === 1) return;
 
                            individualMap[username] = currentRank;
                            currentRank++;
                        });
 
                        GM_setValue(cacheKey, {
                            data: individualMap,
                            expiresAt: nextMidnight.getTime()
                        });
 
                        callback(individualMap);
                    } catch (err) {
                        console.error('[BADGE] Error parsing individual leaderboard:', err);
                        callback({});
                    }
                } else {
                    console.error('[BADGE] Individual leaderboard fetch failed:', response.status);
                    callback({});
                }
            },
            onerror: function() {
                console.error('[BADGE] Network error fetching individual leaderboard');
                callback({});
            }
        });
    }
 
    function fetchTeamLeaderboard(callback) {
        // Check shared cache first (from Leaderboard script)
        if (window.NTShared && window.NTShared.getCache) {
        const sharedData = window.NTShared.getCache('team');
        if (sharedData) {
                console.log('[BADGE] ✓ Using shared team cache (instant, no API call!)');
                const teamMap = {};

                sharedData.forEach((entry, index) => {
                    const teamTag = (entry.TeamTag || entry.teamTag || '').toLowerCase();
                    const teamID = (entry.TeamID || entry.teamID || '').toString();
                    if (teamTag) teamMap[teamTag] = index;
                    if (teamID) teamMap[teamID] = index;
                });

                callback(teamMap);
                return;
            }
        }

        const cacheKey = 'team_leaderboard_cache';
        const cached = GM_getValue(cacheKey);
 
        if (cached && cached.expiresAt && Date.now() < cached.expiresAt) {
            callback(cached.data);
            return;
        }
 
        const endTime = getCTMidnight();
        const startTime = get7DaysBeforeCTMidnight();
        const nextMidnight = getNextCTMidnight();
 
        const startStr = encodeURIComponent(formatDateForAPI(startTime));
        const endStr = encodeURIComponent(formatDateForAPI(endTime));
 
        const url = `https://ntstartrack.org/api/team-leaderboard?start_time=${startStr}&end_time=${endStr}&showbot=FALSE`;
 
        GM_xmlhttpRequest({
            method: "GET",
            url: url,
            onload: function(response) {
                if (response.status === 200) {
                    try {
                        const data = JSON.parse(response.responseText);
 
                        const teamMap = {};
                        data.forEach((entry, index) => {
                            const teamTag = (entry.TeamTag || entry.teamTag || '').toLowerCase();
                            const teamID = (entry.TeamID || entry.teamID || '').toString();
 
                            if (teamTag) {
                                teamMap[teamTag] = index;
                            }
                            if (teamID) {
                                teamMap[teamID] = index;
                            }
                        });
 
                        GM_setValue(cacheKey, {
                            data: teamMap,
                            expiresAt: nextMidnight.getTime()
                        });
 
                        callback(teamMap);
                    } catch (err) {
                        console.error('[BADGE] Error parsing team leaderboard:', err);
                        callback({});
                    }
                } else {
                    console.error('[BADGE] Team leaderboard fetch failed:', response.status);
                    callback({});
                }
            },
            onerror: function() {
                console.error('[BADGE] Network error fetching team leaderboard');
                callback({});
            }
        });
    }
 
    function getBadgeForRank(rank, type) {
        const tiers = BADGE_TIERS[type];
        for (const tier of tiers) {
        if (rank < tier.rank) {
                return { img: tier.img, label: tier.label };
            }
        }
        return null;
    }
 
    function addBadgeTooltip(badgeElement, tooltipText) {
        let customTooltipElement = null;
 
        badgeElement.style.cursor = 'help';
 
        badgeElement.addEventListener('mouseenter', function(event) {
            customTooltipElement = document.createElement('div');
            customTooltipElement.textContent = tooltipText;
            customTooltipElement.style.position = 'absolute';
            customTooltipElement.style.backgroundColor = '#333';
            customTooltipElement.style.color = 'white';
            customTooltipElement.style.padding = '4px 8px';
            customTooltipElement.style.borderRadius = '4px';
            customTooltipElement.style.zIndex = '10001';
            customTooltipElement.style.fontSize = '12px';
            customTooltipElement.style.fontFamily = 'Arial, sans-serif';
            customTooltipElement.style.pointerEvents = 'none';
            customTooltipElement.style.left = (event.pageX + 10) + 'px';
            customTooltipElement.style.top = (event.pageY + 10) + 'px';
            document.body.appendChild(customTooltipElement);
        });
 
        badgeElement.addEventListener('mousemove', function(event) {
        if (customTooltipElement) {
                customTooltipElement.style.left = (event.pageX + 10) + 'px';
                customTooltipElement.style.top = (event.pageY + 10) + 'px';
            }
        });
 
        badgeElement.addEventListener('mouseleave', function() {
        if (customTooltipElement) {
                customTooltipElement.remove();
                customTooltipElement = null;
            }
        });
    }
 
    function addBadgeToElement(element, badgeUrl, displayName, rank, badgeLabel, badgeType) {
        if (element.nextElementSibling && element.nextElementSibling.classList.contains('prxxs')) {
        const existingBadge = element.nextElementSibling;
        const existingType = existingBadge.getAttribute('data-badge-type');
 
        if (badgeType === 'racer') {
                existingBadge.remove();
        } else if (badgeType === 'team') {
                if (existingType === 'racer') {
                    return;
                }
                existingBadge.remove();
            }
        }
 
        const badgeDiv = document.createElement('div');
        badgeDiv.className = 'prxxs';
        badgeDiv.setAttribute('data-badge-type', badgeType);
 
        const badgeImg = document.createElement('img');
        badgeImg.className = 'db';
        badgeImg.src = badgeUrl;
 
        addBadgeTooltip(badgeImg, `Top ${rank + 1} ${badgeType === 'racer' ? 'Racer' : 'Team'} (${badgeLabel})`);
 
        badgeDiv.appendChild(badgeImg);
        element.parentNode.insertBefore(badgeDiv, element.nextSibling);
    }
 
    function batchResolveTeamMembers(teamTag, callback) {
        const token = getToken();
        if (!token) {
            callback([]);
            return;
        }
 
        // ✅ FIX: Use team tag as-is (case-sensitive API)
        GM_xmlhttpRequest({
            method: "GET",
            url: `https://www.nitrotype.com/api/v2/teams/${teamTag}`,
            headers: {
                "Authorization": `Bearer ${token}`,
                "accept": "application/json, text/plain, */*"
            },
            onload: function(response) {
                if (response.status === 200) {
                    try {
                        const data = JSON.parse(response.responseText);
 
                        if (data.status === "OK" && data.results && data.results.members) {
                            const members = data.results.members;
 
                            members.forEach((member) => {
                                const displayName = member.displayName || member.username;
                                const username = member.username;
 
                                if (!username) return;
 
                                // ✅ FIX: Strip sparkles and special chars for consistent matching
                                const cleanDisplayName = displayName.replace(/✨/g, '');
 
                                usernameCache.set(cleanDisplayName, username);
                                usernameCache.set(username, username);
                            });
 
                            callback(members);
                        } else {
                            callback([]);
                        }
                    } catch (err) {
                        console.error('[BADGE] Error parsing team members response:', err);
                        callback([]);
                    }
                } else if (response.status === 401) {
                    getTokenAndRetry(() => batchResolveTeamMembers(teamTag, callback));
                } else {
                    console.error('[BADGE] Failed to fetch team members:', response.status);
                    callback([]);
                }
            },
            onerror: function(error) {
                console.error('[BADGE] Network error fetching team members:', error);
                callback([]);
            }
        });
    }
 
    function batchResolveFriends(callback) {
        const token = getToken();
        if (!token) {
            return;
        }
 
        GM_xmlhttpRequest({
            method: "GET",
            url: "https://www.nitrotype.com/api/v2/friends",
            headers: {
                "Authorization": `Bearer ${token}`,
                "Content-Type": "application/json"
            },
            onload: function(response) {
                if (response.status === 200) {
                    const data = JSON.parse(response.responseText);
                    const fields = data.results.fields;
                    const values = data.results.values;
 
                    const displayNameIndex = fields.indexOf("displayName");
                    const usernameIndex = fields.indexOf("username");
 
                    const friendsData = values.map(friendData => ({
                        displayName: friendData[displayNameIndex] || '',
                        username: friendData[usernameIndex] || ''
                    })).filter(friend => friend.username);
 
                    friendsData.forEach(friend => {
                        if (friend.displayName && friend.username) {
                            // ✅ FIX: Strip sparkles for consistent matching
                            const cleanDisplayName = friend.displayName.replace(/✨/g, '');
                            usernameCache.set(cleanDisplayName, friend.username);
                            usernameCache.set(friend.username, friend.username);
                        }
                    });
 
                    callback(friendsData);
                } else if (response.status === 401) {
                    getTokenAndRetry(() => batchResolveFriends(callback));
                }
            }
        });
    }
 
    function batchResolveLeagues(callback) {
        const token = getToken();
        if (!token) {
            return;
        }
 
        GM_xmlhttpRequest({
            method: "GET",
            url: "https://www.nitrotype.com/api/v2/leagues/user/activity",
            headers: {
                "Authorization": `Bearer ${token}`,
                "Content-Type": "application/json"
            },
            onload: function(response) {
                if (response.status === 200) {
                    const data = JSON.parse(response.responseText);
                    if (data.status === "OK") {
                        const leagueData = data.results.standings.map(user => ({
                            displayName: user.displayName || user.username || '',
                            username: user.username || ''
                        })).filter(user => user.username);
 
                        leagueData.forEach(user => {
                            if (user.displayName && user.username) {
                                // ✅ FIX: Strip sparkles for consistent matching
                                const cleanDisplayName = user.displayName.replace(/✨/g, '');
                                usernameCache.set(cleanDisplayName, user.username);
                            }
                        });
 
                        callback(leagueData);
                    }
                } else if (response.status === 401) {
                    getTokenAndRetry(() => batchResolveLeagues(callback));
                }
            }
        });
    }
 
    function checkAndAddBadge(username, displayName, element, individualMap) {
        const rank = individualMap[username.toLowerCase()];
 
        if (rank !== undefined) {
        const tiers = BADGE_TIERS.individual;
            let badgeForList = null;
            for (const tier of tiers) {
                 if (rank < tier.rank) {
                     badgeForList = { img: tier.img.replace('/badges/profile-racer', '/pages/race/race-results').replace('.png', '-alt.png'), label: tier.label };
                     break;
                 }
            }
 
        if (badgeForList) {
                addBadgeToElement(element, badgeForList.img, displayName, rank, badgeForList.label, 'racer');
            }
        }
    }
 
    function extractTeamTagFromDOM(usernameElement) {
        let teamTagElement = usernameElement.previousElementSibling;
 
        while (teamTagElement) {
        if (teamTagElement.classList && teamTagElement.classList.contains('player-name--tag')) {
                const teamTagText = teamTagElement.textContent.trim();
                const match = teamTagText.match(/\[([^\]]+)\]/);
                if (match) {
                    return match[1];
                }
                return teamTagText.replace(/[\[\]]/g, '');
            }
            teamTagElement = teamTagElement.previousElementSibling;
        }
 
        return null;
    }
 
    function queueUsernameResolution(displayName, element, individualMap, context) {
        if (usernameCache.has(displayName)) {
        const username = usernameCache.get(displayName);
            checkAndAddBadge(username, displayName, element, individualMap);
            return;
        }
 
        if (context === 'team') {
        if (!resolutionQueue.team.has(context)) {
                resolutionQueue.team.set(context, []);
            }
            resolutionQueue.team.get(context).push({ displayName, element, individualMap });
        } else if (context === 'friends') {
            resolutionQueue.friends.add({ displayName, element, individualMap });
        } else if (context === 'leagues') {
            resolutionQueue.leagues.add({ displayName, element, individualMap });
        }
 
        clearTimeout(resolutionQueue.timers[context]);
        resolutionQueue.timers[context] = setTimeout(() => {
            flushResolutionQueue(context);
        }, 300);

    }
 
    function flushResolutionQueue(context) {
        if (context === 'team') {
        const teamTag = window.location.pathname.split('/').pop();
        const queue = resolutionQueue.team.get(context);
        if (queue && queue.length > 0) {
                batchResolveTeamMembers(teamTag, () => {
                    queue.forEach(({ displayName, element, individualMap }) => {
                        if (usernameCache.has(displayName)) {
                            const username = usernameCache.get(displayName);
                            checkAndAddBadge(username, displayName, element, individualMap);
                        }
                    });
                });
                resolutionQueue.team.set(context, []);
            }
        } else if (context === 'friends' && resolutionQueue.friends.size > 0) {
        const queue = Array.from(resolutionQueue.friends);
 
        const needsFetch = queue.some(({ displayName }) => !usernameCache.has(displayName));
 
        if (needsFetch) {
                batchResolveFriends(() => {
                    queue.forEach(({ displayName, element, individualMap }) => {
                        if (usernameCache.has(displayName)) {
                            const username = usernameCache.get(displayName);
                            checkAndAddBadge(username, displayName, element, individualMap);
                        }
                    });
                });
        } else {
                queue.forEach(({ displayName, element, individualMap }) => {
                    if (usernameCache.has(displayName)) {
                        const username = usernameCache.get(displayName);
                        checkAndAddBadge(username, displayName, element, individualMap);
                    }
                });
            }
 
            resolutionQueue.friends.clear();
        } else if (context === 'leagues' && resolutionQueue.leagues.size > 0) {
        const queue = Array.from(resolutionQueue.leagues);
 
        const needsFetch = queue.some(({ displayName }) => !usernameCache.has(displayName));
 
        if (needsFetch) {
                batchResolveLeagues(() => {
                    queue.forEach(({ displayName, element, individualMap }) => {
                        if (usernameCache.has(displayName)) {
                            const username = usernameCache.get(displayName);
                            checkAndAddBadge(username, displayName, element, individualMap);
                        }
                    });
                });
        } else {
                queue.forEach(({ displayName, element, individualMap }) => {
                    if (usernameCache.has(displayName)) {
                        const username = usernameCache.get(displayName);
                        checkAndAddBadge(username, displayName, element, individualMap);
                    }
                });
            }
 
            resolutionQueue.leagues.clear();
        }
    }
 
    function processRacerBadges(individualMap, context) {
        const usernameElements = document.querySelectorAll('.type-ellip:not([data-badge-processed])');
 
        if (usernameElements.length === 0) return;
 
        usernameElements.forEach(element => {
        const displayName = element.textContent.trim().replace(/✨/g, '');
            queueUsernameResolution(displayName, element, individualMap, context);
            element.setAttribute('data-badge-processed', 'true');
        });
    }
 
    function checkAndAddTeamBadge(displayName, element, teamMap) {
        if (element.nextElementSibling && element.nextElementSibling.classList.contains('prxxs')) {
        const existingBadge = element.nextElementSibling;
        if (existingBadge.getAttribute('data-badge-type') === 'racer') {
                return;
            }
        }
 
        const teamTag = extractTeamTagFromDOM(element);
        if (!teamTag) {
            return;
        }
 
        const rank = teamMap[teamTag.toLowerCase()];
        if (rank === undefined) {
            return;
        }
 
        const badge = getBadgeForRank(rank, 'team');
        if (!badge) {
            return;
        }
 
        const badgeForList = {
            img: badge.img.replace('/badges/profile-team', '/pages/race/race-results').replace('.png', '-alt.png'),
            label: badge.label
        };
 
        addBadgeToElement(element, badgeForList.img, displayName, rank, badgeForList.label, 'team');
    }
 
    function processTeamBadgesOnList(teamMap, context) {
        const usernameElements = document.querySelectorAll('.type-ellip[data-badge-processed]:not([data-team-badge-processed])');
 
        if (usernameElements.length === 0) return;
 
        usernameElements.forEach(element => {
        const displayName = element.textContent.trim().replace(/✨/g, '');
            checkAndAddTeamBadge(displayName, element, teamMap);
            element.setAttribute('data-team-badge-processed', 'true');
        });
    }
 
    function processTeamBadge(teamMap) {
        const teamPath = window.location.pathname;
        if (!teamPath.startsWith('/team/')) {
            return;
        }
 
        const teamTag = teamPath.split('/').pop();
 
        const rank = teamMap[teamTag.toLowerCase()];
 
        if (rank === undefined) {
            return;
        }
 
        const badge = getBadgeForRank(rank, 'team');
        if (!badge) {
            return;
        }
 
        const cardCap = document.querySelector('.card-cap');
        if (!cardCap) {
            return;
        }
 
        if (!cardCap.classList.contains('with-player-rank-banner')) {
            cardCap.classList.add('with-player-rank-banner');
        }
 
        if (document.querySelector('.profile-badge[alt*="Top"]')) {
            return;
        }
 
        let bucketMedia = cardCap.querySelector('.bucket-media');
        if (!bucketMedia) {
            bucketMedia = document.createElement('div');
            bucketMedia.className = 'bucket-media';
            cardCap.insertBefore(bucketMedia, cardCap.firstChild);
        }
 
        const badgeImg = document.createElement('img');
        badgeImg.className = 'profile-badge';
        badgeImg.alt = `Top ${rank + 1} Team`;
        badgeImg.src = badge.img;
 
        addBadgeTooltip(badgeImg, `Top ${rank + 1} Team (${badge.label})`);
 
        bucketMedia.appendChild(badgeImg);
    }
 
    function processRacerProfile_IndividualBadge(individualMap) {
        const path = window.location.pathname;
        if (!path.startsWith('/racer/')) {
            return;
        }
 
        const username = path.split('/').pop().toLowerCase();
        if (!username) {
            return;
        }
 
        const rank = individualMap[username];
 
        if (rank === undefined) {
            return;
        }
 
        const badge = getBadgeForRank(rank, 'individual');
        if (!badge) {
            return;
        }
 
        const playerGrid = document.querySelector('.profile--grid--header .profile--grid--player');
        if (!playerGrid) {
            return;
        }
 
        if (document.querySelector('.profile-badge.racer-rank-badge')) {
            return;
        }
 
        if (!playerGrid.hasAttribute('data-badge-shifted')) {
            playerGrid.style.marginLeft = '130px';
            playerGrid.setAttribute('data-badge-shifted', 'true');
        }
 
        const badgeDiv = document.createElement('div');
        badgeDiv.className = 'profile-badge racer-rank-badge';
        badgeDiv.style.cssText = 'position: absolute; left: 0; top: 0;';
 
        const badgeImg = document.createElement('img');
        badgeImg.className = 'profile-badge';
        badgeImg.src = badge.img;
 
        addBadgeTooltip(badgeImg, `Top ${rank + 1} Racer in the Last 7 Days (${badge.label})`);
 
        badgeDiv.appendChild(badgeImg);
 
        playerGrid.parentElement.style.position = 'relative';
        playerGrid.parentElement.insertBefore(badgeDiv, playerGrid);
 
        const teamBadgeExists = !!document.querySelector('.profile-badge.team-rank-badge');
        const racerBadgeExists = !!document.querySelector('.profile-badge.racer-rank-badge');
 
        if (teamBadgeExists && racerBadgeExists) {
            playerGrid.style.marginLeft = '130px';
        } else if (teamBadgeExists || racerBadgeExists) {
            playerGrid.style.marginLeft = '75px';
        } else {
            playerGrid.style.marginLeft = '0px';
        }
 
        if (!playerGrid.classList.contains('with-racer-ranking')) {
            playerGrid.classList.add('with-racer-ranking');
        }
    }
 
    function processRacerProfile_TeamBadge(teamMap) {
        const path = window.location.pathname;
        if (!path.startsWith('/racer/')) {
            return;
        }
 
        const teamTagElement = document.querySelector('.player-name--tag');
        if (!teamTagElement) {
            return;
        }
 
        const teamTag = teamTagElement.textContent.trim().replace(/[\[\]]/g, '').toLowerCase();
        if (!teamTag) {
            return;
        }
 
        const rank = teamMap[teamTag];
 
        if (rank === undefined) {
            return;
        }
 
        const badge = getBadgeForRank(rank, 'team');
        if (!badge) {
            return;
        }
 
        const playerGrid = document.querySelector('.profile--grid--header .profile--grid--player');
        if (!playerGrid) {
            return;
        }
 
        if (document.querySelector('.profile-badge.team-rank-badge')) {
            return;
        }
 
        const racerBadgeExists = !!document.querySelector('.profile-badge.racer-rank-badge');
        const teamBadgeLeft = racerBadgeExists ? '60px' : '0px';
 
        const badgeDiv = document.createElement('div');
        badgeDiv.className = 'profile-badge team-rank-badge';
        badgeDiv.style.cssText = `position: absolute; left: ${teamBadgeLeft}; top: 0;`;
 
        const badgeImg = document.createElement('img');
        badgeImg.className = 'profile-badge';
        badgeImg.src = badge.img;
 
        addBadgeTooltip(badgeImg, `Top ${rank + 1} Team in the Last 7 Days (${badge.label})`);
 
        badgeDiv.appendChild(badgeImg);
 
        playerGrid.parentElement.style.position = 'relative';
        playerGrid.parentElement.insertBefore(badgeDiv, playerGrid);
 
        const teamBadgeExists = !!document.querySelector('.profile-badge.team-rank-badge');
 
        if (teamBadgeExists && racerBadgeExists) {
                playerGrid.style.marginLeft = '130px';
        } else if (teamBadgeExists || racerBadgeExists) {
                playerGrid.style.marginLeft = '75px';
        } else {
                playerGrid.style.marginLeft = '0px';
            }

        if (!playerGrid.classList.contains('with-team-ranking')) {
            playerGrid.classList.add('with-team-ranking');
        }
    }
 
    function processGarageProfile_IndividualBadge(individualMap, username) {
        if (!username) return;
 
        username = username.toLowerCase();
 
        const rank = individualMap[username];
 
        if (rank === undefined) {
            return;
        }
 
        const badge = getBadgeForRank(rank, 'individual');
        if (!badge) {
            return;
        }
 
        let playerGrid = document.querySelector('.profile--grid--header .profile--grid--player');
 
        if (!playerGrid) {
            playerGrid = document.querySelector('.garage--header .profile--grid--player');
        }
        if (!playerGrid) {
            playerGrid = document.querySelector('.card-cap');
        }
 
        if (!playerGrid) {
            return;
        }
 
        if (document.querySelector('.profile-badge.racer-rank-badge')) {
            return;
        }
 
        if (!playerGrid.hasAttribute('data-badge-shifted')) {
            playerGrid.style.marginLeft = '130px';
            playerGrid.setAttribute('data-badge-shifted', 'true');
        }
 
        const badgeDiv = document.createElement('div');
        badgeDiv.className = 'profile-badge racer-rank-badge';
        badgeDiv.style.cssText = 'position: absolute; left: 0; top: 0;';
 
        const badgeImg = document.createElement('img');
        badgeImg.className = 'profile-badge';
        badgeImg.src = badge.img;
 
        addBadgeTooltip(badgeImg, `Top ${rank + 1} Racer in the Last 7 Days (${badge.label})`);
 
        badgeDiv.appendChild(badgeImg);
 
        playerGrid.parentElement.style.position = 'relative';
        playerGrid.parentElement.insertBefore(badgeDiv, playerGrid);
 
        const teamBadgeExists = !!document.querySelector('.profile-badge.team-rank-badge');
        const racerBadgeExists = !!document.querySelector('.profile-badge.racer-rank-badge');
 
        if (teamBadgeExists && racerBadgeExists) {
                playerGrid.style.marginLeft = '130px';
        } else if (teamBadgeExists || racerBadgeExists) {
                playerGrid.style.marginLeft = '75px';
        } else {
                playerGrid.style.marginLeft = '0px';
            }

        if (!playerGrid.classList.contains('with-racer-ranking')) {
            playerGrid.classList.add('with-racer-ranking');
        }
    }
 
    function processGarageProfile_TeamBadge(teamMap) {
        const teamTagElement = document.querySelector('.player-name--tag');
        if (!teamTagElement) {
            return;
        }
 
        const teamTag = teamTagElement.textContent.trim().replace(/[\[\]]/g, '').toLowerCase();
        if (!teamTag) {
            return;
        }
 
        const rank = teamMap[teamTag];
 
        if (rank === undefined) {
            return;
        }
 
        const badge = getBadgeForRank(rank, 'team');
        if (!badge) {
            return;
        }
 
        let playerGrid = document.querySelector('.profile--grid--header .profile--grid--player');
        if (!playerGrid) {
            playerGrid = document.querySelector('.garage--header .profile--grid--player');
        }
        if (!playerGrid) {
            playerGrid = document.querySelector('.card-cap');
        }
 
        if (!playerGrid) {
            return;
        }
 
        if (document.querySelector('.profile-badge.team-rank-badge')) {
            return;
        }
 
        const racerBadgeExists = !!document.querySelector('.profile-badge.racer-rank-badge');
        const teamBadgeLeft = racerBadgeExists ? '60px' : '0px';
 
        const badgeDiv = document.createElement('div');
        badgeDiv.className = 'profile-badge team-rank-badge';
        badgeDiv.style.cssText = `position: absolute; left: ${teamBadgeLeft}; top: 0;`;
 
        const badgeImg = document.createElement('img');
        badgeImg.className = 'profile-badge';
        badgeImg.src = badge.img;
 
        addBadgeTooltip(badgeImg, `Top ${rank + 1} Team in the Last 7 Days (${badge.label})`);
 
        badgeDiv.appendChild(badgeImg);
 
        playerGrid.parentElement.style.position = 'relative';
        playerGrid.parentElement.insertBefore(badgeDiv, playerGrid);
 
        const teamBadgeExists = !!document.querySelector('.profile-badge.team-rank-badge');
 
        if (teamBadgeExists && racerBadgeExists) {
                playerGrid.style.marginLeft = '130px';
        } else if (teamBadgeExists || racerBadgeExists) {
                playerGrid.style.marginLeft = '75px';
        } else {
                playerGrid.style.marginLeft = '0px';
            }

        if (!playerGrid.classList.contains('with-team-ranking')) {
            playerGrid.classList.add('with-team-ranking');
        }
    }
 
    function createDebouncedObserver(callback, delay = 250) {
        let timeoutId;
        return new MutationObserver(() => {
            clearTimeout(timeoutId);
            timeoutId = setTimeout(callback, delay);
        });
    }
 
    function handleTeamPage(individualMap, teamMap) {
        let membersResolved = false;
 
        const teamTag = window.location.pathname.split('/').pop();
 
        batchResolveTeamMembers(teamTag, (members) => {
            membersResolved = true;
 
            processRacerBadges(individualMap, 'team');
 
            processTeamBadgesOnList(teamMap, 'team');
        });
 
        processTeamBadge(teamMap);
 
        const observer = createDebouncedObserver(() => {
        if (membersResolved) {
                processRacerBadges(individualMap, 'team');
                processTeamBadge(teamMap);
 
                processTeamBadgesOnList(teamMap, 'team');
            }
        });
 
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    }
 
    function handleFriendsPage(individualMap) {
        let racerBadgesComplete = false;
 
        batchResolveFriends((friends) => {
            processRacerBadges(individualMap, 'friends');
 
                racerBadgesComplete = true;
                fetchTeamLeaderboard((teamMap) => {
                        processTeamBadgesOnList(teamMap, 'friends');
                    });
        });
 
        const observer = createDebouncedObserver(() => {
            processRacerBadges(individualMap, 'friends');
 
        if (racerBadgesComplete) {
                    fetchTeamLeaderboard((teamMap) => {
                        processTeamBadgesOnList(teamMap, 'friends');
                    });
            }
        });
 
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    }
 
    function getCurrentLeagueTab() {
        const checkedRadio = document.querySelector('input[name="showteam"]:checked');
        if (!checkedRadio) return null;
 
        const label = document.querySelector(`label[for="${checkedRadio.id}"]`);
        return label ? label.textContent.trim() : null;
    }
 
    function handleLeaguesPage(individualMap) {
        let leaguesData = [];
        let teamMap = null;
 
        function handlePersonalTab() {
        if (leaguesData.length === 0) {
                batchResolveLeagues((leagues) => {
                    leaguesData = leagues;
 
                    processRacerBadges(individualMap, 'leagues');
 
                        fetchTeamLeaderboard((tMap) => {
                            teamMap = tMap;
                            processTeamBadgesOnList(teamMap, 'leagues');
                        });

                });
        } else {
                processRacerBadges(individualMap, 'leagues');
 
                if (teamMap) {
                    processTeamBadgesOnList(teamMap, 'leagues');
                } else {
                    fetchTeamLeaderboard((tMap) => {
                        teamMap = tMap;
                        processTeamBadgesOnList(teamMap, 'leagues');
                    });
                }
            }
        }
 
        function handleTeamTab() {
        if (!teamMap) {
                fetchTeamLeaderboard((tMap) => {
                    teamMap = tMap;
                    processTeamLeaguesBadges(teamMap);
                });
        } else {
                processTeamLeaguesBadges(teamMap);
            }
        }
 
        const initialTab = getCurrentLeagueTab();
        if (initialTab === 'Team') {
            handleTeamTab();
        } else {
            handlePersonalTab();
        }
 
        const tabBar = document.querySelector('.switch.switch--horizontal');
        if (tabBar) {
        const radioButtons = tabBar.querySelectorAll('input[name="showteam"]');
            radioButtons.forEach(radio => {
                radio.addEventListener('change', () => {
                    const currentTab = getCurrentLeagueTab();
 
                    if (currentTab === 'Team') {
                        handleTeamTab();
                    } else {
                        handlePersonalTab();
                    }
                });
            });
        }
 
        const contentObserver = createDebouncedObserver(() => {
        const currentTab = getCurrentLeagueTab();
        if (currentTab === 'Team') {
                if (teamMap) {
                    processTeamLeaguesBadges(teamMap);
                }
        } else {
                if (leaguesData.length > 0) {
                    processRacerBadges(individualMap, 'leagues');
                    if (teamMap) {
                        processTeamBadgesOnList(teamMap, 'leagues');
                    }
                }
            }
        });
 
        contentObserver.observe(document.body, {
            childList: true,
            subtree: true
        });
    }
 
    function processTeamLeaguesBadges(teamMap) {
        const allCells = Array.from(document.querySelectorAll('td.table-cell.leagues--standings--team'));
        const visibleCells = allCells.filter(cell => {
                const rect = cell.getBoundingClientRect();
                return rect.width > 0 && rect.height > 0;
            });
 
            visibleCells.forEach(cell => {
                if (cell.querySelector('.team-league-badge')) {
                    return;
                }
 
                const cellText = cell.textContent.trim();
                const match = cellText.match(/\[([^\]]+)\]/);
 
                if (!match) {
                    return;
                }
 
                const teamTag = match[1];
 
                const rank = teamMap[teamTag.toLowerCase()];
                if (rank === undefined) {
                    return;
                }
 
                const badge = getBadgeForRank(rank, 'team');
                if (!badge) {
                    return;
                }
 
                const badgeDiv = document.createElement('div');
                badgeDiv.className = 'prxxs team-league-badge';
                badgeDiv.style.display = 'inline-block';
                badgeDiv.style.marginLeft = '4px';
 
                const badgeImg = document.createElement('img');
                badgeImg.className = 'db';
                badgeImg.src = badge.img.replace('/badges/profile-team', '/pages/race/race-results').replace('.png', '-alt.png');
 
                addBadgeTooltip(badgeImg, `Top ${rank + 1} Team (${badge.label})`);
 
                badgeDiv.appendChild(badgeImg);
 
                const divs = cell.querySelectorAll('div');
 
                let teamNameDiv = null;
                divs.forEach(div => {
                    const text = div.textContent.trim();
                    if (!text.startsWith('[') && text.length > 0) {
                        teamNameDiv = div;
                    }
                });
 
                if (teamNameDiv) {
                    teamNameDiv.appendChild(badgeDiv);
                } else {
                    cell.appendChild(badgeDiv);
                }
            });
    }
 
    function handleRacerPage(individualMap, teamMap) {
        processRacerProfile_IndividualBadge(individualMap);
        processRacerProfile_TeamBadge(teamMap);
 
        const observer = createDebouncedObserver(() => {
            processRacerProfile_IndividualBadge(individualMap);
            processRacerProfile_TeamBadge(teamMap);
        });
 
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    }
 
    function handleGaragePage(individualMap, teamMap) {
        const path = window.location.pathname;
        let username = null;
 
        if (path === '/garage' || path === '/garage/') {
            username = getUsernameFromToken();
        } else if (path.startsWith('/garage/')) {
            username = path.split('/garage/')[1].split('/')[0].split('?')[0];
        }
 
        if (!username) {
            return;
        }
 
        processGarageProfile_IndividualBadge(individualMap, username);
        processGarageProfile_TeamBadge(teamMap);
 
        const observer = createDebouncedObserver(() => {
            processGarageProfile_IndividualBadge(individualMap, username);
            processGarageProfile_TeamBadge(teamMap);
        });
 
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    }
 
    function initialize() {
        const path = window.location.pathname;
 
        fetchIndividualLeaderboard(function(individualMap) {
        if (path.startsWith('/team/') || path.startsWith('/racer/') || path.startsWith('/garage')) {
                fetchTeamLeaderboard(function(teamMap) {
                    if (path.startsWith('/team/')) {
                        handleTeamPage(individualMap, teamMap);
                    } else if (path.startsWith('/racer/')) {
                        handleRacerPage(individualMap, teamMap);
                    } else if (path.startsWith('/garage')) {
                        handleGaragePage(individualMap, teamMap);
                    }
                });
        } else if (path === '/friends') {
                handleFriendsPage(individualMap);
        } else if (path === '/leagues') {
                handleLeaguesPage(individualMap);
            }
        });
    }
 
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initialize);
    } else {
        setTimeout(initialize, 500);
    }
 
})();