def analyse(device): Cluster.objects.filter(device=device).delete() query = Location.objects.filter(device=device, sent_date_time__lt=datetime.now() - timedelta(hours=-1), accuracy__lt=THRESHOLD_ACCURACY, speed__lt=THRESHOLD_SPEED).order_by('sent_date_time') locations = [location for location in query] # Set each potential cluster with a starting point of itself for location in locations: location.points = [location] location.end_date_time = location.sent_date_time # Keep iterating through gradually decreasing number of points until there has been no change since the last iteration locations, passone = merge_points(locations) locations = [location for location in locations if (location.end_date_time - location.sent_date_time) > timedelta(seconds=THRESHOLD_MIN_TIME)] locations = sorted(locations, key=lambda location: location.sent_date_time) locations, passtwo = merge_points(locations) for location in locations: geocoder = geocoders.Google(secrets['GOOGLE']) try: cache = GeocodeCache.objects.get(location=location.location) except GeocodeCache.DoesNotExist: try: place, point = geocoder.reverse((location.location[1], location.location[0])) except IndexError: place = "Unknown location" else: if place is not None: GeocodeCache.objects.create(location=location.location, name=place) else: place = cache.name if place is None: place = 'Unknown location' c = Cluster(geocoded=place, device=device, location=location.location, speed=location.speed, altitude=location.altitude) c.save() c.locations = location.points c.save() return locations, passone, passtwo