This commit is contained in:
Andras Schmelczer 2026-04-04 17:44:44 +01:00
parent b94cf17d75
commit 0c6d207967
41 changed files with 1809 additions and 1204 deletions

View file

@ -10,13 +10,14 @@ use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
use tracing::info;
use crate::aggregation::Aggregator;
use crate::aggregation::{Aggregator, EnumDistConfig};
use crate::auth::OptionalUser;
use crate::consts::MAX_CELLS_PER_REQUEST;
use crate::data::travel_time::TravelData;
use crate::licensing::check_license_bounds;
use crate::parsing::{
bounds_intersect, parse_field_indices, parse_filters, require_bounds, row_passes_filters,
bounds_intersect, parse_enum_dist, parse_field_indices, parse_filters, require_bounds,
row_passes_filters,
};
use crate::routes::travel_time::{parse_optional_travel, TravelTimeAgg};
use crate::state::SharedState;
@ -43,6 +44,8 @@ pub struct PostcodeParams {
fields: Option<String>,
/// Pipe-separated travel time entries: `mode:slug|mode:slug:min:max`
travel: Option<String>,
/// Feature name for enum distribution counting (pie chart visualization).
enum_dist: Option<String>,
}
pub async fn get_postcodes(
@ -73,6 +76,18 @@ pub async fn get_postcodes(
let travel_entries = parse_optional_travel(params.travel.as_deref())
.map_err(|err| (StatusCode::BAD_REQUEST, err).into_response())?;
let enum_dist_config: EnumDistConfig = parse_enum_dist(
params.enum_dist.as_deref(),
&state.feature_name_to_index,
&state.data.enum_values,
)
.map_err(|err| (err.0, err.1).into_response())?;
let enum_dist_key: Option<String> = params
.enum_dist
.as_ref()
.map(|name| format!("dist_{}", name.trim()));
let response = tokio::task::spawn_blocking(move || -> Result<PostcodesResponse, String> {
let postcode_data = &state.postcode_data;
let t0 = std::time::Instant::now();
@ -129,7 +144,7 @@ pub async fn get_postcodes(
if let Some(&pc_idx) = postcode_data.postcode_to_idx.get(postcode) {
let agg = postcode_aggs
.entry(pc_idx)
.or_insert_with(|| Aggregator::new(num_features));
.or_insert_with(|| Aggregator::new(num_features, enum_dist_config));
if has_selective {
agg.add_row_selective(feature_data, row, num_features, sel_indices, &quant);
} else {
@ -272,6 +287,12 @@ pub async fn get_postcodes(
}
}
// Add enum distribution array (for pie chart visualization)
if let (Some(ref key), Some(ref ed)) = (&enum_dist_key, &aggregation.enum_dist) {
let arr: Vec<Value> = ed.counts.iter().map(|&c| Value::from(c)).collect();
props.insert(key.clone(), Value::Array(arr));
}
// Build GeoJSON Feature
let mut feature = Map::new();
feature.insert("type".into(), Value::String("Feature".into()));