Pārlūkot izejas kodu

新增【保养】预警逻辑

andyliu 2 nedēļas atpakaļ
vecāks
revīzija
a39b061a1d

+ 1 - 1
pom.xml

@@ -243,7 +243,7 @@
 
     <build>
         <!-- 打成jar包的名称 -->
-        <finalName>v1-alam-warn-analy-core-1.0.1</finalName>
+        <finalName>v1-alam-warn-analy-core-1.0.2</finalName>
         <plugins>
             <!--运用SpringBoot 插件  使用spring-boot-devtools模块的应用,当classpath中的文件有改变时,会自动重启! -->
             <plugin>

+ 1 - 1
src/main/java/com/shkpr/service/warncore/bizhandler/CommToolHandler.java

@@ -204,7 +204,7 @@ public class CommToolHandler {
         StringBuilder remark = new StringBuilder(StringUtils.isEmpty(eventPrefix)?String.format("【%s】%s",zoneName,StringUtils.isEmpty(objName)?"":("--【"+objName+"】")):eventPrefix);
         remark.append("于")
                 .append(TimeTool.convertUTC2DateStr(sampleDataTime, TimeTool.TIMESTAMP_FORMAT))
-                .append("因数据异常,触发了");
+                .append("因监测数据满足设定规则,触发了");
         String arrItemName[] = itemName.split("--");
         if (arrItemName != null && arrItemName.length >= 2){
             if (arrItemName[0].equals(arrItemName[1])){

+ 253 - 3
src/main/java/com/shkpr/service/warncore/bizhandler/ZoneDataWarnHandler.java

@@ -11,6 +11,7 @@ import com.shkpr.service.warncore.dbdao.DBMgrProxy;
 import com.shkpr.service.warncore.dbdao.services.intef.MixDataBizDBService;
 import com.shkpr.service.warncore.dbdao.services.intef.OrdWarnPlanInfoDBService;
 import com.shkpr.service.warncore.dbdao.services.intef.OrdWarnPlanRulesDBService;
+import com.shkpr.service.warncore.dbdao.tables.OrdTaskUpkeepObjTable;
 import com.shkpr.service.warncore.dbdao.tables.OrdWarnEventInfoTable;
 import com.shkpr.service.warncore.dbdao.tables.OrdWarnPlanInfoTable;
 import com.shkpr.service.warncore.dbdao.tables.OrdWarnTriggerSampleHisTable;
@@ -339,6 +340,7 @@ public class ZoneDataWarnHandler {
             code = ResponseCode.RESULT_BAD;
         }
 
+        final boolean bDoRealTimeCompare = (planDetail.getItemKey().endsWith("upkeep") || planDetail.getItemKey().endsWith("wash"))?true:false;
         final long curUTCTm = TimeTool.getCurMsUTC();
         final long thisDayBegin = TimeTool.getTodayBeginUTC();
         final int preDayInYear = TimeTool.getYearIndex(curUTCTm-TimeTool.MS_ONE_DAY);//日分析时,分析前一日所在的年份
@@ -394,13 +396,20 @@ public class ZoneDataWarnHandler {
                     thisStepTempRes.resetData();
             }
 
-            if (queryBeginUTC >= queryEndUTC){
+            if (!bDoRealTimeCompare && queryBeginUTC >= queryEndUTC){
                 step = "Time is invalid,do analysis next time";
                 code = ResponseCode.RESULT_BAD;
                 break;
             }
 
-            thisStepTempRes.setDoForTodayBefore(true);
+            if (bDoRealTimeCompare){
+                thisStepTempRes.setDoForTodayBefore(false);
+                queryBeginUTC = thisDayBegin;
+                queryEndUTC = thisDayBegin + TimeTool.MS_ONE_DAY;
+                conditionMinUTC = thisDayBegin;
+            }else {
+                thisStepTempRes.setDoForTodayBefore(true);
+            }
             thisStepTempRes.setQueryBeginUTC(queryBeginUTC);
             thisStepTempRes.setQueryEndUTC(queryEndUTC);
             thisStepTempRes.setConditionMinUTC(conditionMinUTC);
@@ -434,7 +443,10 @@ public class ZoneDataWarnHandler {
         }while (false);
 
         if (code == ResponseCode.RESULT_NORMAL){
-            code = analysisDataStepByStep(planDetail, rules, thisStepTempRes);
+            if (planDetail.getItemKey().endsWith("upkeep") || planDetail.getItemKey().endsWith("wash")){
+                code = analysisZoneObjToDo(planDetail, rules, thisStepTempRes);
+            }else
+                code = analysisDataStepByStep(planDetail, rules, thisStepTempRes);
         }else {//单独更新预警方案的分析时间、次数、说明
             thisStepTempRes.setLastAnalyExplain(step);
             Map<String, Object> updatePlan = thisStepTempRes.genUpdatePlan();
@@ -1090,4 +1102,242 @@ public class ZoneDataWarnHandler {
         }while (false);
         return value;
     }
+
+    private static TRecordRes<ZoneDoObjItem> pickZoneObjToDo(String itemKey, String zoneId, long compareTime){
+        TRecordRes<ZoneDoObjItem> oRes = new TRecordRes<>(ResponseCode.RESULT_BAD.toInt());
+        Map<String, Object> where = null;
+        String desTable = "";
+        if (itemKey.endsWith("upkeep")){
+            desTable = OrdTaskUpkeepObjTable.R_INFO.TABLE;
+            where = new HashMap<String, Object>(){{
+                put(OrdTaskUpkeepObjTable.R_INFO.ZONE_ID, zoneId);
+            }};
+        }
+
+        if (StringUtils.isEmpty(desTable)){
+            oRes.setCode(ResponseCode.BUSINESS_BUSY.toInt());
+            return oRes;
+        }
+
+        List<Map<String, Object>> arrTmpData = getMixDataDBService().batchQueryWithsEx(desTable,"", where, null, "", "");
+        do {
+            if (arrTmpData == null){
+                oRes.setCode(ResponseCode.BUSINESS_DB_ERROR.toInt());
+                break;
+            }
+            if (arrTmpData.size() <= 0){
+                oRes.setCode(ResponseCode.RESULT_NORMAL.toInt());
+                break;
+            }
+
+            Set<String> uqObjId = new HashSet<>();
+            List<ZoneDoObjItem> arrItem = FastJsonUtil.batchMap2Obj(arrTmpData, ZoneDoObjItem.class, true);
+            for (int i=arrItem.size()-1;i>=0;i--){
+                boolean bNeedDo = false;
+                ZoneDoObjItem thisItem = arrItem.get(i);
+                if (uqObjId.contains(thisItem.getObjId())){
+                    arrItem.remove(i);
+                    continue;
+                }
+
+                int period = CastUtil.castInt(thisItem.getDoPeriod(), 0);
+                if (period > 0){
+                    long lastTime = thisItem.getLastTime()>0L?thisItem.getLastTime():thisItem.getInstallTime();
+                    if (lastTime > 0L && (lastTime+TimeTool.MS_ONE_DAY*period) <= compareTime)
+                        bNeedDo = true;
+                }
+                if (!bNeedDo)
+                    arrItem.remove(i);
+                else
+                    uqObjId.add(thisItem.getObjId());
+            }
+            oRes.setData(arrItem);
+            oRes.setCode(ResponseCode.RESULT_NORMAL.toInt());
+            arrTmpData.clear();
+        }while (false);
+        oRes.checkRes();
+        return oRes;
+    }
+
+    private static ResponseCode analysisZoneObjToDo(OrdWarnPlanDetail planDetail, List<OrdWarnPlanRules> rules, OrdWarnPlanTempStep thisTempStep){
+        String step = "Start to deep analysis";
+        ResponseCode code = ResponseCode.RESULT_NORMAL;
+        long curTime = TimeTool.getCurMsUTC();
+        final String zoneId = rules.get(0).getObjId();
+        List<ZoneDoObjItem> zoneStatsData = null;
+        Map<String, Long> oldEvent2EndUTC = new HashMap<>();//需要更新预警事件的样本截止时间
+        Map<String, JPOrdWarnEventInfo> newEvent2Gen = new HashMap<>();
+        String eventIdAcceptPlanHisTriggerSam = "";//将预案的历史触发样本数据迁移到该事件
+        boolean clearPlanHisTriggerSam = false;//是否需要清空预案的历史触发样本数据
+
+        do {
+            TRecordRes<ZoneDoObjItem> sampleRes = pickZoneObjToDo(planDetail.getItemKey(), zoneId, curTime);
+            if (sampleRes != null && sampleRes.getCode() == ResponseCode.RESULT_NORMAL.toInt()){
+                zoneStatsData = sampleRes.getData();
+            }
+            if (zoneStatsData == null){
+                step = String.format("Get zone stats data failed");
+                code = ResponseCode.RESULT_BAD;
+                break;
+            }
+            /*if (CommTool.listSize(zoneStatsData) <= 0){//数据条目缺失可认为,还在等待录入则跳过
+                step = String.format("Get zone stats data empty");
+                code = ResponseCode.RESULT_BAD;
+                break;
+            }*/
+
+            do {
+                boolean matched = CommTool.listSize(zoneStatsData)<=0?false:true;
+                long sampleRecordTm = curTime;
+                String eventPrefix = "";
+                if (code != ResponseCode.RESULT_NORMAL)
+                    break;
+
+                if (!matched){//本次没有匹配成功
+                    step = "This is not matched.";
+                    thisTempStep.setLastCompareSampleTime(sampleRecordTm);
+                    thisTempStep.setLastCompareSampleResult(COMPARE_FALSE);
+                    thisTempStep.setFirstMatchSampleTime(0L);
+                    thisTempStep.setLastEventId("");
+                    thisTempStep.setLastEventTime(0L);
+                    thisTempStep.setLastCompareSampleExplain(step);
+
+                    if (StringUtils.isEmpty(eventIdAcceptPlanHisTriggerSam))
+                        clearPlanHisTriggerSam = true;
+                    break;
+                }else {//本次匹配成功进入下一步
+                }
+
+                long triggerEventPeriodSwitch = planDetail.getFrequency()*planDetail.getThreshold();//触发预警事件的最小时长(单位:时/天/月)
+                if (thisTempStep.getLastCompareSampleResult() <= COMPARE_FALSE){//上一次没有匹配成功
+                    step = "This is matched, but last is not matched.";
+                    thisTempStep.setLastCompareSampleTime(sampleRecordTm);
+                    thisTempStep.setLastCompareSampleResult(COMPARE_TURE);
+                    thisTempStep.setFirstMatchSampleTime(sampleRecordTm);
+                    thisTempStep.setLastCompareSampleExplain(step);
+                    if (triggerEventPeriodSwitch <= 1){//触发事件
+                        step = "This is matched and trigger short period(for anew matched), it will gen event.";
+                        thisTempStep.setLastEventTime(sampleRecordTm);
+                        thisTempStep.setLastCompareSampleExplain(step);
+
+                        JPOrdWarnEventInfo newEvent = new JPOrdWarnEventInfo(planDetail, rules, thisTempStep, thisTempStep.getLastEventTime(), eventPrefix);
+                        newEvent2Gen.put(newEvent.getUid(), newEvent);
+                        thisTempStep.setLastEventId(newEvent.getUid());
+                        thisTempStep.setLastEventAction(newEvent.getAction());
+                        thisTempStep.setCycleTriggerTimes(thisTempStep.getCycleTriggerTimes()+1);
+
+                        if (StringUtils.isEmpty(eventIdAcceptPlanHisTriggerSam))
+                            eventIdAcceptPlanHisTriggerSam = newEvent.getUid();
+                    }
+                    break;
+                }//上一次匹配成功了进入下一步
+
+                if (StringUtils.isEmpty(thisTempStep.getLastEventId())){//之前无预警事件
+                    step = "This is matched(for always matched), and will gen event.";
+                    thisTempStep.setLastCompareSampleTime(sampleRecordTm);
+                    thisTempStep.setLastCompareSampleResult(COMPARE_TURE);
+                    thisTempStep.setLastEventTime(sampleRecordTm);
+                    thisTempStep.setLastCompareSampleExplain(step);
+
+                    JPOrdWarnEventInfo newEvent = new JPOrdWarnEventInfo(planDetail, rules, thisTempStep, thisTempStep.getLastEventTime(), eventPrefix);
+                    newEvent2Gen.put(newEvent.getUid(), newEvent);
+                    thisTempStep.setLastEventId(newEvent.getUid());
+                    thisTempStep.setLastEventAction(newEvent.getAction());
+                    thisTempStep.setCycleTriggerTimes(thisTempStep.getCycleTriggerTimes()+1);
+                    //[!!!]do not change the FirstMatchSampleTime[!!!]
+
+                    if (StringUtils.isEmpty(eventIdAcceptPlanHisTriggerSam))
+                        eventIdAcceptPlanHisTriggerSam = newEvent.getUid();
+                }else {//之前有预警事件
+                    if (planDetail.getMergeToEvent() == 0 || thisTempStep.getLastEventAction() >= EventAction.DONE){//之前的预警事件已处理,则可认为进行重新计数
+                        step = "This is matched, but need to wait the next matched.";
+                        thisTempStep.setLastCompareSampleTime(sampleRecordTm);
+                        thisTempStep.setLastCompareSampleResult(COMPARE_TURE);
+                        thisTempStep.setFirstMatchSampleTime(sampleRecordTm);
+                        thisTempStep.setLastCompareSampleExplain(step);
+                        if (triggerEventPeriodSwitch <= 1){//触发事件
+                            step = "This is matched and trigger short period(for cycle matched), it will gen event.";
+                            thisTempStep.setLastEventTime(sampleRecordTm);
+                            thisTempStep.setLastCompareSampleExplain(step);
+
+                            JPOrdWarnEventInfo newEvent = new JPOrdWarnEventInfo(planDetail, rules, thisTempStep, thisTempStep.getLastEventTime(), eventPrefix);
+                            newEvent2Gen.put(newEvent.getUid(), newEvent);
+                            thisTempStep.setLastEventId(newEvent.getUid());
+                            thisTempStep.setLastEventAction(newEvent.getAction());
+                            thisTempStep.setCycleTriggerTimes(thisTempStep.getCycleTriggerTimes()+1);
+
+                            if (StringUtils.isEmpty(eventIdAcceptPlanHisTriggerSam))
+                                eventIdAcceptPlanHisTriggerSam = newEvent.getUid();
+                        }else {
+                            thisTempStep.setLastEventId("");
+                            thisTempStep.setLastEventTime(0L);
+                        }
+                    }else {//之前的预警事件未处理,则更新预警事件的样本截止时刻
+                        step = "This is matched, but need to merge the last event.";
+                        thisTempStep.setLastCompareSampleTime(sampleRecordTm);
+                        thisTempStep.setLastCompareSampleResult(COMPARE_TURE);
+                        if (newEvent2Gen.containsKey(thisTempStep.getLastEventId())){
+                            newEvent2Gen.get(thisTempStep.getLastEventId()).setToTime(sampleRecordTm);
+                        }else
+                            oldEvent2EndUTC.put(thisTempStep.getLastEventId(), sampleRecordTm);
+                        thisTempStep.setLastCompareSampleExplain(step);
+
+                        final String lastEventID = thisTempStep.getLastEventId();
+                        if (StringUtils.isEmpty(eventIdAcceptPlanHisTriggerSam))
+                            eventIdAcceptPlanHisTriggerSam = lastEventID;
+                    }
+                }
+            }while (false);
+        }while (false);
+
+        final String thisSampleContent = FastJsonUtil.toJSON(zoneStatsData);
+        thisTempStep.setLastAnalyExplain(step);
+        Map<String, Object> updatePlan = thisTempStep.genUpdatePlan();
+        updatePlan.put(OrdWarnPlanInfoTable.W_INFO.VERSION, planDetail.getVersion()+1);
+        updatePlan.put(OrdWarnPlanInfoTable.W_INFO.UPDATE_TIME, System.currentTimeMillis());
+        List<Map<String, Object>> genNewEventObj = null;
+        Map<String, String> eventId2PlanId = null;
+        if (CommTool.mapSize(newEvent2Gen) > 0){
+            genNewEventObj = new ArrayList<>();
+            eventId2PlanId = new HashMap<>();
+            for (Map.Entry<String, JPOrdWarnEventInfo> entry:newEvent2Gen.entrySet()){
+                entry.getValue().setContent(thisSampleContent);
+                genNewEventObj.add(FastJsonUtil.obj2Map(entry.getValue(), true));
+                eventId2PlanId.put(entry.getValue().getUid(), entry.getValue().getPlanId());
+            }
+        }
+        List<Map<String, Object>> genOldEventObj = null;
+        if (CommTool.mapSize(oldEvent2EndUTC) > 0){
+            genOldEventObj = new ArrayList<>();
+            for (Map.Entry<String, Long> entry:oldEvent2EndUTC.entrySet()){
+                genOldEventObj.add(new HashMap<String, Object>(){{
+                    put(OrdWarnEventInfoTable.W_INFO.UNIQUE_ID, entry.getKey());
+                    put(OrdWarnEventInfoTable.W_INFO.TO_TIME, entry.getValue());
+                    put(OrdWarnEventInfoTable.W_INFO.UPDATE_TIME, TimeTool.getCurMsUTC());
+                    put(OrdWarnEventInfoTable.W_INFO.CONTENT, thisSampleContent);
+                }});
+            }
+        }
+        List<Map<String, Object>> triggerSampleHisObj = null;
+        if (!StringUtils.isEmpty(eventIdAcceptPlanHisTriggerSam)){
+            final Map<String, Object> oneObj = new HashMap<>();
+            oneObj.put(OrdWarnTriggerSampleHisTable.W_INFO.OWNER_ID, eventIdAcceptPlanHisTriggerSam);
+            oneObj.put(OrdWarnTriggerSampleHisTable.W_INFO.SAMPLE, thisSampleContent);
+            triggerSampleHisObj = new ArrayList<Map<String, Object>>(){{
+                add(oneObj);
+            }};
+        }
+
+        if (getWarnPlanInfoDBService().updatePlanForTrigger(new HashMap<String, Object>(){{
+            put(OrdWarnPlanInfoTable.W_INFO.UNIQUE_ID, planDetail.getUid());
+            put(OrdWarnPlanInfoTable.W_INFO.VERSION, planDetail.getVersion());
+        }}, updatePlan, genNewEventObj, genOldEventObj, triggerSampleHisObj, eventId2PlanId, clearPlanHisTriggerSam, eventIdAcceptPlanHisTriggerSam) <= 0){
+            step = "Update warn plan trigger result to db failed.";
+            code = ResponseCode.RESULT_BAD;
+        }
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBusinessType, mStrClassName
+                , String.format("Analysis Zone Do(item=%s):{planId=%s,zoneId=%s} {step=%s} {clearPlanHisTrigSam=%b,eventAcceptPlanHisTrigSam=%s} {%s}...",
+                        planDetail.getItemKey(), planDetail.getUid(), zoneId, step, clearPlanHisTriggerSam, eventIdAcceptPlanHisTriggerSam, code.toString()));
+        return code;
+    }
 }

+ 21 - 0
src/main/java/com/shkpr/service/warncore/dbdao/tables/OrdTaskUpkeepObjTable.java

@@ -0,0 +1,21 @@
+package com.shkpr.service.warncore.dbdao.tables;
+
+public interface OrdTaskUpkeepObjTable {
+    interface R_INFO{
+        String TABLE = "v_k4_ssp_upkeep_obj_lists";
+        String PRIMARY_KEY = "obj_id";
+        String UNIQUE_ID = "obj_id";
+        String ALL_FILED = "*";
+        String DEFAULT_ORDER = "";
+        String DEFAULT_EXTEND = "";
+        String ZONE_ID = "zone_id";
+    }
+
+    interface W_INFO{
+        String ID = "id";
+        String TABLE = "v_k4_ssp_upkeep_obj_lists";
+        String PRIMARY_KEY = "obj_id";
+        String UNIQUE_ID = "obj_id";
+        String ZONE_ID = "zone_id";
+    }
+}

+ 1 - 0
src/main/java/com/shkpr/service/warncore/dbdao/tables/OrdWarnEventInfoTable.java

@@ -26,5 +26,6 @@ public interface OrdWarnEventInfoTable {
         String HANDLE_TIME = "handle_time";
         String UPDATE_TIME = "update_time";
         String ACTION = "action";
+        String CONTENT = "content";
     }
 }

+ 22 - 0
src/main/java/com/shkpr/service/warncore/dto/ZoneDoObjItem.java

@@ -0,0 +1,22 @@
+package com.shkpr.service.warncore.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class ZoneDoObjItem {
+    private String objSrc = "";
+    private String objType = "";
+    private String objTypeName = "";
+    private String objId = "";
+    private String objName = "";
+    private String objNo = "";
+    private String gis = "";
+    private long lastTime = 0L;//最近一次保养时间
+    private long installTime = 0L;//安装时间
+    private String doPeriod = "";//保养/清洗周期(单位:天)
+
+    public ZoneDoObjItem() {
+    }
+}