def _parse_utfgrid(self, json_grid): """Parse geocache coordinates from UTFGrid Consume json-decoded UTFGrid data from MechanicalSoup browser. Calculate waypoint coordinates and return generator object of Cache instances. Geocaching.com UTFGrids do not follow UTFGrid specification [2] in grid contents and key values. List "grid" contains valid code pixels that are individual, but list "keys" contain a list of coordinates as "(x, y)" for points where there are geocaches on the grid. Code pixels can however be decoded to produce index of coordinate point in list "keys". Grid resolution is 64x64 and coordinates run from northwest corner. Dictionary "data" has key-value pairs, where keys are same coordinates as previously described and values are lists of dictionaries each containing geocache waypoint code and name in form {"n": name, "i": waypoint}. Waypoints seem to appear nine times each, if the cache is not cut out from edges. [2] https://github.com/mapbox/utfgrid-spec""" logging.debug("Parsing UTFGrid") caches = {} # {waypoint: [<Cache>, <GridCoordinateBlock>]} size = len(json_grid["grid"]) assert len(json_grid["grid"][1]) == size # square grid if size != self.size: logging.warning("GC.com UTFGrid specs seem to have changed: " "grid resolution is not 64!") self.size = size caches = {} for coordinate_key in json_grid["data"]: cache_list = json_grid["data"][coordinate_key] x_i, y_i = (int(i) for i in coordinate_key.strip(" ()").split(",")) # Store all caches to dictionary for cache_dic in cache_list: waypoint = cache_dic["i"] # Store all found coordinate points if waypoint not in caches: c = Cache(waypoint, self._gc, name=cache_dic["n"]) caches[waypoint] \ = [c, GridCoordinateBlock(self, (x_i, y_i),)] else: caches[waypoint][1].add((x_i, y_i)) # Try to determine grid coordinate block size GridCoordinateBlock.determine_block_size( *[len(caches[wp][1].points) for wp in caches]) # Calculate geocache coordinates and yield objects for waypoint in caches: c, coord_block = caches[waypoint] c.location = coord_block.get_location() yield c logging.info("Found {} caches".format(len(caches)))
def _parse_utfgrid(self, json_grid): """Parse geocache coordinates from UTFGrid Consume json-decoded UTFGrid data from MechanicalSoup browser. Calculate waypoint coordinates and return generator object of Cache instances. Geocaching.com UTFGrids do not follow UTFGrid specification [2] in grid contents and key values. List "grid" contains valid code pixels that are individual, but list "keys" contain a list of coordinates as "(x, y)" for points where there are geocaches on the grid. Code pixels can however be decoded to produce index of coordinate point in list "keys". Grid resolution is 64x64 and coordinates run from northwest corner. Dictionary "data" has key-value pairs, where keys are same coordinates as previously described and values are lists of dictionaries each containing geocache waypoint code and name in form {"n": name, "i": waypoint}. Waypoints seem to appear nine times each, if the cache is not cut out from edges. [2] https://github.com/mapbox/utfgrid-spec""" logging.debug("Parsing UTFGrid") caches = {} # {waypoint: [<Cache>, <GridCoordinateBlock>]} size = len(json_grid["grid"]) assert len(json_grid["grid"][1]) == size # square grid if size != self.size: logging.warning("GC.com UTFGrid specs seem to have changed: " "grid resolution is not 64!") self.size = size caches = {} for coordinate_key in json_grid["data"]: cache_list = json_grid["data"][coordinate_key] x_i, y_i = (int(i) for i in coordinate_key.strip(" ()").split(",")) # Store all caches to dictionary for cache_dic in cache_list: waypoint = cache_dic["i"] # Store all found coordinate points if waypoint not in caches: c = Cache(waypoint, self._gc, name=cache_dic["n"]) caches[waypoint] = [c, GridCoordinateBlock(self, (x_i, y_i))] else: caches[waypoint][1].add((x_i, y_i)) # Try to determine grid coordinate block size GridCoordinateBlock.determine_block_size(*[len(caches[wp][1].points) for wp in caches]) # Calculate geocache coordinates and yield objects for waypoint in caches: c, coord_block = caches[waypoint] c.location = coord_block.get_location() yield c logging.info("Found {} caches".format(len(caches)))