Torn Starter Job Upgrade Notice

Check job points and work stats to see if you are able to upgrade to the next position, and display a message at the top of the page.

当前为 2024-10-21 提交的版本,查看 最新版本

// ==UserScript==
// @name         Torn Starter Job Upgrade Notice
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Check job points and work stats to see if you are able to upgrade to the next position, and display a message at the top of the page.
// @author       Baccy
// @icon         https://www.google.com/s2/favicons?sz=64&domain=torn.com
// @match        https://www.torn.com/*
// @grant        none
// ==/UserScript==

const APIKey = 'LimitedKey';

let showFalseMessage = false; // Set to true to show a message with your missing stats or job points




const jobRequirements = {
    army: [
        { position: 'Private', manual_labor: 50, intelligence: 15, endurance: 20 },
        { position: 'Corporal', manual_labor: 120, intelligence: 35, endurance: 50 },
        { position: 'Sergeant', manual_labor: 325, intelligence: 60, endurance: 115 },
        { position: 'Master Sergeant', manual_labor: 700, intelligence: 160, endurance: 300 },
        { position: 'Warrant Officer', manual_labor: 1300, intelligence: 360, endurance: 595 },
        { position: 'Lieutenant', manual_labor: 2550, intelligence: 490, endurance: 900 },
        { position: 'Major', manual_labor: 4150, intelligence: 600, endurance: 1100 },
        { position: 'Colonel', manual_labor: 7500, intelligence: 1350, endurance: 2530 },
        { position: 'Brigadier', manual_labor: 10000, intelligence: 2000, endurance: 4000 },
        { position: 'General', manual_labor: null, intelligence: null, endurance: null } // Final position
    ],
    grocer: [
        { position: 'Bag Boy', manual_labor: 30, intelligence: 15, endurance: 50 },
        { position: 'Price Labeller', manual_labor: 50, intelligence: 35, endurance: 120 },
        { position: 'Cashier', manual_labor: 120, intelligence: 60, endurance: 225 },
        { position: 'Food Delivery', manual_labor: 250, intelligence: 200, endurance: 500 },
        { position: 'Manager', manual_labor: null, intelligence: null, endurance: null } // Final position
    ],
    casino: [
        { position: 'Dealer', manual_labor: 35, intelligence: 50, endurance: 120 },
        { position: 'Gaming Consultant', manual_labor: 60, intelligence: 115, endurance: 325 },
        { position: 'Marketing Manager', manual_labor: 360, intelligence: 595, endurance: 1300 },
        { position: 'Revenue Manager', manual_labor: 490, intelligence: 900, endurance: 2550 },
        { position: 'Casino Manager', manual_labor: 755, intelligence: 1100, endurance: 4150 },
        { position: 'Casino President', manual_labor: null, intelligence: null, endurance: null } // Final position
    ],
    medical: [
        { position: 'Medical Student', manual_labor: 100, intelligence: 600, endurance: 150 },
        { position: 'Houseman', manual_labor: 175, intelligence: 1000, endurance: 275 },
        { position: 'Senior Houseman', manual_labor: 300, intelligence: 1500, endurance: 500 },
        { position: 'GP', manual_labor: 600, intelligence: 2500, endurance: 1000 },
        { position: 'Consultant', manual_labor: 1300, intelligence: 5000, endurance: 2000 },
        { position: 'Surgeon', manual_labor: 2600, intelligence: 10000, endurance: 4000 },
        { position: 'Brain Surgeon', manual_labor: null, intelligence: null, endurance: null } // Final position
    ],
    education: [
        { position: 'Recess Supervisor', manual_labor: 300, intelligence: 750, endurance: 500 },
        { position: 'Substitute Teacher', manual_labor: 600, intelligence: 1000, endurance: 700 },
        { position: 'Elementary Teacher', manual_labor: 1000, intelligence: 1300, endurance: 1000 },
        { position: 'Secondary Teacher', manual_labor: 1500, intelligence: 2000, endurance: 1500 },
        { position: 'Professor', manual_labor: 1500, intelligence: 3000, endurance: 1500 },
        { position: 'Vice Principal', manual_labor: 1500, intelligence: 5000, endurance: 1500 },
        { position: 'Principal', manual_labor: null, intelligence: null, endurance: null } // Final position
    ],
    law: [
        { position: 'Law Student', manual_labor: 1750, intelligence: 2500, endurance: 5000 },
        { position: 'Paralegal', manual_labor: 2500, intelligence: 5000, endurance: 7500 },
        { position: 'Probate Lawyer', manual_labor: 3500, intelligence: 6500, endurance: 7750 },
        { position: 'Trial Lawyer', manual_labor: 4000, intelligence: 7250, endurance: 10000 },
        { position: 'Circuit Court Judge', manual_labor: 6000, intelligence: 9000, endurance: 15000 },
        { position: 'Federal Judge', manual_labor: null, intelligence: null, endurance: null } // Final position
    ]
};


// Function to check if the user can upgrade to the next job position
function checkJobUpgrade(job, currentPosition, jobPoints, workStats) {
    console.log(`Checking job upgrade for job: ${job}, current position: ${currentPosition}, job points: ${jobPoints}, work stats:`, workStats);

    const positions = jobRequirements[job.toLowerCase()];
    const currentIndex = positions.findIndex(pos => pos.position === currentPosition);

    // Additional logging for the next position
    if (currentIndex === -1 || currentIndex >= positions.length - 1) {
        console.log("User has reached the highest position or job data is incorrect.");
        return "You have reached the highest position or your job data is incorrect.";
    }

    const nextPositionRequirements = positions[currentIndex + 1];
    const pointsRequired = (currentIndex + 1) * 5;

    // Log the next position and its requirements
    console.log(`Next position: ${positions[currentIndex + 1].position}, Points required: ${pointsRequired}, Requirements:`, nextPositionRequirements);

    // Check if the user meets the requirements for the next position
    const canUpgrade = jobPoints >= pointsRequired &&
        workStats.manual_labor >= nextPositionRequirements.manual_labor &&
        workStats.intelligence >= nextPositionRequirements.intelligence &&
        workStats.endurance >= nextPositionRequirements.endurance;

    if (canUpgrade) {
        console.log(`User can upgrade to: ${positions[currentIndex + 1].position}`);
        return `You can upgrade to ${positions[currentIndex + 1].position}!`;
    } else {
        console.log(`User cannot upgrade to: ${positions[currentIndex + 1].position}`);
        if (showFalseMessage) {
            // Calculate what is lacking for the upgrade
            const missingStats = [];
            if (jobPoints < pointsRequired) {
                missingStats.push(`Job points required: ${pointsRequired} (You have: ${jobPoints})`);
            }
            if (workStats.manual_labor < nextPositionRequirements.manual_labor) {
                missingStats.push(`Manual labor required: ${nextPositionRequirements.manual_labor} (You have: ${workStats.manual_labor})`);
            }
            if (workStats.intelligence < nextPositionRequirements.intelligence) {
                missingStats.push(`Intelligence required: ${nextPositionRequirements.intelligence} (You have: ${workStats.intelligence})`);
            }
            if (workStats.endurance < nextPositionRequirements.endurance) {
                missingStats.push(`Endurance required: ${nextPositionRequirements.endurance} (You have: ${workStats.endurance})`);
            }

            // Combine missing stats into a message
            const missingMessage = `You cannot upgrade to ${positions[currentIndex + 1].position} yet. You are missing:\n${missingStats.join('\n')}`;
            console.log(missingMessage);
            return missingMessage;
        }
    }
}



// Function to display the upgrade message after the specified element
function displayUpgradeMessage(jobUpgradeMessage) {
    // Find the container where the message should be inserted
    const container = document.querySelector('#topHeaderBanner');

    if (container) {
        // Remove any existing message
        let existingMessage = document.getElementById('job-upgrade-message');
        if (existingMessage) {
            existingMessage.remove(); // Remove it from DOM
        }

        // Create a new div to display the job upgrade message
        const messageDiv = document.createElement('div');
        messageDiv.id = 'job-upgrade-message';
        messageDiv.innerHTML = jobUpgradeMessage;

        // Add inline styles to the div
        messageDiv.style.fontSize = '16px';
        messageDiv.style.marginTop = '10px';
        messageDiv.style.color = '#ffffff'; // Highlight color
        messageDiv.style.padding = '10px';
        messageDiv.style.backgroundColor = '#1c1b22'; // Dark background
        messageDiv.style.borderRadius = '5px';
        messageDiv.style.lineHeight = '1.5';
        messageDiv.style.textAlign = 'center'; // Center the text

        // Append the new div as a child to the container
        container.appendChild(messageDiv);
    }
}



// Log when API data is being fetched
async function fetchAPIData() {
    console.log("Attempting to fetch data");
    try {
        const workStatsResponse = await fetch(`https://api.torn.com/user/?selections=workstats&key=${APIKey}&comment=StarterJobNotice`);
        const jobPointsResponse = await fetch(`https://api.torn.com/user/?selections=jobpoints&key=${APIKey}&comment=StarterJobNotice`);
        const profileResponse = await fetch(`https://api.torn.com/user/?selections=profile&key=${APIKey}&comment=StarterJobNotice`);

        const workStats = await workStatsResponse.json();
        const jobPoints = await jobPointsResponse.json();
        const profile = await profileResponse.json();

        console.log("Fetched workStats:", workStats);
        console.log("Fetched jobPoints:", jobPoints);
        console.log("Fetched profile:", profile);

        localStorage.setItem('workStats', JSON.stringify(workStats));
        localStorage.setItem('jobPoints', JSON.stringify(jobPoints));
        localStorage.setItem('profile', JSON.stringify(profile));
        localStorage.setItem('lastFetchDate', new Date().toISOString().split('T')[0]);

    } catch (error) {
        console.error("Error fetching API data:", error);
    }
}

// Function to check if stored data exists and is valid
function checkStoredData() {
    console.log("Checking stored data...");

    // Retrieve the stored data from localStorage
    const workStats = JSON.parse(localStorage.getItem('workStats'));
    const jobPoints = JSON.parse(localStorage.getItem('jobPoints'));
    const profile = JSON.parse(localStorage.getItem('profile'));

    console.log("Retrieved stored data:");
    console.log("Work Stats:", workStats);
    console.log("Job Points:", jobPoints);
    console.log("Profile:", profile);

    // Check if the data exists and if there is an error like "Incorrect key"
    const invalidWorkStats = workStats && workStats.error && workStats.error.code === 2;
    const invalidJobPoints = jobPoints && jobPoints.error && jobPoints.error.code === 2;
    const invalidProfile = profile && profile.error && profile.error.code === 2;

    // Log the validation results
    console.log("Validation results:");
    console.log("Work Stats valid:", !invalidWorkStats);
    console.log("Job Points valid:", !invalidJobPoints);
    console.log("Profile valid:", !invalidProfile);

    // If any data is missing or invalid (contains "Incorrect key" error), fetch the data
    if (!workStats || !jobPoints || !profile || invalidWorkStats || invalidJobPoints || invalidProfile) {
        console.log("One or more data items are missing or invalid. Fetching new data...");
        fetchAPIData();
    } else {
        console.log("All stored data is valid.");
    }
}


// Function to get the last passed 6:30 PM UTC for job updates
function getLastJobUpdateTime() {
    const now = new Date();
    const jobUpdateTime = new Date(now);
    // Set to the latest 6:30 PM UTC
    jobUpdateTime.setUTCHours(18, 30, 0, 0); // 6:30 PM UTC
    if (now < jobUpdateTime) {
        // If the current time is before 6:30 PM today, subtract one day
        jobUpdateTime.setUTCDate(jobUpdateTime.getUTCDate() - 1);
    }
    return jobUpdateTime;
}

// Function to fetch API data if the last fetch date is older than the last 6:30 PM UTC for job updates
async function checkAndFetchAPIData() {
    const lastFetchDateStr = localStorage.getItem('lastFetchDate');
    const lastFetchedJobTime = lastFetchDateStr ? new Date(lastFetchDateStr) : null;
    const lastScheduledJobUpdateTime = getLastJobUpdateTime();
    console.log("Last fetch time:", lastFetchedJobTime);
    console.log("Last scheduled time (6:30 PM UTC):", lastScheduledJobUpdateTime);
    if (!lastFetchedJobTime || lastFetchedJobTime < lastScheduledJobUpdateTime) {
        console.log("Fetching new API data...");
        await fetchAPIData();
    } else {
        console.log("No need to fetch data yet.");
    }
}

// Function to run on page load
function onPageLoad() {
    console.log("Page loaded. Checking stored data...");

    // Check if stored data exists and fetch early if needed
    checkStoredData();

    // Get stored data after ensuring it exists
    const workStats = JSON.parse(localStorage.getItem('workStats'));
    const jobPoints = JSON.parse(localStorage.getItem('jobPoints'));
    const profile = JSON.parse(localStorage.getItem('profile'));

    console.log("Retrieved stored data:");
    console.log("Work Stats:", workStats);
    console.log("Job Points:", jobPoints);
    console.log("Profile:", profile);

    if (workStats && jobPoints && profile) {
        const job = profile.job.job;
        const currentPosition = profile.job.position;
        const jobPointsAvailable = jobPoints.jobpoints.jobs[job.toLowerCase()];
        const workStatsData = {
            manual_labor: workStats.manual_labor,
            intelligence: workStats.intelligence,
            endurance: workStats.endurance,
        };

        console.log(`Checking job upgrade for ${job}, current position: ${currentPosition}, available job points: ${jobPointsAvailable}`);

        // Check if the user can upgrade
        const upgradeMessage = checkJobUpgrade(job, currentPosition, jobPointsAvailable, workStatsData);
        if (upgradeMessage) {
            console.log("Upgrade message found:", upgradeMessage);
            displayUpgradeMessage(upgradeMessage);
        } else {
            console.log("No upgrade available at this time.");
        }
    } else {
        console.log("One or more data items are missing. Work Stats, Job Points, and Profile must all be available.");
    }
}



// Check and fetch the API data on page load
checkAndFetchAPIData();
onPageLoad();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址