增強報號 Lotto Auto Submit Enhanced

增強報號 Lotto Auto Submit Enhanced 是一款專為樂透研究院網站(lotto.arclink.com.tw)設計的自動化報號腳本。

// ==UserScript==
// @name         增強報號 Lotto Auto Submit Enhanced
// @namespace    http://tampermonkey.net/
// @version      3.2.58
// @description  增強報號 Lotto Auto Submit Enhanced 是一款專為樂透研究院網站(lotto.arclink.com.tw)設計的自動化報號腳本。
// @author       ArnoldCode
// @match        https://lotto.arclink.com.tw/*
// @grant        none
// @license      GPL-3.0
// ==/UserScript==

/*
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * See <https://www.gnu.org/licenses/> for more details.
 */

(function() {
    'use strict';

    const gameTypes = {
        '大樂透': {
            numbers: 6, range: [1, 49], special: false, splitByComma: true,
            urlSix: 'https://lotto.arclink.com.tw/post.do?go=game&iType=1',
            urlFive: 'https://lotto.arclink.com.tw/post.do?go=gameno&iType=1',
            urlTwo: 'https://lotto.arclink.com.tw/post.do?go=gamesec&iType=1',
            urlSingle: 'https://lotto.arclink.com.tw/post.do?go=gameone&iType=1',
            labelSix: '大樂透(報六碼):', labelFive: '大樂透(刪五碼):'
        },
        '六合彩': {
            numbers: 6, range: [1, 49], special: false, splitByComma: true,
            urlSix: 'https://lotto.arclink.com.tw/post.do?go=game&iType=5',
            urlFive: 'https://lotto.arclink.com.tw/post.do?go=gameno&iType=5',
            urlTwo: 'https://lotto.arclink.com.tw/post.do?go=gamesec&iType=5',
            urlSingle: 'https://lotto.arclink.com.tw/post.do?go=gameone&iType=5',
            labelSix: '六合彩(報六碼):', labelFive: '六合彩(刪五碼):'
        },
        '威力彩': {
            numbers: 6, range: [1, 38], special: false, splitByComma: true,
            urlSix: 'https://lotto.arclink.com.tw/post.do?go=game&iType=12',
            urlFive: 'https://lotto.arclink.com.tw/post.do?go=gameno&iType=12',
            urlTwo: 'https://lotto.arclink.com.tw/post.do?go=gamesec&iType=12',
            urlSingle: 'https://lotto.arclink.com.tw/post.do?go=gameone&iType=12',
            labelSix: '威力彩(報六碼):', labelFive: '威力彩(刪五碼):'
        },
        '今彩539': {
            numbers: 5, range: [1, 39], special: false, splitByComma: true,
            urlSix: 'https://lotto.arclink.com.tw/post.do?go=game395&iType=9',
            urlFive: 'https://lotto.arclink.com.tw/post.do?go=game395no&iType=9',
            urlTwo: 'https://lotto.arclink.com.tw/post.do?go=game395sec&iType=9',
            urlSingle: 'https://lotto.arclink.com.tw/post.do?go=game395one&iType=9',
            labelSix: '今彩539(報五碼):', labelFive: '今彩539(刪五碼):'
        },
        '三星彩': {
            numbers: 3, range: [0, 9], special: false, splitByComma: false,
            urlSix: 'https://lotto.arclink.com.tw/post.do?go=game3star&iType=7',
            urlFive: null,
            urlTwo: null,
            urlSingle: null,
            labelSix: '三星彩:', labelFive: null
        },
        '四星彩': {
            numbers: 4, range: [0, 9], special: false, splitByComma: false,
            urlSix: 'https://lotto.arclink.com.tw/post.do?go=game4star&iType=4',
            urlFive: null,
            urlTwo: null,
            urlSingle: null,
            labelSix: '四星彩:', labelFive: null
        }
    };

    const defaultChecked = ['今彩539'];

    function createFloatBox() {
    if (!window.location.href.includes('lotterygame.html')) return;

    let floatBox = document.createElement('div');
    floatBox.id = 'lottoBox';
    floatBox.style.position = 'fixed';
    floatBox.style.left = '50%';
    floatBox.style.transform = 'translateX(-50%)';
    floatBox.style.bottom = localStorage.getItem('lottoBoxBottom') || '20px';
    floatBox.style.width = '330px';
    floatBox.style.background = 'rgba(0, 0, 0, 0.8)';
    floatBox.style.color = 'white';
    floatBox.style.padding = '15px';
    floatBox.style.borderRadius = '8px';
    floatBox.style.zIndex = '9999';
    floatBox.style.cursor = 'move';
    floatBox.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.2)';
    floatBox.style.display = 'flex';
    floatBox.style.flexDirection = 'column';
    floatBox.style.alignItems = 'center';
    floatBox.style.fontFamily = 'Arial, sans-serif';
    floatBox.style.fontSize = '14px';
    floatBox.style.transition = 'top 0.1s ease, left 0.1s ease';

    floatBox.innerHTML = `
        <b style="margin-bottom: 10px;">增強報號</b>
        <div style="display: flex; width: 100%; gap: 5px; margin-bottom: 10px;">
            <button id="tabSix" style="flex: 1; padding: 5px; background: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer;">報六碼</button>
            <button id="tabFive" style="flex: 1; padding: 5px; background: #2196F3; color: white; border: none; border-radius: 4px; cursor: pointer;">刪五碼</button>
            <button id="tabTwo" style="flex: 1; padding: 5px; background: #FF9800; color: white; border: none; border-radius: 4px; cursor: pointer;">報二碼</button>
            <button id="tabSingle" style="flex: 1; padding: 5px; background: #9C27B0; color: white; border: none; border-radius: 4px; cursor: pointer;">報獨支</button>
        </div>
        <div id="tabContent" style="width: 100%;">
            <div id="sixCodeContent" style="display: block;">
                <div id="gameInputsSix" style="width: 100%;">
                    ${Object.entries(gameTypes).map(([type, config]) => `
                        <div style="display: flex; align-items: center; gap: 5px; margin-bottom: 10px;">
                            <input type="checkbox" id="checkbox_six_${type}" ${defaultChecked.includes(type) ? 'checked' : ''} style="margin-right: 5px;">
                            <label style="white-space: nowrap; width: 120px;" for="checkbox_six_${type}">${config.labelSix}</label>
                            <input type="text" id="lottoNumbers_six_${type}" style="width: 130px; padding: 5px; border-radius: 4px; border: none;" placeholder="${config.splitByComma ? `例: ${Array(config.numbers).fill(0).map((_, i) => i + 1).join(',')}` : `例: ${Array(config.numbers).fill(0).map((_, i) => i + 1).join('')}`}">
                            <button class="randomPickSix" data-type="${type}" style="padding: 5px; background: #2196F3; color: white; border: none; border-radius: 4px; cursor: pointer;">隨機</button>
                        </div>
                    `).join('')}
                </div>
                <div style="display: flex; width: 100%; gap: 5px; margin-top: 10px;">
                    <button id="selectAllSix" style="padding: 5px; background: #FF9800; color: white; border: none; border-radius: 4px; cursor: pointer; width: auto;">全部勾選</button>
                    <button id="clearAllSix" style="padding: 5px; background: #F44336; color: white; border: none; border-radius: 4px; cursor: pointer; flex: 1;">全部取消</button>
                    <button id="randomAllSix" style="padding: 5px; background: #2196F3; color: white; border: none; border-radius: 4px; cursor: pointer; width: auto;">全部隨機</button>
                </div>
                <button id="submitAllSix" style="width: 100%; margin-top: 10px; padding: 5px; background: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer;">一鍵提交自動勾選號碼</button>
                <div id="messageBox" style="width: 100%; margin-top: 10px; padding: 5px; color: white; word-wrap: break-word; display: none;"></div>
            </div>
            <div id="fiveCodeContent" style="display: none;">
                <div id="gameInputsFive" style="width: 100%;">
                    ${Object.entries(gameTypes).filter(([type]) => type !== '三星彩' && type !== '四星彩').map(([type, config]) => `
                        <div style="display: flex; align-items: center; gap: 5px; margin-bottom: 10px;">
                            <input type="checkbox" id="checkbox_five_${type}" ${defaultChecked.includes(type) ? 'checked' : ''} style="margin-right: 5px;">
                            <label style="white-space: nowrap; width: 120px;" for="checkbox_five_${type}">${config.labelFive}</label>
                            <input type="text" id="lottoNumbers_five_${type}" style="width: 130px; padding: 5px; border-radius: 4px; border: none;" placeholder="例: 1,2,3,4,5">
                            <button class="randomPickFive" data-type="${type}" style="padding: 5px; background: #2196F3; color: white; border: none; border-radius: 4px; cursor: pointer;">隨機</button>
                        </div>
                    `).join('')}
                </div>
                <div style="display: flex; width: 100%; gap: 5px; margin-top: 10px;">
                    <button id="selectAllFive" style="padding: 5px; background: #FF9800; color: white; border: none; border-radius: 4px; cursor: pointer; width: auto;">全部勾選</button>
                    <button id="clearAllFive" style="padding: 5px; background: #F44336; color: white; border: none; border-radius: 4px; cursor: pointer; flex: 1;">全部取消</button>
                    <button id="randomAllFive" style="padding: 5px; background: #2196F3; color: white; border: none; border-radius: 4px; cursor: pointer; width: auto;">全部隨機</button>
                </div>
                <button id="submitAllFive" style="width: 100%; margin-top: 10px; padding: 5px; background: #2196F3; color: white; border: none; border-radius: 4px; cursor: pointer;">一鍵提交自動勾選號碼</button>
                <div id="messageBox" style="width: 100%; margin-top: 10px; padding: 5px; color: white; word-wrap: break-word; display: none;"></div>
            </div>
            <div id="twoCodeContent" style="display: none;">
                <div id="gameInputsTwo" style="width: 100%;">
                    ${Object.entries(gameTypes).filter(([type]) => type !== '三星彩' && type !== '四星彩').map(([type, config]) => `
                        <div style="display: flex; align-items: center; gap: 5px; margin-bottom: 10px;">
                            <input type="checkbox" id="checkbox_two_${type}" ${defaultChecked.includes(type) ? 'checked' : ''} style="margin-right: 5px;">
                            <label style="white-space: nowrap; width: 120px;" for="checkbox_two_${type}">${config.labelFive.replace('刪五碼', '報二碼')}</label>
                            <input type="text" id="lottoNumbers_two_${type}" style="width: 130px; padding: 5px; border-radius: 4px; border: none;" placeholder="例: 1,2">
                            <button class="randomPickTwo" data-type="${type}" style="padding: 5px; background: #FF9800; color: white; border: none; border-radius: 4px; cursor: pointer;">隨機</button>
                        </div>
                    `).join('')}
                </div>
                <div style="display: flex; width: 100%; gap: 5px; margin-top: 10px;">
                    <button id="selectAllTwo" style="padding: 5px; background: #FF9800; color: white; border: none; border-radius: 4px; cursor: pointer; width: auto;">全部勾選</button>
                    <button id="clearAllTwo" style="padding: 5px; background: #F44336; color: white; border: none; border-radius: 4px; cursor: pointer; flex: 1;">全部取消</button>
                    <button id="randomAllTwo" style="padding: 5px; background: #FF9800; color: white; border: none; border-radius: 4px; cursor: pointer; width: auto;">全部隨機</button>
                </div>
                <button id="submitAllTwo" style="width: 100%; margin-top: 10px; padding: 5px; background: #FF9800; color: white; border: none; border-radius: 4px; cursor: pointer;">一鍵提交自動勾選號碼</button>
                <div id="messageBox" style="width: 100%; margin-top: 10px; padding: 5px; color: white; word-wrap: break-word; display: none;"></div>
            </div>
            <div id="singleCodeContent" style="display: none;">
                <div id="gameInputsSingle" style="width: 100%;">
                    ${Object.entries(gameTypes).filter(([type]) => type !== '三星彩' && type !== '四星彩').map(([type, config]) => `
                        <div style="display: flex; align-items: center; gap: 5px; margin-bottom: 10px;">
                            <input type="checkbox" id="checkbox_single_${type}" ${defaultChecked.includes(type) ? 'checked' : ''} style="margin-right: 5px;">
                            <label style="white-space: nowrap; width: 120px;" for="checkbox_single_${type}">${config.labelFive.replace('刪五碼', '報獨支')}</label>
                            <input type="text" id="lottoNumbers_single_${type}" style="width: 130px; padding: 5px; border-radius: 4px; border: none;" placeholder="例: 1">
                            <button class="randomPickSingle" data-type="${type}" style="padding: 5px; background: #9C27B0; color: white; border: none; border-radius: 4px; cursor: pointer;">隨機</button>
                        </div>
                    `).join('')}
                </div>
                <div style="display: flex; width: 100%; gap: 5px; margin-top: 10px;">
                    <button id="selectAllSingle" style="padding: 5px; background: #FF9800; color: white; border: none; border-radius: 4px; cursor: pointer; width: auto;">全部勾選</button>
                    <button id="clearAllSingle" style="padding: 5px; background: #F44336; color: white; border: none; border-radius: 4px; cursor: pointer; flex: 1;">全部取消</button>
                    <button id="randomAllSingle" style="padding: 5px; background: #9C27B0; color: white; border: none; border-radius: 4px; cursor: pointer; width: auto;">全部隨機</button>
                </div>
                <button id="submitAllSingle" style="width: 100%; margin-top: 10px; padding: 5px; background: #9C27B0; color: white; border: none; border-radius: 4px; cursor: pointer;">一鍵提交自動勾選號碼</button>
                <div id="messageBox" style="width: 100%; margin-top: 10px; padding: 5px; color: white; word-wrap: break-word; display: none;"></div>
            </div>
        </div>
    `;
    document.body.appendChild(floatBox);

    // 以下為原有的按鈕事件監聽器,保持不變
    const tabSix = document.getElementById('tabSix');
    const tabFive = document.getElementById('tabFive');
    const tabTwo = document.getElementById('tabTwo');
    const tabSingle = document.getElementById('tabSingle');
    const sixCodeContent = document.getElementById('sixCodeContent');
    const fiveCodeContent = document.getElementById('fiveCodeContent');
    const twoCodeContent = document.getElementById('twoCodeContent');
    const singleCodeContent = document.getElementById('singleCodeContent');

    tabSix.addEventListener('click', () => {
        tabSix.style.background = '#4CAF50';
        tabFive.style.background = '#2196F3';
        tabTwo.style.background = '#FF9800';
        tabSingle.style.background = '#9C27B0';
        sixCodeContent.style.display = 'block';
        fiveCodeContent.style.display = 'none';
        twoCodeContent.style.display = 'none';
        singleCodeContent.style.display = 'none';
    });

    tabFive.addEventListener('click', () => {
        tabSix.style.background = '#4CAF50';
        tabFive.style.background = '#2196F3';
        tabTwo.style.background = '#FF9800';
        tabSingle.style.background = '#9C27B0';
        sixCodeContent.style.display = 'none';
        fiveCodeContent.style.display = 'block';
        twoCodeContent.style.display = 'none';
        singleCodeContent.style.display = 'none';
    });

    tabTwo.addEventListener('click', () => {
        tabSix.style.background = '#4CAF50';
        tabFive.style.background = '#2196F3';
        tabTwo.style.background = '#FF9800';
        tabSingle.style.background = '#9C27B0';
        sixCodeContent.style.display = 'none';
        fiveCodeContent.style.display = 'none';
        twoCodeContent.style.display = 'block';
        singleCodeContent.style.display = 'none';
    });

    tabSingle.addEventListener('click', () => {
        tabSix.style.background = '#4CAF50';
        tabFive.style.background = '#2196F3';
        tabTwo.style.background = '#FF9800';
        tabSingle.style.background = '#9C27B0';
        sixCodeContent.style.display = 'none';
        fiveCodeContent.style.display = 'none';
        twoCodeContent.style.display = 'none';
        singleCodeContent.style.display = 'block';
    });

    makeDraggable(floatBox);
    document.querySelectorAll('.randomPickSix').forEach(btn => btn.addEventListener('click', (e) => randomPickHandler(e, 'six')));
    document.querySelectorAll('.randomPickFive').forEach(btn => btn.addEventListener('click', (e) => randomPickHandler(e, 'five')));
    document.querySelectorAll('.randomPickTwo').forEach(btn => btn.addEventListener('click', (e) => randomPickHandler(e, 'two')));
    document.querySelectorAll('.randomPickSingle').forEach(btn => btn.addEventListener('click', (e) => randomPickHandler(e, 'single')));
    document.getElementById('submitAllSix').addEventListener('click', () => submitNumbers('six'));
    document.getElementById('submitAllFive').addEventListener('click', () => submitNumbers('five'));
    document.getElementById('submitAllTwo').addEventListener('click', () => submitNumbers('two'));
    document.getElementById('submitAllSingle').addEventListener('click', () => submitNumbers('single'));
    document.getElementById('selectAllSix').addEventListener('click', () => selectAll('six'));
    document.getElementById('clearAllSix').addEventListener('click', () => clearAll('six'));
    document.getElementById('randomAllSix').addEventListener('click', () => randomAll('six'));
    document.getElementById('selectAllFive').addEventListener('click', () => selectAll('five'));
    document.getElementById('clearAllFive').addEventListener('click', () => clearAll('five'));
    document.getElementById('randomAllFive').addEventListener('click', () => randomAll('five'));
    document.getElementById('selectAllTwo').addEventListener('click', () => selectAll('two'));
    document.getElementById('clearAllTwo').addEventListener('click', () => clearAll('two'));
    document.getElementById('randomAllTwo').addEventListener('click', () => randomAll('two'));
    document.getElementById('selectAllSingle').addEventListener('click', () => selectAll('single'));
    document.getElementById('clearAllSingle').addEventListener('click', () => clearAll('single'));
    document.getElementById('randomAllSingle').addEventListener('click', () => randomAll('single'));
}

    function makeDraggable(element) {
        let isDragging = false;
        let shiftX, shiftY;

        const rect = element.getBoundingClientRect();
        element.style.left = `${rect.left}px`;
        element.style.top = `${rect.top}px`;
        element.style.bottom = 'auto';
        element.style.transform = 'none';

        element.onmousedown = function(event) {
            if (event.button !== 0) return;
            if (event.target.tagName === 'INPUT' || event.target.tagName === 'BUTTON') return;

            event.preventDefault();

            isDragging = true;

            const rect = element.getBoundingClientRect();
            shiftX = event.clientX - rect.left;
            shiftY = event.clientY - rect.top;

            element.style.left = `${rect.left}px`;
            element.style.top = `${rect.top}px`;

            function moveAt(clientX, clientY) {
                let newLeft = clientX - shiftX;
                let newTop = clientY - shiftY;

                const minLeft = 0;
                const minTop = 0;
                const maxLeft = window.innerWidth - rect.width;
                const maxTop = window.innerHeight - rect.height;

                newLeft = Math.max(minLeft, Math.min(newLeft, maxLeft));
                newTop = Math.max(minTop, Math.min(newTop, maxTop));

                element.style.left = `${newLeft}px`;
                element.style.top = `${newTop}px`;
                localStorage.setItem('lottoBoxLeft', element.style.left);
                localStorage.setItem('lottoBoxTop', element.style.top);
                localStorage.removeItem('lottoBoxBottom');
            }

            function onMouseMove(event) {
                if (isDragging) {
                    moveAt(event.clientX, event.clientY);
                }
            }

            document.addEventListener('mousemove', onMouseMove);
            document.addEventListener('mouseup', function onMouseUp() {
                isDragging = false;
                document.removeEventListener('mousemove', onMouseMove);
                document.removeEventListener('mouseup', onMouseUp);
            }, { once: true });
        };

        element.ondragstart = function() { return false; };
    }

    function randomPickHandler(e, tab) {
        let type = e.target.dataset.type;
        if (document.getElementById(`checkbox_${tab}_${type}`).checked) {
            randomPickNumbers(type, tab);
        } else {
            logToStorage(`請先勾選 ${type} 以啟用隨機選號`, true);
        }
    }

    function randomPickNumbers(gameType, tab) {
        let config = gameTypes[gameType];
        let numbers = [];
        let targetCount = (tab === 'five') ? 5 : (tab === 'two') ? 2 : (tab === 'single') ? 1 : config.numbers;

        while (numbers.length < targetCount) {
            let num = Math.floor(Math.random() * (config.range[1] - config.range[0] + 1)) + config.range[0];
            if (!numbers.includes(num)) numbers.push(num);
        }

        document.getElementById(`lottoNumbers_${tab}_${gameType}`).value = config.splitByComma ? numbers.join(',') : numbers.join('');
    }

    function selectAll(tab) {
        Object.keys(gameTypes).forEach(type => {
            if (tab !== 'six' && (type === '三星彩' || type === '四星彩')) return;
            document.getElementById(`checkbox_${tab}_${type}`).checked = true;
        });
    }

    function clearAll(tab) {
        Object.keys(gameTypes).forEach(type => {
            if (tab !== 'six' && (type === '三星彩' || type === '四星彩')) return;
            document.getElementById(`checkbox_${tab}_${type}`).checked = false;
            document.getElementById(`lottoNumbers_${tab}_${type}`).value = '';
        });
    }

    function randomAll(tab) {
        Object.keys(gameTypes).forEach(type => {
            if (tab !== 'six' && (type === '三星彩' || type === '四星彩')) return;
            if (document.getElementById(`checkbox_${tab}_${type}`).checked) {
                randomPickNumbers(type, tab);
            }
        });
    }

    function submitNumbers(tab) {
        let gamesToSubmit = [];
        let hasError = false;

        for (let [type, config] of Object.entries(gameTypes)) {
            if (tab !== 'six' && (type === '三星彩' || type === '四星彩')) continue;
            let checkbox = document.getElementById(`checkbox_${tab}_${type}`);
            if (!checkbox.checked) continue;

            let inputText = document.getElementById(`lottoNumbers_${tab}_${type}`).value.trim();
            if (!inputText) {
                let errorMsg = `請填寫 ${type} 的號碼`;
                logToStorage(errorMsg, true);
                showMessage(errorMsg);
                hasError = true;
                continue;
            }

            let numbers = config.splitByComma
                ? inputText.split(',').map(n => parseInt(n.trim(), 10)).filter(n => !isNaN(n))
                : inputText.split('').map(n => parseInt(n, 10)).filter(n => !isNaN(n));
            let targetCount = (tab === 'five') ? 5 : (tab === 'two') ? 2 : (tab === 'single') ? 1 : config.numbers;

            if (numbers.length !== targetCount ||
                numbers.some(n => n < config.range[0] || n > config.range[1])) {
                let errorMsg = `請輸入有效的${type}號碼,${targetCount}個數字(${config.range[0]}-${config.range[1]})`;
                logToStorage(errorMsg, true);
                showMessage(errorMsg);
                hasError = true;
                continue;
            }

            let url;
            if (tab === 'six') url = config.urlSix;
            else if (tab === 'five') url = config.urlFive;
            else if (tab === 'two') url = config.urlTwo;
            else if (tab === 'single') url = config.urlSingle;

            gamesToSubmit.push({
                gameType: type,
                numbers: numbers,
                url: url,
                isFiveCode: (tab !== 'six') // 報六碼以外的都視為類似刪五碼的提交邏輯
            });
        }

        if (hasError) return;

        if (gamesToSubmit.length === 0) {
            let errorMsg = '請至少勾選並填寫一種彩券號碼';
            logToStorage(errorMsg, true);
            showMessage(errorMsg);
            return;
        }

        logToStorage(`準備提交 ${gamesToSubmit.length} 個遊戲: ${gamesToSubmit.map(g => g.gameType).join(', ')}`);
        localStorage.setItem('gamesToSubmit', JSON.stringify(gamesToSubmit));
        localStorage.setItem('currentGameIndex', '0');
        processNextGame();
    }

    function processNextGame() {
        let gamesToSubmit = JSON.parse(localStorage.getItem('gamesToSubmit') || '[]');
        let currentGameIndex = parseInt(localStorage.getItem('currentGameIndex') || '0', 10);

        if (currentGameIndex >= gamesToSubmit.length) {
            logToStorage('所有遊戲報號完成!返回首頁...');
            localStorage.removeItem('gamesToSubmit');
            localStorage.removeItem('currentGameIndex');
            localStorage.removeItem('lottoNumbers');
            setTimeout(() => {
                window.location.href = 'https://lotto.arclink.com.tw/';
            }, 2000);
            return;
        }

        let currentGame = gamesToSubmit[currentGameIndex];
        logToStorage(`處理第 ${currentGameIndex + 1}/${gamesToSubmit.length} 個遊戲: ${currentGame.gameType},跳轉至 ${currentGame.url}`);
        localStorage.setItem('lottoNumbers', JSON.stringify(currentGame));
        window.location.href = currentGame.url;
    }

    function logToStorage(message, isError = false) {
        let logs = JSON.parse(localStorage.getItem('lottoLogs') || '[]');
        logs.push({ time: new Date().toLocaleString(), message, isError });
        localStorage.setItem('lottoLogs', JSON.stringify(logs.slice(-10)));
    }

    function showMessage(message) {
        let activeTab = document.getElementById('sixCodeContent').style.display === 'block' ? 'sixCodeContent' :
                        document.getElementById('fiveCodeContent').style.display === 'block' ? 'fiveCodeContent' :
                        document.getElementById('twoCodeContent').style.display === 'block' ? 'twoCodeContent' : 'singleCodeContent';
        let msgBox = document.getElementById('lottoBox').querySelector(`#${activeTab} #messageBox`);
        msgBox.style.display = 'block';
        msgBox.style.background = 'rgba(255, 0, 0, 0.8)';
        msgBox.textContent = message;
        msgBox.style.height = 'auto';
        setTimeout(() => {
            msgBox.style.display = 'none';
            msgBox.textContent = '';
        }, 3000);
    }

    function fillNumbers() {
        let storedData = localStorage.getItem('lottoNumbers');
        let gamesToSubmit = localStorage.getItem('gamesToSubmit');
        if (!storedData || !gamesToSubmit) {
            logToStorage('無待處理的號碼資料或不在自動提交流程中,跳過 fillNumbers');
            return;
        }

        let data = JSON.parse(storedData);
        logToStorage(`開始填充 ${data.gameType} 的號碼: ${data.numbers.join(',')}`);

        // 等待頁面載入並檢查重複參加
        function checkDuplicateBeforeFilling(callback) {
            let attempts = 0;
            const maxAttempts = 10;

            function check() {
                attempts++;
                if (document.readyState === 'complete' || document.querySelector('.error-message, .alert, .warning')) {
                    if (checkDuplicateParticipation()) {
                        logToStorage(`提前檢測到 ${data.gameType} 已重複參加,中斷流程並返回首頁`, true);
                        localStorage.removeItem('gamesToSubmit');
                        localStorage.removeItem('currentGameIndex');
                        localStorage.removeItem('lottoNumbers');
                        setTimeout(() => {
                            window.location.href = 'https://lotto.arclink.com.tw/';
                        }, 1000);
                        return;
                    } else {
                        callback();
                    }
                } else if (attempts < maxAttempts) {
                    logToStorage(`頁面未載入完成,等待 ${attempts}/${maxAttempts}`);
                    setTimeout(check, 500);
                } else {
                    logToStorage(`頁面載入超時,繼續填充 ${data.gameType}`, true);
                    callback();
                }
            }
            check();
        }

        checkDuplicateBeforeFilling(() => {
            function startFilling() {
                let observer = new MutationObserver((mutations, obs) => {
                    let checkboxes;
                    if (data.gameType === '三星彩') {
                        checkboxes = [
                            document.querySelectorAll('input[name="c1"]'),
                            document.querySelectorAll('input[name="c2"]'),
                            document.querySelectorAll('input[name="c3"]')
                        ];
                        if (checkboxes.every(cb => cb.length >= 10)) {
                            obs.disconnect();
                            logToStorage(`三星彩 Checkboxes found: ${checkboxes.map(cb => cb.length).join(', ')}`);
                            fillInputsAndCheckboxes(null, checkboxes, data, 0);
                        }
                    } else if (data.gameType === '四星彩') {
                        checkboxes = [
                            document.querySelectorAll('input[name="c1"]'),
                            document.querySelectorAll('input[name="c2"]'),
                            document.querySelectorAll('input[name="c3"]'),
                            document.querySelectorAll('input[name="c4"]')
                        ];
                        if (checkboxes.every(cb => cb.length >= 10)) {
                            obs.disconnect();
                            logToStorage(`四星彩 Checkboxes found: ${checkboxes.map(cb => cb.length).join(', ')}`);
                            fillInputsAndCheckboxes(null, checkboxes, data, 0);
                        }
                    } else {
                        checkboxes = document.querySelectorAll('input[name="c1"]');
                        if (checkboxes.length >= data.numbers.length) {
                            obs.disconnect();
                            logToStorage(`找到 ${data.gameType} 的勾選框: ${checkboxes.length} 個`);
                            fillInputsAndCheckboxes(null, checkboxes, data, 0);
                        }
                    }
                });
                observer.observe(document.body, { childList: true, subtree: true });

                setTimeout(() => {
                    observer.disconnect();
                    let checkboxes;
                    if (data.gameType === '三星彩') {
                        checkboxes = [
                            document.querySelectorAll('input[name="c1"]'),
                            document.querySelectorAll('input[name="c2"]'),
                            document.querySelectorAll('input[name="c3"]')
                        ];
                    } else if (data.gameType === '四星彩') {
                        checkboxes = [
                            document.querySelectorAll('input[name="c1"]'),
                            document.querySelectorAll('input[name="c2"]'),
                            document.querySelectorAll('input[name="c3"]'),
                            document.querySelectorAll('input[name="c4"]')
                        ];
                    } else {
                        checkboxes = document.querySelectorAll('input[name="c1"]');
                    }
                    logToStorage(`超時後強制執行 ${data.gameType},找到 ${checkboxes.length} 個勾選框組`);
                    fillInputsAndCheckboxes(null, checkboxes, data, 0);
                }, 2000);
            }

            setTimeout(startFilling, 2000);
        });
    }

    function fillInputsAndCheckboxes(inputs, checkboxes, data, retryCount) {
        let index = 0;
        let numbers = data.numbers;
        let checkedCount = 0;
        const maxRetries = 5;

        function fillNext() {
            if (index >= numbers.length) {
                if (checkedCount === numbers.length) {
                    setTimeout(() => {
                        let submitBtn = document.querySelector('input[type="submit"][name="start"]');
                        if (submitBtn) {
                            submitBtn.disabled = false;
                            logToStorage(`提交 ${data.gameType} 的號碼: ${numbers.join(',')}`);
                            submitBtn.click();
                            waitForResultPage(data.gameType, data.isFiveCode);
                        } else {
                            logToStorage(`未找到 ${data.gameType} 的提交按鈕,跳至下一遊戲`, true);
                            localStorage.setItem('currentGameIndex', (parseInt(localStorage.getItem('currentGameIndex'), 10) + 1).toString());
                            processNextGame();
                        }
                    }, 1000);
                } else if (retryCount < maxRetries) {
                    logToStorage(`勾選 ${data.gameType} 未完成: ${checkedCount}/${numbers.length},重試 (${retryCount + 1}/${maxRetries})`);
                    setTimeout(() => fillInputsAndCheckboxes(inputs, checkboxes, data, retryCount + 1), 1000);
                } else {
                    logToStorage(`超過最大重試次數 ${data.gameType}: ${checkedCount}/${numbers.length},跳至下一遊戲`, true);
                    localStorage.setItem('currentGameIndex', (parseInt(localStorage.getItem('currentGameIndex'), 10) + 1).toString());
                    processNextGame();
                }
                return;
            }

            let num = numbers[index].toString();
            let checkbox;

            if (data.gameType === '三星彩' || data.gameType === '四星彩') {
                let checkboxGroup = checkboxes[index];
                checkbox = Array.from(checkboxGroup).find(cb => cb.value === num || cb.value === num.padStart(2, '0'));
            } else {
                checkbox = Array.from(checkboxes).find(cb => cb.value === num || cb.value === num.padStart(2, '0'));
            }

            if (checkbox) {
                checkbox.checked = true;
                checkbox.dispatchEvent(new Event('click', { bubbles: true }));
                setTimeout(() => {
                    if (checkbox.checked) {
                        checkedCount++;
                    }
                    index++;
                    setTimeout(fillNext, 123);
                }, 123);
            } else {
                logToStorage(`未找到 ${data.gameType} 的勾選框: ${num}`, true);
                index++;
                setTimeout(fillNext, 123);
            }
        }
        fillNext();
    }

    function checkLoginStatus() {
        const url = window.location.href;
        const title = document.title;
        const loginButton = document.querySelector('input[type="submit"][value="登入"]');
        const logoutLink = document.querySelector('a[href*="logout"]');
        let isLoggedOut = false;

        if (logoutLink) {
            isLoggedOut = false;
        } else if (loginButton || title.includes('登入') || url === 'https://lotto.arclink.com.tw/') {
            isLoggedOut = true;
        }

        logToStorage(`檢查登入狀態 - URL: ${url}, 標題: ${title}, 登入按鈕: ${!!loginButton}, 登出連結: ${!!logoutLink}, 判定: ${isLoggedOut ? '未登入' : '已登入'}`);
        return isLoggedOut;
    }

    function handleLoginStatus() {
        if (checkLoginStatus()) {
            logToStorage('未登入檢測到,返回首頁', true);
            localStorage.removeItem('gamesToSubmit');
            localStorage.removeItem('currentGameIndex');
            localStorage.removeItem('lottoNumbers');
            setTimeout(() => {
                window.location.href = 'https://lotto.arclink.com.tw/';
            }, 1000);
            return true;
        }
        return false;
    }

    function checkDuplicateParticipation() {
        const pageContent = document.body.innerHTML || '';
        const errorDiv = document.querySelector('.error-message, .alert, .warning') || {};
        const duplicateMessages = [
            '你已經有參加過該類型的報號',
            '本台電腦已經有其它帳號報過',
            '已參加',
            '重複報號',
            '報號遊戲每期每人只限報號一次',
            '你所用的電腦已經有其它帳號報號過了',
            '抱歉,報號發生錯誤,可能的原因是:你已經有參加過該類型的報號了或者是本台電腦已經有其它帳號報過該類型的遊戲了!',
            '抱歉,報號發生錯誤,可能的原因是:報號遊戲每期每人只限報號一次,或者你所用的電腦已經有其它帳號報號過了!',
            '抱歉,報號發生錯誤,可能的原因是:你已經有參加過該類型的報號了!!',
            '抱歉!開獎日的19點之後,則不能繼續進行報號。謝謝!'
        ];
        const isDuplicate = duplicateMessages.some(msg => pageContent.includes(msg)) ||
                            duplicateMessages.some(msg => errorDiv.textContent && errorDiv.textContent.includes(msg));
        logToStorage(`檢查重複參加 - URL: ${window.location.href}, 檢測結果: ${isDuplicate}, 頁面內容樣本: ${pageContent.slice(0, 200)}`);
        return isDuplicate;
    }

    function waitForResultPage(gameType, isFiveCode = false) {
        let attempts = 0;
        const maxAttempts = 10;
        const expectedUrls = [
            'https://lotto.arclink.com.tw/LottoGames.do',
            'https://lotto.arclink.com.tw/LottoGamesno.do'
        ];
        const preferredUrl = isFiveCode ? expectedUrls[1] : expectedUrls[0];

        function check() {
            attempts++;
            const hasErrorElement = !!document.querySelector('.error-message, .alert, .warning');
            logToStorage(`等待 ${gameType} 結果頁,第 ${attempts}/${maxAttempts} 次檢查,當前 URL: ${window.location.href}, 預期 URL: ${preferredUrl}, readyState: ${document.readyState}, 錯誤元素: ${hasErrorElement}`);

            if (expectedUrls.includes(window.location.href)) {
                // 只要到達任一結果頁,立即檢查重複
                logToStorage(`結果頁已載入 ${gameType},URL: ${window.location.href}`);
                if (handleLoginStatus()) {
                    return;
                }
                if (checkDuplicateParticipation()) {
                    logToStorage(`結果頁檢測到 ${gameType} 重複參加提醒,返回首頁`, true);
                    localStorage.removeItem('gamesToSubmit');
                    localStorage.removeItem('currentGameIndex');
                    localStorage.removeItem('lottoNumbers');
                    setTimeout(() => {
                        window.location.href = 'https://lotto.arclink.com.tw/';
                    }, 1000);
                    return;
                }
                let nextIndex = parseInt(localStorage.getItem('currentGameIndex'), 10) + 1;
                localStorage.setItem('currentGameIndex', nextIndex.toString());
                setTimeout(processNextGame, 1000);
            } else if (attempts < maxAttempts) {
                setTimeout(check, 1000);
            } else {
                logToStorage(`未到達預期結果頁 ${expectedUrls.join(' 或 ')},超過最大嘗試次數,跳至下一遊戲`, true);
                localStorage.setItem('currentGameIndex', (parseInt(localStorage.getItem('currentGameIndex'), 10) + 1).toString());
                processNextGame();
            }
        }
        setTimeout(check, 2000);
    }

    if (window.location.href.includes('lotterygame.html')) {
        createFloatBox();
    }

    if (window.location.href.includes('post.do?go=game&iType=1') ||
        window.location.href.includes('post.do?go=game&iType=5') ||
        window.location.href.includes('post.do?go=game&iType=12') ||
        window.location.href.includes('post.do?go=game395&iType=9') ||
        window.location.href.includes('post.do?go=game3star&iType=7') ||
        window.location.href.includes('post.do?go=game4star&iType=4') ||
        window.location.href.includes('post.do?go=gameno&iType=1') ||
        window.location.href.includes('post.do?go=gameno&iType=5') ||
        window.location.href.includes('post.do?go=gameno&iType=12') ||
        window.location.href.includes('post.do?go=game395no&iType=9') ||
        window.location.href.includes('post.do?go=gamesec&iType=1') ||
        window.location.href.includes('post.do?go=gamesec&iType=5') ||
        window.location.href.includes('post.do?go=gamesec&iType=12') ||
        window.location.href.includes('post.do?go=game395sec&iType=9') ||
        window.location.href.includes('post.do?go=gameone&iType=1') ||
        window.location.href.includes('post.do?go=gameone&iType=5') ||
        window.location.href.includes('post.do?go=gameone&iType=12') ||
        window.location.href.includes('post.do?go=game395one&iType=9')) {
        fillNumbers();
    } else if (window.location.href === 'https://lotto.arclink.com.tw/LottoGames.do' ||
               window.location.href === 'https://lotto.arclink.com.tw/LottoGamesno.do') {
        let storedData = JSON.parse(localStorage.getItem('lottoNumbers') || '{}');
        waitForResultPage(storedData.gameType || 'unknown', storedData.isFiveCode || false);
    }
})();