Files
auto-solution/auto-solution-rule/src/main/resources/rules/rule.drl

182 lines
11 KiB
Plaintext
Raw Normal View History

package rules;
import com.solution.rule.domain.ultimately.fact.DroolsFact;
import java.util.Map;
import static com.solution.rule.utils.RuleFunction.equipmentRule;
import static com.solution.rule.utils.RuleFunction.target;
import static com.solution.rule.utils.RuleFunction.position;
global java.util.Map globalParams;
/**
* 构建装备匹配所需的全部可调参数(会 merge 进 globalParams覆盖 Java 侧同名默认值)。
*
* ========== 总体运算逻辑(与 RuleFunction.equipmentRule 一致)==========
* 1先拼「蓝方文本串」blueBlob任务 drawName、dataType、taskWeapons 下各武器的 name/supportType/equipmentId、组件 deviceName。
* 2对每个红方装备拼「红方文本串」redBlobname、platform_type、SupportType。
* 3每件红装得分 score = 规则槽得分(scoreRuleSlots) + 兼容层得分(scoreLegacyLayer),均为整数。
* - 规则槽:对 i=1..ruleSlotCount若 blueBlob 命中 blueRuleKeywords_i 且 redBlob 命中 redRuleKeywords_i
* 则加上 ruleScore_i * weight。
* - 兼容层:多组「蓝关键词 + 红关键词 + 对应分数」,见下方各键说明;每组条件同时满足则加上 对应Score * weight。
* 4在池中取 score 最大者;若多人并列,由 tieBreak 决定(见 tieBreak
* 5若 maxScore < minSelectedScore视为未匹配不往 fireRuleInputs 追加行redWeapons 输出仍为当前池。
* 6若匹配成功从池中 remove 该件fireRuleInputs 追加一行drawName 后接 outputDrawNameSuffixtaskWeapons 填选中红装映射。
*
* 关键词格式英文逗号分隔子串包含即算命中contains不要求整词匹配。
*/
function Map buildParam(){
Map param = new java.util.HashMap();
// ---------- 全局倍率与门槛 ----------
// weight对上述所有「基础分数」的统一乘数规则槽的 ruleScore_i、兼容层的 *Score 都会乘 weight
param.put("weight", 1);
// minSelectedScore单件红装总分达到该值及以上才会被选中并写入 fireRuleInputs否则本任务视为未匹配到装备。
param.put("minSelectedScore", 1);
// tieBreak并列最高分时的决胜方式。当前实现仅支持 "equipmentId":装备 ID 字典序更小的优先。
param.put("tieBreak", "equipmentId");
// outputDrawNameSuffix匹配成功写入 fireRuleInputs 时,在蓝方原 drawName 后面拼接的后缀(如「打击任务」)。
param.put("outputDrawNameSuffix", "打击任务");
// ---------- 规则槽(可配置条数,便于只改本文件而不改 Java----------
// ruleSlotCount启用几条槽规则第 i 条使用 blueRuleKeywords_i、redRuleKeywords_i、ruleScore_i。
param.put("ruleSlotCount", 3);
// 槽1蓝方文本中出现任一子串 且 红方文本中出现任一子串 → 加 ruleScore_1 * weight。
param.put("blueRuleKeywords_1", "F-16,F-35");
param.put("redRuleKeywords_1", "防空,导弹,无人机");
param.put("ruleScore_1", 5);
param.put("blueRuleKeywords_2", "坦克,装甲");
param.put("redRuleKeywords_2", "反坦克");
param.put("ruleScore_2", 4);
param.put("blueRuleKeywords_3", "地面,突击");
param.put("redRuleKeywords_3", "远火,榴弹,炮");
param.put("ruleScore_3", 2);
// ---------- 兼容层:按「场景关键词」配对加分(与 RuleFunction.scoreLegacyLayer 一一对应)----------
// 以下每组均为:蓝方文本命中第一列关键词 且 红方文本命中第二列关键词 → 加 第三列分数 * weight。
//
// ① 空中平台类:蓝方像「对空/机型」且红方像对空装备 → + airScore * weight
param.put("bluePlatformKeywords_air", "F-16,J-10,F-35");
param.put("redPreferredWhenBlueAir", "防空,导弹,无人机,直升机,空空");
param.put("airScore", 2);
// ② 任务文案像空中任务 且 红方偏好对空 → + airTaskScore * weight可与①叠加
param.put("airTaskKeywords", "空中,制空,拦截,空战");
param.put("airTaskScore", 10);
// ③ 任务文案像地面任务 且 红方偏好地面火力 → + groundScore * weight
param.put("groundTaskKeywords", "地面,突击,登陆");
param.put("redPreferredWhenGround", "远火,榴弹,炮,火箭");
param.put("groundScore", 1);
// ④ 蓝方像坦克/装甲目标 且 红方文本命中 redMatchKeywords_tank → + tankScore * weight
param.put("tankKeywords", "坦克,装甲");
param.put("redMatchKeywords_tank", "反坦克");
param.put("tankScore", 1);
// ⑤ 蓝方像导弹类 且 红方文本命中 redMatchKeywords_missile → + missileScore * weight
param.put("missileKeywords", "导弹,火箭弹,巡航");
param.put("redMatchKeywords_missile", "防空,导弹,导弹发射");
param.put("missileScore", 1);
// ===================== 目标分配参数(写入 Tasks.task.execute =====================
// executeTypeDefault生成 execute[0] 的类型字段
param.put("executeTypeDefault", "assault");
// targetPickModeroundRobin(稳定轮询) / random(伪随机但同输入稳定)
param.put("targetPickMode", "roundRobin");
// minTargetsPerRed / maxTargetsPerRedCap每个红方任务最少/最多分配的目标数
param.put("minTargetsPerRed", 1);
param.put("maxTargetsPerRedCap", 3);
// radToTargetsCsvsuccessTargetRad(命中率) -> 每红装目标数 的映射(阈值:目标数),按阈值从大到小匹配
// 例0.8:1,0.5:2,0.2:3 表示 successTargetRad>=0.8 分1个>=0.5 分2个>=0.2 分3个
param.put("radToTargetsCsv", "0.8:1,0.5:2,0.2:3");
// rangeParseRegex从 attDefaultValue/attExplain 中提取射程数值的正则取第1个数字
param.put("rangeParseRegex", "(\\\\d+(?:\\\\.\\\\d+)?)");
// rangeUnit提取数值的单位km/m二选一
param.put("rangeUnit", "km");
// minRangeToAllowAssignKm若解析到的蓝方射程小于该值则该蓝方装备不参与被分配无法解析则忽略此过滤
param.put("minRangeToAllowAssignKm", 0);
// ===================== 低命中率补拿装备参数 =====================
// redHitRateThreshold红方装备命中率阈值低于该值时触发补拿
param.put("redHitRateThreshold", 0.6);
// maxExtraWeaponsPerTask每条蓝方任务最多补拿几件红装
param.put("maxExtraWeaponsPerTask", 2);
// maxSupplementRounds补拿循环最大轮次防死循环
param.put("maxSupplementRounds", 2);
// extraPickMinScore补拿时红装最低匹配分
param.put("extraPickMinScore", 1);
// ===================== 阵位规则参数(写入 SubComponents.platform[].positions =====================
// positionRuleEnabled是否启用阵位规则。true=执行阵位生成false=跳过,不改 platform.positions。
param.put("positionRuleEnabled", true);
// positionAnchorMode锚点模式。当前实现使用 hybrid蓝方 taskWeapons.coordinate 的中心点作为主锚点)。
param.put("positionAnchorMode", "hybrid");
// trackPointDirectionMode航向计算模式。
// - head2next取 trackPoints[0] -> trackPoints[1] 作为方向(默认)
// - tail2prev取倒数第二个 -> 最后一个点作为方向
param.put("trackPointDirectionMode", "head2next");
// fallbackBearingDeg当 trackPoints 缺失或无法计算方位时使用该默认方位角0-360
param.put("fallbackBearingDeg", 0);
// deployDistanceKmMin部署距离下限km。最终距离不会小于该值。
param.put("deployDistanceKmMin", 8);
// deployDistanceKmMax部署距离上限km。最终距离不会大于该值。
param.put("deployDistanceKmMax", 30);
// deployDistanceKmDefault默认部署距离km
// 当 distanceByPlatformCsv 未命中任何关键词时,使用该值。
param.put("deployDistanceKmDefault", 15);
// distanceByPlatformCsv按“关键词”覆盖部署距离km不写死具体类型完全由业务配置。
// 格式:关键词:距离,关键词:距离(示例:防空:18,反坦克:10,迫击炮:8
// 匹配范围:红方装备 Name / Platform_type 文本包含关键词即命中。
// 优先级:命中后覆盖 deployDistanceKmDefault但最终仍受 deployDistanceKmMin 与 deployDistanceKmMax 约束。
param.put("distanceByPlatformCsv", "");
// formationType编队样式可选 line / wedge / circle。
param.put("formationType", "line");
// formationSpacingMeters编队间距影响同一红装下 platform[] 点位离散程度。
// 说明Java 侧会与 minInterPlatformDistanceMeters 比较,取更大值,避免平台重叠过近。
param.put("formationSpacingMeters", 300);
// formationHeadingOffsetDeg编队相对主航向的偏转角主要用于 wedge/circle 的分散方向。
param.put("formationHeadingOffsetDeg", 15);
// defaultDeployHeight默认部署高度用于 positions 第3位高度值基线。
param.put("defaultDeployHeight", 30);
// heightFollowBlueRatio高度跟随蓝方比例>=0
// 计算方式:高度 = defaultDeployHeight + 蓝方锚点平均高度 * heightFollowBlueRatio。
// 0 表示不跟随蓝方高度,仅使用默认高度。
param.put("heightFollowBlueRatio", 0.0);
// enableWarZoneClamp是否启用作战区约束。true=超出 warZoneLocation 时回拉到区内。
param.put("enableWarZoneClamp", true);
// warZoneClampMode作战区约束模式。当前实现使用 nearestInside沿锚点到目标点方向二分回拉到区内
param.put("warZoneClampMode", "nearestInside");
// minInterPlatformDistanceMeters平台最小间距下限用于抑制平台点位过度重叠。
param.put("minInterPlatformDistanceMeters", 80);
return param;
}
rule "装备匹配"
salience 100
when
$fact : DroolsFact(task != null)
then
// 以本文件 buildParam 为真源覆盖同名键,再执行 Java 侧匹配逻辑
globalParams.putAll(buildParam());
equipmentRule($fact, globalParams);
end
rule "目标匹配"
salience 90
when
$fact : DroolsFact(task != null)
then
// 显式目标分配规则:填充 Tasks.task.execute.targetList[*].targetId
globalParams.putAll(buildParam());
target($fact, globalParams);
end
rule "阵位匹配"
salience 80
when
$fact : DroolsFact(task != null)
then
// 显式阵位规则:填充 redWeapons.SubComponents.platform[].positions
globalParams.putAll(buildParam());
position($fact, globalParams);
end