Refactor the server

This commit is contained in:
Andras Schmelczer 2026-01-31 20:25:54 +00:00
parent 3b9ad11d71
commit 01ec17ff04
15 changed files with 939 additions and 1226 deletions

View file

@ -0,0 +1,87 @@
use std::sync::Arc;
use axum::response::Json;
use serde::Serialize;
use tracing::info;
use crate::data::Histogram;
use crate::state::AppState;
#[derive(Serialize)]
#[serde(tag = "type")]
pub enum FeatureInfo {
#[serde(rename = "numeric")]
Numeric {
name: String,
label: String,
min: f64,
max: f64,
histogram: Histogram,
},
#[serde(rename = "enum")]
Enum {
name: String,
label: String,
values: Vec<String>,
},
}
#[derive(Serialize)]
pub struct FeaturesResponse {
features: Vec<FeatureInfo>,
}
fn snake_to_label(name: &str) -> String {
// If name contains '/' or uppercase, assume it's already human-readable
if name.contains('/') || name.chars().any(|c| c.is_uppercase()) {
return name.to_string();
}
name.split('_')
.map(|word| {
let mut chars = word.chars();
match chars.next() {
None => String::new(),
Some(c) => {
let mut s = c.to_uppercase().to_string();
s.extend(chars);
s
}
}
})
.collect::<Vec<_>>()
.join(" ")
}
pub async fn get_features(state: Arc<AppState>) -> Json<FeaturesResponse> {
let mut features: Vec<FeatureInfo> = state
.data
.feature_names
.iter()
.enumerate()
.map(|(i, name): (usize, &String)| {
let stats = &state.data.feature_stats[i];
FeatureInfo::Numeric {
name: name.clone(),
label: snake_to_label(name),
min: stats.p_low,
max: stats.p_high,
histogram: stats.histogram.clone(),
}
})
.collect();
for ef in &state.data.enum_features {
features.push(FeatureInfo::Enum {
name: ef.name.clone(),
label: snake_to_label(&ef.name),
values: ef.values.clone(),
});
}
info!(
numeric = features.iter().filter(|f| matches!(f, FeatureInfo::Numeric { .. })).count(),
enums = features.iter().filter(|f| matches!(f, FeatureInfo::Enum { .. })).count(),
"GET /api/features"
);
Json(FeaturesResponse { features })
}