Browse Source

物计算优化-第二版

2025年12月1日18:16:30
qingyuan_dev_new
lis 1 month ago
parent
commit
201a4556a8
  1. 10
      common/core/src/main/java/com/thing/common/core/utils/FormulaUtil.java
  2. 100
      modules/calculation/src/main/java/com/thing/calculation/service/impl/CalcTargetConfigServiceImpl.java

10
common/core/src/main/java/com/thing/common/core/utils/FormulaUtil.java

@ -147,12 +147,12 @@ public class FormulaUtil {
* @return 计算结果 * @return 计算结果
*/ */
public static Object executeFormula(String formula, Map<String, Object> variableMap) { public static Object executeFormula(String formula, Map<String, Object> variableMap) {
Expression compiledExp = AviatorEvaluator.compile(formula);
Object result = compiledExp.execute(variableMap);
if (Objects.isNull(result)) {
throw new SysException("execute to a null result");
try {
Expression compiledExp = AviatorEvaluator.compile(formula);
return compiledExp.execute(variableMap);
}catch (Exception e){
return "0";
} }
return result;
} }
} }

100
modules/calculation/src/main/java/com/thing/calculation/service/impl/CalcTargetConfigServiceImpl.java

@ -2,6 +2,7 @@ package com.thing.calculation.service.impl;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import com.google.common.collect.Lists;
import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.query.QueryWrapper;
import com.thing.calculation.dto.*; import com.thing.calculation.dto.*;
import com.thing.calculation.entity.CalcSourceConfigEntity; import com.thing.calculation.entity.CalcSourceConfigEntity;
@ -23,22 +24,28 @@ import com.thing.common.core.utils.DateTimeUtils;
import com.thing.common.core.utils.FormulaUtil; import com.thing.common.core.utils.FormulaUtil;
import com.thing.common.core.utils.excel.ExcelUtils; import com.thing.common.core.utils.excel.ExcelUtils;
import com.thing.common.core.web.response.PageData; import com.thing.common.core.web.response.PageData;
import com.thing.common.data.event.QueueConsumerEvent;
import com.thing.common.data.proto.QueueProto;
import com.thing.common.data.tskv.TsKvDTO; import com.thing.common.data.tskv.TsKvDTO;
import com.thing.common.orm.service.impl.BaseServiceImpl; import com.thing.common.orm.service.impl.BaseServiceImpl;
import com.thing.common.orm.utils.IdGenerator; import com.thing.common.orm.utils.IdGenerator;
import com.thing.common.tskv.service.TsKvService; import com.thing.common.tskv.service.TsKvService;
import com.thing.queue.util.Topics;
import com.thing.sys.security.context.UserContext; import com.thing.sys.security.context.UserContext;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.MapUtils; import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*; import java.util.*;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
@ -64,6 +71,7 @@ public class CalcTargetConfigServiceImpl
private final CalcExecuteHandler calcExecuteHandler; private final CalcExecuteHandler calcExecuteHandler;
private final CalcLogSaveHandler calcLogSaveHandler; private final CalcLogSaveHandler calcLogSaveHandler;
private final CalcSourceConfigService calcSourceConfigService; private final CalcSourceConfigService calcSourceConfigService;
private final ApplicationEventPublisher publisher;
/** 变量池:A ~ Z */ /** 变量池:A ~ Z */
// private static final List<String> variablePool = new ArrayList<>(); // private static final List<String> variablePool = new ArrayList<>();
@ -380,7 +388,33 @@ public class CalcTargetConfigServiceImpl
List<Long> ids = request.getCalcTargetConfigIds(); List<Long> ids = request.getCalcTargetConfigIds();
List<CalcTargetConfigDTO> configList = getListByIdsAs(ids, CalcTargetConfigDTO.class); List<CalcTargetConfigDTO> configList = getListByIdsAs(ids, CalcTargetConfigDTO.class);
fillData(configList); fillData(configList);
List<CalcSourceConfigDTO> sourceConfigs =
Long startTime = DateTimeUtils.convertTimeToLong(request.getStartTime());
Long endTime = DateTimeUtils.convertTimeToLong(request.getEndTime());
//开始======================================================
List<QueueProto.DataProto> protoList = new ArrayList<>();
for (CalcTargetConfigDTO config : configList) {
List<CalcSourceConfigDTO> sourceConfigs = config.getSourceConfigs();
//转换入参
Map<String, Collection<String>> multiMap = convertParam(sourceConfigs);
//查询计算目标的最新值
List<TsKvDTO> tsKvByMultiMap = tsKvService.findTsKvByMultiMap(multiMap, startTime, endTime, true);
if(CollectionUtil.isEmpty(tsKvByMultiMap)){
//若是source tskv值是空的,则跳过
continue;
}
getCalResult(config, tsKvByMultiMap, protoList, sourceConfigs);
}
if(CollectionUtil.isEmpty(protoList)){
return;
}
List<QueueProto.DataProto> list = protoList.stream().sorted(Comparator.comparing(s -> s.getTskvProto().getTs())).toList();
// 批量推送
publisher.publishEvent(
new QueueConsumerEvent(Topics.V1_TSKV_CALC_LOG_CAL.getValue(), list));
/* List<CalcSourceConfigDTO> sourceConfigs =
configList.stream() configList.stream()
.map(CalcTargetConfigDTO::getSourceConfigs) .map(CalcTargetConfigDTO::getSourceConfigs)
.filter(Objects::nonNull) .filter(Objects::nonNull)
@ -403,7 +437,69 @@ public class CalcTargetConfigServiceImpl
calcLogSaveHandler.handleLogSave(tskvList, configList, true); calcLogSaveHandler.handleLogSave(tskvList, configList, true);
// 立即执行计算 // 立即执行计算
calcExecuteHandler.handleCalculate(new ExecuteCalcRequest(request.getStartTime(), request.getEndTime()),ids);
calcExecuteHandler.handleCalculate(new ExecuteCalcRequest(request.getStartTime(), request.getEndTime()),ids);*/
}
private static void getCalResult(CalcTargetConfigDTO config, List<TsKvDTO> tsKvByMultiMap, List<QueueProto.DataProto> protoList, List<CalcSourceConfigDTO> sourceConfigs) {
//若有source tskv值,则计算结果
Map<Long, List<TsKvDTO>> tsMap = tsKvByMultiMap.stream().collect(Collectors.groupingBy(TsKvDTO::getTs));
for (Map.Entry<Long, List<TsKvDTO>> entry : tsMap.entrySet()) {
if(config.getConfigType().equals(CalcConfigType.DATA_MAPPING.getCode()) || config.getConfigType().equals(CalcConfigType.AGG_MAPPING.getCode())){
//直接计算结果
BigDecimal totalVal =
entry.getValue().stream()
.map(s-> new BigDecimal(s.getVal()))
.reduce(BigDecimal.ZERO, BigDecimal::add).setScale(4, RoundingMode.HALF_UP);
QueueProto.TsKvProto tsKvProto =
QueueProto.TsKvProto.newBuilder()
.setThingCode(config.getTargetThingCode())
.setKey(config.getTargetAttrCode())
.setTs(entry.getKey())
.setVal(totalVal.toPlainString())
.build();
protoList.add(
QueueProto.DataProto.newBuilder().setTskvProto(tsKvProto).build());
}else{
//公式计算
Map<String, Object> variableMap = new HashMap<>();
for (CalcSourceConfigDTO sourceConfig : sourceConfigs) {
TsKvDTO tsKvDTO = entry.getValue().stream().filter(s -> s.getThingCode().equals(sourceConfig.getSourceThingCode())
&& s.getAttrKey().equals(sourceConfig.getSourceAttrCode())).findFirst().orElse(null);
if(!Objects.isNull(tsKvDTO)){
variableMap.put(sourceConfig.getSourceAttrAlias(), new BigDecimal(tsKvDTO.getVal()));
}else{
variableMap.put(sourceConfig.getSourceAttrAlias(), BigDecimal.ZERO);
}
}
Object result = FormulaUtil.executeFormula(config.getFormula(), variableMap);
QueueProto.TsKvProto tsKvProto =
QueueProto.TsKvProto.newBuilder()
.setThingCode(config.getTargetThingCode())
.setKey(config.getTargetAttrCode())
.setTs(entry.getKey())
.setVal(new BigDecimal(result.toString()).setScale(4, RoundingMode.HALF_UP).toPlainString())
.build();
protoList.add(
QueueProto.DataProto.newBuilder().setTskvProto(tsKvProto).build());
}
}
}
@NotNull
private static Map<String, Collection<String>> convertParam(List<CalcSourceConfigDTO> sourceConfigs) {
//将sourceConfigs 转换入参
Map<String, Collection<String>> multiMap = new HashMap<>();
for (CalcSourceConfigDTO sourceConfig : sourceConfigs) {
if(multiMap.containsKey(sourceConfig.getSourceThingCode())){
Collection<String> list = multiMap.get(sourceConfig.getSourceThingCode());
list.add(sourceConfig.getSourceAttrCode());
multiMap.put(sourceConfig.getSourceThingCode(), list);
}else{
multiMap.put(sourceConfig.getSourceThingCode(), Lists.newArrayList(sourceConfig.getSourceAttrCode()));
}
}
return multiMap;
} }
@Override @Override

Loading…
Cancel
Save