mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-09-09 17:45:32 -04:00
Support aggregating local authority clusters
This applies some heuristics to try and keep the overall list of areas short when many are selected in the same wider area. Currently we only have relationship information between upper and lower tier local authorities, so we can't / won't aggregate up to Greater London (it's own special thing) or whole countries.
This commit is contained in:
@@ -1,9 +1,12 @@
|
||||
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 areas
|
||||
|
||||
|
||||
@@ -24,3 +27,39 @@ def _aggregate_wards_by_local_authority(areas):
|
||||
area.parent if area.id.startswith('wd20-')
|
||||
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 keep lone area as itself
|
||||
if len(cluster) == 1:
|
||||
results |= set(cluster)
|
||||
# aggregate multi-area cluster
|
||||
elif len(cluster) > 3:
|
||||
results |= {cluster[0].parent}
|
||||
# aggregate many small clusters
|
||||
elif len(clusters) > 1:
|
||||
area = cluster[0]
|
||||
results |= {area.parent or area}
|
||||
# keep one small cluster in full
|
||||
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.id.startswith('lad20-') and area.parent:
|
||||
result[area.parent] += [area]
|
||||
# leave countries, unitary authorities as-is
|
||||
else:
|
||||
result[area] = [area]
|
||||
|
||||
return result.values()
|
||||
|
||||
Reference in New Issue
Block a user