|
@@ -1,14 +1,21 @@
|
|
|
package com.syjy.calculate.service;
|
|
|
|
|
|
+import cn.hutool.core.collection.CollUtil;
|
|
|
+import cn.hutool.core.convert.Convert;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import com.googlecode.aviator.AviatorEvaluator;
|
|
|
-import com.syjy.calculate.entity.*;
|
|
|
+import com.syjy.calculate.entity.CalculateRequest;
|
|
|
+import com.syjy.calculate.entity.CalculateResult;
|
|
|
+import com.syjy.calculate.entity.CalculationFormula;
|
|
|
+import com.syjy.calculate.entity.CalculationInfo;
|
|
|
import com.syjy.calculate.repository.CalculationFormulaRepository;
|
|
|
import com.syjy.calculate.util.Common;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.cglib.beans.BeanMap;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
import java.math.BigDecimal;
|
|
|
import java.text.SimpleDateFormat;
|
|
|
import java.util.*;
|
|
@@ -25,347 +32,356 @@ import java.util.stream.Collectors;
|
|
|
@Slf4j
|
|
|
public class AccuracyPassRateCalculateService {
|
|
|
|
|
|
- @Autowired
|
|
|
- private CalculationFormulaRepository calculationFormulaRepository;
|
|
|
- @Autowired
|
|
|
- private Common common;
|
|
|
-
|
|
|
- /**
|
|
|
- * 计算准确率、合格率
|
|
|
- *
|
|
|
- * @param calculateRequest
|
|
|
- * @return
|
|
|
- */
|
|
|
- public CalculateResult calculate(CalculateRequest calculateRequest) {
|
|
|
- // 根据类型从数据库中查出公式列表
|
|
|
- CalculationFormula calculationFormula = calculationFormulaRepository.findByTypeAndProvince(CalculateResult.FORMULA, calculateRequest.getFormulaType(), calculateRequest.getProvince(), calculateRequest.getElectricType(), calculateRequest.getStationCode());
|
|
|
- if (calculationFormula == null || calculationFormula.getFormula() == null) {
|
|
|
- // 未匹配到公式
|
|
|
- return CalculateResult.error(CalculateResult.MSG_NO_FORMULA);
|
|
|
- }
|
|
|
+ @Autowired
|
|
|
+ private CalculationFormulaRepository calculationFormulaRepository;
|
|
|
+ @Autowired
|
|
|
+ private Common common;
|
|
|
|
|
|
- // 对细则进行校验
|
|
|
- CalculateResult checkedDataResult = checkDataRules(calculateRequest, calculationFormula);
|
|
|
- // 如果细则校验失败,返回细则结果
|
|
|
- if (!String.valueOf(checkedDataResult.get(CalculateResult.CODE_TAG)).equals(CalculateResult.Type.SUCCESS.value())) {
|
|
|
- return checkedDataResult;
|
|
|
- }
|
|
|
- // 获取细则校验过的数据
|
|
|
- List<Map<String, Object>> checkedData = (List<Map<String, Object>>) checkedDataResult.get(CalculateResult.DATA_TAG);
|
|
|
- if (checkedData == null || checkedData.size() == 0) {
|
|
|
- return CalculateResult.error(CalculateResult.MSG_CALCULATE_DATA_NULL);
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * 计算准确率、合格率
|
|
|
+ *
|
|
|
+ * @param calculateRequest
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public CalculateResult calculate(CalculateRequest calculateRequest) {
|
|
|
+ // 根据类型从数据库中查出公式列表
|
|
|
+ CalculationFormula calculationFormula = calculationFormulaRepository.findByTypeAndProvince(CalculateResult.FORMULA, calculateRequest.getFormulaType(), calculateRequest.getProvince(), calculateRequest.getElectricType(), calculateRequest.getStationCode());
|
|
|
+ if (calculationFormula == null || calculationFormula.getFormula() == null) {
|
|
|
+ // 未匹配到公式
|
|
|
+ return CalculateResult.error(CalculateResult.MSG_NO_FORMULA);
|
|
|
+ }
|
|
|
|
|
|
- // 获取公式
|
|
|
- String formula = calculationFormula.getFormula();
|
|
|
- // 初始化公式并获取缓存的公式
|
|
|
- String scriptName = common.initFormula(formula, calculateRequest.getProvince(), calculateRequest.getFormulaType(), calculateRequest.getElectricType(), CalculateResult.FORMULA);
|
|
|
- // 上下文
|
|
|
- Map<String, Object> env = new HashMap<>();
|
|
|
- // 如果是多日多文件计算准确率,则将数据根据日期和文件类型分组,并放入list中
|
|
|
- if (calculationFormula.getDataSourceType() != null) {
|
|
|
- List<List<Map<String, Object>>> groupingList = groupingList(checkedData, calculationFormula.getDataSourceType());
|
|
|
- env.put(CalculateResult.LIST, groupingList);
|
|
|
- if (groupingList == null || groupingList.size() == 0) {
|
|
|
- return CalculateResult.error(CalculateResult.MSG_CALCULATE_DATA_NULL);
|
|
|
- }
|
|
|
- // 如果是多日数据,将数据按照日期分组
|
|
|
- } else if(calculationFormula.getFormula().contains("manyDay")){
|
|
|
- List<List<Map<String, Object>>> manyDaysList = groupingDaysList(checkedData,"genTime");
|
|
|
- env.put(CalculateResult.LIST, manyDaysList);
|
|
|
- }else {
|
|
|
- env.put(CalculateResult.LIST, checkedData);
|
|
|
- }
|
|
|
+ // 对细则进行校验
|
|
|
+ CalculateResult checkedDataResult = checkDataRules(calculateRequest, calculationFormula);
|
|
|
+ // 如果细则校验失败,返回细则结果
|
|
|
+ if (!String.valueOf(checkedDataResult.get(CalculateResult.CODE_TAG)).equals(CalculateResult.Type.SUCCESS.value())) {
|
|
|
+ return checkedDataResult;
|
|
|
+ }
|
|
|
+ // 获取细则校验过的数据
|
|
|
+ List<Map<String, Object>> checkedData = (List<Map<String, Object>>) checkedDataResult.get(CalculateResult.DATA_TAG);
|
|
|
+ if (checkedData == null || checkedData.size() == 0) {
|
|
|
+ return CalculateResult.error(CalculateResult.MSG_CALCULATE_DATA_NULL);
|
|
|
+ }
|
|
|
|
|
|
- // 将需要计算的list数据放入上下文
|
|
|
- env.put(CalculateResult.CAPACITY, calculateRequest.getElectricCapacity());
|
|
|
- env.put(CalculateResult.SIGN, calculateRequest.getSign());
|
|
|
-
|
|
|
- // 获取最大开机容量
|
|
|
- List<CalculationInfo> calculationInfoList = calculateRequest.getCalculationInfoList();
|
|
|
- BigDecimal maxOpenCapacity = calculateRequest.getElectricCapacity();
|
|
|
- // 如果数据不为空,获取最大开机容量
|
|
|
- if (calculationInfoList != null && calculationInfoList.size() > 0) {
|
|
|
- calculationInfoList.sort(Comparator.comparing(CalculationInfo::getOpenCapacity).reversed());
|
|
|
- maxOpenCapacity = calculationInfoList.get(0).getOpenCapacity();
|
|
|
- }
|
|
|
- env.put(CalculateResult.MAX_OPEN_CAPACITY, maxOpenCapacity);
|
|
|
-
|
|
|
- // 执行计算并得出结果
|
|
|
- try {
|
|
|
- // 获取计算结果
|
|
|
- Object executeResult = AviatorEvaluator.getInstance().getCachedExpressionByKey(scriptName).execute(env);
|
|
|
- // 过滤计算结果
|
|
|
- String result = filterResult(executeResult, calculationFormula.getIsRate(),calculationFormula.getMaxMinLimit());
|
|
|
- return CalculateResult.success(CalculateResult.MSG_CALCULATE_SUCCESS, result);
|
|
|
- } catch (Exception e) {
|
|
|
- e.printStackTrace();
|
|
|
- return CalculateResult.error(CalculateResult.MSG_CALCULATE_FAIL + e.toString());
|
|
|
- }
|
|
|
+ // 获取公式
|
|
|
+ String formula = calculationFormula.getFormula();
|
|
|
+ // 初始化公式并获取缓存的公式
|
|
|
+ String scriptName = common.initFormula(formula, calculateRequest.getProvince(), calculateRequest.getFormulaType(), calculateRequest.getElectricType(), CalculateResult.FORMULA);
|
|
|
+ // 上下文
|
|
|
+ Map<String, Object> env = new HashMap<>();
|
|
|
+ // 如果是多日多文件计算准确率,则将数据根据日期和文件类型分组,并放入list中
|
|
|
+ if (calculationFormula.getDataSourceType() != null) {
|
|
|
+ List<List<Map<String, Object>>> groupingList = groupingList(checkedData, calculationFormula.getDataSourceType());
|
|
|
+ env.put(CalculateResult.LIST, groupingList);
|
|
|
+ if (groupingList == null || groupingList.size() == 0) {
|
|
|
+ return CalculateResult.error(CalculateResult.MSG_CALCULATE_DATA_NULL);
|
|
|
+ }
|
|
|
+ // 如果是多日数据,将数据按照日期分组
|
|
|
+ } else if (calculationFormula.getFormula().contains("manyDay")) {
|
|
|
+ List<List<Map<String, Object>>> manyDaysList = groupingDaysList(checkedData, "genTime");
|
|
|
+ env.put(CalculateResult.LIST, manyDaysList);
|
|
|
+ } else {
|
|
|
+ env.put(CalculateResult.LIST, checkedData);
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 过滤结果 <0=0 >100=100
|
|
|
- *
|
|
|
- * @param result 过滤前的结果
|
|
|
- * @return 过滤后的结果
|
|
|
- */
|
|
|
- private String filterResult(Object result, String type ,String maxMinLimit) {
|
|
|
- // 如果是map类型,转为jsonString
|
|
|
- if (result instanceof HashMap) {
|
|
|
- String jsonStr = JSONObject.toJSONString(result);
|
|
|
- return jsonStr;
|
|
|
- }
|
|
|
- // 如果返回的不是数值类型,则不用过滤,直接返回
|
|
|
- if ((result instanceof String) || (result instanceof Boolean) || (result instanceof HashMap)) {
|
|
|
- return String.valueOf(result);
|
|
|
- }
|
|
|
- BigDecimal resultBig = new BigDecimal(String.valueOf(result));
|
|
|
- // 判断计算结果是否限定上下限
|
|
|
- if(maxMinLimit != null && maxMinLimit.equals(CalculateResult.STR_TRUE)){
|
|
|
- //当结果为负数时,说明偏差过大,准确率为0
|
|
|
- if (resultBig.compareTo(BigDecimal.ZERO) == -1 || resultBig.compareTo(BigDecimal.ZERO) == 0) {
|
|
|
- log.warn("结果为负数:" + resultBig + "自动转换为0%");
|
|
|
- resultBig = BigDecimal.ZERO;
|
|
|
- }
|
|
|
- // 如果结果大于1,则准确率设为100
|
|
|
- if (resultBig.compareTo(BigDecimal.ONE) == 1) {
|
|
|
- log.warn("结果大于100%:" + resultBig + "自动转换为100%");
|
|
|
- resultBig = BigDecimal.ONE;
|
|
|
- }
|
|
|
- }
|
|
|
+ // 将需要计算的list数据放入上下文
|
|
|
+ env.put(CalculateResult.CAPACITY, calculateRequest.getElectricCapacity());
|
|
|
+ env.put(CalculateResult.SIGN, calculateRequest.getSign());
|
|
|
|
|
|
- // 如果公式结果为带百分号
|
|
|
- if (type != null && type.equals(CalculateResult.STR_TRUE)) {
|
|
|
- // 对数据*100
|
|
|
- resultBig = resultBig.multiply(CalculateResult.ONE_HUNDRED);
|
|
|
- // 对数据进行四舍五入
|
|
|
- resultBig = resultBig.setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
- // 数据加上百分号
|
|
|
- return resultBig + CalculateResult.PERCENT;
|
|
|
- }
|
|
|
+ // 获取最大开机容量
|
|
|
+ List<CalculationInfo> calculationInfoList = calculateRequest.getCalculationInfoList();
|
|
|
+ BigDecimal maxOpenCapacity = calculateRequest.getElectricCapacity();
|
|
|
+ // 如果数据不为空,获取最大开机容量
|
|
|
+ if (calculationInfoList != null && calculationInfoList.size() > 0) {
|
|
|
+ calculationInfoList.sort(Comparator.comparing(CalculationInfo::getOpenCapacity).reversed());
|
|
|
+ maxOpenCapacity = calculationInfoList.get(0).getOpenCapacity();
|
|
|
+ }
|
|
|
+ env.put(CalculateResult.MAX_OPEN_CAPACITY, maxOpenCapacity);
|
|
|
|
|
|
- //如果结果不带百分号,直接四舍五入4位小数
|
|
|
- resultBig = resultBig.setScale(4, BigDecimal.ROUND_HALF_UP);
|
|
|
+ // 执行计算并得出结果
|
|
|
+ try {
|
|
|
+ // 获取计算结果
|
|
|
+ Object executeResult = AviatorEvaluator.getInstance().getCachedExpressionByKey(scriptName).execute(env);
|
|
|
+ // 过滤计算结果
|
|
|
+ String result = filterResult(executeResult, calculationFormula.getIsRate(), calculationFormula.getMaxMinLimit());
|
|
|
+ return CalculateResult.success(CalculateResult.MSG_CALCULATE_SUCCESS, result);
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ return CalculateResult.error(CalculateResult.MSG_CALCULATE_FAIL + e.toString());
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- return resultBig.toString();
|
|
|
+ /**
|
|
|
+ * 过滤结果 <0=0 >100=100
|
|
|
+ *
|
|
|
+ * @param result 过滤前的结果
|
|
|
+ * @return 过滤后的结果
|
|
|
+ */
|
|
|
+ private String filterResult(Object result, String type, String maxMinLimit) {
|
|
|
+ // 如果是map类型,转为jsonString
|
|
|
+ if (result instanceof HashMap) {
|
|
|
+ String jsonStr = JSONObject.toJSONString(result);
|
|
|
+ return jsonStr;
|
|
|
+ }
|
|
|
+ // 如果返回的不是数值类型,则不用过滤,直接返回
|
|
|
+ if ((result instanceof String) || (result instanceof Boolean) || (result instanceof HashMap)) {
|
|
|
+ return String.valueOf(result);
|
|
|
+ }
|
|
|
+ BigDecimal resultBig = new BigDecimal(String.valueOf(result));
|
|
|
+ // 判断计算结果是否限定上下限
|
|
|
+ if (maxMinLimit != null && maxMinLimit.equals(CalculateResult.STR_TRUE)) {
|
|
|
+ //当结果为负数时,说明偏差过大,准确率为0
|
|
|
+ if (resultBig.compareTo(BigDecimal.ZERO) == -1 || resultBig.compareTo(BigDecimal.ZERO) == 0) {
|
|
|
+ log.warn("结果为负数:" + resultBig + "自动转换为0%");
|
|
|
+ resultBig = BigDecimal.ZERO;
|
|
|
+ }
|
|
|
+ // 如果结果大于1,则准确率设为100
|
|
|
+ if (resultBig.compareTo(BigDecimal.ONE) == 1) {
|
|
|
+ log.warn("结果大于100%:" + resultBig + "自动转换为100%");
|
|
|
+ resultBig = BigDecimal.ONE;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 根据细则过滤数据
|
|
|
- *
|
|
|
- * @param calculateRequest
|
|
|
- * @param calculateRequest
|
|
|
- * @return
|
|
|
- */
|
|
|
- private CalculateResult checkDataRules(CalculateRequest calculateRequest, CalculationFormula calculationFormula) {
|
|
|
- // 对入参进行校验
|
|
|
- if (calculateRequest == null) {
|
|
|
- return CalculateResult.error(CalculateResult.MSG_REQUEST_NULL);
|
|
|
- }
|
|
|
- // 公式类型
|
|
|
- String formulaType = calculateRequest.getFormulaType();
|
|
|
- if ("".equals(formulaType) || formulaType == null) {
|
|
|
- return CalculateResult.error(CalculateResult.MSG_FORMULA_TYPE_NULL);
|
|
|
- }
|
|
|
- // 省调
|
|
|
- String province = calculateRequest.getProvince();
|
|
|
- if ("".equals(province) || province == null) {
|
|
|
- return CalculateResult.error(CalculateResult.MSG_PROVINCE_NULL);
|
|
|
- }
|
|
|
+ // 如果公式结果为带百分号
|
|
|
+ if (type != null && type.equals(CalculateResult.STR_TRUE)) {
|
|
|
+ // 对数据*100
|
|
|
+ resultBig = resultBig.multiply(CalculateResult.ONE_HUNDRED);
|
|
|
+ // 对数据进行四舍五入
|
|
|
+ resultBig = resultBig.setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
+ // 数据加上百分号
|
|
|
+ return resultBig + CalculateResult.PERCENT;
|
|
|
+ }
|
|
|
|
|
|
- // 场站编码
|
|
|
- String stationCode = calculateRequest.getStationCode();
|
|
|
- if ("".equals(stationCode) || stationCode == null) {
|
|
|
- return CalculateResult.error(CalculateResult.MSG_STATION_CODE_NULL);
|
|
|
- }
|
|
|
+ //如果结果不带百分号,直接四舍五入4位小数
|
|
|
+ resultBig = resultBig.setScale(4, BigDecimal.ROUND_HALF_UP);
|
|
|
|
|
|
- // 场站类型
|
|
|
- String electricType = calculateRequest.getElectricType();
|
|
|
- if ("".equals(electricType) || electricType == null) {
|
|
|
- return CalculateResult.error(CalculateResult.MSG_ELECTRIC_TYPE_NULL);
|
|
|
- }
|
|
|
- // 获取被校验数据
|
|
|
- List<CalculationInfo> calculationInfoList = calculateRequest.getCalculationInfoList();
|
|
|
+ return resultBig.toString();
|
|
|
+ }
|
|
|
|
|
|
- // 计算数据为空
|
|
|
- if (calculationInfoList == null || calculationInfoList.size() == 0) {
|
|
|
- return CalculateResult.error(CalculateResult.MSG_CALCULATE_DATA_NULL);
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * 根据细则过滤数据
|
|
|
+ *
|
|
|
+ * @param calculateRequest
|
|
|
+ * @param calculateRequest
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private CalculateResult checkDataRules(CalculateRequest calculateRequest, CalculationFormula calculationFormula) {
|
|
|
+ // 对入参进行校验
|
|
|
+ if (calculateRequest == null) {
|
|
|
+ return CalculateResult.error(CalculateResult.MSG_REQUEST_NULL);
|
|
|
+ }
|
|
|
+ // 公式类型
|
|
|
+ String formulaType = calculateRequest.getFormulaType();
|
|
|
+ if ("".equals(formulaType) || formulaType == null) {
|
|
|
+ return CalculateResult.error(CalculateResult.MSG_FORMULA_TYPE_NULL);
|
|
|
+ }
|
|
|
+ // 省调
|
|
|
+ String province = calculateRequest.getProvince();
|
|
|
+ if ("".equals(province) || province == null) {
|
|
|
+ return CalculateResult.error(CalculateResult.MSG_PROVINCE_NULL);
|
|
|
+ }
|
|
|
|
|
|
- // 装机容量校验
|
|
|
- if (calculateRequest.getElectricCapacity() == null || calculateRequest.getElectricCapacity().compareTo(BigDecimal.ZERO) == 0) {
|
|
|
- return CalculateResult.error(CalculateResult.MSG_CAP_NULL);
|
|
|
- }
|
|
|
+ // 场站编码
|
|
|
+ String stationCode = calculateRequest.getStationCode();
|
|
|
+ if ("".equals(stationCode) || stationCode == null) {
|
|
|
+ return CalculateResult.error(CalculateResult.MSG_STATION_CODE_NULL);
|
|
|
+ }
|
|
|
|
|
|
- // 获取细则公式
|
|
|
- CalculationFormula rulesCalculationFormula = calculationFormulaRepository.findByTypeAndProvince(CalculateResult.RULES, formulaType, province, electricType, stationCode);
|
|
|
+ // 场站类型
|
|
|
+ String electricType = calculateRequest.getElectricType();
|
|
|
+ if ("".equals(electricType) || electricType == null) {
|
|
|
+ return CalculateResult.error(CalculateResult.MSG_ELECTRIC_TYPE_NULL);
|
|
|
+ }
|
|
|
+ // 获取被校验数据
|
|
|
+ List<CalculationInfo> calculationInfoList = calculateRequest.getCalculationInfoList();
|
|
|
|
|
|
- // 将数据转为List Map 格式
|
|
|
- List<Map<String, Object>> calculationInfoListMap = getCalculationInfoList(calculationInfoList, calculateRequest.getElectricCapacity());
|
|
|
+ // 计算数据为空
|
|
|
+ if (calculationInfoList == null || calculationInfoList.size() == 0) {
|
|
|
+ return CalculateResult.error(CalculateResult.MSG_CALCULATE_DATA_NULL);
|
|
|
+ }
|
|
|
|
|
|
- if (rulesCalculationFormula == null || rulesCalculationFormula.getFormula() == null) {
|
|
|
- // 未匹配到细则文件,则不进行细则校验,返回数据
|
|
|
- return CalculateResult.success(calculationInfoListMap);
|
|
|
- }
|
|
|
+ // 装机容量校验
|
|
|
+ if (calculateRequest.getElectricCapacity() == null || calculateRequest.getElectricCapacity().compareTo(BigDecimal.ZERO) == 0) {
|
|
|
+ return CalculateResult.error(CalculateResult.MSG_CAP_NULL);
|
|
|
+ }
|
|
|
|
|
|
- // 获取数据文件类型
|
|
|
- String dataSourceType = calculationFormula.getDataSourceType();
|
|
|
- // 获取公式
|
|
|
- String formulaInfo = calculationFormula.getFormula();
|
|
|
-
|
|
|
- // 如果 实际功率/可用功率/预测功率为null 则剔除此条
|
|
|
- calculationInfoList.stream().filter(s -> s.getAbleValue() != null && s.getForecastAbleValue() != null);
|
|
|
- // 循环判断实际功率/预测功率、开机容量
|
|
|
- for (int i = 0; i < calculationInfoList.size(); i++) {
|
|
|
- // 如果公式中包含开机容量,才校验
|
|
|
- if (formulaInfo.indexOf("openCapacity") > 0) {
|
|
|
- // 如果开机容量 null 返回
|
|
|
- if (calculationInfoList.get(i).getOpenCapacity() == null || calculationInfoList.get(i).getOpenCapacity().compareTo(BigDecimal.ZERO) == 0) {
|
|
|
- return CalculateResult.error(CalculateResult.MSG_CAP_NULL);
|
|
|
- }
|
|
|
- }
|
|
|
- // 如果数据文件类型不为空,则判断数据的生成时间和文件类型不可以为空
|
|
|
- if (dataSourceType != null && !"".equals(dataSourceType)) {
|
|
|
- if (calculationInfoList.get(i).getGenTime() == null) {
|
|
|
- return CalculateResult.error(CalculateResult.MSG_GEN_TIME_NULL);
|
|
|
- }
|
|
|
- if (calculationInfoList.get(i).getDataSourceType() == null || "".equals(calculationInfoList.get(i).getDataSourceType())) {
|
|
|
- return CalculateResult.error(CalculateResult.MSG_DATA_SOURCE_TYPE_NULL);
|
|
|
- }
|
|
|
- }
|
|
|
+ // 获取细则公式
|
|
|
+ CalculationFormula rulesCalculationFormula = calculationFormulaRepository.findByTypeAndProvince(CalculateResult.RULES, formulaType, province, electricType, stationCode);
|
|
|
+
|
|
|
+ // 将数据转为List Map 格式
|
|
|
+ List<Map<String, Object>> calculationInfoListMap = getCalculationInfoList(calculationInfoList, calculateRequest.getElectricCapacity());
|
|
|
+
|
|
|
+ if (rulesCalculationFormula == null || rulesCalculationFormula.getFormula() == null) {
|
|
|
+ // 未匹配到细则文件,则不进行细则校验,返回数据
|
|
|
+ return CalculateResult.success(calculationInfoListMap);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取数据文件类型
|
|
|
+ String dataSourceType = calculationFormula.getDataSourceType();
|
|
|
+ // 获取公式
|
|
|
+ String formulaInfo = calculationFormula.getFormula();
|
|
|
+
|
|
|
+ // 如果 实际功率/可用功率/预测功率为null 则剔除此条
|
|
|
+ calculationInfoList.stream().filter(s -> s.getAbleValue() != null && s.getForecastAbleValue() != null);
|
|
|
+ // 循环判断实际功率/预测功率、开机容量
|
|
|
+ for (int i = 0; i < calculationInfoList.size(); i++) {
|
|
|
+ // 如果公式中包含开机容量,才校验
|
|
|
+ if (formulaInfo.indexOf("openCapacity") > 0) {
|
|
|
+ // 如果开机容量 null 返回
|
|
|
+ if (calculationInfoList.get(i).getOpenCapacity() == null || calculationInfoList.get(i).getOpenCapacity().compareTo(BigDecimal.ZERO) == 0) {
|
|
|
+ return CalculateResult.error(CalculateResult.MSG_CAP_NULL);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 如果数据文件类型不为空,则判断数据的生成时间和文件类型不可以为空
|
|
|
+ if (dataSourceType != null && !"".equals(dataSourceType)) {
|
|
|
+ if (calculationInfoList.get(i).getGenTime() == null) {
|
|
|
+ return CalculateResult.error(CalculateResult.MSG_GEN_TIME_NULL);
|
|
|
}
|
|
|
+ if (calculationInfoList.get(i).getDataSourceType() == null || "".equals(calculationInfoList.get(i).getDataSourceType())) {
|
|
|
+ return CalculateResult.error(CalculateResult.MSG_DATA_SOURCE_TYPE_NULL);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- // 获取公式
|
|
|
- String formula = rulesCalculationFormula.getFormula();
|
|
|
- // 初始化公式并获取缓存的公式
|
|
|
- String scriptName = common.initFormula(formula, calculateRequest.getProvince(), calculateRequest.getFormulaType(), calculateRequest.getElectricType(), CalculateResult.RULES);
|
|
|
- // 通过校验的数据
|
|
|
- List<Map<String, Object>> passList = new ArrayList<>();
|
|
|
- // 循环数据,对数据进行校验
|
|
|
- for (Map<String, Object> calculationMap : calculationInfoListMap) {
|
|
|
- // 循环公式,对每条功率信息进行细则处理
|
|
|
- try {
|
|
|
- Map<String, Object> checkResult = (HashMap<String, Object>) AviatorEvaluator.getInstance().getCachedExpressionByKey(scriptName).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.DATA_TAG));
|
|
|
- String msg = String.valueOf(checkResult.get(CalculateResult.MSG_TAG));
|
|
|
- return CalculateResult.error(msg, resultValue);
|
|
|
- }
|
|
|
- // 校验成功,将通过的数据放入passList
|
|
|
- passList.add(calculationMap);
|
|
|
- } catch (Exception e) {
|
|
|
- log.error(CalculateResult.MSG_DATA_CHECK_ERROR + e.toString());
|
|
|
- return CalculateResult.error(CalculateResult.MSG_DATA_CHECK_ERROR);
|
|
|
- }
|
|
|
+ // 获取公式
|
|
|
+ String formula = rulesCalculationFormula.getFormula();
|
|
|
+ // 初始化公式并获取缓存的公式
|
|
|
+ String scriptName = common.initFormula(formula, calculateRequest.getProvince(), calculateRequest.getFormulaType(), calculateRequest.getElectricType(), CalculateResult.RULES);
|
|
|
+ // 通过校验的数据
|
|
|
+ List<Map<String, Object>> passList = new ArrayList<>();
|
|
|
+ List<Map<String, Object>> no_assessment = new ArrayList<>();
|
|
|
+ // 循环数据,对数据进行校验
|
|
|
+ for (Map<String, Object> calculationMap : calculationInfoListMap) {
|
|
|
+ // 循环公式,对每条功率信息进行细则处理
|
|
|
+ try {
|
|
|
+ Map<String, Object> checkResult = Convert.toMap(String.class, Object.class, AviatorEvaluator.getInstance().getCachedExpressionByKey(scriptName).execute(calculationMap));
|
|
|
+ // 如果返回结果是忽略,则结束本次循环
|
|
|
+ if (String.valueOf(checkResult.get(CalculateResult.CODE_TAG)).equals(CalculateResult.IGNORE)) {
|
|
|
+ if (StrUtil.contains(Convert.toStr(checkResult.get(CalculateResult.DATA_TAG), ""), "不予考核")) {
|
|
|
+ no_assessment.add(checkResult);
|
|
|
+ }
|
|
|
+ continue;
|
|
|
+ // 如果返回错误,直接返回结果
|
|
|
+ } else if (String.valueOf(checkResult.get(CalculateResult.CODE_TAG)).equals(CalculateResult.ERROR)) {
|
|
|
+ String resultValue = String.valueOf(checkResult.get(CalculateResult.DATA_TAG));
|
|
|
+ String msg = String.valueOf(checkResult.get(CalculateResult.MSG_TAG));
|
|
|
+ return CalculateResult.error(msg, resultValue);
|
|
|
}
|
|
|
- // 校验成功,返回待计算的数据
|
|
|
- return CalculateResult.success(passList);
|
|
|
+ // 校验成功,将通过的数据放入passList
|
|
|
+ passList.add(calculationMap);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("{}{}", CalculateResult.MSG_DATA_CHECK_ERROR, e.toString());
|
|
|
+ return CalculateResult.error(CalculateResult.MSG_DATA_CHECK_ERROR);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (passList.isEmpty() && no_assessment.size() == calculationInfoListMap.size()) {
|
|
|
+ Map<String, Object> checkResult = CollUtil.getLast(no_assessment);
|
|
|
+ String resultValue = String.valueOf(checkResult.get(CalculateResult.DATA_TAG));
|
|
|
+ String msg = String.valueOf(checkResult.get(CalculateResult.MSG_TAG));
|
|
|
+ return CalculateResult.error(msg, resultValue);
|
|
|
}
|
|
|
+ // 校验成功,返回待计算的数据
|
|
|
+ return CalculateResult.success(passList);
|
|
|
+ }
|
|
|
|
|
|
- /**
|
|
|
- * 格式化被校验数据
|
|
|
- *
|
|
|
- * @return
|
|
|
- */
|
|
|
- private List<Map<String, Object>> getCalculationInfoList(List<CalculationInfo> calculationInfoList, BigDecimal electricCapacity) {
|
|
|
- List<Map<String, Object>> resultList = new ArrayList<>();
|
|
|
- long time;
|
|
|
- Date timeDate;
|
|
|
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
|
- // 循环每条数据
|
|
|
- for (CalculationInfo calculationInfo : calculationInfoList) {
|
|
|
- // 将bean BeanMap
|
|
|
- BeanMap beanMap = BeanMap.create(calculationInfo);
|
|
|
- Map<String, Object> map = new HashMap<>();
|
|
|
- // 将beanMap转为Map
|
|
|
- for (Object key : beanMap.keySet()) {
|
|
|
- map.put(String.valueOf(key), beanMap.get(key));
|
|
|
- if("time".equals(key.toString())){
|
|
|
- time = (long)beanMap.get(key);
|
|
|
- timeDate = new Date(time);
|
|
|
- map.put("timeStr", sdf.format(timeDate));
|
|
|
- }
|
|
|
- }
|
|
|
- map.put("electricCapacity", electricCapacity);
|
|
|
- resultList.add(map);
|
|
|
+ /**
|
|
|
+ * 格式化被校验数据
|
|
|
+ *
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private List<Map<String, Object>> getCalculationInfoList(List<CalculationInfo> calculationInfoList, BigDecimal electricCapacity) {
|
|
|
+ List<Map<String, Object>> resultList = new ArrayList<>();
|
|
|
+ long time;
|
|
|
+ Date timeDate;
|
|
|
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
|
+ // 循环每条数据
|
|
|
+ for (CalculationInfo calculationInfo : calculationInfoList) {
|
|
|
+ // 将bean BeanMap
|
|
|
+ BeanMap beanMap = BeanMap.create(calculationInfo);
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ // 将beanMap转为Map
|
|
|
+ for (Object key : beanMap.keySet()) {
|
|
|
+ map.put(String.valueOf(key), beanMap.get(key));
|
|
|
+ if ("time".equals(key.toString())) {
|
|
|
+ time = (long) beanMap.get(key);
|
|
|
+ timeDate = new Date(time);
|
|
|
+ map.put("timeStr", sdf.format(timeDate));
|
|
|
}
|
|
|
- return resultList;
|
|
|
+ }
|
|
|
+ map.put("electricCapacity", electricCapacity);
|
|
|
+ resultList.add(map);
|
|
|
}
|
|
|
+ return resultList;
|
|
|
+ }
|
|
|
|
|
|
- /**
|
|
|
- * 将多组计算准确率的数据,分组成每个文件类型为一组,并放入list中
|
|
|
- *
|
|
|
- * @param list
|
|
|
- * @param dataSourceType
|
|
|
- * @return
|
|
|
- */
|
|
|
- private List<List<Map<String, Object>>> groupingList(List<Map<String, Object>> list, String dataSourceType) {
|
|
|
- // 将文件类型转为arr
|
|
|
- String[] dataSourceTypeArr = dataSourceType.split(CalculateResult.COMMA);
|
|
|
- // 最终分好组的list
|
|
|
- List<List<Map<String, Object>>> groupingList = new ArrayList<>();
|
|
|
- // 同一个生成时间和同一个文件类型的数据,分再一组
|
|
|
- List<Map<String, Object>> group = new ArrayList<>();
|
|
|
- // 对比时间
|
|
|
- Date dataTime = (Date) list.get(0).get("genTime");
|
|
|
- for (String type : dataSourceTypeArr) {
|
|
|
- for (Map<String, Object> map : list) {
|
|
|
- // 获取数据生成时间
|
|
|
- Date forDataTime = (Date) map.get("genTime");
|
|
|
- // 如果当前数据的文件类型是当前循环中的
|
|
|
- if (map.get("dataSourceType").equals(type)) {
|
|
|
- // 如果当前数据和上一条数据的 生成时间相同,则放入组中
|
|
|
- if (dataTime.equals(forDataTime)) {
|
|
|
- group.add(map);
|
|
|
- // 如果不是,则将dataTime修改为新时间,并将之前的组数据放入最终list
|
|
|
- } else {
|
|
|
- dataTime = forDataTime;
|
|
|
- if (group.size() != 0) {
|
|
|
- groupingList.add(group);
|
|
|
- }
|
|
|
- // 清空之前的组,向组中放入本次内循环的数据
|
|
|
- group = new ArrayList<>();
|
|
|
- group.add(map);
|
|
|
- }
|
|
|
- // 如果当前数据的文件类型 不是当前循环中的,将之前的组存入最终list,并清空组
|
|
|
- } else {
|
|
|
- if (group.size() != 0) {
|
|
|
- groupingList.add(group);
|
|
|
- }
|
|
|
- group = new ArrayList<>();
|
|
|
- continue;
|
|
|
- }
|
|
|
- }
|
|
|
- // 内循环最后一次执行完后,将未保存的组数据存入最终list
|
|
|
+ /**
|
|
|
+ * 将多组计算准确率的数据,分组成每个文件类型为一组,并放入list中
|
|
|
+ *
|
|
|
+ * @param list
|
|
|
+ * @param dataSourceType
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private List<List<Map<String, Object>>> groupingList(List<Map<String, Object>> list, String dataSourceType) {
|
|
|
+ // 将文件类型转为arr
|
|
|
+ String[] dataSourceTypeArr = dataSourceType.split(CalculateResult.COMMA);
|
|
|
+ // 最终分好组的list
|
|
|
+ List<List<Map<String, Object>>> groupingList = new ArrayList<>();
|
|
|
+ // 同一个生成时间和同一个文件类型的数据,分再一组
|
|
|
+ List<Map<String, Object>> group = new ArrayList<>();
|
|
|
+ // 对比时间
|
|
|
+ Date dataTime = (Date) list.get(0).get("genTime");
|
|
|
+ for (String type : dataSourceTypeArr) {
|
|
|
+ for (Map<String, Object> map : list) {
|
|
|
+ // 获取数据生成时间
|
|
|
+ Date forDataTime = (Date) map.get("genTime");
|
|
|
+ // 如果当前数据的文件类型是当前循环中的
|
|
|
+ if (map.get("dataSourceType").equals(type)) {
|
|
|
+ // 如果当前数据和上一条数据的 生成时间相同,则放入组中
|
|
|
+ if (dataTime.equals(forDataTime)) {
|
|
|
+ group.add(map);
|
|
|
+ // 如果不是,则将dataTime修改为新时间,并将之前的组数据放入最终list
|
|
|
+ } else {
|
|
|
+ dataTime = forDataTime;
|
|
|
if (group.size() != 0) {
|
|
|
- groupingList.add(group);
|
|
|
+ groupingList.add(group);
|
|
|
}
|
|
|
+ // 清空之前的组,向组中放入本次内循环的数据
|
|
|
+ group = new ArrayList<>();
|
|
|
+ group.add(map);
|
|
|
+ }
|
|
|
+ // 如果当前数据的文件类型 不是当前循环中的,将之前的组存入最终list,并清空组
|
|
|
+ } else {
|
|
|
+ if (group.size() != 0) {
|
|
|
+ groupingList.add(group);
|
|
|
+ }
|
|
|
+ group = new ArrayList<>();
|
|
|
+ continue;
|
|
|
}
|
|
|
-
|
|
|
- return groupingList;
|
|
|
+ }
|
|
|
+ // 内循环最后一次执行完后,将未保存的组数据存入最终list
|
|
|
+ if (group.size() != 0) {
|
|
|
+ groupingList.add(group);
|
|
|
+ }
|
|
|
}
|
|
|
- /**
|
|
|
- * 将多日数据分成多组,并放入list中
|
|
|
- *
|
|
|
- * @param list
|
|
|
- * @return
|
|
|
- */
|
|
|
- private List<List<Map<String, Object>>> groupingDaysList(List<Map<String, Object>> list,String groupBy) {
|
|
|
- List<List<Map<String, Object>>> groupingList = new ArrayList<>();
|
|
|
-
|
|
|
- Map<String, List<Map<String, Object>>> groupedMap = list.stream()
|
|
|
- .collect(Collectors.groupingBy(map -> map.get(groupBy).toString().substring(0,10)));
|
|
|
-
|
|
|
- for (Map.Entry<String, List<Map<String, Object>>> entry : groupedMap.entrySet()) {
|
|
|
- groupingList.add(entry.getValue());
|
|
|
- }
|
|
|
- return groupingList;
|
|
|
+
|
|
|
+ return groupingList;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将多日数据分成多组,并放入list中
|
|
|
+ *
|
|
|
+ * @param list
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private List<List<Map<String, Object>>> groupingDaysList(List<Map<String, Object>> list, String groupBy) {
|
|
|
+ List<List<Map<String, Object>>> groupingList = new ArrayList<>();
|
|
|
+
|
|
|
+ Map<String, List<Map<String, Object>>> groupedMap = list.stream().collect(Collectors.groupingBy(map -> map.get(groupBy).toString().substring(0, 10)));
|
|
|
+
|
|
|
+ for (Map.Entry<String, List<Map<String, Object>>> entry : groupedMap.entrySet()) {
|
|
|
+ groupingList.add(entry.getValue());
|
|
|
}
|
|
|
+ return groupingList;
|
|
|
+ }
|
|
|
}
|
|
|
|