新球体育网亚盘分析

新球体育网(球探)手机端网页,比赛的分析页面右上角添加了一个按钮,点击后生成表格,通过两家公司的让球走势分析赛果。

// ==UserScript==
// @name         新球体育网亚盘分析
// @namespace    http://dol.freevar.com/
// @version      0.3
// @description  新球体育网(球探)手机端网页,比赛的分析页面右上角添加了一个按钮,点击后生成表格,通过两家公司的让球走势分析赛果。
// @author       Dolphin
// @match        https://m.titan007.com/Analy/Analysis/*
// @match        https://m.titan007.com/analy/Analysis/*
// @run-at       document-idle
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // 公司信息映射
    const companies = {
        42: { id: 42, name: "18Bet" },
        47: { id: 47, name: "Pinnacle" }
    };

    // 转换ModifyTime(YYYYMMDDHHmmss)为时间戳(秒)
    function modifyTimeToTimestamp(modifyTime) {
        if (!modifyTime || modifyTime.length !== 14) return 0;
        const year = modifyTime.substr(0, 4);
        const month = modifyTime.substr(4, 2) - 1; // 月份从0开始
        const day = modifyTime.substr(6, 2);
        const hour = modifyTime.substr(8, 2);
        const minute = modifyTime.substr(10, 2);
        const second = modifyTime.substr(12, 2);
        return new Date(year, month, day, hour, minute, second).getTime() / 1000;
    }

    // 转换时间戳为可读格式
    function timestampToReadable(timestamp) {
        const date = new Date(timestamp * 1000);
        const month = String(date.getMonth() + 1).padStart(2, '0');
        const day = String(date.getDate()).padStart(2, '0');
        const hours = String(date.getHours()).padStart(2, '0');
        const minutes = String(date.getMinutes()).padStart(2, '0');
        return `${month}-${day} ${hours}:${minutes}`;
    }

    // 获取指定公司的赔率数据
    async function fetchOddsData(companyId) {
        try {
            const url = `/HandicapDataInterface.ashx?scheid=${scheduleId}&type=3&oddskind=0&companyid=${companyId}&isHalf=0`;
            const response = await fetch(url);
            const data = await response.json();

            // 转换时间并按时间戳排序(最新的在前)
            return data.map(item => ({
                ...item,
                timestamp: modifyTimeToTimestamp(item.ModifyTime)
            })).sort((a, b) => b.timestamp - a.timestamp);
        } catch (error) {
            console.error(`获取${companies[companyId].name}数据失败:`, error);
            return [];
        }
    }

    // 创建并显示赔率对比表格
    function createOddsTable(bet18Data, pinnacleData, homeMatchTime, awayMatchTime) {
        // 确定需要显示的所有时间点
        const timeSet = new Set();

        // 添加两家公司的所有赔率时间
        [...bet18Data, ...pinnacleData].forEach(item => timeSet.add(item.timestamp));

        // 添加主客队上一场比赛相关时间点(开始和开始后2小时)
        const homeEndTime = homeMatchTime + 2 * 3600;
        const awayEndTime = awayMatchTime + 2 * 3600;
        timeSet.add(homeMatchTime);
        timeSet.add(homeEndTime);
        timeSet.add(awayMatchTime);
        timeSet.add(awayEndTime);

        // 转换为数组并按时间排序(最新的在前)
        const sortedTimes = Array.from(timeSet).sort((a, b) => b - a);

        // 创建表格元素
        const table = document.createElement('table');
        table.className = 'odds-table';
        table.style.borderCollapse = 'collapse';
        table.style.margin = '0px auto';
        table.style.border = '1px solid #aaa';
        table.style.textAlign = 'center';

        // 创建表头
        const thead = document.createElement('thead');
        const headerRow = document.createElement('tr');
        headerRow.style.backgroundColor = '#eee';

        const headers = [
            '时间',
            '18Bet让球',
            '18Bet差值',
            '平博让球',
            '平博差值'
        ];

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

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

        // 创建表格内容
        const tbody = document.createElement('tbody');

        sortedTimes.forEach(timestamp => {
            const row = document.createElement('tr');

            // 检查是否在比赛期间(需要标红)
            const inHomeMatch = timestamp >= homeMatchTime && timestamp <= homeEndTime;
            const inAwayMatch = timestamp >= awayMatchTime && timestamp <= awayEndTime;

            if (inHomeMatch || inAwayMatch) {
                row.style.color = '#f00';
            }

            // 时间单元格
            const timeCell = document.createElement('td');
            timeCell.textContent = timestampToReadable(timestamp);
            timeCell.style.border = '1px solid #aaa';
            row.appendChild(timeCell);

            // 18Bet数据
            const bet18Item = bet18Data.find(item => item.timestamp === timestamp);
            const bet18PanKou = document.createElement('td');
            const bet18Diff = document.createElement('td');

            if (bet18Item) {
                bet18PanKou.textContent = bet18Item.PanKou + '⚽';
                const diff = (parseFloat(bet18Item.AwayOdds) - parseFloat(bet18Item.HomeOdds)).toFixed(2);
                bet18Diff.textContent = diff;
            } else {
                bet18PanKou.textContent = '';
                bet18Diff.textContent = '';
            }

            bet18PanKou.style.border = '1px solid #aaa';
            bet18Diff.style.border = '1px solid #aaa';
            bet18Diff.style.fontSize = '18px';
            row.appendChild(bet18PanKou);
            row.appendChild(bet18Diff);

            // Pinnacle数据
            const pinnacleItem = pinnacleData.find(item => item.timestamp === timestamp);
            const pinnaclePanKou = document.createElement('td');
            const pinnacleDiff = document.createElement('td');

            if (pinnacleItem) {
                pinnaclePanKou.textContent = pinnacleItem.PanKou + '⚽';
                const diff = (parseFloat(pinnacleItem.AwayOdds) - parseFloat(pinnacleItem.HomeOdds)).toFixed(2);
                pinnacleDiff.textContent = diff;
            } else {
                pinnaclePanKou.textContent = '';
                pinnacleDiff.textContent = '';
            }

            pinnaclePanKou.style.border = '1px solid #aaa';
            pinnacleDiff.style.border = '1px solid #aaa';
            pinnacleDiff.style.fontSize = '18px';
            row.appendChild(pinnaclePanKou);
            row.appendChild(pinnacleDiff);

            tbody.appendChild(row);
        });

        table.appendChild(tbody);

        // 在#content的第一个元素前插入表格
        const contentDiv = document.getElementById('content');
        if (contentDiv) {
            if (contentDiv.firstChild) {
                contentDiv.insertBefore(table, contentDiv.firstChild);
            } else {
                contentDiv.appendChild(table);
            }
        } else {
            console.error('未找到#content元素');
        }
    }

    // 处理并显示赔率数据
    async function processAndDisplayOdds() {
        // 获取两家公司的赔率数据
        const [bet18Data, pinnacleData] = await Promise.all([
            fetchOddsData(42),
            fetchOddsData(47)
        ]);

        // 获取主客队上一场比赛时间(时间戳)
        const homeLastMatchTime = parseInt(jsonData.nearMatches.homeMatches.matches[0].matchTime) || 0;
        const awayLastMatchTime = parseInt(jsonData.nearMatches.awayMatches.matches[0].matchTime) || 0;

        // 计算三个关键时间点
        const homeTimePlus26h = homeLastMatchTime + 26 * 3600;
        const awayTimePlus26h = awayLastMatchTime + 26 * 3600;

        // 找到两家公司最早的赔率时间
        const getEarliestTime = (data) => data.length > 0 ? Math.min(...data.map(item => item.timestamp)) : 0;
        const bet18EarliestTime = getEarliestTime(bet18Data);
        const pinnacleEarliestTime = getEarliestTime(pinnacleData);

        // 较晚开盘公司的最早时间 + 24小时
        const laterOpenTimePlus24h = Math.max(bet18EarliestTime, pinnacleEarliestTime) + 24 * 3600;

        // 三个时间点中最晚的那个
        const cutoffTime = Math.max(homeTimePlus26h, awayTimePlus26h, laterOpenTimePlus24h);

        // 筛选出截止时间之前的数据
        const filterData = (data) => data.filter(item => item.timestamp <= cutoffTime);

        // 创建表格
        createOddsTable(
            filterData(bet18Data),
            filterData(pinnacleData),
            homeLastMatchTime,
            awayLastMatchTime
        );
    }

    // 添加触发按钮
    function addTriggerButton() {
        const existingBtn = document.querySelector('div.btn');
        if (existingBtn) {
            const newBtn = document.createElement('div');
            newBtn.className = 'btn';
            newBtn.textContent = '亚盘';
            newBtn.style.background = '#3c6';
            newBtn.addEventListener('click', processAndDisplayOdds);

            // 插入到现有按钮后面
            existingBtn.parentNode.insertBefore(newBtn, existingBtn.nextSibling);
        } else {
            console.error('未找到原有的.btn元素');
        }
    }

    // 页面加载完成后添加按钮
    addTriggerButton();
})();