package jtznyj.engineer.service.winform;

import com.alibaba.fastjson.JSON;
import jtznyj.engineer.entity.BWellOwnEngineer;
import jtznyj.engineer.service.dataDiagnosticService.data.*;
import jtznyj.engineer.service.dataDiagnosticService.models.AlarmType;
import jtznyj.engineer.service.dataDiagnosticService.models.FieldRule;
import jtznyj.engineer.vo.LtdRecord;
import jtznyj.engineer.service.dataDiagnosticService.models.WellOwn;
import jtznyj.engineer.service.winform.data.*;

import java.util.*;

/**
 * 预警引擎诊断配置类
 */
public class CheckEngineerWarning {

    private WellOwn wellOwn;
    /**
     * 参数模板列表
     */
    public Hashtable<String, MonitorCurverParams> mcpsList = new Hashtable<String, MonitorCurverParams>();

    private RecordHashTable _prevDrillStateData = null;
    public Hashtable _monitorConfig = new Hashtable();


    public boolean _isPumpRun = true;
    public Date _dtPumpRunTime = new Date();
    public Date _dtPumpStopTime = new Date();

    public final static String DateTimeFormat = "yyyy-MM-dd HH:mm:ss.SSS";

    String WellNameField = "井号";
    String DateField = "时间";
    /**
     * 实时数据字段
     */
    public static ArrayList<RealDataField> RealDataFields = new ArrayList<RealDataField>() {
        {
            add(new RealDataField("JS", "时间","秒", 0f, 5000f));
            add(new RealDataField("[实测井深(M)]", "井深","m", 0f, 5000f));
            add(new RealDataField("[钻时(MIN/M)]", "钻时", "min/m",0f, 5000f));
            add(new RealDataField("[转速(RPM)]", "转盘转速","rpm", 0f, 5000f));
            add(new RealDataField("[钻压(kN)]", "钻压","kN", 0f, 5000f));
            add(new RealDataField("[大钩负荷(kN)]", "大钩负荷","kN", 0f, 5000f, 9.8f));
            add(new RealDataField("[立压(MPa)]", "立管压力","MPa", 0f, 5000f));
            add(new RealDataField("[扭矩(kN.m)]", "转盘扭矩","kN.m", 0f, 5000f));
            add(new RealDataField("[泵冲1(SPM)]", "一号泵冲", "spm",0f, 5000f));
            add(new RealDataField("[泵冲2(SPM)]", "二号泵冲","spm", 0f, 5000f));
            add(new RealDataField("[一号池体积(m3)]", "池体积1","m3", 0f, 5000f));
            add(new RealDataField("[二号池体积(m3)]", "池体积2","m3", 0f, 5000f));
            add(new RealDataField("[三号池体积(m3)]", "池体积3","m3", 0f, 5000f));
            add(new RealDataField("[四号池体积(m3)]", "池体积4","m3", 0f, 5000f));
            add(new RealDataField("[总体积(m3)]", "总池体积","m3", 0f, 5000f));
            add(new RealDataField("[体积变化量(%)]", "泥浆溢漏", "%",0f, 5000f));
            add(new RealDataField("[入口温度(degC)]", "入口温度","deg_f", 0f, 5000f));
            add(new RealDataField("[出口温度(degC)]", "出口温度","deg_f", 0f, 5000f));
            add(new RealDataField("[入口电导(ms)]", "入口电导","ms", 0f, 5000f));
            add(new RealDataField("[出口电导(ms)]", "出口电导","ms", 0f, 5000f));
            add(new RealDataField("[入口密度(g/cm3)]", "入口密度","g/cm3", 0f, 5000f));
            add(new RealDataField("[出口密度(g/cm3)]", "出口密度","g/cm3", 0f, 5000f));
            add(new RealDataField("[入口流量(1/min)]", "入口流量", "L/min",0f, 5000f));
            add(new RealDataField("[出口流量(%)]", "出口流量%", "%",0f, 5000f));
            add(new RealDataField("[出口流量(l/min)]", "出口流量", "L/min",0f, 5000f));
            add(new RealDataField("[D指数]", "","", 0f, 5000f));
            add(new RealDataField("[DC指数]", "","", 0f, 5000f));
            add(new RealDataField("[循环当量密度]", "","", 0f, 5000f));
            add(new RealDataField("[压力梯度]", "","", 0f, 5000f));
            add(new RealDataField("[破裂梯度]", "","", 0f, 5000f));
            add(new RealDataField("[迟到井深(m)]", "迟到井深","m", 0f, 5000f));
            add(new RealDataField("[总烃(%)]", "总烃", "%",0f, 5000f));
            add(new RealDataField("[C1(%)]", "C1","%", 0f, 5000f));
            add(new RealDataField("[C2(%)]", "C2","%", 0f, 5000f));
            add(new RealDataField("[C3(%)]", "C3", "%",0f, 5000f));
            add(new RealDataField("[iC4(%)]", "iC4","%", 0f, 5000f));
            add(new RealDataField("[nC4(%)]", "nC4","%", 0f, 5000f));
            add(new RealDataField("[iC5(%)]", "iC5","%", 0f, 5000f));
            add(new RealDataField("[nC5(%)]", "nC5","%", 0f, 5000f));
            add(new RealDataField("[Co2(%)]", "Co2","%", 0f, 5000f));
            add(new RealDataField("[H(%)]", "H2","%", 0f, 5000f));
            add(new RealDataField("[一号H2s(%)]", "H2S_1","%", 0f, 5000f));
            add(new RealDataField("[二号H2s(%)]", "H2S_2","%", 0f, 5000f));
            add(new RealDataField("[三号H2s(%)]", "H2S_3","%", 0f, 5000f));
            add(new RealDataField("[湿度比]", "","", 0f, 5000f));
            add(new RealDataField("[平衡比]", "","", 0f, 5000f));
            add(new RealDataField("[特性比]", "","", 0f, 5000f));
            add(new RealDataField("[垂直井深(m)]", "垂直井深","m", 0f, 5000f));
            add(new RealDataField("[钻头位置(m)]", "钻头位置","m", 0f, 5000f));
            add(new RealDataField("[大钩高度(m)]", "大钩位置","m", 0f, 5000f));
            add(new RealDataField("[泵冲3(SPM)]", "三号泵冲","spm", 0f, 5000f));
            add(new RealDataField("[Temp1]", "","", 0f, 5000f));
            add(new RealDataField("[Temp2]", "","", 0f, 5000f));
            add(new RealDataField("[Temp3]", "","", 0f, 5000f));
            add(new RealDataField("[Temp4]", "","", 0f, 5000f));
            add(new RealDataField("[Temp5]", "","", 0f, 5000f));
            add(new RealDataField("[Temp6]", "","", 0f, 5000f));
            add(new RealDataField("[Temp7]", "","", 0f, 5000f));
            add(new RealDataField("[Temp8]", "","", 0f, 5000f));
            add(new RealDataField("[Temp9]", "","", 0f, 5000f));
            add(new RealDataField("[Temp10]", "","", 0f, 5000f));
            add(new RealDataField("[Temp11]", "", "",0f, 5000f));
            add(new RealDataField("[Temp12]", "","", 0f, 5000f));
            add(new RealDataField("[Temp13]", "","", 0f, 5000f));
            add(new RealDataField("[Temp14]", "", "",0f, 5000f));
            add(new RealDataField("[Temp15]", "","", 0f, 5000f));
            add(new RealDataField("[Temp16]", "","", 0f, 5000f));
            add(new RealDataField("[Temp17]", "","", 0f, 5000f));
            add(new RealDataField("[Temp18]", "", "",0f, 5000f));
            add(new RealDataField("[Temp19]", "","", 0f, 5000f));
            add(new RealDataField("[Temp20]", "","", 0f, 5000f));
            add(new RealDataField("[Temp21]", "","", 0f, 5000f));
            add(new RealDataField("[Temp22]", "","", 0f, 5000f));
            add(new RealDataField("[Temp23]", "","", 0f, 5000f));
            add(new RealDataField("[Temp24]", "","", 0f, 5000f));
        }
    };

    public CheckEngineerWarning(BWellOwnEngineer template) {
        //解析预警参数
        wellOwn = JSON.parseObject(template.getLargeText(), WellOwn.class);

        //初始化预警参数列表
        for (AlarmType alarmType : wellOwn.AlarmTypeList) {
            mcpsList.put(alarmType.name, LoadMonitorCurverParams(alarmType));
        }
    }

    /// <summary>
    /// 预警分析
    /// </summary>
    /// <param name="record">预警的单条数据记录</param>
    /// <param name="monitorAlarmRecords">预警结果</param>
    /// <param name="ds"></param>
    /// <returns></returns>
    @Deprecated
    public void AnalyseDataList(List<RecordHashTable> dataList, MonitorAlarmRecords monitorAlarmRecords) {
        boolean result = false;
        //result = result ||
        //当前钻井状态
        DrillState drillState = DrillState.None;
        for (Map.Entry<String, MonitorCurverParams> entry : mcpsList.entrySet()) {
            //System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
            if(entry.getValue()._isEnable){
                this.CalcModel(entry.getKey(), entry.getValue(), dataList, drillState, monitorAlarmRecords);
            }
        }
    }

    /// <summary>
    /// 预警分析
    /// </summary>
    /// <param name="record">预警的单条数据记录</param>
    /// <param name="monitorAlarmRecords">预警结果</param>
    /// <param name="ds"></param>
    /// <returns></returns>
    public HashMap<String, Object> Analyse(RecordHashTable record, MonitorAlarmRecords monitorAlarmRecords, DrillState ds) {
        boolean isNewAlarm = false;
        boolean result = false;
        HashMap<String, Object> rv = new HashMap<String, Object>();
        if (record == null) {
            ds = DrillState.TakePipe;
            result = isNewAlarm;
            rv.put("result", result);
            rv.put("ds", ds);
            return rv;
        }

        // region 准备数据
        // 数据准备阶段可以进步优化掉-多余的一个过程
        //RecordHashTable insertRecord = (RecordHashTable) record.Clone();
        RecordHashTable insertRecord = record;
        //屏蔽无用的代码
        boolean currentIsPumpRun = false;
        DrillStateResult temp = this.GetDrillState(insertRecord);
        //钻机状态
        ds = temp.state;
        //当前是否开泵
        currentIsPumpRun = temp.isPumpRun;
        if (_prevDrillStateData == null) {
            _dtPumpRunTime =  (Date) insertRecord.get(MonitorContext.fieldTime);
            _dtPumpStopTime = (Date) insertRecord.get(MonitorContext.fieldTime);
        } else {
            //_dtPumpRunTime = Date.Parse(_prevDrillStateData[MonitorContext.fieldTime].ToString().Trim());
            //_dtPumpStopTime = Date.Parse(_prevDrillStateData[MonitorContext.fieldTime].ToString().Trim());

        }
        if (this._isPumpRun != currentIsPumpRun) {
            if (currentIsPumpRun) {
                this._dtPumpRunTime = (Date) insertRecord.get(MonitorContext.fieldTime);
            } else {
                this._dtPumpStopTime = (Date) insertRecord.get(MonitorContext.fieldTime);
            }
        }
        this._isPumpRun = currentIsPumpRun;
        // endregion
        Enumeration<String> k2 = mcpsList.keys();
        while (k2.hasMoreElements()) {
            String key = k2.nextElement();
            MonitorCurverParams value = (MonitorCurverParams) mcpsList.get(key);
            if (value._isEnable) {
                result = result || Cal(key, value, insertRecord, currentIsPumpRun, ds, monitorAlarmRecords);
            }
        }

        result = isNewAlarm;

        rv.put("result", result);
        rv.put("ds", ds);

        return rv;
    }

    /**
     * 根据一个具体诊断模型诊断给定的一段数据
     * @param alarmName
     * @param mcps:模型所有参数
     * @param drillState
     * @param monitorAlarmRecords
     * @return 返回值 false:没有异常 true:有异常
     */
    private boolean CalcModel(String alarmName, MonitorCurverParams mcps,
                              List<RecordHashTable> dataList,DrillState drillState, MonitorAlarmRecords monitorAlarmRecords) {
        boolean result = false;
        // 多个预警模型， 每个模型多个条件， 每个条件对应一个字段？
        mcps.sort(MonitorCurverParam.McpSortByGroupNum);
        Hashtable groups = new Hashtable();
        for (MonitorCurverParam mcp : mcps) {
            if (!groups.containsKey(mcp._fzNum)) {
                groups.put(mcp._fzNum, 1);
            }
        }

        //System.out.println(groups);

        //监控信息列表
        ArrayList<MonitorDescription> monitorDescriptions = new ArrayList<MonitorDescription>();
        int nGroupAlarmState = 1;

        double percent = 0.0;

        //================================================================
        //遍历所有模型--Begin
        for (int i = 0; i < mcps.size(); i++) {
            MonitorCurverParam mcp = mcps.get(i);//监控参数
            if (mcp._fieldUseable) {
                nGroupAlarmState = (int) groups.get(mcp._fzNum);
                MonitorDescription monitorDescription;
                boolean bAlarm;//是否报警

                double percentItem = 0.0;
                double mulItem = 1.0 / (double) mcps.size();
                CurverAnalyseResult results = mcp.doPerformAnalyse(dataList);

                if (results==null ){
                    continue;
                }

                bAlarm = results.result;
                percentItem = results.percent;
                monitorDescription = results.md;
                if (percentItem > 1.0) {
                    percentItem = 1.0;
                }
                percent += percentItem * mulItem;
                if (percent > 1.0) {
                    percent = 1.0;
                }
                //屏蔽掉所有参数的重置功能
//                if (results.resetAllParams) {
//                    for (MonitorCurverParam mcpItem : mcps) {
//                        mcpItem.ResetMonitorParams();
//                    }
//                }
                // 20220915
                if (bAlarm) {
                    monitorDescriptions.add(monitorDescription);
                    if(mcp._fieldHandleType == FieldHandleType.FHT_Or){
                        nGroupAlarmState |= 1;
                    }
                } else if (mcp._fieldHandleType == FieldHandleType.FHT_And) {
                    nGroupAlarmState = 0;
                }
//                if (bAlarm) {
//                    monitorDescriptions.add(monitorDescription);
//                } else if (mcp._fieldHandleType == FieldHandleType.FHT_And) {
//                    nGroupAlarmState = 0;
//                }
//                if(bAlarm && mcp._fieldHandleType == FieldHandleType.FHT_Or){
//                    nGroupAlarmState |= 1;
//                }
                groups.put(mcp._fzNum, nGroupAlarmState);
            }
        }

        //遍历所有模型--end
        //================================================================

        //按照分组设计，对预警状态进行分析
        int nAllAlarmState = 1;//预警状态值
        Enumeration<Object> k5 = groups.keys();
        while (k5.hasMoreElements()) {
            Object key = k5.nextElement();
            int nAlarmState = (int) groups.get(key);
            // TODO: 确认是需要按位计算和，还是逻辑计算和 20220914
            nAllAlarmState &= nAlarmState;
        }
        if (mcps.size() == 0) {
            nAllAlarmState = 0;
        }
        if ((mcps._drillState & drillState.value()) == drillState.value()) {
            if (nAllAlarmState > 0 && monitorDescriptions.size() > 0) {
                percent = 1.0;
                monitorDescriptions.sort(MonitorDescription.McpSortByStartTime);
                this.UpdateListMonitorDescriptions(monitorAlarmRecords, alarmName, monitorDescriptions);

                result = true;
            }
            //矫正百分数（确保0<=percent<=1）
            percent = Math.min(Math.max(0,percent),1.0);
            mcps.percent = percent;
        }

        return result;
    }


    /**
     * 根据一个具体诊断模型参数诊断状况
     * @param alarmName
     * @param mcps
     * @param insertRecord
     * @param currentIsPumpRun
     * @param drillState
     * @param monitorAlarmRecords
     * @return 返回值 false:没有异常 true:有异常
     */
    private boolean Cal(String alarmName, MonitorCurverParams mcps,
                        Hashtable insertRecord, boolean currentIsPumpRun,
                        DrillState drillState, MonitorAlarmRecords monitorAlarmRecords) {
        boolean result = false;
        // 多个预警模型， 每个模型多个条件， 每个条件对应一个字段？
        // mcps 对应一个模型 ?
        //MonitorCurverParams mcps = (MonitorCurverParams)this._monitorConfig[key];

        mcps.sort(MonitorCurverParam.McpSortByGroupNum);
        Hashtable groups = new Hashtable();
        for (MonitorCurverParam mcp : mcps) {
            if (!groups.containsKey(mcp._fzNum)) {
                groups.put(mcp._fzNum, 1);
            }
        }

        //System.out.println(groups);

        //监控信息列表
        ArrayList<MonitorDescription> monitorDescriptions = new ArrayList<MonitorDescription>();
        int nGroupAlarmState = 1;

        double percent = 0.0;

        //================================================================
        //遍历所有模型--Begin
        for (int i = 0; i < mcps.size(); i++) {
            MonitorCurverParam mcp = mcps.get(i);//监控参数
            if (mcp._fieldUseable) {
                //这个mcp._fieldUseable 全部都是true  这一步为啥要写？？？？？？？

                nGroupAlarmState = (int) groups.get(mcp._fzNum);
                MonitorDescription monitorDescription;
                boolean bResetParams = false;
                boolean bAlarm = false;//是否报警

                double percentItem = 0.0;
                double mulItem = 1.0 / (double) mcps.size();
                CurverAnalyseResult results = mcp.CurverAnalyse(
                        insertRecord,
                        currentIsPumpRun,
                        drillState,
                        this._dtPumpRunTime,
                        this._dtPumpStopTime);

                bAlarm = results.result;
                bResetParams = results.resetAllParams;
                percentItem = results.percent;
                monitorDescription = results.md;
                if (percentItem > 1.0) {
                    percentItem = 1.0;
                }
                percent += percentItem * mulItem;
                if (percent > 1.0) {
                    percent = 1.0;
                }
                if (bResetParams) {
                    for (MonitorCurverParam mcpItem : mcps) {
                        mcpItem.ResetMonitorParams();
                    }
                }
                if (bAlarm) {
                    monitorDescriptions.add(monitorDescription);
                } else if (mcp._fieldHandleType == FieldHandleType.FHT_And) {
                    nGroupAlarmState = 0;
                }
                if (bAlarm && mcp._fieldHandleType == FieldHandleType.FHT_Or) {
                    nGroupAlarmState |= 1;
                }
                groups.put(mcp._fzNum, nGroupAlarmState);
                mcp.AdjustDataByMonitorTime();
            }
        }

        //遍历所有模型--end
        //================================================================

        //按照分组设计，对预警状态进行分析
        int nAllAlarmState = 1;//预警状态值
        Enumeration<Object> k5 = groups.keys();
        while (k5.hasMoreElements()) {
            Object key = k5.nextElement();
            int nAlarmState = (int) groups.get(key);
            nAllAlarmState &= nAlarmState;
        }
        if (mcps.size() == 0) {
            nAllAlarmState = 0;
        }
        if ((mcps._drillState & drillState.value()) == drillState.value()) {
            if (nAllAlarmState > 0 && monitorDescriptions.size() > 0) {
                percent = 1.0;
                monitorDescriptions.sort(MonitorDescription.McpSortByStartTime);
                this.UpdateListMonitorDescriptions(monitorAlarmRecords, alarmName, monitorDescriptions);

                result = true;
            }
            //矫正百分数（确保0<=percent<=1）
            percent = Math.min(Math.max(0,percent),1.0);
            mcps.percent = percent;
        }

        return result;
    }

    /**
     * 加载监控曲线参数
     * @param src
     * @return
     */
    public MonitorCurverParams LoadMonitorCurverParams(AlarmType src) {
        MonitorCurverParams mcps = new MonitorCurverParams();
        mcps._isEnable = src.isEnable;
        mcps._drillState = src.drillState;

        for (FieldRule field : src.FieldRules) {
            mcps.add(Translate(field));
        }

        return mcps;
    }

    public String getFieldName(String sName){
        RealDataField field;
        sName = sName.toLowerCase();
        for (int i = 0; i < CheckEngineerWarning.RealDataFields.size(); i++) {
            field = CheckEngineerWarning.RealDataFields.get(i);
            if(sName.equals(field.get_realField().toLowerCase()) || sName.equals(field.get_displayName().toLowerCase())){
                return field.StandardName;
            }
        }

        return "";
    }

    public static String getRealFieldName(String sName){
        RealDataField field;
        sName = sName.toLowerCase();
        for (int i = 0; i < CheckEngineerWarning.RealDataFields.size(); i++) {
            field = CheckEngineerWarning.RealDataFields.get(i);
            if(sName.equals(field.get_realField().toLowerCase()) || sName.equals(field.get_displayName().toLowerCase())){
                return field.StandardName;
            }
        }

        return "";
    }

    /**
     * 字段规则转换--强制将字段配置规范：Trim+toLowerCase
     * @param src
     * @return
     */
    private MonitorCurverParam Translate(FieldRule src) {
        // color, upDownRangeTotalNum 未转译
        MonitorCurverParam mcp = new MonitorCurverParam();
        if (src.fieldHandleType != -1) {
            mcp._fieldHandleType = FieldHandleType.valueOf(src.fieldHandleType);
        }
        
        mcp._fzNum = src.fzNum;
        mcp._continue = src.Continue;
        mcp._continueValue = src.continueValue;
        mcp._analyseType = AnalyseType.valueOf(src.analyseType);
        mcp._fieldUseable = src.fieldUseable;
        mcp._name = src.name;
        //强制将字段配置规范：Trim+toLowerCase
        mcp._originalField = this.getFieldName(src.realField==null ?"":src.realField);
//        mcp._displayField =
        mcp._realField = src.realField==null ? "" : src.realField.trim();
        mcp._monitorTime = src.monitorTime;
        mcp._continuedTime = src.continuedTime;
        mcp._maxTotalNum = src.maxTotalNum;
        mcp._minTotalNum = src.minTotalNum;
        mcp._zdCount = src.zdCount;
        mcp._bdLtValue = src.bdLtValue;
        mcp._trendType = TrendType.valueOf(src.trendType);
        mcp._totalNum = src.TotalNum;
        mcp._trendTypeParam = TrendTypeParam.valueOf(src.trendTypeParam);
        mcp._beginValue = src.beginValue;
        if (mcp._beginValue <= 0.0001) {
            mcp._beginValue = 0.0;
        }
        mcp._endValue = src.endValue;
        mcp._mul = src.mul;
        mcp._isPumpRunJump = src.isPumpRunJump;
        mcp._isPumpRunJumpTime = src.isPumpRunJumpTime;
        mcp._isPumpStopJump = src.isPumpStopJump;
        mcp._isPumpStopJumpTime = src.isPumpStopJumpTime;
        mcp._pchx = src.pchx;
        mcp._pchxTime = src.pchxTime;

        /**
         * 是否启用前置条件
         */
        mcp.preconditions = src.preconditions;
        /**
         * 前置条件判断字段
         */
        mcp.preconditionsField = src.preconditionsField;
        /**
         * 前置条件list
         */
        mcp.doorList = src.doorList;

        return mcp;
    }

    /**
     * 获得钻机状态信息
     * @param record
     * @return
     */
    public DrillStateResult GetDrillState(RecordHashTable record) {
        DrillStateResult result = new DrillStateResult();

        boolean currentIsPumpRun;
        //时间
        //泵冲1(SPM)
        double bc = (double) record.get(MonitorContext.fieldBc1);
        //泵冲2(SPM)
        double bc2 = (double) record.get(MonitorContext.fieldBc2);
        //泵冲3(SPM)
        double bc3 = (double) record.get(MonitorContext.fieldBc3);
        //钻头位置(m)
        double ztwz = (double) record.get(MonitorContext.fieldZtwz);
        //实测井深(M)
        double js = (double) record.get(MonitorContext.fieldScjs);

        //fieldCdsj = "迟到时间";

        //大钩高度(m)
        double dggd = (double) record.get(MonitorContext.fieldDggd);
        //大钩负荷(kN)
        double dgfh = (double) record.get(MonitorContext.fieldDgfh);
        //立压(MPa)
        double ly = (double) record.get(MonitorContext.fieldLy);
        //转速(RPM)
        double zpzs = (double) record.get(MonitorContext.fieldZpzs);

        //fieldZtjc = "Temp5";
        //默认也是没有对应的字段
        double ztjc = 0.0;
        try {
            ztjc = (double) record.get(MonitorContext.fieldZtjc);
        } catch (Exception ex_C0) {
        }
        double bc4 = bc + bc2 + bc3;
        double zqmx = 15.0;
        zqmx *= 9.8;
        double bcmx = 1.0;
        double qxzcd = 27.0;
        //开泵条件
        currentIsPumpRun = (bc > bcmx || bc2 > bcmx || bc3 > bcmx);
        boolean bZpRun = zpzs > 0.001;
        boolean bZtjc = ztjc > 0.001;

        boolean bQxzRange = Math.abs(ztwz - js) < qxzcd;//Math.abs(钻头位置-实测井深)
        DrillState curDrillState;
        if (this._prevDrillStateData == null) {
            //默认第一条是停钻状态
            curDrillState = DrillState.Stop;
        } else {
            //上一钻头位置
            double prevZtwz = (double) this._prevDrillStateData.get(MonitorContext.fieldZtwz);
            //上一大钩高度
            double prevDggd = (double) this._prevDrillStateData.get(MonitorContext.fieldDggd);
            boolean bZj = ztwz - prevZtwz > 0.0;
            boolean bDgDown = prevDggd - dggd > 0.0;
            double dAbsZtwz = Math.abs(ztwz - prevZtwz);
            //判断大钩负荷和zqmx关系
            if (dgfh < zqmx) {
                //钻机状态--卡坐
                curDrillState = DrillState.TakePipe;
                if (currentIsPumpRun) {
                    //如果是开泵状态，则钻机状态处于循环状态
                    curDrillState = DrillState.Circulate;
                }
            } else if (currentIsPumpRun && (bZpRun || bZtjc) && bQxzRange) {
                double subZtjs = ztwz - js;
                if (Math.abs(subZtjs) < 0.1 || bZtjc) {
                    curDrillState = DrillState.Drilling;
                } else {
                    curDrillState = DrillState.ClearHole;
                }
            } else if (dAbsZtwz < 1E-05) {
                if (currentIsPumpRun) {
                    if (bZpRun) {
                        curDrillState = DrillState.ClearHole;
                    } else {
                        curDrillState = DrillState.Circulate;
                    }
                } else if (bDgDown) {
                    curDrillState = DrillState.Trip;
                } else {
                    curDrillState = DrillState.DrillDown;
                }
            } else if (currentIsPumpRun) {
                curDrillState = DrillState.Circulate;
            } else if (ztwz - prevZtwz >= 0.0) {
                curDrillState = DrillState.DrillDown;
            } else {
                curDrillState = DrillState.Trip;
            }
        }
        //不必克隆数据
        //this._prevDrillStateData = (RecordHashTable) record.Clone();
        this._prevDrillStateData = record;
        result.state = curDrillState;
        result.isPumpRun = currentIsPumpRun;
        return result;
    }

    /**
     * 将诊断的数据（数据库）转为哈希表--KEY值小写
     * @param src
     * @return
     */
    private static Hashtable LtdToHashtable(LtdRecord src) {
        Hashtable result = new Hashtable();
        result.put("钻压", src.WOB); //钻压 0
        result.put("h2s_2", src.H2S2); //h2s_2 0
        result.put("h2s_3", src.H2S3); //h2s_3 0
        result.put("转盘转速", src.RPM);//转盘转速 0.1786
        result.put("h2s_1", src.H2S1);//h2s_1 0
        result.put("出口电导", src.CONDOUT);//出口电导 0
        result.put("大钩负荷", src.WOH);//大钩负荷 290.421
        result.put("入口密度", src.MWIN);//入口密度 1.4265
        result.put("池体积2", src.PIT2);//池体积2 27.219
        result.put("二号泵冲", src.PUMP2);//二号泵冲 0
        result.put("三号泵冲", src.PUMP3);//三号泵冲 0
        result.put("井深", src.DEPTH);//井深 4232
        result.put("入口流量", src.FLOWIN);//入口流量 0
        result.put("c3", src.C3);//c3 0.0011
        result.put("出口密度", src.MWOUT);//出口密度 0.96
        result.put("迟到井深", src.LAGDEPTH);//迟到井深 4232
        result.put("池体积1", src.PIT1);//池体积1 25.2598
        result.put("出口流量", src.FLOWOUT);//出口流量 - 999.25
        result.put("出口流量%", src.FLOWOUTPERCENT);//出口流量 - 999.25
        result.put("立管压力", src.SPP);//立管压力 0
        result.put("时间", src.TIME);//时间 2021 / 9 / 6 0:00:22
        result.put("垂直井深", src.VDEPTH);//垂直井深 4013.48
        result.put("c1", src.C1);//c1 0.0025
        result.put("转盘扭矩", src.TORQUE);//转盘扭矩 0
        result.put("nc5", src.NC5);//nc5 0
        result.put("池体积5", src.PIT5);//池体积5 0
        result.put("co2", src.CO2);//co2 0.0396
        result.put("钻时", src.ROP_MAVG);//钻时 16.2108
        result.put("总池体积", src.PITTOTAL);//总池体积 78.0719
        result.put("套压", src.WHP);//套压 0
        result.put("ic4", src.IC4);//ic4 0.0011
        result.put("h2", src.H2);//h2 - 0.9999
        result.put("总烃", src.TG);//总烃 0
        result.put("ic5", src.IC5);//ic5 0.0018
        result.put("池体积4", src.PIT4);//池体积4 0
        result.put("nc4", src.NC4);//nc4 0
        result.put("一号泵冲", src.PUMP1);//一号泵冲 0
        result.put("大钩位置", src.HKH);//大钩位置 35.9999
        result.put("c2", src.C2);//c2 0.0014
        result.put("入口温度", src.TEMPIN);//入口温度 48.285
        result.put("泥浆溢漏", src.GAINLOSSVOL);//泥浆溢漏 - 999.25
        result.put("出口温度", src.TEMPOUT);//出口温度 27.97
        result.put("钻头位置", src.BITDEPTH);//钻头位置 8.9763
        result.put("入口电导", src.CONDIN);//入口电导 442.495
        result.put("池体积3", src.PIT3);//池体积3 25.5931

        return result;
    }

    /**
     * 将诊断的数据（数据库）转为哈希表--KEY值小写
     * @param src
     * @return
     */
    public static RecordHashTable LtdToRecordHashTable(LtdRecord src) {
        RecordHashTable result = new RecordHashTable();
        result.put("钻压", src.WOB); //钻压 0
        result.put("h2s_2", src.H2S2); //h2s_2 0
        result.put("转盘转速", src.RPM);//转盘转速 0.1786
        result.put("h2s_1", src.H2S1);//h2s_1 0
        result.put("h2s_3", src.H2S3);//h2s_3 0
        result.put("出口电导", src.CONDOUT);//出口电导 0
        result.put("大钩负荷", src.WOH);//大钩负荷 290.421
        result.put("入口密度", src.MWIN);//入口密度 1.4265
        result.put("池体积2", src.PIT2);//池体积2 27.219
        result.put("二号泵冲", src.PUMP2);//二号泵冲 0
        result.put("三号泵冲", src.PUMP3);//三号泵冲 0
        result.put("井深", src.DEPTH);//井深 4232
        result.put("入口流量", src.FLOWIN);//入口流量 0
        result.put("c3", src.C3);//c3 0.0011
        result.put("出口密度", src.MWOUT);//出口密度 0.96
        result.put("迟到井深", src.LAGDEPTH);//迟到井深 4232
        result.put("池体积1", src.PIT1);//池体积1 25.2598
        result.put("出口流量", src.FLOWOUT);//出口流量 - 999.25
        result.put("出口流量%", src.FLOWOUTPERCENT);//出口流量 - 999.25
        result.put("立管压力", src.SPP);//立管压力 0
        try {
            Date dtTime = org.jeecg.common.util.DateUtils.parseDate(src.TIME.trim(), DateTimeFormat);
            result.put("时间", dtTime);//时间 2021 / 9 / 6 0:00:22
        } catch (Exception ex) {

        }
        //result.put("时间", src.TIME);//时间 2021 / 9 / 6 0:00:22
        result.put("垂直井深", src.VDEPTH);//垂直井深 4013.48
        result.put("c1", src.C1);//c1 0.0025
        result.put("转盘扭矩", src.TORQUE);//转盘扭矩 0
        result.put("nc5", src.NC5);//nc5 0
        result.put("池体积5", src.PIT5);//池体积5 0
        result.put("co2", src.CO2);//co2 0.0396
        result.put("钻时", src.ROP_MAVG);//钻时 16.2108
        result.put("总池体积", src.PITTOTAL);//总池体积 78.0719
        result.put("套压", src.WHP);//套压 0
        result.put("ic4", src.IC4);//ic4 0.0011
        result.put("h2", src.H2);//h2 - 0.9999
        result.put("总烃", src.TG);//总烃 0
        result.put("ic5", src.IC5);//ic5 0.0018
        result.put("池体积4", src.PIT4);//池体积4 0
        result.put("nc4", src.NC4);//nc4 0
        result.put("一号泵冲", src.PUMP1);//一号泵冲 0
        result.put("大钩位置", src.HKH);//大钩位置 35.9999
        result.put("c2", src.C2);//c2 0.0014
        result.put("入口温度", src.TEMPIN);//入口温度 48.285
        result.put("泥浆溢漏", src.GAINLOSSVOL);//泥浆溢漏 - 999.25
        result.put("出口温度", src.TEMPOUT);//出口温度 27.97
        result.put("钻头位置", src.BITDEPTH);//钻头位置 8.9763
        result.put("入口电导", src.CONDIN);//入口电导 442.495
        result.put("池体积3", src.PIT3);//池体积3 25.5931

        return result;
    }

    /**
     * 规范处理row数据
     * @param row
     * @return
     */
    private static RecordHashTable HtFix(Hashtable row) {
        RecordHashTable insertRecord = new RecordHashTable();
        String fieldTimeName = MonitorContext.fieldTime.toLowerCase();
        Enumeration<Object> k1 = row.keys();
        while (k1.hasMoreElements()) {
            Object key = k1.nextElement();

            String name = "";
            if (key.toString().equals(fieldTimeName)) {
                name = fieldTimeName;
                try {
                    Date dtTime = org.jeecg.common.util.DateUtils.parseDate(row.get(fieldTimeName).toString().trim(), DateTimeFormat);
                    insertRecord.put(name, dtTime);
                } catch (Exception ex) {

                }
            } else {
                String fieldName = key.toString().toLowerCase();
                int iFind = FindFieldByRealDataField(fieldName);
                if (iFind == -1) {
                    continue;
                }
                name = RealDataFields.get(iFind).get_field();
                double f = 0.0;
                try {
                    f = Double.parseDouble(row.get(key).toString().trim());
                } catch (Exception ex) {
                }
                insertRecord.put(name, f);
            }
        }
        return insertRecord;
    }

    public static int FindFieldByRealDataField(String realDataField) {
        int result;
        for (int i = 1; i < RealDataFields.size(); i++) {
            if (RealDataFields.get(i).get_realField().equals(realDataField)) {
                result = i;
                return result;
            }
        }
        result = -1;
        return result;
    }

    /**
     * 合并监控预警信息
     * @param listMonitorAlarmRecords
     * @param name
     * @param listMds
     */
    private void UpdateListMonitorDescriptions(MonitorAlarmRecords listMonitorAlarmRecords, String name, ArrayList<MonitorDescription> listMds) {
        if (listMds.size() > 0) {
            int iFind = -1;
            Date dtStart = listMds.get(0)._dtStart;
            Date dtEnd = listMds.get(0)._dtEnd;
            for (int i = 0; i < listMonitorAlarmRecords.size(); i++) {
                MonitorAlarmRecord item = listMonitorAlarmRecords.get(i);
                if (item._name == name
                        && ((item._dtStart.getTime() <= dtStart.getTime() && dtStart.getTime() <= item._dtEnd.getTime()) ||
                        (item._dtStart.getTime() <= dtEnd.getTime() && dtEnd.getTime() <= item._dtEnd.getTime()))) {
                    iFind = i;
                    break;
                } else if (listMonitorAlarmRecords.get(i)._name == name && listMonitorAlarmRecords.get(i)._dtStart == dtStart) {
                    iFind = i;
                    break;
                }
            }
            MonitorAlarmRecord newAlarmRecord = new MonitorAlarmRecord(name, dtStart, dtEnd, listMds);
            for (int j = 0; j < listMds.size(); j++) {
                newAlarmRecord._secondStates.add(listMds.get(j)._secondState);
            }
            newAlarmRecord._isNeedUpdate = true;
            if (iFind == -1) {
                newAlarmRecord._dtFirstForcast = dtEnd;
                listMonitorAlarmRecords.add(newAlarmRecord);
            } else {
                MonitorAlarmRecord oldAlarmRecord = (MonitorAlarmRecord) listMonitorAlarmRecords.get(iFind).Clone();

                listMonitorAlarmRecords.get(iFind)._dtEnd = newAlarmRecord._dtEnd;
                listMonitorAlarmRecords.get(iFind)._bitDepthEnd = newAlarmRecord._bitDepthEnd;
                listMonitorAlarmRecords.get(iFind)._realDepthEnd = newAlarmRecord._realDepthEnd;
            }
        }
    }


}
