新球体育网欧赔统计

新球体育网(球探)手机端网页,在赛程页面加入“统计”按钮,统计当前页面里所有已完场的比赛。在分析页面加入“统计”,“表格”,“预测”按钮,“统计”按钮统计当前页面这场比赛。“表格”按钮生成各个公司对已统计场次的准确度表格,误差越低的公司越准确。选择公司后可点击“预测”按钮,比较两极分化的公司预测赛果。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         新球体育网欧赔统计
// @namespace    http://dol.freevar.com/
// @version      0.941
// @description  新球体育网(球探)手机端网页,在赛程页面加入“统计”按钮,统计当前页面里所有已完场的比赛。在分析页面加入“统计”,“表格”,“预测”按钮,“统计”按钮统计当前页面这场比赛。“表格”按钮生成各个公司对已统计场次的准确度表格,误差越低的公司越准确。选择公司后可点击“预测”按钮,比较两极分化的公司预测赛果。
// @author       Dolphin
// @match        https://m.titan007.com/info/*
// @match        https://m.titan007.com/Analy/Analysis/*
// @match        https://m.titan007.com/analy/Analysis/*
// @run-at       document-end
// @grant        GM_xmlhttpRequest
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // 存储表格数据
    let tableData = [];

    // 检查当前页面类型并执行相应操作
    if (window.location.href.includes('/info/')) {
        // info页面
        addButtonsToInfoPage();
    } else if (window.location.href.includes('/Analysis/')) {
        // Analysis页面
        addButtonsToAnalysisPage();
    }

    /**
     * 在info页面添加按钮
     */
    function addButtonsToInfoPage() {
        const contentDiv = document.getElementById('content');
        if (!contentDiv) return;

        // 创建按钮容器
        const buttonContainer = document.createElement('div');
        buttonContainer.style.cssText = 'text-align: right;';

        // 清除按钮
        const clearBtn = document.createElement('button');
        clearBtn.id = 'clearEuroStatsBtn';
        clearBtn.textContent = '清除';
        clearBtn.style.cssText = 'margin: 5px; font-size: 18px; background: #fbb;';

        // 统计按钮
        const statsBtn = document.createElement('button');
        statsBtn.id = 'calcEuroStatsBtn';
        statsBtn.textContent = '统计';
        statsBtn.style.cssText = 'margin: 5px; font-size: 18px; background: #bfb;';

        // 添加按钮事件
        clearBtn.addEventListener('click', clearEuroStats);
        statsBtn.addEventListener('click', calculateEuroStatsForInfoPage);

        // 添加按钮到容器
        buttonContainer.appendChild(clearBtn);
        buttonContainer.appendChild(statsBtn);

        // 插入到content第一个元素前
        contentDiv.insertBefore(buttonContainer, contentDiv.firstChild);
    }

    /**
     * 在Analysis页面添加按钮
     */
    function addButtonsToAnalysisPage() {
        const contentDiv = document.getElementById('content');
        if (!contentDiv) return;

        // 创建按钮容器
        const buttonContainer = document.createElement('div');
        buttonContainer.style.cssText = 'text-align: right;';

        // 清除按钮
        const clearBtn = document.createElement('button');
        clearBtn.id = 'clearEuroStatsBtn';
        clearBtn.textContent = '清除';
        clearBtn.style.cssText = 'margin: 5px; font-size: 18px; background: #fbb;';

        // 统计按钮
        const statsBtn = document.createElement('button');
        statsBtn.id = 'calcEuroStatsBtn';
        statsBtn.textContent = '统计';
        statsBtn.style.cssText = 'margin: 5px; font-size: 18px; background: #bfb;';

        // 表格按钮
        const tableBtn = document.createElement('button');
        tableBtn.id = 'showTableBtn';
        tableBtn.textContent = '表格';
        tableBtn.style.cssText = 'margin: 5px; font-size: 18px; background: #ffb;';

        // 预测按钮
        const predictBtn = document.createElement('button');
        predictBtn.id = 'predictBtn';
        predictBtn.textContent = '预测';
        predictBtn.style.cssText = 'margin: 5px; font-size: 18px; background: #bbf;';

        // 添加按钮事件
        clearBtn.addEventListener('click', clearEuroStats);
        statsBtn.addEventListener('click', calculateEuroStatsForAnalysisPage);
        tableBtn.addEventListener('click', showTable);
        predictBtn.addEventListener('click', showPrediction);

        // 添加按钮到容器
        buttonContainer.appendChild(clearBtn);
        buttonContainer.appendChild(statsBtn);
        buttonContainer.appendChild(tableBtn);
        buttonContainer.appendChild(predictBtn);

        // 插入到content第一个元素前
        contentDiv.insertBefore(buttonContainer, contentDiv.firstChild);
    }

    /**
     * 清除统计数据
     */
    function clearEuroStats() {
        localStorage.removeItem('euroStats');
        alert('统计数据已清除!');
    }

    /**
     * 为info页面统计误差
     */
    function calculateEuroStatsForInfoPage() {
        const btn = document.getElementById('calcEuroStatsBtn');
        btn.disabled = true;
        btn.textContent = '统计中';

        // 查找所有红色比分元素
        const redSpans = document.querySelectorAll('span[style*="color:red"], span.red');
        const matches = [];

        // 提取比赛信息
        redSpans.forEach(span => {
            const tr = span.closest('tr');
            if (!tr) return;

            // 提取比赛ID
            const onclickAttr = tr.getAttribute('onclick');
            if (!onclickAttr) return;

            const matchIdMatch = onclickAttr.match(/ToAnaly\((\d+)/);
            if (!matchIdMatch) return;

            const scheduleId = matchIdMatch[1];

            // 提取比分
            const scoreText = span.textContent.trim();
            if (!scoreText || !scoreText.includes(':')) return;

            matches.push({
                scheduleId: scheduleId,
                score: scoreText
            });
        });

        if (matches.length === 0) {
            alert('没有完场比分!');
            btn.disabled = false;
            btn.textContent = '统计';
            return;
        }

        // 开始逐场比赛统计
        processMatchesSequentially(matches, 0, btn);
    }

    /**
     * 为Analysis页面统计误差
     */
    function calculateEuroStatsForAnalysisPage() {
        const btn = document.getElementById('calcEuroStatsBtn');
        btn.disabled = true;
        btn.textContent = '统计中';

        // 从页面变量获取比赛ID
        if (typeof scheduleId === 'undefined') {
            alert('未找到比赛ID');
            btn.disabled = false;
            btn.textContent = '统计';
            return;
        }

        // 提取比分
        const homeScoreEl = document.getElementById('homeScore');
        const guestScoreEl = document.getElementById('guestScore');

        if (!homeScoreEl || !guestScoreEl) {
            alert('没有比分!');
            btn.disabled = false;
            btn.textContent = '统计';
            return;
        }

        const homeScore = parseInt(homeScoreEl.textContent.trim());
        const guestScore = parseInt(guestScoreEl.textContent.trim());

        if (isNaN(homeScore) || isNaN(guestScore)) {
            alert('比分数据无效');
            btn.disabled = false;
            btn.textContent = '统计';
            return;
        }

        const score = `${homeScore}:${guestScore}`;

        // 单场比赛统计
        const matches = [{
            scheduleId: scheduleId.toString(),
            score: score
        }];

        processMatchesSequentially(matches, 0, btn);
    }

    /**
     * 顺序处理多场比赛
     */
    function processMatchesSequentially(matches, index, btn) {
        if (index >= matches.length) {
            // 所有比赛处理完成
            btn.disabled = false;
            btn.textContent = '统计';
            if (match.length > 1) alert(`已统计 ${matches.length} 场比赛`);
            return;
        }

        const match = matches[index];

        // 获取赔率数据
        getOddsData(match.scheduleId)
            .then(companiesData => {
                if (!companiesData || companiesData.length === 0) {
                    console.warn(`比赛 ${match.scheduleId} 无赔率数据`);
                    // 继续处理下一场
                    setTimeout(() => {
                        processMatchesSequentially(matches, index + 1, btn);
                    }, 100);
                    return;
                }

                // 计算误差
                const errorData = calculateMatchError(companiesData, match.score, match.scheduleId);

                // 保存到localStorage
                saveErrorData(errorData);

                // 间隔100毫秒后处理下一场
                setTimeout(() => {
                    processMatchesSequentially(matches, index + 1, btn);
                }, 100);
            })
            .catch(error => {
                console.error(`处理比赛 ${match.scheduleId} 时出错:`, error);
                // 继续处理下一场
                setTimeout(() => {
                    processMatchesSequentially(matches, index + 1, btn);
                }, 100);
            });
    }

    /**
     * 获取赔率数据
     */
    function getOddsData(scheduleId) {
        return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                method: 'GET',
                url: `https://txt.titan007.com/1x2/${scheduleId}.js`,
                timeout: 10000,
                onload: function(response) {
                    if (response.status !== 200) {
                        alert('请求失败,比赛ID: ' + scheduleId);
                        reject(new Error(`请求失败: ${response.status}`));
                        return;
                    }

                    try {
                        // 提取game数组数据
                        const gameMatch = response.responseText.match(/game=Array\(([\s\S]*?)\);/);
                        if (!gameMatch) {
                            resolve([]);
                            return;
                        }

                        const gameData = gameMatch[1];
                        // 清理数据并解析
                        const companies = parseGameData(gameData);
                        resolve(companies);
                    } catch (error) {
                        reject(error);
                    }
                },
                onerror: function(error) {
                    reject(error);
                },
                ontimeout: function() {
                    reject(new Error('请求超时'));
                }
            });
        });
    }

    /**
     * 解析game数据
     */
    function parseGameData(gameData) {
        // 移除首尾引号并按行分割
        const cleanedData = gameData.replace(/^"|"$/g, '').replace(/\\"/g, '"');
        const items = cleanedData.split('","');

        const companies = [];

        items.forEach(item => {
            const parts = item.split('|');
            if (parts.length >= 6) {
                const companyName = parts[2].trim();
                const winOdds = parseFloat(parts[3]);
                const drawOdds = parseFloat(parts[4]);
                const loseOdds = parseFloat(parts[5]);

                if (companyName && !isNaN(winOdds) && !isNaN(drawOdds) && !isNaN(loseOdds)) {
                    // 计算归一化概率
                    const winProb = 100 / winOdds;
                    const drawProb = 100 / drawOdds;
                    const loseProb = 100 / loseOdds;
                    const totalProb = winProb + drawProb + loseProb;

                    // 归一化
                    const normalizedWinProb = winProb / totalProb * 100;
                    const normalizedDrawProb = drawProb / totalProb * 100;
                    const normalizedLoseProb = loseProb / totalProb * 100;

                    companies.push({
                        name: companyName,
                        winOdds: winOdds,
                        drawOdds: drawOdds,
                        loseOdds: loseOdds,
                        winProb: normalizedWinProb,
                        drawProb: normalizedDrawProb,
                        loseProb: normalizedLoseProb
                    });
                }
            }
        });

        return companies;
    }

    /**
     * 计算单场比赛误差
     */
    function calculateMatchError(companiesData, score, scheduleId) {
        // 解析比分
        const [homeScoreStr, awayScoreStr] = score.split(':');
        const homeScore = parseInt(homeScoreStr);
        const awayScore = parseInt(awayScoreStr);

        if (isNaN(homeScore) || isNaN(awayScore)) {
            return {};
        }

        const goalDiff = homeScore - awayScore;

        let standardProb = 0;
        let targetType = ''; // 'win', 'draw', 或 'lose'

        // 确定标准概率和目标类型
        if (goalDiff === 0) {
            // 平局
            targetType = 'draw';
            // 找出平概率最高的公司
            companiesData.sort((a, b) => b.drawProb - a.drawProb);
            standardProb = companiesData[0].drawProb;
        } else if (Math.abs(goalDiff) === 1) {
            // 净胜1球
            if (goalDiff > 0) {
                targetType = 'win';
                // 找出胜概率最接近60%的公司
                companiesData.sort((a, b) => Math.abs(a.winProb - 60) - Math.abs(b.winProb - 60));
                standardProb = companiesData[0].winProb;
            } else {
                targetType = 'lose';
                // 找出负概率最接近60%的公司
                companiesData.sort((a, b) => Math.abs(a.loseProb - 60) - Math.abs(b.loseProb - 60));
                standardProb = companiesData[0].loseProb;
            }
        } else if (Math.abs(goalDiff) === 2) {
            // 净胜2球
            if (goalDiff > 0) {
                targetType = 'win';
                // 找出胜概率最接近80%的公司
                companiesData.sort((a, b) => Math.abs(a.winProb - 80) - Math.abs(b.winProb - 80));
                standardProb = companiesData[0].winProb;
            } else {
                targetType = 'lose';
                // 找出负概率最接近80%的公司
                companiesData.sort((a, b) => Math.abs(a.loseProb - 80) - Math.abs(b.loseProb - 80));
                standardProb = companiesData[0].loseProb;
            }
        } else {
            // 净胜2球以上
            if (goalDiff > 0) {
                targetType = 'win';
                // 找出胜概率最高的公司
                companiesData.sort((a, b) => b.winProb - a.winProb);
                standardProb = companiesData[0].winProb;
            } else {
                targetType = 'lose';
                // 找出负概率最高的公司
                companiesData.sort((a, b) => b.loseProb - a.loseProb);
                standardProb = companiesData[0].loseProb;
            }
        }

        // 计算各公司误差
        const errorData = {};

        companiesData.forEach(company => {
            let companyProb = 0;

            switch(targetType) {
                case 'win':
                    companyProb = company.winProb;
                    break;
                case 'draw':
                    companyProb = company.drawProb;
                    break;
                case 'lose':
                    companyProb = company.loseProb;
                    break;
            }

            const error = standardProb - companyProb;
            errorData[company.name] = {
                [scheduleId]: error
            };
        });

        return errorData;
    }

    /**
     * 保存误差数据到localStorage
     */
    function saveErrorData(newErrorData) {
        // 读取现有数据
        let euroStats = JSON.parse(localStorage.getItem('euroStats') || '{}');

        // 合并新数据
        Object.keys(newErrorData).forEach(companyName => {
            if (!euroStats[companyName]) {
                euroStats[companyName] = {};
            }

            // 合并比赛数据
            Object.assign(euroStats[companyName], newErrorData[companyName]);
        });

        // 保存回localStorage
        localStorage.setItem('euroStats', JSON.stringify(euroStats));
    }

    /**
     * 显示表格
     */
    function showTable() {
        // 移除现有表格
        const existingTable = document.getElementById('euroStatsTable');
        if (existingTable) {
            existingTable.remove();
        }

        // 获取当前比赛ID
        if (typeof scheduleId === 'undefined') {
            alert('未找到比赛ID');
            return;
        }

        const scheduleIdStr = scheduleId.toString();

        // 获取赔率数据
        getOddsData(scheduleIdStr)
            .then(companiesData => {
                if (!companiesData || companiesData.length === 0) {
                    alert('无赔率数据');
                    return;
                }

                // 获取误差统计数据
                const euroStats = JSON.parse(localStorage.getItem('euroStats') || '{}');

                // 计算每个公司的统计数据
                tableData = [];

                companiesData.forEach(company => {
                    const companyName = company.name;
                    const companyStats = euroStats[companyName] || {};

                    // 计算开盘次数和平均误差
                    const matchIds = Object.keys(companyStats);
                    const openCount = matchIds.length;

                    let totalAbsError = 0;
                    matchIds.forEach(matchId => {
                        totalAbsError += Math.abs(companyStats[matchId]);
                    });

                    const avgError = openCount > 0 ? totalAbsError / openCount : 0;

                    tableData.push({
                        name: companyName,
                        openCount: openCount,
                        avgError: avgError,
                        winProb: company.winProb,
                        drawProb: company.drawProb,
                        loseProb: company.loseProb
                    });
                });

                // 按平均误差排序
                tableData.sort((a, b) => a.avgError - b.avgError);

                // 创建表格
                createTable();
            })
            .catch(error => {
                alert(`获取数据失败: ${error.message}`);
            });
    }

    /**
     * 创建表格
     */
    function createTable() {
        // 创建表格容器
        const tableContainer = document.createElement('div');
        tableContainer.id = 'euroStatsTable';
        tableContainer.style.cssText = 'overflow-x: auto;';

        // 创建表格
        const table = document.createElement('table');
        table.style.cssText = 'border-collapse: collapse; font-size: 16px; text-align: center; margin: 0 auto;';

        // 创建表头
        const thead = document.createElement('thead');
        thead.style.cssText = 'background-color: #efe;';

        const headerRow = document.createElement('tr');

        const headers = ['公司', '开盘', '平均误差', '胜概率', '平概率', '负概率', '选'];

        headers.forEach(headerText => {
            const th = document.createElement('th');
            th.textContent = headerText;
            th.style.cssText = 'border: 1px solid #888;';
            headerRow.appendChild(th);
        });

        thead.appendChild(headerRow);
        table.appendChild(thead);

        // 创建表格主体
        const tbody = document.createElement('tbody');

        tableData.forEach((company, index) => {
            const row = document.createElement('tr');
            row.style.cssText = index % 2 === 0 ? 'background-color: #fff;' : 'background-color: #ffe;';

            // 公司名称
            const nameCell = document.createElement('td');
            nameCell.textContent = company.name;
            nameCell.style.cssText = 'font-size: 12px; border: 1px solid #888;';
            row.appendChild(nameCell);

            // 开盘次数
            const openCountCell = document.createElement('td');
            openCountCell.textContent = company.openCount;
            openCountCell.style.cssText = 'border: 1px solid #888;';
            row.appendChild(openCountCell);

            // 平均误差
            const avgErrorCell = document.createElement('td');
            avgErrorCell.textContent = company.avgError.toFixed(4);
            avgErrorCell.style.cssText = 'border: 1px solid #888;';
            row.appendChild(avgErrorCell);

            // 胜平负概率
            const winProbCell = document.createElement('td');
            winProbCell.textContent = company.winProb ? company.winProb.toFixed(2) : '没开盘';
            winProbCell.style.cssText = 'border: 1px solid #888;';
            row.appendChild(winProbCell);

            const drawProbCell = document.createElement('td');
            drawProbCell.textContent = company.drawProb ? company.drawProb.toFixed(2) : '没开盘';
            drawProbCell.style.cssText = 'border: 1px solid #888;';
            row.appendChild(drawProbCell);

            const loseProbCell = document.createElement('td');
            loseProbCell.textContent = company.loseProb ? company.loseProb.toFixed(2) : '没开盘';
            loseProbCell.style.cssText = 'border: 1px solid #888;';
            row.appendChild(loseProbCell);

            // 选择复选框
            const selectCell = document.createElement('td');
            selectCell.style.cssText = 'border: 1px solid #888;';

            const checkbox = document.createElement('input');
            checkbox.type = 'checkbox';
            checkbox.id = `company_${index}`;
            checkbox.style.position = 'initial';
            checkbox.dataset.companyName = company.name;

            selectCell.appendChild(checkbox);
            row.appendChild(selectCell);

            tbody.appendChild(row);
        });

        table.appendChild(tbody);
        tableContainer.appendChild(table);

        // 插入到按钮容器后面
        const buttonContainer = document.querySelector('#content > div:first-child');
        if (buttonContainer && buttonContainer.nextSibling) {
            buttonContainer.parentNode.insertBefore(tableContainer, buttonContainer.nextSibling);
        } else {
            document.getElementById('content').appendChild(tableContainer);
        }
    }

    /**
     * 显示预测结果
     */
    function showPrediction() {
        // 移除现有预测结果
        const existingPrediction = document.getElementById('predictionResult');
        if (existingPrediction) {
            existingPrediction.remove();
        }

        if (!tableData || tableData.length === 0) {
            alert('请先点击"表格"按钮生成数据');
            return;
        }

        // 获取已选择的公司
        const selectedCompanies = [];
        const checkboxes = document.querySelectorAll('#euroStatsTable input[type="checkbox"]');

        checkboxes.forEach(checkbox => {
            if (checkbox.checked && checkbox.dataset.companyName) {
                const companyName = checkbox.dataset.companyName;
                const companyData = tableData.find(c => c.name === companyName);
                if (companyData) {
                    selectedCompanies.push(companyData);
                }
            }
        });

        if (selectedCompanies.length < 2) {
            alert('请至少选择两家公司');
            return;
        }

        // 按平均误差排序
        selectedCompanies.sort((a, b) => a.avgError - b.avgError);

        // 分组
        let lowErrorGroup = [];
        let highErrorGroup = [];

        if (selectedCompanies.length % 2 === 1) {
            // 奇数个,去掉中间那个
            const middleIndex = Math.floor(selectedCompanies.length / 2);
            lowErrorGroup = selectedCompanies.slice(0, middleIndex);
            highErrorGroup = selectedCompanies.slice(middleIndex + 1);
        } else {
            // 偶数个,平均分
            const half = selectedCompanies.length / 2;
            lowErrorGroup = selectedCompanies.slice(0, half);
            highErrorGroup = selectedCompanies.slice(half);
        }

        // 计算各组平均概率
        const allAvg = calculateAverageProbabilities(selectedCompanies);
        const lowAvg = calculateAverageProbabilities(lowErrorGroup);
        const highAvg = calculateAverageProbabilities(highErrorGroup);

        // 创建预测结果显示表格
        const predictionDiv = document.createElement('div');
        predictionDiv.id = 'predictionResult';

        // 标题
        const title = document.createElement('h3');
        title.textContent = '对比概率,让1球60%,让2球80%';
        title.style.cssText = 'padding: 5px; background: #eee;';
        predictionDiv.appendChild(title);

        // 创建预测结果表格
        const predictionTable = document.createElement('table');
        predictionTable.style.cssText = 'border-collapse: collapse; font-size: 16px; text-align: center; margin: 5px auto;';

        // 创建表头
        const predictionThead = document.createElement('thead');
        predictionThead.style.cssText = 'background-color: #eef;';

        const predictionHeaderRow = document.createElement('tr');

        const predictionHeaders = ['分组', '个', '平均胜', '平均平', '平均负'];

        predictionHeaders.forEach(headerText => {
            const th = document.createElement('th');
            th.textContent = headerText;
            th.style.cssText = 'border: 1px solid #888;';
            predictionHeaderRow.appendChild(th);
        });

        predictionThead.appendChild(predictionHeaderRow);
        predictionTable.appendChild(predictionThead);

        // 创建表格主体
        const predictionTbody = document.createElement('tbody');

        // 误差偏小组数据行
        const lowErrorRow = document.createElement('tr');

        const lowErrorGroupCell = document.createElement('td');
        lowErrorGroupCell.textContent = '误差小';
        lowErrorGroupCell.style.cssText = 'border: 1px solid #888;';
        lowErrorRow.appendChild(lowErrorGroupCell);

        const lowErrorCountCell = document.createElement('td');
        lowErrorCountCell.textContent = lowErrorGroup.length;
        lowErrorCountCell.style.cssText = 'border: 1px solid #888;';
        lowErrorRow.appendChild(lowErrorCountCell);

        const lowWinProbCell = document.createElement('td');
        lowWinProbCell.textContent = lowAvg.win.toFixed(2);
        lowWinProbCell.style.cssText = 'border: 1px solid #888;';
        lowErrorRow.appendChild(lowWinProbCell);

        const lowDrawProbCell = document.createElement('td');
        lowDrawProbCell.textContent = lowAvg.draw.toFixed(2);
        lowDrawProbCell.style.cssText = 'border: 1px solid #888;';
        lowErrorRow.appendChild(lowDrawProbCell);

        const lowLoseProbCell = document.createElement('td');
        lowLoseProbCell.textContent = lowAvg.lose.toFixed(2);
        lowLoseProbCell.style.cssText = 'border: 1px solid #888;';
        lowErrorRow.appendChild(lowLoseProbCell);

        predictionTbody.appendChild(lowErrorRow);

        // 所有已选公司数据行
        const allGroupRow = document.createElement('tr');
        allGroupRow.style.cssText = 'background-color: #ffe;';

        const allGroupCell = document.createElement('td');
        allGroupCell.textContent = '已选择';
        allGroupCell.style.cssText = 'border: 1px solid #888;';
        allGroupRow.appendChild(allGroupCell);

        const allCountCell = document.createElement('td');
        allCountCell.textContent = selectedCompanies.length;
        allCountCell.style.cssText = 'border: 1px solid #888;';
        allGroupRow.appendChild(allCountCell);

        const allWinProbCell = document.createElement('td');
        allWinProbCell.textContent = allAvg.win.toFixed(2);
        allWinProbCell.style.cssText = 'border: 1px solid #888;';
        allGroupRow.appendChild(allWinProbCell);

        const allDrawProbCell = document.createElement('td');
        allDrawProbCell.textContent = allAvg.draw.toFixed(2);
        allDrawProbCell.style.cssText = 'border: 1px solid #888;';
        allGroupRow.appendChild(allDrawProbCell);

        const allLoseProbCell = document.createElement('td');
        allLoseProbCell.textContent = allAvg.lose.toFixed(2);
        allLoseProbCell.style.cssText = 'border: 1px solid #888;';
        allGroupRow.appendChild(allLoseProbCell);

        predictionTbody.appendChild(allGroupRow);

        // 误差偏大组数据行
        const highErrorRow = document.createElement('tr');

        const highErrorGroupCell = document.createElement('td');
        highErrorGroupCell.textContent = '误差大';
        highErrorGroupCell.style.cssText = 'border: 1px solid #888;';
        highErrorRow.appendChild(highErrorGroupCell);

        const highErrorCountCell = document.createElement('td');
        highErrorCountCell.textContent = highErrorGroup.length;
        highErrorCountCell.style.cssText = 'border: 1px solid #888;';
        highErrorRow.appendChild(highErrorCountCell);

        const highWinProbCell = document.createElement('td');
        highWinProbCell.textContent = highAvg.win.toFixed(2);
        highWinProbCell.style.cssText = 'border: 1px solid #888;';
        highErrorRow.appendChild(highWinProbCell);

        const highDrawProbCell = document.createElement('td');
        highDrawProbCell.textContent = highAvg.draw.toFixed(2);
        highDrawProbCell.style.cssText = 'border: 1px solid #888;';
        highErrorRow.appendChild(highDrawProbCell);

        const highLoseProbCell = document.createElement('td');
        highLoseProbCell.textContent = highAvg.lose.toFixed(2);
        highLoseProbCell.style.cssText = 'border: 1px solid #888;';
        highErrorRow.appendChild(highLoseProbCell);

        predictionTbody.appendChild(highErrorRow);

        predictionTable.appendChild(predictionTbody);
        predictionDiv.appendChild(predictionTable);

        // 插入到表格后面
        const tableContainer = document.getElementById('euroStatsTable');
        if (tableContainer) {
            tableContainer.parentNode.insertBefore(predictionDiv, tableContainer);
        }
    }

    /**
     * 计算平均概率
     */
    function calculateAverageProbabilities(companies) {
        if (companies.length === 0) {
            return { win: 0, draw: 0, lose: 0 };
        }

        let totalWin = 0;
        let totalDraw = 0;
        let totalLose = 0;
        let count = 0;

        companies.forEach(company => {
            if (company.winProb && company.drawProb && company.loseProb) {
                totalWin += company.winProb;
                totalDraw += company.drawProb;
                totalLose += company.loseProb;
                count++;
            }
        });

        if (count === 0) {
            return { win: 0, draw: 0, lose: 0 };
        }

        return {
            win: totalWin / count,
            draw: totalDraw / count,
            lose: totalLose / count
        };
    }
})();