def get_metadata(self, request, ptypes, entity=None): context = NearbyDetailView.initial_context(self, request, ptypes, entity) if len(context['entity_types']) == 0: return { 'exclude_from_search': True, 'title': _('Things near %(title)s') % {'title': entity.title} } et_name = capfirst(context['entity_types'][0].verbose_name_plural) if entity is not None: title = _('%(entity_type)s near %(entity)s') % { 'entity_type':et_name, 'title': entity.title } else: title = _('%(et)s nearby') % {'et': et_name} if len(context['entity_types']) > 1: return { 'exclude_from_search': True, 'title': title} number = len([e for e in context['entities'] if haversine(e.location, context['point']) <= 1000]) entity_type = context['entity_types'][0].verbose_name_plural return { 'title': title, 'additional': _('<strong>%(number)d %(entity_type)s</strong> within 1km') \ % {'number': number, 'entity_type': entity_type} }
def get_metadata(self, request, ptypes, entity=None): context = NearbyDetailView.initial_context(self, request, ptypes, entity) if len(context['entity_types']) == 0: return { 'exclude_from_search': True, 'title': _('Things near %(title)s') % { 'title': entity.title } } et_name = capfirst(context['entity_types'][0].verbose_name_plural) if entity is not None: title = _('%(entity_type)s near %(entity)s') % { 'entity_type': et_name, 'title': entity.title } else: title = _('%(et)s nearby') % {'et': et_name} if len(context['entity_types']) > 1: return {'exclude_from_search': True, 'title': title} number = len([ e for e in context['entities'] if haversine(e.location, context['point']) <= 1000 ]) entity_type = context['entity_types'][0].verbose_name_plural return { 'title': title, 'additional': _('<strong>%(number)d %(entity_type)s</strong> within 1km') \ % {'number': number, 'entity_type': entity_type} }
def set_location(self, request, name, location, accuracy, method, with_history=False): request.session['geolocation:location'] = location request.session['geolocation:updated'] = datetime.utcnow() request.session['geolocation:name'] = name request.session['geolocation:method'] = method request.session['geolocation:accuracy'] = accuracy if not with_history: return if isinstance(location, list): location = tuple(location) last_updated = request.session.get('geolocation:updated', datetime(1970, 1, 1)) try: last_location = Point(request.session['geolocation:location']) distance_moved = haversine(last_location, Point(location)) except KeyError: distance_moved = float('inf') if method in ('other', 'manual', 'geocoded', 'html5request') or \ not 'geolocation:location' in request.session or \ (last_updated > datetime.utcnow() - timedelta(seconds=3600) and distance_moved > 250): self.add_to_history(request, name, location, accuracy, method)
def h(*args, **kwargs): args = getargsfunc(*args, **kwargs) app = get_app('molly.geolocation', args.pop('local_name', None)) try: geocode = Geocode.recent.get(local_name=app.local_name, **args) logger.debug('Found cached geocode') return geocode.results except Geocode.DoesNotExist: logger.debug('Geocode not found in cache') pass except Geocode.MultipleObjectsReturned: Geocode.recent.filter(local_name=app.local_name, **args).delete() results = f(providers=app.providers, **args) i = 0 while i < len(results): loc, name = Point(results[i]['location']), results[i]['name'] if any((r['name'] == name and haversine(Point(r['location']), loc) < 100) for r in results[:i]): results[i:i + 1] = [] else: i += 1 if hasattr(app, 'prefer_results_near'): point = Point(app.prefer_results_near[:2]) distance = app.prefer_results_near[2] filtered_results = [ result for result in results if haversine(Point(result['location']), point) <= distance ] if filtered_results: results = filtered_results try: geocode, created = Geocode.objects.get_or_create( local_name=app.local_name, **args) except Geocode.MultipleObjectsReturned: Geocode.objects.filter(local_name=app.local_name, **args).delete() geocode, created = Geocode.objects.get_or_create( local_name=app.local_name, **args) geocode.results = results geocode.save() return results
def get_distance_and_bearing_from(self, point): """ Returns a distance and compass direction from current Entity to another point """ if point is None or not self.location: return None, None return haversine(point, self.location), self.get_bearing(point)
def h(*args, **kwargs): args = getargsfunc(*args, **kwargs) app = get_app('molly.geolocation', args.pop('local_name', None)) try: geocode = Geocode.recent.get(local_name=app.local_name, **args) logger.debug('Found cached geocode') return geocode.results except Geocode.DoesNotExist: logger.debug('Geocode not found in cache') pass except Geocode.MultipleObjectsReturned: Geocode.recent.filter(local_name=app.local_name, **args).delete() results = f(providers=app.providers, **args) i = 0 while i < len(results): loc, name = Point(results[i]['location']), results[i]['name'] if any((r['name'] == name and haversine(Point(r['location']), loc) < 100) for r in results[:i]): results[i:i+1] = [] else: i += 1 if hasattr(app, 'prefer_results_near'): point = Point(app.prefer_results_near[:2]) distance = app.prefer_results_near[2] filtered_results = [ result for result in results if haversine(Point(result['location']), point) <= distance] if filtered_results: results = filtered_results try: geocode, created = Geocode.objects.get_or_create( local_name=app.local_name, **args) except Geocode.MultipleObjectsReturned: Geocode.objects.filter(local_name=app.local_name, **args).delete() geocode, created = Geocode.objects.get_or_create( local_name=app.local_name, **args) geocode.results = results geocode.save() return results
def handle_GET(self, request, context, control_number): # Build a map of all the libraries that have this book, with markers # corresponding to colours user_location = request.session.get('geolocation:location') points = [] point_libraries = [] lbs = context['item'].libraries.items() for library, books in lbs: library.entity = library.get_entity() if user_location: lbs = sorted(lbs, key=lambda (l, b): (haversine(user_location, l.entity.location) if l.entity and l.entity.location else float('inf'))) for library, books in lbs: if library.entity != None and library.entity.location != None: colour = AVAIL_COLORS[max(b['availability'] for b in books)] points.append( (library.entity.location[0], library.entity.location[1], colour, library.entity.title)) point_libraries.append(library) if len(points) > 0: context['map'] = Map( centre_point=(user_location[0], user_location[1], 'green', '') if user_location != None else None, points=points, min_points=0 if context['zoom'] else len(points), zoom=context['zoom'], width=request.map_width, height=request.map_height, ) # Yes, this is weird. fit_to_map() groups libraries with the same # location so here we add a marker_number to each library to display # in the template. lib_iter = iter(point_libraries) for i, (a, b) in enumerate(context['map'].points): for j in range(len(b)): lib_iter.next().marker_number = i + 1 context.update({ 'sorted_libraries': lbs, }) return self.render(request, context, 'library/item_detail')
def handle_GET(self, request, context, control_number): # Build a map of all the libraries that have this book, with markers # corresponding to colours user_location = request.session.get('geolocation:location') points = [] point_libraries = [] lbs = context['item'].libraries.items() for library, books in lbs: library.entity = library.get_entity() if user_location: lbs = sorted(lbs, key=lambda (l,b): haversine(user_location, l.entity.location)) for library, books in lbs: if library.entity != None and library.entity.location != None: colour = AVAIL_COLORS[max(b['availability'] for b in books)] points.append((library.entity.location[0], library.entity.location[1], colour, library.entity.title)) point_libraries.append(library) if len(points) > 0: context['map'] = Map( centre_point = (user_location[0], user_location[1], 'green', '') if user_location != None else None, points = points, min_points = 0 if context['zoom'] else len(points), zoom = context['zoom'], width = request.map_width, height = request.map_height, ) # Yes, this is weird. fit_to_map() groups libraries with the same # location so here we add a marker_number to each library to display # in the template. lib_iter = iter(point_libraries) for i, (a,b) in enumerate(context['map'].points): for j in range(len(b)): lib_iter.next().marker_number = i + 1 context.update({ 'sorted_libraries': lbs, }) return self.render(request, context, 'library/item_detail')
def optimise_points(points): """ This algorithm takes some points and then tries to figure out the shortest route between them. It uses "as the crow flies" distance, which may not necessarily be the best. Points should be a list of tuples, where the first element is the object and the second element is the location of that object (first element is ignored by this algorithm, but is useful for you to correlate the resulting order with your original). This assumes that the first point is always the starting point of the user """ if len(points) > 10: raise NotImplementedError() distances = {} for e, x in points: for e, y in points: distances[(x, y)] = haversine(x, y) def tsp_recurse(current, remaining): weights = [] for point in remaining: path = [point[0]] weight = distances[(current, point[1])] next = set(remaining) next.remove(point) if next: path_r, weight_r = tsp_recurse(point[1], next) weight += weight_r path += path_r weights.append((path, weight)) return min(weights, key=itemgetter(1)) path, weight = tsp_recurse(points[0][1], set(points[1:])) return [points[0][0]] + path
def optimise_points(points): """ This algorithm takes some points and then tries to figure out the shortest route between them. It uses "as the crow flies" distance, which may not necessarily be the best. Points should be a list of tuples, where the first element is the object and the second element is the location of that object (first element is ignored by this algorithm, but is useful for you to correlate the resulting order with your original). This assumes that the first point is always the starting point of the user """ if len(points) > 10: raise NotImplementedError() distances = {} for e, x in points: for e, y in points: distances[(x,y)] = haversine(x, y) def tsp_recurse(current, remaining): weights = [] for point in remaining: path = [point[0]] weight = distances[(current, point[1])] next = set(remaining) next.remove(point) if next: path_r, weight_r = tsp_recurse(point[1], next) weight += weight_r path += path_r weights.append((path, weight)) return min(weights, key=itemgetter(1)) path, weight = tsp_recurse(points[0][1], set(points[1:])) return [points[0][0]] + path