// ==UserScript== // @name Geoguessr GeoStats Script // @description Keeps track of various stats in duels games and displays it on an interactive map on your profile // @author nappyslappy // @version 2.1.0 // @match https://www.geoguessr.com/* // @grant none // @license none // @icon https://www.google.com/s2/favicons?sz=64&domain=geoguessr.com // @copyright nappyslappy 2022, (https://greasyfork.org/en/users/922456) // @namespace https://greasyfork.org/en/users/922456-nappyslappy // @downloadURL none // ==/UserScript== //Published: June 6th, 2022 //Last Update: August 6th, 2022 //******************************* SETUP *******************************// /* */ /* If you haven't already, download the free extension 'tampermonkey' */ /* and then install this script */ /* */ /* Go to your profile page and setup the script at the bottom */ /* */ /* You do not need an API key to use this script */ /* nor do you need to change anything below */ /* */ /***********************************************************************/ //************************************************************* START OF SCRIPT *************************************************************// //Global Variables let USER_ID = JSON.parse(document.getElementById('__NEXT_DATA__').innerText).props.middlewareResults[0].account.user.userId; let statsToProfile = false; let setupToProfile = false; let player_index = 0; let previous_last_guess_number = 0; //Map Colors let green_range = 0.75; let yellow_range = 0.25; let red_range = 0; if(window.localStorage.getItem(`duels-map-color-left-range-${USER_ID}`)){ green_range = parseInt(window.localStorage.getItem(`duels-map-color-right-range-${USER_ID}`)) * 0.01; yellow_range = parseInt(window.localStorage.getItem(`duels-map-color-left-range-${USER_ID}`)) * 0.01; } else{ window.localStorage.setItem(`duels-map-color-left-range-${USER_ID}`, 25); window.localStorage.setItem(`duels-map-color-right-range-${USER_ID}`, 75); } //Set the healing rounds toggle switch if(window.localStorage.getItem('allow-healing-rounds') == null){ window.localStorage.setItem('allow-healing-rounds', JSON.stringify({include: true})); } //Set the competitive mode toggle switch if(window.localStorage.getItem('competitive-only-mode') == null){ window.localStorage.setItem('competitive-only-mode', JSON.stringify({include: true})); } //Evaluate the new guess function evaluate(guess,location,distance,userScore,opponentScore,startTime,timerTime,guessTime,opponentDistance){ //If guess is in antarctica (black screen round) if(guess == 'AQ'){ return; } let correct_exists = window.localStorage.getItem(`${location}-number-correct-${USER_ID}`); let total_exists = window.localStorage.getItem(`${location}-number-total-${USER_ID}`); let correct_overall = window.localStorage.getItem(`overall-correct-${USER_ID}`); let total_overall = window.localStorage.getItem(`overall-total-${USER_ID}`); let correct_value = 1; let total_value = 1; //Setting correct value if(guess === location){ if(correct_exists !== null){ correct_value = parseInt(correct_exists,10); correct_value = correct_value + 1; } window.localStorage.setItem(`${location}-number-correct-${USER_ID}`,correct_value); } //Setting overall values if(total_overall !== null){ if(guess === location){ window.localStorage.setItem(`overall-correct-${USER_ID}`,((parseInt(correct_overall,10))+1)); } window.localStorage.setItem(`overall-total-${USER_ID}`,((parseInt(total_overall,10))+1)); } else{ if(guess === location){ window.localStorage.setItem(`overall-correct-${USER_ID}`,1); } else{ window.localStorage.setItem(`overall-correct-${USER_ID}`,0); } window.localStorage.setItem(`overall-total-${USER_ID}`,1); } //Setting total value if(total_exists !== null){ total_value = parseInt(total_exists,10); total_value = total_value + 1; } window.localStorage.setItem(`${location}-number-total-${USER_ID}`,total_value); //Setting distance let distance_average = window.localStorage.getItem(`${location}-distance-average-${USER_ID}`); let distance_number = window.localStorage.getItem(`${location}-distance-number-${USER_ID}`); if(distance_average === null && distance_number === null){ window.localStorage.setItem(`${location}-distance-average-${USER_ID}`,distance); window.localStorage.setItem(`${location}-distance-number-${USER_ID}`,1); } else{ distance_number = parseInt(distance_number) + 1; distance_average = ((distance_average * (distance_number - 1)) + distance) / distance_number; window.localStorage.setItem(`${location}-distance-average-${USER_ID}`,distance_average); window.localStorage.setItem(`${location}-distance-number-${USER_ID}`,distance_number); } //SETTING ALL OTHER STATS FOR COUNTRY AND OVERALL let countryStats = { totalCount: 0, averageScore: 0, averageDistance: 0, closerThanOpponent: 0, averageTime: 0, guessedFirst: 0, total5ks: 0, countryCorrectStreak: 0, countryCorrectMax: 0, countryWrongStreak: 0, countryWrongMax: 0, distanceFromOpponent: [0,0], }; let overallStats = { //Total totalCount: 0, totalWin: 0, totalLoss: 0, total5ks: 0, totalGames: 0, totalSeconds: 0, //Average averageScore: 0, averageDistance: 0, averageGameLengthWin: 0, averageGameLengthLoss: 0, averageTime: 0, //Other guessedFirst: 0, closerThanOpponent: 0, countryCorrectStreak: 0, countryCorrectMax: 0, countryWrongStreak: 0, countryWrongMax: 0, opponentRating: 0, distanceFromOpponent: [0,0], }; if(window.localStorage.getItem(`${location}-all-country-stats-${USER_ID}`)){ countryStats = JSON.parse(window.localStorage.getItem(`${location}-all-country-stats-${USER_ID}`)); } if(window.localStorage.getItem(`overall-country-stats-${USER_ID}`)){ overallStats = JSON.parse(window.localStorage.getItem(`overall-country-stats-${USER_ID}`)); } //Time String to Seconds function timeToSeconds(value){ let time = value.slice(11,19); time = time.split(/[.:]/); time = (parseInt(time[0]) * 60 * 60) + (parseInt(time[1]) * 60) + parseInt(time[2]); return time; } //Get Correct Time Values startTime = timeToSeconds(startTime); timerTime = timeToSeconds(timerTime); guessTime = timeToSeconds(guessTime); let timeToGuess = guessTime - startTime; //Total Count countryStats.totalCount++; overallStats.totalCount++; //Average Score countryStats.averageScore = ((countryStats.averageScore * (countryStats.totalCount - 1)) + userScore) / countryStats.totalCount; overallStats.averageScore = ((overallStats.averageScore * (overallStats.totalCount - 1)) + userScore) / overallStats.totalCount; //Average Distance countryStats.averageDistance = ((countryStats.averageDistance * (countryStats.totalCount - 1)) + distance) / countryStats.totalCount; overallStats.averageDistance = ((overallStats.averageDistance * (overallStats.totalCount - 1)) + distance) / overallStats.totalCount; //Average Time countryStats.averageTime = ((countryStats.averageTime * (countryStats.totalCount - 1)) + timeToGuess) / countryStats.totalCount; overallStats.averageTime = ((overallStats.averageTime * (overallStats.totalCount - 1)) + timeToGuess) / overallStats.totalCount; //Closer Than Opponent if(userScore >= opponentScore){ countryStats.closerThanOpponent++; overallStats.closerThanOpponent++; } //Guessed First if(guessTime == timerTime){ countryStats.guessedFirst++; overallStats.guessedFirst++; } //Total 5ks if(userScore >= 4999){ countryStats.total5ks++; overallStats.total5ks++; } //Country Streak (Correct) if(guess == location){ //Country countryStats.countryWrongStreak = 0; countryStats.countryCorrectStreak++; if(countryStats.countryCorrectStreak > countryStats.countryCorrectMax){ countryStats.countryCorrectMax = countryStats.countryCorrectStreak; } //Overall overallStats.countryWrongStreak = 0; overallStats.countryCorrectStreak++; if(overallStats.countryCorrectStreak > overallStats.countryCorrectMax){ overallStats.countryCorrectMax = overallStats.countryCorrectStreak; } } //Country Streak (Incorrect) if(guess != location){ //Country countryStats.countryCorrectStreak = 0; countryStats.countryWrongStreak++; if(countryStats.countryWrongStreak > countryStats.countryWrongMax){ countryStats.countryWrongMax = countryStats.countryWrongStreak; } //Overall overallStats.countryCorrectStreak = 0; overallStats.countryWrongStreak++; if(overallStats.countryWrongStreak > overallStats.countryWrongMax){ overallStats.countryWrongMax = overallStats.countryWrongStreak; } } //Distance From Opponent if(opponentDistance != 'DNF'){ let distanceDifference = opponentDistance - distance; //Country if(countryStats.distanceFromOpponent){ countryStats.distanceFromOpponent[0]++; countryStats.distanceFromOpponent[1] = ((countryStats.distanceFromOpponent[1] * (countryStats.distanceFromOpponent[0] - 1)) + distanceDifference) / countryStats.distanceFromOpponent[0]; } else{ countryStats.distanceFromOpponent = [1,distanceDifference]; } //Overall if(overallStats.distanceFromOpponent){ overallStats.distanceFromOpponent[0]++; overallStats.distanceFromOpponent[1] = ((overallStats.distanceFromOpponent[1] * (overallStats.distanceFromOpponent[0] - 1)) + distanceDifference) / overallStats.distanceFromOpponent[0]; } else{ overallStats.distanceFromOpponent = [1,distanceDifference]; } } //Save Updated Stats window.localStorage.setItem(`${location}-all-country-stats-${USER_ID}`, JSON.stringify(countryStats)); window.localStorage.setItem(`overall-country-stats-${USER_ID}`, JSON.stringify(overallStats)); }; //Add Stats When Game Is Finished function gameFinished(opponentRating,userBefore,userAfter,gameId,gameLength,start,end){ if(window.sessionStorage.getItem('current-game-id') == gameId){ return; } window.sessionStorage.setItem('current-game-id', gameId); //Time String to Seconds function timeToSeconds(value){ let time = value.slice(11,19); time = time.split(/[.:]/); time = (parseInt(time[0]) * 60 * 60) + (parseInt(time[1]) * 60) + parseInt(time[2]); return time; } let overallStats = JSON.parse(window.localStorage.getItem(`overall-country-stats-${USER_ID}`)); let gameTime = timeToSeconds(end) - timeToSeconds(start); //Total Games Played overallStats.totalGames++; //Average Opponent Rating overallStats.opponentRating = ((overallStats.opponentRating * (overallStats.totalGames - 1)) + opponentRating) / overallStats.totalGames; //Win or Loss let win = false; if(userAfter - userBefore >= 0){ win = true; } //Game Length (Win) if(win){ overallStats.totalWin++; overallStats.averageGameLengthWin = ((overallStats.averageGameLengthWin * (overallStats.totalWin - 1)) + gameLength) / overallStats.totalWin; } //Game Length (Loss) if(!win){ overallStats.totalLoss++; overallStats.averageGameLengthLoss = ((overallStats.averageGameLengthLoss * (overallStats.totalLoss - 1)) + gameLength) / overallStats.totalLoss; } //Total Seconds Played if(overallStats.totalSeconds){ overallStats.totalSeconds += gameTime; } else{ overallStats.totalSeconds = gameTime; } //Save Updated Stats window.localStorage.setItem(`overall-country-stats-${USER_ID}`, JSON.stringify(overallStats)); }; //Get the guess country code async function getGuessCountryCode(location){ if(location[0] <= -85.05 || location == null){ return 'AQ'; } else{ let api = "https://nominatim.openstreetmap.org/reverse.php?lat="+location[0]+"&lon="+location[1]+"&format=jsonv2"; let country_code = await fetch(api) .then(res => res.json()) .then((out) => { return out.address.country_code; }) return country_code.toUpperCase(); }; }; //Check if a new guess has been made async function checkGuess(api){ return new Promise((resolve,reject) => { fetch(api,{credentials: 'include'}) .then((res) => res.json()) .then((out) => { if(out.teams[0].players[0].playerId === USER_ID){ player_index = 0; } else if(out.teams[1].players[0].playerId === USER_ID){ player_index = 1; } else{ return; } //If competitve only mode is on let competitiveOnly = JSON.parse(window.localStorage.getItem('competitive-only-mode')); if(competitiveOnly.include && !out.options.isRated){ return; } let last_guess_number = out.teams[player_index].players[0].guesses.length; //If the game is finished if(out.status == 'Finished'){ let opponentIndex = 0; if(player_index == 0){ opponentIndex = 1; } let opponentRatingBefore = out.teams[opponentIndex].players[0].rating; let userRatingBefore = out.teams[player_index].players[0].progressChange.competitiveProgress.ratingBefore; let userRatingAfter = out.teams[player_index].players[0].progressChange.competitiveProgress.ratingAfter; let gameLength = out.currentRoundNumber; let gameStartTime = out.rounds[0].startTime; let gameEndTime = out.rounds[gameLength-1].endTime; gameFinished(opponentRatingBefore,userRatingBefore,userRatingAfter,out.gameId,gameLength,gameStartTime,gameEndTime); return; } //If the round's guesses haven't been sent if(out.teams[player_index].roundResults.length != last_guess_number){ return; } //If a new guess hasn't been made if(last_guess_number == previous_last_guess_number){ return; } else if(out.teams[player_index].players[0].guesses[last_guess_number-1].roundNumber !== out.currentRoundNumber){ return; } //If include healing toggle is off let allowHealing = JSON.parse(window.localStorage.getItem('allow-healing-rounds')); if(!allowHealing.include && out.rounds[out.currentRoundNumber-1].isHealingRound){ return; } let current_guess = [out.teams[player_index].players[0].guesses[last_guess_number-1].lat, out.teams[player_index].players[0].guesses[last_guess_number-1].lng]; //If the player refreshes during the 15 second countdown after making a guess if(current_guess[0] == window.sessionStorage.getItem('last-guess-lat') && current_guess[1] == window.sessionStorage.getItem('last-guess-lng')){ return; } else{ window.sessionStorage.setItem('last-guess-lat', current_guess[0]); window.sessionStorage.setItem('last-guess-lng', current_guess[1]); } //Everything is good previous_last_guess_number = last_guess_number; let current_round = out.currentRoundNumber; getGuessCountryCode(current_guess) .then((guess) => { //Get all values let location_code = out.rounds[current_round-1].panorama.countryCode.toUpperCase(); let distance = out.teams[player_index].players[0].guesses[last_guess_number-1].distance; let opponent_index = 0; if(player_index == 0){ opponent_index = 1; } let userScore = out.teams[player_index].roundResults[last_guess_number-1].score; let opponentScore = out.teams[opponent_index].roundResults[last_guess_number-1].score; let startTime = out.rounds[current_round-1].startTime; let timerTime = out.rounds[current_round-1].timerStartTime; let guessTime = out.teams[player_index].players[0].guesses[last_guess_number-1].created; let opponentDistance = 'DNF'; let opponentGuess = out.teams[opponent_index].players[0]; if(opponentGuess.guesses[opponentGuess.guesses.length-1].roundNumber == current_round){ opponentDistance = opponentGuess.guesses[opponentGuess.guesses.length-1].distance; } //If guess is good if(guess != undefined){ //Evaluate all values and update stats evaluate(guess,location_code,distance,userScore,opponentScore,startTime,timerTime,guessTime,opponentDistance); } resolve(out); }); }) .catch((error) => { reject(error); }); }); } //Check if the user is on the profile page function profileCheck(){ if(location.pathname.endsWith('/profile')){ if(window.localStorage.getItem(`geostats-setup-complete-${USER_ID}`) && !statsToProfile){ addMapToProfile(); } else if(!window.localStorage.getItem(`geostats-setup-complete-${USER_ID}`) && !setupToProfile){ addSetupPageToProfile(); } } else if(!location.pathname.endsWith('/profile') && statsToProfile){ statsToProfile = false; document.getElementById('map-wrapper-element').remove(); document.getElementById('css-for-map').remove(); } } //Check if the user is playing a duels game function duelsCheck(){ if(!location.pathname.startsWith('/duels/') || location.pathname.endsWith('/summary')){ return; } const game_tag = window.location.href.substring(window.location.href.lastIndexOf('/') + 1); const api_url = "https://game-server.geoguessr.com/api/duels/"+game_tag; checkGuess(api_url); }; //Run duelsCheck and profileCheck every half-second setInterval(duelsCheck,500); setInterval(profileCheck,500); //Console Log Script Name console.log('*** Geoguessr GeoStats v2.1.0 by NappySlappy ***'); /************************************************** SETUP STUFF HERE **************************************************/ //Add the setup page to the bottom of the profile page when the user uses the script for the first time function addSetupPageToProfile(){ setupToProfile = true; //Create The Setup Elements const cssForSetup = document.createElement('style'); cssForSetup.setAttribute('id','geostats-setup-css'); const htmlForSetup = document.createElement('div'); htmlForSetup.setAttribute('id','geostats-setup-html'); const scriptForSetup = document.createElement('script'); scriptForSetup.setAttribute('id','geostats-setup-script'); //CSS For Setup cssForSetup.textContent = ` #setup-page-title-wrapper{ margin: 20px auto; text-align: center; } #setup-page-title{ font-family: var(--font-neo-sans); font-size: 40px; color: white; } #setup-page-content-wrapper{ margin: 20px auto; text-align: center; width: 65%; border: solid 2px white; border-radius: 40px; } #setup-page-content{ font-family: var(--font-neo-sans); font-size: 20px; color: white; padding: 20px; } #setup-page-button-wrapper{ margin: 20px auto; text-align: center; } #setup-page-button{ border-radius: 15px; background-color: transparent; color: white; border-color: white; padding: 5px 10px 5px 10px; } #setup-page-button:hover{ background-color: white; color: black; border-color: black; cursor: pointer; } `; //HTML For Setup htmlForSetup.innerHTML = `

Welcome To GeoStats!

`; //SCRIPT For Setup scriptForSetup.textContent = ` let currentSlide = 0; let firstSlide = "This script was made to keep track of various stats in duels matches. It will monitor your duels guesses and keep a unique record of stats for each country, as well as for your overall stats. If there is a round where you don't make a guess, it won't count against you. Guesses made in antarctica will also not count since it is not available on the map."; let secondSlide = "All of the stats will be visible at the bottom of your profile page. Some countries are too small to show on the map so there is a search bar on the left side to filter through them. You can hover over a country to see your percentage of getting it correct and double click it to view more detailed stats."; let thirdSlide = "You can reset your stats by clicking the 'Reset All Scores' button in settings, as well as for individual countries. Keep in mind that all information is stored in your browser on your device so the same stats will not be available on different devices or on different browsers. This means that clearing your browser cache will unfortunatlely also clear all of your stats."; let fourthSlide = "The creator of this script is NappySlappy. Please leave some feedback if you like the script or if you have any ideas for improvements. Thanks! :)"; let allSliders = [firstSlide,secondSlide,thirdSlide,fourthSlide]; function changeSlide(){ currentSlide++; if(currentSlide == allSliders.length){ window.localStorage.setItem('geostats-setup-complete-${USER_ID}', new Date()); document.getElementById('geostats-setup-css').remove(); document.getElementById('geostats-setup-html').remove(); } else{ if(currentSlide == allSliders.length-1){ document.getElementById('setup-page-button').textContent = 'View Stats'; } document.getElementById('setup-page-content').textContent = allSliders[currentSlide]; } } document.getElementById('setup-page-content').textContent = allSliders[0]; document.getElementById('setup-page-button').addEventListener('click', changeSlide); `; //Add Everything To The Page let referenceNode = document.getElementsByClassName('version3_main__xNkED')[0]; let siblingNode = document.getElementsByClassName('footer_footer__NmtmJ')[0]; referenceNode.parentNode.insertBefore(htmlForSetup, siblingNode); document.head.appendChild(cssForSetup); document.getElementById('geostats-setup-html').appendChild(scriptForSetup); } /************************************************** MAP STUFF HERE **************************************************/ //Add the map (and related stuff) to the bottom of the profile page function addMapToProfile(){ statsToProfile = true; const svgMap = document.createElement('div'); svgMap.setAttribute('id','map-wrapper-element'); const cssForMap = document.createElement('style'); cssForMap.setAttribute('id', 'css-for-map'); const scriptForMap = document.createElement('script'); scriptForMap.setAttribute('id', 'script-for-map'); cssForMap.textContent = ` .map-wrapper-element{ position: relative; left: 0px; } #map-title{ font-size: 30px; text-align: center; color: var(--ds-color-yellow-50); font-family: var(--font-neo-sans); } #total-percentage-wrapper{ width: 100%; background-color: gray; height: 50px; position: relative; } #total-percentage-text-wrapper{ position: absolute; left: 0; right: 0; height: 100%; } #total-percentage-text{ display: flex; font-size: 20px; height: 100%; justify-content: center; align-items: center; color: black; } #total-percentage-bar{ width: 50%; height: 100%; background-color: gold; } .display-wrapper{ margin: 0 auto; padding: 10px; width: fit-content; font-size: 20px; } .display-wrapper #display-country-details{ visibility: show; color: white; } .display-wrapper #display-country-distance{ visibility: show; font-size: 16px; display: flex; align-items: center; justify-content: center; } .map-wrapper{ margin: 0 auto; pointer-events: none; padding-bottom: 25px; } #world-map { display: block; position: relative; top: 0; left: 0; width: 100%; height: 100%; pointer-events: auto; transform: scale(1); transform-origin: 0px 0px; z-index: 2; border-top-style: solid; border-bottom-style: solid; border-width: 0.5px; border-color: #fbfafa; } #world-map path{ stroke: white; fill: black; transition: fill 0.3s ease; pointer-events: all; } #world-map path:hover{ fill: rgb(175, 175, 175); pointer-events: all; cursor: pointer; } #details-box { padding: 1rem; border-radius: 8px; font-size: 14px; position: fixed; color: white; font-family: "Poppins"; background-color: gray; width: fit-content; transform: translateX(-50%); transition: opacity .4s ease; z-index: 3; } #search-bar-wrapper{ pointer-events: all; position: absolute; z-index: 3; } #search-bar { box-sizing: border-box; z-index: 3; } #search-bar-list { list-style: none; display: none; z-index: 3; } #search-bar-list li { padding: 10px; width: 73.5%; border-bottom: 2px solid #ffffff; z-index: 3; text-align: center; } #search-bar-list li:hover { background: #ffffff; color: #000000; cursor: pointer; } #overall-stats-page-wrapper{ } #overall-stats-display-details{ color: var(--ds-color-yellow-50); margin: 0 auto; width: fit-content; font-size: 30px; padding: 20px; } #overall-stats-values-progress-circles{ display: flex; height: 300px; flex-direction: row; flex-wrap: wrap; } #overall-stats-values-bottom{ border-top: .0625rem solid; margin-top: 360px; margin-bottom: 50px; display: flex; flex-direction: row; flex-wrap: wrap; } .overall-stats-bottom-elements{ margin: 20px 0; width: 33.333%; text-align: center; display: flex; flex-direction: column; } #overall-stats-distance-from-opponent-value{ font-size: 30px; width: 50%; margin: 20px 25%; } #overall-stats-total-play-time-value{ font-size: 30px; width: 50%; margin: 20px 25%; } #country-stats-page-wrapper{ } #country-stats-display-title{ margin: 0 auto; padding: 10px; width: fit-content; font-size: 20px; } #country-stats-display-details{ visibility: show; color: white; } #country-stats-wrapper{ } #country-stats-values{ display: flex; height: 300px; flex-direction: row; flex-wrap: wrap; } .country-stat-wrapper{ width: 33.333%; height: 50%; text-align: center; display: flex; flex-direction: column; } .country-stat-outer-circle{ position: relative; height: 100px; width: 100px; border-radius: 50%; margin: auto; } .country-stat-inner-circle{ position: absolute; height: 85%; width: 85%; border-radius: 50%; background-color: #1a1a2e; top: 0; bottom: 0; left: 0; right: 0; margin: auto; } .country-stat-value-wrapper{ display: flex; align-items: center; justify-content: center; color: white; height: 100%; } .country-stat-value{ font-size: 25px; } .country-stat-title{ position: relative; color: #ffffff; margin: auto; } .country-stat-spacing-wrapper{ width: 100%; height: 25%; } #country-stats-values-bottom{ border-top: .0625rem solid; margin-top: 100px; display: flex; flex-direction: row; flex-wrap: wrap; } .country-stats-bottom-elements{ margin: 20px 0; width: 50%; text-align: center; display: flex; flex-direction: column; } #country-stats-distance-from-opponent-value{ font-size: 30px; width: 50%; margin: 20px 25%; } #country-stats-reset-btn-wrapper{ padding: 20px 0px 100px 0px; text-align: center; } #country-stats-reset-btn{ border-color: red; background-color: red; color: white; } #country-stats-reset-btn:hover{ cursor: pointer; } #map-settings-wrapper{ var(--font-neo-sans); text-align: center; display: none; } #map-settings-title{ font-size: 40px; margin-top: 20px; padding-bottom: 20px; } #map-settings-content{ } #settings-map-color-ranges-wrapper{ border-top: 2px solid white; padding-bottom: 50px; padding-top: 25px; margin-left: 50px; margin-right: 50px; } #map-color-ranges-slider-wrapper{ position: relative; } #slider-output-wrapper{ position: relative; margin-top: 20px; width: 100%; } #left-slider-output{ position: absolute; left: 50%; } #right-slider-output{ position: absolute; left: 50%; } #map-color-ranges-slider{ position: relative; width: 100%; height: 100px; margin-top: 0px; } #slider-track{ width: 100%; height: 5px; position: absolute; margin: auto; top: 0; bottom: 0; border-radius: 5px; } .map-color-ranges{ -webkit-appearance: none; -moz-appearance: none; appearance: none; width: 100%; outline: none; position: absolute; margin: 0px -50%; top: 0; bottom: 0; background-color: transparent; pointer-events: none; border-color: transparent; padding: 0px; } .map-color-ranges::-webkit-slider-runnable-track{ -webkit-appearance: none; height: 5px; } .map-color-ranges::-webkit-slider-thumb{ -webkit-appearance: none; height: 1.7em; width: 1.7em; background-color: #ffffff; cursor: pointer; margin-top: -9px; pointer-events: auto; border-radius: 50%; border: 1px solid #808080; } #settings-toggles-wrapper{ border-top: 2px solid white; padding-bottom: 50px; padding-top: 25px; margin-left: 50px; margin-right: 50px; text-align: center; display: flex; } #settings-allow-healing-rounds-wrapper{ flex: 1; } #settings-allow-healing-rounds{ height: 0; width: 0; visibility: hidden; } #label-allow-healing{ cursor: pointer; text-indent: -9999px; width: 50px; height: 25px; background: gray; display: block; border-radius: 25px; position: relative; margin: auto; } #label-allow-healing:after{ content: ''; position: absolute; top: 1.25px; left: 3px; width: 22.5px; height: 22.5px; background: #fff; border-radius: 22.5px; transition: 0.3s; } #settings-allow-healing-rounds:checked + #label-allow-healing{ background: #bada55; } #settings-allow-healing-rounds:checked + #label-allow-healing:after{ left: calc(100% - 5px); transform: translateX(-100%); } #label-allow-healing:active:after{ width: 32.5px; } #settings-competitive-only-mode-wrapper{ flex: 1; } #settings-competitive-only-mode{ height: 0; width: 0; visibility: hidden; } #label-competitive-only{ cursor: pointer; text-indent: -9999px; width: 50px; height: 25px; background: gray; display: block; border-radius: 25px; position: relative; margin: auto; } #label-competitive-only:after{ content: ''; position: absolute; top: 1.25px; left: 3px; width: 22.5px; height: 22.5px; background: #fff; border-radius: 22.5px; transition: 0.3s; } #settings-competitive-only-mode:checked + #label-competitive-only{ background: #bada55; } #settings-competitive-only-mode:checked + #label-competitive-only:after{ left: calc(100% - 5px); transform: translateX(-100%); } #label-competitive-only:active:after{ width: 32.5px; } #unit-selector{ border-top: 2px solid white; padding-bottom: 50px; padding-top: 25px; margin-left: 50px; margin-right: 50px; } #unit-selector-mi, #unit-selector-km{ accent-color: #bada55; } #unit-selector-mi:hover, #unit-selector-km:hover{ cursor: pointer; } #settings-reset-scores-btn-wrapper{ border-top: 2px solid white; padding-bottom: 50px; padding-top: 25px; margin-left: 50px; margin-right: 50px; } #reset-scores-btn{ border-color: red; background-color: red; color: white; } #reset-scores-btn:hover{ cursor: pointer; } #map-settings-btn-wrapper{ text-align: center; margin-bottom: 10px; } #map-settings-btn{ border-radius: 15px; background-color: transparent; color: white; border-color: white; padding: 5px 10px 5px 10px; } #map-settings-btn:hover{ background-color: white; color: black; border-color: black; cursor: pointer; } #footer-wrapper{ display: flex; } #version-number{ flex: 1; font-family: Arial; padding-left: 10px } #feedback-link-wrapper{ flex: 1; font-family: Arial; text-align: center; } #creator-tag{ flex: 1; font-family: Arial; padding-right: 10px; padding-bottom: 10px; text-align: right; } `; svgMap.innerHTML = `

GeoStats

Country Name: 0 / 0 (0%)

Average Distance: 0.0 km

OVERALL STATS

Average Score

Average Distance (km)

Closer Than Opponent

Average Time (sec)

Guessed First

Total 5ks

Average Rounds Played (Win)

Average Rounds Played (Loss)

Opponent Rating

AVERAGE DISTANCE FROM OPPONENT

COUNTRY STREAKS

Current:

Highest: Correct | Incorrect

TIME PLAYED

SETTINGS

Map Color Ranges

Units

Include Healing Rounds

Competitive Only Mode

`; scriptForMap.textContent = ` { let countries = ['AF','AX','AL','DZ','AS','AD','AO','AI','AQ','AG','AR','AM','AW','AU','AT','AZ','BS','BH','BD','BB','BY','BE','BZ','BJ','BM','BT','BO','BQ','BA','BW','BV','BR','IO','BN','BG','BF','BI','KH','CM','CA','CV','KY','CF','TD','CL','CN','CX','CC','CO','KM','CG','CD','CK','CR','CI','HR','CU','CW','CY','CZ','DK','DJ','DM','DO','EC','EG','SV','GQ','ER','EE','ET','FK','FO','FJ','FI','FR','GF','PF','TF','GA','GM','GE','DE','GH','GI','GR','GL','GD','GP','GU','GT','GG','GN','GW','GY','HT','HM','VA','HN','HK','HU','IS','IN','ID','IR','IQ','IE','IM','IL','IT','JM','JP','JE','JO','KZ','KE','KI','KP','KR','XK','KW','KG','LA','LV','LB','LS','LR','LY','LI','LT','LU','MO','MK','MG','MW','MY','MV','ML','MT','MH','MQ','MR','MU','YT','MX','FM','MD','MC','MN','ME','MS','MA','MZ','MM','NA','NR','NP','NL','NC','NZ','NI','NE','NG','NU','NF','MP','NO','OM','PK','PW','PS','PA','PG','PY','PE','PH','PN','PL','PT','PR','QA','RS','RE','RO','RU','RW','BL','SH','KN','LC','MF','VC','WS','ST','SA','SN','SC','SL','SG','SX','SK','SI','SB','SO','ZA','GS','SS','ES','LK','SD','SR','SJ','SZ','SE','CH','SY','TW','TJ','TZ','TH','TL','TG','TK','TO','TT','TN','TR','TM','TC','TV','UG','UA','AE','GB','US','UM','UY','UZ','VU','VE','VN','VG','VI','WF','EH','YE','ZM','ZW','SM']; let once = false; document.getElementById("details-box").style.opacity = "0%"; //UNIT SELECTION if(window.localStorage.getItem('units-svg-map') === 'mi'){ document.getElementById('unit-selector-mi').checked = true; } else if(window.localStorage.getItem('units-svg-map') === 'km'){ document.getElementById('unit-selector-km').checked = true; } document.getElementById('unit-selector-mi').addEventListener('click', function(){ window.localStorage.setItem('units-svg-map', 'mi'); }); document.getElementById('unit-selector-km').addEventListener('click', function(){ window.localStorage.setItem('units-svg-map', 'km'); }); //MAP SETUP document.getElementById('map-wrapper-element').addEventListener('mousemove', function(e){ if(once){ if(window.location.pathname.endsWith('/profile')){ return; } once = false; } if(!window.location.pathname.endsWith('/profile')){ return; } once = true; //Percentage Bar let correct_total = parseInt(window.localStorage.getItem('overall-correct-${USER_ID}')); let total_total = parseInt(window.localStorage.getItem('overall-total-${USER_ID}')); let percentage_total = Math.floor((correct_total / total_total) * 100); document.getElementById('total-percentage-bar').style.width = percentage_total + '%'; document.getElementById('total-percentage-text').innerHTML = 'Overall Score: ' + correct_total + ' / ' + total_total + ' (' + percentage_total +'%) '; if(percentage_total >= 100*${green_range}){ document.getElementById('total-percentage-bar').style.backgroundColor = 'green'; } else if(percentage_total >= 100*${yellow_range}){ document.getElementById('total-percentage-bar').style.backgroundColor = 'yellow'; } else if(percentage_total >= 100*${red_range}){ document.getElementById('total-percentage-bar').style.backgroundColor = 'red'; } //Country colors countries.forEach(function(country){ let correct = 0; let total = 0; if(window.localStorage.getItem(country + '-number-correct-${USER_ID}') !== null){ correct = window.localStorage.getItem(country + '-number-correct-${USER_ID}'); } if(window.localStorage.getItem(country + '-number-total-${USER_ID}') !== null){ total = window.localStorage.getItem(country + '-number-total-${USER_ID}'); } let percentage = parseInt(correct) / parseInt(total); if(correct === 0 && total === 0){ percentage = 'none'; } let targetCountry = document.getElementById(country); if(!targetCountry){ return; } //Setting the countries to a color based on their percentage if(percentage >= ${green_range}){ targetCountry.setAttribute('style', 'fill: lightgreen'); //green } else if(percentage >= ${yellow_range}){ targetCountry.setAttribute('style', 'fill: rgb(233, 233, 84)'); //yellow } else if(percentage >= ${red_range}){ targetCountry.setAttribute('style', 'fill: lightcoral'); //red } else{ targetCountry.setAttribute('style', 'fill: black'); } }); //OVERALL STATS SETUP let overallStats = JSON.parse(window.localStorage.getItem('overall-country-stats-${USER_ID}')); let percentage; let percentageColor; let totalCount = overallStats.totalCount; let totalWin = overallStats.totalWin; let totalLoss = overallStats.totalLoss; let total5ks = overallStats.total5ks; let totalGames = overallStats.totalGames; let averageScore = Math.floor(overallStats.averageScore); let averageDistance = Math.floor(overallStats.averageDistance/1000); let gameLengthWin = overallStats.averageGameLengthWin; let gameLengthLoss = overallStats.averageGameLengthLoss; let averageTime = Math.floor(overallStats.averageTime); let guessedFirst = overallStats.guessedFirst; let closerThanOpponent = overallStats.closerThanOpponent; let correctStreak = overallStats.countryCorrectStreak; let correctMax = overallStats.countryCorrectMax; let wrongStreak = overallStats.countryWrongStreak; let wrongMax = overallStats.countryWrongMax; let opponentRating = Math.floor(overallStats.opponentRating); //Find correct percentage to color the outside circle function findPercentage(stat, max){ percentage = (stat/max); if(percentage >= ${green_range}){ percentageColor = 'green'; } else if(percentage >= ${yellow_range}){ percentageColor = 'yellow'; } else{ percentageColor = 'red'; } percentage = 100 * percentage; if(percentage <= 0){ percentage = 2; } }; //Average Score findPercentage(averageScore, 5000); document.getElementById('overall-stat-average-score-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)'; document.getElementById('overall-stat-average-score-value').innerText = averageScore; //Average Distance findPercentage(2500-averageDistance, 2500); document.getElementById('overall-stat-average-distance-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)'; if(window.localStorage.getItem('units-svg-map') == 'mi'){ document.getElementById('overall-stat-average-distance-title').innerText = 'Average Distance (mi)'; averageDistance = Math.floor(averageDistance / 1.609); } else{ document.getElementById('country-stat-average-distance-title').innerText = 'Average Distance (km)'; } document.getElementById('overall-stat-average-distance-value').innerText = averageDistance; //Closer Than Opponent findPercentage(closerThanOpponent, totalCount); document.getElementById('overall-stat-closer-than-opponent-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)'; document.getElementById('overall-stat-closer-than-opponent-value').innerText = Math.floor((100 * (closerThanOpponent/totalCount))) + '%'; //Average Time findPercentage(120-averageTime, 120); document.getElementById('overall-stat-average-time-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)'; document.getElementById('overall-stat-average-time-value').innerText = averageTime; //Guessed First findPercentage(guessedFirst, totalCount); document.getElementById('overall-stat-guessed-first-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)'; document.getElementById('overall-stat-guessed-first-value').innerText = Math.floor((100 * (guessedFirst/totalCount))) + '%'; //Total 5ks findPercentage(total5ks, 100); document.getElementById('overall-stat-total-5ks-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)'; document.getElementById('overall-stat-total-5ks-value').innerText = total5ks; //Game Length (Win) findPercentage(15-gameLengthWin, 15); document.getElementById('overall-stat-average-game-length-win-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)'; document.getElementById('overall-stat-average-game-length-win-value').innerText = Math.round(10 * gameLengthWin) / 10; //Game Length (Loss) findPercentage(gameLengthLoss, 15); document.getElementById('overall-stat-average-game-length-loss-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)'; document.getElementById('overall-stat-average-game-length-loss-value').innerText = Math.round(10 * gameLengthLoss) / 10; //Opponent Rating findPercentage(opponentRating, 1200); document.getElementById('overall-stat-opponent-rating-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)'; document.getElementById('overall-stat-opponent-rating-value').innerText = opponentRating; //BOTTOM STATS SETUP //Distance From Opponent let distanceFromOpponent = [Math.round(overallStats.distanceFromOpponent[1] / 1000),'km','+','green']; if(window.localStorage.getItem('units-svg-map') == 'mi'){ distanceFromOpponent[0] = Math.round(distanceFromOpponent[0] / 1.609); distanceFromOpponent[1] = 'mi'; } if(distanceFromOpponent[0] < 0){ distanceFromOpponent[0] *= -1; distanceFromOpponent[2] = '-'; distanceFromOpponent[3] = 'red'; } document.getElementById('overall-stats-distance-from-opponent-value').style.color = distanceFromOpponent[3]; document.getElementById('overall-stats-distance-from-opponent-value').innerText = distanceFromOpponent[2] + distanceFromOpponent[0] + ' ' + distanceFromOpponent[1]; //Country Streaks if(overallStats.countryCorrectStreak > 0){ document.getElementById('overall-stats-country-streaks-value-current-value').innerText = overallStats.countryCorrectStreak + ' Correct'; document.getElementById('overall-stats-country-streaks-value-current-value').style.color = 'green'; } else if(overallStats.countryWrongStreak > 0){ document.getElementById('overall-stats-country-streaks-value-current-value').innerText = overallStats.countryWrongStreak + ' Incorrect'; document.getElementById('overall-stats-country-streaks-value-current-value').style.color = 'red'; } document.getElementById('overall-stats-country-streaks-value-max-correct-value').innerText = overallStats.countryCorrectMax; document.getElementById('overall-stats-country-streaks-value-max-wrong-value').innerText = overallStats.countryWrongMax; //Time Played let minutesPlayed = Math.floor(Math.floor(overallStats.totalSeconds / 60) % 60); let hoursPlayed = Math.floor(overallStats.totalSeconds / 3600); document.getElementById('overall-stats-total-play-time-value').innerText = hoursPlayed + 'h ' + minutesPlayed + 'm '; }); function mouseOverCountry(country){ if(typeof country.target !== 'undefined'){ country = country.target; } if (country.tagName == 'path'){ let content = country.dataset.name; document.getElementById("details-box").innerHTML = content; document.getElementById("details-box").style.opacity = "100%"; //Changing the color when you hover over a country if(country.style.fill == 'lightcoral'){ country.setAttribute('style', 'fill:red'); } else if(country.style.fill == 'lightgreen'){ country.setAttribute('style', 'fill:green'); } else if(country.style.fill == 'rgb(233, 233, 84)'){ country.setAttribute('style', 'fill:yellow'); } else if(country.style.fill == 'black'){ country.setAttribute('style', 'fill:rgb(175, 175, 175)'); } //Displaying the country and the stats at the top of the page let countryName = country.dataset.name; let countryCorrect = 0; let countryTotal = 0; let countryPercentage = 0; let countryDistance = 0.0; let distanceUnit = 'km'; let target = country.id; if(window.localStorage.getItem(target + '-number-correct-${USER_ID}') !== null){ countryCorrect = window.localStorage.getItem(target + '-number-correct-${USER_ID}'); } if(window.localStorage.getItem(target + '-number-total-${USER_ID}') !== null){ countryTotal = window.localStorage.getItem(target + '-number-total-${USER_ID}'); } if((countryCorrect !== 0) && (countryTotal !== 0)){ countryPercentage = Math.floor(100 * (parseInt(countryCorrect) / parseInt(countryTotal))); } if(window.localStorage.getItem(target + '-distance-average-${USER_ID}') !== null){ countryDistance = parseInt(window.localStorage.getItem(target + '-distance-average-${USER_ID}')) / 1000; if(document.getElementById('unit-selector-mi').checked){ countryDistance = countryDistance / 1.609; } countryDistance = round(countryDistance,1); } if(document.getElementById('unit-selector-mi').checked){ distanceUnit = 'mi'; } document.getElementById("display-country-details").textContent = countryName + ": " + countryCorrect + " / " + countryTotal + " (" + countryPercentage + "%)"; document.getElementById("display-country-details").style.visibility = "visible"; document.getElementById("display-country-distance").textContent = 'Average Distance: ' + countryDistance + ' ' + distanceUnit; document.getElementById("display-country-distance").style.visibility = "visible"; } else { document.getElementById("details-box").style.opacity = "0%"; } }; function mouseOutCountry(country){ if(typeof country.target !== 'undefined'){ country = country.target; } if (country.tagName == 'path'){ //Changing the color when you stop hovering over a country if(country.style.fill == 'red'){ country.setAttribute('style', 'fill:lightcoral'); } if(country.style.fill == 'green'){ country.setAttribute('style', 'fill:lightgreen'); } if(country.style.fill == 'yellow'){ country.setAttribute('style', 'fill:rgb(233, 233, 84)'); } if(country.style.fill == 'rgb(175, 175, 175)'){ country.setAttribute('style', 'fill:black'); } //Hiding the display at the top when no country is hovering document.getElementById("display-country-details").style.visibility = "hidden"; document.getElementById("display-country-distance").style.visibility = "hidden"; } }; //DETAILS BOX window.onmousemove = function(e){ let detailsBox = document.getElementById('details-box'); let x = e.clientX; let y = e.clientY; detailsBox.style.top = (y + 20) + 'px'; detailsBox.style.left = (x) + 'px'; }; function round(value, precision) { let multiplier = Math.pow(10, precision || 0); return Math.round(value * multiplier) / multiplier; }; //REGULAR LISTENERS document.getElementById('map-wrapper-element').addEventListener('mouseover', mouseOverCountry); document.getElementById('map-wrapper-element').addEventListener('mouseout', mouseOutCountry); //SEARCH LIST function mouseOverList(e){ let temp = e.target.id.toUpperCase(); let target_country = document.getElementById(temp); mouseOverCountry(target_country); } function mouseOutList(e){ let temp = e.target.id.toUpperCase(); let target_country = document.getElementById(temp); mouseOutCountry(target_country); } document.getElementById('search-bar').addEventListener('click', () => { let search_bar = document.getElementById('search-bar'); let list = document.querySelectorAll('#search-bar-list li'); list.forEach(item => item.addEventListener('mouseover', mouseOverList)); list.forEach(item => item.addEventListener('mouseout', mouseOutList)); search_bar.onkeyup = () => { let search = search_bar.value.toLowerCase(); let count = 0; if(search_bar.value !== ''){ document.getElementById('search-bar-list').style.display = 'inline'; } else{ document.getElementById('search-bar-list').style.display = 'none'; } //Showing the results that match and hiding those that dont (max 6 items) for(let i of list){ let item = i.innerHTML.toLowerCase(); if(item.indexOf(search) == -1){ i.style.display = 'none'; } else{ if(count < 6){ count = count + 1; i.style.display = 'block'; } else{ i.style.display = 'none'; } } }; }; }); //OPEN AND CLOSE SETTINGS (and get back to homepage from country stats) document.getElementById('map-settings-btn').addEventListener('click', () => { if(document.getElementById('map-settings-btn').innerText == 'Back to Map'){ document.getElementById('map-settings-wrapper').style.display = 'none'; document.getElementById("country-stats-page-wrapper").style.display = 'none'; document.getElementById('map-settings-btn').innerText = 'Settings'; document.getElementsByClassName('display-wrapper')[0].style.display = 'block'; document.getElementById('search-bar-wrapper').style.display = 'block'; document.getElementsByClassName('map-wrapper')[0].style.display = 'block'; document.getElementById('overall-stats-page-wrapper').style.display = 'block'; } else{ document.getElementById('map-settings-wrapper').style.display = 'block'; document.getElementById('map-settings-btn').innerText = 'Back to Map'; document.getElementsByClassName('display-wrapper')[0].style.display = 'none'; document.getElementById('search-bar-wrapper').style.display = 'none'; document.getElementsByClassName('map-wrapper')[0].style.display = 'none'; document.getElementById('overall-stats-page-wrapper').style.display = 'none'; } }); //SET HEALING ROUNDS TOGGLE IN SETTINGS let healing = JSON.parse(window.localStorage.getItem('allow-healing-rounds')); if(healing.include){ document.getElementById('settings-allow-healing-rounds').checked = true; } else{ document.getElementById('settings-allow-healing-rounds').checked = false; } document.getElementById('settings-allow-healing-rounds').addEventListener('click', () => { if(document.getElementById('settings-allow-healing-rounds').checked){ window.localStorage.setItem('allow-healing-rounds', JSON.stringify({include: true})); } else{ window.localStorage.setItem('allow-healing-rounds', JSON.stringify({include: false})); } }); //SET COMPETITIVE ONLY TOGGLE IN SETTINGS let competitive = JSON.parse(window.localStorage.getItem('competitive-only-mode')); if(competitive.include){ document.getElementById('settings-competitive-only-mode').checked = true; } else{ document.getElementById('settings-competitive-only-mode').checked = false; } document.getElementById('settings-competitive-only-mode').addEventListener('click', () => { if(document.getElementById('settings-competitive-only-mode').checked){ window.localStorage.setItem('competitive-only-mode', JSON.stringify({include: true})); } else{ window.localStorage.setItem('competitive-only-mode', JSON.stringify({include: false})); } }); //RESET ALL SCORES document.getElementById('reset-scores-btn').addEventListener('click', () => { if(confirm('Are you sure you want to reset your stats? This cannot be undone.')){ //Remove country scores countries.forEach(function(country){ window.localStorage.removeItem(country + '-number-correct-${USER_ID}'); window.localStorage.removeItem(country + '-number-total-${USER_ID}'); window.localStorage.removeItem(country + '-distance-average-${USER_ID}'); window.localStorage.removeItem(country + '-distance-number-${USER_ID}'); window.localStorage.removeItem(country + '-all-country-stats-${USER_ID}'); }); //Remove overall scores window.localStorage.removeItem('overall-total-${USER_ID}'); window.localStorage.removeItem('overall-correct-${USER_ID}'); window.localStorage.removeItem('overall-country-stats-${USER_ID}'); //Reload the page location.reload(); } }); //OPEN COUNTRY STATS PAGE document.getElementById('map-wrapper-element').addEventListener('dblclick', (e) => { let countryId = (e.path[0].id).toUpperCase(); if(countryId.length != 2){ return; } //Set the stats to the correct values for the country setCountryStats(countryId); window.localStorage.setItem('select-country-stats-id', countryId); document.getElementById('search-bar-wrapper').style.display = 'none'; document.getElementById('overall-stats-page-wrapper').style.display = 'none'; document.getElementsByClassName('map-wrapper')[0].style.display = 'none'; document.getElementsByClassName('display-wrapper')[0].style.display = 'none'; let countryName = e.path[0].dataset.name; let countryCorrect = 0; let countryTotal = 0; let countryPercentage = 0; if(typeof countryName == 'undefined'){ countryName = e.path[0].textContent; } if(window.localStorage.getItem(countryId + '-number-correct-${USER_ID}') !== null){ countryCorrect = window.localStorage.getItem(countryId + '-number-correct-${USER_ID}'); } if(window.localStorage.getItem(countryId + '-number-total-${USER_ID}') !== null){ countryTotal = window.localStorage.getItem(countryId + '-number-total-${USER_ID}'); } if((countryCorrect !== 0) && (countryTotal !== 0)){ countryPercentage = Math.floor(100 * (parseInt(countryCorrect) / parseInt(countryTotal))); } document.getElementById('country-stats-display-details').textContent = countryName + ": " + countryCorrect + " / " + countryTotal + " (" + countryPercentage + "%)"; document.getElementById('country-stats-reset-btn').textContent = 'Reset All ' + countryName + ' Stats'; document.getElementById("country-stats-page-wrapper").style.display = 'block'; document.getElementById('map-settings-btn').innerText = 'Back to Map'; }); //SET COUNTRY STATS function setCountryStats(countryCode){ let countryObject = JSON.parse(window.localStorage.getItem(countryCode + '-all-country-stats-${USER_ID}')); let percentage; let percentageColor; //Country Stats let totalCount = countryObject.totalCount; let averageScore = Math.floor(countryObject.averageScore); let averageDistance = Math.floor(countryObject.averageDistance/1000); let closerThanOpponent = countryObject.closerThanOpponent; let averageTime = Math.floor(countryObject.averageTime); let guessedFirst = countryObject.guessedFirst; let total5ks = countryObject.total5ks; //Find correct percentage to color the outside circle function findPercentage(stat, max){ percentage = (stat/max); if(percentage >= ${green_range}){ percentageColor = 'green'; } else if(percentage >= ${yellow_range}){ percentageColor = 'yellow'; } else{ percentageColor = 'red'; } percentage = 100 * percentage; if(percentage <= 0){ percentage = 2; } }; //Average Score findPercentage(averageScore, 5000); document.getElementById('country-stat-average-score-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)'; document.getElementById('country-stat-average-score-value').innerText = averageScore; //Average Distance findPercentage(2500-averageDistance, 2500); document.getElementById('country-stat-average-distance-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)'; if(window.localStorage.getItem('units-svg-map') == 'mi'){ document.getElementById('country-stat-average-distance-title').innerText = 'Average Distance (mi)'; averageDistance = Math.floor(averageDistance / 1.609); } else{ document.getElementById('country-stat-average-distance-title').innerText = 'Average Distance (km)'; } document.getElementById('country-stat-average-distance-value').innerText = averageDistance; //Closer Than Opponent findPercentage(closerThanOpponent, totalCount); document.getElementById('country-stat-closer-than-opponent-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)'; document.getElementById('country-stat-closer-than-opponent-value').innerText = Math.floor((100 * (closerThanOpponent/totalCount))) + '%'; //Average Time findPercentage(120-averageTime, 120); document.getElementById('country-stat-average-time-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)'; document.getElementById('country-stat-average-time-value').innerText = averageTime; //Guessed First findPercentage(guessedFirst, totalCount); document.getElementById('country-stat-guessed-first-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)'; document.getElementById('country-stat-guessed-first-value').innerText = Math.floor((100 * (guessedFirst/totalCount))) + '%'; //Total 5ks findPercentage(total5ks, 10); document.getElementById('country-stat-total-5ks-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)'; document.getElementById('country-stat-total-5ks-value').innerText = total5ks; //BOTTOM STATS SETUP //Distance From Opponent let distanceFromOpponent = [Math.round(countryObject.distanceFromOpponent[1] / 1000),'km','+','green']; if(window.localStorage.getItem('units-svg-map') == 'mi'){ distanceFromOpponent[0] = Math.round(distanceFromOpponent[0] / 1.609); distanceFromOpponent[1] = 'mi'; } if(distanceFromOpponent[0] < 0){ distanceFromOpponent[0] *= -1; distanceFromOpponent[2] = '-'; distanceFromOpponent[3] = 'red'; } document.getElementById('country-stats-distance-from-opponent-value').style.color = distanceFromOpponent[3]; document.getElementById('country-stats-distance-from-opponent-value').innerText = distanceFromOpponent[2] + distanceFromOpponent[0] + ' ' + distanceFromOpponent[1]; //Country Streaks if(countryObject.countryCorrectStreak > 0){ document.getElementById('country-stats-country-streaks-value-current-value').innerText = countryObject.countryCorrectStreak + ' Correct'; document.getElementById('country-stats-country-streaks-value-current-value').style.color = 'green'; } else if(countryObject.countryWrongStreak > 0){ document.getElementById('country-stats-country-streaks-value-current-value').innerText = countryObject.countryWrongStreak + ' Incorrect'; document.getElementById('country-stats-country-streaks-value-current-value').style.color = 'red'; } document.getElementById('country-stats-country-streaks-value-max-correct-value').innerText = countryObject.countryCorrectMax; document.getElementById('country-stats-country-streaks-value-max-wrong-value').innerText = countryObject.countryWrongMax; } //RESET SCORES FOR SELECTED COUNTRY document.getElementById('country-stats-reset-btn').addEventListener('click', () => { let resetId = window.localStorage.getItem('select-country-stats-id'); let countryCorrect = parseInt(window.localStorage.getItem(resetId + '-number-correct-${USER_ID}')); let countryTotal = parseInt(window.localStorage.getItem(resetId + '-number-total-${USER_ID}')); let countryStats = JSON.parse(window.localStorage.getItem(resetId + '-all-country-stats-${USER_ID}')); let overallStats = JSON.parse(window.localStorage.getItem('overall-country-stats-${USER_ID}')); if(isNaN(countryCorrect)){ countryCorrect = 0; } if(isNaN(countryTotal)){ countryTotal = 0; } //Reset all scores for country if(confirm('Are you sure you want to reset your stats? This cannot be undone.')){ //Remove country scores from overall scores countryCorrect = (parseInt(window.localStorage.getItem('overall-correct-${USER_ID}')) - countryCorrect); countryTotal = (parseInt(window.localStorage.getItem('overall-total-${USER_ID}')) - countryTotal); overallStats.totalCount = overallStats.totalCount - countryStats.totalCount; overallStats.closerThanOpponent = overallStats.closerThanOpponent - countryStats.closerThanOpponent; overallStats.guessedFirst = overallStats.guessedFirst - countryStats.guessedFirst; overallStats.total5ks = overallStats.total5ks - countryStats.total5ks; //Set Stats To New Values window.localStorage.setItem('overall-correct-${USER_ID}', countryCorrect); window.localStorage.setItem('overall-total-${USER_ID}', countryTotal); window.localStorage.setItem('overall-country-stats-${USER_ID}',JSON.stringify(overallStats)); //Remove Country Scores window.localStorage.removeItem(resetId + '-number-correct-${USER_ID}'); window.localStorage.removeItem(resetId + '-number-total-${USER_ID}'); window.localStorage.removeItem(resetId + '-distance-average-${USER_ID}'); window.localStorage.removeItem(resetId + '-distance-number-${USER_ID}'); window.localStorage.removeItem(resetId + '-all-country-stats-${USER_ID}'); //Reload the page location.reload(); } }); //MAP SLIDER RANGES let leftSlider = document.getElementById("left-slider"); let rightSlider = document.getElementById("right-slider"); let sliderTrack = document.getElementById("slider-track"); let minGap = 5; leftSlider.value = window.localStorage.getItem('duels-map-color-left-range-${USER_ID}'); rightSlider.value = window.localStorage.getItem('duels-map-color-right-range-${USER_ID}'); //Change Left Slider Value function calcLeftSlider(){ if(parseInt(rightSlider.value) - parseInt(leftSlider.value) <= minGap){ leftSlider.value = parseInt(rightSlider.value) - minGap; } else if(leftSlider.value < 5){ leftSlider.value = 5; } document.getElementById('left-slider-output').innerText = leftSlider.value + '%'; document.getElementById('left-slider-output').style.left = findValue(leftSlider.value); fillColor(); window.localStorage.setItem('duels-map-color-left-range-${USER_ID}', leftSlider.value); } //Change Right Slider Value function calcRightSlider(){ if(parseInt(rightSlider.value) - parseInt(leftSlider.value) <= minGap){ rightSlider.value = parseInt(leftSlider.value) + minGap; } else if(rightSlider.value > 95){ rightSlider.value = 95; } document.getElementById('right-slider-output').innerText = rightSlider.value + '%'; document.getElementById('right-slider-output').style.left = findValue(rightSlider.value); fillColor(); window.localStorage.setItem('duels-map-color-right-range-${USER_ID}', rightSlider.value); } //Fill The Slider With Colors function fillColor(){ let percent1 = parseInt(leftSlider.value); let percent2 = parseInt(rightSlider.value); sliderTrack.style.background = 'linear-gradient(to right, red 0%, red ' + percent1 + '%, yellow ' + percent1 + '%, yellow ' + percent2 +'%, green ' + percent2 + '%, green 100%)'; } //Put Value Above Slider Thumb function findValue(val){ let valueOne = parseInt(val); let valueTwo = valueOne * 0.2; let final = 'calc(' + valueOne + '% - ' + valueTwo + 'px)'; return final; } //Add Event Listeners document.getElementById("left-slider").addEventListener('input', calcLeftSlider); document.getElementById("right-slider").addEventListener('input', calcRightSlider); calcLeftSlider(); calcRightSlider(); //PANNING AND ZOOMING ON THE MAP let worldMap = document.getElementById('world-map'); let viewbox = worldMap.viewBox.baseVal; let pointerDown = false; let mousePoint; //Return x and y values from pointer event function getPointFromEvent(event){ let point = worldMap.createSVGPoint(); point.x = event.clientX; point.y = event.clientY; //Get current transformation matrix and inverse it let invertedSVGMatrix = worldMap.getScreenCTM().inverse(); return point.matrixTransform(invertedSVGMatrix); } //When user clicks map to start panning function onPointerDown(event){ event.preventDefault(); pointerDown = true; mousePoint = getPointFromEvent(event); } //When user drags mouse function onPointerMove(event){ if (!pointerDown){ return; } event.preventDefault(); document.getElementById('world-map').style = 'cursor: grabbing'; document.getElementById('details-box').style.display = 'none'; let pointerPosition = getPointFromEvent(event); viewbox.x = (viewbox.x - (pointerPosition.x - mousePoint.x)); viewbox.y = (viewbox.y - (pointerPosition.y - mousePoint.y)); checkBounds(); } //When user lifts mouse up function onPointerUp(){ event.preventDefault(); pointerDown = false; document.getElementById('world-map').style = 'cursor: auto'; document.getElementById('details-box').style.display = 'inline'; } //When user scrolls mouse function onMouseWheel(event){ let delta = (event.wheelDelta ? event.wheelDelta : -event.deltaY); mousePoint = getPointFromEvent(event); //If mouse wheel moves forward if(delta > 0){ event.preventDefault(); //Zoom In Limit if(viewbox.width > 325 && viewbox.height > 140){ //Make the viewbox smaller viewbox.width /= 1.1; viewbox.height /= 1.1; //Position the top left accordingly viewbox.x = (((mousePoint.x - viewbox.x) * viewbox.width) - ((mousePoint.x - viewbox.x) * mousePoint.x) - ((viewbox.x + (viewbox.width * 1.1) - mousePoint.x) * mousePoint.x) ) / ( -((mousePoint.x - viewbox.x) + (viewbox.x + (viewbox.width * 1.1) - mousePoint.x)) ); viewbox.y = (((mousePoint.y - viewbox.y) * viewbox.height) - ((mousePoint.y - viewbox.y) * mousePoint.y) - ((viewbox.y + (viewbox.height * 1.1) - mousePoint.y) * mousePoint.y) ) / ( -((mousePoint.y - viewbox.y) + (viewbox.y + (viewbox.height * 1.1) - mousePoint.y)) ); } } //If mouse wheel moves backward else{ //Zoom Out Limit if(viewbox.width < 2000 && viewbox.height < 857){ event.preventDefault(); //Make the viewbox bigger viewbox.width *= 1.1; viewbox.height *= 1.1; //Position the top left accordingly viewbox.x = (((viewbox.x + (viewbox.width / 1.1) - mousePoint.x) * mousePoint.x) - ((mousePoint.x - viewbox.x) * viewbox.width) + ((mousePoint.x - viewbox.x) * mousePoint.x)) / ((mousePoint.x - viewbox.x) + (viewbox.x + (viewbox.width / 1.1) - mousePoint.x)); viewbox.y = (((viewbox.y + (viewbox.height / 1.1) - mousePoint.y) * mousePoint.y) - ((mousePoint.y - viewbox.y) * viewbox.height) + ((mousePoint.y - viewbox.y) * mousePoint.y)) / ((mousePoint.y - viewbox.y) + (viewbox.y + (viewbox.height / 1.1) - mousePoint.y)); } } checkBounds(); } //Check if the map is out of bounds function checkBounds(){ //Left if(viewbox.x < 0){ viewbox.x = 0; } //Top if(viewbox.y < 0){ viewbox.y = 0; } //Right if((viewbox.x + viewbox.width) > 2000){ viewbox.x = 2000 - viewbox.width; } //Bottom if((viewbox.y + viewbox.height) > 857){ viewbox.y = 857 - viewbox.height; } } //Add event listeners worldMap.addEventListener('pointerdown', onPointerDown); worldMap.addEventListener('pointerup', onPointerUp); worldMap.addEventListener('pointerleave', onPointerUp); worldMap.addEventListener('pointermove', onPointerMove); worldMap.addEventListener('wheel', onMouseWheel); }`; let referenceNode = document.getElementsByClassName('version3_main__xNkED')[0]; let siblingNode = document.getElementsByClassName('footer_footer__NmtmJ')[0]; referenceNode.parentNode.insertBefore(svgMap, siblingNode); document.head.appendChild(cssForMap); document.getElementById('map-wrapper-element').appendChild(scriptForMap); }; //**************************** END OF SCRIPT ****************************//