ソースを参照

计算方法:实体类和公式方法

zhangchenglong 2 年 前
コミット
c75e367714

+ 55 - 0
src/main/java/com/syjy/calculate/entity/CalculateRequest.java

@@ -0,0 +1,55 @@
+package com.syjy.calculate.entity;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 数据请求参数格式化
+ *
+ * @author zcl
+ * @version 1.0
+ * @since 2022/9/9 10:34
+ */
+@Data
+public class CalculateRequest implements Serializable {
+
+    private static final long serialVersionUID = -437839076132402939L;
+
+    /**
+     * 计算信息
+     */
+    private List<CalculationInfo> calculationInfoList;
+    /**
+     * 容量
+     */
+    private BigDecimal cap;
+
+    /**
+     * 省调
+     */
+    private  String province;
+
+    /**
+     * 省调类型
+     */
+    private String formulaType;
+
+    /**
+     * 场站类型
+     */
+    private String electricType;
+
+    /**
+     * 备用字段
+     */
+    private String backUpA;
+
+    /**
+     * 备用字段
+     */
+    private String backUpB;
+
+}

+ 222 - 0
src/main/java/com/syjy/calculate/entity/CalculateResult.java

@@ -0,0 +1,222 @@
+package com.syjy.calculate.entity;
+
+import java.util.HashMap;
+
+/**
+ * 数据返回格式化
+ *
+ * @author zcl
+ * @version 1.0
+ * @since 2022/9/9 10:34
+ */
+public class CalculateResult extends HashMap<String, Object> {
+
+    private static final long serialVersionUID = 1L;
+
+    /** 100 */
+    public static final String ONE_HUNDRED = "100";
+
+    /** 百分号 */
+    public static final String PERCENT = "%";
+
+    /** formula */
+    public static final String FORMULA = "formula";
+
+    /** rules */
+    public static final String RULES = "rules";
+
+    /** 忽略 */
+    public static final String IGNORE = "666";
+
+    /** 失败 */
+    public static final String ERROR = "500";
+
+    /** 状态码 */
+    public static final String CODE_TAG = "code";
+
+    /** 返回内容 */
+    public static final String MSG_TAG = "msg";
+
+    /** 数据对象 */
+    public static final String DATA_TAG = "data";
+
+    /** 公式上下文中的数据 */
+    public static final String LIST = "list";
+
+    /** 实际功率 */
+    public static final String SJ = "sj";
+
+    /** 预测功率 */
+    public static final String YC = "yc";
+
+    /** 容量 */
+    public static final String RL = "rl";
+
+    /** 时间 */
+    public static final String TIME = "time";
+
+    /** 消息信息*/
+    public static final String MSG_REQUEST_NULL = "入参为空";
+    public static final String MSG_FORMULA_TYPE_NULL = "公式类型为空";
+    public static final String MSG_PROVINCE_NULL = "省调为空";
+    public static final String MSG_ELECTRIC_TYPE_NULL = "场站类型为空";
+    public static final String MSG_CALCULATE_DATA_NULL = "计算数据为空";
+    public static final String MSG_DATA_CHECK_ERROR = "数据校验错误";
+    public static final String MSG_NO_FORMULA = "未匹配到公式:";
+    public static final String MSG_CALCULATE_SUCCESS = "计算成功";
+    public static final String MSG_CALCULATE_FAIL = "计算失败:";
+
+    /**
+     * 状态类型
+     */
+    public enum Type
+    {
+        /** 成功 */
+        SUCCESS("200"),
+        /** 忽略 */
+        IGNORE("666"),
+        /** 警告 */
+        WARN("301"),
+        /** 错误 */
+        ERROR("500");
+        private final String value;
+
+        Type(String value)
+        {
+            this.value = value;
+        }
+
+        public String value()
+        {
+            return this.value;
+        }
+    }
+
+    /**
+     * 初始化一个新创建的 CalculateResult 对象
+     *
+     * @param type 状态类型
+     * @param msg 返回内容
+     */
+    public CalculateResult(Type type, String msg)
+    {
+        super.put(CODE_TAG, type.value);
+        super.put(MSG_TAG, msg);
+    }
+
+    /**
+     * 初始化一个新创建的 CalculateResult 对象
+     *
+     * @param type 状态类型
+     * @param msg 返回内容
+     * @param data 数据对象
+     */
+    public CalculateResult(Type type, String msg, Object data)
+    {
+        super.put(CODE_TAG, type.value);
+        super.put(MSG_TAG, msg);
+        if (data != null) {
+            super.put(DATA_TAG, data);
+        }
+    }
+
+    /**
+     * 返回成功消息
+     *
+     * @return 成功消息
+     */
+    public static CalculateResult success()
+    {
+        return CalculateResult.success("操作成功");
+    }
+
+    /**
+     * 返回成功数据
+     *
+     * @return 成功消息
+     */
+    public static CalculateResult success(Object data)
+    {
+        return CalculateResult.success("操作成功", data);
+    }
+
+    /**
+     * 返回成功消息
+     *
+     * @param msg 返回内容
+     * @return 成功消息
+     */
+    public static CalculateResult success(String msg)
+    {
+        return CalculateResult.success(msg, null);
+    }
+
+    /**
+     * 返回成功消息
+     *
+     * @param msg 返回内容
+     * @param data 数据对象
+     * @return 成功消息
+     */
+    public static CalculateResult success(String msg, Object data)
+    {
+        return new CalculateResult(Type.SUCCESS, msg, data);
+    }
+
+    /**
+     * 返回警告消息
+     *
+     * @param msg 返回内容
+     * @return 警告消息
+     */
+    public static CalculateResult warn(String msg)
+    {
+        return CalculateResult.warn(msg, null);
+    }
+
+    /**
+     * 返回警告消息
+     *
+     * @param msg 返回内容
+     * @param data 数据对象
+     * @return 警告消息
+     */
+    public static CalculateResult warn(String msg, Object data)
+    {
+        return new CalculateResult(Type.WARN, msg, data);
+    }
+
+    /**
+     * 返回错误消息
+     *
+     * @return
+     */
+    public static CalculateResult error()
+    {
+        return CalculateResult.error("操作失败");
+    }
+
+    /**
+     * 返回错误消息
+     *
+     * @param msg 返回内容
+     * @return 警告消息
+     */
+    public static CalculateResult error(String msg)
+    {
+        return CalculateResult.error(msg, null);
+    }
+
+    /**
+     * 返回错误消息
+     *
+     * @param msg 返回内容
+     * @param data 数据对象
+     * @return 警告消息
+     */
+    public static CalculateResult error(String msg, Object data)
+    {
+        return new CalculateResult(Type.ERROR, msg, data);
+    }
+}
+

+ 58 - 0
src/main/java/com/syjy/calculate/entity/CalculationInfo.java

@@ -0,0 +1,58 @@
+package com.syjy.calculate.entity;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 计算入参
+ *
+ * @author zcl
+ * @version 1.0
+ * @since 2022/9/09 10:16
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class CalculationInfo implements Serializable  {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 实际功率
+     */
+    private BigDecimal sj;
+
+    /**
+     * 预测功率
+     */
+    private BigDecimal yc;
+
+    /**
+     *  容量
+     */
+    private BigDecimal rl;
+
+    /**
+     * 时间
+     */
+    private long time;
+
+    /**
+     * 备用字段
+     */
+    private BigDecimal backUpBigDecimal;
+    /**
+     * 备用字段
+     */
+    private String backUpStr;
+    /**
+     * 备用字段
+     */
+    private String backUpLong;
+    /**
+     * 备用字段
+     */
+    private boolean backUpBoolean;
+
+}

+ 23 - 0
src/main/java/com/syjy/calculate/function/CommonUtil.java

@@ -0,0 +1,23 @@
+package com.syjy.calculate.function;
+
+import com.googlecode.aviator.runtime.RuntimeUtils;
+import com.googlecode.aviator.runtime.type.Sequence;
+import java.util.Map;
+
+/**
+ * 公式通用工具
+ *
+ * @author zcl
+ * @version 1.0
+ * @since 2022/9/8 9:30
+ */
+public class CommonUtil {
+    public static Sequence getSeq(Object obj, final Map<String, Object> env){
+        if (obj == null) {
+            throw new NullPointerException("null seq");
+        }
+        // 将参数放入抽象集合中
+        Sequence seq = RuntimeUtils.seq(obj, env);
+        return seq;
+    }
+}

+ 59 - 0
src/main/java/com/syjy/calculate/function/ListToListList.java

@@ -0,0 +1,59 @@
+package com.syjy.calculate.function;
+
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import com.googlecode.aviator.runtime.function.AbstractFunction;
+import com.googlecode.aviator.runtime.type.AviatorObject;
+import com.googlecode.aviator.runtime.type.AviatorRuntimeJavaType;
+import com.googlecode.aviator.runtime.type.Sequence;
+import com.syjy.calculate.entity.CalculateResult;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 将根据每15分钟时间 list数据转为List<List<Map<>>> 格式
+ *
+ * @author zcl
+ * @version 1.0
+ * @since 2022/9/8 9:30
+ */
+public class ListToListList extends AbstractFunction {
+    @Override
+    public AviatorObject call(Map<String, Object> env, AviatorObject arg1) {
+        // 获取参数
+        Object first = arg1.getValue(env);
+        // 将参数转为集合
+        Sequence seq = CommonUtil.getSeq(first,env);
+        // 获取当天开始0时时间和当前时间15分钟节点
+        long startTime = DateUtil.beginOfDay(DateTime.now()).getTime();
+        // 获取当前时间
+        long nowTime = DateTime.now().getTime();
+        long moment15 = 900000L;
+        BigDecimal nowTimeBig = new BigDecimal(String.valueOf(nowTime));
+        BigDecimal moment15Big = new BigDecimal(String.valueOf(moment15));
+        BigDecimal queryTimeBig = nowTimeBig.divideAndRemainder(moment15Big)[0].multiply(moment15Big);
+        long endTime = queryTimeBig.longValue();
+        List<List<Map<String,Object>>> lastList = new ArrayList<>();
+        for(long stepTime = startTime;stepTime<=endTime;stepTime=stepTime+moment15){
+            List<Map<String,Object>> list = new ArrayList<>();
+            for (Object obj : seq) {
+                Map<String, Object> map = (Map<String, Object>) obj;
+                long time = (long)map.get(CalculateResult.TIME);
+                if(stepTime== time){
+                    list.add(map);
+                }
+            }
+            if(list!=null && list.size()>0){
+                lastList.add(list);
+            }
+        }
+        env.put("list",lastList);
+        return AviatorRuntimeJavaType.valueOf(lastList);
+    }
+    @Override
+    public String getName() {
+        return "listToListList";
+    }
+}

+ 45 - 0
src/main/java/com/syjy/calculate/function/MeanAbsoluteError.java

@@ -0,0 +1,45 @@
+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.AviatorObject;
+import com.googlecode.aviator.runtime.type.Sequence;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 计算准确率 :平均绝对误差
+ *
+ * @author zcl
+ * @version 1.0
+ * @since 2022/9/8 9:30
+ */
+public class MeanAbsoluteError extends AbstractFunction {
+    @Override
+    public AviatorObject call(Map<String, Object> env, AviatorObject arg1) {
+        // 获取参数
+        Object first = arg1.getValue(env);
+        // 将参数转为集合
+        Sequence seq = CommonUtil.getSeq(first,env);
+        // 获取Σ|sj-yc|
+        BigDecimal sumDifferenceAbsolute = new BigDecimal(String.valueOf(AviatorEvaluator.execute("sumDifferenceAbsolute(list)",env)));
+        // 获取容量
+        BigDecimal rl = (BigDecimal)env.get("rl");
+        BigDecimal size = new BigDecimal(seq.hintSize());
+        Map<String ,Object> map = new HashMap<>();
+        map.put("rl",rl);
+        map.put("sumDifferenceAbsolute",sumDifferenceAbsolute);
+        map.put("size",size);
+        // 计算 1-(Σ|sj-yc|/cap*n)
+        BigDecimal result = (BigDecimal) AviatorEvaluator.execute("1-(sumDifferenceAbsolute/(rl*size))",map);
+        // 返回结果
+        return new AviatorDecimal(result);
+    }
+    @Override
+    public String getName() {
+        return "meanAbsoluteError";
+    }
+}

+ 52 - 0
src/main/java/com/syjy/calculate/function/Pass.java

@@ -0,0 +1,52 @@
+package com.syjy.calculate.function;
+
+import com.googlecode.aviator.AviatorEvaluator;
+import com.googlecode.aviator.runtime.RuntimeUtils;
+import com.googlecode.aviator.runtime.function.AbstractFunction;
+import com.googlecode.aviator.runtime.type.AviatorDecimal;
+import com.googlecode.aviator.runtime.type.AviatorObject;
+import com.googlecode.aviator.runtime.type.Sequence;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 计算合格率
+ *
+ * @author zcl
+ * @version 1.0
+ * @since 2022/9/8 9:30
+ */
+public class Pass extends AbstractFunction {
+    /**
+     *
+     * @param env
+     * @param arg1
+     * @param arg2
+     * @return
+     */
+    @Override
+    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
+        // 获取参数
+        Object first = arg1.getValue(env);
+        BigDecimal compare = new BigDecimal(String.valueOf(arg2.getValue(env)));
+        BigDecimal sum = BigDecimal.ZERO;
+        Sequence seq = RuntimeUtils.seq(first, env);
+        // 循环集合获取实际功率、预测功率信息并计算
+        for (Object obj : seq) {
+            Map<String, Object> map = (Map<String, Object>) obj;
+            BigDecimal calculateResult = (BigDecimal) AviatorEvaluator.execute("1-math.abs((sj-yc)/rl)",map);
+            Map<String, Object> passMap = new HashMap<>();
+            passMap.put("forResult",calculateResult);
+            passMap.put("compare",compare);
+            BigDecimal forResult = (BigDecimal) AviatorEvaluator.execute("IF(calculateResult>=compare ,1,0)",passMap);
+            sum = sum.add(forResult);
+        }
+        return new AviatorDecimal(sum);
+    }
+    @Override
+    public String getName() {
+        return "pass";
+    }
+}

+ 37 - 0
src/main/java/com/syjy/calculate/function/PointS.java

@@ -0,0 +1,37 @@
+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.AviatorObject;
+import com.googlecode.aviator.runtime.type.Sequence;
+import java.math.BigDecimal;
+import java.util.Map;
+
+/**
+ * 计算准确率 :单点短期准确率
+ *
+ * @author zcl
+ * @version 1.0
+ * @since 2022/9/8 9:30
+ */
+public class PointS extends AbstractFunction {
+    @Override
+    public AviatorObject call(Map<String, Object> env, AviatorObject arg1) {
+        // 获取参数
+        Object first = arg1.getValue(env);
+        // 将参数转为集合
+        Sequence seq = CommonUtil.getSeq(first,env);
+        BigDecimal result = BigDecimal.ZERO;
+        // 循环集合
+        for (Object obj : seq) {
+            Map<String, Object> map = (Map<String, Object>) obj;
+            result = (BigDecimal) AviatorEvaluator.execute("math.abs((sj-yc)/yc)",map);
+        }
+        return new AviatorDecimal(result);
+    }
+    @Override
+    public String getName() {
+        return "pointS";
+    }
+}

+ 47 - 0
src/main/java/com/syjy/calculate/function/PointU.java

@@ -0,0 +1,47 @@
+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.AviatorObject;
+import com.googlecode.aviator.runtime.type.Sequence;
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 计算准确率 :单点超短期准确率
+ *
+ * @author zcl
+ * @version 1.0
+ * @since 2022/9/8 9:30
+ */
+public class PointU extends AbstractFunction {
+    @Override
+    public AviatorObject call(Map<String, Object> env, AviatorObject arg1) {
+        // 获取参数
+        Object first = arg1.getValue(env);
+        // 将参数转为集合
+        Sequence seq = CommonUtil.getSeq(first,env);
+        BigDecimal sum = BigDecimal.ZERO;
+        // 获取Σ|sj-yc|
+        BigDecimal sumDifferenceAbsolute = new BigDecimal(String.valueOf(AviatorEvaluator.execute("sumDifferenceAbsolute(list)",env)));
+        BigDecimal halfOfOne = new BigDecimal("0.5");
+        // 循环集合
+        for (Object obj : seq) {
+            Map<String, Object> map = (Map<String, Object>) obj;
+            map.put("sumDifferenceAbsolute",sumDifferenceAbsolute);
+            map.put("halfOfOne",halfOfOne);
+            BigDecimal forResult = (BigDecimal) AviatorEvaluator.execute("math.abs((sj/(sj+yc)-halfOfOne)) * (math.abs(sj-yc)/sumDifferenceAbsolute)",map);
+            sum = sum.add(forResult);
+        }
+        Map<String, Object> map = new HashMap<>();
+        map.put("sum",sum);
+        BigDecimal result = (BigDecimal) AviatorEvaluator.execute("1-(2*sum)",map);
+        return new AviatorDecimal(result);
+    }
+    @Override
+    public String getName() {
+        return "pointU";
+    }
+}

+ 52 - 0
src/main/java/com/syjy/calculate/function/RootMeanSquaredErrorA.java

@@ -0,0 +1,52 @@
+package com.syjy.calculate.function;
+
+import com.googlecode.aviator.AviatorEvaluator;
+import com.googlecode.aviator.runtime.RuntimeUtils;
+import com.googlecode.aviator.runtime.function.AbstractFunction;
+import com.googlecode.aviator.runtime.type.AviatorDecimal;
+import com.googlecode.aviator.runtime.type.AviatorObject;
+import com.googlecode.aviator.runtime.type.Sequence;
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 计算准确率 :均方根准确率绝对值
+ *
+ * @author zcl
+ * @version 1.0
+ * @since 2022/9/8 9:30
+ */
+public class RootMeanSquaredErrorA extends AbstractFunction {
+    @Override
+    public AviatorObject call(Map<String, Object> env, AviatorObject arg1) {
+        // 获取参数
+        Object first = arg1.getValue(env);
+        // 获取Σ|sj-yc|
+        env.put("list",first);
+        BigDecimal sumDifferenceAbsolute = new BigDecimal(String.valueOf(AviatorEvaluator.execute("sumDifferenceAbsolute(list)",env)));
+        BigDecimal sum = BigDecimal.ZERO;
+        Sequence seq = RuntimeUtils.seq(first, env);
+        // 循环集合获取实际功率、预测功率信息并计算
+        for (Object obj : seq) {
+            Map<String, Object> map = (Map<String, Object>) obj;
+            map.put("sumDifferenceAbsolute",sumDifferenceAbsolute);
+            BigDecimal forResult = (BigDecimal) AviatorEvaluator.execute("differenceSquare(sj,yc) * (differenceAbsolute(sj,yc)/sumDifferenceAbsolute)",map);
+            sum = sum.add(forResult);
+        }
+        // 获取容量
+        BigDecimal rl = (BigDecimal)env.get("rl");
+        Map<String, Object> map = new HashMap<>();
+        map.put("sum",sum);
+        map.put("rl",rl);
+        BigDecimal one = BigDecimal.ONE;
+        map.put("one",one);
+        // 对求和结果开根号
+        Double result = (Double) AviatorEvaluator.execute("one-(math.sqrt(sum)/rl)",map);
+        return new AviatorDecimal(result);
+    }
+    @Override
+    public String getName() {
+        return "rootMeanSquaredErrorA";
+    }
+}

+ 44 - 0
src/main/java/com/syjy/calculate/function/RootMeanSquaredErrorC.java

@@ -0,0 +1,44 @@
+package com.syjy.calculate.function;
+
+import com.googlecode.aviator.AviatorEvaluator;
+import com.googlecode.aviator.runtime.RuntimeUtils;
+import com.googlecode.aviator.runtime.function.AbstractFunction;
+import com.googlecode.aviator.runtime.type.AviatorDecimal;
+import com.googlecode.aviator.runtime.type.AviatorObject;
+import com.googlecode.aviator.runtime.type.Sequence;
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 计算准确率 :标准均方根公式
+ *
+ * @author zcl
+ * @version 1.0
+ * @since 2022/9/8 9:30
+ */
+public class RootMeanSquaredErrorC extends AbstractFunction {
+    @Override
+    public AviatorObject call(Map<String, Object> env, AviatorObject arg1) {
+        // 获取参数
+        Object first = arg1.getValue(env);
+        BigDecimal sum = BigDecimal.ZERO;
+        Sequence seq = RuntimeUtils.seq(first, env);
+        // 循环集合获取实际功率、预测功率信息并计算
+        for (Object obj : seq) {
+            Map<String, Object> map = (Map<String, Object>) obj;
+            BigDecimal forResult = (BigDecimal) AviatorEvaluator.execute("((sj-yc)/rl)**2",map);
+            sum = sum.add(forResult);
+        }
+        Map<String, Object> map = new HashMap<>();
+        map.put("sum",sum);
+        BigDecimal size = new BigDecimal(seq.hintSize());
+        map.put("size",size);
+        BigDecimal result = (BigDecimal) AviatorEvaluator.execute("1-math.sqrt(sum/size)",map);
+        return new AviatorDecimal(result);
+    }
+    @Override
+    public String getName() {
+        return "rootMeanSquaredErrorC";
+    }
+}

+ 46 - 0
src/main/java/com/syjy/calculate/function/RootMeanSquaredErrorR.java

@@ -0,0 +1,46 @@
+package com.syjy.calculate.function;
+
+import com.googlecode.aviator.AviatorEvaluator;
+import com.googlecode.aviator.runtime.RuntimeUtils;
+import com.googlecode.aviator.runtime.function.AbstractFunction;
+import com.googlecode.aviator.runtime.type.AviatorDecimal;
+import com.googlecode.aviator.runtime.type.AviatorObject;
+import com.googlecode.aviator.runtime.type.Sequence;
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 计算准确率 :均方根公式
+ *
+ * @author zcl
+ * @version 1.0
+ * @since 2022/9/8 9:30
+ */
+public class RootMeanSquaredErrorR extends AbstractFunction {
+    @Override
+    public AviatorObject call(Map<String, Object> env, AviatorObject arg1) {
+        // 获取参数
+        Object first = arg1.getValue(env);
+        BigDecimal sum = BigDecimal.ZERO;
+        Sequence seq = RuntimeUtils.seq(first, env);
+        // 循环集合获取实际功率、预测功率信息并计算
+        for (Object obj : seq) {
+            Map<String, Object> map = (Map<String, Object>) obj;
+            BigDecimal forResult = (BigDecimal) AviatorEvaluator.execute("((sj-yc)/sj)**2",map);
+            sum = sum.add(forResult);
+        }
+
+        Map<String, Object> map = new HashMap<>();
+        BigDecimal size = new BigDecimal(seq.hintSize());
+        map.put("size",size);
+        map.put("sum",sum);
+
+        BigDecimal result = (BigDecimal) AviatorEvaluator.execute("1-math.sqrt(sum/size)",map);
+        return new AviatorDecimal(result);
+    }
+    @Override
+    public String getName() {
+        return "rootMeanSquaredErrorR";
+    }
+}

+ 42 - 0
src/main/java/com/syjy/calculate/function/RootMeanSquaredErrorS.java

@@ -0,0 +1,42 @@
+package com.syjy.calculate.function;
+
+import com.googlecode.aviator.AviatorEvaluator;
+import com.googlecode.aviator.runtime.RuntimeUtils;
+import com.googlecode.aviator.runtime.function.AbstractFunction;
+import com.googlecode.aviator.runtime.type.AviatorDecimal;
+import com.googlecode.aviator.runtime.type.AviatorObject;
+import com.googlecode.aviator.runtime.type.Sequence;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 计算准确率 :均方根准确率绝对值
+ *
+ * @author zcl
+ * @version 1.0
+ * @since 2022/9/8 9:30
+ */
+public class RootMeanSquaredErrorS extends AbstractFunction {
+    @Override
+    public AviatorObject call(Map<String, Object> env, AviatorObject arg1) {
+        // 获取参数
+        Object first = arg1.getValue(env);
+        // 获取Σ(sj-yc)²
+        BigDecimal sumDifferenceSquare = new BigDecimal(String.valueOf(AviatorEvaluator.execute("sumDifferenceSquare(list)",env)));
+        Map<String, Object> map = new HashMap<>();
+        map.put("sumDifferenceSquare",sumDifferenceSquare);
+        map.put("rl",env.get("rl"));
+        // 将参数转为集合
+        Sequence seq = RuntimeUtils.seq(first, env);
+        BigDecimal size = new BigDecimal(seq.hintSize());
+        map.put("size",size);
+        BigDecimal result = (BigDecimal) AviatorEvaluator.execute("math.sqrt(sumDifferenceSquare)/(rl*math.sqrt(size))",map);
+        return new AviatorDecimal(result);
+    }
+    @Override
+    public String getName() {
+        return "rootMeanSquaredErrorS";
+    }
+}

+ 38 - 0
src/main/java/com/syjy/calculate/function/SumDifferenceAbsolute.java

@@ -0,0 +1,38 @@
+package com.syjy.calculate.function;
+
+import com.googlecode.aviator.AviatorEvaluator;
+import com.googlecode.aviator.runtime.RuntimeUtils;
+import com.googlecode.aviator.runtime.function.AbstractFunction;
+import com.googlecode.aviator.runtime.type.AviatorDecimal;
+import com.googlecode.aviator.runtime.type.AviatorObject;
+import com.googlecode.aviator.runtime.type.Sequence;
+import java.math.BigDecimal;
+import java.util.Map;
+
+/**
+ * 计算两个数的差值的绝对值并求和:Σ|sj-yc|
+ *
+ * @author zcl
+ * @version 1.0
+ * @since 2022/9/8 9:30
+ */
+public class SumDifferenceAbsolute extends AbstractFunction {
+    @Override
+    public AviatorObject call(Map<String, Object> env, AviatorObject arg1) {
+        Object first = arg1.getValue(env);
+        // 将参数转为集合
+        Sequence seq = CommonUtil.getSeq(first,env);
+        BigDecimal sum = BigDecimal.ZERO;
+        // 循环集合
+        for (Object obj : seq) {
+            Map<String, Object> map = (Map<String, Object>) obj;
+            BigDecimal forResult = (BigDecimal) AviatorEvaluator.execute("differenceAbsolute(sj,yc)",map);
+            sum = sum.add(forResult);
+        }
+        return new AviatorDecimal(sum);
+    }
+    @Override
+    public String getName() {
+        return "sumDifferenceAbsolute";
+    }
+}

+ 39 - 0
src/main/java/com/syjy/calculate/function/SumDifferenceSquare.java

@@ -0,0 +1,39 @@
+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.AviatorObject;
+import com.googlecode.aviator.runtime.type.Sequence;
+import java.math.BigDecimal;
+import java.util.Map;
+
+/**
+ * 计算两个数的差值的平方并求和:Σ(sj-yc)²
+ *
+ * @author zcl
+ * @version 1.0
+ * @since 2022/9/8 9:30
+ */
+public class SumDifferenceSquare extends AbstractFunction {
+    @Override
+    public AviatorObject call(Map<String, Object> env, AviatorObject arg1) {
+        Object first = arg1.getValue(env);
+        // 将参数转为集合
+        Sequence seq = CommonUtil.getSeq(first,env);
+        BigDecimal sum = BigDecimal.ZERO;
+        // 循环集合
+        for (Object obj : seq) {
+            Map<String, Object> map = (Map<String, Object>) obj;
+            // 计算: (实际-预测)的平方
+            BigDecimal forResult = (BigDecimal) AviatorEvaluator.execute("differenceSquare(sj,yc)",map);
+            // 求和
+            sum = sum.add(forResult);
+        }
+        return new AviatorDecimal(sum);
+    }
+    @Override
+    public String getName() {
+        return "sumDifferenceSquare";
+    }
+}

+ 0 - 2
src/main/java/com/syjy/calculate/repository/CalculationFormulaRepository.java

@@ -3,8 +3,6 @@ package com.syjy.calculate.repository;
 import com.syjy.calculate.entity.CalculationFormula;
 import org.springframework.stereotype.Repository;
 
-import java.util.List;
-
 @Repository
 public interface CalculationFormulaRepository {
 

+ 3 - 2
src/main/java/com/syjy/calculate/repository/repositoryImpl/CalculationFormulaRepositoryImpl.java

@@ -1,6 +1,7 @@
 package com.syjy.calculate.repository.repositoryImpl;
 
 import com.syjy.calculate.config.StarterProperties;
+import com.syjy.calculate.entity.CalculateResult;
 import com.syjy.calculate.entity.CalculationFormula;
 import com.syjy.calculate.repository.CalculationFormulaRepository;
 import lombok.extern.slf4j.Slf4j;
@@ -95,9 +96,9 @@ public class CalculationFormulaRepositoryImpl implements CalculationFormulaRepos
 
         String sql = "";
         // 查询sql
-        if ("calculate".equals(type)) {
+        if (CalculateResult.FORMULA.equals(type)) {
             sql = "SELECT * from t_calculation_formula where ELECTRIC_TYPE = ? and PROVINCE_ENUM = ? and TYPE = ? limit 1 ";
-        } else if ("rules".equals(type)) {
+        } else if (CalculateResult.RULES.equals(type)) {
             sql = "SELECT * from t_calculation_formula where TYPE = 'RULES' and ELECTRIC_TYPE = ? and PROVINCE_ENUM = ? and RULE_FORMULA = ? limit 1";
         }
         // 根据类型和省调查询公式

+ 53 - 58
src/main/java/com/syjy/calculate/service/AccuracyPassRateCalculateService.java

@@ -3,12 +3,13 @@ package com.syjy.calculate.service;
 import com.googlecode.aviator.AviatorEvaluator;
 import com.googlecode.aviator.Expression;
 import com.syjy.calculate.entity.CalculateResult;
+import com.syjy.calculate.entity.CalculationFormula;
 import com.syjy.calculate.entity.CalculationInfo;
 import com.syjy.calculate.entity.CalculateRequest;
+import com.syjy.calculate.repository.CalculationFormulaRepository;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import java.io.File;
-import java.io.IOException;
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -26,6 +27,9 @@ import java.util.Map;
 @Slf4j
 public class AccuracyPassRateCalculateService {
 
+    @Autowired
+    private CalculationFormulaRepository calculationFormulaRepository;
+
     /**
      * 计算准确率、合格率
      *
@@ -41,25 +45,18 @@ public class AccuracyPassRateCalculateService {
         }
         // 获取细则校验过的数据
         List<Map<String, Object>> checkedData = (List<Map<String, Object>>) checkedDataResult.get(CalculateResult.DATA_TAG);
-        // 获取jar包所在路径
-        String classPath = System.getProperty(CalculateResult.USER_DIR);
-        // 获取文件路径
-        String fileUrl = classPath + CalculateResult.SLASH + CalculateResult.EXAMPLES + CalculateResult.SLASH + calculateRequest.getProvince() + CalculateResult.UNDERLINE + calculateRequest.getFormulaType() + CalculateResult.UNDERLINE + calculateRequest.getElectricType() + CalculateResult.UNDERLINE + CalculateResult.FORMULA + CalculateResult.AV;
-        // 初始化公式并缓存公式
-
-        File file = new File(fileUrl);
-        // 判断公式文件是否存在
-        if (!file.exists()) {
-            // 未匹配到公式文件
-            return CalculateResult.error(CalculateResult.MSG_NO_FORMULA + fileUrl);
-        }
-        Expression exp = null;
-        // 初始化公式文件
-        try {
-            exp = AviatorEvaluator.getInstance().compileScript(fileUrl, true);
-        } catch (IOException e) {
-            e.printStackTrace();
+        // 根据类型从数据库中查出公式列表
+        CalculationFormula calculationFormula = calculationFormulaRepository.findByTypeAndProvince(CalculateResult.FORMULA, calculateRequest.getFormulaType(), calculateRequest.getProvince(), calculateRequest.getElectricType());
+        if (calculationFormula == null || calculationFormula.getFormula() == null) {
+            // 未匹配到公式
+            return CalculateResult.error(CalculateResult.MSG_NO_FORMULA);
         }
+        // 获取公式
+        String formula = calculationFormula.getFormula();
+        //缓存公式名称
+        String scriptName = calculateRequest.getProvince() + calculateRequest.getFormulaType() + calculateRequest.getElectricType() + CalculateResult.FORMULA;
+        // 初始化公式并缓存公式
+        Expression expression = AviatorEvaluator.getInstance().compile(formula);
         // 上下文
         Map<String, Object> env = new HashMap<>();
         // 将需要计算的list数据放入上下文
@@ -68,9 +65,14 @@ public class AccuracyPassRateCalculateService {
         // 执行计算并得出结果
         try {
             // 获取计算结果
-            BigDecimal executeResult = new BigDecimal(String.valueOf(exp.execute(env)));
+            Map<String, Object> executeResult = (Map<String, Object>) expression.execute(env);
+            // 如果计算失败,返回失败内容
+            if (String.valueOf(executeResult.get(CalculateResult.CODE_TAG)).equals(CalculateResult.ERROR)) {
+                String resultValue = String.valueOf(executeResult.get(CalculateResult.MSG_TAG));
+                return CalculateResult.error(String.valueOf(executeResult.get(CalculateResult.MSG_TAG)), resultValue);
+            }
             // 过滤计算结果
-            String result = filterResult(executeResult);
+            String result = filterResult(executeResult.get(CalculateResult.DATA_TAG));
             return CalculateResult.success(CalculateResult.MSG_CALCULATE_SUCCESS, result);
         } catch (Exception e) {
             e.printStackTrace();
@@ -84,21 +86,22 @@ public class AccuracyPassRateCalculateService {
      * @param result 过滤前的结果
      * @return 过滤后的结果
      */
-    private String filterResult(BigDecimal result) {
+    private String filterResult(Object result) {
+        BigDecimal resultBig = (BigDecimal) result;
         //当结果为负数时,说明偏差过大,准确率为0
-        if (result.compareTo(BigDecimal.ZERO) == -1 || result.compareTo(BigDecimal.ZERO) == 0) {
-            result = BigDecimal.ZERO;
+        if (resultBig.compareTo(BigDecimal.ZERO) == -1 || resultBig.compareTo(BigDecimal.ZERO) == 0) {
+            resultBig = BigDecimal.ZERO;
         }
         // 如果结果大于1,则准确率设为100
-        if (result.compareTo(BigDecimal.ONE) == 1) {
-            result = BigDecimal.ONE;
+        if (resultBig.compareTo(BigDecimal.ONE) == 1) {
+            resultBig = BigDecimal.ONE;
         }
         // 对数据*100
-        result = result.multiply(new BigDecimal(CalculateResult.ONE_HUNDRED));
+        resultBig = resultBig.multiply(new BigDecimal(CalculateResult.ONE_HUNDRED));
         // 对数据进行四舍五入
-        result = result.setScale(2, BigDecimal.ROUND_HALF_UP);
+        resultBig = resultBig.setScale(2, BigDecimal.ROUND_HALF_UP);
         // 数据加上百分号
-        return result + CalculateResult.PERCENT;
+        return resultBig + CalculateResult.PERCENT;
     }
 
     /**
@@ -133,43 +136,36 @@ public class AccuracyPassRateCalculateService {
         if (calculationInfoList == null || calculationInfoList.size() == 0) {
             return CalculateResult.error(CalculateResult.MSG_CALCULATE_DATA_NULL);
         }
-        // 获取jar包所在路径
-        String classPath = System.getProperty(CalculateResult.USER_DIR);
-        // 获取文件路径
-        String fileUrl = classPath + CalculateResult.SLASH + CalculateResult.EXAMPLES + CalculateResult.SLASH + calculateRequest.getProvince() + CalculateResult.UNDERLINE + calculateRequest.getFormulaType() + CalculateResult.UNDERLINE + calculateRequest.getElectricType() + CalculateResult.UNDERLINE + CalculateResult.RULES + CalculateResult.AV;
-        // 获取文件
-        File file = new File(fileUrl);
+        // 循环判断实际功率/预测功率是否为空
+        for (CalculationInfo calculationInfo : calculationInfoList) {
+            if (calculationInfo.getYc() == null || calculationInfo.getSj() == null) {
+                return CalculateResult.error(CalculateResult.MSG_CALCULATE_DATA_NULL);
+            }
+        }
         // 将数据转为List Map 格式
         List<Map<String, Object>> calculationInfoListMap = getCalculationInfoList(calculationInfoList);
-        // 判断公式文件是否存在
-        if (!file.exists()) {
+        // 获取细则公式
+        CalculationFormula rulesCalculationFormula = calculationFormulaRepository.findByTypeAndProvince(CalculateResult.RULES, formulaType, province, electricType);
+        if (rulesCalculationFormula == null || rulesCalculationFormula.getFormula() == null) {
             // 未匹配到细则文件,则不进行细则校验,返回数据
             return CalculateResult.success(calculationInfoListMap);
         }
+        // 初始化公式并缓存公式
+        Expression expression = AviatorEvaluator.getInstance().compile(rulesCalculationFormula.getFormula());
+        // 通过校验的数据
         List<Map<String, Object>> passList = new ArrayList<>();
-        // 初始化细则校验文件
-        Expression exp = null;
-        try {
-            exp = AviatorEvaluator.getInstance().compileScript(fileUrl, true);
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
         // 循环数据,对数据进行校验
         for (Map<String, Object> calculationMap : calculationInfoListMap) {
             // 循环公式,对每条功率信息进行细则处理
             try {
-                Map<String,Object> checkResult = (HashMap<String, Object>) exp.execute(calculationMap);
-                switch (String.valueOf(checkResult.get(CalculateResult.CODE_TAG))){
-                    case CalculateResult.IGNORE :
-                        break;
-                    case CalculateResult.ERROR :
-                        String resultValue = String.valueOf(checkResult.get(CalculateResult.MSG_TAG));
-                        return CalculateResult.error(CalculateResult.MSG_DATA_CHECK_ERROR,resultValue);
-                default:
-                break;
-                }
-                if (String.valueOf(checkResult.get(CalculateResult.CODE_TAG)).equals(CalculateResult.Type.SUCCESS.value())) {
-                    break;
+                Map<String, Object> checkResult = (HashMap<String, Object>) expression.execute(calculationMap);
+                // 如果返回结果是忽略,则结束本次循环
+                if (String.valueOf(checkResult.get(CalculateResult.CODE_TAG)).equals(CalculateResult.IGNORE)) {
+                    continue;
+                    // 如果返回错误,直接返回结果
+                } else if (String.valueOf(checkResult.get(CalculateResult.CODE_TAG)).equals(CalculateResult.ERROR)) {
+                    String resultValue = String.valueOf(checkResult.get(CalculateResult.MSG_TAG));
+                    return CalculateResult.error(CalculateResult.MSG_DATA_CHECK_ERROR, resultValue);
                 }
                 // 校验成功,将通过的数据放入passList
                 passList.add(calculationMap);
@@ -205,6 +201,5 @@ public class AccuracyPassRateCalculateService {
         }
         return resultList;
     }
-
 }