/pokemongo_bot/walkers/polyline_generator.py

https://gitlab.com/falcao.mateus1998/PokemonGo-Bot · Python · 109 lines · 90 code · 13 blank · 6 comment · 25 complexity · 2453e6d545ea4ff55dd40e2560a82a8e MD5 · raw file

  1. import time
  2. from itertools import chain
  3. from math import ceil
  4. import haversine
  5. import polyline
  6. import requests
  7. class Polyline(object):
  8. def __init__(self, origin, destination, speed):
  9. self.DISTANCE_API_URL='https://maps.googleapis.com/maps/api/directions/json?mode=walking'
  10. self.origin = origin
  11. self.destination = destination
  12. self.URL = '{}&origin={}&destination={}'.format(self.DISTANCE_API_URL,
  13. '{},{}'.format(*self.origin),
  14. '{},{}'.format(*self.destination))
  15. self.request_responce = requests.get(self.URL).json()
  16. try:
  17. self.polyline_points = [x['polyline']['points'] for x in
  18. self.request_responce['routes'][0]['legs'][0]['steps']]
  19. except IndexError:
  20. self.polyline_points = self.request_responce['routes']
  21. self.speed = float(speed)
  22. self.points = [self.origin] + self.get_points(self.polyline_points) + [self.destination]
  23. self.lat, self.long = self.points[0][0], self.points[0][1]
  24. self.polyline = self.combine_polylines(self.points)
  25. self._timestamp = time.time()
  26. self.is_paused = False
  27. self._last_paused_timestamp = None
  28. self._paused_total = 0.0
  29. def reset_timestamps(self):
  30. self._timestamp = time.time()
  31. self.is_paused = False
  32. self._last_paused_timestamp = None
  33. self._paused_total = 0.0
  34. def get_points(self, polyline_points):
  35. crd_points = []
  36. for points in polyline_points:
  37. crd_points += polyline.decode(points)
  38. crd_points = [x for n,x in enumerate(crd_points) if x not in crd_points[:n]]
  39. return crd_points
  40. def combine_polylines(self, points):
  41. return polyline.encode(points)
  42. def pause(self):
  43. if not self.is_paused:
  44. self.is_paused = True
  45. self._last_paused_timestamp = time.time()
  46. def unpause(self):
  47. if self.is_paused:
  48. self.is_paused = False
  49. self._paused_total += time.time() - self._last_paused_timestamp
  50. self._last_paused_timestamp = None
  51. def walk_steps(self):
  52. if self.points:
  53. walk_steps = zip(chain([self.points[0]], self.points),
  54. chain(self.points, [self.points[-1]]))
  55. walk_steps = filter(None, [(o, d) if o != d else None for o, d in walk_steps])
  56. # consume the filter as list https://github.com/th3w4y/PokemonGo-Bot/issues/27
  57. return list(walk_steps)
  58. else:
  59. return []
  60. def get_pos(self):
  61. walked_distance = 0.0
  62. if not self.is_paused:
  63. time_passed = time.time()
  64. else:
  65. time_passed = self._last_paused_timestamp
  66. time_passed_distance = self.speed * abs(time_passed - self._timestamp - self._paused_total)
  67. # check if there are any steps to take https://github.com/th3w4y/PokemonGo-Bot/issues/27
  68. if self.walk_steps():
  69. steps_dict = {}
  70. for step in self.walk_steps():
  71. walked_distance += haversine.haversine(*step)*1000
  72. steps_dict[walked_distance] = step
  73. for walked_end_step in sorted(steps_dict.keys()):
  74. if walked_end_step >= time_passed_distance:
  75. break
  76. step_distance = haversine.haversine(*steps_dict[walked_end_step])*1000
  77. if walked_end_step >= time_passed_distance:
  78. percentage_walked = (time_passed_distance - (walked_end_step - step_distance)) / step_distance
  79. else:
  80. percentage_walked = 1.0
  81. return self.calculate_coord(percentage_walked, *steps_dict[walked_end_step])
  82. else:
  83. # otherwise return the destination https://github.com/th3w4y/PokemonGo-Bot/issues/27
  84. return [self.points[-1]]
  85. def calculate_coord(self, percentage, o, d):
  86. # If this is the destination then returning as such
  87. if self.points[-1] == d:
  88. return [d]
  89. else:
  90. # intermediary points returned with 5 decimals precision only
  91. # this ensures ~3-50cm ofset from the geometrical point calculated
  92. lat = o[0]+ (d[0] -o[0]) * percentage
  93. lon = o[1]+ (d[1] -o[1]) * percentage
  94. return [(round(lat, 5), round(lon, 5))]
  95. def get_total_distance(self):
  96. return ceil(sum([haversine.haversine(*x)*1000 for x in self.walk_steps()]))