RFEVB Seeding Points Calculator

Calculate seeding points (factor >= 7) for beach volleyball players with search support

// ==UserScript==
// @name         RFEVB Seeding Points Calculator
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  Calculate seeding points (factor >= 7) for beach volleyball players with search support
// @author       You
// @match        http://rfevb.com/ranking-voley-playa-masculino
// @match        https://rfevb.com/ranking-voley-playa-masculino
// @match        http://www.rfevb.com/ranking-voley-playa-masculino
// @match        https://www.rfevb.com/ranking-voley-playa-masculino
// @match        http://rfevb.com/ranking-voley-playa-femenino
// @match        https://rfevb.com/ranking-voley-playa-femenino
// @match        http://www.rfevb.com/ranking-voley-playa-femenino
// @match        https://www.rfevb.com/ranking-voley-playa-femenino
// @grant        none
// @license      Apache License 2.0
// ==/UserScript==

(function() {
    'use strict';

    console.log("RFEVB Seeding Points Calculator iniciado");

    // Wait for the page to fully load
    window.addEventListener('load', function() {
        console.log("Página cargada, inicializando script...");

        // Add CSS for our custom elements
        const style = document.createElement('style');
        style.textContent = `
            .seeding-header {
                font-weight: bold;
                margin-top: 10px;
                color: #0099ee;
            }
            .seeding-total {
                font-weight: bold;
                color: #0099ee;
                margin-top: 5px;
                border-top: 1px solid #ddd;
                padding-top: 5px;
            }
            .highlighted-row {
                background-color: #e8f4ff !important;
            }
            .loading {
                color: #888;
                font-style: italic;
            }
        `;
        document.head.appendChild(style);

        // Create column header for seeding points
        setTimeout(function() {
            addSeedingHeaderColumn();
            processAllRows();
        }, 1000);

        // Override the getDatos function to add our functionality after search
        interceptGetDatosFunction();

        // Override the existing mostrarTorneosJugador function to add our seeding calculation
        const originalMostrarTorneosJugador = window.mostrarTorneosJugador;
        window.mostrarTorneosJugador = function(idpersona) {
            // Call the original function
            originalMostrarTorneosJugador(idpersona);

            // Add our seeding calculation after a slight delay to let modal open
            setTimeout(() => {
                calculateSeedingInModal(idpersona);
            }, 1000);
        };

        console.log("Script inicializado correctamente");
    });

    // Function to intercept the getDatos function that's called when searching
    function interceptGetDatosFunction() {
        if (typeof window.getDatos === 'function') {
            console.log("Interceptando función getDatos");

            // Store the original function
            const originalGetDatos = window.getDatos;

            // Replace with our wrapper function
            window.getDatos = function() {
                console.log("getDatos interceptado");

                // Call the original function
                originalGetDatos.apply(this, arguments);

                // Wait for the results to load, then add our seeding data
                setTimeout(function() {
                    console.log("Procesando resultados después de getDatos");
                    addSeedingHeaderColumn();
                    processAllRows();
                }, 1500); // Longer timeout to ensure the table has updated
            };

            console.log("Función getDatos interceptada con éxito");
        } else {
            console.warn("No se encontró la función getDatos. Probando método alternativo.");

            // If getDatos isn't defined yet, try again later
            setTimeout(interceptGetDatosFunction, 1000);
        }
    }

    // Function to add the seeding header column
    function addSeedingHeaderColumn() {
        const headerRow = document.querySelector('#tablajson thead tr');
        if (headerRow) {
            // Check if the seeding header already exists
            let seedingHeaderExists = false;
            const headerCells = headerRow.querySelectorAll('th');

            headerCells.forEach(cell => {
                if (cell.textContent.trim() === 'Seeding') {
                    seedingHeaderExists = true;
                }
            });

            if (!seedingHeaderExists) {
                const headerCell = document.createElement('th');
                headerCell.textContent = 'Seeding';
                headerRow.appendChild(headerCell);
                console.log("Columna añadida al encabezado");
            } else {
                console.log("Columna de Seeding ya existe en el encabezado");
            }
        } else {
            console.error("No se encontró la fila de encabezado de la tabla");
        }
    }

    // Process all rows in the table
    function processAllRows() {
        console.log("Procesando todas las filas");

        // Get all rows in the table
        const rows = document.querySelectorAll('#tablajson tbody tr');
        console.log(`Encontradas ${rows.length} filas en la tabla`);

        // Process each row
        rows.forEach(row => {
            // Check if we need to add a seeding cell
            let seedingCell;
            let lastCell = row.querySelector('td:last-child');

            // If the last cell already has seeding data, don't recalculate
            if (lastCell && lastCell.classList.contains('seeding-cell')) {
                if (lastCell.textContent.trim() !== 'Calculando...' && !lastCell.textContent.trim().includes('Error')) {
                    console.log("Esta fila ya tiene datos de seeding válidos");
                    return;
                }
                // Use the existing cell if it's loading or has an error
                seedingCell = lastCell;
            } else {
                // Create a new seeding cell
                seedingCell = document.createElement('td');
                seedingCell.classList.add('seeding-cell');
                seedingCell.innerHTML = '<span class="loading">Calculando...</span>';
                row.appendChild(seedingCell);
            }

            // Get player info for this row
            const cells = row.querySelectorAll('td');
            if (cells.length >= 3) {
                const playerId = cells[1].textContent.trim();
                const playerName = cells[2].textContent.trim();

                // Calculate seeding for this player
                calculateAndDisplaySeeding(playerId, playerName, seedingCell);
            }
        });
    }

    // Helper function to properly parse Spanish formatted numbers (1.680 -> 1680)
    function parseSpanishNumber(numStr) {
        // Remove all thousand separators (periods) and then parse
        return parseInt(numStr.replace(/\./g, ''));
    }

    // Function to calculate seeding points directly from API
    function calculateAndDisplaySeeding(playerId, playerName, seedingCell) {
        console.log(`Calculando puntos de seeding para: ${playerName} (${playerId})`);

        // Set loading state
        seedingCell.innerHTML = '<span class="loading">Calculando...</span>';

        const auxFecha = document.getElementById('fechaRanking').value;
        console.log(`Fecha de ranking: ${auxFecha}`);

        fetch(`https://intranet.rfevb.com/webservices/rfevbcom/vplaya/vp-torneos-deportista-html.php?IdPersona=${playerId}&fechaHasta=${auxFecha}`)
            .then(response => response.text())
            .then(html => {
                const parser = new DOMParser();
                const doc = parser.parseFromString(html, 'text/html');

                let seedingPoints = 0;
                let tournamentCount = 0;

                // Find tournament rows with factor >= 7
                const rows = doc.querySelectorAll('table tr');
                console.log(`Encontrados ${rows.length} torneos para analizar`);

                rows.forEach(row => {
                    const cells = row.querySelectorAll('td');
                    if (cells.length >= 6) {
                        const factorText = cells[4].textContent.trim();
                        const factor = parseFloat(factorText);

                        if (factor >= 7) {
                            const pointsText = cells[6].textContent.trim();
                            const points = parseSpanishNumber(pointsText);
                            if (!isNaN(points)) {
                                seedingPoints += points;
                                tournamentCount++;
                                console.log(`Torneo con factor ${factor}: ${points} puntos`);
                            }
                        }
                    }
                });

                console.log(`Total puntos seeding: ${seedingPoints} de ${tournamentCount} torneos`);

                // Update the seeding cell with the result
                seedingCell.innerHTML = `${seedingPoints.toLocaleString('es-ES')}`;
                seedingCell.title = `Calculado de ${tournamentCount} torneos con factor ≥ 7`;
            })
            .catch(error => {
                console.error('Error fetching player data:', error);
                seedingCell.innerHTML = 'Error';
                seedingCell.title = error.message;
            });
    }

    // Function to calculate and display seeding points in the modal
    function calculateSeedingInModal(playerId) {
        const modal = document.querySelector('#mymodalexp .modal-body');
        if (!modal) {
            console.error("No se encontró el modal");
            return;
        }

        // Check if we already added seeding calculation
        if (modal.querySelector('.seeding-header')) {
            console.log("Cálculo de seeding ya añadido al modal");
            return;
        }

        console.log(`Calculando puntos de seeding en modal para jugador: ${playerId}`);

        let seedingPoints = 0;
        let seedingTournaments = [];

        // Find all tournament rows in the modal
        const rows = modal.querySelectorAll('table tr');
        console.log(`Encontradas ${rows.length} filas en el modal`);

        rows.forEach(row => {
            const cells = row.querySelectorAll('td');
            if (cells.length >= 6) {
                const factorText = cells[4].textContent.trim();
                const factor = parseFloat(factorText);

                if (factor >= 7) {
                    const tournamentId = cells[0].textContent.trim();
                    const tournamentDate = cells[1].textContent.trim();
                    const tournamentName = cells[2].textContent.trim();

                    const pointsText = cells[6].textContent.trim();
                    const points = parseSpanishNumber(pointsText);

                    if (!isNaN(points)) {
                        seedingPoints += points;
                        seedingTournaments.push({
                            id: tournamentId,
                            date: tournamentDate,
                            name: tournamentName,
                            factor: factor,
                            points: points
                        });

                        // Highlight this row
                        row.classList.add('highlighted-row');
                        console.log(`Torneo válido: ${tournamentName}, factor ${factor}, ${points} puntos`);
                    }
                }
            }
        });

        console.log(`Total puntos seeding en modal: ${seedingPoints} de ${seedingTournaments.length} torneos`);

        // Create and append seeding summary
        const seedingHeader = document.createElement('div');
        seedingHeader.className = 'seeding-header';
        seedingHeader.textContent = 'Torneos para seeding (factor ≥ 7):';

        const seedingList = document.createElement('ul');
        seedingList.style.marginLeft = '20px';

        seedingTournaments.forEach(tournament => {
            const listItem = document.createElement('li');
            listItem.textContent = `${tournament.name} (Factor ${tournament.factor}): ${tournament.points.toLocaleString('es-ES')} puntos`;
            seedingList.appendChild(listItem);
        });

        const seedingTotal = document.createElement('div');
        seedingTotal.className = 'seeding-total';
        seedingTotal.innerHTML = `TOTAL PUNTOS SEEDING: ${seedingPoints.toLocaleString('es-ES')}`;

        // Add elements to modal
        modal.appendChild(document.createElement('hr'));
        modal.appendChild(seedingHeader);
        modal.appendChild(seedingList);
        modal.appendChild(seedingTotal);

        console.log("Información de seeding añadida al modal correctamente");
    }
})();