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

Now track inventory when spinning a fort #3774

Merged
merged 16 commits into from
Aug 13, 2016
Merged
Show file tree
Hide file tree
Changes from 14 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ share/
# PyCharm IDE settings
.idea/
*.iml
out/

# Personal load details
src/
Expand Down
3 changes: 2 additions & 1 deletion pokemongo_bot/cell_workers/move_to_fort.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from pokemongo_bot import inventory
from pokemongo_bot.constants import Constants
from pokemongo_bot.step_walker import StepWalker
from pokemongo_bot.worker_result import WorkerResult
Expand All @@ -18,7 +19,7 @@ def initialize(self):
self.ignore_item_count = self.config.get("ignore_item_count", False)

def should_run(self):
has_space_for_loot = self.bot.has_space_for_loot()
has_space_for_loot = inventory.Items.has_space_for_loot()
if not has_space_for_loot and not self.ignore_item_count:
self.emit_event(
'inventory_full',
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 @@ -367,7 +367,7 @@ def _do_catch(self, pokemon, encounter_id, catch_rate_by_ball, is_vip=False):
'encounter_id': self.pokemon['encounter_id'],
'latitude': self.pokemon['latitude'],
'longitude': self.pokemon['longitude'],
'pokemon_id': pokemon.num
'pokemon_id': pokemon.id
}
)
if self._pct(catch_rate_by_ball[current_ball]) == 100:
Expand Down
2 changes: 1 addition & 1 deletion pokemongo_bot/cell_workers/recycle_items.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def should_run(self):
:return: True if the recycling process should be run; otherwise, False.
:rtype: bool
"""
if inventory.items().get_space_left() < (DEFAULT_MIN_EMPTY_SPACE if self.min_empty_space is None else self.min_empty_space):
if inventory.Items.get_space_left() < (DEFAULT_MIN_EMPTY_SPACE if self.min_empty_space is None else self.min_empty_space):
return True
return False

Expand Down
62 changes: 42 additions & 20 deletions pokemongo_bot/cell_workers/spin_fort.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import time

from pgoapi.utilities import f2i
from pokemongo_bot import inventory

from pokemongo_bot.constants import Constants
from pokemongo_bot.human_behaviour import sleep
Expand All @@ -14,6 +15,11 @@
from pokemongo_bot.base_dir import _base_dir
from utils import distance, format_time, fort_details

SPIN_REQUEST_RESULT_SUCCESS = 1
SPIN_REQUEST_RESULT_OUT_OF_RANGE = 2
SPIN_REQUEST_RESULT_IN_COOLDOWN_PERIOD = 3
SPIN_REQUEST_RESULT_INVENTORY_FULL = 4


class SpinFort(BaseTask):
SUPPORTED_TASK_API_VERSION = 1
Expand All @@ -22,12 +28,13 @@ def initialize(self):
self.ignore_item_count = self.config.get("ignore_item_count", False)

def should_run(self):
if not self.bot.has_space_for_loot() and not self.ignore_item_count:
has_space_for_loot = inventory.Items.has_space_for_loot()
if not has_space_for_loot and not self.ignore_item_count:
self.emit_event(
'inventory_full',
formatted="Inventory is full. You might want to change your config to recycle more items if this message appears consistently."
)
return self.ignore_item_count or self.bot.has_space_for_loot()
return self.ignore_item_count or has_space_for_loot

def work(self):
forts = self.get_forts_in_range()
Expand All @@ -50,25 +57,16 @@ def work(self):
player_latitude=f2i(self.bot.position[0]),
player_longitude=f2i(self.bot.position[1])
)
if 'responses' in response_dict and \
'FORT_SEARCH' in response_dict['responses']:
if 'responses' in response_dict and 'FORT_SEARCH' in response_dict['responses']:

spin_details = response_dict['responses']['FORT_SEARCH']
spin_result = spin_details.get('result', -1)
if spin_result == 1:
if spin_result == SPIN_REQUEST_RESULT_SUCCESS:
Copy link
Contributor

Choose a reason for hiding this comment

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

Yesss!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We should make a naming convention for these imo. I don’t like mine so if you got an idea

self.bot.softban = False
experience_awarded = spin_details.get('experience_awarded', 0)
items_awarded = spin_details.get('items_awarded', {})
if items_awarded:
self.bot.latest_inventory = None
tmp_count_items = {}
for item in items_awarded:
item_id = item['item_id']
item_name = self.bot.item_list[str(item_id)]
if not item_name in tmp_count_items:
tmp_count_items[item_name] = item['item_count']
else:
tmp_count_items[item_name] += item['item_count']


items_awarded = self.get_items_awarded_from_fort_spinned(response_dict)

if experience_awarded or items_awarded:
self.emit_event(
Expand All @@ -77,7 +75,7 @@ def work(self):
data={
'pokestop': fort_name,
'exp': experience_awarded,
'items': tmp_count_items
'items': items_awarded
}
)
else:
Expand All @@ -90,13 +88,13 @@ def work(self):
'cooldown_complete_timestamp_ms')
self.bot.fort_timeouts.update({fort["id"]: pokestop_cooldown})
self.bot.recent_forts = self.bot.recent_forts[1:] + [fort['id']]
elif spin_result == 2:
elif spin_result == SPIN_REQUEST_RESULT_OUT_OF_RANGE:
self.emit_event(
'pokestop_out_of_range',
formatted="Pokestop {pokestop} out of range.",
data={'pokestop': fort_name}
)
elif spin_result == 3:
elif spin_result == SPIN_REQUEST_RESULT_IN_COOLDOWN_PERIOD:
pokestop_cooldown = spin_details.get(
'cooldown_complete_timestamp_ms')
if pokestop_cooldown:
Expand All @@ -110,7 +108,7 @@ def work(self):
formatted="Pokestop {pokestop} on cooldown. Time left: {minutes_left}.",
data={'pokestop': fort_name, 'minutes_left': minutes_left}
)
elif spin_result == 4:
elif spin_result == SPIN_REQUEST_RESULT_INVENTORY_FULL:
if not self.ignore_item_count:
self.emit_event(
'inventory_full',
Expand Down Expand Up @@ -165,3 +163,27 @@ def get_forts_in_range(self):
) <= Constants.MAX_DISTANCE_FORT_IS_REACHABLE, forts)

return forts

def get_items_awarded_from_fort_spinned(self, response_dict):
items_awarded = response_dict['responses']['FORT_SEARCH'].get('items_awarded', {})
if items_awarded:
tmp_count_items = {}
for item_awarded in items_awarded:

item_awarded_id = item_awarded['item_id']
item_awarded_name = inventory.Items.name_for(item_awarded_id)
item_awarded_count = item_awarded['item_count']

if not item_awarded_name in tmp_count_items:
tmp_count_items[item_awarded_name] = item_awarded_count
else:
tmp_count_items[item_awarded_name] += item_awarded_count

self._update_inventory(item_awarded)

return tmp_count_items

# TODO : Refactor this class, hide the inventory update right after the api call
def _update_inventory(self, item_awarded):
inventory.items().get(item_awarded['item_id']).add(item_awarded['item_count'])

60 changes: 39 additions & 21 deletions pokemongo_bot/inventory.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,25 @@ def captured(self, pokemon_id):
return False
return self._data[pokemon_id]['times_captured'] > 0

class Item(object):
Copy link
Contributor

Choose a reason for hiding this comment

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

Didn't this just get moved below in a previous PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes someone did. Maybe for the best. But when merging conflicts I simply accepted my modified version. We need to heavily refactor this class anyway, so I didn’t take the time to move it again.

def __init__(self, item_id, item_count):
self.id = item_id
self.name = Items.name_for(self.id)
self.count = item_count

def remove(self, amount):
if self.count < amount:
raise Exception('Tried to remove more {} than you have'.format(self.name))
self.count -= amount

def add(self, amount):
if amount < 0:
raise Exception('Must add positive amount of {}'.format(self.name))
self.count += amount

def __str__(self):
return self.name + " : " + str(self.count)


class Items(_BaseInventoryComponent):
TYPE = 'item'
Expand Down Expand Up @@ -140,11 +159,23 @@ def get_space_used(cls):
def get_space_left(cls):
"""
Compute the space left in item inventory.
:return: The space left in item inventory.
: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()
return _inventory.item_inventory_size - cls.get_space_used()
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

@classmethod
def has_space_for_loot(cls):
"""
Returns a value indicating whether or not the item inventory has enough space to loot a fort
:return: True if the item inventory has enough space; otherwise, False.
:rtype: bool
"""
max_number_of_items_looted_at_stop = 5
return cls.get_space_left() >= max_number_of_items_looted_at_stop


class Pokemons(_BaseInventoryComponent):
Expand Down Expand Up @@ -479,23 +510,6 @@ def add(self, amount):
self.quantity += amount


class Item(object):
def __init__(self, item_id, item_count):
self.id = item_id
self.name = Items.name_for(self.id)
self.count = item_count

def remove(self, amount):
if self.count < amount:
raise Exception('Tried to remove more {} than you have'.format(self.name))
self.count -= amount

def add(self, amount):
if amount < 0:
raise Exception('Must add positive amount of {}'.format(self.name))
self.count += amount


class Egg(object):
def __init__(self, data):
self._data = data
Expand Down Expand Up @@ -1004,6 +1018,7 @@ def refresh(self):
user_web_inventory = os.path.join(_base_dir, 'web', 'inventory-%s.json' % (self.bot.config.username))
with open(user_web_inventory, 'w') as outfile:
json.dump(inventory, outfile)

def retrieve_item_inventory_size(self):
"""
Retrieves the item inventory size
Expand Down Expand Up @@ -1087,12 +1102,10 @@ def init_inventory(bot):
def refresh_inventory():
_inventory.refresh()


def get_item_inventory_size():
_inventory.retrieve_item_inventory_size()
return _inventory.item_inventory_size


def pokedex():
return _inventory.pokedex

Expand All @@ -1110,6 +1123,11 @@ def pokemons(refresh=False):


def items():
"""
Access to the cached item inventory
:return: Instance of the cached item inventory
:rtype: Items
"""
return _inventory.items


Expand Down