Geoguessr Freedom Script

Play Geoguessr with Yandex and Baidu streetviews. Credit to kommu and MrAmericanMike to the original Yandex Script. Thanks to Alok, Mapper for advise for map making.

2021-12-09 या दिनांकाला. सर्वात नवीन आवृत्ती पाहा.

// ==UserScript==
// @name          Geoguessr Freedom Script
// @description   Play Geoguessr with Yandex and Baidu streetviews. Credit to kommu and MrAmericanMike to the original Yandex Script. Thanks to Alok, Mapper for advise for map making.
// @version       3.0.0b
// @include       https://www.geoguessr.com/*
// @run-at        document-start
// @license       MIT
// @namespace https://greatest.deepsurf.us/users/838374
// ==/UserScript==

var YANDEX_API_KEY = "b704b5a9-3d67-4d19-b702-ec7807cecfc6";
var BAIDU_API_KEY = "8dQ9hZPGEQnqg9r0O1C8Ate2N6P8Zk92";
var KAKAO_API_KEY = "cbacbe41e3a223d794f321de4f3e247b";

myLog("Geoguessr Baidu Yandex Plugin");

const MAPS_API_URL = "https://maps.googleapis.com/maps/api/js?";

let PLAYER = null;
let PLAYER2 = null;
let PLAYER3 = null;
let rv = null;
let ROUND = 0;
let YANDEX_INJECTED = false;
let BAIDU_INJECTED = false;
let KAKAO_INJECTED = false;
let NEW_ROUND_LOADED = false;
let COMPASS = null;
let PANORAMA_MAP = false;
let CURRENT_ROUND_DATA = null;
let nextPlayer = "Google";
let global_lat = 0;
let global_lng = 0;
let global_panoID = null;
let playerLoaded = false;

let BR = false;
let eventlistener = false;
let loc_list = [];
let pops = true;

let teleportLoaded = false;

let krCoordinates = [38.75292321084364, 124.2804539232574, 33.18509676203202, 129.597381999198]
let yandex_map = false;


/**
 * Helper Functions
 */

function myLog(...args) {
    console.log(...args);
}
function myHighlight(...args) {
    console.log(`%c${[...args]}`, "color: dodgerblue; font-size: 24px;");
}

function hex2a(hexx) {
    var hex = hexx.toString();//force conversion
    var str = '';
    for (var i = 0; i < hex.length; i += 2)
        str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
    return str;
}

function FindPointAtDistanceFrom(startPoint, initialBearingRadians, distanceKilometres) {
    const radiusEarthKilometres = 6371.01;
    var distRatio = distanceKilometres / radiusEarthKilometres;
    var distRatioSine = Math.sin(distRatio);
    var distRatioCosine = Math.cos(distRatio);

    var startLatRad = DegreesToRadians(startPoint.lat);
    var startLonRad = DegreesToRadians(startPoint.lng);

    var startLatCos = Math.cos(startLatRad);
    var startLatSin = Math.sin(startLatRad);

    var endLatRads = Math.asin((startLatSin * distRatioCosine) + (startLatCos * distRatioSine * Math.cos(initialBearingRadians)));

    var endLonRads = startLonRad
        + Math.atan2(
            Math.sin(initialBearingRadians) * distRatioSine * startLatCos,
            distRatioCosine - startLatSin * Math.sin(endLatRads));

    return { lat: RadiansToDegrees(endLatRads), lng: RadiansToDegrees(endLonRads) };
}

function DegreesToRadians(degrees) {
    const degToRadFactor = Math.PI / 180;
    return degrees * degToRadFactor;
}

function RadiansToDegrees(radians) {
    const radToDegFactor = 180 / Math.PI;
    return radians * radToDegFactor;
}

function runAsClient(f) {
    var s = document.createElement("script");
    s.type = "text/javascript";
    s.text = "(async () => { try { await (" + f.toString() + ")(); } catch (e) { console.error(e); }})();";
    document.body.appendChild(s);
}

window.runAsClient = runAsClient;

/**
 * Resolves succesfully after detecting that Google Maps API was loaded in a page
 *
 * @returns Promise
 */
function gmp() {
    return new Promise((resolve, reject) => {
        let scriptObserver = new MutationObserver((mutations, observer) => {
            for (let mutation of mutations) {
                for (let node of mutation.addedNodes) {
                    if (node.tagName === "SCRIPT" && node.src.startsWith(MAPS_API_URL)) {
                        scriptObserver.disconnect();
                        scriptObserver = undefined;
                        myLog("Detected Google Maps API");
                        node.onload = () => resolve();
                    }
                }
            }
        });

        let bodyDone = false;
        let headDone = false;

        let injectorObserver = new MutationObserver((mutations, observer) => {
            if (!bodyDone && document.body) {
                bodyDone = true;
                myLog("Body Observer Injected");
                scriptObserver && scriptObserver.observe(document.body, {
                    childList: true
                });
            }
            if (!headDone && document.head) {
                headDone = true;
                myLog("Head Observer Injected");
                scriptObserver && scriptObserver.observe(document.head, {
                    childList: true
                });
            }
            if (headDone && bodyDone) {
                myLog("Body and Head Observers Injected");
                observer.disconnect();
            }
        });

        injectorObserver.observe(document.documentElement, {
            childList: true,
            subtree: true
        });
    });
}

/**
 * Creates teleportation and Kakao switch button
 *
 * @returns Promise
 */

function ArisKakao() {
    runAsClient(() => {

        let radi = 100;
        const google = window.google;
        let curPosition, mapPlayer;
        let kakao_enabled = true;

        const isGamePage = () => location.pathname.startsWith("/challenge/") || location.pathname.startsWith("/results/") || location.pathname.startsWith("/game/")|| location.pathname.startsWith("/battle-royale/");

        const getPosition = sv => (
            {
                lat: sv.position.lat(),
                lng: sv.position.lng(),
            });

        // Handle the street view being navigated
        const onMove = (sv) => {
            try {
                if (!isGamePage()) return;
                const position = getPosition(sv);
                // console.log("HHHHHHHHHHHHH");
                // console.log(position);
                curPosition = position;
            }
            catch (e) {
                console.error("GeoGuessr Path Logger Error:", e);
            }
        };

        // Helper Functions

        function FindPointAtDistanceFrom(startPoint, initialBearingRadians, distanceKilometres) {
            const radiusEarthKilometres = 6371.01;
            var distRatio = distanceKilometres / radiusEarthKilometres;
            var distRatioSine = Math.sin(distRatio);
            var distRatioCosine = Math.cos(distRatio);

            var startLatRad = DegreesToRadians(startPoint.lat);
            var startLonRad = DegreesToRadians(startPoint.lng);

            var startLatCos = Math.cos(startLatRad);
            var startLatSin = Math.sin(startLatRad);

            var endLatRads = Math.asin((startLatSin * distRatioCosine) + (startLatCos * distRatioSine * Math.cos(initialBearingRadians)));

            var endLonRads = startLonRad
                + Math.atan2(
                    Math.sin(initialBearingRadians) * distRatioSine * startLatCos,
                    distRatioCosine - startLatSin * Math.sin(endLatRads));

            return { lat: RadiansToDegrees(endLatRads), lng: RadiansToDegrees(endLonRads) };
        }

        function DegreesToRadians(degrees) {
            const degToRadFactor = Math.PI / 180;
            return degrees * degToRadFactor;
        }

        function RadiansToDegrees(radians) {
            const radToDegFactor = 180 / Math.PI;
            return radians * radToDegFactor;
        }

        function svCheck(data, status) {
            if (status === 'OK') {
                console.log("OK for " + data.location.latLng + " at ID " + data.location.pano);
                let l = data.location.latLng.toString().split(',');
                let lat = l[0].replaceAll('(', '')
                let lng = l[1].replaceAll(')', '')
                // console.log(lat);
                // console.log(lng)
                // console.log(curPosition)
                if (lat == curPosition.lat && lng == curPosition.lng)
                {
                    console.log("Trying more distance");
                    radi += 100;
                    teleportButton.innerHTML = "Teleport " + radi + " m";
                }
                else
                {
                    mapPlayer.setPosition(data.location.latLng);
                    // console.log(radi);
                    if (radi > 200)
                    {
                        radi = 100;
                        teleportButton.innerHTML = "Teleport " + radi + " m";
                    }
                }
            }
            else {
                console.log("STATUS NOT OK");
                radi += 100;
                teleportButton.innerHTML = "Teleport " + radi + " m";
            }
        }

        // When a StreetViewPanorama is constructed, add a listener for moving
        const oldSV = google.maps.StreetViewPanorama;
        const svService = new google.maps.StreetViewService();

        google.maps.StreetViewPanorama = Object.assign(function (...args) {
            const res = oldSV.apply(this, args);
            this.addListener('position_changed', () => onMove(this));
            mapPlayer = this;
            // console.log("Hi")
            // console.log(mapPlayer)
            return res;
        }, {
            prototype: Object.create(oldSV.prototype)
        });

        var showButtons = document.createElement("Button");
        showButtons.id = "Show Buttons"
        showButtons.innerHTML = "Script Buttons";
        showButtons.style =
        "top:6em;right:0.5em;width:6em;height:4.5em;position:absolute;z-index:99999;background-color: #4CAF50;border: none;color: white;padding: none;text-align: center;vertical-align: text-top;text-decoration: none;display: inline-block;font-size: 16px;";
        document.body.appendChild(showButtons);
        showButtons.addEventListener("click", () => {
            if (hide) {
                teleportButton.style.visibility = "";
                plusButton.style.visibility = "";
                minusButton.style.visibility = "";
                resetButton.style.visibility = "";
                googleKakaoButton.style.visibility = "";
                hide = false;
            }
            else {
                teleportButton.style.visibility = "hidden";
                plusButton.style.visibility = "hidden";
                minusButton.style.visibility = "hidden";
                resetButton.style.visibility = "hidden"
                googleKakaoButton.style.visibility = "hidden";
                hide = true;
            }
        });

        var teleportButton = document.createElement("Button");
        teleportButton.id = "Main Button"
        teleportButton.innerHTML = "Teleport 100m";
        teleportButton.style =
        "visibility:hidden;top:6em;right:9.5em;width:10em;height:2em;position:absolute;z-index:99999;background-color: #4CAF50;border: none;color: white;padding: none;text-align: center;vertical-align: text-top;text-decoration: none;display: inline-block;font-size: 16px;";
        document.body.appendChild(teleportButton);
        teleportButton.addEventListener("click", () => {
            let heading = mapPlayer.getPov().heading;
            let place = FindPointAtDistanceFrom(curPosition, DegreesToRadians(heading), radi * 0.001)
            svService.getPanorama({ location: place, radius: 1000 }, svCheck);

        });

        var plusButton = document.createElement("Button");
        plusButton.id = "plus"
        plusButton.innerHTML = "+";
        plusButton.style =
        "visibility:hidden;top:6em;right:20em;width:2em;height:2em;position:absolute;z-index:99999;background-color: #4CAF50;border: none;color: white;padding: none;text-align: center;vertical-align: text-top;text-decoration: none;display: inline-block;font-size: 16px;";
        document.body.appendChild(plusButton);
        plusButton.addEventListener("click", () => {
            if (radi > 21 && radi < 200) {
                radi = radi + 25;
            }
            teleportButton.innerHTML = "Teleport " + radi + " m";
        });

        var minusButton = document.createElement("Button");
        minusButton.id = "minus"
        minusButton.innerHTML = "-";
        minusButton.style =
        "visibility:hidden;top:6em;right:7em;width:2em;height:2em;position:absolute;z-index:99999;background-color: #4CAF50;border: none;color: white;padding: none;text-align: center;vertical-align: text-top;text-decoration: none;display: inline-block;font-size: 16px;";
        document.body.appendChild(minusButton);
        minusButton.addEventListener("click", () => {
            if (radi > 26) {
                radi = radi - 25;
            }
            teleportButton.innerHTML = "Teleport " + radi + " m";
        });

        var resetButton = document.createElement("Button");
        resetButton.id = "reset"
        resetButton.innerHTML = "Reset";
        resetButton.style =
        "visibility:hidden;top:8.5em;right:17.5em;width:4.5em;height:2em;position:absolute;z-index:99999;background-color: #4CAF50;border: none;color: white;padding: none;text-align: center;vertical-align: text-top;text-decoration: none;display: inline-block;font-size: 16px;";
        document.body.appendChild(resetButton);
        resetButton.addEventListener("click", () => {
            radi = 100;
            teleportButton.innerHTML = "Teleport " + radi + " m";
        });

        var googleKakaoButton = document.createElement("Button");
        googleKakaoButton.id = "switch"
        googleKakaoButton.innerHTML = "Switch coverage";
        googleKakaoButton.style =
        "visibility:hidden;top:8.5em;right:7em;width:10em;height:2em;position:absolute;z-index:99999;background-color: #4CAF50;border: none;color: white;padding: none;text-align: center;vertical-align: text-top;text-decoration: none;display: inline-block;font-size: 16px;";
        document.body.appendChild(googleKakaoButton);
        googleKakaoButton.addEventListener("click", () => {
            let GOOGLE_MAPS_CANVAS1 = document.querySelector(".game-layout__panorama-canvas");
            let GOOGLE_MAPS_CANVAS2 = document.querySelector(".br-game-layout__panorama-canvas");
            let GOOGLE_MAPS_CANVAS = null;
            if (GOOGLE_MAPS_CANVAS1 !== null)
            {
                GOOGLE_MAPS_CANVAS = GOOGLE_MAPS_CANVAS1;
            }
            else
            {
                GOOGLE_MAPS_CANVAS = GOOGLE_MAPS_CANVAS2;
            }
            let KAKAO_MAPS_CANVAS = document.getElementById("roadview");
            if (kakao_enabled) {
                GOOGLE_MAPS_CANVAS.style.visibility = "";
                KAKAO_MAPS_CANVAS.style.visibility = "hidden";
                kakao_enabled = false;
            }
            else {
                GOOGLE_MAPS_CANVAS.style.visibility = "hidden";
                KAKAO_MAPS_CANVAS.style.visibility = "";
                kakao_enabled = true;
                console.log("use Kakao");
            }
        });

        let hide = true;
        if (document.querySelector(".br-game-layout__panorama-canvas") != null)
        {
            teleportButton.style.top = "2px";
            plusButton.style.top = "2px";
            minusButton.style.top = "2px";
            resetButton.style.top = "calc(2.5em + 2px)";
            googleKakaoButton.style.top = "calc(2.5em + 2px)";
            showButtons.style.top = "2px";

            teleportButton.style.right = "calc(9.5em + 300px)";
            plusButton.style.right = "calc(20em + 300px)";
            minusButton.style.right = "calc(7em + 300px)";
            resetButton.style.right = "calc(17.5em + 300px)";
            googleKakaoButton.style.right = "calc(7em + 300px)";
            showButtons.style.right = "300px";
        }

        console.log("Buttons Loaded");

    });
}

/**
 * Hide or Reveal such buttons
 */

function setHidden(cond)
{
    if (cond)
    {
        if (document.getElementById("Show Buttons") != null)
        {
            document.getElementById("Show Buttons").style.visibility = "hidden";
            if (document.getElementById("Main Button") != null)
                {
                    document.getElementById("plus").style.visibility = "hidden";
                    document.getElementById("minus").style.visibility = "hidden";
                    document.getElementById("reset").style.visibility = "hidden";
                    document.getElementById("Main Button").style.visibility = "hidden";
                    document.getElementById("switch").style.visibility = "hidden";
                }
        }
    }
    else
    {
        if (document.getElementById("Show Buttons") != null)
        {
            document.getElementById("Show Buttons").style.visibility = "";
        }
    }
}

function setDisable(cond)
{
    if (cond !== "Google")
    {
        if (document.getElementById("Main Button") != null)
            {
                document.getElementById("plus").disabled = true;
                document.getElementById("plus").style.backgroundColor = "red";
                document.getElementById("minus").disabled = true;
                document.getElementById("minus").style.backgroundColor = "red";
                document.getElementById("reset").disabled = true;
                document.getElementById("reset").style.backgroundColor = "red";
                document.getElementById("Main Button").disabled = true;
                document.getElementById("Main Button").style.backgroundColor = "red";
                document.getElementById("switch").disabled = true;
                document.getElementById("switch").style.backgroundColor = "red";

            if (cond === "Kakao")
            {
                document.getElementById("switch").disabled = false;
                document.getElementById("switch").style.backgroundColor = "#4CAF50";
            }
            else
            {
                document.getElementById("switch").disabled = true;
                document.getElementById("switch").style.backgroundColor = "red";
            }
        }
    }
    else
    {
        if (document.getElementById("Main Button") != null)
        {
            document.getElementById("plus").disabled = false;
            document.getElementById("plus").style.backgroundColor = "#4CAF50";
            document.getElementById("minus").disabled = false;
            document.getElementById("minus").style.backgroundColor = "#4CAF50";
            document.getElementById("reset").disabled = false;
            document.getElementById("reset").style.backgroundColor = "#4CAF50";
            document.getElementById("Main Button").disabled = false;
            document.getElementById("Main Button").style.backgroundColor = "#4CAF50";
            document.getElementById("switch").disabled = false;
            document.getElementById("switch").style.backgroundColor = "#4CAF50";
            document.getElementById("switch").disabled = true;
            document.getElementById("switch").style.backgroundColor = "red";
    }
    }
}

/**
 * This observer stays alive while the script is running
 */
function launchObserver() {
    ArisKakao();
    myHighlight("Main Observer");
    const OBSERVER = new MutationObserver((mutations, observer) => {
        detectGamePage();
    });
    OBSERVER.observe(document.head, { attributes: true, childList: true, subtree: true });
}

/**
 * Once the Google Maps API was loaded we can do more stuff
 */
gmp().then(() => {
    launchObserver();
});


/**
 * Detects if the current page contains /game/ or /challenge/ in it
 */

function detectGamePage() {
    let toLoad = !playerLoaded && !PLAYER && !PLAYER2 && !PLAYER3 && !YANDEX_INJECTED && !BAIDU_INJECTED && !KAKAO_INJECTED
    const PATHNAME = window.location.pathname;
    if (PATHNAME.startsWith("/game/") || PATHNAME.startsWith("/challenge/")) {
        // myLog("Game page");
        BR = false;

        if (toLoad) {
            loadPlayers();
        }
        waitLoad();
    }
    else if (PATHNAME.startsWith("/battle-royale/")) {
        if (document.querySelector(".br-game-layout") == null) {
            // myLog("Battle Royale Lobby");
        }
        else {
            // myLog("Battle Royale");
            BR = true;
            if (toLoad) {
                loadPlayers();
            }
            waitLoad();
        }
    }
    else {
        //myLog("Not a Game page");
        ROUND = 0;
        PLAYER = null;
        PLAYER2 = null;
        PLAYER3 = null;
        COMPASS = null;
        eventlistener = false;
        BAIDU_INJECTED = false;
        YANDEX_INJECTED = false;
        KAKAO_INJECTED = false;
        global_lat = 0;
        global_lng = 0;
        global_panoID = null;
        playerLoaded = false;
        loc_list = [];
        setHidden(true);
        yandex_map = false;
    }
}

/**
 * Wait for various players to load
 */

function waitLoad() {
    if (!PLAYER || !PLAYER2 || !PLAYER3 || !YANDEX_INJECTED || !BAIDU_INJECTED || !KAKAO_INJECTED) {
        setTimeout(waitLoad, 100);
    } else {
        checkRound();
    }
}

/**
 * Checks for round changes
 */
function checkRound() {
    //   myLog("Check Round");
    if (!BR) {
        let currentRound = getRoundFromPage();
        if (ROUND != currentRound) {
            myHighlight("New round");
            ROUND = currentRound;
            NEW_ROUND_LOADED = true;
            COMPASS = null;
            loc_list = [];
            getMapData();
            nextButtonCallback();
        }
    }
    else {
        // myHighlight("BR New round");
        NEW_ROUND_LOADED = true;
        COMPASS = null;
        loc_list = [];
        getMapData();
    }
}

function nextButtonCallback()
{
    let nextButton = document.querySelector("button[data-qa='close-round-result']");
    if (nextButton != null)
    {
        nextButton.addEventListener("click", (e) => {
            if (document.getElementById("Show Buttons") != null)
            {
                myLog("try to hide show buttons")
                document.getElementById("Show Buttons").style.visibility = "";
            }
        })
    }
    else
    {
        setTimeout(nextButtonCallback, 500);
    }
}

function guessButtonCallback()
{
    let guessButton = document.querySelector("button[data-qa='perform-guess']");

    if (guessButton!= null)
    {

        guessButton.addEventListener("click", (e) => {
            if (document.getElementById("Show Buttons") != null && !BR)
            {
                myLog("try to hide show buttons")
                document.getElementById("Show Buttons").style.visibility = "hidden";
                setHidden(true);
            }
        })
    }
    else
    {
        setTimeout(guessButtonCallback, 500);
    }
}

/**
 * Load different streetview players
 */

function loadPlayers() {
    playerLoaded = true;
    if (!BR)
    {
    getSeed().then((data) => {
        myLog(data);
        if (data.mapName.includes("A United World"))
        {
            injectYandexScript().then(() => {
                myLog("Ready to inject Yandex player");
                injectYandexPlayer();
            }).catch((error) => {
                myLog(error);
            });
        }
        else if (data.mapName.includes("Yandex"))
        {
            yandex_map = true;
            injectYandexScript().then(() => {
                myLog("Ready to inject Yandex player");
                injectYandexPlayer();
            }).catch((error) => {
                myLog(error);
            });
        }
        else{
            YANDEX_API_KEY = "";
            myLog("Not a Yandex map");
            YANDEX_INJECTED = true;
            PLAYER = "YD";
            injectYandexScript().then(() => {
                myLog("Ready to inject Yandex player");
            }).catch((error) => {
                myLog(error);
            });
        }
        setHidden(false);

    }).catch((error) => {
        myLog(error);
    });
}
    initializeCanvas();
    injectBaiduPlayer();
    injectKakaoScript().then(() => {
        myLog("Ready to inject Kakao player");
    }).catch((error) => {
        myLog(error);
    });
    if (BR)
    {
    injectYandexScript().then(() => {
        myLog("Ready to inject Yandex player");
        injectYandexPlayer();
    }).catch((error) => {
        myLog(error);
    });
}
}

/**
 * Handles Return to start and undo
 */

function handleReturnToStart() {
    myLog("handleReturnToStart listener attached");
    let rtsButton = document.querySelector("button[data-qa='return-to-start']");
    if (rtsButton != null) {
        rtsButton.addEventListener("click", (e) => {
            goToLocation(CURRENT_ROUND_DATA);
            const elementClicked = e.target;
            elementClicked.setAttribute('listener', 'true');
            myLog("Return to start");
        });
    }
    guessButtonCallback();
}

function handleUndo() {
    let undoButton = document.querySelector("button[data-qa='undo-move']");
    undoButton.addEventListener("click", (e) => {
        if (loc_list.length > 0) {
            goToUndoMove();
            myLog("Undo Move");
        }
    })

}

function getMapData() {
    getSeed().then((data) => {
        //myHighlight("Seed data");
        //myLog(data);
        if (BR) {
            if (document.querySelector(".br-game-layout") == null) {
                // myLog("Battle Royale Lobby");
            }
            else
            {
                // myLog("hello");
                let origin = false;
                if (!CURRENT_ROUND_DATA) {
                    CURRENT_ROUND_DATA = data
                    origin = true;
                }

                if (origin || !(data.currentRoundNumber === CURRENT_ROUND_DATA.currentRoundNumber)) {
                    if (!origin) {
                        CURRENT_ROUND_DATA = data;
                    }
                    locationCheck(data);
                    // myLog(data)
                    setTimeout(function () {goToLocation(data, nextPlayer);}, 1000);
                    setTimeout(function () { handleReturnToStart(); }, 2000);

                }
            }
        }
        else {
            locationCheck(data);
            setTimeout(function () { goToLocation(data, nextPlayer);}, 1000);
            setTimeout(function () { handleReturnToStart(); }, 2000);
            setTimeout(function () { handleUndo(); }, 2000);
            hideButtons();
        }
    }).catch((error) => {
        myLog(error);
    });
}

function hideButtons() {
    let CHECKPOINT = document.querySelector("button[data-qa='set-checkpoint']");
    let ZOOM_IN = document.querySelector("button[data-qa='pano-zoom-in']");
    let ZOOM_OUT = document.querySelector("button[data-qa='pano-zoom-out']");
    // myLog(CHECKPOINT);
    if (nextPlayer === "Google") {
        if (CHECKPOINT != null) {
            CHECKPOINT.style.visibility = "";
            ZOOM_IN.style.visibility = "";
            ZOOM_OUT.style.visibility = "";
            myLog("Buttons Unhidden");
        }
    }
    else {
        if (CHECKPOINT != null) {
            CHECKPOINT.style.visibility = "hidden";
            ZOOM_IN.style.visibility = "hidden";
            ZOOM_OUT.style.visibility = "hidden";
            myLog("Buttons Hidden");
        }
    }
}

function locationCheck(data) {
    console.log(data);
    if (BR) {
        global_lat = data.rounds[data.currentRoundNumber - 1].lat;
        global_lng = data.rounds[data.currentRoundNumber - 1].lng;
        global_panoID = data.rounds[data.currentRoundNumber - 1].panoId;
    }
    else {
        global_lat = data.rounds[data.round - 1].lat;
        global_lng = data.rounds[data.round - 1].lng;
        global_panoID = data.rounds[data.round - 1].panoId;
    }
    myLog(global_lat);
    myLog(global_lng);
    myLog(krCoordinates);
    if ( krCoordinates[0] > global_lat && krCoordinates[2] < global_lat && krCoordinates[1] < global_lng && krCoordinates[3] > global_lng)
    {
        nextPlayer = "Kakao";
    }
    else
    {
        if (global_panoID) {
            let output = hex2a(global_panoID);
            let type = output.substring(0, 5);
            if (type === "BDMAP") {
                nextPlayer = "Baidu";
                let coord = output.substring(5);
                global_lat = coord.split(",")[0];
                global_lng = coord.split(",")[1];
            }
            else if (type === "YDMAP" ) {
                nextPlayer = "Yandex";
            }
            else {
                nextPlayer = "Google";
            }
        }
        else {
            if (yandex_map)
            {
                nextPlayer = "Yandex";
            }
            else
            {
                nextPlayer = "Google";
            }
        }
    }
    if(!BR)
    {
        if (data.forbidMoving || data.forbidRotating || data.forbidZooming)
        {
            setDisable("NMPZ");
        }
        else
        {
            setDisable(nextPlayer);
        }
    }
    else
    {
        if (data.movementOptions.forbidMoving || data.movementOptions.forbidRotating || data.movementOptions.forbidZooming)
        {
            setDisable("NMPZ");
        }
        else
        {
            setDisable(nextPlayer);
        }
    }

    myLog(nextPlayer);
    injectCanvas();
}


function initializeCanvas() {
    let GAME_CANVAS = ""
    if (!BR) {
        GAME_CANVAS = document.querySelector(".game-layout__canvas");
    }
    else {
        GAME_CANVAS = document.querySelector(".br-game-layout__canvas");
    }
    GAME_CANVAS.id = "player";
    myLog("Canvas injected");
}

function injectCanvas() {
    Google();
    Baidu();
    Kakao();
    Yandex();
    ZoomControls();
}


function Google() {
    let GOOGLE_MAPS_CANVAS = ""
    if (!BR) {
        GOOGLE_MAPS_CANVAS = document.querySelector(".game-layout__panorama-canvas");
    }
    else {
        GOOGLE_MAPS_CANVAS = document.querySelector(".br-game-layout__panorama-canvas");
    }
    if (nextPlayer === "Google") {
        GOOGLE_MAPS_CANVAS.style.visibility = "";
        myLog("Google Canvas loaded");
    }
    else {
        GOOGLE_MAPS_CANVAS.style.visibility = "hidden";
        myLog("Google Canvas hidden");
    }

}


function Baidu() {
    let BAIDU_MAPS_CANVAS = document.getElementById("PanoramaMap");
    myLog("Baidu canvas");
    if (nextPlayer === "Baidu") {
        BAIDU_MAPS_CANVAS.style.visibility = "";
        myLog("Baidu Canvas loaded");
    }
    else {
        BAIDU_MAPS_CANVAS.style.visibility = "hidden";
        myLog("Baidu Canvas hidden");
    }

}

function Kakao() {
    let KAKAO_MAPS_CANVAS = document.getElementById("roadview");
    myLog("Kakao canvas");
    if (nextPlayer === "Kakao") {
        KAKAO_MAPS_CANVAS.style.visibility = "";
        myLog("Kakao Canvas loaded");
    }
    else {
        KAKAO_MAPS_CANVAS.style.visibility = "hidden";
        myLog("Kakao Canvas hidden");
    }

}

function Yandex() {
        let YANDEX_MAPS_CANVAS = document.querySelector(".ymaps-2-1-79-panorama-screen");
        if (YANDEX_MAPS_CANVAS != null)
        {
            myLog("Yandex canvas");
            /*   myLog(YANDEX_MAPS_CANVAS); */
            if (nextPlayer === "Yandex") {
                YANDEX_MAPS_CANVAS.style.visibility = "";
                myLog("Yandex Canvas loaded");
            }
            else {
                YANDEX_MAPS_CANVAS.style.visibility = "hidden";
                myLog("Yandex Canvas hidden");
            }
        }

}

function ZoomControls() {
    let style = `
	.ymaps-2-1-79-panorama-gotoymaps {display: none !important;}
	.game-layout__controls {bottom: 8rem !important; left: 1rem !important;}
	`;

    let style_element = document.createElement("style");
    style_element.innerHTML = style;
    document.body.appendChild(style_element);
}

function goToLocation(data) {
    myLog("Going to location");
    if (nextPlayer === "Yandex") {
        let options = {};
        PLAYER.moveTo([global_lat, global_lng], options);
        PLAYER.setDirection([0, 16]);
        PLAYER.setSpan([10, 67]);
    }
    else if (nextPlayer === "Baidu") {
        let a = new BMap.Point(global_lng, global_lat);
        PLAYER2.setPov({ heading: -40, pitch: 6 });
        PLAYER2.setPosition(a);
    }
    else if (nextPlayer === "Kakao") {
        var roadviewClient = new kakao.maps.RoadviewClient();
        var position = new kakao.maps.LatLng(global_lat, global_lng);
        roadviewClient.getNearestPanoId(position, 500, function (panoId) {
            PLAYER3.setPanoId(panoId, position);
        });
    }
    else {

    }

}

function goToUndoMove(data) {
    /*   myLog(global_lat);
      myLog(global_lng); */
    if (nextPlayer === "Yandex") {
        let options = {};
        let place2 = null;
        if (loc_list.length === 1) {
            place2 = loc_list[0];
        }
        else {
            place2 = loc_list.pop();
        }
        pops = false;
        // myLog(place2);
        // myLog(loc_list)
        PLAYER.moveTo([place2[0], place2[1]], options);
        PLAYER.setDirection([place2[2], place2[3]]);
        PLAYER.setSpan([10, 67]);
    }
    else if (nextPlayer === "Kakao") {
        let place3 = null;
        if (loc_list.length === 1) {
            place3 = loc_list[0];
        }
        else {
            place3 = loc_list.pop();
        }
        pops = false;
        var position = new kakao.maps.LatLng(place3[0], place3[1]);
        PLAYER3.setPanoId(place3[2], position);
    }
    else if (nextPlayer === "Baidu") {
        /*     myLog(PLAYER2);
            myLog(global_lng);
            myLog(global_lat); */
        let place = null;
        if (loc_list.length === 1) {
            place = loc_list[0];
        }
        else {
            place = loc_list.pop();
        }
        // myLog(place);
        let a = new BMap.Point(place[1], place[0]);
        let pov = { heading: place[2], pitch: place[3] };
        PLAYER2.setPosition(a);
        PLAYER2.setPov(pov);
        // myLog(loc_list);
        /*     myLog(PLAYER2); */
    }
    else {

    }

}




/**
 * Gets the seed data for the current game
 *
 * @returns Promise with seed data as object
 */
function getSeed() {
    // myLog("getSeed called");
    return new Promise((resolve, reject) => {
        let token = getToken();
        let URL;
        let cred = ""

        const PATHNAME = window.location.pathname;

        if (PATHNAME.startsWith("/game/")) {
            URL = `https://www.geoguessr.com/api/v3/games/${token}`;
        }
        else if (PATHNAME.startsWith("/challenge/")) {
            URL = `https://www.geoguessr.com/api/v3/challenges/${token}/game`;
        }
        else if (PATHNAME.startsWith("/battle-royale/")) {
            URL = `https://game-server.geoguessr.com/api/battle-royale/${token}`;
        }
        if (BR) {
            fetch(URL, {
                // Include credentials to GET from the endpoint
                credentials: 'include'
            })
                .then((response) => response.json())
                .then((data) => {
                    resolve(data);
                })
                .catch((error) => {
                    reject(error);
                });
        }
        else {
            fetch(URL)
                .then((response) => response.json())
                .then((data) => {
                    resolve(data);
                })
                .catch((error) => {
                    reject(error);
                });
        }
    });
}

/**
 * Gets the token from the current URL
 *
 * @returns token
 */
function getToken() {
    const PATHNAME = window.location.pathname;
    if (PATHNAME.startsWith("/game/")) {
        return PATHNAME.replace("/game/", "");
    }
    else if (PATHNAME.startsWith("/challenge/")) {
        return PATHNAME.replace("/challenge/", "");
    }
    else if (PATHNAME.startsWith("/battle-royale/")) {
        return PATHNAME.replace("/battle-royale/", "");
    }
}

/**
 * Gets the round number from the ongoing game from the page itself
 *
 * @returns Round number
 */
function getRoundFromPage() {
    const roundData = document.querySelector("div[data-qa='round-number']");
    if (roundData) {
        let roundElement = roundData.querySelector("div:last-child");
        if (roundElement) {
            let round = parseInt(roundElement.innerText.charAt(0));
            if (!isNaN(round) && round >= 1 && round <= 5) {
                return round;
            }
        }
    }
    else {
        return ROUND;
    }
}


/**
 * Injects Yandex Script
 */
function injectYandexScript() {
    return new Promise((resolve, reject) => {
        if (!YANDEX_INJECTED) {
            if (YANDEX_API_KEY === "") {
            //     let canvas = document.getElementById("player");
            //     canvas.innerHTML = `
			// <div style="text-align: center;">
			// <h1 style="margin-top: 80px; font-size: 48px;">YOU NEED YANDEX API KEY<h1>
			// <p><a target="_blank" href="https://yandex.com/dev/maps/jsapi/doc/2.1/quick-start/index.html?from=techmapsmain">Get it here</a></p>
			// <br/>
			// <p>After that you need to add that key into this script in</p>
			// <code>const YANDEX_API_KEY = "";</code>
			// </div>
			// `;
                myLog("No Yandex Key")
                reject();
            }
            else {
                const SCRIPT = document.createElement("script");
                SCRIPT.type = "text/javascript";
                SCRIPT.async = true;
                SCRIPT.onload = () => {
                    ymaps.ready(() => {
                        YANDEX_INJECTED = true;
                        myHighlight("Yandex API Loaded");
                        resolve();
                    });
                }
                SCRIPT.src = `https://api-maps.yandex.ru/2.1/?lang=en_US&apikey=${YANDEX_API_KEY}`;
                document.body.appendChild(SCRIPT);
            }
        }
        else {
            resolve();
        }
    });
}

/**
 * Injects Yandex Player and calls handleReturnToStart
 */
function injectYandexPlayer() {
    let lat = 41.321861;
    let lng = 69.212920;

    let options = {
        "direction": [0, 16],
        "span": [10, 67],
        "controls": ["zoomControl"]
    };
    ymaps.panorama.createPlayer("player", [lat, lng], options)
        .done((player) => {
            PLAYER = player;
            PLAYER.events.add("directionchange", (e) => {
                updateCompass();
            });
            PLAYER.events.add("panoramachange", (e) => {
                if (pops && !BR) {
                    let num = PLAYER.getPanorama().getPosition();
                    let pov = PLAYER.getDirection();
                    // myLog(num);
                    // myLog(pov);
                    loc_list.push([num[0], num[1], pov[0], pov[1]]);
                    let btn = document.querySelector("button[data-qa='undo-move']");
                    if (loc_list.length > 1) {
                        btn.disabled = false;
                        btn.classList.remove('styles_disabled__W_k45');
                    }
                    // myLog(loc_list);
                }
                pops = true;

            });
            myHighlight("Player injected");
        });

}


/**
 * Injects Baidu
 */
function injectBaiduScript() {
    return new Promise((resolve, reject) => {
        if (!BAIDU_INJECTED) {
            if (BAIDU_API_KEY === "") {
                let canvas = document.getElementById("player");
                canvas.innerHTML = `
              <div style="text-align: center;">
              <h1 style="margin-top: 80px; font-size: 48px;">YOU NEED Baidu API KEY<h1>
              <br/>
              <p>After that you need to add that key into this script in</p>
              <code>const YANDEX_API_KEY = "";</code>
              </div>
              `;
                reject();
            }
            else {
                const SCRIPT = document.createElement("script");
                SCRIPT.type = "text/javascript";
                SCRIPT.async = true;
                SCRIPT.src = `https://api.map.baidu.com/api?v=3.0&ak=${BAIDU_API_KEY}&callback=init`;
                document.body.appendChild(SCRIPT);

                let canvas = document.createElement("bmap");
                if (BR) {
                    canvas.innerHTML = `
                 <div id="PanoramaMap" class="br-game-layout__panorama" style="zIndex: 99999,position: "absolute", top: 0, left: 0, width: '100%', height: '100%',"> </div>
            `;
                }
                else {
                    canvas.innerHTML = `
                 <div id="PanoramaMap" class="game-layout__panorama" style="zIndex: 99999,position: "absolute", top: 0, left: 0, width: '100%', height: '100%',"> </div>
            `;
                }

                var div = document.getElementById("player");
                div.appendChild(canvas);

                SCRIPT.addEventListener('load', () => {
                    myHighlight("Baidu API Loaded");
                    // resolve(BMap);
                    let timeout = 0;
                    let interval = setInterval(() => {
                        if (timeout >= 20) {
                            reject();
                            clearInterval(interval);
                        }
                        if (typeof BMap.Panorama !== "undefined") {
                            BAIDU_INJECTED = true;
                            resolve(BMap);
                            clearInterval(interval);
                        }
                        timeout += 1;
                    }, 500);
                })


            }
        }
        else {
            resolve();
        }
    });
}



/**
 * Injects Baidu
 */
function injectKakaoScript() {
    return new Promise((resolve, reject) => {
        if (!KAKAO_INJECTED) {
            if (KAKAO_API_KEY === "") {
                let canvas = document.getElementById("player");
                canvas.innerHTML = `
              <div style="text-align: center;">
              <h1 style="margin-top: 80px; font-size: 48px;">YOU NEED Kakao API KEY<h1>
              <br/>
              <p>After that you need to add that key into this script in</p>
              <code>const YANDEX_API_KEY = "";</code>
              </div>
              `;
                reject();
            }
            else {

                let canvas = document.createElement("kmap");
                if (BR) {
                    canvas.innerHTML = `
                 <div id="roadview" class="br-game-layout__panorama" style="zIndex: 99999,position: "absolute", top: 0, left: 0, width: '100%', height: '100%',"> </div>
            `;
                }
                else {
                    canvas.innerHTML = `
                 <div id="roadview" class="game-layout__panorama" style="zIndex: 99999,position: "absolute", top: 0, left: 0, width: '100%', height: '100%',"> </div>
            `;
                }

                var div = document.getElementById("player");
                div.appendChild(canvas);

                const SCRIPT = document.createElement("script");
                SCRIPT.async = true;
                // SCRIPT.type = "text/javascript";
                SCRIPT.src = `//dapi.kakao.com/v2/maps/sdk.js?appkey=${KAKAO_API_KEY}&autoload=false`;
                document.body.appendChild(SCRIPT);
                SCRIPT.onload = () => {
                    kakao.maps.load(function () {
                        var position = new kakao.maps.LatLng(33.450701, 126.560667);
                        let roadviewContainer = document.getElementById('roadview');
                        PLAYER3 = new kakao.maps.Roadview(roadviewContainer);
                        var panoId = 1023434522;
                        PLAYER3.setPanoId(panoId, position);
                        KAKAO_INJECTED = true;
                        kakao.maps.event.addListener(PLAYER3, 'panoid_changed', function() {
                            if (pops && !BR) {
                                let latlng = PLAYER3.getPosition();
                                let lat = latlng.getLat();
                                let lng = latlng.getLng();
                                let pID = PLAYER3.getPanoId();
                                // myLog(num);
                                // myLog(pov);
                                loc_list.push([lat, lng, pID]);
                                let btn = document.querySelector("button[data-qa='undo-move']");
                                if (loc_list.length > 1) {
                                    btn.disabled = false;
                                    btn.classList.remove('styles_disabled__W_k45');
                                }
                                myLog(loc_list);
                            }
                            pops = true;
                        });
                        resolve();
                    });
                };



            }
        }
        else {
            resolve();
        }
    });
}


/**
 * Injects Baidu Player and calls handleReturnToStart
 */
function injectBaiduPlayer() {
    let lat = 0;
    let lng = 0;
    injectBaiduScript().then(BMap => {
        PLAYER2 = new BMap.Panorama('PanoramaMap');
        PLAYER2.setPov({ heading: -40, pitch: 6 });
        PLAYER2.setPosition(new BMap.Point(lng, lat));
        if (!eventlistener && !BR) {
            myLog("position_listener attached");
            PLAYER2.addEventListener('position_changed', function (e) {
                eventlistener = true;
                // myLog('position_changed')
                let num = PLAYER2.getPosition();
                let pov = PLAYER2.getPov();
                if (num.lat != 0 && num.lat != 27.101448386472637) {
                    loc_list.push([num.lat, num.lng, pov.heading, pov.pitch]);
                }
                let btn = document.querySelector("button[data-qa='undo-move']");
                if (loc_list.length > 1) {
                    btn.disabled = false;
                    btn.classList.remove('styles_disabled__W_k45');
                }
                // myLog(loc_list);
            })
        }
    });
}



/**
 * Goes to location when PLAYER already exists
 *
 * @param {*} data
 */

/**
 * Updates the compass to match Yandex Panorama facing
 */
function updateCompass() {
    if (!COMPASS) {
        let compass = document.querySelector("img.compass__indicator");
        if (compass != null) {
            COMPASS = compass;
            let direction = PLAYER.getDirection()[0] * -1;
            COMPASS.setAttribute("style", `transform: rotate(${direction}deg);`);
        }
    }
    else {
        let direction = PLAYER.getDirection()[0] * -1;
        COMPASS.setAttribute("style", `transform: rotate(${direction}deg);`);
    }
}