logisheets_controller 0.6.0

the core of LogiSheets
Documentation
use crate::calc_engine::{
    calculator::calc_vertex::{CalcValue, CalcVertex, Value},
    connector::Connector,
};
use logisheets_parser::ast;
use std::collections::BTreeMap;

pub fn calc<C>(args: Vec<CalcVertex>, fetcher: &mut C) -> CalcVertex
where
    C: Connector,
{
    let mut bmap = BTreeMap::new();
    for arg in args.into_iter() {
        let value = fetcher.get_calc_value(arg);
        if let Err(e) = count_an_arg(value, &mut bmap) {
            return CalcVertex::from_error(e);
        }
    }
    let mut max = 0;
    let mut position = 0;
    let mut result = String::from("");

    bmap.into_iter().for_each(|(k, (cnt, p))| {
        if cnt > max {
            result = k;
            max = cnt;
            position = p;
        } else if cnt == max && position > p {
            position = p;
            result = k;
        }
    });

    let num = result.parse::<f64>().unwrap();
    CalcVertex::from_number(num)
}

fn count_an_arg(
    value: CalcValue,
    bmap: &mut BTreeMap<String, (u32, usize)>,
) -> Result<(), ast::Error> {
    match value {
        CalcValue::Scalar(s) => match s {
            Value::Number(num) => {
                let s = num.to_string();
                let l = bmap.len();
                let mut insert = bmap.entry(s).or_insert((0, l));
                insert.0 += 1;
                Ok(())
            }
            Value::Error(e) => Err(e),
            _ => Err(ast::Error::Value),
        },
        CalcValue::Range(r) => {
            r.into_iter().for_each(|v| match v {
                Value::Number(num) => {
                    let s = num.to_string();
                    let l = bmap.len();
                    let mut insert = bmap.entry(s).or_insert((0, l));
                    insert.0 += 1;
                }
                _ => {}
            });
            Ok(())
        }
        CalcValue::Cube(c) => {
            c.into_iter().for_each(|v| match v {
                Value::Number(num) => {
                    let s = num.to_string();
                    let l = bmap.len();
                    let mut insert = bmap.entry(s).or_insert((0, l));
                    insert.0 += 1;
                }
                _ => {}
            });
            Ok(())
        }
        CalcValue::Union(_) => unreachable!(),
    }
}