Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable pulling each pokemons IVs and Moves by starting their encounter. #1272

Merged
merged 32 commits into from
Sep 28, 2016
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
55dbd18
Scan for IVs and moves
MangoScango Sep 9, 2016
6777297
Don't ignore moves.json
MangoScango Sep 9, 2016
f7ea31e
whoopsie tabsies
MangoScango Sep 9, 2016
bbfdc22
im on a roll here
MangoScango Sep 9, 2016
3bb6484
whitespace is really hard guys
MangoScango Sep 9, 2016
66ba9da
whitespace is really hard guys
MangoScango Sep 9, 2016
b7c9bf9
Merge branch 'IVs-and-Moves' of https://github.com/MangoScango/Pokemo…
MangoScango Sep 9, 2016
78540cc
I'm sorry travis senpai
MangoScango Sep 9, 2016
fd26a1b
Don't pass the whole dictonary to pokemonLabel on top of everything else
MangoScango Sep 9, 2016
99b6351
Notifications based off % perfection
MangoScango Sep 9, 2016
1bd8939
praise travis
MangoScango Sep 9, 2016
0dd3c3e
Fix 0/0/0 results from atypical spawnpoints?
MangoScango Sep 10, 2016
72f1dcf
Merge upstream
MangoScango Sep 10, 2016
5dc897d
minor text fixes
MangoScango Sep 10, 2016
046d8f6
Merge remote-tracking branch 'refs/remotes/origin/develop' into IVs-a…
MangoScango Sep 11, 2016
bbfb6e3
Merge remote-tracking branch 'refs/remotes/PokemonGoMap/develop' into…
MangoScango Sep 11, 2016
697f7f4
Fix get_encountered_pokemon
MangoScango Sep 11, 2016
5c367ff
Default to a whitelist, support a black one
MangoScango Sep 11, 2016
6618816
Stop erroneous empty results when rescanning pokemon
MangoScango Sep 11, 2016
0bb01f5
Minor text fixes
MangoScango Sep 11, 2016
2421e33
Minorer text fixes
MangoScango Sep 11, 2016
4e62f39
No more white/black flip
MangoScango Sep 12, 2016
ef2a900
Fix up the white/blacklists
MangoScango Sep 12, 2016
d3510bb
sorry travis
MangoScango Sep 12, 2016
083b94a
derp
MangoScango Sep 14, 2016
673cc30
leave me alone travis
MangoScango Sep 14, 2016
8c7e345
Improve moves.json handling
MangoScango Sep 22, 2016
aff3407
Reduce db requests to one per cell
MangoScango Sep 22, 2016
dcec218
text minor fixes
MangoScango Sep 23, 2016
d97aae7
Handle failed encounters
MangoScango Sep 24, 2016
be16e9b
Merge remote-tracking branch 'refs/remotes/PokemonGoMap/develop' into…
MangoScango Sep 24, 2016
0ba3212
Minor fixes to the config.ini.example
primaxius Sep 27, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ beehive.*
!Tools/Easy-Setup/setup.bat
!contrib/supervisord/gen-workers.sh
!contrib/supervisord/install-reinstall.sh
!static/data/*
1 change: 1 addition & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ module.exports = function(grunt) {
build: {
files: {
'static/dist/data/pokemon.min.json': 'static/data/pokemon.json',
'static/dist/data/moves.min.json': 'static/data/moves.json',
'static/dist/data/mapstyle.min.json': 'static/data/mapstyle.json',
'static/dist/data/searchmarkerstyle.min.json': 'static/data/searchmarkerstyle.json',
'static/dist/locales/de.min.json': 'static/locales/de.json',
Expand Down
4 changes: 4 additions & 0 deletions config/config.ini.example
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
#gym-info: # enables detailed gym info collection (default false)
#min-seconds-left: # time that must be left on a spawn before considering it too late and skipping it (default 0)
#status-name: # enables writing status updates to the database - if you use multiple processes, each needs a unique value
#encounter: # start encounters to pull more info, like IVs or movesets.
#encounter-delay: # delay before starting an encounter. defaults to 1, must not be zero
#encounter-whitelist: # whitelist of pokemon ids to encounter.
#encounter-blacklist: # blacklist of pokemon ids to NOT encounter. Incompatible with the whitelist.

# Misc
#gmaps-key: # your Google Maps API key
Expand Down
100 changes: 87 additions & 13 deletions pogom/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
flaskDb = FlaskDB()
cache = TTLCache(maxsize=100, ttl=60 * 5)

db_schema_version = 7
db_schema_version = 8


class MyRetryDB(RetryOperationalError, PooledMySQLDatabase):
Expand Down Expand Up @@ -83,10 +83,28 @@ class Pokemon(BaseModel):
latitude = DoubleField()
longitude = DoubleField()
disappear_time = DateTimeField(index=True)
individual_attack = IntegerField(null=True)
individual_defense = IntegerField(null=True)
individual_stamina = IntegerField(null=True)
move_1 = IntegerField(null=True)
move_2 = IntegerField(null=True)

class Meta:
indexes = ((('latitude', 'longitude'), False),)

@staticmethod
def get_encountered_pokemon(encounter_id):
query = (Pokemon
.select()
.where((Pokemon.encounter_id == b64encode(str(encounter_id))) &
(Pokemon.disappear_time > datetime.utcnow()))
.dicts()
)
pokemon = []
for a in query:
pokemon.append(a)
return pokemon

@staticmethod
def get_active(swLat, swLng, neLat, neLng):
if swLat is None or swLng is None or neLat is None or neLng is None:
Expand Down Expand Up @@ -573,16 +591,55 @@ def hex_bounds(center, steps):
return (n, e, s, w)


def construct_pokemon_dict(pokemons, p, encounter_result, d_t):
pokemons[p['encounter_id']] = {
'encounter_id': b64encode(str(p['encounter_id'])),
'spawnpoint_id': p['spawn_point_id'],
'pokemon_id': p['pokemon_data']['pokemon_id'],
'latitude': p['latitude'],
'longitude': p['longitude'],
'disappear_time': d_t,
}
if encounter_result is not None:
ecounter_info = encounter_result['responses']['ENCOUNTER']
pokemon_info = ecounter_info['wild_pokemon']['pokemon_data']
attack = pokemon_info.get('individual_attack', 0)
defense = pokemon_info.get('individual_defense', 0)
stamina = pokemon_info.get('individual_stamina', 0)
pokemons[p['encounter_id']].update({
'individual_attack': attack,
'individual_defense': defense,
'individual_stamina': stamina,
'move_1': pokemon_info['move_1'],
'move_2': pokemon_info['move_2'],
})
else:
pokemons[p['encounter_id']].update({
'individual_attack': None,
'individual_defense': None,
'individual_stamina': None,
'move_1': None,
'move_2': None,
})


# todo: this probably shouldn't _really_ be in "models" anymore, but w/e
def parse_map(args, map_dict, step_location, db_update_queue, wh_update_queue):
def parse_map(args, map_dict, step_location, db_update_queue, wh_update_queue, api):
pokemons = {}
pokestops = {}
gyms = {}
skipped = 0

cells = map_dict['responses']['GET_MAP_OBJECTS']['map_cells']
for cell in cells:
if config['parse_pokemon']:
for p in cell.get('wild_pokemons', []):

# Don't parse pokemon we've already encountered. Avoids IVs getting nulled out on rescanning.
if Pokemon.get_encountered_pokemon(p['encounter_id']):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be optimized? This query in loop can get hit multiple times, and with millions of pokemon in db maybe intense? would it be better as single query? me and @jchristi thought maybe something like this? I know also encounter_id is not guaranteed to be unique.

  for cell in cells:
        if config['parse_pokemon']:
            encounter_ids = [b64encode(str(p['encounter_id'])) for p in cell.get('wild_pokemons', [])]
            query = (Pokemon
                   .select()
                   .where((Pokemon.disappear_time > datetime.utcnow()) & (Pokemon.encounter_id << encounter_ids))
                   .dicts()
                   )
            encountered_pokemon = [(p['encounter_id']) for p in query]
            for p in cell.get('wild_pokemons', []):
                if (p['encounter_id']) in encountered_pokemon:
                    skipped += 1
                    continue

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated my gist. We need to b64encode the encounter_id again when creating encountered_pokemon and also need to account for when encounter_ids is empty. See this PR: https://github.com/PokemonGoMap/PokemonGo-Map/pull/1303/files#diff-541e2b217ba4a7d7859dae2cb443b6b7L585

skipped += 1
continue

# time_till_hidden_ms was overflowing causing a negative integer.
# It was also returning a value above 3.6M ms.
if 0 < p['time_till_hidden_ms'] < 3600000:
Expand All @@ -595,14 +652,17 @@ def parse_map(args, map_dict, step_location, db_update_queue, wh_update_queue):

printPokemon(p['pokemon_data']['pokemon_id'], p['latitude'],
p['longitude'], d_t)
pokemons[p['encounter_id']] = {
'encounter_id': b64encode(str(p['encounter_id'])),
'spawnpoint_id': p['spawn_point_id'],
'pokemon_id': p['pokemon_data']['pokemon_id'],
'latitude': p['latitude'],
'longitude': p['longitude'],
'disappear_time': d_t
}

# Scan for IVs and moves
encounter_result = None
if (args.encounter and (p['pokemon_data']['pokemon_id'] in args.encounter_whitelist or
p['pokemon_data']['pokemon_id'] not in args.encounter_blacklist and not args.encounter_whitelist)):
time.sleep(args.encounter_delay)
encounter_result = api.encounter(encounter_id=p['encounter_id'],
spawn_point_id=p['spawn_point_id'],
player_latitude=step_location[0],
player_longitude=step_location[1])
construct_pokemon_dict(pokemons, p, encounter_result, d_t)

if args.webhooks:
wh_update_queue.put(('pokemon', {
Expand All @@ -613,7 +673,12 @@ def parse_map(args, map_dict, step_location, db_update_queue, wh_update_queue):
'longitude': p['longitude'],
'disappear_time': calendar.timegm(d_t.timetuple()),
'last_modified_time': p['last_modified_timestamp_ms'],
'time_until_hidden_ms': p['time_till_hidden_ms']
'time_until_hidden_ms': p['time_till_hidden_ms'],
'individual_attack': pokemons[p['encounter_id']]['individual_attack'],
'individual_defense': pokemons[p['encounter_id']]['individual_defense'],
'individual_stamina': pokemons[p['encounter_id']]['individual_stamina'],
'move_1': pokemons[p['encounter_id']]['move_1'],
'move_2': pokemons[p['encounter_id']]['move_2']
}))

for f in cell.get('forts', []):
Expand Down Expand Up @@ -701,7 +766,7 @@ def parse_map(args, map_dict, step_location, db_update_queue, wh_update_queue):
db_update_queue.put((Gym, gyms))

log.info('Parsing found %d pokemons, %d pokestops, and %d gyms',
len(pokemons),
len(pokemons) + skipped,
len(pokestops),
len(gyms))

Expand All @@ -712,7 +777,7 @@ def parse_map(args, map_dict, step_location, db_update_queue, wh_update_queue):
}}))

return {
'count': len(pokemons) + len(pokestops) + len(gyms),
'count': len(pokemons) + skipped + len(pokestops) + len(gyms),
'gyms': gyms,
}

Expand Down Expand Up @@ -1009,3 +1074,12 @@ def database_migrate(db, old_ver):
migrator.drop_column('gymdetails', 'description'),
migrator.add_column('gymdetails', 'description', TextField(null=True, default=""))
)

if old_ver < 8:
migrate(
migrator.add_column('pokemon', 'individual_attack', IntegerField(null=True, default=0)),
migrator.add_column('pokemon', 'individual_defense', IntegerField(null=True, default=0)),
migrator.add_column('pokemon', 'individual_stamina', IntegerField(null=True, default=0)),
migrator.add_column('pokemon', 'move_1', IntegerField(null=True, default=0)),
migrator.add_column('pokemon', 'move_2', IntegerField(null=True, default=0))
)
3 changes: 2 additions & 1 deletion pogom/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ def search_worker_thread(args, account_queue, account_failures, search_items_que

# Got the response, parse it out, send todo's to db/wh queues
try:
parsed = parse_map(args, response_dict, step_location, dbq, whq)
parsed = parse_map(args, response_dict, step_location, dbq, whq, api)
search_items_queue.task_done()
status[('success' if parsed['count'] > 0 else 'noitems')] += 1
consecutive_fails = 0
Expand Down Expand Up @@ -573,6 +573,7 @@ def search_worker_thread(args, account_queue, account_failures, search_items_que
time.sleep(args.scan_delay)

# catch any process exceptions, log them, and continue the thread

except Exception as e:
status['message'] = 'Exception in search_worker using account {}. Restarting with fresh account. See logs for details.'.format(account['username'])
time.sleep(args.scan_delay)
Expand Down
14 changes: 14 additions & 0 deletions pogom/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ def get_args():
parser.add_argument('-sd', '--scan-delay',
help='Time delay between requests in scan threads',
type=float, default=10)
parser.add_argument('-enc', '--encounter',
help='Start an encounter to gather IVs and moves',
action='store_true', default=False)
parser.add_argument('-ed', '--encounter-delay',
help='Time delay between encounter pokemon in scan threads',
type=float, default=1)
encounter_list = parser.add_mutually_exclusive_group()
encounter_list.add_argument('-ewht', '--encounter-whitelist', action='append', default=[],
help='List of pokemon to encounter for more stats')
encounter_list.add_argument('-eblk', '--encounter-blacklist', action='append', default=[],
help='List of pokemon to NOT encounter for more stats')
parser.add_argument('-ld', '--login-delay',
help='Time delay between each login attempt',
type=float, default=5)
Expand Down Expand Up @@ -278,6 +289,9 @@ def get_args():
print(sys.argv[0] + ": Error: no accounts specified. Use -a, -u, and -p or --accountcsv to add accounts")
sys.exit(1)

args.encounter_blacklist = [int(i) for i in args.encounter_blacklist]
args.encounter_whitelist = [int(i) for i in args.encounter_whitelist]

# Decide which scanning mode to use
if args.spawnpoint_scanning:
args.scheduler = 'SpawnScan'
Expand Down
2 changes: 2 additions & 0 deletions runserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ def main():
log.info('Parsing of Pokestops disabled')
if args.no_gyms:
log.info('Parsing of Gyms disabled')
if args.encounter:
log.info('Encountering pokemon enabled')

config['LOCALE'] = args.locale
config['CHINA'] = args.china
Expand Down
Loading