package com.syjy.calculate.function;

import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.runtime.function.AbstractFunction;
import com.googlecode.aviator.runtime.type.AviatorDecimal;
import com.googlecode.aviator.runtime.type.AviatorJavaType;
import com.googlecode.aviator.runtime.type.AviatorObject;
import com.googlecode.aviator.runtime.type.Sequence;
import com.syjy.calculate.entity.CalculateResult;
import com.syjy.calculate.entity.FormulaParam;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * 计算准确率 :平均绝对误差
 *
 * @author zcl
 * @version 1.0
 * @since 2022/9/8 9:30
 */
@Slf4j
public class MeanAbsoluteError extends AbstractFunction {
    @Override
    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4) {
        // 获取参数
        FormulaParam formulaParam = CommonUtil.getFormulaParam(env, arg1, arg2, arg3, arg4, null);
        // 将参数转为集合
        Sequence seq = CommonUtil.getSeq(formulaParam.getFirst(), env);
        String exp = "sumDifferenceAbsolute(list," + formulaParam.getSecond() + "," + formulaParam.getThird() + ")";
        // 获取Σ|实际-预测|
        BigDecimal sumDifferenceAbsolute = new BigDecimal(String.valueOf(AviatorEvaluator.execute(exp, env)));
        // 获取容量
        BigDecimal electricCapacity = (BigDecimal) env.get("electricCapacity");
        BigDecimal maxCapacity = (BigDecimal) env.get("maxCapacity");
        BigDecimal size = new BigDecimal(seq.hintSize());
        // 如果容量为0，则分母为0,返回100
        if (electricCapacity.compareTo(BigDecimal.ZERO) == 0) {
            log.warn(CalculateResult.MSG_CAP_ZERO);
            return new AviatorDecimal(CalculateResult.ONE_HUNDRED);
        }
        // 如果数据个数为0，则分母为0,返回100
        if (size.compareTo(BigDecimal.ZERO) == 0) {
            log.warn(CalculateResult.MSG_SIZE_ZERO);
            return new AviatorDecimal(CalculateResult.ONE_HUNDRED);
        }
        Map<String, Object> map = new HashMap<>();
        map.put("electricCapacity", electricCapacity);
        map.put("maxCapacity", maxCapacity);
        map.put("sumDifferenceAbsolute", sumDifferenceAbsolute);
        map.put("size", size);
        // 计算 1-(Σ|实际-预测|/cap*n)
        String expFinal = "1-(sumDifferenceAbsolute/(" + formulaParam.getFourth() + "*size))";
        BigDecimal result = new BigDecimal(String.valueOf(AviatorEvaluator.execute(expFinal, map)));
        // 返回结果
        return new AviatorDecimal(result);
    }

    @Override
    public String getName() {
        return "meanAbsoluteError";
    }
}
