From 91ad8dfce88a3686be25eb0e2118d6715c26fad0 Mon Sep 17 00:00:00 2001 From: Saunier Debes Brice Date: Thu, 18 Aug 2016 23:20:59 +0200 Subject: [PATCH] Removed the old inventory / only one call to the api (#3948) * Removed every call to the old inventory Added some messages to monitor item inventory Added some methods needed on the new inventory * Removed print * Removed print * Keeps track of candy on pokemon catch * Dynamically count candy gained * Rename pokemon id in pokemon unique id * Fixed typo Some clean up * Renamed pokemon id in unique_id * Now display again stats on start * Now use ultraball on non vip too * Merge branch 'dev' of https://github.com/PokemonGoF/PokemonGo-Bot into remove-old-inventory # Conflicts: # pokemongo_bot/__init__.py Now move to map use cached inventory Removed log.logger() --- pokecli.py | 1 + pokemongo_bot/__init__.py | 225 +++++------------- pokemongo_bot/base_task.py | 7 + pokemongo_bot/cell_workers/evolve_pokemon.py | 6 +- .../cell_workers/move_to_map_pokemon.py | 23 +- .../cell_workers/pokemon_catch_worker.py | 50 ++-- pokemongo_bot/cell_workers/recycle_items.py | 4 - .../cell_workers/transfer_pokemon.py | 13 +- .../cell_workers/update_live_stats.py | 3 +- pokemongo_bot/inventory.py | 77 ++++-- pokemongo_bot/services/item_recycle_worker.py | 1 + 11 files changed, 167 insertions(+), 243 deletions(-) diff --git a/pokecli.py b/pokecli.py index 381cc31d45..85f5c4a1c4 100644 --- a/pokecli.py +++ b/pokecli.py @@ -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 diff --git a/pokemongo_bot/__init__.py b/pokemongo_bot/__init__.py index f37709935e..cde856e6da 100644 --- a/pokemongo_bot/__init__.py +++ b/pokemongo_bot/__init__.py @@ -98,6 +98,11 @@ def start(self): self._setup_logging() self._setup_api() self._load_recent_forts() + init_inventory(self) + self.display_player_info() + self._print_character_info() + if self.config.pokemon_bag_show_at_start and self.config.pokemon_bag_pokemon_info: + self._print_list_pokemon() random.seed() @@ -753,12 +758,8 @@ def _setup_api(self): self.login() # chain subrequests (methods) into one RPC call - self._print_character_info() - if self.config.pokemon_bag_show_at_start and self.config.pokemon_bag_pokemon_info: - self._print_list_pokemon() self.api.activate_signature(self.get_encryption_lib()) self.logger.info('') - self.update_inventory() # send empty map_cells and then our position self.update_web_location() @@ -788,7 +789,7 @@ 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'] @@ -796,17 +797,17 @@ def _print_character_info(self): stardust = player['currencies'][1]['amount'] self.logger.info('') self.logger.info('--- {username} ---'.format(**player)) - 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( @@ -815,41 +816,39 @@ 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 _print_list_pokemon(self): - init_inventory(self) - # get pokemon list pokemon_list = inventory.pokemons().all() pokemon_list = sorted(pokemon_list, key=lambda k: k.pokemon_id) @@ -898,84 +897,6 @@ def get_poke_info(info, pokemon): 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) - - try: - with open(user_web_inventory, 'w') as outfile: - json.dump(inventory_dict, outfile) - except IOError as e: - self.logger.info('[x] Error while opening location file: %s' % e) - - # 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( @@ -1129,63 +1050,35 @@ 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 display_player_info(self): + inventory_items = self.api.get_inventory() + inventory_items = inventory_items['responses']['GET_INVENTORY']['inventory_delta']['inventory_items'] + player_stats = next((x["inventory_item_data"]["player_stats"] + for x in inventory_items + if x.get("inventory_item_data", {}).get("player_stats", {})), + None) + + if player_stats: + + nextlvlxp = (int(player_stats.get('next_level_xp', 0)) - int(player_stats.get('experience', 0))) + + if 'level' in player_stats and 'experience' in player_stats: + self.logger.info( + 'Level: {level}'.format( + **player_stats) + + ' (Next Level: {} XP)'.format( + nextlvlxp) + + ' (Total: {experience} XP)' + ''.format(**player_stats)) + + if 'pokemons_captured' in player_stats and 'poke_stop_visits' in player_stats: + self.logger.info( + 'Pokemon Captured: ' + '{pokemons_captured}'.format( + **player_stats) + + ' | Pokestops Visited: ' + '{poke_stop_visits}'.format( + **player_stats)) def get_forts(self, order_by_distance=False): forts = [fort diff --git a/pokemongo_bot/base_task.py b/pokemongo_bot/base_task.py index 1b610d31aa..e643ee7c07 100644 --- a/pokemongo_bot/base_task.py +++ b/pokemongo_bot/base_task.py @@ -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() diff --git a/pokemongo_bot/cell_workers/evolve_pokemon.py b/pokemongo_bot/cell_workers/evolve_pokemon.py index 4de40fdb7d..bb1f1d2b6f 100644 --- a/pokemongo_bot/cell_workers/evolve_pokemon.py +++ b/pokemongo_bot/cell_workers/evolve_pokemon.py @@ -85,7 +85,7 @@ def _sort_and_filter(self): } for pokemon in inventory.pokemons().all(): - if pokemon.id > 0 and pokemon.has_next_evolution() and (logic_to_function[self.cp_iv_logic](pokemon)): + if pokemon.unique_id > 0 and pokemon.has_next_evolution() and (logic_to_function[self.cp_iv_logic](pokemon)): pokemons.append(pokemon) if self.first_evolve_by == "cp": @@ -99,7 +99,7 @@ def _execute_pokemon_evolve(self, pokemon, cache): if pokemon.name in cache: return False - response_dict = self.api.evolve_pokemon(pokemon_id=pokemon.id) + response_dict = self.api.evolve_pokemon(pokemon_id=pokemon.unique_id) if response_dict.get('responses', {}).get('EVOLVE_POKEMON', {}).get('result', 0) == 1: self.emit_event( 'pokemon_evolved', @@ -115,7 +115,7 @@ def _execute_pokemon_evolve(self, pokemon, cache): ) awarded_candies = response_dict.get('responses', {}).get('EVOLVE_POKEMON', {}).get('candy_awarded', 0) inventory.candies().get(pokemon.pokemon_id).consume(pokemon.evolution_cost - awarded_candies) - inventory.pokemons().remove(pokemon.id) + inventory.pokemons().remove(pokemon.unique_id) pokemon = Pokemon(response_dict.get('responses', {}).get('EVOLVE_POKEMON', {}).get('evolved_pokemon_data', {})) inventory.pokemons().add(pokemon) sleep(self.evolve_speed) diff --git a/pokemongo_bot/cell_workers/move_to_map_pokemon.py b/pokemongo_bot/cell_workers/move_to_map_pokemon.py index a598a9f69f..8c275a2528 100644 --- a/pokemongo_bot/cell_workers/move_to_map_pokemon.py +++ b/pokemongo_bot/cell_workers/move_to_map_pokemon.py @@ -54,6 +54,8 @@ import json import base64 import requests + +from pokemongo_bot import inventory from pokemongo_bot.base_dir import _base_dir from pokemongo_bot.cell_workers.utils import distance, format_dist, format_time from pokemongo_bot.step_walker import StepWalker @@ -64,6 +66,9 @@ # Update the map if more than N meters away from the center. (AND'd with # UPDATE_MAP_MIN_TIME_MINUTES) +ULTRABALL_ID = 3 +GREATBALL_ID = 2 +POKEBALL_ID = 1 UPDATE_MAP_MIN_DISTANCE_METERS = 500 # Update the map if it hasn't been updated in n seconds. (AND'd with @@ -181,7 +186,7 @@ def update_map_location(self): except ValueError: err = 'Map location data was not valid' self._emit_failure(err) - return log.logger(err, 'red') + return dist = distance( self.bot.position[0], @@ -235,11 +240,11 @@ def dump_caught_pokemon(self): def work(self): # check for pokeballs (excluding masterball) - pokeballs = self.bot.item_inventory_count(1) - superballs = self.bot.item_inventory_count(2) - ultraballs = self.bot.item_inventory_count(3) + pokeballs_quantity = inventory.items().get(POKEBALL_ID).count + superballs_quantity = inventory.items().get(GREATBALL_ID).count + ultraballs_quantity = inventory.items().get(ULTRABALL_ID).count - if (pokeballs + superballs + ultraballs) < 1: + if (pokeballs_quantity + superballs_quantity + ultraballs_quantity) < 1: return WorkerResult.SUCCESS self.update_map_location() @@ -257,11 +262,9 @@ def work(self): pokemon = pokemon_list[0] - if pokeballs < 1: - if superballs < 1: - if ultraballs < 1: - return WorkerResult.SUCCESS - if not pokemon['is_vip']: + if pokeballs_quantity < 1: + if superballs_quantity < 1: + if ultraballs_quantity < 1: return WorkerResult.SUCCESS if self.config['snipe']: diff --git a/pokemongo_bot/cell_workers/pokemon_catch_worker.py b/pokemongo_bot/cell_workers/pokemon_catch_worker.py index 6fde60c746..b56e1b0581 100644 --- a/pokemongo_bot/cell_workers/pokemon_catch_worker.py +++ b/pokemongo_bot/cell_workers/pokemon_catch_worker.py @@ -75,10 +75,6 @@ def initialize(self): ############################################################################ def work(self, response_dict=None): - pokeballs = self.bot.item_inventory_count(1) - superballs = self.bot.item_inventory_count(2) - ultraballs = self.bot.item_inventory_count(3) - response_dict = response_dict or self.create_encounter_api_call() # validate response @@ -106,11 +102,9 @@ def work(self, response_dict=None): return WorkerResult.SUCCESS is_vip = self._is_vip_pokemon(pokemon) - if pokeballs < 1: - if superballs < 1: - if ultraballs < 1: - return WorkerResult.SUCCESS - if not is_vip: + if inventory.items().get(ITEM_POKEBALL).count < 1: + if inventory.items().get(ITEM_GREATBALL).count < 1: + if inventory.items().get(ITEM_ULTRABALL).count < 1: return WorkerResult.SUCCESS # log encounter @@ -136,11 +130,6 @@ def work(self, response_dict=None): if is_vip: self.emit_event('vip_pokemon', formatted='This is a VIP pokemon. Catch!!!') - # check for VIP pokemon - is_vip = self._is_vip_pokemon(pokemon) - if is_vip: - self.emit_event('vip_pokemon', formatted='This is a VIP pokemon. Catch!!!') - # check catch limits before catch with self.bot.database as conn: c = conn.cursor() @@ -451,9 +440,9 @@ def _do_catch(self, pokemon, encounter_id, catch_rate_by_ball, is_vip=False): if self._pct(catch_rate_by_ball[current_ball]) == 100: self.bot.softban = True - # pokemon caught! + # pokemon caught! elif catch_pokemon_status == CATCH_STATUS_SUCCESS: - pokemon.id = response_dict['responses']['CATCH_POKEMON']['captured_pokemon_id'] + pokemon.unique_id = response_dict['responses']['CATCH_POKEMON']['captured_pokemon_id'] self.bot.metrics.captured_pokemon(pokemon.name, pokemon.cp, pokemon.iv_display, pokemon.iv) try: @@ -491,21 +480,27 @@ def _do_catch(self, pokemon, encounter_id, catch_rate_by_ball, is_vip=False): except IOError as e: self.logger.info('[x] Error while opening location file: %s' % e) - # We could refresh here too, but adding 3 saves a inventory request - candy = inventory.candies(True).get(pokemon.pokemon_id) - self.emit_event( - 'gained_candy', - formatted='You now have {quantity} {type} candy!', - data = { - 'quantity': candy.quantity, - 'type': candy.type, - }, - ) + candy = inventory.candies().get(pokemon.pokemon_id) + candy.add(self.get_candy_gained_count(response_dict)) - self.bot.softban = False + self.emit_event( + 'gained_candy', + formatted='You now have {quantity} {type} candy!', + data = { + 'quantity': candy.quantity, + 'type': candy.type, + }, + ) + self.bot.softban = False break + def get_candy_gained_count(self, response_dict): + total_candy_gained = 0 + for candy_gained in response_dict['responses']['CATCH_POKEMON']['capture_award']['candy']: + total_candy_gained += candy_gained + return total_candy_gained + def generate_spin_parameter(self, throw_parameters): spin_success_rate = self.catch_throw_parameters_spin_success_rate if random() <= spin_success_rate: @@ -552,3 +547,4 @@ def generate_throw_quality_parameters(self, throw_parameters): throw_parameters['normalized_reticle_size'] = 1.25 + 0.70 * random() throw_parameters['normalized_hit_position'] = 0.0 throw_parameters['throw_type_label'] = 'OK' + diff --git a/pokemongo_bot/cell_workers/recycle_items.py b/pokemongo_bot/cell_workers/recycle_items.py index 0d9ca33fd5..1ca8bde91b 100644 --- a/pokemongo_bot/cell_workers/recycle_items.py +++ b/pokemongo_bot/cell_workers/recycle_items.py @@ -88,9 +88,6 @@ 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(): @@ -113,7 +110,6 @@ 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 - return worker_result def recycle_excess_category_max(self, category_max, category_items_list): diff --git a/pokemongo_bot/cell_workers/transfer_pokemon.py b/pokemongo_bot/cell_workers/transfer_pokemon.py index c03bbcab84..1dfad06d52 100644 --- a/pokemongo_bot/cell_workers/transfer_pokemon.py +++ b/pokemongo_bot/cell_workers/transfer_pokemon.py @@ -28,13 +28,13 @@ def work(self): if keep_best_cp >= 1: cp_limit = keep_best_cp best_cp_pokemons = sorted(group, key=lambda x: (x.cp, x.iv), reverse=True)[:cp_limit] - best_pokemon_ids = set(pokemon.id for pokemon in best_cp_pokemons) + best_pokemon_ids = set(pokemon.unique_id for pokemon in best_cp_pokemons) order_criteria = 'cp' if keep_best_iv >= 1: iv_limit = keep_best_iv best_iv_pokemons = sorted(group, key=lambda x: (x.iv, x.cp), reverse=True)[:iv_limit] - best_pokemon_ids |= set(pokemon.id for pokemon in best_iv_pokemons) + best_pokemon_ids |= set(pokemon.unique_id for pokemon in best_iv_pokemons) if order_criteria == 'cp': order_criteria = 'cp and iv' else: @@ -51,7 +51,7 @@ def work(self): best_pokemons = [] for best_pokemon_id in best_pokemon_ids: for pokemon in all_pokemons: - if best_pokemon_id == pokemon.id: + if best_pokemon_id == pokemon.unique_id: all_pokemons.remove(pokemon) best_pokemons.append(pokemon) @@ -78,8 +78,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 @@ -155,7 +154,7 @@ def release_pokemon(self, pokemon): if self.bot.config.test: candy_awarded = 1 else: - response_dict = self.bot.api.release_pokemon(pokemon_id=pokemon.id) + response_dict = self.bot.api.release_pokemon(pokemon_id=pokemon.unique_id) candy_awarded = response_dict['responses']['RELEASE_POKEMON']['candy_awarded'] except KeyError: return @@ -163,7 +162,7 @@ def release_pokemon(self, pokemon): # We could refresh here too, but adding 1 saves a inventory request candy = inventory.candies().get(pokemon.pokemon_id) candy.add(candy_awarded) - inventory.pokemons().remove(pokemon.id) + inventory.pokemons().remove(pokemon.unique_id) self.bot.metrics.released_pokemon() self.emit_event( 'pokemon_release', diff --git a/pokemongo_bot/cell_workers/update_live_stats.py b/pokemongo_bot/cell_workers/update_live_stats.py index f4f10e3762..9a5ba21fd2 100644 --- a/pokemongo_bot/cell_workers/update_live_stats.py +++ b/pokemongo_bot/cell_workers/update_live_stats.py @@ -273,7 +273,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() \ .get('responses', {}) \ .get('GET_INVENTORY', {}) \ .get('inventory_delta', {}) \ diff --git a/pokemongo_bot/inventory.py b/pokemongo_bot/inventory.py index eea820c717..2b92df647f 100644 --- a/pokemongo_bot/inventory.py +++ b/pokemongo_bot/inventory.py @@ -216,7 +216,7 @@ def get_space_left(cls): :return: The space left in item inventory. 0 if the player has more item than his item inventory can carry. :rtype: int """ - _inventory.retrieve_item_inventory_size() + _inventory.retrieve_inventories_size() space_left = _inventory.item_inventory_size - cls.get_space_used() # Space left should never be negative. Returning 0 if the computed value is negative. return space_left if space_left >= 0 else 0 @@ -259,6 +259,26 @@ def process_static_data(cls, data): return data + @classmethod + def get_space_used(cls): + """ + Counts the space used in pokemon inventory. + :return: The space used in pokemon inventory. + :rtype: int + """ + return len(_inventory.pokemons.all()) + + @classmethod + def get_space_left(cls): + """ + Compute the space left in pokemon inventory. + :return: The space left in pokemon inventory. + :rtype: int + """ + _inventory.retrieve_inventories_size() + space_left = _inventory.pokemon_inventory_size - cls.get_space_used() + return space_left + @classmethod def data_for(cls, pokemon_id): # type: (int) -> PokemonInfo @@ -303,16 +323,16 @@ def all(self): return [p for p in super(Pokemons, self).all() if not isinstance(p, Egg)] def add(self, pokemon): - if pokemon.id <= 0: + if pokemon.unique_id <= 0: raise ValueError("Can't add a pokemon without id") - if pokemon.id in self._data: + if pokemon.unique_id in self._data: raise ValueError("Pokemon already present in the inventory") - self._data[pokemon.id] = pokemon + self._data[pokemon.unique_id] = pokemon - def remove(self, pokemon_id): - if pokemon_id not in self._data: + def remove(self, pokemon_unique_id): + if pokemon_unique_id not in self._data: raise ValueError("Pokemon not present in the inventory") - self._data.pop(pokemon_id) + self._data.pop(pokemon_unique_id) # @@ -736,7 +756,7 @@ class Pokemon(object): def __init__(self, data): self._data = data # Unique ID for this particular Pokemon - self.id = data.get('id', 0) + self.unique_id = data.get('id', 0) # Id of the such pokemons in pokedex self.pokemon_id = data['pokemon_id'] # Static information @@ -1059,14 +1079,15 @@ def __init__(self, bot): self.candy = Candies() self.items = Items() self.pokemons = Pokemons() + self.refresh_count = 0 self.refresh() self.item_inventory_size = None + self.pokemon_inventory_size = None def refresh(self): - # TODO: it would be better if this class was used for all - # inventory management. For now, I'm just clearing the old inventory field - self.bot.latest_inventory = None - inventory = self.bot.get_inventory()['responses']['GET_INVENTORY']['inventory_delta']['inventory_items'] + self.refresh_count += 1 + inventory = self.bot.api.get_inventory() + inventory = inventory['responses']['GET_INVENTORY']['inventory_delta']['inventory_items'] for i in (self.pokedex, self.candy, self.items, self.pokemons): i.refresh(inventory) @@ -1077,15 +1098,17 @@ def refresh(self): except IOError as e: errmsg = '[x] Error while opening location file: user_web_inventory' - def retrieve_item_inventory_size(self): + def retrieve_inventories_size(self): """ Retrieves the item inventory size :return: Nothing. :rtype: None """ - # TODO: Force update of _item_inventory_size if the player upgrades its size - if self.item_inventory_size is None: - self.item_inventory_size = self.bot.api.get_player()['responses']['GET_PLAYER']['player_data']['max_item_storage'] + # TODO: Force update of it if the player upgrades its size + if self.item_inventory_size is None or self.pokemon_inventory_size is None: + player_data = self.bot.api.get_player()['responses']['GET_PLAYER']['player_data'] + self.item_inventory_size = player_data['max_item_storage'] + self.pokemon_inventory_size = player_data['max_pokemon_storage'] # @@ -1180,39 +1203,43 @@ def get_item_inventory_size(): :return: Item inventory size. :rtype: int """ - _inventory.retrieve_item_inventory_size() + _inventory.retrieve_inventories_size() return _inventory.item_inventory_size +def get_pokemon_inventory_size(): + """ + Access to the Item inventory size. + :return: Item inventory size. + :rtype: int + """ + _inventory.retrieve_inventories_size() + return _inventory.pokemon_inventory_size + def pokedex(): """ :return: :rtype: Pokedex """ + # Are new pokemons added to the pokedex ? return _inventory.pokedex -def candies(refresh=False): +def candies(): """ - :param refresh: :return: :rtype: Candies """ - if refresh: - refresh_inventory() return _inventory.candy -def pokemons(refresh=False): +def pokemons(): """ - :param refresh: :return: :rtype: Pokemons """ - if refresh: - refresh_inventory() return _inventory.pokemons diff --git a/pokemongo_bot/services/item_recycle_worker.py b/pokemongo_bot/services/item_recycle_worker.py index aa02b366a2..c34d8bb08c 100644 --- a/pokemongo_bot/services/item_recycle_worker.py +++ b/pokemongo_bot/services/item_recycle_worker.py @@ -13,6 +13,7 @@ def __init__(self, bot, item_to_recycle, amount_to_recycle): """ Initialise an instance of ItemRecycler :param bot: The instance of the Bot + :type bot: pokemongo_bot.PokemonGoBot :param item_to_recycle: The item to recycle :type item_to_recycle: inventory.Item :param amount_to_recycle: The amount to recycle