From 9062f9a539881323c386500d16581ec9dd062c0a Mon Sep 17 00:00:00 2001 From: binarydepartment Date: Sat, 30 Jul 2016 20:17:02 +0200 Subject: [PATCH] [FEATURE] Path Navigator (#1457) Adds a navigator that walks along specified points. --- .gitignore | 2 + configs/config.json.path.example | 66 ++++++++++++++ configs/path.example.json | 9 ++ pokecli.py | 31 +++++++ pokemongo_bot/__init__.py | 9 +- pokemongo_bot/navigators/__init__.py | 2 + pokemongo_bot/navigators/path_navigator.py | 85 +++++++++++++++++++ .../{ => navigators}/spiral_navigator.py | 7 +- requirements.txt | 1 + 9 files changed, 206 insertions(+), 6 deletions(-) create mode 100644 configs/config.json.path.example create mode 100644 configs/path.example.json create mode 100644 pokemongo_bot/navigators/__init__.py create mode 100644 pokemongo_bot/navigators/path_navigator.py rename pokemongo_bot/{ => navigators}/spiral_navigator.py (95%) diff --git a/.gitignore b/.gitignore index 43ad76ae03..58f90e86e3 100644 --- a/.gitignore +++ b/.gitignore @@ -108,6 +108,8 @@ configs/* !configs/release_config.json.example !configs/config.json.pokemons.example !configs/config.json.pokemon.example +!configs/config.json.path.example +!configs/path.example.json # Virtualenv folders bin/ diff --git a/configs/config.json.path.example b/configs/config.json.path.example new file mode 100644 index 0000000000..f29ba2043f --- /dev/null +++ b/configs/config.json.path.example @@ -0,0 +1,66 @@ +{ + "auth_service": "google", + "username": "YOUR_USERNAME", + "password": "YOUR_PASSWORD", + "location": "SOME_LOCATION", + "gmapkey": "GOOGLE_MAPS_API_KEY", + "max_steps": 5, + "catch_pokemon": true, + "forts": { + "spin": true, + "move_to_spin": false, + "avoid_circles": true, + "max_circle_size": 50 + }, + "navigator": { + "type": "path", + "path_mode": "loop", + "path_file": "configs/path.example.json" + }, + "websocket_server": false, + "walk": 4.16, + "action_wait_min": 1, + "action_wait_max": 4, + "debug": false, + "test": false, + "health_record": true, + "location_cache": true, + "distance_unit": "km", + "reconnecting_timeout": 15, + "item_filter": { + "1": { "keep" : 100 }, + "101": { "keep" : 10 }, + "102": { "keep" : 30 }, + "103": { "keep" : 30 }, + "201": { "keep" : 30 }, + "701": { "keep" : 100 } + }, + "evolve_all": "NONE", + "evolve_speed": 20, + "evolve_cp_min": 300, + "use_lucky_egg": false, + "hatch_eggs": true, + "longer_eggs_first": true, + "evolve_captured": "NONE", + "release_pokemon": true, + "catch_randomize_reticle_factor": 1.0, + "catch_randomize_spin_factor": 1.0, + "catch": { + "any": {"catch_above_cp": 0, "catch_above_iv": 0, "logic": "or"}, + "// Example of always catching Rattata:": {}, + "// Rattata": { "always_catch" : true } + }, + "release": { + "any": {"release_below_cp": 0, "release_below_iv": 0, "logic": "or"}, + "// Example of always releasing Rattata:": {}, + "// Rattata": {"always_release": true}, + "// Example of keeping 3 stronger (based on CP) Pidgey:": {}, + "// Pidgey": {"keep_best_cp": 3}, + "// Example of keeping 2 stronger (based on IV) Zubat:": {}, + "// Zubat": {"keep_best_iv": 2}, + "// Also, it is working with any": {}, + "// any": {"keep_best_iv": 3}, + "// Example of keeping the 2 strongest (based on CP) and 3 best (based on IV) Zubat:": {}, + "// Zubat": {"keep_best_cp": 2, "keep_best_iv": 3} + } +} diff --git a/configs/path.example.json b/configs/path.example.json new file mode 100644 index 0000000000..06ed1bf13d --- /dev/null +++ b/configs/path.example.json @@ -0,0 +1,9 @@ +[ + {"lng":8.043531775474547,"lat":52.27777834853098}, + {"lng":8.045151829719543,"lat":52.27796214757581}, + {"lng":8.045924305915833,"lat":52.27753218790187}, + {"lng":8.045715093612671,"lat":52.27696437216979}, + {"lng":8.044642210006714,"lat":52.27692826803333}, + {"lng":8.043639063835144,"lat":52.27722694682294}, + {"lng":8.043547868728638,"lat":52.27761095945195} +] diff --git a/pokecli.py b/pokecli.py index f1af812fb9..502c50f2cd 100755 --- a/pokecli.py +++ b/pokecli.py @@ -221,6 +221,37 @@ def init_config(): type=int, default=50 ) + + add_config( + parser, + load, + short_flag="-n", + long_flag="--navigator.type", + help="Set the navigator to be used(DEFAULT spiral)", + type=str, + default='spiral' + ) + + add_config( + parser, + load, + short_flag="-pm", + long_flag="--navigator.path_mode", + help="Set the mode for the path navigator (DEFAULT loop)", + type=str, + default="loop" + ) + + add_config( + parser, + load, + short_flag="-pf", + long_flag="--navigator.path_file", + help="Set the file containing the path for the path navigator (GPX or JSON).", + type=str, + default=None + ) + add_config( parser, load, diff --git a/pokemongo_bot/__init__.py b/pokemongo_bot/__init__.py index b760e95862..0c1b9088b3 100644 --- a/pokemongo_bot/__init__.py +++ b/pokemongo_bot/__init__.py @@ -15,6 +15,7 @@ import cell_workers import logger +import navigators from api_wrapper import ApiWrapper from cell_workers.utils import distance from event_manager import EventManager @@ -23,7 +24,6 @@ from metrics import Metrics from pokemongo_bot.event_handlers import LoggingHandler, SocketIoHandler from pokemongo_bot.socketio_server.runner import SocketIoRunner -from spiral_navigator import SpiralNavigator from worker_result import WorkerResult @@ -53,7 +53,12 @@ def start(self): self._setup_logging() self._setup_api() self._setup_workers() - self.navigator = SpiralNavigator(self) + + if self.config.navigator_type == 'spiral': + self.navigator=navigators.SpiralNavigator(self) + elif self.config.navigator_type == 'path': + self.navigator=navigators.PathNavigator(self) + random.seed() def _setup_event_system(self): diff --git a/pokemongo_bot/navigators/__init__.py b/pokemongo_bot/navigators/__init__.py new file mode 100644 index 0000000000..3611385377 --- /dev/null +++ b/pokemongo_bot/navigators/__init__.py @@ -0,0 +1,2 @@ +from spiral_navigator import SpiralNavigator +from path_navigator import PathNavigator diff --git a/pokemongo_bot/navigators/path_navigator.py b/pokemongo_bot/navigators/path_navigator.py new file mode 100644 index 0000000000..0e55245e66 --- /dev/null +++ b/pokemongo_bot/navigators/path_navigator.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- + +import gpxpy +import gpxpy.gpx +import json +import pokemongo_bot.logger as logger +from pokemongo_bot.cell_workers.utils import distance, i2f, format_dist +from pokemongo_bot.human_behaviour import sleep +from pokemongo_bot.step_walker import StepWalker +from pgoapi.utilities import f2i + + +class PathNavigator(object): + + def __init__(self, bot): + self.bot = bot + self.api = bot.api + self.config = bot.config + self.ptr = 0 + self.points = self.load_path() + + def load_path(self): + if self.config.navigator_path_file == None: + raise RuntimeError('You need to specify a path file (json or gpx)') + + if self.config.navigator_path_file.endswith('.json'): + return self.load_json(self.config.navigator_path_file) + elif self.config.navigator_path_file.endswith('.gpx'): + return self.load_gpx(self.config.navigator_path_file) + + def load_json(self, file): + with open(file) as data_file: + return json.load(data_file) + + def load_gpx(self, file): + gpx_file = open(file, 'r') + gpx = gpxpy.parse(gpx_file) + + if len(gpx.tracks) == 0: + raise RuntimeError('GPX file does not cotain a track') + + points = [] + track = gpx.tracks[0] + for segment in track.segments: + for point in segment.points: + points.append({"lat": point.latitude, "lng": point.longitude}) + + return points; + + def take_step(self): + point = self.points[self.ptr] + lat = float(point['lat']) + lng = float(point['lng']) + + if self.config.walk > 0: + step_walker = StepWalker( + self.bot, + self.config.walk, + lat, + lng + ) + + is_at_destination = False + if step_walker.step(): + is_at_destination = True + + else: + self.api.set_position(lat, lng) + + dist = distance( + self.api._position_lat, + self.api._position_lng, + lat, + lng + ) + + if dist <= 1 or (self.config.walk > 0 and is_at_destination): + if (self.ptr + 1) == len(self.points): + self.ptr = 0 + if self.config.navigator_path_mode == 'linear': + self.points = list(reversed(self.points)) + else: + self.ptr += 1 + + return [lat, lng] \ No newline at end of file diff --git a/pokemongo_bot/spiral_navigator.py b/pokemongo_bot/navigators/spiral_navigator.py similarity index 95% rename from pokemongo_bot/spiral_navigator.py rename to pokemongo_bot/navigators/spiral_navigator.py index 73b3feb3b4..e91e93fbd0 100644 --- a/pokemongo_bot/spiral_navigator.py +++ b/pokemongo_bot/navigators/spiral_navigator.py @@ -1,9 +1,8 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import, unicode_literals - -from . import logger -from .cell_workers.utils import distance, format_dist -from .step_walker import StepWalker +import pokemongo_bot.logger as logger +from pokemongo_bot.cell_workers.utils import distance, format_dist +from pokemongo_bot.step_walker import StepWalker class SpiralNavigator(object): diff --git a/requirements.txt b/requirements.txt index 354382d815..77e2c732c3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,3 +16,4 @@ flask==0.11.1 socketIO_client==0.7.0 eventlet==0.19.0 universal-analytics-python==0.2.4 +gpxpy==1.1.1 \ No newline at end of file