Torn Keno Random Selector (TornPDA Version)

For TornPDA: Places a Torn-styled block with random selection buttons fixed over the interface so that it is not hidden by the matched numbers panel.

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Torn Keno Random Selector (TornPDA Version)
// @namespace    https://greasyfork.org/en/scripts/531078-torn-keno-random-selector
// @version      03.28.2025.20.00
// @description  For TornPDA: Places a Torn-styled block with random selection buttons fixed over the interface so that it is not hidden by the matched numbers panel.
// @author       KillerCleat
// @match        https://www.torn.com/page.php?sid=keno*
// @grant        none
// @license      MIT License
// ==/UserScript==

(function() {
    'use strict';

    // Utility: Randomly select 'count' unique elements from an array.
    function getRandomElements(arr, count) {
        const arrCopy = [...arr];
        const result = [];
        for (let i = 0; i < count; i++) {
            if (arrCopy.length === 0) break;
            const index = Math.floor(Math.random() * arrCopy.length);
            result.push(arrCopy[index]);
            arrCopy.splice(index, 1);
        }
        return result;
    }

    // Inject CSS for the TornPDA version – fixed positioning with a high z-index.
    function injectStyles() {
        const style = document.createElement('style');
        style.innerHTML = `
            /* Our container is fixed, centered horizontally, with high z-index to overlay the win sheet */
            #randomButtonsContainer {
                position: fixed !important;
                top: 250px !important;  /* Adjust this value to push the block down further */
                left: 50% !important;
                transform: translateX(-50%) !important;
                z-index: 999999 !important;
                width: auto;
                text-align: center;
            }
            /* Torn-styled text */
            #randomButtonsContainer .desc p {
                margin: 0;
                padding: 0;
                font-size: 14px;
                font-weight: bold;
            }
            /* Force the buttons to be in one horizontal row */
            #randomButtonsContainer .cancel-btn-wrap {
                display: inline-block;
                white-space: nowrap;
                margin-top: 5px;
            }
            /* Minor spacing for each button */
            .btn-wrap.orange {
                display: inline-block;
                margin: 0 5px 5px 0;
            }
        `;
        document.head.appendChild(style);
    }

    // Create the Torn-styled block (text + row of buttons).
    function createRandomButtons() {
        if (document.getElementById('randomButtonsContainer')) return;

        // Outer container using Torn's "cancel" class.
        const container = document.createElement('div');
        container.id = 'randomButtonsContainer';
        container.className = 'cancel';

        // Description text (using Torn's "desc" class).
        const desc = document.createElement('div');
        desc.className = 'desc';
        desc.tabIndex = 0;
        desc.innerHTML = '<p>Select how many random numbers to pick:</p>';
        container.appendChild(desc);

        // Wrapper for the buttons.
        const cancelBtnWrap = document.createElement('div');
        cancelBtnWrap.className = 'cancel-btn-wrap';
        container.appendChild(cancelBtnWrap);

        // Create 10 Torn-styled buttons (1–10) in one row.
        for (let i = 1; i <= 10; i++) {
            const btnWrap = document.createElement('div');
            btnWrap.className = 'btn-wrap orange';

            const btnDiv = document.createElement('div');
            btnDiv.className = 'btn';

            const button = document.createElement('button');
            button.className = 'torn-btn orange';
            button.setAttribute('aria-label', `Select ${i}`);
            button.setAttribute('data-count', i);
            button.textContent = i;

            btnDiv.appendChild(button);
            btnWrap.appendChild(btnDiv);
            cancelBtnWrap.appendChild(btnWrap);
        }

        // Append the container directly to the body.
        document.body.appendChild(container);

        // Attach click handlers: simulate click on board numbers so Torn marks them.
        const boardSpans = document.querySelectorAll('#boardContainer span');
        const allButtons = container.querySelectorAll('button');
        allButtons.forEach(btn => {
            btn.addEventListener('click', function() {
                const count = parseInt(this.getAttribute('data-count'), 10);
                const unmarkedSpans = Array.from(boardSpans).filter(
                    span => !span.classList.contains('marked')
                );

                if (unmarkedSpans.length < count) {
                    alert(`Not enough unmarked numbers available. Only ${unmarkedSpans.length} left.`);
                    return;
                }

                const selectedSpans = getRandomElements(unmarkedSpans, count);
                selectedSpans.forEach(span => span.click());
            });
        });
    }

    // Poll for the Keno board to be available, then create our container.
    function waitForKenoElements() {
        const boardContainer = document.getElementById('boardContainer');
        if (boardContainer) {
            createRandomButtons();
            clearInterval(checkInterval);
        }
    }

    injectStyles();
    const checkInterval = setInterval(waitForKenoElements, 500);
})();