mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-05-27 17:39:51 -04:00
The aggregate names don't need to be sorted, but it helps to do this for the tests, since the implementation of sets may not be stable between machines and lead to sporadic test failures. I did also toy with sorting granular area names so they have a similar ordering, but this would take them out-of-order with IDs and really the important thing is that the ordering is stable.
66 lines
1.9 KiB
Python
66 lines
1.9 KiB
Python
from collections import defaultdict
|
|
|
|
from app.broadcast_areas.models import CustomBroadcastArea
|
|
|
|
|
|
def aggregate_areas(areas):
|
|
areas = _convert_custom_areas_to_wards(areas)
|
|
areas = _aggregate_wards_by_local_authority(areas)
|
|
areas = _aggregate_lower_tier_authorities(areas)
|
|
return sorted(areas)
|
|
|
|
|
|
def _convert_custom_areas_to_wards(areas):
|
|
results = set()
|
|
|
|
for area in areas:
|
|
if type(area) == CustomBroadcastArea:
|
|
results |= set(area.overlapping_electoral_wards)
|
|
else:
|
|
results |= {area}
|
|
|
|
return results
|
|
|
|
|
|
def _aggregate_wards_by_local_authority(areas):
|
|
return {
|
|
area.parent if area.is_electoral_ward
|
|
else area for area in areas
|
|
}
|
|
|
|
|
|
def _aggregate_lower_tier_authorities(areas):
|
|
results = set()
|
|
clusters = _cluster_lower_tier_authorities(areas)
|
|
|
|
for cluster in clusters:
|
|
# always show a single area cluster as itself (aggregation isn't helpful)
|
|
if len(cluster) == 1:
|
|
results |= set(cluster)
|
|
# aggregate a single cluster with lots of areas (too complex to show in full)
|
|
elif len(cluster) > 3:
|
|
results |= {cluster[0].parent}
|
|
# if cluster is 2 or 3 areas, and there are more than 1 cluster, aggregate the cluster
|
|
elif len(clusters) > 1:
|
|
area = cluster[0]
|
|
results |= {area.parent or area}
|
|
# else keep single 2-3 areas cluster in full (easy enough to understand)
|
|
else:
|
|
results |= set(cluster)
|
|
|
|
return results
|
|
|
|
|
|
def _cluster_lower_tier_authorities(areas):
|
|
result = defaultdict(lambda: [])
|
|
|
|
for area in areas:
|
|
# group lower tier authorities by "county"
|
|
if area.is_lower_tier_local_authority:
|
|
result[area.parent] += [area]
|
|
# leave countries, unitary authorities as-is
|
|
else:
|
|
result[area] = [area]
|
|
|
|
return result.values()
|