diff --git a/config.example.py b/config.example.py
index fce6bd810..71321cd1e 100644
--- a/config.example.py
+++ b/config.example.py
@@ -178,6 +178,8 @@
# allow displaying the live location of workers on the map
MAP_WORKERS = True
+# Highligh EX Raid Gyms on map (default False, uncomment to enable)
+#MAP_SHOW_EX_GYMS = True
# filter these Pokemon from the map to reduce traffic and browser load
#MAP_FILTER_IDS = [161, 165, 16, 19, 167]
diff --git a/monocle/sanitized.py b/monocle/sanitized.py
index b6bfbc4aa..ed3544847 100644
--- a/monocle/sanitized.py
+++ b/monocle/sanitized.py
@@ -74,6 +74,7 @@
'MAP_FILTER_IDS': sequence,
'MAP_PROVIDER_ATTRIBUTION': str,
'MAP_PROVIDER_URL': str,
+ 'MAP_SHOW_EX_GYMS': bool,
'MAP_START': sequence,
'MAP_WORKERS': bool,
'MAX_CAPTCHAS': int,
@@ -190,6 +191,7 @@
'MAP_FILTER_IDS': None,
'MAP_PROVIDER_URL': '//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
'MAP_PROVIDER_ATTRIBUTION': '© OpenStreetMap contributors',
+ 'MAP_SHOW_EX_GYMS': False,
'MAP_WORKERS': True,
'MAX_CAPTCHAS': 0,
'MAX_RETRIES': 3,
diff --git a/monocle/static/css/main.css b/monocle/static/css/main.css
index 7ef71be4e..db9aca9ec 100644
--- a/monocle/static/css/main.css
+++ b/monocle/static/css/main.css
@@ -57,6 +57,10 @@
box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);
}
+.ex-raid-gym {
+ background: #0f0;
+}
+
.leaflet-control-layers-toggle {
background-image: url('../img/layers.png');
}
@@ -215,4 +219,4 @@
}
.instinct {
background: #fe9c0a;
-}
\ No newline at end of file
+}
diff --git a/monocle/static/js/main.js b/monocle/static/js/main.js
index 05dd02b35..c861f128a 100644
--- a/monocle/static/js/main.js
+++ b/monocle/static/js/main.js
@@ -210,6 +210,9 @@ function PokemonMarker (raw) {
function FortMarker (raw) {
var icon = new FortIcon({iconUrl: '/static/monocle-icons/forts/' + raw.team + '.png'});
+ if (raw.ex) {
+ icon.options.className += " ex-raid-gym"
+ }
var marker = L.marker([raw.lat, raw.lon], {icon: icon, opacity: 1});
marker.raw = raw;
markers[raw.id] = marker;
@@ -281,9 +284,9 @@ function RaidMarker (raw) {
}, 2500);
var userPreference = getPreference('raids-'+raw.level);
- if (userPreference === 'show'){
+ if (userPreference === 'show' || (userPreference === 'showex' && raw.ex)){
marker.overlay = 'Raids';
- }else if (userPreference === 'hide'){
+ }else{
marker.overlay = 'Hidden';
}
@@ -652,7 +655,7 @@ function moveToLayer(id, layer, type){
var m = markers[k];
if ((k.indexOf("raid-") > -1) && (m !== undefined) && (m.raw.level === id)){
m.removeFrom(overlays[m.overlay]);
- if (layer === 'show'){
+ if (layer === 'show' || (layer === 'showex' && m.raw.ex)){
m.overlay = "Raids";
m.addTo(overlays.Raids);
}else{
@@ -688,6 +691,7 @@ function populateSettingsPanels(){
'Level ' + i + ' (' + _raids_labels[i-1] + ')' +
'
' +
'' +
+ '' +
'' +
'
' +
'';
@@ -701,7 +705,7 @@ function setSettingsDefaults(){
_defaultSettings['filter-'+i] = (_defaultSettings['TRASH_IDS'].indexOf(i) > -1) ? "trash" : "pokemon";
};
for (var i = 1; i <= _raids_count; i++){
- _defaultSettings['raids-'+i] = (_defaultSettings['RAIDS_FILTER'].indexOf(i) > -1) ? "show" : "hide";
+ _defaultSettings['raids-'+i] = (_defaultSettings['RAIDS_FILTER'].indexOf(i) > -1) ? "show" : "showex";
};
$("#settings div.btn-group").each(function(){
diff --git a/monocle/web_utils.py b/monocle/web_utils.py
index 6e69f2404..e436104c1 100644
--- a/monocle/web_utils.py
+++ b/monocle/web_utils.py
@@ -125,11 +125,13 @@ def get_pokemarkers(after_id=0):
return tuple(map(sighting_to_marker, pokemons))
-def get_raid_markers(names=POKEMON, moves=MOVES):
+def get_raid_markers(names=POKEMON, moves=MOVES, show_ex=conf.MAP_SHOW_EX_GYMS):
with session_scope() as session:
markers = []
raids = session.query(Raid) \
.filter(Raid.time_end > time())
+ if show_ex:
+ forts = get_forts(session)
for raid in raids:
fort = session.query(Fort) \
.filter(Fort.id == raid.fort_id) \
@@ -140,6 +142,7 @@ def get_raid_markers(names=POKEMON, moves=MOVES):
.first()
markers.append({
'id': 'raid-' + str(raid.id),
+ 'ex': show_ex and raid.fort_id in get_ex_raid_gyms(forts),
'level': raid.level,
'team': fortsighting.team,
'pokemon_id': raid.pokemon_id,
@@ -180,11 +183,12 @@ def get_weather():
return markers
-def get_gym_markers(names=POKEMON):
+def get_gym_markers(names=POKEMON, show_ex=conf.MAP_SHOW_EX_GYMS):
with session_scope() as session:
forts = get_forts(session)
return [{
'id': 'fort-' + str(fort['fort_id']),
+ 'ex': show_ex and fort['fort_id'] in get_ex_raid_gyms(forts),
'sighting_id': fort['id'],
'prestige': fort['prestige'],
'pokemon_id': fort['guard_pokemon_id'],
@@ -269,6 +273,42 @@ def get_all_parks():
return parks
+def get_ex_raid_gyms(forts=None):
+ gyms = []
+ with session_scope() as session:
+ if not forts:
+ forts = get_forts(session)
+ try:
+ pickle = load_pickle('ex_raid_gyms', raise_exception=True)
+ gyms = pickle['gyms']
+ max_id = pickle.get('max_id', 0)
+ for g in forts:
+ if g['fort_id'] > max_id:
+ raise KeyError("Cache outdated")
+ except (FileNotFoundError, TypeError, KeyError):
+ parks = get_all_parks()
+ max_id = 0
+ for g in forts:
+ if g['fort_id'] > max_id:
+ max_id = g['fort_id']
+ gym_point = Point(g['lat'], g['lon'])
+ cell = Polygon(get_s2_cell_as_polygon(g['lat'], g['lon'], 20)) # s2 lvl 20
+ for p in parks:
+ coords = p['coords']
+ # osm polygon can be a line
+ if len(coords) == 2:
+ shape = LineString(coords)
+ if shape.within(cell.centroid):
+ gyms.append(g['fort_id'])
+ break
+ if len(coords) > 2:
+ shape = Polygon(coords)
+ if shape.contains(cell.centroid):
+ gyms.append(g['fort_id'])
+ break
+ dump_pickle('ex_raid_gyms', {"max_id": max_id, "gyms": gyms})
+ return gyms
+
def get_s2_cells(n=north, w=west, s=south, e=east, level=12):
region_covered = s2sphere.LatLngRect.from_point_pair(
s2sphere.LatLng.from_degrees(n, w),
diff --git a/raidex.py b/raidex.py
index c007e3197..7128229f2 100644
--- a/raidex.py
+++ b/raidex.py
@@ -38,22 +38,9 @@ def fullmap(map_html=render_map()):
def gym_data():
gyms = []
parks = get_all_parks()
- for g in get_gym_markers():
- gym_point = Point(g['lat'], g['lon'])
- cell = Polygon(get_s2_cell_as_polygon(g['lat'], g['lon'], 20)) # s2 lvl 20
- for p in parks:
- coords = p['coords']
- # osm polygon can be a line
- if len(coords) == 2:
- shape = LineString(coords)
- if shape.within(cell.centroid):
- gyms.append(g)
- break
- if len(coords) > 2:
- shape = Polygon(coords)
- if shape.contains(cell.centroid):
- gyms.append(g)
- break
+ for g in get_gym_markers(show_ex=True):
+ if g['ex']:
+ gyms.append(g)
return jsonify(gyms)
@app.route('/parks_cells')