Browse Source

Merge branch 'master' of http://124.70.43.205:3000/xieshengjie/sis-background into yiqu

xushili 2 years ago
parent
commit
e6d27ec990
95 changed files with 4936 additions and 309 deletions
  1. 3 3
      gyee-sample-impala/src/main/java/com/gyee/impala/common/config/ThreadPoolConfig.java
  2. 1 1
      pom.xml
  3. 0 26
      power-fetting/src/main/java/com/gyee/power/fetting/BootApplication.java
  4. 0 16
      power-fetting/src/main/java/com/gyee/power/fetting/common/config/GyeeConfig.java
  5. 0 152
      power-fetting/src/main/java/com/gyee/power/fetting/common/spring/InitialRunner.java
  6. 37 11
      power-fetting/pom.xml
  7. 11 11
      power-fetting/src/main/java/com/gyee/power/fetting/MapperGenerator.java
  8. 47 0
      power-fitting/src/main/java/com/gyee/power/fitting/PowerBootApplication.java
  9. 39 0
      power-fitting/src/main/java/com/gyee/power/fitting/common/alg/DBSCANPointALG.java
  10. 465 0
      power-fitting/src/main/java/com/gyee/power/fitting/common/alg/MpptFittingAlg.java
  11. 424 0
      power-fitting/src/main/java/com/gyee/power/fitting/common/alg/PowerFittingALG.java
  12. 356 0
      power-fitting/src/main/java/com/gyee/power/fitting/common/alg/PowerProcessALG.java
  13. 137 0
      power-fitting/src/main/java/com/gyee/power/fitting/common/alg/WindDirectionALG.java
  14. 1 1
      power-fetting/src/main/java/com/gyee/power/fetting/common/base/ExcludeQueryWrapper.java
  15. 1 1
      power-fetting/src/main/java/com/gyee/power/fetting/common/config/CorsConfig.java
  16. 1 8
      power-fetting/src/main/java/com/gyee/power/fetting/common/config/datasource/DataSourceConfig.java
  17. 68 0
      power-fitting/src/main/java/com/gyee/power/fitting/common/config/GyeeConfig.java
  18. 50 0
      power-fitting/src/main/java/com/gyee/power/fitting/common/config/ThreadPoolConfig.java
  19. 20 0
      power-fitting/src/main/java/com/gyee/power/fitting/common/config/WebSocketConfig.java
  20. 39 0
      power-fitting/src/main/java/com/gyee/power/fitting/common/constants/Constants.java
  21. 3 3
      power-fetting/src/main/java/com/gyee/power/fetting/common/exception/AdviceException.java
  22. 2 2
      power-fetting/src/main/java/com/gyee/power/fetting/common/exception/CustomException.java
  23. 3 3
      power-fetting/src/main/java/com/gyee/power/fetting/common/feign/IAdapterService.java
  24. 2 2
      power-fetting/src/main/java/com/gyee/power/fetting/common/feign/RemoteServiceBuilder.java
  25. 1 1
      power-fetting/src/main/java/com/gyee/power/fetting/common/result/JsonResult.java
  26. 2 1
      power-fetting/src/main/java/com/gyee/power/fetting/common/result/ResultCode.java
  27. 1 1
      power-fetting/src/main/java/com/gyee/power/fetting/common/spring/ExitDisposable.java
  28. 125 0
      power-fitting/src/main/java/com/gyee/power/fitting/common/spring/InitialRunner.java
  29. 1 1
      power-fetting/src/main/java/com/gyee/power/fetting/common/spring/SpringContextUtil.java
  30. 1 1
      power-fetting/src/main/java/com/gyee/power/fetting/common/util/Base64Util.java
  31. 1 1
      power-fetting/src/main/java/com/gyee/power/fetting/common/util/CollectUtil.java
  32. 21 3
      power-fetting/src/main/java/com/gyee/power/fetting/common/util/DateUtil.java
  33. 107 10
      power-fetting/src/main/java/com/gyee/power/fetting/common/util/FileUtil.java
  34. 1 1
      power-fetting/src/main/java/com/gyee/power/fetting/common/util/JudeSystem.java
  35. 20 1
      power-fetting/src/main/java/com/gyee/power/fetting/common/util/NumberUtil.java
  36. 62 0
      power-fitting/src/main/java/com/gyee/power/fitting/common/util/PowerFittingUtil.java
  37. 1 1
      power-fetting/src/main/java/com/gyee/power/fetting/common/util/SnowFlakeUtil.java
  38. 1 1
      power-fetting/src/main/java/com/gyee/power/fetting/common/util/TokenGenerator.java
  39. 127 0
      power-fitting/src/main/java/com/gyee/power/fitting/controller/analyse/DataFittingController.java
  40. 83 0
      power-fitting/src/main/java/com/gyee/power/fitting/controller/analyse/DataPrepareController.java
  41. 106 0
      power-fitting/src/main/java/com/gyee/power/fitting/controller/analyse/DataProcessController.java
  42. 61 0
      power-fitting/src/main/java/com/gyee/power/fitting/controller/analyse/DateOptionController.java
  43. 33 0
      power-fitting/src/main/java/com/gyee/power/fitting/controller/analyse/RatioController.java
  44. 48 0
      power-fitting/src/main/java/com/gyee/power/fitting/controller/analyse/WindDirectionController.java
  45. 36 0
      power-fitting/src/main/java/com/gyee/power/fitting/controller/base/WindInfoController.java
  46. 18 0
      power-fitting/src/main/java/com/gyee/power/fitting/mapper/EquipmentmodelMapper.java
  47. 21 0
      power-fitting/src/main/java/com/gyee/power/fitting/mapper/ModelpowerMapper.java
  48. 18 0
      power-fitting/src/main/java/com/gyee/power/fitting/mapper/ModelpowerdetailsMapper.java
  49. 18 0
      power-fitting/src/main/java/com/gyee/power/fitting/mapper/PowerfittinganalysisMapper.java
  50. 2 2
      power-fetting/src/main/java/com/gyee/power/fetting/mapper/WindpowerstationMapper.java
  51. 2 2
      power-fetting/src/main/java/com/gyee/power/fetting/mapper/WindturbineMapper.java
  52. 18 0
      power-fitting/src/main/java/com/gyee/power/fitting/mapper/Windturbinetestingpointai2Mapper.java
  53. 72 0
      power-fitting/src/main/java/com/gyee/power/fitting/model/Equipmentmodel.java
  54. 47 0
      power-fitting/src/main/java/com/gyee/power/fitting/model/Modelpower.java
  55. 47 0
      power-fitting/src/main/java/com/gyee/power/fitting/model/Modelpowerdetails.java
  56. 74 0
      power-fitting/src/main/java/com/gyee/power/fitting/model/Powerfittinganalysis.java
  57. 5 4
      power-fetting/src/main/java/com/gyee/power/fetting/model/Windpowerstation.java
  58. 4 3
      power-fetting/src/main/java/com/gyee/power/fetting/model/Windturbine.java
  59. 86 0
      power-fitting/src/main/java/com/gyee/power/fitting/model/Windturbinetestingpointai2.java
  60. 35 0
      power-fitting/src/main/java/com/gyee/power/fitting/model/custom/LineCurveFitting.java
  61. 16 0
      power-fitting/src/main/java/com/gyee/power/fitting/model/custom/Point.java
  62. 19 0
      power-fitting/src/main/java/com/gyee/power/fitting/model/custom/PointVo.java
  63. 27 0
      power-fitting/src/main/java/com/gyee/power/fitting/model/custom/PowerFittingPoint.java
  64. 62 0
      power-fitting/src/main/java/com/gyee/power/fitting/model/custom/PowerPointData.java
  65. 43 0
      power-fitting/src/main/java/com/gyee/power/fitting/model/custom/TableTitle.java
  66. 2 1
      power-fetting/src/main/java/com/gyee/power/fetting/model/custom/TsDoubleData.java
  67. 26 0
      power-fitting/src/main/java/com/gyee/power/fitting/service/EquipmentmodelService.java
  68. 19 0
      power-fitting/src/main/java/com/gyee/power/fitting/service/ModelpowerService.java
  69. 19 0
      power-fitting/src/main/java/com/gyee/power/fitting/service/ModelpowerdetailsService.java
  70. 33 0
      power-fitting/src/main/java/com/gyee/power/fitting/service/PowerfittinganalysisService.java
  71. 2 2
      power-fetting/src/main/java/com/gyee/power/fetting/service/WindpowerstationService.java
  72. 3 3
      power-fetting/src/main/java/com/gyee/power/fetting/service/WindturbineService.java
  73. 19 0
      power-fitting/src/main/java/com/gyee/power/fitting/service/Windturbinetestingpointai2Service.java
  74. 459 0
      power-fitting/src/main/java/com/gyee/power/fitting/service/custom/curve/DataFittingService.java
  75. 161 0
      power-fitting/src/main/java/com/gyee/power/fitting/service/custom/curve/DataPrepareService.java
  76. 162 0
      power-fitting/src/main/java/com/gyee/power/fitting/service/custom/curve/DataProcessService.java
  77. 20 0
      power-fitting/src/main/java/com/gyee/power/fitting/service/custom/curve/DataScanService.java
  78. 117 0
      power-fitting/src/main/java/com/gyee/power/fitting/service/custom/fx/WindDirectionService.java
  79. 85 0
      power-fitting/src/main/java/com/gyee/power/fitting/service/custom/ratio/RatioService.java
  80. 174 0
      power-fitting/src/main/java/com/gyee/power/fitting/service/custom/socket/WebSocketServer.java
  81. 46 0
      power-fitting/src/main/java/com/gyee/power/fitting/service/impl/EquipmentmodelServiceImpl.java
  82. 34 0
      power-fitting/src/main/java/com/gyee/power/fitting/service/impl/ModelpowerServiceImpl.java
  83. 37 0
      power-fitting/src/main/java/com/gyee/power/fitting/service/impl/ModelpowerdetailsServiceImpl.java
  84. 92 0
      power-fitting/src/main/java/com/gyee/power/fitting/service/impl/PowerfittinganalysisServiceImpl.java
  85. 6 6
      power-fetting/src/main/java/com/gyee/power/fetting/service/impl/WindpowerstationServiceImpl.java
  86. 8 7
      power-fetting/src/main/java/com/gyee/power/fetting/service/impl/WindturbineServiceImpl.java
  87. 40 0
      power-fitting/src/main/java/com/gyee/power/fitting/service/impl/Windturbinetestingpointai2ServiceImpl.java
  88. 30 10
      power-fetting/src/main/resources/application.yaml
  89. BIN
      power-fitting/src/main/resources/gdnx.db
  90. 27 0
      power-fitting/src/main/resources/mapper/EquipmentmodelMapper.xml
  91. 28 0
      power-fitting/src/main/resources/mapper/PowerfittinganalysisMapper.xml
  92. 4 4
      power-fetting/src/main/resources/mapper/WindpowerstationMapper.xml
  93. 2 2
      power-fetting/src/main/resources/mapper/WindturbineMapper.xml
  94. 32 0
      power-fitting/src/main/resources/mapper/Windturbinetestingpointai2Mapper.xml
  95. 66 0
      power-fitting/src/test/java/AlgTest.java

+ 3 - 3
gyee-sample-impala/src/main/java/com/gyee/impala/common/config/ThreadPoolConfig.java

@@ -16,13 +16,13 @@ public class ThreadPoolConfig {
      */
 
     /** 核心线程数(默认线程数) */
-    private static final int corePoolSize = 20;
+    private static final int corePoolSize = 10;
     /** 最大线程数 */
-    private static final int maxPoolSize = 40;
+    private static final int maxPoolSize = 20;
     /** 允许线程空闲时间(单位:默认为秒) */
     private static final int keepAliveTime = 60;
     /** 缓冲队列大小 */
-    private static final int queueCapacity = 200;
+    private static final int queueCapacity = 100;
     /** 允许等待最长时间 */
     private static final int awaitTime = 15;
     /** 线程池名前缀 */

+ 1 - 1
pom.xml

@@ -23,7 +23,7 @@
         <module>benchmarking-impala</module>
         <module>consumer</module>
         <module>gyee-sample-impala</module>
-        <module>power-fetting</module>
+        <module>power-fitting</module>
     </modules>
 
 

+ 0 - 26
power-fetting/src/main/java/com/gyee/power/fetting/BootApplication.java

@@ -1,26 +0,0 @@
-package com.gyee.power.fetting;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.cache.annotation.EnableCaching;
-import org.springframework.scheduling.annotation.EnableAsync;
-import org.springframework.scheduling.annotation.EnableScheduling;
-
-
-/**
- * 使用exclude = {DataSourceAutoConfiguration.class}
- * 禁用springboot默认加载的application.properties单数据源配置
- * 关闭springBoot关于mybatisPlus的一些自动注入
- */
-@EnableAsync
-@EnableCaching
-@EnableScheduling
-@SpringBootApplication
-public class BootApplication {
-
-    public static void main(String[] args) {
-        SpringApplication.run(BootApplication.class, args);
-    }
-
-}

+ 0 - 16
power-fetting/src/main/java/com/gyee/power/fetting/common/config/GyeeConfig.java

@@ -1,16 +0,0 @@
-package com.gyee.power.fetting.common.config;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.stereotype.Component;
-
-@Data
-@Component
-@ConfigurationProperties(prefix = "gyee")
-public class GyeeConfig {
-
-    /**数据适配器网址 **/
-    private String adapterUrl;
-
-
-}

+ 0 - 152
power-fetting/src/main/java/com/gyee/power/fetting/common/spring/InitialRunner.java

@@ -1,152 +0,0 @@
-package com.gyee.power.fetting.common.spring;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.CommandLineRunner;
-import org.springframework.core.annotation.Order;
-import org.springframework.stereotype.Component;
-
-import javax.annotation.Resource;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-/**
- * 服务启动前执行,进行全局变量初始化
- */
-@Component
-@Order(2)
-public class InitialRunner implements CommandLineRunner {
-
-//    @Resource
-//    private WindturbineService windturbineService;
-//    @Resource
-//    private WindpowerstationService windpowerstationService;
-//    @Autowired
-//    private KnowcategoryService faulttypeService;
-//    @Autowired
-//    private EquipmentmodelService modelService;
-//    @Autowired
-//    private DiagnosepointService diagnosepointService;
-//    @Autowired
-//    private DiagnosetrainhistoryService diagnosetrainhistoryService;
-//
-//    /**场站所有信息**/
-//    public static List<Windpowerstation> wpList = new ArrayList<>();
-//    /**场站的风机**/
-//    public static Map<String, List<Windturbine>> wpMap = new HashMap<>();
-//    /** <MHS_FDC, 麻黄山风电场> **/
-//    public static Map<String, String> stationMap = new HashMap<>();
-//    /** <麻黄山风电场, MHS_FDC> **/
-//    public static Map<String, String> stationenMap = new HashMap<>();
-//    /**所有的风机**/
-//    public static List<Windturbine> wtList = new ArrayList<>();
-//    /** <NG01_01, Windturbine> **/
-//    public static Map<String, Windturbine> wtMap = new HashMap<>();
-//    /**功率曲线预处理数据表格数据 key:time+wtId  value:当前风机的总条数 **/
-//    public static Map<String, Integer> scatterMap = new HashMap<>();
-//    /***故障  <FDJ,发电机故障>  类型*/
-//    public static Map<String, String> faultTypeMap = new HashMap<>();
-//    public static List<Knowcategory> faultTypeList = new ArrayList<>();
-//    /***scada预警  <FDJ,发电机>  类型*/
-//    public static Map<String, String> scadaWarnMap = new HashMap<>();
-//    public static List<Knowcategory> scadaWarnList = new ArrayList<>();
-//    /***自定义预警  <FDJ,发电机>  类型*/
-//    public static Map<String, String> customWarnMap = new HashMap<>();
-//    public static List<Knowcategory> customWarnList = new ArrayList<>();
-//    /** 设备型号配置 <UP82, Equipmentmodel> **/
-//    public static Map<String, Equipmentmodel> modelMap = new HashMap<>();
-//    /** 故障诊断 训练需要的测点 <NSS_FDC, UP82, Diagnosepoint></> **/
-//    public static Map<String, Map<String, List<Diagnosepoint>>> mapPoint = new HashMap<>();
-//
-//    /*** 故障训练历史模型 */
-//    public static Map<String, List<Diagnosetrainhistory>> historyModelMap = new HashMap<>();
-//    public static List<Diagnosetrainhistory> historyList = new ArrayList<>();
-
-
-
-    @Override
-    public void run(String... args){
-        System.out.println(">>>>>>>>>>>>>>>服务启动,正在缓存数据<<<<<<<<<<<<<<");
-
-//        cacheStation();
-//        cacheKnowCategory();
-//        cacheEquipmentModel();
-//        cacheDiagnosePoint();
-//        cacheHistory();
-
-        System.out.println(">>>>>>>>>>>>>>>数据缓存完成<<<<<<<<<<<<<<");
-    }
-
-    /**
-     * 缓存场站数据
-     * 数据新增或删除后需要更新,故每次清空
-     */
-//    public void cacheStation(){
-//        wpList.clear();
-//        wtList.clear();
-//        stationMap.clear();
-//        stationenMap.clear();
-//        wpMap.clear();
-//        wtMap.clear();
-//
-//        List<Windpowerstation> stations = windpowerstationService.getAll();
-//        wpList = stations;
-//        stations.stream().forEach(obj -> {
-//            List<Windturbine> wts = windturbineService.getWindTurbineId(obj.getId());
-//            stationMap.put(obj.getId(), obj.getName());
-//            stationenMap.put(obj.getName(), obj.getId());
-//            wpMap.put(obj.getId(), wts);
-//            wtList.addAll(wts);
-//            wts.stream().forEach(o -> wtMap.put(o.getId(), o));
-//        });
-//    }
-//
-//    /**
-//     * 缓存故障知识数据
-//     */
-//    public void cacheKnowCategory() {
-//        faultTypeList.clear();
-//        scadaWarnList.clear();
-//        customWarnList.clear();
-//        faultTypeMap.clear();
-//        scadaWarnMap.clear();
-//        customWarnMap.clear();
-//
-//        List<Knowcategory> faultType = faulttypeService.getAll();
-//        faultType.stream().forEach(obj -> {
-//            if (obj.getCategory().equals("GZ")) {
-//                faultTypeList.add(obj);
-//                faultTypeMap.put(obj.getCode().toUpperCase(), obj.getName());
-//            }
-//            else if (obj.getCategory().equals("SCADABJ")) {
-//                scadaWarnList.add(obj);
-//                scadaWarnMap.put(obj.getCode().toUpperCase(), obj.getName());
-//            }
-//            else if (obj.getCategory().equals("CUSTOMBJ")) {
-//                customWarnList.add(obj);
-//                customWarnMap.put(obj.getCode().toUpperCase(), obj.getName());
-//            }
-//        });
-//    }
-//
-//    public void cacheEquipmentModel() {
-//        modelMap.clear();
-//        List<Equipmentmodel> models = modelService.getAll();
-//        models.stream().forEach(obj -> modelMap.put(obj.getId(), obj));
-//    }
-//
-//    public void cacheDiagnosePoint(){
-//        mapPoint.clear();
-//        List<Diagnosepoint> points = diagnosepointService.getDiagnosepointList();
-//        mapPoint = points.stream().collect(Collectors.groupingBy(Diagnosepoint::getStationen, Collectors.groupingBy(Diagnosepoint::getModel)));
-//    }
-//
-//    public void cacheHistory(){
-//        historyModelMap.clear();
-//        historyList.clear();
-//        historyList = diagnosetrainhistoryService.getListAll();
-//        historyModelMap = historyList.stream().filter(h -> h.isEnable()).collect(Collectors.groupingBy(Diagnosetrainhistory::getModel));
-//    }
-}

+ 37 - 11
power-fetting/pom.xml

@@ -9,7 +9,7 @@
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
-    <artifactId>power-fetting</artifactId>
+    <artifactId>power-fitting</artifactId>
 
     <properties>
         <maven.compiler.source>8</maven.compiler.source>
@@ -19,26 +19,46 @@
     <dependencies>
         <dependency>
             <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-web</artifactId>
+            <artifactId>spring-boot-starter-websocket</artifactId>
         </dependency>
 
-        <!-- 模板引擎 -->
         <dependency>
-            <groupId>org.apache.velocity</groupId>
-            <artifactId>velocity-engine-core</artifactId>
-            <version>2.0</version>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid-spring-boot-starter</artifactId>
+            <version>1.2.11</version>
         </dependency>
 
         <dependency>
             <groupId>com.alibaba</groupId>
-            <artifactId>druid-spring-boot-starter</artifactId>
-            <version>1.2.11</version>
+            <artifactId>easyexcel</artifactId>
+            <version>3.1.1</version>
+        </dependency>
+
+<!--        <dependency>-->
+<!--            <groupId>com.oracle</groupId>-->
+<!--            <artifactId>ojdbc6</artifactId>-->
+<!--            <version>11.2.0.3</version>-->
+<!--        </dependency>-->
+
+        <!--oracle驱动-->
+        <!-- https://mvnrepository.com/artifact/com.oracle.database.jdbc/ojdbc8 -->
+        <dependency>
+            <groupId>com.oracle.database.jdbc</groupId>
+            <artifactId>ojdbc8</artifactId>
+            <version>19.7.0.0</version>
+        </dependency>
+
+        <!-- oracle字符集  https://mvnrepository.com/artifact/cn.easyproject/orai18n -->
+        <dependency>
+            <groupId>cn.easyproject</groupId>
+            <artifactId>orai18n</artifactId>
+            <version>12.1.0.2.0</version>
         </dependency>
 
         <dependency>
-            <groupId>com.oracle</groupId>
-            <artifactId>ojdbc6</artifactId>
-            <version>11.2.0.3</version>
+            <groupId>org.xerial</groupId>
+            <artifactId>sqlite-jdbc</artifactId>
+            <version>3.36.0.3</version>
         </dependency>
 
         <!--mybatis依赖-->
@@ -65,6 +85,12 @@
             <optional>true</optional>
         </dependency>
 
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-math3</artifactId>
+            <version>3.6.1</version>
+        </dependency>
+
 
         <!--http请求-->
         <dependency>

+ 11 - 11
power-fetting/src/main/java/com/gyee/power/fetting/MapperGenerator.java

@@ -1,4 +1,4 @@
-package com.gyee.power.fetting;
+package com.gyee.power.fitting;
 
 import com.baomidou.mybatisplus.annotation.DbType;
 import com.baomidou.mybatisplus.generator.AutoGenerator;
@@ -23,30 +23,30 @@ public class MapperGenerator {
     private static String canonicalPath = "";
 
     //基本包名
-    private static String basePackage = "com.gyee.impala";
+    private static String basePackage = "com.gyee.power.fetting";
     //作者
     private static String authorName = "chenmh";
     //要生成的表名
-    private static String[] tables = {"",};
+    private static String[] tables = {"WINDPOWERSTATION"};
     //table前缀
     private static String prefix = "";
 
     //数据库类型
-    private static DbType dbType = DbType.ORACLE;
+    private static DbType dbType = DbType.SQLITE;
     //数据库配置四要素
 //    private static String driverName = "com.mysql.cj.jdbc.Driver";
 //    private static String url = "jdbc:mysql://localhost:3306/gyee_sample_kudu?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=UTC";
 //    private static String username = "root";
 //    private static String password = "";
 
-    private static String driverName = "oracle.jdbc.driver.OracleDriver";
-//    private static String url = "jdbc:oracle:thin:@192.168.1.10:1521:ORCL";
-//    private static String username = "mis";
-//    private static String password = "GDnxXNY_2020#!";
+    private static String driverName = "org.sqlite.JDBC";
+    private static String url = "jdbc:sqlite::resource:DataMiningTools.db";
+    private static String username = null;
+    private static String password = null;
 
-    private static String url = "jdbc:oracle:thin:@192.168.1.105:1521:gdnxfd";
-    private static String username = "nxfdprod";
-    private static String password = "gdnxfd123";
+//    private static String url = "jdbc:oracle:thin:@192.168.1.105:1521:gdnxfd";
+//    private static String username = "nxfdprod";
+//    private static String password = "gdnxfd123";
 
 
     public static void main(String[] args) {

+ 47 - 0
power-fitting/src/main/java/com/gyee/power/fitting/PowerBootApplication.java

@@ -0,0 +1,47 @@
+package com.gyee.power.fitting;
+
+import com.gyee.power.fitting.common.config.GyeeConfig;
+import com.gyee.power.fitting.common.spring.SpringContextUtil;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+import java.io.File;
+
+
+/**
+ * 使用exclude = {DataSourceAutoConfiguration.class}
+ * 禁用springboot默认加载的application.properties单数据源配置
+ * 关闭springBoot关于mybatisPlus的一些自动注入
+ */
+@EnableAsync
+@EnableCaching
+@EnableScheduling
+@SpringBootApplication
+public class PowerBootApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(PowerBootApplication.class, args);
+
+        createFile();
+    }
+
+    private static void createFile(){
+        GyeeConfig bean = SpringContextUtil.getBean(GyeeConfig.class);
+        File f1 = new File(bean.getFilePathPrepare());
+        File f2 = new File(bean.getFilePathProcess());
+        File f3 = new File(bean.getFilePathFitting());
+        File f4 = new File(bean.getFilePathDownload());
+        if (!f1.exists())
+            f1.mkdirs();
+        if (!f2.exists())
+            f2.mkdirs();
+        if (!f3.exists())
+            f3.mkdirs();
+        if (!f4.exists())
+            f4.mkdirs();
+    }
+
+}

+ 39 - 0
power-fitting/src/main/java/com/gyee/power/fitting/common/alg/DBSCANPointALG.java

@@ -0,0 +1,39 @@
+package com.gyee.power.fitting.common.alg;
+
+import com.gyee.power.fitting.model.custom.PowerPointData;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 散点聚合
+ */
+public class DBSCANPointALG {
+
+    /**
+     * 功率曲线拟合 散点聚合
+     * @param points  散点list
+     * @param param   聚合参数  10
+     * @return
+     */
+    public static  Map<String, List<PowerPointData>> dbscan(List<PowerPointData> points, double param){
+        Map<String, List<PowerPointData>> map = new HashMap<>();
+
+        for (PowerPointData item : points){
+            double x = item.getSpeed() * param;
+            double y = item.getPower() / param;
+
+            String key = Math.round(x) +  String.valueOf(Math.round(y));
+
+            if (!map.containsKey(key)){
+                map.put(key, new ArrayList<>());
+            }
+            map.get(key).add(item);
+        }
+
+        return map;
+    }
+
+}

+ 465 - 0
power-fitting/src/main/java/com/gyee/power/fitting/common/alg/MpptFittingAlg.java

@@ -0,0 +1,465 @@
+package com.gyee.power.fitting.common.alg;
+
+//package easyexcel;
+
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+//绘制曲线需要
+import  java.awt.*;
+import  javax.swing.*;
+import  java.awt.geom.GeneralPath;
+
+
+import com.gyee.power.fitting.model.custom.LineCurveFitting;
+import com.gyee.power.fitting.model.custom.PointVo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import java.math.BigDecimal;
+
+import org.apache.commons.math3.fitting.PolynomialCurveFitter;
+import org.apache.commons.math3.fitting.WeightedObservedPoints;
+
+
+/**
+ * I-V曲线拟合算法
+ * 最小二乘法
+ */
+public class MpptFittingAlg {
+
+
+    public static List<PointVo> BuildLine_IV_LSC(double[] arrX, double[] arrY, int length, int dimension, double scale){
+
+        List<PointVo> points = new ArrayList<>();
+
+        if(arrX.length != arrY.length || arrX.length < 3){
+            return points;
+        }
+
+        double minValue = arrY[arrY.length - 1];
+        double maxValue = arrY[0];
+
+        double min = 0;
+        double max = 0;
+
+        double[] coefficient = MultiLine(arrX, arrY, length, dimension);
+
+        for (double i = arrX[arrX.length - 1]; i > arrX[0]; i -= scale) {
+            PointVo point = new PointVo();
+            point.setX(i);
+
+            for (int j = 0; j < coefficient.length; j++) {
+                if (j == 0) {
+                    point.setY(coefficient[j] * Math.pow(point.getX(), j));
+                } else {
+                    double temp = coefficient[j] *Math.pow(point.getX(), j);
+                    point.setY(point.getY() + temp);
+                }
+            }
+
+            if (point.getY() < minValue) {
+                point.setY(minValue);
+
+
+            }
+            if (point.getY() > maxValue) {
+                point.setY(maxValue);
+
+            }
+
+            if (point.getY() < min) {
+                min = point.getY();
+            }
+            if (point.getY() > max) {
+                max = point.getY();
+            }
+
+            points.add(point);
+        }
+        Builder(points, min, max);
+        System.out.print("X轴数据\n");
+        int len = points.size();
+        double[] aX = new double[len];
+        for (int i = len-1; i >0; i --){
+            aX[i] = points.get(i).getX();
+            System.out.print(aX[i]+",");
+            System.out.print("\n");
+        }
+        System.out.print("\n");
+        System.out.print("Y轴数据\n");
+
+        double[] aY = new double[len];
+        for(int i = len-1;i >0; i--){
+            aY[i] = points.get(i).getY();
+            System.out.print(aY[i]+",");
+            System.out.print("\n");
+        }
+
+        return points;
+    }
+    /**
+     * P-V曲线拟合算法
+     * 最小二乘法
+     */
+    public static List<PointVo> BuildLine_PV_LSC(double[] arrX, double[] arrY, int length, int dimension, double scale){
+
+        List<PointVo> points = new ArrayList<>();
+
+        if(arrX.length != arrY.length || arrX.length < 3){
+            return points;
+        }
+
+        double minValue = arrY[0];
+        double maxValue = 0;
+        for(int i = 0 ;i < arrY.length; i++){
+            double val = arrY[i];
+            if(val > maxValue){
+                maxValue = val;
+            }
+        }
+
+        double min = 0;
+        double max = 0;
+
+        double[] coefficient = MultiLine(arrX, arrY, length, dimension);
+
+        for (double i = arrX[arrX.length - 1]; i > arrX[0]; i -= scale) {
+            PointVo point = new PointVo();
+            point.setX(i);
+
+            for (int j = 0; j < coefficient.length; j++) {
+                if (j == 0) {
+                    point.setY(coefficient[j] * Math.pow(point.getX(), j));
+                } else {
+                    double temp = coefficient[j] *Math.pow(point.getX(), j);
+                    point.setY(point.getY() + temp);
+                }
+            }
+
+            if (point.getY() < minValue) {
+                point.setY(minValue);
+
+
+            }
+            if (point.getY() > maxValue) {
+                point.setY(maxValue);
+
+            }
+
+            if (point.getY() < min) {
+                min = point.getY();
+            }
+            if (point.getY() > max) {
+                max = point.getY();
+            }
+
+            points.add(point);
+        }
+        Builder(points, min, max);
+        System.out.print("X轴数据\n");
+        int len = points.size();
+        double[] aX = new double[len];
+        for (int i = len-1; i >0; i --){
+            aX[i] = points.get(i).getX();
+            System.out.print(aX[i]+",");
+            System.out.print("\n");
+        }
+        System.out.print("\n");
+        System.out.print("Y轴数据\n");
+
+        double[] aY = new double[len];
+        for (int i = len-1;i >0; i--){
+            aY[i] = points.get(i).getY();
+            System.out.print(aY[i]+",");
+            System.out.print("\n");
+        }
+
+        return points;
+    }
+
+    private static void Builder(List<PointVo> points, double min, double max) {
+        boolean b = false;
+        for (int i = 0; i < points.size(); i++) {
+            if (b) {
+                points.get(i).setY(max);
+            } else {
+                if (max == points.get(i).getY()) {
+                    b = true;
+                }
+            }
+
+        }
+        for (int i = points.size() - 1; i > -1; i--) {
+            if (!b) {
+                points.get(i).setY(min);
+            } else {
+                if (min == points.get(i).getY()) {
+                    b = false;
+                }
+            }
+        }
+    }
+
+    private static double[] MultiLine(double[] arrX, double[] arrY, int length,int dimension)
+    {
+        int n = dimension + 1;                  //dimension次方程需要求 dimension+1个 系数
+        double[][] Guass = new double[n][n + 1];      //高斯矩阵 例如:y=a0+a1*x+a2*x*x
+        for (int i = 0; i < n; i++) {
+            int j;
+            for (j = 0; j < n; j++) {
+                Guass[i][j] = SumArr(arrX, j + i, length);
+            }
+            Guass[i][j] = SumArr(arrX, i, arrY, 1, length);
+        }
+        return ComputGauss(Guass, n);
+    }
+
+    private static double SumArr(double[] arr, int n, int length) //求数组的元素的n次方的和
+    {
+        double s = 0;
+        for (int i = 0; i < length; i++) {
+            if (arr[i] != 0 || n != 0)
+                s = s + Math.pow(arr[i], n);
+            else
+                s = s + 1;
+        }
+        return s;
+    }
+
+    private static double SumArr(double[] arr1, int n1, double[] arr2, int n2, int length) {
+        double s = 0;
+        for (int i = 0; i < length; i++) {
+            if ((arr1[i] != 0 || n1 != 0) && (arr2[i] != 0 || n2 != 0))
+                s = s + Math.pow(arr1[i], n1) * Math.pow(arr2[i], n2);
+            else
+                s = s + 1;
+        }
+        return s;
+
+    }
+
+    private static double[] ComputGauss(double[][] Guass, int n) {
+        int i, j;
+        int k, m;
+        double temp;
+        double max;
+        double s;
+        double[] x = new double[n];
+        for (i = 0; i < n; i++) x[i] = 0.0;//初始化
+
+        for (j = 0; j < n; j++) {
+            max = 0;
+            k = j;
+            for (i = j; i < n; i++) {
+                if (Math.abs(Guass[i][j]) > max) {
+                    max = Guass[i][j];
+                    k = i;
+                }
+            }
+
+
+            if (k != j) {
+                for (m = j; m < n + 1; m++) {
+                    temp = Guass[j][m];
+                    Guass[j][m] = Guass[k][m];
+                    Guass[k][m] = temp;
+                }
+            }
+            if (0 == max) {
+                // "此线性方程为奇异线性方程"
+                return x;
+            }
+
+            for (i = j + 1; i < n; i++) {
+                s = Guass[i][j];
+                for (m = j; m < n + 1; m++) {
+                    Guass[i][m] = Guass[i][m] - Guass[j][m] * s / (Guass[j][j]);
+                }
+            }
+
+        }//结束for (j=0;j<n;j++)
+
+        for (i = n - 1; i >= 0; i--) {
+            s = 0;
+            for (j = i + 1; j < n; j++) {
+                s = s + Guass[i][j] * x[j];
+            }
+            x[i] = (Guass[i][n] - s) / Guass[i][i];
+        }
+        return x;
+    }//返回值是函数的系数
+
+
+
+    /**
+     * P-V曲线拟合算法
+     * 多项式曲线拟合
+     * @param arrX --功率(P)值
+     * @param arrY  --电流(I)值
+     * @param order 进行拟合的阶数
+     */
+
+    public static List<PointVo> BuildLine_PV_Poly(double[] arrX, double[] arrY, int order) {
+
+        double[] aX = new double[10];
+
+        double maxValue = 0;
+        for(int i = 0 ;i < arrX.length; i++){
+            double val = arrX[i];
+            if(val > maxValue){
+                maxValue = val;
+            }
+        }
+        double scale = 0.1;
+        int ylen = (int)(maxValue/scale);
+
+        double[] aY = new double[ylen];
+        for(int i = 0; i< arrX.length; i++){
+            aX[i] = arrX[i];
+        }
+        PointVo point = new PointVo();
+        List<PointVo> points = new ArrayList<>();
+
+        // N阶多项式会有N+1个系数,其中之一为常数项
+        double[] factor = new double[order + 1];
+        for(int index = 0; index < factor.length; index++) {
+            factor[index] = index + 1;
+        }
+        for(int index = 0; index < arrY.length; index++) {
+            arrX[index] = index * 0.00001;
+            arrY[index] = calcPoly(arrX[index], factor); // y = sum(x[n) * fact[n])
+
+        }
+
+        //调用将arrX和arrY序列中的数据逐个添加到观察点序列对象中
+        WeightedObservedPoints point1 = new WeightedObservedPoints();
+        for(int index = 0; index < arrX.length; index++) {
+            point1.add(arrX[index], arrY[index]);
+        }
+       // 创建PolynomialCurveFitter对象,需指定拟合多项式的阶数
+        PolynomialCurveFitter fitter = PolynomialCurveFitter.create(order);
+
+        List<Object> params = new ArrayList<Object>();
+        params.add(point1);
+       // 调用PolynomialCurveFitter的fit方法进行多项式曲线拟合
+        WeightedObservedPoints point2 = (WeightedObservedPoints)params.get(0);
+     //   拟合结果通过一个double数组返回,按元素顺序依次是常数项、一次项、二次项、……。
+        double[] result = fitter.fit(point2.toList());//例如 3,4,2,6 y=3*x^3+4*x^2+2*x+6
+
+       // String y = printPoly(result);
+        int k = result.length - 1;
+        System.out.print("X轴数据\n");
+        for(int i = 0;i < aX.length; i++){
+            System.out.print(aX[i]+",");
+            System.out.print("\n");
+        }
+        System.out.print("Y轴数据\n");
+
+        int q = 0;
+
+        for (double i = aX[aX.length - 1]; i > aX[0]; i -= scale) {
+
+            for (int j = 0; j < result.length; j++) {
+                if (j == 0) {
+                    aY[q] = result[k];
+                } else {
+                    aY[q] += Math.pow(arrX[q], j) * result[k - j];
+                }
+            }
+            System.out.print(aY[q]+",");
+            System.out.print("\n");
+            q++;
+        }
+        return points;
+    }
+
+    /**
+     * P-V曲线拟合算法
+     * 多项式曲线拟合
+     *
+     * @param arrX --电压(V)值
+     * @param arrY  --电流(I)值
+     * @param order 进行拟合的阶数
+     */
+
+    public static List<PointVo> BuildLine_IV_Poly(double[] arrX, double[] arrY, int order) {
+
+        PointVo point = new PointVo();
+        List<PointVo> points = new ArrayList<>();
+
+        // N阶多项式会有N+1个系数,其中之一为常数项
+        double[] factor = new double[order + 1];
+        for(int index = 0; index < factor.length; index++)
+        {
+            factor[index] = index + 1;
+        }
+        for(int index = 0; index < arrY.length; index++)
+        {
+            arrX[index] = index * 0.00001;
+            arrY[index] = calcPoly(arrX[index], factor); // y = sum(x[n) * fact[n])
+        }
+        //调用将arrX和arrY序列中的数据逐个添加到观察点序列对象中
+        WeightedObservedPoints point1 = new WeightedObservedPoints();
+        for(int index = 0; index < arrX.length; index++)
+        {
+            point1.add(arrX[index], arrY[index]);
+        }
+        // 创建PolynomialCurveFitter对象,需指定拟合多项式的阶数
+        PolynomialCurveFitter fitter = PolynomialCurveFitter.create(order);
+
+        List<Object> params = new ArrayList<Object>();
+        params.add(point1);
+        // 调用PolynomialCurveFitter的fit方法进行多项式曲线拟合
+        WeightedObservedPoints point2 = (WeightedObservedPoints)params.get(0);
+        //   拟合结果通过一个double数组返回,按元素顺序依次是常数项、一次项、二次项、……。
+        double[] result = fitter.fit(point2.toList());//例如 3,4,2,6 y=3*x^3+4*x^2+2*x+6
+
+        int k = result.length - 1;
+        for (int i = 0 ; i <= arrX[arrX.length - 1]; i++) {
+            for (int j = 0; j < result.length; j++) {
+                if (j == 0) {
+                    arrY[i] = result[k];
+                    break;
+                }
+                arrY[i] += Math.pow(arrX[i], j) * result[k - j];
+            }
+            point.setX(arrX[i]);
+            point.setX(arrY[i]);
+            points.add(point);
+        }
+
+        return points;
+    }
+
+    public static double calcPoly(double x, double[] factor)
+    {
+        double y = 0;
+        for(int deg = 0; deg < factor.length; deg++)
+        {
+            y += Math.pow(x, deg) * factor[deg];
+        }
+        return y;
+    }
+    public static String printPoly(double[] result) {
+
+        String polynomialString = "";
+        for (int i = 0; i < result.length; i++) {
+            if (i == 0) {
+                polynomialString += result[i];
+                break;
+            }
+            polynomialString += result[i] + "x^" + i + " ";
+        }
+        return polynomialString;
+    }
+}
+
+

+ 424 - 0
power-fitting/src/main/java/com/gyee/power/fitting/common/alg/PowerFittingALG.java

@@ -0,0 +1,424 @@
+package com.gyee.power.fitting.common.alg;
+
+import com.gyee.power.fitting.model.custom.LineCurveFitting;
+import com.gyee.power.fitting.model.custom.Point;
+import com.gyee.power.fitting.model.custom.PointVo;
+
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 功率曲线拟合算法
+ * 最小二乘法
+ */
+public class PowerFittingALG {
+
+    /**
+     * 功率曲线拟合
+     *
+     * @param arrX        风速数组
+     * @param arrY        功率数据
+     * @param length      点个数
+     * @param dimension   维度
+     * @param scale       精度  0.1  0.01
+     * @return
+     */
+    public static List<Point> buildLine(double[] arrX, double[] arrY, int length, int dimension, double scale) {
+
+        List<Point> points = new ArrayList<>();
+
+        if (arrX.length != arrY.length || arrX.length < 3) {
+            return points;
+        }
+
+        double minValue = arrY[0];
+        double maxValue = arrY[arrY.length - 1];
+
+        double min = 0;
+        double max = 0;
+
+        double[] coefficient = MultiLine(arrX, arrY, length, dimension);
+
+        for (double i = arrX[0]; i <= arrX[arrX.length - 1]; i += scale) {
+            Point point = new Point();
+            point.setX(i);
+
+
+            for (int j = 0; j < coefficient.length; j++) {
+                if (j == 0) {
+                    point.setY(coefficient[j] * Math.pow(point.getX(), j));
+                } else {
+                    double temp = coefficient[j] * Math.pow(point.getX(), j);
+                    point.setY(point.getY() + temp);
+                }
+
+            }
+            if (point.getY() < minValue) {
+                point.setY(minValue);
+
+            }
+            if (point.getY() > maxValue) {
+                point.setY(maxValue);
+            }
+
+            if (point.getY() < min) {
+                min = point.getY();
+            }
+            if (point.getY() > max) {
+                max = point.getY();
+            }
+
+            points.add(point);
+        }
+        Builder(points, min, max);
+        return points;
+    }
+
+    private static void Builder(List<Point> points, double min, double max) {
+        boolean b = false;
+        for (int i = 0; i < points.size(); i++) {
+            if (b) {
+                points.get(i).setY(max);
+            } else {
+                if (max == points.get(i).getY()) {
+                    b = true;
+                }
+            }
+
+        }
+
+        for (int i = points.size() - 1; i > -1; i--) {
+            if (!b) {
+                points.get(i).setY(min);
+            } else {
+                if (min == points.get(i).getY()) {
+                    b = false;
+                }
+            }
+
+        }
+    }
+
+
+    ///<summary>
+    ///用最小二乘法拟合二元多次曲线
+    ///</summary>
+    ///<param name="arrX">已知点的x坐标集合</param>
+    ///<param name="arrY">已知点的y坐标集合</param>
+    ///<param name="length">已知点的个数</param>
+    ///<param name="dimension">方程的最高次数</param>
+    //二元多次线性方程拟合曲线
+    private static double[] MultiLine(double[] arrX, double[] arrY, int length, int dimension) {
+        int n = dimension + 1;                  //dimension次方程需要求 dimension+1个 系数
+        double[][] Guass = new double[n][n + 1];      //高斯矩阵 例如:y=a0+a1*x+a2*x*x
+        for (int i = 0; i < n; i++) {
+            int j;
+            for (j = 0; j < n; j++) {
+                Guass[i][j] = SumArr(arrX, j + i, length);
+            }
+            Guass[i][j] = SumArr(arrX, i, arrY, 1, length);
+        }
+        return ComputGauss(Guass, n);
+    }
+
+    //求数组的元素的n次方的和
+    private static double SumArr(double[] arr, int n, int length) {
+        double s = 0;
+        for (int i = 0; i < length; i++) {
+            if (arr[i] != 0 || n != 0)
+                s = s + Math.pow(arr[i], n);
+            else
+                s = s + 1;
+        }
+        return s;
+    }
+
+    private static double SumArr(double[] arr1, int n1, double[] arr2, int n2, int length) {
+        double s = 0;
+        for (int i = 0; i < length; i++) {
+            if ((arr1[i] != 0 || n1 != 0) && (arr2[i] != 0 || n2 != 0))
+                s = s + Math.pow(arr1[i], n1) * Math.pow(arr2[i], n2);
+            else
+                s = s + 1;
+        }
+        return s;
+
+    }
+
+    private static double[] ComputGauss(double[][] Guass, int n) {
+        int i, j;
+        int k, m;
+        double temp;
+        double max;
+        double s;
+        double[] x = new double[n];
+        for (i = 0; i < n; i++) x[i] = 0.0;//初始化
+
+        for (j = 0; j < n; j++) {
+            max = 0;
+            k = j;
+            for (i = j; i < n; i++) {
+                if (Math.abs(Guass[i][j]) > max) {
+                    max = Guass[i][j];
+                    k = i;
+                }
+            }
+
+
+            if (k != j) {
+                for (m = j; m < n + 1; m++) {
+                    temp = Guass[j][m];
+                    Guass[j][m] = Guass[k][m];
+                    Guass[k][m] = temp;
+                }
+            }
+            if (0 == max) {
+                // "此线性方程为奇异线性方程" 
+                return x;
+            }
+
+            for (i = j + 1; i < n; i++) {
+                s = Guass[i][j];
+                for (m = j; m < n + 1; m++) {
+                    Guass[i][m] = Guass[i][m] - Guass[j][m] * s / (Guass[j][j]);
+                }
+            }
+
+        }//结束for (j=0;j<n;j++)
+
+        for (i = n - 1; i >= 0; i--) {
+            s = 0;
+            for (j = i + 1; j < n; j++) {
+                s = s + Guass[i][j] * x[j];
+            }
+            x[i] = (Guass[i][n] - s) / Guass[i][i];
+        }
+        return x;
+    }//返回值是函数的系数
+
+
+    /**
+     * 推力系数 CP 值
+     * @param sweptarea  扫风面积
+     * @param line
+     * @return
+     */
+    public static LineCurveFitting buildCp(Double sweptarea, LineCurveFitting line){
+        List<Point> cpValue = new ArrayList<>();
+
+        double kqmd = 1.225; //空气密度
+        double max = 0;
+        double cpAvg = 0;
+        double sum1 = 0;
+
+        for (int i = 0; i < line.getYLines().size(); i++)
+        {
+            Point point = line.getYLines().get(i);
+            double speed = point.getX();
+            double power = point.getY();
+            double k = 0.5 * kqmd * Math.pow(speed, 3) * sweptarea;
+            double result = 0;
+            if (k != 0)
+                result = power / k * 1000;
+            //s5.Points.AddXY(speed, result);
+            Point cppoint = new Point();
+            cppoint.setX(speed);
+            cppoint.setY(result);
+            cpValue.add(cppoint);
+
+            if (max < result)
+            {
+                max = result;
+            }
+
+            if (result > 0 && speed >= 3 && speed <= 25)
+            {
+                cpAvg += result;
+                sum1++;
+
+            }
+
+        }
+        if(sum1>0)
+            cpAvg /= sum1;
+
+        line.setCpValue(cpValue);
+        line.setCpAvg(cpAvg);
+
+        return line;
+    }
+
+
+    /**
+     * 静风频率计算
+     * @param list  风速数组
+     * @param speed 切入风速
+     * @return
+     */
+    public static double frequency(List<Double> list, double speed){
+        DecimalFormat df = new DecimalFormat("0.00");
+        int count = 0;
+        for (Double fs : list){
+            if (fs < speed)
+                count ++;
+        }
+        return list.size() > 0 ? Double.valueOf(df.format(((double)count / list.size() * 100 ))) : 0.0;
+    }
+
+
+    /**
+     * 曲线偏差率
+     * @param points1 风速功率数组
+     * @param points2
+     * @param maxp
+     * @return
+     */
+    public static double curveDeviationRatio(List<Point> points1, List<Point> points2, double maxp) {
+        double result = -0;
+        double pc = 0;
+        if (points1 != null && points1.size() > 0 && points2 != null && points2.size() > 0)
+        {
+            double count = 0;
+            double sum = 0;
+            for (Point point : points1){
+                List<Point> list = points2.stream().filter(it -> it.getX() == point.getX()).collect(Collectors.toList());
+                if (list.size() > 0){
+                    sum += Math.pow(point.getY() - list.get(0).getY(), 2);
+                    count ++;
+                    pc += point.getY() - list.get(0).getY();
+                }
+            }
+            sum = Math.sqrt(sum);
+            count = Math.sqrt(count);
+            maxp = maxp * count;
+            if (maxp != 0)
+                result = sum / maxp * 100;
+            if (pc < 0)
+                result = 0 - result;
+        }
+        return result;
+    }
+
+    /**
+     * 曲线偏差率  正负偏差
+     * @param points1 风速功率数组
+     * @param points2 风速功率数组(保证功率)
+     * @param maxp  区间内的最大保证功率
+     * @param speed 最小风速
+     * @return
+     */
+    public static double curveDeviationRatio2(List<Point> points1, List<Point> points2, double maxp, double speed) {
+        double minSpeed = speed;
+        double maxSpeed = minSpeed + 1;
+        double result = -0;
+        double pc = 0;
+        if (points1 != null && points1.size() > 0 && points2 != null && points2.size() > 0)
+        {
+            double count = 0;
+            double sum = 0;
+            for (Point point : points1){
+                List<Point> list = points2.stream().filter(it -> it.getX() == point.getX()).collect(Collectors.toList());
+                if (list.size() > 0 && list.get(0).getX() >= minSpeed && list.get(0).getX() < maxSpeed){
+                    sum += Math.pow(point.getY() - list.get(0).getY(), 2);
+                    count ++;
+                    pc += point.getY() - list.get(0).getY();
+                }
+            }
+            sum = Math.sqrt(sum);
+            count = Math.sqrt(count);
+            maxp = maxp * count;
+            if (maxp != 0)
+                result = sum / maxp * 100;
+            if (pc < 0)
+                result = 0 - result;
+        }
+        return result;
+    }
+
+
+    /**
+     * 对风偏差散点过滤  统计-50 到 50的
+     *
+     * @param list
+     * @return
+     */
+    public static List<Point> windDeviationScatter(List<PointVo> list){
+        //正负偏差 [-50,-49,....,0,1,2,.....50]
+        List<Point> ls = new ArrayList<>();
+        LinkedHashSet<Double> keys = new LinkedHashSet<>();  //散点太多去重
+        //次数统计
+        for (int i = 0; i < list.size(); i++){
+            PointVo item = list.get(i);
+            int ele = (int)Math.round((item.getX() + Math.abs(item.getY())));
+            int index = ele - 180;
+            if (index >= -50 && index <= 50) {
+                double key = Math.abs(index) + item.getS();
+                if (!keys.contains(key))
+                    ls.add(new Point(index, item.getS()));
+                keys.add(key);
+            }
+        }
+
+        return ls;
+    }
+
+
+    /**
+     * 对风偏差散点过滤  统计-50 到 50的
+     * 数据为二维数组 内层数组为3项. 第一项表示Y轴索引,  第二项代表X轴的索引 第三项代表value值.
+     * @param list
+     * @return
+     */
+    public static int[][] windDeviationPoint(List<PointVo> list){
+        //正负偏差 [-50,-49,....,0,1,2,.....50]
+        int[][] ints = new int[101][3];
+        //次数统计
+        for (int i = 0; i < list.size(); i++){
+            PointVo item = list.get(i);
+            int ele = (int)Math.round((item.getX() + Math.abs(item.getY())));
+            int index = ele - 180;
+            if (index >= -50 && index <= 50) {
+                int x = 50 - (index > 0 ? -index : Math.abs(index)); //[-50,-49,-48,....50]
+                int y = (int)Math.round(item.getS()) > 25 ? 25 : (int)Math.round(item.getS()); //风速[0,1,2,.....25]
+                ints[x][0] = y;
+                ints[x][1] = x;
+                ints[x][2] = 10;
+            }
+        }
+
+        return ints;
+    }
+
+
+    /**
+     * 对风偏差频次统计  统计-50 到 50
+     * @param list
+     * @return
+     */
+    public static int[] windDeviationRatio(List<PointVo> list){
+        int[] pc = new int[101];  //正负偏差 [-50,-49,....,0,1,2,.....50]
+        //次数统计
+        for (int i = 0; i < list.size(); i++){
+            PointVo item = list.get(i);
+            int ele = (int) (Math.abs(item.getX()) + Math.abs(item.getY()));
+            int index = ele - 180;
+            if (index >= -50 && index <= 50)
+                pc[50-(index > 0 ? -index : Math.abs(index))]++;
+        }
+
+        return pc;
+    }
+
+    public static void main(String[] args){
+        StringBuilder sb = new StringBuilder();
+        for (int i = -50; i < 101; i++){
+            sb.append("'").append(i).append("',");
+        }
+        System.out.println(sb.toString());
+    }
+
+}
+

+ 356 - 0
power-fitting/src/main/java/com/gyee/power/fitting/common/alg/PowerProcessALG.java

@@ -0,0 +1,356 @@
+package com.gyee.power.fitting.common.alg;
+
+import com.gyee.power.fitting.common.util.DateUtil;
+import com.gyee.power.fitting.model.custom.PowerPointData;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 数据预处理算法
+ */
+public class PowerProcessALG {
+
+
+    /**
+     * 数据预处理
+     *
+     * @param list   预处理的数据
+     * @param map    风速对应的保证功率
+     * @param maxs   最大风速
+     * @param mins   最小风速
+     * @param maxp   最大功率
+     * @param minp   最小功率
+     * @param isfbw  是否并网
+     * @param isfhl  是否合理值
+     * @param isbw   并网后10分钟
+     * @param istj   停机前10分钟
+     * @param isglpc 功率曲线偏差
+     * @param isqfh  是否欠符合
+     * @param qfhdj  欠符合等级
+     * @return
+     */
+    public static List<PowerPointData> dataProcess(List<PowerPointData> list, Map<Double, Double> map,
+                                                   Double maxs, Double mins, Double maxp, Double minp, Boolean isfbw,
+                                                   Boolean isfhl, Boolean isbw, Boolean istj, Boolean isglpc, Boolean isqfh, Integer qfhdj){
+        String timeBW = DateUtil.format(new Date(0), DateUtil.DATE_TIME_PATTERN);
+        List<PowerPointData> tempei = new ArrayList<>();
+        List<PowerPointData> tempqf = new ArrayList<>();
+
+        //TODO 数据过滤  // 0正常,1过滤掉
+        for (PowerPointData item : list) {
+            int filter = 0;
+            int fjstatus = 0;
+            if (timeBW == DateUtil.format(new Date(0), DateUtil.DATE_TIME_PATTERN)){
+                timeBW = item.getTime();
+            }
+            // 过滤非并网值  风机状态不等于2
+            if (filter == 0 && isfbw && item.getMxzt() != 2) {
+                filter = 1;
+                fjstatus = 1;
+                timeBW = item.getTime();
+            } else {
+                filter = 0;
+                fjstatus = 0;
+            }
+            // 按给定风速功率过滤
+            if (item.getSpeed() < mins || item.getSpeed() > maxs || item.getPower() < minp || item.getPower() > maxp) {
+                filter = 1;
+            }
+            // 过滤非合理值 并网状态下功率小于等于0
+            if (filter == 0 && isfhl && item.getPower() <= 0) {
+                filter = 1;
+            }
+            // 过滤非合理值 并网状态下功率小于等于0
+            if (filter == 0 && isfhl && item.getSpeed() < 3 && item.getPower() != 0) {
+                filter = 1;
+            }
+            // 过滤并网后十分钟
+            if (filter == 0 && isbw) {
+                if (DateUtil.getTimeDiff(item.getTime(), timeBW) <= 10)
+                    filter = 1;
+            }
+            // 过滤停机前十分钟
+            if (istj) {
+                if (fjstatus == 0) {
+                    if (tempei.size() > 0) {
+                        if (DateUtil.getTimeDiff(tempei.get(0).getTime(), timeBW) >= 10) {
+                            tempei.remove(0);
+                        }
+                    }
+                    tempei.add(item);
+                } else {
+                    for (PowerPointData temp : tempei) {
+                        temp.setFilter(1);
+                    }
+                    tempei.clear();
+                }
+            }
+            //欠发
+            if (filter == 0 && item.getSpeed() >= 6 && item.getSpeed() < 12.5 && isqfh && qfhdj < item.getQfzt()) {
+                filter = 1;
+                for (PowerPointData temp : tempqf) {
+                    temp.setFilter(1);
+                }
+            } else if (filter == 0 && item.getSpeed() >= 12.5 && isqfh && qfhdj < 1) {
+                filter = 1;
+                for (PowerPointData temp : tempqf) {
+                    temp.setFilter(1);
+                }
+            }
+            if (tempqf.size() > 0) {
+                if (DateUtil.getTimeDiff(tempqf.get(0).getTime(), item.getTime()) >= 5) {
+                    tempqf.remove(0);
+                }
+            }
+            tempqf.add(0, item);
+            item.setFilter(filter);
+
+            //功率曲线偏差
+            if (isglpc) {
+                if (map.containsKey(item.getSpeed())) {
+                    double power = map.get(item.getSpeed());  //不同风速对应的保证功率
+                    double maxPower = map.get(24.0);     //最大保证功率
+                    double k = item.getPower() / power;  //保证功率/实际功率   k:偏差百分比
+                    if (item.getPower() > 0) {
+                        if (k < 0.95 && maxPower <= power) {
+                            item.setFilter(1);
+                        }
+                        if (k < 0.9 && maxPower > power) {
+                            item.setFilter(1);
+                        }
+                        if (k < 0.85 && item.getSpeed() < 6 && item.getSpeed() > 4) {
+                            item.setFilter(1);
+                        }
+
+                        if (k < 0.9 && item.getSpeed() <= 4 && item.getSpeed() > 3.5) {
+                            item.setFilter(1);
+                        }
+                        if (k < 0.85 && item.getSpeed() <= 3.5 && item.getSpeed() > 3) {
+                            item.setFilter(1);
+                        }
+                        if (k < 0.4 && item.getSpeed() <= 3 && item.getSpeed() > 0) {
+                            item.setFilter(1);
+                        }
+                    }
+                }
+            }
+        }
+
+        return list;
+    }
+
+
+    /**
+     * 按照给定风俗功率过滤
+     * @param list
+     * @param maxs  最大风速
+     * @param mins  最小风速
+     * @param maxp  最大功率
+     * @param minp  最小风速
+     * @return
+     */
+    public static List<PowerPointData> dataProcessPS(List<PowerPointData> list, Double maxs, Double mins, Double maxp, Double minp){
+        //TODO 数据过滤  // 0正常,1过滤掉
+        for (PowerPointData item : list) {
+            int filter = 0;
+            // 按给定风速功率过滤
+            if (item.getSpeed() < mins || item.getSpeed() > maxs || item.getPower() < minp || item.getPower() > maxp) {
+                filter = 1;
+            }
+
+            item.setFilter(filter);
+        }
+
+        return list;
+    }
+
+    /**
+     * 过滤非并网值
+     * @param list
+     * @return
+     */
+    public static List<PowerPointData> dataProcessFBW(List<PowerPointData> list){
+        //TODO 数据过滤  // 0正常,1过滤掉
+        for (PowerPointData item : list) {
+            int filter = 0;
+            // 过滤非并网值  风机状态不等于2
+            if (filter == 0 && item.getMxzt() != 2)
+                filter = 1;
+
+            item.setFilter(filter);
+        }
+
+        return list;
+    }
+
+
+    /**
+     * 过滤非合理值
+     * @param list
+     * @return
+     */
+    public static List<PowerPointData> dataProcessFHLZ(List<PowerPointData> list){
+        //TODO 数据过滤  // 0正常,1过滤掉
+        for (PowerPointData item : list) {
+            int filter = 0;
+            // 过滤非合理值 并网状态下功率小于等于0
+            if (filter == 0 && item.getMxzt() != 2 && item.getPower() <= 0) {
+                filter = 1;
+            }
+
+            item.setFilter(filter);
+        }
+
+        return list;
+    }
+
+    /**
+     * 过滤并网后几分钟内数据
+     * @param list
+     * @param minute  分钟
+     * @return
+     */
+    public static List<PowerPointData> dataProcessBWH(List<PowerPointData> list, int minute){
+        String timeBW = DateUtil.format(new Date(0), DateUtil.DATE_TIME_PATTERN);
+        //TODO 数据过滤  // 0正常,1过滤掉
+        for (PowerPointData item : list) {
+            int filter = 0;
+            if (timeBW == DateUtil.format(new Date(0), DateUtil.DATE_TIME_PATTERN)){
+                timeBW = item.getTime();
+            }
+            // 过滤并网后十分钟
+            if (filter == 0 && DateUtil.getTimeDiff(item.getTime(), timeBW) <= minute){
+                filter = 1;
+            }
+
+            item.setFilter(filter);
+        }
+
+        return list;
+    }
+
+
+    /**
+     * 过滤停机前几分钟内数据
+     * @param list
+     * @param minute  分钟
+     * @return
+     */
+    public static List<PowerPointData> dataProcessTJQ(List<PowerPointData> list, int minute){
+        String timeBW = DateUtil.format(new Date(0), DateUtil.DATE_TIME_PATTERN);
+        List<PowerPointData> tempei = new ArrayList<>();
+
+        //TODO 数据过滤  // 0正常,1过滤掉
+        for (PowerPointData item : list) {
+            int filter = 0;
+            int fjstatus = 0;
+            if (timeBW == DateUtil.format(new Date(0), DateUtil.DATE_TIME_PATTERN)){
+                timeBW = item.getTime();
+            }
+            if (filter == 0 && item.getMxzt() != 2) {
+                filter = 1;
+                fjstatus = 1;
+                timeBW = item.getTime();
+            } else {
+                filter = 0;
+                fjstatus = 0;
+            }
+            // 过滤停机前十分钟
+            if (fjstatus == 0) {
+                if (tempei.size() > 0) {
+                    if (DateUtil.getTimeDiff(tempei.get(0).getTime(), timeBW) >= minute) {
+                        tempei.remove(0);
+                    }
+                }
+                tempei.add(item);
+            } else {
+                for (PowerPointData temp : tempei) {
+                    temp.setFilter(1);
+                }
+                tempei.clear();
+            }
+
+            item.setFilter(filter);
+        }
+
+        return list;
+    }
+
+    /**
+     * 曲线偏差率过滤
+     * @param list
+     * @param map  风速对应的保证功率
+     * @return
+     */
+    public static List<PowerPointData> dataProcessQXPC(List<PowerPointData> list, Map<Double, Double> map){
+        //TODO 数据过滤  // 0正常,1过滤掉
+        for (PowerPointData item : list) {
+            if (map.containsKey(item.getSpeed())) {
+                double power = map.get(item.getSpeed());  //不同风速对应的保证功率
+                double maxPower = map.get(24.0);     //最大保证功率
+                double k = item.getPower() / power;  //保证功率/实际功率   k:偏差百分比
+                if (item.getPower() > 0) {
+                    if (k < 0.95 && maxPower <= power) {
+                        item.setFilter(1);
+                    }
+                    if (k < 0.9 && maxPower > power) {
+                        item.setFilter(1);
+                    }
+                    if (k < 0.85 && item.getSpeed() < 6 && item.getSpeed() > 4) {
+                        item.setFilter(1);
+                    }
+
+                    if (k < 0.9 && item.getSpeed() <= 4 && item.getSpeed() > 3.5) {
+                        item.setFilter(1);
+                    }
+                    if (k < 0.85 && item.getSpeed() <= 3.5 && item.getSpeed() > 3) {
+                        item.setFilter(1);
+                    }
+                    if (k < 0.4 && item.getSpeed() <= 3 && item.getSpeed() > 0) {
+                        item.setFilter(1);
+                    }
+                }
+            }
+        }
+
+        return list;
+    }
+
+    /**
+     * 根据欠发过滤
+     * @param list
+     * @param qfhdj 签发等级
+     * @return
+     */
+    public static List<PowerPointData> dataProcessQF(List<PowerPointData> list, int qfhdj){
+        List<PowerPointData> tempqf = new ArrayList<>();
+        //TODO 数据过滤  // 0正常,1过滤掉
+        for (PowerPointData item : list) {
+            int filter = 0;
+            //欠发
+            if (filter == 0 && item.getSpeed() >= 6 && item.getSpeed() < 12.5 && qfhdj < item.getQfzt()) {
+                filter = 1;
+                for (PowerPointData temp : tempqf) {
+                    temp.setFilter(1);
+                }
+            } else if (filter == 0 && item.getSpeed() >= 12.5 && qfhdj < 1) {
+                filter = 1;
+                for (PowerPointData temp : tempqf) {
+                    temp.setFilter(1);
+                }
+            }
+            if (tempqf.size() > 0) {
+                if (DateUtil.getTimeDiff(tempqf.get(0).getTime(), item.getTime()) >= 5) {
+                    tempqf.remove(0);
+                }
+            }
+            tempqf.add(0, item);
+            item.setFilter(filter);
+        }
+
+        return list;
+    }
+}

+ 137 - 0
power-fitting/src/main/java/com/gyee/power/fitting/common/alg/WindDirectionALG.java

@@ -0,0 +1,137 @@
+package com.gyee.power.fitting.common.alg;
+
+
+import com.gyee.power.fitting.model.custom.PowerPointData;
+
+import java.util.*;
+
+
+/**
+ * 风向玫瑰图
+ * 风向频次玫瑰图
+ */
+public class WindDirectionALG {
+
+    /**
+     * 风速风向玫瑰图
+     * 风速:[0,2.5) [2.5,5) [5,7.5) [7.5,10) [10,12.5) [12.5,15) [15,17.5) [17.5,20) [20,22.5) [22.5,25) [25,inf)  11
+     * @param list
+     */
+    public static Object fxRoses(List<PowerPointData> list){
+        int[][] count = new int[11][16];
+
+        list.stream().forEach(item -> {
+            int fx = windFXAngle(item.getFX());
+            int speed = windSpeed(item.getSpeed());
+            count[speed][fx] = 1;
+        });
+
+        return count;
+    }
+
+
+    /**
+     * 风向频次玫瑰图
+     * 风速:[0,2.5) [2.5,5) [5,7.5) [7.5,10) [10,12.5) [12.5,15) [15,17.5) [17.5,20) [20,22.5) [22.5,25) [25,inf)  11
+     * @param list
+     */
+    public static int[][] fxCountRoses(List<PowerPointData> list){
+        int[][] count = new int[11][16];
+        list.stream().sorted(Comparator.comparing(PowerPointData::getSpeed)).forEach(item -> {
+            int fx = windFXAngle(item.getFX());
+            int speed = windSpeed(item.getSpeed());
+            count[speed][fx] ++;
+        });
+
+        return count;
+    }
+
+
+    /**
+     * 风向频次雷达图
+     * @param list
+     * @return
+     */
+    public static int[] fxRadarRoses(List<PowerPointData> list){
+        int[] count = new int[16];
+        list.stream().sorted(Comparator.comparing(PowerPointData::getSpeed)).forEach(item -> {
+            int fx = windFXAngle(item.getFX());
+            count[fx] ++;
+        });
+
+        return count;
+    }
+
+
+    /**
+     * 风向划分
+     * 0:0-22.5
+     * 1:22.5-45
+     * 2:90-135
+     * .。。。。。。
+     * @param fx
+     * @return params: 0,1,2。。。。。15
+     */
+    private static int windFXAngle(double fx){
+        int split = 16;  //风向分为16个角度
+        double angle = (double)360 / split;
+        int index = (int) (fx / angle);
+        return index;
+    }
+
+    /**
+     * 风速区域划分
+     * @param speed
+     * @return
+     */
+    private static int windSpeed(double speed){
+        if (speed < 2.5)
+            return 0;
+        else if (speed < 5)
+            return 1;
+        else if (speed < 7.5)
+            return 2;
+        else if (speed < 10)
+            return 3;
+        else if (speed < 12.5)
+            return 4;
+        else if (speed < 15)
+            return 5;
+        else if (speed < 17.5)
+            return 6;
+        else if (speed < 20)
+            return 7;
+        else if (speed < 22.5)
+            return 8;
+        else if (speed < 25)
+            return 9;
+        else
+            return 10;
+    }
+
+
+    /**
+     * 数据聚合  间隔10
+     * @param list
+     * @return
+     */
+    private static Object arrayDistinct(List<List<Double>> list){
+        for (List<Double> item : list){
+            List<Double> lt = new ArrayList<>();
+            LinkedHashSet<Integer> ls = new LinkedHashSet<>();
+            item.forEach(ele -> {
+                if (ele == null)
+                    return;
+                int v = (int) (ele / 10);
+                if (!ls.contains(v))
+                    lt.add(ele);
+
+                ls.add(v);
+            });
+            item.clear();
+            item.addAll(lt);
+        }
+
+        return list;
+    }
+}

+ 1 - 1
power-fetting/src/main/java/com/gyee/power/fetting/common/base/ExcludeQueryWrapper.java

@@ -1,4 +1,4 @@
-package com.gyee.power.fetting.common.base;
+package com.gyee.power.fitting.common.base;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;

+ 1 - 1
power-fetting/src/main/java/com/gyee/power/fetting/common/config/CorsConfig.java

@@ -1,4 +1,4 @@
-package com.gyee.power.fetting.common.config;
+package com.gyee.power.fitting.common.config;
 
 import org.springframework.context.annotation.Configuration;
 import org.springframework.web.servlet.config.annotation.CorsRegistry;

+ 1 - 8
power-fetting/src/main/java/com/gyee/power/fetting/common/config/datasource/DataSourceConfig.java

@@ -1,16 +1,9 @@
-package com.gyee.power.fetting.common.config.datasource;
+package com.gyee.power.fitting.common.config;
 
 import com.alibaba.druid.pool.DruidDataSource;
-import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
-import org.apache.ibatis.session.SqlSessionFactory;
-import org.mybatis.spring.SqlSessionTemplate;
-import org.mybatis.spring.annotation.MapperScan;
-import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.boot.jdbc.DataSourceBuilder;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
 
 import javax.sql.DataSource;
 

+ 68 - 0
power-fitting/src/main/java/com/gyee/power/fitting/common/config/GyeeConfig.java

@@ -0,0 +1,68 @@
+package com.gyee.power.fitting.common.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.system.ApplicationHome;
+import org.springframework.stereotype.Component;
+
+import java.io.File;
+import java.util.List;
+
+@Data
+@Component
+@ConfigurationProperties(prefix = "gyee")
+public class GyeeConfig {
+
+    public File jarF = null;
+    {
+        ApplicationHome h = new ApplicationHome(getClass());
+        jarF = h.getSource();
+    }
+
+    /** 数据适配器网址 **/
+    private String adapterUrl;
+    /** 数据准备保存路径(原始数据) **/
+    private String filePathPrepare;
+    /** 数据处理保存路径(处理后的数据) **/
+    private String filePathProcess;
+    /** 数据拟合保存路径(拟合后的数据) **/
+    private String filePathFitting;
+    /** 数据压缩下载 **/
+    private String filePathDownload;
+    /** 功率曲线拟合测点 **/
+    private List<String> points;
+    /** 适配器读取数据等间隔时间 **/
+    private Integer interval;
+
+    public String getFilePathPrepare() {
+        return jarF.getParentFile().getAbsolutePath() + "\\" + filePathPrepare;
+    }
+
+    public void setFilePathPrepare(String filePathPrepare) {
+        this.filePathPrepare = filePathPrepare;
+    }
+
+    public String getFilePathProcess() {
+        return jarF.getParentFile().getAbsolutePath() + "\\" + filePathProcess;
+    }
+
+    public void setFilePathProcess(String filePathProcess) {
+        this.filePathProcess = filePathProcess;
+    }
+
+    public String getFilePathFitting() {
+        return jarF.getParentFile().getAbsolutePath() + "\\" + filePathFitting;
+    }
+
+    public void setFilePathFitting(String filePathFitting) {
+        this.filePathFitting = filePathFitting;
+    }
+
+    public String getFilePathDownload() {
+        return jarF.getParentFile().getAbsolutePath() + "\\" + filePathDownload;
+    }
+
+    public void setFilePathDownload(String filePathDownload) {
+        this.filePathDownload = filePathDownload;
+    }
+}

+ 50 - 0
power-fitting/src/main/java/com/gyee/power/fitting/common/config/ThreadPoolConfig.java

@@ -0,0 +1,50 @@
+package com.gyee.power.fitting.common.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.ThreadPoolExecutor;
+
+
+@Configuration
+public class ThreadPoolConfig {
+    /**
+     *   默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,
+     *	当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中;
+     *  当队列满了,就继续创建线程,当线程数量大于等于maxPoolSize后,开始使用拒绝策略拒绝
+     */
+
+    /** 核心线程数(默认线程数) */
+    private static final int corePoolSize = 10;
+    /** 最大线程数 */
+    private static final int maxPoolSize = 20;
+    /** 允许线程空闲时间(单位:默认为秒) */
+    private static final int keepAliveTime = 60;
+    /** 缓冲队列大小 */
+    private static final int queueCapacity = 100;
+    /** 允许等待最长时间 */
+    private static final int awaitTime = 15;
+    /** 线程池名前缀 */
+    private static final String threadNamePrefix = "GYEE-Thread-";
+
+
+    @Bean
+    public ThreadPoolTaskExecutor taskExecutor(){
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        executor.setCorePoolSize(corePoolSize);
+        executor.setMaxPoolSize(maxPoolSize);
+        executor.setQueueCapacity(queueCapacity);
+        executor.setKeepAliveSeconds(keepAliveTime);
+        executor.setThreadNamePrefix(threadNamePrefix);
+        executor.setAwaitTerminationSeconds(awaitTime);
+
+        // 线程池对拒绝任务的处理策略
+        // CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务
+        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+        // 初始化
+        executor.initialize();
+        return executor;
+    }
+
+}

+ 20 - 0
power-fitting/src/main/java/com/gyee/power/fitting/common/config/WebSocketConfig.java

@@ -0,0 +1,20 @@
+package com.gyee.power.fitting.common.config;
+
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+
+/**
+ * 开启 WebSocket 支持
+ **/
+@Configuration
+public class WebSocketConfig {
+
+    @Bean
+    public ServerEndpointExporter serverEndpointExporter() {
+        System.out.println("开启websocket支持。。。。。");
+        return new ServerEndpointExporter();
+    }
+
+}

+ 39 - 0
power-fitting/src/main/java/com/gyee/power/fitting/common/constants/Constants.java

@@ -0,0 +1,39 @@
+package com.gyee.power.fitting.common.constants;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Constants {
+
+    // 数据准备  标记
+    public static final String DATA_PREPARE = "prepare";
+
+    // 数据处理完  标记
+    public static final String DATA_PROCESS = "process";
+
+    // 数据处理完  标记
+    public static final String DATA_FITTING = "fitting";
+
+    // 数据表头
+    public static final List<String> TABLE_TITLE = new ArrayList<>();
+
+    // 拟合后的数据表头
+    public static final List<String> FITTING_TITLE = new ArrayList<>();
+
+
+    static {
+        TABLE_TITLE.add("时间");
+        TABLE_TITLE.add("风机功率");
+        TABLE_TITLE.add("风机风速");
+        TABLE_TITLE.add("发电机转速");
+        TABLE_TITLE.add("风机状态");
+        TABLE_TITLE.add("风机电量");
+        TABLE_TITLE.add("欠发状态");
+        TABLE_TITLE.add("风向");
+        TABLE_TITLE.add("对风角度");
+
+        FITTING_TITLE.add("风速");
+        FITTING_TITLE.add("拟合功率");
+        FITTING_TITLE.add("Cp值");
+    }
+}

+ 3 - 3
power-fetting/src/main/java/com/gyee/power/fetting/common/exception/AdviceException.java

@@ -1,8 +1,8 @@
-package com.gyee.power.fetting.common.exception;
+package com.gyee.power.fitting.common.exception;
 
 import com.alibaba.fastjson.JSONObject;
-import com.gyee.power.fetting.common.result.JsonResult;
-import com.gyee.power.fetting.common.result.ResultCode;
+import com.gyee.power.fitting.common.result.JsonResult;
+import com.gyee.power.fitting.common.result.ResultCode;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.bind.annotation.RestControllerAdvice;

+ 2 - 2
power-fetting/src/main/java/com/gyee/power/fetting/common/exception/CustomException.java

@@ -1,6 +1,6 @@
-package com.gyee.power.fetting.common.exception;
+package com.gyee.power.fitting.common.exception;
 
-import com.gyee.power.fetting.common.result.ResultCode;
+import com.gyee.power.fitting.common.result.ResultCode;
 import lombok.Data;
 
 @Data

+ 3 - 3
power-fetting/src/main/java/com/gyee/power/fetting/common/feign/IAdapterService.java

@@ -1,7 +1,7 @@
-package com.gyee.power.fetting.common.feign;
+package com.gyee.power.fitting.common.feign;
 
 import com.alibaba.fastjson.JSONObject;
-import com.gyee.power.fetting.model.custom.TsDoubleData;
+import com.gyee.power.fitting.model.custom.TsDoubleData;
 import feign.Headers;
 import feign.Param;
 import feign.RequestLine;
@@ -19,6 +19,6 @@ public interface IAdapterService {
 
     @Headers({"Content-Type: application/json", "Accept: application/json"})
     @RequestLine("GET /ts/history/snap?tagName={tagName}&startTs={startTs}&endTs={endTs}&interval={interval}")
-    List<TsDoubleData> getHistorySnapAI(@Param(value = "tagName") String tagName, @Param(value = "startTs") long startTs,
+    List<TsDoubleData> getHistorySnap(@Param(value = "tagName") String tagName, @Param(value = "startTs") long startTs,
                                         @Param(value = "endTs") long endTs, @Param(value = "interval") Integer interval);
 }

+ 2 - 2
power-fetting/src/main/java/com/gyee/power/fetting/common/feign/RemoteServiceBuilder.java

@@ -1,6 +1,6 @@
-package com.gyee.power.fetting.common.feign;
+package com.gyee.power.fitting.common.feign;
 
-import com.gyee.power.fetting.common.config.GyeeConfig;
+import com.gyee.power.fitting.common.config.GyeeConfig;
 import feign.Feign;
 import feign.Request;
 import feign.Retryer;

+ 1 - 1
power-fetting/src/main/java/com/gyee/power/fetting/common/result/JsonResult.java

@@ -1,4 +1,4 @@
-package com.gyee.power.fetting.common.result;
+package com.gyee.power.fitting.common.result;
 
 import com.alibaba.fastjson.JSONObject;
 import lombok.Data;

+ 2 - 1
power-fetting/src/main/java/com/gyee/power/fetting/common/result/ResultCode.java

@@ -1,4 +1,4 @@
-package com.gyee.power.fetting.common.result;
+package com.gyee.power.fitting.common.result;
 
 /*
  * #1001~1999 区间表示参数错误
@@ -9,6 +9,7 @@ package com.gyee.power.fetting.common.result;
 public enum ResultCode {
     /* 成功 */
     SUCCESS(200, "成功"),
+    SUCCESS_DATA_PREPARE(200, "数据已提交,稍后查看"),
 
     /* 默认失败 */
     ERROR(4000, "失败"),

+ 1 - 1
power-fetting/src/main/java/com/gyee/power/fetting/common/spring/ExitDisposable.java

@@ -1,4 +1,4 @@
-package com.gyee.power.fetting.common.spring;
+package com.gyee.power.fitting.common.spring;
 
 import org.springframework.beans.factory.DisposableBean;
 import org.springframework.boot.ExitCodeGenerator;

+ 125 - 0
power-fitting/src/main/java/com/gyee/power/fitting/common/spring/InitialRunner.java

@@ -0,0 +1,125 @@
+package com.gyee.power.fitting.common.spring;
+
+import com.gyee.power.fitting.common.config.GyeeConfig;
+import com.gyee.power.fitting.model.*;
+import com.gyee.power.fitting.service.*;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 服务启动前执行,进行全局变量初始化
+ */
+@Slf4j
+@Component
+@Order(1)
+public class InitialRunner implements CommandLineRunner {
+
+    @Autowired
+    GyeeConfig config;
+    @Resource
+    private WindturbineService windturbineService;
+    @Resource
+    private WindpowerstationService windpowerstationService;
+    @Resource
+    private Windturbinetestingpointai2Service pointService;
+    @Resource
+    private EquipmentmodelService equipmentmodelService;
+    @Resource
+    private ModelpowerService modelpowerService;
+    @Resource
+    private ModelpowerdetailsService modelpowerdetailsService;
+
+
+    /**场站所有信息**/
+    public static List<Windpowerstation> wpList = new ArrayList<>();
+    /** <MHS_FDC, 麻黄山风电场> **/
+    public static Map<String, String> stationMap = new HashMap<>();
+
+    /**所有的风机**/
+    public static List<Windturbine> wtList = new ArrayList<>();
+    /** key:wtId NG01_01 **/
+    public static Map<String, Windturbine> wtMap = new HashMap<>();
+    /**场站的风机**/
+    public static Map<String, List<Windturbine>> wpMap = new HashMap<>();
+
+    public static Map<String, List<Windturbinetestingpointai2>> pointMap = new HashMap<>();
+
+    /**所有设备型号**/
+    public static List<Equipmentmodel> equipmentList = new ArrayList<>();
+    public static Map<String, Equipmentmodel> equipmentMap = new HashMap<>();
+
+    /**功率曲线拟合的风速功率点**/
+    /** key: model  UP82 **/
+    public static Map<String, List<Modelpower>> modelPowerMap = new HashMap<>();
+    /** key: model  UP82 **/
+    public static Map<String, List<Modelpowerdetails>> modelPowerDetailMap = new HashMap<>();
+
+
+    @Override
+    public void run(String... args){
+        System.out.println(">>>>>>>>>>>>>>>服务启动,正在缓存数据<<<<<<<<<<<<<<");
+
+        cacheStation();
+        cachePoints();
+        cacheEquipment();
+        cacheModelPower();
+
+        System.out.println(">>>>>>>>>>>>>>>数据缓存完成<<<<<<<<<<<<<<");
+    }
+
+    /**
+     * 缓存场站、风机数据
+     * 数据新增或删除后需要更新,故每次清空
+     */
+    public void cacheStation(){
+        List<Windpowerstation> stations = windpowerstationService.selectList();
+        wpList = stations.stream().filter(f -> f.getId().contains("FDC")).collect(Collectors.toList());
+        wpList.stream().forEach(obj -> {
+            List<Windturbine> wts = windturbineService.selectList(obj.getId());
+            stationMap.put(obj.getId(), obj.getName());
+            wpMap.put(obj.getId(), wts);
+            wtList.addAll(wts);
+
+            wts.stream().forEach(u -> wtMap.put(u.getId(), u));
+        });
+    }
+
+    /**
+     * 缓存测点数据
+     */
+    private void cachePoints() {
+        List<Windturbinetestingpointai2> list = new ArrayList<>();
+        wpList.stream().forEach(d -> list.addAll(pointService.selectList(d.getId(), config.getPoints())));
+        pointMap.putAll(list.stream().collect(Collectors.groupingBy(u -> u.getWindturbineid())));
+        System.out.println("cachePoints: " + pointMap.size());
+        if (pointMap.size() == 0)
+            log.error("cachePoints", "测点数据缓存失败");
+    }
+
+    /**
+     * 缓存设备型号
+     */
+    private void cacheEquipment() {
+        equipmentList.addAll(equipmentmodelService.selectList());
+        for (Equipmentmodel eq : equipmentList)
+            equipmentMap.put(eq.getId(), eq);
+    }
+
+    private void cacheModelPower() {
+        List<Modelpower> lsMP = modelpowerService.selectList();
+        List<Modelpowerdetails> lsMPD = modelpowerdetailsService.selectList();
+        modelPowerMap.putAll(lsMP.stream().collect(Collectors.groupingBy(u -> u.getModelid())));
+        modelPowerDetailMap.putAll(lsMPD.stream().collect(Collectors.groupingBy(u -> u.getModelid())));
+    }
+
+}

+ 1 - 1
power-fetting/src/main/java/com/gyee/power/fetting/common/spring/SpringContextUtil.java

@@ -1,4 +1,4 @@
-package com.gyee.power.fetting.common.spring;
+package com.gyee.power.fitting.common.spring;
 
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.DisposableBean;

+ 1 - 1
power-fetting/src/main/java/com/gyee/power/fetting/common/util/Base64Util.java

@@ -1,4 +1,4 @@
-package com.gyee.power.fetting.common.util;
+package com.gyee.power.fitting.common.util;
 
 import java.io.UnsupportedEncodingException;
 import java.util.Base64;

+ 1 - 1
power-fetting/src/main/java/com/gyee/power/fetting/common/util/CollectUtil.java

@@ -1,4 +1,4 @@
-package com.gyee.power.fetting.common.util;
+package com.gyee.power.fitting.common.util;
 
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;

+ 21 - 3
power-fetting/src/main/java/com/gyee/power/fetting/common/util/DateUtil.java

@@ -1,4 +1,4 @@
-package com.gyee.power.fetting.common.util;
+package com.gyee.power.fitting.common.util;
 
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.time.DateFormatUtils;
@@ -152,6 +152,8 @@ public class DateUtil extends DateUtils {
 
     public static String YYYY_MM = "yyyy-MM";
 
+    public static String YYYY_MM_DD_CHN = "yyyy年MM月dd日";
+
     public static String YYYY_MM_DD = "yyyy-MM-dd";
 
     public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
@@ -181,7 +183,7 @@ public class DateUtil extends DateUtils {
         return dateTimeNow(YYYY_MM_DD);
     }
 
-    public static final String getTime() {
+    public static final String getTimeDiff() {
         return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
     }
 
@@ -488,9 +490,25 @@ public class DateUtil extends DateUtils {
         return utcSDF;
     }
 
+    // 获取两个时间相差分钟数
+    public static int getTimeDiff(String oldTime, String newTime) {
+        int diff = 0;
+        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        long NTime = 0;
+        long OTime = 0;
+        try {
+            NTime = df.parse(newTime).getTime();
+            //从对象中拿到时间
+            OTime = df.parse(oldTime).getTime();
+            diff = (int) (Math.abs((NTime-OTime))/1000/60);
+        } catch (ParseException e) {
+        }
+
+        return diff;
+    }
+
 
     public static void main(String[] args) {
-        System.out.println(getCurrentDate());
         System.out.println(getPreviousDate(3 * 360 * 24));
         System.out.println(covertDateTimestamp("2021-12-30 00:00:00"));
     }

+ 107 - 10
power-fetting/src/main/java/com/gyee/power/fetting/common/util/FileUtil.java

@@ -1,13 +1,15 @@
-package com.gyee.power.fetting.common.util;
+package com.gyee.power.fitting.common.util;
 
-import com.gyee.power.fetting.common.exception.CustomException;
-import com.gyee.power.fetting.common.result.ResultCode;
 import lombok.extern.slf4j.Slf4j;
 
 import javax.servlet.http.HttpServletResponse;
 import java.io.*;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
 
 @Slf4j
 public class FileUtil {
@@ -18,7 +20,7 @@ public class FileUtil {
      * @param fileName
      * @param content
      */
-    public static void writeFile(String fileName, String content) {
+    public static boolean writeFile(String fileName, String content) {
         BufferedWriter bw = null;
 
         try {
@@ -29,15 +31,16 @@ public class FileUtil {
             bw = new BufferedWriter(new FileWriter(file, true));
 
             String[] list = content.split("\n");
-            for(int i = 0; i < list.length; i++){
+            for (int i = 0; i < list.length; i++) {
                 bw.write(list[i]);
                 bw.write("\n");
-                if (i % 500 == 0)
+                if (i % 1000 == 0)
                     bw.flush();
             }
             bw.flush();
         } catch (Exception e) {
-            log.error(e.getMessage());
+            log.error("writePowerData", e);
+            return false;
         } finally {
             try {
                 bw.close();
@@ -45,6 +48,8 @@ public class FileUtil {
                 e.printStackTrace();
             }
         }
+
+        return true;
     }
 
     /**
@@ -97,6 +102,45 @@ public class FileUtil {
 
     }
 
+    /**
+     * 读取文件
+     *
+     * @param fileName
+     * @param isAll    是否读取全部数据
+     * @return
+     */
+    public static List<String> readFile(String fileName, boolean isAll) {
+        List<String> list = new ArrayList<>();
+
+        File file = new File(fileName);
+        BufferedReader reader = null;
+        try {
+            reader = new BufferedReader(new FileReader(file));
+            String content = null;
+            int line = 0;
+            // 一次读入一行,直到读入null为文件结束
+            while ((content = reader.readLine()) != null) {
+                // 显示行号
+                list.add(content);
+                line++;
+                if (!isAll && line == 300)
+                    break;
+            }
+            reader.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            if (reader != null) {
+                try {
+                    reader.close();
+                } catch (IOException e1) {
+                }
+            }
+        }
+
+        return list;
+    }
+
 
     /**
      * 加载文件
@@ -128,10 +172,8 @@ public class FileUtil {
                 os.write(buffer, 0, i);
                 i = bis.read(buffer);
             }
-        } catch (FileNotFoundException e) {
-            throw new CustomException(ResultCode.ERROR_FILE_NO);
         } catch (Exception e) {
-            throw new CustomException(ResultCode.ERROR);
+            log.error("FileUtil--download", e);
         } finally {
             if (bis != null) {
                 try {
@@ -149,4 +191,59 @@ public class FileUtil {
             }
         }
     }
+
+
+    /**
+     * @describe 压缩多个文件
+     * @author zfc
+     */
+    public static String zipFiles(List<File> srcFiles, File zipFile) {
+        // 判断压缩后的文件存在不,不存在则创建
+        if (!zipFile.exists()) {
+            try {
+                zipFile.createNewFile();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        // 创建 FileOutputStream 对象
+        FileOutputStream fileOutputStream = null;
+        // 创建 ZipOutputStream
+        ZipOutputStream zipOutputStream = null;
+        // 创建 FileInputStream 对象
+        FileInputStream fileInputStream = null;
+
+        try {
+            // 实例化 FileOutputStream 对象
+            fileOutputStream = new FileOutputStream(zipFile);
+            // 实例化 ZipOutputStream 对象
+            zipOutputStream = new ZipOutputStream(fileOutputStream);
+            // 创建 ZipEntry 对象
+            ZipEntry zipEntry = null;
+            // 遍历源文件数组
+            for (int i = 0; i < srcFiles.size(); i++) {
+                // 将源文件数组中的当前文件读入 FileInputStream 流中
+                fileInputStream = new FileInputStream(srcFiles.get(i));
+                // 实例化 ZipEntry 对象,源文件数组中的当前文件
+                zipEntry = new ZipEntry(srcFiles.get(i).getName());
+                zipOutputStream.putNextEntry(zipEntry);
+                // 该变量记录每次真正读的字节个数
+                int len;
+                // 定义每次读取的字节数组
+                byte[] buffer = new byte[1024];
+                while ((len = fileInputStream.read(buffer)) > 0) {
+                    zipOutputStream.write(buffer, 0, len);
+                }
+            }
+            zipOutputStream.closeEntry();
+            zipOutputStream.close();
+            fileInputStream.close();
+            fileOutputStream.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return zipFile.getAbsolutePath();
+    }
+
 }

+ 1 - 1
power-fetting/src/main/java/com/gyee/power/fetting/common/util/JudeSystem.java

@@ -1,4 +1,4 @@
-package com.gyee.power.fetting.common.util;
+package com.gyee.power.fitting.common.util;
 
 
 /**

+ 20 - 1
power-fetting/src/main/java/com/gyee/power/fetting/common/util/NumberUtil.java

@@ -1,4 +1,4 @@
-package com.gyee.power.fetting.common.util;
+package com.gyee.power.fitting.common.util;
 
 
 import java.math.BigDecimal;
@@ -87,4 +87,23 @@ public class NumberUtil {
         return sb.toString();
     }
 
+    public static String toNum(int num){
+        String interval = "";
+        switch(num){
+            case 1:
+                interval = "一秒";
+                break;
+            case 60:
+                interval = "一分钟";
+                break;
+            case 600:
+                interval = "十分钟";
+                break;
+            default:
+                interval = "一分钟";
+        }
+
+        return interval;
+    }
+
 }

+ 62 - 0
power-fitting/src/main/java/com/gyee/power/fitting/common/util/PowerFittingUtil.java

@@ -0,0 +1,62 @@
+package com.gyee.power.fitting.common.util;
+
+import com.gyee.power.fitting.common.constants.Constants;
+import com.gyee.power.fitting.model.Powerfittinganalysis;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class PowerFittingUtil {
+
+    /**
+     * 功率曲线拟合数据  tree
+     * @return
+     */
+    public static List<Object> powerDataTree(List<Powerfittinganalysis> list, String type){
+        /**多层分组**/
+        Map<String, Map<String, Map<String, List<Powerfittinganalysis>>>> map = list.stream().
+                collect(Collectors.groupingBy(Powerfittinganalysis::getInterval, TreeMap::new,
+                        Collectors.groupingBy(Powerfittinganalysis::getTime,
+                                Collectors.groupingBy(Powerfittinganalysis::getStationcn))));
+
+        List<Object> result = new ArrayList<>();
+        map.forEach((k, v) -> {
+            List<Object> l1 = new ArrayList<>();
+            Map<String, Object> map1 = new TreeMap<>();
+
+            map.get(k).forEach((k1, v1) -> {
+                List<Object> l2 = new ArrayList<>();
+                Map<String, Object> map2 = new HashMap<>();
+                map.get(k).get(k1).forEach((k2, v2) -> {
+                    Map<String, Object> map3 = new HashMap<>();
+                    map3.put("id", SnowFlakeUtil.generateId());
+                    map3.put("label", k2);
+                    map3.put("children", v2.stream().sorted(Comparator.comparing(Powerfittinganalysis::getWindturbine)));
+                    l2.add(map3);
+                });
+
+                map2.put("id", SnowFlakeUtil.generateId());
+                map2.put("label", k1);
+                map2.put("children", l2);
+                l1.add(map2);
+            });
+
+            map1.put("id", SnowFlakeUtil.generateId());
+            map1.put("label", k);
+            map1.put("children", l1);
+            result.add(map1);
+        });
+
+        Map<String, Object> mp = new HashMap<>();
+        mp.put("id", SnowFlakeUtil.generateId());
+        mp.put("label", type.equals(Constants.DATA_PREPARE) ? "数据准备" :
+                type.equals(Constants.DATA_PROCESS) ? "数据预处理" : type.equals(Constants.DATA_FITTING) ? "功率曲线拟合" : "数据");
+        mp.put("children", result);
+
+        List<Object> ls = new ArrayList<>();
+        ls.add(mp);
+
+        return ls;
+    }
+
+}

+ 1 - 1
power-fetting/src/main/java/com/gyee/power/fetting/common/util/SnowFlakeUtil.java

@@ -1,4 +1,4 @@
-package com.gyee.power.fetting.common.util;
+package com.gyee.power.fitting.common.util;
 
 
 /**

+ 1 - 1
power-fetting/src/main/java/com/gyee/power/fetting/common/util/TokenGenerator.java

@@ -1,4 +1,4 @@
-package com.gyee.power.fetting.common.util;
+package com.gyee.power.fitting.common.util;
 
 import java.security.MessageDigest;
 import java.util.UUID;

+ 127 - 0
power-fitting/src/main/java/com/gyee/power/fitting/controller/analyse/DataFittingController.java

@@ -0,0 +1,127 @@
+package com.gyee.power.fitting.controller.analyse;
+
+
+import com.alibaba.fastjson.JSONObject;
+import com.gyee.power.fitting.common.result.JsonResult;
+import com.gyee.power.fitting.common.result.ResultCode;
+import com.gyee.power.fitting.model.Powerfittinganalysis;
+import com.gyee.power.fitting.model.custom.PowerPointData;
+import com.gyee.power.fitting.service.custom.curve.DataFittingService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * 功率曲线拟合
+ */
+@RestController
+@CrossOrigin
+@RequestMapping("/power/fitting")
+public class DataFittingController {
+
+    @Autowired
+    private DataFittingService fittingService;
+
+
+    /**
+     * 数据拟合
+     * @param ids    数据预处理id
+     * @param maxs
+     * @param mins
+     * @param maxp
+     * @param minp
+     * @param dimension 多项式
+     * @param mode  拟合方式  0:单台拟合  1:合并拟合  2:同名拟合
+     * @return
+     */
+    @GetMapping("/data")
+    public JSONObject dataFitting(@RequestParam(value = "ids",  required = false) String ids,
+                                  @RequestParam(value = "maxs",  required = false) Double maxs,
+                                  @RequestParam(value = "mins",  required = false) Double mins,
+                                  @RequestParam(value = "maxp",  required = false) Double maxp,
+                                  @RequestParam(value = "minp",  required = false) Double minp,
+                                  @RequestParam(value = "dimension",  required = false) Integer dimension,
+                                  @RequestParam(value = "mode",  required = false) Integer mode){
+        if (ids.isEmpty())
+            return JsonResult.error(ResultCode.PARAM_IS_BLANK);
+
+        Powerfittinganalysis obj = fittingService.dataFitting(ids, maxs, mins, maxp, minp, dimension, mode);
+        return JsonResult.successData(ResultCode.SUCCESS, obj);
+    }
+
+
+    /** 文件 tree
+     * @return
+     */
+    @GetMapping("tree")
+    public JSONObject dataFIttingTree(){
+        List<Object> result = fittingService.dataFittingTree();
+        return JsonResult.successData(ResultCode.SUCCESS, result);
+    }
+
+
+    /**
+     * file 文件数据展示
+     * @param id
+     * @return
+     */
+    @GetMapping("show")
+    public JSONObject dataFittingShow(String id){
+        Map<String, Object> result = fittingService.dataFittingShow(id);
+        return JsonResult.successData(ResultCode.SUCCESS, result);
+    }
+
+
+    /**
+     * 读取曲线,散点等数据
+     * @param id  拟合好的数据ID
+     * @return
+     */
+    @GetMapping("curve")
+    public JSONObject dataFittingCurve(String id){
+        Map<String, Object> result = fittingService.dataFittingCurve(id);
+        return JsonResult.successData(ResultCode.SUCCESS, result);
+    }
+
+
+    /**
+     * 通过key获取原始数据
+     * 对应前端的圈选功能
+     * @param yk  有用点的key
+     * @param wk  无用点的key
+     * @return
+     */
+    @GetMapping("filter")
+    public JSONObject dataFittingFilter(String yk, String wk){
+        List<PowerPointData> list = fittingService.dataOrigin(yk, wk);
+        return JsonResult.successData(ResultCode.SUCCESS, list);
+    }
+
+
+    /**
+     * 计算曲线偏差率
+     * @param id 曲线拟合的id
+     * @return
+     */
+    @GetMapping("curve/ratio")
+    public JSONObject dataCurveRatio(String id){
+        Map<String, Double> map = fittingService.dataCurveRatio(id);
+        return JsonResult.successData(ResultCode.SUCCESS, map);
+    }
+
+
+    /**
+     * 获取多风机的拟合曲线功率
+     * @param ids  拟合好的数据ID
+     * @return
+     */
+    @GetMapping("line")
+    public JSONObject dataFittingLine(String ids){
+        Object o = fittingService.dataFittingLine(ids);
+        return JsonResult.successData(ResultCode.SUCCESS, o);
+    }
+}

+ 83 - 0
power-fitting/src/main/java/com/gyee/power/fitting/controller/analyse/DataPrepareController.java

@@ -0,0 +1,83 @@
+package com.gyee.power.fitting.controller.analyse;
+
+import com.alibaba.fastjson.JSONObject;
+import com.gyee.power.fitting.common.result.JsonResult;
+import com.gyee.power.fitting.common.result.ResultCode;
+import com.gyee.power.fitting.common.util.FileUtil;
+import com.gyee.power.fitting.model.Powerfittinganalysis;
+import com.gyee.power.fitting.service.PowerfittinganalysisService;
+import com.gyee.power.fitting.service.custom.curve.DataPrepareService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.*;
+
+
+/**
+ * 功率曲线拟合  数据准备
+ */
+@RestController
+@CrossOrigin
+@RequestMapping("/power/prepare")
+public class DataPrepareController {
+
+    @Autowired
+    private DataPrepareService prepareService;
+    @Autowired
+    private PowerfittinganalysisService powerService;
+
+
+    /**
+     * 数据准备  golden-file
+     * @param station
+     * @param wtIds
+     * @param st
+     * @param et
+     * @param interval
+     * @return
+     */
+    @GetMapping("data")
+    public JSONObject dataPrepare(String station, String wtIds, Long st,
+                                  Long et, Integer interval){
+        if (station.isEmpty() || wtIds.isEmpty())
+            return JsonResult.error(ResultCode.PARAM_NOT_COMPLETE);
+
+        String[] points = wtIds.split(",");
+        prepareService.dataPrepare(station, Arrays.asList(points), st, et, interval);
+
+        return JsonResult.error(ResultCode.SUCCESS_DATA_PREPARE);
+    }
+
+    /** 文件 tree
+     * @return
+     */
+    @GetMapping("tree")
+    public JSONObject dataPrepareTree(){
+        List<Object> result = prepareService.dataPrepareTree();
+        return JsonResult.successData(ResultCode.SUCCESS, result);
+    }
+
+
+    /**
+     * file 文件数据展示前500行
+     * @param id
+     * @return
+     */
+    @GetMapping("show")
+    public JSONObject dataPrepareShow(String id){
+        Map<String, Object> result = prepareService.dataPrepareShow(id);
+        return JsonResult.successData(ResultCode.SUCCESS, result);
+    }
+
+
+    /**
+     * file 下载
+     * @return
+     */
+    @GetMapping("download")
+    public void dataPrepareDownload(HttpServletResponse response, @RequestParam(value = "id", required = false) String id){
+        Powerfittinganalysis obj = powerService.selectItemById(id);
+        FileUtil.download(obj.getPath(), response);
+    }
+}

+ 106 - 0
power-fitting/src/main/java/com/gyee/power/fitting/controller/analyse/DataProcessController.java

@@ -0,0 +1,106 @@
+package com.gyee.power.fitting.controller.analyse;
+
+import com.alibaba.fastjson.JSONObject;
+import com.gyee.power.fitting.common.result.JsonResult;
+import com.gyee.power.fitting.common.result.ResultCode;
+import com.gyee.power.fitting.common.util.FileUtil;
+import com.gyee.power.fitting.model.Powerfittinganalysis;
+import com.gyee.power.fitting.service.PowerfittinganalysisService;
+import com.gyee.power.fitting.service.custom.curve.DataProcessService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 功率曲线拟合  数据预处理
+ */
+@RestController
+@CrossOrigin
+@RequestMapping("/power/process")
+public class DataProcessController {
+
+    @Autowired
+    private PowerfittinganalysisService powerService;
+    @Autowired
+    private DataProcessService processService;
+
+
+    /**
+     * 数据预处理
+     * @param ids       预处理数据的ID  自定义
+     * @param maxs     最大风速
+     * @param mins     最小风速
+     * @param maxp     最大功率
+     * @param minp     最小功率
+     * @param isfbw    非并网
+     * @param isfhl    非合理值
+     * @param isbw     并网后10分钟
+     * @param istj     停机前10分钟
+     * @param isglpc   功率曲线偏差
+     * @param isqfh    是否欠符合
+     * @param qfhdj    欠符合等级
+     * @return
+     */
+    @GetMapping("data")
+    public JSONObject dataProcess(@RequestParam(value = "ids",  required = false) String ids,
+                                  @RequestParam(value = "maxs",  required = false) Double maxs,
+                                  @RequestParam(value = "mins",  required = false) Double mins,
+                                  @RequestParam(value = "maxp",  required = false) Double maxp,
+                                  @RequestParam(value = "minp",  required = false) Double minp,
+                                  @RequestParam(value = "isfbw",  required = false) Boolean isfbw,
+                                  @RequestParam(value = "isfhl",  required = false) Boolean isfhl,
+                                  @RequestParam(value = "isbw",  required = false) Boolean isbw,
+                                  @RequestParam(value = "istj",  required = false) Boolean istj,
+                                  @RequestParam(value = "isglpc",  required = false) Boolean isglpc,
+                                  @RequestParam(value = "isqfh",  required = false) Boolean isqfh,
+                                  @RequestParam(value = "qfhdj",  required = false) Integer qfhdj){
+
+        isfbw = isfbw == null ? false : isfbw;
+        isfhl = isfhl == null ? false : isfhl;
+        isbw = isbw == null ? false : isbw;
+        istj = istj == null ? false : istj;
+        isglpc = isglpc == null ? false : isglpc;
+        isqfh = isqfh == null ? false : isqfh;
+
+        String[] id = ids.split(",");
+        processService.dataProcess(Arrays.asList(id), maxs, mins, maxp, minp, isfbw, isfhl, isbw, istj, isglpc, isqfh, qfhdj);
+
+        return JsonResult.error(ResultCode.SUCCESS);
+    }
+
+    /** 文件 tree
+     * @return
+     */
+    @GetMapping("tree")
+    public JSONObject dataProcessTree(){
+        List<Object> result = processService.dataProcessTree();
+        return JsonResult.successData(ResultCode.SUCCESS, result);
+    }
+
+
+    /**
+     * file 文件数据展示前500行
+     * @param id
+     * @return
+     */
+    @GetMapping("show")
+    public JSONObject dataProcessShow(String id){
+        Map<String, Object> result = processService.dataProcessShow(id);
+        return JsonResult.successData(ResultCode.SUCCESS, result);
+    }
+
+    /**
+     * file 下载
+     * @return
+     */
+    @GetMapping("download")
+    public void dataProcessDownload(HttpServletResponse response, @RequestParam(value = "id", required = false) String id){
+        Powerfittinganalysis obj = powerService.selectItemById(id);
+        FileUtil.download(obj.getPath(), response);
+    }
+
+}

+ 61 - 0
power-fitting/src/main/java/com/gyee/power/fitting/controller/analyse/DateOptionController.java

@@ -0,0 +1,61 @@
+package com.gyee.power.fitting.controller.analyse;
+
+import com.alibaba.fastjson.JSONObject;
+import com.gyee.power.fitting.common.config.GyeeConfig;
+import com.gyee.power.fitting.common.result.JsonResult;
+import com.gyee.power.fitting.common.result.ResultCode;
+import com.gyee.power.fitting.common.util.FileUtil;
+import com.gyee.power.fitting.model.Powerfittinganalysis;
+import com.gyee.power.fitting.service.PowerfittinganalysisService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.File;;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 数据删除、下载...
+ */
+@RestController
+@CrossOrigin
+@RequestMapping("/data/option")
+public class DateOptionController {
+
+    @Autowired
+    private GyeeConfig gyeeConfig;
+    @Autowired
+    private PowerfittinganalysisService powerfittinganalysisService;
+
+
+    /** 删除
+     * @return
+     */
+    @GetMapping("delete")
+    public JSONObject dataDelete(String ids){
+        powerfittinganalysisService.deleteList(ids);
+        return JsonResult.success(ResultCode.SUCCESS);
+    }
+
+
+    /**
+     * 文件压缩下载
+     * @return
+     */
+    @GetMapping("download")
+    public void dataProcessDownload(HttpServletResponse response, @RequestParam(value = "ids", required = false) String ids){
+        if (ids.isEmpty())
+            return;
+
+        List<Powerfittinganalysis> objs = powerfittinganalysisService.selectListByIds(ids);
+        List<String> list = objs.stream().map(p -> p.getPath()).collect(Collectors.toList());
+        List<File> files = list.stream().map(File::new).collect(Collectors.toList());
+
+        File zipFile = new File(gyeeConfig.getFilePathDownload()  + "\\" + objs.get(0).getStation() + "_" + System.currentTimeMillis() + ".zip");
+        // 调用压缩方法
+        String ps = FileUtil.zipFiles(files, zipFile);
+        FileUtil.download(ps, response);
+    }
+
+}

+ 33 - 0
power-fitting/src/main/java/com/gyee/power/fitting/controller/analyse/RatioController.java

@@ -0,0 +1,33 @@
+package com.gyee.power.fitting.controller.analyse;
+
+import com.alibaba.fastjson.JSONObject;
+import com.gyee.power.fitting.common.result.JsonResult;
+import com.gyee.power.fitting.common.result.ResultCode;
+import com.gyee.power.fitting.service.custom.ratio.RatioService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ */
+@RestController
+@CrossOrigin
+@RequestMapping("/wind")
+public class RatioController {
+
+    @Autowired
+    private RatioService ratioService;
+
+    /**
+     * 对风偏差率
+     * @param ids  预处理数据 ids
+     * @param mode 拟合方式  0:单台统计   1:合并统计
+     * @return
+     */
+    @GetMapping("deviation/ratio")
+    public JSONObject fsRoses(String ids, @RequestParam(value = "mode",  required = false) Integer mode){
+        mode = mode == null ? 0 : mode;
+        Object o = ratioService.windDeviationRatio(ids, mode);
+        return JsonResult.successData(ResultCode.SUCCESS, o);
+    }
+
+}

+ 48 - 0
power-fitting/src/main/java/com/gyee/power/fitting/controller/analyse/WindDirectionController.java

@@ -0,0 +1,48 @@
+package com.gyee.power.fitting.controller.analyse;
+
+
+import com.alibaba.fastjson.JSONObject;
+import com.gyee.power.fitting.common.result.JsonResult;
+import com.gyee.power.fitting.common.result.ResultCode;
+import com.gyee.power.fitting.service.custom.fx.WindDirectionService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+
+/**
+ * 风向玫瑰图
+ */
+@RestController
+@CrossOrigin
+@RequestMapping("/wind")
+public class WindDirectionController {
+
+    @Autowired
+    private WindDirectionService windDirectionService;
+
+    /***
+     * 风向玫瑰图
+     * @param ids  预处理数据的id
+     * @param mode 统计方式   0:单台统计   1:合并统计
+     * @return
+     */
+    @GetMapping("roses")
+    public JSONObject fsRoses(String ids, @RequestParam(value = "mode",  required = false) Integer mode){
+        mode = mode == null ? 0 : mode;
+        Object o = windDirectionService.fxRoses(ids, mode);
+        return JsonResult.successData(ResultCode.SUCCESS, o);
+    }
+
+    /***
+     * 风向频次玫瑰图
+     * @param ids  预处理数据的id
+     * @param mode 统计方式   0:单台统计   1:合并统计
+     * @return
+     */
+    @GetMapping("roses/count")
+    public JSONObject fxRoses(String ids, @RequestParam(value = "mode",  required = false) Integer mode){
+        mode = mode == null ? 0 : mode;
+        Object o = windDirectionService.fxCountRoses(ids, mode);
+        return JsonResult.successData(ResultCode.SUCCESS, o);
+    }
+}

+ 36 - 0
power-fitting/src/main/java/com/gyee/power/fitting/controller/base/WindInfoController.java

@@ -0,0 +1,36 @@
+package com.gyee.power.fitting.controller.base;
+
+import com.alibaba.fastjson.JSONObject;
+import com.gyee.power.fitting.common.result.JsonResult;
+import com.gyee.power.fitting.common.result.ResultCode;
+import com.gyee.power.fitting.common.spring.InitialRunner;
+import com.gyee.power.fitting.model.Windpowerstation;
+import com.gyee.power.fitting.model.Windturbine;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 场站风机等基础数据
+ */
+@RestController
+@CrossOrigin
+@RequestMapping("/base")
+public class WindInfoController {
+
+    @GetMapping("station")
+    public JSONObject getStation(){
+        List<Windpowerstation> list = InitialRunner.wpList;
+        return JsonResult.successData(ResultCode.SUCCESS, list);
+    }
+
+    @GetMapping("windturbine")
+    public JSONObject getWindTurbine(String stationId){
+        List<Windturbine> list = InitialRunner.wpMap.get(stationId);
+        return JsonResult.successData(ResultCode.SUCCESS, list);
+    }
+}

+ 18 - 0
power-fitting/src/main/java/com/gyee/power/fitting/mapper/EquipmentmodelMapper.java

@@ -0,0 +1,18 @@
+package com.gyee.power.fitting.mapper;
+
+import com.gyee.power.fitting.model.Equipmentmodel;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author chenmh
+ * @since 2022-11-08
+ */
+@Mapper
+public interface EquipmentmodelMapper extends BaseMapper<Equipmentmodel> {
+
+}

+ 21 - 0
power-fitting/src/main/java/com/gyee/power/fitting/mapper/ModelpowerMapper.java

@@ -0,0 +1,21 @@
+package com.gyee.power.fitting.mapper;
+
+import com.gyee.power.fitting.model.Modelpower;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author chenmh
+ * @since 2022-11-08
+ */
+@Mapper
+public interface ModelpowerMapper extends BaseMapper<Modelpower> {
+
+    List<Modelpower> selectList();
+}

+ 18 - 0
power-fitting/src/main/java/com/gyee/power/fitting/mapper/ModelpowerdetailsMapper.java

@@ -0,0 +1,18 @@
+package com.gyee.power.fitting.mapper;
+
+import com.gyee.power.fitting.model.Modelpowerdetails;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author chenmh
+ * @since 2022-11-08
+ */
+@Mapper
+public interface ModelpowerdetailsMapper extends BaseMapper<Modelpowerdetails> {
+
+}

+ 18 - 0
power-fitting/src/main/java/com/gyee/power/fitting/mapper/PowerfittinganalysisMapper.java

@@ -0,0 +1,18 @@
+package com.gyee.power.fitting.mapper;
+
+import com.gyee.power.fitting.model.Powerfittinganalysis;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author chenmh
+ * @since 2022-11-03
+ */
+@Mapper
+public interface PowerfittinganalysisMapper extends BaseMapper<Powerfittinganalysis> {
+
+}

+ 2 - 2
power-fetting/src/main/java/com/gyee/power/fetting/mapper/WindpowerstationMapper.java

@@ -1,8 +1,8 @@
-package com.gyee.power.fetting.mapper;
+package com.gyee.power.fitting.mapper;
 
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.gyee.power.fetting.model.Windpowerstation;
+import com.gyee.power.fitting.model.Windpowerstation;
 import org.apache.ibatis.annotations.Mapper;
 
 /**

+ 2 - 2
power-fetting/src/main/java/com/gyee/power/fetting/mapper/WindturbineMapper.java

@@ -1,8 +1,8 @@
-package com.gyee.power.fetting.mapper;
+package com.gyee.power.fitting.mapper;
 
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.gyee.power.fetting.model.Windturbine;
+import com.gyee.power.fitting.model.Windturbine;
 import org.apache.ibatis.annotations.Mapper;
 
 /**

+ 18 - 0
power-fitting/src/main/java/com/gyee/power/fitting/mapper/Windturbinetestingpointai2Mapper.java

@@ -0,0 +1,18 @@
+package com.gyee.power.fitting.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.gyee.power.fitting.model.Windturbinetestingpointai2;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author chenmh
+ * @since 2022-11-01
+ */
+@Mapper
+public interface Windturbinetestingpointai2Mapper extends BaseMapper<Windturbinetestingpointai2> {
+
+}

+ 72 - 0
power-fitting/src/main/java/com/gyee/power/fitting/model/Equipmentmodel.java

@@ -0,0 +1,72 @@
+package com.gyee.power.fitting.model;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author chenmh
+ * @since 2022-11-08
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("EQUIPMENTMODEL")
+public class Equipmentmodel extends Model<Equipmentmodel> {
+
+    private static final long serialVersionUID=1L;
+
+      @TableId("ID")
+    private String id;
+
+    @TableField("CODE")
+    private String code;
+
+    @TableField("NAME")
+    private String name;
+
+    @TableField("DESCRIPTION")
+    private String description;
+
+    @TableField("POWERPRODUCTION")
+    private String powerproduction;
+
+    @TableField("CUTINWINDSPEED")
+    private String cutinwindspeed;
+
+    @TableField("RATEDWINDSPEED")
+    private String ratedwindspeed;
+
+    @TableField("CUTOUTWINDSPEED")
+    private String cutoutwindspeed;
+
+    @TableField("WINDTURBINEMANUFACTURERID")
+    private String windturbinemanufacturerid;
+
+    @TableField("PHOTO")
+    private String photo;
+
+    @TableField("UNIT")
+    private String unit;
+
+    //扫风面积
+    @TableField("SWEPTAREA")
+    private Double sweptarea;
+
+    @TableField("EQUIPMENTCATEGORY")
+    private String equipmentcategory;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 47 - 0
power-fitting/src/main/java/com/gyee/power/fitting/model/Modelpower.java

@@ -0,0 +1,47 @@
+package com.gyee.power.fitting.model;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author chenmh
+ * @since 2022-11-08
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("MODELPOWER")
+public class Modelpower extends Model<Modelpower> {
+
+    private static final long serialVersionUID=1L;
+
+      @TableId("ID")
+    private String id;
+
+    @TableField("MODELID")
+    private String modelid;
+
+    @TableField("SPEED")
+    private String speed;
+
+    @TableField("THEORYPOWER")
+    private String theorypower;
+
+    @TableField("ENSUREPOWER")
+    private String ensurepower;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 47 - 0
power-fitting/src/main/java/com/gyee/power/fitting/model/Modelpowerdetails.java

@@ -0,0 +1,47 @@
+package com.gyee.power.fitting.model;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author chenmh
+ * @since 2022-11-08
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("MODELPOWERDETAILS")
+public class Modelpowerdetails extends Model<Modelpowerdetails> {
+
+    private static final long serialVersionUID=1L;
+
+      @TableId("ID")
+    private String id;
+
+    @TableField("MODELID")
+    private String modelid;
+
+    @TableField("SPEED")
+    private Double speed;
+
+    @TableField("THEORYPOWER")
+    private Double theorypower;
+
+    @TableField("ENSUREPOWER")
+    private Double ensurepower;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 74 - 0
power-fitting/src/main/java/com/gyee/power/fitting/model/Powerfittinganalysis.java

@@ -0,0 +1,74 @@
+package com.gyee.power.fitting.model;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author chenmh
+ * @since 2022-11-03
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("POWERFITTINGANALYSIS")
+public class Powerfittinganalysis extends Model<Powerfittinganalysis> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableField("ID")
+    private String id;
+
+    @TableField("STATION")
+    private String station;
+
+    @TableField("STATIONCN")
+    private String stationcn;
+
+    @TableField("WINDTURBINE")
+    private String windturbine;
+
+    @TableField("CODE")
+    private String code;
+
+    @TableField("INTERVAL")
+    private String interval;
+
+    @TableField("TIME")
+    private String time;
+
+    @TableField("PATH")
+    private String path;
+
+    @TableField("TYPE")
+    private String type;
+
+    @TableField("PREPAREID")
+    private String prepareid;
+
+    @TableField("CPAVG")
+    private Double cpavg;
+
+    @TableField("SPEEDAVG")
+    private Double speedavg;
+
+    @TableField("FREQUENCY")
+    private Double frequency;
+
+    @TableField("PCRATIO")
+    private Double pcratio;
+
+
+
+    @Override
+    protected Serializable pkVal() {
+        return null;
+    }
+
+}

+ 5 - 4
power-fetting/src/main/java/com/gyee/power/fetting/model/Windpowerstation.java

@@ -1,11 +1,12 @@
-package com.gyee.power.fetting.model;
+package com.gyee.power.fitting.model;
 
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
-import java.time.LocalDate;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableField;
 import java.io.Serializable;
+import java.util.Date;
+
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
@@ -84,8 +85,8 @@ public class Windpowerstation extends Model<Windpowerstation> {
     @TableField("HEIGHT")
     private String height;
 
-    @TableField("AQTS")
-    private LocalDate aqts;
+//    @TableField("AQTS")
+//    private Date aqts;
 
 
     @Override

+ 4 - 3
power-fetting/src/main/java/com/gyee/power/fetting/model/Windturbine.java

@@ -1,11 +1,12 @@
-package com.gyee.power.fetting.model;
+package com.gyee.power.fitting.model;
 
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
-import java.time.LocalDate;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableField;
 import java.io.Serializable;
+import java.util.Date;
+
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
@@ -52,7 +53,7 @@ public class Windturbine extends Model<Windturbine> {
     private String lineid;
 
     @TableField("FIRSTINTEGRATEDTIME")
-    private LocalDate firstintegratedtime;
+    private String firstintegratedtime;
 
     @TableField("PHOTO")
     private String photo;

+ 86 - 0
power-fitting/src/main/java/com/gyee/power/fitting/model/Windturbinetestingpointai2.java

@@ -0,0 +1,86 @@
+package com.gyee.power.fitting.model;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author chenmh
+ * @since 2022-11-01
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("WINDTURBINETESTINGPOINTAI2")
+public class Windturbinetestingpointai2 extends Model<Windturbinetestingpointai2> {
+
+    private static final long serialVersionUID=1L;
+
+      @TableId("ID")
+    private String id;
+
+    @TableField("CODE")
+    private String code;
+
+    @TableField("NAME")
+    private String name;
+
+    @TableField("MODEL")
+    private String model;
+
+    @TableField("VALUEUNIT")
+    private String valueunit;
+
+    @TableField("ENGLISHNAME")
+    private String englishname;
+
+    @TableField("TYPEID")
+    private String typeid;
+
+    @TableField("MODELID")
+    private String modelid;
+
+    @TableField("MAXVAL")
+    private String maxval;
+
+    @TableField("MINVAL")
+    private String minval;
+
+    @TableField("REASONABLEMAXVAL")
+    private String reasonablemaxval;
+
+    @TableField("REASONABLEMINVAL")
+    private String reasonableminval;
+
+    @TableField("WINDTURBINEID")
+    private String windturbineid;
+
+    @TableField("UNIFORMCODE")
+    private String uniformcode;
+
+    @TableField("SHORTID")
+    private String shortid;
+
+    @TableField("LONGID")
+    private String longid;
+
+    @TableField("WINDPOWERSTATIONID")
+    private String windpowerstationid;
+
+    @TableField("REALTIMEID")
+    private String realtimeid;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 35 - 0
power-fitting/src/main/java/com/gyee/power/fitting/model/custom/LineCurveFitting.java

@@ -0,0 +1,35 @@
+package com.gyee.power.fitting.model.custom;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class LineCurveFitting {
+
+    public String name;
+    public List<Point> lines;
+    public List<Point> YLines;
+
+    public List<Point> point;
+    public List<Point> YPoint;
+
+    /// <summary>
+    /// 推力系数
+    /// </summary>
+    public List<Point> CpValue;
+    /// <summary>
+    /// 推力系数平均值
+    /// </summary>
+    public double CpAvg;
+    /// <summary>
+    /// 平均风速
+    /// </summary>
+    public double speed;
+
+    /// <summary>
+    /// 静风频率
+    /// </summary>
+    public double frequency;
+
+}

+ 16 - 0
power-fitting/src/main/java/com/gyee/power/fitting/model/custom/Point.java

@@ -0,0 +1,16 @@
+package com.gyee.power.fitting.model.custom;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class Point {
+
+    private double x;
+
+    private double y;
+
+}

+ 19 - 0
power-fitting/src/main/java/com/gyee/power/fitting/model/custom/PointVo.java

@@ -0,0 +1,19 @@
+package com.gyee.power.fitting.model.custom;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class PointVo {
+
+    private double x;
+
+    private double y;
+
+    private double s;
+
+    private String k;
+}

+ 27 - 0
power-fitting/src/main/java/com/gyee/power/fitting/model/custom/PowerFittingPoint.java

@@ -0,0 +1,27 @@
+package com.gyee.power.fitting.model.custom;
+
+import lombok.Data;
+
+/**
+ * 拟合后对应的曲线 model
+ */
+@Data
+public class PowerFittingPoint {
+
+    //风速
+    private Double speed;
+    //拟合数据
+    private Double nhdata;
+    //修正数据
+    private Double xzdata;
+    //cp值
+    private Double cpdata;
+
+    public PowerFittingPoint(String[] str) {
+        if (str.length >= 2){
+            this.speed = Double.valueOf(str[0]);
+            this.nhdata = Double.valueOf(str[1]);
+            this.cpdata = ((double)((int)(Double.valueOf(str[2])*1000)))/1000;
+        }
+    }
+}

+ 62 - 0
power-fitting/src/main/java/com/gyee/power/fitting/model/custom/PowerPointData.java

@@ -0,0 +1,62 @@
+package com.gyee.power.fitting.model.custom;
+
+import lombok.Data;
+
+import java.text.DecimalFormat;
+
+/**
+ * 数据准备的测点
+ */
+@Data
+public class PowerPointData {
+
+    public PowerPointData(){}
+
+    public PowerPointData(String[] str){
+        DecimalFormat df = new DecimalFormat("0.00");
+        if (str.length >= 9){
+            this.time = str[0];
+            this.power = Double.valueOf(df.format(Double.valueOf(str[1])));
+            this.speed = Double.valueOf(df.format(Double.valueOf(str[2])));
+            this.RR = Double.valueOf(df.format(Double.valueOf(str[3])));
+            this.mxzt = Double.valueOf(df.format(Double.valueOf(str[4]))).intValue();
+            this.DL = Double.valueOf(df.format(Double.valueOf(str[5])));
+            this.qfzt = Double.valueOf(df.format(Double.valueOf(str[6]))).intValue();
+            this.FX = Double.valueOf(df.format(Double.valueOf(str[7])));
+            this.angle = Double.valueOf(df.format(Double.valueOf(str[8])));
+        }
+    }
+
+    //时间
+    private String time;
+
+    //功率
+    private double power = 0;
+
+    //风速
+    private double speed = 0;
+
+    //转速
+    private double RR = 0;
+
+    //明细状态
+    private int mxzt = 0;
+
+    //电量
+    private double DL = 0;
+
+    //欠发状态
+    private int qfzt = 0;
+
+    //风向
+    private double FX = 0;
+
+    //对风角度
+    private double angle = 0;
+
+    //是否过滤  0:不过滤 1:过滤
+    private int filter = 0;
+
+    private String wtId;
+}
+

+ 43 - 0
power-fitting/src/main/java/com/gyee/power/fitting/model/custom/TableTitle.java

@@ -0,0 +1,43 @@
+package com.gyee.power.fitting.model.custom;
+
+import lombok.Data;
+
+/**
+ * 和 PowerPointData / PowerFittingPoint 对应
+ * 主要给前端表格提供对应标题
+ */
+@Data
+public class TableTitle {
+
+    private String key;
+    private String des;
+
+    public TableTitle(String des){
+        this.des = des;
+        if (des.contains("时间")){
+            this.key = "time";
+        } else if (des.contains("风机功率")){
+            this.key = "power";
+        } else if (des.contains("风速")){
+            this.key = "speed";
+        } else if (des.contains("转速")){
+            this.key = "rr";
+        } else if (des.contains("风机状态")){
+            this.key = "mxzt";
+        } else if (des.contains("电量")){
+            this.key = "dl";
+        } else if (des.contains("欠发")){
+            this.key = "qfzt";
+        } else if (des.contains("风向")){
+            this.key = "fx";
+        } else if (des.contains("角度")){
+            this.key = "angle";
+        } else if (des.contains("筛选")){
+            this.key = "filter";
+        } else if (des.contains("拟合功率")){
+            this.key = "nhdata";
+        } else if (des.contains("Cp值")){
+            this.key = "cpdata";
+        }
+    }
+}

+ 2 - 1
power-fetting/src/main/java/com/gyee/power/fetting/model/custom/TsDoubleData.java

@@ -1,5 +1,6 @@
-package com.gyee.power.fetting.model.custom;
+package com.gyee.power.fitting.model.custom;
 
+// 数据适配器取数对应的类
 public class TsDoubleData {
 
     private long ts;

+ 26 - 0
power-fitting/src/main/java/com/gyee/power/fitting/service/EquipmentmodelService.java

@@ -0,0 +1,26 @@
+package com.gyee.power.fitting.service;
+
+import com.gyee.power.fitting.model.Equipmentmodel;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author chenmh
+ * @since 2022-11-08
+ */
+public interface EquipmentmodelService extends IService<Equipmentmodel> {
+
+    List<Equipmentmodel> selectList();
+
+    /**
+     * 通过幸好查询
+     * @param id
+     * @return
+     */
+    Equipmentmodel selectItemByModel(String id);
+}

+ 19 - 0
power-fitting/src/main/java/com/gyee/power/fitting/service/ModelpowerService.java

@@ -0,0 +1,19 @@
+package com.gyee.power.fitting.service;
+
+import com.gyee.power.fitting.model.Modelpower;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author chenmh
+ * @since 2022-11-08
+ */
+public interface ModelpowerService extends IService<Modelpower> {
+
+    List<Modelpower> selectList();
+}

+ 19 - 0
power-fitting/src/main/java/com/gyee/power/fitting/service/ModelpowerdetailsService.java

@@ -0,0 +1,19 @@
+package com.gyee.power.fitting.service;
+
+import com.gyee.power.fitting.model.Modelpowerdetails;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author chenmh
+ * @since 2022-11-08
+ */
+public interface ModelpowerdetailsService extends IService<Modelpowerdetails> {
+
+    List<Modelpowerdetails> selectList();
+}

+ 33 - 0
power-fitting/src/main/java/com/gyee/power/fitting/service/PowerfittinganalysisService.java

@@ -0,0 +1,33 @@
+package com.gyee.power.fitting.service;
+
+import com.gyee.power.fitting.model.Powerfittinganalysis;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author chenmh
+ * @since 2022-11-03
+ */
+public interface PowerfittinganalysisService extends IService<Powerfittinganalysis> {
+
+
+    Powerfittinganalysis selectItemById(String id);
+
+    /**
+     * 根据类型查询
+     * @param type   prepare
+     * @return
+     */
+    List<Powerfittinganalysis> selectList(String type);
+
+    void insertItem(Powerfittinganalysis obj);
+
+    List<Powerfittinganalysis> selectListByIds(String ids);
+
+    void deleteList(String ids);
+}

+ 2 - 2
power-fetting/src/main/java/com/gyee/power/fetting/service/WindpowerstationService.java

@@ -1,7 +1,7 @@
-package com.gyee.power.fetting.service;
+package com.gyee.power.fitting.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.gyee.power.fetting.model.Windpowerstation;
+import com.gyee.power.fitting.model.Windpowerstation;
 
 import java.util.List;
 

+ 3 - 3
power-fetting/src/main/java/com/gyee/power/fetting/service/WindturbineService.java

@@ -1,7 +1,7 @@
-package com.gyee.power.fetting.service;
+package com.gyee.power.fitting.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.gyee.power.fetting.model.Windturbine;
+import com.gyee.power.fitting.model.Windturbine;
 
 import java.util.List;
 
@@ -19,6 +19,6 @@ public interface WindturbineService extends IService<Windturbine> {
      * 查询所有的风机ID
      * @return
      */
-    List<Windturbine> selectList();
+    List<Windturbine> selectList(String station);
 
 }

+ 19 - 0
power-fitting/src/main/java/com/gyee/power/fitting/service/Windturbinetestingpointai2Service.java

@@ -0,0 +1,19 @@
+package com.gyee.power.fitting.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.gyee.power.fitting.model.Windturbinetestingpointai2;
+
+import java.util.List;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author chenmh
+ * @since 2022-11-01
+ */
+public interface Windturbinetestingpointai2Service extends IService<Windturbinetestingpointai2> {
+
+    List<Windturbinetestingpointai2> selectList(String station, List<String> points);
+}

+ 459 - 0
power-fitting/src/main/java/com/gyee/power/fitting/service/custom/curve/DataFittingService.java

@@ -0,0 +1,459 @@
+package com.gyee.power.fitting.service.custom.curve;
+
+import com.gyee.power.fitting.common.alg.DBSCANPointALG;
+import com.gyee.power.fitting.common.config.GyeeConfig;
+import com.gyee.power.fitting.common.constants.Constants;
+import com.gyee.power.fitting.common.spring.InitialRunner;
+import com.gyee.power.fitting.common.util.FileUtil;
+import com.gyee.power.fitting.common.alg.PowerFittingALG;
+import com.gyee.power.fitting.common.util.PowerFittingUtil;
+import com.gyee.power.fitting.common.util.SnowFlakeUtil;
+import com.gyee.power.fitting.model.Modelpowerdetails;
+import com.gyee.power.fitting.model.Powerfittinganalysis;
+import com.gyee.power.fitting.model.custom.*;
+import com.gyee.power.fitting.service.PowerfittinganalysisService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.text.DecimalFormat;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
+
+
+@Slf4j
+@Service
+public class DataFittingService {
+
+    @Resource
+    private GyeeConfig config;
+    @Resource
+    private DataScanService dataScanService;
+    @Resource
+    private PowerfittinganalysisService powerService;
+
+
+    /**
+     * 曲线拟合
+     * @param ids
+     * @param maxs
+     * @param mins
+     * @param maxp
+     * @param minp
+     * @param dimension
+     * @param mode   拟合方式  0:单台拟合  1:合并拟合 2:同名拟合
+     */
+    public Powerfittinganalysis dataFitting(String ids, Double maxs, Double mins, Double maxp, Double minp, Integer dimension, Integer mode){
+        AtomicReference<Powerfittinganalysis> object = new AtomicReference<>();
+
+        if (mode == 0){  //单台拟合
+            String[] splitId = ids.split(",");
+            for (String id : splitId) {
+                List<Powerfittinganalysis> list = powerService.selectListByIds(id);
+                List<Double> arraySpeed = new ArrayList<>();
+                List<Double> arrayPower = new ArrayList<>();
+                List<String> line = FileUtil.readFile(list.get(0).getPath(), true);
+                csvParse(line, arraySpeed, arrayPower, mins, maxs, minp, maxp);
+                List<Modelpowerdetails> mp = InitialRunner.modelPowerDetailMap.get(InitialRunner.wtMap.get(list.get(0).getWindturbine()).getModelid());
+                Double maxP = mp.stream().map(Modelpowerdetails::getEnsurepower).max(Comparator.comparing(Double::doubleValue)).get();
+                object.set(fittingMode(list, maxP, arraySpeed, arrayPower, dimension, mode));
+            }
+        }
+        if (mode == 1){  //合并拟合
+            List<Powerfittinganalysis> list = powerService.selectListByIds(ids);
+            AtomicReference<Double> maxP = new AtomicReference<>(0.0);
+            List<Double> arraySpeed = new ArrayList<>();
+            List<Double> arrayPower = new ArrayList<>();
+            for (Powerfittinganalysis obj : list){
+                List<String> line = FileUtil.readFile(obj.getPath(), true);
+                csvParse(line, arraySpeed, arrayPower, mins, maxs, minp, maxp);
+                List<Modelpowerdetails> mp = InitialRunner.modelPowerDetailMap.get(InitialRunner.wtMap.get(obj.getWindturbine()).getModelid());
+                Double maxPower = mp.stream().map(Modelpowerdetails::getEnsurepower).max(Comparator.comparing(Double::doubleValue)).get();
+                if (maxPower > maxP.get()) maxP.set(maxPower);
+            }
+            object.set(fittingMode(list, maxP.get(), arraySpeed, arrayPower, dimension, mode));
+        }
+        if (mode == 2){  //同名拟合
+            List<Powerfittinganalysis> list = powerService.selectListByIds(ids);
+            Map<String, List<Powerfittinganalysis>> map = list.stream().collect(Collectors.groupingBy(d -> d.getWindturbine()));
+            map.forEach((k, ls) -> {
+                if (ls.size() > 1){
+                    double maxP = 0;
+                    List<Modelpowerdetails> mp = null;
+                    List<Double> arraySpeed = new ArrayList<>();
+                    List<Double> arrayPower = new ArrayList<>();
+                    for (Powerfittinganalysis obj : ls){
+                        List<String> line = FileUtil.readFile(obj.getPath(), true);
+                        csvParse(line, arraySpeed, arrayPower, mins, maxs, minp, maxp);
+                        mp = InitialRunner.modelPowerDetailMap.get(InitialRunner.wtMap.get(obj.getWindturbine()).getModelid());
+                        maxP = mp.stream().map(Modelpowerdetails::getEnsurepower).max(Comparator.comparing(Double::doubleValue)).get();
+                    }
+                    object.set(fittingMode(ls, maxP, arraySpeed, arrayPower, dimension, mode));
+                }else {
+                    for (Powerfittinganalysis obj : ls) {
+                        List<Powerfittinganalysis> collect = new ArrayList<>();
+                        collect.add(obj);
+                        List<Double> arraySpeed = new ArrayList<>();
+                        List<Double> arrayPower = new ArrayList<>();
+                        List<String> line = FileUtil.readFile(collect.get(0).getPath(), true);
+                        csvParse(line, arraySpeed, arrayPower, mins, maxs, minp, maxp);
+                        List<Modelpowerdetails> mp = InitialRunner.modelPowerDetailMap.get(InitialRunner.wtMap.get(list.get(0).getWindturbine()).getModelid());
+                        Double maxP = mp.stream().map(Modelpowerdetails::getEnsurepower).max(Comparator.comparing(Double::doubleValue)).get();
+                        object.set(fittingMode(collect, maxP, arraySpeed, arrayPower, dimension, mode));
+                    }
+                }
+            });
+        }
+
+        return object.get();
+    }
+
+
+    /**
+     * 拟合模块展示  tree
+     * @return
+     */
+    public List<Object> dataFittingTree(){
+        List<Powerfittinganalysis> list = powerService.selectList(Constants.DATA_FITTING);
+        List<Object> ls = PowerFittingUtil.powerDataTree(list, Constants.DATA_FITTING);
+        return ls;
+    }
+
+    /**
+     * 组装表格数据
+     * @param id
+     * @return
+     */
+    public Map<String, Object> dataFittingShow(String id){
+        Map<String, Object> map = new HashMap<>();
+
+        /** 添加标题 **/
+        List<TableTitle> lt = new ArrayList<>();
+        StringBuilder sb = setTitle();
+        String[] str = sb.toString().split(",");
+        for (String s : str){
+            lt.add(new TableTitle(s));
+        }
+
+        /** 添加内容 **/
+        List<PowerFittingPoint> list = new ArrayList<>();
+        Powerfittinganalysis obj = powerService.selectItemById(id);
+        List<String> ls = FileUtil.readFile(obj.getPath(), false);
+        for (int i = 1; i < ls.size(); i++){
+            PowerFittingPoint data = new PowerFittingPoint(ls.get(i).split(","));
+            list.add(data);
+        }
+
+        map.put("title", lt);
+        map.put("data", list);
+
+        return map;
+    }
+
+
+    /**
+     * 曲线,散点等数据
+     * 风速 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<>();
+        Powerfittinganalysis obj = powerService.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++){
+            String[] split = ls.get(i).split(",");
+            sjglList.add(new double[]{Double.valueOf(split[0]), Double.valueOf(split[1])});
+            cpzList.add(new double[]{Double.valueOf(split[0]), Double.valueOf(split[2])});
+        }
+
+        //保证功率
+        List<Modelpowerdetails> modelPower = InitialRunner.modelPowerDetailMap.get(InitialRunner.wtMap.get(obj.getWindturbine()).getModelid());
+        List<Object> bzglList = modelPower.stream().sorted(Comparator.comparing(Modelpowerdetails::getSpeed)).map(m -> new double[]{m.getSpeed(), m.getEnsurepower()}).collect(Collectors.toList());
+
+        //散点
+        String[] ids = obj.getPrepareid().split(",");
+        List<PowerPointData> yyd = new ArrayList<>(); //有用点
+        List<PowerPointData> wyd = new ArrayList<>(); //无用点
+        for (String pid : ids){
+            Powerfittinganalysis pf = powerService.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);
+                if (pd.getSpeed() < 0 || pd.getPower() < 0)
+                    continue;
+                pd.setWtId(pf.getWindturbine());
+                pd.setFilter(Integer.parseInt(split[9]));
+                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) -> {
+            listYY.add(new PointVo(v.get(0).getSpeed(), v.get(0).getPower(), dataScanService.getMapYY().get(k).size() + 3, k));
+        });
+        dataScanService.getMapWY().forEach((k, v) -> {
+            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);     //对象
+        map.put("yyd", listYY);  //有用散点
+        map.put("wyd", listWY);  //无用散点
+
+        return map;
+    }
+
+    private String assemble(LineCurveFitting lf){
+        StringBuilder sb = setTitle();
+        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();
+    }
+
+
+    private StringBuilder setTitle(){
+        StringBuilder sb = new StringBuilder();
+        String columnName = String.join(",", Constants.FITTING_TITLE);
+        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(",");
+            int filter = Integer.valueOf(split[9]); //是否过滤 0:没过滤 1:过滤
+            double x = Double.valueOf(split[2]);    //风速
+            double y = Double.valueOf(split[1]);    //功率
+            if (filter == 0 && (x >= mins && x <= maxs && y >= minp && y <= maxp)) {
+                arrayS.add(x);
+                arrayP.add(y);
+            }
+        }
+    }
+
+    private Powerfittinganalysis fittingMode(List<Powerfittinganalysis> list, Double powerMax, List<Double> arraySpeed, List<Double> arrayPower, Integer dimension, int mode){
+        if (list == null || list.size() == 0)
+            return null;
+
+        Powerfittinganalysis 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(InitialRunner.equipmentMap.get(InitialRunner.wtMap.get(obj.getWindturbine()).getModelid()).getSweptarea(), lf);
+
+        //曲线偏差率
+        List<Point> pointsAll = new ArrayList<>();
+        List<Modelpowerdetails> mp = InitialRunner.modelPowerDetailMap.get(InitialRunner.wtMap.get(obj.getWindturbine()).getModelid());
+        for (int i = 0; i < mp.size(); i++){
+            Modelpowerdetails power = mp.get(i);
+            pointsAll.add(new Point(power.getSpeed(), power.getEnsurepower()));
+        }
+        double maxp = mp.stream().max(Comparator.comparing(d -> d.getEnsurepower())).get().getEnsurepower();
+        double pcl = PowerFittingALG.curveDeviationRatio(temp, pointsAll, maxp);
+
+        String content = assemble(lf);
+        String prepareId = "";
+        String fileName = null;
+        if (mode == 0){
+            prepareId = obj.getId();
+            fileName = config.getFilePathFitting() + obj.getStation() + "_" + obj.getCode() + "_" + SnowFlakeUtil.generateIdL() / 100000 + ".csv";
+        }
+        if (mode == 1){
+            prepareId = list.stream().map(d -> d.getId()).collect(Collectors.joining(","));
+            fileName = config.getFilePathFitting() + obj.getStation() + "_merge" + "_" + SnowFlakeUtil.generateIdL() / 100000 + ".csv";
+        }
+        if (mode == 2){
+            prepareId = list.stream().map(d -> d.getId()).collect(Collectors.joining(","));
+            fileName = config.getFilePathFitting() + obj.getStation() + "_same" + "_" + SnowFlakeUtil.generateIdL() / 100000 + ".csv";
+        }
+        boolean flag = FileUtil.writeFile(fileName, content);
+        if (flag) {  // TODO  保存数据库
+            obj.setPath(fileName);
+            obj.setPrepareid(prepareId);
+            obj.setCpavg(lf.getCpAvg());
+            obj.setPcratio(pcl);
+            obj.setType(Constants.DATA_FITTING);
+            powerService.insertItem(obj);
+        }
+        System.out.println("功率曲线拟合完成:" + obj.getWindturbine());
+
+        return obj;
+    }
+
+    /**
+     * 通过大点的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
+     *  3-5  5-10  10-12  12-25
+     * @return
+     */
+    public Map<String, Double> dataCurveRatio(String id) {
+        Map<String, Double> map = new HashMap<>();
+        DecimalFormat df = new DecimalFormat("0.00");
+        Powerfittinganalysis obj = powerService.selectItemById(id);
+        try{
+            //风速、实际功率
+            List<Point> point5 = new ArrayList<>();  //分段
+            List<Point> point10 = new ArrayList<>();  //分段
+            List<Point> point12= new ArrayList<>();  //分段
+            List<Point> point25 = new ArrayList<>();  //分段
+            List<String> ls = FileUtil.readFile(obj.getPath(), true);
+            for (int i = 1; i < ls.size(); i++){
+                String[] split = ls.get(i).split(",");
+                double speed = Double.valueOf(split[0]);
+                if (speed >= 3 && speed < 5)
+                    point5.add(new Point(speed, Double.valueOf(split[1])));
+                if (speed >= 5 && speed < 10)
+                    point10.add(new Point(speed, Double.valueOf(split[1])));
+                if (speed >= 10 && speed < 12)
+                    point12.add(new Point(speed, Double.valueOf(split[1])));
+                if (speed >= 12 && speed <= 25)
+                    point25.add(new Point(speed, Double.valueOf(split[1])));
+            }
+
+            //保证功率
+            List<Point> points5 = new ArrayList<>();  //分段
+            List<Point> points10 = new ArrayList<>();  //分段
+            List<Point> points12 = new ArrayList<>();  //分段
+            List<Point> points25 = new ArrayList<>();  //分段
+            List<Modelpowerdetails> list = InitialRunner.modelPowerDetailMap.get(InitialRunner.wtMap.get(obj.getWindturbine()).getModelid());
+            for (int i = 0; i < list.size(); i++){
+                Modelpowerdetails 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()));
+            }
+
+            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 pcl5 = PowerFittingALG.curveDeviationRatio2(point5, points5, maxp5, 3);
+            double pcl10 = PowerFittingALG.curveDeviationRatio2(point10, points10, maxp10, 5);
+            double pcl12 = PowerFittingALG.curveDeviationRatio2(point12, points12, maxp12, 10);
+            double pcl25 = PowerFittingALG.curveDeviationRatio2(point25, points25, maxp25, 12);
+
+            map.put("pcl5", Double.valueOf(df.format(pcl5)));
+            map.put("pcl10", Double.valueOf(df.format(pcl10)));
+            map.put("pcl12", Double.valueOf(df.format(pcl12)));
+            map.put("pcl25", Double.valueOf(df.format(pcl25)));
+
+        } catch (Exception e){
+            log.error("DataFittingService--dataCurveRatio",e);
+        }
+
+        return map;
+    }
+
+
+    /**
+     * 多风机功率曲线展示
+     * @param ids
+     * @return
+     */
+    public Object dataFittingLine(String ids) {
+        List<Object> result = new ArrayList<>();
+        List<Powerfittinganalysis> list = powerService.selectListByIds(ids);
+        if (list.size() == 0)
+            return result;
+
+        list.forEach(item -> {
+            //实际功率、风速
+            Map<String, Object> map = new HashMap<>();
+            List<Object> sjgl = new ArrayList<>();
+            List<String> ls = FileUtil.readFile(item.getPath(), true);
+            for (int i = 1; i < ls.size(); i++){
+                String[] split = ls.get(i).split(",");
+                sjgl.add(new double[]{Double.valueOf(split[0]), Double.valueOf(split[1])});
+            }
+            map.put("wtId", item.getWindturbine());
+            map.put("sjgl", sjgl);
+            result.add(map);
+        });
+
+        //保证功率
+        List<Modelpowerdetails> modelPower = InitialRunner.modelPowerDetailMap.get(InitialRunner.wtMap.get(list.get(0).getWindturbine()).getModelid());
+        List<Object> bzgl = modelPower.stream().sorted(Comparator.comparing(Modelpowerdetails::getSpeed)).map(m -> new double[]{m.getSpeed(), m.getEnsurepower()}).collect(Collectors.toList());
+
+        Map<String, Object> map = new HashMap<>();
+        map.put("sjgl", result);
+        map.put("bzgl", bzgl);
+
+        return map;
+    }
+}

+ 161 - 0
power-fitting/src/main/java/com/gyee/power/fitting/service/custom/curve/DataPrepareService.java

@@ -0,0 +1,161 @@
+package com.gyee.power.fitting.service.custom.curve;
+
+import com.gyee.power.fitting.common.config.GyeeConfig;
+import com.gyee.power.fitting.common.constants.Constants;
+import com.gyee.power.fitting.common.feign.RemoteServiceBuilder;
+import com.gyee.power.fitting.common.result.JsonResult;
+import com.gyee.power.fitting.common.result.ResultCode;
+import com.gyee.power.fitting.common.spring.InitialRunner;
+import com.gyee.power.fitting.common.util.*;
+import com.gyee.power.fitting.model.Powerfittinganalysis;
+import com.gyee.power.fitting.model.Windturbinetestingpointai2;
+import com.gyee.power.fitting.model.custom.PowerPointData;
+import com.gyee.power.fitting.model.custom.TableTitle;
+import com.gyee.power.fitting.model.custom.TsDoubleData;
+import com.gyee.power.fitting.service.PowerfittinganalysisService;
+import com.gyee.power.fitting.service.custom.socket.WebSocketServer;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+import java.text.DecimalFormat;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+public class DataPrepareService {
+
+    @Autowired
+    private GyeeConfig config;
+    @Autowired
+    WebSocketServer socketServer;
+    @Autowired
+    private PowerfittinganalysisService powerService;
+    @Autowired
+    private RemoteServiceBuilder remoteService;
+
+    /**
+     * 数据准备
+     * @param station 场站
+     * @param wtId  风机ID eg:<NG01_01,NG01_02>
+     * @param st 开始时间  毫秒
+     * @param et 结束时间
+     */
+    @Async
+    public void dataPrepare(String station, List<String> wtId, long st, long et, int interval){
+        for (int k = 0; k < wtId.size(); k++){
+            String wt = wtId.get(k);
+            List<List<TsDoubleData>> result = new ArrayList<>();
+            try{
+                List<String> points = config.getPoints();
+                Map<String, List<Windturbinetestingpointai2>> collect = InitialRunner.pointMap.get(wt).stream().collect(Collectors.groupingBy(w -> w.getUniformcode()));
+                if (collect.size() < 8)
+                    continue;
+
+                for (int i = 0; i < points.size(); i++){
+                    Windturbinetestingpointai2 point = collect.get(points.get(i)).get(0);
+                    List<TsDoubleData> data = remoteService.adapter().getHistorySnap(point.getId(), st, et, interval);
+                    if (data == null || data.size() < 0)
+                        break;
+                    result.add(data);
+                    Thread.sleep(200);
+                }
+                if (result.size() != points.size())
+                    continue;
+
+                String content = assemble(result);
+                // 处理的数据保存在本地
+                String wtCode = InitialRunner.wtMap.get(wt).getCode();
+                String fileName = config.getFilePathPrepare() + station + "_" + wtCode + "_" + System.currentTimeMillis() / 1000 + ".csv";
+                boolean flag = FileUtil.writeFile(fileName, content);
+                if (flag){  // TODO  保存数据库
+                    Powerfittinganalysis obj = new Powerfittinganalysis();
+                    obj.setStation(station);
+                    obj.setStationcn(InitialRunner.stationMap.get(station));
+                    obj.setWindturbine(wt);
+                    obj.setCode(wtCode);
+                    obj.setTime(DateUtil.format(st, DateUtil.YYYY_MM_DD_CHN) + "-" + DateUtil.format(et, DateUtil.YYYY_MM_DD_CHN));
+                    obj.setInterval(NumberUtil.toNum(interval));
+                    obj.setPath(fileName);
+                    obj.setType(Constants.DATA_PREPARE);
+                    powerService.insertItem(obj);
+                }
+                socketServer.sendInfo(JsonResult.successData(ResultCode.SUCCESS, new DecimalFormat("0.00").format((double)(k + 1)/wtId.size())), null);
+                System.out.println("数据准备完成:" + wt);
+            } catch (Exception e) {
+                socketServer.sendInfo(JsonResult.error(), null);
+            } finally {}
+        }
+    }
+
+
+    /**
+     * 数据准备模块展示  tree
+     * @return
+     */
+    public List<Object> dataPrepareTree(){
+        List<Powerfittinganalysis> list = powerService.selectList(Constants.DATA_PREPARE);
+        List<Object> ls = PowerFittingUtil.powerDataTree(list, Constants.DATA_PREPARE);
+        return ls;
+    }
+
+
+    /**
+     * 组装表格数据
+     * @param id
+     * @return
+     */
+    public Map<String, Object> dataPrepareShow(String id){
+        Map<String, Object> map = new HashMap<>();
+
+        /** 添加标题 **/
+        List<TableTitle> lt = new ArrayList<>();
+        StringBuilder sb = setTitle();
+        String[] str = sb.toString().split(",");
+        for (String s : str){
+            lt.add(new TableTitle(s));
+        }
+
+        /** 添加内容  读取前500行 **/
+        List<PowerPointData> list = new ArrayList<>();
+        Powerfittinganalysis obj = powerService.selectItemById(id);
+        List<String> ls = FileUtil.readFile(obj.getPath(), false);
+        for (int i = 1; i < ls.size(); i++){
+            PowerPointData data = new PowerPointData(ls.get(i).split(","));
+            list.add(data);
+        }
+
+        map.put("title", lt);
+        map.put("data", list);
+
+        return map;
+    }
+
+    private String assemble(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(",");
+            sb.append(data.get(i).getDoubleValue()).append(",");
+            for (int j = 1; j < list.size(); j++){
+                sb.append(list.get(j).get(i).getDoubleValue()).append(",");
+            }
+            sb.append("\n");
+        }
+
+        return sb.toString();
+    }
+
+    private StringBuilder setTitle(){
+        StringBuilder sb = new StringBuilder();
+        String columnName = String.join(",", Constants.TABLE_TITLE);
+        sb.append(columnName).append("\n");
+        return sb;
+    }
+
+}

+ 162 - 0
power-fitting/src/main/java/com/gyee/power/fitting/service/custom/curve/DataProcessService.java

@@ -0,0 +1,162 @@
+package com.gyee.power.fitting.service.custom.curve;
+
+import com.gyee.power.fitting.common.alg.PowerFittingALG;
+import com.gyee.power.fitting.common.alg.PowerProcessALG;
+import com.gyee.power.fitting.common.config.GyeeConfig;
+import com.gyee.power.fitting.common.constants.Constants;
+import com.gyee.power.fitting.common.spring.InitialRunner;
+import com.gyee.power.fitting.common.util.*;
+import com.gyee.power.fitting.model.Modelpowerdetails;
+import com.gyee.power.fitting.model.Powerfittinganalysis;
+import com.gyee.power.fitting.model.custom.PowerPointData;
+import com.gyee.power.fitting.model.custom.TableTitle;
+import com.gyee.power.fitting.service.PowerfittinganalysisService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+public class DataProcessService {
+
+    @Autowired
+    private GyeeConfig config;
+    @Autowired
+    private PowerfittinganalysisService powerService;
+
+    /**
+     * 数据预处理
+     *
+     * @param ids     预处理数据的ID
+     * @param maxs   最大风速
+     * @param mins   最小风速
+     * @param maxp   最大功率
+     * @param minp   最小功率
+     * @param isfbw  是否并网
+     * @param isfhl  是否合理值
+     * @param isbw   并网后10分钟
+     * @param istj   停机前10分钟
+     * @param isglpc 功率曲线偏差
+     * @param isqfh  是否欠符合
+     * @param qfhdj  欠符合等级
+     * @return
+     */
+    public void dataProcess(List<String> ids, Double maxs, Double mins, Double maxp, Double minp, Boolean isfbw,
+                            Boolean isfhl, Boolean isbw, Boolean istj, Boolean isglpc, Boolean isqfh, Integer qfhdj) {
+        ids.forEach(id -> {
+            Powerfittinganalysis obj = powerService.selectItemById(id);
+            if (obj == null)
+                return;
+
+            /** 读取csv数据  转换成对象数组 **/
+            List<PowerPointData> eis = new ArrayList<>();
+            List<String> list = FileUtil.readFile(obj.getPath(), true);
+            for (int i = 1; i < list.size(); i++) {
+                eis.add(new PowerPointData(list.get(i).split(",")));
+            }
+
+            /** 风速  ->  保证功率  来自数据库 **/
+            List<Modelpowerdetails> modelPowerList = InitialRunner.modelPowerDetailMap.get(InitialRunner.wtMap.get(obj.getWindturbine()).getModelid());
+            Map<Double, Double> modelPowerMap = modelPowerList.stream().collect(Collectors.toMap(Modelpowerdetails::getSpeed, Modelpowerdetails::getEnsurepower));
+
+            /** 数据预处理 **/
+            List<PowerPointData> data = PowerProcessALG.dataProcess(eis, modelPowerMap, maxs, mins, maxp, minp, isfbw, isfhl, isbw, istj, isglpc, isqfh, qfhdj);
+
+
+            /** 静风频率 **/
+            double frequency = PowerFittingALG.frequency(data.stream().map(PowerPointData::getSpeed).collect(Collectors.toList()), 3);
+
+            String content = assemble(data);
+            String fileName = config.getFilePathProcess() + obj.getStation() + "_" + obj.getCode() + "_" + SnowFlakeUtil.generateIdL() / 100000 + ".csv";
+            boolean flag = FileUtil.writeFile(fileName, content);
+            if (flag) {  // TODO  保存数据库
+                obj.setPath(fileName);
+                obj.setFrequency(frequency);
+                obj.setType(Constants.DATA_PROCESS);
+                powerService.insertItem(obj);
+            }
+            System.out.println("功率曲线拟合数据预处理完成:" + obj.getWindturbine());
+        });
+    }
+
+    /**
+     * 数据预处理模块展示  tree
+     *
+     * @return
+     */
+    public List<Object> dataProcessTree() {
+        List<Powerfittinganalysis> list = powerService.selectList(Constants.DATA_PROCESS);
+        List<Object> ls = PowerFittingUtil.powerDataTree(list, Constants.DATA_PROCESS);
+        return ls;
+    }
+
+
+    /**
+     * 组装表格数据
+     * @param id
+     * @return
+     */
+    public Map<String, Object> dataProcessShow(String id){
+        Map<String, Object> map = new HashMap<>();
+
+        /** 添加标题 **/
+        List<TableTitle> lt = new ArrayList<>();
+        StringBuilder sb = setTitle();
+        String[] str = sb.toString().split(",");
+        for (String s : str){
+            lt.add(new TableTitle(s));
+        }
+
+        /** 添加内容  读取前500行 **/
+        List<PowerPointData> list = new ArrayList<>();
+        Powerfittinganalysis obj = powerService.selectItemById(id);
+        List<String> ls = FileUtil.readFile(obj.getPath(), false);
+        for (int i = 1; i < ls.size(); i++){
+            String[] split = ls.get(i).split(",");
+            PowerPointData data = new PowerPointData(split);
+            data.setFilter(Integer.valueOf(split[9]));
+            list.add(data);
+        }
+
+        map.put("title", lt);
+        map.put("data", list);
+
+        return map;
+    }
+
+
+    private String assemble(List<PowerPointData> list) {
+        if (list.size() == 0)
+            return null;
+
+        StringBuilder sb = setTitle();
+        for (int i = 0; i < list.size(); i++) {
+            sb.append(list.get(i).getTime()).append(",");
+            sb.append(list.get(i).getPower()).append(",");
+            sb.append(list.get(i).getSpeed()).append(",");
+            sb.append(list.get(i).getRR()).append(",");
+            sb.append(list.get(i).getMxzt()).append(",");
+            sb.append(list.get(i).getDL()).append(",");
+            sb.append(list.get(i).getQfzt()).append(",");
+            sb.append(list.get(i).getFX()).append(",");
+            sb.append(list.get(i).getAngle()).append(",");
+            sb.append(list.get(i).getFilter()).append(",");
+            sb.append("\n");
+        }
+
+        return sb.toString();
+    }
+
+    private StringBuilder setTitle() {
+        StringBuilder sb = new StringBuilder();
+        List<String> tableTitle = new ArrayList<>();
+        tableTitle.addAll(Constants.TABLE_TITLE);
+        tableTitle.add("筛选");
+        String columnName = String.join(",", tableTitle);
+        sb.append(columnName).append("\n");
+        return sb;
+    }
+
+}

+ 20 - 0
power-fitting/src/main/java/com/gyee/power/fitting/service/custom/curve/DataScanService.java

@@ -0,0 +1,20 @@
+package com.gyee.power.fitting.service.custom.curve;
+
+import com.gyee.power.fitting.model.custom.PowerPointData;
+import lombok.Data;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 散点聚合实例
+ */
+@Data
+@Component
+public class DataScanService {
+
+    public Map<String, List<PowerPointData>> mapYY;
+
+    public Map<String, List<PowerPointData>> mapWY;
+}

+ 117 - 0
power-fitting/src/main/java/com/gyee/power/fitting/service/custom/fx/WindDirectionService.java

@@ -0,0 +1,117 @@
+package com.gyee.power.fitting.service.custom.fx;
+
+import com.gyee.power.fitting.common.alg.WindDirectionALG;
+import com.gyee.power.fitting.common.util.FileUtil;
+import com.gyee.power.fitting.model.Powerfittinganalysis;
+import com.gyee.power.fitting.model.custom.PowerPointData;
+import com.gyee.power.fitting.service.PowerfittinganalysisService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;;
+
+
+@Service
+public class WindDirectionService {
+
+    @Autowired
+    private PowerfittinganalysisService powerService;
+
+
+    /**
+     * 风向玫瑰图\风向频率玫瑰图
+     * @param ids  预处理数据的id
+     * @param mode  0:单台风机  1:多台风机合并
+     * @return
+     */
+    public Object fxRoses(String ids, int mode){
+        List<Powerfittinganalysis> list = powerService.selectListByIds(ids);
+        if (list == null || list.size() == 0)
+            return null;
+
+        List<Object> result = new ArrayList<>();
+        if (mode == 0){
+            for (Powerfittinganalysis obj : list){
+                Map<String, Object> map = new HashMap<>();
+                List<PowerPointData> ls = csvParse(obj);
+                map.put("wt", obj.getWindturbine());
+                map.put("roses", WindDirectionALG.fxRoses(ls));
+                map.put("count", WindDirectionALG.fxCountRoses(ls));
+                map.put("radar", WindDirectionALG.fxRadarRoses(ls));
+                result.add(map);
+            }
+        }
+        if (mode == 1){
+            List<PowerPointData> ls = new ArrayList<>();
+            for (Powerfittinganalysis obj : list)
+                ls.addAll(csvParse(obj));
+            Map<String, Object> map = new HashMap<>();
+            map.put("wt", "merge");
+            map.put("roses", WindDirectionALG.fxRoses(ls));
+            map.put("count", WindDirectionALG.fxCountRoses(ls));
+            map.put("radar", WindDirectionALG.fxRadarRoses(ls));
+            result.add(map);
+        }
+
+        return result;
+    }
+
+
+    /**
+     * 风向频率玫瑰图
+     * @param ids  预处理数据的id
+     * @param mode  0:单台风机  1:多台风机合并
+     * @return
+     */
+    public Object fxCountRoses(String ids, int mode){
+        List<Powerfittinganalysis> list = powerService.selectListByIds(ids);
+        if (list == null || list.size() == 0)
+            return null;
+
+        List<Object> result = new ArrayList<>();
+        if (mode == 0){
+            for (Powerfittinganalysis obj : list){
+                Map<String, Object> map = new HashMap<>();
+                List<PowerPointData> ls = csvParse(obj);
+                int[][] ints = WindDirectionALG.fxCountRoses(ls);
+                map.put("wt", obj.getWindturbine());
+                map.put("data", ints);
+                result.add(map);
+            }
+        }
+        if (mode == 1){
+            List<PowerPointData> ls = new ArrayList<>();
+            for (Powerfittinganalysis obj : list)
+                ls.addAll(csvParse(obj));
+
+            Map<String, Object> map = new HashMap<>();
+            int[][] ints = WindDirectionALG.fxCountRoses(ls);
+            map.put("wt", "merge");
+            map.put("data", ints);
+            result.add(map);
+        }
+
+        return result;
+    }
+
+
+    /**
+     * csv 文件解析成对象
+     * @param obj
+     * @return
+     */
+    private List<PowerPointData> csvParse(Powerfittinganalysis obj){
+        List<PowerPointData> ls = new ArrayList<>();
+        List<String> content = FileUtil.readFile(obj.getPath(), true);
+        for (int i = 1; i < content.size(); i++){
+            String[] split = content.get(i).split(",");
+            PowerPointData data = new PowerPointData(split);
+            if (data.getSpeed() < 0 || data.getPower() < 0)
+                continue;
+            data.setWtId(obj.getWindturbine());
+            data.setFilter(Integer.parseInt(split[9]));
+            ls.add(data);
+        }
+        return ls;
+    }
+}

+ 85 - 0
power-fitting/src/main/java/com/gyee/power/fitting/service/custom/ratio/RatioService.java

@@ -0,0 +1,85 @@
+package com.gyee.power.fitting.service.custom.ratio;
+
+
+import com.gyee.power.fitting.common.alg.PowerFittingALG;
+import com.gyee.power.fitting.common.util.FileUtil;
+import com.gyee.power.fitting.model.Powerfittinganalysis;
+import com.gyee.power.fitting.model.custom.Point;
+import com.gyee.power.fitting.model.custom.PointVo;
+import com.gyee.power.fitting.service.PowerfittinganalysisService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+public class RatioService {
+
+    @Autowired
+    private PowerfittinganalysisService powerService;
+
+
+    /**
+     * 对风偏差率
+     * @param ids
+     * @return
+     */
+    public List<Object> windDeviationRatio(String ids, int mode){
+        List<Object> list = new ArrayList<>();
+
+        List<Powerfittinganalysis> listObj = powerService.selectListByIds(ids);
+        if (mode == 0){
+            listObj.forEach(obj -> {
+                List<PointVo> points = csvParse(obj);
+                int[] count = PowerFittingALG.windDeviationRatio(points);
+                List<Point> scatter = PowerFittingALG.windDeviationScatter(points);
+                Map<String, Object> map = new HashMap<>();
+                map.put("wtId", obj.getWindturbine());
+                map.put("count", count);
+                map.put("scatter", scatter);
+                list.add(map);
+            });
+        }
+        if (mode == 1){
+            List<PointVo> ls = new ArrayList<>();
+            listObj.forEach(obj -> {
+                List<PointVo> points = csvParse(obj);
+                ls.addAll(points);
+            });
+            int[] count = PowerFittingALG.windDeviationRatio(ls);
+            List<Point> scatter = PowerFittingALG.windDeviationScatter(ls);
+            Map<String, Object> map = new HashMap<>();
+            map.put("wtId", "merge");
+            map.put("count", count);
+            map.put("scatter", scatter);
+            list.add(map);
+        }
+
+        return list;
+    }
+
+    /**
+     * csv 文件解析成对象
+     * @param obj
+     * @return
+     */
+    private List<PointVo> csvParse(Powerfittinganalysis obj){
+        List<PointVo> list = new ArrayList<>();
+        DecimalFormat df = new DecimalFormat("0.00");
+        List<String> content = FileUtil.readFile(obj.getPath(), true);
+        for (int i = 1; i < content.size(); i++){
+            String[] split = content.get(i).split(",");
+            PointVo point = new PointVo();
+            point.setX(Double.parseDouble(df.format(Double.parseDouble(split[7]))));  //风向
+            point.setY(Double.parseDouble(df.format(Double.parseDouble(split[8]))));  //对风角度
+            point.setS(Double.parseDouble(df.format(Double.parseDouble(split[2]))));  //风速
+            list.add(point);
+        }
+
+        return list;
+    }
+}

+ 174 - 0
power-fitting/src/main/java/com/gyee/power/fitting/service/custom/socket/WebSocketServer.java

@@ -0,0 +1,174 @@
+package com.gyee.power.fitting.service.custom.socket;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.extension.exceptions.ApiException;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import javax.websocket.*;
+import javax.websocket.server.PathParam;
+import javax.websocket.server.ServerEndpoint;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ **/
+@Slf4j
+@ServerEndpoint("/ws/powerfitting/{userId}")
+@Component
+public class WebSocketServer {
+
+    /**
+     * 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的
+     */
+    private static int onlineCount = 0;
+
+    /**
+     * concurrent 包的线程安全Set,用来存放每个客户端对应的 myWebSocket对象
+     * 根据userId来获取对应的 WebSocket
+     */
+    private static ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();
+
+    /**
+     * 与某个客户端的连接会话,需要通过它来给客户端发送数据
+     */
+    private Session session;
+
+    /**
+     * 接收 sid
+     */
+    private String userId = "";
+
+
+    /**
+     * 连接建立成功调用的方法
+     *
+     * @param session
+     * @param userId
+     */
+    @OnOpen
+    public void onOpen(Session session, @PathParam("userId") String userId) {
+        this.session = session;
+        this.userId = userId;
+
+        webSocketMap.put(userId, this);
+        log.info("webSocketMap -> " + JSON.toJSONString(webSocketMap));
+
+        addOnlineCount(); // 在线数 +1
+        log.info("有新窗口开始监听:" + userId + ",当前在线人数为" + getOnlineCount());
+
+        try {
+            sendMessage("连接成功");
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new ApiException("websocket IO异常!!!!");
+        }
+
+    }
+
+    /**
+     * 关闭连接
+     */
+
+    @OnClose
+    public void onClose() {
+        if (webSocketMap.get(this.userId) != null) {
+            webSocketMap.remove(this.userId);
+            subOnlineCount(); // 人数 -1
+            log.info("有一连接关闭,当前在线人数为:" + getOnlineCount());
+        }
+    }
+
+    /**
+     * 收到客户端消息后调用的方法
+     *
+     * @param message 客户端发送过来的消息
+     * @param session
+     */
+    @OnMessage
+    public void onMessage(String message, Session session) {
+        log.info("收到来自窗口" + userId + "的信息:" + message);
+
+        if (StringUtils.isNotBlank(message)) {
+            try {
+                // 解析发送的报文
+                JSONObject jsonObject = JSON.parseObject(message);
+                // 追加发送人(防窜改)
+                jsonObject.put("fromUserId", this.userId);
+                String toUserId = jsonObject.getString("toUserId");
+                // 传送给对应 toUserId 用户的 WebSocket
+                if (StringUtils.isNotBlank(toUserId) && webSocketMap.containsKey(toUserId)) {
+                    webSocketMap.get(toUserId).sendMessage(jsonObject.toJSONString());
+                } else {
+                    log.info("请求的userId:" + toUserId + "不在该服务器上"); // 否则不在这个服务器上,发送到 MySQL 或者 Redis
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+    }
+
+    /**
+     * @param session
+     * @param error
+     */
+    @OnError
+    public void onError(Session session, Throwable error) {
+        log.error("用户错误:" + this.userId + ",原因:" + error.getMessage());
+        error.printStackTrace();
+    }
+
+    /**
+     * 实现服务器主动推送
+     *
+     * @param message
+     * @throws IOException
+     */
+    @SneakyThrows
+    public void sendMessage(Object message) {
+        this.session.getBasicRemote().sendText(JSONObject.toJSONString(message));
+    }
+
+    /**
+     * 群发自定义消息
+     *
+     * @param message
+     * @param userId
+     * @throws IOException
+     */
+    public void sendInfo(Object message, @PathParam("userId") String userId) {
+
+        // 遍历集合,可设置为推送给指定sid,为 null 时发送给所有人
+        Iterator entrys = webSocketMap.entrySet().iterator();
+        while (entrys.hasNext()) {
+            Map.Entry entry = (Map.Entry) entrys.next();
+
+            if (userId == null) {
+                webSocketMap.get(entry.getKey()).sendMessage(message);
+                log.info("发送消息到:" + entry.getKey() + ",消息:" + message);
+            } else if (entry.getKey().equals(userId)) {
+                webSocketMap.get(entry.getKey()).sendMessage(message);
+                log.info("发送消息到:" + entry.getKey() + ",消息:" + message);
+            }
+
+        }
+    }
+
+    private static synchronized int getOnlineCount() {
+        return onlineCount;
+    }
+
+    private static synchronized void addOnlineCount() {
+        WebSocketServer.onlineCount++;
+    }
+
+    private static synchronized void subOnlineCount() {
+        WebSocketServer.onlineCount--;
+    }
+}

+ 46 - 0
power-fitting/src/main/java/com/gyee/power/fitting/service/impl/EquipmentmodelServiceImpl.java

@@ -0,0 +1,46 @@
+package com.gyee.power.fitting.service.impl;
+
+import com.gyee.power.fitting.model.Equipmentmodel;
+import com.gyee.power.fitting.mapper.EquipmentmodelMapper;
+import com.gyee.power.fitting.service.EquipmentmodelService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author chenmh
+ * @since 2022-11-08
+ */
+@Service
+public class EquipmentmodelServiceImpl extends ServiceImpl<EquipmentmodelMapper, Equipmentmodel> implements EquipmentmodelService {
+
+    @Override
+    public List<Equipmentmodel> selectList() {
+        List<Equipmentmodel> list = new ArrayList<>();
+        try{
+            list = baseMapper.selectList(null);
+        }catch (Exception e){
+            log.error("EquipmentmodelServiceImpl--selectList", e);
+        }
+
+        return list;
+    }
+
+    @Override
+    public Equipmentmodel selectItemByModel(String id) {
+        Equipmentmodel obj = new Equipmentmodel();
+        try{
+            obj = baseMapper.selectById(id);
+        }catch (Exception e){
+            log.error("EquipmentmodelServiceImpl--selectItemByModel", e);
+        }
+
+        return obj;
+    }
+}

+ 34 - 0
power-fitting/src/main/java/com/gyee/power/fitting/service/impl/ModelpowerServiceImpl.java

@@ -0,0 +1,34 @@
+package com.gyee.power.fitting.service.impl;
+
+import com.gyee.power.fitting.model.Modelpower;
+import com.gyee.power.fitting.mapper.ModelpowerMapper;
+import com.gyee.power.fitting.service.ModelpowerService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author chenmh
+ * @since 2022-11-08
+ */
+@Service
+public class ModelpowerServiceImpl extends ServiceImpl<ModelpowerMapper, Modelpower> implements ModelpowerService {
+
+    @Override
+    public List<Modelpower> selectList() {
+        List<Modelpower> list = new ArrayList<>();
+        try{
+            list = baseMapper.selectList(null);
+        }catch (Exception e){
+            log.error("ModelpowerServiceImpl--selectList", e);
+        }
+
+        return list;
+    }
+}

+ 37 - 0
power-fitting/src/main/java/com/gyee/power/fitting/service/impl/ModelpowerdetailsServiceImpl.java

@@ -0,0 +1,37 @@
+package com.gyee.power.fitting.service.impl;
+
+import com.gyee.power.fitting.common.base.ExcludeQueryWrapper;
+import com.gyee.power.fitting.model.Modelpowerdetails;
+import com.gyee.power.fitting.mapper.ModelpowerdetailsMapper;
+import com.gyee.power.fitting.service.ModelpowerdetailsService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author chenmh
+ * @since 2022-11-08
+ */
+@Service
+public class ModelpowerdetailsServiceImpl extends ServiceImpl<ModelpowerdetailsMapper, Modelpowerdetails> implements ModelpowerdetailsService {
+
+    @Override
+    public List<Modelpowerdetails> selectList() {
+        List<Modelpowerdetails> list = new ArrayList<>();
+        ExcludeQueryWrapper wrapper = new ExcludeQueryWrapper();
+        wrapper.orderByAsc("speed");
+        try{
+            list = baseMapper.selectList(wrapper);
+        }catch (Exception e){
+            log.error("ModelpowerdetailsServiceImpl--selectList", e);
+        }
+
+        return list;
+    }
+}

+ 92 - 0
power-fitting/src/main/java/com/gyee/power/fitting/service/impl/PowerfittinganalysisServiceImpl.java

@@ -0,0 +1,92 @@
+package com.gyee.power.fitting.service.impl;
+
+import com.gyee.power.fitting.common.base.ExcludeQueryWrapper;
+import com.gyee.power.fitting.common.util.SnowFlakeUtil;
+import com.gyee.power.fitting.model.Powerfittinganalysis;
+import com.gyee.power.fitting.mapper.PowerfittinganalysisMapper;
+import com.gyee.power.fitting.service.PowerfittinganalysisService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * <p>
+ *  服务实现类
+0 .00.000* </p>
+ *
+ * @author chenmh
+ * @since 2022-11-03
+ */
+@Service
+public class PowerfittinganalysisServiceImpl extends ServiceImpl<PowerfittinganalysisMapper, Powerfittinganalysis> implements PowerfittinganalysisService {
+
+    @Override
+    public Powerfittinganalysis selectItemById(String id) {
+        Powerfittinganalysis obj = new Powerfittinganalysis();
+
+        ExcludeQueryWrapper wrapper = new ExcludeQueryWrapper();
+        wrapper.eq("ID", id);
+        try{
+            obj = baseMapper.selectOne(wrapper);
+        }catch (Exception e){
+            log.error("PowerfittinganalysisServiceImpl--selectItemById", e);
+        }
+
+        return obj;
+    }
+
+    @Override
+    public List<Powerfittinganalysis> selectList(String type) {
+        List<Powerfittinganalysis> list = new ArrayList();
+
+        ExcludeQueryWrapper wrapper = new ExcludeQueryWrapper();
+        wrapper.eq("type", type);
+
+        try{
+            list = baseMapper.selectList(wrapper);
+        }catch (Exception e){
+            log.error("PowerfittinganalysisServiceImpl--selectList", e);
+        }
+
+        return list;
+    }
+
+
+    @Override
+    public void insertItem(Powerfittinganalysis obj) {
+        if (obj == null)
+            return;
+
+        obj.setId(SnowFlakeUtil.generateId());
+        try{
+            baseMapper.insert(obj);
+        }catch (Exception e){
+            log.error("PowerfittinganalysisServiceImpl--insertItem", e);
+        }
+    }
+
+    @Override
+    public List<Powerfittinganalysis> selectListByIds(String ids) {
+        List<Powerfittinganalysis> list = new ArrayList();
+
+        try{
+            list = baseMapper.selectBatchIds(Arrays.asList(ids.split(",")));
+        }catch (Exception e){
+            log.error("PowerfittinganalysisServiceImpl--selectListByIds", e);
+        }
+
+        return list;
+    }
+
+    @Override
+    public void deleteList(String ids) {
+        try{
+            baseMapper.deleteBatchIds(Arrays.asList(ids.split(",")));
+        }catch (Exception e){
+            log.error("PowerfittinganalysisServiceImpl--deleteList", e);
+        }
+    }
+}

+ 6 - 6
power-fetting/src/main/java/com/gyee/power/fetting/service/impl/WindpowerstationServiceImpl.java

@@ -1,10 +1,10 @@
-package com.gyee.power.fetting.service.impl;
+package com.gyee.power.fitting.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.gyee.power.fetting.common.base.ExcludeQueryWrapper;
-import com.gyee.power.fetting.mapper.WindpowerstationMapper;
-import com.gyee.power.fetting.model.Windpowerstation;
-import com.gyee.power.fetting.service.WindpowerstationService;
+import com.gyee.power.fitting.common.base.ExcludeQueryWrapper;
+import com.gyee.power.fitting.mapper.WindpowerstationMapper;
+import com.gyee.power.fitting.model.Windpowerstation;
+import com.gyee.power.fitting.service.WindpowerstationService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
@@ -32,7 +32,7 @@ public class WindpowerstationServiceImpl extends ServiceImpl<WindpowerstationMap
         try{
             list = baseMapper.selectList(wrapper);
         }catch (Exception e){
-            log.error("WindpowerstationServiceImpl", e.getMessage());
+            log.error("WindpowerstationServiceImpl--selectList", e);
         }
 
         return list;

+ 8 - 7
power-fetting/src/main/java/com/gyee/power/fetting/service/impl/WindturbineServiceImpl.java

@@ -1,10 +1,10 @@
-package com.gyee.power.fetting.service.impl;
+package com.gyee.power.fitting.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.gyee.power.fetting.common.base.ExcludeQueryWrapper;
-import com.gyee.power.fetting.mapper.WindturbineMapper;
-import com.gyee.power.fetting.model.Windturbine;
-import com.gyee.power.fetting.service.WindturbineService;
+import com.gyee.power.fitting.common.base.ExcludeQueryWrapper;
+import com.gyee.power.fitting.mapper.WindturbineMapper;
+import com.gyee.power.fitting.model.Windturbine;
+import com.gyee.power.fitting.service.WindturbineService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
@@ -24,15 +24,16 @@ import java.util.List;
 public class WindturbineServiceImpl extends ServiceImpl<WindturbineMapper, Windturbine> implements WindturbineService {
 
     @Override
-    public List<Windturbine> selectList() {
+    public List<Windturbine> selectList(String station) {
         List<Windturbine> list = new ArrayList();
 
         ExcludeQueryWrapper wrapper = new ExcludeQueryWrapper();
+        wrapper.eq("WINDPOWERSTATIONID", station);
 
         try{
             list = baseMapper.selectList(wrapper);
         }catch (Exception e){
-            log.error("WindturbineServiceImpl", e.getMessage());
+            log.error("WindturbineServiceImpl--selectList", e);
         }
 
         return list;

+ 40 - 0
power-fitting/src/main/java/com/gyee/power/fitting/service/impl/Windturbinetestingpointai2ServiceImpl.java

@@ -0,0 +1,40 @@
+package com.gyee.power.fitting.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.gyee.power.fitting.common.base.ExcludeQueryWrapper;
+import com.gyee.power.fitting.mapper.Windturbinetestingpointai2Mapper;
+import com.gyee.power.fitting.model.Windturbinetestingpointai2;
+import com.gyee.power.fitting.service.Windturbinetestingpointai2Service;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author chenmh
+ * @since 2022-11-01
+ */
+@Service
+public class Windturbinetestingpointai2ServiceImpl extends ServiceImpl<Windturbinetestingpointai2Mapper, Windturbinetestingpointai2> implements Windturbinetestingpointai2Service {
+
+    @Override
+    public List<Windturbinetestingpointai2> selectList(String station, List<String> points) {
+        List<Windturbinetestingpointai2> list = new ArrayList();
+
+        ExcludeQueryWrapper wrapper = new ExcludeQueryWrapper();
+        wrapper.eq("windpowerstationid", station);
+        wrapper.in("UNIFORMCODE", points);
+
+        try{
+            list = baseMapper.selectList(wrapper);
+        }catch (Exception e){
+            log.error("WindturbineServiceImpl--selectList", e);
+        }
+
+        return list;
+    }
+}

+ 30 - 10
power-fetting/src/main/resources/application.yaml

@@ -1,10 +1,26 @@
 gyee:
   # 实时适配器的url
   adapter-url: http://10.155.32.4:8011
-  # 数据准备路径(原始数据)
-  file-path-prepare: /home/gyee/data/prepare
-  # 数据处理路径(处理完的数据)
-  file-path-process: /home/gyee/data/precess
+  # 数据准备保存路径(原始数据)
+  file-path-prepare: data\prepare\
+  # 数据处理保存路径(处理后的数据)
+  file-path-process: data\precess\
+  # 数据拟合保存路径(拟合后的数据)
+  file-path-fitting: data\fitting\
+  # 数据压缩下载
+  file-path-download: data\zip\
+  # 风机实发功率\风机风速\发电机转速\明细状态\风机日发电量\实时欠发状态\风向\对风角度(对风误差)  顺序不能乱
+  points:
+    - AI130
+    - AI022
+    - AI128
+    - ZTMX
+    - RFDL
+    - RSSQFZT
+    - AI008
+    - AI036
+  # 数据准备时由于数据量太大,初始一个默认间隔,用于适配器取数
+  interval: 20
 
 server:
   port: 9002
@@ -24,12 +40,16 @@ spring:
     allow-bean-definition-overriding: false #当遇到同样名字的时候,是否允许覆盖注册
   datasource:
     type: com.alibaba.druid.pool.DruidDataSource
-    druid:
-      #kudu数据库
-      master:
-        driver-class-name: com.cloudera.impala.jdbc41.Driver
-        jdbc-url: jdbc:impala://192.168.1.62:21050/gyee_sample_kudu
+#    url: jdbc:oracle:thin:@192.168.1.105:1521:gdnxfd
+#    username: nxfdprod
+#    password: gdnxfd123
+#    driver-class-name: oracle.jdbc.OracleDriver
+    driver-class-name: org.sqlite.JDBC
+    url: jdbc:sqlite::resource:gdnx.db
+    username:
+    password:
 
+    druid:
       # 初始化大小,最小,最大
       initial-size: 1
       min-idle: 1
@@ -58,7 +78,7 @@ mybatis-plus:
 
 logging:
   level:
-    root: info
+    root: error
     com.example: debug
   file:
     path: ./logs

BIN
power-fitting/src/main/resources/gdnx.db


+ 27 - 0
power-fitting/src/main/resources/mapper/EquipmentmodelMapper.xml

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.gyee.power.fitting.mapper.EquipmentmodelMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.gyee.power.fitting.model.Equipmentmodel">
+        <id column="ID" property="id" />
+        <result column="CODE" property="code" />
+        <result column="NAME" property="name" />
+        <result column="DESCRIPTION" property="description" />
+        <result column="POWERPRODUCTION" property="powerproduction" />
+        <result column="CUTINWINDSPEED" property="cutinwindspeed" />
+        <result column="RATEDWINDSPEED" property="ratedwindspeed" />
+        <result column="CUTOUTWINDSPEED" property="cutoutwindspeed" />
+        <result column="WINDTURBINEMANUFACTURERID" property="windturbinemanufacturerid" />
+        <result column="PHOTO" property="photo" />
+        <result column="UNIT" property="unit" />
+        <result column="SWEPTAREA" property="sweptarea" />
+        <result column="EQUIPMENTCATEGORY" property="equipmentcategory" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        ID, CODE, NAME, DESCRIPTION, POWERPRODUCTION, CUTINWINDSPEED, RATEDWINDSPEED, CUTOUTWINDSPEED, WINDTURBINEMANUFACTURERID, PHOTO, UNIT, SWEPTAREA, EQUIPMENTCATEGORY
+    </sql>
+
+</mapper>

+ 28 - 0
power-fitting/src/main/resources/mapper/PowerfittinganalysisMapper.xml

@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.gyee.power.fitting.mapper.PowerfittinganalysisMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.gyee.power.fitting.model.Powerfittinganalysis">
+        <result column="ID" property="id" />
+        <result column="STATION" property="station" />
+        <result column="STATIONCN" property="stationcn" />
+        <result column="WINDTURBINE" property="windturbine" />
+        <result column="CODE" property="code" />
+        <result column="INTERVAL" property="interval" />
+        <result column="TIME" property="time" />
+        <result column="PATH" property="path" />
+        <result column="TYPE" property="type" />
+        <result column="PREPAREID" property="prepareid" />
+        <result column="CPAVG" property="cpavg" />
+        <result column="SPEEDAVG" property="speedavg" />
+        <result column="FREQUENCY" property="frequency" />
+        <result column="PCRATIO" property="pcratio" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        ID, STATION, STATIONCN, WINDTURBINE, code, interval, TIME, PATH, TYPE, PREPAREID, CPAVG, SPEEDAVG, FREQUENCY, PCRATIO
+    </sql>
+
+</mapper>

+ 4 - 4
power-fetting/src/main/resources/mapper/WindpowerstationMapper.xml

@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.gyee.power.fetting.mapper.WindpowerstationMapper">
+<mapper namespace="com.gyee.power.fitting.mapper.WindpowerstationMapper">
 
     <!-- 通用查询映射结果 -->
-    <resultMap id="BaseResultMap" type="com.gyee.power.fetting.model.Windpowerstation">
+    <resultMap id="BaseResultMap" type="com.gyee.power.fitting.model.Windpowerstation">
         <id column="ID" property="id" />
         <result column="CODE" property="code" />
         <result column="NAME" property="name" />
@@ -24,12 +24,12 @@
         <result column="ORDERNUM" property="ordernum" />
         <result column="ALTITUDE" property="altitude" />
         <result column="HEIGHT" property="height" />
-        <result column="AQTS" property="aqts" />
+<!--        <result column="AQTS" property="aqts" />-->
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        ID, CODE, NAME, ADDRESS, TELEPHONE, CAPACITY, CAPACITYUNIT, QUANTITY, ANAME, LONGITUDE, LATITUDE, PHOTO, COMPANYID, SYSTEMMANUFACT, HEADFARM, HEADFARMPHONE, MODEL, ORDERNUM, ALTITUDE, HEIGHT, AQTS
+        ID, CODE, NAME, ADDRESS, TELEPHONE, CAPACITY, CAPACITYUNIT, QUANTITY, ANAME, LONGITUDE, LATITUDE, PHOTO, COMPANYID, SYSTEMMANUFACT, HEADFARM, HEADFARMPHONE, MODEL, ORDERNUM, ALTITUDE, HEIGHT
     </sql>
 
 </mapper>

+ 2 - 2
power-fetting/src/main/resources/mapper/WindturbineMapper.xml

@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.gyee.power.fetting.mapper.WindturbineMapper">
+<mapper namespace="com.gyee.power.fitting.mapper.WindturbineMapper">
 
     <!-- 通用查询映射结果 -->
-    <resultMap id="BaseResultMap" type="com.gyee.power.fetting.model.Windturbine">
+    <resultMap id="BaseResultMap" type="com.gyee.power.fitting.model.Windturbine">
         <id column="ID" property="id" />
         <result column="CODE" property="code" />
         <result column="WINDPOWERSTATIONID" property="windpowerstationid" />

+ 32 - 0
power-fitting/src/main/resources/mapper/Windturbinetestingpointai2Mapper.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.gyee.power.fitting.mapper.Windturbinetestingpointai2Mapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.gyee.power.fitting.model.Windturbinetestingpointai2">
+        <id column="ID" property="id" />
+        <result column="CODE" property="code" />
+        <result column="NAME" property="name" />
+        <result column="MODEL" property="model" />
+        <result column="VALUEUNIT" property="valueunit" />
+        <result column="ENGLISHNAME" property="englishname" />
+        <result column="TYPEID" property="typeid" />
+        <result column="MODELID" property="modelid" />
+        <result column="MAXVAL" property="maxval" />
+        <result column="MINVAL" property="minval" />
+        <result column="REASONABLEMAXVAL" property="reasonablemaxval" />
+        <result column="REASONABLEMINVAL" property="reasonableminval" />
+        <result column="WINDTURBINEID" property="windturbineid" />
+        <result column="UNIFORMCODE" property="uniformcode" />
+        <result column="SHORTID" property="shortid" />
+        <result column="LONGID" property="longid" />
+        <result column="WINDPOWERSTATIONID" property="windpowerstationid" />
+        <result column="REALTIMEID" property="realtimeid" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        ID, CODE, NAME, MODEL, VALUEUNIT, ENGLISHNAME, TYPEID, MODELID, MAXVAL, MINVAL, REASONABLEMAXVAL, REASONABLEMINVAL, WINDTURBINEID, UNIFORMCODE, SHORTID, LONGID, WINDPOWERSTATIONID, REALTIMEID
+    </sql>
+
+</mapper>

+ 66 - 0
power-fitting/src/test/java/AlgTest.java

@@ -0,0 +1,66 @@
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+import com.gyee.power.fitting.common.alg.MpptFittingAlg;
+
+import java.util.*;
+
+public class AlgTest {
+
+    public static void main(String[] args){
+        double[] arrX = new double[10];
+        double[] arrY = new double[10];
+        importdata_1("data1", arrX);
+        importdata_1("data2", arrY);
+
+        int order = 2;
+        double[] result = new double[3];
+    //   MpptFittingAlg.BuildLine_PV_Poly(arrX,arrY,order);
+       MpptFittingAlg.BuildLine_PV_LSC(arrX,arrY,10,10,0.1);
+      //  MpptFittingAlg.BuildLine_IV_LSC(arrX,arrY,10,10,0.1);
+    }
+
+    /**
+     * 从execl中导入数据
+     */
+    public static void importdata_1(String sheet, final double[] data)
+    {
+        int i=0;
+        List<Map<Integer,String>> list = new LinkedList<>(); //初始化列表
+
+        EasyExcel.read("D:/JavaCode/WTest.xlsx") //文件路径
+                .sheet(sheet) //表单名
+                .registerReadListener(new AnalysisEventListener<Map<Integer,String>>() { //监听器,以行的形式读取Excel
+
+                    //一行一行读取Excel,在这里处理读取到的数据
+                    @Override
+                    public void invoke(Map<Integer, String> integerStringMap, AnalysisContext analysisContext) {
+                        // TODO Auto-generated method stub
+                        list.add(integerStringMap); //将读取到的每一行为一组存入列表中
+                    }
+
+                    //数据读取完毕后运行下面
+                    @Override
+                    public void doAfterAllAnalysed(AnalysisContext context) {
+                        System.out.println("数据读取完毕");
+                    }
+                }).headRowNumber(1).doRead(); //headRowNumber(num)为指定前num行为表头,从num+1开始读,默认为1
+
+        //遍历列表存储数据
+        for (Map<Integer, String> integerStringMap : list)
+        {
+            Set<Integer> keySet =integerStringMap.keySet();
+            Iterator<Integer> iterator = keySet.iterator();
+            while (iterator.hasNext())
+            {
+                Integer key = iterator.next();
+                Double val = Double.valueOf(integerStringMap.get(key));
+                System.out.print(val+",");
+                data[i++] = val;
+            }
+        }
+        System.out.println();
+        System.out.println(i+"条数据已导入");
+    }
+
+}