package com.njcn.gather.tool.wave.component;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.gather.tool.wave.pojo.dto.*;
import com.njcn.gather.tool.wave.pojo.enums.WaveFileResponseEnum;
import com.njcn.gather.tool.wave.utils.BitConverter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.file.Files;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * 波形文件解析组件。
 */
@Slf4j
@Component
public class WaveFileComponent {

    /** 90% 额定电压阈值。 */
    private static final float UN09 = 0.90f * 57.74f;
    /** 2% 额定电压变化阈值。 */
    private static final float UN002 = 0.02f * 57.74f;
    /** 110% 额定电压阈值。 */
    private static final float UN110 = 1.10f * 57.74f;


    /**
     * 解析 COMTRADE 配置与数据流，返回波形基础数据。
     */
    public WaveDataDTO getComtrade(InputStream cfgStream, InputStream datStream, int iType) {
        WaveDataDTO waveDataDTO = new WaveDataDTO();
        ComtradeCfgDTO comtradeCfgDTO = getComtradeCfg(cfgStream);
        if (comtradeCfgDTO == null || !"BINARY".equalsIgnoreCase(comtradeCfgDTO.getStrBinType())) {
            throw new BusinessException(WaveFileResponseEnum.CFG_DATA_ERROR);
        }


        if (comtradeCfgDTO.getNAnalogNum() % 3 == 0) {
            comtradeCfgDTO.setNPhasic(3);
        } else {
            comtradeCfgDTO.setNPhasic(1);
        }

        waveDataDTO.setIPhasic(comtradeCfgDTO.getNPhasic());

        getWaveTitle(waveDataDTO, comtradeCfgDTO);

        List<List<Float>> listWaveData = getComtradeDat(comtradeCfgDTO, datStream, iType);

        waveDataDTO.setComtradeCfgDTO(comtradeCfgDTO);

        waveDataDTO.setListWaveData(listWaveData);

        waveDataDTO.setTime(DateUtil.format(comtradeCfgDTO.getTimeTrige(), DatePattern.NORM_DATETIME_MS_PATTERN));


        return waveDataDTO;
    }

    /**
     * 基于瞬时值计算 RMS 数据。
     */
    @SuppressWarnings("unused")
    public WaveDataDTO getValidData(WaveDataDTO waveDataDTO) {
        ComtradeCfgDTO comtradeCfgDTO = waveDataDTO.getComtradeCfgDTO();
        List<List<Float>> lstWave = waveDataDTO.getListWaveData();
        List<List<Float>> listRms = new ArrayList<>();
        if (comtradeCfgDTO == null || comtradeCfgDTO.getFinalSampleRate() == null || comtradeCfgDTO.getFinalSampleRate() <= 0) {
            throw new BusinessException(WaveFileResponseEnum.RMS_DATA_ERROR);
        }

        int halfTs = comtradeCfgDTO.getFinalSampleRate().intValue();

        double iWave;
        int nPhasic;
        List<List<Float>> listRmsMin = new ArrayList<>();
        if (lstWave.size() > 0) {
            nPhasic = comtradeCfgDTO.getNPhasic();
            iWave = Math.floor((lstWave.get(0).size() - 1) / (double) nPhasic);
            List<Float> tmpListRms;
            List<Float> tmpListRmsMin;
            double fMinTime = 0.0, fMinValue = 0.0;
            for (int j = 0; j < iWave; j++) {
                tmpListRmsMin = new ArrayList<>();
                double fSumA = 0.0, fSumB = 0.0, fSumC = 0.0;
                double fValidA, fValidB, fValidC;
                for (int i = 0; i < lstWave.size(); i++) {
                    List<Float> tmpListValue = lstWave.get(i);
                    if (j == 0) {
                        tmpListRms = new ArrayList<>();
                        tmpListRms.add(tmpListValue.get(0));
                        listRms.add(tmpListRms);
                    } else {
                        tmpListRms = listRms.get(i);
                    }

                    if (tmpListValue.size() >= 2) {
                        switch (comtradeCfgDTO.getNPhasic()) {
                            case 1:
                                fSumA += Math.pow(tmpListValue.get(1 + nPhasic * j), 2);
                                if (i >= halfTs) {
                                    List<Float> forwardListValue = lstWave.get(i - halfTs);
                                    fSumA -= Math.pow(forwardListValue.get(1 + nPhasic * j), 2);
                                }
                                fValidA = Math.sqrt(fSumA / halfTs);
                                tmpListRms.add((float) (Math.round(fValidA * 100)) / 100);
                                listRms.set(i, tmpListRms);
                                if (i >= halfTs) {
                                    if (i == halfTs) {
                                        fMinValue = fValidA;
                                        fMinTime = tmpListValue.get(0);
                                    } else {
                                        if (fValidA < fMinValue) {
                                            fMinValue = fValidA;
                                            fMinTime = tmpListValue.get(0);
                                        }
                                    }
                                }
                                break;
                            case 2:
                                fSumA += Math.pow(tmpListValue.get(1 + nPhasic * j), 2);
                                fSumB += Math.pow(tmpListValue.get(2 + nPhasic * j), 2);
                                if (i >= halfTs) {
                                    List<Float> forwardListValue = lstWave.get(i - halfTs);
                                    fSumA -= Math.pow(forwardListValue.get(1 + nPhasic * j), 2);
                                    fSumB -= Math.pow(forwardListValue.get(2 + nPhasic * j), 2);
                                }
                                fValidA = Math.sqrt(fSumA / halfTs);
                                fValidB = Math.sqrt(fSumB / halfTs);

                                tmpListRms.add((float) (Math.round(fValidA * 100)) / 100);
                                tmpListRms.add((float) (Math.round(fValidB * 100)) / 100);
                                listRms.set(i, tmpListRms);

                                if (i >= halfTs) {
                                    if (i == halfTs) {
                                        fMinValue = fValidA;
                                        fMinTime = tmpListValue.get(0);
                                    } else {
                                        if (fValidA < fMinValue) {
                                            fMinValue = fValidA;
                                            fMinTime = tmpListValue.get(0);
                                        }
                                        if (fValidB < fMinValue) {
                                            fMinValue = fValidB;
                                            fMinTime = tmpListValue.get(0);
                                        }
                                    }
                                }
                                break;
                            case 3:
                                fSumA += Math.pow(tmpListValue.get(1 + nPhasic * j), 2);
                                fSumB += Math.pow(tmpListValue.get(2 + nPhasic * j), 2);
                                fSumC += Math.pow(tmpListValue.get(3 + nPhasic * j), 2);
                                if (i >= halfTs) {
                                    List<Float> forwardListValue = lstWave.get(i - halfTs);
                                    fSumA -= Math.pow(forwardListValue.get(1 + nPhasic * j), 2);
                                    fSumB -= Math.pow(forwardListValue.get(2 + nPhasic * j), 2);
                                    fSumC -= Math.pow(forwardListValue.get(3 + nPhasic * j), 2);
                                }
                                fValidA = Math.sqrt(fSumA / halfTs);
                                fValidB = Math.sqrt(fSumB / halfTs);
                                fValidC = Math.sqrt(fSumC / halfTs);

                                tmpListRms.add((float) (Math.round(fValidA * 100)) / 100);
                                tmpListRms.add((float) (Math.round(fValidB * 100)) / 100);
                                tmpListRms.add((float) (Math.round(fValidC * 100)) / 100);
                                listRms.set(i, tmpListRms);

                                if (i >= halfTs) {
                                    if (i == halfTs) {
                                        fMinValue = fValidA;
                                        fMinTime = tmpListValue.get(0);
                                    } else {
                                        if (fValidA < fMinValue) {
                                            fMinValue = fValidA;
                                            fMinTime = tmpListValue.get(0);
                                        }
                                        if (fValidB < fMinValue) {
                                            fMinValue = fValidB;
                                            fMinTime = tmpListValue.get(0);
                                        }
                                        if (fValidC < fMinValue) {
                                            fMinValue = fValidC;
                                            fMinTime = tmpListValue.get(0);
                                        }
                                    }
                                }
                                break;
                            default:
                                break;
                        }
                    }
                }
                tmpListRmsMin.add((float) fMinTime);
                tmpListRmsMin.add((float) (Math.round(fMinValue * 100)) / 100);
                listRmsMin.add(tmpListRmsMin);
            }

            try {
                for (int i = 0; i < halfTs; i++) {
                    List<Float> tmpNewListRms = new ArrayList<>();
                    for (int j = 0; j < iWave; j++) {
                        if (j == 0) {
                            tmpNewListRms.add(listRms.get(i).get(0));
                        }
                        switch (nPhasic) {
                            case 1:
                                tmpNewListRms.add(listRms.get(i + halfTs).get(1 + nPhasic * j));
                                break;
                            case 2:
                                tmpNewListRms.add(listRms.get(i + halfTs).get(1 + nPhasic * j));
                                tmpNewListRms.add(listRms.get(i + halfTs).get(2 + nPhasic * j));
                                break;
                            case 3:
                                tmpNewListRms.add(listRms.get(i + halfTs).get(1 + nPhasic * j));
                                tmpNewListRms.add(listRms.get(i + halfTs).get(2 + nPhasic * j));
                                tmpNewListRms.add(listRms.get(i + halfTs).get(3 + nPhasic * j));
                                break;
                            default:
                                break;
                        }
                    }
                    listRms.set(i, tmpNewListRms);
                }
            } catch (Exception e) {
                throw new BusinessException(WaveFileResponseEnum.RMS_DATA_ERROR);
            }
        }
        waveDataDTO.setListRmsData(listRms);
        waveDataDTO.setListRmsMinData(listRmsMin);

        return waveDataDTO;
    }

    /**
     * 计算波形特征值结果。
     */
    public List<EigenvalueDTO> getEigenvalue(WaveDataDTO waveDataDTO, boolean blType) {
        ComtradeCfgDTO comtradeCfgDTO = waveDataDTO.getComtradeCfgDTO();
        List<List<Float>> lstWave = waveDataDTO.getListWaveData();
        if (comtradeCfgDTO == null || comtradeCfgDTO.getFinalSampleRate() == null || comtradeCfgDTO.getFinalSampleRate() <= 0) {
            throw new BusinessException(WaveFileResponseEnum.CFG_DATA_ERROR);
        }
        int finalSampleRate = comtradeCfgDTO.getFinalSampleRate();
        List<EigenvalueDTO> lstEigenvalueDTO = new ArrayList<>();

        if (lstWave.size() > 0) {
            MutationDTO mutationDTO = getMutationValue(lstWave, finalSampleRate);
            if (mutationDTO.getListRms_Offline().size() > 0 && mutationDTO.getListTBL_Offline().size() > 0) {
                lstEigenvalueDTO = getEventValue(lstWave, mutationDTO, comtradeCfgDTO, blType);
            }
        } else {
            lstEigenvalueDTO = null;
        }
        return lstEigenvalueDTO;
    }

    /**
     * 按文件路径打开波形文件输入流。
     */
    public InputStream getFileInputStreamByFilePath(String filePath) {
        File file = new File(filePath);
        if (file.isFile() && file.exists()) {
            InputStream inputStream;
            try {
                inputStream = Files.newInputStream(file.toPath());
                if (inputStream.available() < 1) {
                    throw new BusinessException(WaveFileResponseEnum.WAVE_DATA_INVALID);
                }
                return inputStream;
            } catch (IOException e) {
                throw new BusinessException(WaveFileResponseEnum.WAVE_DATA_INVALID);
            }
        } else {
            throw new BusinessException(WaveFileResponseEnum.ANALYSE_WAVE_NOT_FOUND);
        }
    }

    /**
     * 读取并解析 CFG 配置内容。
     */
    private ComtradeCfgDTO getComtradeCfg(InputStream cfgStream) {
        ComtradeCfgDTO comtradeCfgDTO = new ComtradeCfgDTO();
        try (InputStreamReader read = new InputStreamReader(cfgStream, CharsetUtil.CHARSET_GBK);
             BufferedReader bufferedReader = new BufferedReader(read)) {
            String strFileLine = bufferedReader.readLine();
            if (StrUtil.isBlank(strFileLine)) {
                throw new BusinessException(WaveFileResponseEnum.CFG_DATA_ERROR);
            }

            strFileLine = bufferedReader.readLine();
            if (StrUtil.isBlank(strFileLine)) {
                throw new BusinessException(WaveFileResponseEnum.CFG_DATA_ERROR);
            }
            String[] strTempArray = strFileLine.split(StrUtil.COMMA);
            comtradeCfgDTO.setNChannelNum(Integer.parseInt(strTempArray[0]));
            comtradeCfgDTO.setNAnalogNum(Integer.parseInt(strTempArray[1].substring(0, strTempArray[1].length() - 1)));
            comtradeCfgDTO.setNDigitalNum(Integer.parseInt(strTempArray[2].substring(0, strTempArray[2].length() - 1)));

            List<AnalogDTO> lstAnalogDTO = new ArrayList<>();
            comtradeCfgDTO.setLstAnalogDTO(lstAnalogDTO);
            for (int i = 0; i < comtradeCfgDTO.getNAnalogNum(); i++) {
                AnalogDTO analogDTO = new AnalogDTO();
                lstAnalogDTO.add(analogDTO);
                strFileLine = bufferedReader.readLine();
                strTempArray = strFileLine.split(StrUtil.COMMA);
                analogDTO.setNIndex(Integer.parseInt(strTempArray[0]));
                analogDTO.setSzChannleName(strTempArray[1]);
                analogDTO.setSzPhasicName(strTempArray[2]);
                analogDTO.setSzMonitoredChannleName(strTempArray[3]);
                analogDTO.setSzUnitName(strTempArray[4]);
                analogDTO.setFCoefficent(Float.parseFloat(strTempArray[5]));
                analogDTO.setFOffset(Float.parseFloat(strTempArray[6]));
                analogDTO.setFTimeOffset(Float.parseFloat(strTempArray[7]));
                analogDTO.setNMin(Integer.parseInt(strTempArray[8]));
                analogDTO.setNMax(Integer.parseInt(strTempArray[9]));
                analogDTO.setFPrimary(Float.parseFloat(strTempArray[10]));
                analogDTO.setFSecondary(Float.parseFloat(strTempArray[11]));
                analogDTO.setSzValueType(strTempArray[12]);
            }

            List<DigitalDTO> lstDigitalDTO = new ArrayList<>();
            comtradeCfgDTO.setLstDigitalDTO(lstDigitalDTO);
            for (int i = 0; i < comtradeCfgDTO.getNDigitalNum(); i++) {
                DigitalDTO digitalDTO = new DigitalDTO();
                lstDigitalDTO.add(digitalDTO);
                strFileLine = bufferedReader.readLine();
                strTempArray = strFileLine.split(StrUtil.COMMA);
                digitalDTO.setNIndex(Integer.parseInt(strTempArray[0]));
                digitalDTO.setSzChannleName(strTempArray[1]);
                digitalDTO.setSzPhasicName(strTempArray[2]);
                digitalDTO.setSzMonitoredChannleName(strTempArray[3]);
                digitalDTO.setInitial(Integer.parseInt(strTempArray[4]));
            }

            String freqLine = bufferedReader.readLine();
            int nFreq;
            try {
                nFreq = (int) Math.round(Double.parseDouble(freqLine));
            } catch (NumberFormatException e) {
                nFreq = Integer.parseInt(freqLine);
            }

            strFileLine = bufferedReader.readLine();
            int nRates = Integer.parseInt(strFileLine);
            comtradeCfgDTO.setNRates(nRates);
            List<RateDTO> lstRate = new ArrayList<>();
            int nOffset = 0;
            for (int i = 0; i < nRates; i++) {
                strFileLine = bufferedReader.readLine();
                strTempArray = strFileLine.split(StrUtil.COMMA);
                RateDTO rateDTO = new RateDTO();
                double doubleValue = Double.parseDouble(strTempArray[0]); // 先按 double 解析采样率
                int result = (int) (doubleValue / nFreq); // 转换为单周波采样点数
                rateDTO.setNOneSample(result);
                rateDTO.setNSampleNum((Integer.parseInt(strTempArray[1]) - nOffset));
                nOffset += rateDTO.getNSampleNum();
                lstRate.add(rateDTO);
            }
            comtradeCfgDTO.setLstRate(lstRate);
            String timeFormat = "dd/MM/yyyy,HH:mm:ss.SSS";
            strFileLine = bufferedReader.readLine();
            strFileLine = strFileLine.substring(0, strFileLine.length() - 3);
            comtradeCfgDTO.setTimeStart(DateUtil.parse(strFileLine, timeFormat));

            strFileLine = bufferedReader.readLine();
            strFileLine = strFileLine.substring(0, strFileLine.length() - 3);
            comtradeCfgDTO.setTimeTrige(DateUtil.parse(strFileLine, timeFormat));

            Calendar calendar = DateUtil.calendar(comtradeCfgDTO.getTimeTrige());
            comtradeCfgDTO.setFirstMs(calendar.get(Calendar.MILLISECOND));
            comtradeCfgDTO.setFirstTime(calendar.getTime());


            long a = comtradeCfgDTO.getTimeStart().getTime();
            long b = comtradeCfgDTO.getTimeTrige().getTime();

            int c = (int) (b - a);
            if (c >= 90 && c <= 110) {
                comtradeCfgDTO.setNPush(100);
            } else if (c >= 190 && c <= 210) {
                comtradeCfgDTO.setNPush(200);
            }
            comtradeCfgDTO.setStrBinType(bufferedReader.readLine().toUpperCase());
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("CFG 文件解析失败", e);
            throw new BusinessException(WaveFileResponseEnum.CFG_DATA_ERROR);
        }
        return comtradeCfgDTO;
    }

    /**
     * 读取并按目标采样率转换 DAT 数据。
     */
    private List<List<Float>> getComtradeDat(ComtradeCfgDTO comtradeCfgDTO, InputStream datStream, int iType) {
        List<List<Float>> listWaveData = new ArrayList<>();
        float xValueAll = 0;
        boolean blxValue = false;
        byte[] datArray;
        int datLength = -1;
        int nDigSize = -1;
        int nBlockSize = -1;
        int nBlockNum = -1;
        try {
            datArray = IoUtil.readBytes(datStream);
            datLength = datArray == null ? -1 : datArray.length;
            if (ArrayUtil.isEmpty(datArray)) {
                log.warn("DAT 文件解析失败：文件内容为空，{}", buildDatParseContext(comtradeCfgDTO, 0, iType, nDigSize, nBlockSize, nBlockNum));
                throw new BusinessException(WaveFileResponseEnum.DAT_DATA_ERROR);
            }
            nDigSize = (comtradeCfgDTO.getNDigitalNum() % 16) > 0 ? (comtradeCfgDTO.getNDigitalNum() / 16 + 1) * 2 : comtradeCfgDTO.getNDigitalNum() / 16 * 2;
            nBlockSize = 2 * Integer.SIZE / 8 + comtradeCfgDTO.getNAnalogNum() * 2 + nDigSize;
            if (nBlockSize <= 0) {
                log.error("DAT 文件解析失败：根据 CFG 计算出的块大小非法，{}", buildDatParseContext(comtradeCfgDTO, datArray.length, iType, nDigSize, nBlockSize, nBlockNum));
                throw new BusinessException(WaveFileResponseEnum.DAT_DATA_ERROR);
            }
            nBlockNum = (int) Math.floor((double) datArray.length / nBlockSize);
            if (nBlockNum <= 0) {
                log.warn("DAT 文件解析失败：DAT 长度小于单帧块大小，{}", buildDatParseContext(comtradeCfgDTO, datArray.length, iType, nDigSize, nBlockSize, nBlockNum));
                throw new BusinessException(WaveFileResponseEnum.DAT_DATA_ERROR);
            }
            if (datArray.length % nBlockSize != 0) {
                log.warn("DAT 文件长度与块大小不整除，将按完整块解析，{}", buildDatParseContext(comtradeCfgDTO, datArray.length, iType, nDigSize, nBlockSize, nBlockNum));
            }

            int finalSampleRate = getFinalWaveSample(comtradeCfgDTO.getLstRate(), iType);
            if (finalSampleRate <= 0) {
                log.error("DAT 文件解析失败：最终采样率非法，{}，采样率分段={}",
                        buildDatParseContext(comtradeCfgDTO, datArray.length, iType, nDigSize, nBlockSize, nBlockNum),
                        buildRateSummary(comtradeCfgDTO.getLstRate()));
                throw new BusinessException(WaveFileResponseEnum.DAT_DATA_ERROR);
            }
            comtradeCfgDTO.setFinalSampleRate(finalSampleRate);
            int nnInd = 0;
            int nWaveNum;
            List<RateDTO> newLstRate = new ArrayList<>();
            for (int iRate = 0; iRate < comtradeCfgDTO.getNRates(); iRate++) {
                nWaveNum = comtradeCfgDTO.getLstRate().get(iRate).getNSampleNum() / comtradeCfgDTO.getLstRate().get(iRate).getNOneSample();
                comtradeCfgDTO.setNAllWaveNum(comtradeCfgDTO.getNAllWaveNum() + nWaveNum);
                RateDTO tmpRateDTO = new RateDTO();
                if (comtradeCfgDTO.getLstRate().get(iRate).getNOneSample() >= 32) {
                    //YXB 2025-08-27
                    tmpRateDTO.bRMSFlag = false;
                } else if (comtradeCfgDTO.getLstRate().get(iRate).getNOneSample() <= 2) {
                    //YXB 2025-08-27
                    tmpRateDTO.bRMSFlag = true;
                }
                newLstRate.add(tmpRateDTO);
                if (iType != 3) {
                    if (!Objects.equals(comtradeCfgDTO.getLstRate().get(iRate).getNOneSample(), comtradeCfgDTO.getFinalSampleRate())) {
                        newLstRate.get(nnInd).setNOneSample(comtradeCfgDTO.getFinalSampleRate());
                        newLstRate.get(nnInd).setNSampleNum(comtradeCfgDTO.getFinalSampleRate() * nWaveNum);
                    } else {
                        newLstRate.get(nnInd).setNOneSample(comtradeCfgDTO.getLstRate().get(iRate).getNOneSample());
                        newLstRate.get(nnInd).setNSampleNum(comtradeCfgDTO.getLstRate().get(iRate).getNOneSample() * nWaveNum);
                    }
                } else {
                    newLstRate.get(nnInd).setNOneSample(comtradeCfgDTO.getLstRate().get(iRate).getNOneSample());
                    newLstRate.get(nnInd).setNSampleNum(comtradeCfgDTO.getLstRate().get(iRate).getNOneSample() * nWaveNum);
                }

                nnInd++;
            }
            long nOffSet = 0, nWaveSpan;
            float fValue, dfValue;
            int nIndex = 0;
            RateDTO tmpRateDTO;
            for (int i = 0; i < nBlockNum; i++) {
                tmpRateDTO = comtradeCfgDTO.getLstRate().get(nIndex);
                if (i == tmpRateDTO.getNSampleNum() + nOffSet) {
                    nOffSet += tmpRateDTO.getNSampleNum();
                    nIndex++;
                    if (nIndex == nnInd) {
                        break;
                    }
                }
                tmpRateDTO = comtradeCfgDTO.getLstRate().get(nIndex);
                if (newLstRate.get(nIndex).bRMSFlag == true) {
                    nWaveSpan = newLstRate.get(nIndex).getNOneSample() / tmpRateDTO.getNOneSample();
                } else {
                    nWaveSpan = tmpRateDTO.getNOneSample() / newLstRate.get(nIndex).getNOneSample();
                }

                dfValue = (float) 20 / tmpRateDTO.getNOneSample();
                if (i % nWaveSpan == 0) {
                    List<Float> tmpWaveData = new ArrayList<>();
                    if (newLstRate.get(nIndex).bRMSFlag == true) {
                        long allWaveTemp = newLstRate.get(nIndex).getNSampleNum() / newLstRate.get(nIndex).getNOneSample();
                        long allempSample = newLstRate.get(nIndex).getNOneSample();

                        int currentDataIndex = i;
                        for (int iWaveTemp = 0; iWaveTemp < allWaveTemp; iWaveTemp++) {
                            for (int mTempSample = 0; mTempSample < allempSample; mTempSample++) {
                                tmpWaveData = new ArrayList<>();
                                for (int j = 0; j < comtradeCfgDTO.getNAnalogNum(); j++) {
                                    if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzPhasicName().equalsIgnoreCase("N")) {
                                        break;
                                    }
                                    float fCoef = comtradeCfgDTO.getLstAnalogDTO().get(j).getFCoefficent();
                                    fValue = BitConverter.byte2ToUnsignedShort(datArray, currentDataIndex * nBlockSize + 2 * 4 + j * 2) * fCoef;
                                    //WW 2019-11-14

                                    if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzValueType().equalsIgnoreCase("S")) {
                                        if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzUnitName().equalsIgnoreCase("KV")) {
                                            fValue = fValue * 1000.0f;
                                        } else {
                                            fValue = fValue;
                                        }
                                    } else if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzValueType().equalsIgnoreCase("P")) {
                                        if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzUnitName().equalsIgnoreCase("V")) {
                                            if (comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary() != 0.0f) {
                                                fValue = fValue * comtradeCfgDTO.getLstAnalogDTO().get(j).getFSecondary() / comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary();
                                            } else {
                                                fValue = fValue;
                                            }
                                        } else if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzUnitName().equalsIgnoreCase("KV")) {
                                            if (comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary() != 0.0f) {
                                                fValue = fValue * 1000.0f * comtradeCfgDTO.getLstAnalogDTO().get(j).getFSecondary() / comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary();
                                            } else {
                                                fValue = fValue;
                                            }
                                        } else {
                                            if (comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary() != 0.0f) {
                                                fValue = fValue * comtradeCfgDTO.getLstAnalogDTO().get(j).getFSecondary() / comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary();
                                            } else {
                                                fValue = fValue;
                                            }
                                        }
                                    }

                                    if (!blxValue && j == 0) {
                                        xValueAll = (float) (currentDataIndex * 20) / tmpRateDTO.getNOneSample() - comtradeCfgDTO.getNPush();
                                        blxValue = true;
                                        tmpWaveData.add(roundWaveTime(xValueAll));
                                    } else if (j == 0) {
                                        xValueAll += (float) dfValue / nWaveSpan;
                                        tmpWaveData.add(roundWaveTime(xValueAll));
                                    }

                                    tmpWaveData.add(roundWaveAmplitude(fValue));
                                }
                                listWaveData.add(tmpWaveData);
                            }
                            if (iWaveTemp < (allWaveTemp - 1)) {
                                currentDataIndex++;
                            }
                        }
                    } else {
                        for (int j = 0; j < comtradeCfgDTO.getNAnalogNum(); j++) {
                            if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzPhasicName().equalsIgnoreCase("N")) {
                                break;
                            }

                            float fCoef = comtradeCfgDTO.getLstAnalogDTO().get(j).getFCoefficent();
                            fValue = BitConverter.byte2ToUnsignedShort(datArray, i * nBlockSize + 2 * 4 + j * 2) * fCoef;

                            //WW 2019-11-14

                            if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzValueType().equalsIgnoreCase("S")) {
                                if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzUnitName().equalsIgnoreCase("KV")) {
                                    fValue = fValue * 1000.0f;
                                } else {
                                    fValue = fValue;
                                }
                            } else if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzValueType().equalsIgnoreCase("P")) {
                                if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzUnitName().equalsIgnoreCase("V")) {
                                    if (comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary() != 0.0f) {
                                        fValue = fValue * comtradeCfgDTO.getLstAnalogDTO().get(j).getFSecondary() / comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary();
                                    } else {
                                        fValue = fValue;
                                    }
                                } else if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzUnitName().equalsIgnoreCase("KV")) {
                                    if (comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary() != 0.0f) {
                                        fValue = fValue * 1000.0f * comtradeCfgDTO.getLstAnalogDTO().get(j).getFSecondary() / comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary();
                                    } else {
                                        fValue = fValue;
                                    }
                                } else {
                                    if (comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary() != 0.0f) {
                                        fValue = fValue * comtradeCfgDTO.getLstAnalogDTO().get(j).getFSecondary() / comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary();
                                    } else {
                                        fValue = fValue;
                                    }
                                }
                            }
                            if (!blxValue && j == 0) {
                                xValueAll = (float) (i * 20) / tmpRateDTO.getNOneSample() - comtradeCfgDTO.getNPush();
                                blxValue = true;
                                tmpWaveData.add(roundWaveTime(xValueAll));
                            } else if (j == 0) {
                                xValueAll += (float) nWaveSpan * dfValue;
                                tmpWaveData.add(roundWaveTime(xValueAll));
                            }

                            tmpWaveData.add(roundWaveAmplitude(fValue));
                        }
                        listWaveData.add(tmpWaveData);
                    }
                }
            }
        } catch (BusinessException e) {
            throw e;
        } catch (ArithmeticException e) {
            log.error("DAT 文件解析失败：采样率计算出现算术异常，{}，采样率分段={}",
                    buildDatParseContext(comtradeCfgDTO, datLength, iType, nDigSize, nBlockSize, nBlockNum),
                    buildRateSummary(comtradeCfgDTO.getLstRate()), e);
            throw new BusinessException(WaveFileResponseEnum.DAT_DATA_ERROR);
        } catch (IndexOutOfBoundsException e) {
            log.error("DAT 文件解析失败：按 CFG 读取 DAT 时发生越界，疑似 CFG 与 DAT 不匹配，{}，采样率分段={}",
                    buildDatParseContext(comtradeCfgDTO, datLength, iType, nDigSize, nBlockSize, nBlockNum),
                    buildRateSummary(comtradeCfgDTO.getLstRate()), e);
            throw new BusinessException(WaveFileResponseEnum.DAT_DATA_ERROR);
        } catch (Exception e) {
            log.error("DAT 文件解析失败：{}，采样率分段={}",
                    buildDatParseContext(comtradeCfgDTO, datLength, iType, nDigSize, nBlockSize, nBlockNum),
                    buildRateSummary(comtradeCfgDTO.getLstRate()), e);
            throw new BusinessException(WaveFileResponseEnum.DAT_DATA_ERROR);
        }

        return listWaveData;
    }

    /**
     * 波形时间统一保留 3 位小数。
     */
    static Float roundWaveTime(float value) {
        return BigDecimal.valueOf(value).setScale(3, RoundingMode.HALF_UP).floatValue();
    }

    /**
     * 波形幅值统一保留 3 位小数。
     */
    static Float roundWaveAmplitude(float value) {
        return BigDecimal.valueOf(value).setScale(3, RoundingMode.HALF_UP).floatValue();
    }

    /**
     * 组装 DAT 解析上下文，便于日志直接定位 cfg/dat 是否匹配。
     */
    private String buildDatParseContext(ComtradeCfgDTO comtradeCfgDTO, int datLength, int iType, int nDigSize, int nBlockSize, int nBlockNum) {
        if (comtradeCfgDTO == null) {
            return StrUtil.format("parseType={}, datLength={}, nDigSize={}, nBlockSize={}, nBlockNum={}, cfg=空",
                    iType, datLength, nDigSize, nBlockSize, nBlockNum);
        }
        return StrUtil.format(
                "parseType={}, datLength={}, nDigSize={}, nBlockSize={}, nBlockNum={}, analogNum={}, digitalNum={}, nRates={}, strBinType={}",
                iType,
                datLength,
                nDigSize,
                nBlockSize,
                nBlockNum,
                comtradeCfgDTO.getNAnalogNum(),
                comtradeCfgDTO.getNDigitalNum(),
                comtradeCfgDTO.getNRates(),
                comtradeCfgDTO.getStrBinType()
        );
    }

    /**
     * 摘要输出采样率分段，便于判断最终采样率为何被算成非法值。
     */
    private String buildRateSummary(List<RateDTO> lstRate) {
        if (lstRate == null || lstRate.isEmpty()) {
            return "[]";
        }
        StringJoiner joiner = new StringJoiner("; ", "[", "]");
        for (int i = 0; i < lstRate.size(); i++) {
            RateDTO rateDTO = lstRate.get(i);
            if (rateDTO == null) {
                joiner.add(StrUtil.format("#{}=null", i));
                continue;
            }
            joiner.add(StrUtil.format("#{}:nOneSample={},nSampleNum={},bRMSFlag={}",
                    i,
                    rateDTO.getNOneSample(),
                    rateDTO.getNSampleNum(),
                    rateDTO.bRMSFlag));
        }
        return joiner.toString();
    }

    /**
     * 根据解析类型确定最终采样点数。
     */
    private int getFinalWaveSample(List<RateDTO> lstRate, int iType) {
        int nFinalOneSample = -1;
        int nMinOneSample = -1;
        if (!lstRate.isEmpty()) {
            nMinOneSample = lstRate.get(0).getNOneSample();
            int tmpOneSample;
            for (RateDTO rateDTO : lstRate) {
                tmpOneSample = rateDTO.getNOneSample();
                //YXB 2025-08-27  32->16
                if (tmpOneSample >= 16) {
                    if (nMinOneSample > tmpOneSample) {
                        nMinOneSample = tmpOneSample;
                    }
                }
            }
        }

        switch (iType) {
            case 0:
                if (nMinOneSample < 32) {
                    nFinalOneSample = 32;
                } else if (nMinOneSample > 128) {
                    nFinalOneSample = 128;
                } else {
                    nFinalOneSample = nMinOneSample;
                }
                break;
            case 2:
                nFinalOneSample = 32;
                break;

            default:
                nFinalOneSample = nMinOneSample;
                break;

        }
        return nFinalOneSample;
    }


    /**
     * 计算 RMS 与突变量基础数据。
     */
    private MutationDTO getMutationValue(List<List<Float>> lstWave, float finalSampleRate) {
        MutationDTO mutationDTO = new MutationDTO();
        double fSumA = 0.0, fSumB = 0.0, fSumC = 0.0;
        double fValidA, fValidB, fValidC;
        double fValue = 0.0;
        int HalfTs = (int) finalSampleRate;
        List<Float> tmpRealValue, forwardRealValue, tblValue, forwardTblValue;
        for (int i = 0; i < lstWave.size(); i++) {
            tmpRealValue = lstWave.get(i);
            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 >= finalSampleRate) {
                    forwardRealValue = lstWave.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 = lstWave.get(i);
                    forwardTblValue = lstWave.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 >= finalSampleRate) {
                    if (fValidA < mutationDTO.getFMinMagA()) {
                        mutationDTO.setFMinMagA(fValidA);
                    }
                    if (fValidB < mutationDTO.getFMinMagB()) {
                        mutationDTO.setFMinMagB(fValidB);
                    }
                    if (fValidC < mutationDTO.getFMinMagC()) {
                        mutationDTO.setFMinMagC(fValidC);
                    }
                }
                tmpRmsValue.add(tmpRealValue.get(0));
                tmpRmsValue.add((float) fValidA);
                tmpRmsValue.add((float) fValidB);
                tmpRmsValue.add((float) fValidC);
                mutationDTO.getListRms_Offline().add(tmpRmsValue);

                mutationDTO.getListTBL_Offline().add(tmpTblValue);
            }
        }
        return mutationDTO;
    }

    /**
     * 计算三相电压特征值。
     */
    private List<EigenvalueDTO> getEventValue(List<List<Float>> lstWave, MutationDTO mutationDTO, ComtradeCfgDTO comtradeCfgDTO, boolean blType) {
        List<List<Float>> tblWave = mutationDTO.getListTBL_Offline();
        List<List<Float>> rmstWave = mutationDTO.getListRms_Offline();
        float fBase = 57.74f;
        List<AnalogDTO> lstAnalogDTO = comtradeCfgDTO.getLstAnalogDTO();
        if (!lstAnalogDTO.isEmpty()) {
            if (lstAnalogDTO.get(0).getFPrimary() / lstAnalogDTO.get(0).getFSecondary() <= 1) {
                fBase = 220f;
            }
        }
        int nSJ = comtradeCfgDTO.getFinalSampleRate().intValue();

        List<EigenvalueDTO> lstEigenvalueDTO = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            EigenvalueDTO eigenvalueDTO = new EigenvalueDTO();
            DisturbanceResult ddyResult = App_Disturb_DDY1(lstWave, tblWave, rmstWave, nSJ, i, blType);
            DisturbanceResult finalResult = ddyResult;
            if (ddyResult.disturbValue == 0 && ddyResult.disturbStart == 0) {
                DisturbanceResult gdyResult = App_Disturb_GDY1(lstWave, tblWave, rmstWave, nSJ, i, blType);
                finalResult = gdyResult;
                if (gdyResult.tableIndex != 0) {
                    if (gdyResult.disturbValue != 0) {
                        if (blType) {
                            eigenvalueDTO.setAmplitude(gdyResult.disturbValue / rmstWave.get(nSJ + 2).get(i + 1));
                            eigenvalueDTO.setResidualVoltage(gdyResult.disturbValue);
                            eigenvalueDTO.setRatedVoltage(rmstWave.get(nSJ + 2).get(i + 1));
                        } else {
                            eigenvalueDTO.setAmplitude(gdyResult.disturbValue / 57.74f);
                            eigenvalueDTO.setResidualVoltage(gdyResult.disturbValue);
                            eigenvalueDTO.setRatedVoltage(57.74f);
                        }
                    }
                }
                else {
                    double rate = 0f;
                    double residualVoltage = 0.f;
                    switch (i) {
                        case 0:
                            residualVoltage = mutationDTO.getFMinMagA();
                            break;
                        case 1:
                            residualVoltage = mutationDTO.getFMinMagB();
                            break;
                        case 2:
                            residualVoltage = mutationDTO.getFMinMagC();
                            break;
                        default:
                            break;
                    }

                    if (residualVoltage != -1) {
                        rate = residualVoltage / fBase > 1 ? 1.0f : residualVoltage / fBase;
                    }
                    eigenvalueDTO.setAmplitude((float) rate);
                    eigenvalueDTO.setResidualVoltage((float) residualVoltage);
                    eigenvalueDTO.setRatedVoltage(fBase);
                }
            } else {
                if (ddyResult.disturbValue != 0) {
                    if (blType) {
                        eigenvalueDTO.setAmplitude(ddyResult.disturbValue / rmstWave.get(nSJ + 2).get(i + 1));
                        eigenvalueDTO.setResidualVoltage(ddyResult.disturbValue);
                        eigenvalueDTO.setRatedVoltage(rmstWave.get(nSJ + 2).get(i + 1));
                    } else {
                        eigenvalueDTO.setAmplitude(ddyResult.disturbValue / 57.74f);
                        eigenvalueDTO.setResidualVoltage(ddyResult.disturbValue);
                        eigenvalueDTO.setRatedVoltage(57.74f);
                    }
                }
            }
            eigenvalueDTO.setDurationTime(finalResult.disturbStart / nSJ * 20.0f);
            lstEigenvalueDTO.add(eigenvalueDTO);
        }
        return lstEigenvalueDTO;
    }

    /**
     * 电压暂降判据，兼容暂降与短时中断。
     */
    private DisturbanceResult App_Disturb_DDY1(List<List<Float>> realWave, List<List<Float>> tblWave, List<List<Float>> rmstWave,
                                               int nCirclePoint, int nType, boolean blFlag) {
        DisturbanceResult result = new DisturbanceResult();
        double temp, ADC, Disturb_JS_Val = 0;
        int iTbl = 0;
        long Disturb_QD = 0;
        int nSJ = nCirclePoint, nHalfSJ = nCirclePoint / 2;
        float fUN09 = UN09, fUN002 = UN002;
        if (blFlag) {
            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++) {
            float rmsValue = rmstWave.get(i).get(nType + 1);
            if (Disturb_QD == 0) {
                if (rmsValue < fUN09) {
                    Disturb_QD = 0xff;
                    result.disturbValue = rmsValue;
                    Disturb_JS_Val = rmsValue;
                    for (int j = 0; j < nHalfSJ; j++) {
                        ADC = tblWave.get(i - nHalfSJ + j).get(nType + 1);
                        if (ADC < 0) {
                            ADC = 0 - ADC;
                        }
                        if (ADC > fUN002) {
                            result.disturbStart += (nHalfSJ - j);
                            iTbl = (i - nHalfSJ + j);
                            result.tableIndex = iTbl;
                            break;
                        }
                    }
                }
            }
            else {
                if (rmsValue < (fUN09 + fUN002)) {
                    result.disturbStart++;
                    if (result.disturbValue > rmsValue) {
                        result.disturbValue = rmsValue;
                    }
                    Disturb_JS_Val = rmsValue;
                } else {
                    if (result.disturbStart >= (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;
                            }
                        }
                        result.disturbStart -= (nHalfSJ - iFlag);
                        result.tableIndex = iTbl;
                        return result;
                    } else {
                        result.disturbStart++;
                        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)) {
                            result.disturbStart -= (nHalfSJ + 1);
                            result.tableIndex = iTbl;
                            return result;
                        }
                    }
                    Disturb_JS_Val = rmsValue;
                }
            }
        }
        result.tableIndex = iTbl;
        return result;
    }

    /**
     * 电压过电压判据。
     */
    private DisturbanceResult App_Disturb_GDY1(List<List<Float>> realWave, List<List<Float>> tblWave, List<List<Float>> rmstWave,
                                               int nCirclePoint, int nType, boolean blFlag) {
        DisturbanceResult result = new DisturbanceResult();
        double temp, ADC, Disturb_JS_Val = 0;
        int iTbl = 0;
        long Disturb_QD = 0;
        int nSJ = nCirclePoint, nHalfSJ = nCirclePoint / 2;
        float fUN110 = UN110, fUN002 = UN002;
        if (blFlag) {
            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++) {
            float rmsValue = rmstWave.get(i).get(nType + 1);
            if (Disturb_QD == 0) {
                if (rmsValue > fUN110) {
                    Disturb_QD = 0xff;
                    result.disturbValue = rmsValue;
                    Disturb_JS_Val = rmsValue;
                    for (int j = 0; j < nHalfSJ; j++) {
                        ADC = tblWave.get(i - nHalfSJ + j).get(nType + 1);
                        if (ADC < 0) {
                            ADC = 0 - ADC;
                        }
                        if (ADC > fUN002) {
                            result.disturbStart += (nHalfSJ - j);
                            iTbl = (int) (i - nHalfSJ + j);
                            result.tableIndex = iTbl;
                            break;
                        }
                    }
                }
            }
            else {
                if (rmsValue > (fUN110 - fUN002)) {
                    result.disturbStart++;
                    if (result.disturbValue < rmsValue) {
                        result.disturbValue = rmsValue;
                    }
                    Disturb_JS_Val = rmsValue;
                } else {
                    if (result.disturbStart >= (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;
                            }
                        }
                        result.disturbStart -= (nHalfSJ - iFlag);
                        result.tableIndex = iTbl;
                        return result;
                    } else {
                        result.disturbStart++;
                        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)) {
                            result.disturbStart -= (nHalfSJ + 1);
                            result.tableIndex = iTbl;
                            return result;
                        }
                    }
                    Disturb_JS_Val = rmsValue;
                }
            }
        }
        result.tableIndex = iTbl;
        return result;
    }

    /**
     * 组装波形标题与通道名称。
     */
    private void getWaveTitle(WaveDataDTO waveDataDTO, ComtradeCfgDTO comtradeCfgDTO) {
        List<String> tmpWaveTitle = new ArrayList<>();
        List<String> channelName = new ArrayList<>();
        AnalogDTO analogDTO;
        tmpWaveTitle.add("Time");
        channelName.add("/");
        String strUnit;
        for (int j = 0; j < comtradeCfgDTO.getNAnalogNum(); j++) {
            analogDTO = comtradeCfgDTO.getLstAnalogDTO().get(j);
            if (!StrUtil.equals(analogDTO.getSzPhasicName().toUpperCase(), "N")) {
                if ("A".equalsIgnoreCase(analogDTO.getSzUnitName())) {
                    strUnit = "I";
                } else {
                    strUnit = "U";
                }
                tmpWaveTitle.add(strUnit + analogDTO.getSzPhasicName().toUpperCase() + "相");
                channelName.add(analogDTO.getSzChannleName());
            }
        }
        waveDataDTO.setWaveTitle(tmpWaveTitle);
        waveDataDTO.setChannelNames(channelName);
    }

    /**
     * 单次扰动判据的中间结果。
     */
    private static final class DisturbanceResult {
        /** 扰动幅值。 */
        private float disturbValue;
        /** 扰动持续采样点数。 */
        private float disturbStart;
        /** 扰动起始索引。 */
        private int tableIndex;
    }

    public static void main(String[] args) {
        /********************************************************
         * iFlag == 0  高级算法的要求，采样率只能是32-128
         * iFlag == 1  普通展示，采样率按照cfg里面最小的（大于32）
         * iFlag == 2  App抽点要求，采样率抽点成32
         * iFlag == 3  高级算法原始波形（大于32）
         ********************************************************/
        /** 输出格式: 2014-5-05 00:00:00 大写H为24小时制 */
        DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String s;
        Date d = new Date();
        s = sdf.format(d);
        System.out.println(s);
        WaveFileComponent waveFileComponent = new WaveFileComponent();
        InputStream cfgStream = waveFileComponent.getFileInputStreamByFilePath("C:\\Users\\Administrator\\Desktop\\wave\\PQMonitor_PQM1_000062_20260501_053729_063_WAV.cfg");
        InputStream datStream = waveFileComponent.getFileInputStreamByFilePath("C:\\Users\\Administrator\\Desktop\\wave\\PQMonitor_PQM1_000062_20260501_053729_063_WAV.dat");
        // 获取瞬时波形 //获取原始波形值
        WaveDataDTO waveDataDTO = waveFileComponent.getComtrade(cfgStream, datStream, 1);
        d = new Date();
        s = sdf.format(d);
        System.out.println(s);
        // 获取RMS波形
        WaveDataDTO waveDataDTO1 = waveFileComponent.getValidData(waveDataDTO);
        d = new Date();
        s = sdf.format(d);
        System.out.println(s);
        // 获取特征值
        List<EigenvalueDTO> lstEigenvalueDTO = waveFileComponent.getEigenvalue(waveDataDTO, true);
        System.out.println(1);
    }


}


