火力规则:java静态方法实现规则
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package com.solution.rule.domain.ultimately.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
@@ -23,7 +24,14 @@ public class FireRuleInputDTO {
|
||||
private List<FireRuleTaskInputDTO> tasks;
|
||||
|
||||
/**
|
||||
* 红方侧异构条目列表(武器、场景任务节点、装备、指挥所、防区等)
|
||||
* 红方装备等条目列表,对应 JSON 键 {@code redWeapons}(当前 {@link FireRuleInputRedWeaponElementDTO} 与装备结构一致)
|
||||
*/
|
||||
private List<FireRuleInputRedWeaponElementDTO> redWeapons;
|
||||
@JsonProperty("equipments")
|
||||
private List<FireRuleInputRedWeaponElementDTO> equipments;
|
||||
|
||||
/**
|
||||
* 阵营与姿态关系列表,对应 JSON 键 {@code ForceSides}
|
||||
*/
|
||||
@JsonProperty("ForceSides")
|
||||
private List<FireRuleInputForceSideDTO> forceSides;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.solution.rule.domain.ultimately.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 阵营侧一方与其它方的姿态关系项
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class FireRuleInputForcePostureDTO {
|
||||
|
||||
@JsonProperty("ObjectHandle")
|
||||
private String objectHandle;
|
||||
|
||||
@JsonProperty("Type")
|
||||
private Integer type;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.solution.rule.domain.ultimately.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 阵营侧(ForceSides 数组中的一项)
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class FireRuleInputForceSideDTO {
|
||||
|
||||
private String groupType;
|
||||
|
||||
@JsonProperty("Postures")
|
||||
private List<FireRuleInputForcePostureDTO> postures;
|
||||
|
||||
@JsonProperty("ObjectHandle")
|
||||
private String objectHandle;
|
||||
|
||||
@JsonProperty("ForceSideName")
|
||||
private String forceSideName;
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.solution.rule.domain.ultimately.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 防区圆形条目中 isWing 为对象时的样式字段
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class FireRuleInputRedCircleStyleDTO {
|
||||
|
||||
private String outlineWidth;
|
||||
|
||||
private String lineType;
|
||||
|
||||
private String outlineColor;
|
||||
|
||||
private String color;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.solution.rule.domain.ultimately.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* redWeapons 条目中 isLead:可能是长机编队参数,也可能是圆形防区参数(字段并集)
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class FireRuleInputRedLeadPayloadDTO {
|
||||
|
||||
private String leader;
|
||||
|
||||
private String side;
|
||||
|
||||
private String supportType;
|
||||
|
||||
private List<FireRuleInputRedLeadPositionDTO> positions;
|
||||
|
||||
private String drawName;
|
||||
|
||||
private String airspaceType;
|
||||
|
||||
private String selectLonLat;
|
||||
|
||||
private String radius;
|
||||
|
||||
private String height;
|
||||
|
||||
private String extrudedHeight;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.solution.rule.domain.ultimately.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 长机/圆形等结构中的坐标点(示例中可能为数值或占位字符串)
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class FireRuleInputRedLeadPositionDTO {
|
||||
|
||||
private String longitude;
|
||||
|
||||
private String latitude;
|
||||
|
||||
private String height;
|
||||
}
|
||||
@@ -4,44 +4,16 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 输入 JSON 中 {@code redWeapons} 数组元素并集:武器摘要、红方装备、营指挥所、防区圆形等形态共用此类。
|
||||
* <p>
|
||||
* {@code isWing} 在 JSON 中可能为僚机数组或圆形样式对象,故使用 {@link Object} 承接;可结合
|
||||
* {@link FireRuleInputRedWingItemDTO}、{@link FireRuleInputRedCircleStyleDTO} 在业务层转型。
|
||||
* {@code redWeapons} 中红方装备(platform)条目,与 {@code 火力规则输入-无注释.json} 中带
|
||||
* {@code SubComponents} 的装备对象字段一致。
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class FireRuleInputRedWeaponElementDTO {
|
||||
|
||||
private String name;
|
||||
|
||||
@JsonProperty("Name")
|
||||
private String displayName;
|
||||
|
||||
private String id;
|
||||
|
||||
@JsonProperty("EquipmentID")
|
||||
private String equipmentId;
|
||||
|
||||
private List<FireRuleWeaponComponentDTO> components;
|
||||
|
||||
private Object number;
|
||||
|
||||
private String successTargetRad;
|
||||
|
||||
private FireRuleInputRedLeadPayloadDTO isLead;
|
||||
|
||||
private Object isWing;
|
||||
|
||||
/**
|
||||
* 装备类条目中为 {@code equipment} 等
|
||||
*/
|
||||
private String groupType;
|
||||
|
||||
@JsonProperty("SupportType")
|
||||
private String supportType;
|
||||
|
||||
@@ -59,6 +31,14 @@ public class FireRuleInputRedWeaponElementDTO {
|
||||
|
||||
private Boolean isDefendImportantPlace;
|
||||
|
||||
private String groupType;
|
||||
|
||||
@JsonProperty("EquipmentID")
|
||||
private String equipmentId;
|
||||
|
||||
@JsonProperty("Name")
|
||||
private String name;
|
||||
|
||||
@JsonProperty("OwnerForceSide")
|
||||
private String ownerForceSide;
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
package com.solution.rule.domain.ultimately.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class FireRuleInputRedWingItemDTO {
|
||||
|
||||
private String name;
|
||||
|
||||
private String distance;
|
||||
|
||||
private String angle;
|
||||
|
||||
private String alt;
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
/**
|
||||
* 火力规则输入侧 DTO,与 {@code resources/json/火力规则输入-无注释.json} 对齐。
|
||||
* <p>
|
||||
* {@code redWeapons} 数组元素为并集类型 {@link com.solution.rule.domain.ultimately.dto.FireRuleInputRedWeaponElementDTO},
|
||||
* 常见形态包括:武器摘要、红方装备(含子组件)、营指挥所、防区圆形等。
|
||||
* {@code redWeapons} 中装备项为 {@link com.solution.rule.domain.ultimately.dto.FireRuleInputRedWeaponElementDTO}(含 {@code SubComponents})。
|
||||
*/
|
||||
package com.solution.rule.domain.ultimately.dto;
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
//package com.solution.rule.parser;
|
||||
//
|
||||
//import com.fasterxml.jackson.core.JsonParser;
|
||||
//import com.fasterxml.jackson.core.JsonToken;
|
||||
//import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
//import javax.servlet.http.HttpServletRequest;
|
||||
//import java.io.IOException;
|
||||
//import java.util.*;
|
||||
//
|
||||
//public class JsonStreamParser {
|
||||
//
|
||||
// // 核心:解析所有集合 → 内存关联ID → 组装完整数据
|
||||
// public List<AssembledWeapon> parseAndAssemble(HttpServletRequest request) throws IOException {
|
||||
// ObjectMapper mapper = new ObjectMapper();
|
||||
// try (JsonParser parser = mapper.getFactory().createParser(request.getInputStream())) {
|
||||
//
|
||||
// // ========== 步骤1:流式解析,把所有关联集合存到内存 ==========
|
||||
// String version = null;
|
||||
// // 存储所有集合:key=集合名(weaponList/weaponParams),value=数据列表
|
||||
// Map<String, List<Map<String, Object>>> allCollections = new HashMap<>();
|
||||
//
|
||||
// // 解析状态
|
||||
// String currentCollection = null;
|
||||
// Map<String, Object> currentItem = null;
|
||||
//
|
||||
// JsonToken token;
|
||||
// while ((token = parser.nextToken()) != null) {
|
||||
// switch (token) {
|
||||
// case START_OBJECT:
|
||||
// if (currentCollection != null) currentItem = new HashMap<>();
|
||||
// break;
|
||||
// case END_OBJECT:
|
||||
// if (currentCollection != null && currentItem != null) {
|
||||
// allCollections.get(currentCollection).add(currentItem);
|
||||
// currentItem = null;
|
||||
// }
|
||||
// break;
|
||||
// case START_ARRAY:
|
||||
// currentCollection = parser.getCurrentName();
|
||||
// allCollections.putIfAbsent(currentCollection, new ArrayList<>());
|
||||
// break;
|
||||
// case END_ARRAY:
|
||||
// currentCollection = null;
|
||||
// break;
|
||||
// case FIELD_NAME:
|
||||
// String field = parser.getCurrentName();
|
||||
// // 解析版本号
|
||||
// if ("version".equals(field) && isInMeta(parser)) {
|
||||
// version = parser.nextTextValue();
|
||||
// break;
|
||||
// }
|
||||
// // 解析普通字段
|
||||
// if (currentItem != null) {
|
||||
// parser.nextToken();
|
||||
// currentItem.put(field, getValue(parser));
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // ========== 步骤2:核心!通过ID关联匹配,组装完整数据 ==========
|
||||
// return assembleFullWeaponData(allCollections);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 【核心逻辑】ID关联匹配:武器列表 + 参数列表 → 完整武器
|
||||
// */
|
||||
// private List<AssembledWeapon> assembleFullWeaponData(Map<String, List<Map<String, Object>>> allCollections) {
|
||||
// List<AssembledWeapon> result = new ArrayList<>();
|
||||
//
|
||||
// // 1. 获取武器主列表
|
||||
// List<Map<String, Object>> weaponList = allCollections.getOrDefault("weaponList", Collections.emptyList());
|
||||
// // 2. 获取武器参数列表
|
||||
// List<Map<String, Object>> paramList = allCollections.getOrDefault("weaponParams", Collections.emptyList());
|
||||
//
|
||||
// // 3. 构建【ID -> 参数】索引Map(O(1)快速匹配,效率最高)
|
||||
// Map<Long, Map<String, Object>> paramIndex = new HashMap<>();
|
||||
// for (Map<String, Object> param : paramList) {
|
||||
// Long weaponId = Long.valueOf(param.get("weaponId").toString());
|
||||
// paramIndex.put(weaponId, param);
|
||||
// }
|
||||
//
|
||||
// // 4. 遍历武器,通过ID匹配参数,组装完整对象
|
||||
// for (Map<String, Object> weapon : weaponList) {
|
||||
// AssembledWeapon fullWeapon = new AssembledWeapon();
|
||||
// Long weaponId = Long.valueOf(weapon.get("id").toString());
|
||||
//
|
||||
// // 填充基础信息
|
||||
// fullWeapon.setId(weaponId);
|
||||
// fullWeapon.setName((String) weapon.get("name"));
|
||||
//
|
||||
// // 匹配参数(通过ID)
|
||||
// Map<String, Object> param = paramIndex.get(weaponId);
|
||||
// if (param != null) {
|
||||
// fullWeapon.setDamage(Integer.valueOf(param.get("damage").toString()));
|
||||
// fullWeapon.setMagazine(Integer.valueOf(param.get("magazine").toString()));
|
||||
// fullWeapon.setType((String) param.get("type"));
|
||||
// }
|
||||
//
|
||||
// result.add(fullWeapon);
|
||||
// }
|
||||
//
|
||||
// return result;
|
||||
// }
|
||||
//
|
||||
// // ---------------- 工具方法 ----------------
|
||||
// private boolean isInMeta(JsonParser parser) {
|
||||
// return parser.getParsingContext().getParent() != null
|
||||
// && "meta".equals(parser.getParsingContext().getParent().getCurrentName());
|
||||
// }
|
||||
//
|
||||
// private Object getValue(JsonParser parser) throws IOException {
|
||||
// if (parser.getCurrentToken().isNumeric()) return parser.getLongValue();
|
||||
// if (parser.getCurrentToken() == JsonToken.VALUE_STRING) return parser.getText();
|
||||
// if (parser.getCurrentToken() == JsonToken.VALUE_TRUE) return true;
|
||||
// if (parser.getCurrentToken() == JsonToken.VALUE_FALSE) return false;
|
||||
// return null;
|
||||
// }
|
||||
//}
|
||||
@@ -9,6 +9,7 @@ import com.solution.rule.domain.simplerulepojo.Task;
|
||||
import com.solution.rule.domain.simplerulepojo.Weapon;
|
||||
import com.solution.rule.domain.simplerulepojo.fact.FactTask;
|
||||
import com.solution.rule.domain.ultimately.dto.FireRuleInputDTO;
|
||||
import com.solution.rule.domain.ultimately.dto.FireRuleInputForceSideDTO;
|
||||
import com.solution.rule.domain.ultimately.dto.FireRuleInputRedWeaponElementDTO;
|
||||
import com.solution.rule.domain.ultimately.dto.FireRuleTaskInputDTO;
|
||||
import com.solution.rule.domain.ultimately.fact.DroolsFact;
|
||||
@@ -209,8 +210,20 @@ public class FireRuleServiceImpl implements FireRuleService {
|
||||
//设置Drools全局变量
|
||||
Map<String, Object> globalParams = new HashMap<>();
|
||||
kieSession.setGlobal("globalParams", globalParams);
|
||||
kieSession.insert(globalParams);
|
||||
//获取红方阵营id
|
||||
String redObjectHandleId = getObjectHandle(task);
|
||||
if(ObjectUtil.isEmpty(redObjectHandleId)){
|
||||
throw new RuntimeException(ExceptionConstants.PARAMETER_EXCEPTION);
|
||||
}
|
||||
//获取所有武器库
|
||||
List<FireRuleInputRedWeaponElementDTO> allWeapons = task.getEquipments();
|
||||
//获取红方武器库
|
||||
List<FireRuleInputRedWeaponElementDTO> redWeapons = task.getRedWeapons();
|
||||
List<FireRuleInputRedWeaponElementDTO> redWeapons = allWeapons.stream()
|
||||
.filter(weapon -> redObjectHandleId.equals(weapon.getOwnerForceSide()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
|
||||
//创建返回数据
|
||||
FireRuleOutputVO fireRuleOutputVO = new FireRuleOutputVO();
|
||||
fireRuleOutputVO.setSourceFile(task.getSourceFile());
|
||||
@@ -259,4 +272,15 @@ public class FireRuleServiceImpl implements FireRuleService {
|
||||
return ruleMapper.findAllBasicPlatformComponents();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取红方阵营id
|
||||
* @param task
|
||||
* @return
|
||||
*/
|
||||
private String getObjectHandle(FireRuleInputDTO task){
|
||||
List<FireRuleInputForceSideDTO> forceSides = task.getForceSides();
|
||||
List<FireRuleInputForceSideDTO> collect = forceSides.stream().filter(f -> "红方".equals(f.getForceSideName())).collect(Collectors.toList());
|
||||
return collect.get(0).getObjectHandle();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.solution.rule.utils;
|
||||
|
||||
import com.solution.rule.domain.ultimately.dto.FireRuleTaskInputDTO;
|
||||
import com.solution.rule.domain.ultimately.fact.DroolsFact;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 规则函数方法
|
||||
*/
|
||||
public class RuleFunction {
|
||||
|
||||
|
||||
/**
|
||||
* 装备匹配
|
||||
*/
|
||||
public static void equipmentRule(DroolsFact task, Map globalParams){
|
||||
//空中总分数
|
||||
Integer airScore = 0;
|
||||
//反坦克总分数
|
||||
Integer antitankScore = 0;
|
||||
//远程打击总分数
|
||||
Integer remoteScore = 0;
|
||||
|
||||
FireRuleTaskInputDTO blueTask = task.getTask();
|
||||
|
||||
//权重因子
|
||||
Integer weight = (Integer) globalParams.get("weight");
|
||||
String drawName = blueTask.getDrawName();
|
||||
if("".contains(drawName)){
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
3500
auto-solution-rule/src/main/resources/legacy/fire-rule.drl
Normal file
3500
auto-solution-rule/src/main/resources/legacy/fire-rule.drl
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,37 @@
|
||||
package rules;
|
||||
|
||||
import com.solution.rule.domain.ultimately.fact.DroolsFact;
|
||||
import java.util.Map;
|
||||
|
||||
import com.solution.rule.utils.RuleFunction.equipmentRule;
|
||||
|
||||
|
||||
global java.util.Map globalParams;
|
||||
|
||||
function Map buildParam(){
|
||||
Map param = new java.util.HashMap();
|
||||
//权重因子
|
||||
param.put("weight", 1);
|
||||
//最低入选分数
|
||||
param.put("minSelectedScore",1);
|
||||
//蓝方坦克类 -> 红方反坦克加分
|
||||
param.put("tankScore", 1);
|
||||
//蓝方空中类 -> 红方反空中加分
|
||||
param.put("airScore", 2);
|
||||
//蓝方地面类 -> 红方远程打击加分
|
||||
param.put("groundScore", 1);
|
||||
//蓝方有导弹 -> 红方防空加分
|
||||
param.put("missileScore", 1);
|
||||
//蓝方是空中任务 -> 红方防空加分
|
||||
param.put("airTaskScore", 10);
|
||||
|
||||
}
|
||||
|
||||
rule "装备匹配"
|
||||
salience 100
|
||||
when
|
||||
$fact : DroolsFact(task.side != "")
|
||||
then
|
||||
//如何引入Java静态方法?
|
||||
equipmentRule($fact, globalParams);
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user