// ==UserScript== // @name Geoguessr GeoStats Script // @description Keeps track of various stats and displays it on an interactive map on your profile (Duels and Classic) // @author nappyslappy // @version 2.2.8 // @match https://www.geoguessr.com/* // @grant none // @license none // @icon https://www.google.com/s2/favicons?sz=64&domain=geoguessr.com // @copyright nappyslappy 2023, (https://greasyfork.org/en/users/922456) // @namespace https://greasyfork.org/en/users/922456-nappyslappy // @downloadURL https://update.greasyfork.icu/scripts/446052/Geoguessr%20GeoStats%20Script.user.js // @updateURL https://update.greasyfork.icu/scripts/446052/Geoguessr%20GeoStats%20Script.meta.js // ==/UserScript== //Published: June 6, 2022 //Last Update: April 21, 2024 /******************************** 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 *************************************************************// // NUM OF COUNTRIES SHOWN IN TOP INCORRECT LIST let TOP_INCORRECT_NUM = 5; // CHANGE THIS NUMBER ^^^^^ TO THE NUMBER OF COUNTRIES YOU WANT SHOWN //GLOBAL VARIABLES //Get User ID let USER_ID = JSON.parse(document.getElementById('__NEXT_DATA__').innerText).props.accountProps.account.user.userId; //Currently Fixing Bugs window.localStorage.setItem(`geostats-fixing-bugs-${USER_ID}`, false); //Checking Profile let statsToProfile = false; let setupToProfile = false; let updateToProfile = false; let fixingToProfile = false; //Checking Duels Rounds let player_index = 0; let previous_last_guess_number = 0; let checkingDuelsRoundOver = false; let checkingDuelsGameOver = false; //Checking Classic Rounds let checkingClassicRoundOver = false; //Checking Challenge Rounds let checkingChallengeRoundOver = false; //Map Colors let green_range = 0.75; let yellow_range = 0.25; let red_range = 0; //Set the map color ranges 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})); } //Set the included maps if(!window.localStorage.getItem(`geostats-classic-included-maps-${USER_ID}`)){ window.localStorage.setItem(`geostats-classic-included-maps-${USER_ID}`, JSON.stringify({ids: ['us-state-streak','country-streak']})); } //Evaluate the new duels guess function evaluateDuelsGuess(guess,location,distance,userScore,opponentScore,startTime,timerTime,guessTime,opponentDistance){ 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, totalCorrect: 0, averageScore: 0, averageDistance: 0, closerThanOpponent: 0, averageTime: 0, guessedFirst: 0, total5ks: 0, countryCorrectStreak: 0, countryCorrectMax: 0, countryWrongStreak: 0, countryWrongMax: 0, distanceFromOpponent: [0,0], //Wrong country incorrectCountry: {}, }; let overallStats = { //Total totalCount: 0, totalCorrect: 0, totalWin: 0, totalLoss: 0, total5ks: 0, totalGames: 0, totalSeconds: 0, //Average averageScore: 0, averageDistance: 0, averageGameLengthWin: 0, averageGameLengthLoss: 0, averageTime: 0, //Wrong country incorrectCountry: {}, //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++; //Total Correct countryStats.totalCorrect = correct_value; overallStats.totalCorrect = parseInt(correct_overall,10); //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 if(timeToGuess >= 0){ 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 == 5000){ countryStats.total5ks++; overallStats.total5ks++; } //Country Streaks (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 Streaks (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; } } //Wrong Country if(guess != location){ //Overall if(!overallStats.incorrectCountry){ overallStats.incorrectCountry = {}; } if(location != 'ERROR'){ if(overallStats.incorrectCountry[`${location}`]){ overallStats.incorrectCountry[`${location}`]++; } else{ overallStats.incorrectCountry[`${location}`] = 1; } } //Country if(!countryStats.incorrectCountry){ countryStats.incorrectCountry = {}; } if(guess != 'ERROR'){ if(countryStats.incorrectCountry[`${guess}`]){ countryStats.incorrectCountry[`${guess}`]++; } else{ countryStats.incorrectCountry[`${guess}`] = 1; } } } //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 Duels Game Is Finished function duelsGameFinished(userHealth,opponentHealth,opponentRating,userBefore,userAfter,gameId,gameLength,start,end){ if(window.sessionStorage.getItem('current-duels-game-id') == gameId){ return; } window.sessionStorage.setItem('current-duels-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); //If there is a calculation error (end is smaller than start) if(gameTime < 0){ gameTime = 0; } if(overallStats.totalSeconds < 0){ overallStats.totalSeconds = 0; } //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(userHealth > opponentHealth){ 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; } //Average Rating Change if(userBefore != null && userAfter != null){ if(!overallStats.averageRatingChange){ overallStats.averageRatingChange = { win: [0,0], loss: [0,0], }; } if(win){ overallStats.averageRatingChange.win[0]++; overallStats.averageRatingChange.win[1] = ((overallStats.averageRatingChange.win[1] * (overallStats.averageRatingChange.win[0] - 1)) + (userAfter-userBefore)) / overallStats.averageRatingChange.win[0]; } else if(!win){ overallStats.averageRatingChange.loss[0]++; overallStats.averageRatingChange.loss[1] = ((overallStats.averageRatingChange.loss[1] * (overallStats.averageRatingChange.loss[0] - 1)) + (userAfter-userBefore)) / overallStats.averageRatingChange.loss[0]; } } //Save Updated Stats window.localStorage.setItem(`overall-country-stats-${USER_ID}`, JSON.stringify(overallStats)); }; //Check the country code function checkGuessCountryCode(out){ let countryCode = 'NO CODE'; if(out.address.country_code){ countryCode = out.address.country_code; } //Check for US territories if(countryCode == 'us'){ //Puerto Rico if(out.address['ISO3166-2-lvl4'] == 'US-PR'){ countryCode = 'pr'; } //Guam if(out.address['ISO3166-2-lvl4'] == 'US-GU'){ countryCode = 'gu'; } //Northern Mariana Islands if(out.address['ISO3166-2-lvl4'] == 'US-MP'){ countryCode = 'mp'; } //Virgin Islands if(out.address['ISO3166-2-lvl4'] == 'US-VI'){ countryCode = 'vi'; } //American Samoa if(out.address['ISO3166-2-lvl4'] == 'US-AS'){ countryCode = 'as'; } } //US Minor Outlying Islands if(countryCode == 'um'){ countryCode = 'us'; } //Check for AU territories if(countryCode == 'au'){ //Cocos Islands if(out.address['territory'] == 'Cocos (Keeling) Islands'){ countryCode = 'cc'; } //Christmas Island if(out.address['territory'] == 'Christmas Island'){ countryCode = 'cx'; } } //Check for NL territories if(countryCode == 'nl'){ //CuraƧao if(out.address['ISO3166-2-lvl3'] == 'NL-CW'){ countryCode = 'cw'; } } //Check for Palestine if(countryCode == 'ps'){ countryCode = 'il'; } //Check for Hong Kong & Macau if(countryCode == 'cn'){ if(out.address['ISO3166-2-lvl3']){ if(out.address['ISO3166-2-lvl3'] == 'CN-HK'){ countryCode = 'hk'; } else if(out.address['ISO3166-2-lvl3'] == 'CN-MO'){ countryCode = 'mo'; } } } return countryCode; }; //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 checkGuessCountryCode(out); }).catch(err => {return 'ERROR'}); return country_code.toUpperCase(); }; }; //Check if a new duels guess has been made async function checkDuelsGuess(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 userRatingBefore = null; let userRatingAfter = null; if(out.options.isRated){ userRatingBefore = out.teams[player_index].players[0].progressChange.competitiveProgress.ratingBefore; userRatingAfter = out.teams[player_index].players[0].progressChange.competitiveProgress.ratingAfter; } let opponentRatingBefore = out.teams[opponentIndex].players[0].rating; let userHealth = out.teams[player_index].health; let opponentHealth = out.teams[opponentIndex].health; let gameLength = out.currentRoundNumber; let gameStartTime = out.rounds[0].startTime; let gameEndTime = out.rounds[gameLength-1].endTime; duelsGameFinished(userHealth,opponentHealth,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] && opponentGuess.guesses[opponentGuess.guesses.length-1].roundNumber == current_round){ opponentDistance = opponentGuess.guesses[opponentGuess.guesses.length-1].distance; } //If guess is good if(guess != undefined){ //Check location code location_code = checkGuessCountryCode({address:{country_code:location_code}}); //Evaluate all values and update stats evaluateDuelsGuess(guess,location_code,distance,userScore,opponentScore,startTime,timerTime,guessTime,opponentDistance); } resolve(out); }); }) .catch((error) => { reject(error); }); }); }; //Evaluate The Stats For The Finished Classic Game function evaluateClassicGameFinished(out){ if(out.mode == 'streak'){ //Evaluate Country Streaks Game Stats if(out.streakType == 'countrystreak'){ } //Evaluate USA Streaks Game Stats else if(out.streakType == 'usstatestreak'){ } } //Evaluate Standard Game Stats else if(out.mode == 'standard'){ let overallStats = JSON.parse(window.localStorage.getItem(`geostats-overall-standard-stats-${USER_ID}`)); overallStats.totalGames++; overallStats.totalSeconds += out.player.totalTime; overallStats.averageGameTime = ((overallStats.averageGameTime * (overallStats.totalGames - 1)) + out.player.totalTime) / overallStats.totalGames; //HIGHSCORE STUFF HERE //Save Updated Stats window.localStorage.setItem(`geostats-overall-standard-stats-${USER_ID}`, JSON.stringify(overallStats)); } }; //Evaluate The Guess For The Finished Classic Round function evaluateClassicRoundFinished(out){ if(out.mode == 'streak'){ //Evaluate Country Streaks Round Stats if(out.streakType == 'countrystreak'){ } //Evaluate USA Streaks Game Stats else if(out.streakType == 'usstatestreak'){ } } else if(out.mode == 'standard'){ //Evaluate Standard Game Stats let current_guess = [out.player.guesses[out.player.guesses.length-1].lat, out.player.guesses[out.player.guesses.length-1].lng]; let current_location = [out.rounds[out.player.guesses.length-1].lat, out.rounds[out.player.guesses.length-1].lng]; //If the guess timed out if(out.player.guesses[out.player.guesses.length-1].timedOut){ return; } getGuessCountryCode(current_guess) .then(guess => { getGuessCountryCode(current_location) .then(location => { let standardCountryStats = { //Total totalCount: 0, totalCorrect: 0, totalSeconds: 0, total5ks: 0, //Average averageScore: 0, averageDistance: 0, averageRoundTime: 0, //Wrong country incorrectCountry: {}, //Streak countryCorrectStreak: 0, countryCorrectMax: 0, countryWrongStreak: 0, countryWrongMax: 0, }; let standardOverallStats = { //Total totalCount: 0, totalCorrect: 0, totalGames: 0, totalSeconds: 0, total5ks: 0, //Average averageScore: 0, averageDistance: 0, averageRoundTime: 0, averageGameTime: 0, //Wrong country incorrectCountry: {}, //5k locations: all5kLocations: [], //Streak countryCorrectStreak: 0, countryCorrectMax: 0, countryWrongStreak: 0, countryWrongMax: 0, }; //Get Exisiting Stats if(window.localStorage.getItem(`geostats-${location}-all-standard-stats-${USER_ID}`)){ standardCountryStats = JSON.parse(window.localStorage.getItem(`geostats-${location}-all-standard-stats-${USER_ID}`)); } if(window.localStorage.getItem(`geostats-overall-standard-stats-${USER_ID}`)){ standardOverallStats = JSON.parse(window.localStorage.getItem(`geostats-overall-standard-stats-${USER_ID}`)); } //Useful variables let score = out.player.guesses[out.player.guesses.length-1].roundScoreInPoints; let distance = out.player.guesses[out.player.guesses.length-1].distanceInMeters; let time = out.player.guesses[out.player.guesses.length-1].time; //Country Total standardCountryStats.totalCount++; standardOverallStats.totalCount++; //Country Correct if(guess == location){ //Country standardCountryStats.totalCorrect++; standardCountryStats.countryWrongStreak = 0; standardCountryStats.countryCorrectStreak++; if(standardCountryStats.countryCorrectStreak > standardCountryStats.countryCorrectMax){ standardCountryStats.countryCorrectMax = standardCountryStats.countryCorrectStreak; } //Overall standardOverallStats.totalCorrect++; standardOverallStats.countryWrongStreak = 0; standardOverallStats.countryCorrectStreak++; if(standardOverallStats.countryCorrectStreak > standardOverallStats.countryCorrectMax){ standardOverallStats.countryCorrectMax = standardOverallStats.countryCorrectStreak; } } //Country Incorrect else{ //Country standardCountryStats.countryCorrectStreak = 0; standardCountryStats.countryWrongStreak++; if(standardCountryStats.countryWrongStreak > standardCountryStats.countryWrongMax){ standardCountryStats.countryWrongMax = standardCountryStats.countryWrongStreak; } if(guess != 'ERROR'){ if(standardCountryStats.incorrectCountry[`${guess}`]){ standardCountryStats.incorrectCountry[`${guess}`]++; } else{ standardCountryStats.incorrectCountry[`${guess}`] = 1; } } //Overall standardOverallStats.countryCorrectStreak = 0; standardOverallStats.countryWrongStreak++; if(standardOverallStats.countryWrongStreak > standardOverallStats.countryWrongMax){ standardOverallStats.countryWrongMax = standardOverallStats.countryWrongStreak; } if(location != 'ERROR'){ if(standardOverallStats.incorrectCountry[`${location}`]){ standardOverallStats.incorrectCountry[`${location}`]++; } else{ standardOverallStats.incorrectCountry[`${location}`] = 1; } } } //Average Score standardCountryStats.averageScore = ((standardCountryStats.averageScore * (standardCountryStats.totalCount - 1)) + score) / standardCountryStats.totalCount; standardOverallStats.averageScore = ((standardOverallStats.averageScore * (standardOverallStats.totalCount - 1)) + score) / standardOverallStats.totalCount; //Average Distance standardCountryStats.averageDistance = ((standardCountryStats.averageDistance * (standardCountryStats.totalCount - 1)) + distance) / standardCountryStats.totalCount; standardOverallStats.averageDistance = ((standardOverallStats.averageDistance * (standardOverallStats.totalCount - 1)) + distance) / standardOverallStats.totalCount; //Average Round Time standardCountryStats.averageRoundTime = ((standardCountryStats.averageRoundTime * (standardCountryStats.totalCount - 1)) + time) / standardCountryStats.totalCount; standardOverallStats.averageRoundTime = ((standardOverallStats.averageRoundTime * (standardOverallStats.totalCount - 1)) + time) / standardOverallStats.totalCount; //Total Seconds standardCountryStats.totalSeconds += time; //Total 5ks if(score == 5000){ standardCountryStats.total5ks++; standardOverallStats.total5ks++; standardOverallStats.all5kLocations.push({lat: out.rounds[out.player.guesses.length-1].lat, lng: out.rounds[out.player.guesses.length-1].lng, id: out.token, map: out.map, round: out.player.guesses.length-1}); } //Save Updated Stats window.localStorage.setItem(`geostats-${location}-all-standard-stats-${USER_ID}`, JSON.stringify(standardCountryStats)); window.localStorage.setItem(`geostats-overall-standard-stats-${USER_ID}`, JSON.stringify(standardOverallStats)); }); }); } }; //Add The Classic Game Id (if needed) function addGameId(newId){ if(!window.localStorage.getItem(`geostats-unfinished-classic-games-${USER_ID}`)){ window.localStorage.setItem(`geostats-unfinished-classic-games-${USER_ID}`, JSON.stringify({gameIds:[]})); } let allGames = JSON.parse(window.localStorage.getItem(`geostats-unfinished-classic-games-${USER_ID}`)); if(!allGames.gameIds.includes(newId)){ allGames.gameIds.push(newId); } //Save Updated Ids window.localStorage.setItem(`geostats-unfinished-classic-games-${USER_ID}`, JSON.stringify(allGames)); }; //Evaluate The Stats For The Finished Challenge Game function evaluateChallengeGameFinished(out){ console.log("Game Finished"); let overallStats = JSON.parse(window.localStorage.getItem(`geostats-overall-challenge-stats-${USER_ID}`)); overallStats.totalGames++; overallStats.totalSeconds += out.player.totalTime; overallStats.averageGameTime = ((overallStats.averageGameTime * (overallStats.totalGames - 1)) + out.player.totalTime) / overallStats.totalGames; //HIGHSCORE STUFF HERE //Save Updated Stats window.localStorage.setItem(`geostats-overall-challenge-stats-${USER_ID}`, JSON.stringify(overallStats)); }; //Evaluate The Guess For The Finished Round function evaluateChallengeRoundFinished(out){ console.log("Round Finished"); console.log(out); const currentRound = out.rounds[out.round-1]; const currentGuess = out.player.guesses[out.round-1]; //If User Timed Out if(currentGuess.timedOut || currentGuess.timedOutWithGuess){ return; } getGuessCountryCode([currentGuess.lat, currentGuess.lng]) .then(guess => { getGuessCountryCode([currentRound.lat, currentRound.lng]) .then(location => { //Setup Stats For First Time let challengeCountryStats = { //Total totalCount: 0, totalCorrect: 0, totalSeconds: 0, total5ks: 0, //Average averageScore: 0, averageDistance: 0, averageRoundTime: 0, //Wrong country incorrectCountry: {}, //Streak countryCorrectStreak: 0, countryCorrectMax: 0, countryWrongStreak: 0, countryWrongMax: 0, }; let challengeOverallStats = { //Total totalCount: 0, totalCorrect: 0, totalGames: 0, totalSeconds: 0, total5ks: 0, //Average averageScore: 0, averageDistance: 0, averageRoundTime: 0, averageGameTime: 0, //Wrong country incorrectCountry: {}, //5k locations: all5kLocations: [], //Streak countryCorrectStreak: 0, countryCorrectMax: 0, countryWrongStreak: 0, countryWrongMax: 0, }; //Get Exisiting Stats if(window.localStorage.getItem(`geostats-${location}-all-challenge-stats-${USER_ID}`)){ challengeCountryStats = JSON.parse(window.localStorage.getItem(`geostats-${location}-all-challenge-stats-${USER_ID}`)); } if(window.localStorage.getItem(`geostats-overall-challenge-stats-${USER_ID}`)){ challengeOverallStats = JSON.parse(window.localStorage.getItem(`geostats-overall-challenge-stats-${USER_ID}`)); } //Useful variables let score = currentGuess.roundScoreInPoints; let distance = currentGuess.distanceInMeters; let time = currentGuess.time; //Country Total challengeCountryStats.totalCount++; challengeOverallStats.totalCount++; //Country Correct if(guess == location){ //Country challengeCountryStats.totalCorrect++; challengeCountryStats.countryWrongStreak = 0; challengeCountryStats.countryCorrectStreak++; if(challengeCountryStats.countryCorrectStreak > challengeCountryStats.countryCorrectMax){ challengeCountryStats.countryCorrectMax = challengeCountryStats.countryCorrectStreak; } //Overall challengeOverallStats.totalCorrect++; challengeOverallStats.countryWrongStreak = 0; challengeOverallStats.countryCorrectStreak++; if(challengeOverallStats.countryCorrectStreak > challengeOverallStats.countryCorrectMax){ challengeOverallStats.countryCorrectMax = challengeOverallStats.countryCorrectStreak; } } //Country Incorrect else{ //Country challengeCountryStats.countryCorrectStreak = 0; challengeCountryStats.countryWrongStreak++; if(challengeCountryStats.countryWrongStreak > challengeCountryStats.countryWrongMax){ challengeCountryStats.countryWrongMax = challengeCountryStats.countryWrongStreak; } if(guess != 'ERROR'){ if(challengeCountryStats.incorrectCountry[`${guess}`]){ challengeCountryStats.incorrectCountry[`${guess}`]++; } else{ challengeCountryStats.incorrectCountry[`${guess}`] = 1; } } //Overall challengeOverallStats.countryCorrectStreak = 0; challengeOverallStats.countryWrongStreak++; if(challengeOverallStats.countryWrongStreak > challengeOverallStats.countryWrongMax){ challengeOverallStats.countryWrongMax = challengeOverallStats.countryWrongStreak; } if(location != 'ERROR'){ if(challengeOverallStats.incorrectCountry[`${location}`]){ challengeOverallStats.incorrectCountry[`${location}`]++; } else{ challengeOverallStats.incorrectCountry[`${location}`] = 1; } } } //Average Score challengeCountryStats.averageScore = ((challengeCountryStats.averageScore * (challengeCountryStats.totalCount - 1)) + score) / challengeCountryStats.totalCount; challengeOverallStats.averageScore = ((challengeOverallStats.averageScore * (challengeOverallStats.totalCount - 1)) + score) / challengeOverallStats.totalCount; //Average Distance challengeCountryStats.averageDistance = ((challengeCountryStats.averageDistance * (challengeCountryStats.totalCount - 1)) + distance) / challengeCountryStats.totalCount; challengeOverallStats.averageDistance = ((challengeOverallStats.averageDistance * (challengeOverallStats.totalCount - 1)) + distance) / challengeOverallStats.totalCount; //Average Round Time challengeCountryStats.averageRoundTime = ((challengeCountryStats.averageRoundTime * (challengeCountryStats.totalCount - 1)) + time) / challengeCountryStats.totalCount; challengeOverallStats.averageRoundTime = ((challengeOverallStats.averageRoundTime * (challengeOverallStats.totalCount - 1)) + time) / challengeOverallStats.totalCount; //Total Seconds challengeCountryStats.totalSeconds += time; //Total 5ks if(score == 5000){ challengeCountryStats.total5ks++; challengeOverallStats.total5ks++; challengeOverallStats.all5kLocations.push({lat: out.rounds[out.player.guesses.length-1].lat, lng: out.rounds[out.player.guesses.length-1].lng, id: out.token, map: out.map, round: out.player.guesses.length-1}); } //Save Updated Stats window.localStorage.setItem(`geostats-${location}-all-challenge-stats-${USER_ID}`, JSON.stringify(challengeCountryStats)); window.localStorage.setItem(`geostats-overall-challenge-stats-${USER_ID}`, JSON.stringify(challengeOverallStats)); }) }); }; //Check if the user is on the profile page function profileCheck(){ if(location.pathname.endsWith('/profile')){ //If script is currently being updated and running it would cause more problems if(window.localStorage.getItem(`geostats-fixing-bugs-${USER_ID}`) == 'tru'){ if(!fixingToProfile){ addFixingToProfile(); } } else if(window.localStorage.getItem(`geostats-setup-complete-${USER_ID}`)){ if(!window.localStorage.getItem(`geostats-update-2.2.8-complete-${USER_ID}`) && !updateToProfile){ addUpdateToProfile(); } else if(window.localStorage.getItem(`geostats-update-2.2.8-complete-${USER_ID}`) && !statsToProfile){ USER_ID = JSON.parse(document.getElementById('__NEXT_DATA__').innerText).props.accountProps.account.user.userId; addMapToProfile(); } } else if(!window.localStorage.getItem(`geostats-setup-complete-${USER_ID}`) && !setupToProfile){ addSetupPageToProfile(); } } else if(!location.pathname.endsWith('/profile')){ if(statsToProfile){ statsToProfile = false; document.getElementById('map-wrapper-element').remove(); document.getElementById('css-for-map').remove(); } else if(setupToProfile){ setupToProfile = false; document.getElementById('geostats-setup-css').remove(); document.getElementById('geostats-setup-html').remove(); } else if(updateToProfile){ updateToProfile = false; document.getElementById('geostats-update-css').remove(); document.getElementById('geostats-update-html').remove(); } else if(fixingToProfile){ fixingToProfile = false; document.getElementById('geostats-fixing-bugs-css').remove(); document.getElementById('geostats-fixing-bugs-html').remove(); } } }; //Check if the user is playing a challenge function challengeCheck(){ if(!location.pathname.startsWith('/challenge/')){ return; } //If A Round Has Finished if(document.getElementsByClassName('result-layout_root__fRPgH').length > 0){ const game_tag = window.location.href.substring(window.location.href.lastIndexOf('/') + 1); const api_url = 'https://www.geoguessr.com/api/v3/challenges/' + game_tag + '/game'; if(!checkingChallengeRoundOver){ checkingChallengeRoundOver = true; fetch(api_url) .then((res) => res.json()) .then((out) => { //Set All Unfinished Challenge Games if(!window.localStorage.getItem(`geostats-unfinished-challenge-games-${USER_ID}`)){window.localStorage.setItem(`geostats-unfinished-challenge-games-${USER_ID}`, JSON.stringify({games: []}))}; let allChallengeGames = JSON.parse(window.localStorage.getItem(`geostats-unfinished-challenge-games-${USER_ID}`)); //Check If First Round For Challenge if(!allChallengeGames.games.includes(game_tag)){ if(out.round == 1){ allChallengeGames.games.push(game_tag); } else{ //Not First Round - Already Started Challenge return; } } //Don't Duplicate Round On Refresh if(window.sessionStorage.getItem('last-challenge-guess')){ let lastGuess = JSON.parse(window.sessionStorage.getItem('last-challenge-guess')); if(lastGuess.id == game_tag && lastGuess.round == out.round){ return; } } window.sessionStorage.setItem('last-challenge-guess', JSON.stringify({id: game_tag, round: out.round})); evaluateChallengeRoundFinished(out); //If Game Is Finished if(out.state == 'finished'){ evaluateChallengeGameFinished(out); const index = allChallengeGames.games.indexOf(game_tag); allChallengeGames.games.splice(index,1); } //Update Changed Stats window.localStorage.setItem(`geostats-unfinished-challenge-games-${USER_ID}`, JSON.stringify(allChallengeGames)); }) .catch((error) => { throw error; }); } } else{ checkingChallengeRoundOver = false; } }; //Check if the user is playing a classic game function classicCheck(){ if(!location.pathname.startsWith('/game/')){ return; } //If a round has finished if(document.getElementsByClassName('result-layout_root__fRPgH').length > 0){ const game_tag = window.location.href.substring(window.location.href.lastIndexOf('/') + 1); const api_url = 'https://www.geoguessr.com/api/v3/games/' + game_tag; if(!checkingClassicRoundOver){ checkingClassicRoundOver = true; fetch(api_url) .then((res) => res.json()) .then((out) => { //Check if the map is included in the selected maps if(!window.localStorage.getItem(`geostats-classic-included-maps-${USER_ID}`)){ window.localStorage.setItem(`geostats-classic-included-maps-${USER_ID}`, JSON.stringify({ids: ['us-state-streak','country-streak']})); } let mapId = out.map; let includedMaps = JSON.parse(window.localStorage.getItem(`geostats-classic-included-maps-${USER_ID}`)); if(!includedMaps.ids.includes(mapId)){ return; } //IF THE GAME IS FINISHED if(out.state == 'finished'){ if(window.localStorage.getItem(`geostats-unfinished-classic-games-${USER_ID}`)){ let allGames = JSON.parse(window.localStorage.getItem(`geostats-unfinished-classic-games-${USER_ID}`)); if(allGames.gameIds.length > 0 && allGames.gameIds.includes(game_tag)){ //Remove the game id from unfinished games const index = allGames.gameIds.indexOf(game_tag); allGames.gameIds.splice(index,1); window.localStorage.setItem(`geostats-unfinished-classic-games-${USER_ID}`, JSON.stringify(allGames)); evaluateClassicRoundFinished(out); evaluateClassicGameFinished(out); } } else{ return; } } //IF THE GAME IS NOT FINISHED else{ evaluateClassicRoundFinished(out); addGameId(game_tag); } }) .catch((error) => { throw error; }); } } else{ checkingClassicRoundOver = false; } }; //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; //If a round has finished if(document.getElementsByClassName('overlay_overlay__AR02x').length > 0){ //If the round is finished if(document.getElementsByClassName('round-score_container__s6qNg').length > 0){ if(!checkingDuelsRoundOver){ checkingDuelsRoundOver = true; checkDuelsGuess(api_url); } } //If the game is finished else if(document.getElementsByClassName('game-finished_container___UprU').length > 0){ if(!checkingDuelsGameOver){ checkingDuelsGameOver = true; checkDuelsGuess(api_url); } } } else{ checkingDuelsRoundOver = false; checkingDuelsGameOver = false; } }; //Check if the user is about to start a standard game function startpageCheck(){ if(location.pathname.startsWith('/maps/') && location.pathname.endsWith('/play')){ if(!document.getElementById('geostats-standard-game-start-page-toggle-html')){ addToggleToStartPage(); } } }; //Run duelsCheck twice every second setInterval(duelsCheck,500); //Run classicCheck four times every second setInterval(classicCheck,250); //Run challengeCheck four times every second setInterval(challengeCheck,250) //Run profileCheck twice every second setInterval(profileCheck,500); //Console Log Script Name console.log('*** Geoguessr GeoStats v2.2.8 by NappySlappy ***'); /************************************************** UPDATE STUFF HERE **************************************************/ function addFixingToProfile(){ fixingToProfile = true; //Create The Fixing Elements const cssForFixing = document.createElement('style'); cssForFixing.setAttribute('id','geostats-fixing-bugs-css'); const htmlForFixing = document.createElement('div'); htmlForFixing.setAttribute('id','geostats-fixing-bugs-html'); //CSS For Fixing cssForFixing.textContent = ` #fixing-page-title-wrapper{ margin: 20px auto; text-align: center; } #fixing-page-title{ font-family: var(--font-neo-sans); font-size: 40px; color: white; } #fixing-page-content-wrapper{ margin: 20px auto; text-align: center; width: 65%; border: solid 2px white; border-radius: 40px; } #fixing-page-content{ font-family: var(--font-neo-sans); font-size: 20px; color: white; padding: 20px; } `; //HTML For Fixing htmlForFixing.innerHTML = `

GeoStats Fixing Bugs

Sorry, due to Geoguessr's recent update, some things in this script have broken. I'm working on fixing everything and will have the updates out shortly. Thanks! :)
`; //Add Everything To The Page let referenceNode = document.getElementsByClassName('version4_main__Zjun_')[0]; let siblingNode = document.getElementsByClassName('version4_notificationPreviewList__OOMPZ')[0]; //If old version (version 3) if(document.getElementsByClassName('version3_main__xNkED').length > 0 && document.getElementsByClassName('footer_footer__NmtmJ').length > 0){ referenceNode = document.getElementsByClassName('version3_main__xNkED')[0]; siblingNode = document.getElementsByClassName('footer_footer__NmtmJ')[0]; } referenceNode.parentNode.insertBefore(htmlForFixing, siblingNode); document.head.appendChild(cssForFixing); }; /************************************************** UPDATE STUFF HERE **************************************************/ function addUpdateToProfile(){ updateToProfile = true; //Create The Update Elements const cssForUpdate = document.createElement('style'); cssForUpdate.setAttribute('id','geostats-update-css'); const htmlForUpdate = document.createElement('div'); htmlForUpdate.setAttribute('id','geostats-update-html'); const scriptForUpdate = document.createElement('script'); scriptForUpdate.setAttribute('id','geostats-update-script'); //CSS For Update cssForUpdate.textContent = ` #update-page-title-wrapper{ margin: 20px auto; text-align: center; } #update-page-title{ font-family: var(--font-neo-sans); font-size: 40px; color: white; } #update-page-content-wrapper{ margin: 20px auto; text-align: center; width: 65%; border: solid 2px white; border-radius: 40px; } #update-page-content{ font-family: var(--font-neo-sans); font-size: 20px; color: white; padding: 20px; } #update-page-button-wrapper{ margin: 20px auto; text-align: center; } #update-page-button{ border-radius: 15px; background-color: transparent; color: white; border-color: white; padding: 5px 10px 5px 10px; } #update-page-button:hover{ background-color: white; color: black; border-color: black; cursor: pointer; } `; //HTML For Update htmlForUpdate.innerHTML = `

GeoStats Update v2.2.8

`; //Script For Update scriptForUpdate.textContent = ` { let currentSlide = 0; let firstSlide = 'Minor Bug Fixes'; let allSliders = [firstSlide]; function changeSlide(){ currentSlide++; if(currentSlide == allSliders.length){ window.localStorage.setItem('geostats-update-2.2.8-complete-${USER_ID}', new Date()); document.getElementById('geostats-update-css').remove(); document.getElementById('geostats-update-html').remove(); } else{ document.getElementById('update-page-content').textContent = allSliders[currentSlide]; } } document.getElementById('update-page-content').textContent = allSliders[0]; document.getElementById('update-page-button').addEventListener('click', changeSlide); } `; //Add Everything To The Page let referenceNode = document.getElementsByClassName('version4_main__Zjun_')[0]; let siblingNode = document.getElementsByClassName('version4_notificationPreviewList__OOMPZ')[0]; //If old version (version 3) if(document.getElementsByClassName('version3_main__xNkED').length > 0 && document.getElementsByClassName('footer_footer__NmtmJ').length > 0){ referenceNode = document.getElementsByClassName('version3_main__xNkED')[0]; siblingNode = document.getElementsByClassName('footer_footer__NmtmJ')[0]; } referenceNode.parentNode.insertBefore(htmlForUpdate, siblingNode); document.head.appendChild(cssForUpdate); document.getElementById('geostats-update-html').appendChild(scriptForUpdate); }; /************************************************** 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 your games. It will monitor your 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. Currently supported gamemodes are: Duels and Classic"; 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. You can also use 'shift + scroll' to zoom into the map."; let thirdSlide = "You can reset your stats by clicking the 'Reset All Stats' button in settings, as well as for individual countries. Keep in mind that all information is stored in your browser on your device so if you want the same stats on different devices/browsers you will need to download a file of your stats (located in settings) and upload the same file on the other device/browser. This also 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('version4_main__Zjun_')[0]; let siblingNode = document.getElementsByClassName('version4_notificationPreviewList__OOMPZ')[0]; //If old version (version 3) if(document.getElementsByClassName('version3_main__xNkED').length > 0 && document.getElementsByClassName('footer_footer__NmtmJ').length > 0){ referenceNode = document.getElementsByClassName('version3_main__xNkED')[0]; siblingNode = document.getElementsByClassName('footer_footer__NmtmJ')[0]; } referenceNode.parentNode.insertBefore(htmlForSetup, siblingNode); document.head.appendChild(cssForSetup); document.getElementById('geostats-setup-html').appendChild(scriptForSetup); }; /************************************************** STATS 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; padding-bottom: 10px; left: 0px; } #map-title{ font-size: 30px; text-align: center; color: var(--ds-color-yellow-50); font-family: var(--font-neo-sans); } #geostats-gamemodes-menu{ display: flex; margin: 0px 0px; justify-content: center; padding-inline-start: 0; } .geostats-gamemodes-menu-item{ display: block; padding: 8px; color: var(--ds-color-white-60) } .geostats-gamemodes-menu-item:hover{ cursor: pointer; } .geostats-gamemodes-menu-item-wrapper{ } ol li::marker{ content: "" !important; } #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; } #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{ margin-top: 10px; } #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-import-and-export-wrapper{ border-top: 2px solid white; padding-bottom: 50px; padding-top: 25px; margin-left: 50px; margin-right: 50px; display: flex; } .download-upload-buttons{ border: 1px solid #ccc; border-radius: 15px; background-color: transparent; color: white; border-color: white; cursor: pointer; padding: 5px 10px 5px 10px; } .download-upload-buttons:hover{ background-color: white; color: black; } #settings-export-wrapper{ flex: 1; } #download-file-status{ padding-top: 7px; } #settings-import-wrapper{ flex: 1; } #settings-import-content{ display: flex; justify-content: space-evenly; align-items: baseline; } #select-file-button{ display: none; } #select-file-status{ padding-top: 15px; } #upload-file-status{ padding-top: 7px; } #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

Zoom: shift + scroll

OVERALL STATS

Average Score

Average Distance (km)

Closer Than Opponent

Average Time To Guess (Sec)

Guessed First

Total 5ks

Average Rounds Played (Win)

Average Rounds Played (Loss)

Opponent Rating

Average Score

Average Distance (km)

Average Round Time (sec)

Average Game Time (min)

Total 5ks

AVERAGE DISTANCE FROM OPPONENT

COUNTRY STREAKS

Current:

Highest: Correct | Incorrect

TIME PLAYED

SETTINGS

Map Color Ranges

Units

Include Healing Rounds

Competitive Only (Duels)

Download Stats

Upload Stats

No File Selected
`; 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','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','UY','UZ','VU','VE','VN','VG','VI','WF','EH','YE','ZM','ZW','SM']; //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'); }); //DUELS MAP SETUP function setAllDuelsStats(){ //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('overall-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-title').innerText = 'AVERAGE DISTANCE FROM OPPONENT'; 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 '; //Make All Stats Visible document.getElementById('overall-stat-average-score-wrapper').style.display = 'flex'; document.getElementById('overall-stat-average-distance-wrapper').style.display = 'flex'; document.getElementById('overall-stat-closer-than-opponent-wrapper').style.display = 'flex'; document.getElementById('overall-stat-average-time-wrapper').style.display = 'flex'; document.getElementById('overall-stat-guessed-first-wrapper').style.display = 'flex'; document.getElementById('overall-stat-total-5ks-wrapper').style.display = 'flex'; document.getElementById('overall-stat-average-game-length-win-wrapper').style.display = 'flex'; document.getElementById('overall-stat-average-game-length-loss-wrapper').style.display = 'flex'; document.getElementById('overall-stat-opponent-rating-wrapper').style.display = 'flex'; document.getElementById('duels-stats-spacing-wrapper-1').style.display = 'flex' document.getElementById('duels-stats-spacing-wrapper-2').style.display = 'flex' document.getElementById('overall-stats-values-bottom').style.marginTop = '360px'; }; //Set All Classic Stats function setAllClassicStats(){ //Total Percentage Bar let totalCount = 'none'; let totalCorrect = 'none' let percentage_total = 'none'; if(window.localStorage.getItem('geostats-overall-standard-stats-${USER_ID}')){ totalCount = JSON.parse(window.localStorage.getItem('geostats-overall-standard-stats-${USER_ID}')).totalCount; totalCorrect = JSON.parse(window.localStorage.getItem('geostats-overall-standard-stats-${USER_ID}')).totalCorrect; percentage_total = Math.floor((totalCorrect / totalCount) * 100); } 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'; } if(percentage_total != 'none'){ document.getElementById('total-percentage-bar').style.width = percentage_total + '%'; document.getElementById('total-percentage-text').innerHTML = 'Overall Score: ' + totalCorrect + ' / ' + totalCount + ' (' + percentage_total +'%) '; } //Country colors countries.forEach(function(countryId){ let countryStats = null; let percentage = 'none'; if(window.localStorage.getItem('geostats-' + countryId + '-all-standard-stats-${USER_ID}')){ countryStats = JSON.parse(window.localStorage.getItem('geostats-' + countryId + '-all-standard-stats-${USER_ID}')); percentage = countryStats.totalCorrect / countryStats.totalCount; } let targetCountry = document.getElementById(countryId); 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'); } }); //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; } }; //OVERALL STATS let overallStats = JSON.parse(window.localStorage.getItem('geostats-overall-standard-stats-${USER_ID}')); let percentage; let percentageColor; let averageScore = Math.floor(overallStats.averageScore); let averageDistance = Math.floor(overallStats.averageDistance/1000); let averageRoundTime = Math.floor(overallStats.averageRoundTime); let averageGameTime = overallStats.averageGameTime/60; let total5ks = overallStats.total5ks; //Average Score findPercentage(averageScore, 5000); document.getElementById('standard-overall-stat-average-score-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)'; document.getElementById('standard-overall-stat-average-score-value').innerText = averageScore; //Average Distance findPercentage(2500-averageDistance, 2500); document.getElementById('standard-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('standard-overall-stat-average-distance-title').innerText = 'Average Distance (mi)'; averageDistance = Math.floor(averageDistance / 1.609); } else{ document.getElementById('standard-overall-stat-average-distance-title').innerText = 'Average Distance (km)'; } document.getElementById('standard-overall-stat-average-distance-value').innerText = averageDistance; //Average Round Time findPercentage(120-averageRoundTime, 120); document.getElementById('standard-overall-stat-average-round-time-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)'; document.getElementById('standard-overall-stat-average-round-time-value').innerText = averageRoundTime; //Average Game Time findPercentage(10-averageGameTime, 10); document.getElementById('standard-overall-stat-average-game-time-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)'; document.getElementById('standard-overall-stat-average-game-time-value').innerText = round(averageGameTime,1); //Total 5ks findPercentage(total5ks, 100); document.getElementById('standard-overall-stat-total5ks-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)'; document.getElementById('standard-overall-stat-total5ks-value').innerText = total5ks; //BOTTOM STATS SETUP //Commonly Guessed Incorrectly document.getElementById('overall-stats-distance-from-opponent-title').innerText = 'TOP INCORRECT COUNTRIES'; let textColor = 'green'; let innerText = ''; if(Object.keys(overallStats.incorrectCountry).length != 0){ let incorrectGuesses = Object.entries(overallStats.incorrectCountry).sort((a,b) => b[1]-a[1]); for(let i = 0; i < ${TOP_INCORRECT_NUM}; i++){ let tempText = ''; if(i < incorrectGuesses.length && incorrectGuesses[i][0] != 'ERROR'){ tempText = document.getElementById(incorrectGuesses[i][0]).dataset.name + ' - ' + incorrectGuesses[i][1]; } innerText += tempText + '\\n'; } textColor = 'red'; } else{ innerText = 'N/A'; } document.getElementById('overall-stats-distance-from-opponent-value').style.color = textColor; document.getElementById('overall-stats-distance-from-opponent-value').innerText = innerText; //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 '; //Make All Stats Visible document.getElementById('standard-overall-stat-average-score-wrapper').style.display = 'flex'; document.getElementById('standard-overall-stat-average-distance-wrapper').style.display = 'flex'; document.getElementById('standard-overall-stat-average-round-time-wrapper').style.display = 'flex'; document.getElementById('standard-overall-stat-average-game-time-wrapper').style.display = 'flex'; document.getElementById('standard-overall-stat-total5ks-wrapper').style.display = 'flex'; document.getElementById('standard-stats-spacing-wrapper-1').style.display = 'flex' document.getElementById('overall-stats-values-bottom').style.marginTop = '160px'; }; //Clear All Overall Stats On Gamemode Change function clearAllOverallStats(){ //Duels document.getElementById('overall-stat-average-score-wrapper').style.display = 'none'; document.getElementById('overall-stat-average-distance-wrapper').style.display = 'none'; document.getElementById('overall-stat-closer-than-opponent-wrapper').style.display = 'none'; document.getElementById('overall-stat-average-time-wrapper').style.display = 'none'; document.getElementById('overall-stat-guessed-first-wrapper').style.display = 'none'; document.getElementById('overall-stat-total-5ks-wrapper').style.display = 'none'; document.getElementById('overall-stat-average-game-length-win-wrapper').style.display = 'none'; document.getElementById('overall-stat-average-game-length-loss-wrapper').style.display = 'none'; document.getElementById('overall-stat-opponent-rating-wrapper').style.display = 'none'; document.getElementById('duels-stats-spacing-wrapper-1').style.display = 'none'; document.getElementById('duels-stats-spacing-wrapper-2').style.display = 'none'; //Standard document.getElementById('standard-overall-stat-average-score-wrapper').style.display = 'none'; document.getElementById('standard-overall-stat-average-distance-wrapper').style.display = 'none'; document.getElementById('standard-overall-stat-average-round-time-wrapper').style.display = 'none'; document.getElementById('standard-overall-stat-average-game-time-wrapper').style.display = 'none'; document.getElementById('standard-overall-stat-total5ks-wrapper').style.display = 'none'; document.getElementById('standard-stats-spacing-wrapper-1').style.display = 'none'; } //If Current Gamemode Is Not Set if(!window.localStorage.getItem('geostats-current-gamemode-${USER_ID}')){ window.localStorage.setItem('geostats-current-gamemode-${USER_ID}', 'duels'); } //Event Listener For Gamemode Menu document.getElementById('geostats-gamemodes-menu').addEventListener('click', (e) => { let gameMode = e.target.id; if(!(gameMode.includes('duels') || gameMode.includes('classic'))){ return; } //Make all gray function menuItemsGray(){ let menuItems = document.getElementsByClassName('geostats-gamemodes-menu-item'); for(let i in menuItems){ if(i < menuItems.length){ menuItems[i].style.color = 'var(--ds-color-white-60)'; } } } //If duels - set the stats and make it white if(gameMode.includes('duels') && window.localStorage.getItem('overall-country-stats-${USER_ID}')){ //Clear All Current Overall Stats clearAllOverallStats(); //Set Stats setAllDuelsStats(); window.localStorage.setItem('geostats-current-gamemode-${USER_ID}', 'duels'); //Change Menu Color menuItemsGray(); document.getElementById('geostats-gamemodes-menu-item-duels').style.color = 'white'; //If country stats are open, change to duels if(document.getElementById('country-stats-page-wrapper').style.display == 'block'){ setupCountryStatsDuels('switch', window.localStorage.getItem('select-country-stats-id')); } } //If classic - set the stats and make it white else if(gameMode.includes('classic') && window.localStorage.getItem('geostats-overall-standard-stats-${USER_ID}')){ //Clear All Current Overall Stats clearAllOverallStats(); //Set stats setAllClassicStats(); window.localStorage.setItem('geostats-current-gamemode-${USER_ID}', 'classic'); //Change Menu Color menuItemsGray(); document.getElementById('geostats-gamemodes-menu-item-classic').style.color = 'white'; //If country stats are open, change to classic if(document.getElementById('country-stats-page-wrapper').style.display == 'block'){ setupCountryStatsClassic('switch', window.localStorage.getItem('select-country-stats-id')); } } }); //First Time clearAllOverallStats(); switch(window.localStorage.getItem('geostats-current-gamemode-${USER_ID}')){ case 'duels': if(window.localStorage.getItem('overall-country-stats-${USER_ID}')){ setAllDuelsStats(); } document.getElementById('geostats-gamemodes-menu-item-duels').style.color = 'white'; break; case 'classic': if(window.localStorage.getItem('geostats-overall-standard-stats-${USER_ID}')){ setAllClassicStats(); } document.getElementById('geostats-gamemodes-menu-item-classic').style.color = 'white'; break; } function mouseOverCountry(country){ if(typeof country.target !== 'undefined'){ country = country.target; } if (country.tagName == 'path'){ let content = country.dataset.name; //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 DUELS if(window.localStorage.getItem('geostats-current-gamemode-${USER_ID}') == 'duels'){ 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'; } } //IF CLASSIC else if(window.localStorage.getItem('geostats-current-gamemode-${USER_ID}') == 'classic'){ if(window.localStorage.getItem('geostats-' + target +'-all-standard-stats-${USER_ID}')){ let stats = JSON.parse(window.localStorage.getItem('geostats-' + target +'-all-standard-stats-${USER_ID}')); countryCorrect = stats.totalCorrect; countryTotal = stats.totalCount; countryPercentage = Math.floor(100 * (countryCorrect / countryTotal)); countryDistance = stats.averageDistance / 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"; } }; 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"; } }; 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'; //Scroll to the map window.scrollTo(0,2550); } 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'; //Reset button text if(window.localStorage.getItem('geostats-current-gamemode-${USER_ID}') == 'duels'){ document.getElementById('reset-scores-btn').textContent = 'Reset All Duels Stats'; } else if(window.localStorage.getItem('geostats-current-gamemode-${USER_ID}') == 'classic'){ document.getElementById('reset-scores-btn').textContent = 'Reset All Classic Stats'; } } }); //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.')){ if(window.localStorage.getItem('geostats-current-gamemode-${USER_ID}') == 'duels'){ resetDuelsScores(); } else if(window.localStorage.getItem('geostats-current-gamemode-${USER_ID}') == 'classic'){ resetClassicScores(); } //Reload the page location.reload(); } }); //Reset Duels Scores function resetDuelsScores(){ //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}'); }; //Reset Classic Scores function resetClassicScores(){ //Country countries.forEach(function(country){ window.localStorage.removeItem('geostats-' + country + '-all-standard-stats-${USER_ID}'); }); //Overall window.localStorage.removeItem('geostats-overall-standard-stats-${USER_ID}'); }; //OPEN COUNTRY STATS PAGE document.getElementById('map-wrapper-element').addEventListener('dblclick', (e) => { let countryId = (e.target.id).toUpperCase(); if(countryId.length != 2){ return; } //Setup window.localStorage.setItem('select-country-stats-id', countryId); //IF DUELS if(window.localStorage.getItem('geostats-current-gamemode-${USER_ID}') == 'duels'){ if(!window.localStorage.getItem(countryId + '-all-country-stats-${USER_ID}')){ return; } setupCountryStatsDuels(e,countryId); } //IF CLASSIC else if(window.localStorage.getItem('geostats-current-gamemode-${USER_ID}') == 'classic'){ if(!window.localStorage.getItem('geostats-' + countryId + '-all-standard-stats-${USER_ID}')){ return; } setupCountryStatsClassic(e,countryId); } //HIDE EVERYTHING 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'; //SHOW CORRECT STUFF document.getElementById("country-stats-page-wrapper").style.display = 'block'; document.getElementById('map-settings-btn').innerText = 'Back to Map'; }); //Setup For Country Stats (Duels) function setupCountryStatsDuels(type,countryId){ //Set the stats to the correct values for the country (IF THE COUNTRY HAS STATS) if(!window.localStorage.getItem(countryId + '-all-country-stats-${USER_ID}')){ return; } clearAllCountryStats(); setCountryStatsDuels(countryId); let countryName; //If Switching Gamemodes if(type == 'switch'){ countryName = document.getElementById(countryId).dataset.name } else{ countryName = type.target.dataset.name; } let countryCorrect = 0; let countryTotal = 0; let countryPercentage = 0; if(typeof countryName == 'undefined'){ countryName = type.target.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 + ' Duels Stats'; }; //Setup For Country Stats (Classic) function setupCountryStatsClassic(type,countryId){ //Set the stats to the correct values for the country (IF THE COUNTRY HAS STATS) if(!window.localStorage.getItem('geostats-' + countryId + '-all-standard-stats-${USER_ID}')){ return; } clearAllCountryStats(); setCountryStatsClassic(countryId); let countryName; //If Switching Gamemodes if(type == 'switch'){ countryName = document.getElementById(countryId).dataset.name } else{ countryName = type.target.dataset.name; } let countryCorrect = 0; let countryTotal = 0; let countryPercentage = 0; if(typeof countryName == 'undefined'){ countryName = type.target.textContent; } let stats = JSON.parse(window.localStorage.getItem('geostats-' + countryId + '-all-standard-stats-${USER_ID}')); countryCorrect = stats.totalCorrect; countryTotal = stats.totalCount; countryPercentage = Math.floor(100 * (countryCorrect / countryTotal)); document.getElementById('country-stats-display-details').textContent = countryName + ": " + countryCorrect + " / " + countryTotal + " (" + countryPercentage + "%)"; document.getElementById('country-stats-reset-btn').textContent = 'Reset All ' + countryName + ' Classic Stats'; }; //Clear All Country Stats On Gamemode Change function clearAllCountryStats(){ //Duels document.getElementById('country-stat-average-score-wrapper').style.display = 'none'; document.getElementById('country-stat-average-distance-wrapper').style.display = 'none'; document.getElementById('country-stat-closer-than-opponent-wrapper').style.display = 'none'; document.getElementById('country-stat-average-time-wrapper').style.display = 'none'; document.getElementById('country-stat-guessed-first-wrapper').style.display = 'none'; document.getElementById('country-stat-total-5ks-wrapper').style.display = 'none'; document.getElementById('duels-country-stats-spacing-wrapper-1').style.display = 'none'; //Standard document.getElementById('standard-country-stat-average-score-wrapper').style.display = 'none'; document.getElementById('standard-country-stat-average-distance-wrapper').style.display = 'none'; document.getElementById('standard-country-stat-average-round-time-wrapper').style.display = 'none'; document.getElementById('standard-country-stat-total-5ks-wrapper').style.display = 'none'; document.getElementById('standard-country-stats-total-time-spent').style.display = 'none'; document.getElementById('standard-country-stats-spacing-wrapper-1').style.display = 'none'; }; //SET COUNTRY STATS FOR DUELS(ON DOUBLE CLICK) function setCountryStatsDuels(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 document.getElementById('country-stats-distance-from-opponent-title').innerText = 'AVERAGE DISTANCE FROM OPPONENT'; //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; //SHOW CORRECT VALUES document.getElementById('country-stat-average-score-wrapper').style.display = 'flex'; document.getElementById('country-stat-average-distance-wrapper').style.display = 'flex'; document.getElementById('country-stat-closer-than-opponent-wrapper').style.display = 'flex'; document.getElementById('country-stat-average-time-wrapper').style.display = 'flex'; document.getElementById('country-stat-guessed-first-wrapper').style.display = 'flex'; document.getElementById('country-stat-total-5ks-wrapper').style.display = 'flex'; document.getElementById('duels-country-stats-spacing-wrapper-1').style.display = 'flex'; //CORRECT WIDTH FOR BOTTOM STATS document.getElementById('country-stats-distance-from-opponent').style.width = '50%'; document.getElementById('country-stats-country-streaks').style.width = '50%'; document.getElementById('standard-country-stats-total-time-spent').style.width = '50%'; }; //SET COUNTRY STATS FOR CLASSIC (ON DOUBLE CLICK) function setCountryStatsClassic(countryCode){ //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; } }; //OVERALL STATS let overallStats = JSON.parse(window.localStorage.getItem('geostats-' + countryCode + '-all-standard-stats-${USER_ID}')); let percentage; let percentageColor; let averageScore = Math.floor(overallStats.averageScore); let averageDistance = Math.floor(overallStats.averageDistance/1000); let averageRoundTime = Math.floor(overallStats.averageRoundTime); let total5ks = overallStats.total5ks; //Average Score findPercentage(averageScore, 5000); document.getElementById('standard-country-stat-average-score-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)'; document.getElementById('standard-country-stat-average-score-value').innerText = averageScore; //Average Distance findPercentage(2500-averageDistance, 2500); document.getElementById('standard-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('standard-country-stat-average-distance-title').innerText = 'Average Distance (mi)'; averageDistance = Math.floor(averageDistance / 1.609); } else{ document.getElementById('standard-country-stat-average-distance-title').innerText = 'Average Distance (km)'; } document.getElementById('standard-country-stat-average-distance-value').innerText = averageDistance; //Average Round Time findPercentage(120-averageRoundTime, 120); document.getElementById('standard-country-stat-average-round-time-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)'; document.getElementById('standard-country-stat-average-round-time-value').innerText = averageRoundTime; //Total 5ks findPercentage(total5ks, 10); document.getElementById('standard-country-stat-total-5ks-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)'; document.getElementById('standard-country-stat-total-5ks-value').innerText = total5ks; //BOTTOM STATS SETUP //Commonly Guessed Incorrectly document.getElementById('country-stats-distance-from-opponent-title').innerText = 'COMMONLY GUESSED INSTEAD'; let textColor = 'green'; let innerText = ''; if(Object.keys(overallStats.incorrectCountry).length != 0){ let incorrectGuesses = Object.entries(overallStats.incorrectCountry).sort((a,b) => b[1]-a[1]); for(let i = 0; i < ${TOP_INCORRECT_NUM}; i++){ let tempText = ''; if(i < incorrectGuesses.length && incorrectGuesses[i][0] != 'ERROR'){ tempText = document.getElementById(incorrectGuesses[i][0]).dataset.name + ' - ' + incorrectGuesses[i][1]; } innerText += tempText + '\\n'; } textColor = 'red'; } else{ innerText = 'N/A'; } document.getElementById('country-stats-distance-from-opponent-value').style.color = textColor; document.getElementById('country-stats-distance-from-opponent-value').innerText = innerText; //Country Streaks if(overallStats.countryCorrectStreak > 0){ document.getElementById('country-stats-country-streaks-value-current-value').innerText = overallStats.countryCorrectStreak + ' Correct'; document.getElementById('country-stats-country-streaks-value-current-value').style.color = 'green'; } else if(overallStats.countryWrongStreak > 0){ document.getElementById('country-stats-country-streaks-value-current-value').innerText = overallStats.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 = overallStats.countryCorrectMax; document.getElementById('country-stats-country-streaks-value-max-wrong-value').innerText = overallStats.countryWrongMax; //Time Spent let minutesPlayed = Math.floor(Math.floor(overallStats.totalSeconds / 60) % 60); let hoursPlayed = Math.floor(overallStats.totalSeconds / 3600); document.getElementById('standard-country-stats-total-time-spent-value').innerText = hoursPlayed + 'h ' + minutesPlayed + 'm '; //SHOW CORRECT VALUES document.getElementById('standard-country-stat-average-score-wrapper').style.display = 'flex'; document.getElementById('standard-country-stat-average-distance-wrapper').style.display = 'flex'; document.getElementById('standard-country-stat-average-round-time-wrapper').style.display = 'flex'; document.getElementById('standard-country-stat-total-5ks-wrapper').style.display = 'flex'; document.getElementById('standard-country-stats-total-time-spent').style.display = 'flex'; document.getElementById('standard-country-stats-spacing-wrapper-1').style.display = 'flex'; //CORRECT WIDTH FOR BOTTOM STATS document.getElementById('country-stats-distance-from-opponent').style.width = '33.333%'; document.getElementById('country-stats-country-streaks').style.width = '33.333%'; document.getElementById('standard-country-stats-total-time-spent').style.width = '33.333%'; }; //RESET SCORES FOR SELECTED COUNTRY document.getElementById('country-stats-reset-btn').addEventListener('click', () => { let resetId = window.localStorage.getItem('select-country-stats-id'); //Reset all scores for country if(confirm('Are you sure you want to reset your stats? This cannot be undone.')){ if(window.localStorage.getItem('geostats-current-gamemode-${USER_ID}') == 'duels'){ resetDuelsCountryScores(resetId); } else if(window.localStorage.getItem('geostats-current-gamemode-${USER_ID}') == 'classic'){ resetClassicCountryScores(resetId); } //Reload the page location.reload(); } }); //Reset Duels Country Scores function resetDuelsCountryScores(resetId){ 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; } //REMOVE FROM OVERALL countryCorrect = (parseInt(window.localStorage.getItem('overall-correct-${USER_ID}')) - countryCorrect); countryTotal = (parseInt(window.localStorage.getItem('overall-total-${USER_ID}')) - countryTotal); //Average Score let overallScore = overallStats.averageScore * overallStats.totalCount; let countryScore = countryStats.averageScore * countryStats.totalCount; overallStats.averageScore = (overallScore - countryScore) / (overallStats.totalCount - countryStats.totalCount); //Average Distance let overallDistance = overallStats.averageDistance * overallStats.totalCount; let countryDistance = countryStats.averageDistance * countryStats.totalCount; overallStats.averageDistance = (overallDistance - countryDistance) / (overallStats.totalCount - countryStats.totalCount); //Average Time let overallTime = overallStats.averageTime * overallStats.totalCount; let countryTime = countryStats.averageTime * countryStats.totalCount; overallStats.averageRoundTime = (overallTime - countryTime) / (overallStats.totalCount - countryStats.totalCount); //Average Distance From Opponent let overallAverageDistance = overallStats.distanceFromOpponent[0] * overallStats.distanceFromOpponent[1]; let countryAverageDistance = countryStats.distanceFromOpponent[0] * countryStats.distanceFromOpponent[1]; overallStats.distanceFromOpponent[0] = (overallStats.distanceFromOpponent[0] - countryStats.distanceFromOpponent[0]); overallStats.distanceFromOpponent[1] = (overallAverageDistance - countryAverageDistance) / overallStats.distanceFromOpponent[0]; //Incorrect Countries if(overallStats.incorrectCountry[resetId]){ delete overallStats.incorrectCountry[resetId]; } //Closer Than Opponent overallStats.closerThanOpponent -= countryStats.closerThanOpponent; //Guessed First overallStats.guessedFirst -= countryStats.guessedFirst; //Total 5ks overallStats.total5ks -= countryStats.total5ks; //Total Correct overallStats.totalCorrect -= countryStats.totalCorrect; //Total Count overallStats.totalCount -= countryStats.totalCount; //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}'); }; //Reset Classic Country Scores function resetClassicCountryScores(resetId){ let country = JSON.parse(window.localStorage.getItem('geostats-' + resetId + '-all-standard-stats-${USER_ID}')); let overall = JSON.parse(window.localStorage.getItem('geostats-overall-standard-stats-${USER_ID}')); //REMOVE FROM OVERALL //Average Score let overallScore = overall.averageScore * overall.totalCount; let countryScore = country.averageScore * country.totalCount; overall.averageScore = (overallScore - countryScore) / (overall.totalCount - country.totalCount); //Average Distance let overallDistance = overall.averageDistance * overall.totalCount; let countryDistance = country.averageDistance * country.totalCount; overall.averageDistance = (overallDistance - countryDistance) / (overall.totalCount - country.totalCount); //Average Round Time let overallRoundTime = overall.averageRoundTime * overall.totalCount; let countryRoundTime = country.averageRoundTime * country.totalCount; overall.averageRoundTime = (overallRoundTime - countryRoundTime) / (overall.totalCount - country.totalCount); //Total overall.totalCount -= country.totalCount; overall.totalCorrect -= country.totalCorrect; overall.total5ks -= country.total5ks; overall.totalSeconds -= country.totalSeconds; //Incorrect Countries if(overall.incorrectCountry[resetId]){ delete overall.incorrectCountry[resetId]; } // Remove country window.localStorage.removeItem('geostats-' + resetId + '-all-standard-stats-${USER_ID}'); //Save overall window.localStorage.setItem('geostats-overall-standard-stats-${USER_ID}',JSON.stringify(overall)); }; //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(); //UPLOAD AND DOWNLOAD STATS FILE let downloadFile = null; let uploadFileData = {}; let readyToUpload = false; let uploadData = null; function getAllDuelsStats(downloadData){ downloadData.gameMode = 'duels'; //Get All Scores for(let key in window.localStorage){ let newValue = []; if(key.includes('${USER_ID}')){ if(key.includes('-number-correct-') || key.includes('-number-total-') || key.includes('-distance-average-') || key.includes('-distance-number-') || key.includes('-all-country-stats-') || key.includes('overall-total-') || key.includes('overall-correct-') || key.includes('overall-country-stats-')){ newValue.push(key); if(isJson(window.localStorage[key])){ newValue.push(JSON.parse(window.localStorage[key])); } else{ newValue.push(window.localStorage[key]); } downloadData.userInfo.push(newValue); } } } }; function getAllClassicStats(downloadData){ downloadData.gameMode = 'classic'; //Country countries.forEach(function(country){ let key = 'geostats-' + country + '-all-standard-stats-${USER_ID}'; if(window.localStorage.getItem(key)){ downloadData.userInfo.push([key, JSON.parse(window.localStorage.getItem(key))]); } }); //Overall key = 'geostats-overall-standard-stats-${USER_ID}'; if(window.localStorage.getItem(key)){ downloadData.userInfo.push([key , JSON.parse(window.localStorage.getItem(key))]); } //Included Maps key = 'geostats-classic-included-maps-${USER_ID}'; if(window.localStorage.getItem(key)){ downloadData.userInfo.push([key , JSON.parse(window.localStorage.getItem(key))]); } //Unfinished Classic Games key = 'geostats-unfinished-classic-games-${USER_ID}'; if(window.localStorage.getItem(key)){ downloadData.userInfo.push([key , JSON.parse(window.localStorage.getItem(key))]); } }; function getAllGamemodeStats(downloadData){ downloadData.gameMode = 'all'; for(let key in window.localStorage){ let newValue = []; if(key.includes('${USER_ID}')){ newValue.push(key); if(isJson(window.localStorage[key])){ newValue.push(JSON.parse(window.localStorage[key])); } else{ newValue.push(window.localStorage[key]); } downloadData.userInfo.push(newValue); } } }; function isJson(string){ try{ JSON.parse(string); } catch(e){ return false; } return true; }; //DOWNLOAD function getFileContent(){ let downloadData = { type: 'GeoStats_Object', id: '${USER_ID}', gameMode: '', userInfo: [] }; //Get Settings Values if(window.localStorage.getItem('units-svg-map')){ downloadData.userInfo.push(['units-svg-map', window.localStorage.getItem('units-svg-map')]); } if(window.localStorage.getItem('allow-healing-rounds')){ downloadData.userInfo.push(['allow-healing-rounds', JSON.parse(window.localStorage.getItem('allow-healing-rounds'))]); } if(window.localStorage.getItem('competitive-only-mode')){ downloadData.userInfo.push(['competitive-only-mode', JSON.parse(window.localStorage.getItem('competitive-only-mode'))]); } let baseInfoCount = downloadData.userInfo.length + 4; //+4 is for: "update, setup, left range, right range" in localstorage let userOption = prompt("Which Stats Would You Like To Download?\\nEnter 'd' for Duels, 'c' for Classic, or 'a' for All"); switch(userOption){ case 'd': getAllDuelsStats(downloadData); break; case'c': getAllClassicStats(downloadData); break; case 'a': getAllGamemodeStats(downloadData); break; case null: return 'NO OPTION SELECTED'; break; default: return 'INVALID INPUT'; } //If There Are No Stats To Download if(downloadData.userInfo.length <= baseInfoCount){ return 'NO EXISTING STATS TO DOWNLOAD'; } return JSON.stringify(downloadData); }; function makeTextFile(text){ let data = new Blob([text], {type: 'text/plain'}); if(downloadFile != null){ window.URL.revokeObjectURL(downloadFile); } downloadFile = window.URL.createObjectURL(data); return downloadFile; }; function downloadAllStats(e){ if(!e.isTrusted){ return; } let link = document.getElementById('download-link'); let fileContent = getFileContent(); if(fileContent == 'NO EXISTING STATS TO DOWNLOAD'){ document.getElementById('download-file-status').style.color = 'red'; document.getElementById('download-file-status').textContent = 'No Existing Stats To Download'; } else if(fileContent == 'NO OPTION SELECTED'){ document.getElementById('download-file-status').style.color = 'red'; document.getElementById('download-file-status').textContent = 'No option selected'; } else if(fileContent == 'INVALID INPUT'){ document.getElementById('download-file-status').style.color = 'red'; document.getElementById('download-file-status').textContent = 'Invalid Input'; } else{ link.href = makeTextFile(fileContent); link.click(); document.getElementById('download-file-status').style.color = 'green'; document.getElementById('download-file-status').textContent = 'Successfully Downloaded Stats'; } }; //UPLOAD function deleteOldStats(gameMode){ switch(gameMode){ case 'duels': resetDuelsScores(); break; case 'classic': resetClassicScores(); break; case 'all': for(let key in window.localStorage){ if(key.includes('${USER_ID}')){ window.localStorage.removeItem(key); } } break; default: } }; function addNewStats(){ uploadFileData.userInfo.forEach((value) => { if(typeof value[1] === 'string'){ window.localStorage.setItem(value[0], value[1]); } else{ window.localStorage.setItem(value[0], JSON.stringify(value[1])); } }); }; function getFileData(event){ let reader = new FileReader(); reader.readAsText(event.target.files[0]); reader.addEventListener('load', (event) => { try{ //Check if file content is JSON if(!isJson(event.target.result)){ throw "File Content Is Not Json"; } uploadFileData = JSON.parse(event.target.result); //Check if the object is the right one if(uploadFileData.type != 'GeoStats_Object'){ throw "File Content Is The Wrong Type"; } //Check if the file stats have the same user id if(uploadFileData.id != '${USER_ID}'){ throw "File Contains Different User Id"; } let gameMode = uploadFileData.gameMode; if(confirm('Are you sure you want to upload new stats? This will erase ' + gameMode + ' exisiting stats.')){ //Delete existing stats deleteOldStats(gameMode); //Add new stats addNewStats(); //If all good document.getElementById('upload-file-status').style.color = 'green'; document.getElementById('upload-file-status').textContent = 'Successfully Uploaded New Stats - Reload Page'; } } catch(message){ //If error exists document.getElementById('upload-file-status').style.color = 'red'; document.getElementById('upload-file-status').textContent = message; } }); }; function checkFile(event){ readyToUpload = false; uploadData = null; document.getElementById('select-file-status').style.color = 'red'; document.getElementById('select-file-status').textContent = event.target.files[0].name; //Check if the file is the right type to upload if(event.target.files.length != 1){ return; } if(event.target.files[0].type != 'text/plain'){ return; } //If all good readyToUpload = true; uploadData = event; document.getElementById('select-file-status').style.color = 'green'; }; //Add Event Listeners For Upload and Download document.getElementById('download-file-button').addEventListener('click', downloadAllStats); document.getElementById('select-file-button').addEventListener('change', checkFile); document.getElementById('upload-file-button').addEventListener('click', () => { if(readyToUpload){ getFileData(uploadData); } else{ document.getElementById('upload-file-status').style.color = 'red'; document.getElementById('upload-file-status').textContent = 'Please Select A File To Upload'; } }); //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'; 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'; } //When user scrolls mouse function onMouseWheel(event){ if(!event.shiftKey){ return; } event.preventDefault(); let delta = (event.wheelDelta ? event.wheelDelta : -event.deltaY); mousePoint = getPointFromEvent(event); //If mouse wheel moves forward if(delta > 0){ //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){ //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); }`; //Add Everything To The Page let referenceNode = document.getElementsByClassName('version4_main__Zjun_')[0]; let siblingNode = document.getElementsByClassName('version4_notificationPreviewList__OOMPZ')[0]; //If old version (version 3) if(document.getElementsByClassName('version3_main__xNkED').length > 0 && document.getElementsByClassName('footer_footer__NmtmJ').length > 0){ referenceNode = document.getElementsByClassName('version3_main__xNkED')[0]; siblingNode = document.getElementsByClassName('footer_footer__NmtmJ')[0]; } referenceNode.parentNode.insertBefore(svgMap, siblingNode); document.head.appendChild(cssForMap); document.getElementById('map-wrapper-element').appendChild(scriptForMap); }; /************************************************** START PAGE STUFF HERE **************************************************/ function addToggleToStartPage(){ //Create The Html const htmlForToggle = `

GeoStats Settings

Track Stats For This Map
`; //Create The Script const scriptForToggle = document.createElement('script'); scriptForToggle.setAttribute('id','geostats-standard-game-start-page-toggle-script'); scriptForToggle.textContent = `{ //Check If Toggle Should Be Checked let maps = JSON.parse(window.localStorage.getItem('geostats-classic-included-maps-${USER_ID}')); let currentMapId = window.location.href.replace('https://www.geoguessr.com/maps/', ''); currentMapId = currentMapId.replace('/play', ''); if(maps.ids.includes(currentMapId)){ document.getElementById('geostats-track-stats-for-this-map-toggle').checked = true; } //When The Toggle Changes function toggleChange(toggle){ let currentMapId = window.location.href.replace('https://www.geoguessr.com/maps/', ''); currentMapId = currentMapId.replace('/play', ''); let maps = JSON.parse(window.localStorage.getItem('geostats-classic-included-maps-${USER_ID}')); if(toggle.target.checked){ //Add The Map Id if(!maps.ids.includes(currentMapId)){ maps.ids.push(currentMapId); } } else{ //Remove The Map Id if(maps.ids.includes(currentMapId)){ const index = maps.ids.indexOf(currentMapId); maps.ids.splice(index,1); } } //Save Updated Maps List window.localStorage.setItem('geostats-classic-included-maps-${USER_ID}', JSON.stringify(maps)); } document.getElementById('geostats-track-stats-for-this-map-toggle').addEventListener('click', toggleChange); }`; //Add Everything To The Page document.querySelector('.section_sectionMedium__wbXjF').insertAdjacentHTML('beforeend', htmlForToggle); document.getElementById('geostats-standard-game-start-page-toggle-html').appendChild(scriptForToggle); }; let observer = new MutationObserver((mutations) => { startpageCheck(); }); observer.observe(document.body, { characterDataOldValue: false, subtree: true, childList: true, characterData: false }); //************************************************************** END OF SCRIPT **************************************************************//