Explorar o código

计算准确率通用方法修改

zhangchenglong %!s(int64=2) %!d(string=hai) anos
pai
achega
c52ff20a13

+ 9 - 5
src/main/java/com/syjy/calculate/conotroller/test.java

@@ -1,10 +1,10 @@
 package com.syjy.calculate.conotroller;
 
-import com.syjy.calculate.service.AccuarcyPassRateCalculateService;
+import com.alibaba.fastjson.JSONObject;
+import com.syjy.calculate.service.AccuracyPassRateCalculateService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
-
 import java.math.BigDecimal;
 import java.util.*;
 
@@ -12,7 +12,7 @@ import java.util.*;
 @RequestMapping("/test")
 public class test {
     @Autowired
-    private AccuarcyPassRateCalculateService accuarcyPassRateCalculateService;
+    private AccuracyPassRateCalculateService accuracyPassRateCalculateService;
 
     @RequestMapping(value = "/test")
     public void saveElectricField() {
@@ -29,8 +29,12 @@ public class test {
         BigDecimal rl = new BigDecimal("10");
         String provinceEnum = "E62";
         String type = "DQ";
-
-        accuarcyPassRateCalculateService.calculate(powerData, rl, provinceEnum, type);
+        JSONObject jsonResult = accuracyPassRateCalculateService.calculate(powerData, rl, provinceEnum, type);
+        String reslut = jsonResult.getString("value");
+        String accuracy = "";
+        if("success".equals(reslut)){
+            accuracy = jsonResult.getString("value");
+        }
     }
 
 }

+ 18 - 0
src/main/java/com/syjy/calculate/listener/ApplicationListenerImpl.java

@@ -0,0 +1,18 @@
+package com.syjy.calculate.listener;
+
+import com.syjy.calculate.repository.CalculationFormulaRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.event.ApplicationStartedEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ApplicationListenerImpl implements ApplicationListener<ApplicationStartedEvent> {
+    @Autowired
+    private CalculationFormulaRepository calculationFormulaRepository;
+
+    @Override
+    public void onApplicationEvent(ApplicationStartedEvent event) {
+        calculationFormulaRepository.createTable();
+    }
+}

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

@@ -9,6 +9,18 @@ import java.util.List;
 public interface CalculationFormulaRepository {
 
     /**
+     * 创建公式表
+     *
+     */
+    void createTable();
+
+    /**
+     * 创建公式表
+     *
+     */
+    void updateTable();
+
+    /**
      * 保存公式数据
      *
      * @param calculationFormula 单条公式记录
@@ -25,11 +37,10 @@ public interface CalculationFormulaRepository {
     /**
      * 查询数据
      *
-     * @param province 省调
      * @param type     类型
      * @return 返回记录
      */
-    List<CalculationFormula> findByTypeAndProvince(String province, String type);
+    List<CalculationFormula> findByTypeAndProvince(String type);
 
     /**
      * 查询变量数据

+ 70 - 7
src/main/java/com/syjy/calculate/repository/repositoryImpl/CalculationFormulaRepositoryImpl.java

@@ -2,20 +2,76 @@ package com.syjy.calculate.repository.repositoryImpl;
 
 import com.syjy.calculate.entity.CalculationFormula;
 import com.syjy.calculate.repository.CalculationFormulaRepository;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.dao.DataAccessException;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.ResultSetExtractor;
 import org.springframework.stereotype.Service;
-
+import javax.annotation.Resource;
+import java.sql.ResultSet;
+import java.sql.SQLException;
 import java.util.List;
 
 @Service
+@Slf4j
 public class CalculationFormulaRepositoryImpl implements CalculationFormulaRepository {
 
-    @Autowired
+    @Resource
     public JdbcTemplate jdbcTemplate;
 
     @Override
+    public void createTable() {
+        // 判断表是否存在
+        String checkSql = "SHOW TABLES LIKE 't_calculation_formula'";
+        Boolean created = jdbcTemplate.query(checkSql, null, null, new ResultSetExtractor<Boolean>() {
+            @Override
+            public Boolean extractData(ResultSet rs) throws SQLException, DataAccessException {
+                return rs.next();
+            }
+        });
+
+        try {
+            // 如果表存在,删除表
+            if (created) {
+                String dropSql = "DROP table t_calculation_formula";
+                jdbcTemplate.execute(dropSql);
+            }
+            // 创建表
+            String createSql = "create table t_calculation_formula ( ID int(0) not null auto_increment primary key, TYPE varchar(50) , `ORDER` int(0), FORMULA varchar(255) not null , PROVINCE_ENUM varchar(10), STATE varchar(10), CREATE_TIME datetime(0), CREATOR varchar(50), LAST_MODIFIER varchar(50), LAST_MODIFY_TIME datetime(0));";
+
+            jdbcTemplate.execute(createSql);
+
+            // 拼接插入语句,配置文件要增加&allowMultiQueries=true ,允许一次提交多条sql语句
+            String insertSql =
+                    "INSERT INTO `t_calculation_formula` VALUES (1, 'DQ', 1, 'sum:math.abs(VariateA-VariateB)', 'E62', NULL, NULL, NULL, NULL, NULL);" +
+                    "INSERT INTO `t_calculation_formula` VALUES (2, 'DQ', 2, 'sum:math.pow((VariateA-VariateB),2)*math.abs(VariateA-VariateB)/result1', 'E62', NULL, NULL, NULL, NULL, NULL);" +
+                    "INSERT INTO `t_calculation_formula` VALUES (3, 'DQ', 3, '(1-(math.sqrt(result2)/VariateC))*100', 'E62', NULL, NULL, NULL, NULL, NULL);" +
+                    "INSERT INTO `t_calculation_formula` VALUES (4, 'VariateA', NULL, 'sj', 'E62', NULL, NULL, NULL, NULL, NULL);" +
+                    "INSERT INTO `t_calculation_formula` VALUES (5, 'VariateB', NULL, 'yc', 'E62', NULL, NULL, NULL, NULL, NULL);" +
+                    "INSERT INTO `t_calculation_formula` VALUES (6, 'VariateC', NULL, 'rl', 'E62', NULL, NULL, NULL, NULL, NULL);" +
+                    "INSERT INTO `t_calculation_formula` VALUES (7, 'VariateD', NULL, 'count', 'E62', NULL, NULL, NULL, NULL, NULL);" +
+                    "INSERT INTO `t_calculation_formula` VALUES (8, 'Point', 1, 'math.abs((VariateA-VariateB)/VariateC)*100', 'E62', NULL, NULL, NULL, NULL, NULL);" +
+                    "INSERT INTO `t_calculation_formula` VALUES (9, 'MAE', 1, 'sum:math.abs((VariateA-VariateB)', 'E62', NULL, NULL, NULL, NULL, NULL);" +
+                    "INSERT INTO `t_calculation_formula` VALUES (10, 'MAE', 2, '1-(result1/(VariateC*VariateD))', 'E62', NULL, NULL, NULL, NULL, NULL);" +
+                    "INSERT INTO `t_calculation_formula` VALUES (11, 'RMSE', 1, 'sum:math.pow((VariateA-VariateB)/VariateC,2)', 'E62', NULL, NULL, NULL, NULL, NULL);" +
+                    "INSERT INTO `t_calculation_formula` VALUES (12, 'RMSE', 2, '(1-math.sqrt((result1/VariateD)))*100', 'E62', NULL, NULL, NULL, NULL, NULL);" +
+                    "INSERT INTO `t_calculation_formula` VALUES (13, 'RMSES', 1, 'sum:math.pow((VariateA-VariateB),2)', 'E62', NULL, NULL, NULL, NULL, NULL);" +
+                    "INSERT INTO `t_calculation_formula` VALUES (14, 'RMSES', 2, '(1-(result1/VariateC*math.sqrt(VariateD)))*100', 'E62', NULL, NULL, NULL, NULL, NULL);";
+
+            jdbcTemplate.execute(insertSql);
+        } catch (DataAccessException e) {
+            e.printStackTrace();
+            log.info("删除/创建表错误:" + e.toString());
+        }
+    }
+
+    @Override
+    public void updateTable() {
+
+    }
+
+    @Override
     public void save(CalculationFormula calculationFormula) {
 
     }
@@ -26,16 +82,23 @@ public class CalculationFormulaRepositoryImpl implements CalculationFormulaRepos
     }
 
     @Override
-    public List<CalculationFormula> findByTypeAndProvince( String province, String type) {
-        String sql = "SELECT * from t_calculation_formula where PROVINCE_ENUM = ? and TYPE = ? ";
-        List<CalculationFormula> calculationFormulaList = jdbcTemplate.query(sql,new BeanPropertyRowMapper<>(CalculationFormula.class),province,type);
+    public List<CalculationFormula> findByTypeAndProvince(String type) {
+        String sql = "SELECT * from t_calculation_formula where TYPE = ? ";
+
+        List<CalculationFormula> calculationFormulaList = null;
+        try {
+            calculationFormulaList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(CalculationFormula.class), type);
+        } catch (DataAccessException e) {
+            e.printStackTrace();
+        }
+
         return calculationFormulaList;
     }
 
     @Override
     public List<CalculationFormula> findVariate(String provinceEnum) {
         String sql = "SELECT * from t_calculation_formula where TYPE in ('VariateA','VariateB','VariateC') and PROVINCE_ENUM = ?";
-        List<CalculationFormula> calculationFormulaList = jdbcTemplate.query(sql,new BeanPropertyRowMapper<>(CalculationFormula.class),provinceEnum);
+        List<CalculationFormula> calculationFormulaList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(CalculationFormula.class), provinceEnum);
         return calculationFormulaList;
     }
 

+ 63 - 19
src/main/java/com/syjy/calculate/service/AccuarcyPassRateCalculateService.java → src/main/java/com/syjy/calculate/service/AccuracyPassRateCalculateService.java

@@ -1,12 +1,12 @@
 package com.syjy.calculate.service;
 
+import com.alibaba.fastjson.JSONObject;
 import com.googlecode.aviator.AviatorEvaluator;
 import com.syjy.calculate.entity.CalculationFormula;
 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.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -22,8 +22,9 @@ import java.util.Map;
  */
 @Service
 @Slf4j
-public class AccuarcyPassRateCalculateService {
+public class AccuracyPassRateCalculateService {
     BigDecimal ZERO = new BigDecimal("0");
+    BigDecimal HUNDRED = new BigDecimal("100");
 
     @Autowired
     private CalculationFormulaRepository calculationFormulaRepository;
@@ -33,12 +34,18 @@ public class AccuarcyPassRateCalculateService {
      * @param rl           容量
      * @param provinceEnum 省调
      * @param type         短期、超短期
-     * @return
+     * @return 返回Json  result:fail/success  value: 99%  msg:失败及原因
      */
-    public String calculate(List<Map<String, Object>> powerData, BigDecimal rl, String provinceEnum, String type) {
-        String result;
+    public JSONObject calculate(List<Map<String, Object>> powerData, BigDecimal rl, String provinceEnum, String type) {
+        JSONObject jsonResult = new JSONObject();
+        String lastResult = "";
+        jsonResult.put("result","fail");
         // 获取公式
-        List<CalculationFormula> calculationFormulaList = getCalculationFormulaData(provinceEnum, type);
+        List<CalculationFormula> calculationFormulaList = getCalculationFormulaData(type);
+        if (calculationFormulaList == null || calculationFormulaList.size() == 0) {
+            jsonResult.put("msg","计算失败,未匹配到公式");
+        }
+        BigDecimal count = BigDecimal.valueOf(calculationFormulaList.size());
         // 获取当前省调的公式变量值
         Map<String, String> variateMap = getVariate(provinceEnum);
         // 存放每步计算结果
@@ -60,12 +67,15 @@ public class AccuarcyPassRateCalculateService {
                     // 将执行过的公式结果放入dataMap
                     dataMap.putAll(resultMap);
                     dataMap.put("rl", rl);
+                    dataMap.put("count", count);
                     try {
                         // 求和计算 AviatorEvaluator.execute(公式,公式中的参数及值(以Map形式存放))
                         formulaResult = formulaResult.add(new BigDecimal(String.valueOf(AviatorEvaluator.execute(formula, dataMap))));
                     } catch (Exception e) {
                         e.printStackTrace();
                         log.error("计算公式:" + formula + "错误:" + e.toString());
+                        jsonResult.put("msg", "计算失败" + "错误:" + e.toString());
+                        return jsonResult;
                     }
                 }
                 // 非求和计算
@@ -76,12 +86,16 @@ public class AccuarcyPassRateCalculateService {
                     Map<String, Object> dataMap = powerData.get(0);
                     // 将执行过的公式结果放入dataMap
                     dataMap.putAll(resultMap);
+                    dataMap.put("rl", rl);
+                    dataMap.put("count", count);
                     try {
                         // 根据公式进行计算
                         formulaResult = new BigDecimal(String.valueOf(AviatorEvaluator.execute(formula, dataMap)));
                     } catch (Exception e) {
-                        e.printStackTrace();
                         log.error("计算公式:" + formula + "错误:" + e.toString());
+                        e.printStackTrace();
+                        jsonResult.put("msg", "计算失败" + "错误:" + e.toString());
+                        return jsonResult;
                     }
                 }
             }
@@ -90,24 +104,28 @@ public class AccuarcyPassRateCalculateService {
             log.info("result" + calculationFormula.getOrder() + ":" + formulaResult);
         }
         // 获取最后一个公式计算的结果
-        result = String.valueOf(resultMap.get("result" + calculationFormulaList.size()));
-        BigDecimal bResult = new BigDecimal(result);
+        lastResult = String.valueOf(resultMap.get("result" + calculationFormulaList.size()));
+        BigDecimal bResult = new BigDecimal(lastResult);
         bResult = bResult.setScale(2, BigDecimal.ROUND_HALF_UP);
-        result = bResult + "%";
-        return result;
+        // 过滤准确率
+        bResult = filterResult(bResult);
+        lastResult = bResult + "%";
+        jsonResult.put("result","success");
+        jsonResult.put("value",lastResult);
+        log.info("准确率:" + lastResult );
+        return jsonResult;
     }
 
     /**
      * 获取当前省调的公式列表
      *
-     * @param provinceEnum 当前省调
-     * @param type         类型(短期、超短期)
+     * @param type         类型
      * @return
      */
-    public List<CalculationFormula> getCalculationFormulaData(String provinceEnum, String type) {
+    public List<CalculationFormula> getCalculationFormulaData(String type) {
         List<CalculationFormula> calculationFormulaList = new ArrayList<>();
-        // 根据当前省调和类型(短期、超短期)从数据库中查出公式列表
-        calculationFormulaList = calculationFormulaRepository.findByTypeAndProvince(provinceEnum, type);
+        // 根据类型从数据库中查出公式列表
+        calculationFormulaList = calculationFormulaRepository.findByTypeAndProvince(type);
         return calculationFormulaList;
     }
 
@@ -137,6 +155,9 @@ public class AccuarcyPassRateCalculateService {
                 case "VariateC":
                     variateMap.put("VariateC", calculationFormula.getFormula());
                     break;
+                case "VariateD":
+                    variateMap.put("VariateD", calculationFormula.getFormula());
+                    break;
                 default:
                     break;
             }
@@ -155,16 +176,39 @@ public class AccuarcyPassRateCalculateService {
         String variateA = variateMap.get("VariateA");
         String variateB = variateMap.get("VariateB");
         String variateC = variateMap.get("VariateC");
-        if (variateA != null) {
+        String variateD = variateMap.get("variateD");
+        if (variateA != null && !"".equals(variateA)) {
             formula = formula.replace("VariateA", variateA);
         }
-        if (variateB != null) {
+        if (variateB != null && !"".equals(variateB)) {
             formula = formula.replace("VariateB", variateB);
         }
-        if (variateC != null) {
+        if (variateC != null && !"".equals(variateC)) {
             formula = formula.replace("VariateC", variateC);
         }
+        if (variateD != null && !"".equals(variateD)) {
+            formula = formula.replace("variateD", variateD);
+        }
         return formula;
     }
 
+
+    /**
+     * 过滤结果 <0=0  >100=100
+     * @param result 过滤前的结果
+     * @return 过滤后的结果
+     */
+    private BigDecimal filterResult(BigDecimal result){
+        //当结果为负数时,说明偏差过大,准确率为0
+        if(result.compareTo(BigDecimal.ZERO)==-1 || result.compareTo(BigDecimal.ZERO)==0){
+            result = BigDecimal.ZERO;
+        }
+
+        if(result.compareTo(this.HUNDRED)==1){
+            result = this.HUNDRED;
+        }
+        return result;
+    }
+
 }
+

+ 1 - 1
src/main/resources/application.yml

@@ -7,5 +7,5 @@ spring:
       # 数据源配置
       username: root
       password: '123456'
-      url: jdbc:mysql://localhost:3306/ipfcst-v3?useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8&autoReconnect=true&rewriteBatchedStatements=true&serverTimezone=Asia/Shanghai
+      url: jdbc:mysql://localhost:3306/ipfcst-v3?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&characterSetResults=UTF-8&autoReconnect=true&rewriteBatchedStatements=true&serverTimezone=Asia/Shanghai
       driver-class-name: com.mysql.cj.jdbc.Driver