seems alright
This commit is contained in:
parent
ebe7bbb51d
commit
eac1bd0d13
58 changed files with 23125 additions and 153505 deletions
|
|
@ -1,6 +1,8 @@
|
|||
use std::collections::{HashMap, HashSet};
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::sync::{Arc, Once};
|
||||
|
||||
static OUT_OF_RANGE_WARN: Once = Once::new();
|
||||
|
||||
use axum::extract::{Query, State};
|
||||
use axum::http::StatusCode;
|
||||
|
|
@ -260,6 +262,14 @@ pub(super) fn top_filter_exclusions(
|
|||
continue;
|
||||
};
|
||||
let Some(category) = values.get(raw as usize) else {
|
||||
OUT_OF_RANGE_WARN.call_once(|| {
|
||||
warn!(
|
||||
feature = %data.feature_names[filter.feat_idx],
|
||||
raw,
|
||||
max = values.len(),
|
||||
"Enum value index out of range (logged once)"
|
||||
);
|
||||
});
|
||||
continue;
|
||||
};
|
||||
|
||||
|
|
@ -372,10 +382,10 @@ pub(super) fn top_filter_exclusions(
|
|||
.unwrap_or(f32::INFINITY);
|
||||
|
||||
let replace = path_score < current_score
|
||||
|| (path_score == current_score
|
||||
|| (path_score.total_cmp(¤t_score) == std::cmp::Ordering::Equal
|
||||
&& best_path
|
||||
.as_ref()
|
||||
.map_or(true, |current| path.len() < current.len()));
|
||||
.is_none_or(|current| path.len() < current.len()));
|
||||
if replace {
|
||||
best_path = Some(path);
|
||||
}
|
||||
|
|
@ -394,8 +404,7 @@ pub(super) fn top_filter_exclusions(
|
|||
|
||||
exclusions.sort_by(|a, b| {
|
||||
a.relative_difference
|
||||
.partial_cmp(&b.relative_difference)
|
||||
.unwrap_or(std::cmp::Ordering::Equal)
|
||||
.total_cmp(&b.relative_difference)
|
||||
.then_with(|| b.rejected_count.cmp(&a.rejected_count))
|
||||
.then_with(|| a.name.cmp(&b.name))
|
||||
});
|
||||
|
|
@ -524,6 +533,27 @@ pub async fn get_hexagon_stats(
|
|||
// for the requested journey destination (so it has journey data). Fall back
|
||||
// to geographic proximity to the hexagon center.
|
||||
let central_postcode = if !matching_rows.is_empty() {
|
||||
let center: h3o::LatLng = cell.into();
|
||||
let center_lat = center.lat() as f32;
|
||||
let center_lon = center.lng() as f32;
|
||||
let lat = state.data.lat.as_slice();
|
||||
let lon = state.data.lon.as_slice();
|
||||
let distance_sq = |row: usize| -> Option<f32> {
|
||||
match (lat.get(row), lon.get(row)) {
|
||||
(Some(&la), Some(&lo)) if la.is_finite() && lo.is_finite() => {
|
||||
Some((la - center_lat).powi(2) + (lo - center_lon).powi(2))
|
||||
}
|
||||
_ => {
|
||||
OUT_OF_RANGE_WARN.call_once(|| {
|
||||
warn!(
|
||||
"matching_rows index out of range or non-finite lat/lon (logged once)"
|
||||
);
|
||||
});
|
||||
None
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(ref travel_data) = journey_travel_data {
|
||||
// Find the row with the shortest travel time in the travel data
|
||||
let best_row = matching_rows
|
||||
|
|
@ -537,40 +567,24 @@ pub async fn get_hexagon_stats(
|
|||
.map(|(row, _)| row);
|
||||
|
||||
// Fall back to geographic center if no row has travel data
|
||||
let row = best_row.unwrap_or_else(|| {
|
||||
let center: h3o::LatLng = cell.into();
|
||||
let center_lat = center.lat() as f32;
|
||||
let center_lon = center.lng() as f32;
|
||||
let row = best_row.or_else(|| {
|
||||
matching_rows
|
||||
.iter()
|
||||
.copied()
|
||||
.min_by(|&a, &b| {
|
||||
let da = (state.data.lat[a] - center_lat).powi(2)
|
||||
+ (state.data.lon[a] - center_lon).powi(2);
|
||||
let db = (state.data.lat[b] - center_lat).powi(2)
|
||||
+ (state.data.lon[b] - center_lon).powi(2);
|
||||
da.partial_cmp(&db).unwrap_or(std::cmp::Ordering::Equal)
|
||||
})
|
||||
.expect("matching_rows is non-empty")
|
||||
.filter_map(|row| distance_sq(row).map(|d| (row, d)))
|
||||
.min_by(|a, b| a.1.total_cmp(&b.1))
|
||||
.map(|(row, _)| row)
|
||||
});
|
||||
Some(state.data.postcode(row).to_string())
|
||||
row.map(|row| state.data.postcode(row).to_string())
|
||||
} else {
|
||||
// No journey destination requested — use geographic center
|
||||
let center: h3o::LatLng = cell.into();
|
||||
let center_lat = center.lat() as f32;
|
||||
let center_lon = center.lng() as f32;
|
||||
let closest_row = matching_rows
|
||||
.iter()
|
||||
.copied()
|
||||
.min_by(|&a, &b| {
|
||||
let da = (state.data.lat[a] - center_lat).powi(2)
|
||||
+ (state.data.lon[a] - center_lon).powi(2);
|
||||
let db = (state.data.lat[b] - center_lat).powi(2)
|
||||
+ (state.data.lon[b] - center_lon).powi(2);
|
||||
da.partial_cmp(&db).unwrap_or(std::cmp::Ordering::Equal)
|
||||
})
|
||||
.expect("matching_rows is non-empty");
|
||||
Some(state.data.postcode(closest_row).to_string())
|
||||
.filter_map(|row| distance_sq(row).map(|d| (row, d)))
|
||||
.min_by(|a, b| a.1.total_cmp(&b.1))
|
||||
.map(|(row, _)| row);
|
||||
closest_row.map(|row| state.data.postcode(row).to_string())
|
||||
}
|
||||
} else {
|
||||
None
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue