My Match Analyzer (Standalone)

Standalone Match Analyzer for TrophyManager

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name           My Match Analyzer (Standalone)
// @namespace      *trophymanager.com/matches*
// @include        *trophymanager.com/matches*
// @grant          none
// @version 1
// @license MIT 
// @description    Standalone Match Analyzer for TrophyManager
// ==/UserScript==

(function() {
    'use strict';

    function extractMatchData() {
        let matchData = {};

        let homeTeam = document.querySelector(".abs.names.home_name .very_large")?.innerText || 'N/A';
        let awayTeam = document.querySelector(".abs.names.away_name .very_large")?.innerText || 'N/A';

        matchData.home_team = homeTeam;
        matchData.away_team = awayTeam;

        let statsList = document.querySelectorAll("ul.clean.tcenter.large_padding.underlined.stats.three_parts li");
        matchData.home_score = document.querySelector(".home")?.innerText || 'N/A';
        matchData.away_score = document.querySelector(".away")?.innerText || 'N/A';

        matchData.home_possession = statsList[0]?.querySelector(".home")?.innerText || 'N/A';
        matchData.away_possession = statsList[0]?.querySelector(".away")?.innerText || 'N/A';
        matchData.home_shots = statsList[1]?.querySelector(".home")?.innerText || 'N/A';
        matchData.away_shots = statsList[1]?.querySelector(".away")?.innerText || 'N/A';
        matchData.home_on_goal = statsList[2]?.querySelector(".home")?.innerText || 'N/A';
        matchData.away_on_goal = statsList[2]?.querySelector(".away")?.innerText || 'N/A';

        matchData.match_type = document.querySelector(".match_type_class")?.innerText || 'N/A';
        matchData.kickoff = document.querySelector(".kickoff_class")?.innerText || 'N/A';
        matchData.city = document.querySelector(".city_class")?.innerText || 'N/A';
        matchData.stadium = document.querySelector(".stadium_class")?.innerText || 'N/A';
        matchData.attendance = document.querySelector(".attendance_class")?.innerText || 'N/A';
        matchData.weather = document.querySelector(".weather_class")?.innerText || 'N/A';
        matchData.pitch_condition = document.querySelector(".pitch_class")?.innerText || 'N/A';

        matchData.home_color = document.querySelector(".home_color")?.style.backgroundColor || 'N/A';
        matchData.away_color = document.querySelector(".away_color")?.style.backgroundColor || 'N/A';

        let chances = document.querySelectorAll('ul.report_list.clean.underlined.text_left li');
        let homeChances = 0;
        let awayChances = 0;
        let ballGifCount = 0;
        let homeAssists = [];
        let awayAssists = [];
        let wordOccurrences = {
            "counter": 0,
            "freekick": 0,
            "through": 0,
            "wing": 0,
            "short": 0,
            "corner": 0,
            "long": 0
        };

        let homeWordOccurrences = {
            "counter": 0,
            "freekick": 0,
            "through": 0,
            "wing": 0,
            "short": 0,
            "corner": 0,
            "long": 0
        };

        let awayWordOccurrences = {
            "counter": 0,
            "freekick": 0,
            "through": 0,
            "wing": 0,
            "short": 0,
            "corner": 0,
            "long": 0
        };

        chances.forEach(chance => {
            let substitutionText = chance.querySelector("p")?.innerText || "";
            if (substitutionText.includes("looking to do a substitution after")) {
                return;
            }

            let managerOrderText = chance.querySelector("div.text.small p")?.innerText || "";
            if (managerOrderText.includes("calls out new orders to shake things up")) {
                return;
            }

            let positionChangeText = chance.querySelector("p")?.innerText || "";
            if (positionChangeText.includes(" calls out a position change for")) {
                return;
            }

            let chanceText = chance.querySelector("div.text.small")?.innerText.toLowerCase().trim();

            let paragraphs = chance.querySelectorAll("div.text.small p");
            let seenWords = new Set();

            paragraphs.forEach(p => {
                let pText = p.innerText.toLowerCase().trim();
                chanceText += " " + pText;
            });

            if (chance.querySelector('img[src="/pics/icons/ball.gif"]') && chanceText) {
                ballGifCount++;

                let uniqueChanceText = [...new Set(chanceText.split(" "))].join(" ");

                const wordsOrder = ["counter", "freekick", "corner", "short", "through", "wing", "long"];

                let foundWord = false;
                for (let word of wordsOrder) {
                    if (uniqueChanceText.includes(word) && !seenWords.has(word)) {
                        seenWords.add(word);
                        let minutes = chance.closest('li').getAttribute("report_id");
                        if (chance.style.backgroundColor === matchData.home_color) {
                            homeAssists.push({ word, minutes });
                        } else if (chance.style.backgroundColor === matchData.away_color) {
                            awayAssists.push({ word, minutes });
                        }
                        foundWord = true;
                        break;
                    }
                }
            }

            let chanceColor = chance.style.backgroundColor;
            let normalizedHomeColor = matchData.home_color.toLowerCase().trim();
            let normalizedAwayColor = matchData.away_color.toLowerCase().trim();

            if (chanceColor && chanceColor.toLowerCase().includes(normalizedHomeColor)) {
                homeChances++;
            } else if (chanceColor && chanceColor.toLowerCase().includes(normalizedAwayColor)) {
                awayChances++;
            }
        });

        // Adjust percentage formatting to show only one '%'
        if (matchData.home_possession !== 'N/A') {
            matchData.home_possession = parseFloat(matchData.home_possession).toFixed(1);
        }
        if (matchData.away_possession !== 'N/A') {
            matchData.away_possession = parseFloat(matchData.away_possession).toFixed(1);
        }

        matchData.home_chances = homeChances;
        matchData.away_chances = awayChances;
        matchData.ball_gif_count = ballGifCount;
        matchData.home_word_occurrences = homeWordOccurrences;
        matchData.away_word_occurrences = awayWordOccurrences;
        matchData.home_assists = homeAssists;
        matchData.away_assists = awayAssists;

        return matchData;
    }

    function clickAnalyze() {
        let matchData = extractMatchData();
        let homeWordStats = Object.entries(matchData.home_word_occurrences)
            .filter(([word, count]) => count > 0)
            .map(([word, count]) => `<tr><td style="background-color: ${matchData.home_color};">${word}</td><td>${count}</td></tr>`)
            .join('');

        let awayWordStats = Object.entries(matchData.away_word_occurrences)
            .filter(([word, count]) => count > 0)
            .map(([word, count]) => `<tr><td style="background-color: ${matchData.away_color};">${word}</td><td>${count}</td></tr>`)
            .join('');

        // Home assists with minutes
        let homeAssistsStats = matchData.home_assists
            .map(({ word, minutes }) => `<tr><td style="background-color: ${matchData.home_color};">${word}</td><td>${minutes}</td></tr>`)
            .join('');
        if (homeAssistsStats === '') homeAssistsStats = `<tr><td colspan="2">ZERO</td></tr>`;

        // Away assists with minutes
        let awayAssistsStats = matchData.away_assists
            .map(({ word, minutes }) => `<tr><td style="background-color: ${matchData.away_color};">${word}</td><td>${minutes}</td></tr>`)
            .join('');
        if (awayAssistsStats === '') awayAssistsStats = `<tr><td colspan="2">ZERO</td></tr>`;

        let analysisDiv = document.getElementById("mma_analysis");
        analysisDiv.innerHTML =
            `<div style="display: flex; gap: 20px; background: black; color: white; padding: 10px; font-family: Arial; border-radius: 5px;">
                <table border="1" style="border-collapse: collapse; width: 50%; text-align: center;">
                    <tr><th colspan="3">Match statistics</th></tr>
                    <tr>
                        <th></th>
                        <th style="background: ${matchData.home_color};">${matchData.home_team}</th>
                        <th style="background: ${matchData.away_color};">${matchData.away_team}</th>
                    </tr>
                    <tr><td>Score</td><td>${matchData.home_score}</td><td>${matchData.away_score}</td></tr>
                    <tr><td>Possession</td><td>${matchData.home_possession}%</td><td>${matchData.away_possession}%</td></tr>
                    <tr><td>Shots</td><td>${matchData.home_shots}</td><td>${matchData.away_shots}</td></tr>
                    <tr><td>On Goal</td><td>${matchData.home_on_goal}</td><td>${matchData.away_on_goal}</td></tr>
                    <tr><td>Chances</td><td>${matchData.home_chances}</td><td>${matchData.away_chances}</td></tr>
                </table>
                <table border="1" style="border-collapse: collapse; width: 50%; text-align: center;">
                    <tr><th colspan="2">Home Team Assists at the minute</th></tr>
                    ${homeAssistsStats}
                </table>
                <table border="1" style="border-collapse: collapse; width: 50%; text-align: center;">
                    <tr><th colspan="2">Away Team Assists at the minute</th></tr>
                    ${awayAssistsStats}
                </table>
            </div>`;
    }

    function createUI() {
        let container = document.createElement("div");
        container.setAttribute("id", "mma_container");
        container.style.position = "fixed";
        container.style.bottom = "10px";
        container.style.left = "10px";
        container.style.background = "#222";
        container.style.color = "white";
        container.style.padding = "10px";
        container.style.borderRadius = "5px";
        container.style.zIndex = "1000";

        let closeButton = document.createElement("button");
        closeButton.innerText = "X";
        closeButton.style.position = "absolute";
        closeButton.style.top = "5px";
        closeButton.style.right = "5px";
        closeButton.style.backgroundColor = "red";
        closeButton.style.color = "white";
        closeButton.style.border = "none";
        closeButton.style.borderRadius = "50%";
        closeButton.style.width = "30px";
        closeButton.style.height = "30px";
        closeButton.style.fontSize = "16px";
        closeButton.style.cursor = "pointer";
        closeButton.onclick = function() {
            container.style.display = "none";
        };

        let analyzeButton = document.createElement("button");
        analyzeButton.innerText = "Analyze Match";
        analyzeButton.style.padding = "10px 20px";
        analyzeButton.style.fontSize = "16px";
        analyzeButton.style.cursor = "pointer";
        analyzeButton.style.backgroundColor = "#333";  // Dark grey background
        analyzeButton.style.color = "white";  // White text color
        analyzeButton.style.border = "2px solid #444";  // Slightly lighter border
        analyzeButton.style.borderRadius = "5px";
        analyzeButton.style.boxShadow = "0 4px 6px rgba(0, 0, 0, 0.2)";  // Shadow for a floating effect
        analyzeButton.style.transition = "all 0.3s ease";  // Smooth transition effect on hover

        // Hover effect
        analyzeButton.onmouseover = function() {
            analyzeButton.style.backgroundColor = "#555";  // Lighter grey when hovered
            analyzeButton.style.borderColor = "#666";  // Lighter border on hover
        };

        analyzeButton.onmouseout = function() {
            analyzeButton.style.backgroundColor = "#333";  // Original background
            analyzeButton.style.borderColor = "#444";  // Original border
        };

        analyzeButton.onclick = clickAnalyze;

        let analysisDiv = document.createElement("div");
        analysisDiv.setAttribute("id", "mma_analysis");
        analysisDiv.style.marginTop = "10px";
        analysisDiv.style.maxHeight = "500px";
        analysisDiv.style.overflowY = "auto";
        analysisDiv.style.background = "#000";
        analysisDiv.style.padding = "10px";
        analysisDiv.style.borderRadius = "5px";

        container.appendChild(closeButton);
        container.appendChild(analyzeButton);
        container.appendChild(analysisDiv);
        document.body.appendChild(container);
    }

    window.addEventListener('load', createUI);
})();