1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
use super::condition::{
get_condition_value, match_condition, parse_condition, Condition, LogicalCondition, Op,
};
use crate::calc_engine::connector::Connector;
use logisheets_parser::ast;
use super::{CalcValue, CalcVertex, Value};
pub fn calc<C>(args: Vec<CalcVertex>, fetcher: &mut C) -> CalcVertex
where
C: Connector,
{
if args.len() != 2 {
return CalcVertex::from_error(ast::Error::Unspecified);
}
let mut iter = args.into_iter();
let first = fetcher.get_calc_value(iter.next().unwrap());
let second = fetcher.get_calc_value(iter.next().unwrap());
let condition = match second {
CalcValue::Scalar(v) => match v {
Value::Text(t) => parse_condition(&t),
_ => {
let value = get_condition_value(&v);
let condition = Condition::Logical(LogicalCondition { op: Op::Eq, value });
Some(condition)
}
},
_ => None,
};
match condition {
Some(cond) => CalcVertex::from_number(count_if_calc_value(&cond, first) as f64),
None => CalcVertex::from_error(ast::Error::Unspecified),
}
}
fn count_if_calc_value(cond: &Condition, value: CalcValue) -> u32 {
match value {
CalcValue::Scalar(v) => count_if_value(cond, &v),
CalcValue::Range(r) => r
.into_iter()
.fold(0, |prev, this| prev + count_if_value(&cond, &this)),
CalcValue::Cube(c) => c
.into_iter()
.fold(0, |prev, this| prev + count_if_value(&cond, &this)),
CalcValue::Union(values) => values
.into_iter()
.map(|v| count_if_calc_value(cond, *v))
.fold(0_u32, |prev, this| prev + this),
}
}
fn count_if_value(condition: &Condition, v: &Value) -> u32 {
if match_condition(condition, v) {
1
} else {
0
}
}