Skip to content

Add metrics logging and output on close #1059

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

Merged
merged 5 commits into from
Jul 27, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
26 changes: 24 additions & 2 deletions pokecli.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import ssl
import sys
import time
from datetime import timedelta
from getpass import getpass
from pgoapi.exceptions import NotLoggedInException

Expand Down Expand Up @@ -240,6 +241,7 @@ def main():
try:
bot = PokemonGoBot(config)
bot.start()
bot.metrics.capture_stats()

logger.log('Starting PokemonGo Bot....', 'green')

Expand All @@ -249,8 +251,28 @@ def main():
except KeyboardInterrupt:
logger.log('Exiting PokemonGo Bot', 'red')
finished = True
# TODO Add number of pokemon catched, pokestops visited, highest CP
# pokemon catched, etc.
if bot.metrics.start_time is None:
return # Bot didn't actually start, no metrics to show.

metrics = bot.metrics
metrics.capture_stats()
logger.log('')
logger.log('Ran for {}'.format(metrics.runtime()), 'red')
logger.log('Total XP Earned: {} Average: {:.2f}/h'.format(metrics.xp_earned, metrics.xp_per_hour()), 'red')
logger.log('Travelled {:.2f}km'.format(metrics.distance_travelled()), 'red')
logger.log('Visited {} stops'.format(metrics.visits['latest'] - metrics.visits['start']), 'red')
logger.log('Encountered {} pokemon, {} caught, {} released, {} evolved, {} never seen before'
.format(metrics.num_encounters(), metrics.num_captures(), metrics.releases,
metrics.num_evolutions(), metrics.num_new_mons()), 'red')
logger.log('Threw {} pokeball{}'.format(metrics.num_throws(), '' if metrics.num_throws() == 1 else 's'),
'red')
logger.log('Earned {} Stardust'.format(metrics.earned_dust()), 'red')
logger.log('')
if metrics.highest_cp is not None:
logger.log('Highest CP Pokemon: {}'.format(metrics.highest_cp['desc']), 'red')
if metrics.most_perfect is not None:
logger.log('Most Perfect Pokemon: {}'.format(metrics.most_perfect['desc']), 'red')


except NotLoggedInException:
logger.log('[x] Error while connecting to the server, please wait %s minutes' % config.reconnecting_timeout, 'red')
Expand Down
2 changes: 2 additions & 0 deletions pokemongo_bot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from cell_workers.utils import distance, get_cellid, encode, i2f
from human_behaviour import sleep
from item_list import Item
from metrics import Metrics
from spiral_navigator import SpiralNavigator


Expand All @@ -31,6 +32,7 @@ def __init__(self, config):
self.config = config
self.pokemon_list = json.load(open(os.path.join('data', 'pokemon.json')))
self.item_list = json.load(open(os.path.join('data', 'items.json')))
self.metrics = Metrics(self)

def start(self):
self._setup_logging()
Expand Down
3 changes: 3 additions & 0 deletions pokemongo_bot/cell_workers/pokemon_catch_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ def work(self):

id_list2 = self.count_pokemon_inventory()

self.bot.metrics.captured_pokemon(pokemon_name, cp, iv_display, pokemon_potential)

logger.log('Captured {}! [CP {}] [{}]'.format(
pokemon_name,
cp,
Expand All @@ -196,6 +198,7 @@ def work(self):

if self.config.evolve_captured:
pokemon_to_transfer = list(Set(id_list2) - Set(id_list1))
# No need to capture this even for metrics, player stats includes it.
self.api.evolve_pokemon(pokemon_id=pokemon_to_transfer[0])
response_dict = self.api.call()
status = response_dict['responses']['EVOLVE_POKEMON']['result']
Expand Down
114 changes: 114 additions & 0 deletions pokemongo_bot/metrics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import time

from datetime import timedelta


class Metrics(object):

def __init__(self, bot):
self.bot = bot
self.start_time = None
self.dust = {'start': None, 'latest': None}
self.xp = {'start': None, 'latest': None}
self.distance = {'start': None, 'latest': None}
self.encounters = {'start': None, 'latest': None}
self.throws = {'start': None, 'latest': None}
self.captures = {'start': None, 'latest': None}
self.visits = {'start': None, 'latest': None}
self.unique_mons = {'start': None, 'latest': None}
self.evolutions = {'start': None, 'latest': None}

self.releases = 0
self.highest_cp = {'cp': 0, 'desc': ''}
self.most_perfect = {'potential': 0, 'desc': ''}

def runtime(self):
return str(timedelta(seconds=round(time.time() - self.start_time)))

def xp_earned(self):
return self.xp['latest'] - self.xp['start']

def xp_per_hour(self):
return self.xp_earned/(time.time() - self.start_time/60/60)

def distance_travelled(self):
return self.distance['latest'] - self.distance['start']

def num_encounters(self):
return self.encounters['latest'] - self.encounters['start']

def num_throws(self):
return self.throws['latest'] - self.throws['start']

def num_captures(self):
return self.captures['latest'] - self.captures['start']

def num_visits(self):
return self.visits['latest'] - self.visits['start']

def num_new_mons(self):
return self.unique_mons['latest'] - self.unique_mons['start']

def num_evolutions(self):
return self.evolutions['latest'] - self.evolutions['start']

def earned_dust(self):
return self.dust['latest'] - self.dust['start']

def captured_pokemon(self, name, cp, iv_display, potential):
if cp > self.highest_cp['cp']:
self.highest_cp = \
{'cp': cp, 'desc': '{} [CP: {}] [IV: {}] Potential: {} '
.format(name, cp, iv_display, potential)}

if potential > self.most_perfect['potential']:
self.most_perfect = \
{'potential': cp, 'desc': '{} [CP: {}] [IV: {}] Potential: {} '
.format(name, cp, iv_display, potential)}
return

def released_pokemon(self, count=1):
self.releases += count

def capture_stats(self):
if self.start_time is None: self.start_time = time.time()
self.bot.api.get_inventory()
self.bot.api.get_player()
response_dict = self.bot.api.call()
try:
self.dust['latest'] = response_dict['responses']['GET_PLAYER']['player_data']['currencies'][1]['amount']
if self.dust['start'] is None: self.dust['start'] = self.dust['latest']
for item in response_dict['responses']['GET_INVENTORY']['inventory_delta']['inventory_items']:
if 'inventory_item_data' in item:
if 'player_stats' in item['inventory_item_data']:
playerdata = item['inventory_item_data']['player_stats']

self.xp['latest'] = playerdata.get('experience', 0)
if self.xp['start'] is None: self.xp['start'] = self.xp['latest']

self.visits['latest'] = playerdata.get('poke_stop_visits', 0)
if self.visits['start'] is None: self.visits['start'] = self.visits['latest']

self.captures['latest'] = playerdata.get('pokemons_captured', 0)
if self.captures['start'] is None: self.captures['start'] = self.captures['latest']

self.distance['latest'] = playerdata.get('km_walked', 0)
if self.distance['start'] is None: self.distance['start'] = self.distance['latest']

self.encounters['latest'] = playerdata.get('pokemons_encountered', 0)
if self.encounters['start'] is None: self.encounters['start'] = self.encounters['latest']

self.throws['latest'] = playerdata.get('pokeballs_thrown', 0)
if self.throws['start'] is None: self.throws['start'] = self.throws['latest']

self.unique_mons['latest'] = playerdata.get('unique_pokedex_entries', 0)
if self.unique_mons['start'] is None: self.unique_mons['start'] = self.unique_mons['latest']

self.visits['latest'] = playerdata.get('poke_stop_visits', 0)
if self.visits['start'] is None: self.visits['start'] = self.visits['latest']

self.evolutions['latest'] = playerdata.get('evolutions', 0)
if self.evolutions['start'] is None: self.evolutions['start'] = self.evolutions['latest']
except KeyError:
# Nothing we can do if there's no player info.
return