Beispiel #1
0
    def find_routes(self,
                    needed_items,
                    nearby_stores,
                    max_distance,
                    use_api=True):
        """ Finds all the possible routes to purchase the needed items within the specified search radius.
            NOTE: The list of stores passed may include stores outside the search radius. This method will
            filter the list based on search radius before finding routes.
            :param needed_items: list of grocery items needed - [str]
            :param nearby_stores: list of nearby stores - [Store]
            :param max_distance: maximum distance (in miles) of stores from starting location to include in route - int
            :param use_api: whether or not to use the Supermarket API - bool
            :return a list of TripPlans sorted best to worst - [TripPlan]
        """
        # Filter the stores to only include stores with a Euclidean distance within the specified search radius
        self.stores = [
            store for store in nearby_stores if Geolocation.get_euclidean_dist(
                self.starting_location, store.location) <= max_distance
        ]

        print('Checking nearest {} stores for the needed items...'.format(
            len(self.stores)))
        # Load items at stores
        found_all_items, missing_item = StoreItemFetcher(
            use_api).check_stores_for_ingredients(needed_items, self.stores)

        if not found_all_items:
            print('Could not find item {} anywhere. Aborting.'.format(
                missing_item))
            return False, missing_item

        print('Calculating the distances between places...')
        # Get distances between places
        locations = [store.location for store in self.stores]
        locations.insert(0, self.starting_location)
        self.distance_mapper.load_distances(locations, locations)

        print('Planning...')
        base_plan = TripPlan(first_stop=self.starting_location)
        routes = self.__find_path_continuations(
            base_plan, [], needed_items,
            2 * max_distance)  # Max distance is the diameter of the circle
        # Add returning to the starting point
        for route in routes:
            dist_home = self.distance_mapper.get_distance(
                route.last_stop.location, self.starting_location)
            home_stop = TripStop(route.last_stop, None, self.starting_location,
                                 dist_home, None, 0)
            route.add_stop(home_stop)

        # Sort stores best to worst
        routes.sort(key=lambda r: r.last_stop.dist_from_start)

        return True, routes
Beispiel #2
0
def get_stores_near_me(my_loc, radius, number):
    """ Get stores within a certain radius of user location.
        :param my_loc: location of the user - Location
        :param radius: search radius (miles)
        :param number: maximum number of stores to return
    """
    sia = StoreInfoAccessor()
    stores = sia.get_stores_in_zip_range(my_loc.zipcode - 200,
                                         my_loc.zipcode + 200)

    stores_in_range = []
    euc_dists = {}
    for s in stores:
        dist = Geolocation.get_euclidean_dist(my_loc, s.location)
        if dist <= radius:
            euc_dists[s.store_id] = dist
            stores_in_range.append(s)

    # Sort according to Euclidean distance
    stores_in_range.sort(key=lambda store: euc_dists[store.store_id])

    # Return the top _number_ of stores
    return stores_in_range[:number]