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

Fra 26.01.2022. Se den seneste versjonen.

  1. // ==UserScript==
  2. // @name Geoguessr Unity Script
  3. // @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
  4. // @version 4.5.0
  5. // @include https://www.geoguessr.com/*
  6. // @run-at document-start
  7. // @license MIT
  8. // @namespace https://greatest.deepsurf.us/users/838374
  9. // ==/UserScript==
  10.  
  11. /**
  12. * Custom your minimap here!
  13. */
  14.  
  15. /**
  16. * 1: replace "roadmap" in the customMode field with any of the options below:
  17. * "roadmap" displays the default road map view. This is the default map type.
  18. * "satellite" displays Google Earth satellite images.
  19. * "hybrid" displays a mixture of normal and satellite views.
  20. * "terrain" displays a physical map based on terrain information.
  21. */
  22.  
  23. let customMode = "terrain";
  24.  
  25. /**
  26. * 2: Go to https://mapstyle.withgoogle.com/ first click "No thanks, take me to the old style wizard"
  27. * then click "MORE OPTIONS" to hide or reveal certain features.
  28. * When you are done, click "FINISH", then "COPY JSON", and replace my settings in custom with your settings below.
  29. */
  30.  
  31. let custom =
  32.  
  33. [
  34. {
  35. "featureType": "administrative",
  36. "stylers": [
  37. {
  38. "visibility": "off"
  39. }
  40. ]
  41. }
  42. ]
  43.  
  44. /**
  45. * End of Minimap customization instruction section
  46. */
  47.  
  48. // API Keys
  49.  
  50. var YANDEX_API_KEY = "b704b5a9-3d67-4d19-b702-ec7807cecfc6";
  51. var KAKAO_API_KEY = "cbacbe41e3a223d794f321de4f3e247b";
  52. const MAPS_API_URL = "https://maps.googleapis.com/maps/api/js"; // removed "?" from the link
  53. var MAPILLARY_API_KEY_LIST =
  54. ["MLY|6723031704435203|5afd537469b114cf814881137ad74b7c",
  55. "MLY|6691659414239148|b45e7e82cde126044cbc2cf5d4a7c9b1",
  56. "MLY|5074369465929308|f7ad2802cbaf26c63f88046a292df68b",
  57. "MLY|7451643761528219|6477f2db0e3928b51e45ec9311983936",
  58. "MLY|4855256237866198|6d0464771831c8a4bf2be095e1e1aabc",
  59. "MLY|4772941976102161|8458d4f08d2e1970cdfe0a4e242c04ff",
  60. "MLY|4492067214235489|94c44703942362ad6f6b70b5d32c3a45",
  61. "MLY|4618251611628426|0cef71d6ec8b997a5ec06ecdeabf11ec",
  62. "MLY|4096846270415982|fa2ce29641503e6ef665f17459633570",
  63. "MLY|4231415756962414|fe353880fd246e8a4a6ae32152f7dbb0",]
  64.  
  65. var MAPILLARY_API_KEY = MAPILLARY_API_KEY_LIST[Math.floor(Math.random() * MAPILLARY_API_KEY_LIST.length)];
  66.  
  67. myLog("Geoguessr Unity Script V4.5.0");
  68. // myLog(MAPILLARY_API_KEY);
  69.  
  70. // Store each player instance
  71.  
  72. let YandexPlayer, KakaoPlayer, GooglePlayer, MapillaryPlayer;
  73. let YANDEX_INJECTED = false;
  74. let BAIDU_INJECTED = false;
  75. let KAKAO_INJECTED = false;
  76. let MAPILLARY_INJECTED = false;
  77.  
  78. // Game mode detection
  79.  
  80. let isBattleRoyale = false;
  81. let isDuel = false;
  82.  
  83. // Player detection and coordinate conversion
  84.  
  85. let nextPlayer = "Google";
  86. let global_lat = 0;
  87. let global_lng = 0;
  88. let global_panoID = null;
  89. let global_BDID, global_BDAh, global_BDBh;
  90. let global_heading = null;
  91. let global_pitch = null;
  92.  
  93. let krCoordinates = [38.75292321084364, 124.2804539232574, 33.18509676203202, 129.597381999198]
  94. let global_radi = 100
  95.  
  96. // Callback variables
  97.  
  98. let eventListenerAttached = false;
  99. let povListenerAttached = false;
  100. let playerLoaded = false;
  101. let teleportLoaded = false;
  102. let syncLoaded = false;
  103.  
  104. // Minimize Yandex API use
  105.  
  106. let yandex_map = false;
  107.  
  108. // Mapillary Image Key
  109.  
  110. let mmKey = 0;
  111.  
  112. // Handle Yandex compass
  113.  
  114. let COMPASS = null;
  115.  
  116. // Handle undo
  117.  
  118. let locHistory = [];
  119. let defaultPanoIdChange = true;
  120.  
  121. // Round check
  122.  
  123. let ROUND = 0;
  124. let CURRENT_ROUND_DATA = null;
  125.  
  126. let switch_call = true;
  127. let one_reset = false;
  128. // let cnt = 0;
  129.  
  130. let cn_tips = false;
  131. var isFirefox = typeof InstallTrigger !== 'undefined';
  132.  
  133. let linksList = []
  134. let fire1 = true;
  135.  
  136. let CNBorder = false;
  137.  
  138. // let NEW_ROUND_LOADED = false;
  139.  
  140. /**
  141. * Helper Functions
  142. */
  143.  
  144. // Pretty print
  145.  
  146. function myLog(...args) {
  147. console.log(...args);
  148. }
  149. function myHighlight(...args) {
  150. console.log(`%c${[...args]}`, "color: dodgerblue; font-size: 24px;");
  151. }
  152.  
  153. // Hex to number conversion for Baidu coordinate conversion
  154.  
  155. function hex2a(hexx) {
  156. var hex = hexx.toString();
  157. var str = '';
  158. for (var i = 0; i < hex.length; i += 2)
  159. str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
  160. return str;
  161. }
  162.  
  163. // Coordinate computation given heading, distance and current coordinates for teleport
  164.  
  165. function FindPointAtDistanceFrom(lat, lng, initialBearingRadians, distanceKilometres) {
  166. const radiusEarthKilometres = 6371.01;
  167. var distRatio = distanceKilometres / radiusEarthKilometres;
  168. var distRatioSine = Math.sin(distRatio);
  169. var distRatioCosine = Math.cos(distRatio);
  170.  
  171. var startLatRad = DegreesToRadians(lat);
  172. var startLonRad = DegreesToRadians(lng);
  173.  
  174. var startLatCos = Math.cos(startLatRad);
  175. var startLatSin = Math.sin(startLatRad);
  176.  
  177. var endLatRads = Math.asin((startLatSin * distRatioCosine) + (startLatCos * distRatioSine * Math.cos(initialBearingRadians)));
  178.  
  179. var endLonRads = startLonRad
  180. + Math.atan2(
  181. Math.sin(initialBearingRadians) * distRatioSine * startLatCos,
  182. distRatioCosine - startLatSin * Math.sin(endLatRads));
  183.  
  184. return { lat: RadiansToDegrees(endLatRads), lng: RadiansToDegrees(endLonRads) };
  185. }
  186.  
  187. function DegreesToRadians(degrees) {
  188. const degToRadFactor = Math.PI / 180;
  189. return degrees * degToRadFactor;
  190. }
  191.  
  192. function RadiansToDegrees(radians) {
  193. const radToDegFactor = 180 / Math.PI;
  194. return radians * radToDegFactor;
  195. }
  196.  
  197. // Check if two floating point numbers are really really really really close to each other (to 10 decimal points)
  198. function almostEqual (a, b) {
  199. return a.toFixed(10) === b.toFixed(10)
  200. }
  201.  
  202. function almostEqual2 (a, b) {
  203. return a.toFixed(3) === b.toFixed(3)
  204. }
  205.  
  206. // Script injection, extracted from extenssr:
  207. // https://gitlab.com/nonreviad/extenssr/-/blob/main/src/injected_scripts/maps_api_injecter.ts
  208.  
  209. function overrideOnLoad(googleScript, observer, overrider) {
  210. const oldOnload = googleScript.onload
  211. googleScript.onload = (event) => {
  212. const google = unsafeWindow.google
  213. if (google) {
  214. observer.disconnect()
  215. overrider(google)
  216. }
  217. if (oldOnload) {
  218. oldOnload.call(googleScript, event)
  219. }
  220. }
  221. }
  222.  
  223. function grabGoogleScript(mutations) {
  224. for (const mutation of mutations) {
  225. for (const newNode of mutation.addedNodes) {
  226. const asScript = newNode
  227. if (asScript && asScript.src && asScript.src.startsWith('https://maps.googleapis.com/')) {
  228. return asScript
  229. }
  230. }
  231. }
  232. return null
  233. }
  234.  
  235. function injecter(overrider) {
  236. if (document.documentElement)
  237. {
  238. injecterCallback(overrider);
  239. }
  240. else
  241. {
  242. alert("Script didn't load, refresh to try loading the script");
  243. }
  244. // else
  245. // {
  246. // setTimeout(injecter(overrider), 2000);
  247. // }
  248. }
  249.  
  250. function injecterCallback(overrider)
  251. {
  252. new MutationObserver((mutations, observer) => {
  253. const googleScript = grabGoogleScript(mutations)
  254. if (googleScript) {
  255. overrideOnLoad(googleScript, observer, overrider)
  256. }
  257. }).observe(document.documentElement, { childList: true, subtree: true })
  258. }
  259.  
  260. /**
  261. * Creates teleportation and Kakao switch button
  262. *
  263. * @returns Promise
  264. */
  265.  
  266.  
  267.  
  268.  
  269.  
  270. function ArisKakao() {
  271. // let radi = 100;
  272. const google = unsafeWindow.google;
  273.  
  274. // console.log(google);
  275. let curPosition;
  276. let kakao_enabled = true;
  277.  
  278. // Helper Functions
  279.  
  280. function FindPointAtDistanceFrom(startPoint, initialBearingRadians, distanceKilometres) {
  281. const radiusEarthKilometres = 6371.01;
  282. var distRatio = distanceKilometres / radiusEarthKilometres;
  283. var distRatioSine = Math.sin(distRatio);
  284. var distRatioCosine = Math.cos(distRatio);
  285.  
  286. var startLatRad = DegreesToRadians(startPoint.lat);
  287. var startLonRad = DegreesToRadians(startPoint.lng);
  288.  
  289. var startLatCos = Math.cos(startLatRad);
  290. var startLatSin = Math.sin(startLatRad);
  291.  
  292. var endLatRads = Math.asin((startLatSin * distRatioCosine) + (startLatCos * distRatioSine * Math.cos(initialBearingRadians)));
  293.  
  294. var endLonRads = startLonRad
  295. + Math.atan2(
  296. Math.sin(initialBearingRadians) * distRatioSine * startLatCos,
  297. distRatioCosine - startLatSin * Math.sin(endLatRads));
  298.  
  299. return { lat: RadiansToDegrees(endLatRads), lng: RadiansToDegrees(endLonRads) };
  300. }
  301.  
  302. function svCheck(data, status) {
  303. if (status === 'OK') {
  304. // console.log("OK for " + data.location.latLng + " at ID " + data.location.pano);
  305. let l = data.location.latLng.toString().split(',');
  306. let lat = l[0].replaceAll('(', '')
  307. let lng = l[1].replaceAll(')', '')
  308. if (lat == curPosition.lat && lng == curPosition.lng && !switch_call)
  309. {
  310. console.log("Trying more distance");
  311. teleportButton.distance += 100;
  312. teleportButton.innerHTML = "Teleport " + teleportButton.distance + " m";
  313. }
  314. else
  315. {
  316. console.log("Teleport Success");
  317. GooglePlayer.setPosition(data.location.latLng);
  318. GooglePlayer.setPov({
  319. heading: googleKakaoButton.heading,
  320. pitch: 0,
  321. })
  322. // console.log(teleportButton.distance);
  323. if (teleportButton.distance > 150)
  324. {
  325. teleportButton.distance = 100;
  326. teleportButton.innerHTML = "Teleport " + teleportButton.distance + " m";
  327. }
  328. }
  329. switch_call = false;
  330. }
  331. else {
  332. console.log("STATUS NOT OK");
  333. teleportButton.distance += 100;
  334. teleportButton.innerHTML = "Teleport " + teleportButton.distance + " m";
  335. }
  336. }
  337.  
  338.  
  339.  
  340. google.maps.Map = class extends google.maps.Map {
  341. constructor(...args) {
  342. super(...args);
  343. if (CNBorder)
  344. {
  345.  
  346. this.data.loadGeoJson("https://raw.githubusercontent.com/Jupaoqq/Jupaoqq.github.io/main/10DD.json");
  347. this.data.setStyle(function(feature) {
  348. return {
  349. clickable: false,
  350. strokeWeight: 1
  351. }
  352. });
  353.  
  354. const imageBounds3 = {
  355. north: NW[0],
  356. west: NW[1],
  357. south: NW[2],
  358. east: NW[3],
  359. };
  360.  
  361. historicalOverlay3 = new google.maps.GroundOverlay(
  362. "https://www.countryflags.com/wp-content/uploads/china-flag-png-large.png",
  363. imageBounds3, {clickable: false, opacity: 1}
  364. );
  365. historicalOverlay3.setMap(this);
  366.  
  367. this.addListener("zoom_changed", () => {
  368. let zo = this.getZoom();
  369. let opc = 1;
  370. // console.log(zo)
  371. if (historicalOverlay)
  372. {
  373. historicalOverlay.setMap(null);
  374. historicalOverlay2.setMap(null);
  375. //historicalOverlay3.setMap(null);
  376. }
  377. let bod = TW[0]
  378. let bod2 = TS[0]
  379. if (zo > 7 && zo < 14)
  380. {
  381. bod = TW[zo - 7];
  382. bod2 = TS[1];
  383. }
  384. if (zo >= 14)
  385. {
  386. opc = 0;
  387. }
  388.  
  389. const imageBounds = {
  390. north: bod[0],
  391. west: bod[1],
  392. south: bod[2],
  393. east: bod[3],
  394. };
  395.  
  396. historicalOverlay = new google.maps.GroundOverlay(
  397. "https://www.countryflags.com/wp-content/uploads/china-flag-png-large.png",
  398. imageBounds, {clickable: false, opacity: opc}
  399. );
  400. historicalOverlay.setMap(this);
  401.  
  402. const imageBounds2 = {
  403. north: bod2[0],
  404. west: bod2[1],
  405. south: bod2[2],
  406. east: bod2[3],
  407. };
  408.  
  409. historicalOverlay2 = new google.maps.GroundOverlay(
  410. "https://www.countryflags.com/wp-content/uploads/china-flag-png-large.png",
  411. imageBounds2, {clickable: false, opacity: 1}
  412. );
  413. historicalOverlay2.setMap(this);
  414.  
  415. });
  416. }
  417. for (let mapDiv of document.getElementsByClassName("preset-minimap")){
  418. google.maps.event.addDomListener(mapDiv, "click", () => {
  419. document.getElementById("Minimap Button").current = mapDiv.id;
  420.  
  421. if (mapDiv.id == "Hybrid")
  422. {
  423. this.setMapTypeId('hybrid');
  424. }
  425. else if (mapDiv.id == "Terrain")
  426. {
  427. this.setMapTypeId('terrain');
  428. }
  429. else if (mapDiv.id == "Satellite")
  430. {
  431. this.setMapTypeId('satellite');
  432. }
  433. else if (mapDiv.id == "Custom")
  434. {
  435. this.setMapTypeId(customMode);
  436. }
  437. else
  438. {
  439. this.setMapTypeId('roadmap');
  440. }
  441. // this.setTilt(45);
  442. for (let ar of presetMinimap)
  443. {
  444. if (ar[1] == mapDiv.id)
  445. {
  446. this.set('styles', ar[0]);
  447. }
  448. }
  449. for (let element of document.getElementsByClassName("preset-minimap")){
  450. if (element.id == document.getElementById("Minimap Button").current)
  451. {
  452. element.style.background = "#ff6600";
  453. }
  454. else
  455. {
  456. element.style.background = "orange";
  457. }
  458. }
  459.  
  460. });
  461. }
  462. }
  463.  
  464. }
  465.  
  466. const svService = new google.maps.StreetViewService();
  467. google.maps.StreetViewPanorama = class extends google.maps.StreetViewPanorama {
  468. constructor(...args) {
  469. super(...args);
  470. GooglePlayer = this;
  471.  
  472. 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/");
  473.  
  474. this.addListener('position_changed', () => {
  475. // Maybe this could be used to update the position in the other players
  476. // so that they are always in sync
  477. try {
  478. if (!isGamePage()) return;
  479. // YearButton.panoId = GooglePlayer.pano;
  480. // YearButton.index = -1;
  481. const lat = this.getPosition().lat();
  482. const lng = this.getPosition().lng();
  483. const { heading } = this.getPov();
  484.  
  485. curPosition = { lat, lng, heading };
  486.  
  487. if (googleKakaoButton.useGoogle)
  488. {
  489. googleKakaoButton.lng = lng;
  490. googleKakaoButton.lat = lat;
  491. googleKakaoButton.heading = heading;
  492. if (!YearButton.list.some(row => row.includes(GooglePlayer.pano)))
  493. {
  494. YearButton.innerHTML = "Time Machine";
  495. YearButton.panoId = GooglePlayer.pano;
  496. YearButton.index = -1;
  497. YearButton.plusminusLock = true;
  498. document.getElementById("plus year").style.backgroundColor = "red";
  499. document.getElementById("plus year").disabled = true;
  500. document.getElementById("minus year").style.backgroundColor = "red";
  501. document.getElementById("minus year").disabled = true;
  502. }
  503. }
  504. googleKakaoButton.useGoogle = true;
  505. teleportButton.google = true;
  506. // console.log("also run");
  507.  
  508. // googleKakaoButton.heading = position.lat;
  509. // console.log(position.heading);
  510. // console.log(googleKakaoButton.lng);
  511. }
  512. catch (e) {
  513. console.error("GeoGuessr Path Logger Error:", e);
  514. }
  515. });
  516. this.addListener('pov_changed', () => {
  517. const { heading, pitch } = this.getPov();
  518. if (KakaoPlayer) {
  519. const vp = KakaoPlayer.getViewpoint();
  520. // Prevent a recursive loop: only update kakao's viewpoint if it got out of sync with google's
  521. if ((!almostEqual(vp.pan, heading) || !almostEqual(vp.tilt, pitch)) && nextPlayer == "Kakao") {
  522. KakaoPlayer.setViewpoint({ pan: heading, tilt: pitch, zoom: vp.zoom });
  523. }
  524. }
  525. });
  526. }
  527. };
  528.  
  529.  
  530. var showButtons = document.createElement("Button");
  531. showButtons.id = "Show Buttons"
  532. showButtons.innerHTML = "Geoguessr Unity Script<br><font size=1>by Jupaoqq<br>v4.5.0</font>";
  533. showButtons.style =
  534. "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;";
  535. // document.querySelector(".game-layout__status").appendChild(showButtons)
  536. document.body.appendChild(showButtons);
  537. showButtons.addEventListener("click", () => {
  538. if (hide) {
  539. teleportButton.style.visibility = "";
  540. plusButton.style.visibility = "";
  541. minusButton.style.visibility = "";
  542. resetButton.style.visibility = "";
  543. googleKakaoButton.style.visibility = "";
  544. YearButton.style.visibility = "";
  545. YearplusButton.style.visibility = "";
  546. YearminusButton.style.visibility = "";
  547. MinimapButton.style.visibility = "";
  548. hide = false;
  549. }
  550. else {
  551. teleportButton.style.visibility = "hidden";
  552. plusButton.style.visibility = "hidden";
  553. minusButton.style.visibility = "hidden";
  554. resetButton.style.visibility = "hidden"
  555. googleKakaoButton.style.visibility = "hidden";
  556. YearButton.style.visibility = "hidden";
  557. YearplusButton.style.visibility = "hidden";
  558. YearminusButton.style.visibility = "hidden";
  559. MinimapButton.style.visibility = "hidden";
  560. for (let element of document.getElementsByClassName("preset-minimap")){
  561. element.style.visibility="hidden";
  562. }
  563. hide = true;
  564. }
  565. });
  566.  
  567. var teleportButton = document.createElement("Button");
  568. teleportButton.id = "Main Button";
  569. teleportButton.distance = 100;
  570. teleportButton.google = true;
  571. teleportButton.innerHTML = "Teleport 100m";
  572. teleportButton.style =
  573. "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;";
  574. document.body.appendChild(teleportButton);
  575. teleportButton.addEventListener("click", () => {
  576. // console.log("Google Teleport");
  577. if (googleKakaoButton.init)
  578. {
  579. // console.log("run");
  580. googleKakaoButton.init = false;
  581. if (teleportButton.google)
  582. {
  583. googleKakaoButton.useGoogle = true;
  584. teleportButton.google = true;
  585. }
  586. else
  587. {
  588. googleKakaoButton.useGoogle = false;
  589. teleportButton.google = false;
  590. }
  591. }
  592. else
  593. {
  594. // myLog(teleportButton.google)
  595. if (teleportButton.google && GooglePlayer != null)
  596. {
  597. let heading = GooglePlayer.getPov().heading;
  598. let place = FindPointAtDistanceFrom(curPosition, DegreesToRadians(heading), teleportButton.distance * 0.001)
  599. svService.getPanorama({ location: place, radius: 1000 }, svCheck);
  600. }
  601. }
  602. });
  603.  
  604. var plusButton = document.createElement("Button");
  605. plusButton.id = "plus"
  606. plusButton.innerHTML = "+";
  607. plusButton.style =
  608. "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;";
  609. document.body.appendChild(plusButton);
  610. plusButton.addEventListener("click", () => {
  611. if (teleportButton.distance > 21 && teleportButton.distance < 149) {
  612. teleportButton.distance = teleportButton.distance + 25;
  613. }
  614. teleportButton.innerHTML = "Teleport " + teleportButton.distance + " m";
  615. });
  616.  
  617. var minusButton = document.createElement("Button");
  618. minusButton.id = "minus"
  619. minusButton.innerHTML = "-";
  620. minusButton.style =
  621. "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;";
  622. document.body.appendChild(minusButton);
  623. minusButton.addEventListener("click", () => {
  624. if (teleportButton.distance > 26) {
  625. teleportButton.distance = teleportButton.distance - 25;
  626. }
  627. teleportButton.innerHTML = "Teleport " + teleportButton.distance + " m";
  628. });
  629.  
  630. var resetButton = document.createElement("Button");
  631. resetButton.id = "reset"
  632. resetButton.innerHTML = "Reset";
  633. resetButton.style =
  634. "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;";
  635. document.body.appendChild(resetButton);
  636. resetButton.addEventListener("click", () => {
  637. teleportButton.distance = 100;
  638. teleportButton.innerHTML = "Teleport " + teleportButton.distance + " m";
  639. });
  640.  
  641. var googleKakaoButton = document.createElement("Button");
  642. googleKakaoButton.id = "switch";
  643. googleKakaoButton.init = false;
  644. googleKakaoButton.nextPlayer = "Google";
  645. googleKakaoButton.useGoogle = false;
  646. googleKakaoButton.lng = 0
  647. googleKakaoButton.lat = 0
  648. googleKakaoButton.heading = 0
  649. googleKakaoButton.innerHTML = "Switch Coverage";
  650. googleKakaoButton.small_canvas = false;
  651. googleKakaoButton.style =
  652. "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;";
  653. document.body.appendChild(googleKakaoButton);
  654. googleKakaoButton.addEventListener("click", () => {
  655. let GOOGLE_MAPS_CANVAS1 = document.querySelector(".game-layout__panorama-canvas");
  656. let GOOGLE_MAPS_CANVAS2 = document.querySelector(".br-game-layout__panorama-canvas");
  657. let GOOGLE_MAPS_CANVAS3 = document.querySelector(".inactive");
  658. let duel = false;
  659.  
  660. let GOOGLE_MAPS_CANVAS = null;
  661. if (GOOGLE_MAPS_CANVAS1 !== null)
  662. {
  663. GOOGLE_MAPS_CANVAS = GOOGLE_MAPS_CANVAS1;
  664. }
  665. else if (GOOGLE_MAPS_CANVAS2 !== null)
  666. {
  667. GOOGLE_MAPS_CANVAS = GOOGLE_MAPS_CANVAS2;
  668. }
  669.  
  670.  
  671. if (GOOGLE_MAPS_CANVAS3 !== null)
  672. {
  673. duel = true;
  674. }
  675.  
  676. let KAKAO_MAPS_CANVAS = document.getElementById("roadview");
  677. let YANDEX_MAPS_CANVAS = document.querySelector(".ymaps-2-1-79-panorama-screen");
  678. let MAPILLARY_MAPS_CANVAS = document.getElementById("mly")
  679. let BAIDU_MAPS_CANVAS = document.getElementById("PanoramaMap");
  680. // if (googleKakaoButton.nextPlayer !== "Baidu") {
  681. if (googleKakaoButton.useGoogle == false) {
  682. if (duel)
  683. {
  684. document.getElementById("default_player").className = "game-panorama_panoramaCanvas__PNKve";
  685. if (googleKakaoButton.nextPlayer == "Kakao")
  686. {
  687. document.getElementById("roadview").className = "inactive";
  688. }
  689. else
  690. {
  691. MAPILLARY_MAPS_CANVAS.className = "inactive";
  692. MAPILLARY_MAPS_CANVAS.style.visibility = "hidden";
  693. }
  694. }
  695. else
  696. {
  697. GOOGLE_MAPS_CANVAS.style.visibility = "";
  698. if (googleKakaoButton.nextPlayer == "Kakao")
  699. {
  700. KAKAO_MAPS_CANVAS.style.visibility = "hidden";
  701. }
  702. else if (googleKakaoButton.nextPlayer == "Yandex")
  703. {
  704. YANDEX_MAPS_CANVAS.style.visibility = "hidden";
  705. }
  706. else if (googleKakaoButton.nextPlayer == "Baidu")
  707. {
  708. BAIDU_MAPS_CANVAS.style.visibility = "hidden";
  709. }
  710. else if (googleKakaoButton.nextPlayer == "Mapillary" || googleKakaoButton.nextPlayer == "Google")
  711. {
  712. MAPILLARY_MAPS_CANVAS.style.visibility = "hidden";
  713. }
  714.  
  715. }
  716. const lat = GooglePlayer.getPosition().lat();
  717. const lng = GooglePlayer.getPosition().lng();
  718. switch_call = true;
  719. if (!almostEqual2(lat, googleKakaoButton.lat) || !almostEqual2(lat, googleKakaoButton.lng)) {
  720. svService.getPanorama({ location: { lat: googleKakaoButton.lat, lng: googleKakaoButton.lng }, radius: 1000 }, svCheck);
  721. }
  722. googleKakaoButton.useGoogle = true;
  723. teleportButton.google = true;
  724. googleKakaoButton.init = false;
  725. console.log("use Google");
  726. }
  727. else {
  728. if (duel)
  729. {
  730. document.getElementById("default_player").className = "inactive";
  731. if (googleKakaoButton.nextPlayer == "Kakao")
  732. {
  733. document.getElementById("roadview").className = "game-panorama_panorama__3b2wI";
  734. }
  735. else
  736. {
  737. MAPILLARY_MAPS_CANVAS.className = "game-panorama_panorama__3b2wI";
  738. MAPILLARY_MAPS_CANVAS.style.visibility = "";
  739. MapillaryPlayer.resize();
  740. //window.dispatchEvent(new Event('resize'));
  741. // document.querySelector(".mapillary-canvas").style.;
  742. // mapillary-canvas
  743. }
  744.  
  745. }
  746. else
  747. {
  748. GOOGLE_MAPS_CANVAS.style.visibility = "hidden";
  749. if (googleKakaoButton.nextPlayer == "Kakao")
  750. {
  751. KAKAO_MAPS_CANVAS.style.visibility = "";
  752. }
  753. else if (googleKakaoButton.nextPlayer == "Yandex")
  754. {
  755. YANDEX_MAPS_CANVAS.style.visibility = "";
  756. }
  757. else if (googleKakaoButton.nextPlayer == "Baidu")
  758. {
  759. BAIDU_MAPS_CANVAS.style.visibility = "";
  760. }
  761. else if (googleKakaoButton.nextPlayer == "Mapillary" || googleKakaoButton.nextPlayer == "Google" )
  762. {
  763. MAPILLARY_MAPS_CANVAS.style.visibility = "";
  764. }
  765. }
  766. googleKakaoButton.useGoogle = false;
  767. teleportButton.google = false;
  768. googleKakaoButton.init = true;
  769. console.log("use Others");
  770. }
  771. // }
  772. // else {
  773. // googleKakaoButton.useGoogle = false;
  774. // teleportButton.google = false;
  775. // console.log("use Others");
  776. // }
  777.  
  778. });
  779.  
  780. var YearplusButton = document.createElement("Button");
  781. YearplusButton.id = "plus year"
  782. YearplusButton.innerHTML = "+";
  783. YearplusButton.style =
  784. "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;";
  785. document.body.appendChild(YearplusButton);
  786. YearplusButton.addEventListener("click", () => {
  787. if (YearButton.index < YearButton.list.length - 1 && !YearButton.plusminusLock) {
  788. YearButton.index = YearButton.index + 1;
  789. GooglePlayer.setPano(YearButton.list[YearButton.index][0]);
  790. YearButton.innerHTML = "<font size=2>[" + (YearButton.index + 1) + "] " + YearButton.list[YearButton.index][1] + "</font>";
  791. // myLog(YearButton.index)
  792. }
  793. GenBtnColor();
  794.  
  795. });
  796.  
  797. var YearminusButton = document.createElement("Button");
  798. YearminusButton.id = "minus year"
  799. YearminusButton.innerHTML = "-";
  800. YearminusButton.style =
  801. "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;";
  802. document.body.appendChild(YearminusButton);
  803. YearminusButton.addEventListener("click", () => {
  804. if (YearButton.index > 0 && !YearButton.plusminusLock) {
  805. YearButton.index = YearButton.index - 1;
  806. GooglePlayer.setPano(YearButton.list[YearButton.index][0]);
  807. YearButton.innerHTML = "<font size=2>[" + (YearButton.index + 1) + "] " + YearButton.list[YearButton.index][1] + "</font>";
  808. // myLog(YearButton.index)
  809. }
  810. GenBtnColor();
  811. });
  812.  
  813. function svCheck2(data, status) {
  814. let l = []
  815. if (status === 'OK') {
  816. // console.log("OK for " + data.location.latLng + " at ID " + data.location.pano);
  817. // myLog(data.time)
  818. for (const alt of data.time) {
  819. let date = Object.values(alt).find((value) => value instanceof Date)
  820.  
  821. l.push([alt.pano, date.toDateString()]);
  822. }
  823. // myLog(l);
  824. YearButton.list = l
  825. YearButton.index = l.length - 1;
  826. YearButton.innerHTML = "<font size=2>[" + (YearButton.index + 1) + "] " + YearButton.list[YearButton.index][1] + "</font>";
  827. GenBtnColor();
  828. YearButton.plusminusLock = false;
  829. // YearminusButton.click()
  830. // YearButton.innerHTML = "Default Date";
  831. }
  832. }
  833.  
  834. var YearButton = document.createElement("Button");
  835. YearButton.id = "Date Button";
  836. YearButton.plusminusLock = true;
  837. YearButton.panoId = 0;
  838. YearButton.index = -1;
  839. YearButton.list = [];
  840. YearButton.innerHTML = "Time Machine";
  841. YearButton.style =
  842. "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;";
  843. document.body.appendChild(YearButton);
  844. YearButton.addEventListener("click", () => {
  845. // myLog(YearButton.index)
  846. if (YearButton.panoId != 0)
  847. {
  848. if(YearButton.index == -1)
  849. {
  850. svService.getPanorama({pano: YearButton.panoId}, svCheck2);
  851. }
  852. else
  853. {
  854. YearButton.index = YearButton.list.length - 1;
  855. GooglePlayer.setPano(YearButton.list[YearButton.index][0]);
  856. YearButton.innerHTML = "<font size=2>[" + (YearButton.index + 1) + "] " + YearButton.list[YearButton.index][1] + "</font>";
  857. GenBtnColor();
  858. }
  859. }
  860. else
  861. {
  862. YearButton.panoId = GooglePlayer.pano;
  863. svService.getPanorama({pano: YearButton.panoId}, svCheck2);
  864. }
  865. });
  866.  
  867. // Battle Royale UI optimization
  868.  
  869. let hide = true;
  870.  
  871. var MinimapButton = document.createElement("Button");
  872. MinimapButton.id = "Minimap Button";
  873. MinimapButton.innerHTML = "Minimap Options";
  874. MinimapButton.current = "Default";
  875. MinimapButton.childVisible = false;
  876. MinimapButton.style =
  877. "visibility:hidden;top:13.5em;right:7em;width:15em;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;";
  878. document.body.appendChild(MinimapButton);
  879. MinimapButton.addEventListener("click", () => {
  880. if (MinimapButton.childVisible)
  881. {
  882. for (let element of document.getElementsByClassName("preset-minimap")){
  883. element.style.visibility="hidden";
  884. }
  885. MinimapButton.childVisible = false;
  886. }
  887. else
  888. {
  889. for (let element of document.getElementsByClassName("preset-minimap")){
  890. element.style.visibility="";
  891. }
  892. MinimapButton.childVisible = true;
  893. }
  894.  
  895. });
  896.  
  897.  
  898. let HeightCount = 0
  899. for (let a of presetMinimap)
  900. {
  901. let aButton = document.createElement("Button");
  902. aButton.id = a[1];
  903. aButton.className = "preset-minimap";
  904. aButton.innerHTML = a[1];
  905. aButton.style =
  906. "visibility:hidden;top:" + (15.6 + HeightCount * 1.6).toString() + "em;right:10em;width:9em;height:1.5em;position:absolute;z-index:99999;background-color: orange;border: none;color: white;padding: none;text-align: center;vertical-align: text-top;text-decoration: none;display: inline-block;font-size: 16px;";
  907. document.body.appendChild(aButton);
  908. HeightCount++;
  909. }
  910.  
  911. console.log("Buttons Loaded");
  912. }
  913.  
  914. function GenBtnColor()
  915. {
  916. if (document.getElementById("Date Button").index == document.getElementById("Date Button").list.length - 1)
  917. {
  918. document.getElementById("plus year").style.backgroundColor = "red";
  919. document.getElementById("plus year").disabled = true;
  920. }
  921. else
  922. {
  923. document.getElementById("plus year").style.backgroundColor = "#4CAF50";
  924. document.getElementById("plus year").disabled = false;
  925. }
  926. if (document.getElementById("Date Button").index == 0)
  927. {
  928. document.getElementById("minus year").style.backgroundColor = "red";
  929. document.getElementById("minus year").disabled = true;
  930. }
  931. else
  932. {
  933. document.getElementById("minus year").style.backgroundColor = "#4CAF50";
  934. document.getElementById("minus year").disabled = false;
  935. }
  936. }
  937.  
  938. /**
  939. * Handle Keyboard inputs
  940. */
  941.  
  942. function kBoard()
  943. {
  944. document.addEventListener('keydown', logKey);
  945. }
  946.  
  947. function logKey(e) {
  948. // myLog(e.code);
  949. if (e.code == "Space")
  950. {
  951. setHidden(true);
  952. }
  953. if (e.code == "Digit1")
  954. {
  955. setHidden(false);
  956. document.getElementById("Show Buttons").click();
  957. }
  958. else if (e.code == "Digit3")
  959. {
  960. document.getElementById("Main Button").click();
  961. }
  962. else if (e.code == "Digit2")
  963. {
  964. document.getElementById("minus").click();
  965. }
  966. else if (e.code == "Digit4")
  967. {
  968. document.getElementById("plus").click();
  969.  
  970. }
  971. else if (e.code == "Digit5")
  972. {
  973. document.getElementById("reset").click();
  974. }
  975. else if (e.code == "Digit6")
  976. {
  977. document.getElementById("switch").click();
  978. }
  979. else if (e.code == "Digit7")
  980. {
  981. document.getElementById("minus year").click();
  982. }
  983. else if (e.code == "Digit8")
  984. {
  985. document.getElementById("Date Button").click();
  986. }
  987. else if (e.code == "Digit9")
  988. {
  989. document.getElementById("plus year").click();
  990. }
  991. else if (e.code == "Digit0")
  992. {
  993. if (document.getElementById("Show Buttons").style.visibility == "hidden")
  994. {
  995. document.getElementById("Show Buttons").style.visibility = "";
  996. }
  997. else
  998. {
  999. document.getElementById("Show Buttons").style.visibility = "hidden";
  1000. }
  1001. }
  1002. }
  1003.  
  1004.  
  1005. /**
  1006. * Hide or reveal the buttons, and disable buttons if such feature is not available
  1007. */
  1008.  
  1009. function setHidden(cond)
  1010. {
  1011. // myLog("Sethidden")
  1012. if (cond)
  1013. {
  1014. if (document.getElementById("Show Buttons") != null)
  1015. {
  1016. document.getElementById("Show Buttons").style.visibility = "hidden";
  1017. if (document.getElementById("Main Button") != null)
  1018. {
  1019. document.getElementById("plus").style.visibility = "hidden";
  1020. document.getElementById("minus").style.visibility = "hidden";
  1021. document.getElementById("reset").style.visibility = "hidden";
  1022. document.getElementById("Main Button").style.visibility = "hidden";
  1023. document.getElementById("switch").style.visibility = "hidden";
  1024. document.getElementById("Date Button").style.visibility = "hidden";
  1025. document.getElementById("plus year").style.visibility = "hidden";
  1026. document.getElementById("minus year").style.visibility = "hidden";
  1027. document.getElementById("Minimap Button").style.visibility = "hidden";
  1028. for (let element of document.getElementsByClassName("preset-minimap")){
  1029. element.style.visibility="hidden";
  1030. }
  1031. }
  1032. }
  1033. }
  1034. else
  1035. {
  1036. if (document.getElementById("Show Buttons") != null)
  1037. {
  1038. document.getElementById("Show Buttons").style.visibility = "";
  1039. }
  1040. }
  1041. }
  1042.  
  1043. function setDisable(cond) {
  1044. if (document.getElementById("Main Button") != null) {
  1045. if (cond == "NMPZ") {
  1046. document.getElementById("plus").style.backgroundColor = "red";
  1047. document.getElementById("plus").disabled = true;
  1048. document.getElementById("minus").style.backgroundColor = "red";
  1049. document.getElementById("minus").disabled = true;
  1050. document.getElementById("reset").style.backgroundColor = "red";
  1051. document.getElementById("reset").disabled = true;
  1052. if (nextPlayer == "Kakao")
  1053. {
  1054. document.getElementById("switch").style.backgroundColor = "#4CAF50";
  1055. document.getElementById("switch").disabled = false;
  1056. }
  1057. else
  1058. {
  1059. document.getElementById("switch").style.backgroundColor = "red";
  1060. document.getElementById("switch").disabled = true;
  1061. }
  1062. document.getElementById("switch").innerHTML = "Switch Coverage";
  1063. document.getElementById("Main Button").disabled = true;
  1064. document.getElementById("Main Button").style.backgroundColor = "red";
  1065.  
  1066. document.getElementById("Date Button").style.backgroundColor = "#4CAF50";
  1067. document.getElementById("Date Button").disabled = false;
  1068. }
  1069. else if (cond == "Google") {
  1070.  
  1071. document.getElementById("plus").style.backgroundColor = "#4CAF50";
  1072. document.getElementById("plus").disabled = false;
  1073. document.getElementById("minus").style.backgroundColor = "#4CAF50";
  1074. document.getElementById("minus").disabled = false;
  1075. document.getElementById("reset").style.backgroundColor = "#4CAF50";
  1076. document.getElementById("reset").disabled = false;
  1077. document.getElementById("switch").style.backgroundColor = "#4CAF50";
  1078. document.getElementById("switch").disabled = false;
  1079. document.getElementById("switch").innerHTML = "Switch Coverage";
  1080. document.getElementById("Main Button").disabled = false;
  1081. document.getElementById("Main Button").style.backgroundColor = "#4CAF50";
  1082. document.getElementById("Date Button").style.backgroundColor = "#4CAF50";
  1083. document.getElementById("Date Button").disabled = false;
  1084. }
  1085. else if (cond == "Baidu") {
  1086. document.getElementById("plus").style.backgroundColor = "red";
  1087. document.getElementById("plus").disabled = true;
  1088. document.getElementById("minus").style.backgroundColor = "red";
  1089. document.getElementById("minus").disabled = true;
  1090. document.getElementById("reset").style.backgroundColor = "red";
  1091. document.getElementById("reset").disabled = true;
  1092. document.getElementById("switch").style.backgroundColor = "#4CAF50";
  1093. document.getElementById("switch").disabled = false;
  1094. document.getElementById("switch").innerHTML = "Switch Coverage";
  1095. document.getElementById("Main Button").disabled = true;
  1096. document.getElementById("Main Button").style.backgroundColor = "red";
  1097. document.getElementById("Date Button").style.backgroundColor = "red";
  1098. document.getElementById("Date Button").disabled = true;
  1099. }
  1100. else if (cond == "Kakao" || cond == "Yandex" || cond == "Mapillary") {
  1101. document.getElementById("plus").style.backgroundColor = "#4CAF50";
  1102. document.getElementById("plus").disabled = false;
  1103. document.getElementById("minus").style.backgroundColor = "#4CAF50";
  1104. document.getElementById("minus").disabled = false;
  1105. document.getElementById("reset").style.backgroundColor = "#4CAF50";
  1106. document.getElementById("reset").disabled = false;
  1107. document.getElementById("switch").style.backgroundColor = "#4CAF50";
  1108. document.getElementById("switch").disabled = false;
  1109. document.getElementById("switch").innerHTML = "Switch Coverage";
  1110. document.getElementById("Main Button").disabled = false;
  1111. document.getElementById("Main Button").style.backgroundColor = "#4CAF50";
  1112. document.getElementById("Date Button").style.backgroundColor = "red";
  1113. document.getElementById("Date Button").disabled = true;
  1114. }
  1115. document.getElementById("plus year").style.backgroundColor = "red";
  1116. document.getElementById("plus year").disabled = true;
  1117. document.getElementById("minus year").style.backgroundColor = "red";
  1118. document.getElementById("minus year").disabled = true;
  1119. // else if (cond == "Mapillary") {
  1120. // document.getElementById("plus").style.backgroundColor = "red";
  1121. // document.getElementById("plus").disabled = true;
  1122. // document.getElementById("minus").style.backgroundColor = "red";
  1123. // document.getElementById("minus").disabled = true;
  1124. // document.getElementById("reset").style.backgroundColor = "red";
  1125. // document.getElementById("reset").disabled = true;
  1126. // document.getElementById("switch").style.backgroundColor = "#4CAF50";
  1127. // document.getElementById("switch").disabled = false
  1128. // document.getElementById("switch").innerHTML = "Switch Coverage";
  1129. // document.getElementById("Main Button").disabled = true;
  1130. // document.getElementById("Main Button").style.backgroundColor = "red";
  1131. // }
  1132.  
  1133. }
  1134. }
  1135.  
  1136.  
  1137. /**
  1138. * This observer stays alive while the script is running
  1139. */
  1140.  
  1141. function launchObserver() {
  1142. ArisKakao();
  1143. BYKTeleport();
  1144. SyncListener();
  1145. kBoard();
  1146. myHighlight("Main Observer");
  1147. const OBSERVER = new MutationObserver((mutations, observer) => {
  1148. detectGamePage();
  1149. });
  1150. observerCallback(OBSERVER)
  1151. }
  1152. function observerCallback(obs)
  1153. {
  1154. if (obs)
  1155. {
  1156. obs.observe(document.head, { attributes: true, childList: true, subtree: true });
  1157. }
  1158. else
  1159. {
  1160. setTimeout(observerCallback, 250);
  1161. }
  1162. }
  1163.  
  1164. /**
  1165. * Once the Google Maps API was loaded we can do more stuff
  1166. */
  1167.  
  1168. injecter(() => {
  1169. launchObserver();
  1170. })
  1171.  
  1172.  
  1173. /**
  1174. * Check whether the current page is a game, if so which game mode
  1175. */
  1176.  
  1177. function detectGamePage() {
  1178. if (document.querySelector(".game-layout__panorama-message") !== null && !one_reset)
  1179. {
  1180. one_reset = true;
  1181. myLog("Hide fail to load panorama canvas");
  1182. document.querySelector(".game-layout__panorama-message").style.visibility = "hidden";
  1183. }
  1184. let toLoad = !playerLoaded && !YandexPlayer && !KakaoPlayer && !MapillaryPlayer && !YANDEX_INJECTED && !KAKAO_INJECTED && !MAPILLARY_INJECTED
  1185. const PATHNAME = window.location.pathname;
  1186. if (PATHNAME.startsWith("/game/") || PATHNAME.startsWith("/challenge/")) {
  1187. // myLog("Game page");
  1188. isBattleRoyale = false;
  1189. isDuel = false;
  1190. if (toLoad) {
  1191. loadPlayers();
  1192. }
  1193. waitLoad();
  1194. }
  1195. else if (PATHNAME.startsWith("/battle-royale/")) {
  1196. if (document.querySelector(".br-game-layout") == null) {
  1197. // myLog("Battle Royale Lobby");
  1198. rstValues();
  1199. }
  1200. else {
  1201. // myLog("Battle Royale");
  1202. isBattleRoyale = true;
  1203. isDuel = false;
  1204. if (toLoad) {
  1205. loadPlayers();
  1206. }
  1207. waitLoad();
  1208. }
  1209. }
  1210. else if (PATHNAME.startsWith("/duels/") || PATHNAME.startsWith("/team-duels/")) {
  1211. if (document.querySelector(".game_layout__TO_jf") == null) {
  1212. // myLog("Battle Royale Lobby");
  1213. rstValues();
  1214. }
  1215. else {
  1216. // myLog("Duels");
  1217. isBattleRoyale = true;
  1218. isDuel = true;
  1219. if (toLoad) {
  1220. loadPlayers();
  1221. }
  1222. waitLoad();
  1223. }
  1224. }
  1225. else {
  1226. rstValues();
  1227. //myLog("Not a Game page");
  1228. }
  1229. }
  1230.  
  1231. function rstValues()
  1232. {
  1233. ROUND = 0;
  1234. YandexPlayer = null;
  1235. KakaoPlayer = null;
  1236. MapillaryPlayer = null;
  1237.  
  1238. BAIDU_INJECTED = false;
  1239. YANDEX_INJECTED = false;
  1240. KAKAO_INJECTED = false;
  1241. MAPILLARY_INJECTED = false;
  1242.  
  1243. nextPlayer = "Google"
  1244. global_lat = 0;
  1245. global_lng = 0;
  1246. global_panoID = null;
  1247. global_BDAh = null;
  1248. global_BDBh = null;
  1249. global_BDID = null;
  1250.  
  1251. COMPASS = null;
  1252. eventListenerAttached = false;
  1253. povListenerAttached = false;
  1254. playerLoaded = false;
  1255. locHistory = [];
  1256. one_reset = false;
  1257. setHidden(true);
  1258. yandex_map = false;
  1259. mmKey = 0;
  1260. CURRENT_ROUND_DATA = null;
  1261.  
  1262. linksList = [];
  1263. }
  1264.  
  1265. /**
  1266. * Wait for various players to load
  1267. */
  1268.  
  1269. function waitLoad() {
  1270. if (!YandexPlayer || !KakaoPlayer || !MapillaryPlayer || !YANDEX_INJECTED || !KAKAO_INJECTED || !MAPILLARY_INJECTED) {
  1271. let teleportButton = document.getElementById("Main Button");
  1272. let plusButton = document.getElementById("plus");
  1273. let minusButton = document.getElementById("minus");
  1274. let resetButton = document.getElementById("reset");
  1275. let googleKakaoButton = document.getElementById("switch");
  1276. let showButtons = document.getElementById("Show Buttons");
  1277. let YearButton = document.getElementById("Date Button");
  1278. let YearminusButton = document.getElementById("minus year");
  1279. let YearplusButton = document.getElementById("plus year");
  1280. let MinimapButton = document.getElementById("Minimap Button");
  1281. if (document.querySelector(".br-game-layout__panorama-canvas") != null)
  1282. {
  1283. teleportButton.style.top = "2px";
  1284. plusButton.style.top = "2px";
  1285. minusButton.style.top = "2px";
  1286. resetButton.style.top = "calc(2.5em + 2px)";
  1287. googleKakaoButton.style.top = "calc(2.5em + 2px)";
  1288. showButtons.style.top = "2px";
  1289. YearButton.style.top = "calc(5em + 2px)";
  1290. YearminusButton.style.top = "calc(5em + 2px)";
  1291. YearplusButton.style.top = "calc(5em + 2px)";
  1292. MinimapButton.style.top = "calc(7.5em + 2px)";
  1293.  
  1294. teleportButton.style.right = "calc(9.5em + 300px)";
  1295. plusButton.style.right = "calc(7em + 300px)";
  1296. minusButton.style.right = "calc(20em + 300px)";
  1297. resetButton.style.right = "calc(17.5em + 300px)";
  1298. googleKakaoButton.style.right = "calc(7em + 300px)";
  1299. showButtons.style.right = "300px";
  1300. YearButton.style.right = "calc(9.5em + 300px)";
  1301. YearminusButton.style.right = "calc(20em + 300px)";
  1302. YearplusButton.style.right = "calc(7em + 300px)";
  1303. MinimapButton.style.right = "calc(7em + 300px)";
  1304.  
  1305. let hC = 0
  1306. for (let mapDiv of document.getElementsByClassName("preset-minimap")){
  1307. mapDiv.style.top = "calc(" + (10 + hC * 1.6).toString() + "em + 2px)";
  1308. mapDiv.style.right = "calc(10em + 300px)";
  1309. hC++;
  1310. }
  1311. }
  1312. else if (document.querySelector(".game-panorama_panorama__rdhFg") != null)
  1313. {
  1314. teleportButton.style.top = "8em";
  1315. plusButton.style.top = "8em";
  1316. minusButton.style.top = "8em";
  1317. resetButton.style.top = "10.5em";
  1318. googleKakaoButton.style.top = "10.5em";
  1319. showButtons.style.top = "8em";
  1320. YearButton.style.top = "13em";
  1321. YearminusButton.style.top = "13em";
  1322. YearplusButton.style.top = "13em";
  1323. MinimapButton.style.top = "15.5em";
  1324.  
  1325. teleportButton.style.right = "9.5em";
  1326. plusButton.style.right = "7em";
  1327. minusButton.style.right = "20em";
  1328. resetButton.style.right = "17.5em";
  1329. googleKakaoButton.style.right = "7em";
  1330. showButtons.style.right = "0.5em";
  1331. YearButton.style.right = "9.5em";
  1332. YearminusButton.style.right = "20em";
  1333. YearplusButton.style.right = "7em";
  1334. MinimapButton.style.right = "7em";
  1335. let hC = 0
  1336. for (let mapDiv of document.getElementsByClassName("preset-minimap")){
  1337. mapDiv.style.top = (18 + (hC * 1.6)).toString() + "em";
  1338. mapDiv.style.right = "10em";
  1339. hC++;
  1340. }
  1341. }
  1342. else
  1343. {
  1344. teleportButton.style.top = "6em";
  1345. plusButton.style.top = "6em";
  1346. minusButton.style.top = "6em";
  1347. resetButton.style.top = "8.5em";
  1348. googleKakaoButton.style.top = "8.5em";
  1349. showButtons.style.top = "6em";
  1350. YearButton.style.top = "1em";
  1351. YearminusButton.style.top = "11em";
  1352. YearplusButton.style.top = "11em";
  1353. MinimapButton.style.top = "13.5em";
  1354.  
  1355. teleportButton.style.right = "9.5em";
  1356. plusButton.style.right = "7em";
  1357. minusButton.style.right = "20em";
  1358. resetButton.style.right = "17.5em";
  1359. googleKakaoButton.style.right = "7em";
  1360. showButtons.style.right = "0.5em";
  1361. YearButton.style.right = "9.5em";
  1362. YearminusButton.style.right = "20em";
  1363. YearplusButton.style.right = "7em";
  1364. MinimapButton.style.right = "7em";
  1365. let hC = 0
  1366. for (let mapDiv of document.getElementsByClassName("preset-minimap")){
  1367. mapDiv.style.top = (15.6 + (hC * 1.6)).toString() + "em";
  1368. mapDiv.style.right = "10em";
  1369. hC++;
  1370. }
  1371. }
  1372.  
  1373. setTimeout(waitLoad, 250);
  1374. } else {
  1375. checkRound();
  1376. }
  1377. }
  1378.  
  1379. /**
  1380. * Checks for round changes
  1381. */
  1382.  
  1383. function checkRound() {
  1384. // myLog("Check Round");
  1385. if (!isBattleRoyale) {
  1386. // myLog("Check Round");
  1387. let currentRound = getRoundFromPage();
  1388. if (ROUND != currentRound) {
  1389. fire1 = true;
  1390. document.getElementById("switch").init = true;
  1391. myHighlight("New round");
  1392. ROUND = currentRound;
  1393. // NEW_ROUND_LOADED = true;
  1394. COMPASS = null;
  1395. locHistory = [];
  1396. one_reset = false;
  1397. getMapData();
  1398. nextButtonCallback();
  1399. }
  1400. }
  1401. else {
  1402. getMapData();
  1403. }
  1404. }
  1405.  
  1406. /**
  1407. * Add listeners if buttons have been created
  1408. */
  1409.  
  1410. function finalDetail()
  1411. {
  1412. let target = document.querySelector("a[data-qa='play-same-map']");
  1413. if (target)
  1414. {
  1415. var div = document.createElement("div");
  1416. div.classList.add("buttons_buttons__0B3SB")
  1417. document.querySelector('.result-layout_content__jAHfP').appendChild(div);
  1418. for (var rd of linksList)
  1419. {
  1420. let cl = target.cloneNode( true );
  1421. let tx = "View R" + rd[0] + " in " + rd[1];
  1422. cl.querySelector('.button_label__kpJrA').innerHTML = tx;
  1423. cl.removeAttribute('data-qa');
  1424. cl.addEventListener("click", (e) => {
  1425. window.open(rd[2]);
  1426. })
  1427. cl.style = "top:10px;right:-10px;";
  1428. div.appendChild(cl);
  1429. }
  1430. }
  1431. else
  1432. {
  1433. setTimeout(finalDetail, 500);
  1434. }
  1435. }
  1436.  
  1437. function nextButtonCallback()
  1438. {
  1439. let nextButton = document.querySelector("button[data-qa='close-round-result']");
  1440. if (nextButton != null && fire1)
  1441. {
  1442. fire1 = false;
  1443. nextButton.addEventListener("click", (e) => {
  1444. if (document.getElementById("Show Buttons") != null && !cn_tips && ROUND !== 5)
  1445. {
  1446. myLog("try to show show buttons")
  1447. document.getElementById("Show Buttons").style.visibility = "";
  1448. }
  1449. if (ROUND == 5)
  1450. {
  1451. myLog("Game Finished")
  1452. if (linksList)
  1453. {
  1454. finalDetail();
  1455. }
  1456. }
  1457. })
  1458.  
  1459. if (nextPlayer !== "Google")
  1460. {
  1461. myLog("Clone buttons");
  1462. let clone = document.querySelector("button[data-qa='close-round-result']").cloneNode( true );
  1463. let tx = "View Location in " + nextPlayer;
  1464. clone.querySelector('.button_label__kpJrA').innerHTML = tx;
  1465. clone.setAttribute('id', "LinkBtn");
  1466. clone.removeAttribute('data-qa');
  1467. let urlStr = ""
  1468. if (nextPlayer == "Baidu")
  1469. {
  1470. urlStr = "https://map.baidu.com/?panotype=street&pid=" + global_BDID + "&panoid=" + global_BDID + "&from=api";
  1471. }
  1472. else if (nextPlayer == "Kakao")
  1473. {
  1474. urlStr = "https://map.kakao.com/link/roadview/" + global_lat + "," + global_lng;
  1475. }
  1476. else if (nextPlayer == "Mapillary")
  1477. {
  1478. urlStr = "https://www.mapillary.com/app/?pKey=" + mmKey + "&focus=photo";
  1479. }
  1480. else if (nextPlayer == "Yandex")
  1481. {
  1482. urlStr = "https://yandex.com/maps/?&panorama%5Bdirection%5D=16%2C0&panorama%5Bpoint%5D=" + global_lng + "%2C" + global_lat;
  1483. }
  1484. linksList.push([ROUND, nextPlayer, urlStr]);
  1485. clone.addEventListener("click", (e) => {
  1486. window.open(urlStr);
  1487. })
  1488. if (ROUND == 5)
  1489. {
  1490. clone.style = "top:10px;";
  1491. }
  1492. else
  1493. {
  1494. clone.style = "right:-10px;";
  1495. }
  1496. document.querySelector('.round-result_actions__5j26U').appendChild(clone);
  1497. }
  1498. }
  1499. else
  1500. {
  1501. setTimeout(nextButtonCallback, 500);
  1502. }
  1503. }
  1504.  
  1505. function guessButtonCallback()
  1506. {
  1507. let guessButton = document.querySelector("button[data-qa='perform-guess']");
  1508. if (guessButton != null)
  1509. {
  1510.  
  1511. guessButton.addEventListener("click", (e) => {
  1512. if (document.getElementById("Show Buttons") != null)
  1513. {
  1514. myLog("try to hide show buttons")
  1515. document.getElementById("Show Buttons").style.visibility = "hidden";
  1516. setHidden(true);
  1517. }
  1518. })
  1519. }
  1520. else
  1521. {
  1522. setTimeout(guessButtonCallback, 500);
  1523. }
  1524. }
  1525.  
  1526. /**
  1527. * Load different streetview players
  1528. */
  1529.  
  1530. function injectYandex()
  1531. {
  1532. injectYandexScript().then(() => {
  1533. myLog("Ready to inject Yandex player");
  1534. injectYandexPlayer();
  1535. }).catch((error) => {
  1536. myLog(error);
  1537. });
  1538. }
  1539.  
  1540. function tutorialPosition(flag)
  1541. {
  1542. let teleportButton = document.getElementById("Main Button");
  1543. let plusButton = document.getElementById("plus");
  1544. let minusButton = document.getElementById("minus");
  1545. let resetButton = document.getElementById("reset");
  1546. let googleKakaoButton = document.getElementById("switch");
  1547. let showButtons = document.getElementById("Show Buttons");
  1548. let YearButton = document.getElementById("Date Button");
  1549. let YearminusButton = document.getElementById("minus year");
  1550. let YearplusButton = document.getElementById("plus year");
  1551. // document.getElementById("Show Buttons").style.visibility = "hidden";
  1552. if (flag)
  1553. {
  1554. teleportButton.style.top = "20em";
  1555. plusButton.style.top = "20em";
  1556. minusButton.style.top = "20em";
  1557. resetButton.style.top = "22.5em";
  1558. googleKakaoButton.style.top = "22.5em";
  1559. showButtons.style.top = "20em";
  1560. YearButton.style.top = "25em";
  1561. YearminusButton.style.top = "25em";
  1562. YearplusButton.style.top = "25em";
  1563. }
  1564. else
  1565. {
  1566. teleportButton.style.top = "6em";
  1567. plusButton.style.top = "6em";
  1568. minusButton.style.top = "6em";
  1569. resetButton.style.top = "8.5em";
  1570. googleKakaoButton.style.top = "8.5em";
  1571. showButtons.style.top = "6em";
  1572. YearButton.style.top = "11em";
  1573. YearminusButton.style.top = "11em";
  1574. YearplusButton.style.top = "11em";
  1575.  
  1576. }
  1577.  
  1578. }
  1579.  
  1580. function loadPlayers() {
  1581. playerLoaded = true;
  1582. if (!isBattleRoyale)
  1583. {
  1584. getSeed().then((data) => {
  1585. // myLog(data);
  1586. if (data.mapName.includes("A United World") || data.mapName.includes("byk"))
  1587. {
  1588. myLog("A United World");
  1589. injectYandex();
  1590. }
  1591. else if (data.mapName.includes("Yandex"))
  1592. {
  1593. yandex_map = true;
  1594. myLog("Is Yandex Map");
  1595. injectYandex();
  1596. }
  1597. else{
  1598. // YANDEX_API_KEY = "";
  1599. YANDEX_INJECTED = true;
  1600. YandexPlayer = "YD";
  1601. myLog("Not a Yandex map");
  1602. }
  1603. if (!data.mapName.includes("China Tips for each province"))
  1604. {
  1605. cn_tips = false;
  1606. document.getElementById("Show Buttons").style.visibility = "";
  1607. setHidden(false);
  1608. }
  1609. else
  1610. {
  1611. cn_tips = true;
  1612. guaranteeUI();
  1613. }
  1614. }).catch((error) => {
  1615. myLog(error);
  1616. });
  1617. }
  1618. else
  1619. {
  1620. injectYandex();
  1621. }
  1622.  
  1623. initializeCanvas();
  1624.  
  1625.  
  1626.  
  1627.  
  1628. }
  1629.  
  1630. function guaranteeUI()
  1631. {
  1632. // myLog("UI")
  1633. if (document.getElementById("GH-ui") !== null)
  1634. {
  1635. document.getElementById("GH-ui").style.display = "block";
  1636. }
  1637. else
  1638. {
  1639. setTimeout(guaranteeUI, 500);
  1640. }
  1641. }
  1642.  
  1643. /**
  1644. * Handles Return to start and undo
  1645. */
  1646.  
  1647. function handleReturnToStart() {
  1648. let rtsButton = document.querySelector("button[data-qa='return-to-start']");
  1649. if (rtsButton != null) {
  1650. myLog("handleReturnToStart listener attached");
  1651. rtsButton.addEventListener("click", (e) => {
  1652. if (nextPlayer != "Baidu")
  1653. {
  1654. goToLocation();
  1655. }
  1656. else
  1657. {
  1658. document.getElementById("PanoramaMap").src = "https://map.baidu.com/?panotype=street&pid=" + global_BDID + "&panoid=" + global_BDID + "&from=api";
  1659. }
  1660. const elementClicked = e.target;
  1661. elementClicked.setAttribute('listener', 'true');
  1662. myLog("Return to start");
  1663. });
  1664. guessButtonCallback();
  1665. setTimeout(function () {goToLocation();}, 1000);
  1666. }
  1667. else
  1668. {
  1669. setTimeout(handleReturnToStart, 500);
  1670. }
  1671. }
  1672.  
  1673. function handleUndo() {
  1674. let undoButton = document.querySelector("button[data-qa='undo-move']");
  1675. if (undoButton != null)
  1676. {
  1677. myLog("Attach undo");
  1678. undoButton.addEventListener("click", (e) => {
  1679. if (locHistory.length > 0) {
  1680. goToUndoMove();
  1681. myLog("Undo Move");
  1682. }
  1683. })
  1684. }
  1685. else
  1686. {
  1687. setTimeout(handleUndo, 500);
  1688. }
  1689.  
  1690. }
  1691.  
  1692. /**
  1693. * Load game information
  1694. */
  1695.  
  1696. function getMapData() {
  1697. // myHighlight("Seed data");
  1698. getSeed().then((data) => {
  1699. // myHighlight("Seed data");
  1700. // myLog(data);
  1701. if (isBattleRoyale) {
  1702. if ((document.querySelector(".br-game-layout") == null && document.querySelector(".version3-in-game_layout__Hi_Iw") == null) || typeof data.gameId == typeof undefined) {
  1703. // myLog("Battle Royale Lobby");
  1704. }
  1705. else
  1706. {
  1707. let origin = false;
  1708. if (!CURRENT_ROUND_DATA) {
  1709. CURRENT_ROUND_DATA = data
  1710. origin = true;
  1711. }
  1712.  
  1713. if (origin || !(data.currentRoundNumber === CURRENT_ROUND_DATA.currentRoundNumber)) {
  1714. // myHighlight("Battle Royale New round");
  1715. document.getElementById("switch").init = true;
  1716. // NEW_ROUND_LOADED = true;
  1717. COMPASS = null;
  1718. locHistory = [];
  1719. one_reset = false;
  1720. setHidden(false);
  1721. if (!origin) {
  1722. CURRENT_ROUND_DATA = data;
  1723. }
  1724. locationCheck(data);
  1725. // myLog(data);
  1726. if (data.currentRoundNumber == 1)
  1727. {
  1728. setTimeout(function () {goToLocation();}, 3000);
  1729. }
  1730. else
  1731. {
  1732. goToLocation();
  1733. }
  1734. handleReturnToStart();
  1735. if (isDuel)
  1736. {
  1737. handleUndo();
  1738. hideButtons();
  1739. }
  1740. handleMinimapCallback();
  1741.  
  1742. }
  1743. }
  1744. }
  1745. else {
  1746. if (!cn_tips)
  1747. {
  1748. document.getElementById("Show Buttons").style.visibility = "";
  1749. tutorialPosition(false);
  1750. }
  1751. else
  1752. {
  1753. document.getElementById("Show Buttons").style.visibility = "hidden";
  1754. tutorialPosition(true);
  1755. }
  1756. locationCheck(data);
  1757. if (data.currentRoundNumber == 1)
  1758. {
  1759. setTimeout(function () {goToLocation();}, 3000);
  1760. }
  1761. else
  1762. {
  1763. goToLocation();
  1764. }
  1765. handleReturnToStart();
  1766. handleUndo();
  1767. hideButtons();
  1768. handleMinimapCallback();
  1769. }
  1770.  
  1771.  
  1772.  
  1773. }).catch((error) => {
  1774. myLog(error);
  1775. });
  1776. }
  1777.  
  1778. function handleMinimapCallback()
  1779. {
  1780. let trueCond = true;
  1781. let timeoutTime = 250;
  1782. if (isBattleRoyale) {
  1783. if (isDuel)
  1784. {
  1785. if (document.querySelector(".overlay_overlay__AR02x"))
  1786. {
  1787. trueCond = false;
  1788. }
  1789. else
  1790. {
  1791. trueCond = true;
  1792. }
  1793. }
  1794. else
  1795. {
  1796. if (document.querySelector(".popup__content"))
  1797. {
  1798. trueCond = false;
  1799. }
  1800. else
  1801. {
  1802. trueCond = true;
  1803. }
  1804. }
  1805. timeoutTime = 2500;
  1806. }
  1807.  
  1808. if (trueCond)
  1809. {
  1810. let cur = document.getElementById("Minimap Button").current;
  1811. myLog(cur)
  1812. for (let mapDiv of document.getElementsByClassName("preset-minimap")){
  1813. if (cur == mapDiv.id)
  1814. {
  1815. setTimeout(function () {mapDiv.click();}, 500);
  1816. setTimeout(function () {mapDiv.click();}, 1000);
  1817. setTimeout(function () {mapDiv.click();}, 3000);
  1818. }
  1819. }
  1820. }
  1821. else
  1822. {
  1823. setTimeout(handleMinimapCallback, 250);
  1824. }
  1825. }
  1826.  
  1827. /**
  1828. * Hide unnecessary buttons for non-Google coverages
  1829. */
  1830.  
  1831. function hideButtons() {
  1832. let CHECKPOINT = document.querySelector("button[data-qa='set-checkpoint']");
  1833. let ZOOM_IN = document.querySelector("button[data-qa='pano-zoom-in']");
  1834. let ZOOM_OUT = document.querySelector("button[data-qa='pano-zoom-out']");
  1835.  
  1836. if (CHECKPOINT != null)
  1837. {
  1838. if (nextPlayer === "Google") {
  1839.  
  1840. CHECKPOINT.style.visibility = "";
  1841. ZOOM_IN.style.visibility = "";
  1842. ZOOM_OUT.style.visibility = "";
  1843. myLog("Buttons Unhidden");
  1844.  
  1845. }
  1846. else {
  1847.  
  1848. CHECKPOINT.style.visibility = "hidden";
  1849. ZOOM_IN.style.visibility = "hidden";
  1850. ZOOM_OUT.style.visibility = "hidden";
  1851. myLog("Buttons Hidden");
  1852.  
  1853. }
  1854. }
  1855. else
  1856. {
  1857. setTimeout(hideButtons, 250);
  1858. }
  1859. }
  1860.  
  1861. /**
  1862. * Check which player to use for the next location
  1863. */
  1864.  
  1865. function locationCheck(data) {
  1866. // console.log(data);
  1867. let round;
  1868. if (isBattleRoyale) {
  1869. if (isDuel)
  1870. {
  1871. round = data.rounds[data.currentRoundNumber - 1].panorama;
  1872. }
  1873. else
  1874. {
  1875. round = data.rounds[data.currentRoundNumber - 1];
  1876. }
  1877. }
  1878. else {
  1879. round = data.rounds[data.round - 1];
  1880. }
  1881. global_lat = round.lat;
  1882. global_lng = round.lng;
  1883. global_panoID = round.panoId;
  1884. global_heading = round.heading;
  1885. global_pitch = round.pitch;
  1886. // myLog(global_lat);
  1887. // myLog(global_lng);
  1888. // myLog(krCoordinates);
  1889.  
  1890. nextPlayer = "Google";
  1891.  
  1892. if ( krCoordinates[0] > global_lat && krCoordinates[2] < global_lat && krCoordinates[1] < global_lng && krCoordinates[3] > global_lng)
  1893. {
  1894. nextPlayer = "Kakao";
  1895. }
  1896. else if (yandex_map)
  1897. {
  1898. nextPlayer = "Yandex";
  1899. }
  1900. else
  1901. {
  1902. if (global_panoID) {
  1903. let locInfo = hex2a(global_panoID);
  1904. // myLog(locInfo)
  1905. let mapType = locInfo.substring(0, 5);
  1906. if (mapType === "BDMAP") {
  1907. nextPlayer = "Baidu";
  1908. let coord = locInfo.substring(5);
  1909.  
  1910. if(coord.includes('BDAh'))
  1911. {
  1912. global_BDID = coord.split('BDAh')[0].replace("panoId","");
  1913. let tem = coord.split('BDAh')[1];
  1914. global_BDAh = tem.split('BDBh')[0];
  1915. global_BDBh = tem.split('BDBh')[1];
  1916. }
  1917. else
  1918. {
  1919. global_BDID = coord.replace("panoId","");
  1920. }
  1921. // myLog(global_BDID)
  1922. // myLog(global_BDAh)
  1923. // myLog(global_BDBh)
  1924. // global_lat = coord.split(",")[0];
  1925. // global_lng = coord.split(",")[1];
  1926. // myLog(global_lat);
  1927. }
  1928. else if (mapType === "MLMAP") {
  1929. nextPlayer = "Mapillary";
  1930. mmKey = locInfo.substring(5);
  1931. }
  1932. else if (mapType === "YDMAP" ) {
  1933. nextPlayer = "Yandex";
  1934. }
  1935. }
  1936. }
  1937.  
  1938. // Disable buttons if NM, NMPZ
  1939.  
  1940. if(!isBattleRoyale)
  1941. {
  1942. if (data.forbidMoving || data.forbidRotating || data.forbidZooming)
  1943. {
  1944. setDisable("NMPZ");
  1945. }
  1946. else
  1947. {
  1948. setDisable(nextPlayer);
  1949. }
  1950. }
  1951. else
  1952. {
  1953. if (data.movementOptions.forbidMoving || data.movementOptions.forbidRotating || data.movementOptions.forbidZooming)
  1954. {
  1955. setDisable("NMPZ");
  1956. }
  1957. else
  1958. {
  1959. setDisable(nextPlayer);
  1960. }
  1961. }
  1962.  
  1963. myLog(nextPlayer);
  1964. injectCanvas();
  1965. }
  1966.  
  1967.  
  1968. /**
  1969. * setID for canvas
  1970. */
  1971.  
  1972. function initializeCanvas() {
  1973. let GAME_CANVAS = "";
  1974. let DUEL_CANVAS = "";
  1975. //myLog("Is duels");
  1976. //myLog(duels);
  1977.  
  1978. if (isBattleRoyale) {
  1979. if (isDuel) {
  1980. GAME_CANVAS = document.querySelector(".game-panorama_panorama__rdhFg");
  1981. DUEL_CANVAS = document.querySelector(".game-panorama_panoramaCanvas__PNKve");
  1982. }
  1983. else
  1984. {
  1985. GAME_CANVAS = document.querySelector(".br-game-layout__panorama-wrapper");
  1986. DUEL_CANVAS = "dummy";
  1987. }
  1988. }
  1989. else {
  1990. GAME_CANVAS = document.querySelector(".game-layout__canvas");
  1991. DUEL_CANVAS = "dummy";
  1992. }
  1993. if (GAME_CANVAS && DUEL_CANVAS)
  1994. {
  1995. myLog("Canvas injected");
  1996. GAME_CANVAS.id = "player";
  1997. if (isDuel) {
  1998. DUEL_CANVAS.id = "default_player";
  1999. }
  2000. injectBaiduScript();
  2001. injectMapillaryPlayer();
  2002. injectKakaoScript().then(() => {
  2003. myLog("Ready to inject Kakao player");
  2004. }).catch((error) => {
  2005. myLog(error);
  2006. });
  2007. }
  2008. else
  2009. {
  2010. setTimeout(initializeCanvas, 250);
  2011. }
  2012.  
  2013. }
  2014.  
  2015. /**
  2016. * Hide or show players based on where the next location is
  2017. */
  2018.  
  2019. function injectCanvas() {
  2020. if (isDuel)
  2021. {
  2022. canvasSwitch();
  2023. }
  2024. else
  2025. {
  2026. Google();
  2027. Baidu();
  2028. Kakao();
  2029. Yandex();
  2030. Mapillary();
  2031. }
  2032. ZoomControls();
  2033. }
  2034.  
  2035. // for duels (class ID change)
  2036.  
  2037. function canvasSwitch()
  2038. {
  2039. if (document.querySelector(".compass") !== null && document.querySelector("button[data-qa='undo-move']") !== null)
  2040. {
  2041. let GOOGLE_MAPS_CANVAS = document.querySelector(".game-panorama_panoramaCanvas__PNKve");
  2042. document.querySelector(".ymaps-2-1-79-panorama-screen").style.position = "absolute";
  2043. if (nextPlayer === "Google") {
  2044. document.getElementById("default_player").className = "game-panorama_panoramaCanvas__PNKve";
  2045. document.getElementById("PanoramaMap").className = "inactive";
  2046. document.getElementById("roadview").className = "inactive";
  2047. document.querySelector(".ymaps-2-1-79-panorama-screen").style.visibility = "hidden";
  2048. document.getElementById("Main Button").google = true;
  2049. document.getElementById("switch").nextPlayer = "Google";
  2050. document.getElementById("switch").useGoogle = true;
  2051. document.getElementById("default_player").style.position = "absolute";
  2052. document.querySelector(".compass").style.visibility = "";
  2053. document.querySelector("button[data-qa='undo-move']").visibility = "";
  2054. myLog("Google Duel Canvas loaded");
  2055. }
  2056. else if (nextPlayer === "Baidu")
  2057. {
  2058. document.getElementById("default_player").className = "inactive";
  2059. document.getElementById("PanoramaMap").className = "game-panorama_panorama__rdhFg";
  2060. document.getElementById("roadview").className = "inactive";
  2061. document.getElementById("mly").style.visibility = "hidden";
  2062. document.querySelector(".ymaps-2-1-79-panorama-screen").style.visibility = "hidden";
  2063. document.getElementById("Main Button").google = false;
  2064. document.getElementById("switch").nextPlayer = "Baidu";
  2065. document.getElementById("switch").useGoogle = false;
  2066. document.getElementById("PanoramaMap").style.position = "absolute";
  2067. document.querySelector(".compass").style.visibility = "hidden";
  2068. document.querySelector("button[data-qa='undo-move']").visibility = "hidden";
  2069. myLog("Baidu Duel Canvas loaded");
  2070. }
  2071. else if (nextPlayer === "Kakao")
  2072. {
  2073. document.getElementById("default_player").className = "inactive";
  2074. document.getElementById("PanoramaMap").className = "inactive";
  2075. document.getElementById("roadview").className = "game-panorama_panorama__rdhFg";
  2076. document.getElementById("mly").style.visibility = "hidden";
  2077. document.querySelector(".ymaps-2-1-79-panorama-screen").style.visibility = "hidden";
  2078. document.getElementById("Main Button").google = false;
  2079. document.getElementById("switch").nextPlayer = "Kakao";
  2080. document.getElementById("switch").useGoogle = false;
  2081. document.getElementById("roadview").style.position = "absolute";
  2082. document.querySelector(".compass").style.visibility = "";
  2083. document.querySelector("button[data-qa='undo-move']").visibility = "";
  2084. myLog("Kakao Duel Canvas loaded");
  2085. }
  2086. else if (nextPlayer === "Yandex")
  2087. {
  2088. document.getElementById("default_player").className = "inactive";
  2089. document.getElementById("PanoramaMap").className = "inactive";
  2090. document.getElementById("roadview").className = "inactive";
  2091. document.getElementById("mly").style.visibility = "hidden";
  2092. document.querySelector(".ymaps-2-1-79-panorama-screen").style.visibility = "";
  2093. document.getElementById("Main Button").google = false;
  2094. document.getElementById("switch").nextPlayer = "Yandex";
  2095. document.getElementById("switch").useGoogle = false;
  2096. document.querySelector(".ymaps-2-1-79-panorama-screen").style.position = "absolute";
  2097. document.querySelector(".compass").style.visibility = "";
  2098. document.querySelector("button[data-qa='undo-move']").visibility = "";
  2099. myLog("Yandex Duel Canvas loaded");
  2100. }
  2101. else if (nextPlayer === "Mapillary")
  2102. {
  2103. document.getElementById("default_player").className = "inactive";
  2104. document.getElementById("PanoramaMap").className = "inactive";
  2105. document.getElementById("roadview").className = "inactive";
  2106. document.getElementById("mly").style.visibility = "";
  2107. document.querySelector(".ymaps-2-1-79-panorama-screen").style.visibility = "hidden";
  2108. document.getElementById("Main Button").google = false;
  2109. document.getElementById("switch").nextPlayer = "Mapillary";
  2110. document.getElementById("switch").useGoogle = false;
  2111. document.getElementById("mly").style.position = "absolute";
  2112. document.querySelector(".compass").style.visibility = "hidden";
  2113. document.querySelector("button[data-qa='undo-move']").visibility = "";
  2114. myLog("Mapillary Duel Canvas loaded");
  2115. }
  2116. }
  2117. else
  2118. {
  2119. setTimeout(canvasSwitch, 250);
  2120. }
  2121. }
  2122.  
  2123. // for Battle Royale and classic (change visibility)
  2124.  
  2125. function Google() {
  2126. let GOOGLE_MAPS_CANVAS = ""
  2127. if (isBattleRoyale) {
  2128. GOOGLE_MAPS_CANVAS = document.querySelector(".br-game-layout__panorama-canvas");
  2129. }
  2130. else {
  2131. GOOGLE_MAPS_CANVAS = document.querySelector(".game-layout__panorama-canvas");
  2132. }
  2133. if (nextPlayer === "Google") {
  2134. GOOGLE_MAPS_CANVAS.style.visibility = "";
  2135. document.getElementById("Main Button").google = true;
  2136. document.getElementById("switch").nextPlayer = "Google";
  2137. document.getElementById("switch").useGoogle = true;
  2138. myLog("Google Canvas loaded");
  2139. }
  2140. else {
  2141. GOOGLE_MAPS_CANVAS.style.visibility = "hidden";
  2142. document.getElementById("Main Button").google = false;
  2143. myLog("Google Canvas hidden");
  2144. }
  2145.  
  2146. }
  2147.  
  2148. function Baidu() {
  2149. let BAIDU_MAPS_CANVAS = document.getElementById("PanoramaMap");
  2150. // myLog("Baidu canvas");
  2151. if (BAIDU_MAPS_CANVAS !== null && document.querySelector(".compass") !== null && document.querySelector("button[data-qa='undo-move']") !== null)
  2152. {
  2153. BAIDU_MAPS_CANVAS.style.position = "absolute";
  2154. if (nextPlayer === "Baidu") {
  2155. BAIDU_MAPS_CANVAS.style.visibility = "";
  2156. document.getElementById("switch").nextPlayer = "Baidu";
  2157. document.getElementById("switch").useGoogle = false;
  2158. document.querySelector(".compass").style.visibility = "hidden";
  2159. document.querySelector("button[data-qa='undo-move']").style.visibility = "hidden";
  2160. myLog("Baidu Canvas loaded");
  2161. }
  2162. else {
  2163. document.querySelector(".compass").style.visibility = "";
  2164. document.querySelector("button[data-qa='undo-move']").style.visibility = "";
  2165. BAIDU_MAPS_CANVAS.style.visibility = "hidden";
  2166. myLog("Baidu Canvas hidden");
  2167. }
  2168. }
  2169. else
  2170. {
  2171. setTimeout(Baidu, 250);
  2172. }
  2173.  
  2174. }
  2175.  
  2176. function Kakao() {
  2177. let KAKAO_MAPS_CANVAS = document.getElementById("roadview");
  2178. // myLog("Kakao canvas");
  2179. document.getElementById("roadview").style.position = "absolute";
  2180. if (KAKAO_MAPS_CANVAS != null)
  2181. {
  2182. if (nextPlayer === "Kakao") {
  2183. KAKAO_MAPS_CANVAS.style.visibility = "";
  2184. document.getElementById("switch").nextPlayer = "Kakao";
  2185. document.getElementById("switch").useGoogle = false;
  2186. myLog("Kakao Canvas loaded");
  2187. }
  2188. else {
  2189. KAKAO_MAPS_CANVAS.style.visibility = "hidden";
  2190. myLog("Kakao Canvas hidden");
  2191. }
  2192. }
  2193. else
  2194. {
  2195. setTimeout(Kakao, 250);
  2196. }
  2197.  
  2198. }
  2199.  
  2200. function Yandex() {
  2201. let YANDEX_MAPS_CANVAS = document.querySelector(".ymaps-2-1-79-panorama-screen");
  2202. if (YANDEX_MAPS_CANVAS != null)
  2203. {
  2204. // myLog("Yandex canvas");
  2205. document.querySelector(".ymaps-2-1-79-panorama-screen").style.position = "absolute";
  2206. // myLog("Yandex canvas");
  2207. /* myLog(YANDEX_MAPS_CANVAS); */
  2208. if (nextPlayer === "Yandex") {
  2209. YANDEX_MAPS_CANVAS.style.visibility = "";
  2210. document.getElementById("switch").nextPlayer = "Yandex";
  2211. document.getElementById("switch").useGoogle = false;
  2212. myLog("Yandex Canvas loaded");
  2213. }
  2214. else {
  2215. YANDEX_MAPS_CANVAS.style.visibility = "hidden";
  2216. myLog("Yandex Canvas hidden");
  2217. }
  2218. }
  2219. else
  2220. {
  2221. setTimeout(Yandex, 250);
  2222. }
  2223.  
  2224. }
  2225.  
  2226. function Mapillary()
  2227. {
  2228.  
  2229. let MAPILLARY_MAPS_CANVAS = document.getElementById("mly");
  2230. if (MAPILLARY_MAPS_CANVAS != null)
  2231. {
  2232. // myLog("Mapillary canvas");
  2233. MAPILLARY_MAPS_CANVAS.style.position = "absolute";
  2234. if (nextPlayer === "Mapillary") {
  2235. MAPILLARY_MAPS_CANVAS.style.visibility = "";
  2236. document.getElementById("switch").nextPlayer = "Mapillary";
  2237. document.getElementById("switch").useGoogle = false;
  2238. myLog("Mapillary Canvas loaded");
  2239. }
  2240. else {
  2241. MAPILLARY_MAPS_CANVAS.style.visibility = "hidden";
  2242. myLog("Mapillary Canvas hidden");
  2243. }
  2244. }
  2245. else
  2246. {
  2247. setTimeout(Mapillary, 250);
  2248. }
  2249.  
  2250. }
  2251.  
  2252. /**
  2253. * Adjust button placement
  2254. */
  2255.  
  2256. function ZoomControls() {
  2257. let style = `
  2258. .ymaps-2-1-79-panorama-gotoymaps {display: none !important;}
  2259. .game-layout__controls {bottom: 8rem !important; left: 1rem !important;}
  2260. `;
  2261.  
  2262. let style_element = document.createElement("style");
  2263. style_element.innerHTML = style;
  2264. document.body.appendChild(style_element);
  2265. }
  2266.  
  2267. /**
  2268. * Updates the compass to match Yandex Panorama facing
  2269. */
  2270. function updateCompass() {
  2271. if (!COMPASS) {
  2272. let compass = document.querySelector("img.compass__indicator");
  2273. if (compass != null) {
  2274. COMPASS = compass;
  2275. let direction = YandexPlayer.getDirection()[0] * -1;
  2276. COMPASS.setAttribute("style", `transform: rotate(${direction}deg);`);
  2277. }
  2278. }
  2279. else {
  2280. let direction = YandexPlayer.getDirection()[0] * -1;
  2281. COMPASS.setAttribute("style", `transform: rotate(${direction}deg);`);
  2282. }
  2283. }
  2284.  
  2285. /**
  2286. * Open next location in streetview player given next player and next coordinate
  2287. */
  2288.  
  2289. function goToLocation() {
  2290. myLog("Going to location");
  2291. if (nextPlayer === "Yandex") {
  2292. let options = {};
  2293. YandexPlayer.moveTo([global_lat, global_lng], options);
  2294. YandexPlayer.setDirection([0, 16]);
  2295. YandexPlayer.setSpan([10, 67]);
  2296. }
  2297. else if (nextPlayer === "Baidu") {
  2298. if (document.getElementById("PanoramaMap") !== null)
  2299. {
  2300. let urlStr2 = "https://map.baidu.com/?panotype=street&pid=" + global_BDID + "&panoid=" + global_BDID + "&from=api";
  2301. 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;
  2302. // myLog(urlStr)
  2303. if (global_BDAh != null)
  2304. {
  2305. document.getElementById("PanoramaMap").src = urlStr;
  2306. }
  2307. else
  2308. {
  2309. document.getElementById("PanoramaMap").src = urlStr2;
  2310. }
  2311. }
  2312. else
  2313. {
  2314. setTimeout(goToLocation, 250);
  2315. }
  2316. // let a = new BMap.Point(global_lng, global_lat);
  2317. // BaiduPlayer.setPov({ heading: -40, pitch: 6 });
  2318. // BaiduPlayer.setPosition(a);
  2319. }
  2320. else if (nextPlayer === "Kakao") {
  2321. var roadviewClient = new kakao.maps.RoadviewClient();
  2322. var position = new kakao.maps.LatLng(global_lat, global_lng);
  2323. roadviewClient.getNearestPanoId(position, 500, function (panoId) {
  2324. KakaoPlayer.setPanoId(panoId, position);
  2325. KakaoPlayer.setViewpoint({ pan: global_heading, tilt: global_pitch, zoom: -3 })
  2326. });
  2327. }
  2328. else if (nextPlayer === "Mapillary") {
  2329. MapillaryPlayer.moveTo(mmKey).then(
  2330. image => { //myLog(image);
  2331. },
  2332. error => { myLog(error); });
  2333. }
  2334. else if (nextPlayer === "Google") {
  2335. handleMapillary({lat: global_lat, lng: global_lng}, {meters: 500, limit: 500});
  2336. }
  2337. document.getElementById("switch").lat = global_lat;
  2338. document.getElementById("switch").lng = global_lng;
  2339. }
  2340.  
  2341. /**
  2342. * Handle undo using the location history of the current round
  2343. */
  2344.  
  2345. function goToUndoMove(data) {
  2346. /* myLog(global_lat);
  2347. myLog(global_lng); */
  2348. let options = {};
  2349. let prevStep = null;
  2350. if (locHistory.length === 1) {
  2351. prevStep = locHistory[0];
  2352. }
  2353. else {
  2354. prevStep = locHistory.pop();
  2355. }
  2356. // myLog(prevStep);
  2357. // myLog(locHistory)
  2358. if (nextPlayer === "Yandex") {
  2359. defaultPanoIdChange = false;
  2360. YandexPlayer.moveTo([prevStep[0], prevStep[1]], options);
  2361. YandexPlayer.setDirection([prevStep[2], prevStep[3]]);
  2362. YandexPlayer.setSpan([10, 67]);
  2363. document.getElementById("switch").lat = prevStep[0];
  2364. document.getElementById("switch").lng = prevStep[1];
  2365. }
  2366. else if (nextPlayer === "Kakao") {
  2367. let btn = document.querySelector("button[data-qa='undo-move']");
  2368. btn.disabled = false;
  2369. btn.classList.remove('styles_disabled__W_k45');
  2370. defaultPanoIdChange = false;
  2371. let position = new kakao.maps.LatLng(prevStep[0], prevStep[1]);
  2372. KakaoPlayer.setPanoId(prevStep[2], position);
  2373. document.getElementById("switch").lat = prevStep[0];
  2374. document.getElementById("switch").lng = prevStep[1];
  2375. document.getElementById("switch").useGoogle = false;
  2376. document.getElementById("Main Button").google = false;
  2377. // myLog("Undo 1 step");
  2378. // myLog(locHistory);
  2379. }
  2380. else if (nextPlayer === "Baidu") {
  2381. // myLog(prevStep[1]);
  2382. // let position = new BMap.Point(prevStep[1], prevStep[0]);
  2383. // let pov = { heading: prevStep[2], pitch: prevStep[3] };
  2384. // BaiduPlayer.setPosition(position);
  2385. // BaiduPlayer.setPov(pov);
  2386. // document.getElementById("switch").lat = prevStep[1];
  2387. // document.getElementById("switch").lng = prevStep[0];
  2388. }
  2389. else if (nextPlayer === "Mapillary" ) {
  2390. // myLog(prevStep[1]);
  2391.  
  2392. MapillaryPlayer.moveTo(prevStep[2]).then(
  2393. image => {
  2394. //myLog(image);
  2395. document.getElementById("switch").lat = prevStep[1];
  2396. document.getElementById("switch").lng = prevStep[0];
  2397. },
  2398. error => { myLog(error); });
  2399. }
  2400.  
  2401. }
  2402.  
  2403. function BYKTeleport()
  2404. {
  2405. let teleportButtonBYK = document.getElementById("Main Button");
  2406. if (teleportButtonBYK)
  2407. {
  2408. teleportButtonBYK.addEventListener("click", () => {
  2409. if (!teleportButtonBYK.google)
  2410. {
  2411. // myLog("non-Google Teleport");
  2412. let prevStep = null;
  2413. if (locHistory.length === 1) {
  2414. prevStep = locHistory[0];
  2415. }
  2416. else {
  2417. prevStep = locHistory[locHistory.length - 1];
  2418. }
  2419. // myLog(prevStep);
  2420. let options = {};
  2421. let place, position, pID;
  2422. if (nextPlayer === "Yandex") {
  2423. place = FindPointAtDistanceFrom(prevStep[0], prevStep[1], DegreesToRadians(prevStep[2]), teleportButtonBYK.distance * 0.001);
  2424. YandexPlayer.setDirection([prevStep[2], prevStep[3]]);
  2425. YandexPlayer.moveTo([place.lat, place.lng], options);
  2426. YandexPlayer.setSpan([10, 67]);
  2427. // locHistory.push([place.lat, place.lng, prevStep[2], prevStep[3]]);
  2428. }
  2429. else if (nextPlayer === "Kakao") {
  2430. // place = FindPointAtDistanceFrom(prevStep[0], prevStep[1], DegreesToRadians(prevStep[3]), teleportButtonBYK.distance * 0.001);
  2431. // position = new kakao.maps.LatLng(place.lat, place.lng);
  2432. // pID = KakaoPlayer.getViewpointWithPanoId();
  2433. // KakaoPlayer.setPanoId(pID.panoId, position);
  2434. // locHistory.push([place.lat, place.lng, pID.panoId, prevStep[3]]);
  2435. var roadviewClient = new kakao.maps.RoadviewClient();
  2436. place = FindPointAtDistanceFrom(prevStep[0], prevStep[1], DegreesToRadians(prevStep[3]), teleportButtonBYK.distance * 0.001);
  2437. position = new kakao.maps.LatLng(place.lat, place.lng);
  2438. roadviewClient.getNearestPanoId(position, 500, function (panoId) {
  2439. KakaoPlayer.setPanoId(panoId, position);
  2440. // myLog("Teleport 1 step");
  2441. // myLog(locHistory);
  2442. // locHistory.push([place.lat, place.lng, panoId, prevStep[3]]);
  2443. });
  2444. }
  2445. else if (nextPlayer === "Baidu") {
  2446. // place = FindPointAtDistanceFrom(prevStep[0], prevStep[1], DegreesToRadians(prevStep[2]), teleportButtonBYK.distance * 0.001);
  2447. // position = new BMap.Point(place.lng, place.lat);
  2448. // let pov = { heading: prevStep[2], pitch: prevStep[3] };
  2449. // BaiduPlayer.setPosition(position);
  2450. // BaiduPlayer.setPov(pov);
  2451.  
  2452. // locHistory.push([place.lat, place.lng, prevStep[2], prevStep[3]]);
  2453. }
  2454. else if (nextPlayer === "Mapillary" || nextPlayer === "Google") {
  2455. place = FindPointAtDistanceFrom(prevStep[0], prevStep[1], DegreesToRadians(prevStep[2]), teleportButtonBYK.distance * 0.001);
  2456. handleMapillary(place, {meters: 500, limit: 500});
  2457. // locHistory.push([place.lat, place.lng, prevStep[2], prevStep[3]]);
  2458. }
  2459. document.getElementById("switch").lat = place.lat;
  2460. document.getElementById("switch").lng = place.lng;
  2461. if (teleportButtonBYK.distance > 150)
  2462. {
  2463. teleportButtonBYK.distance = 100;
  2464. teleportButtonBYK.innerHTML = "Teleport " + teleportButtonBYK.distance + " m";
  2465. }
  2466. }
  2467. });
  2468. }
  2469. else
  2470. {
  2471. }
  2472. }
  2473.  
  2474. function SyncListener()
  2475. {
  2476. let googleKakaoButton = document.getElementById("switch");
  2477. googleKakaoButton.addEventListener("click", () => {
  2478. if (googleKakaoButton.useGoogle == false) {
  2479. // googleKakaoButton.useGoogle = true;
  2480. if (googleKakaoButton.nextPlayer === "Yandex") {
  2481. let options = {};
  2482. YandexPlayer.moveTo([googleKakaoButton.lat, googleKakaoButton.lng], options);
  2483. YandexPlayer.setDirection([document.getElementById("switch").heading, 0]);
  2484.  
  2485. // document.getElementById("switch").nextPlayer = "Yandex";
  2486. }
  2487. else if (googleKakaoButton.nextPlayer === "Kakao") {
  2488. let roadviewClient = new kakao.maps.RoadviewClient();
  2489. // myLog(googleKakaoButton.lat);
  2490. let position = new kakao.maps.LatLng(googleKakaoButton.lat, googleKakaoButton.lng);
  2491. roadviewClient.getNearestPanoId(position, 500, function (panoId) {
  2492. KakaoPlayer.setPanoId(panoId, position);
  2493. });
  2494. KakaoPlayer.setViewpoint({
  2495. pan: document.getElementById("switch").heading,
  2496. tilt: 0,
  2497. zoom: 0
  2498. });
  2499. // document.getElementById("switch").nextPlayer = "Kakao";
  2500. }
  2501. else if (googleKakaoButton.nextPlayer === "Mapillary" || googleKakaoButton.nextPlayer === "Google") {
  2502. // document.getElementById("switch").nextPlayer = "Kakao";
  2503. handleMapillary({lat: googleKakaoButton.lat, lng: googleKakaoButton.lng}, {meters: 100, limit: 100});
  2504. }
  2505. }
  2506. });
  2507.  
  2508. }
  2509.  
  2510. /**
  2511. * Gets the seed data for the current game
  2512. *
  2513. * @returns Promise with seed data as object
  2514. */
  2515. function getSeed() {
  2516. // myLog("getSeed called");
  2517. return new Promise((resolve, reject) => {
  2518. let token = getToken();
  2519. let URL;
  2520. let cred = ""
  2521.  
  2522. const PATHNAME = window.location.pathname;
  2523.  
  2524. if (PATHNAME.startsWith("/game/")) {
  2525. URL = `https://www.geoguessr.com/api/v3/games/${token}`;
  2526. }
  2527. else if (PATHNAME.startsWith("/challenge/")) {
  2528. URL = `https://www.geoguessr.com/api/v3/challenges/${token}/game`;
  2529. }
  2530. else if (PATHNAME.startsWith("/battle-royale/")) {
  2531. URL = `https://game-server.geoguessr.com/api/battle-royale/${token}`;
  2532. }
  2533. else if (PATHNAME.startsWith("/duels/") || PATHNAME.startsWith("/team-duels/")) {
  2534. URL = `https://game-server.geoguessr.com/api/duels/${token}`;
  2535. }
  2536. if (isBattleRoyale) {
  2537. fetch(URL, {
  2538. // Include credentials to GET from the endpoint
  2539. credentials: 'include'
  2540. })
  2541. .then((response) => response.json())
  2542. .then((data) => {
  2543. resolve(data);
  2544. })
  2545. .catch((error) => {
  2546. reject(error);
  2547. });
  2548. }
  2549. else {
  2550. fetch(URL)
  2551. .then((response) => response.json())
  2552. .then((data) => {
  2553. resolve(data);
  2554. })
  2555. .catch((error) => {
  2556. reject(error);
  2557. });
  2558. }
  2559. });
  2560. }
  2561.  
  2562. /**
  2563. * Gets the token from the current URL
  2564. *
  2565. * @returns token
  2566. */
  2567. function getToken() {
  2568. const PATHNAME = window.location.pathname;
  2569. if (PATHNAME.startsWith("/game/")) {
  2570. return PATHNAME.replace("/game/", "");
  2571. }
  2572. else if (PATHNAME.startsWith("/challenge/")) {
  2573. return PATHNAME.replace("/challenge/", "");
  2574. }
  2575. else if (PATHNAME.startsWith("/battle-royale/")) {
  2576. return PATHNAME.replace("/battle-royale/", "");
  2577. }
  2578. else if (PATHNAME.startsWith("/duels/")) {
  2579. return PATHNAME.replace("/duels/", "");
  2580. }
  2581. else if (PATHNAME.startsWith("/team-duels/")) {
  2582. return PATHNAME.replace("/team-duels/", "");
  2583. }
  2584. }
  2585.  
  2586. /**
  2587. * Gets the round number from the ongoing game from the page itself
  2588. *
  2589. * @returns Round number
  2590. */
  2591. function getRoundFromPage() {
  2592. const roundData = document.querySelector("div[data-qa='round-number']");
  2593. if (roundData) {
  2594. let roundElement = roundData.querySelector("div:last-child");
  2595. if (roundElement) {
  2596. let round = parseInt(roundElement.innerText.charAt(0));
  2597. if (!isNaN(round) && round >= 1 && round <= 5) {
  2598. return round;
  2599. }
  2600. }
  2601. }
  2602. else {
  2603. return ROUND;
  2604. }
  2605. }
  2606.  
  2607.  
  2608. /**
  2609. * Injects Yandex Script
  2610. */
  2611. function injectYandexScript() {
  2612. return new Promise((resolve, reject) => {
  2613. if (!YANDEX_INJECTED) {
  2614. if (YANDEX_API_KEY === "") {
  2615. myLog("No Yandex Key")
  2616. reject();
  2617. }
  2618. else {
  2619. const SCRIPT = document.createElement("script");
  2620. SCRIPT.type = "text/javascript";
  2621. SCRIPT.async = true;
  2622. SCRIPT.onload = () => {
  2623. ymaps.ready(() => {
  2624. YANDEX_INJECTED = true;
  2625. myHighlight("Yandex API Loaded");
  2626. resolve();
  2627. });
  2628. }
  2629. SCRIPT.src = `https://api-maps.yandex.ru/2.1/?lang=en_US&apikey=${YANDEX_API_KEY}`;
  2630. document.body.appendChild(SCRIPT);
  2631. }
  2632. }
  2633. else {
  2634. resolve();
  2635. }
  2636. });
  2637. }
  2638.  
  2639. /**
  2640. * Injects Yandex Player and calls handleReturnToStart
  2641. */
  2642. function injectYandexPlayer() {
  2643. let lat = 41.321861;
  2644. let lng = 69.212920;
  2645.  
  2646. let options = {
  2647. "direction": [0, 16],
  2648. "span": [10, 67],
  2649. "controls": ["zoomControl"]
  2650. };
  2651. ymaps.panorama.createPlayer("player", [lat, lng], options)
  2652. .done((player) => {
  2653. YandexPlayer = player;
  2654. YandexPlayer.events.add("directionchange", (e) => {
  2655. updateCompass();
  2656. let pov = YandexPlayer.getDirection();
  2657. if (locHistory.length > 0 && nextPlayer == "Yandex") {
  2658. document.getElementById("switch").heading = pov[0];
  2659. locHistory[locHistory.length - 1][2] = pov[0];
  2660. locHistory[locHistory.length - 1][3] = pov[1];
  2661. }
  2662. });
  2663. YandexPlayer.events.add("panoramachange", (e) => {
  2664. if (defaultPanoIdChange) {
  2665. let num = YandexPlayer.getPanorama().getPosition();
  2666. let pov = YandexPlayer.getDirection();
  2667. // myLog(num);
  2668. // myLog(pov);
  2669. if (nextPlayer == "Yandex")
  2670. {
  2671. locHistory.push([num[0], num[1], pov[0], pov[1]]);
  2672. document.getElementById("switch").lat = num[0];
  2673. document.getElementById("switch").lng = num[1];
  2674. }
  2675. let btn = document.querySelector("button[data-qa='undo-move']");
  2676. if (locHistory.length > 1) {
  2677. btn.disabled = false;
  2678. btn.classList.remove('styles_disabled__W_k45');
  2679. }
  2680. // myLog(locHistory);
  2681. }
  2682. defaultPanoIdChange = true;
  2683.  
  2684. });
  2685. myLog("Yandex Player injected");
  2686. });
  2687.  
  2688. }
  2689.  
  2690.  
  2691. /**
  2692. * Injects Baidu script
  2693. */
  2694.  
  2695. function reportWindowSize() {
  2696. let iframeC = document.getElementById("PanoramaMap");
  2697. if (iframeC)
  2698. {
  2699. iframeC.style.top = '-60px';
  2700. iframeC.style.height = (window.innerHeight + 200) + 'px';
  2701. iframeC.style.right = '-55px';
  2702. iframeC.style.width = (window.innerWidth + 55) + 'px';
  2703. }
  2704. }
  2705.  
  2706. window.onresize = reportWindowSize;
  2707.  
  2708. function injectBaiduScript() {
  2709. myLog("Iframe")
  2710. const iframe = document.createElement('iframe');
  2711.  
  2712. // iframe.src = "https://map.baidu.com/"
  2713. iframe.frameBorder = 0;
  2714. iframe.style.position = "absolute";
  2715. iframe.id = "PanoramaMap";
  2716. if (!isFirefox)
  2717. {
  2718. iframe.style.top = '-60px';
  2719. iframe.style.height = (window.innerHeight + 200) + 'px';
  2720. }
  2721. else
  2722. {
  2723. iframe.style.top = '-60px';
  2724. iframe.style.height = (window.innerHeight + 219) + 'px';
  2725. }
  2726.  
  2727. if (!isFirefox)
  2728. {
  2729. iframe.style.right = '-55px';
  2730. iframe.style.width = (window.innerWidth + 55) + 'px';
  2731. }
  2732. else
  2733. {
  2734. iframe.style.right = '-15px';
  2735. iframe.style.width = (window.innerWidth + 15) + 'px';
  2736. }
  2737.  
  2738.  
  2739.  
  2740. if (isBattleRoyale) {
  2741. if (isDuel)
  2742. {
  2743. iframe.className = "inactive"
  2744. }
  2745. else
  2746. {
  2747. iframe.className = "br-game-layout__panorama"
  2748. }
  2749. }
  2750. else {
  2751. iframe.className = "game-layout__panorama"
  2752. }
  2753. var div = document.getElementById("player");
  2754. div.style.overflow = "hidden";
  2755. div.appendChild(iframe);
  2756. }
  2757.  
  2758. /**
  2759. * Injects Kakao script
  2760. */
  2761.  
  2762. function injectKakaoScript() {
  2763. return new Promise((resolve, reject) => {
  2764. if (!KAKAO_INJECTED) {
  2765. if (KAKAO_API_KEY === "") {
  2766. myLog("No Kakao Key")
  2767. }
  2768. else {
  2769.  
  2770. let canvas = document.createElement("kmap");
  2771. if (isBattleRoyale) {
  2772. if (isDuel)
  2773. {
  2774. canvas.innerHTML = `
  2775. <div id="roadview" class="inactive" style="zIndex: 99999,position: "absolute", top: 0, left: 0, width: '100%', height: '100%',"> </div>
  2776. `;
  2777. }
  2778. else
  2779. {
  2780. canvas.innerHTML = `
  2781. <div id="roadview" class="br-game-layout__panorama" style="zIndex: 99999,position: "absolute", top: 0, left: 0, width: '100%', height: '100%',"> </div>
  2782. `;
  2783. }
  2784. }
  2785. else {
  2786. canvas.innerHTML = `
  2787. <div id="roadview" class="game-layout__panorama" style="zIndex: 99999,position: "absolute", top: 0, left: 0, width: '100%', height: '100%',"> </div>
  2788. `;
  2789. }
  2790.  
  2791. var div = document.getElementById("player");
  2792. div.appendChild(canvas);
  2793.  
  2794. const SCRIPT = document.createElement("script");
  2795. SCRIPT.async = true;
  2796. // SCRIPT.type = "text/javascript";
  2797. SCRIPT.src = `//dapi.kakao.com/v2/maps/sdk.js?appkey=${KAKAO_API_KEY}&autoload=false`;
  2798. document.body.appendChild(SCRIPT);
  2799. SCRIPT.onload = () => {
  2800. kakao.maps.load(function () {
  2801. var position = new kakao.maps.LatLng(33.450701, 126.560667);
  2802. let roadviewContainer = document.getElementById('roadview');
  2803. KakaoPlayer = new kakao.maps.Roadview(roadviewContainer);
  2804. var panoId = 1023434522;
  2805. KakaoPlayer.setPanoId(panoId, position);
  2806. KAKAO_INJECTED = true;
  2807. // Remove the compass from Kakao
  2808. kakao.maps.event.addListener(KakaoPlayer, 'init', () => {
  2809. const compassContainer = roadviewContainer.querySelector('div[id*="_box_util_"]');
  2810. if (compassContainer) compassContainer.style.display = 'none';
  2811. });
  2812. kakao.maps.event.addListener(KakaoPlayer, 'panoid_changed', function() {
  2813. if (defaultPanoIdChange && KakaoPlayer) {
  2814. let latlng = KakaoPlayer.getPosition();
  2815. let lat = latlng.getLat();
  2816. let lng = latlng.getLng();
  2817. let pID = KakaoPlayer.getViewpointWithPanoId();
  2818. if (nextPlayer == "Kakao" && lat != 33.45047613915499)
  2819. {
  2820. // myLog("push");
  2821. locHistory.push([lat, lng, pID.panoId, pID.pan]);
  2822. document.getElementById("switch").lat = lat;
  2823. document.getElementById("switch").lng = lng;
  2824. document.getElementById("switch").heading = pID.pan;
  2825. }
  2826. let btn = document.querySelector("button[data-qa='undo-move']");
  2827. if (locHistory.length > 1 && (btn != null)) {
  2828. btn.disabled = false;
  2829. btn.classList.remove('styles_disabled__W_k45');
  2830. }
  2831. // myLog(locHistory);
  2832. }
  2833. defaultPanoIdChange = true;
  2834. });
  2835. kakao.maps.event.addListener(KakaoPlayer, 'viewpoint_changed', function() {
  2836. // myLog("pov_listener attached");
  2837. let pID = KakaoPlayer.getViewpointWithPanoId();
  2838. if (locHistory.length > 0 && nextPlayer == "Kakao") {
  2839. document.getElementById("switch").heading = pID.pan;
  2840. locHistory[locHistory.length - 1][3] = pID.pan;
  2841. }
  2842. if (GooglePlayer) {
  2843. const { heading, pitch } = GooglePlayer.getPov()
  2844. if ((!almostEqual(pID.pan, heading) || !almostEqual(pID.tilt, pitch)) && nextPlayer == "Kakao") {
  2845. // Updating the google street view POV will update the compass
  2846. GooglePlayer.setPov({ heading: pID.pan, pitch: pID.tilt })
  2847. }
  2848. }
  2849. // myLog(locHistory);
  2850. })
  2851. myHighlight("Kakao API Loaded");
  2852. resolve();
  2853. });
  2854. };
  2855.  
  2856. }
  2857. }
  2858. else {
  2859. resolve();
  2860. }
  2861. });
  2862. }
  2863.  
  2864.  
  2865.  
  2866. function injectMapillaryPlayer() {
  2867. return new Promise((resolve, reject) => {
  2868. if (!MAPILLARY_INJECTED) {
  2869. if (MAPILLARY_API_KEY === "") {
  2870. let canvas = document.getElementById("player");
  2871. myLog("No Mapillary Key")
  2872. }
  2873. else {
  2874. const SCRIPT = document.createElement("script");
  2875. SCRIPT.type = "text/javascript";
  2876. SCRIPT.async = true;
  2877. SCRIPT.src = `https://unpkg.com/mapillary-js@4.0.0/dist/mapillary.js`;
  2878. document.body.appendChild(SCRIPT);
  2879. document.querySelector('head').innerHTML += '<link href="https://unpkg.com/mapillary-js@4.0.0/dist/mapillary.css" rel="stylesheet"/>';
  2880. let canvas = document.createElement("mmap");
  2881. if (isBattleRoyale) {
  2882. if (isDuel)
  2883. {
  2884.  
  2885. canvas.innerHTML = `<div id="mly" class="inactive" style="zIndex: 99999, position: 'absolute', top: 0, left: 0, width: '100%', height: '100%'"></div>`;
  2886. }
  2887. else
  2888. {
  2889. canvas.innerHTML = `<div id="mly" class="br-game-layout__panorama" style="zIndex: 99999, position: 'absolute', top: 0, left: 0, width: '100%', height: '100%'"></div>`;
  2890. }
  2891. }
  2892. else {
  2893. canvas.innerHTML = `<div id="mly" class="game-layout__panorama" style="zIndex: 99999, position: 'absolute', top: 0, left: 0, width: '100%', height: '100%'"></div>`;
  2894. }
  2895.  
  2896. var div = document.getElementById("player");
  2897. div.appendChild(canvas);
  2898.  
  2899. SCRIPT.addEventListener('load', () => {
  2900. myHighlight("Mapillary API Loaded");
  2901. // resolve(BMap);
  2902. var {Viewer} = mapillary;
  2903.  
  2904. MapillaryPlayer = new Viewer({
  2905. accessToken: MAPILLARY_API_KEY,
  2906. container: 'mly', // the ID of our container defined in the HTML body
  2907. });
  2908.  
  2909. MapillaryPlayer.on('image', async (event) => {
  2910. // cnt = cnt + 1;
  2911. // myLog(cnt);
  2912. let image = event.image;
  2913. let pos = image.originalLngLat;
  2914. let cond = true;
  2915. for (const element of locHistory) {
  2916. if (element[2] == image.id)
  2917. {
  2918. cond = false;
  2919. }
  2920. }
  2921. if (cond)
  2922. {
  2923. document.getElementById("switch").lat = pos.lat;
  2924. document.getElementById("switch").lng = pos.lng;
  2925. document.getElementById("switch").heading = image.compassAngle;
  2926. // myLog(pos);
  2927. locHistory.push([pos.lat, pos.lng, image.id, image.compassAngle]);
  2928. }
  2929. let btn = document.querySelector("button[data-qa='undo-move']");
  2930. if (btn !== null && locHistory.length > 1)
  2931. {
  2932. btn.disabled = false;
  2933. btn.classList.remove('styles_disabled__W_k45');
  2934. }
  2935. });
  2936.  
  2937. MAPILLARY_INJECTED = true;
  2938. resolve();
  2939. })
  2940.  
  2941.  
  2942. }
  2943. }
  2944. else {
  2945. resolve();
  2946. }
  2947. });
  2948. }
  2949.  
  2950.  
  2951. function handleMapillary(latlng, options)
  2952. {
  2953. myLog("handleMapillary")
  2954. handleMapillaryHelper(latlng, options).then((data) => {
  2955. //myLog(data.data)
  2956. let idToSet = 0;
  2957. let curDist = 100000000;
  2958. for (const element of data.data) {
  2959. // myLog(element)
  2960. if (element.hasOwnProperty("computed_geometry"))
  2961. {
  2962. try {
  2963. let rCord = element.computed_geometry["coordinates"];
  2964. let dist = distance(latlng.lat,latlng.lng,rCord[1],rCord[0])
  2965. if (dist < curDist)
  2966. {
  2967. idToSet = element.id;
  2968. curDist = dist
  2969. }
  2970. } catch (e) {
  2971. myLog("Error")
  2972. }
  2973. }
  2974. }
  2975. if (idToSet !== 0)
  2976. {
  2977. MapillaryPlayer.moveTo(idToSet).then(
  2978. image => { //myLog(image);
  2979. },
  2980. error => { myLog(error); });
  2981. }}).catch((error) => {
  2982. myLog(error);
  2983. });
  2984. }
  2985.  
  2986. function handleMapillaryHelper(latlng, options)
  2987. {
  2988. return new Promise((resolve, reject) => {
  2989. // myLog("1")
  2990. let bbox = getBBox(latlng, options.meters);
  2991. 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)
  2992. // myLog(URL)
  2993. fetch(URL)
  2994. .then((response) => {resolve(response.json())})
  2995. .catch((error) => {myLog(error);});
  2996. });
  2997. }
  2998.  
  2999. function moveFrom(coords, angle, distance){
  3000. const R_EARTH = 6378.137;
  3001. const M = (1 / ((2 * Math.PI / 360) * R_EARTH)) / 1000;
  3002. let radianAngle = -angle * Math.PI / 180;
  3003. let x = 0 + (distance * Math.cos(radianAngle));
  3004. let y = 0 + (distance * Math.sin(radianAngle));
  3005.  
  3006. let newLat = coords.lat + (y * M);
  3007. let newLng = coords.lng + (x * M) / Math.cos(coords.lat * (Math.PI / 180));
  3008. return { lat: newLat, lng: newLng };
  3009. }
  3010.  
  3011. function getBBox(coordinates, meters){
  3012. let SW = moveFrom(coordinates, 135, meters);
  3013. let NE = moveFrom(coordinates, 315, meters);
  3014. return `${SW.lng},${SW.lat},${NE.lng},${NE.lat}`;
  3015. }
  3016.  
  3017.  
  3018. function distance(lat1, lon1, lat2, lon2) {
  3019. var p = 0.017453292519943295; // Math.PI / 180
  3020. var c = Math.cos;
  3021. var a = 0.5 - c((lat2 - lat1) * p)/2 +
  3022. c(lat1 * p) * c(lat2 * p) *
  3023. (1 - c((lon2 - lon1) * p))/2;
  3024.  
  3025. return 1000 * 12742 * Math.asin(Math.sqrt(a)); // 2 * R; R = 6371 km
  3026. }
  3027.  
  3028.  
  3029. /**
  3030. * Minimap presets
  3031. */
  3032.  
  3033. let water_name_only =
  3034. [
  3035. {
  3036. "elementType": "geometry",
  3037. "stylers": [
  3038. {
  3039. "visibility": "off"
  3040. }
  3041. ]
  3042. },
  3043. {
  3044. "featureType": "administrative",
  3045. "stylers": [
  3046. {
  3047. "visibility": "off"
  3048. }
  3049. ]
  3050. },
  3051. {
  3052. "featureType": "landscape",
  3053. "stylers": [
  3054. {
  3055. "visibility": "off"
  3056. }
  3057. ]
  3058. },
  3059. {
  3060. "featureType": "poi",
  3061. "stylers": [
  3062. {
  3063. "visibility": "off"
  3064. }
  3065. ]
  3066. },
  3067. {
  3068. "featureType": "road",
  3069. "stylers": [
  3070. {
  3071. "visibility": "off"
  3072. }
  3073. ]
  3074. },
  3075. {
  3076. "featureType": "transit",
  3077. "stylers": [
  3078. {
  3079. "visibility": "off"
  3080. }
  3081. ]
  3082. }
  3083. ]
  3084. let country_name_only =
  3085. [
  3086. {
  3087. "elementType": "geometry",
  3088. "stylers": [
  3089. {
  3090. "visibility": "off"
  3091. }
  3092. ]
  3093. },
  3094. {
  3095. "featureType": "administrative",
  3096. "stylers": [
  3097. {
  3098. "visibility": "off"
  3099. }
  3100. ]
  3101. },
  3102. {
  3103. "featureType": "administrative.country",
  3104. "elementType": "labels",
  3105. "stylers": [
  3106. {
  3107. "visibility": "on"
  3108. }
  3109. ]
  3110. },
  3111. {
  3112. "featureType": "landscape",
  3113. "stylers": [
  3114. {
  3115. "visibility": "off"
  3116. }
  3117. ]
  3118. },
  3119. {
  3120. "featureType": "poi",
  3121. "stylers": [
  3122. {
  3123. "visibility": "off"
  3124. }
  3125. ]
  3126. },
  3127. {
  3128. "featureType": "road",
  3129. "stylers": [
  3130. {
  3131. "visibility": "off"
  3132. }
  3133. ]
  3134. },
  3135. {
  3136. "featureType": "transit",
  3137. "stylers": [
  3138. {
  3139. "visibility": "off"
  3140. }
  3141. ]
  3142. },
  3143. {
  3144. "featureType": "water",
  3145. "stylers": [
  3146. {
  3147. "visibility": "off"
  3148. }
  3149. ]
  3150. }
  3151. ]
  3152.  
  3153. let no_label_or_terrain =
  3154. [
  3155. {
  3156. "elementType": "geometry",
  3157. "stylers": [
  3158. {
  3159. "visibility": "off"
  3160. }
  3161. ]
  3162. },
  3163. {
  3164. "featureType": "administrative",
  3165. "stylers": [
  3166. {
  3167. "visibility": "off"
  3168. }
  3169. ]
  3170. },
  3171. {
  3172. "featureType": "landscape",
  3173. "stylers": [
  3174. {
  3175. "visibility": "off"
  3176. }
  3177. ]
  3178. },
  3179. {
  3180. "featureType": "poi",
  3181. "stylers": [
  3182. {
  3183. "visibility": "off"
  3184. }
  3185. ]
  3186. },
  3187. {
  3188. "featureType": "road",
  3189. "stylers": [
  3190. {
  3191. "visibility": "off"
  3192. }
  3193. ]
  3194. },
  3195. {
  3196. "featureType": "transit",
  3197. "stylers": [
  3198. {
  3199. "visibility": "off"
  3200. }
  3201. ]
  3202. },
  3203. {
  3204. "featureType": "water",
  3205. "stylers": [
  3206. {
  3207. "visibility": "on"
  3208. }
  3209. ]
  3210. },
  3211. {
  3212. "featureType": "water",
  3213. "elementType": "labels",
  3214. "stylers": [
  3215. {
  3216. "visibility": "off"
  3217. }
  3218. ]
  3219. }
  3220. ]
  3221.  
  3222. let no_label =
  3223. [
  3224. {
  3225. "elementType": "labels",
  3226. "stylers": [
  3227. {
  3228. "visibility": "off"
  3229. }
  3230. ]
  3231. },
  3232. {
  3233. "featureType": "administrative",
  3234. "stylers": [
  3235. {
  3236. "visibility": "off"
  3237. }
  3238. ]
  3239. }
  3240. ]
  3241.  
  3242. let default_preset = []
  3243.  
  3244. let presetMinimap = [[default_preset, "Default"],
  3245. [water_name_only, "Oceanman"],
  3246. [country_name_only, "Impossible"],
  3247. [no_label_or_terrain, "Streaks"],
  3248. [no_label, "Easy 5K"],
  3249. [default_preset, "Satellite"],
  3250. [default_preset, "Terrain"],
  3251. [default_preset, "Hybrid"],
  3252. [custom, "Custom", customMode]]
  3253.  
  3254.  
  3255. /**
  3256. * Display map per local laws and regulations
  3257. */
  3258.  
  3259. let historicalOverlay, historicalOverlay2, historicalOverlay3;
  3260. let TW = [[24.80, 119.00, 22.00, 123.20],
  3261. [24.20, 119.90, 22.90, 121.85],
  3262. [24.00, 120.90, 23.80, 121.20],
  3263. [23.93, 121.03, 23.85, 121.15],
  3264. [23.92, 121.055, 23.89, 121.10],
  3265. [23.92, 121.055, 23.89, 121.10],
  3266. [23.92, 121.055, 23.89, 121.10],
  3267. ]
  3268.  
  3269. let TS = [[30.40, 93.40, 28, 97.20],
  3270. [29.40, 94.55, 28.20, 96.45]]
  3271.  
  3272. let NW = [36.20, 77.70, 34.40, 80.70]