Geoguessr Unity Script

For a full list of features included in this script, see this document https://docs.google.com/document/d/18nLXSQQLOzl4WpUgZkM-mxhhQLY6P3FKonQGp-H0fqI/edit?usp=sharing

目前为 2022-01-22 提交的版本。查看 最新版本

// ==UserScript==
// @name          Geoguessr Unity Script
// @description   For a full list of features included in this script, see this document https://docs.google.com/document/d/18nLXSQQLOzl4WpUgZkM-mxhhQLY6P3FKonQGp-H0fqI/edit?usp=sharing
// @version       4.3.0
// @include       https://www.geoguessr.com/*
// @run-at        document-start
// @license       MIT
// @namespace https://greasyfork.org/users/838374
// ==/UserScript==


// API Keys

var YANDEX_API_KEY = "b704b5a9-3d67-4d19-b702-ec7807cecfc6";
var KAKAO_API_KEY = "cbacbe41e3a223d794f321de4f3e247b";
const MAPS_API_URL = "https://maps.googleapis.com/maps/api/js"; // removed "?" from the link
var MAPILLARY_API_KEY_LIST =
    ["MLY|6723031704435203|5afd537469b114cf814881137ad74b7c",
     "MLY|6691659414239148|b45e7e82cde126044cbc2cf5d4a7c9b1",
     "MLY|5074369465929308|f7ad2802cbaf26c63f88046a292df68b",
     "MLY|7451643761528219|6477f2db0e3928b51e45ec9311983936",
     "MLY|4855256237866198|6d0464771831c8a4bf2be095e1e1aabc",
     "MLY|4772941976102161|8458d4f08d2e1970cdfe0a4e242c04ff",
     "MLY|4492067214235489|94c44703942362ad6f6b70b5d32c3a45",
     "MLY|4618251611628426|0cef71d6ec8b997a5ec06ecdeabf11ec",
     "MLY|4096846270415982|fa2ce29641503e6ef665f17459633570",
     "MLY|4231415756962414|fe353880fd246e8a4a6ae32152f7dbb0",]

var MAPILLARY_API_KEY = MAPILLARY_API_KEY_LIST[Math.floor(Math.random() * MAPILLARY_API_KEY_LIST.length)];

myLog("Geoguessr Unity Script V4.3.0");
// myLog(MAPILLARY_API_KEY);

// Store each player instance

let YandexPlayer, KakaoPlayer, GooglePlayer, MapillaryPlayer;
let YANDEX_INJECTED = false;
let BAIDU_INJECTED = false;
let KAKAO_INJECTED = false;
let MAPILLARY_INJECTED = false;

// Game mode detection

let isBattleRoyale = false;
let isDuel = false;

// Player detection and coordinate conversion

let nextPlayer = "Google";
let global_lat = 0;
let global_lng = 0;
let global_panoID = null;
let global_BDID, global_BDAh, global_BDBh;
let global_heading = null;
let global_pitch = null;

let krCoordinates = [38.75292321084364, 124.2804539232574, 33.18509676203202, 129.597381999198]
let global_radi = 100

// Callback variables

let eventListenerAttached = false;
let povListenerAttached = false;
let playerLoaded = false;
let teleportLoaded = false;
let syncLoaded = false;

// Minimize Yandex API use

let yandex_map = false;

// Mapillary Image Key

let mmKey = 0;

// Handle Yandex compass

let COMPASS = null;

// Handle undo

let locHistory = [];
let defaultPanoIdChange = true;

// Round check

let ROUND = 0;
let CURRENT_ROUND_DATA = null;

let switch_call = true;
let one_reset = false;
// let cnt = 0;

let cn_tips = false;
var isFirefox = typeof InstallTrigger !== 'undefined';

let linksList = []
let fire1 = true;

// let NEW_ROUND_LOADED = false;

/**
 * Helper Functions
 */

// Pretty print

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

// Hex to number conversion for Baidu coordinate conversion

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

// Coordinate computation given heading, distance and current coordinates for teleport

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

    var startLatRad = DegreesToRadians(lat);
    var startLonRad = DegreesToRadians(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;
}

// Check if two floating point numbers are really really really really close to each other (to 10 decimal points)
function almostEqual (a, b) {
    return a.toFixed(10) === b.toFixed(10)
}

function almostEqual2 (a, b) {
    return a.toFixed(3) === b.toFixed(3)
}

// Script injection, extracted from extenssr:
// https://gitlab.com/nonreviad/extenssr/-/blob/main/src/injected_scripts/maps_api_injecter.ts

function overrideOnLoad(googleScript, observer, overrider) {
    const oldOnload = googleScript.onload
    googleScript.onload = (event) => {
        const google = unsafeWindow.google
        if (google) {
            observer.disconnect()
            overrider(google)
        }
        if (oldOnload) {
            oldOnload.call(googleScript, event)
        }
    }
}

function grabGoogleScript(mutations) {
    for (const mutation of mutations) {
        for (const newNode of mutation.addedNodes) {
            const asScript = newNode
            if (asScript && asScript.src && asScript.src.startsWith('https://maps.googleapis.com/')) {
                return asScript
            }
        }
    }
    return null
}

function injecter(overrider) {
    if (document.documentElement)
    {
        injecterCallback(overrider);
    }
    else
    {
        setTimeout(injecter(overrider), 1000);
    }
}

function injecterCallback(overrider)
{
    new MutationObserver((mutations, observer) => {
        const googleScript = grabGoogleScript(mutations)
        if (googleScript) {
            overrideOnLoad(googleScript, observer, overrider)
        }
    }).observe(document.documentElement, { childList: true, subtree: true })
}

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

function ArisKakao() {
    // let radi = 100;
    const google = unsafeWindow.google;
    // console.log(google);
    let curPosition;
    let kakao_enabled = true;

    // 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 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(')', '')
            if (lat == curPosition.lat && lng == curPosition.lng && !switch_call)
            {
                console.log("Trying more distance");
                teleportButton.distance += 100;
                teleportButton.innerHTML = "Teleport " + teleportButton.distance + " m";
            }
            else
            {
                console.log("Teleport Success");
                GooglePlayer.setPosition(data.location.latLng);
                GooglePlayer.setPov({
                    heading: googleKakaoButton.heading,
                    pitch: 0,
                })
                // console.log(teleportButton.distance);
                if (teleportButton.distance > 150)
                {
                    teleportButton.distance = 100;
                    teleportButton.innerHTML = "Teleport " + teleportButton.distance + " m";
                }
            }
            switch_call = false;
        }
        else {
            console.log("STATUS NOT OK");
            teleportButton.distance += 100;
            teleportButton.innerHTML = "Teleport " + teleportButton.distance + " m";
        }
    }

    const svService = new google.maps.StreetViewService();
    google.maps.StreetViewPanorama = class extends google.maps.StreetViewPanorama {
        constructor(...args) {
            super(...args);
            GooglePlayer = this;

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

            this.addListener('position_changed', () => {
                // Maybe this could be used to update the position in the other players
                // so that they are always in sync
                try {
                    if (!isGamePage()) return;
                    // YearButton.panoId = GooglePlayer.pano;
                    // YearButton.index = -1;
                    const lat = this.getPosition().lat();
                    const lng = this.getPosition().lng();
                    const { heading } = this.getPov();

                    curPosition = { lat, lng, heading };

                    if (googleKakaoButton.useGoogle)
                    {
                        googleKakaoButton.lng = lng;
                        googleKakaoButton.lat = lat;
                        googleKakaoButton.heading = heading;
                        if (!YearButton.list.some(row => row.includes(GooglePlayer.pano)))
                        {
                            YearButton.innerHTML = "Time Machine";
                            YearButton.panoId = GooglePlayer.pano;
                            YearButton.index = -1;
                            YearButton.plusminusLock = true;
                            document.getElementById("plus year").style.backgroundColor = "red";
                            document.getElementById("plus year").disabled = true;
                            document.getElementById("minus year").style.backgroundColor = "red";
                            document.getElementById("minus year").disabled = true;
                        }
                    }
                    googleKakaoButton.useGoogle = true;
                    teleportButton.google = true;
                    // console.log("also run");

                    // googleKakaoButton.heading = position.lat;
                    // console.log(position.heading);
                    // console.log(googleKakaoButton.lng);
                }
                catch (e) {
                    console.error("GeoGuessr Path Logger Error:", e);
                }
            });
            this.addListener('pov_changed', () => {
                const { heading, pitch } = this.getPov();
                if (KakaoPlayer) {
                    const vp = KakaoPlayer.getViewpoint();
                    // Prevent a recursive loop: only update kakao's viewpoint if it got out of sync with google's
                    if (!almostEqual(vp.pan, heading) || !almostEqual(vp.tilt, pitch)) {
                        KakaoPlayer.setViewpoint({ pan: heading, tilt: pitch, zoom: vp.zoom });
                    }
                }
            });
        }
    };


    var showButtons = document.createElement("Button");
    showButtons.id = "Show Buttons"
    showButtons.innerHTML = "Geoguessr Unity Script<br><font size=1>by Jupaoqq<br>v4.3.0</font>";
    showButtons.style =
        "visibility:hidden;top:6em;right:0.5em;width:6em;height:7em;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.querySelector(".game-layout__status").appendChild(showButtons)
    document.body.appendChild(showButtons);
    showButtons.addEventListener("click", () => {
        if (hide) {
            teleportButton.style.visibility = "";
            plusButton.style.visibility = "";
            minusButton.style.visibility = "";
            resetButton.style.visibility = "";
            googleKakaoButton.style.visibility = "";
            YearButton.style.visibility = "";
            YearplusButton.style.visibility = "";
            YearminusButton.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";
            YearButton.style.visibility = "hidden";
            YearplusButton.style.visibility = "hidden";
            YearminusButton.style.visibility = "hidden";
            hide = true;
        }
    });

    var teleportButton = document.createElement("Button");
    teleportButton.id = "Main Button";
    teleportButton.distance = 100;
    teleportButton.google = true;
    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", () => {
        // console.log("Google Teleport");
        if (googleKakaoButton.init)
        {
            // console.log("run");
            googleKakaoButton.init = false;
            if (teleportButton.google)
            {
                googleKakaoButton.useGoogle = true;
                teleportButton.google = true;
            }
            else
            {
                googleKakaoButton.useGoogle = false;
                teleportButton.google = false;
            }
        }
        else
        {
            // myLog(teleportButton.google)
            if (teleportButton.google && GooglePlayer != null)
            {
                let heading = GooglePlayer.getPov().heading;
                let place = FindPointAtDistanceFrom(curPosition, DegreesToRadians(heading), teleportButton.distance * 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: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(plusButton);
    plusButton.addEventListener("click", () => {
        if (teleportButton.distance > 21 && teleportButton.distance < 149) {
            teleportButton.distance = teleportButton.distance + 25;
        }
        teleportButton.innerHTML = "Teleport " + teleportButton.distance + " m";
    });

    var minusButton = document.createElement("Button");
    minusButton.id = "minus"
    minusButton.innerHTML = "-";
    minusButton.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(minusButton);
    minusButton.addEventListener("click", () => {
        if (teleportButton.distance > 26) {
            teleportButton.distance = teleportButton.distance - 25;
        }
        teleportButton.innerHTML = "Teleport " + teleportButton.distance + " 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", () => {
        teleportButton.distance = 100;
        teleportButton.innerHTML = "Teleport " + teleportButton.distance + " m";
    });

    var googleKakaoButton = document.createElement("Button");
    googleKakaoButton.id = "switch";
    googleKakaoButton.init = false;
    googleKakaoButton.nextPlayer = "Google";
    googleKakaoButton.useGoogle = false;
    googleKakaoButton.lng = 0
    googleKakaoButton.lat = 0
    googleKakaoButton.heading = 0
    googleKakaoButton.innerHTML = "Switch Coverage";
    googleKakaoButton.small_canvas = false;
    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_CANVAS3 = document.querySelector(".inactive");
        let duel = false;

        let GOOGLE_MAPS_CANVAS = null;
        if (GOOGLE_MAPS_CANVAS1 !== null)
        {
            GOOGLE_MAPS_CANVAS = GOOGLE_MAPS_CANVAS1;
        }
        else if (GOOGLE_MAPS_CANVAS2 !== null)
        {
            GOOGLE_MAPS_CANVAS = GOOGLE_MAPS_CANVAS2;
        }


        if (GOOGLE_MAPS_CANVAS3 !== null)
        {
            duel = true;
        }

        let KAKAO_MAPS_CANVAS = document.getElementById("roadview");
        let YANDEX_MAPS_CANVAS = document.querySelector(".ymaps-2-1-79-panorama-screen");
        let MAPILLARY_MAPS_CANVAS = document.getElementById("mly")
        let BAIDU_MAPS_CANVAS = document.getElementById("PanoramaMap");
        //         if (googleKakaoButton.nextPlayer !== "Baidu") {
        if (googleKakaoButton.useGoogle == false) {
            if (duel)
            {
                document.getElementById("default_player").className = "game-panorama_panoramaCanvas__PNKve";
                if (googleKakaoButton.nextPlayer == "Kakao")
                {
                    document.getElementById("roadview").className = "inactive";
                }
                else
                {
                    MAPILLARY_MAPS_CANVAS.className = "inactive";
                    MAPILLARY_MAPS_CANVAS.style.visibility = "hidden";
                }
            }
            else
            {
                GOOGLE_MAPS_CANVAS.style.visibility = "";
                if (googleKakaoButton.nextPlayer == "Kakao")
                {
                    KAKAO_MAPS_CANVAS.style.visibility = "hidden";
                }
                else if (googleKakaoButton.nextPlayer == "Yandex")
                {
                    YANDEX_MAPS_CANVAS.style.visibility = "hidden";
                }
                else if (googleKakaoButton.nextPlayer == "Baidu")
                {
                    BAIDU_MAPS_CANVAS.style.visibility = "hidden";
                }
                else if (googleKakaoButton.nextPlayer == "Mapillary" || googleKakaoButton.nextPlayer == "Google")
                {
                    MAPILLARY_MAPS_CANVAS.style.visibility = "hidden";
                }

            }
            const lat = GooglePlayer.getPosition().lat();
            const lng = GooglePlayer.getPosition().lng();
            switch_call = true;
            if (!almostEqual2(lat, googleKakaoButton.lat) || !almostEqual2(lat, googleKakaoButton.lng)) {
                svService.getPanorama({ location: { lat: googleKakaoButton.lat, lng: googleKakaoButton.lng }, radius: 1000 }, svCheck);
            }
            googleKakaoButton.useGoogle = true;
            teleportButton.google = true;
            googleKakaoButton.init = false;
            console.log("use Google");
        }
        else {
            if (duel)
            {
                document.getElementById("default_player").className = "inactive";
                if (googleKakaoButton.nextPlayer == "Kakao")
                {
                    document.getElementById("roadview").className = "game-panorama_panorama__3b2wI";
                }
                else
                {
                    MAPILLARY_MAPS_CANVAS.className = "game-panorama_panorama__3b2wI";
                    MAPILLARY_MAPS_CANVAS.style.visibility = "";
                    MapillaryPlayer.resize();
                    //window.dispatchEvent(new Event('resize'));
                    // document.querySelector(".mapillary-canvas").style.;
                    // mapillary-canvas
                }

            }
            else
            {
                GOOGLE_MAPS_CANVAS.style.visibility = "hidden";
                if (googleKakaoButton.nextPlayer == "Kakao")
                {
                    KAKAO_MAPS_CANVAS.style.visibility = "";
                }
                else if (googleKakaoButton.nextPlayer == "Yandex")
                {
                    YANDEX_MAPS_CANVAS.style.visibility = "";
                }
                else if (googleKakaoButton.nextPlayer == "Baidu")
                {
                    BAIDU_MAPS_CANVAS.style.visibility = "";
                }
                else if (googleKakaoButton.nextPlayer == "Mapillary" || googleKakaoButton.nextPlayer == "Google" )
                {
                    MAPILLARY_MAPS_CANVAS.style.visibility = "";
                }
            }
            googleKakaoButton.useGoogle = false;
            teleportButton.google = false;
            googleKakaoButton.init = true;
            console.log("use Others");
        }
        //         }
        //         else {
        //             googleKakaoButton.useGoogle = false;
        //             teleportButton.google = false;
        //             console.log("use Others");
        //         }

    });

    var YearplusButton = document.createElement("Button");
    YearplusButton.id = "plus year"
    YearplusButton.innerHTML = "+";
    YearplusButton.style =
        "visibility:hidden;top:11em;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(YearplusButton);
    YearplusButton.addEventListener("click", () => {
        if (YearButton.index < YearButton.list.length - 1 && !YearButton.plusminusLock) {
            YearButton.index = YearButton.index + 1;
            GooglePlayer.setPano(YearButton.list[YearButton.index][0]);
            YearButton.innerHTML = "<font size=2>[" + (YearButton.index + 1) + "] " + YearButton.list[YearButton.index][1] + "</font>";
            // myLog(YearButton.index)
        }
        GenBtnColor();

    });

    var YearminusButton = document.createElement("Button");
    YearminusButton.id = "minus year"
    YearminusButton.innerHTML = "-";
    YearminusButton.style =
        "visibility:hidden;top:11em;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(YearminusButton);
    YearminusButton.addEventListener("click", () => {
        if (YearButton.index > 0 && !YearButton.plusminusLock) {
            YearButton.index = YearButton.index - 1;
            GooglePlayer.setPano(YearButton.list[YearButton.index][0]);
            YearButton.innerHTML = "<font size=2>[" + (YearButton.index + 1) + "] " + YearButton.list[YearButton.index][1] + "</font>";
            // myLog(YearButton.index)
        }
        GenBtnColor();
    });

    function svCheck2(data, status) {
        let l = []
        if (status === 'OK') {
            // console.log("OK for " + data.location.latLng + " at ID " + data.location.pano);
            // myLog(data.time)
            for (const alt of data.time) {
                let date = Object.values(alt).find((value) => value instanceof Date)

                l.push([alt.pano, date.toDateString()]);
            }
            // myLog(l);
            YearButton.list = l
            YearButton.index = l.length - 1;
            YearButton.innerHTML = "<font size=2>[" + (YearButton.index + 1) + "] " + YearButton.list[YearButton.index][1] + "</font>";
            GenBtnColor();
            YearButton.plusminusLock = false;
            // YearminusButton.click()
            // YearButton.innerHTML = "Default Date";
        }
    }

    var YearButton = document.createElement("Button");
    YearButton.id = "Date Button";
    YearButton.plusminusLock = true;
    YearButton.panoId = 0;
    YearButton.index = -1;
    YearButton.list = [];
    YearButton.innerHTML = "Time Machine";
    YearButton.style =
        "visibility:hidden;top:11em;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(YearButton);
    YearButton.addEventListener("click", () => {
        // myLog(YearButton.index)
        if (YearButton.panoId != 0)
        {
            if(YearButton.index == -1)
            {
                svService.getPanorama({pano: YearButton.panoId}, svCheck2);
            }
            else
            {
                YearButton.index = YearButton.list.length - 1;
                GooglePlayer.setPano(YearButton.list[YearButton.index][0]);
                YearButton.innerHTML = "<font size=2>[" + (YearButton.index + 1) + "] " + YearButton.list[YearButton.index][1] + "</font>";
                GenBtnColor();
            }
        }
        else
        {
            YearButton.panoId = GooglePlayer.pano;
            svService.getPanorama({pano: YearButton.panoId}, svCheck2);
        }
    });

    // Battle Royale UI optimization

    let hide = true;

    console.log("Buttons Loaded");
}

function GenBtnColor()
{
    if (document.getElementById("Date Button").index == document.getElementById("Date Button").list.length - 1)
    {
        document.getElementById("plus year").style.backgroundColor = "red";
        document.getElementById("plus year").disabled = true;
    }
    else
    {
        document.getElementById("plus year").style.backgroundColor = "#4CAF50";
        document.getElementById("plus year").disabled = false;
    }
    if (document.getElementById("Date Button").index == 0)
    {
        document.getElementById("minus year").style.backgroundColor = "red";
        document.getElementById("minus year").disabled = true;
    }
    else
    {
        document.getElementById("minus year").style.backgroundColor = "#4CAF50";
        document.getElementById("minus year").disabled = false;
    }
}

/**
 * Handle Keyboard inputs
 */

function kBoard()
{
    document.addEventListener('keydown', logKey);
}

function logKey(e) {
    // myLog(e.code);
    if (e.code == "Space")
    {
        setHidden(true);
    }
    if (e.code == "Digit1")
    {
        setHidden(false);
        document.getElementById("Show Buttons").click();
    }
    else if (e.code == "Digit3")
    {
        document.getElementById("Main Button").click();
    }
    else if (e.code == "Digit2")
    {
        document.getElementById("minus").click();
    }
    else if (e.code == "Digit4")
    {
        document.getElementById("plus").click();

    }
    else if (e.code == "Digit5")
    {
        document.getElementById("reset").click();

    }
    else if (e.code == "Digit6")
    {
        document.getElementById("switch").click();
    }
    else if (e.code == "Digit7")
    {
        document.getElementById("minus year").click();
    }
    else if (e.code == "Digit8")
    {
        document.getElementById("Date Button").click();
    }
    else if (e.code == "Digit9")
    {
        document.getElementById("plus year").click();
    }
    else if (e.code == "Digit0")
    {
        if (document.getElementById("Show Buttons").style.visibility == "hidden")
        {
            document.getElementById("Show Buttons").style.visibility = "";
        }
        else
        {
            document.getElementById("Show Buttons").style.visibility = "hidden";
        }
    }
}


/**
 * Hide or reveal the buttons, and disable buttons if such feature is not available
 */

function setHidden(cond)
{
    // myLog("Sethidden")
    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";
                document.getElementById("Date Button").style.visibility = "hidden";
                document.getElementById("plus year").style.visibility = "hidden";
                document.getElementById("minus year").style.visibility = "hidden";
            }
        }
    }
    else
    {
        if (document.getElementById("Show Buttons") != null)
        {
            document.getElementById("Show Buttons").style.visibility = "";
        }
    }
}

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

            document.getElementById("Date Button").style.backgroundColor = "#4CAF50";
            document.getElementById("Date Button").disabled = false;
        }
        else if (cond == "Google") {

            document.getElementById("plus").style.backgroundColor = "#4CAF50";
            document.getElementById("plus").disabled = false;
            document.getElementById("minus").style.backgroundColor = "#4CAF50";
            document.getElementById("minus").disabled = false;
            document.getElementById("reset").style.backgroundColor = "#4CAF50";
            document.getElementById("reset").disabled = false;
            document.getElementById("switch").style.backgroundColor = "#4CAF50";
            document.getElementById("switch").disabled = false;
            document.getElementById("switch").innerHTML = "Switch Coverage";
            document.getElementById("Main Button").disabled = false;
            document.getElementById("Main Button").style.backgroundColor = "#4CAF50";
            document.getElementById("Date Button").style.backgroundColor = "#4CAF50";
            document.getElementById("Date Button").disabled = false;
        }
        else if (cond == "Baidu") {
            document.getElementById("plus").style.backgroundColor = "red";
            document.getElementById("plus").disabled = true;
            document.getElementById("minus").style.backgroundColor = "red";
            document.getElementById("minus").disabled = true;
            document.getElementById("reset").style.backgroundColor = "red";
            document.getElementById("reset").disabled = true;
            document.getElementById("switch").style.backgroundColor = "#4CAF50";
            document.getElementById("switch").disabled = false;
            document.getElementById("switch").innerHTML = "Switch Coverage";
            document.getElementById("Main Button").disabled = true;
            document.getElementById("Main Button").style.backgroundColor = "red";
            document.getElementById("Date Button").style.backgroundColor = "red";
            document.getElementById("Date Button").disabled = true;
        }
        else if (cond == "Kakao" || cond == "Yandex" || cond == "Mapillary") {
            document.getElementById("plus").style.backgroundColor = "#4CAF50";
            document.getElementById("plus").disabled = false;
            document.getElementById("minus").style.backgroundColor = "#4CAF50";
            document.getElementById("minus").disabled = false;
            document.getElementById("reset").style.backgroundColor = "#4CAF50";
            document.getElementById("reset").disabled = false;
            document.getElementById("switch").style.backgroundColor = "#4CAF50";
            document.getElementById("switch").disabled = false;
            document.getElementById("switch").innerHTML = "Switch Coverage";
            document.getElementById("Main Button").disabled = false;
            document.getElementById("Main Button").style.backgroundColor = "#4CAF50";
            document.getElementById("Date Button").style.backgroundColor = "red";
            document.getElementById("Date Button").disabled = true;
        }
        document.getElementById("plus year").style.backgroundColor = "red";
        document.getElementById("plus year").disabled = true;
        document.getElementById("minus year").style.backgroundColor = "red";
        document.getElementById("minus year").disabled = true;
        //         else if (cond == "Mapillary") {
        //             document.getElementById("plus").style.backgroundColor = "red";
        //             document.getElementById("plus").disabled = true;
        //             document.getElementById("minus").style.backgroundColor = "red";
        //             document.getElementById("minus").disabled = true;
        //             document.getElementById("reset").style.backgroundColor = "red";
        //             document.getElementById("reset").disabled = true;
        //             document.getElementById("switch").style.backgroundColor = "#4CAF50";
        //             document.getElementById("switch").disabled = false
        //             document.getElementById("switch").innerHTML = "Switch Coverage";
        //             document.getElementById("Main Button").disabled = true;
        //             document.getElementById("Main Button").style.backgroundColor = "red";
        //         }

    }
}


/**
 * This observer stays alive while the script is running
 */

function launchObserver() {
    ArisKakao();
    BYKTeleport();
    SyncListener();
    kBoard();
    myHighlight("Main Observer");
    const OBSERVER = new MutationObserver((mutations, observer) => {
        detectGamePage();
    });
    observerCallback(OBSERVER)
}
function observerCallback(obs)
{
    if (obs)
    {
        obs.observe(document.head, { attributes: true, childList: true, subtree: true });
    }
    else
    {
        setTimeout(observerCallback, 250);
    }
}

/**
 * Once the Google Maps API was loaded we can do more stuff
 */

injecter(() => {
    launchObserver();
})


/**
 * Check whether the current page is a game, if so which game mode
 */

function detectGamePage() {
    if (document.querySelector(".game-layout__panorama-message") !== null && !one_reset)
    {
        one_reset = true;
        myLog("Hide fail to load panorama canvas");
        document.querySelector(".game-layout__panorama-message").style.visibility = "hidden";
    }
    let toLoad = !playerLoaded && !YandexPlayer && !KakaoPlayer && !MapillaryPlayer && !YANDEX_INJECTED && !KAKAO_INJECTED && !MAPILLARY_INJECTED
    const PATHNAME = window.location.pathname;
    if (PATHNAME.startsWith("/game/") || PATHNAME.startsWith("/challenge/")) {
        // myLog("Game page");
        isBattleRoyale = false;
        isDuel = false;
        if (toLoad) {
            loadPlayers();
        }
        waitLoad();
    }
    else if (PATHNAME.startsWith("/battle-royale/")) {
        if (document.querySelector(".br-game-layout") == null) {
            // myLog("Battle Royale Lobby");
            rstValues();
        }
        else {
            // myLog("Battle Royale");
            isBattleRoyale = true;
            isDuel = false;
            if (toLoad) {
                loadPlayers();
            }
            waitLoad();
        }
    }
    else if (PATHNAME.startsWith("/duels/") || PATHNAME.startsWith("/team-duels/")) {
        if (document.querySelector(".game_layout__TO_jf") == null) {
            // myLog("Battle Royale Lobby");
            rstValues();
        }
        else {
            // myLog("Duels");
            isBattleRoyale = true;
            isDuel = true;
            if (toLoad) {
                loadPlayers();
            }
            waitLoad();
        }
    }
    else {
        rstValues();
        //myLog("Not a Game page");
    }
}

function rstValues()
{
    ROUND = 0;
    YandexPlayer = null;
    KakaoPlayer = null;
    MapillaryPlayer = null;

    BAIDU_INJECTED = false;
    YANDEX_INJECTED = false;
    KAKAO_INJECTED = false;
    MAPILLARY_INJECTED = false;

    nextPlayer = "Google"
    global_lat = 0;
    global_lng = 0;
    global_panoID = null;
    global_BDAh = null;
    global_BDBh = null;
    global_BDID = null;

    COMPASS = null;
    eventListenerAttached = false;
    povListenerAttached = false;
    playerLoaded = false;
    locHistory = [];
    one_reset = false;
    setHidden(true);
    yandex_map = false;
    mmKey = 0;
    CURRENT_ROUND_DATA = null;

    linksList = [];
}

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

function waitLoad() {
    if (!YandexPlayer || !KakaoPlayer || !MapillaryPlayer || !YANDEX_INJECTED || !KAKAO_INJECTED || !MAPILLARY_INJECTED) {
        let teleportButton = document.getElementById("Main Button");
        let plusButton = document.getElementById("plus");
        let minusButton = document.getElementById("minus");
        let resetButton = document.getElementById("reset");
        let googleKakaoButton = document.getElementById("switch");
        let showButtons = document.getElementById("Show Buttons");
        let YearButton = document.getElementById("Date Button");
        let YearminusButton = document.getElementById("minus year");
        let YearplusButton = document.getElementById("plus year");
        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";
            YearButton.style.top = "calc(5em + 2px)";
            YearminusButton.style.top = "calc(5em + 2px)";
            YearplusButton.style.top = "calc(5em + 2px)";

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


        if (document.querySelector(".game-panorama_panorama__rdhFg") != null)
        {
            teleportButton.style.top = "8em";
            plusButton.style.top = "8em";
            minusButton.style.top = "8em";
            resetButton.style.top = "10.5em";
            googleKakaoButton.style.top = "10.5em";
            showButtons.style.top = "8em";
            YearButton.style.top = "13em";
            YearminusButton.style.top = "13em";
            YearplusButton.style.top = "13em";

            teleportButton.style.right = "9.5em";
            plusButton.style.right = "7em";
            minusButton.style.right = "20em";
            resetButton.style.right = "17.5em";
            googleKakaoButton.style.right = "7em";
            showButtons.style.right = "0.5em";
            YearButton.style.right = "9.5em";
            YearminusButton.style.right = "20em";
            YearplusButton.style.right = "7em";
        }

        setTimeout(waitLoad, 250);
    } else {
        checkRound();
    }
}

/**
 * Checks for round changes
 */

function checkRound() {
    //   myLog("Check Round");
    if (!isBattleRoyale) {
        // myLog("Check Round");
        let currentRound = getRoundFromPage();
        if (ROUND != currentRound) {
            fire1 = true;
            document.getElementById("switch").init = true;
            myHighlight("New round");
            ROUND = currentRound;
            // NEW_ROUND_LOADED = true;
            COMPASS = null;
            locHistory = [];
            one_reset = false;
            getMapData();
            nextButtonCallback();
        }
    }
    else {
        getMapData();
    }
}

/**
 * Add listeners if buttons have been created
 */

function finalDetail()
{
    let target = document.querySelector("a[data-qa='play-same-map']");
    if (target)
    {
        var div = document.createElement("div");
        div.classList.add("buttons_buttons__0B3SB")
        document.querySelector('.result-layout_content__jAHfP').appendChild(div);
        for (var rd of linksList)
        {
            let cl = target.cloneNode( true );
            let tx = "View R" + rd[0] + " in " + rd[1];
            cl.querySelector('.button_label__kpJrA').innerHTML = tx;
            cl.removeAttribute('data-qa');
            cl.addEventListener("click", (e) => {
                window.open(rd[2]);
            })
            cl.style = "top:10px;right:-10px;";
            div.appendChild(cl);
        }
    }
    else
    {
        setTimeout(finalDetail, 500);
    }
}

function nextButtonCallback()
{
    let nextButton = document.querySelector("button[data-qa='close-round-result']");
    if (nextButton != null && fire1)
    {
        fire1 = false;
        nextButton.addEventListener("click", (e) => {
            if (document.getElementById("Show Buttons") != null && !cn_tips && ROUND !== 5)
            {
                myLog("try to show show buttons")
                document.getElementById("Show Buttons").style.visibility = "";
            }
            if (ROUND == 5)
            {
                myLog("Game Finished")
                if (linksList)
                {
                    finalDetail();
                }
            }
        })

        if (nextPlayer !== "Google")
        {
            myLog("Clone buttons");
            let clone = document.querySelector("button[data-qa='close-round-result']").cloneNode( true );
            let tx = "View Location in " + nextPlayer;
            clone.querySelector('.button_label__kpJrA').innerHTML = tx;
            clone.setAttribute('id', "LinkBtn");
            clone.removeAttribute('data-qa');
            let urlStr = ""
            if (nextPlayer == "Baidu")
            {
                urlStr = "https://map.baidu.com/?panotype=street&pid=" + global_BDID + "&panoid=" + global_BDID + "&from=api";
            }
            else if (nextPlayer == "Kakao")
            {
                urlStr = "https://map.kakao.com/link/roadview/" + global_lat + "," + global_lng;
            }
            else if (nextPlayer == "Mapillary")
            {
                urlStr = "https://www.mapillary.com/app/?pKey=" + mmKey + "&focus=photo";
            }
            else if (nextPlayer == "Yandex")
            {
                urlStr = "https://yandex.com/maps/?&panorama%5Bdirection%5D=16%2C0&panorama%5Bpoint%5D=" + global_lng + "%2C" + global_lat;
            }
            linksList.push([ROUND, nextPlayer, urlStr]);
            clone.addEventListener("click", (e) => {
                window.open(urlStr);
            })
            if (ROUND == 5)
            {
                clone.style = "top:10px;";
            }
            else
            {
                clone.style = "right:-10px;";
            }
            document.querySelector('.round-result_actions__5j26U').appendChild(clone);
        }
    }
    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)
            {
                myLog("try to hide show buttons")
                document.getElementById("Show Buttons").style.visibility = "hidden";
                setHidden(true);
            }
        })
    }
    else
    {
        setTimeout(guessButtonCallback, 500);
    }
}

/**
 * Load different streetview players
 */

function injectYandex()
{
    injectYandexScript().then(() => {
        myLog("Ready to inject Yandex player");
        injectYandexPlayer();
    }).catch((error) => {
        myLog(error);
    });
}

function tutorialPosition(flag)
{
    let teleportButton = document.getElementById("Main Button");
    let plusButton = document.getElementById("plus");
    let minusButton = document.getElementById("minus");
    let resetButton = document.getElementById("reset");
    let googleKakaoButton = document.getElementById("switch");
    let showButtons = document.getElementById("Show Buttons");
    let YearButton = document.getElementById("Date Button");
    let YearminusButton = document.getElementById("minus year");
    let YearplusButton = document.getElementById("plus year");
    // document.getElementById("Show Buttons").style.visibility = "hidden";
    if (flag)
    {
        teleportButton.style.top = "20em";
        plusButton.style.top = "20em";
        minusButton.style.top = "20em";
        resetButton.style.top = "22.5em";
        googleKakaoButton.style.top = "22.5em";
        showButtons.style.top = "20em";
        YearButton.style.top = "25em";
        YearminusButton.style.top = "25em";
        YearplusButton.style.top = "25em";
    }
    else
    {
        teleportButton.style.top = "6em";
        plusButton.style.top = "6em";
        minusButton.style.top = "6em";
        resetButton.style.top = "8.5em";
        googleKakaoButton.style.top = "8.5em";
        showButtons.style.top = "6em";
        YearButton.style.top = "11em";
        YearminusButton.style.top = "11em";
        YearplusButton.style.top = "11em";

    }

}

function loadPlayers() {
    playerLoaded = true;
    if (!isBattleRoyale)
    {
        getSeed().then((data) => {
            // myLog(data);
            if (data.mapName.includes("A United World") || data.mapName.includes("byk"))
            {
                myLog("A United World");
                injectYandex();
            }
            else if (data.mapName.includes("Yandex"))
            {
                yandex_map = true;
                myLog("Is Yandex Map");
                injectYandex();
            }
            else{
                // YANDEX_API_KEY = "";
                YANDEX_INJECTED = true;
                YandexPlayer = "YD";
                myLog("Not a Yandex map");
            }
            if (!data.mapName.includes("China Tips for each province"))
            {
                cn_tips = false;
                document.getElementById("Show Buttons").style.visibility = "";
                setHidden(false);
            }
            else
            {
                cn_tips = true;
                guaranteeUI();
            }
        }).catch((error) => {
            myLog(error);
        });
    }
    else
    {
        injectYandex();
    }

    initializeCanvas();




}

function guaranteeUI()
{
    // myLog("UI")
    if (document.getElementById("GH-ui") !== null)
    {
        document.getElementById("GH-ui").style.display = "block";
    }
    else
    {
        setTimeout(guaranteeUI, 500);
    }
}

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

function handleReturnToStart() {
    let rtsButton = document.querySelector("button[data-qa='return-to-start']");
    if (rtsButton != null) {
        myLog("handleReturnToStart listener attached");
        rtsButton.addEventListener("click", (e) => {
            if (nextPlayer != "Baidu")
            {
                goToLocation();
            }
            else
            {
                document.getElementById("PanoramaMap").src = "https://map.baidu.com/?panotype=street&pid=" + global_BDID + "&panoid=" + global_BDID + "&from=api";
            }
            const elementClicked = e.target;
            elementClicked.setAttribute('listener', 'true');
            myLog("Return to start");
        });
        guessButtonCallback();
        setTimeout(function () {goToLocation();}, 1000);
    }
    else
    {
        setTimeout(handleReturnToStart, 500);
    }
}

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

}

/**
 * Load game information
 */

function getMapData() {
    // myHighlight("Seed data");
    getSeed().then((data) => {
        // myHighlight("Seed data");
        // myLog(data);
        if (isBattleRoyale) {
            if ((document.querySelector(".br-game-layout") == null && document.querySelector(".version3-in-game_layout__Hi_Iw") == null) || typeof data.gameId == typeof undefined) {
                // myLog("Battle Royale Lobby");
            }
            else
            {
                let origin = false;
                if (!CURRENT_ROUND_DATA) {
                    CURRENT_ROUND_DATA = data
                    origin = true;
                }

                if (origin || !(data.currentRoundNumber === CURRENT_ROUND_DATA.currentRoundNumber)) {
                    // myHighlight("Battle Royale New round");
                    document.getElementById("switch").init = true;
                    // NEW_ROUND_LOADED = true;
                    COMPASS = null;
                    locHistory = [];
                    one_reset = false;
                    setHidden(false);
                    if (!origin) {
                        CURRENT_ROUND_DATA = data;
                    }
                    locationCheck(data);
                    // myLog(data);
                    if (data.currentRoundNumber == 1)
                    {
                        setTimeout(function () {goToLocation();}, 3000);
                    }
                    else
                    {
                        goToLocation();
                    }
                    handleReturnToStart();
                    if (isDuel)
                    {
                        handleUndo();
                        hideButtons();
                    }

                }
            }
        }
        else {
            if (!cn_tips)
            {
                document.getElementById("Show Buttons").style.visibility = "";
                tutorialPosition(false);
            }
            else
            {
                document.getElementById("Show Buttons").style.visibility = "hidden";
                tutorialPosition(true);
            }
            locationCheck(data);
            if (data.currentRoundNumber == 1)
            {
                setTimeout(function () {goToLocation();}, 3000);
            }
            else
            {
                goToLocation();
            }
            handleReturnToStart();
            handleUndo();
            hideButtons();
        }
    }).catch((error) => {
        myLog(error);
    });
}

/**
 * Hide unnecessary buttons for non-Google coverages
 */

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']");

    if (CHECKPOINT != null)
    {
        if (nextPlayer === "Google") {

            CHECKPOINT.style.visibility = "";
            ZOOM_IN.style.visibility = "";
            ZOOM_OUT.style.visibility = "";
            myLog("Buttons Unhidden");

        }
        else {

            CHECKPOINT.style.visibility = "hidden";
            ZOOM_IN.style.visibility = "hidden";
            ZOOM_OUT.style.visibility = "hidden";
            myLog("Buttons Hidden");

        }
    }
    else
    {
        setTimeout(hideButtons, 250);
    }
}

/**
 * Check which player to use for the next location
 */

function locationCheck(data) {
    // console.log(data);
    let round;
    if (isBattleRoyale) {
        if (isDuel)
        {
            round = data.rounds[data.currentRoundNumber - 1].panorama;
        }
        else
        {
            round = data.rounds[data.currentRoundNumber - 1];
        }
    }
    else {
        round = data.rounds[data.round - 1];
    }
    global_lat = round.lat;
    global_lng = round.lng;
    global_panoID = round.panoId;
    global_heading = round.heading;
    global_pitch = round.pitch;
    // myLog(global_lat);
    // myLog(global_lng);
    // myLog(krCoordinates);

    nextPlayer = "Google";

    if ( krCoordinates[0] > global_lat && krCoordinates[2] < global_lat && krCoordinates[1] < global_lng && krCoordinates[3] > global_lng)
    {
        nextPlayer = "Kakao";
    }
    else if (yandex_map)
    {
        nextPlayer = "Yandex";
    }
    else
    {
        if (global_panoID) {
            let locInfo = hex2a(global_panoID);
            // myLog(locInfo)
            let mapType = locInfo.substring(0, 5);
            if (mapType === "BDMAP") {
                nextPlayer = "Baidu";
                let coord = locInfo.substring(5);

                if(coord.includes('BDAh'))
                {
                    global_BDID = coord.split('BDAh')[0].replace("panoId","");
                    let tem = coord.split('BDAh')[1];
                    global_BDAh = tem.split('BDBh')[0];
                    global_BDBh = tem.split('BDBh')[1];
                }
                else
                {
                    global_BDID = coord.replace("panoId","");
                }
                //                 myLog(global_BDID)
                //                 myLog(global_BDAh)
                //                 myLog(global_BDBh)
                //                 global_lat = coord.split(",")[0];
                //                 global_lng = coord.split(",")[1];
                // myLog(global_lat);
            }
            else if (mapType === "MLMAP") {
                nextPlayer = "Mapillary";
                mmKey = locInfo.substring(5);
            }
            else if (mapType === "YDMAP" ) {
                nextPlayer = "Yandex";
            }
        }
    }

    // Disable buttons if NM, NMPZ

    if(!isBattleRoyale)
    {
        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();
}


/**
 * setID for canvas
 */

function initializeCanvas() {
    let GAME_CANVAS = "";
    let DUEL_CANVAS = "";
    //myLog("Is duels");
    //myLog(duels);

    if (isBattleRoyale) {
        if (isDuel) {
            GAME_CANVAS = document.querySelector(".game-panorama_panorama__rdhFg");
            DUEL_CANVAS = document.querySelector(".game-panorama_panoramaCanvas__PNKve");
        }
        else
        {
            GAME_CANVAS = document.querySelector(".br-game-layout__panorama-wrapper");
            DUEL_CANVAS = "dummy";
        }
    }
    else {
        GAME_CANVAS = document.querySelector(".game-layout__canvas");
        DUEL_CANVAS = "dummy";
    }
    if (GAME_CANVAS && DUEL_CANVAS)
    {
        myLog("Canvas injected");
        GAME_CANVAS.id = "player";
        if (isDuel) {
            DUEL_CANVAS.id = "default_player";
        }
        injectBaiduScript();
        injectMapillaryPlayer();
        injectKakaoScript().then(() => {
            myLog("Ready to inject Kakao player");
        }).catch((error) => {
            myLog(error);
        });
    }
    else
    {
        setTimeout(initializeCanvas, 250);
    }

}

/**
 * Hide or show players based on where the next location is
 */

function injectCanvas() {
    if (isDuel)
    {
        canvasSwitch();
    }
    else
    {
        Google();
        Baidu();
        Kakao();
        Yandex();
        Mapillary();
    }
    ZoomControls();
}

// for duels (class ID change)

function canvasSwitch()
{
    if (document.querySelector(".compass") !== null && document.querySelector("button[data-qa='undo-move']") !== null)
    {
        let GOOGLE_MAPS_CANVAS = document.querySelector(".game-panorama_panoramaCanvas__PNKve");
        document.querySelector(".ymaps-2-1-79-panorama-screen").style.position = "absolute";
        if (nextPlayer === "Google") {
            document.getElementById("default_player").className = "game-panorama_panoramaCanvas__PNKve";
            document.getElementById("PanoramaMap").className = "inactive";
            document.getElementById("roadview").className = "inactive";
            document.querySelector(".ymaps-2-1-79-panorama-screen").style.visibility = "hidden";
            document.getElementById("Main Button").google = true;
            document.getElementById("switch").nextPlayer = "Google";
            document.getElementById("switch").useGoogle = true;
            document.getElementById("default_player").style.position = "absolute";
            document.querySelector(".compass").style.visibility = "";
            document.querySelector("button[data-qa='undo-move']").visibility = "";
            myLog("Google Duel Canvas loaded");
        }
        else if (nextPlayer === "Baidu")
        {
            document.getElementById("default_player").className = "inactive";
            document.getElementById("PanoramaMap").className = "game-panorama_panorama__rdhFg";
            document.getElementById("roadview").className = "inactive";
            document.getElementById("mly").style.visibility = "hidden";
            document.querySelector(".ymaps-2-1-79-panorama-screen").style.visibility = "hidden";
            document.getElementById("Main Button").google = false;
            document.getElementById("switch").nextPlayer = "Baidu";
            document.getElementById("switch").useGoogle = false;
            document.getElementById("PanoramaMap").style.position = "absolute";
            document.querySelector(".compass").style.visibility = "hidden";
            document.querySelector("button[data-qa='undo-move']").visibility = "hidden";
            myLog("Baidu Duel Canvas loaded");
        }
        else if (nextPlayer === "Kakao")
        {
            document.getElementById("default_player").className = "inactive";
            document.getElementById("PanoramaMap").className = "inactive";
            document.getElementById("roadview").className = "game-panorama_panorama__rdhFg";
            document.getElementById("mly").style.visibility = "hidden";
            document.querySelector(".ymaps-2-1-79-panorama-screen").style.visibility = "hidden";
            document.getElementById("Main Button").google = false;
            document.getElementById("switch").nextPlayer = "Kakao";
            document.getElementById("switch").useGoogle = false;
            document.getElementById("roadview").style.position = "absolute";
            document.querySelector(".compass").style.visibility = "";
            document.querySelector("button[data-qa='undo-move']").visibility = "";
            myLog("Kakao Duel Canvas loaded");
        }
        else if (nextPlayer === "Yandex")
        {
            document.getElementById("default_player").className = "inactive";
            document.getElementById("PanoramaMap").className = "inactive";
            document.getElementById("roadview").className = "inactive";
            document.getElementById("mly").style.visibility = "hidden";
            document.querySelector(".ymaps-2-1-79-panorama-screen").style.visibility = "";
            document.getElementById("Main Button").google = false;
            document.getElementById("switch").nextPlayer = "Yandex";
            document.getElementById("switch").useGoogle = false;
            document.querySelector(".ymaps-2-1-79-panorama-screen").style.position = "absolute";
            document.querySelector(".compass").style.visibility = "";
            document.querySelector("button[data-qa='undo-move']").visibility = "";
            myLog("Yandex Duel Canvas loaded");
        }
        else if (nextPlayer === "Mapillary")
        {
            document.getElementById("default_player").className = "inactive";
            document.getElementById("PanoramaMap").className = "inactive";
            document.getElementById("roadview").className = "inactive";
            document.getElementById("mly").style.visibility = "";
            document.querySelector(".ymaps-2-1-79-panorama-screen").style.visibility = "hidden";
            document.getElementById("Main Button").google = false;
            document.getElementById("switch").nextPlayer = "Mapillary";
            document.getElementById("switch").useGoogle = false;
            document.getElementById("mly").style.position = "absolute";
            document.querySelector(".compass").style.visibility = "hidden";
            document.querySelector("button[data-qa='undo-move']").visibility = "";
            myLog("Mapillary Duel Canvas loaded");
        }
    }
    else
    {
        setTimeout(canvasSwitch, 250);
    }
}

// for Battle Royale and classic (change visibility)

function Google() {
    let GOOGLE_MAPS_CANVAS = ""
    if (isBattleRoyale) {
        GOOGLE_MAPS_CANVAS = document.querySelector(".br-game-layout__panorama-canvas");
    }
    else {
        GOOGLE_MAPS_CANVAS = document.querySelector(".game-layout__panorama-canvas");
    }
    if (nextPlayer === "Google") {
        GOOGLE_MAPS_CANVAS.style.visibility = "";
        document.getElementById("Main Button").google = true;
        document.getElementById("switch").nextPlayer = "Google";
        document.getElementById("switch").useGoogle = true;
        myLog("Google Canvas loaded");
    }
    else {
        GOOGLE_MAPS_CANVAS.style.visibility = "hidden";
        document.getElementById("Main Button").google = false;
        myLog("Google Canvas hidden");
    }

}

function Baidu() {
    let BAIDU_MAPS_CANVAS = document.getElementById("PanoramaMap");
    // myLog("Baidu canvas");
    if (BAIDU_MAPS_CANVAS !== null && document.querySelector(".compass") !== null && document.querySelector("button[data-qa='undo-move']") !== null)
    {
        BAIDU_MAPS_CANVAS.style.position = "absolute";
        if (nextPlayer === "Baidu") {
            BAIDU_MAPS_CANVAS.style.visibility = "";
            document.getElementById("switch").nextPlayer = "Baidu";
            document.getElementById("switch").useGoogle = false;
            document.querySelector(".compass").style.visibility = "hidden";
            document.querySelector("button[data-qa='undo-move']").style.visibility = "hidden";
            myLog("Baidu Canvas loaded");
        }
        else {
            document.querySelector(".compass").style.visibility = "";
            document.querySelector("button[data-qa='undo-move']").style.visibility = "";
            BAIDU_MAPS_CANVAS.style.visibility = "hidden";
            myLog("Baidu Canvas hidden");
        }
    }
    else
    {
        setTimeout(Baidu, 250);
    }

}

function Kakao() {
    let KAKAO_MAPS_CANVAS = document.getElementById("roadview");
    // myLog("Kakao canvas");
    document.getElementById("roadview").style.position = "absolute";
    if (KAKAO_MAPS_CANVAS != null)
    {
        if (nextPlayer === "Kakao") {
            KAKAO_MAPS_CANVAS.style.visibility = "";
            document.getElementById("switch").nextPlayer = "Kakao";
            document.getElementById("switch").useGoogle = false;
            myLog("Kakao Canvas loaded");
        }
        else {
            KAKAO_MAPS_CANVAS.style.visibility = "hidden";
            myLog("Kakao Canvas hidden");
        }
    }
    else
    {
        setTimeout(Kakao, 250);
    }

}

function Yandex() {
    let YANDEX_MAPS_CANVAS = document.querySelector(".ymaps-2-1-79-panorama-screen");
    if (YANDEX_MAPS_CANVAS != null)
    {
        // myLog("Yandex canvas");
        document.querySelector(".ymaps-2-1-79-panorama-screen").style.position = "absolute";
        // myLog("Yandex canvas");
        /*   myLog(YANDEX_MAPS_CANVAS); */
        if (nextPlayer === "Yandex") {
            YANDEX_MAPS_CANVAS.style.visibility = "";
            document.getElementById("switch").nextPlayer = "Yandex";
            document.getElementById("switch").useGoogle = false;
            myLog("Yandex Canvas loaded");
        }
        else {
            YANDEX_MAPS_CANVAS.style.visibility = "hidden";
            myLog("Yandex Canvas hidden");
        }
    }
    else
    {
        setTimeout(Yandex, 250);
    }

}

function Mapillary()
{

    let MAPILLARY_MAPS_CANVAS = document.getElementById("mly");
    if (MAPILLARY_MAPS_CANVAS != null)
    {
        // myLog("Mapillary canvas");
        MAPILLARY_MAPS_CANVAS.style.position = "absolute";
        if (nextPlayer === "Mapillary") {
            MAPILLARY_MAPS_CANVAS.style.visibility = "";
            document.getElementById("switch").nextPlayer = "Mapillary";
            document.getElementById("switch").useGoogle = false;
            myLog("Mapillary Canvas loaded");
        }
        else {
            MAPILLARY_MAPS_CANVAS.style.visibility = "hidden";
            myLog("Mapillary Canvas hidden");
        }
    }
    else
    {
        setTimeout(Mapillary, 250);
    }

}

/**
 * Adjust button placement
 */

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);
}

/**
 * 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 = YandexPlayer.getDirection()[0] * -1;
            COMPASS.setAttribute("style", `transform: rotate(${direction}deg);`);
        }
    }
    else {
        let direction = YandexPlayer.getDirection()[0] * -1;
        COMPASS.setAttribute("style", `transform: rotate(${direction}deg);`);
    }
}

/**
 * Open next location in streetview player given next player and next coordinate
 */

function goToLocation() {
    myLog("Going to location");
    if (nextPlayer === "Yandex") {
        let options = {};
        YandexPlayer.moveTo([global_lat, global_lng], options);
        YandexPlayer.setDirection([0, 16]);
        YandexPlayer.setSpan([10, 67]);
    }
    else if (nextPlayer === "Baidu") {
        if (document.getElementById("PanoramaMap") !== null)
        {
            let urlStr2 = "https://map.baidu.com/?panotype=street&pid=" + global_BDID + "&panoid=" + global_BDID + "&from=api";
            let urlStr = "https://map.baidu.com/@" + global_BDAh + "," + global_BDBh + "#panoid=" + global_BDID + "&panotype=street&l=12&tn=B_NORMAL_MAP&sc=0&newmap=1&shareurl=1&pid=" + global_BDID;
            // myLog(urlStr)
            if (global_BDAh != null)
            {
                document.getElementById("PanoramaMap").src = urlStr;
            }
            else
            {
                document.getElementById("PanoramaMap").src = urlStr2;
            }
        }
        else
        {
            setTimeout(goToLocation, 250);
        }
        //         let a = new BMap.Point(global_lng, global_lat);
        //         BaiduPlayer.setPov({ heading: -40, pitch: 6 });
        //         BaiduPlayer.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) {
            KakaoPlayer.setPanoId(panoId, position);
            KakaoPlayer.setViewpoint({ pan: global_heading, tilt: global_pitch, zoom: -3 })
        });
    }
    else if (nextPlayer === "Mapillary") {
        MapillaryPlayer.moveTo(mmKey).then(
            image => { //myLog(image);
            },
            error => { myLog(error); });
    }
    else if (nextPlayer === "Google") {
        handleMapillary({lat: global_lat, lng: global_lng}, {meters: 500, limit: 500});
    }
    document.getElementById("switch").lat = global_lat;
    document.getElementById("switch").lng = global_lng;
}

/**
 * Handle undo using the location history of the current round
 */

function goToUndoMove(data) {
    /*   myLog(global_lat);
      myLog(global_lng); */
    let options = {};
    let prevStep = null;
    if (locHistory.length === 1) {
        prevStep = locHistory[0];
    }
    else {
        prevStep = locHistory.pop();
    }
    // myLog(prevStep);
    // myLog(locHistory)
    if (nextPlayer === "Yandex") {
        defaultPanoIdChange = false;
        YandexPlayer.moveTo([prevStep[0], prevStep[1]], options);
        YandexPlayer.setDirection([prevStep[2], prevStep[3]]);
        YandexPlayer.setSpan([10, 67]);
        document.getElementById("switch").lat = prevStep[0];
        document.getElementById("switch").lng = prevStep[1];
    }
    else if (nextPlayer === "Kakao") {
        let btn = document.querySelector("button[data-qa='undo-move']");
        btn.disabled = false;
        btn.classList.remove('styles_disabled__W_k45');
        defaultPanoIdChange = false;
        let position = new kakao.maps.LatLng(prevStep[0], prevStep[1]);
        KakaoPlayer.setPanoId(prevStep[2], position);
        document.getElementById("switch").lat = prevStep[0];
        document.getElementById("switch").lng = prevStep[1];
        document.getElementById("switch").useGoogle = false;
        document.getElementById("Main Button").google = false;
        // myLog("Undo 1 step");
        // myLog(locHistory);
    }
    else if (nextPlayer === "Baidu") {
        // myLog(prevStep[1]);
        //         let position = new BMap.Point(prevStep[1], prevStep[0]);
        //         let pov = { heading: prevStep[2], pitch: prevStep[3] };
        //         BaiduPlayer.setPosition(position);
        //         BaiduPlayer.setPov(pov);
        //         document.getElementById("switch").lat = prevStep[1];
        //         document.getElementById("switch").lng = prevStep[0];
    }
    else if (nextPlayer === "Mapillary" ) {
        // myLog(prevStep[1]);

        MapillaryPlayer.moveTo(prevStep[2]).then(
            image => {
                //myLog(image);
                document.getElementById("switch").lat = prevStep[1];
                document.getElementById("switch").lng = prevStep[0];
            },
            error => { myLog(error); });
    }

}

function BYKTeleport()
{
    let teleportButtonBYK = document.getElementById("Main Button");
    if (teleportButtonBYK)
    {
        teleportButtonBYK.addEventListener("click", () => {
            if (!teleportButtonBYK.google)
            {
                // myLog("non-Google Teleport");
                let prevStep = null;
                if (locHistory.length === 1) {
                    prevStep = locHistory[0];
                }
                else {
                    prevStep = locHistory[locHistory.length - 1];
                }
                // myLog(prevStep);
                let options = {};
                let place, position, pID;
                if (nextPlayer === "Yandex") {
                    place = FindPointAtDistanceFrom(prevStep[0], prevStep[1], DegreesToRadians(prevStep[2]), teleportButtonBYK.distance * 0.001);
                    YandexPlayer.setDirection([prevStep[2], prevStep[3]]);
                    YandexPlayer.moveTo([place.lat, place.lng], options);
                    YandexPlayer.setSpan([10, 67]);
                    //                     locHistory.push([place.lat, place.lng, prevStep[2], prevStep[3]]);
                }
                else if (nextPlayer === "Kakao") {
                    //                     place = FindPointAtDistanceFrom(prevStep[0], prevStep[1], DegreesToRadians(prevStep[3]), teleportButtonBYK.distance * 0.001);
                    //                     position = new kakao.maps.LatLng(place.lat, place.lng);
                    //                     pID = KakaoPlayer.getViewpointWithPanoId();
                    //                     KakaoPlayer.setPanoId(pID.panoId, position);
                    //                     locHistory.push([place.lat, place.lng, pID.panoId, prevStep[3]]);
                    var roadviewClient = new kakao.maps.RoadviewClient();
                    place = FindPointAtDistanceFrom(prevStep[0], prevStep[1], DegreesToRadians(prevStep[3]), teleportButtonBYK.distance * 0.001);
                    position = new kakao.maps.LatLng(place.lat, place.lng);
                    roadviewClient.getNearestPanoId(position, 500, function (panoId) {
                        KakaoPlayer.setPanoId(panoId, position);
                        // myLog("Teleport 1 step");
                        // myLog(locHistory);
                        //                         locHistory.push([place.lat, place.lng, panoId, prevStep[3]]);
                    });
                }
                else if (nextPlayer === "Baidu") {
                    //                     place = FindPointAtDistanceFrom(prevStep[0], prevStep[1], DegreesToRadians(prevStep[2]), teleportButtonBYK.distance * 0.001);
                    //                     position = new BMap.Point(place.lng, place.lat);
                    //                     let pov = { heading: prevStep[2], pitch: prevStep[3] };
                    //                     BaiduPlayer.setPosition(position);
                    //                     BaiduPlayer.setPov(pov);

                    // locHistory.push([place.lat, place.lng, prevStep[2], prevStep[3]]);
                }
                else if (nextPlayer === "Mapillary" || nextPlayer === "Google") {
                    place = FindPointAtDistanceFrom(prevStep[0], prevStep[1], DegreesToRadians(prevStep[2]), teleportButtonBYK.distance * 0.001);
                    handleMapillary(place, {meters: 500, limit: 500});
                    // locHistory.push([place.lat, place.lng, prevStep[2], prevStep[3]]);
                }
                document.getElementById("switch").lat = place.lat;
                document.getElementById("switch").lng = place.lng;
                if (teleportButtonBYK.distance > 150)
                {
                    teleportButtonBYK.distance = 100;
                    teleportButtonBYK.innerHTML = "Teleport " + teleportButtonBYK.distance + " m";
                }
            }
        });
    }
    else
    {
    }
}

function SyncListener()
{
    let googleKakaoButton = document.getElementById("switch");
    googleKakaoButton.addEventListener("click", () => {
        if (googleKakaoButton.useGoogle == false) {
            // googleKakaoButton.useGoogle = true;
            if (googleKakaoButton.nextPlayer === "Yandex") {
                let options = {};
                YandexPlayer.moveTo([googleKakaoButton.lat, googleKakaoButton.lng], options);
                YandexPlayer.setDirection([document.getElementById("switch").heading, 0]);

                // document.getElementById("switch").nextPlayer = "Yandex";
            }
            else if (googleKakaoButton.nextPlayer === "Kakao") {
                let roadviewClient = new kakao.maps.RoadviewClient();
                // myLog(googleKakaoButton.lat);
                let position = new kakao.maps.LatLng(googleKakaoButton.lat, googleKakaoButton.lng);
                roadviewClient.getNearestPanoId(position, 500, function (panoId) {
                    KakaoPlayer.setPanoId(panoId, position);
                });
                KakaoPlayer.setViewpoint({
                    pan: document.getElementById("switch").heading,
                    tilt: 0,
                    zoom: 0
                });
                // document.getElementById("switch").nextPlayer = "Kakao";
            }
            else if (googleKakaoButton.nextPlayer === "Mapillary" || googleKakaoButton.nextPlayer === "Google") {
                // document.getElementById("switch").nextPlayer = "Kakao";
                handleMapillary({lat: googleKakaoButton.lat, lng: googleKakaoButton.lng}, {meters: 100, limit: 100});
            }
        }
    });

}

/**
 * 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}`;
        }
        else if (PATHNAME.startsWith("/duels/") || PATHNAME.startsWith("/team-duels/")) {
            URL = `https://game-server.geoguessr.com/api/duels/${token}`;
        }
        if (isBattleRoyale) {
            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/", "");
    }
    else if (PATHNAME.startsWith("/duels/")) {
        return PATHNAME.replace("/duels/", "");
    }
    else if (PATHNAME.startsWith("/team-duels/")) {
        return PATHNAME.replace("/team-duels/", "");
    }
}

/**
 * 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 === "") {
                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) => {
        YandexPlayer = player;
        YandexPlayer.events.add("directionchange", (e) => {
            updateCompass();
            let pov = YandexPlayer.getDirection();
            if (locHistory.length > 0 && nextPlayer == "Yandex") {
                document.getElementById("switch").heading = pov[0];
                locHistory[locHistory.length - 1][2] = pov[0];
                locHistory[locHistory.length - 1][3] = pov[1];
            }
        });
        YandexPlayer.events.add("panoramachange", (e) => {
            if (defaultPanoIdChange) {
                let num = YandexPlayer.getPanorama().getPosition();
                let pov = YandexPlayer.getDirection();
                // myLog(num);
                // myLog(pov);
                if (nextPlayer == "Yandex")
                {
                    locHistory.push([num[0], num[1], pov[0], pov[1]]);
                    document.getElementById("switch").lat = num[0];
                    document.getElementById("switch").lng = num[1];
                }
                let btn = document.querySelector("button[data-qa='undo-move']");
                if (locHistory.length > 1) {
                    btn.disabled = false;
                    btn.classList.remove('styles_disabled__W_k45');
                }
                // myLog(locHistory);
            }
            defaultPanoIdChange = true;

        });
        myLog("Yandex Player injected");
    });

}


/**
 * Injects Baidu script
 */

function reportWindowSize() {
    let iframeC = document.getElementById("PanoramaMap");
    if (iframeC)
    {
        iframeC.style.top = '-60px';
        iframeC.style.height = (window.innerHeight + 200) + 'px';
        iframeC.style.right = '-55px';
        iframeC.style.width = (window.innerWidth + 55) + 'px';
    }
}

window.onresize = reportWindowSize;

function injectBaiduScript() {
    myLog("Iframe")
    const iframe = document.createElement('iframe');

    // iframe.src = "https://map.baidu.com/"
    iframe.frameBorder = 0;
    iframe.style.position = "absolute";
    iframe.id = "PanoramaMap";
    if (!isFirefox)
    {
        iframe.style.top = '-60px';
        iframe.style.height = (window.innerHeight + 200) + 'px';
    }
    else
    {
        iframe.style.top = '-60px';
        iframe.style.height = (window.innerHeight + 219) + 'px';
    }

    if (!isFirefox)
    {
        iframe.style.right = '-55px';
        iframe.style.width = (window.innerWidth + 55) + 'px';
    }
    else
    {
        iframe.style.right = '-15px';
        iframe.style.width = (window.innerWidth + 15) + 'px';
    }



    if (isBattleRoyale) {
        if (isDuel)
        {
            iframe.className = "inactive"
        }
        else
        {
            iframe.className = "br-game-layout__panorama"
        }
    }
    else {
        iframe.className = "game-layout__panorama"
    }
    var div = document.getElementById("player");
    div.style.overflow = "hidden";
    div.appendChild(iframe);
}

/**
 * Injects Kakao script
 */

function injectKakaoScript() {
    return new Promise((resolve, reject) => {
        if (!KAKAO_INJECTED) {
            if (KAKAO_API_KEY === "") {
                myLog("No Kakao Key")
            }
            else {

                let canvas = document.createElement("kmap");
                if (isBattleRoyale) {
                    if (isDuel)
                    {
                        canvas.innerHTML = `
                 <div id="roadview" class="inactive" style="zIndex: 99999,position: "absolute", top: 0, left: 0, width: '100%', height: '100%',"> </div>
            `;
                    }
                    else
                    {
                        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');
                        KakaoPlayer = new kakao.maps.Roadview(roadviewContainer);
                        var panoId = 1023434522;
                        KakaoPlayer.setPanoId(panoId, position);
                        KAKAO_INJECTED = true;
                        // Remove the compass from Kakao
                        kakao.maps.event.addListener(KakaoPlayer, 'init', () => {
                            const compassContainer = roadviewContainer.querySelector('div[id*="_box_util_"]');
                            if (compassContainer) compassContainer.style.display = 'none';
                        });
                        kakao.maps.event.addListener(KakaoPlayer, 'panoid_changed', function() {
                            if (defaultPanoIdChange && KakaoPlayer) {
                                let latlng = KakaoPlayer.getPosition();
                                let lat = latlng.getLat();
                                let lng = latlng.getLng();
                                let pID = KakaoPlayer.getViewpointWithPanoId();
                                if (nextPlayer == "Kakao" && lat != 33.45047613915499)
                                {
                                    // myLog("push");
                                    locHistory.push([lat, lng, pID.panoId, pID.pan]);
                                    document.getElementById("switch").lat = lat;
                                    document.getElementById("switch").lng = lng;
                                    document.getElementById("switch").heading = pID.pan;
                                }
                                let btn = document.querySelector("button[data-qa='undo-move']");
                                if (locHistory.length > 1 && (btn != null)) {
                                    btn.disabled = false;
                                    btn.classList.remove('styles_disabled__W_k45');
                                }
                                // myLog(locHistory);
                            }
                            defaultPanoIdChange = true;
                        });
                        kakao.maps.event.addListener(KakaoPlayer, 'viewpoint_changed', function() {
                            // myLog("pov_listener attached");
                            let pID = KakaoPlayer.getViewpointWithPanoId();
                            if (locHistory.length > 0 && nextPlayer == "Kakao") {
                                document.getElementById("switch").heading = pID.pan;
                                locHistory[locHistory.length - 1][3] = pID.pan;
                            }
                            if (GooglePlayer) {
                                const { heading, pitch } = GooglePlayer.getPov()
                                if (!almostEqual(pID.pan, heading) || !almostEqual(pID.tilt, pitch)) {
                                    // Updating the google street view POV will update the compass
                                    GooglePlayer.setPov({ heading: pID.pan, pitch: pID.tilt })
                                }
                            }
                            // myLog(locHistory);
                        })
                        myHighlight("Kakao API Loaded");
                        resolve();
                    });
                };

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



function injectMapillaryPlayer() {
    return new Promise((resolve, reject) => {
        if (!MAPILLARY_INJECTED) {
            if (MAPILLARY_API_KEY === "") {
                let canvas = document.getElementById("player");
                myLog("No Mapillary Key")
            }
            else {
                const SCRIPT = document.createElement("script");
                SCRIPT.type = "text/javascript";
                SCRIPT.async = true;
                SCRIPT.src = `https://unpkg.com/[email protected]/dist/mapillary.js`;
                document.body.appendChild(SCRIPT);
                document.querySelector('head').innerHTML += '<link href="https://unpkg.com/[email protected]/dist/mapillary.css" rel="stylesheet"/>';
                let canvas = document.createElement("mmap");
                if (isBattleRoyale) {
                    if (isDuel)
                    {

                        canvas.innerHTML = `<div id="mly" class="inactive" style="zIndex: 99999, position: 'absolute', top: 0, left: 0, width: '100%', height: '100%'"></div>`;
                    }
                    else
                    {
                        canvas.innerHTML = `<div id="mly" class="br-game-layout__panorama" style="zIndex: 99999, position: 'absolute', top: 0, left: 0, width: '100%', height: '100%'"></div>`;
                    }
                }
                else {
                    canvas.innerHTML = `<div id="mly" 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("Mapillary API Loaded");
                    // resolve(BMap);
                    var {Viewer} = mapillary;

                    MapillaryPlayer = new Viewer({
                        accessToken: MAPILLARY_API_KEY,
                        container: 'mly', // the ID of our container defined in the HTML body
                    });

                    MapillaryPlayer.on('image', async (event) => {
                        // cnt = cnt + 1;
                        // myLog(cnt);
                        let image = event.image;
                        let pos = image.originalLngLat;
                        let cond = true;
                        for (const element of locHistory) {
                            if (element[2] == image.id)
                            {
                                cond = false;
                            }
                        }
                        if (cond)
                        {
                            document.getElementById("switch").lat = pos.lat;
                            document.getElementById("switch").lng = pos.lng;
                            document.getElementById("switch").heading = image.compassAngle;
                            // myLog(pos);
                            locHistory.push([pos.lat, pos.lng, image.id, image.compassAngle]);
                        }
                        let btn = document.querySelector("button[data-qa='undo-move']");
                        if (btn !== null && locHistory.length > 1)
                        {
                            btn.disabled = false;
                            btn.classList.remove('styles_disabled__W_k45');
                        }
                    });

                    MAPILLARY_INJECTED = true;
                    resolve();
                })


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


function handleMapillary(latlng, options)
{
    myLog("handleMapillary")
    handleMapillaryHelper(latlng, options).then((data) => {
        //myLog(data.data)
        let idToSet = 0;
        let curDist = 100000000;
        for (const element of data.data) {
            // myLog(element)
            if (element.hasOwnProperty("computed_geometry"))
            {
                try {
                    let rCord = element.computed_geometry["coordinates"];
                    let dist = distance(latlng.lat,latlng.lng,rCord[1],rCord[0])
                    if (dist < curDist)
                    {
                        idToSet = element.id;
                        curDist = dist
                    }
                } catch (e) {
                    myLog("Error")
                }
            }
        }
        if (idToSet !== 0)
        {
            MapillaryPlayer.moveTo(idToSet).then(
                image => { //myLog(image);
                },
                error => { myLog(error); });
        }}).catch((error) => {
        myLog(error);
    });
}

function handleMapillaryHelper(latlng, options)
{
    return new Promise((resolve, reject) => {
        // myLog("1")
        let bbox = getBBox(latlng, options.meters);
        let URL = "https://graph.mapillary.com/images?access_token={0}&fields=id,computed_geometry&bbox={1}&limit={2}".replace('{0}', MAPILLARY_API_KEY).replace('{1}', bbox).replace('{2}', options.limit)
        // myLog(URL)
        fetch(URL)
            .then((response) => {resolve(response.json())})
            .catch((error) => {myLog(error);});
    });
}

function moveFrom(coords, angle, distance){
    const R_EARTH = 6378.137;
    const M = (1 / ((2 * Math.PI / 360) * R_EARTH)) / 1000;
    let radianAngle = -angle * Math.PI / 180;
    let x = 0 + (distance * Math.cos(radianAngle));
    let y = 0 + (distance * Math.sin(radianAngle));

    let newLat = coords.lat + (y * M);
    let newLng = coords.lng + (x * M) / Math.cos(coords.lat * (Math.PI / 180));
    return { lat: newLat, lng: newLng };
}

function getBBox(coordinates, meters){
    let SW = moveFrom(coordinates, 135, meters);
    let NE = moveFrom(coordinates, 315, meters);
    return `${SW.lng},${SW.lat},${NE.lng},${NE.lat}`;
}


function distance(lat1, lon1, lat2, lon2) {
    var p = 0.017453292519943295;    // Math.PI / 180
    var c = Math.cos;
    var a = 0.5 - c((lat2 - lat1) * p)/2 +
        c(lat1 * p) * c(lat2 * p) *
        (1 - c((lon2 - lon1) * p))/2;

    return 1000 * 12742 * Math.asin(Math.sqrt(a)); // 2 * R; R = 6371 km
}