package com.gyee.runeconomy.service.auto.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gyee.runeconomy.config.GyeeConfig;
import com.gyee.runeconomy.dto.AlarmDataParser;
import com.gyee.runeconomy.dto.FiveLoss.AnnotationTool;
import com.gyee.runeconomy.dto.FiveLoss.FixedVo;
import com.gyee.runeconomy.dto.FiveLoss.TableTitle;
import com.gyee.runeconomy.dto.fitting.Alarm;
import com.gyee.runeconomy.dto.fitting.AlarmDataVo;
import com.gyee.runeconomy.dto.result.PowerPointData;
import com.gyee.runeconomy.dto.speed.WindDirectionALG;
import com.gyee.runeconomy.init.CacheContext;
import com.gyee.runeconomy.model.LineCurveFitting;
import com.gyee.runeconomy.model.PowerFittingALG;
import com.gyee.runeconomy.model.PowerFittingData;
import com.gyee.runeconomy.model.PowerProcessALG;
import com.gyee.runeconomy.model.auto.ProBasicEquipment;
import com.gyee.runeconomy.model.auto.ProBasicEquipmentPoint;
import com.gyee.runeconomy.model.auto.ProBasicModelPower;
import com.gyee.runeconomy.model.auto.ProEconPowerFittingAnalySis;
import com.gyee.runeconomy.model.vo.PointVo;
import com.gyee.runeconomy.model.vo.PoliceVo;
import com.gyee.runeconomy.model.vo.ResultItem;
import com.gyee.runeconomy.model.vo.alarmWtVo;
import com.gyee.runeconomy.service.DBSCANPointALG;
import com.gyee.runeconomy.service.DataScanService;
import com.gyee.runeconomy.service.EarlyWarning.ApiClient;
import com.gyee.runeconomy.service.WindDirection.Point;
import com.gyee.runeconomy.util.FileUtil;
import com.gyee.runeconomy.util.realtimesource.feign.RemoteServiceBuilder;
import com.gyee.runeconomy.util.realtimesource.feign.TsDoubleData;
import io.swagger.annotations.ApiResponse;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Slf4j
@Service
public class NewDataFittingService {
    @Autowired
    private GyeeConfig config;


    @Autowired
    private RemoteServiceBuilder remoteService;

    @Autowired
    private ProEconPowerFittingAnalySisService proEconPowerFittingAnalySisService;

    public static final String DATA_PROCESS = "process";

    public static final String DATA_FITTING = "fitting";

    //    private List<List<TsDoubleData>> res = new ArrayList<>();

    //    private List<PowerPointData> dataFilter = new ArrayList<>();


    @Resource
    private DataScanService dataScanService;


    //数据map
    private Map<String, String> prepareMap = null;//数据准备map
    private Map<String, String> processMap = null;//数据处理map
    private Map<String, String> fittingMap = null;//数据拟合map

    /**
     * 数据准备拟合
     *
     * @param
     * @return
     */
    public ProEconPowerFittingAnalySis newDataFitting(String station,String wtId,Long st,Long et,Integer interval,Boolean isbw,Boolean isfbw,Boolean isfhl,Boolean istj,Boolean isglpc,double maxp,double maxs,double mins,double minp,Integer mode,Integer dimension) {
        prepareMap = new HashMap<>();
        processMap = new HashMap<>();
        fittingMap = new HashMap<>();

        //1.数据获取
        List<String> wtIds = Arrays.asList(wtId.split(","));
        //        deleteDir(config.getFilePathPrepare());
        for (int k = 0; k < wtIds.size(); k++) {
            String wt = wtIds.get(k);
            List<List<TsDoubleData>> result = new ArrayList<>();

            try {
                List<String> points = config.getPoints();
                //                Map<String, List<ProBasicEquipmentPoint>> collect = CacheContext.pointNewMap.get(wt).stream().collect(Collectors.groupingBy(w -> w.getUniformCode()));
                Map<String, List<ProBasicEquipmentPoint>> collect = CacheContext.pointNewMap.get(wt).stream().collect(Collectors.groupingBy(w -> w.getUniformCode()));
                if (collect.size() < 8)
                    continue;
                for (int i = 0; i < points.size(); i++) {
                    ProBasicEquipmentPoint point = collect.get(points.get(i)).get(0);
                    if (point == null) continue;
                    log.info("测点：" + point.getId() + "----" + point.getName());
                    List<TsDoubleData> data = remoteService.adapterfd().getHistorySnap(point.getNemCode(), st, et, interval);
                    //                    List<TsDoubleData> data = edosUtil.getHistorySnap(point.getNemCode(), vo.getSt(), vo.getEt(), vo.getInterval());
                    //                    List<PointData> data = edosUtil.getHistoryDatasSnap(point.getNemCode(), vo.getSt(), vo.getEt(), vo.getInterval());
                    if (data == null || data.size() == 0)
                        break;
                    result.add(data);
                    TimeUnit.MILLISECONDS.sleep(200);
                }
                if (result.size() != points.size())
                    continue;

                SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
                String content = prepareAssemble(result);
                //                 处理的数据保存在本地
                String wtCode = CacheContext.wtmap.get(wt).getId();
                String wtCode2 = CacheContext.wtmap.get(wt).getNemCode();
//                String fileName = config.getFilePathPrepare() + station + "_" + wtCode + "_" + System.currentTimeMillis() / 1000 + ".csv";
                String fileName = config.getFilePathPrepare() + station + "_" + wtCode + "_" + sdf.format(new Date(st)) + "-" + sdf.format(new Date(et)) + ".csv";

                // 创建 File 对象
                File file = new File(fileName);
                // 检查文件是否存在
                if (file.exists()) {
                    // 尝试删除文件
                    boolean isDeleted = file.delete();
                    if (isDeleted) {
                        System.out.println("文件删除成功: " + fileName);
                    } else {
                        System.out.println("文件删除失败: " + fileName);
                    }
                } else {
                    System.out.println("文件不存在: " + fileName);
                }

                boolean flag = FileUtil.writeFile(fileName, content);

                if (flag) {  // TODO  保存数据库
                    ProEconPowerFittingAnalySis obj = new ProEconPowerFittingAnalySis();
                    obj.setStation(station);
                    obj.setStationcn(CacheContext.wtstandardmap.get(station));
                    obj.setWindturbineId(wt);
                    obj.setCode(wtCode2);
                    //                    obj.setTime(DateUtil.format(vo.getSt(), "yyyy年MM月dd日") + "-" + DateUtil.format(vo.getEt(), "yyyy年MM月dd日"));

                    obj.setTime(sdf.format(new Date(st)) + "-" + sdf.format(new Date(et)));
                    obj.setInterval(String.valueOf(interval));
                    obj.setPath(fileName);
                    obj.setType("prepare");
                    obj.setInterp(interval);

                    proEconPowerFittingAnalySisService.delete(obj.getTime(), fileName);
                    proEconPowerFittingAnalySisService.saveOrUpdate(obj);
                    prepareMap.put(obj.getId(), fileName);//保存拿到的数据
                }
                System.out.println("数据准备完成：" + wt);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }


        //2.数据筛选
        try {
            for (String key : prepareMap.keySet()) {
                ProEconPowerFittingAnalySis obj = proEconPowerFittingAnalySisService.getById(key);
                /** 读取csv数据  转换成对象数组 **/
                List<PowerPointData> eis = new ArrayList<>();
                List<String> list = FileUtil.readFile(prepareMap.get(key), true);
                //                String s = prepareAssemble(res);
                //                String[] lines = s.split("\n");
                //                List<String> list = new ArrayList<>(Arrays.asList(lines));
                for (int i = 1; i < list.size(); i++) {
                    eis.add(new PowerPointData(list.get(i).split(","), false));
                }

                /** 风速  ->  保证功率  来自数据库 **/
                List<ProBasicModelPower> modelPowerList = CacheContext.modelPowerDetailNewMap.get(CacheContext.wtmap.get(obj.getWindturbineId()).getModelId());
                Map<Double, Double> modelPowerMap = modelPowerList.stream().collect(Collectors.toMap(ProBasicModelPower::getSpeed, ProBasicModelPower::getEnsurePower));
                /** 数据预处理 **/
                Boolean qfh = true;
                Integer qfhdj = 2;
                List<PowerPointData> data = PowerProcessALG.dataProcess(eis, modelPowerMap, maxs, mins, maxp, minp, isfbw, isfhl, isbw, istj, isglpc, qfh, qfhdj);
                /** 静风频率 **/
                List<Double> ls = WindDirectionALG.frequency(data.stream().map(PowerPointData::getSpeed).collect(Collectors.toList()), 3);
                double frequency = ls.get(0);
                double speed = ls.get(1);

                String content = processAssemble(data);
//                String fileName = config.getFilePathProcess() + station + "_" + obj.getWindturbineId() + "_" + SnowFlakeUtil.generateIdL() / 100000 + ".csv";
                String fileName = config.getFilePathProcess() + station + "_" + obj.getWindturbineId() + "_" + obj.getTime() + ".csv";

                // 创建 File 对象
                File file = new File(fileName);
                // 检查文件是否存在
                if (file.exists()) {
                    // 尝试删除文件
                    boolean isDeleted = file.delete();
                    if (isDeleted) {
                        System.out.println("文件删除成功: " + fileName);
                    } else {
                        System.out.println("文件删除失败: " + fileName);
                    }
                } else {
                    System.out.println("文件不存在: " + fileName);
                }


                boolean flag = FileUtil.writeFile(fileName, content);
                ProEconPowerFittingAnalySis obj1 = new ProEconPowerFittingAnalySis();
                if (flag) {  // TODO  保存数据库
                    //                    obj.setId(null);
                    obj1.setStation(station);
                    obj1.setStationcn(CacheContext.wtstandardmap.get(station));
                    obj1.setWindturbineId(obj.getWindturbineId());
                    obj1.setCode(obj.getCode());
                    obj1.setTime(obj.getTime());
                    obj1.setPath(fileName);
                    obj1.setFrequency(frequency);
                    obj1.setSpeedavg(speed);
                    obj1.setInterval(obj.getInterval());
                    obj1.setType(DATA_PROCESS);

                    proEconPowerFittingAnalySisService.delete(obj1.getTime(), fileName);
                    proEconPowerFittingAnalySisService.saveOrUpdate(obj1);
                    processMap.put(obj1.getId(), fileName);//保存预处理的的数据
                }

                System.out.println("功率曲线拟合数据预处理完成：" + obj.getWindturbineId());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //3.数据拟合

        AtomicReference<ProEconPowerFittingAnalySis> object = new AtomicReference<>();
        //        deleteDir(config.getFilePathFitting());
        if (mode == 0) {  //单台拟合
            for (String processkey : processMap.keySet()) {
                List<ProEconPowerFittingAnalySis> list = proEconPowerFittingAnalySisService.selectListByIds(processkey);
                List<Double> arraySpeed = new ArrayList<>();
                List<Double> arrayPower = new ArrayList<>();
                List<String> line = FileUtil.readFile(processMap.get(processkey), true);
                //                String content = processAssemble(dataFilter);
                //                String[] lines = content.split("\n");
                //                List<String> line = new ArrayList<>(Arrays.asList(lines));
                csvParse(line, arraySpeed, arrayPower, mins, maxs, minp, maxp);
                List<ProBasicModelPower> mp = CacheContext.modelPowerDetailNewMap.get(CacheContext.wtmap.get(list.get(0).getWindturbineId()).getModelId());
                Double maxP = mp.stream().map(ProBasicModelPower::getEnsurePower).max(Comparator.comparing(Double::doubleValue)).get();
                object.set(fittingMode(list, maxP, arraySpeed, arrayPower, dimension, mode));

            }
        }
        if (mode == 1) {  //合并拟合

            AtomicReference<Double> maxP = new AtomicReference<>(0.0);
            List<Double> arraySpeed = new ArrayList<>();
            List<Double> arrayPower = new ArrayList<>();
            StringBuffer ids = new StringBuffer();
            for (String processkey : processMap.keySet()) {
                ids.append(processkey).append(",");
                ProEconPowerFittingAnalySis fittingAnalySis = proEconPowerFittingAnalySisService.getById(processkey);
                List<String> line = FileUtil.readFile(processMap.get(processkey), true);
                //                String content = processAssemble(dataFilter);
                //                String[] lines = content.split("\n");
                //                List<String> line = new ArrayList<>(Arrays.asList(lines));
                csvParse(line, arraySpeed, arrayPower, mins, maxs, minp, maxp);
                List<ProBasicModelPower> mp = CacheContext.modelPowerDetailNewMap.get(CacheContext.wtmap.get(fittingAnalySis.getWindturbineId()).getModelId());
                Double maxPower = mp.stream().map(ProBasicModelPower::getEnsurePower).max(Comparator.comparing(Double::doubleValue)).get();
                if (maxPower > maxP.get()) maxP.set(maxPower);
            }
            List<ProEconPowerFittingAnalySis> list = proEconPowerFittingAnalySisService.selectListByIds(ids.toString());

            object.set(fittingMode(list, maxP.get(), arraySpeed, arrayPower, dimension, mode));
        }
        if (mode == 2) {
            //同名拟合（暂时不支持）
        }
        fittingMap.put(object.get().getId(), object.get().getPath());

        return object.get();
    }


    /**
     * 曲线，散点等数据
     * 风速 eg:[1,2,3,4。。。。]
     * 曲线 eg:[1,2,3,4。。。。]
     * 散点 eg:[[1,2],[3,2],[3,5]。。。。。]
     *
     * @param id
     * @return
     */
    public Map<String, Object> dataFittingCurve(String id) {

        Map<String, Object> map = new HashMap<>();
        ProEconPowerFittingAnalySis obj = proEconPowerFittingAnalySisService.selectItemById(id);

        //实际功率、风速、Cp值
        List<Object> sjglList = new ArrayList<>();
        List<Object> cpzList = new ArrayList<>();
        List<String> ls = FileUtil.readFile(obj.getPath(), true);
        for (int i = 1; i < ls.size(); i++) {
            PowerFittingData data = new PowerFittingData(ls.get(i).split(","));
            sjglList.add(new double[]{Double.valueOf(data.getSpeed()), data.getNhdata()});
            cpzList.add(new double[]{Double.valueOf(data.getSpeed()), data.getCpdata()});
        }

        //保证功率
        List<ProBasicModelPower> modelPower = CacheContext.modelPowerDetailNewMap.get(CacheContext.wtmap.get(obj.getWindturbineId()).getModelId());
        List<Object> bzglList = modelPower.stream().sorted(Comparator.comparing(ProBasicModelPower::getSpeed)).map(m -> new double[]{m.getSpeed(), m.getEnsurePower()}).collect(Collectors.toList());

        //散点
        String[] ids = obj.getProcessid().split(",");
        List<PowerPointData> yyd = new ArrayList<>(); //有用点
        List<PowerPointData> wyd = new ArrayList<>(); //无用点
        for (String pid : ids) {
            ProEconPowerFittingAnalySis pf = proEconPowerFittingAnalySisService.selectItemById(pid);
            List<String> lp = FileUtil.readFile(pf.getPath(), true);
            for (int i = 1; i < lp.size(); i++) {
                String[] split = lp.get(i).split(",");
                PowerPointData pd = new PowerPointData(split, true);
                if (pd.getSpeed() < 0 || pd.getPower() < 0)
                    continue;
                pd.setWtId(pf.getCode());
                if (0 == pd.getFilter())
                    yyd.add(pd);   //没有过滤
                if (1 == pd.getFilter())
                    wyd.add(pd);   //已过滤
            }
        }

        dataScanService.setMapYY(DBSCANPointALG.dbscan(yyd, 10));
        dataScanService.setMapWY(DBSCANPointALG.dbscan(wyd, 10));

        List<PointVo> listYY = new ArrayList<>();
        List<PointVo> listWY = new ArrayList<>();
        dataScanService.getMapYY().forEach((k, v) -> {
            // k: 前端画圈时的散点数据标记
            listYY.add(new PointVo(v.get(0).getSpeed(), v.get(0).getPower(), dataScanService.getMapYY().get(k).size() + 3, k));
        });
        dataScanService.getMapWY().forEach((k, v) -> {
            // k: 前端画圈时的散点数据标记
            listWY.add(new PointVo(v.get(0).getSpeed(), v.get(0).getPower(), dataScanService.getMapWY().get(k).size() + 3, k));
        });

        map.put("sjgl", sjglList);    //实际功率
        map.put("llgl", bzglList);    //保证功率
        map.put("cpz", cpzList);      //Cp值
        map.put("obj", obj);     //对w象
        map.put("yyd", listYY);  //有用散点
        map.put("wyd", listWY);  //无用散点

        return map;
    }


    /**
     * 通过大点的key获取小散点
     *
     * @param yk
     * @param wk
     * @return
     */
    public List<PowerPointData> dataOrigin(String yk, String wk) {
        List<PowerPointData> list = new ArrayList<>();

        if (!StringUtils.isEmpty(yk)) {
            String[] key = yk.split(",");
            for (String k : key) {
                list.addAll(dataScanService.getMapYY().get(k));
            }
        }
        if (!StringUtils.isEmpty(wk)) {
            String[] kew = wk.split(",");
            for (String k : kew) {
                list.addAll(dataScanService.getMapWY().get(k));
            }
        }

        return list;
    }


    /**
     * 组装表格数据
     *
     * @param id
     * @return
     */
    public Map<String, Object> dataFittingShow(String id) {
        Map<String, Object> map = new HashMap<>();

        /** 添加标题 **/
        List<FixedVo> fxList = AnnotationTool.getFixedVoList(PowerFittingData.class);
        List<TableTitle> lt = fxList.stream().filter(f -> f.getRemark().equals("1"))
                .map(d -> new TableTitle(d.getName(), d.getDes())).collect(Collectors.toList());

        /** 添加内容 **/
        /** 添加内容 **/
        List<PowerFittingData> list = new ArrayList<>();
        ProEconPowerFittingAnalySis obj = proEconPowerFittingAnalySisService.selectItemById(id);
        List<String> ls = FileUtil.readFile(obj.getPath(), true);
        for (int i = 1; i < ls.size(); i++) {
            PowerFittingData data = new PowerFittingData(ls.get(i).split(","),CacheContext.wtmap.get(obj.getWindturbineId()).getModelId());
            list.add(data);
        }

        map.put("title", lt);
        map.put("data", list);

        return map;
    }


    private String prepareAssemble(List<List<TsDoubleData>> list) {
        if (list.size() == 0)
            return null;

        StringBuilder sb = setTitle();
        List<TsDoubleData> data = list.get(0);
        for (int i = 0; i < data.size(); i++) {
            //                sb.append(DateUtil.format(data.get(i).getTs(), DateUtil.DATE_TIME_PATTERN)).append(",");
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            sb.append(sdf.format(data.get(i).getTs())).append(",");
            sb.append(data.get(i).getDoubleValue()).append(",");
            for (int j = 1; j < list.size(); j++) {

                //
                if (null != list.get(j) && list.get(j).size() > 0) {
                    sb.append(list.get(j).get(i).getDoubleValue()).append(",");
                } else {
                    sb.append(0).append(",");
                }

            }
            sb.deleteCharAt(sb.lastIndexOf(","));
            sb.append("\n");
        }

        return sb.toString();
    }


    private String processAssemble(List<PowerPointData> list) {
        StringBuilder sb = setTitle();
        for (PowerPointData obj : list) {
            List<FixedVo> ls = AnnotationTool.getValueList(obj);
            String data = ls.stream().filter(f -> !StringUtils.isEmpty(f.getRemark())).map(FixedVo::getKey).collect(Collectors.joining(","));
            sb.append(data).append("\n");
        }

        return sb.toString();
    }


    private StringBuilder setTitle() {
        StringBuilder sb = new StringBuilder();
        val list = AnnotationTool.getFixedVoList(PowerPointData.class);
        String columnName = list.stream().filter(f -> f.getRemark().equals("1")).map(FixedVo::getDes).collect(Collectors.joining(","));
        sb.append(columnName).append("\n");
        return sb;
    }

    private StringBuilder setTitleFitting() {
        StringBuilder sb = new StringBuilder();
        val list = AnnotationTool.getFixedVoList(PowerFittingData.class);
        String columnName = list.stream().filter(f -> f.getRemark().equals("1")).map(FixedVo::getDes).collect(Collectors.joining(","));
        sb.append(columnName).append("\n");
        return sb;
    }


    /**
     * 读取csv数据 转换成对象数组
     **/
    private void csvParse(List<String> line, List<Double> arrayS, List<Double> arrayP, double mins, double maxs, double minp, double maxp) {
        for (int i = 1; i < line.size(); i++) {
            String[] split = line.get(i).split(",");
            PowerPointData data = new PowerPointData(split, true);//是否过滤 0：没过滤 1：过滤
            double x = data.getSpeed();    //风速
            double y = data.getPower();    //功率
            int filter = data.getFilter();
            if (filter == 0 && (x >= mins && x <= maxs && y >= minp && y <= maxp)) {
                arrayS.add(x);
                arrayP.add(y);
            }
        }
    }


    private ProEconPowerFittingAnalySis fittingMode(List<ProEconPowerFittingAnalySis> list, Double powerMax, List<Double> arraySpeed, List<Double> arrayPower, Integer dimension, int mode) {
        if (list == null || list.size() == 0)
            return null;

        ProEconPowerFittingAnalySis obj = list.get(0);
        //风速0-25，数据不全拟合的则不全，需要补一下
        arraySpeed.add(0.0);
        arraySpeed.add(25.01);
        arrayPower.add(0.0);
        arrayPower.add(powerMax);
        double[] arrX = arraySpeed.stream().sorted().mapToDouble(i -> i).toArray();
        double[] arrY = arrayPower.stream().sorted().mapToDouble(i -> i).toArray();

        //功率曲线拟合 不合理数据过滤
        List<Point> temp = PowerFittingALG.buildLine(arrX, arrY, arraySpeed.size(), dimension, 0.01);
        //推力系数 CP值
        LineCurveFitting lf = new LineCurveFitting();
        lf.setYLines(temp);

        lf = PowerFittingALG.buildCp(CacheContext.modelMap.get(CacheContext.wtmap.get(obj.getWindturbineId()).getModelId()).getSweptArea(), lf);
        lf.getCpValue().forEach(f -> {
            if (f.getX() <= 2.5) f.setY(0);
        });
        //曲线偏差率
        dataCurveRatio(lf, obj);

        String content = fittingAssemble(lf);
        String processId = "";
        String fileName = null;
        if (mode == 0) {
            processId = obj.getId();
//            fileName = config.getFilePathFitting() + obj.getStation() + "_" + obj.getCode() + "_" + SnowFlakeUtil.generateIdL() / 100000 + ".csv";
            fileName = config.getFilePathFitting() + obj.getStation() + "_" + obj.getCode() + "_" + obj.getTime() + ".csv";
        }
        if (mode == 1) {
            processId = list.stream().map(d -> d.getId()).collect(Collectors.joining(","));
            fileName = config.getFilePathFitting() + obj.getStation() + "_merge" + "_" + obj.getTime() + ".csv";
        }
        if (mode == 2) {
            processId = list.stream().map(d -> d.getId()).collect(Collectors.joining(","));
            fileName = config.getFilePathFitting() + obj.getStation() + "_same" + "_" + obj.getTime() + ".csv";
        }

        // 创建 File 对象
        File file = new File(fileName);
        // 检查文件是否存在
        if (file.exists()) {
            // 尝试删除文件
            boolean isDeleted = file.delete();
            if (isDeleted) {
                System.out.println("文件删除成功: " + fileName);
            } else {
                System.out.println("文件删除失败: " + fileName);
            }
        } else {
            System.out.println("文件不存在: " + fileName);
        }
        ProEconPowerFittingAnalySis obj2 = new ProEconPowerFittingAnalySis();
        boolean flag = FileUtil.writeFile(fileName, content);
        if (flag) {  // TODO  保存数据库
            //        obj.setId(null);

            obj2.setCode(obj.getCode());
            obj2.setStation(obj.getStation());
            obj2.setTime(obj.getTime());
            obj2.setWindturbineId(obj.getWindturbineId());
            obj2.setPath(fileName);
            obj2.setInterval(obj.getInterval());
            obj2.setProcessid(processId);
            obj2.setCpavg(lf.getCpAvg());
            obj2.setType(DATA_FITTING);

            proEconPowerFittingAnalySisService.delete(obj2.getTime(), fileName);
            proEconPowerFittingAnalySisService.saveOrUpdate(obj2);
        }
        System.out.println("功率曲线拟合完成：" + obj.getWindturbineId());

        return obj2;
    }


    /**
     * 曲线偏差率  分段的+全部的
     * 3-5  5-10  10-12  12-25
     *
     * @return
     */
    private void dataCurveRatio(LineCurveFitting lf, ProEconPowerFittingAnalySis obj) {
        DecimalFormat df = new DecimalFormat("0.00");
        try {
            //风速、实际功率
            List<Point> point = new ArrayList<>();  //3-25m
            List<Point> point5 = new ArrayList<>();  //分段
            List<Point> point10 = new ArrayList<>();  //分段
            List<Point> point12 = new ArrayList<>();  //分段
            List<Point> point25 = new ArrayList<>();  //分段
            List<Point> line = lf.getYLines();
            for (int i = 1; i < line.size(); i++) {
                double speed = Double.valueOf(df.format(line.get(i).getX()));
                if (speed >= 3 && speed < 5)
                    point5.add(new Point(speed, line.get(i).getY()));
                if (speed >= 5 && speed < 10)
                    point10.add(new Point(speed, line.get(i).getY()));
                if (speed >= 10 && speed < 12)
                    point12.add(new Point(speed, line.get(i).getY()));
                if (speed >= 12 && speed <= 25)
                    point25.add(new Point(speed, line.get(i).getY()));
                if (speed >= 3 && speed <= 25) {
                    point.add(new Point(speed, line.get(i).getY()));
                }
            }

            //保证功率
            List<Point> points = new ArrayList<>();  //3-25m
            List<Point> points5 = new ArrayList<>();  //分段
            List<Point> points10 = new ArrayList<>();  //分段
            List<Point> points12 = new ArrayList<>();  //分段
            List<Point> points25 = new ArrayList<>();  //分段
            List<ProBasicModelPower> list = CacheContext.modelPowerDetailNewMap.get(CacheContext.wtmap.get(obj.getWindturbineId()).getModelId());
            for (int i = 0; i < list.size(); i++) {
                ProBasicModelPower power = list.get(i);
                if (power.getSpeed() >= 3 && power.getSpeed() < 5)
                    points5.add(new Point(power.getSpeed(), power.getEnsurePower()));
                if (power.getSpeed() >= 5 && power.getSpeed() < 10)
                    points10.add(new Point(power.getSpeed(), power.getEnsurePower()));
                if (power.getSpeed() >= 10 && power.getSpeed() < 12)
                    points12.add(new Point(power.getSpeed(), power.getEnsurePower()));
                if (power.getSpeed() >= 12 && power.getSpeed() <= 25)
                    points25.add(new Point(power.getSpeed(), power.getEnsurePower()));
                if (power.getSpeed() >= 3 && power.getSpeed() <= 25)
                    points.add(new Point(power.getSpeed(), power.getEnsurePower()));
            }

            double maxp5 = list.stream().filter(f -> 5.0 == f.getSpeed()).collect(Collectors.toList()).get(0).getEnsurePower();
            double maxp10 = list.stream().filter(f -> 10.0 == f.getSpeed()).collect(Collectors.toList()).get(0).getEnsurePower();
            double maxp12 = list.stream().filter(f -> 12.0 == f.getSpeed()).collect(Collectors.toList()).get(0).getEnsurePower();
            double maxp25 = list.stream().filter(f -> 25.0 == f.getSpeed()).collect(Collectors.toList()).get(0).getEnsurePower();

            //曲线偏差率
            double pcl = PowerFittingALG.curveDeviationRatio2(point, points, maxp25, 3, 25);
            double pcl5 = PowerFittingALG.curveDeviationRatio2(point5, points5, maxp5, 3, 5);
            double pcl10 = PowerFittingALG.curveDeviationRatio2(point10, points10, maxp10, 5, 10);
            double pcl12 = PowerFittingALG.curveDeviationRatio2(point12, points12, maxp12, 10, 12);
            double pcl25 = PowerFittingALG.curveDeviationRatio2(point25, points25, maxp25, 12, 25);

            obj.setPcratio(Double.valueOf(df.format(pcl)));
            obj.setPc5ratio(Double.valueOf(df.format(pcl5)));
            obj.setPc10ratio(Double.valueOf(df.format(pcl10)));
            obj.setPc12ratio(Double.valueOf(df.format(pcl12)));
            obj.setPc25ratio(Double.valueOf(df.format(pcl25)));

        } catch (Exception e) {
            log.error("DataFittingService--dataCurveRatio", e);
        }
    }

    private String fittingAssemble(LineCurveFitting lf) {
        StringBuilder sb = setTitleFitting();
        for (int i = 0; i < lf.getYLines().size(); i++) {
            Point cp = lf.getCpValue().get(i);
            Point gl = lf.getYLines().get(i);

            String stx = String.format("%.2f", gl.getX());
            double x = Double.parseDouble(stx);
            String sty = String.format("%.2f", gl.getY());
            double y = Double.parseDouble(sty);
            String stcp = String.format("%.4f", cp.getY());
            double z = Double.parseDouble(stcp);
            sb.append(x).append(",").append(y).append(",").append(z).append("\n");
        }

        return sb.toString();
    }


    /**
     * @param table //     * @param only
     * @return
     */
    public List<AlarmDataVo> getDataAlarms(String table, List<Alarm> alarmList) {

        ApiClient client = new ApiClient();

        List<AlarmDataVo> list1 = new ArrayList<>();
        if (table.equals("alarmWt")) {
            for (Alarm alarm : alarmList) {

                List<ProBasicEquipment> equipments = CacheContext.wtls.stream()
                        .filter(a -> alarm.getWtId().equals(a.getAname())).collect(Collectors.toList());

                String modelId = equipments.get(0).getModelId();
                String wtid = equipments.get(0).getId();
                String station = equipments.get(0).getWindpowerstationId();
                String begin = alarm.getTime();

                // 定义日期时间格式
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

                // 将时间字符串转换为 LocalDateTime
                LocalDateTime parsedTime = LocalDateTime.parse(begin, formatter);

                // 增加一分钟
//                LocalDateTime endTime = parsedTime.plusMinutes(1);
                LocalDateTime endTime = parsedTime.plusDays(1);

                // 将新的时间转换回字符串
                String end = endTime.format(formatter);

                String result = client.getglqxgzFromApi(
                        station,
                        wtid,
                        modelId,
                        "",
                        begin,
                        end,
                        "1",
                        "20",
                        "gz"
                );


                String json = result;

                ObjectMapper mapper = new ObjectMapper();
                try {
                    alarmWtVo response = mapper.readValue(json, alarmWtVo.class);

                    // 使用解析后的数据
                    for (ResultItem item : response.getData().getResult()) {
                        // 读取所需数据
                        AlarmDataVo vo = new AlarmDataVo();
                        vo.setWtid(equipments.get(0).getAname());
                        vo.setTime(begin);
                        vo.setBj("故障");
                        vo.setTx("自定义");
                        vo.setAlarmname(item.getFaultView());
                        list1.add(vo);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }

            return list1;

        } else if (table.equals("alarmCt")) {

            for (Alarm alarm : alarmList) {

                List<ProBasicEquipment> equipments = CacheContext.wtls.stream()
                        .filter(a -> alarm.getWtId().equals(a.getAname())).collect(Collectors.toList());

                String modelId = equipments.get(0).getModelId();
                String wtid = equipments.get(0).getId();
                String begin = alarm.getTime();

                // 定义日期时间格式
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

                // 将时间字符串转换为 LocalDateTime
                LocalDateTime parsedTime = LocalDateTime.parse(begin, formatter);

                // 增加一分钟
                LocalDateTime endTime = parsedTime.plusMinutes(1);

                // 将新的时间转换回字符串
                String end = endTime.format(formatter);

                String result = client.getDataFromApi(
                        begin,
                        end,
                        wtid,
                        modelId,
                        "windturbine",
                        "",  // 如果没有 alarmIds，可以传空字符串
                        "s"
                );

//                String result = "[\n" +
//                        "    {\n" +
//                        "        \"GJNY_SXGS_LJSF01_LN\":[\n" +
//                        "            {\n" +
//                        "                \"snapId\":1302951473243889700,\n" +
//                        "                \"stationId\":\"GJNY_SXGS_LJSF01_LN\",\n" +
//                        "                \"windturbineId\":null,\n" +
//                        "                \"alertText\":\"变桨电容电压小于57v\",\n" +
//                        "                \"count\":1,\n" +
//                        "                \"alarmid\":\"0000425\",\n" +
//                        "                \"time\":0,\n" +
//                        "                \"relateParts\":\"BJXT\",\n" +
//                        "                \"relatePartsText\":\"变桨系统\",\n" +
//                        "                \"code\":null,\n" +
//                        "                \"windturbineCode\":null,\n" +
//                        "                \"lineId\":null\n" +
//                        "            },\n" +
//                        "            {\n" +
//                        "                \"snapId\":1302951473243889700,\n" +
//                        "                \"stationId\":\"GJNY_SXGS_LJSF01_LN\",\n" +
//                        "                \"windturbineId\":null,\n" +
//                        "                \"alertText\":\"如果风机轴a 和 轴b 温度差 大于20度，则报警\",\n" +
//                        "                \"count\":3,\n" +
//                        "                \"alarmid\":\"0000454\",\n" +
//                        "                \"time\":4270,\n" +
//                        "                \"relateParts\":\"ZZ\",\n" +
//                        "                \"relatePartsText\":null,\n" +
//                        "                \"code\":null,\n" +
//                        "                \"windturbineCode\":null,\n" +
//                        "                \"lineId\":null\n" +
//                        "            }\n" +
//                        "        ]\n" +
//                        "    }\n" +
//                        "]";
                List response = AlarmDataParser.parseResponse(result);

                if (response != null) {
                    for (Object resc : response) {
                        AlarmDataParser.AlarmData alarmData = (AlarmDataParser.AlarmData) resc;
                        // 读取所需数据
                        String alertText = alarmData.getAlertText(); // 预警内容
                        String relateType = alarmData.getRelatePartsText(); // 部件名称
                        AlarmDataVo vo = new AlarmDataVo();
                        vo.setWtid(equipments.get(0).getAname());
                        vo.setTime(begin);
                        vo.setBj(relateType);
                        vo.setTx("自定义");
                        vo.setAlarmname(alertText);
                        list1.add(vo);
                    }
                }
            }
            return list1;
        }

        return list1;
    }

}

