GeoGuessr - Who played better?

Shows which player made better guesses overall in a duel, independent of the actual outcome influenced by multipliers.

目前為 2024-10-02 提交的版本,檢視 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         GeoGuessr - Who played better?
// @description  Shows which player made better guesses overall in a duel, independent of the actual outcome influenced by multipliers.
// @namespace    https://greasyfork.org/users/1375871
// @version      0.1
// @author       teqoa
// @match        https://www.geoguessr.com/duels/*/summary
// @run-at       document-idle
// @icon         https://www.google.com/s2/favicons?domain=geoguessr.com
// @grant        unsafeWindow
// @grant        GM_addStyle
// @license      MIT
// ==/UserScript==

// Note: Only works for 1v1 duels on normal settings for now (useless on games with round limit because it uses the last round to determine who won according to GG).

(function() {
    'use strict';
    let text = "{winner} scored {pointsDifference} points more than {loser}."
    let multiMerchantedText = "However, multipliers led to {loser} winning."

    function extractGameData() {
        const roundElements = document.querySelectorAll('.game-summary_playedRound__VukPu');
        let totalDifference = 0;
        let player1TotalScore = 0;
        let player2TotalScore = 0;
        let lastRoundDifference = 0;

        roundElements.forEach((round, index) => {
            const scores = round.querySelectorAll('.game-summary_text__viPc6');
            if (scores.length >= 3) {
                const player1Score = parseInt(scores[1].textContent);
                const player2Score = parseInt(scores[2].textContent);
                const difference = player1Score - player2Score;
                totalDifference += difference;
                player1TotalScore += player1Score;
                player2TotalScore += player2Score;

                if (index === roundElements.length - 1) {
                    lastRoundDifference = difference;
                }
            }
        });

        const player1Name = 'Blue';
        const player2Name = 'Red';

        return {
            player1: {
                name: player1Name,
                score: player1TotalScore
            },
            player2: {
                name: player2Name,
                score: player2TotalScore
            },
            totalDifference: Math.abs(totalDifference),
            lastRoundDifference: lastRoundDifference
        };
    }

    function addText() {
        const gameData = extractGameData();
        if (!gameData) return;

        const targetElement = document.querySelector('.game-mode-brand_root__8782u');
        if (targetElement) {
            const winner = gameData.player1.score > gameData.player2.score ? gameData.player1 : gameData.player2;
            const loser = winner === gameData.player1 ? gameData.player2 : gameData.player1;

            const firstText = document.createElement('div');
            firstText.innerHTML = text
                .replace("{winner}", `<span class="player-name ${winner.name.toLowerCase()}">${winner.name}</span>`)
                .replace("{pointsDifference}", gameData.totalDifference)
                .replace("{loser}", `<span class="player-name ${loser.name.toLowerCase()}">${loser.name}</span>`);
            firstText.style.marginTop = '10px';
            targetElement.appendChild(firstText);

            // check if the player who scored better overall scored worse in the last round (bodged)
            const multiMerchanted = (winner === gameData.player1 && gameData.lastRoundDifference < 0) ||
                                    (winner === gameData.player2 && gameData.lastRoundDifference > 0);

            if (multiMerchanted) {
                const secondText = document.createElement('div');
                secondText.innerHTML = multiMerchantedText
                    .replace("{loser}", `<span class="player-name ${loser.name.toLowerCase()}">${loser.name}</span>`);
                secondText.style.marginTop = '5px';
                targetElement.appendChild(secondText);
            }
        }
    }

    window.addEventListener('load', addText);

    GM_addStyle(`
        .game-mode-brand_root__8782u {
        }
        .player-name {
            font-weight: bold;
            color: white;
            padding: 0px 0px;
            border-radius: 3px;
            margin: 0 0px;
        }
        .blue {
            -webkit-text-stroke: 1px blue;
            text-stroke: 1px blue;
        }
        .red {
            -webkit-text-stroke: 1px red;
            text-stroke: 1px red;
        }
    `);
})();