您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Track racing data and show acceleration status
当前为
// ==UserScript== // @name Torn Racing Telemetry // @namespace https://www.torn.com/profiles.php?XID=2782979 // @version 1.3 // @description Track racing data and show acceleration status // @match https://www.torn.com/page.php?sid=racing* // @match https://www.torn.com/loader.php?sid=racing* // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; // Store previous percentages and timestamps for calculations let previousData = {}; // Function to get track data function getTrackData() { const trackInfoElement = document.querySelector('.track-info'); const trackLength = trackInfoElement ? parseFloat(trackInfoElement.dataset.length) : 3.4; const titleElement = document.querySelector('.title-black'); const lapMatch = titleElement ? titleElement.textContent.match(/(\d+)\s+laps?/) : null; const numberOfLaps = lapMatch ? parseInt(lapMatch[1]) : 5; const totalDistance = trackLength * numberOfLaps; return { trackLength, numberOfLaps, totalDistance }; } // Function to parse race time to seconds function parseRaceTime(timeStr) { const parts = timeStr.split(':'); if (parts.length === 2) { const minutes = parseFloat(parts[0]); const seconds = parseFloat(parts[1]); return (minutes * 60) + seconds; } return 0; } // Function to calculate average speed for finished racers function calculateAverageSpeed(timeStr) { const { totalDistance } = getTrackData(); const totalSeconds = parseRaceTime(timeStr); if (totalSeconds === 0) return 0; // Convert to mph (distance in miles / time in hours) return (totalDistance / (totalSeconds / 3600)); } // Function to calculate speed and acceleration from percentage function calculateMetrics(currentPercentage, driverId, currentTime) { const { totalDistance } = getTrackData(); if (!previousData[driverId]) { previousData[driverId] = { percentage: currentPercentage, timestamp: currentTime, speed: 0, acceleration: 'calculating...' }; return { speed: 0, acceleration: 'calculating...' }; } const timeDiff = (currentTime - previousData[driverId].timestamp) / 1000; if (timeDiff === 0) return previousData[driverId]; const previousDistanceCovered = (previousData[driverId].percentage / 100) * totalDistance; const currentDistanceCovered = (currentPercentage / 100) * totalDistance; const distanceDifference = currentDistanceCovered - previousDistanceCovered; const speed = (distanceDifference / timeDiff) * 3600; let acceleration; const speedDiff = speed - (previousData[driverId].speed || 0); const threshold = 1; if (Math.abs(speedDiff) < threshold) { acceleration = 'steady'; } else if (speedDiff > threshold) { acceleration = 'accelerating'; } else { acceleration = 'braking'; } previousData[driverId] = { percentage: currentPercentage, timestamp: currentTime, speed: speed, acceleration: acceleration }; return { speed: Math.abs(speed), acceleration: acceleration }; } // Function to update status display function updateStatusDisplay(nameElement, status, speed, isFinished = false) { const existingStatus = nameElement.querySelector('.status-text'); if (existingStatus) { existingStatus.remove(); } const statusElement = document.createElement('span'); statusElement.className = 'status-text'; statusElement.style.marginLeft = '10px'; statusElement.style.fontSize = '12px'; if (isFinished) { statusElement.style.color = '#666'; statusElement.textContent = `[Finished - Avg: ${speed.toFixed(1)} mph]`; } else if (status === 'not started') { statusElement.style.color = '#666'; statusElement.textContent = '[Not Started]'; } else { statusElement.style.color = status === 'accelerating' ? 'green' : status === 'braking' ? 'red' : 'gray'; const speedText = status === 'calculating...' ? '' : ` - ${Math.abs(speed).toFixed(1)} mph`; statusElement.textContent = `[${status}${speedText}]`; } nameElement.appendChild(statusElement); } // Main update function function updateRacingData() { const drivers = document.querySelectorAll('#leaderBoard li[id^="lbr-"]'); const currentTime = Date.now(); drivers.forEach(driver => { const driverId = driver.id; const nameElement = driver.querySelector('.name'); const timeElement = driver.querySelector('.time'); const statusElement = driver.querySelector('.status-wrap div'); if (!nameElement || !timeElement) return; // Check if race is finished for this driver const isFinished = statusElement.classList.contains('finished') || statusElement.classList.contains('gold') || statusElement.classList.contains('silver') || statusElement.classList.contains('bronze'); // Check if race hasn't started const notStarted = !timeElement.textContent.trim(); if (notStarted) { updateStatusDisplay(nameElement, 'not started', 0); } else if (isFinished) { const avgSpeed = calculateAverageSpeed(timeElement.textContent); updateStatusDisplay(nameElement, null, avgSpeed, true); } else { // Race is in progress const currentPercentage = parseFloat(timeElement.textContent.replace('%', '')); if (!isNaN(currentPercentage)) { const { speed, acceleration } = calculateMetrics(currentPercentage, driverId, currentTime); updateStatusDisplay(nameElement, acceleration, speed); } } }); } // Add custom styles const styles = document.createElement('style'); styles.textContent = ` .status-text { display: inline-block; font-family: Arial, sans-serif; padding: 2px 5px; border-radius: 3px; background-color: rgba(0,0,0,0.05); } `; document.head.appendChild(styles); // Run update every 2 seconds setInterval(updateRacingData, 2000); // Initial update updateRacingData(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址