Refactor and improve

This commit is contained in:
Andras Schmelczer 2026-02-03 20:26:57 +00:00
parent 1f148b2185
commit 242acff987
22 changed files with 754 additions and 1053 deletions

View file

@ -4,11 +4,11 @@ use axum::response::Json;
use serde::Serialize;
use tracing::info;
use crate::data::Histogram;
use crate::data::{Histogram, PropertyData};
use crate::features::{ENUM_FEATURE_GROUPS, FEATURE_GROUPS};
use crate::state::AppState;
#[derive(Serialize)]
#[derive(Clone, Serialize)]
#[serde(tag = "type")]
pub enum FeatureInfo {
#[serde(rename = "numeric")]
@ -32,18 +32,19 @@ pub enum FeatureInfo {
},
}
#[derive(Serialize)]
#[derive(Clone, Serialize)]
pub struct FeatureGroupResponse {
name: String,
features: Vec<FeatureInfo>,
}
#[derive(Serialize)]
#[derive(Clone, Serialize)]
pub struct FeaturesResponse {
groups: Vec<FeatureGroupResponse>,
pub groups: Vec<FeatureGroupResponse>,
}
pub async fn get_features(state: Arc<AppState>) -> Json<FeaturesResponse> {
/// Build the features response at startup. Called once and cached in AppState.
pub fn build_features_response(data: &PropertyData) -> FeaturesResponse {
// Collect all group names in order, merging numeric and enum groups with the same name
let mut group_names: Vec<&str> = Vec::new();
for feature_group in FEATURE_GROUPS {
@ -66,13 +67,12 @@ pub async fn get_features(state: Arc<AppState>) -> Json<FeaturesResponse> {
for feature_group in FEATURE_GROUPS {
if feature_group.name == group_name {
for feature_config in feature_group.features {
if let Some(feat_idx) = state
.data
if let Some(feat_idx) = data
.feature_names
.iter()
.position(|feat_name| feat_name == feature_config.name)
{
let stats = &state.data.feature_stats[feat_idx];
let stats = &data.feature_stats[feat_idx];
features.push(FeatureInfo::Numeric {
name: feature_config.name.to_string(),
min: stats.slider_min,
@ -92,19 +92,22 @@ pub async fn get_features(state: Arc<AppState>) -> Json<FeaturesResponse> {
for enum_group in ENUM_FEATURE_GROUPS {
if enum_group.name == group_name {
for enum_config in enum_group.features {
if let Some(enum_feature) = state
.data
.enum_features
// Find the feature index by name
if let Some(feat_idx) = data
.feature_names
.iter()
.find(|enum_feat| enum_feat.name == enum_config.name)
.position(|name| name == enum_config.name)
{
features.push(FeatureInfo::Enum {
name: enum_config.name.to_string(),
values: enum_feature.values.clone(),
description: enum_config.description,
detail: enum_config.detail,
source: enum_config.source,
});
// Check if this feature has enum values
if let Some(values) = data.enum_values.get(&feat_idx) {
features.push(FeatureInfo::Enum {
name: enum_config.name.to_string(),
values: values.clone(),
description: enum_config.description,
detail: enum_config.detail,
source: enum_config.source,
});
}
}
}
}
@ -118,22 +121,10 @@ pub async fn get_features(state: Arc<AppState>) -> Json<FeaturesResponse> {
}
}
let num_numeric: usize = groups
.iter()
.flat_map(|group| &group.features)
.filter(|feature| matches!(feature, FeatureInfo::Numeric { .. }))
.count();
let num_enum: usize = groups
.iter()
.flat_map(|group| &group.features)
.filter(|feature| matches!(feature, FeatureInfo::Enum { .. }))
.count();
info!(
numeric = num_numeric,
enums = num_enum,
groups = groups.len(),
"GET /api/features"
);
Json(FeaturesResponse { groups })
FeaturesResponse { groups }
}
pub async fn get_features(state: Arc<AppState>) -> Json<FeaturesResponse> {
info!("GET /api/features");
Json(state.features_response.clone())
}