Torn Keno Random Selector

Places a Torn-styled block under BET & ROUNDS, centered, to pick random Keno numbers.

当前为 2025-03-28 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

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

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Torn Keno Random Selector
// @namespace    https://greasyfork.org/en/scripts/531078-torn-keno-random-selector
// @version      03.28.2025.19.10
// @description  Places a Torn-styled block under BET & ROUNDS, centered, to pick random Keno numbers.
// @author       KillerCleat
// @match        https://www.torn.com/page.php?sid=keno*
// @grant        none
// @license      MIT License
// ==/UserScript==


(function() {
    'use strict';

    // 1. Randomly pick 'count' unique items from 'arr'
    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); // Remove to ensure uniqueness
        }
        return result;
    }

    // 2. Inject minimal CSS to center our Torn-styled block under BET & ROUNDS
    function injectStyles() {
        const style = document.createElement('style');
        style.innerHTML = `
            /* This container replicates the "cancel" style block but is placed under #controls */
            #randomButtonsContainer {
                width: 100%;
                text-align: center;  /* Center horizontally */
                margin-top: 10px;    /* Space above */
                margin-bottom: 10px; /* Optional space below */
            }
            /* The .desc and .cancel-btn-wrap come from Torn's classes */
            #randomButtonsContainer .desc p {
                margin: 0;
                padding: 0;
            }
            /* Force buttons in a single horizontal row */
            #randomButtonsContainer .cancel-btn-wrap {
                display: inline-block;   /* Keep the buttons together horizontally */
                white-space: nowrap;     /* Prevent wrapping */
                text-align: left;        /* Buttons align left inside the inline-block */
                margin-top: 5px;         /* Space between text and buttons */
            }
            /* Minor spacing for each .btn-wrap.orange so they appear side by side */
            .btn-wrap.orange {
                display: inline-block;
                margin: 0 5px 5px 0;  /* Right & bottom spacing */
            }
        `;
        document.head.appendChild(style);
    }

    // 3. Build the Torn-styled block: text + row of 10 buttons
    function createRandomButtons() {
        // Avoid reinserting if it already exists
        if (document.getElementById('randomButtonsContainer')) return;

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

        // The text area (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);

        // The wrapper that holds the row of buttons
        const cancelBtnWrap = document.createElement('div');
        cancelBtnWrap.className = 'cancel-btn-wrap';
        container.appendChild(cancelBtnWrap);

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

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

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

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

        // Insert our container below BET & ROUNDS (inside #controls)
        const controls = document.getElementById('controls');
        if (controls) {
            controls.appendChild(container);
        } else {
            // Fallback if #controls not found
            document.body.appendChild(container);
        }

        // Attach click handlers to pick random Keno numbers
        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);
                // Filter out any already-marked numbers
                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;
                }

                // Randomly select the requested number
                const selectedSpans = getRandomElements(unmarkedSpans, count);
                // Simulate clicks so Torn's code marks them
                selectedSpans.forEach(span => span.click());
            });
        });
    }

    // 4. Wait until the Keno board & controls exist, then insert our block
    function waitForKenoElements() {
        const boardContainer = document.getElementById('boardContainer');
        const controls = document.getElementById('controls');
        if (boardContainer && controls) {
            createRandomButtons();
            clearInterval(checkInterval);
        }
    }

    // 5. Inject styles & poll every 500ms for #controls to appear
    injectStyles();
    const checkInterval = setInterval(waitForKenoElements, 500);
})();