package com.njcn.utils;

import com.njcn.pojo.commons.wave.AnalyWaveModel;
import jcifs.smb.NtlmPasswordAuthentication;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbFileInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;

public class AnalyWave {

    /*****************************************
     * 解析comtrate文件工具类
     * author yexb根据Ww算法装换
     *****************************************/
    // 日志记录
    private static final Logger logger = LoggerFactory.getLogger(AnalyWave.class);

    private AnalyWaveModel.tagComtradeCfg ComtradeCfg;//cfg实体类
    private AnalyWaveModel.tagRates RatesCfg;//cfg_采样率实体类
    private AnalyWaveModel.tagDataValue TagDataValue;//返回数据实体类
    private String strBinType;//结束读取cfg标志
    private int iPush = 0;//前推周波个数（目前常见的是5个或者10个周波）
    private float nFreq;//comtrade频率  WW 2019-11-14
    private long nOneWaveNum = 32;//最小采样率，高级算法时候需要
    private long nAllWaveNum = 0;//所有波形
    private Date TimeTrige;//cfg中【波形的触发时间】、【波形的起始时间】

	private static Date TimeWave;

    public Date getTimeTrige() {
        return TimeTrige;
    }

    public void setTimeTrige(Date timeTrige) {
        TimeTrige = timeTrige;
    }

    public static Date getTimeWave() {
        return TimeWave;
    }

    public void setTimeWave(Date timeWave) {
        TimeWave = timeWave;
    }

    //add by sw 暂降触发时间
    private Date firstTime;//暂降触发第一次
    private Integer firstMs;

    //add by sw获取最小采样率供其他类使用
    public long getnOneWaveNum() {
        return nOneWaveNum;
    }

    public AnalyWaveModel.tagRates getRatesCfg() {
        return RatesCfg;
    }

    public Date getFirstTime() {
        return firstTime;
    }

    public Integer getFirstMs() {
        return firstMs;
    }

    public String startTime;

    public String ms;


    /******************************************
     * 调用读取comtrate文件方法
     ** ** strFilePath *** cfg文件路径
     * *** auth *** 读取方式 null则使用本地读取方式读取
     ******************************************/
    public AnalyWaveModel.tagDataValue readComtrade(String strFilePath, NtlmPasswordAuthentication auth, int iFlag) {
        //初始化参数
        ComtradeCfg = new AnalyWaveModel.tagComtradeCfg();
        RatesCfg = new AnalyWaveModel.tagRates();
        TagDataValue = new AnalyWaveModel.tagDataValue();
        // 读取cfg文件
        if (!AnalyseComtradeCfg(strFilePath, auth))
            return TagDataValue;

        if (!strBinType.equals("BINARY")) {
            return TagDataValue;
        }

        //编辑数据标题 YXB2020-10-09 去除相别为N相的数据//存储数据标题
        List<String> tmpWaveTitle = new ArrayList<>();
        tmpWaveTitle.add("Time");
        for (int j = 0; j < ComtradeCfg.nAnalogNum; j++) {
            if (ComtradeCfg.OneChannleCfg.get(j).szPhasicName.toUpperCase().equals("N")) {
                continue;
            } else {
                String  strUnit = "U";
                switch (ComtradeCfg.OneChannleCfg.get(j).szUnitName.toUpperCase()){
                    case "KV":
                        strUnit = "U";
                        break;
                    case "V":
                        strUnit = "U";
                        break;
                    case "A":
                        strUnit = "I";
                        break;
                }
                tmpWaveTitle.add(strUnit + ComtradeCfg.OneChannleCfg.get(j).szPhasicName.toUpperCase()+"相");
            }
        }
        // 读取dat
        /*****根据通道号计算相别**  add by yexb -----Start****
         * 1、判断是否是3的倍数，是3的倍数则是3相
         * 2、假如不是3的倍数 ，是1的倍数则是单相
         ********************************************************/
        if(ComtradeCfg.nAnalogNum%3 == 0) {
            ComtradeCfg.nPhasic = 3;
        }else if(ComtradeCfg.nAnalogNum%1 == 0) {
            ComtradeCfg.nPhasic = 1;
        }
        TagDataValue.setiPhasic(ComtradeCfg.nPhasic);

        List<List<Float>> listWaveData = AnalyseComtradeDat(strFilePath, auth, iFlag);
        TagDataValue.setTmpWaveTitle(tmpWaveTitle);
        TagDataValue.setListWaveData(listWaveData);

        /*****根据通道号计算相别**  add by yexb -----end****/
        return TagDataValue;
    }


    /*********************************
     * 读取cfg方法
     * param strFilePath 文件路径
     * return  返回bool为是否解析出错
     **********************************/
    private boolean AnalyseComtradeCfg(String strFilePath, NtlmPasswordAuthentication auth) {
        if (strFilePath.equals(""))
            return false;
        BufferedReader bufferedReader;
        InputStreamReader read;
        String strFileLine;// 每行读取内容
        String[] strTempArray;// 读取cfg文件
        try {
            //读取本地文件
            if (auth == null) {
                String encoding = "GBK";
                File file = new File(strFilePath);
                // 判断文件是否存在
                if (file.isFile() && file.exists()) {
                    read = new InputStreamReader(new FileInputStream(file), encoding);// 考虑到编码格式
                    bufferedReader = new BufferedReader(read);
                } else {
                    logger.error("找不到指定的文件");
                    return false;
                }
            } else {//读取共享文件
                strFilePath = strFilePath.replace('\\', '/');
                SmbFile smbFile = new SmbFile(strFilePath, auth);

                if (smbFile.isFile() && smbFile.exists()) {
                    SmbFileInputStream in = new SmbFileInputStream(smbFile);
                    read = new InputStreamReader(in);
                    bufferedReader = new BufferedReader(read);
                } else {
                    logger.error("找不到指定的文件！");
                    return false;
                }
            }

            if (bufferedReader != null) {
                nFreq = 0f;//WW 2019-11-14
                // 第一行不关心仅仅是一些描述类的信息
                strFileLine = bufferedReader.readLine();

                // 第二行需要关心第二个(模拟量的个数)和第三个参数(开关量的个数)
                strFileLine = bufferedReader.readLine();
                strTempArray = strFileLine.split(",");

                for (int i = 0; i < strTempArray.length; i++) {
                    switch (i) {
                        case 0:// 总个数
                            ComtradeCfg.nChannelNum = Integer.parseInt(strTempArray[i]);
                            break;
                        case 1:// 模拟量的个数
                        {
                            String str = strTempArray[i].substring(0, strTempArray[i].length() - 1);
                            ComtradeCfg.nAnalogNum = Integer.parseInt(str);
                        }
                        break;
                        case 2:// 开关量的个数
                        {
                            String str = strTempArray[i].substring(0, strTempArray[i].length() - 1);
                            ComtradeCfg.nDigitalNum = Integer.parseInt(str);
                        }
                        break;
                    }
                }

                // 从第三行到第ComtradeCfg.nChannelNum+3行是模拟量通道和数字量通道
                for (int i = 0; i < ComtradeCfg.nChannelNum; i++) {
                    AnalyWaveModel.tagOneChannleCfg OneChannlecfg = new AnalyWaveModel.tagOneChannleCfg();
                    ComtradeCfg.OneChannleCfg.add(OneChannlecfg);

                    strFileLine = bufferedReader.readLine();
                    strTempArray = strFileLine.split(",");
                    // 配置总共13项
                    for (int j = 0; j < strTempArray.length; j++) {
                        switch (j) {
                            case 0:// 通道序号
                                OneChannlecfg.nIndex = Integer.parseInt(strTempArray[j]);
                                break;
                            case 1:// 通道名称
                                OneChannlecfg.szChannleName = strTempArray[j];
                                break;
                            case 2:// 相位名称
                                OneChannlecfg.szPhasicName = strTempArray[j];
                                break;
                            case 3:// 监视的通道名称
                                OneChannlecfg.szMonitoredChannleName = strTempArray[j];
                                break;
                            case 4:// 通道的单位
                                OneChannlecfg.szUnitName = strTempArray[j];
                                break;
                            case 5:// 通道的系数
                                OneChannlecfg.fCoefficent = Float.parseFloat(strTempArray[j]);
                                break;
                            case 6:// 通道的偏移量
                                OneChannlecfg.fOffset = Float.parseFloat(strTempArray[j]);
                                break;
                            case 7:// 起始采样时间的偏移量
                                OneChannlecfg.fTimeOffset = Float.parseFloat(strTempArray[j]);
                                break;
                            case 8:// 采样值的最小值
                                OneChannlecfg.nMin = Integer.parseInt(strTempArray[j]);
                                break;
                            case 9:// 采样值的最大值
                                OneChannlecfg.nMax = Integer.parseInt(strTempArray[j]);
                                break;
                            case 10:// 一次变比
                                OneChannlecfg.fPrimary = Float.parseFloat(strTempArray[j]);
                                break;
                            case 11:// 二次变比
                                OneChannlecfg.fSecondary = Float.parseFloat(strTempArray[j]);
                                break;
                            case 12:// 一次值还是二次值标志
                                OneChannlecfg.szValueType = strTempArray[j];
                                break;
                        }
                    }
                }
                // 采样频率
                strFileLine = bufferedReader.readLine();
                float fFreq = Float.parseFloat(strFileLine);
                nFreq = (float) fFreq;//WW 2019-11-14
                // 采样段数
                strFileLine = bufferedReader.readLine();
                int nRates = Integer.parseInt(strFileLine);
                RatesCfg.nRates = nRates;
                // 获得每段的采样率
                long nOffset = 0;
                for (int i = 0; i < nRates; i++) {
                    strFileLine = bufferedReader.readLine();
                    strTempArray = strFileLine.split(",");

                    AnalyWaveModel.tagOneRate OneRate = new AnalyWaveModel.tagOneRate();
                    RatesCfg.OneRate.add(OneRate);

                    for (int j = 0; j < strTempArray.length; j++) {

                        switch (j) {
                            case 0:// 单周波采样点数
                                OneRate.nOneSample = (int) (Float.parseFloat(strTempArray[j]) / nFreq);//WW 2019-11-14
                                break;
                            case 1:// 总点数 //这里的strTemp是一个偏移量
                                OneRate.nSampleNum = (long) (Float.parseFloat(strTempArray[j]) - nOffset);
                                nOffset = OneRate.nSampleNum;
                                break;
                        }
                    }
                }

                SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss.SSS");
                // 波形起始时间
                strFileLine = bufferedReader.readLine();
                strFileLine = strFileLine.substring(0, strFileLine.length() - 3).replace(",", " ");
                TimeTrige = sdf.parse(strFileLine);
                // 暂态触发时间
                strFileLine = bufferedReader.readLine();
                strFileLine = strFileLine.substring(0, strFileLine.length() - 3).replace(",", " ");
                TimeWave = sdf.parse(strFileLine);

                Calendar calendar = Calendar.getInstance();
                calendar.setTime(TimeWave);
                firstMs = calendar.get(Calendar.MILLISECOND);
                firstTime = calendar.getTime();

                long a = TimeWave.getTime();
                long b = TimeTrige.getTime();
                int c = (int) (a - b);
                if (c >= 90 && c <= 110) {
                    iPush = 100;
                } else if (c >= 190 && c <= 210) {
                    iPush = 200;
                }
                // 赋值编码格式（二进制）
                strBinType = bufferedReader.readLine().toUpperCase();

                read.close();
            } else {
                logger.error("读取文件内容出错");
                return false;
            }
        } catch (Exception e) {
            logger.error("读取文件内容出错");
            return false;
        }
        return true;
    }

    /*********************************
     * 读取dat方法
     * param strFilePath
     *  List<List<Float>>  返回波形瞬时值
     **********************************/
    private List<List<Float>> AnalyseComtradeDat(String strFilePath, NtlmPasswordAuthentication auth, int iFlag) {
        float xValueAll = 0;//初始化xValue的值
        boolean blxValue = false;//判断是否首次登陆

        List<List<Float>> listWaveData = new ArrayList<>();//返回数据

        byte[] Array;
        try {
            String strOriginally=".cfg";//替换前的
            String strReplace=".dat";//替换后的
            String strIntercept=strFilePath.substring(strFilePath.lastIndexOf(".") + 1);//截取.之后字符串
            switch(strIntercept)
            {
                case "cfg":
                     strOriginally=".cfg";
                     strReplace=".dat";
                    break;
                case "CFG":
                    strOriginally=".CFG";
                    strReplace=".DAT";
                    break;
                case "Cfg":
                    strOriginally=".Cfg";
                    strReplace=".Dat";
                    break;
                case "CFg":
                    strOriginally=".CFg";
                    strReplace=".DAt";
                    break;
                case "cFg":
                    strOriginally=".cFg";
                    strReplace=".dAt";
                    break;
                case "cFG":
                    strOriginally=".cFG";
                    strReplace=".dAT";
                    break;
            }
            strFilePath = strFilePath.replace(strOriginally, strReplace);//把.cfg换成.dat
            //读取本地文件
            if (auth == null) {
                File file = new File(strFilePath);
                // 判断文件是否存在
                if (file.isFile() && file.exists()) {
                    Array = new byte[(int) file.length()];
                    FileInputStream readFile = null;
                    try {
                        readFile = new FileInputStream(file);
                        readFile.read(Array, 0, Array.length);
                    } catch (IOException e) {
                        logger.error("读取CFG文件失败：" + e.getMessage());
                    }
                    finally {
                        if (readFile != null) {
                            PubUtils.safeClose(readFile,"安全关闭读取CFG文件失败，异常为：");
                        }
                    }
                } else {
                    logger.error("找不到指定的文件!");
                    return listWaveData;
                }
            } else {//读取共享文件
                strFilePath = strFilePath.replace('\\', '/');
                strFilePath = strFilePath.toUpperCase();
                strFilePath = strFilePath.replace(".CFG", ".DAT");
                SmbFile smbFile = new SmbFile(strFilePath, auth);
                Array = new byte[smbFile.getContentLength()];// 得到文件的大小

                if (smbFile.exists()) {
                    SmbFileInputStream in = new SmbFileInputStream(smbFile);
                    // 建立smb文件输入流
                    in.read(Array);
                    in.close();
                } else {
                    logger.error("找不到指定的文件!");
                    return listWaveData;
                }
            }

            // 计算每个单独的数据块的大小 4字节的序号 4字节的时间 2字节的值
            // 示例中的排布是 4字节的序号 4字节的时间 UA(2字节) UB(2字节) UC(2字节) IA(2字节) IB(2字节)
            // IC(2字节)
            int nDigSize = (ComtradeCfg.nDigitalNum % 16) > 0 ? (ComtradeCfg.nDigitalNum / 16 + 1) * 2
                    : ComtradeCfg.nDigitalNum / 16 * 2;
            int nBlockSize = 2 * Integer.SIZE / 8 + ComtradeCfg.nAnalogNum * 2 + nDigSize;
            int nBlockNum = Array.length / nBlockSize;
            nOneWaveNum = MinWaveSample(RatesCfg.OneRate);
            /********************************************************
             * iFlag == 0  高级算法的要求，采样率只能是32-128
             * iFlag == 1  普通展示，采样率按照cfg里面最小的（大于32）
             * iFlag == 2  App抽点要求，采样率抽点成32
             * iFlag == 3  高级算法原始波形（大于32）
             ********************************************************/
            //高级算法的要求，采样率只能是32-128
            if (iFlag == 0) {
                if (nOneWaveNum < 32) {
                    nOneWaveNum = 32;
                } else if (nOneWaveNum > 128) {
                    nOneWaveNum = 128;
                }
            }
            //App抽点要求，采样率抽点成32
            else if(iFlag == 2){
                if (nOneWaveNum < 32) {
                    nOneWaveNum = 32;
                } else if (nOneWaveNum > 32) {
                    nOneWaveNum = 32;
                }
            }

            int iRates = 0;
            // 设定最小采样率
            int nnInd = 0;
            long nWaveNum = 0, nNum = 0;// 抽点后总共多少点数据
            AnalyWaveModel.tagRates RateTemp = new AnalyWaveModel.tagRates();
            for (iRates = 0; iRates < RatesCfg.nRates; iRates++) {
                if (RatesCfg.OneRate.get(iRates).nOneSample >= 32) {
                    // 计算本段录波总共有多少波形
                    nWaveNum = RatesCfg.OneRate.get(iRates).nSampleNum / RatesCfg.OneRate.get(iRates).nOneSample;
                    nAllWaveNum += nWaveNum;
                    // 将最低采样率替换到本段录波内
                    AnalyWaveModel.tagOneRate OneTempRate = new AnalyWaveModel.tagOneRate();
                    RateTemp.OneRate.add(OneTempRate);
                    //iFlag =3 一定不进行抽点算法
                    if(iFlag !=3) {
                        //true 抽点算法（当前采样率跟统一采样率不一样则是抽点，否则是未抽点）
                        if (RatesCfg.OneRate.get(iRates).nOneSample != nOneWaveNum) {
                            RateTemp.OneRate.get(nnInd).nOneSample = nOneWaveNum;
                            // 计算本段录波按照最低采样点应该有多少录波
                            RateTemp.OneRate.get(nnInd).nSampleNum = nOneWaveNum * nWaveNum;
                        } else {
                            RateTemp.OneRate.get(nnInd).nOneSample = RatesCfg.OneRate.get(iRates).nOneSample;
                            // 计算本段录波按照最低采样点应该有多少录波
                            RateTemp.OneRate.get(nnInd).nSampleNum = RatesCfg.OneRate.get(iRates).nOneSample * nWaveNum;
                        }
                    } else{
                        RateTemp.OneRate.get(nnInd).nOneSample = RatesCfg.OneRate.get(iRates).nOneSample;
                        // 计算本段录波按照最低采样点应该有多少录波
                        RateTemp.OneRate.get(nnInd).nSampleNum = RatesCfg.OneRate.get(iRates).nOneSample * nWaveNum;
                    }

                    nNum += RateTemp.OneRate.get(nnInd).nSampleNum;
                    // 正常的配置中采样率
                    RatesCfg.OneRate.get(nnInd).nOneSample = RatesCfg.OneRate.get(iRates).nOneSample;
                    RatesCfg.OneRate.get(nnInd).nSampleNum = RatesCfg.OneRate.get(iRates).nSampleNum;
                    nnInd++;
                }
            }

            long nOffSet = 0;
            int nIndex = 0;
            long nWaveSpan = 0;

            float fValue;
            float dfValue;//两个点之间的时间差
            for (int i = 0; i < nBlockNum; i++) {
                // 计算本段抽点采样间隔
                nWaveSpan = RatesCfg.OneRate.get(nIndex).nOneSample / RateTemp.OneRate.get(nIndex).nOneSample;
                // 判断是否进入下一段
                if (i == RatesCfg.OneRate.get(nIndex).nSampleNum + nOffSet) {
                    nOffSet += RatesCfg.OneRate.get(nIndex).nSampleNum;
                    nIndex++;
                    if (nIndex == nnInd) {
                        break;
                    }
                }
                dfValue = (float) 20 / RatesCfg.OneRate.get(nIndex).nOneSample;
                // 判断是否到了需要抽的采样点
                if (i % nWaveSpan == 0) {
                    // 计算每个通道的值
                    List<Float> tmpWaveData = new ArrayList<Float>();//存储局部数据集合，包含了时间，A，B，C三相
                    for (int j = 0; j < ComtradeCfg.nAnalogNum; j++) {
                        //数据只有电压ABC三相数据，不展示U0、I0等数据 YXB2020-10-09 去除相别为N相的数据
                        if (ComtradeCfg.OneChannleCfg.get(j).szPhasicName.toUpperCase().equals("N")) {
                            break;
                        }

                        float fCoef = ComtradeCfg.OneChannleCfg.get(j).fCoefficent;
                        fValue = BitConverter.byte2ToUnsignedShort(Array, i * nBlockSize + 2 * 4 + j * 2) * fCoef;

                        //WW 2019-11-14
                        /**************************
                         * 1、接口返回的默认是二次值
                         * 2、P是一次值 S是二次值
                         * 3、S(二次值）情况下：
                         *     ①、单位为"V"时候则直接等于；
                         *     ②、单位为"kV"时候需要乘以1000
                         * 4、P(一次值）情况下：
                         *     ①、单位为"V"时候则直接等于；
                         *     ②、单位为"kV"时候需要乘以1000
                         **************************/
                        if (ComtradeCfg.OneChannleCfg.get(j).szValueType.toUpperCase().equals("S"))//P是一次值 S是二次值
                        {
                            if (ComtradeCfg.OneChannleCfg.get(j).szUnitName.toUpperCase().equals("KV"))//判断单位是V还是kV
                            {
                                fValue = fValue * 1000.0f;
                            } else {
                                fValue = fValue;
                            }
                        }
                        else if (ComtradeCfg.OneChannleCfg.get(j).szValueType.toUpperCase().equals("P"))//P是一次值 S是二次值
                        {
                            if (ComtradeCfg.OneChannleCfg.get(j).szUnitName.toUpperCase().equals("V"))//判断单位是V还是kV
                            {
                                if (ComtradeCfg.OneChannleCfg.get(j).fPrimary != 0.0f)//根据cfg内的变比，将一次值转换成二次值
                                {
                                    fValue = fValue * ComtradeCfg.OneChannleCfg.get(j).fSecondary / ComtradeCfg.OneChannleCfg.get(j).fPrimary;
                                } else {
                                    fValue = fValue;
                                }
                            }
                            else if(ComtradeCfg.OneChannleCfg.get(j).szUnitName.toUpperCase().equals("KV"))//判断单位是V还是kV
                            {
                                if (ComtradeCfg.OneChannleCfg.get(j).fPrimary != 0.0f)//根据cfg内的变比，将一次值转换成二次值
                                {
                                    fValue = fValue * 1000.0f * ComtradeCfg.OneChannleCfg.get(j).fSecondary / ComtradeCfg.OneChannleCfg.get(j).fPrimary;
                                } else {
                                    fValue = fValue;
                                }
                            }
                            else //还有可能是电流，单位是A
                            {
                                if (ComtradeCfg.OneChannleCfg.get(j).fPrimary != 0.0f)//根据cfg内的变比，将一次值转换成二次值
                                {
                                    fValue = ComtradeCfg.OneChannleCfg.get(j).fSecondary / ComtradeCfg.OneChannleCfg.get(j).fPrimary;
                                } else {
                                    fValue= fValue;
                                }
                            }
                        }

                        //ComtradeCfg.OneChannleCfg.get(j)

                        //xValue前移量，假如是第一次时候则需要前移
                        if (!blxValue && j == 0) {
                            xValueAll = (float) (i * 20) / RatesCfg.OneRate.get(nIndex).nOneSample - iPush;
                            blxValue = true;
                            //只增加一个xValue的值
                            tmpWaveData.add((float) (Math.round(xValueAll * 100)) / 100);//增加时间值
                        } else if (j == 0) {
                            xValueAll += (float) nWaveSpan * dfValue;
                            //只增加一个xValue的值
                            tmpWaveData.add((float) (Math.round(xValueAll * 100)) / 100);//增加时间值
                        }

                        //不同通道yValue的值都需要增加，最终成ABC三相
                        tmpWaveData.add((float) (Math.round(fValue * 100)) / 100);//每个通道的值
                    }
                    listWaveData.add(tmpWaveData);//把每个单独的值赋予到整体里面去
                }
            }
        } catch (Exception e) {
            logger.error("读取文件出错：" + e.getMessage());
            return listWaveData;
        }

        return listWaveData;
    }

    /*********************************
     * 根据波形数据算出rms值数据
     * param tmplistwave 瞬时波形数据
     *  List<List<Float>>  返回RMS波形
     **********************************/
    @SuppressWarnings("unused")
    public List<List<Float>> showValidData(List<List<Float>> tmplistwave) {
        List<List<Float>> listRms = new ArrayList<>();//返回rms的值

        float fs = nOneWaveNum;
        int nWaveNum = (int) nAllWaveNum;

        int HalfTs = (int) fs;// 全波有效值  (int)fs / 2;//半波有效值
        // 计算有效值算法
        /*********************************
         * modify by yexibao 2020-10-29
         * 增加多波形算法  ---------start
         ********************************/
        double iWave = 0 ;
        if(tmplistwave.size() > 0){
            //ComtradeCfg.nAnalogNum为值的个数(-1的原因是一个存的是时间)
            iWave =  Math.floor((tmplistwave.get(0).size() -1) / ComtradeCfg.nPhasic );
            List<Float> tmpListRms;
            //每一项一项计算
            for(int j = 0; j < iWave; j ++){
                double fSumA = 0.0, fSumB= 0.0, fSumC = 0.0;
                double fValidA = 0.0, fValidB = 0.0, fValidC = 0.0;
                //循环原始数据
                for (int i = 0; i < tmplistwave.size(); i++) {
                    // 当第一次循环的时候实例化，其余的获取已有的List
                    List<Float> tmpListValue = tmplistwave.get(i); //获取每一项的值
                    if (j == 0) {
                        tmpListRms = new ArrayList<>();
                        tmpListRms.add(tmpListValue.get(0));//获取时间
                        listRms.add(tmpListRms);
                    } else {
                        tmpListRms = listRms.get(i);
                    }

                    //包含了时间、电压（A、B、C）三相、电流（A、B、C）三相
                    if (tmpListValue.size() >= 2) {
                        //电压有效值算法,根据相别进行处理
                        switch(ComtradeCfg.nPhasic) {
                            case 1:
                                fSumA += Math.pow(tmpListValue.get(1 + ComtradeCfg.nPhasic*j), 2);
                                if (i >= HalfTs)// 计算有效值
                                {
                                    List<Float> forwardListValue = tmplistwave.get(i - HalfTs);//获取前推周波的值
                                    fSumA -= Math.pow(forwardListValue.get(1 + ComtradeCfg.nPhasic*j), 2);
                                }
                                fValidA = Math.sqrt(fSumA / HalfTs);

                                tmpListRms.add((float) fValidA);
                                listRms.set(i,tmpListRms);
                                break;
                            case 2:
                                fSumA += Math.pow(tmpListValue.get(1 + ComtradeCfg.nPhasic*j), 2);
                                fSumB += Math.pow(tmpListValue.get(2 + ComtradeCfg.nPhasic*j), 2);
                                if (i >= HalfTs)// 计算有效值
                                {
                                    List<Float> forwardListValue = tmplistwave.get(i - HalfTs);//获取前推周波的值
                                    fSumA -= Math.pow(forwardListValue.get(1 + ComtradeCfg.nPhasic*j), 2);
                                    fSumB -= Math.pow(forwardListValue.get(2 + ComtradeCfg.nPhasic*j), 2);
                                }
                                fValidA = Math.sqrt(fSumA / HalfTs);
                                fValidB = Math.sqrt(fSumB / HalfTs);

                                tmpListRms.add((float) fValidA);
                                tmpListRms.add((float) fValidB);
                                listRms.set(i,tmpListRms);
                                break;
                            case 3:
                                fSumA += Math.pow(tmpListValue.get(1 + ComtradeCfg.nPhasic*j), 2);
                                fSumB += Math.pow(tmpListValue.get(2 + ComtradeCfg.nPhasic*j), 2);
                                fSumC += Math.pow(tmpListValue.get(3 + ComtradeCfg.nPhasic*j), 2);
                                if (i >= HalfTs)// 计算有效值
                                {
                                    List<Float> forwardListValue = tmplistwave.get(i - HalfTs);//获取前推周波的值
                                    fSumA -= Math.pow(forwardListValue.get(1 + ComtradeCfg.nPhasic*j), 2);
                                    fSumB -= Math.pow(forwardListValue.get(2 + ComtradeCfg.nPhasic*j), 2);
                                    fSumC -= Math.pow(forwardListValue.get(3 + ComtradeCfg.nPhasic*j), 2);
                                }
                                fValidA = Math.sqrt(fSumA / HalfTs);
                                fValidB = Math.sqrt(fSumB / HalfTs);
                                fValidC = Math.sqrt(fSumC / HalfTs);

                                tmpListRms.add((float) fValidA);
                                tmpListRms.add((float) fValidB);
                                tmpListRms.add((float) fValidC);
                                listRms.set(i,tmpListRms);
                                break;
                        }
                    }
                }
            }
        }
        //过滤前一个周波
        //HalfTs表示一个周波
        try {
            for (int i = 0; i < HalfTs; i++) {
                //电压有效值算法
                List<Float> tmpListRms = new ArrayList<>();//没相具体的值
                for(int j = 0; j < iWave; j ++) {
                    if (j == 0) {
                        tmpListRms.add(listRms.get(i).get(0));//获取时间
                    }

                    switch(ComtradeCfg.nPhasic) {
                        case 1:
                            tmpListRms.add(listRms.get(i + HalfTs).get(1 + ComtradeCfg.nPhasic*j));
                            break;
                        case 2:
                            tmpListRms.add(listRms.get(i + HalfTs).get(1 + ComtradeCfg.nPhasic*j));
                            tmpListRms.add(listRms.get(i + HalfTs).get(2 + ComtradeCfg.nPhasic*j));
                            break;
                        case 3:
                            tmpListRms.add(listRms.get(i + HalfTs).get(1 + ComtradeCfg.nPhasic*j));
                            tmpListRms.add(listRms.get(i + HalfTs).get(2 + ComtradeCfg.nPhasic*j));
                            tmpListRms.add(listRms.get(i + HalfTs).get(3 + ComtradeCfg.nPhasic*j));
                            break;
                    }
                }
                listRms.set(i, tmpListRms);//重新赋值
            }
        } catch (Exception e) {
            logger.error("更改收个周波值出错");
        }
        return listRms;
    }

    public static void main(String[] args) {
        AnalyWave analyWave = new AnalyWave();
        AnalyWaveModel.tagDataValue realWave = analyWave.readComtrade("G:\\comtrade\\192.168.1.80\\PQ_PQLD1_000013_20230714_150727_977.CFG", null, 1);//获取原始波形值
        //List<List<Float>> realWave = analyWave.readComtrade("C:\\Users\\Lenovo\\Desktop\\Comtrade\\waveTemp9200\\192.168.10.128\\1_20200927_135822_644.CFG", null, 0);//获取原始波形值
        List<List<Float>> result1=analyWave.showValidData(realWave.getListWaveData());
        realWave.getListWaveData();
        /********************************************************
         * iFlag == 0  高级算法的要求，采样率只能是32-128
         * iFlag == 1  普通展示，采样率按照cfg里面最小的（大于32）
         * iFlag == 2  App抽点要求，采样率抽点成32
         * iFlag == 3  高级算法原始波形（大于32）
         ********************************************************/
        List<List<Float>> result = analyWave.getEigenvalue(realWave.getListWaveData(), true);
        List<List<Float>> result2 = analyWave.getEigenvalue(realWave.getListWaveData(), true);

    }

    /*****************************
     *获取暂降特征值，包含离线
     ** ** strFilePath *** cfg文件路径
     *** auth *** 读取方式 null则使用本地读取方式读取
     *****************************/
    public List<List<Float>> getEigenvalue(List<List<Float>> realWave, boolean iFlag) {
        List<List<Float>> result = null;//返回值
        if (realWave.size() > 0) {
            //获取突变量和rms值
            if (GetAnaylseValue(realWave)) {
                if (listRms_Offline.size() > 0 && listTBL_Offline.size() > 0) {
                    result = GetEventValue(realWave, listTBL_Offline, listRms_Offline, (int) nOneWaveNum, iFlag);
                    if (result.size() == 3) {
                        if ((result.get(0).get(1) > 0.9 && result.get(0).get(1) < 1.1) && (result.get(1).get(1) > 0.9 && result.get(1).get(1) < 1.1) &&
                                (result.get(2).get(1) > 0.9 && result.get(2).get(1) < 1.1)) {
                            result = GetEventValue(realWave, listTBL_Offline, listRms_Offline, (int) nOneWaveNum, iFlag);
                        }
//                        //第五行显示电压PU
//                        //String strDes = TimeTrige.ToString("yyyy-MM-dd HH:mm:ss.fff");
//                        String strDes = "";
//                        if (result.get(0).get(1) <= 0.9 || result.get(1).get(1) <= 0.9 || result.get(2).get(1) <= 0.9)
//                            strDes += "事件类型：暂降事件 ";
//                        else if (result.get(0).get(1) <= 0.05 || result.get(1).get(1) <= 0.05 || result.get(2).get(1) <= 0.05)
//                            strDes += "事件类型：中断事件 ";
//                        else if (result.get(0).get(1) >= 1.1 || result.get(1).get(1) >= 1.1 || result.get(2).get(1) >= 1.1)
//                            strDes += "事件类型：暂升事件 ";
//                        for (int iTemp = 0; iTemp < 3; iTemp++) {
//                            String strPhasic = "A相";
//                            switch (iTemp) {
//                                case 0:
//                                    strPhasic = "A相";
//                                    break;
//                                case 1:
//                                    strPhasic = "B相";
//                                    break;
//                                case 2:
//                                    strPhasic = "C相";
//                                    break;
//                            }
//                            String strType = "";
//                            if (result.get(iTemp).get(1) <= 0.05)
//                                strType = "电压中断";
//                            else if (result.get(iTemp).get(1) <= 0.9)
//                                strType = "电压暂降";
//                            else if (result.get(iTemp).get(1) >= 1.1)
//                                strType = "电压暂升";
//                            if (strType != "") {
//                                strDes +="暂降事件："+ strPhasic +  strType + "，运行电压：" + result.get(iTemp).get(2) + "V,残余电压:" + result.get(iTemp).get(2) +
//                                        "V，残余电压(百分比)：" + result.get(iTemp).get(1) * 100.0f + "%，持续时间：" + result.get(iTemp).get(1) + "毫秒；    ";
//                            }
//                        }
                    }
                }
            }
        }
        return result;
    }

    /*********************************
     * 离线波形导入时获取突变量算法
     * param tmpListWave 波形原始数据
     **********************************/
    private List<List<Float>> listRms_Offline;//离线数据RMS有效值数据
    private List<List<Float>> listTBL_Offline;//离线数据突变量数据
    private double fMinMagA = 0;
    private double fMinMagB = 0;
    private double fMinMagC = 0;

    public Boolean GetAnaylseValue(List<List<Float>> realWave) {
        boolean blFlag = true;
        //实例化
        listRms_Offline = new ArrayList<>();
        listTBL_Offline = new ArrayList<>();

        float fs = nOneWaveNum;
        int nWaveNum = (int) nAllWaveNum;

        // 计算有效值
        double fSumA = 0.0, fSumB = 0.0, fSumC = 0.0;
        double fValidA = 0.0, fValidB = 0.0, fValidC = 0.0;
        fMinMagA = 99999;
        fMinMagB = 99999;
        fMinMagC = 99999;
        double fValue = 0.0;
        int HalfTs = (int) fs;// 全波有效值 ； (int)fs / 2;//半波有效值
        //瞬时波形数据_瞬时
        List<Float> tmpRealValue;
        //获取前推周波的值_瞬时
        List<Float> forwardRealValue;
        //获取前推周波的值_突变量
        List<Float> tblValue;
        //获取前推周波的值_突变量
        List<Float> forwardTblValue;

        // 计算有效值算法
        for (int i = 0; i < realWave.size(); i++) {
            //获取每一项的值
            tmpRealValue = realWave.get(i);
            //包含了时间、A、B、C三相
            if (tmpRealValue.size() >= 4) {
                fSumA += Math.pow(tmpRealValue.get(1), 2);
                fSumB += Math.pow(tmpRealValue.get(2), 2);
                fSumC += Math.pow(tmpRealValue.get(3), 2);
                // 计算有效值
                List<Float> tmpRmsValue = new ArrayList<>();
                if (i >= fs) {
                    forwardRealValue = realWave.get(i - HalfTs);
                    fSumA -= Math.pow(forwardRealValue.get(1), 2);
                    fSumB -= Math.pow(forwardRealValue.get(2), 2);
                    fSumC -= Math.pow(forwardRealValue.get(3), 2);
                }
                // 计算突变量值
                List<Float> tmpTblValue = new ArrayList<>();
                tmpTblValue.add(tmpRealValue.get(0));//获取时间
                if (i >= HalfTs) {
                    tblValue = realWave.get(i);//获取前推周波的值
                    forwardTblValue = realWave.get(i - HalfTs);//获取前推周波的值
                    tmpTblValue.add(tblValue.get(1) - forwardTblValue.get(1));
                    tmpTblValue.add(tblValue.get(2) - forwardTblValue.get(2));
                    tmpTblValue.add(tblValue.get(3) - forwardTblValue.get(3));
                } else {
                    tmpTblValue.add(0f);
                    tmpTblValue.add(0f);
                    tmpTblValue.add(0f);
                }
                fValidA = Math.sqrt(fSumA / HalfTs);
                fValidB = Math.sqrt(fSumB / HalfTs);
                fValidC = Math.sqrt(fSumC / HalfTs);

                if (i >= fs) {
                    if (fValidA < fMinMagA) {
                        fMinMagA = fValidA;
                    }
                    if (fValidB < fMinMagB) {
                        fMinMagB = fValidB;
                    }
                    if (fValidC < fMinMagC) {
                        fMinMagC = fValidC;
                    }
                }
                //RMS获取
                tmpRmsValue.add(tmpRealValue.get(0));//获取时间
                tmpRmsValue.add((float) fValidA);
                tmpRmsValue.add((float) fValidB);
                tmpRmsValue.add((float) fValidC);
                listRms_Offline.add(tmpRmsValue);

                //RMS获取
                listTBL_Offline.add(tmpTblValue);
            }
        }
        return blFlag;
    }

    /*********************************
     * 离线波形导入时获取暂降特征值的算法
     * List<List<Float>>  返回暂降数据
     **********************************/
    private List<List<Float>> GetEventValue(List<List<Float>> realWave, List<List<Float>> tblWave, List<List<Float>> rmstWave, int nCirclePoint, boolean blFlag) {
        //额定电压
        float fBase = 57.74f;
        //假如所选的是380V，那么PT变比是1:1，因此额定电压要选220
        if (ComtradeCfg.OneChannleCfg.size() > 0) {
            if (ComtradeCfg.OneChannleCfg.get(0).fPrimary / ComtradeCfg.OneChannleCfg.get(0).fSecondary <= 1) {
                fBase = 220f;
            }
        }
        //采样率
        int nSJ = nCirclePoint;
        /*********************************
         * 0是特征幅值（残余电压百分比）
         * 1是特征幅值（残余电压）
         * 2额定定压（动态电压）
         * 3是持续时间
         **********************************/
        List<List<Float>> listEventValue = new ArrayList<>();//ABC三相分析结果
        for (int i = 0; i < 3; i++) {
            int iDDY = 0, iGDY = 0;//低电压和郭电压标识值
            List<Float> tmpListEventValue = new ArrayList<>();//某一项分析结果
            iDDY = App_Disturb_DDY1(realWave, tblWave, rmstWave, nSJ, i, blFlag);
            if (Disturb_Val == 0 && Disturb_SJ == 0) {
                //判断A相的暂态事件类型是否为短时中断或电压暂降
                iGDY = App_Disturb_GDY1(realWave, tblWave, rmstWave, nSJ, i, blFlag);
                if (iGDY != 0) {
                    if (Disturb_Val != 0) {
                        if (blFlag) {
                            tmpListEventValue.add(Disturb_Val / rmstWave.get(nSJ + 2).get(i + 1));//征幅值（残余电压百分比）
                            tmpListEventValue.add(Disturb_Val);//特征幅值（残余电压）
                            tmpListEventValue.add(rmstWave.get(nSJ + 2).get(i + 1));//额定定压（动态电压）
                        } else {
                            tmpListEventValue.add(Disturb_Val / 57.74f);//征幅值（残余电压百分比）
                            tmpListEventValue.add(Disturb_Val);//特征幅值（残余电压）
                            tmpListEventValue.add(57.74f);//额定定压（动态电压）
                        }
                    }
                } else//如果都没有找到，那么需要从曲线里面找出比较小的值来计算
                {
                    double rate = 0f;
                    double residualVoltage = 0.f;//残余电压
                    switch (i) {
                        case 0:
                            residualVoltage = fMinMagA;
                            break;
                        case 1:
                            residualVoltage = fMinMagB;
                            break;
                        case 2:
                            residualVoltage = fMinMagC;
                            break;
                    }

                    if (residualVoltage != -1) {
                        rate = residualVoltage / fBase > 1 ? 1.0f : residualVoltage / fBase;
                    }
                    tmpListEventValue.add((float) rate);//征幅值（残余电压百分比）
                    tmpListEventValue.add((float) residualVoltage);//特征幅值（残余电压）
                    tmpListEventValue.add(fBase);//额定定压（动态电压）
                }
            } else {
                if (Disturb_Val != 0) {
                    if (Disturb_Val != 0) {
                        if (blFlag) {
                            tmpListEventValue.add(Disturb_Val / rmstWave.get(nSJ + 2).get(i + 1));//征幅值（残余电压百分比）
                            tmpListEventValue.add(Disturb_Val);//特征幅值（残余电压）
                            tmpListEventValue.add(rmstWave.get(nSJ + 2).get(i + 1));//额定定压（动态电压）
                        } else {
                            tmpListEventValue.add(Disturb_Val / 57.74f);//征幅值（残余电压百分比）
                            tmpListEventValue.add(Disturb_Val);//特征幅值（残余电压）
                            tmpListEventValue.add(57.74f);//额定定压（动态电压）
                        }
                    }
                }
            }
            tmpListEventValue.add(Disturb_SJ / nSJ * 20.0f);//持续时间
            listEventValue.add(tmpListEventValue);
        }
        return listEventValue;
    }

    private float Disturb_Val = 0;//暂降幅值
    private double Disturb_Time = 0;//持续时间
    private float Disturb_SJ = 0;//暂态启动点号

    private float Un09 = (0.90f * 57.74f);//暂降幅值90%
    private float Un002 = (0.02f * 57.74f);//暂降幅值2%
    private float Un110 = (1.10f * 57.74f);//暂降幅值110%

    /************************************
     *低电压的判据 包含了暂降和中断
     * @param realWave  原始波形数据
     * @param tblWave   突变量波形数据
     * @param rmstWave  RMS波形数据
     * @param nCirclePoint 采样率
     * @param nType  类别 0：A相，1：B相，2：C相
     * @param blFlag 浮动门槛和固定门槛
     * @return
     *************************************/
    private int App_Disturb_DDY1(List<List<Float>> realWave, List<List<Float>> tblWave, List<List<Float>> rmstWave, int nCirclePoint, int nType, boolean blFlag) {
        Disturb_Val = 0;
        Disturb_Time = 0;
        Disturb_SJ = 0;

        /****************************
         * ADC 临时的突变量判据
         * Disturb_JS_Val 事件启动点时刻的有效值
         ****************************/
        double temp, ADC, Disturb_JS_Val = 0;
        int iTbl = 0;
        long Disturb_QD = 0;
        //nSJ就是全波的采样率,nHalfSJ是半波的采样率
        int nSJ = nCirclePoint, nHalfSJ = nCirclePoint / 2;
        //定义90%和20%额定电压
        float fUN09 = Un09, fUN002 = Un002;
        //增加浮动门槛判断
        if (blFlag) {
            /****************************
             * 计算值去掉一个前一个周波后
             * 取第二个周波的第二个有效值
             * 第一个值是时间、A,B,C三相
             ****************************/
            if (rmstWave.size() > nSJ + 2) {
                fUN09 = rmstWave.get(nSJ + 2).get(nType + 1) * 0.9f;
                fUN002 = rmstWave.get(nSJ + 2).get(nType + 1) * 0.02f;
            }
        }
        /****************************
         * 从第二个周波开始
         ****************************/
        for (int i = nSJ; i < realWave.size(); i++) {
            //获取RMS有效值
            float rmsValue = rmstWave.get(i).get(nType + 1);
            //电压扰动启动判别
            if (Disturb_QD == 0) {
                //有效值小于90%
                if (rmsValue < fUN09) {
                    Disturb_QD = 0xff;
                    Disturb_Val = rmsValue;
                    Disturb_JS_Val = rmsValue;
                    //寻找突变点
                    for (int j = 0; j < nHalfSJ; j++) {
                        //临时的突变量
                        ADC = tblWave.get(i - nHalfSJ + j).get(nType + 1);
                        //临时的突变量小于0时候取绝对值
                        if (ADC < 0) {
                            ADC = 0 - ADC;
                        }
                        if (ADC > fUN002) {
                            Disturb_SJ += (nHalfSJ - j);
                            iTbl = (int) (i - nHalfSJ + j);
                            break;
                        }
                    }
                }
            }
            //电压扰动返回判别
            else {
                if (rmsValue < (fUN09 + fUN002)) {
                    Disturb_SJ++;
                    if (Disturb_Val > rmsValue) {
                        Disturb_Val = rmsValue;
                    }
                    Disturb_JS_Val = rmsValue;
                } else {
                    if (Disturb_SJ >= (nSJ + nHalfSJ)) {
                        //20%突变量标志
                        int iFlag = 0;
                        for (int j = 0; j < nHalfSJ; j++) {
                            iFlag = j;
                            //临时的突变量
                            ADC = tblWave.get(i - nHalfSJ + j).get(nType + 1);
                            //临时的突变量小于0时候取绝对值
                            if (ADC < 0) {
                                ADC = 0 - ADC;
                            }
                            if (ADC > fUN002) {
                                break;
                            }
                        }
                        Disturb_SJ -= (nHalfSJ - iFlag);
                        Disturb_Time = ((double) Disturb_SJ) * 20 / nSJ;
                        return iTbl;
                    } else {
                        Disturb_SJ++;
                        ADC = realWave.get(i).get(nType + 1);
                        if (ADC < 0) {
                            ADC = 0 - ADC;
                        }
                        temp = rmsValue - Disturb_JS_Val;
                        if (temp < 0) {
                            temp = 0 - temp;
                        }
                        if ((ADC > 100) && (temp < 0.1)) {
                            Disturb_SJ -= (nHalfSJ + 1);
                            Disturb_Time = ((double) Disturb_SJ) * 20 / nSJ + 1;
                            return iTbl;
                        }
                    }
                    Disturb_JS_Val = rmsValue;
                }
            }
        }
        return iTbl;
    }

    /************************************
     *过电压的判据
     * @param realWave  原始波形数据
     * @param tblWave   突变量波形数据
     * @param rmstWave  RMS波形数据
     * @param nCirclePoint 采样率
     * @param nType  类别 0：A相，1：B相，2：C相
     * @param blFlag 浮动门槛和固定门槛
     * @return
     *************************************/
    private int App_Disturb_GDY1(List<List<Float>> realWave, List<List<Float>> tblWave, List<List<Float>> rmstWave, int nCirclePoint, int nType, boolean blFlag) {
        Disturb_Val = 0;
        Disturb_Time = 0;
        Disturb_SJ = 0;

        /****************************
         * ADC 临时的突变量判据
         * Disturb_JS_Val 事件启动点时刻的有效值
         ****************************/
        double temp, ADC, Disturb_JS_Val = 0;
        int iTbl = 0;
        long Disturb_QD = 0;
        //nSJ就是全波的采样率,nHalfSJ是半波的采样率
        int nSJ = nCirclePoint, nHalfSJ = nCirclePoint / 2;
        //定义110%和20%额定电压
        float fUN110 = Un110, fUN002 = Un002;
        //增加浮动门槛判断
        if (blFlag) {
            /****************************
             * 计算值去掉一个前一个周波后
             * 取第二个周波的第二个有效值
             * 第一个值是时间、A,B,C三相
             ****************************/
            if (rmstWave.size() > nSJ + 2) {
                fUN110 = rmstWave.get(nSJ + 2).get(nType + 1) * 1.1f;
                fUN002 = rmstWave.get(nSJ + 2).get(nType + 1) * 0.02f;
            }
        }
        /****************************
         * 从第二个周波开始
         ****************************/
        for (int i = nSJ; i < realWave.size(); i++) {
            //获取RMS有效值
            float rmsValue = rmstWave.get(i).get(nType + 1);
            //电压扰动启动判别
            if (Disturb_QD == 0) {
                if (rmsValue > fUN110) {
                    Disturb_QD = 0xff;
                    Disturb_Val = rmsValue;
                    Disturb_JS_Val = rmsValue;
                    //寻找突变点
                    for (int j = 0; j < nHalfSJ; j++) {
                        //临时的突变量
                        ADC = tblWave.get(i - nHalfSJ + j).get(nType + 1);
                        //临时的突变量小于0时候取绝对值
                        if (ADC < 0) {
                            ADC = 0 - ADC;
                        }
                        if (ADC > fUN002) {
                            Disturb_SJ += (nHalfSJ - j);
                            iTbl = (int) (i - nHalfSJ + j);
                            break;
                        }
                    }
                }
            }
            //电压扰动返回判别
            else {
                if (rmsValue > (fUN110 - fUN002)) {
                    Disturb_SJ++;
                    if (Disturb_Val < rmsValue)
                        Disturb_Val = rmsValue;
                    Disturb_JS_Val = rmsValue;
                } else {
                    if (Disturb_SJ >= (nSJ + nHalfSJ)) {
                        int iFlag = 0;
                        for (int j = 0; j < nHalfSJ; j++) {
                            iFlag = j;
                            ADC = tblWave.get(i - nHalfSJ + j).get(nType + 1);
                            if (ADC < 0) {
                                ADC = 0 - ADC;
                            }
                            if (ADC > fUN002) {
                                break;
                            }
                        }
                        Disturb_SJ -= (nHalfSJ - iFlag);
                        Disturb_Time = (double) Disturb_SJ * 20 / nSJ;
                        return iTbl;
                    } else {
                        Disturb_SJ++;
                        ADC = realWave.get(i).get(nType + 1);
                        if (ADC < 0) {
                            ADC = 0 - ADC;
                        }
                        temp = rmsValue - Disturb_JS_Val;
                        if (temp < 0) {
                            temp = 0 - temp;
                        }
                        if ((ADC > 100) && (temp < 0.1)) {
                            Disturb_SJ -= (nHalfSJ + 1);
                            Disturb_Time = Disturb_SJ * 20 / nSJ + 1;
                            return iTbl;
                        }
                    }
                    Disturb_JS_Val = rmsValue;
                }
            }
        }
        return iTbl;
    }


    /*********************************
     * 获取最小采样率方法
     * @param OneRate  cfg中关于采样率参数
     * @return 返回最小采样率
     **********************************/
    private long MinWaveSample(List<AnalyWaveModel.tagOneRate> OneRate) {
        long nMinOneSample = OneRate.get(0).nOneSample;
        for (int i = 0; i < OneRate.size(); i++) {
            if (OneRate.get(i).nOneSample >= 32) {
                if (nMinOneSample > OneRate.get(i).nOneSample) {
                    nMinOneSample = OneRate.get(i).nOneSample;
                }
            }
        }
        return nMinOneSample;
    }

    /************************************************
     * 判断文件是否存在
     * 假如不存在则进行遍历文件夹下的所有文件
     * 判断是否存在，不存在则返回之前的，存在则更新
     * @param strFile  文件夹路径
     * @param strFileName 文件名称 .CFG的
     * @param auth 远程读取的标志，为空则为本地读取，反之则远程读取
     * @return resultFileName 返回文件名称.cfg
     *************************************************/
    @Deprecated
    public static String VerificationFile(String strFile, String strFileName, NtlmPasswordAuthentication auth) {
        //返回值，文件名称.CFG名称
        String resultFileName = strFileName;
        //原始波形路径
        String strFilePath = strFile + "\\" + strFileName;
        //分割原始波形
        String[] strOriginalTime = strFileName.substring(0, strFileName.lastIndexOf(".")).split("_");
        //原始时间
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        Date OriginalDate = PubUtils.GetDateByCfgName(strFileName, sdf);//原始时间
        Date OcurrentlyDate;//遍历文获取到的波形
        try {
            //读取本地文件
            if (auth == null) {
                String encoding = "GBK";
                File file = new File(strFilePath);
                // 判断文件是否存在
                if (!(file.isFile() && file.exists())) {
                    //判断是否是文件夹
                    File folder = new File(strFile);
                    //判断是否是文件夹
                    if (folder.isDirectory()) {
                        //获取文件夹下的所有文件
                        File[] files = folder.listFiles();
                        //遍历该文件夹
                        for (File file2 : files) {
                            String fileName = file2.getName().toUpperCase();
                            // 判断文件名是否以.cfg结尾
                            if (fileName.endsWith("CFG") && fileName.indexOf(strOriginalTime[0] + "_") == 0) {
                                OcurrentlyDate = PubUtils.GetDateByCfgName(fileName, sdf);//原始时间
                                //过滤掉时间为空的不合格的数据
                                if (OcurrentlyDate != null && OriginalDate != null) {
                                    //计算两个相差毫秒数
                                    int c = Math.abs((int) (OcurrentlyDate.getTime() - OriginalDate.getTime()));
                                    //999毫秒
                                    if (c < 999) {
                                        resultFileName = fileName;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            } else {//读取共享文件
                strFilePath = strFilePath.replace('\\', '/');
                SmbFile smbFile = new SmbFile(strFilePath, auth);
                if (!(smbFile.isFile() && smbFile.exists())) {
                    strFile = strFile.replace('\\', '/');
                    //判断是否是文件夹
                    SmbFile smbfolder = new SmbFile(strFile + '/', auth);//文件夹必须以/结束
                    //判断是否是文件夹
                    if (smbfolder.isDirectory()) {
                        //获取文件夹下的所有文件
                        SmbFile[] files = smbfolder.listFiles();
                        //遍历该文件夹
                        for (SmbFile file2 : files) {
                            String fileName = file2.getName().toUpperCase();
                            // 判断文件名是否以.cfg结尾
                            if (fileName.endsWith("CFG")) {
                                OcurrentlyDate = PubUtils.GetDateByCfgName(fileName, sdf);//原始时间
                                //过滤掉时间为空的不合格的数据
                                if (OcurrentlyDate != null && OriginalDate != null) {
                                    //计算两个相差毫秒数
                                    int c = Math.abs((int) (OcurrentlyDate.getTime() - OriginalDate.getTime()));
                                    //999毫秒
                                    if (c < 999) {
                                        resultFileName = fileName;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error("获取波形名称出错：" + e.getMessage());
        }
        return resultFileName;
    }
}
