use perspective_client::View;
use perspective_client::config::{ColumnType, Scalar};
use perspective_js::utils::ApiFuture;
use crate::session::{Session, SessionMetadata};
fn scalar_to_f64(s: &Scalar) -> Option<f64> {
match s {
Scalar::Float(x) => Some(*x),
_ => None,
}
}
pub fn min_max_to_abs_max(min: &Scalar, max: &Scalar) -> Option<f64> {
let min = scalar_to_f64(min)?;
let max = scalar_to_f64(max)?;
Some(min.abs().max(max.abs()))
}
pub fn is_numeric_column(metadata: &SessionMetadata, col_name: &str) -> bool {
matches!(
metadata.get_column_view_type(col_name),
Some(ColumnType::Integer | ColumnType::Float)
)
}
pub async fn resolve_abs_max(
session: &Session,
metadata: &SessionMetadata,
view: Option<&View>,
col_name: &str,
) -> Option<f64> {
if let Some(stats) = session.get_column_stats(col_name)
&& let Some(v) = stats.abs_max
{
return Some(v);
}
if !is_numeric_column(metadata, col_name) {
return None;
}
let view = view?;
let (min, max) = view.get_min_max(col_name.to_string()).await.ok()?;
let v = min_max_to_abs_max(&min, &max)?;
session.set_column_abs_max(col_name.to_string(), v);
Some(v)
}
pub fn fetch_column_abs_max(session: &Session, column_name: String) {
let session = session.clone();
ApiFuture::spawn(async move {
let metadata = session.metadata().clone();
let view = session.get_view();
resolve_abs_max(&session, &metadata, view.as_ref(), &column_name).await;
Ok::<_, perspective_js::utils::ApiError>(())
});
}