(function() { function fetchSeed(id) { var HttpRequest = Packages.com.gmt2001.HttpRequest, HashMap = Packages.java.util.HashMap, JSONObject = Packages.org.json.JSONObject, header = new HashMap(0), json = new JSONObject('{}'); var request = HttpRequest.getData(HttpRequest.RequestType.GET,'https://www.geoguessr.com/api/v3/games/'+id,json.toString(),header); if (request.success) { var data = new JSONObject(request.content) return JSON.parse(data); } return {}; }; function getCountryBDC(location) { var HttpRequest = Packages.com.gmt2001.HttpRequest, HashMap = Packages.java.util.HashMap, JSONObject = Packages.org.json.JSONObject, header = new HashMap(0), json = new JSONObject('{}'); const BDC_KEY = "067c718d2bbd4a2ba8d0645e1633cac2"; var request = HttpRequest.getData(HttpRequest.RequestType.GET,'https://api.bigdatacloud.net/data/reverse-geocode?latitude='+location.lat+'&longitude='+location.lng+'&key='+BDC_KEY,json.toString(),header); if (request.success) { var data = new JSONObject(request.content) return data.countryCode; } }; function moveFrom(coords, angle, distance) { var radianAngle = (angle * Math.PI) / 180; var x = 0 + distance * Math.cos(radianAngle); var y = 0 + distance * Math.sin(radianAngle); var newLat = coords.lat + y * M; var newLng = coords.lng + (x * M) / Math.cos(coords.lat * (Math.PI / 180)); return { lat: newLat, lng: newLng }; } function toPos(coords) { return { lat: parseFloat(coords.split(",")[0]), lng: parseFloat(coords.split(",")[1]) }; } function getSurroundings (location) { const meters = 100; const R_EARTH = 6378.137; const M = 1 / (((2 * Math.PI) / 360) * R_EARTH) / 1000; var coordinates = [location]; for (var angle = 0; angle < 360; angle += 45) { coordinates.push(moveFrom({ lat: location.lat, lng: location.lng }, angle, meters)); } return coordinates; }; function isCoordinates (coordinates) { const regex = /^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?),\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$/g; return regex.test(coordinates); }; function calculateScale(bounds){ return haversineDistance({ lat: bounds.min.lat, lng: bounds.min.lng }, { lat: bounds.max.lat, lng: bounds.max.lng }) / 7.458421; } function haversineDistance(mk1, mk2){ const R = 6371.071; const rlat1 = mk1.lat * (Math.PI / 180); const rlat2 = mk2.lat * (Math.PI / 180); const difflat = rlat2 - rlat1; const difflon = (mk2.lng - mk1.lng) * (Math.PI / 180); const km = 2 * R * Math.asin(Math.sqrt(Math.sin(difflat / 2) * Math.sin(difflat / 2) + Math.cos(rlat1) * Math.cos(rlat2) * Math.sin(difflon / 2) * Math.sin(difflon / 2))); return km; }; function calculateScore(distance, scale){ return Math.round(5000 * Math.pow(0.99866017, (distance * 1000) / scale)); } function normalize(val){ return val.normalize("NFD").replace(/[\u0300-\u036f]/g, ""); } function isMatch(input, key){ return input.length >= 3 && key.includes(input) && input.length <= key.length; } function findCountry(input){ const normalized = GameHelper.normalize(input); return countryCodesNames.find((country) => country.code === normalized || GameHelper.isMatch(normalized, country.names.toLowerCase())); }; $.getSetIniDbBoolean('chatguessr', 'isOpen', false); var seed = {}, scale, guesses = {}; function addGuess(user,position) { if(seed.round == undefined) return; var current_round = ""+(seed.round-1); if(guesses[current_round]==undefined) guesses[current_round] = [] if(guesses[current_round].some((v)=>v.user==user)) return; if(!isCoordinates(position)) return; var pos = toPos(position) var distance = haversineDistance(pos, {lat: seed.rounds[current_round].lat, lng: seed.rounds[current_round].lng}) var score = calculateScore(distance, scale) guesses[current_round].push({ user:user, location:position, distance:distance, score:score, streak: 0, }); guesses.round = seed.round - 1; sendGuessData(); } function sendGuessData() { guesses.rounds = seed.rounds; $.panelsocketserver.sendJSONToAll(JSON.stringify({ 'eventFamily': 'chatguessr', 'eventType': 'guesses', 'data': JSON.stringify(guesses) })); } function accGuesses(){ var res = {}; for(var rr = 0; rr < guesses.round; ++rr){ for(var s = 0; s < guesses[rr].length; ++s){ if(!res[guesses[rr][s].user]){ res[guesses[rr][s].user] = {score:0,distance:0} } res[guesses[rr][s].user].score += guesses[rr][s].score res[guesses[rr][s].user].distance += guesses[rr][s].distance } } return Object.keys(res).map(k => { var v = res[k] v.user = k; return v; }); } $.bind('command', function(event) { const sender = event.getSender().toLowerCase(), command = event.getCommand(), args = event.getArgs(), action = args[0]; if (command.equalsIgnoreCase('g')) { if($.getIniDbBoolean('chatguessr', 'isOpen')) addGuess(sender,args); }else if (command.equalsIgnoreCase('cg')) { //send url //$.say($.whisperPrefix(sender) + $.lang.get('chatguessr.help', ' Use "!cg [open | close | ...]" to open/close the feature.')); }else if(command.equalsIgnoreCase('cga')){ if(action.equalsIgnoreCase('open')){ $.setIniDbBoolean('cgstatus', 'isOpen', true); }else if(action.equalsIgnoreCase('close')){ $.setIniDbBoolean('cgstatus', 'isOpen', false) }else if(action.equalsIgnoreCase('start')){ seed = fetchSeed(args[1]); scale = calculateScale(seed.bounds); guesses.round = seed.round - 1; sendGuessData(); }else if(action.equalsIgnoreCase('end')){ $.setIniDbBoolean('cgstatus', 'isOpen', false) guesses = {}; seed = {}; sendGuessData(); }else if(action.equalsIgnoreCase('refresh')){ if(seed.token == undefined) return; var newseed = fetchSeed(seed.token); if(newseed.round > seed.round){ $.setIniDbBoolean('chatguessr', 'isOpen',false) //NEW ROUND /Score var gp = newseed.player.guesses[seed.round - 1].lat+","+newseed.player.guesses[seed.round - 1].lng addGuess($.channelName,gp); }else if(newseed.state=="finished" && newseed.player.guesses.length > seed.player.guesses.length){ $.setIniDbBoolean('chatguessr', 'isOpen',false) var gp = newseed.player.guesses[newseed.round - 1].lat+","+newseed.player.guesses[newseed.round - 1].lng addGuess($.channelName,gp); }else if(newseed.state=="finished"){ $.setIniDbBoolean('chatguessr', 'isOpen',false) //FINISHED seed = newseed; guesses.final = accGuesses() //Compute total scores + give reward sendGuessData(); }else{ $.setIniDbBoolean('chatguessr', 'isOpen',true) //NEW ROUD /Guess guesses.round = seed.round - 1; sendGuessData(); } seed = newseed; }else if(action.equalsIgnoreCase('gg')){ sendGuessData(); }else if(action.equalsIgnoreCase('fg')){ addGuess("Alpha","0,0"); addGuess("Beta","40,0"); addGuess("Charlie","0,60"); addGuess("Delta","80,80"); } } }); $.bind('initReady', function() { $.registerChatCommand('./custom/custom/chatguessr.js', 'cg',7); $.registerChatCommand('./custom/custom/chatguessr.js', 'g',7); $.registerChatCommand('./custom/custom/chatguessr.js', 'cga',7); $.registerChatSubcommand('cga', 'open', 2); $.registerChatSubcommand('cga', 'close', 2); $.registerChatSubcommand('cga', 'start', 2); $.registerChatSubcommand('cga', 'end', 2); $.registerChatSubcommand('cga', 'refresh', 2); $.registerChatSubcommand('cga', 'gg', 2); $.registerChatSubcommand('cga', 'fg', 2); }); })();