|
@@ -0,0 +1,84 @@
|
|
|
|
|
+package com.etotem.cfc.service;
|
|
|
|
|
+
|
|
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
+import com.etotem.cfc.entity.EnergyDimension;
|
|
|
|
|
+import com.etotem.cfc.entity.EnergyRule;
|
|
|
|
|
+import com.etotem.cfc.mapper.EnergyDimensionMapper;
|
|
|
|
|
+import com.etotem.cfc.mapper.EnergyRuleMapper;
|
|
|
|
|
+import com.fasterxml.jackson.core.type.TypeReference;
|
|
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
|
+import javax.annotation.Resource;
|
|
|
|
|
+import java.util.List;
|
|
|
|
|
+import java.util.Map;
|
|
|
|
|
+
|
|
|
|
|
+@Slf4j
|
|
|
|
|
+@Service
|
|
|
|
|
+public class EnergyRuleEngine {
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private EnergyRuleMapper energyRuleMapper;
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private EnergyDimensionMapper energyDimensionMapper;
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private EnergyService energyService;
|
|
|
|
|
+ private final ObjectMapper objectMapper = new ObjectMapper();
|
|
|
|
|
+
|
|
|
|
|
+ public List<EnergyRule> findActiveRules(String eventType) {
|
|
|
|
|
+ return energyRuleMapper.selectList(
|
|
|
|
|
+ new LambdaQueryWrapper<EnergyRule>()
|
|
|
|
|
+ .eq(EnergyRule::getEventType, eventType)
|
|
|
|
|
+ .eq(EnergyRule::getStatus, 1)
|
|
|
|
|
+ .orderByDesc(EnergyRule::getPriority)
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public void evaluate(String eventType, Long sourceId, Long childId, Map<String, Object> context) {
|
|
|
|
|
+ List<EnergyRule> rules = findActiveRules(eventType);
|
|
|
|
|
+ if (rules.isEmpty()) return;
|
|
|
|
|
+ for (EnergyRule rule : rules) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ if (!matchesConditions(rule, context)) continue;
|
|
|
|
|
+ int amount = calculateAmount(rule, context);
|
|
|
|
|
+ if (amount == 0) continue;
|
|
|
|
|
+ Long dimId = resolveDimensionId(rule);
|
|
|
|
|
+ if ("increase".equals(rule.getAction())) {
|
|
|
|
|
+ energyService.awardEnergy(childId, eventType, sourceId, amount, rule.getDescription(), null);
|
|
|
|
|
+ } else if ("decrease".equals(rule.getAction())) {
|
|
|
|
|
+ energyService.deductEnergy(childId, dimId, Math.abs(amount), rule.getDescription());
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("规则执行失败: ruleId={}, error={}", rule.getId(), e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private boolean matchesConditions(EnergyRule rule, Map<String, Object> context) {
|
|
|
|
|
+ if (rule.getConditions() == null || rule.getConditions().isEmpty()) return true;
|
|
|
|
|
+ try {
|
|
|
|
|
+ Map<String, Object> conditions = objectMapper.readValue(rule.getConditions(), new TypeReference<Map<String, Object>>() {});
|
|
|
|
|
+ for (Map.Entry<String, Object> entry : conditions.entrySet()) {
|
|
|
|
|
+ Object ctxValue = context.get(entry.getKey());
|
|
|
|
|
+ if (ctxValue == null || !ctxValue.equals(entry.getValue())) return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ return true;
|
|
|
|
|
+ } catch (Exception e) { log.warn("条件解析失败: ruleId={}", rule.getId()); return false; }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private int calculateAmount(EnergyRule rule, Map<String, Object> context) {
|
|
|
|
|
+ if (rule.getAmount() != null && rule.getAmount() != 0) return rule.getAmount();
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Long resolveDimensionId(EnergyRule rule) {
|
|
|
|
|
+ if (rule.getDimensionCode() == null || rule.getDimensionCode().isEmpty()) return null;
|
|
|
|
|
+ EnergyDimension dim = energyDimensionMapper.selectOne(
|
|
|
|
|
+ new LambdaQueryWrapper<EnergyDimension>().eq(EnergyDimension::getCode, rule.getDimensionCode()).last("LIMIT 1"));
|
|
|
|
|
+ return dim != null ? dim.getId() : null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public List<EnergyDimension> getAllDimensions() {
|
|
|
|
|
+ return energyDimensionMapper.selectList(
|
|
|
|
|
+ new LambdaQueryWrapper<EnergyDimension>().eq(EnergyDimension::getStatus, 1).orderByAsc(EnergyDimension::getSortOrder));
|
|
|
|
|
+ }
|
|
|
|
|
+}
|