logisheets_controller/calc_engine/calculator/funcs/
mode.rs

1use crate::calc_engine::{
2    calculator::calc_vertex::{CalcValue, CalcVertex, Value},
3    connector::Connector,
4};
5use logisheets_parser::ast;
6use std::collections::BTreeMap;
7
8pub fn calc<C>(args: Vec<CalcVertex>, fetcher: &mut C) -> CalcVertex
9where
10    C: Connector,
11{
12    let mut bmap = BTreeMap::new();
13    for arg in args.into_iter() {
14        let value = fetcher.get_calc_value(arg);
15        if let Err(e) = count_an_arg(value, &mut bmap) {
16            return CalcVertex::from_error(e);
17        }
18    }
19    let mut max = 0;
20    let mut position = 0;
21    let mut result = String::from("");
22
23    bmap.into_iter().for_each(|(k, (cnt, p))| {
24        if cnt > max {
25            result = k;
26            max = cnt;
27            position = p;
28        } else if cnt == max && position > p {
29            position = p;
30            result = k;
31        }
32    });
33
34    let num = result.parse::<f64>().unwrap();
35    CalcVertex::from_number(num)
36}
37
38fn count_an_arg(
39    value: CalcValue,
40    bmap: &mut BTreeMap<String, (u32, usize)>,
41) -> Result<(), ast::Error> {
42    match value {
43        CalcValue::Scalar(s) => match s {
44            Value::Number(num) => {
45                let s = num.to_string();
46                let l = bmap.len();
47                let insert = bmap.entry(s).or_insert((0, l));
48                insert.0 += 1;
49                Ok(())
50            }
51            Value::Error(e) => Err(e),
52            _ => Err(ast::Error::Value),
53        },
54        CalcValue::Range(r) => {
55            r.into_iter().for_each(|v| match v {
56                Value::Number(num) => {
57                    let s = num.to_string();
58                    let l = bmap.len();
59                    let insert = bmap.entry(s).or_insert((0, l));
60                    insert.0 += 1;
61                }
62                _ => {}
63            });
64            Ok(())
65        }
66        CalcValue::Cube(c) => {
67            c.into_iter().for_each(|v| match v {
68                Value::Number(num) => {
69                    let s = num.to_string();
70                    let l = bmap.len();
71                    let insert = bmap.entry(s).or_insert((0, l));
72                    insert.0 += 1;
73                }
74                _ => {}
75            });
76            Ok(())
77        }
78        CalcValue::Union(_) => unreachable!(),
79    }
80}