403Webshell
Server IP : 74.208.236.79  /  Your IP : 216.73.217.19
Web Server : Apache
System : Linux infongp-us50 4.4.400-icpu-108 #2 SMP Wed Feb 11 10:12:42 UTC 2026 x86_64
User : u93192080 ( 6162215)
PHP Version : 8.4.22
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /homepages/45/d732875416/htdocs/clickandbuilds/IronWyvern/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /homepages/45/d732875416/htdocs/clickandbuilds/IronWyvern/simple-tourny.js
(function () {
    // --- Global State & Element Caching ---
    const dynamicFieldsContainer = document.getElementById('dynamic-fields-container');
    const makePairingsBtn = document.getElementById('make-pairings-btn');
    const pairingsContainer = document.getElementById('pairings-container');
    const standingsContainer = document.getElementById('standings-container');
    const resetBtn = document.getElementById('reset-btn');
    const titleInput = document.getElementById('title-input');
    const dateInput = document.getElementById('date-input');
    const roundsSelect = document.getElementById('rounds-select');
    const downloadBtn = document.getElementById('download-btn');
    const fileInput = document.getElementById('file-input');
    const setupContent = document.getElementById('setup-content');
    const setupToggleHeader = document.getElementById('setup-toggle-header');
    const setupToggleIcon = document.getElementById('setup-toggle-icon');
    const modeSelect = document.getElementById('mode-select');

    let pairings = {};
    let standings = [];
    let currentRound = 0;
    let podIdCounter = 0;

    // --- Modal UI for Alerts and Confirmation ---
    function createModal(title, message, type = 'alert', callback = () => {}) {
        let modal = document.getElementById('custom-modal');
        if (!modal) {
            modal = document.createElement('div');
            modal.id = 'custom-modal';
            modal.className = 'fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center p-4 z-50 hidden';
            document.body.appendChild(modal);
        }

        const modalContent = document.createElement('div');
        modalContent.className = 'bg-gray-800 p-6 rounded-lg shadow-2xl w-full max-w-sm';
        modalContent.innerHTML = `
            <h3 id="modal-title" class="text-xl font-bold mb-4 text-white">${title}</h3>
            <p id="modal-message" class="text-gray-300 mb-6">${message}</p>
            <div id="modal-buttons" class="flex justify-end gap-2"></div>
        `;
        modal.innerHTML = '';
        modal.appendChild(modalContent);

        const buttonsContainer = modalContent.querySelector('#modal-buttons');

        if (type === 'confirm') {
            const cancelButton = document.createElement('button');
            cancelButton.className = 'px-4 py-2 bg-gray-600 text-white rounded-lg hover:bg-gray-700 transition-colors';
            cancelButton.textContent = 'Cancel';
            cancelButton.addEventListener('click', () => {
                modal.classList.add('hidden');
                callback(false);
            });
            buttonsContainer.appendChild(cancelButton);
        }

        const okButton = document.createElement('button');
        okButton.className = 'px-4 py-2 bg-orange-500 text-white rounded-lg hover:bg-orange-600 transition-colors';
        okButton.textContent = 'OK';
        okButton.addEventListener('click', () => {
                modal.classList.add('hidden');
            if (type === 'alert') {
                callback();
            } else {
                callback(true);
            }
        });
        buttonsContainer.appendChild(okButton);

        modal.classList.remove('hidden');
    }

    // --- Utility Functions ---

    function updateMakePairingsButton() {
        const playerInputs = dynamicFieldsContainer.querySelectorAll('.player-input');
        const validPlayers = Array.from(playerInputs).filter(input => input.value.trim() !== '' && isValidName(input.value));
        const playerCount = validPlayers.length;
        const mode = modeSelect.value;
        
        let requiredPlayers;
        if (mode === '1v1') {
            requiredPlayers = 4;
        } else if (mode === 'pod') {
            requiredPlayers = 5;
        }

        makePairingsBtn.disabled = playerCount < requiredPlayers;
        makePairingsBtn.classList.toggle('opacity-50', makePairingsBtn.disabled);
        makePairingsBtn.classList.toggle('cursor-not-allowed', makePairingsBtn.disabled);
    }

    function updateDeleteButtonVisibility() {
        const playerRows = document.querySelectorAll('.player-row');
        if (playerRows.length <= 1) {
            playerRows[0].querySelector('.remove-player-btn').style.visibility = 'hidden';
        } else {
            playerRows.forEach(row => {
                row.querySelector('.remove-player-btn').style.visibility = 'visible';
            });
        }
    }

    // New function to enable/disable setup inputs
    function toggleSetupInputs(isDisabled) {
        titleInput.disabled = isDisabled;
        dateInput.disabled = isDisabled;
        modeSelect.disabled = isDisabled;
        roundsSelect.disabled = isDisabled;
        
        const playerInputs = dynamicFieldsContainer.querySelectorAll('.player-input');
        playerInputs.forEach(input => {
            input.disabled = isDisabled;
        });
        
        const removeButtons = dynamicFieldsContainer.querySelectorAll('.remove-player-btn');
        removeButtons.forEach(button => {
            button.disabled = isDisabled;
            button.classList.toggle('opacity-50', isDisabled);
            button.classList.toggle('cursor-not-allowed', isDisabled);
            button.classList.toggle('hidden', isDisabled);
        });

        // Toggle the make pairings button's disabled state
        makePairingsBtn.disabled = isDisabled;
        makePairingsBtn.classList.toggle('opacity-50', isDisabled);
        makePairingsBtn.classList.toggle('cursor-not-allowed', isDisabled);
    }

    function createPlayerInputRow() {
        const playerRow = document.createElement('div');
        playerRow.className = 'player-row flex items-center gap-2';

        const input = document.createElement('input');
        input.type = 'text';
        input.className = 'player-input flex-1 p-3 rounded-lg border-2 border-gray-600 bg-gray-800 text-white placeholder-gray-400 focus:outline-none focus:border-orange-500 transition-colors duration-200 shadow-inner';
        input.placeholder = 'Player Name';

        const removeButton = document.createElement('button');
        removeButton.className = 'remove-player-btn';
        removeButton.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-minus"><path d="M5 12h14"/></svg>`;

        playerRow.appendChild(input);
        playerRow.appendChild(removeButton);

        return playerRow;
    }

    function isValidName(name) {
        const regex = /^[a-zA-Z0-9\s]+$/;
        return regex.test(name);
    }

    function getPlayers() {
        const playerInputs = document.querySelectorAll('.player-input');
        return Array.from(playerInputs)
            .map(input => input.value.trim())
            .filter(name => name !== '' && isValidName(name));
    }

    // --- Pairing Logic ---

    // 1v1 Swiss System pairings
    function make1v1Pairings() {
        const sortedPlayers = [...standings].sort((a, b) => {
            if (b.points !== a.points) return b.points - a.points;
            return (b.tiebreaker || 0) - (a.tiebreaker || 0);
        });

        const playerList = sortedPlayers.map(p => ({
            name: p.name,
            played: p.played,
            points: p.points,
            byes: p.byes
        }));

        const currentPairings = [];
        const pairedPlayers = new Set();
        let byePlayer = null;
        let byePairing = null;

        if (playerList.length % 2 !== 0) {
            let eligibleForBye = playerList.filter(p => p.byes === 0);
            if (eligibleForBye.length === 0) {
                eligibleForBye = playerList;
            }
            byePlayer = eligibleForBye[eligibleForBye.length - 1];
            byePairing = [byePlayer.name, 'Bye'];
            pairedPlayers.add(byePlayer.name);
            byePlayer.byes++;
        }

        for (let i = 0; i < playerList.length; i++) {
            const playerA = playerList[i];
            if (pairedPlayers.has(playerA.name)) continue;

            let paired = false;
            for (let j = i + 1; j < playerList.length; j++) {
                const playerB = playerList[j];
                if (pairedPlayers.has(playerB.name)) continue;

                const hasPlayed = playerA.played.some(match => match === playerB.name);

                if (!hasPlayed) {
                    currentPairings.push([playerA.name, playerB.name]);
                    pairedPlayers.add(playerA.name);
                    pairedPlayers.add(playerB.name);
                    paired = true;
                    break;
                }
            }

            if (!paired) {
                for (let j = i + 1; j < playerList.length; j++) {
                    const playerB = playerList[j];
                    if (!pairedPlayers.has(playerB.name)) {
                        currentPairings.push([playerA.name, playerB.name]);
                        pairedPlayers.add(playerA.name);
                        pairedPlayers.add(playerB.name);
                        break;
                    }
                }
            }
        }

        // Add the bye pairing to the end of the list
        if (byePairing) {
            currentPairings.push(byePairing);
        }

        return currentPairings;
    }

    // Pod Pairing Logic (updated)
    function makePodPairings() {
        const playerNames = getPlayers();
        const numPlayers = playerNames.length;
        let pairings = [];

        // Handle the specific case for exactly 5 players
        if (numPlayers === 5) {
            return [playerNames];
        }

        // Handle the general case for 3 and 4 player pairings
        if (numPlayers < 3) {
            console.error("Not enough players for a valid pairing (minimum 3).");
            return [];
        }

        // Shuffle the players to ensure random pods
        const shuffledPlayers = [...playerNames].sort(() => Math.random() - 0.5);

        // Determine the number of 4-player and 3-player pods
        let numFours = 0;
        let numThrees = 0;

        // Greedy approach: Maximize 4-player pods first
        for (let i = Math.floor(numPlayers / 4); i >= 0; i--) {
            const remaining = numPlayers - (i * 4);
            if (remaining % 3 === 0) {
                numFours = i;
                numThrees = remaining / 3;
                break;
            }
        }
        
        // If no combination is found, it's an invalid number of players
        if ((numFours * 4 + numThrees * 3) !== numPlayers) {
            console.error(`Cannot form valid 3 or 4 player pods with ${numPlayers} players.`);
            return [];
        }

        // Create the 4-player pods
        let currentIndex = 0;
        for (let i = 0; i < numFours; i++) {
            pairings.push(shuffledPlayers.slice(currentIndex, currentIndex + 4));
            currentIndex += 4;
        }

        // Create the 3-player pods
        for (let i = 0; i < numThrees; i++) {
            pairings.push(shuffledPlayers.slice(currentIndex, currentIndex + 3));
            currentIndex += 3;
        }

        return pairings;
    }

    function updateStandings() {
        // Reset points and tiebreakers for recalculation from the start
        standings.forEach(player => {
            player.points = 0;
            player.tiebreaker = 0;
            player.byes = 0;
            player.played = [];
        });

        // Loop through all past rounds to update standings
        for (let r = 1; r <= currentRound; r++) {
            const roundPairings = pairings[r];
            roundPairings.forEach(pairing => {
                if (pairing.type === '1v1') {
                    if (pairing.players[1] === 'Bye') {
                        const player = standings.find(p => p.name === pairing.players[0]);
                        if (player) {
                            player.points += 1;
                            player.byes++;
                        }
                    } else {
                        const player1 = standings.find(p => p.name === pairing.players[0]);
                        const player2 = standings.find(p => p.name === pairing.players[1]);
                        if (player1 && player2) {
                            if (pairing.result === 'win') {
                                const winner = standings.find(p => p.name === pairing.winner);
                                if (winner) winner.points += 1;
                            } else if (pairing.result === 'draw') {
                                player1.points += 0.5;
                                player2.points += 0.5;
                            }
                        }
                        // Update 'played' list for 1v1
                        if (player1) player1.played.push(player2.name);
                        if (player2) player2.played.push(player1.name);
                    }
                } else if (pairing.type === 'pod') {
                    const podPlayers = pairing.players.map(name => standings.find(p => p.name === name)).filter(p => p);
                    if (pairing.result === 'win') {
                        const winner = standings.find(p => p.name === pairing.winner);
                        if (winner) winner.points += 1;
                    } else if (pairing.result === 'draw') {
                        pairing.winners.forEach(winnerName => {
                            const winner = standings.find(p => p.name === winnerName);
                            if (winner) winner.points += 0.5;
                        });
                    }
                    // Update 'played' list for pods (each player played against everyone else in the pod)
                    podPlayers.forEach(p1 => {
                        podPlayers.forEach(p2 => {
                            if (p1 && p2 && p1.name !== p2.name) {
                                p1.played.push(p2.name);
                            }
                        });
                    });
                }
            });
        }

        // Recalculate tiebreakers after updating all points
        standings.forEach(player => {
            player.tiebreaker = 0;
            const playedOpponents = new Set(player.played);
            playedOpponents.forEach(opponentName => {
                const opponent = standings.find(p => p.name === opponentName);
                if (opponent) {
                    player.tiebreaker += opponent.points;
                }
            });
        });
        renderStandings();
    }

    // --- Rendering Functions ---
    function renderPairings(currentRoundPairings) {
        pairingsContainer.innerHTML = '';
        const mode = modeSelect.value;
        if (currentRoundPairings.length === 0) {
            pairingsContainer.innerHTML = `<p class="text-center text-red-400">Not enough players for a new round.</p>`;
            return;
        }

        const roundHeader = document.createElement('div');
        roundHeader.className = 'flex items-center justify-between p-4 bg-gray-700 rounded-lg mb-4';
        roundHeader.innerHTML = `<h2 class="text-xl font-semibold text-orange-400">Round ${currentRound} Pairings</h2>`;
        pairingsContainer.appendChild(roundHeader);

        const pairingsList = document.createElement('div');
        pairingsList.className = 'space-y-4';

        currentRoundPairings.forEach((pairing) => {
            const pairingItem = document.createElement('div');
            pairingItem.className = 'pairing-item p-4 bg-gray-700 rounded-lg flex flex-col sm:flex-row items-center justify-center gap-4 shadow-inner';
            
            const playerButtonsContainer = document.createElement('div');
            playerButtonsContainer.className = 'flex flex-wrap justify-center gap-2 w-full';
            playerButtonsContainer.dataset.podId = pairing.podId;

            if (mode === '1v1') {
                const [player1, player2] = pairing.players;
                if (player2 === 'Bye') {
                    // This is a BYE match
                    pairingItem.classList.remove('bg-gray-700');
                    pairingItem.classList.add('bye-pairing');
                    pairingItem.innerHTML = `
                        <span class="text-lg font-semibold">${player1} has a BYE</span>
                        <div class="flex items-center space-x-2">
                            <button class="bg-green-500 text-white font-bold py-2 px-4 rounded-xl shadow-lg bye-button transition-colors duration-200">
                                Will receive a win
                            </button>
                        </div>
                    `;
                } else {
                    // This is a regular 1v1 match
                    let winnerBtnClass = '';
                    let loserBtnClass = '';
                    let centerText = 'vs';
                    if (pairing) {
                        if (pairing.result === 'win') {
                            if (pairing.winner === player1) {
                                winnerBtnClass = 'selected-win';
                            } else {
                                loserBtnClass = 'selected-win';
                            }
                        } else if (pairing.result === 'draw') {
                            winnerBtnClass = 'selected-draw';
                            loserBtnClass = 'selected-draw';
                            centerText = 'Draw';
                        }
                    }
                    pairingItem.innerHTML = `
                        <div class="flex flex-col sm:flex-row items-center justify-center gap-2 sm:gap-4 w-full">
                            <button class="win-btn ${winnerBtnClass}" data-player="${player1}" data-opponent="${player2}">${player1}</button>
                            <span class="text-lg font-semibold text-gray-400">${centerText}</span>
                            <button class="win-btn ${loserBtnClass}" data-player="${player2}" data-opponent="${player1}">${player2}</button>
                        </div>
                    `;
                }
            } else if (mode === 'pod') {
                pairing.players.forEach(player => {
                    const button = document.createElement('button');
                    button.textContent = player;
                    button.className = 'pod-btn';
                    button.dataset.player = player;
                    if (pairing && pairing.winners && pairing.winners.includes(player)) {
                        if (pairing.result === 'win') {
                            button.classList.add('selected-win');
                        } else if (pairing.result === 'draw') {
                            button.classList.add('selected-draw');
                        }
                    }
                    playerButtonsContainer.appendChild(button);
                });
                pairingItem.appendChild(playerButtonsContainer);
            }

            pairingsList.appendChild(pairingItem);
        });
        pairingsContainer.appendChild(pairingsList);

        const submitRoundBtn = document.createElement('button');
        submitRoundBtn.id = 'submit-round-btn';
        submitRoundBtn.className = 'w-full bg-orange-500 text-white font-semibold py-3 px-6 rounded-lg shadow-md mt-4 transition-colors duration-200 opacity-50 cursor-not-allowed';
        submitRoundBtn.textContent = 'Submit Round Results';
        submitRoundBtn.disabled = true;
        pairingsContainer.appendChild(submitRoundBtn);

        pairingsContainer.classList.remove('hidden');
    }

    function renderStandings() {
        standingsContainer.innerHTML = '';
        const standingsHeader = document.createElement('div');
        standingsHeader.className = 'flex items-center justify-between p-4 bg-gray-700 rounded-lg mb-4';
        standingsHeader.innerHTML = `<h2 id="standings-title" class="text-xl font-semibold text-orange-400">Standings</h2>`;
        standingsContainer.appendChild(standingsHeader);

        const table = document.createElement('table');
        table.className = 'min-w-full leading-normal';
        table.innerHTML = `
            <thead>
                <tr>
                    <th class="px-5 py-3 border-b-2 border-gray-600 !text-white text-left text-xs font-semibold uppercase tracking-wider">Rank</th>
                    <th class="px-5 py-3 border-b-2 border-gray-600 !text-white text-left text-xs font-semibold uppercase tracking-wider">Name</th>
                    <th class="px-5 py-3 border-b-2 border-gray-600 !text-white text-left text-xs font-semibold uppercase tracking-wider">Points</th>
                    <th class="px-5 py-3 border-b-2 border-gray-600 !text-white text-left text-xs font-semibold uppercase tracking-wider">Tiebreaker</th>
                </tr>
            </thead>
            <tbody></tbody>
        `;

        const tbody = table.querySelector('tbody');
        standings.sort((a, b) => {
            if (b.points !== a.points) return b.points - a.points;
            return b.tiebreaker - a.tiebreaker;
        });

        standings.forEach((player, index) => {
            const row = document.createElement('tr');
            row.className = 'border-b border-gray-600 hover:bg-gray-700 transition-colors duration-200';
            row.innerHTML = `
                <td class="px-5 py-5 text-sm whitespace-nowrap">${index + 1}</td>
                <td class="px-5 py-5 text-sm font-medium whitespace-nowrap">${player.name}</td>
                <td class="px-5 py-5 text-sm whitespace-nowrap">${player.points}</td>
                <td class="px-5 py-5 text-sm whitespace-nowrap">${player.tiebreaker.toFixed(2)}</td>
            `;
            tbody.appendChild(row);
        });

        standingsContainer.appendChild(table);
        standingsContainer.classList.remove('hidden');
    }

    // --- Main Logic & Event Listeners ---
    document.addEventListener('DOMContentLoaded', () => {
        const firstInput = dynamicFieldsContainer.querySelector('.player-input');
        if (firstInput) {
            firstInput.focus();
        }
        updateDeleteButtonVisibility();
        updateMakePairingsButton();
    });

    makePairingsBtn.addEventListener('click', () => {
        const playerNames = getPlayers();
        const roundsValue = parseInt(roundsSelect.value);
        const mode = modeSelect.value;
        
        let requiredPlayers;
        if (mode === '1v1') {
            requiredPlayers = 4;
        } else if (mode === 'pod') {
            requiredPlayers = 5;
        }

        if (playerNames.length < requiredPlayers) {
            createModal('Invalid Player Count', `Please add at least ${requiredPlayers} players to start this type of tournament.`);
            return;
        }

        setupContent.classList.add('hidden');
        setupToggleIcon.classList.remove('rotate-180');
        
        // Disable all setup fields
        toggleSetupInputs(true);

        if (currentRound === 0) {
            standings = playerNames.map(name => ({
                name,
                points: 0,
                tiebreaker: 0,
                played: [],
                byes: 0
            }));
        }
        
        let newPairingPlayers;
        if (mode === '1v1') {
            newPairingPlayers = make1v1Pairings();
        } else if (mode === 'pod') {
            newPairingPlayers = makePodPairings();
        }

        if (newPairingPlayers.length === 0) {
            createModal('Invalid Player Count', 'Cannot form valid pods with the current number of players. Please adjust the player count.');
            return;
        }

        currentRound++;

        if (mode === '1v1') {
            pairings[currentRound] = newPairingPlayers.map(p => ({
                players: p,
                result: null,
                winner: null,
                type: '1v1'
            }));
        } else if (mode === 'pod') {
            pairings[currentRound] = newPairingPlayers.map(p => ({
                players: p,
                result: null,
                winners: [],
                type: 'pod',
                podId: podIdCounter++
            }));
        }
        
        renderPairings(pairings[currentRound]);
        renderStandings();
    });

    pairingsContainer.addEventListener('click', (e) => {
        const mode = modeSelect.value;
        const submitRoundBtn = document.getElementById('submit-round-btn');
        let allMatchesComplete = true;

        if (mode === '1v1') {
            const winBtn = e.target.closest('.win-btn');
            if (winBtn) {
                const player = winBtn.dataset.player;
                const opponent = winBtn.dataset.opponent;
                const pairing = pairings[currentRound].find(p => p.players.includes(player) && p.players.includes(opponent));
                if (!pairing) return;
                const opponentBtn = e.target.parentElement.querySelector(`[data-player="${opponent}"]`);
                winBtn.classList.toggle('selected-win');

                if (winBtn.classList.contains('selected-win') && opponentBtn && opponentBtn.classList.contains('selected-win')) {
                    winBtn.classList.add('selected-draw');
                    opponentBtn.classList.add('selected-draw');
                    pairing.result = 'draw';
                    pairing.winner = null;
                } else if (winBtn.classList.contains('selected-win')) {
                    if (opponentBtn) {
                        opponentBtn.classList.remove('selected-win', 'selected-draw');
                    }
                    winBtn.classList.remove('selected-draw');
                    pairing.result = 'win';
                    pairing.winner = player;
                } else {
                    if (opponentBtn) {
                        opponentBtn.classList.remove('selected-draw');
                    }
                    pairing.result = null;
                    pairing.winner = null;
                }
                const centerText = winBtn.closest('.pairing-item').querySelector('.text-gray-400');
                if (pairing.result === 'draw') {
                    centerText.textContent = 'Draw';
                } else {
                    centerText.textContent = 'vs';
                }
            }
            allMatchesComplete = pairings[currentRound].every(p => p.result !== null || p.players[1] === 'Bye');

        } else if (mode === 'pod') {
            const podBtn = e.target.closest('.pod-btn');
            if (podBtn) {
                const podContainer = podBtn.closest('.flex-wrap');
                const player = podBtn.dataset.player;
                const podId = podContainer.dataset.podId;
                const pairing = pairings[currentRound].find(p => p.podId == podId);
                if (!pairing) return;

                // Toggle selection
                podBtn.classList.toggle('selected-win');
                podBtn.classList.remove('selected-draw');
                
                const selectedButtons = Array.from(podContainer.querySelectorAll('.pod-btn.selected-win'));
                const allButtons = Array.from(podContainer.querySelectorAll('.pod-btn'));

                if (selectedButtons.length === 0) {
                    pairing.result = null;
                    pairing.winners = [];
                } else if (selectedButtons.length === 1) {
                    allButtons.forEach(btn => btn.classList.remove('selected-draw'));
                    pairing.result = 'win';
                    pairing.winner = selectedButtons[0].dataset.player;
                    pairing.winners = [selectedButtons[0].dataset.player];
                } else {
                    allButtons.forEach(btn => btn.classList.remove('selected-win'));
                    selectedButtons.forEach(btn => btn.classList.add('selected-draw'));
                    pairing.result = 'draw';
                    pairing.winners = selectedButtons.map(btn => btn.dataset.player);
                }
            }
            allMatchesComplete = pairings[currentRound].every(p => p.result !== null);
        }

        if (submitRoundBtn) {
            submitRoundBtn.disabled = !allMatchesComplete;
            submitRoundBtn.classList.toggle('opacity-50', !allMatchesComplete);
            submitRoundBtn.classList.toggle('cursor-not-allowed', !allMatchesComplete);
            submitRoundBtn.classList.toggle('hover:bg-orange-600', allMatchesComplete);
        }
    });

    document.addEventListener('click', (e) => {
        const submitRoundBtn = e.target.closest('#submit-round-btn');
        if (submitRoundBtn) {
            const roundsValue = parseInt(roundsSelect.value);
            updateStandings();

            if (currentRound >= roundsValue) {
                // Tournament is complete
                pairingsContainer.classList.add('hidden');
                const standingsTitle = document.getElementById('standings-title');
                if (standingsTitle) {
                    standingsTitle.textContent = 'Standings - Final';
                }
                createModal('Tournament Complete', 'The tournament has reached its conclusion! The final standings are now displayed below.');
                return;
            }
            const mode = modeSelect.value;
            let newPairingPlayers;
            if (mode === '1v1') {
                newPairingPlayers = make1v1Pairings();
            } else if (mode === 'pod') {
                newPairingPlayers = makePodPairings();
            }

            currentRound++;

            if (mode === '1v1') {
                pairings[currentRound] = newPairingPlayers.map(p => ({
                    players: p,
                    result: null,
                    winner: null,
                    type: '1v1'
                }));
            } else if (mode === 'pod') {
                pairings[currentRound] = newPairingPlayers.map(p => ({
                    players: p,
                    result: null,
                    winners: [],
                    type: 'pod',
                    podId: podIdCounter++
                }));
            }
            renderPairings(pairings[currentRound]);
        }
    });

    resetBtn.addEventListener('click', () => {
        createModal('Confirm Restart', 'Are you sure you want to restart the event? All pairings and standings will be lost.', 'confirm', (confirmed) => {
            if (confirmed) {
                pairings = {};
                standings = [];
                currentRound = 0;
                pairingsContainer.innerHTML = '';
                standingsContainer.innerHTML = '';
                toggleSetupInputs(false); // Re-enable setup fields
                updateDeleteButtonVisibility();
                updateMakePairingsButton();
                setupContent.classList.remove('hidden');
                setupToggleIcon.classList.add('rotate-180');
            }
        });
    });

    downloadBtn.addEventListener('click', () => {
        const playerNames = getPlayers();
        const tournamentData = {
            title: titleInput.value,
            date: dateInput.value,
            mode: modeSelect.value,
            rounds: roundsSelect.value,
            players: playerNames,
            pairings,
            standings,
            currentRound
        };
        const jsonData = JSON.stringify(tournamentData, null, 2);
        const blob = new Blob([jsonData], { type: 'text/plain;charset=utf-8' });
        const link = document.createElement('a');
        link.href = URL.createObjectURL(blob);
        link.download = 'tournament_data.txt';
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
    });

    fileInput.addEventListener('change', (e) => {
        const file = e.target.files[0];
        if (file) {
            const reader = new FileReader();
            reader.onload = function(event) {
                try {
                    const loadedData = JSON.parse(event.target.result);
                    titleInput.value = loadedData.title;
                    dateInput.value = loadedData.date;
                    modeSelect.value = loadedData.mode;
                    roundsSelect.value = loadedData.rounds;

                    dynamicFieldsContainer.innerHTML = '';
                    loadedData.players.forEach(name => {
                        const newRow = createPlayerInputRow();
                        newRow.querySelector('.player-input').value = name;
                        dynamicFieldsContainer.appendChild(newRow);
                    });

                    pairings = loadedData.pairings;
                    standings = loadedData.standings;
                    currentRound = loadedData.currentRound;

                    if (currentRound > 0) {
                        const currentRoundPairings = pairings[currentRound];
                        renderPairings(currentRoundPairings);
                        renderStandings();
                        toggleSetupInputs(true); // Disable inputs after loading
                    } else {
                        pairingsContainer.innerHTML = '';
                        standingsContainer.innerHTML = '';
                        toggleSetupInputs(false); // Enable inputs if no rounds have been played
                    }
                    updateDeleteButtonVisibility();
                    updateMakePairingsButton();

                } catch (error) {
                    createModal('Load Error', 'Error loading file. Please ensure it is a valid tournament file.');
                    console.error('File load error:', error);
                }
            };
            reader.readAsText(file);
        }
    });

    setupToggleHeader.addEventListener('click', () => {
        setupContent.classList.toggle('hidden');
        setupToggleIcon.classList.toggle('rotate-180');
    });

    dynamicFieldsContainer.addEventListener('keydown', function(event) {
        if (event.key === 'Enter') {
            event.preventDefault();
            const input = event.target;
            const playerName = input.value.trim();
            if (!isValidName(playerName) || playerName === '') {
                input.style.borderColor = '#ef4444';
                return;
            }
            input.style.borderColor = '';
            const playerRows = dynamicFieldsContainer.querySelectorAll('.player-row');
            const isLastRow = input.closest('.player-row') === playerRows[playerRows.length - 1];
            if (isLastRow) {
                const newRow = createPlayerInputRow();
                dynamicFieldsContainer.appendChild(newRow);
                updateDeleteButtonVisibility();
                newRow.querySelector('.player-input').focus();
            }
        }
    });
    
    dynamicFieldsContainer.addEventListener('click', (event) => {
        const removeButton = event.target.closest('.remove-player-btn');
        if (removeButton && !removeButton.disabled) {
            const playerRow = removeButton.closest('.player-row');
            if (playerRow) {
                playerRow.remove();
                updateDeleteButtonVisibility();
                updateMakePairingsButton();
            }
        }
    });

    dynamicFieldsContainer.addEventListener('input', (event) => {
        const input = event.target;
        if (isValidName(input.value) || input.value === '') {
            input.style.borderColor = '';
        }
        updateMakePairingsButton();
    });

    modeSelect.addEventListener('change', updateMakePairingsButton);
    roundsSelect.addEventListener('change', updateMakePairingsButton);

})();

Youez - 2016 - github.com/yon3zu
LinuXploit