def find_by_distance(self, election_id, search_point, distance_threshold_km, limit): from demsausage.app.models import PollingPlaces return find_by_distance( search_point, distance_threshold_km, limit, PollingPlaces.objects.filter(election_id=election_id, status=PollingPlaceStatus.ACTIVE))
def safe_find_by_distance(self, label, *args, **kwargs): results = find_by_distance(*args, **kwargs) count = results.count() if count >= 2: self.logger.error("Find by distance [{}]: Found {} existing polling places spatially near each other. Polling places: {}".format(label, count, "; ".join(["{}/{}/{}".format(pp.name, pp.premises, pp.address) for pp in results]))) return results
def filter(self, qs, value): if value not in (None, ""): from django.contrib.gis.geos import Point from demsausage.app.sausage.polling_places import find_by_distance try: lon, lat = [float(v) for v in value[0:1000].split(",")] search_point = Point(float(lon), float(lat), srid=4326) except Exception as e: raise BadRequest(e) polling_places_filter = find_by_distance(search_point, distance_threshold_km=50, limit=15, qs=qs) if polling_places_filter.count() == 0: polling_places_filter = find_by_distance( search_point, distance_threshold_km=1000, limit=15, qs=qs) return polling_places_filter return qs
def detect_facility_type(self): update_count = 0 queryset = PollingPlaces.objects.filter(election=self.election, status=PollingPlaceStatus.ACTIVE, facility_type__isnull=True) facility_type_queryset = PollingPlaces.objects.filter(status=PollingPlaceStatus.ACTIVE, facility_type__isnull=False).exclude(election=self.election) for polling_place in queryset: most_recent_facility_type = find_by_distance(polling_place.geom, 0.2, limit=None, qs=facility_type_queryset).order_by("election_id").last() if most_recent_facility_type is not None: polling_place.facility_type_id = most_recent_facility_type.facility_type_id polling_place.save() update_count += 1 self.logger.info("Facility types detected from historical data: {}".format(update_count))
def calculate_chance_of_sausage(self): def calculate_score(polling_places): def _is_a_positive_report(polling_place): return is_noms_item_true(polling_place, "bbq") or is_noms_item_true(polling_place, "cake") def _has_multiple_positive_reports(polling_places): count = 0 for polling_place in polling_places: if _is_a_positive_report(polling_place) is True: count += 1 if count >= 2: return True return False def _has_one_positive_report(polling_places): for polling_place in polling_places: if _is_a_positive_report(polling_place) is True: return True return False def _has_a_red_cross_of_shame(polling_places): for polling_place in polling_places: if is_noms_item_true(polling_place, "nothing") is True: return True return False def _has_multiple_red_crosses_of_shame(polling_places): count = 0 for polling_place in polling_places: if is_noms_item_true(polling_place, "nothing") is True: count += 1 if count >= 2: return True return False if _has_multiple_red_crosses_of_shame(polling_places) is True: if _has_one_positive_report(polling_places) is True: return PollingPlaceChanceOfSausage.MIXED return PollingPlaceChanceOfSausage.UNLIKELY elif _has_multiple_positive_reports(polling_places) is True: if _has_a_red_cross_of_shame(polling_places) is True: return PollingPlaceChanceOfSausage.MIXED return PollingPlaceChanceOfSausage.STRONG elif _has_one_positive_report(polling_places) is True: if _has_a_red_cross_of_shame(polling_places) is True: return PollingPlaceChanceOfSausage.MIXED return PollingPlaceChanceOfSausage.FAIR else: return PollingPlaceChanceOfSausage.NO_IDEA update_count = 0 queryset = PollingPlaces.objects.filter(election=self.election, status=PollingPlaceStatus.ACTIVE, noms__isnull=True) for polling_place in queryset: matching_polling_places = find_by_distance(polling_place.geom, 0.2, limit=None, qs=PollingPlaces.objects.filter(status=PollingPlaceStatus.ACTIVE).exclude(election=self.election)).order_by("election_id") if len(matching_polling_places) > 0: polling_place.chance_of_sausage = calculate_score(matching_polling_places) polling_place.save() update_count += 1 self.logger.info("Chance of Sausage calculations completed: Considered = {}; Updated = {}".format(queryset.count(), update_count))