logisheets_controller 0.6.0

the core of LogiSheets
Documentation
use super::utils::convert_f64;
use super::{CalcValue, CalcVertex};
use crate::calc_engine::calculator::math::npv::calc_npv;
use crate::calc_engine::connector::Connector;
use logisheets_parser::ast;

pub fn calc<C>(args: Vec<CalcVertex>, fetcher: &mut C) -> CalcVertex
where
    C: Connector,
{
    if args.len() <= 1 {
        return CalcVertex::from_error(ast::Error::Unspecified);
    }
    let mut iter = args.into_iter();
    let rate_vertex = iter.next().unwrap();
    let rate_value = fetcher.get_calc_value(rate_vertex);
    if let CalcValue::Scalar(v) = rate_value {
        let rate = convert_f64(v);
        match rate {
            Ok(rate) => {
                let num_vec = iter.try_fold(Vec::<f64>::new(), |mut prev, v| {
                    let value = fetcher.get_calc_value(v);
                    let nums = get_num_vec(value);
                    match nums {
                        Ok(n) => {
                            prev.extend(n);
                            Ok(prev)
                        }
                        Err(e) => Err(e),
                    }
                });
                match num_vec {
                    Ok(nums) => {
                        let result = calc_npv(rate, &nums);
                        CalcVertex::from_number(result)
                    }
                    Err(e) => CalcVertex::from_error(e),
                }
            }
            Err(e) => CalcVertex::from_error(e),
        }
    } else {
        CalcVertex::from_error(ast::Error::Unspecified)
    }
}

fn get_num_vec(value: CalcValue) -> Result<Vec<f64>, ast::Error> {
    match value {
        CalcValue::Scalar(s) => match convert_f64(s) {
            Ok(n) => Ok(vec![n]),
            Err(e) => Err(e),
        },
        CalcValue::Range(range) => {
            let r = range
                .into_iter()
                .try_fold(Vec::<f64>::new(), |mut prev, value| {
                    match convert_f64(value) {
                        Ok(num) => {
                            prev.push(num);
                            Ok(prev)
                        }
                        Err(e) => Err(e),
                    }
                })?;
            Ok(r)
        }
        CalcValue::Cube(cube) => cube
            .into_iter()
            .try_fold(Vec::<f64>::new(), |mut prev, value| {
                match convert_f64(value) {
                    Ok(num) => {
                        prev.push(num);
                        Ok(prev)
                    }
                    Err(e) => Err(e),
                }
            }),
        CalcValue::Union(union) => {
            union
                .into_iter()
                .try_fold(Vec::<f64>::new(), |mut prev, calc| {
                    match get_num_vec(*calc) {
                        Ok(v) => {
                            prev.extend(v);
                            Ok(prev)
                        }
                        Err(e) => Err(e),
                    }
                })
        }
    }
}