// ==UserScript==
// @name Geoguessr GeoStats Script
// @description Keeps track of various stats in duels games and displays it on an interactive map on your profile
// @author nappyslappy
// @version 2.1.0
// @match https://www.geoguessr.com/*
// @grant none
// @license none
// @icon https://www.google.com/s2/favicons?sz=64&domain=geoguessr.com
// @copyright nappyslappy 2022, (https://greasyfork.org/en/users/922456)
// @namespace https://greasyfork.org/en/users/922456-nappyslappy
// @downloadURL none
// ==/UserScript==
//Published: June 6th, 2022
//Last Update: August 6th, 2022
//******************************* SETUP *******************************//
/* */
/* If you haven't already, download the free extension 'tampermonkey' */
/* and then install this script */
/* */
/* Go to your profile page and setup the script at the bottom */
/* */
/* You do not need an API key to use this script */
/* nor do you need to change anything below */
/* */
/***********************************************************************/
//************************************************************* START OF SCRIPT *************************************************************//
//Global Variables
let USER_ID = JSON.parse(document.getElementById('__NEXT_DATA__').innerText).props.middlewareResults[0].account.user.userId;
let statsToProfile = false;
let setupToProfile = false;
let player_index = 0;
let previous_last_guess_number = 0;
//Map Colors
let green_range = 0.75;
let yellow_range = 0.25;
let red_range = 0;
if(window.localStorage.getItem(`duels-map-color-left-range-${USER_ID}`)){
green_range = parseInt(window.localStorage.getItem(`duels-map-color-right-range-${USER_ID}`)) * 0.01;
yellow_range = parseInt(window.localStorage.getItem(`duels-map-color-left-range-${USER_ID}`)) * 0.01;
}
else{
window.localStorage.setItem(`duels-map-color-left-range-${USER_ID}`, 25);
window.localStorage.setItem(`duels-map-color-right-range-${USER_ID}`, 75);
}
//Set the healing rounds toggle switch
if(window.localStorage.getItem('allow-healing-rounds') == null){
window.localStorage.setItem('allow-healing-rounds', JSON.stringify({include: true}));
}
//Set the competitive mode toggle switch
if(window.localStorage.getItem('competitive-only-mode') == null){
window.localStorage.setItem('competitive-only-mode', JSON.stringify({include: true}));
}
//Evaluate the new guess
function evaluate(guess,location,distance,userScore,opponentScore,startTime,timerTime,guessTime,opponentDistance){
//If guess is in antarctica (black screen round)
if(guess == 'AQ'){
return;
}
let correct_exists = window.localStorage.getItem(`${location}-number-correct-${USER_ID}`);
let total_exists = window.localStorage.getItem(`${location}-number-total-${USER_ID}`);
let correct_overall = window.localStorage.getItem(`overall-correct-${USER_ID}`);
let total_overall = window.localStorage.getItem(`overall-total-${USER_ID}`);
let correct_value = 1;
let total_value = 1;
//Setting correct value
if(guess === location){
if(correct_exists !== null){
correct_value = parseInt(correct_exists,10);
correct_value = correct_value + 1;
}
window.localStorage.setItem(`${location}-number-correct-${USER_ID}`,correct_value);
}
//Setting overall values
if(total_overall !== null){
if(guess === location){
window.localStorage.setItem(`overall-correct-${USER_ID}`,((parseInt(correct_overall,10))+1));
}
window.localStorage.setItem(`overall-total-${USER_ID}`,((parseInt(total_overall,10))+1));
}
else{
if(guess === location){
window.localStorage.setItem(`overall-correct-${USER_ID}`,1);
}
else{
window.localStorage.setItem(`overall-correct-${USER_ID}`,0);
}
window.localStorage.setItem(`overall-total-${USER_ID}`,1);
}
//Setting total value
if(total_exists !== null){
total_value = parseInt(total_exists,10);
total_value = total_value + 1;
}
window.localStorage.setItem(`${location}-number-total-${USER_ID}`,total_value);
//Setting distance
let distance_average = window.localStorage.getItem(`${location}-distance-average-${USER_ID}`);
let distance_number = window.localStorage.getItem(`${location}-distance-number-${USER_ID}`);
if(distance_average === null && distance_number === null){
window.localStorage.setItem(`${location}-distance-average-${USER_ID}`,distance);
window.localStorage.setItem(`${location}-distance-number-${USER_ID}`,1);
}
else{
distance_number = parseInt(distance_number) + 1;
distance_average = ((distance_average * (distance_number - 1)) + distance) / distance_number;
window.localStorage.setItem(`${location}-distance-average-${USER_ID}`,distance_average);
window.localStorage.setItem(`${location}-distance-number-${USER_ID}`,distance_number);
}
//SETTING ALL OTHER STATS FOR COUNTRY AND OVERALL
let countryStats = {
totalCount: 0,
averageScore: 0,
averageDistance: 0,
closerThanOpponent: 0,
averageTime: 0,
guessedFirst: 0,
total5ks: 0,
countryCorrectStreak: 0,
countryCorrectMax: 0,
countryWrongStreak: 0,
countryWrongMax: 0,
distanceFromOpponent: [0,0],
};
let overallStats = {
//Total
totalCount: 0,
totalWin: 0,
totalLoss: 0,
total5ks: 0,
totalGames: 0,
totalSeconds: 0,
//Average
averageScore: 0,
averageDistance: 0,
averageGameLengthWin: 0,
averageGameLengthLoss: 0,
averageTime: 0,
//Other
guessedFirst: 0,
closerThanOpponent: 0,
countryCorrectStreak: 0,
countryCorrectMax: 0,
countryWrongStreak: 0,
countryWrongMax: 0,
opponentRating: 0,
distanceFromOpponent: [0,0],
};
if(window.localStorage.getItem(`${location}-all-country-stats-${USER_ID}`)){
countryStats = JSON.parse(window.localStorage.getItem(`${location}-all-country-stats-${USER_ID}`));
}
if(window.localStorage.getItem(`overall-country-stats-${USER_ID}`)){
overallStats = JSON.parse(window.localStorage.getItem(`overall-country-stats-${USER_ID}`));
}
//Time String to Seconds
function timeToSeconds(value){
let time = value.slice(11,19);
time = time.split(/[.:]/);
time = (parseInt(time[0]) * 60 * 60) + (parseInt(time[1]) * 60) + parseInt(time[2]);
return time;
}
//Get Correct Time Values
startTime = timeToSeconds(startTime);
timerTime = timeToSeconds(timerTime);
guessTime = timeToSeconds(guessTime);
let timeToGuess = guessTime - startTime;
//Total Count
countryStats.totalCount++;
overallStats.totalCount++;
//Average Score
countryStats.averageScore = ((countryStats.averageScore * (countryStats.totalCount - 1)) + userScore) / countryStats.totalCount;
overallStats.averageScore = ((overallStats.averageScore * (overallStats.totalCount - 1)) + userScore) / overallStats.totalCount;
//Average Distance
countryStats.averageDistance = ((countryStats.averageDistance * (countryStats.totalCount - 1)) + distance) / countryStats.totalCount;
overallStats.averageDistance = ((overallStats.averageDistance * (overallStats.totalCount - 1)) + distance) / overallStats.totalCount;
//Average Time
countryStats.averageTime = ((countryStats.averageTime * (countryStats.totalCount - 1)) + timeToGuess) / countryStats.totalCount;
overallStats.averageTime = ((overallStats.averageTime * (overallStats.totalCount - 1)) + timeToGuess) / overallStats.totalCount;
//Closer Than Opponent
if(userScore >= opponentScore){
countryStats.closerThanOpponent++;
overallStats.closerThanOpponent++;
}
//Guessed First
if(guessTime == timerTime){
countryStats.guessedFirst++;
overallStats.guessedFirst++;
}
//Total 5ks
if(userScore >= 4999){
countryStats.total5ks++;
overallStats.total5ks++;
}
//Country Streak (Correct)
if(guess == location){
//Country
countryStats.countryWrongStreak = 0;
countryStats.countryCorrectStreak++;
if(countryStats.countryCorrectStreak > countryStats.countryCorrectMax){
countryStats.countryCorrectMax = countryStats.countryCorrectStreak;
}
//Overall
overallStats.countryWrongStreak = 0;
overallStats.countryCorrectStreak++;
if(overallStats.countryCorrectStreak > overallStats.countryCorrectMax){
overallStats.countryCorrectMax = overallStats.countryCorrectStreak;
}
}
//Country Streak (Incorrect)
if(guess != location){
//Country
countryStats.countryCorrectStreak = 0;
countryStats.countryWrongStreak++;
if(countryStats.countryWrongStreak > countryStats.countryWrongMax){
countryStats.countryWrongMax = countryStats.countryWrongStreak;
}
//Overall
overallStats.countryCorrectStreak = 0;
overallStats.countryWrongStreak++;
if(overallStats.countryWrongStreak > overallStats.countryWrongMax){
overallStats.countryWrongMax = overallStats.countryWrongStreak;
}
}
//Distance From Opponent
if(opponentDistance != 'DNF'){
let distanceDifference = opponentDistance - distance;
//Country
if(countryStats.distanceFromOpponent){
countryStats.distanceFromOpponent[0]++;
countryStats.distanceFromOpponent[1] = ((countryStats.distanceFromOpponent[1] * (countryStats.distanceFromOpponent[0] - 1)) + distanceDifference) / countryStats.distanceFromOpponent[0];
}
else{
countryStats.distanceFromOpponent = [1,distanceDifference];
}
//Overall
if(overallStats.distanceFromOpponent){
overallStats.distanceFromOpponent[0]++;
overallStats.distanceFromOpponent[1] = ((overallStats.distanceFromOpponent[1] * (overallStats.distanceFromOpponent[0] - 1)) + distanceDifference) / overallStats.distanceFromOpponent[0];
}
else{
overallStats.distanceFromOpponent = [1,distanceDifference];
}
}
//Save Updated Stats
window.localStorage.setItem(`${location}-all-country-stats-${USER_ID}`, JSON.stringify(countryStats));
window.localStorage.setItem(`overall-country-stats-${USER_ID}`, JSON.stringify(overallStats));
};
//Add Stats When Game Is Finished
function gameFinished(opponentRating,userBefore,userAfter,gameId,gameLength,start,end){
if(window.sessionStorage.getItem('current-game-id') == gameId){
return;
}
window.sessionStorage.setItem('current-game-id', gameId);
//Time String to Seconds
function timeToSeconds(value){
let time = value.slice(11,19);
time = time.split(/[.:]/);
time = (parseInt(time[0]) * 60 * 60) + (parseInt(time[1]) * 60) + parseInt(time[2]);
return time;
}
let overallStats = JSON.parse(window.localStorage.getItem(`overall-country-stats-${USER_ID}`));
let gameTime = timeToSeconds(end) - timeToSeconds(start);
//Total Games Played
overallStats.totalGames++;
//Average Opponent Rating
overallStats.opponentRating = ((overallStats.opponentRating * (overallStats.totalGames - 1)) + opponentRating) / overallStats.totalGames;
//Win or Loss
let win = false;
if(userAfter - userBefore >= 0){
win = true;
}
//Game Length (Win)
if(win){
overallStats.totalWin++;
overallStats.averageGameLengthWin = ((overallStats.averageGameLengthWin * (overallStats.totalWin - 1)) + gameLength) / overallStats.totalWin;
}
//Game Length (Loss)
if(!win){
overallStats.totalLoss++;
overallStats.averageGameLengthLoss = ((overallStats.averageGameLengthLoss * (overallStats.totalLoss - 1)) + gameLength) / overallStats.totalLoss;
}
//Total Seconds Played
if(overallStats.totalSeconds){
overallStats.totalSeconds += gameTime;
}
else{
overallStats.totalSeconds = gameTime;
}
//Save Updated Stats
window.localStorage.setItem(`overall-country-stats-${USER_ID}`, JSON.stringify(overallStats));
};
//Get the guess country code
async function getGuessCountryCode(location){
if(location[0] <= -85.05 || location == null){
return 'AQ';
}
else{
let api = "https://nominatim.openstreetmap.org/reverse.php?lat="+location[0]+"&lon="+location[1]+"&format=jsonv2";
let country_code = await fetch(api)
.then(res => res.json())
.then((out) => {
return out.address.country_code;
})
return country_code.toUpperCase();
};
};
//Check if a new guess has been made
async function checkGuess(api){
return new Promise((resolve,reject) => {
fetch(api,{credentials: 'include'})
.then((res) => res.json())
.then((out) => {
if(out.teams[0].players[0].playerId === USER_ID){
player_index = 0;
}
else if(out.teams[1].players[0].playerId === USER_ID){
player_index = 1;
}
else{
return;
}
//If competitve only mode is on
let competitiveOnly = JSON.parse(window.localStorage.getItem('competitive-only-mode'));
if(competitiveOnly.include && !out.options.isRated){
return;
}
let last_guess_number = out.teams[player_index].players[0].guesses.length;
//If the game is finished
if(out.status == 'Finished'){
let opponentIndex = 0;
if(player_index == 0){
opponentIndex = 1;
}
let opponentRatingBefore = out.teams[opponentIndex].players[0].rating;
let userRatingBefore = out.teams[player_index].players[0].progressChange.competitiveProgress.ratingBefore;
let userRatingAfter = out.teams[player_index].players[0].progressChange.competitiveProgress.ratingAfter;
let gameLength = out.currentRoundNumber;
let gameStartTime = out.rounds[0].startTime;
let gameEndTime = out.rounds[gameLength-1].endTime;
gameFinished(opponentRatingBefore,userRatingBefore,userRatingAfter,out.gameId,gameLength,gameStartTime,gameEndTime);
return;
}
//If the round's guesses haven't been sent
if(out.teams[player_index].roundResults.length != last_guess_number){
return;
}
//If a new guess hasn't been made
if(last_guess_number == previous_last_guess_number){
return;
}
else if(out.teams[player_index].players[0].guesses[last_guess_number-1].roundNumber !== out.currentRoundNumber){
return;
}
//If include healing toggle is off
let allowHealing = JSON.parse(window.localStorage.getItem('allow-healing-rounds'));
if(!allowHealing.include && out.rounds[out.currentRoundNumber-1].isHealingRound){
return;
}
let current_guess = [out.teams[player_index].players[0].guesses[last_guess_number-1].lat, out.teams[player_index].players[0].guesses[last_guess_number-1].lng];
//If the player refreshes during the 15 second countdown after making a guess
if(current_guess[0] == window.sessionStorage.getItem('last-guess-lat') && current_guess[1] == window.sessionStorage.getItem('last-guess-lng')){
return;
}
else{
window.sessionStorage.setItem('last-guess-lat', current_guess[0]);
window.sessionStorage.setItem('last-guess-lng', current_guess[1]);
}
//Everything is good
previous_last_guess_number = last_guess_number;
let current_round = out.currentRoundNumber;
getGuessCountryCode(current_guess)
.then((guess) => {
//Get all values
let location_code = out.rounds[current_round-1].panorama.countryCode.toUpperCase();
let distance = out.teams[player_index].players[0].guesses[last_guess_number-1].distance;
let opponent_index = 0;
if(player_index == 0){
opponent_index = 1;
}
let userScore = out.teams[player_index].roundResults[last_guess_number-1].score;
let opponentScore = out.teams[opponent_index].roundResults[last_guess_number-1].score;
let startTime = out.rounds[current_round-1].startTime;
let timerTime = out.rounds[current_round-1].timerStartTime;
let guessTime = out.teams[player_index].players[0].guesses[last_guess_number-1].created;
let opponentDistance = 'DNF';
let opponentGuess = out.teams[opponent_index].players[0];
if(opponentGuess.guesses[opponentGuess.guesses.length-1].roundNumber == current_round){
opponentDistance = opponentGuess.guesses[opponentGuess.guesses.length-1].distance;
}
//If guess is good
if(guess != undefined){
//Evaluate all values and update stats
evaluate(guess,location_code,distance,userScore,opponentScore,startTime,timerTime,guessTime,opponentDistance);
}
resolve(out);
});
})
.catch((error) => {
reject(error);
});
});
}
//Check if the user is on the profile page
function profileCheck(){
if(location.pathname.endsWith('/profile')){
if(window.localStorage.getItem(`geostats-setup-complete-${USER_ID}`) && !statsToProfile){
addMapToProfile();
}
else if(!window.localStorage.getItem(`geostats-setup-complete-${USER_ID}`) && !setupToProfile){
addSetupPageToProfile();
}
}
else if(!location.pathname.endsWith('/profile') && statsToProfile){
statsToProfile = false;
document.getElementById('map-wrapper-element').remove();
document.getElementById('css-for-map').remove();
}
}
//Check if the user is playing a duels game
function duelsCheck(){
if(!location.pathname.startsWith('/duels/') || location.pathname.endsWith('/summary')){
return;
}
const game_tag = window.location.href.substring(window.location.href.lastIndexOf('/') + 1);
const api_url = "https://game-server.geoguessr.com/api/duels/"+game_tag;
checkGuess(api_url);
};
//Run duelsCheck and profileCheck every half-second
setInterval(duelsCheck,500);
setInterval(profileCheck,500);
//Console Log Script Name
console.log('*** Geoguessr GeoStats v2.1.0 by NappySlappy ***');
/************************************************** SETUP STUFF HERE **************************************************/
//Add the setup page to the bottom of the profile page when the user uses the script for the first time
function addSetupPageToProfile(){
setupToProfile = true;
//Create The Setup Elements
const cssForSetup = document.createElement('style');
cssForSetup.setAttribute('id','geostats-setup-css');
const htmlForSetup = document.createElement('div');
htmlForSetup.setAttribute('id','geostats-setup-html');
const scriptForSetup = document.createElement('script');
scriptForSetup.setAttribute('id','geostats-setup-script');
//CSS For Setup
cssForSetup.textContent = `
#setup-page-title-wrapper{
margin: 20px auto;
text-align: center;
}
#setup-page-title{
font-family: var(--font-neo-sans);
font-size: 40px;
color: white;
}
#setup-page-content-wrapper{
margin: 20px auto;
text-align: center;
width: 65%;
border: solid 2px white;
border-radius: 40px;
}
#setup-page-content{
font-family: var(--font-neo-sans);
font-size: 20px;
color: white;
padding: 20px;
}
#setup-page-button-wrapper{
margin: 20px auto;
text-align: center;
}
#setup-page-button{
border-radius: 15px;
background-color: transparent;
color: white;
border-color: white;
padding: 5px 10px 5px 10px;
}
#setup-page-button:hover{
background-color: white;
color: black;
border-color: black;
cursor: pointer;
}
`;
//HTML For Setup
htmlForSetup.innerHTML = `
Welcome To GeoStats!
`;
//SCRIPT For Setup
scriptForSetup.textContent = `
let currentSlide = 0;
let firstSlide = "This script was made to keep track of various stats in duels matches. It will monitor your duels guesses and keep a unique record of stats for each country, as well as for your overall stats. If there is a round where you don't make a guess, it won't count against you. Guesses made in antarctica will also not count since it is not available on the map.";
let secondSlide = "All of the stats will be visible at the bottom of your profile page. Some countries are too small to show on the map so there is a search bar on the left side to filter through them. You can hover over a country to see your percentage of getting it correct and double click it to view more detailed stats.";
let thirdSlide = "You can reset your stats by clicking the 'Reset All Scores' button in settings, as well as for individual countries. Keep in mind that all information is stored in your browser on your device so the same stats will not be available on different devices or on different browsers. This means that clearing your browser cache will unfortunatlely also clear all of your stats.";
let fourthSlide = "The creator of this script is NappySlappy. Please leave some feedback if you like the script or if you have any ideas for improvements. Thanks! :)";
let allSliders = [firstSlide,secondSlide,thirdSlide,fourthSlide];
function changeSlide(){
currentSlide++;
if(currentSlide == allSliders.length){
window.localStorage.setItem('geostats-setup-complete-${USER_ID}', new Date());
document.getElementById('geostats-setup-css').remove();
document.getElementById('geostats-setup-html').remove();
}
else{
if(currentSlide == allSliders.length-1){
document.getElementById('setup-page-button').textContent = 'View Stats';
}
document.getElementById('setup-page-content').textContent = allSliders[currentSlide];
}
}
document.getElementById('setup-page-content').textContent = allSliders[0];
document.getElementById('setup-page-button').addEventListener('click', changeSlide);
`;
//Add Everything To The Page
let referenceNode = document.getElementsByClassName('version3_main__xNkED')[0];
let siblingNode = document.getElementsByClassName('footer_footer__NmtmJ')[0];
referenceNode.parentNode.insertBefore(htmlForSetup, siblingNode);
document.head.appendChild(cssForSetup);
document.getElementById('geostats-setup-html').appendChild(scriptForSetup);
}
/************************************************** MAP STUFF HERE **************************************************/
//Add the map (and related stuff) to the bottom of the profile page
function addMapToProfile(){
statsToProfile = true;
const svgMap = document.createElement('div');
svgMap.setAttribute('id','map-wrapper-element');
const cssForMap = document.createElement('style');
cssForMap.setAttribute('id', 'css-for-map');
const scriptForMap = document.createElement('script');
scriptForMap.setAttribute('id', 'script-for-map');
cssForMap.textContent = `
.map-wrapper-element{
position: relative;
left: 0px;
}
#map-title{
font-size: 30px;
text-align: center;
color: var(--ds-color-yellow-50);
font-family: var(--font-neo-sans);
}
#total-percentage-wrapper{
width: 100%;
background-color: gray;
height: 50px;
position: relative;
}
#total-percentage-text-wrapper{
position: absolute;
left: 0;
right: 0;
height: 100%;
}
#total-percentage-text{
display: flex;
font-size: 20px;
height: 100%;
justify-content: center;
align-items: center;
color: black;
}
#total-percentage-bar{
width: 50%;
height: 100%;
background-color: gold;
}
.display-wrapper{
margin: 0 auto;
padding: 10px;
width: fit-content;
font-size: 20px;
}
.display-wrapper #display-country-details{
visibility: show;
color: white;
}
.display-wrapper #display-country-distance{
visibility: show;
font-size: 16px;
display: flex;
align-items: center;
justify-content: center;
}
.map-wrapper{
margin: 0 auto;
pointer-events: none;
padding-bottom: 25px;
}
#world-map {
display: block;
position: relative;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: auto;
transform: scale(1);
transform-origin: 0px 0px;
z-index: 2;
border-top-style: solid;
border-bottom-style: solid;
border-width: 0.5px;
border-color: #fbfafa;
}
#world-map path{
stroke: white;
fill: black;
transition: fill 0.3s ease;
pointer-events: all;
}
#world-map path:hover{
fill: rgb(175, 175, 175);
pointer-events: all;
cursor: pointer;
}
#details-box {
padding: 1rem;
border-radius: 8px;
font-size: 14px;
position: fixed;
color: white;
font-family: "Poppins";
background-color: gray;
width: fit-content;
transform: translateX(-50%);
transition: opacity .4s ease;
z-index: 3;
}
#search-bar-wrapper{
pointer-events: all;
position: absolute;
z-index: 3;
}
#search-bar {
box-sizing: border-box;
z-index: 3;
}
#search-bar-list {
list-style: none;
display: none;
z-index: 3;
}
#search-bar-list li {
padding: 10px;
width: 73.5%;
border-bottom: 2px solid #ffffff;
z-index: 3;
text-align: center;
}
#search-bar-list li:hover {
background: #ffffff;
color: #000000;
cursor: pointer;
}
#overall-stats-page-wrapper{
}
#overall-stats-display-details{
color: var(--ds-color-yellow-50);
margin: 0 auto;
width: fit-content;
font-size: 30px;
padding: 20px;
}
#overall-stats-values-progress-circles{
display: flex;
height: 300px;
flex-direction: row;
flex-wrap: wrap;
}
#overall-stats-values-bottom{
border-top: .0625rem solid;
margin-top: 360px;
margin-bottom: 50px;
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.overall-stats-bottom-elements{
margin: 20px 0;
width: 33.333%;
text-align: center;
display: flex;
flex-direction: column;
}
#overall-stats-distance-from-opponent-value{
font-size: 30px;
width: 50%;
margin: 20px 25%;
}
#overall-stats-total-play-time-value{
font-size: 30px;
width: 50%;
margin: 20px 25%;
}
#country-stats-page-wrapper{
}
#country-stats-display-title{
margin: 0 auto;
padding: 10px;
width: fit-content;
font-size: 20px;
}
#country-stats-display-details{
visibility: show;
color: white;
}
#country-stats-wrapper{
}
#country-stats-values{
display: flex;
height: 300px;
flex-direction: row;
flex-wrap: wrap;
}
.country-stat-wrapper{
width: 33.333%;
height: 50%;
text-align: center;
display: flex;
flex-direction: column;
}
.country-stat-outer-circle{
position: relative;
height: 100px;
width: 100px;
border-radius: 50%;
margin: auto;
}
.country-stat-inner-circle{
position: absolute;
height: 85%;
width: 85%;
border-radius: 50%;
background-color: #1a1a2e;
top: 0; bottom: 0; left: 0; right: 0;
margin: auto;
}
.country-stat-value-wrapper{
display: flex;
align-items: center;
justify-content: center;
color: white;
height: 100%;
}
.country-stat-value{
font-size: 25px;
}
.country-stat-title{
position: relative;
color: #ffffff;
margin: auto;
}
.country-stat-spacing-wrapper{
width: 100%;
height: 25%;
}
#country-stats-values-bottom{
border-top: .0625rem solid;
margin-top: 100px;
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.country-stats-bottom-elements{
margin: 20px 0;
width: 50%;
text-align: center;
display: flex;
flex-direction: column;
}
#country-stats-distance-from-opponent-value{
font-size: 30px;
width: 50%;
margin: 20px 25%;
}
#country-stats-reset-btn-wrapper{
padding: 20px 0px 100px 0px;
text-align: center;
}
#country-stats-reset-btn{
border-color: red;
background-color: red;
color: white;
}
#country-stats-reset-btn:hover{
cursor: pointer;
}
#map-settings-wrapper{
var(--font-neo-sans);
text-align: center;
display: none;
}
#map-settings-title{
font-size: 40px;
margin-top: 20px;
padding-bottom: 20px;
}
#map-settings-content{
}
#settings-map-color-ranges-wrapper{
border-top: 2px solid white;
padding-bottom: 50px;
padding-top: 25px;
margin-left: 50px;
margin-right: 50px;
}
#map-color-ranges-slider-wrapper{
position: relative;
}
#slider-output-wrapper{
position: relative;
margin-top: 20px;
width: 100%;
}
#left-slider-output{
position: absolute;
left: 50%;
}
#right-slider-output{
position: absolute;
left: 50%;
}
#map-color-ranges-slider{
position: relative;
width: 100%;
height: 100px;
margin-top: 0px;
}
#slider-track{
width: 100%;
height: 5px;
position: absolute;
margin: auto;
top: 0;
bottom: 0;
border-radius: 5px;
}
.map-color-ranges{
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
width: 100%;
outline: none;
position: absolute;
margin: 0px -50%;
top: 0;
bottom: 0;
background-color: transparent;
pointer-events: none;
border-color: transparent;
padding: 0px;
}
.map-color-ranges::-webkit-slider-runnable-track{
-webkit-appearance: none;
height: 5px;
}
.map-color-ranges::-webkit-slider-thumb{
-webkit-appearance: none;
height: 1.7em;
width: 1.7em;
background-color: #ffffff;
cursor: pointer;
margin-top: -9px;
pointer-events: auto;
border-radius: 50%;
border: 1px solid #808080;
}
#settings-toggles-wrapper{
border-top: 2px solid white;
padding-bottom: 50px;
padding-top: 25px;
margin-left: 50px;
margin-right: 50px;
text-align: center;
display: flex;
}
#settings-allow-healing-rounds-wrapper{
flex: 1;
}
#settings-allow-healing-rounds{
height: 0;
width: 0;
visibility: hidden;
}
#label-allow-healing{
cursor: pointer;
text-indent: -9999px;
width: 50px;
height: 25px;
background: gray;
display: block;
border-radius: 25px;
position: relative;
margin: auto;
}
#label-allow-healing:after{
content: '';
position: absolute;
top: 1.25px;
left: 3px;
width: 22.5px;
height: 22.5px;
background: #fff;
border-radius: 22.5px;
transition: 0.3s;
}
#settings-allow-healing-rounds:checked + #label-allow-healing{
background: #bada55;
}
#settings-allow-healing-rounds:checked + #label-allow-healing:after{
left: calc(100% - 5px);
transform: translateX(-100%);
}
#label-allow-healing:active:after{
width: 32.5px;
}
#settings-competitive-only-mode-wrapper{
flex: 1;
}
#settings-competitive-only-mode{
height: 0;
width: 0;
visibility: hidden;
}
#label-competitive-only{
cursor: pointer;
text-indent: -9999px;
width: 50px;
height: 25px;
background: gray;
display: block;
border-radius: 25px;
position: relative;
margin: auto;
}
#label-competitive-only:after{
content: '';
position: absolute;
top: 1.25px;
left: 3px;
width: 22.5px;
height: 22.5px;
background: #fff;
border-radius: 22.5px;
transition: 0.3s;
}
#settings-competitive-only-mode:checked + #label-competitive-only{
background: #bada55;
}
#settings-competitive-only-mode:checked + #label-competitive-only:after{
left: calc(100% - 5px);
transform: translateX(-100%);
}
#label-competitive-only:active:after{
width: 32.5px;
}
#unit-selector{
border-top: 2px solid white;
padding-bottom: 50px;
padding-top: 25px;
margin-left: 50px;
margin-right: 50px;
}
#unit-selector-mi,
#unit-selector-km{
accent-color: #bada55;
}
#unit-selector-mi:hover,
#unit-selector-km:hover{
cursor: pointer;
}
#settings-reset-scores-btn-wrapper{
border-top: 2px solid white;
padding-bottom: 50px;
padding-top: 25px;
margin-left: 50px;
margin-right: 50px;
}
#reset-scores-btn{
border-color: red;
background-color: red;
color: white;
}
#reset-scores-btn:hover{
cursor: pointer;
}
#map-settings-btn-wrapper{
text-align: center;
margin-bottom: 10px;
}
#map-settings-btn{
border-radius: 15px;
background-color: transparent;
color: white;
border-color: white;
padding: 5px 10px 5px 10px;
}
#map-settings-btn:hover{
background-color: white;
color: black;
border-color: black;
cursor: pointer;
}
#footer-wrapper{
display: flex;
}
#version-number{
flex: 1;
font-family: Arial;
padding-left: 10px
}
#feedback-link-wrapper{
flex: 1;
font-family: Arial;
text-align: center;
}
#creator-tag{
flex: 1;
font-family: Arial;
padding-right: 10px;
padding-bottom: 10px;
text-align: right;
}
`;
svgMap.innerHTML = `
Country Name: 0 / 0 (0%)
Average Distance: 0.0 km
OVERALL STATS
Average Rounds Played (Win)
Average Rounds Played (Loss)
AVERAGE DISTANCE FROM OPPONENT
COUNTRY STREAKS
Current:
Highest: Correct | Incorrect
AVERAGE DISTANCE FROM OPPONENT
COUNTRY STREAKS
Current:
Highest: Correct | Incorrect
`;
scriptForMap.textContent = `
{
let countries = ['AF','AX','AL','DZ','AS','AD','AO','AI','AQ','AG','AR','AM','AW','AU','AT','AZ','BS','BH','BD','BB','BY','BE','BZ','BJ','BM','BT','BO','BQ','BA','BW','BV','BR','IO','BN','BG','BF','BI','KH','CM','CA','CV','KY','CF','TD','CL','CN','CX','CC','CO','KM','CG','CD','CK','CR','CI','HR','CU','CW','CY','CZ','DK','DJ','DM','DO','EC','EG','SV','GQ','ER','EE','ET','FK','FO','FJ','FI','FR','GF','PF','TF','GA','GM','GE','DE','GH','GI','GR','GL','GD','GP','GU','GT','GG','GN','GW','GY','HT','HM','VA','HN','HK','HU','IS','IN','ID','IR','IQ','IE','IM','IL','IT','JM','JP','JE','JO','KZ','KE','KI','KP','KR','XK','KW','KG','LA','LV','LB','LS','LR','LY','LI','LT','LU','MO','MK','MG','MW','MY','MV','ML','MT','MH','MQ','MR','MU','YT','MX','FM','MD','MC','MN','ME','MS','MA','MZ','MM','NA','NR','NP','NL','NC','NZ','NI','NE','NG','NU','NF','MP','NO','OM','PK','PW','PS','PA','PG','PY','PE','PH','PN','PL','PT','PR','QA','RS','RE','RO','RU','RW','BL','SH','KN','LC','MF','VC','WS','ST','SA','SN','SC','SL','SG','SX','SK','SI','SB','SO','ZA','GS','SS','ES','LK','SD','SR','SJ','SZ','SE','CH','SY','TW','TJ','TZ','TH','TL','TG','TK','TO','TT','TN','TR','TM','TC','TV','UG','UA','AE','GB','US','UM','UY','UZ','VU','VE','VN','VG','VI','WF','EH','YE','ZM','ZW','SM'];
let once = false;
document.getElementById("details-box").style.opacity = "0%";
//UNIT SELECTION
if(window.localStorage.getItem('units-svg-map') === 'mi'){
document.getElementById('unit-selector-mi').checked = true;
}
else if(window.localStorage.getItem('units-svg-map') === 'km'){
document.getElementById('unit-selector-km').checked = true;
}
document.getElementById('unit-selector-mi').addEventListener('click', function(){
window.localStorage.setItem('units-svg-map', 'mi');
});
document.getElementById('unit-selector-km').addEventListener('click', function(){
window.localStorage.setItem('units-svg-map', 'km');
});
//MAP SETUP
document.getElementById('map-wrapper-element').addEventListener('mousemove', function(e){
if(once){
if(window.location.pathname.endsWith('/profile')){
return;
}
once = false;
}
if(!window.location.pathname.endsWith('/profile')){
return;
}
once = true;
//Percentage Bar
let correct_total = parseInt(window.localStorage.getItem('overall-correct-${USER_ID}'));
let total_total = parseInt(window.localStorage.getItem('overall-total-${USER_ID}'));
let percentage_total = Math.floor((correct_total / total_total) * 100);
document.getElementById('total-percentage-bar').style.width = percentage_total + '%';
document.getElementById('total-percentage-text').innerHTML = 'Overall Score: ' + correct_total + ' / ' + total_total + ' (' + percentage_total +'%) ';
if(percentage_total >= 100*${green_range}){
document.getElementById('total-percentage-bar').style.backgroundColor = 'green';
}
else if(percentage_total >= 100*${yellow_range}){
document.getElementById('total-percentage-bar').style.backgroundColor = 'yellow';
}
else if(percentage_total >= 100*${red_range}){
document.getElementById('total-percentage-bar').style.backgroundColor = 'red';
}
//Country colors
countries.forEach(function(country){
let correct = 0;
let total = 0;
if(window.localStorage.getItem(country + '-number-correct-${USER_ID}') !== null){
correct = window.localStorage.getItem(country + '-number-correct-${USER_ID}');
}
if(window.localStorage.getItem(country + '-number-total-${USER_ID}') !== null){
total = window.localStorage.getItem(country + '-number-total-${USER_ID}');
}
let percentage = parseInt(correct) / parseInt(total);
if(correct === 0 && total === 0){
percentage = 'none';
}
let targetCountry = document.getElementById(country);
if(!targetCountry){
return;
}
//Setting the countries to a color based on their percentage
if(percentage >= ${green_range}){
targetCountry.setAttribute('style', 'fill: lightgreen'); //green
}
else if(percentage >= ${yellow_range}){
targetCountry.setAttribute('style', 'fill: rgb(233, 233, 84)'); //yellow
}
else if(percentage >= ${red_range}){
targetCountry.setAttribute('style', 'fill: lightcoral'); //red
}
else{
targetCountry.setAttribute('style', 'fill: black');
}
});
//OVERALL STATS SETUP
let overallStats = JSON.parse(window.localStorage.getItem('overall-country-stats-${USER_ID}'));
let percentage;
let percentageColor;
let totalCount = overallStats.totalCount;
let totalWin = overallStats.totalWin;
let totalLoss = overallStats.totalLoss;
let total5ks = overallStats.total5ks;
let totalGames = overallStats.totalGames;
let averageScore = Math.floor(overallStats.averageScore);
let averageDistance = Math.floor(overallStats.averageDistance/1000);
let gameLengthWin = overallStats.averageGameLengthWin;
let gameLengthLoss = overallStats.averageGameLengthLoss;
let averageTime = Math.floor(overallStats.averageTime);
let guessedFirst = overallStats.guessedFirst;
let closerThanOpponent = overallStats.closerThanOpponent;
let correctStreak = overallStats.countryCorrectStreak;
let correctMax = overallStats.countryCorrectMax;
let wrongStreak = overallStats.countryWrongStreak;
let wrongMax = overallStats.countryWrongMax;
let opponentRating = Math.floor(overallStats.opponentRating);
//Find correct percentage to color the outside circle
function findPercentage(stat, max){
percentage = (stat/max);
if(percentage >= ${green_range}){
percentageColor = 'green';
}
else if(percentage >= ${yellow_range}){
percentageColor = 'yellow';
}
else{
percentageColor = 'red';
}
percentage = 100 * percentage;
if(percentage <= 0){
percentage = 2;
}
};
//Average Score
findPercentage(averageScore, 5000);
document.getElementById('overall-stat-average-score-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)';
document.getElementById('overall-stat-average-score-value').innerText = averageScore;
//Average Distance
findPercentage(2500-averageDistance, 2500);
document.getElementById('overall-stat-average-distance-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)';
if(window.localStorage.getItem('units-svg-map') == 'mi'){
document.getElementById('overall-stat-average-distance-title').innerText = 'Average Distance (mi)';
averageDistance = Math.floor(averageDistance / 1.609);
}
else{
document.getElementById('country-stat-average-distance-title').innerText = 'Average Distance (km)';
}
document.getElementById('overall-stat-average-distance-value').innerText = averageDistance;
//Closer Than Opponent
findPercentage(closerThanOpponent, totalCount);
document.getElementById('overall-stat-closer-than-opponent-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)';
document.getElementById('overall-stat-closer-than-opponent-value').innerText = Math.floor((100 * (closerThanOpponent/totalCount))) + '%';
//Average Time
findPercentage(120-averageTime, 120);
document.getElementById('overall-stat-average-time-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)';
document.getElementById('overall-stat-average-time-value').innerText = averageTime;
//Guessed First
findPercentage(guessedFirst, totalCount);
document.getElementById('overall-stat-guessed-first-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)';
document.getElementById('overall-stat-guessed-first-value').innerText = Math.floor((100 * (guessedFirst/totalCount))) + '%';
//Total 5ks
findPercentage(total5ks, 100);
document.getElementById('overall-stat-total-5ks-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)';
document.getElementById('overall-stat-total-5ks-value').innerText = total5ks;
//Game Length (Win)
findPercentage(15-gameLengthWin, 15);
document.getElementById('overall-stat-average-game-length-win-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)';
document.getElementById('overall-stat-average-game-length-win-value').innerText = Math.round(10 * gameLengthWin) / 10;
//Game Length (Loss)
findPercentage(gameLengthLoss, 15);
document.getElementById('overall-stat-average-game-length-loss-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)';
document.getElementById('overall-stat-average-game-length-loss-value').innerText = Math.round(10 * gameLengthLoss) / 10;
//Opponent Rating
findPercentage(opponentRating, 1200);
document.getElementById('overall-stat-opponent-rating-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)';
document.getElementById('overall-stat-opponent-rating-value').innerText = opponentRating;
//BOTTOM STATS SETUP
//Distance From Opponent
let distanceFromOpponent = [Math.round(overallStats.distanceFromOpponent[1] / 1000),'km','+','green'];
if(window.localStorage.getItem('units-svg-map') == 'mi'){
distanceFromOpponent[0] = Math.round(distanceFromOpponent[0] / 1.609);
distanceFromOpponent[1] = 'mi';
}
if(distanceFromOpponent[0] < 0){
distanceFromOpponent[0] *= -1;
distanceFromOpponent[2] = '-';
distanceFromOpponent[3] = 'red';
}
document.getElementById('overall-stats-distance-from-opponent-value').style.color = distanceFromOpponent[3];
document.getElementById('overall-stats-distance-from-opponent-value').innerText = distanceFromOpponent[2] + distanceFromOpponent[0] + ' ' + distanceFromOpponent[1];
//Country Streaks
if(overallStats.countryCorrectStreak > 0){
document.getElementById('overall-stats-country-streaks-value-current-value').innerText = overallStats.countryCorrectStreak + ' Correct';
document.getElementById('overall-stats-country-streaks-value-current-value').style.color = 'green';
}
else if(overallStats.countryWrongStreak > 0){
document.getElementById('overall-stats-country-streaks-value-current-value').innerText = overallStats.countryWrongStreak + ' Incorrect';
document.getElementById('overall-stats-country-streaks-value-current-value').style.color = 'red';
}
document.getElementById('overall-stats-country-streaks-value-max-correct-value').innerText = overallStats.countryCorrectMax;
document.getElementById('overall-stats-country-streaks-value-max-wrong-value').innerText = overallStats.countryWrongMax;
//Time Played
let minutesPlayed = Math.floor(Math.floor(overallStats.totalSeconds / 60) % 60);
let hoursPlayed = Math.floor(overallStats.totalSeconds / 3600);
document.getElementById('overall-stats-total-play-time-value').innerText = hoursPlayed + 'h ' + minutesPlayed + 'm ';
});
function mouseOverCountry(country){
if(typeof country.target !== 'undefined'){
country = country.target;
}
if (country.tagName == 'path'){
let content = country.dataset.name;
document.getElementById("details-box").innerHTML = content;
document.getElementById("details-box").style.opacity = "100%";
//Changing the color when you hover over a country
if(country.style.fill == 'lightcoral'){
country.setAttribute('style', 'fill:red');
}
else if(country.style.fill == 'lightgreen'){
country.setAttribute('style', 'fill:green');
}
else if(country.style.fill == 'rgb(233, 233, 84)'){
country.setAttribute('style', 'fill:yellow');
}
else if(country.style.fill == 'black'){
country.setAttribute('style', 'fill:rgb(175, 175, 175)');
}
//Displaying the country and the stats at the top of the page
let countryName = country.dataset.name;
let countryCorrect = 0;
let countryTotal = 0;
let countryPercentage = 0;
let countryDistance = 0.0;
let distanceUnit = 'km';
let target = country.id;
if(window.localStorage.getItem(target + '-number-correct-${USER_ID}') !== null){
countryCorrect = window.localStorage.getItem(target + '-number-correct-${USER_ID}');
}
if(window.localStorage.getItem(target + '-number-total-${USER_ID}') !== null){
countryTotal = window.localStorage.getItem(target + '-number-total-${USER_ID}');
}
if((countryCorrect !== 0) && (countryTotal !== 0)){
countryPercentage = Math.floor(100 * (parseInt(countryCorrect) / parseInt(countryTotal)));
}
if(window.localStorage.getItem(target + '-distance-average-${USER_ID}') !== null){
countryDistance = parseInt(window.localStorage.getItem(target + '-distance-average-${USER_ID}')) / 1000;
if(document.getElementById('unit-selector-mi').checked){
countryDistance = countryDistance / 1.609;
}
countryDistance = round(countryDistance,1);
}
if(document.getElementById('unit-selector-mi').checked){
distanceUnit = 'mi';
}
document.getElementById("display-country-details").textContent = countryName + ": " + countryCorrect + " / " + countryTotal + " (" + countryPercentage + "%)";
document.getElementById("display-country-details").style.visibility = "visible";
document.getElementById("display-country-distance").textContent = 'Average Distance: ' + countryDistance + ' ' + distanceUnit;
document.getElementById("display-country-distance").style.visibility = "visible";
}
else {
document.getElementById("details-box").style.opacity = "0%";
}
};
function mouseOutCountry(country){
if(typeof country.target !== 'undefined'){
country = country.target;
}
if (country.tagName == 'path'){
//Changing the color when you stop hovering over a country
if(country.style.fill == 'red'){
country.setAttribute('style', 'fill:lightcoral');
}
if(country.style.fill == 'green'){
country.setAttribute('style', 'fill:lightgreen');
}
if(country.style.fill == 'yellow'){
country.setAttribute('style', 'fill:rgb(233, 233, 84)');
}
if(country.style.fill == 'rgb(175, 175, 175)'){
country.setAttribute('style', 'fill:black');
}
//Hiding the display at the top when no country is hovering
document.getElementById("display-country-details").style.visibility = "hidden";
document.getElementById("display-country-distance").style.visibility = "hidden";
}
};
//DETAILS BOX
window.onmousemove = function(e){
let detailsBox = document.getElementById('details-box');
let x = e.clientX;
let y = e.clientY;
detailsBox.style.top = (y + 20) + 'px';
detailsBox.style.left = (x) + 'px';
};
function round(value, precision) {
let multiplier = Math.pow(10, precision || 0);
return Math.round(value * multiplier) / multiplier;
};
//REGULAR LISTENERS
document.getElementById('map-wrapper-element').addEventListener('mouseover', mouseOverCountry);
document.getElementById('map-wrapper-element').addEventListener('mouseout', mouseOutCountry);
//SEARCH LIST
function mouseOverList(e){
let temp = e.target.id.toUpperCase();
let target_country = document.getElementById(temp);
mouseOverCountry(target_country);
}
function mouseOutList(e){
let temp = e.target.id.toUpperCase();
let target_country = document.getElementById(temp);
mouseOutCountry(target_country);
}
document.getElementById('search-bar').addEventListener('click', () => {
let search_bar = document.getElementById('search-bar');
let list = document.querySelectorAll('#search-bar-list li');
list.forEach(item => item.addEventListener('mouseover', mouseOverList));
list.forEach(item => item.addEventListener('mouseout', mouseOutList));
search_bar.onkeyup = () => {
let search = search_bar.value.toLowerCase();
let count = 0;
if(search_bar.value !== ''){
document.getElementById('search-bar-list').style.display = 'inline';
}
else{
document.getElementById('search-bar-list').style.display = 'none';
}
//Showing the results that match and hiding those that dont (max 6 items)
for(let i of list){
let item = i.innerHTML.toLowerCase();
if(item.indexOf(search) == -1){
i.style.display = 'none';
}
else{
if(count < 6){
count = count + 1;
i.style.display = 'block';
}
else{
i.style.display = 'none';
}
}
};
};
});
//OPEN AND CLOSE SETTINGS (and get back to homepage from country stats)
document.getElementById('map-settings-btn').addEventListener('click', () => {
if(document.getElementById('map-settings-btn').innerText == 'Back to Map'){
document.getElementById('map-settings-wrapper').style.display = 'none';
document.getElementById("country-stats-page-wrapper").style.display = 'none';
document.getElementById('map-settings-btn').innerText = 'Settings';
document.getElementsByClassName('display-wrapper')[0].style.display = 'block';
document.getElementById('search-bar-wrapper').style.display = 'block';
document.getElementsByClassName('map-wrapper')[0].style.display = 'block';
document.getElementById('overall-stats-page-wrapper').style.display = 'block';
}
else{
document.getElementById('map-settings-wrapper').style.display = 'block';
document.getElementById('map-settings-btn').innerText = 'Back to Map';
document.getElementsByClassName('display-wrapper')[0].style.display = 'none';
document.getElementById('search-bar-wrapper').style.display = 'none';
document.getElementsByClassName('map-wrapper')[0].style.display = 'none';
document.getElementById('overall-stats-page-wrapper').style.display = 'none';
}
});
//SET HEALING ROUNDS TOGGLE IN SETTINGS
let healing = JSON.parse(window.localStorage.getItem('allow-healing-rounds'));
if(healing.include){
document.getElementById('settings-allow-healing-rounds').checked = true;
}
else{
document.getElementById('settings-allow-healing-rounds').checked = false;
}
document.getElementById('settings-allow-healing-rounds').addEventListener('click', () => {
if(document.getElementById('settings-allow-healing-rounds').checked){
window.localStorage.setItem('allow-healing-rounds', JSON.stringify({include: true}));
}
else{
window.localStorage.setItem('allow-healing-rounds', JSON.stringify({include: false}));
}
});
//SET COMPETITIVE ONLY TOGGLE IN SETTINGS
let competitive = JSON.parse(window.localStorage.getItem('competitive-only-mode'));
if(competitive.include){
document.getElementById('settings-competitive-only-mode').checked = true;
}
else{
document.getElementById('settings-competitive-only-mode').checked = false;
}
document.getElementById('settings-competitive-only-mode').addEventListener('click', () => {
if(document.getElementById('settings-competitive-only-mode').checked){
window.localStorage.setItem('competitive-only-mode', JSON.stringify({include: true}));
}
else{
window.localStorage.setItem('competitive-only-mode', JSON.stringify({include: false}));
}
});
//RESET ALL SCORES
document.getElementById('reset-scores-btn').addEventListener('click', () => {
if(confirm('Are you sure you want to reset your stats? This cannot be undone.')){
//Remove country scores
countries.forEach(function(country){
window.localStorage.removeItem(country + '-number-correct-${USER_ID}');
window.localStorage.removeItem(country + '-number-total-${USER_ID}');
window.localStorage.removeItem(country + '-distance-average-${USER_ID}');
window.localStorage.removeItem(country + '-distance-number-${USER_ID}');
window.localStorage.removeItem(country + '-all-country-stats-${USER_ID}');
});
//Remove overall scores
window.localStorage.removeItem('overall-total-${USER_ID}');
window.localStorage.removeItem('overall-correct-${USER_ID}');
window.localStorage.removeItem('overall-country-stats-${USER_ID}');
//Reload the page
location.reload();
}
});
//OPEN COUNTRY STATS PAGE
document.getElementById('map-wrapper-element').addEventListener('dblclick', (e) => {
let countryId = (e.path[0].id).toUpperCase();
if(countryId.length != 2){
return;
}
//Set the stats to the correct values for the country
setCountryStats(countryId);
window.localStorage.setItem('select-country-stats-id', countryId);
document.getElementById('search-bar-wrapper').style.display = 'none';
document.getElementById('overall-stats-page-wrapper').style.display = 'none';
document.getElementsByClassName('map-wrapper')[0].style.display = 'none';
document.getElementsByClassName('display-wrapper')[0].style.display = 'none';
let countryName = e.path[0].dataset.name;
let countryCorrect = 0;
let countryTotal = 0;
let countryPercentage = 0;
if(typeof countryName == 'undefined'){
countryName = e.path[0].textContent;
}
if(window.localStorage.getItem(countryId + '-number-correct-${USER_ID}') !== null){
countryCorrect = window.localStorage.getItem(countryId + '-number-correct-${USER_ID}');
}
if(window.localStorage.getItem(countryId + '-number-total-${USER_ID}') !== null){
countryTotal = window.localStorage.getItem(countryId + '-number-total-${USER_ID}');
}
if((countryCorrect !== 0) && (countryTotal !== 0)){
countryPercentage = Math.floor(100 * (parseInt(countryCorrect) / parseInt(countryTotal)));
}
document.getElementById('country-stats-display-details').textContent = countryName + ": " + countryCorrect + " / " + countryTotal + " (" + countryPercentage + "%)";
document.getElementById('country-stats-reset-btn').textContent = 'Reset All ' + countryName + ' Stats';
document.getElementById("country-stats-page-wrapper").style.display = 'block';
document.getElementById('map-settings-btn').innerText = 'Back to Map';
});
//SET COUNTRY STATS
function setCountryStats(countryCode){
let countryObject = JSON.parse(window.localStorage.getItem(countryCode + '-all-country-stats-${USER_ID}'));
let percentage;
let percentageColor;
//Country Stats
let totalCount = countryObject.totalCount;
let averageScore = Math.floor(countryObject.averageScore);
let averageDistance = Math.floor(countryObject.averageDistance/1000);
let closerThanOpponent = countryObject.closerThanOpponent;
let averageTime = Math.floor(countryObject.averageTime);
let guessedFirst = countryObject.guessedFirst;
let total5ks = countryObject.total5ks;
//Find correct percentage to color the outside circle
function findPercentage(stat, max){
percentage = (stat/max);
if(percentage >= ${green_range}){
percentageColor = 'green';
}
else if(percentage >= ${yellow_range}){
percentageColor = 'yellow';
}
else{
percentageColor = 'red';
}
percentage = 100 * percentage;
if(percentage <= 0){
percentage = 2;
}
};
//Average Score
findPercentage(averageScore, 5000);
document.getElementById('country-stat-average-score-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)';
document.getElementById('country-stat-average-score-value').innerText = averageScore;
//Average Distance
findPercentage(2500-averageDistance, 2500);
document.getElementById('country-stat-average-distance-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)';
if(window.localStorage.getItem('units-svg-map') == 'mi'){
document.getElementById('country-stat-average-distance-title').innerText = 'Average Distance (mi)';
averageDistance = Math.floor(averageDistance / 1.609);
}
else{
document.getElementById('country-stat-average-distance-title').innerText = 'Average Distance (km)';
}
document.getElementById('country-stat-average-distance-value').innerText = averageDistance;
//Closer Than Opponent
findPercentage(closerThanOpponent, totalCount);
document.getElementById('country-stat-closer-than-opponent-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)';
document.getElementById('country-stat-closer-than-opponent-value').innerText = Math.floor((100 * (closerThanOpponent/totalCount))) + '%';
//Average Time
findPercentage(120-averageTime, 120);
document.getElementById('country-stat-average-time-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)';
document.getElementById('country-stat-average-time-value').innerText = averageTime;
//Guessed First
findPercentage(guessedFirst, totalCount);
document.getElementById('country-stat-guessed-first-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)';
document.getElementById('country-stat-guessed-first-value').innerText = Math.floor((100 * (guessedFirst/totalCount))) + '%';
//Total 5ks
findPercentage(total5ks, 10);
document.getElementById('country-stat-total-5ks-outer-circle').style.background = 'conic-gradient(' + percentageColor + ', ' + percentageColor + ' ' + percentage + '%, #808080 ' + percentage + '%, #808080)';
document.getElementById('country-stat-total-5ks-value').innerText = total5ks;
//BOTTOM STATS SETUP
//Distance From Opponent
let distanceFromOpponent = [Math.round(countryObject.distanceFromOpponent[1] / 1000),'km','+','green'];
if(window.localStorage.getItem('units-svg-map') == 'mi'){
distanceFromOpponent[0] = Math.round(distanceFromOpponent[0] / 1.609);
distanceFromOpponent[1] = 'mi';
}
if(distanceFromOpponent[0] < 0){
distanceFromOpponent[0] *= -1;
distanceFromOpponent[2] = '-';
distanceFromOpponent[3] = 'red';
}
document.getElementById('country-stats-distance-from-opponent-value').style.color = distanceFromOpponent[3];
document.getElementById('country-stats-distance-from-opponent-value').innerText = distanceFromOpponent[2] + distanceFromOpponent[0] + ' ' + distanceFromOpponent[1];
//Country Streaks
if(countryObject.countryCorrectStreak > 0){
document.getElementById('country-stats-country-streaks-value-current-value').innerText = countryObject.countryCorrectStreak + ' Correct';
document.getElementById('country-stats-country-streaks-value-current-value').style.color = 'green';
}
else if(countryObject.countryWrongStreak > 0){
document.getElementById('country-stats-country-streaks-value-current-value').innerText = countryObject.countryWrongStreak + ' Incorrect';
document.getElementById('country-stats-country-streaks-value-current-value').style.color = 'red';
}
document.getElementById('country-stats-country-streaks-value-max-correct-value').innerText = countryObject.countryCorrectMax;
document.getElementById('country-stats-country-streaks-value-max-wrong-value').innerText = countryObject.countryWrongMax;
}
//RESET SCORES FOR SELECTED COUNTRY
document.getElementById('country-stats-reset-btn').addEventListener('click', () => {
let resetId = window.localStorage.getItem('select-country-stats-id');
let countryCorrect = parseInt(window.localStorage.getItem(resetId + '-number-correct-${USER_ID}'));
let countryTotal = parseInt(window.localStorage.getItem(resetId + '-number-total-${USER_ID}'));
let countryStats = JSON.parse(window.localStorage.getItem(resetId + '-all-country-stats-${USER_ID}'));
let overallStats = JSON.parse(window.localStorage.getItem('overall-country-stats-${USER_ID}'));
if(isNaN(countryCorrect)){
countryCorrect = 0;
}
if(isNaN(countryTotal)){
countryTotal = 0;
}
//Reset all scores for country
if(confirm('Are you sure you want to reset your stats? This cannot be undone.')){
//Remove country scores from overall scores
countryCorrect = (parseInt(window.localStorage.getItem('overall-correct-${USER_ID}')) - countryCorrect);
countryTotal = (parseInt(window.localStorage.getItem('overall-total-${USER_ID}')) - countryTotal);
overallStats.totalCount = overallStats.totalCount - countryStats.totalCount;
overallStats.closerThanOpponent = overallStats.closerThanOpponent - countryStats.closerThanOpponent;
overallStats.guessedFirst = overallStats.guessedFirst - countryStats.guessedFirst;
overallStats.total5ks = overallStats.total5ks - countryStats.total5ks;
//Set Stats To New Values
window.localStorage.setItem('overall-correct-${USER_ID}', countryCorrect);
window.localStorage.setItem('overall-total-${USER_ID}', countryTotal);
window.localStorage.setItem('overall-country-stats-${USER_ID}',JSON.stringify(overallStats));
//Remove Country Scores
window.localStorage.removeItem(resetId + '-number-correct-${USER_ID}');
window.localStorage.removeItem(resetId + '-number-total-${USER_ID}');
window.localStorage.removeItem(resetId + '-distance-average-${USER_ID}');
window.localStorage.removeItem(resetId + '-distance-number-${USER_ID}');
window.localStorage.removeItem(resetId + '-all-country-stats-${USER_ID}');
//Reload the page
location.reload();
}
});
//MAP SLIDER RANGES
let leftSlider = document.getElementById("left-slider");
let rightSlider = document.getElementById("right-slider");
let sliderTrack = document.getElementById("slider-track");
let minGap = 5;
leftSlider.value = window.localStorage.getItem('duels-map-color-left-range-${USER_ID}');
rightSlider.value = window.localStorage.getItem('duels-map-color-right-range-${USER_ID}');
//Change Left Slider Value
function calcLeftSlider(){
if(parseInt(rightSlider.value) - parseInt(leftSlider.value) <= minGap){
leftSlider.value = parseInt(rightSlider.value) - minGap;
}
else if(leftSlider.value < 5){
leftSlider.value = 5;
}
document.getElementById('left-slider-output').innerText = leftSlider.value + '%';
document.getElementById('left-slider-output').style.left = findValue(leftSlider.value);
fillColor();
window.localStorage.setItem('duels-map-color-left-range-${USER_ID}', leftSlider.value);
}
//Change Right Slider Value
function calcRightSlider(){
if(parseInt(rightSlider.value) - parseInt(leftSlider.value) <= minGap){
rightSlider.value = parseInt(leftSlider.value) + minGap;
}
else if(rightSlider.value > 95){
rightSlider.value = 95;
}
document.getElementById('right-slider-output').innerText = rightSlider.value + '%';
document.getElementById('right-slider-output').style.left = findValue(rightSlider.value);
fillColor();
window.localStorage.setItem('duels-map-color-right-range-${USER_ID}', rightSlider.value);
}
//Fill The Slider With Colors
function fillColor(){
let percent1 = parseInt(leftSlider.value);
let percent2 = parseInt(rightSlider.value);
sliderTrack.style.background = 'linear-gradient(to right, red 0%, red ' + percent1 + '%, yellow ' + percent1 + '%, yellow ' + percent2 +'%, green ' + percent2 + '%, green 100%)';
}
//Put Value Above Slider Thumb
function findValue(val){
let valueOne = parseInt(val);
let valueTwo = valueOne * 0.2;
let final = 'calc(' + valueOne + '% - ' + valueTwo + 'px)';
return final;
}
//Add Event Listeners
document.getElementById("left-slider").addEventListener('input', calcLeftSlider);
document.getElementById("right-slider").addEventListener('input', calcRightSlider);
calcLeftSlider();
calcRightSlider();
//PANNING AND ZOOMING ON THE MAP
let worldMap = document.getElementById('world-map');
let viewbox = worldMap.viewBox.baseVal;
let pointerDown = false;
let mousePoint;
//Return x and y values from pointer event
function getPointFromEvent(event){
let point = worldMap.createSVGPoint();
point.x = event.clientX;
point.y = event.clientY;
//Get current transformation matrix and inverse it
let invertedSVGMatrix = worldMap.getScreenCTM().inverse();
return point.matrixTransform(invertedSVGMatrix);
}
//When user clicks map to start panning
function onPointerDown(event){
event.preventDefault();
pointerDown = true;
mousePoint = getPointFromEvent(event);
}
//When user drags mouse
function onPointerMove(event){
if (!pointerDown){
return;
}
event.preventDefault();
document.getElementById('world-map').style = 'cursor: grabbing';
document.getElementById('details-box').style.display = 'none';
let pointerPosition = getPointFromEvent(event);
viewbox.x = (viewbox.x - (pointerPosition.x - mousePoint.x));
viewbox.y = (viewbox.y - (pointerPosition.y - mousePoint.y));
checkBounds();
}
//When user lifts mouse up
function onPointerUp(){
event.preventDefault();
pointerDown = false;
document.getElementById('world-map').style = 'cursor: auto';
document.getElementById('details-box').style.display = 'inline';
}
//When user scrolls mouse
function onMouseWheel(event){
let delta = (event.wheelDelta ? event.wheelDelta : -event.deltaY);
mousePoint = getPointFromEvent(event);
//If mouse wheel moves forward
if(delta > 0){
event.preventDefault();
//Zoom In Limit
if(viewbox.width > 325 && viewbox.height > 140){
//Make the viewbox smaller
viewbox.width /= 1.1;
viewbox.height /= 1.1;
//Position the top left accordingly
viewbox.x = (((mousePoint.x - viewbox.x) * viewbox.width) - ((mousePoint.x - viewbox.x) * mousePoint.x) - ((viewbox.x + (viewbox.width * 1.1) - mousePoint.x) * mousePoint.x) ) / ( -((mousePoint.x - viewbox.x) + (viewbox.x + (viewbox.width * 1.1) - mousePoint.x)) );
viewbox.y = (((mousePoint.y - viewbox.y) * viewbox.height) - ((mousePoint.y - viewbox.y) * mousePoint.y) - ((viewbox.y + (viewbox.height * 1.1) - mousePoint.y) * mousePoint.y) ) / ( -((mousePoint.y - viewbox.y) + (viewbox.y + (viewbox.height * 1.1) - mousePoint.y)) );
}
}
//If mouse wheel moves backward
else{
//Zoom Out Limit
if(viewbox.width < 2000 && viewbox.height < 857){
event.preventDefault();
//Make the viewbox bigger
viewbox.width *= 1.1;
viewbox.height *= 1.1;
//Position the top left accordingly
viewbox.x = (((viewbox.x + (viewbox.width / 1.1) - mousePoint.x) * mousePoint.x) - ((mousePoint.x - viewbox.x) * viewbox.width) + ((mousePoint.x - viewbox.x) * mousePoint.x)) / ((mousePoint.x - viewbox.x) + (viewbox.x + (viewbox.width / 1.1) - mousePoint.x));
viewbox.y = (((viewbox.y + (viewbox.height / 1.1) - mousePoint.y) * mousePoint.y) - ((mousePoint.y - viewbox.y) * viewbox.height) + ((mousePoint.y - viewbox.y) * mousePoint.y)) / ((mousePoint.y - viewbox.y) + (viewbox.y + (viewbox.height / 1.1) - mousePoint.y));
}
}
checkBounds();
}
//Check if the map is out of bounds
function checkBounds(){
//Left
if(viewbox.x < 0){
viewbox.x = 0;
}
//Top
if(viewbox.y < 0){
viewbox.y = 0;
}
//Right
if((viewbox.x + viewbox.width) > 2000){
viewbox.x = 2000 - viewbox.width;
}
//Bottom
if((viewbox.y + viewbox.height) > 857){
viewbox.y = 857 - viewbox.height;
}
}
//Add event listeners
worldMap.addEventListener('pointerdown', onPointerDown);
worldMap.addEventListener('pointerup', onPointerUp);
worldMap.addEventListener('pointerleave', onPointerUp);
worldMap.addEventListener('pointermove', onPointerMove);
worldMap.addEventListener('wheel', onMouseWheel);
}`;
let referenceNode = document.getElementsByClassName('version3_main__xNkED')[0];
let siblingNode = document.getElementsByClassName('footer_footer__NmtmJ')[0];
referenceNode.parentNode.insertBefore(svgMap, siblingNode);
document.head.appendChild(cssForMap);
document.getElementById('map-wrapper-element').appendChild(scriptForMap);
};
//**************************** END OF SCRIPT ****************************//