java双层递归,并结合javascript 求多层循环嵌套,并解析成数学公式

4 篇文章 2 订阅
1 篇文章 0 订阅
@Slf4j
public class RuleCalcUtils {

    public static String json = "{\"id\":1,\"parentId\":0,\"rules\":1,\"map\":[{\"id\":0.5752577160621279,\"parentId\":1,\"rules\":0,\"map\":[{\"id\":0.3720240970679103,\"parentId\":0.5752577160621279,\"rules\":1,\"map\":[{\"id\":0.9482223038757285,\"parentId\":0.3720240970679103,\"rules\":2,\"map\":[{\"userLevelParam\":\"司龄(月)\",\"range\":\"实时数据\",\"relation\":\"<\",\"userLevelValue\":\"20\"}],\"active\":false,\"level\":4,\"parentLevel\":3},{\"id\":0.7664580817231594,\"parentId\":0.3720240970679103,\"rules\":2,\"map\":[{\"userLevelParam\":\"案加分\",\"range\":\"实时数据\",\"relation\":\"==\",\"userLevelValue\":\"10\"}],\"active\":false,\"level\":4,\"parentLevel\":3},{\"id\":0.2566599589893268,\"parentId\":0.3720240970679103,\"rules\":2,\"map\":[{\"userLevelParam\":\"职类\",\"range\":\"实时数据\",\"relation\":\"属于\",\"userLevelValue\":\"哈哈\"}],\"active\":false,\"level\":4,\"parentLevel\":3}],\"active\":false,\"level\":3,\"parentLevel\":2},{\"id\":0.6148288892102602,\"parentId\":0.5752577160621279,\"rules\":2,\"map\":[{\"userLevelParam\":\"职类\",\"range\":\"实时数据\",\"relation\":\"属于\",\"userLevelValue\":\"职类\"}],\"active\":false,\"level\":3,\"parentLevel\":2}],\"active\":false,\"level\":2,\"parentLevel\":1},{\"id\":0.9406835531825224,\"parentId\":1,\"rules\":2,\"map\":[{\"userLevelParam\":\"司龄(月)\",\"range\":\"实时数据\",\"relation\":\"==\",\"userLevelValue\":\"10\"}],\"active\":false,\"level\":2,\"parentLevel\":1},{\"id\":0.3356643339471186,\"parentId\":1,\"rules\":2,\"map\":[{\"userLevelParam\":\"职务\",\"range\":\"实时数据\",\"relation\":\"属于\",\"userLevelValue\":\"职务\"}],\"active\":false,\"level\":2,\"parentLevel\":1},{\"id\":0.31367304398725127,\"parentId\":1,\"rules\":2,\"map\":[{\"userLevelParam\":\"职级\",\"range\":\"实时数据\",\"relation\":\"属于\",\"userLevelValue\":\"哈哈\"}],\"active\":false,\"level\":2,\"parentLevel\":1}],\"active\":false,\"level\":1,\"parentLevel\":0}";

    private final static Integer RULE_LOGICAL_RELATION = 2;

    /**
     *  固定删除后4个字符的原因是因为处理最后拼接的多余逻辑运算符号,
     *  4个字符是因代码块美观  strRule.append(" || ")加入2个空格,若不需要空格要删除数据为 2
     */
    private final static Integer RULE_STRING_DISPOSE_LENGTH = 4;

    static ScriptEngine jse = new ScriptEngineManager().getEngineByName("JavaScript");

    public static void main(String[] args) throws Exception {
        /**
         * TODO exampleSource数据要在calcRule方法中取样本数据使用。可根据业务自行进行修改
         */
        Map<String,String> exampleSource = new HashMap<>();
        exampleSource.put("司龄(月)","10");
        exampleSource.put("职级","职级");
        exampleSource.put("职类","职类");
        exampleSource.put("薯片分","10");
        exampleSource.put("案加分","10");
        exampleSource.put("WI分","10");
        exampleSource.put("职务","职务");
        boolean result = decisionMaking(json,exampleSource);
        log.info("result calc {}",result);
    }

    public static boolean decisionMaking(String ruleStr,Map<String,String> exampleSource) throws Exception {
        try {
            List<JSONObject> rulesArr = new ArrayList<>();
            StringBuilder strRule = new StringBuilder();
            /*格式数据*/
            JSONObject jsonStr = JSONObject.parseObject(ruleStr);

            /*树形规则钻取*/
            factorial(jsonStr.getJSONArray("map"), rulesArr, jsonStr.getString("rules"));

            /*按照父类ID进行分组*/
            Map<Object, List<JSONObject>> groupCalcMap = rulesArr.stream().collect(Collectors.groupingBy(info -> info.getString("parentId"),Collectors.toList()));

            /*计算规则公式*/
            calcRuleFormula(jsonStr.getString("id"),groupCalcMap,strRule,jsonStr.getInteger("rules"),exampleSource);

            /*处理尾部多余运算符,规则参看常量(RULE_STRING_DISPOSE_LENGTH)描述*/
            String resultStr = strRule.delete(strRule.length()-RULE_STRING_DISPOSE_LENGTH,strRule.length()).toString();
            System.out.println(resultStr);
            return (boolean) jse.eval(resultStr);
        }  catch (Exception e) {
            throw new Exception("Rule calculation exception ! ",e);
        }
    }

    /**
     * 计算规则公式
     * /*0(&&)  1(||)  2(end loop))
     */
    private static void calcRuleFormula(String masterId,Map<Object, List<JSONObject>> groupCalcMap,StringBuilder strRule,Integer logicalRelationStr,Map<String,String> exampleSource){
        if(!groupCalcMap.containsKey(masterId) || logicalRelationStr == RULE_LOGICAL_RELATION){
            log.warn("Data exception parent rules different.  masterId = {} ; rules info = {} ; rule_logical_relation = {}",masterId,groupCalcMap,logicalRelationStr);
            return;
        }
        strRule.append("(");
        for (JSONObject object : groupCalcMap.get(masterId)) {
            /**
             * 判断是否有逻辑运算符
             */
            if(object.containsKey("relation")){

                /*TODO 需要修改 按照逻辑修改 go */
                //样本数据获取逻辑
                if("司龄(月)".equals(object.getString("userLevelParam"))){
                    strRule.append(exampleSource.get("司龄(月)"));
                }
                if("职级".equals(object.getString("userLevelParam"))){
                    strRule.append("\'");
                    strRule.append(exampleSource.get("职级"));
                    strRule.append("\'");
                }
                if("职类".equals(object.getString("userLevelParam"))){
                    strRule.append("\'");
                    strRule.append(exampleSource.get("职类"));
                    strRule.append("\'");
                }
                if("薯片分".equals(object.getString("userLevelParam"))){
                    strRule.append(exampleSource.get("薯片分"));
                }
                if("案加分".equals(object.getString("userLevelParam"))){
                    strRule.append(exampleSource.get("案加分"));
                }
                if("WI分".equals(object.getString("userLevelParam"))){
                    strRule.append(exampleSource.get("WI分"));
                }
                if("职务".equals(object.getString("userLevelParam"))){
                    strRule.append("\'");
                    strRule.append(exampleSource.get("职务"));
                    strRule.append("\'");
                }

                /*运算规则替换*/
                if(object.getString("relation").equals("属于")){
                    strRule.append("==");
                    strRule.append("\'");
                    strRule.append(object.getString("userLevelValue"));
                    strRule.append("\'");
                }
                else if (object.getString("relation").equals("不属于")){
                    strRule.append("!=");
                    strRule.append("\'");
                    strRule.append(object.getString("userLevelValue"));
                    strRule.append("\'");
                }
                else{
                    strRule.append(object.getString("relation"));
                    strRule.append(object.getString("userLevelValue"));
                }

                /*需修改 按照逻辑修改 end */

                /**
                 *判断逻辑运算公式拼接
                 */
                if (object.getInteger("gradeStr") == BigDecimal.ZERO.intValue()) {
                    strRule.append(" && ");
                } else {
                    strRule.append(" || ");
                }
            }else{
                calcRuleFormula(object.getString("id"),groupCalcMap,strRule,object.getInteger("gradeStr"),exampleSource);
            }
        }

        /**
         *处理字符串拼接尾行多余运算符
         */
        strRule.delete(strRule.length()-RULE_STRING_DISPOSE_LENGTH,strRule.length());
        strRule.append(")");

        if (logicalRelationStr == BigDecimal.ZERO.intValue()) {
            strRule.append(" && ");
        } else {
            strRule.append(" || ");
        }
    }

    /**
     * 递归树形规则
     * 钻取规则数据 0(&&)  1(||)  2(end loop(recursion)))
     * gradeStr取值父级的rules,标识字迹规则的关系
     */
    private static void factorial(JSONArray obj, List resultList, String gradeStr) {
        for (Object o : obj) {
            JSONObject subsets = JSONObject.parseObject(o.toString());
            /**
             *若还有子集继续递归
             */
            if (subsets.getInteger("rules") == RULE_LOGICAL_RELATION) {
                JSONArray arrayInfo = subsets.getJSONArray("map");
                for (Object o1 : arrayInfo) {
                    JSONObject subsetInfo = JSONObject.parseObject(o1.toString());
                    subsetInfo.put("parentId", subsets.getString("parentId"));
                    subsetInfo.put("id", subsets.getString("id"));
                    subsetInfo.put("gradeStr", gradeStr);
                    resultList.add(JSONObject.parseObject(subsetInfo.toString()));
                }
            } else {
                JSONObject subsetInfo = new JSONObject();
                subsetInfo.put("parentId", subsets.getString("parentId"));
                subsetInfo.put("id", subsets.getString("id"));
                subsetInfo.put("gradeStr", gradeStr);
                resultList.add(JSONObject.parseObject(subsetInfo.toString()));

                /**
                 * 若不是结束标志继续递归钻取
                 */
                factorial(subsets.getJSONArray("map"), resultList, subsets.getString("rules"));
            }
        }
    }
}

最后打印计算公式结果:

公式;true表示该规则匹配

(((10<20 || 10==10 || '职类'=='哈哈') && '职类'=='职类') || 10==10 || '职务'=='职务' || '职级'=='哈哈')
15:42:48.012 [main] INFO net.crisps.cloud.common.utils.RuleCalcUtils - result calc true

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值