diff --git a/common/core/src/main/java/com/thing/common/core/utils/FormulaUtil.java b/common/core/src/main/java/com/thing/common/core/utils/FormulaUtil.java index fb3b8d8..88fbf4d 100644 --- a/common/core/src/main/java/com/thing/common/core/utils/FormulaUtil.java +++ b/common/core/src/main/java/com/thing/common/core/utils/FormulaUtil.java @@ -147,12 +147,12 @@ public class FormulaUtil { * @return 计算结果 */ public static Object executeFormula(String formula, Map 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; } } diff --git a/modules/calculation/src/main/java/com/thing/calculation/service/impl/CalcTargetConfigServiceImpl.java b/modules/calculation/src/main/java/com/thing/calculation/service/impl/CalcTargetConfigServiceImpl.java index cc05865..83d760a 100644 --- a/modules/calculation/src/main/java/com/thing/calculation/service/impl/CalcTargetConfigServiceImpl.java +++ b/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.util.ObjectUtil; +import com.google.common.collect.Lists; import com.mybatisflex.core.query.QueryWrapper; import com.thing.calculation.dto.*; 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.excel.ExcelUtils; 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.orm.service.impl.BaseServiceImpl; import com.thing.common.orm.utils.IdGenerator; import com.thing.common.tskv.service.TsKvService; +import com.thing.queue.util.Topics; import com.thing.sys.security.context.UserContext; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.web.multipart.MultipartFile; import java.math.BigDecimal; +import java.math.RoundingMode; import java.util.*; import java.util.function.Consumer; import java.util.function.Function; @@ -64,6 +71,7 @@ public class CalcTargetConfigServiceImpl private final CalcExecuteHandler calcExecuteHandler; private final CalcLogSaveHandler calcLogSaveHandler; private final CalcSourceConfigService calcSourceConfigService; + private final ApplicationEventPublisher publisher; /** 变量池:A ~ Z */ // private static final List variablePool = new ArrayList<>(); @@ -380,7 +388,33 @@ public class CalcTargetConfigServiceImpl List ids = request.getCalcTargetConfigIds(); List configList = getListByIdsAs(ids, CalcTargetConfigDTO.class); fillData(configList); - List sourceConfigs = + Long startTime = DateTimeUtils.convertTimeToLong(request.getStartTime()); + Long endTime = DateTimeUtils.convertTimeToLong(request.getEndTime()); + //开始====================================================== + List protoList = new ArrayList<>(); + for (CalcTargetConfigDTO config : configList) { + List sourceConfigs = config.getSourceConfigs(); + //转换入参 + Map> multiMap = convertParam(sourceConfigs); + //查询计算目标的最新值 + List 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 list = protoList.stream().sorted(Comparator.comparing(s -> s.getTskvProto().getTs())).toList(); + // 批量推送 + publisher.publishEvent( + new QueueConsumerEvent(Topics.V1_TSKV_CALC_LOG_CAL.getValue(), list)); + + + /* List sourceConfigs = configList.stream() .map(CalcTargetConfigDTO::getSourceConfigs) .filter(Objects::nonNull) @@ -403,7 +437,69 @@ public class CalcTargetConfigServiceImpl 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 tsKvByMultiMap, List protoList, List sourceConfigs) { + //若有source tskv值,则计算结果 + Map> tsMap = tsKvByMultiMap.stream().collect(Collectors.groupingBy(TsKvDTO::getTs)); + for (Map.Entry> 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 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> convertParam(List sourceConfigs) { + //将sourceConfigs 转换入参 + Map> multiMap = new HashMap<>(); + for (CalcSourceConfigDTO sourceConfig : sourceConfigs) { + if(multiMap.containsKey(sourceConfig.getSourceThingCode())){ + Collection 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