Skip to content

Instantly share code, notes, and snippets.

@to-fr
Last active October 15, 2020 21:04
Show Gist options
  • Save to-fr/908cfbaacb207b08b152dc172fc81426 to your computer and use it in GitHub Desktop.
Save to-fr/908cfbaacb207b08b152dc172fc81426 to your computer and use it in GitHub Desktop.
from datetime import datetime, timedelta
import json
import time
import sys
sys.path.append("..")
from mapadroid.db.DbFactory import DbFactory
from mapadroid.geofence.geofenceHelper import GeofenceHelper
from mapadroid.utils.walkerArgs import parse_args
from mapadroid.utils.logging import *
# List of your geofences:
geofence_names = ["geofence_name1", "geofence_name2", "geofence_name3"]
geofences = {}
# Put this script into your MAD/scripts dir
#
# This is heavily based on https://gist.github.com/sn0opy/b7254a19a5312c8e2ed5ee2d5ebd1cf3
# All credits go to him.
#
# In addition this script has not production quality! I only made it work.
#
# At the moment only DEFAULT spawnpoints will be considered.
#
# Perhaps this should be in DbWrapper.py
def get_geofence_data(db_wrapper, geofence_name):
query = "SELECT fence_data FROM settings_geofence where name = '{}'".format(geofence_name)
res = db_wrapper.execute(query)
if res == []:
print("geofence", geofence_name, "not found.")
sys.exit()
return res[0][0][1:-1].replace('"', '').split(", ")
def isTitle(entry):
if entry[0] == '[' and entry[-1] == ']':
return True
else:
return False
def processGeofence(geofence_data, title, db_wrapper):
geofence_helper = GeofenceHelper(geofence_data, None)
# get outer bounds of fence
aa, ab, ba, bb = geofence_helper.get_polygon_from_fence()
# get spawns and mons
spawns = json.loads(db_wrapper.download_spawns(ba, bb, aa, ab))
mons = db_wrapper.get_mons_in_rectangle(ba, bb, aa, ab)
counts = {
"inactive": 0,
"active": 0,
"spawnwithoutmon": 0,
"unknown_despawn": 0,
"mons_in_geofence": 0,
"spawns_in_geofence": 0,
"mons_without_iv": 0,
"mons_with_iv": 0
}
mons_in_geofence = []
for mon in mons:
if geofence_helper.is_coord_inside_include_geofence((mon["latitude"], mon["longitude"])):
mons_in_geofence.append(mon["spawnpoint_id"])
if mon["cp"] is None:
counts["mons_without_iv"] += 1
else:
counts["mons_with_iv"] += 1
counts["mons_in_geofence"] = len(mons_in_geofence)
spawns_in_geofence = []
for i in spawns:
spawn = spawns[i]
if geofence_helper.is_coord_inside_include_geofence((spawn["lat"], spawn["lon"])):
spawn["spawnpoint_id"] = i
spawns_in_geofence.append(spawn)
counts["spawns_in_geofence"] = len(spawns_in_geofence)
current_time_of_day = datetime.now().replace(microsecond=0)
current_time = time.time()
active_spawnpoint_ids = []
for spawn in spawns_in_geofence:
if spawn["event"] != "DEFAULT":
continue
if spawn["endtime"] is None:
counts["unknown_despawn"] += 1
continue
endminsec_split = spawn["endtime"].split(":")
minutes = int(endminsec_split[0])
seconds = int(endminsec_split[1])
spawn_duration_minutes = 60 if spawn["spawndef"] == 15 else 30
despawn_time = current_time_of_day.replace(minute=minutes, second=seconds)
if minutes < datetime.now().minute:
despawn_time = despawn_time + timedelta(hours=1)
spawn_time = despawn_time - timedelta(minutes=spawn_duration_minutes)
if despawn_time > current_time_of_day > spawn_time:
counts["active"] += 1
active_spawnpoint_ids.append(int(spawn["spawnpoint_id"]))
else:
counts["inactive"] += 1
for active_spawnpoint_id in active_spawnpoint_ids:
if not active_spawnpoint_id in mons_in_geofence:
counts['spawnwithoutmon'] += 1
geofences[title] = counts
counts['spawns_with_mons'] = counts['active'] - counts['spawnwithoutmon']
counts['inactive_percent'] = counts['inactive'] / counts['spawns_in_geofence'] * 100
counts['active_percent'] = counts['active'] / counts['spawns_in_geofence'] * 100
counts['spawnwithoutmon_percent'] = counts['spawnwithoutmon'] / counts['active'] * 100
counts['mons_without_iv_percent'] = 0 if counts['mons_in_geofence'] == 0 else counts['mons_without_iv'] / counts['mons_in_geofence'] * 100
counts['mons_with_iv_percent'] = 0 if counts['mons_in_geofence'] == 0 else counts['mons_with_iv'] / counts['mons_in_geofence'] * 100
def printData():
print()
print(str(datetime.now())[0:19])
print("_______ Spawns __________")
row_geofences = "geofence_name............: "
row_spawns_in_geofence = "spawns_in_geofence.......: "
row_inactive_spawns = "inactive spawns..........: "
row_active_spawns = "active spawns............: "
row_active_spawns_wo = "active spawns w/o mons...: "
row_spawns_with_mons = "spawns with mons.........: "
row_unknown_despawn = "unknown_despawn..........: "
row_mons_in_geofence = "mons_in_geofence.........: "
row_mons_without_iv = "mons_without_iv..........: "
row_mons_with_iv = "mons_with_iv.............: "
for geofenceName in geofences:
row_geofences += '{:>.13} '.format(geofenceName)
row_spawns_in_geofence += '{:>5} '.format(str(geofences[geofenceName]['spawns_in_geofence']))
row_inactive_spawns += '{:>5} ({:.0f}%)'.format(str(geofences[geofenceName]['inactive']), geofences[geofenceName]['inactive_percent'])
row_active_spawns += '{:>5} ({:.0f}%)'.format(str(geofences[geofenceName]['active']), geofences[geofenceName]['active_percent'])
row_active_spawns_wo += '{:>5} ({:.0f}%)'.format(str(geofences[geofenceName]['spawnwithoutmon']), geofences[geofenceName]['spawnwithoutmon_percent'])
row_spawns_with_mons += '{:>5} '.format(str(geofences[geofenceName]['spawns_with_mons']))
row_unknown_despawn += '{:>5} '.format(str(geofences[geofenceName]['unknown_despawn']))
row_mons_in_geofence += '{:>5} '.format(str(geofences[geofenceName]['mons_in_geofence']))
row_mons_without_iv += '{:>5} ({:.0f}%)'.format(str(geofences[geofenceName]['mons_without_iv']), geofences[geofenceName]['mons_without_iv_percent'])
row_mons_with_iv += '{:>5} ({:.0f}%)'.format(str(geofences[geofenceName]['mons_with_iv']), geofences[geofenceName]['mons_with_iv_percent'])
print(row_geofences)
print(row_spawns_in_geofence)
print(row_inactive_spawns)
print(row_active_spawns)
print(row_active_spawns_wo)
print(row_spawns_with_mons)
print(row_unknown_despawn)
print("_______ Mons ____________")
print(row_mons_in_geofence)
print(row_mons_without_iv)
print(row_mons_with_iv)
if __name__ == "__main__":
args = parse_args()
db_wrapper, db_wrapper_manager = DbFactory.get_wrapper(args)
for currentGeofence in geofence_names:
title = currentGeofence
geofence_data = get_geofence_data(db_wrapper, currentGeofence)
if not isTitle(geofence_data[0]):
processGeofence({'fence_data': geofence_data}, title, db_wrapper)
else:
title = geofence_data[0]
geofence_data = geofence_data[1:]
coords = []
for entry in geofence_data:
if isTitle(entry):
processGeofence({'fence_data': coords}, title, db_wrapper)
title = entry
coords = []
else:
coords.append(entry)
processGeofence({'fence_data': coords}, title, db_wrapper)
printData()
@to-fr
Copy link
Author

to-fr commented Sep 27, 2020

Prints out information like this:

2020-09-27 09:20:41
_______ Spawns __________
geofence_name............:      area1      area2           area3
spawns_in_geofence.......:  1829        702        384
inactive spawns..........:   556 (30%)  249 (35%)  158 (41%)
active spawns............:   750 (41%)  260 (37%)  225 (59%)
active spawns w/o mons...:   232 (31%)  108 (42%)  225 (100%)
spawns with mons.........:   518        152          0
unknown_despawn..........:     1          1          1
_______ Mons ____________
mons_in_geofence.........:   518        153          0
mons_without_iv..........:    31 (6%)   18 (12%)    0 (0%)
mons_with_iv.............:   487 (94%)  135 (88%)    0 (0%)

@svenberg
Copy link

Do I understand the code correctly that it takes the outer bounds of the geofence as a rectangle, and would include spawnpoints outside a multipolygon geofence?

@to-fr
Copy link
Author

to-fr commented Oct 15, 2020

Hi, I took that part of the code over from sn0opy. I think the outer bounds are fetched as a rectangle as a first approximation (geofence_helper.get_polygon_from_fence()) but then every single coordinate is checked via geofence_helper.is_coord_inside_include_geofence. So the answer to your question is: hopefully no :-)

@svenberg
Copy link

Ah, ok, now I see - the first query is to get all mons within that area, and then comparing if those mons are within the multipolygon geofence.
That should be much faster than querying each mon towards the polygon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment