|
|
@@ -0,0 +1,342 @@
|
|
|
+package com.shkpr.service.warncore.bizhandler;
|
|
|
+
|
|
|
+import com.global.base.tools.FastJsonUtil;
|
|
|
+import com.shkpr.service.warncore.commtools.CommTool;
|
|
|
+import com.shkpr.service.warncore.commtools.TimeTool;
|
|
|
+import com.shkpr.service.warncore.components.locks.CountDownLatchEx;
|
|
|
+import com.shkpr.service.warncore.components.locks.OrdWarnPlanLockMgr;
|
|
|
+import com.shkpr.service.warncore.constants.CommFieldStatus;
|
|
|
+import com.shkpr.service.warncore.dbdao.DBMgrProxy;
|
|
|
+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.OrdWarnPlanInfoTable;
|
|
|
+import com.shkpr.service.warncore.dbdao.tables.OrdWarnPlanRulesTable;
|
|
|
+import com.shkpr.service.warncore.dto.*;
|
|
|
+import com.shkpr.service.warncore.jsonbean.JPGetRegionData;
|
|
|
+import com.shkpr.service.warncore.jsonbean.JPStrIdsSK;
|
|
|
+import com.shkpr.service.warncore.services.ServiceMgrProxy;
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
+
|
|
|
+import java.util.*;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 站点数据处理
|
|
|
+ */
|
|
|
+public class SiteDataHandler {
|
|
|
+ private static OrdWarnPlanInfoDBService getWarnPlanInfoDBService(){
|
|
|
+ return DBMgrProxy.getInstance().applyXXXApi(OrdWarnPlanInfoDBService.class);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static OrdWarnPlanRulesDBService getWarnPlanRuleDBService(){
|
|
|
+ return DBMgrProxy.getInstance().applyXXXApi(OrdWarnPlanRulesDBService.class);
|
|
|
+ }
|
|
|
+
|
|
|
+ //先获取方案信息,然后规则列表,再加锁
|
|
|
+ public void handlerData(String planId){
|
|
|
+ ResponseCode code = ResponseCode.RESULT_NORMAL;
|
|
|
+ String step = "Start Get Plan Info";
|
|
|
+ List<OrdWarnPlanRules> rules = null;
|
|
|
+ OrdWarnPlanDetail planDetail = null;
|
|
|
+ do {
|
|
|
+ Map<String, Object> infoDb = getWarnPlanInfoDBService().fastGetFiled("", "", planId);
|
|
|
+ if (infoDb == null || infoDb.size() <= 0){
|
|
|
+ code = ResponseCode.RESULT_BAD;
|
|
|
+ step = "Get Warn Plan Info Failed";
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ planDetail = FastJsonUtil.map2Obj(infoDb, OrdWarnPlanDetail.class,true);
|
|
|
+ if (planDetail == null || planDetail.getStatus() != CommFieldStatus.ENABLE){
|
|
|
+ code = ResponseCode.RESULT_BAD;
|
|
|
+ step = "Warn Plan Info Invalid";
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ infoDb.clear();
|
|
|
+ List<Map<String, Object>> rulesDb = getWarnPlanInfoDBService().batchQueryWithsEx("", ""
|
|
|
+ , new HashMap<String, Object>(){{put(OrdWarnPlanRulesTable.R_INFO.PLAN_ID, planId);}}
|
|
|
+ , null, OrdWarnPlanRulesTable.R_INFO.DEFAULT_ORDER, "");
|
|
|
+ if (CommTool.listSize(rulesDb) <= 0){
|
|
|
+ code = ResponseCode.RESULT_BAD;
|
|
|
+ step = "Warn Plan Rules Invalid";
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ rules = OrdWarnPlanRules.batchFromJsonEx(rulesDb);
|
|
|
+ rulesDb.clear();
|
|
|
+ }while (false);
|
|
|
+
|
|
|
+ if (code == ResponseCode.RESULT_NORMAL){
|
|
|
+ CountDownLatchEx latchEx = null;
|
|
|
+ int nRetry = 3;
|
|
|
+ do {
|
|
|
+ try {
|
|
|
+ latchEx = OrdWarnPlanLockMgr.tryLatchForPlan(planId, 2000);
|
|
|
+ }catch (Exception e){
|
|
|
+ latchEx = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (latchEx != null){
|
|
|
+ handlerDataFun(planDetail, rules);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }while ((--nRetry) > 0);
|
|
|
+
|
|
|
+ if (latchEx != null){
|
|
|
+ latchEx.countDown();
|
|
|
+ }else{
|
|
|
+ step = "Request Lock For Analysis Failed";
|
|
|
+ code = ResponseCode.RESULT_BAD;
|
|
|
+ //handlerAnalysisForPlan(planDetail, siteDataResult);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private ResponseCode handlerDataFun(OrdWarnPlanDetail planDetail, List<OrdWarnPlanRules> rules){
|
|
|
+ ResponseCode code = ResponseCode.RESULT_NORMAL;
|
|
|
+ String step = "Start To Pre Analysis";
|
|
|
+ if (getWarnPlanInfoDBService().existsLineEx(OrdWarnPlanInfoTable.R_INFO.TABLE
|
|
|
+ , new HashMap<String, Object>(){{put(OrdWarnPlanInfoTable.R_INFO.STATUS, CommFieldStatus.ENABLE);
|
|
|
+ put(OrdWarnPlanInfoTable.R_INFO.UNIQUE_ID, planDetail.getUid());
|
|
|
+ put(OrdWarnPlanInfoTable.R_INFO.VERSION, planDetail.getVersion());
|
|
|
+ }}, null, "") <= 0){
|
|
|
+ step = "Plan Is Changed,Do Analysis Next Time";
|
|
|
+ code = ResponseCode.RESULT_BAD;
|
|
|
+ }
|
|
|
+
|
|
|
+ final long curUTCTm = TimeTool.getCurMsUTC();
|
|
|
+ final int curClock = (int)((curUTCTm/1000/60/60%24+8)%24);
|
|
|
+ final String curDate = TimeTool.convertUTC2DateStr(curUTCTm, TimeTool.YEAR_MONTH_DAY_FORMAT);
|
|
|
+ long queryBeginUTC = 0L, queryEndUTC = 0L, conditionMinUTC = 0L;
|
|
|
+ OrdWarnPlanTempStep thisStepTempRes = new OrdWarnPlanTempStep(planDetail);
|
|
|
+ do {
|
|
|
+ if (code != ResponseCode.RESULT_NORMAL)
|
|
|
+ break;
|
|
|
+
|
|
|
+ int findStartClock = -1;
|
|
|
+ for (int i=rules.size()-1;i>=0;i--){
|
|
|
+ if (i == 0)
|
|
|
+ conditionMinUTC = TimeTool.convertDateStr2UTC(String.format("%s %2d:00:00", curDate, rules.get(i).getStart()));
|
|
|
+ if (curClock >= rules.get(i).getStart() && curClock <= rules.get(i).getEnd()){
|
|
|
+ findStartClock = rules.get(i).getStart();
|
|
|
+ queryEndUTC = Math.min(curUTCTm, TimeTool.convertDateStr2UTC(String.format("%s %2d:59:59", curDate, rules.get(i).getEnd())));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (findStartClock < 0){
|
|
|
+ step = "Not In Time Range,Do Analysis Next Time";
|
|
|
+ code = ResponseCode.RESULT_BAD;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ findStartClock = findStartClock-1;
|
|
|
+ for (int i=rules.size()-1;i>=0;i--){
|
|
|
+ if (findStartClock < 0)
|
|
|
+ break;
|
|
|
+ if (findStartClock == rules.get(i).getEnd())
|
|
|
+ findStartClock = rules.get(i).getStart()-1;
|
|
|
+ }
|
|
|
+ queryBeginUTC = TimeTool.convertDateStr2UTC(String.format("%s %2d:00:00", curDate, findStartClock+1));
|
|
|
+
|
|
|
+ if (thisStepTempRes.getLastCompareSampleTime() <= 0L //从未分析过则重新计数
|
|
|
+ || thisStepTempRes.getLastCompareSampleTime() < queryBeginUTC){//样本跨了时段则重新计数
|
|
|
+ thisStepTempRes.resetData();
|
|
|
+ }else if (thisStepTempRes.getLastCompareSampleTime() >= queryBeginUTC){
|
|
|
+ queryBeginUTC = thisStepTempRes.getLastCompareSampleTime() + 1000L;
|
|
|
+ }
|
|
|
+ thisStepTempRes.setQueryBeginUTC(queryBeginUTC);
|
|
|
+ thisStepTempRes.setQueryEndUTC(queryEndUTC);
|
|
|
+ thisStepTempRes.setConditionMinUTC(conditionMinUTC);
|
|
|
+ thisStepTempRes.setDayTriggerTimes(planDetail.getDayTriggerTimes());
|
|
|
+ if (planDetail.getLastEventTime() < conditionMinUTC)
|
|
|
+ thisStepTempRes.setDayTriggerTimes(0);
|
|
|
+ if (planDetail.getDayTriggerUpperTimes() > 0
|
|
|
+ && thisStepTempRes.getDayTriggerTimes() >= planDetail.getDayTriggerUpperTimes()){//触发事件达到最大个数
|
|
|
+ step = "Event Arrive Max Limit,Stop Analysis For Today";
|
|
|
+ code = ResponseCode.RESULT_BAD;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!StringUtils.isEmpty(planDetail.getLastEventId())){
|
|
|
+ //向数据库中快速查询事件最近处理阶段action的值
|
|
|
+ //并赋值给thisTempStep
|
|
|
+ }
|
|
|
+
|
|
|
+ if (planDetail.getItemKey().endsWith("miss")){//数据缺失
|
|
|
+
|
|
|
+ }else if (planDetail.getItemKey().endsWith("swo")){//小时水量
|
|
|
+
|
|
|
+ }else {
|
|
|
+ if ("set".equals(planDetail.getDoPickWay())){//时段曲线
|
|
|
+ return analysisDataBySet(planDetail, rules, thisStepTempRes);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }while (false);
|
|
|
+ return code;
|
|
|
+ }
|
|
|
+
|
|
|
+ //处理时段样本数据
|
|
|
+ private ResponseCode analysisDataBySet(OrdWarnPlanDetail planDetail, List<OrdWarnPlanRules> rules, OrdWarnPlanTempStep thisTempStep){
|
|
|
+ ResponseCode code = ResponseCode.RESULT_NORMAL;
|
|
|
+ String step = "Start To Deep Analysis";
|
|
|
+ long curTime = TimeTool.getCurMsUTC();
|
|
|
+ final String siteId = rules.get(0).getObjId();
|
|
|
+ SiteSampleDataResult siteSampleData = null;
|
|
|
+ Map<String, Long> eventId2NewEndUTC = new HashMap<>();//需要更新预警事件的样本截止时间
|
|
|
+ do {
|
|
|
+ JPGetRegionData jpParam = new JPGetRegionData();
|
|
|
+ jpParam.setTotal(1);
|
|
|
+ jpParam.setIds(new ArrayList<String>(){{add(siteId);}});
|
|
|
+ jpParam.setBeginTime(thisTempStep.getQueryBeginUTC());
|
|
|
+ jpParam.setEndTime(thisTempStep.getQueryEndUTC());
|
|
|
+
|
|
|
+ try {
|
|
|
+ ResponseRes<String> resHttp = ServiceMgrProxy.getInstance().applyDataQeServiceApi().siteRegionData(jpParam);
|
|
|
+ if (ResponseCode.RESULT_NORMAL.toStrCode().equals(resHttp.getRescode()))
|
|
|
+ siteSampleData = FastJsonUtil.fromJSONByGson(resHttp.getResdata(), SiteSampleDataResult.class);
|
|
|
+ }catch (Exception e){}
|
|
|
+
|
|
|
+ if (siteSampleData == null){
|
|
|
+ step = String.format("Get Site Sample Data Failed");
|
|
|
+ code = ResponseCode.RESULT_BAD;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (CommTool.listSize(siteSampleData.getData()) <= 0
|
|
|
+ || CommTool.listSize(siteSampleData.getData().get(0).getRecords()) <= 0){
|
|
|
+ step = String.format("Get Site Sample Data Empty");
|
|
|
+ code = ResponseCode.RESULT_BAD;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (SiteSampleGroupItem sampleItem:siteSampleData.getData().get(0).getRecords()){
|
|
|
+ if (sampleItem.getTime() <= 0L)
|
|
|
+ continue;
|
|
|
+ if (planDetail.getDayTriggerUpperTimes() > 0
|
|
|
+ && thisTempStep.getDayTriggerTimes() >= planDetail.getDayTriggerUpperTimes()){
|
|
|
+ step = String.format("Event Arrive Max Limit");
|
|
|
+ code = ResponseCode.RESULT_BAD;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ boolean matched = false;
|
|
|
+ OrdWarnPlanRules findRule = null;
|
|
|
+ int dataClock = (int)((sampleItem.getTime()/1000/60/60%24+8)%24);
|
|
|
+ for (OrdWarnPlanRules ruleItem:rules){
|
|
|
+ if (dataClock <= ruleItem.getEnd() && dataClock >= ruleItem.getStart()){
|
|
|
+ findRule = ruleItem;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (findRule == null)
|
|
|
+ continue;
|
|
|
+ for (OrdWarnRuleCondition condition:findRule.getConditions()){
|
|
|
+ String needMatchValue = "";
|
|
|
+ for (KeyValue kv:sampleItem.getFields()){
|
|
|
+ if (condition.getTag().equals(kv.getKey())){
|
|
|
+ needMatchValue = kv.getValue();
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (StringUtils.isEmpty(needMatchValue))
|
|
|
+ matched = matched || false;
|
|
|
+ else {
|
|
|
+ try {
|
|
|
+ int nRes = CommTool.compareFloat(needMatchValue, condition.getThreshold());
|
|
|
+ if (nRes == 0){
|
|
|
+ if ("!=".equals(condition.getMethod())){
|
|
|
+ matched = (matched || false);
|
|
|
+ }else if (condition.getMethod().contains("=")){
|
|
|
+ matched = (matched || true);
|
|
|
+ }else
|
|
|
+ matched = (matched || false);
|
|
|
+ }else if (nRes > 0){
|
|
|
+ if ("!=".equals(condition.getMethod())){
|
|
|
+ matched = (matched || true);
|
|
|
+ }else if (condition.getMethod().contains(">")){
|
|
|
+ matched = (matched || true);
|
|
|
+ }else
|
|
|
+ matched = (matched || false);
|
|
|
+ }else {
|
|
|
+ if ("!=".equals(condition.getMethod())){
|
|
|
+ matched = (matched || true);
|
|
|
+ }else if (condition.getMethod().contains("<")){
|
|
|
+ matched = (matched || true);
|
|
|
+ }else
|
|
|
+ matched = (matched || false);
|
|
|
+ }
|
|
|
+ }catch (Exception e){}
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!matched){//本次没有匹配成功
|
|
|
+ thisTempStep.setLastCompareSampleTime(sampleItem.getTime());
|
|
|
+ thisTempStep.setLastCompareSampleResult(0);
|
|
|
+ thisTempStep.setFirstMatchSampleTime(0L);
|
|
|
+ thisTempStep.setLastEventId("");
|
|
|
+ thisTempStep.setLastEventTime(0L);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (thisTempStep.getLastCompareSampleResult() <= 0){//上一次没有匹配成功
|
|
|
+ thisTempStep.setLastCompareSampleTime(sampleItem.getTime());
|
|
|
+ thisTempStep.setLastCompareSampleResult(1);
|
|
|
+ thisTempStep.setFirstMatchSampleTime(sampleItem.getTime());
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ long diffMatch = sampleItem.getTime()-thisTempStep.getLastCompareSampleTime();//两个最近匹配样本之间的时间差(单位:毫秒)
|
|
|
+ if (diffMatch > planDetail.getThresholdPeriod()*TimeTool.MS_ONE_MIN){//两个最近匹配样本间缺失的数据太多、或跨了天、或跨了时段,可重新计数
|
|
|
+ thisTempStep.setLastCompareSampleTime(sampleItem.getTime());
|
|
|
+ thisTempStep.setLastCompareSampleResult(1);
|
|
|
+ thisTempStep.setFirstMatchSampleTime(sampleItem.getTime());
|
|
|
+ thisTempStep.setLastEventId("");
|
|
|
+ thisTempStep.setLastEventTime(0L);
|
|
|
+ continue;
|
|
|
+ }else {
|
|
|
+ //两个最近匹配样本间隔很近,可认为是持续匹配
|
|
|
+ }
|
|
|
+
|
|
|
+ if (thisTempStep.getLastCompareSampleTime() < thisTempStep.getConditionMinUTC()){//上一个匹配样本是昨天的,可重新计数
|
|
|
+ thisTempStep.setLastCompareSampleTime(sampleItem.getTime());
|
|
|
+ thisTempStep.setLastCompareSampleResult(1);
|
|
|
+ thisTempStep.setFirstMatchSampleTime(sampleItem.getTime());
|
|
|
+ thisTempStep.setLastEventId("");
|
|
|
+ thisTempStep.setLastEventTime(0L);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ long matchLen = (thisTempStep.getFirstMatchSampleTime()<=0)?0:(sampleItem.getTime()-thisTempStep.getFirstMatchSampleTime());//样本匹配的持续时长(单位:毫秒)
|
|
|
+ if (StringUtils.isEmpty(thisTempStep.getLastEventId())){//之前无预警事件
|
|
|
+ if (matchLen < planDetail.getThresholdPeriod()*TimeTool.MS_ONE_MIN){//还有持续等待
|
|
|
+ thisTempStep.setLastCompareSampleTime(sampleItem.getTime());
|
|
|
+ thisTempStep.setLastCompareSampleResult(1);
|
|
|
+ if (thisTempStep.getFirstMatchSampleTime() <= 0)
|
|
|
+ thisTempStep.setFirstMatchSampleTime(sampleItem.getTime());
|
|
|
+ }else {//触发一个新的事件
|
|
|
+ thisTempStep.setLastCompareSampleTime(sampleItem.getTime());
|
|
|
+ thisTempStep.setLastCompareSampleResult(1);
|
|
|
+ thisTempStep.setLastEventId("新事件ID");
|
|
|
+ thisTempStep.setLastEventTime(curTime);
|
|
|
+ thisTempStep.setLastEventAction(1);
|
|
|
+ thisTempStep.setDayTriggerTimes(thisTempStep.getDayTriggerTimes()+1);
|
|
|
+ }
|
|
|
+ }else {//之前有预警事件
|
|
|
+ if (thisTempStep.getLastEventAction() >= 2){//之前的预警事件已处理,则可认为进行重新计数
|
|
|
+ thisTempStep.setLastCompareSampleTime(sampleItem.getTime());
|
|
|
+ thisTempStep.setLastCompareSampleResult(1);
|
|
|
+ thisTempStep.setFirstMatchSampleTime(sampleItem.getTime());
|
|
|
+ thisTempStep.setLastEventId("");
|
|
|
+ thisTempStep.setLastEventTime(0L);
|
|
|
+ }else {//之前的预警事件未处理,则更新预警事件的样本截止时刻
|
|
|
+ thisTempStep.setLastCompareSampleTime(sampleItem.getTime());
|
|
|
+ thisTempStep.setLastCompareSampleResult(1);
|
|
|
+ eventId2NewEndUTC.put(thisTempStep.getLastEventId(), sampleItem.getTime());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }while (false);
|
|
|
+ return code;
|
|
|
+ }
|
|
|
+
|
|
|
+ //处理时段差值数据
|
|
|
+ private void handleDataByDiff(){
|
|
|
+
|
|
|
+ }
|
|
|
+}
|