iSparks / Getting Started with a User Script

// ==UserScript==
// @namespace     https://openuserjs.org/users/SadBubFurry
// @name          Getting Started with a User Script
// @description   SadBubFurry
// @version       0.0.3
// @license       MIT
// @include       https://www.example.com/*
// ==/UserScript==

// ==OpenUserJS==
// @author SadBubFurry
// ==/OpenUserJS==

/**
  *
  * Please begin typing or paste your User script now.
  *
  */
  
"use strict";

function excludePokemon(e) {
    $selectExclude.val($selectExclude.val().concat(e)).trigger("change")
}

function notifyAboutPokemon(e) {
    $selectPokemonNotify.val($selectPokemonNotify.val().concat(e)).trigger("change")
}

function removePokemonMarker(e) {
    mapData.pokemons[e].marker.rangeCircle && (mapData.pokemons[e].marker.rangeCircle.setMap(null), delete mapData.pokemons[e].marker.rangeCircle), mapData.pokemons[e].marker.setMap(null), mapData.pokemons[e].hidden = !0
}

function initMap() {
    console.log("locname: " + locname);
    var e = 0;
    $.ajax({
        url: "static/data/cords.json",
        dataType: "json",
        async: !1,
        success: function t(a) {
            for (var o = 0, n = a.length; o < n; o++)
                if (a[o].regio == locname) {
                    centerLat = a[o].lat, centerLng = a[o].long, console.log(locname + " gevonden:"), e = 1;
                    break
                }
        }
    }), 1 != e && console.log("stad : " + locname + " niet gevonden!"), centerLat = parseFloat(centerLat), centerLng = parseFloat(centerLng), map = new google.maps.Map(document.getElementById("map"), {
        center: {
            lat: centerLat,
            lng: centerLng
        },
        zoom: null == zoom ? Store.get("zoomLevel") : zoom,
        minZoom: minZoom,
        fullscreenControl: !0,
        streetViewControl: !1,
        mapTypeControl: !1,
        clickableIcons: !1,
        mapTypeControlOptions: {
            style: google.maps.MapTypeControlStyle.DROPDOWN_MENU,
            position: google.maps.ControlPosition.RIGHT_TOP,
            mapTypeIds: [google.maps.MapTypeId.ROADMAP, google.maps.MapTypeId.SATELLITE, google.maps.MapTypeId.HYBRID, "nolabels_style", "dark_style", "style_light2", "style_pgo", "dark_style_nl", "style_light2_nl", "style_pgo_nl", "style_pgo_day", "style_pgo_night", "style_pgo_dynamic"]
        }
    });
    var t = new google.maps.StyledMapType(noLabelsStyle, {
        name: "No Labels"
    });
    map.mapTypes.set("nolabels_style", t);
    var a = new google.maps.StyledMapType(darkStyle, {
        name: "Dark"
    });
    map.mapTypes.set("dark_style", a);
    var o = new google.maps.StyledMapType(light2Style, {
        name: "Light2"
    });
    map.mapTypes.set("style_light2", o);
    var n = new google.maps.StyledMapType(pGoStyle, {
        name: "PokemonGo"
    });
    map.mapTypes.set("style_pgo", n);
    var i = new google.maps.StyledMapType(darkStyleNoLabels, {
        name: "Dark (No Labels)"
    });
    map.mapTypes.set("dark_style_nl", i);
    var s = new google.maps.StyledMapType(light2StyleNoLabels, {
        name: "Light2 (No Labels)"
    });
    map.mapTypes.set("style_light2_nl", s);
    var r = new google.maps.StyledMapType(pGoStyleNoLabels, {
        name: "PokemonGo (No Labels)"
    });
    map.mapTypes.set("style_pgo_nl", r);
    var l = new google.maps.StyledMapType(pGoStyleDay, {
        name: "PokemonGo Day"
    });
    map.mapTypes.set("style_pgo_day", l);
    var d = new google.maps.StyledMapType(pGoStyleNight, {
        name: "PokemonGo Night"
    });
    map.mapTypes.set("style_pgo_night", d);
    var c = (new Date).getHours(),
        m = c >= 6 && c < 19 ? l : d;
    map.mapTypes.set("style_pgo_dynamic", m), map.addListener("maptypeid_changed", function(e) {
        Store.set("map_style", this.mapTypeId)
    }), map.setMapTypeId(Store.get("map_style")), map.addListener("idle", updateMap), map.addListener("zoom_changed", function() {
        !0 === storeZoom ? Store.set("zoomLevel", this.getZoom()) : storeZoom = !0, redrawPokemon(mapData.pokemons), redrawPokemon(mapData.lurePokemons)
    }), createMyLocationButton(), initSidebar()
}

function updateLocationMarker(e) {
    return e in searchMarkerStyles && (locationMarker.setIcon(searchMarkerStyles[e].icon), Store.set("locationMarkerStyle", e)), locationMarker
}

function createLocationMarker() {
    var e = Store.get("followMyLocationPosition"),
        t = "lat" in e ? e.lat : centerLat,
        a = "lng" in e ? e.lng : centerLng,
        o = new google.maps.Marker({
            map: map,
            animation: google.maps.Animation.DROP,
            position: {
                lat: t,
                lng: a
            },
            draggable: !1,
            icon: null,
            optimized: !1,
            zIndex: google.maps.Marker.MAX_ZINDEX + 2
        });
    return o.setIcon(searchMarkerStyles[Store.get("locationMarkerStyle")].icon), o.infoWindow = new google.maps.InfoWindow({
        content: "<div><b>My Location</b></div>",
        disableAutoPan: !0
    }), addListeners(o), google.maps.event.addListener(o, "dragend", function() {
        var e = o.getPosition();
        Store.set("followMyLocationPosition", {
            lat: e.lat(),
            lng: e.lng()
        })
    }), o
}

function initSidebar() {
    if ($("#gyms-switch").prop("checked", Store.get("showGyms")), $("#gym-sidebar-switch").prop("checked", Store.get("useGymSidebar")), $("#gyms-filter-wrapper").toggle(Store.get("showGyms")), $("#team-gyms-only-switch").val(Store.get("showTeamGymsOnly")), $("#open-gyms-only-switch").prop("checked", Store.get("showOpenGymsOnly")), $("#raids-switch").prop("checked", Store.get("showRaids")), $("#raids-filter-wrapper").toggle(Store.get("showRaids")), $("#min-level-gyms-filter-switch").val(Store.get("minGymLevel")), $("#max-level-gyms-filter-switch").val(Store.get("maxGymLevel")), $("#min-level-raids-filter-switch").val(Store.get("minRaidLevel")), $("#max-level-raids-filter-switch").val(Store.get("maxRaidLevel")), $("#last-update-gyms-switch").val(Store.get("showLastUpdatedGymsOnly")), $("#pokemon-switch").prop("checked", Store.get("showPokemon")), $("#pokestops-switch").prop("checked", Store.get("showPokestops")), $("#lured-pokestops-only-switch").val(Store.get("showLuredPokestopsOnly")), $("#lured-pokestops-only-wrapper").toggle(Store.get("showPokestops")), $("#start-at-user-location-switch").prop("checked", Store.get("startAtUserLocation")), $("#start-at-last-location-switch").prop("checked", Store.get("startAtLastLocation")), $("#follow-my-location-switch").prop("checked", Store.get("followMyLocation")), $("#spawn-area-switch").prop("checked", Store.get("spawnArea")), $("#scanned-switch").prop("checked", Store.get("showScanned")), $("#spawnpoints-switch").prop("checked", Store.get("showSpawnpoints")), $("#ranges-switch").prop("checked", Store.get("showRanges")), $("#sound-switch").prop("checked", Store.get("playSound")), document.getElementById("next-location")) {
        var e = new google.maps.places.Autocomplete(document.getElementById("next-location"));
        $("#next-location").css("background-color", $("#geoloc-switch").prop("checked") ? "#e0e0e0" : "#ffffff"), e.addListener("place_changed", function() {
            var t = e.getPlace();
            if (t.geometry) {
                var a = t.geometry.location;
                changeLocation(a.lat(), a.lng())
            }
        })
    }
    var t = $("#pokemon-icons");
    $.each(pokemonSprites, function(e, a) {
        t.append($("<option></option>").attr("value", e).text(a.name))
    }), t.val(pokemonSprites[Store.get("pokemonIcons")] ? Store.get("pokemonIcons") : "highres"), $("#pokemon-icon-size").val(Store.get("iconSizeModifier"))
}

function pad(e) {
    return e <= 99 ? ("0" + e).slice(-2) : e
}

function getTypeSpan(e) {
    return '<span style="padding: 2px 5px; text-transform: uppercase; color: white; margin-right: 2px; border-radius: 4px; font-size: 0.8em; vertical-align: text-bottom; background-color: ' + e.color + ';">' + e.type + "</span>"
}

function openMapDirections(e, t) {
    var a = "https://www.google.com/maps/?daddr=" + e + "," + t;
    window.open(a, "_blank")
}

function getDateStr(e) {
    var t = "Unknown";
    return e && (t = moment(e).format("DD-MM-YYYY, HH:mm:ss")), t
}

function getTimeStr(e) {
    var t = "Unknown";
    return e && (t = moment(e).format("HH:mm:ss")), t
}

function toggleOtherPokemon(e) {
    0 === (onlyPokemon = 0 === onlyPokemon ? e : 0) ? (lastpokemon = !1, updateMap()) : clearStaleMarkers()
}

function isTemporaryHidden(e) {
    return 0 !== onlyPokemon && e !== onlyPokemon
}

function pokemonLabel(e) {
    var t = e.pokemon_name,
        a = e.pokemon_rarity ? "(" + e.pokemon_rarity + ")" : "",
        o = e.pokemon_types,
        n = "",
        i = e.encounter_id,
        s = e.pokemon_id,
        r = e.latitude,
        l = e.longitude,
        d = e.disappear_time,
        c = new Date(d),
        m = e.individual_attack,
        p = e.individual_defense,
        g = e.individual_stamina,
        u = void 0 !== moves[e.move_1] ? i8ln(moves[e.move_1].name) : "gen/unknown",
        y = void 0 !== moves[e.move_2] ? i8ln(moves[e.move_2].name) : "gen/unknown",
        v = e.weight,
        k = e.height,
        f = e.gender,
        h = e.form,
        w = e.cp,
        _ = e.cp_multiplier,
        S = e.level;
    $.each(o, function(e, t) {
        n += getTypeSpan(t)
    });
    var M = "";
    if (null != w) {
        if (M = "<div>IV: " + getIv(m, p, g).toFixed(1) + "% (" + m + "/" + p + "/" + g + ")</div>", null != w && (null != _ || null != S)) {
            var L;
            M += "<div>CP: " + w + " | Level: " + (L = null != S ? S : getPokemonLevel(_)) + "</div>"
        }
        M += "<div>Moves: " + u + " / " + y + "</div>"
    }
    null != f && (M += "<div>Gender: " + genderType[f - 1], null != v && null != k && (M += " | Weight: " + v.toFixed(2) + "kg | Height: " + k.toFixed(2) + "m"), M += "</div>");
    var b = "<div><b>" + t + "</b>";
    return 201 === s && null !== h && h > 0 && (b += " (" + unownForm[e.form] + ")"), b += '<span> - </span><small><a href="https://pokemon.gameinfo.io/en/pokemon/' + s + '" target="_blank" title="View in Pokedex">#' + s + "</a></small><span> " + a + "</span><span> - </span><small>" + n + "</small></div><div>Disappears at " + pad(c.getHours()) + ":" + pad(c.getMinutes()) + ":" + pad(c.getSeconds()) + '<span class="label-countdown" disappears-at="' + d + '">(00m00s)</span></div><div>Location: <a href="javascript:void(0)" onclick="javascript:openMapDirections(' + r + ", " + l + ')" title="View in Maps">' + r.toFixed(6) + ", " + l.toFixed(7) + "</a></div>" + M + '<div><a href="javascript:excludePokemon(' + s + ')">Exclude</a>&nbsp&nbsp<a href="javascript:notifyAboutPokemon(' + s + ')">Notify</a>&nbsp&nbsp<a href="javascript:removePokemonMarker(\'' + i + '\')">Remove</a>&nbsp&nbsp<a href="javascript:void(0);" onclick="javascript:toggleOtherPokemon(' + s + ');" title="Toggle display of other Pokemon">Toggle Others</a></div>'
}

function gymLabel(e) {
    var t = gymTypes[e.team_id],
        a = e.team_id,
        o = e.latitude,
        n = e.longitude,
        i = e.last_scanned,
        s = e.last_modified,
        r = e.name,
        l = e.pokemon,
        d = null != e.raid_level,
        c = null != e.raid_pokemon_id,
        m = "",
        p = "";
    if (d && e.raid_end > Date.now()) {
        var g = "";
        for (k = 0; k < e.raid_level; k++) g += "★";
        if (m = '<h3 style="margin-bottom: 0">Raid ' + g, c) {
            var u = "";
            null != e.raid_pokemon_cp && (u = " CP " + e.raid_pokemon_cp), m += "<br>" + e.raid_pokemon_name + u
        }
        if (m += "</h3>", c && null != e.raid_pokemon_move_1 && null != e.raid_pokemon_move_2 && (m += "<div><b>" + (void 0 !== moves[e.raid_pokemon_move_1] ? i8ln(moves[e.raid_pokemon_move_1].name) : "gen/unknown") + " / " + (void 0 !== moves[e.raid_pokemon_move_2] ? i8ln(moves[e.raid_pokemon_move_2].name) : "gen/unknown") + "</b></div>"), m += '<div style="margin-bottom: 10px">Time: <b>' + getTimeStr(e.raid_start) + "</b> - <b>" + getTimeStr(e.raid_end) + "</b></div>", c) p = '<i class="pokemon-large-sprite n' + e.raid_pokemon_id + '"></i>';
        else {
            var y = "";
            p = '<img src="static/raids/egg_' + (y = e.raid_level <= 2 ? "normal" : e.raid_level <= 4 ? "rare" : "legendary") + '.png">'
        }
    }
    for (var v = "", k = 0; k < l.length; k++) v += '<span class="gym-member" title="' + l[k].pokemon_name + " | " + l[k].trainer_name + " (Lvl " + l[k].trainer_level + ')"><i class="pokemon-sprite n' + l[k].pokemon_id + '"></i><span class="cp team-' + a + '">' + l[k].pokemon_cp + "</span></span>";
    var f = "";
    null != i && (f = "<div>Last Scanned: " + getDateStr(i) + "</div>");
    var h = getDateStr(s),
        w = r ? "<div>" + r + "</div>" : "",
        _ = ["0, 0, 0, .4", "74, 138, 202, .6", "240, 68, 58, .6", "254, 217, 40, .6"],
        S;
    if (0 === a) S = '<div><center><div><b style="color:rgba(' + _[a] + ')">' + t + '</b><br><img height="70px" style="padding: 5px;" src="static/forts/' + t + '_large.png">' + p + "</div>" + w + m + '<div>Location: <a href="javascript:void(0);" onclick="javascript:openMapDirections(' + o + "," + n + ');" title="View in Maps">' + o.toFixed(6) + " , " + n.toFixed(7) + "</a></div><div>" + f + "</div><div>Last Modified: " + h + "</div></center></div>";
    else {
        var M = e.slots_available,
            L = "";
        null != e.total_gym_cp && (L = "<div>Total Gym CP: <b>" + e.total_gym_cp + "</b></div>"), S = '<div><center><div style="padding-bottom: 2px">Gym owned by:</div><div><b style="color:rgba(' + _[a] + ')">Team ' + t + '</b><br><img height="70px" style="padding: 5px;" src="static/forts/' + t + '_large.png">' + p + "</div>" + w + m + "<div><b>" + M + " Free Slots</b></div>" + L + "<div>" + v + '</div><div>Location: <a href="javascript:void(0);" onclick="javascript:openMapDirections(' + o + "," + n + ');" title="View in Maps">' + o.toFixed(6) + " , " + n.toFixed(7) + "</a></div><div>" + f + "</div><div>Last Modified: " + h + "</div></center></div>"
    }
    return S
}

function pokestopLabel(e, t, a) {
    var o;
    if (e) {
        var n = new Date(e);
        o = "<div><b>Lured Pokéstop</b></div><div>Lure expires at " + pad(n.getHours()) + ":" + pad(n.getMinutes()) + ":" + pad(n.getSeconds()) + '<span class="label-countdown" disappears-at="' + e + '">(00m00s)</span></div><div>Location: <a href="javascript:void(0)" onclick="javascript:openMapDirections(' + t + "," + a + ')" title="View in Maps">' + t.toFixed(6) + ", " + a.toFixed(7) + "</a></div>"
    } else o = '<div><b>Pokéstop</b></div><div>Location: <a href="javascript:void(0)" onclick="javascript:openMapDirections(' + t + "," + a + ')" title="View in Maps">' + t.toFixed(6) + ", " + a.toFixed(7) + "</a></div>";
    return o
}

function formatSpawnTime(e) {
    return ("0" + Math.floor((e + 3600) % 3600 / 60)).substr(-2) + ":" + ("0" + e % 60).substr(-2)
}

function spawnpointLabel(e) {
    var t = "<div><b>Spawn Point</b></div><div>Every hour from " + formatSpawnTime(e.time) + " to " + formatSpawnTime(e.time + 900) + "</div>";
    return e.special && (t += "<div>May appear as early as " + formatSpawnTime(e.time - 1800) + "</div>"), t
}

function addRangeCircle(e, t, a, o) {
    var n = null,
        i = new google.maps.LatLng(e.position.lat(), e.position.lng()),
        s = ["#999999", "#0051CF", "#FF260E", "#FECC23"],
        r = s[0];
    o && (r = s[o]);
    var l, d;
    switch (a) {
        case "pokemon":
            d = "#C233F2", l = 40;
            break;
        case "pokestop":
            d = "#3EB0FF", l = 40;
            break;
        case "gym":
            d = r, l = 40
    }
    t && (n = t);
    var c = {
        map: n,
        radius: l,
        strokeWeight: 1,
        strokeColor: d,
        strokeOpacity: .9,
        center: i,
        fillColor: d,
        fillOpacity: .3
    };
    return new google.maps.Circle(c)
}

function isRangeActive(e) {
    return !(e.getZoom() < 16) && Store.get("showRanges")
}

function getIv(e, t, a) {
    return null !== e && 100 * (e + t + a) / 45
}

function getPokemonLevel(e) {
    if (e < .734) var t = 58.35178527 * e * e - 2.838007664 * e + .8539209906;
    else t = 171.0112688 * e - 95.20425243;
    return t = 2 * Math.round(t) / 2
}

function lpad(e, t, a) {
    return Array(Math.max(t - String(e).length + 1, 0)).join(a) + e
}

function repArray(e, t, a) {
    for (var o = 0; o < t.length; o++) e = e.replace(t[o], a[o]);
    return e
}

function getTimeUntil(e) {
    var t = +new Date,
        a = e - t,
        o = Math.floor(a / 1e3 % 60),
        n = Math.floor(a / 1e3 / 60 % 60);
    return {
        total: a,
        hour: Math.floor(a / 36e5 % 24),
        min: n,
        sec: o,
        now: t,
        ttime: e
    }
}

function getNotifyText(e) {
    var t = getIv(e.individual_attack, e.individual_defense, e.individual_stamina),
        a = ["<prc>", "<pkm>", "<atk>", "<def>", "<sta>"],
        o = [t ? t.toFixed(1) : "", e.pokemon_name, e.individual_attack, e.individual_defense, e.individual_stamina],
        n = repArray(t ? notifyIvTitle : notifyNoIvTitle, a, o),
        i = new Date(e.disappear_time).toLocaleString([], {
            hour: "2-digit",
            minute: "2-digit",
            second: "2-digit",
            hour12: !1
        }),
        s = getTimeUntil(e.disappear_time),
        r = s.hour > 0 ? s.hour + ":" : "";
    return r += lpad(s.min, 2, 0) + "m" + lpad(s.sec, 2, 0) + "s", {
        fav_title: n,
        fav_text: repArray(notifyText, a = ["<dist>", "<udist>"], o = [i, r])
    }
}

function customizePokemonMarker(e, t, a) {
    if (e.addListener("click", function() {
            this.setAnimation(null), this.animationDisabled = !0
        }), !e.rangeCircle && isRangeActive(map) && (e.rangeCircle = addRangeCircle(e, map, "pokemon")), e.infoWindow = new google.maps.InfoWindow({
            content: pokemonLabel(t),
            disableAutoPan: !0
        }), (notifiedPokemon.indexOf(t.pokemon_id) > -1 || notifiedRarity.indexOf(t.pokemon_rarity) > -1) && (a || (Store.get("playSound") && audio.play(), sendNotification(getNotifyText(t).fav_title, getNotifyText(t).fav_text, "static/icons/" + t.pokemon_id + ".png", t.latitude, t.longitude)), !0 !== e.animationDisabled && e.setAnimation(google.maps.Animation.BOUNCE)), null != t.individual_attack) {
        var o = getIv(t.individual_attack, t.individual_defense, t.individual_stamina);
        notifiedMinPerfection > 0 && o >= notifiedMinPerfection && (a || (Store.get("playSound") && audio.play(), sendNotification(getNotifyText(t).fav_title, getNotifyText(t).fav_text, "static/icons/" + t.pokemon_id + ".png", t.latitude, t.longitude)), !0 !== e.animationDisabled && e.setAnimation(google.maps.Animation.BOUNCE))
    }
    addListeners(e)
}

function getGymMarkerIcon(e) {
    var t = e.raid_level,
        a = "";
    if (a = 0 === e.team_id ? gymTypes[e.team_id] : gymTypes[e.team_id] + "_" + t, null != e.raid_pokemon_id && e.raid_end > Date.now()) return '<div style="position:relative;"><img src="static/forts/' + Store.get("gymMarkerStyle") + "/" + a + '.png" style="width:55px;height:auto;"/><i class="pokemon-raid-sprite n' + e.raid_pokemon_id + '"></i></div>';
    if (null !== e.raid_level && e.raid_end > Date.now()) {
        var o = "";
        return o = e.raid_level <= 2 ? "normal" : e.raid_level <= 4 ? "rare" : "legendary", '<div style="position:relative;"><img src="static/forts/' + Store.get("gymMarkerStyle") + "/" + a + '.png" style="width:55px;height:auto;"/><img src="static/raids/egg_' + o + '.png" style="width:30px;height:auto;position:absolute;top:8px;right:12px;"/></div>'
    }
    return '<div><img src="static/forts/' + Store.get("gymMarkerStyle") + "/" + gymTypes[e.team_id] + '.png" style="width:48px;height: auto;"/></div>'
}

function setupGymMarker(e) {
    var t = new RichMarker({
        position: new google.maps.LatLng(e.latitude, e.longitude),
        map: map,
        content: getGymMarkerIcon(e),
        flat: !0,
        anchor: RichMarkerPosition.MIDDLE
    });
    !t.rangeCircle && isRangeActive(map) && (t.rangeCircle = addRangeCircle(t, map, "gym", e.team_id)), t.infoWindow = new google.maps.InfoWindow({
        content: gymLabel(e),
        disableAutoPan: !0,
        pixelOffset: new google.maps.Size(0, -20)
    });
    var a = e.raid_level;
    if (a >= Store.get("remember_raid_notify") && e.raid_end > Date.now() && 0 !== Store.get("remember_raid_notify")) {
        Store.get("playSound") && audio.play();
        var o = "Raid level: " + a,
            n = getTimeStr(e.raid_start) + " - " + getTimeStr(e.raid_end),
            i;
        if (null != e.raid_pokemon_id) i = "static/icons/" + e.raid_pokemon_id + ".png";
        else {
            var s = "";
            i = "static/raids/egg_" + (s = e.raid_level <= 2 ? "normal" : e.raid_level <= 4 ? "rare" : "legendary") + ".png"
        }
        sendNotification(o, n, i, e.latitude, e.longitude)
    }
    return Store.get("useGymSidebar") ? (t.addListener("click", function() {
        var t = document.querySelector("#gym-details");
        t.getAttribute("data-id") === e.gym_id && t.classList.contains("visible") ? t.classList.remove("visible") : (t.setAttribute("data-id", e.gym_id), showGymDetails(e.gym_id))
    }), google.maps.event.addListener(t.infoWindow, "closeclick", function() {
        t.persist = null
    }), isMobileDevice() || isTouchDevice() || t.addListener("mouseover", function() {
        t.infoWindow.open(map, t), clearSelection(), updateLabelDiffTime()
    }), t.addListener("mouseout", function() {
        t.persist || t.infoWindow.close()
    })) : addListeners(t), t
}

function updateGymMarker(e, t) {
    t.setContent(getGymMarkerIcon(e)), t.infoWindow.setContent(gymLabel(e));
    var a = e.raid_level;
    if (a >= Store.get("remember_raid_notify") && e.raid_end > Date.now() && 0 !== Store.get("remember_raid_notify")) {
        var o = mapData.gyms[e.gym_id].raid_pokemon_id;
        if (e.raid_pokemon_id !== o) {
            Store.get("playSound") && audio.play();
            var n = "Raid level: " + a,
                i = getTimeStr(e.raid_start) + " - " + getTimeStr(e.raid_end),
                s;
            if (null != e.raid_pokemon_id) s = "static/icons/" + e.raid_pokemon_id + ".png";
            else {
                var r = "";
                s = "static/raids/egg_" + (r = e.raid_level <= 2 ? "normal" : e.raid_level <= 4 ? "rare" : "legendary") + ".png"
            }
            sendNotification(n, i, s, e.latitude, e.longitude)
        }
    }
    return t
}

function updateGymIcons() {
    $.each(mapData.gyms, function(e, t) {
        mapData.gyms[e].marker.setContent(getGymMarkerIcon(mapData.gyms[e]))
    })
}

function setupPokestopMarker(e) {
    var t = e.lure_expiration ? "PstopLured" : "Pstop",
        a = new google.maps.Marker({
            position: {
                lat: e.latitude,
                lng: e.longitude
            },
            map: map,
            zIndex: 2,
            icon: "static/forts/" + t + ".png"
        });
    return !a.rangeCircle && isRangeActive(map) && (a.rangeCircle = addRangeCircle(a, map, "pokestop")), a.infoWindow = new google.maps.InfoWindow({
        content: pokestopLabel(e.lure_expiration, e.latitude, e.longitude),
        disableAutoPan: !0
    }), addListeners(a), a
}

function getColorByDate(e) {
    var t = (Date.now() - e) / 1e3 / 60 / 15;
    return t > 1 && (t = 1), ["hsl(", (120 * (1 - t)).toString(10), ",100%,50%)"].join("")
}

function setupScannedMarker(e) {
    var t = new google.maps.LatLng(e.latitude, e.longitude);
    return new google.maps.Circle({
        map: map,
        clickable: !1,
        center: t,
        radius: 70,
        fillColor: getColorByDate(e.last_modified),
        fillOpacity: .1,
        strokeWeight: 1,
        strokeOpacity: .5
    })
}

function getColorBySpawnTime(e) {
    var t = new Date,
        a = 60 * t.getMinutes() + t.getSeconds();
    a < 900 && e > 2700 ? a += 3600 : a > 2700 && e < 900 && (e += 3600);
    var o = a - e,
        n = 275;
    return o >= 0 && o <= 900 ? n = 120 * (1 - o / 60 / 15) : o < 0 && o > -300 && (n = 50 * (1 - -o / 60 / 5) + 200), n = 5 * Math.round(n / 5)
}

function changeSpawnIcon(e, t) {
    var a = "";
    a = 275 === e ? "./static/icons/hsl-275-light.png" : "./static/icons/hsl-" + e + ".png";
    var o = 1.6,
        n = 1,
        i = Math.round(1.6 * (t - 10));
    return i < 1 && (i = 1), {
        url: a,
        scaledSize: new google.maps.Size(i, i),
        anchor: new google.maps.Point(i / 2, i / 2)
    }
}

function spawnPointIndex(e) {
    var t = 1,
        a = 0;
    return e >= 0 && e <= 120 ? t = 100 + 100 * (a = e / 120) : e >= 200 && e <= 250 && (t = 100 * (a = (e - 200) / 50)), t
}

function setupSpawnpointMarker(e) {
    var t = new google.maps.LatLng(e.latitude, e.longitude),
        a = getColorBySpawnTime(e.time),
        o = map.getZoom(),
        n = new google.maps.Marker({
            map: map,
            position: t,
            icon: changeSpawnIcon(a, o),
            zIndex: spawnPointIndex(a)
        });
    return n.infoWindow = new google.maps.InfoWindow({
        content: spawnpointLabel(e),
        disableAutoPan: !0,
        position: t
    }), addListeners(n), n
}

function clearSelection() {
    document.selection ? document.selection.empty() : window.getSelection && window.getSelection().removeAllRanges()
}

function addListeners(e) {
    return e.addListener("click", function() {
        e.infoWindowIsOpen ? (e.persist = null, e.infoWindow.close(), e.infoWindowIsOpen = !1) : (e.infoWindow.open(map, e), clearSelection(), updateLabelDiffTime(), e.persist = !0, e.infoWindowIsOpen = !0)
    }), google.maps.event.addListener(e.infoWindow, "closeclick", function() {
        e.persist = null
    }), isMobileDevice() || isTouchDevice() || e.addListener("mouseover", function() {
        e.infoWindow.open(map, e), clearSelection(), updateLabelDiffTime()
    }), e.addListener("mouseout", function() {
        e.persist || e.infoWindow.close()
    }), e
}

function clearStaleMarkers() {
    $.each(mapData.pokemons, function(e, t) {
        (mapData.pokemons[e].disappear_time < (new Date).getTime() || excludedPokemon.indexOf(mapData.pokemons[e].pokemon_id) >= 0 || isTemporaryHidden(mapData.pokemons[e].pokemon_id)) && (mapData.pokemons[e].marker.rangeCircle && (mapData.pokemons[e].marker.rangeCircle.setMap(null), delete mapData.pokemons[e].marker.rangeCircle), mapData.pokemons[e].marker.setMap(null), delete mapData.pokemons[e])
    }), $.each(mapData.lurePokemons, function(e, t) {
        (mapData.lurePokemons[e].lure_expiration < (new Date).getTime() || excludedPokemon.indexOf(mapData.lurePokemons[e].pokemon_id) >= 0) && (mapData.lurePokemons[e].marker.setMap(null), delete mapData.lurePokemons[e])
    }), $.each(mapData.scanned, function(e, t) {
        mapData.scanned[e].last_modified < (new Date).getTime() - 9e5 && (mapData.scanned[e].marker.setMap(null), delete mapData.scanned[e])
    })
}

function showInBoundsMarkers(e, t) {
    $.each(e, function(a, o) {
        var n = e[a].marker,
            i = !1;
        e[a].hidden || ("function" == typeof n.getBounds ? map.getBounds().intersects(n.getBounds()) && (i = !0) : "function" == typeof n.getPosition && map.getBounds().contains(n.getPosition()) && (i = !0)), i && -1 !== rangeMarkers.indexOf(t) && (n.rangeCircle ? isRangeActive(map) ? n.rangeCircle.setMap(map) : n.rangeCircle.setMap(null) : isRangeActive(map) && (n.rangeCircle = "gym" === t ? addRangeCircle(n, map, t, e[a].team_id) : addRangeCircle(n, map, t))), i && !n.getMap() ? (n.setMap(map), n.setAnimation && n.oldAnimation && n.setAnimation(n.oldAnimation)) : !i && n.getMap() && (n.getAnimation && (n.oldAnimation = n.getAnimation()), n.rangeCircle && n.rangeCircle.setMap(null), n.setMap(null))
    })
}

function loadRawData() {
    var e = Store.get("showPokemon"),
        t = Store.get("showGyms") || Store.get("showRaids") ? "true" : "false",
        a = Store.get("showPokestops"),
        o = Store.get("showScanned"),
        n = Store.get("showSpawnpoints"),
        i = Boolean(Store.get("showLuredPokestopsOnly")),
        s = map.getBounds(),
        r = s.getSouthWest(),
        l = s.getNorthEast(),
        d = r.lat(),
        c = r.lng(),
        m = l.lat(),
        p = l.lng();
	return $.ajax({
        url: "raw_data",
        type: "GET",
        timeout: 3e5,
        data: {
            timestamp: timestamp,
            pokemon: e,
            lastpokemon: lastpokemon,
            pokestops: a,
            lastpokestops: lastpokestops,
            luredonly: i,
            gyms: t,
            lastgyms: lastgyms,
            scanned: o,
            lastslocs: lastslocs,
            spawnpoints: n,
            lastspawns: lastspawns,
            swLat: d,
            swLng: c,
            neLat: m,
            neLng: p,
            oSwLat: oSwLat,
            oSwLng: oSwLng,
            oNeLat: oNeLat,
            oNeLng: oNeLng,
            reids: String(reincludedPokemon),
            eids: String(excludedPokemon)
        },
        dataType: "json",
        cache: !1,
        beforeSend: function e() {
            if (rawDataIsLoading) return !1;
            rawDataIsLoading = !0
        },
        error: function e() {
            toastr.error("Please check connectivity or reduce marker settings.", "Error getting data"), toastr.options = {
                closeButton: !0,
                debug: !1,
                newestOnTop: !0,
                progressBar: !1,
                positionClass: "toast-top-right",
                preventDuplicates: !0,
                onclick: null,
                showDuration: "300",
                hideDuration: "1000",
                timeOut: "25000",
                extendedTimeOut: "1000",
                showEasing: "swing",
                hideEasing: "linear",
                showMethod: "fadeIn",
                hideMethod: "fadeOut"
            }
        },
        complete: function e() {
            rawDataIsLoading = !1
        }
    })
}

function isInteresting (p) {
    var iv = p.individual_attack + p.individual_defense + p.individual_stamina;
    var interestingId = [106, 107, 113, 130, 131, 142, 143, 149, 201, 237, 242, 246, 247, 248];
    if (iv == 45)
        return true;
    if (iv >= 43 && p.level >= 20)
        return true;
    if (iv >= 40 && p.level >= 25)
        return true;
    if (iv >= 37 && p.level >= 30)
        return true;
    if (interestingId.indexOf(p.pokemon_id) >= 0)
        return true;
    return false;
}

function processPokemons(e, t) {
    if (!Store.get("showPokemon")) return !1;
    !(t.encounter_id in mapData.pokemons) && excludedPokemon.indexOf(t.pokemon_id) < 0 && isInteresting(t) && t.disappear_time > Date.now() && !isTemporaryHidden(t.pokemon_id) && (t.marker && t.marker.setMap(null), t.hidden || (t.marker = setupPokemonMarker(t, map), customizePokemonMarker(t.marker, t), mapData.pokemons[t.encounter_id] = t))
}

function processPokestops(e, t) {
    if (!Store.get("showPokestops")) return !1;
    if (Store.get("showLuredPokestopsOnly") && !t.lure_expiration) return !0;
    if (mapData.pokestops[t.pokestop_id]) {
        var a = mapData.pokestops[t.pokestop_id];
        !!t.lure_expiration != !!a.lure_expiration && (a.marker && a.marker.rangeCircle && a.marker.rangeCircle.setMap(null), a.marker.setMap(null), t.marker = setupPokestopMarker(t), mapData.pokestops[t.pokestop_id] = t)
    } else t.marker && t.marker.rangeCircle && t.marker.rangeCircle.setMap(null), t.marker && t.marker.setMap(null), t.marker = setupPokestopMarker(t), mapData.pokestops[t.pokestop_id] = t
}

function updatePokestops() {
    if (!Store.get("showPokestops")) return !1;
    var e = [],
        t = (new Date).getTime();
    $.each(mapData.pokestops, function(e, a) {
        a.lure_expiration && a.lure_expiration < t && (a.lure_expiration = null, a.marker && a.marker.rangeCircle && a.marker.rangeCircle.setMap(null), a.marker.setMap(null), a.marker = setupPokestopMarker(a))
    }), Store.get("showLuredPokestopsOnly") && ($.each(mapData.pokestops, function(t, a) {
        a.lure_expiration || e.push(t)
    }), $.each(e, function(e, t) {
        mapData.pokestops[t] && mapData.pokestops[t].marker && (mapData.pokestops[t].marker.rangeCircle && mapData.pokestops[t].marker.rangeCircle.setMap(null), mapData.pokestops[t].marker.setMap(null), delete mapData.pokestops[t])
    }))
}

function processGyms(e, t) {
    if (!Store.get("showGyms") && !Store.get("showRaids")) return !1;
    var a = t.slots_available,
        o = t.raid_level,
        n = function e(t) {
            mapData.gyms[t] && mapData.gyms[t].marker && (mapData.gyms[t].marker.rangeCircle && mapData.gyms[t].marker.rangeCircle.setMap(null), mapData.gyms[t].marker.setMap(null), delete mapData.gyms[t])
        };
    if (!Store.get("showGyms") && Store.get("showRaids") && void 0 === t.raid_end) return n(t.gym_id), !0;
    if (!Store.get("showGyms") && Store.get("showRaids") && t.raid_end < Date.now()) return n(t.gym_id), !0;
    if (Store.get("showGyms") && !Store.get("showRaids") && t.raid_end > Date.now()) return n(t.gym_id), !0;
    if (o < Store.get("minRaidLevel") && t.raid_end > Date.now()) return n(t.gym_id), !0;
    if (o > Store.get("maxRaidLevel") && t.raid_end > Date.now()) return n(t.gym_id), !0;
    if (Store.get("showOpenGymsOnly") && 0 === t.slots_available && (void 0 === t.raid_end || t.raid_end < Date.now())) return n(t.gym_id), !0;
    if (Store.get("showTeamGymsOnly") && Store.get("showTeamGymsOnly") !== t.team_id && (void 0 === t.raid_end || t.raid_end < Date.now())) return n(t.gym_id), !0;
    if (Store.get("showLastUpdatedGymsOnly")) {
        var i = new Date;
        if (null == t.last_scanned) {
            if (3600 * Store.get("showLastUpdatedGymsOnly") * 1e3 + t.last_modified < i.getTime() && (void 0 === t.raid_end || t.raid_end < Date.now())) return n(t.gym_id), !0
        } else if (3600 * Store.get("showLastUpdatedGymsOnly") * 1e3 + t.last_scanned < i.getTime() && (void 0 === t.raid_end || t.raid_end < Date.now())) return n(t.gym_id), !0
    }
    return a < Store.get("minGymLevel") && (void 0 === t.raid_end || t.raid_end < Date.now()) ? (n(t.gym_id), !0) : a > Store.get("maxGymLevel") && (void 0 === t.raid_end || t.raid_end < Date.now()) ? (n(t.gym_id), !0) : (t.gym_id in mapData.gyms ? t.marker = updateGymMarker(t, mapData.gyms[t.gym_id].marker) : t.marker = setupGymMarker(t), void(mapData.gyms[t.gym_id] = t))
}

function processScanned(e, t) {
    if (!Store.get("showScanned")) return !1;
    var a = t.latitude + "|" + t.longitude;
    a in mapData.scanned ? mapData.scanned[a].last_modified = t.last_modified : (t.marker && t.marker.setMap(null), t.marker = setupScannedMarker(t), mapData.scanned[a] = t)
}

function updateScanned() {
    if (!Store.get("showScanned")) return !1;
    $.each(mapData.scanned, function(e, t) {
        map.getBounds().intersects(t.marker.getBounds()) && t.marker.setOptions({
            fillColor: getColorByDate(t.last_modified)
        })
    })
}

function processSpawnpoints(e, t) {
    if (!Store.get("showSpawnpoints")) return !1;
    var a = t.spawnpoint_id;
    a in mapData.spawnpoints || (t.marker && t.marker.setMap(null), t.marker = setupSpawnpointMarker(t), mapData.spawnpoints[a] = t)
}

function updateSpawnPoints() {
    if (!Store.get("showSpawnpoints")) return !1;
    var e = map.getZoom();
    $.each(mapData.spawnpoints, function(t, a) {
        if (map.getBounds().contains(a.marker.getPosition())) {
            var o = getColorBySpawnTime(a.time);
            a.marker.setIcon(changeSpawnIcon(o, e)), a.marker.setZIndex(spawnPointIndex(o))
        }
    })
}

function updateMap() {
    var e = map.getCenter();
    Store.set("startAtLastLocationPosition", {
        lat: e.lat(),
        lng: e.lng()
    }), loadRawData().done(function(e) {
        $.each(e.pokemons, processPokemons), $.each(e.pokestops, processPokestops), $.each(e.gyms, processGyms), $.each(e.scanned, processScanned), $.each(e.spawnpoints, processSpawnpoints), showInBoundsMarkers(mapData.pokemons, "pokemon"), showInBoundsMarkers(mapData.lurePokemons, "pokemon"), showInBoundsMarkers(mapData.gyms, "gym"), showInBoundsMarkers(mapData.pokestops, "pokestop"), showInBoundsMarkers(mapData.scanned, "scanned"), showInBoundsMarkers(mapData.spawnpoints, "inbound"), clearStaleMarkers(), updateScanned(), updateSpawnPoints(), updatePokestops(), $("#stats").hasClass("visible") && countMarkers(map), oSwLat = e.oSwLat, oSwLng = e.oSwLng, oNeLat = e.oNeLat, oNeLng = e.oNeLng, lastgyms = e.lastgyms, lastpokestops = e.lastpokestops, lastpokemon = e.lastpokemon, lastslocs = e.lastslocs, lastspawns = e.lastspawns, (reids = e.reids) instanceof Array && (reincludedPokemon = reids.filter(function(e) {
            return this.indexOf(e) < 0
        }, reincludedPokemon)), timestamp = e.timestamp, lastUpdateTime = Date.now()
    })
}

function drawScanPath(e) {
    var t = [];
    $.each(e, function(e, a) {
        t.push({
            lat: a.latitude,
            lng: a.longitude
        })
    }), scanPath && scanPath.setMap(null), scanPath = new google.maps.Polyline({
        path: t,
        geodesic: !0,
        strokeColor: "#FF0000",
        strokeOpacity: 1,
        strokeWeight: 2,
        map: map
    })
}

function redrawPokemon(e) {
    var t = !0;
    $.each(e, function(t, a) {
        var o = e[t];
        if (!o.hidden) {
            o.marker.rangeCircle && o.marker.rangeCircle.setMap(null);
            var n = setupPokemonMarker(o, map, this.marker.animationDisabled);
            customizePokemonMarker(n, o, !0), o.marker.setMap(null), e[t].marker = n
        }
    })
}

function getPointDistance(e, t) {
    return google.maps.geometry.spherical.computeDistanceBetween(e, t)
}

function sendNotification(e, t, a, o, n) {
    if (!("Notification" in window)) return !1;
    if ("granted" !== Notification.permission) Notification.requestPermission();
    else {
        var i = new Notification(e, {
            icon: a,
            body: t,
            sound: "sounds/ding.mp3"
        });
        i.onclick = function() {
            window.focus(), i.close(), centerMap(o, n, 20)
        }
    }
}

function createMyLocationButton() {
    var e = document.createElement("div"),
        t = document.createElement("button");
    t.style.backgroundColor = "#fff", t.style.border = "none", t.style.outline = "none", t.style.width = "28px", t.style.height = "28px", t.style.borderRadius = "2px", t.style.boxShadow = "0 1px 4px rgba(0,0,0,0.3)", t.style.cursor = "pointer", t.style.marginRight = "10px", t.style.padding = "0px", t.title = "My Location", e.appendChild(t);
    var a = document.createElement("div");
    a.style.margin = "5px", a.style.width = "18px", a.style.height = "18px", a.style.backgroundImage = "url(static/mylocation-sprite-1x.png)", a.style.backgroundSize = "180px 18px", a.style.backgroundPosition = "0px 0px", a.style.backgroundRepeat = "no-repeat", a.id = "current-location", t.appendChild(a), t.addEventListener("click", function() {
        centerMapOnLocation()
    }), e.index = 1, map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(e), google.maps.event.addListener(map, "dragend", function() {
        document.getElementById("current-location").style.backgroundPosition = "0px 0px"
    })
}

function centerMapOnLocation() {
    var e = document.getElementById("current-location");
    if (null !== e) var t = "0",
        a = setInterval(function() {
            t = "-18" === t ? "0" : "-18", e.style.backgroundPosition = t + "px 0"
        }, 500);
    navigator.geolocation ? navigator.geolocation.getCurrentPosition(function(t) {
        var o = new google.maps.LatLng(t.coords.latitude, t.coords.longitude);
        locationMarker.setPosition(o), map.setCenter(o), Store.set("followMyLocationPosition", {
            lat: t.coords.latitude,
            lng: t.coords.longitude
        }), clearInterval(a), null !== e && (e.style.backgroundPosition = "-144px 0px")
    }) : (clearInterval(a), null !== e && (e.style.backgroundPosition = "0px 0px"))
}

function changeLocation(e, t) {
    var a = new google.maps.LatLng(e, t);
    map.setCenter(a)
}

function centerMap(e, t, a) {
    var o = new google.maps.LatLng(e, t);
    map.setCenter(o), a && (storeZoom = !1, map.setZoom(a))
}

function i8ln(e) {
    return $.isEmptyObject(i8lnDictionary) && "en" !== language && languageLookups < languageLookupThreshold && $.ajax({
        url: "static/dist/locales/" + language + ".min.json",
        dataType: "json",
        async: !1,
        success: function e(t) {
            i8lnDictionary = t
        },
        error: function e(t, a, o) {
            console.log("Error loading i8ln dictionary: " + o), languageLookups++
        }
    }), e in i8lnDictionary ? i8lnDictionary[e] : e
}

function updateGeoLocation() {
    navigator.geolocation && Store.get("followMyLocation") && navigator.geolocation.getCurrentPosition(function(e) {
        var t = e.coords.latitude,
            a = e.coords.longitude,
            o = new google.maps.LatLng(t, a);
        if (Store.get("followMyLocation") && void 0 !== locationMarker && getPointDistance(locationMarker.getPosition(), o) >= 5) {
            if (map.panTo(o), locationMarker.setPosition(o), Store.get("spawnArea")) {
                locationMarker.rangeCircle && (locationMarker.rangeCircle.setMap(null), delete locationMarker.rangeCircle);
                var n = {
                    map: map,
                    radius: 35,
                    strokeWeight: 1,
                    strokeColor: "#FF9200",
                    strokeOpacity: .9,
                    center: o,
                    fillColor: "#FF9200",
                    fillOpacity: .3
                };
                locationMarker.rangeCircle = new google.maps.Circle(n)
            }
            Store.set("followMyLocationPosition", {
                lat: t,
                lng: a
            })
        }
    })
}

function createUpdateWorker() {
    try {
        if (isMobileDevice() && window.Worker) {
            var e = new Blob(["onmessage = function(e) {\n                var data = e.data\n                if (data.name === 'backgroundUpdate') {\n                    self.setInterval(function () {self.postMessage({name: 'backgroundUpdate'})}, 5000)\n                }\n            }"]),
                t = window.URL.createObjectURL(e);
            (updateWorker = new Worker(t)).onmessage = function(e) {
                var t = e.data;
                document.hidden && "backgroundUpdate" === t.name && Date.now() - lastUpdateTime > 2500 && (updateMap(), updateGeoLocation())
            }, updateWorker.postMessage({
                name: "backgroundUpdate"
            })
        }
    } catch (e) {
        console.log("Webworker error: " + e.message)
    }
}

function showGymDetails(e) {
    var t = document.querySelector("#gym-details"),
        a;
    t.classList.add("visible"), $.ajax({
        url: "gym_data",
        type: "GET",
        timeout: 3e5,
        data: {
            id: e
        },
        dataType: "json",
        cache: !1
    }).done(function(e) {
        var o = getDateStr(e.last_modified),
            n = "";
        null != e.last_scanned && (n = '<div style="font-size: .7em">Last Scanned: ' + getDateStr(e.last_scanned) + "</div>");
        var i = void 0 !== e.pokemon ? e.pokemon : [],
            s = e.slots_available,
            r = "";
        0 !== e.team_id && (r = '<center class="team-' + e.team_id + '-text"><b class="team-' + e.team_id + '-text">' + s + " Free Slots</b></center>");
        var l = null != e.raid_level,
            d = null != e.raid_pokemon_id,
            c = "",
            m = "";
        if (l && e.raid_end > Date.now()) {
            for (var p = "", g = 0; g < e.raid_level; g++) p += "★";
            if (c = '<h3 style="margin-bottom: 0">Raid ' + p, d) {
                var u = "";
                null != e.raid_pokemon_cp && (u = " CP " + e.raid_pokemon_cp), c += "<br>" + e.raid_pokemon_name + u
            }
            if (c += "</h3>", d && null != e.raid_pokemon_move_1 && null != e.raid_pokemon_move_2 && (c += "<div><b>" + (void 0 !== moves[e.raid_pokemon_move_1] ? i8ln(moves[e.raid_pokemon_move_1].name) : "gen/unknown") + " / " + (void 0 !== moves[e.raid_pokemon_move_2] ? i8ln(moves[e.raid_pokemon_move_2].name) : "gen/unknown") + "</b></div>"), c += '<div style="margin-bottom: 10px">Time: <b>' + getTimeStr(e.raid_start) + "</b> - <b>" + getTimeStr(e.raid_end) + "</b></div>", d) m = '<i class="pokemon-large-sprite n' + e.raid_pokemon_id + '"></i>';
            else {
                var y = "";
                m = '<img src="static/raids/egg_' + (y = e.raid_level <= 2 ? "normal" : e.raid_level <= 4 ? "rare" : "legendary") + '.png">'
            }
        }
        var v = "",
            k = '<center class="team-' + e.team_id + '-text"><div><b class="team-' + e.team_id + '-text">' + (e.name || "") + '</b></div><div><img height="100px" style="padding: 5px;" src="static/forts/' + gymTypes[e.team_id] + '_large.png">' + m + "</div>" + c + r + '<div style="font-size: .7em">Last Modified: ' + o + "</div>" + n + "<div><a href='javascript:void(0)' onclick='javascript:openMapDirections(" + e.latitude + "," + e.longitude + ")' title='View in Maps'>Get directions</a></div></center>";
        i.length ? ($.each(i, function(t, a) {
            var o = getIv(a.iv_attack, a.iv_defense, a.iv_stamina),
                n = Math.round(100 / a.move_2_energy);
            v += '<tr onclick=toggleGymPokemonDetails(this)><td width="30px"><i class="pokemon-sprite n' + a.pokemon_id + '"></i></td><td class="team-' + e.team_id + '-text"><div style="line-height:1em">' + a.pokemon_name + '</div><div class="cp">CP ' + a.pokemon_cp + '</div></td><td width="190" class="team-' + e.team_id + '-text" align="center"><div class="trainer-level">' + a.trainer_level + '</div><div style="line-height: 1em">' + a.trainer_name + '</div></td><td width="10">\x3c!--<a href="#" onclick="toggleGymPokemonDetails(this)">--\x3e<i class="team-' + e.team_id + '-text fa fa-angle-double-down"></i>\x3c!--</a>--\x3e</td></tr><tr class="details"><td colspan="2"><div class="ivs"><div class="iv"><div class="type">ATK</div><div class="value">' + a.iv_attack + '</div></div><div class="iv"><div class="type">DEF</div><div class="value">' + a.iv_defense + '</div></div><div class="iv"><div class="type">STA</div><div class="value">' + a.iv_stamina + '</div></div><div class="iv" style="width: 36px"><div class="type">PERFECT</div><div class="value">' + o.toFixed(0) + '<span style="font-size: .6em">%</span></div></div></div></td><td colspan="2"><div class="moves"><div class="move"><div class="name">' + a.move_1_name + ' <div class="type ' + a.move_1_type.type_en.toLowerCase() + '">' + a.move_1_type.type + '</div></div><div class="damage">' + a.move_1_damage + '</div></div><br><div class="move"><div class="name">' + a.move_2_name + ' <div class="type ' + a.move_2_type.type_en.toLowerCase() + '">' + a.move_2_type.type + '</div><div><i class="move-bar-sprite move-bar-sprite-' + n + '"></i></div></div><div class="damage">' + a.move_2_damage + "</div></div></div></td></tr>"
        }), v = "<table><tbody>" + v + "</tbody></table>") : v = 0 === e.team_id ? "" : '<center class="team-' + e.team_id + '-text">Gym Leader:<br><i class="pokemon-large-sprite n' + e.guard_pokemon_id + '"></i><br><b class="team-' + e.team_id + '-text">' + e.guard_pokemon_name + '</b><p style="font-size: .75em margin: 5px">No additional gym information is available for this gym. Make sure you are collecting detailed gym info. If you have detailed gym info collection running, this gym\'s Pokemon information may be out of date.</p></center>', t.innerHTML = k + v, (a = document.createElement("a")).href = "#", a.className = "close", a.tabIndex = 0, t.appendChild(a), a.addEventListener("click", function(e) {
            e.preventDefault(), e.stopPropagation(), t.classList.remove("visible")
        })
    })
}

function toggleGymPokemonDetails(e) {
    e.lastElementChild.firstElementChild.classList.toggle("fa-angle-double-up"), e.lastElementChild.firstElementChild.classList.toggle("fa-angle-double-down"), e.nextElementSibling.classList.toggle("visible")
}

function download(e, t) {
    var a = document.createElement("a");
    a.setAttribute("href", "data:text/plain;charset=utf-8," + encodeURIComponent(t)), a.setAttribute("download", e + "_" + moment().format("DD-MM-YYYY HH:mm")), a.style.display = "none", document.body.appendChild(a), a.click(), document.body.removeChild(a)
}

function upload(e) {
    var t = JSON.parse(JSON.parse(e));
    Object.keys(t).forEach(function(e) {
        localStorage.setItem(e, t[e])
    }), window.location.reload()
}

function openFile(e) {
    var t = e.target,
        a = new FileReader;
    a.onload = function() {
        console.log(a.result), upload(a.result)
    }, a.readAsText(t.files[0])
}
var $selectExclude, $selectPokemonNotify, $selectRarityNotify, $textPerfectionNotify, $raidNotify, $selectStyle, $selectIconResolution, $selectIconSize, $switchOpenGymsOnly, $selectTeamGymsOnly, $selectLastUpdateGymsOnly, $selectMinGymLevel, $selectMaxGymLevel, $selectMinRaidLevel, $selectMaxRaidLevel, $selectLuredPokestopsOnly, $selectGymMarkerStyle, $selectLocationIconMarker, $switchGymSidebar, language = "" === document.documentElement.lang ? "en" : document.documentElement.lang,
    idToPokemon = {},
    i8lnDictionary = {},
    languageLookups = 0,
    languageLookupThreshold = 3,
    searchMarkerStyles, timestamp, excludedPokemon = [],
    notifiedPokemon = [],
    notifiedRarity = [],
    notifiedMinPerfection = null,
    onlyPokemon = 0,
    buffer = [],
    reincludedPokemon = [],
    reids = [],
    map, rawDataIsLoading = !1,
    locationMarker, rangeMarkers = ["pokemon", "pokestop", "gym"],
    storeZoom = !0,
    scanPath, moves, oSwLat, oSwLng, oNeLat, oNeLng, lastpokestops, lastgyms, lastpokemon, lastslocs, lastspawns, selectedStyle = "light",
    updateWorker, lastUpdateTime, gymTypes = ["Uncontested", "Mystic", "Valor", "Instinct"],
    audio = new Audio("static/sounds/ding.mp3"),
    genderType = ["♂", "♀", "⚲"],
    unownForm = ["unset", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "!", "?"],
    notifyIvTitle = "<pkm> <prc>% (<atk>/<def>/<sta>)",
    notifyNoIvTitle = "<pkm>",
    notifyText = "disappears at <dist> (<udist>)",
    updateLabelDiffTime = function e() {
        $(".label-countdown").each(function(e, t) {
            var a = getTimeUntil(parseInt(t.getAttribute("disappears-at"))),
                o = a.hour,
                n = a.min,
                i = a.sec,
                s = "";
            a.ttime < a.now ? s = "(expired)" : (s = "(", o > 0 && (s = o + "h"), s += lpad(n, 2, 0) + "m", s += lpad(i, 2, 0) + "s", s += ")"), $(t).text(s)
        })
    };
$(function() {
    try {
        if (!Notification) return void console.log("could not load notifications")
    } catch (e) {}
    try {
        "granted" !== Notification.permission && Notification.requestPermission()
    } catch (e) {}
}), $(function() {
    $.ajax({
        url: "motd_data",
        type: "GET",
        dataType: "json",
        cache: !1,
        success: function e(t) {
            $("#motd").attr("title", t.title).html(t.content).dialog()
        },
        fail: function e() {
            return !1
        }
    })
}), $(function() {
    $selectStyle = $("#map-style"), $.getJSON("static/dist/data/mapstyle.min.json").done(function(e) {
        var t = [];
        $.each(e, function(e, a) {
            t.push({
                id: e,
                text: i8ln(a)
            })
        }), $selectStyle.select2({
            placeholder: "Select Style",
            data: t,
            minimumResultsForSearch: 1 / 0
        }), $selectStyle.on("change", function(e) {
            selectedStyle = $selectStyle.val(), map.setMapTypeId(selectedStyle), Store.set("map_style", selectedStyle)
        }), $selectStyle.val(Store.get("map_style")).trigger("change")
    }), ($selectIconResolution = $("#pokemon-icons")).select2({
        placeholder: "Select Icon Resolution",
        minimumResultsForSearch: 1 / 0
    }), $selectIconResolution.on("change", function() {
        Store.set("pokemonIcons", this.value), redrawPokemon(mapData.pokemons), redrawPokemon(mapData.lurePokemons)
    }), ($selectIconSize = $("#pokemon-icon-size")).select2({
        placeholder: "Select Icon Size",
        minimumResultsForSearch: 1 / 0
    }), $selectIconSize.on("change", function() {
        Store.set("iconSizeModifier", this.value), redrawPokemon(mapData.pokemons), redrawPokemon(mapData.lurePokemons)
    }), ($switchOpenGymsOnly = $("#open-gyms-only-switch")).on("change", function() {
        Store.set("showOpenGymsOnly", this.checked), lastgyms = !1, updateMap()
    }), ($selectTeamGymsOnly = $("#team-gyms-only-switch")).select2({
        placeholder: "Only Show Gyms For Team",
        minimumResultsForSearch: 1 / 0
    }), $selectTeamGymsOnly.on("change", function() {
        Store.set("showTeamGymsOnly", this.value), lastgyms = !1, updateMap()
    }), ($selectLastUpdateGymsOnly = $("#last-update-gyms-switch")).select2({
        placeholder: "Only Show Gyms Last Updated",
        minimumResultsForSearch: 1 / 0
    }), $selectLastUpdateGymsOnly.on("change", function() {
        Store.set("showLastUpdatedGymsOnly", this.value), lastgyms = !1, updateMap()
    }), ($selectMinGymLevel = $("#min-level-gyms-filter-switch")).select2({
        placeholder: "Minimum Gym Level",
        minimumResultsForSearch: 1 / 0
    }), $selectMinGymLevel.on("change", function() {
        Store.set("minGymLevel", this.value), lastgyms = !1, updateMap()
    }), ($selectMaxGymLevel = $("#max-level-gyms-filter-switch")).select2({
        placeholder: "Maximum Gym Level",
        minimumResultsForSearch: 1 / 0
    }), $selectMaxGymLevel.on("change", function() {
        Store.set("maxGymLevel", this.value), lastgyms = !1, updateMap()
    }), ($selectMinRaidLevel = $("#min-level-raids-filter-switch")).select2({
        placeholder: "Minimum Raid Level",
        minimumResultsForSearch: 1 / 0
    }), $selectMinRaidLevel.on("change", function() {
        Store.set("minRaidLevel", this.value), lastgyms = !1, updateMap()
    }), ($selectMaxRaidLevel = $("#max-level-raids-filter-switch")).select2({
        placeholder: "Maximum Raid Level",
        minimumResultsForSearch: 1 / 0
    }), $selectMaxRaidLevel.on("change", function() {
        Store.set("maxRaidLevel", this.value), lastgyms = !1, updateMap()
    }), ($selectLuredPokestopsOnly = $("#lured-pokestops-only-switch")).select2({
        placeholder: "Only Show Lured Pokestops",
        minimumResultsForSearch: 1 / 0
    }), $selectLuredPokestopsOnly.on("change", function() {
        Store.set("showLuredPokestopsOnly", this.value), lastpokestops = !1, updateMap()
    }), ($switchGymSidebar = $("#gym-sidebar-switch")).on("change", function() {
        Store.set("useGymSidebar", this.checked), lastgyms = !1, $.each(["gyms"], function(e, t) {
            $.each(mapData[t], function(e, a) {
                mapData[t][e].marker.rangeCircle && (mapData[t][e].marker.rangeCircle.setMap(null), delete mapData[t][e].marker.rangeCircle), mapData[t][e].marker.setMap(null)
            }), mapData[t] = {}
        }), updateMap()
    }), $selectLocationIconMarker = $("#locationmarker-style"), $.getJSON("static/dist/data/searchmarkerstyle.min.json").done(function(e) {
        searchMarkerStyles = e;
        var t = [];
        if ($.each(e, function(e, a) {
                t.push({
                    id: e,
                    text: a.name
                })
            }), locationMarker = createLocationMarker(), Store.get("startAtUserLocation") && centerMapOnLocation(), Store.get("startAtLastLocation")) {
            var a = Store.get("startAtLastLocationPosition"),
                o = "lat" in a ? a.lat : centerLat,
                n = "lng" in a ? a.lng : centerLng,
                i = new google.maps.LatLng(o, n);
            locationMarker.setPosition(i), map.setCenter(i)
        }
        $selectLocationIconMarker.select2({
            placeholder: "Select Location Marker",
            data: t,
            minimumResultsForSearch: 1 / 0
        }), $selectLocationIconMarker.on("change", function(e) {
            Store.set("locationMarkerStyle", this.value), updateLocationMarker(this.value)
        }), $selectLocationIconMarker.val(Store.get("locationMarkerStyle")).trigger("change")
    }), ($selectGymMarkerStyle = $("#gym-marker-style")).select2({
        placeholder: "Select Style",
        minimumResultsForSearch: 1 / 0
    }), $selectGymMarkerStyle.on("change", function(e) {
        Store.set("gymMarkerStyle", this.value), updateGymIcons()
    }), $selectGymMarkerStyle.val(Store.get("gymMarkerStyle")).trigger("change")
}), $(function() {
    function e(e) {
        return e.id ? $('<span><i class="pokemon-sprite n' + e.element.value.toString() + '"></i> ' + e.text + "</span>") : e.text
    }

    function t(e, t, a) {
        return function() {
            Store.set(a, this.checked), this.checked ? ("showPokemon" === a ? lastpokemon = !1 : "showRaids" === a ? lastgyms = !1 : "showGyms" === a ? lastgyms = !1 : "showPokestops" === a ? lastpokestops = !1 : "showScanned" === a ? lastslocs = !1 : "showSpawnpoints" === a && (lastspawns = !1), updateMap()) : ($.each(t, function(t, o) {
                $.each(e[o], function(t, n) {
                    e[o][t].marker.rangeCircle && (e[o][t].marker.rangeCircle.setMap(null), delete e[o][t].marker.rangeCircle), "showRanges" !== a && e[o][t].marker.setMap(null)
                }), "showRanges" !== a && (e[o] = {})
            }), "showRanges" === a && updateMap())
        }
    }
    $.getJSON("static/dist/data/moves.min.json").done(function(e) {
        moves = e
    }), $selectExclude = $("#exclude-pokemon"), $selectPokemonNotify = $("#notify-pokemon"), $selectRarityNotify = $("#notify-rarity"), $textPerfectionNotify = $("#notify-perfection");
    var a = 493;
    ($raidNotify = $("#notify-raid")).select2({
        placeholder: "Minimum raid level",
        minimumResultsForSearch: 1 / 0
    }), $raidNotify.on("change", function() {
        Store.set("remember_raid_notify", this.value)
    }), $.getJSON("static/dist/data/pokemon.min.json").done(function(t) {
        var a = [];
        $.each(t, function(e, t) {
            if (e > 493) return !1;
            var o = [];
            a.push({
                id: e,
                text: i8ln(t.name) + " - #" + e
            }), t.name = i8ln(t.name), t.rarity = i8ln(t.rarity), $.each(t.types, function(e, t) {
                o.push({
                    type: i8ln(t.type),
                    color: t.color
                })
            }), t.types = o, idToPokemon[e] = t
        }), $selectExclude.select2({
            placeholder: i8ln("Select Pokémon"),
            data: a,
            templateResult: e
        }), $selectPokemonNotify.select2({
            placeholder: i8ln("Select Pokémon"),
            data: a,
            templateResult: e
        }), $selectRarityNotify.select2({
            placeholder: i8ln("Select Rarity"),
            data: [i8ln("Common"), i8ln("Uncommon"), i8ln("Rare"), i8ln("Very Rare"), i8ln("Ultra Rare")],
            templateResult: e
        }), $selectExclude.on("change", function(e) {
            buffer = excludedPokemon, excludedPokemon = $selectExclude.val().map(Number), buffer = buffer.filter(function(e) {
                return this.indexOf(e) < 0
            }, excludedPokemon), reincludedPokemon = reincludedPokemon.concat(buffer), clearStaleMarkers(), Store.set("remember_select_exclude", excludedPokemon)
        }), $selectPokemonNotify.on("change", function(e) {
            notifiedPokemon = $selectPokemonNotify.val().map(Number), Store.set("remember_select_notify", notifiedPokemon)
        }), $selectRarityNotify.on("change", function(e) {
            notifiedRarity = $selectRarityNotify.val().map(String), Store.set("remember_select_rarity_notify", notifiedRarity)
        }), $textPerfectionNotify.on("change", function(e) {
            notifiedMinPerfection = parseInt($textPerfectionNotify.val(), 10), (isNaN(notifiedMinPerfection) || notifiedMinPerfection <= 0) && (notifiedMinPerfection = ""), notifiedMinPerfection > 100 && (notifiedMinPerfection = 100), $textPerfectionNotify.val(notifiedMinPerfection), Store.set("remember_text_perfection_notify", notifiedMinPerfection)
        }), $selectExclude.val(Store.get("remember_select_exclude")).trigger("change"), $selectPokemonNotify.val(Store.get("remember_select_notify")).trigger("change"), $selectRarityNotify.val(Store.get("remember_select_rarity_notify")).trigger("change"), $textPerfectionNotify.val(Store.get("remember_text_perfection_notify")).trigger("change"), $raidNotify.val(Store.get("remember_raid_notify")).trigger("change"), isTouchDevice() && isMobileDevice() && $(".select2-search input").prop("readonly", !0)
    }), window.setInterval(updateLabelDiffTime, 1e3), window.setInterval(updateMap, 1e4), window.setInterval(updateGeoLocation, 1e3), createUpdateWorker(), $("#raids-switch").change(function() {
        var e = {
                duration: 500
            },
            a = $("#raids-filter-wrapper");
        this.checked ? (lastgyms = !1, a.show(e)) : (lastgyms = !1, a.hide(e)), t(mapData, ["gyms"], "showRaids").bind(this)()
    }), $("#gyms-switch").change(function() {
        var e = {
                duration: 500
            },
            a = $("#gyms-filter-wrapper");
        this.checked ? (lastgyms = !1, a.show(e)) : (lastgyms = !1, a.hide(e)), t(mapData, ["gyms"], "showGyms").bind(this)()
    }), $("#pokemon-switch").change(function() {
        t(mapData, ["pokemons"], "showPokemon").bind(this)()
    }), $("#scanned-switch").change(function() {
        t(mapData, ["scanned"], "showScanned").bind(this)()
    }), $("#spawnpoints-switch").change(function() {
        t(mapData, ["spawnpoints"], "showSpawnpoints").bind(this)()
    }), $("#ranges-switch").change(t(mapData, ["gyms", "pokemons", "pokestops"], "showRanges")), $("#pokestops-switch").change(function() {
        var e = {
                duration: 500
            },
            a = $("#lured-pokestops-only-wrapper");
        return this.checked ? (lastpokestops = !1, a.show(e)) : (lastpokestops = !1, a.hide(e)), t(mapData, ["pokestops"], "showPokestops").bind(this)()
    }), $("#sound-switch").change(function() {
        Store.set("playSound", this.checked)
    }), $("#start-at-user-location-switch").change(function() {
        Store.set("startAtUserLocation", this.checked), !0 === this.checked && !0 === Store.get("startAtLastLocation") && (Store.set("startAtLastLocation", !1), $("#start-at-last-location-switch").prop("checked", !1))
    }), $("#start-at-last-location-switch").change(function() {
        Store.set("startAtLastLocation", this.checked), !0 === this.checked && !0 === Store.get("startAtUserLocation") && (Store.set("startAtUserLocation", !1), $("#start-at-user-location-switch").prop("checked", !1))
    }), $("#follow-my-location-switch").change(function() {
        navigator.geolocation ? Store.set("followMyLocation", this.checked) : this.checked = !1, locationMarker.setDraggable(!this.checked)
    }), $("#spawn-area-switch").change(function() {
        Store.set("spawnArea", this.checked), locationMarker.rangeCircle && (locationMarker.rangeCircle.setMap(null), delete locationMarker.rangeCircle)
    }), $("#nav-accordion").length && $("#nav-accordion").accordion({
        active: !1,
        collapsible: !0,
        heightStyle: "content"
    }), $("#pokemonList_table").DataTable({
        paging: !1,
        searching: !1,
        info: !1,
        errMode: "throw",
        language: {
            emptyTable: ""
        },
        columns: [{
            orderable: !1
        }, null, null, null]
    }).order([1, "asc"])
});