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

Removed the old inventory / only one call to the api #3948

Merged
merged 17 commits into from
Aug 18, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
7 changes: 7 additions & 0 deletions pokecli.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
from pgoapi.exceptions import NotLoggedInException, ServerSideRequestThrottlingException, ServerBusyOrOfflineException
from geopy.exc import GeocoderQuotaExceeded

from pokemongo_bot import inventory
from pokemongo_bot import PokemonGoBot, TreeConfigBuilder
from pokemongo_bot.base_dir import _base_dir
from pokemongo_bot.health_record import BotEvent
Expand Down Expand Up @@ -188,6 +189,12 @@ def report_summary(bot):
metrics.num_evolutions(), metrics.num_new_mons()))
logger.info('Threw {} pokeball{}'.format(metrics.num_throws(), '' if metrics.num_throws() == 1 else 's'))
logger.info('Earned {} Stardust'.format(metrics.earned_dust()))
print("##############################")
print("# #")
print("# Refreshed the inventory #")
print("# {} times #".format(inventory._inventory.refresh_count))
print("# #")
print("##############################")
logger.info('')
if metrics.highest_cp is not None:
logger.info('Highest CP Pokemon: {}'.format(metrics.highest_cp['desc']))
Expand Down
213 changes: 54 additions & 159 deletions pokemongo_bot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ def start(self):
self._setup_logging()
self._setup_api()
self._load_recent_forts()
init_inventory(self)
self._print_character_info()

random.seed()

Expand Down Expand Up @@ -702,10 +704,9 @@ def _setup_api(self):
self.login()
# chain subrequests (methods) into one RPC call

self._print_character_info()
self.api.activate_signature(self.get_encryption_lib())
self.logger.info('')
self.update_inventory()
#self.update_inventory()
Copy link
Contributor

Choose a reason for hiding this comment

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

It's probably best to just remove code rather than comment it out.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed, still got some clean up to do

# send empty map_cells and then our position
self.update_web_location()

Expand Down Expand Up @@ -735,25 +736,25 @@ def _print_character_info(self):

pokecoins = '0'
stardust = '0'
items_stock = self.current_inventory()
items_inventory = inventory.items()

if 'amount' in player['currencies'][0]:
pokecoins = player['currencies'][0]['amount']
if 'amount' in player['currencies'][1]:
stardust = player['currencies'][1]['amount']
self.logger.info('')
self.logger.info('--- {username} ---'.format(**player))
self.get_player_info()
#self.get_player_info()
self.logger.info(
'Pokemon Bag: {}/{}'.format(
self.get_inventory_count('pokemon'),
player['max_pokemon_storage']
inventory.Pokemons.get_space_used(),
inventory.get_pokemon_inventory_size()
)
)
self.logger.info(
'Items: {}/{}'.format(
self.get_inventory_count('item'),
player['max_item_storage']
inventory.Items.get_space_used(),
inventory.get_item_inventory_size()
)
)
self.logger.info(
Expand All @@ -762,116 +763,41 @@ def _print_character_info(self):
)
# Items Output
self.logger.info(
'PokeBalls: ' + str(items_stock[1]) +
' | GreatBalls: ' + str(items_stock[2]) +
' | UltraBalls: ' + str(items_stock[3]) +
' | MasterBalls: ' + str(items_stock[4]))
'PokeBalls: ' + str(items_inventory.get(1).count) +
' | GreatBalls: ' + str(items_inventory.get(2).count) +
' | UltraBalls: ' + str(items_inventory.get(3).count) +
' | MasterBalls: ' + str(items_inventory.get(4).count))

self.logger.info(
'RazzBerries: ' + str(items_stock[701]) +
' | BlukBerries: ' + str(items_stock[702]) +
' | NanabBerries: ' + str(items_stock[703]))
'RazzBerries: ' + str(items_inventory.get(701).count) +
' | BlukBerries: ' + str(items_inventory.get(702).count) +
' | NanabBerries: ' + str(items_inventory.get(703).count))

self.logger.info(
'LuckyEgg: ' + str(items_stock[301]) +
' | Incubator: ' + str(items_stock[902]) +
' | TroyDisk: ' + str(items_stock[501]))
'LuckyEgg: ' + str(items_inventory.get(301).count) +
' | Incubator: ' + str(items_inventory.get(902).count) +
' | TroyDisk: ' + str(items_inventory.get(501).count))

self.logger.info(
'Potion: ' + str(items_stock[101]) +
' | SuperPotion: ' + str(items_stock[102]) +
' | HyperPotion: ' + str(items_stock[103]) +
' | MaxPotion: ' + str(items_stock[104]))
'Potion: ' + str(items_inventory.get(101).count) +
' | SuperPotion: ' + str(items_inventory.get(102).count) +
' | HyperPotion: ' + str(items_inventory.get(103).count) +
' | MaxPotion: ' + str(items_inventory.get(104).count))

self.logger.info(
'Incense: ' + str(items_stock[401]) +
' | IncenseSpicy: ' + str(items_stock[402]) +
' | IncenseCool: ' + str(items_stock[403]))
'Incense: ' + str(items_inventory.get(401).count) +
' | IncenseSpicy: ' + str(items_inventory.get(402).count) +
' | IncenseCool: ' + str(items_inventory.get(403).count))

self.logger.info(
'Revive: ' + str(items_stock[201]) +
' | MaxRevive: ' + str(items_stock[202]))
'Revive: ' + str(items_inventory.get(201).count) +
' | MaxRevive: ' + str(items_inventory.get(202).count))

self.logger.info('')

def use_lucky_egg(self):
return self.api.use_item_xp_boost(item_id=301)

def get_inventory(self):
if self.latest_inventory is None:
self.latest_inventory = self.api.get_inventory()
return self.latest_inventory

def update_inventory(self):
# TODO: transition to using this inventory class everywhere
init_inventory(self)
response = self.get_inventory()
self.inventory = list()
inventory_items = response.get('responses', {}).get('GET_INVENTORY', {}).get(
'inventory_delta', {}).get('inventory_items', {})
if inventory_items:
for item in inventory_items:
item_info = item.get('inventory_item_data', {}).get('item', {})
if {"item_id", "count"}.issubset(set(item_info.keys())):
self.inventory.append(item['inventory_item_data']['item'])

def current_inventory(self):
inventory_req = self.get_inventory()
inventory_dict = inventory_req['responses']['GET_INVENTORY'][
'inventory_delta']['inventory_items']

user_web_inventory = os.path.join(_base_dir, 'web', 'inventory-%s.json' % self.config.username)

with open(user_web_inventory, 'w') as outfile:
json.dump(inventory_dict, outfile)

# get player items stock
# ----------------------
items_stock = {x.value: 0 for x in list(Item)}

for item in inventory_dict:
item_dict = item.get('inventory_item_data', {}).get('item', {})
item_count = item_dict.get('count')
item_id = item_dict.get('item_id')

if item_count and item_id:
if item_id in items_stock:
items_stock[item_id] = item_count
return items_stock

def item_inventory_count(self, id):
inventory_req = self.get_inventory()
inventory_dict = inventory_req['responses'][
'GET_INVENTORY']['inventory_delta']['inventory_items']

if id == 'all':
return self._all_items_inventory_count(inventory_dict)
else:
return self._item_inventory_count_per_id(id, inventory_dict)

def _item_inventory_count_per_id(self, id, inventory_dict):
item_count = 0

for item in inventory_dict:
item_dict = item.get('inventory_item_data', {}).get('item', {})
item_id = item_dict.get('item_id', False)
item_count = item_dict.get('count', False)
if item_id == int(id) and item_count:
return item_count
return 0

def _all_items_inventory_count(self, inventory_dict):
item_count_dict = {}

for item in inventory_dict:
item_dict = item.get('inventory_item_data', {}).get('item', {})
item_id = item_dict.get('item_id', False)
item_count = item_dict.get('count', False)
if item_id and item_count:
item_count_dict[item_id] = item_count

return item_count_dict

def _set_starting_position(self):

self.event_manager.emit(
Expand Down Expand Up @@ -1021,63 +947,32 @@ def update_web_location_worker(self):
self.web_update_queue.get()
self.update_web_location()

def get_inventory_count(self, what):
response_dict = self.get_inventory()
inventory_items = response_dict.get('responses', {}).get('GET_INVENTORY', {}).get(
'inventory_delta', {}).get('inventory_items', {})
if inventory_items:
pokecount = 0
itemcount = 1
for item in inventory_items:
if 'inventory_item_data' in item:
if 'pokemon_data' in item['inventory_item_data']:
pokecount += 1
itemcount += item['inventory_item_data'].get('item', {}).get('count', 0)
if 'pokemon' in what:
return pokecount
if 'item' in what:
return itemcount
return '0'

def get_player_info(self):
response_dict = self.get_inventory()
inventory_items = response_dict.get('responses', {}).get('GET_INVENTORY', {}).get(
'inventory_delta', {}).get('inventory_items', {})
if inventory_items:
pokecount = 0
itemcount = 1
for item in inventory_items:
# print('item {}'.format(item))
playerdata = item.get('inventory_item_data', {}).get('player_stats')
if playerdata:
nextlvlxp = (int(playerdata.get('next_level_xp', 0)) - int(playerdata.get('experience', 0)))

if 'level' in playerdata and 'experience' in playerdata:
self.logger.info(
'Level: {level}'.format(
**playerdata) +
' (Next Level: {} XP)'.format(
nextlvlxp) +
' (Total: {experience} XP)'
''.format(**playerdata))

if 'pokemons_captured' in playerdata and 'poke_stop_visits' in playerdata:
self.logger.info(
'Pokemon Captured: '
'{pokemons_captured}'.format(
**playerdata) +
' | Pokestops Visited: '
'{poke_stop_visits}'.format(
**playerdata))

def has_space_for_loot(self):
number_of_things_gained_by_stop = 5
enough_space = (
self.get_inventory_count('item') <
self._player['max_item_storage'] - number_of_things_gained_by_stop
)

return enough_space
# def get_player_info(self):
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we not want this anymore? I think we like printing this stuff on startup.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep we do. But I deleted the api call. So we can’t access to player stats for now.
These stats are used in the UpdateLiveStats. Gotta find a better way than having a method. Since it’s coupled with the inventory datas we should add a class which make the api call an handle the instantiation of the inventory if needed as well as facilitate the access to player infos.

# pokecount = 0
# itemcount = 1
# for item in inventory.items().all():
# # print('item {}'.format(item))
# playerdata = item.get('inventory_item_data', {}).get('player_stats')
# if playerdata:
# nextlvlxp = (int(playerdata.get('next_level_xp', 0)) - int(playerdata.get('experience', 0)))
#
# if 'level' in playerdata and 'experience' in playerdata:
# self.logger.info(
# 'Level: {level}'.format(
# **playerdata) +
# ' (Next Level: {} XP)'.format(
# nextlvlxp) +
# ' (Total: {experience} XP)'
# ''.format(**playerdata))
#
# if 'pokemons_captured' in playerdata and 'poke_stop_visits' in playerdata:
# self.logger.info(
# 'Pokemon Captured: '
# '{pokemons_captured}'.format(
# **playerdata) +
# ' | Pokestops Visited: '
# '{poke_stop_visits}'.format(
# **playerdata))

def get_forts(self, order_by_distance=False):
forts = [fort
Expand Down
7 changes: 7 additions & 0 deletions pokemongo_bot/base_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ class BaseTask(object):
TASK_API_VERSION = 1

def __init__(self, bot, config):
"""

:param bot:
:type bot: pokemongo_bot.PokemonGoBot
:param config:
:return:
"""
self.bot = bot
self.config = config
self._validate_work_exists()
Expand Down
2 changes: 1 addition & 1 deletion pokemongo_bot/cell_workers/pokemon_catch_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ def _do_catch(self, pokemon, encounter_id, catch_rate_by_ball, is_vip=False):
)

# We could refresh here too, but adding 3 saves a inventory request
candy = inventory.candies(True).get(pokemon.pokemon_id)
candy = inventory.candies().get(pokemon.pokemon_id)
Copy link
Contributor

Choose a reason for hiding this comment

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

Need to add +3 here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks

self.emit_event(
'gained_candy',
formatted='You now have {quantity} {type} candy!',
Expand Down
1 change: 0 additions & 1 deletion pokemongo_bot/cell_workers/pokemon_optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ def work(self):
evo_all = evo_all_best + evo_all_crap

self.apply_optimization(transfer_all, evo_all)
inventory.refresh_inventory()

return WorkerResult.SUCCESS

Expand Down
17 changes: 13 additions & 4 deletions pokemongo_bot/cell_workers/recycle_items.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ class RecycleItems(BaseTask):
"""
SUPPORTED_TASK_API_VERSION = 1

def __init__(self, bot, config):
"""

:param bot:
:type bot: pokemongo_bot.PokemonGoBot
:param config:
:return:
"""
super(RecycleItems, self).__init__(bot, config)

def initialize(self):
self.items_filter = self.config.get('item_filter', {})
Expand Down Expand Up @@ -78,11 +87,10 @@ def work(self):
:rtype: WorkerResult
"""

# TODO: Use new inventory everywhere and then remove this inventory update
inventory.refresh_inventory()

worker_result = WorkerResult.SUCCESS
if self.should_run():
print("Inventory BEFORE item recycling : ")
self.bot._print_character_info()

for item_in_inventory in inventory.items().all():

Expand All @@ -92,7 +100,8 @@ def work(self):
# If at any recycling process call we got an error, we consider that the result of this task is error too.
if ItemRecycler(self.bot, item_in_inventory, self.get_amount_to_recycle(item_in_inventory)).work() == WorkerResult.ERROR:
worker_result = WorkerResult.ERROR

print("Inventory AFTER item recycling : ")
self.bot._print_character_info()
return worker_result

def item_should_be_recycled(self, item):
Expand Down
3 changes: 1 addition & 2 deletions pokemongo_bot/cell_workers/transfer_pokemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ def work(self):

def _release_pokemon_get_groups(self):
pokemon_groups = {}
# TODO: Use new inventory everywhere and then remove the inventory update
for pokemon in inventory.pokemons(True).all():
for pokemon in inventory.pokemons().all():
if pokemon.in_fort or pokemon.is_favorite:
continue

Expand Down
3 changes: 2 additions & 1 deletion pokemongo_bot/cell_workers/update_live_stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,8 @@ def _get_player_stats(self):
:return: The player stats object.
:rtype: dict
"""
inventory_items = self.bot.get_inventory() \
# TODO : find a better solution than calling the api
inventory_items = self.bot.api.get_inventory() \
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Moonlight-Angel If you got any idea about it :)

Copy link
Contributor

Choose a reason for hiding this comment

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

@BriceSD I don't know if we can avoid calling the API for the player stats. Are they stored and correctly updated internally ? In which case we could use the internally stored info instead of calling the API.
If no such thing is available, then I guess the same kind of refactoring is necessary to get the player data once and update it internally.

Copy link
Contributor Author

@BriceSD BriceSD Aug 17, 2016

Choose a reason for hiding this comment

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

@Moonlight-Angel It doesn’t track player stats. After putting some thought in it, I think it shouldn’t after all. We don’t even make an api call each tick, making one hear is completely fine. The fact that it’s called get_inventory() confused me.

But what about moving these to metrics, I can see a use for them somewhere else :

        current_level = int(player_stats.get('level', 0))
        prev_level_xp = int(player_stats.get('prev_level_xp', 0))
        next_level_xp = int(player_stats.get('next_level_xp', 0))
        experience = int(player_stats.get('experience', 0))
        current_level_xp = experience - prev_level_xp
        whole_level_xp = next_level_xp - prev_level_xp

edit : we need some of them at start up.

.get('responses', {}) \
.get('GET_INVENTORY', {}) \
.get('inventory_delta', {}) \
Expand Down
Loading