Torn - Training Tracker

Tracks how many times each employee has been trained. Reset all counts with one button.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

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

Tendrás que instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Tendrás que instalar una extensión como Tampermonkey antes de poder instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         Torn - Training Tracker 
// @namespace    https://www.torn.com/
// @version      1.1
// @description  Tracks how many times each employee has been trained. Reset all counts with one button.
// @author       Systoned
// @match        https://www.torn.com/companies.php*
// @grant        none
// @run-at       document-end
// ==/UserScript==

(function () {
    'use strict';

    const STORAGE_KEY = 'resilience_train_counts';

    function getCounts() {
        try {
            return JSON.parse(localStorage.getItem(STORAGE_KEY)) || {};
        } catch (e) {
            return {};
        }
    }

    function saveCounts(counts) {
        localStorage.setItem(STORAGE_KEY, JSON.stringify(counts));
    }

    function injectCountBadge(li, id) {
        const counts = getCounts();
        const count = counts[id] || 0;

        const existing = li.querySelector('.tt-count');
        if (existing) {
            existing.textContent = `Trained: ${count}`;
            return;
        }

        const trainDiv = li.querySelector('.train');
        if (!trainDiv) return;

        const badge = document.createElement('div');
        badge.className = 'tt-count';
        badge.style.cssText = `
            clear: both;
            padding: 4px 10px;
            margin: 4px 0 0 0;
            background: #2a2a2a;
            color: #aaa;
            font-size: 12px;
            border-radius: 4px;
            display: inline-block;
        `;
        badge.textContent = `Trained: ${count}`;

        // Inject as a sibling after .train, not inside it
        trainDiv.insertAdjacentElement('afterend', badge);
    }

    function injectResetButton() {
        const existing = document.getElementById('tt-reset-btn');
        if (existing) existing.remove();

        const target = document.querySelector('.title.p10');
        if (!target) return;

        const btn = document.createElement('button');
        btn.id = 'tt-reset-btn';
        btn.textContent = 'Reset Train Counts';
        btn.style.cssText = `
            margin-left: 12px;
            padding: 4px 10px;
            background: #8b0000;
            color: #fff;
            border: none;
            border-radius: 4px;
            font-size: 12px;
            cursor: pointer;
            vertical-align: middle;
        `;

        btn.addEventListener('click', () => {
            if (confirm('Reset all training counts to zero?')) {
                saveCounts({});
                document.querySelectorAll('.tt-count').forEach(el => {
                    el.textContent = 'Trained: 0';
                });
            }
        });

        target.appendChild(btn);
    }

    function processEmployees() {
        const rows = document.querySelectorAll('li[data-user]');
        rows.forEach(li => {
            const id = li.getAttribute('data-user');
            if (!id) return;
            injectCountBadge(li, id);
        });

        injectResetButton();
    }

    // Watch for AJAX train completions
    $('body').on('ajaxComplete', function (e, xhr, settings) {
        const target = (settings.url || '') + (settings.data || '');
        if (!target.includes('trainemp2')) return;

        let data;
        try {
            data = JSON.parse(xhr.responseText);
        } catch (err) {
            return;
        }

        if (!data.success) return;

        const idMatch = target.match(/ID=(\d+)/);
        if (!idMatch) return;

        const id = idMatch[1];
        const counts = getCounts();
        counts[id] = (counts[id] || 0) + 1;
        saveCounts(counts);

        const li = document.querySelector(`li[data-user="${id}"]`);
        if (li) injectCountBadge(li, id);
    });

    function init() {
        if (!window.location.href.includes('companies.php')) return;

        const employeesPanel = document.getElementById('employees');
        if (!employeesPanel) return;

        let debounce;
        const observer = new MutationObserver(() => {
            clearTimeout(debounce);
            debounce = setTimeout(processEmployees, 300);
        });

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

        // Run once in case the tab is already visible on load
        processEmployees();
    }

    if (document.readyState === 'complete') {
        init();
    } else {
        window.addEventListener('load', init);
    }

})();