Browse Source

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

xushili 2 years ago
parent
commit
5b7890f830
36 changed files with 1515 additions and 380 deletions
  1. 6 0
      power-fitting/pom.xml
  2. 9 9
      power-fitting/src/main/java/com/gyee/power/fitting/MapperGenerator.java
  3. 39 0
      power-fitting/src/main/java/com/gyee/power/fitting/common/alg/DBSCANPointALG.java
  4. 187 13
      power-fitting/src/main/java/com/gyee/power/fitting/common/alg/PowerFittingALG.java
  5. 232 27
      power-fitting/src/main/java/com/gyee/power/fitting/common/alg/PowerProcessALG.java
  6. 137 0
      power-fitting/src/main/java/com/gyee/power/fitting/common/alg/WindDirectionALG.java
  7. 1 1
      power-fitting/src/main/java/com/gyee/power/fitting/common/spring/InitialRunner.java
  8. 2 2
      power-fitting/src/main/java/com/gyee/power/fitting/common/util/DateUtil.java
  9. 1 0
      power-fitting/src/main/java/com/gyee/power/fitting/common/util/PowerFittingUtil.java
  10. 48 6
      power-fitting/src/main/java/com/gyee/power/fitting/controller/DataFittingController.java
  11. 2 2
      power-fitting/src/main/java/com/gyee/power/fitting/controller/DataPrepareController.java
  12. 9 2
      power-fitting/src/main/java/com/gyee/power/fitting/controller/DataProcessController.java
  13. 1 1
      power-fitting/src/main/java/com/gyee/power/fitting/controller/DateOptionController.java
  14. 33 0
      power-fitting/src/main/java/com/gyee/power/fitting/controller/analyse/RatioController.java
  15. 48 0
      power-fitting/src/main/java/com/gyee/power/fitting/controller/analyse/WindDirectionController.java
  16. 1 1
      power-fitting/src/main/java/com/gyee/power/fitting/controller/WindInfoController.java
  17. 10 0
      power-fitting/src/main/java/com/gyee/power/fitting/model/Powerfittinganalysis.java
  18. 1 1
      power-fitting/src/main/java/com/gyee/power/fitting/model/Windturbine.java
  19. 5 5
      power-fitting/src/main/java/com/gyee/power/fitting/model/custom/LineCurveFitting.java
  20. 16 0
      power-fitting/src/main/java/com/gyee/power/fitting/model/custom/Point.java
  21. 7 2
      power-fitting/src/main/java/com/gyee/power/fitting/model/custom/PointVo.java
  22. 10 9
      power-fitting/src/main/java/com/gyee/power/fitting/model/custom/PowerPointData.java
  23. 0 263
      power-fitting/src/main/java/com/gyee/power/fitting/service/custom/DataFittingService.java
  24. 0 15
      power-fitting/src/main/java/com/gyee/power/fitting/service/custom/DataOptionService.java
  25. 0 11
      power-fitting/src/main/java/com/gyee/power/fitting/service/custom/DataPointMP.java
  26. 459 0
      power-fitting/src/main/java/com/gyee/power/fitting/service/custom/curve/DataFittingService.java
  27. 2 1
      power-fitting/src/main/java/com/gyee/power/fitting/service/custom/DataPrepareService.java
  28. 9 2
      power-fitting/src/main/java/com/gyee/power/fitting/service/custom/DataProcessService.java
  29. 20 0
      power-fitting/src/main/java/com/gyee/power/fitting/service/custom/curve/DataScanService.java
  30. 117 0
      power-fitting/src/main/java/com/gyee/power/fitting/service/custom/fx/WindDirectionService.java
  31. 85 0
      power-fitting/src/main/java/com/gyee/power/fitting/service/custom/ratio/RatioService.java
  32. 1 1
      power-fitting/src/main/java/com/gyee/power/fitting/service/custom/WebSocketServer.java
  33. 4 1
      power-fitting/src/main/java/com/gyee/power/fitting/service/impl/ModelpowerdetailsServiceImpl.java
  34. 8 4
      power-fitting/src/main/resources/application.yaml
  35. BIN
      power-fitting/src/main/resources/gdnx.db
  36. 5 1
      power-fitting/src/main/resources/mapper/PowerfittinganalysisMapper.xml

+ 6 - 0
power-fitting/pom.xml

@@ -55,6 +55,12 @@
             <version>12.1.0.2.0</version>
         </dependency>
 
+        <dependency>
+            <groupId>org.xerial</groupId>
+            <artifactId>sqlite-jdbc</artifactId>
+            <version>3.36.0.3</version>
+        </dependency>
+
         <!--mybatis依赖-->
         <dependency>
             <groupId>com.baomidou</groupId>

+ 9 - 9
power-fitting/src/main/java/com/gyee/power/fitting/MapperGenerator.java

@@ -27,26 +27,26 @@ public class MapperGenerator {
     //作者
     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) {

+ 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;
+    }
+
+}

+ 187 - 13
power-fitting/src/main/java/com/gyee/power/fitting/common/alg/PowerFittingALG.java

@@ -1,11 +1,14 @@
 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;
 
 /**
  * 功率曲线拟合算法
@@ -14,6 +17,7 @@ import java.util.List;
 public class PowerFittingALG {
 
     /**
+     * 功率曲线拟合
      *
      * @param arrX        风速数组
      * @param arrY        功率数据
@@ -22,9 +26,9 @@ public class PowerFittingALG {
      * @param scale       精度  0.1  0.01
      * @return
      */
-    public static List<PointVo> BuildLine(double[] arrX, double[] arrY, int length, int dimension, double scale) {
+    public static List<Point> buildLine(double[] arrX, double[] arrY, int length, int dimension, double scale) {
 
-        List<PointVo> points = new ArrayList<>();
+        List<Point> points = new ArrayList<>();
 
         if (arrX.length != arrY.length || arrX.length < 3) {
             return points;
@@ -39,7 +43,7 @@ public class PowerFittingALG {
         double[] coefficient = MultiLine(arrX, arrY, length, dimension);
 
         for (double i = arrX[0]; i <= arrX[arrX.length - 1]; i += scale) {
-            PointVo point = new PointVo();
+            Point point = new Point();
             point.setX(i);
 
 
@@ -73,7 +77,7 @@ public class PowerFittingALG {
         return points;
     }
 
-    private static void Builder(List<PointVo> points, double min, double max) {
+    private static void Builder(List<Point> points, double min, double max) {
         boolean b = false;
         for (int i = 0; i < points.size(); i++) {
             if (b) {
@@ -106,8 +110,8 @@ public class PowerFittingALG {
     ///<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)//二元多次线性方程拟合曲线
-    {
+    //二元多次线性方程拟合曲线
+    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++) {
@@ -120,8 +124,8 @@ public class PowerFittingALG {
         return ComputGauss(Guass, n);
     }
 
-    private static double SumArr(double[] arr, int n, int length) //求数组的元素的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)
@@ -202,8 +206,8 @@ public class PowerFittingALG {
      * @param line
      * @return
      */
-    public static LineCurveFitting BuildCp(Double sweptarea, LineCurveFitting line){
-        List<PointVo> cpValue = new ArrayList<>();
+    public static LineCurveFitting buildCp(Double sweptarea, LineCurveFitting line){
+        List<Point> cpValue = new ArrayList<>();
 
         double kqmd = 1.225; //空气密度
         double max = 0;
@@ -212,7 +216,7 @@ public class PowerFittingALG {
 
         for (int i = 0; i < line.getYLines().size(); i++)
         {
-            PointVo point = line.getYLines().get(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;
@@ -220,7 +224,7 @@ public class PowerFittingALG {
             if (k != 0)
                 result = power / k * 1000;
             //s5.Points.AddXY(speed, result);
-            PointVo cppoint = new PointVo();
+            Point cppoint = new Point();
             cppoint.setX(speed);
             cppoint.setY(result);
             cpValue.add(cppoint);
@@ -246,5 +250,175 @@ public class PowerFittingALG {
 
         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());
+    }
+
 }
 

+ 232 - 27
power-fitting/src/main/java/com/gyee/power/fitting/common/alg/PowerProcessALG.java

@@ -9,7 +9,6 @@ import java.util.List;
 import java.util.Map;
 
 /**
- * 功率曲线拟合
  * 数据预处理算法
  */
 public class PowerProcessALG {
@@ -19,7 +18,7 @@ public class PowerProcessALG {
      * 数据预处理
      *
      * @param list   预处理的数据
-     * @param map    风速对应的理论功率
+     * @param map    风速对应的保证功率
      * @param maxs   最大风速
      * @param mins   最小风速
      * @param maxp   最大功率
@@ -47,15 +46,7 @@ public class PowerProcessALG {
             if (timeBW == DateUtil.format(new Date(0), DateUtil.DATE_TIME_PATTERN)){
                 timeBW = item.getTime();
             }
-            // 过滤非并网状态下的数据
-//            if (filter == 0 && isfbw && item.getMxzt() != 1) {
-//                filter = 1;
-//                fjstatus = 1;
-//                timeBW = item.getTime();
-//            } else {
-//                filter = 0;
-//                fjstatus = 0;
-//            }
+            // 过滤非并网值  风机状态不等于2
             if (filter == 0 && isfbw && item.getMxzt() != 2) {
                 filter = 1;
                 fjstatus = 1;
@@ -63,8 +54,8 @@ public class PowerProcessALG {
             } else {
                 filter = 0;
                 fjstatus = 0;
-
             }
+            // 按给定风速功率过滤
             if (item.getSpeed() < mins || item.getSpeed() > maxs || item.getPower() < minp || item.getPower() > maxp) {
                 filter = 1;
             }
@@ -78,14 +69,14 @@ public class PowerProcessALG {
             }
             // 过滤并网后十分钟
             if (filter == 0 && isbw) {
-                if (DateUtil.getTime(item.getTime(), timeBW) <= 10)
+                if (DateUtil.getTimeDiff(item.getTime(), timeBW) <= 10)
                     filter = 1;
             }
-            // 过滤停机十分钟
+            // 过滤停机十分钟
             if (istj) {
                 if (fjstatus == 0) {
                     if (tempei.size() > 0) {
-                        if (DateUtil.getTime(tempei.get(0).getTime(), timeBW) >= 10) {
+                        if (DateUtil.getTimeDiff(tempei.get(0).getTime(), timeBW) >= 10) {
                             tempei.remove(0);
                         }
                     }
@@ -98,46 +89,49 @@ public class PowerProcessALG {
                 }
             }
             //欠发
-            if (filter == 0 && item.getSpeed() >= 6 && item.getSpeed() < 12.5 && isqfh && qfhdj <= item.getQfzt()) {
+            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) {
+            } 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.getTime(tempqf.get(0).getTime(), item.getTime()) >= 5) {
+                if (DateUtil.getTimeDiff(tempqf.get(0).getTime(), item.getTime()) >= 5) {
                     tempqf.remove(0);
                 }
             }
-            tempqf.add(item);
+            tempqf.add(0, item);
             item.setFilter(filter);
 
             //功率曲线偏差
             if (isglpc) {
-                if (map.containsKey(item)) {
-                    double power = map.get(item.getSpeed());
-                    double maxPower = map.get(map.size() - 1);
-                    double k = item.getPower() / power;
+                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.85 && maxPower > power) {
+                        if (k < 0.9 && maxPower > power) {
                             item.setFilter(1);
                         }
-                        if (k > 3 && item.getSpeed() < 6 && item.getSpeed() > 4) {
+                        if (k < 0.85 && item.getSpeed() < 6 && item.getSpeed() > 4) {
                             item.setFilter(1);
                         }
 
-                        if (k > 6 && item.getSpeed() <= 4 && item.getSpeed() > 3.5) {
+                        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 > 12 && item.getSpeed() <= 3.5 && item.getSpeed() > 3) {
+                        if (k < 0.4 && item.getSpeed() <= 3 && item.getSpeed() > 0) {
                             item.setFilter(1);
                         }
                     }
@@ -148,4 +142,215 @@ public class PowerProcessALG {
         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-fitting/src/main/java/com/gyee/power/fitting/common/spring/InitialRunner.java

@@ -83,7 +83,7 @@ public class InitialRunner implements CommandLineRunner {
      */
     public void cacheStation(){
         List<Windpowerstation> stations = windpowerstationService.selectList();
-        wpList = stations.stream().filter(f -> f.getId().endsWith("FDC")).collect(Collectors.toList());
+        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());

+ 2 - 2
power-fitting/src/main/java/com/gyee/power/fitting/common/util/DateUtil.java

@@ -183,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);
     }
 
@@ -491,7 +491,7 @@ public class DateUtil extends DateUtils {
     }
 
     // 获取两个时间相差分钟数
-    public static int getTime(String oldTime,String newTime) {
+    public static int getTimeDiff(String oldTime, String newTime) {
         int diff = 0;
         SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
         long NTime = 0;

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

@@ -58,4 +58,5 @@ public class PowerFittingUtil {
 
         return ls;
     }
+
 }

+ 48 - 6
power-fitting/src/main/java/com/gyee/power/fitting/controller/DataFittingController.java

@@ -1,10 +1,12 @@
-package com.gyee.power.fitting.controller;
+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.DataFittingService;
+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.*;
 
@@ -33,7 +35,7 @@ public class DataFittingController {
      * @param maxp
      * @param minp
      * @param dimension 多项式
-     * @param mode  拟合方式  0:单台拟合  1:合并拟合
+     * @param mode  拟合方式  0:单台拟合  1:合并拟合  2:同名拟合
      * @return
      */
     @GetMapping("/data")
@@ -44,9 +46,11 @@ public class DataFittingController {
                                   @RequestParam(value = "minp",  required = false) Double minp,
                                   @RequestParam(value = "dimension",  required = false) Integer dimension,
                                   @RequestParam(value = "mode",  required = false) Integer mode){
-        String[] id = ids.split(",");
-        fittingService.dataFitting(Arrays.asList(id), maxs, mins, maxp, minp, dimension, mode);
-        return JsonResult.success(ResultCode.SUCCESS);
+        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);
     }
 
 
@@ -82,4 +86,42 @@ public class DataFittingController {
         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);
+    }
 }

+ 2 - 2
power-fitting/src/main/java/com/gyee/power/fitting/controller/DataPrepareController.java

@@ -1,4 +1,4 @@
-package com.gyee.power.fitting.controller;
+package com.gyee.power.fitting.controller.analyse;
 
 import com.alibaba.fastjson.JSONObject;
 import com.gyee.power.fitting.common.result.JsonResult;
@@ -6,7 +6,7 @@ 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.DataPrepareService;
+import com.gyee.power.fitting.service.custom.curve.DataPrepareService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 

+ 9 - 2
power-fitting/src/main/java/com/gyee/power/fitting/controller/DataProcessController.java

@@ -1,4 +1,4 @@
-package com.gyee.power.fitting.controller;
+package com.gyee.power.fitting.controller.analyse;
 
 import com.alibaba.fastjson.JSONObject;
 import com.gyee.power.fitting.common.result.JsonResult;
@@ -6,7 +6,7 @@ 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.DataProcessService;
+import com.gyee.power.fitting.service.custom.curve.DataProcessService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
@@ -59,6 +59,13 @@ public class DataProcessController {
                                   @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);
 

+ 1 - 1
power-fitting/src/main/java/com/gyee/power/fitting/controller/DateOptionController.java

@@ -1,4 +1,4 @@
-package com.gyee.power.fitting.controller;
+package com.gyee.power.fitting.controller.analyse;
 
 import com.alibaba.fastjson.JSONObject;
 import com.gyee.power.fitting.common.config.GyeeConfig;

+ 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);
+    }
+}

+ 1 - 1
power-fitting/src/main/java/com/gyee/power/fitting/controller/WindInfoController.java

@@ -1,4 +1,4 @@
-package com.gyee.power.fitting.controller;
+package com.gyee.power.fitting.controller.base;
 
 import com.alibaba.fastjson.JSONObject;
 import com.gyee.power.fitting.common.result.JsonResult;

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

@@ -52,7 +52,17 @@ public class Powerfittinganalysis extends Model<Powerfittinganalysis> {
     @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;
 
 
 

+ 1 - 1
power-fitting/src/main/java/com/gyee/power/fitting/model/Windturbine.java

@@ -53,7 +53,7 @@ public class Windturbine extends Model<Windturbine> {
     private String lineid;
 
     @TableField("FIRSTINTEGRATEDTIME")
-    private Date firstintegratedtime;
+    private String firstintegratedtime;
 
     @TableField("PHOTO")
     private String photo;

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

@@ -8,16 +8,16 @@ import java.util.List;
 public class LineCurveFitting {
 
     public String name;
-    public List<PointVo> lines;
-    public List<PointVo> YLines;
+    public List<Point> lines;
+    public List<Point> YLines;
 
-    public List<PointVo> point;
-    public List<PointVo> YPoint;
+    public List<Point> point;
+    public List<Point> YPoint;
 
     /// <summary>
     /// 推力系数
     /// </summary>
-    public List<PointVo> CpValue;
+    public List<Point> CpValue;
     /// <summary>
     /// 推力系数平均值
     /// </summary>

+ 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;
+
+}

+ 7 - 2
power-fitting/src/main/java/com/gyee/power/fitting/model/custom/PointVo.java

@@ -9,6 +9,11 @@ import lombok.NoArgsConstructor;
 @AllArgsConstructor
 public class PointVo {
 
-    private Double x;
-    private Double y;
+    private double x;
+
+    private double y;
+
+    private double s;
+
+    private String k;
 }

+ 10 - 9
power-fitting/src/main/java/com/gyee/power/fitting/model/custom/PowerPointData.java

@@ -31,31 +31,32 @@ public class PowerPointData {
     private String time;
 
     //功率
-    private Double power;
+    private double power = 0;
 
     //风速
-    private Double speed;
+    private double speed = 0;
 
     //转速
-    private Double RR;
+    private double RR = 0;
 
     //明细状态
-    private Integer mxzt;
+    private int mxzt = 0;
 
     //电量
-    private Double DL;
+    private double DL = 0;
 
     //欠发状态
-    private Integer qfzt;
+    private int qfzt = 0;
 
     //风向
-    private Double FX;
+    private double FX = 0;
 
     //对风角度
-    private Double angle;
+    private double angle = 0;
 
     //是否过滤  0:不过滤 1:过滤
-    private Integer filter;
+    private int filter = 0;
 
     private String wtId;
 }
+

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

@@ -1,263 +0,0 @@
-package com.gyee.power.fitting.service.custom;
-
-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.model.Modelpowerdetails;
-import com.gyee.power.fitting.model.Powerfittinganalysis;
-import com.gyee.power.fitting.model.custom.*;
-import com.gyee.power.fitting.service.PowerfittinganalysisService;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.Resource;
-import java.util.*;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.stream.Collectors;
-
-
-@Service
-public class DataFittingService {
-
-    @Resource
-    private GyeeConfig config;
-    @Resource
-    private PowerfittinganalysisService powerService;
-
-
-    /**
-     * 曲线拟合
-     * @param ids
-     * @param maxs
-     * @param mins
-     * @param maxp
-     * @param minp
-     * @param dimension
-     * @param mode   拟合方式  0:单台拟合  1:合并拟合
-     */
-    public void dataFitting(List<String> ids, Double maxs, Double mins, Double maxp, Double minp, Integer dimension, Integer mode){
-        if (mode == 0){  //单台拟合
-            List<Powerfittinganalysis> listObj = new ArrayList<>();
-            ids.forEach(id -> {
-                Powerfittinganalysis obj = powerService.selectItemById(id);
-                listObj.add(obj);
-                List<Double> arraySpeed = new ArrayList<>();
-                List<Double> arrayPower = new ArrayList<>();
-                /** 读取csv数据 转换成对象数组 **/
-                List<String> line = FileUtil.readFile(obj.getPath(), true);
-                for (int i = 1; i < line.size(); i++) {
-                    String[] split = line.get(i).split(",");
-                    int filter = Integer.valueOf(split[9]); //是否过滤
-                    double x = Double.valueOf(split[2]);    //风速
-                    double y = Double.valueOf(split[1]);    //功率
-                    if (filter == 0 && (x >= mins && x <= maxs && y >= minp && y <= maxp)){
-                        arraySpeed.add(x);
-                        arrayPower.add(y);
-                    }
-                }
-                List<Modelpowerdetails> mp = InitialRunner.modelPowerDetailMap.get(InitialRunner.wtMap.get(obj.getWindturbine()).getModelid());
-                Optional<Double> maxP = mp.stream().map(Modelpowerdetails::getEnsurepower).max(Comparator.comparing(Double::doubleValue));
-                fittingMode(listObj, maxP.get(), arraySpeed, arrayPower, dimension, mode);
-            });
-        }
-        if (mode == 1){  //合并拟合
-            AtomicReference<Double> maxP = new AtomicReference<>(0.0);
-            List<Double> arraySpeed = new ArrayList<>();
-            List<Double> arrayPower = new ArrayList<>();
-            List<Powerfittinganalysis> listObj = new ArrayList<>();
-            for (String id : ids){
-                Powerfittinganalysis obj = powerService.selectItemById(id);
-                listObj.add(obj);
-                /** 读取csv数据 转换成对象数组 **/
-                List<String> line = FileUtil.readFile(obj.getPath(), true);
-                for (int i = 1; i < line.size(); i++) {
-                    String[] split = line.get(i).split(",");
-                    int filter = Integer.valueOf(split[9]); //是否过滤
-                    double x = Double.valueOf(split[2]);    //风速
-                    double y = Double.valueOf(split[1]);    //功率
-                    if (filter == 0 && (x >= mins && x <= maxs && y >= minp && y <= maxp)){
-                        arraySpeed.add(x);
-                        arrayPower.add(y);
-                    }
-                }
-                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);
-            }
-
-            fittingMode(listObj, maxP.get(), arraySpeed, arrayPower, dimension, mode);
-        }
-    }
-
-
-    /**
-     * 拟合模块展示  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 String[]{split[0], split[1]});
-            cpzList.add(new String[]{split[0], split[2]});
-        }
-
-        //理论功率
-        List<Modelpowerdetails> modelPower = InitialRunner.modelPowerDetailMap.get(InitialRunner.wtMap.get(obj.getWindturbine()).getModelid());
-        List<Object> llglList = modelPower.stream().sorted(Comparator.comparing(Modelpowerdetails::getSpeed)).map(m -> new double[]{m.getSpeed(), m.getEnsurepower()}).collect(Collectors.toList());
-
-        //散点
-        String[] ids = obj.getPrepareid().split(",");
-        List<Object> scatterls = new ArrayList<>(); //蓝色散点 筛选掉的
-        List<Object> scatterhs = 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);
-                pd.setWtId(pf.getWindturbine());
-                pd.setFilter(Integer.parseInt(split[9]));
-
-                DataPointMP pm = new DataPointMP();
-                pm.setS(pd.getSpeed());
-                pm.setP(pd.getPower());
-                pm.setW(pf.getWindturbine());
-                if (0 == pd.getFilter())
-                    scatterls.add(pm);   //没有过滤
-                if (1 == pd.getFilter())
-                    scatterhs.add(pm);   //已过滤
-            }
-        }
-
-        map.put("sjgl", sjglList);    //实际功率
-        map.put("llgl", llglList);    //理论功率
-        map.put("cpz", cpzList);      //Cp值
-        map.put("scatterhs", scatterhs);  //黄色散点
-        map.put("scatterls", scatterls);  //蓝色散点
-
-        return map;
-    }
-
-
-    private String assemble(LineCurveFitting lf){
-        StringBuilder sb = setTitle();
-        for (int i = 0; i < lf.getYLines().size(); i++){
-            PointVo cp = lf.getCpValue().get(i);
-            PointVo 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;
-    }
-
-
-    private void fittingMode(List<Powerfittinganalysis> listObj, Double powerMax, List<Double> arraySpeed, List<Double> arrayPower, Integer dimension, int mode){
-        Powerfittinganalysis obj = listObj.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<PointVo> 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);
-
-        String content = assemble(lf);
-        String prepareId = "";
-        String fileName = null;
-        if (mode == 0){
-            prepareId = obj.getId();
-            fileName = config.getFilePathFitting() + obj.getStation() + "_" + obj.getCode() + "_" + System.currentTimeMillis() / 1000 + ".csv";
-        }
-        if (mode == 1){
-            prepareId = listObj.stream().map(d -> d.getId()).collect(Collectors.joining(","));
-            fileName = config.getFilePathFitting() + obj.getStation() + "_merge" + "_" + System.currentTimeMillis() / 1000 + ".csv";
-        }
-        boolean flag = FileUtil.writeFile(fileName, content);
-        if (flag) {  // TODO  保存数据库
-            obj.setPath(fileName);
-            obj.setPrepareid(prepareId);
-            obj.setType(Constants.DATA_FITTING);
-            powerService.insertItem(obj);
-        }
-        System.out.println("功率曲线拟合完成:" + obj.getWindturbine());
-    }
-
-}

+ 0 - 15
power-fitting/src/main/java/com/gyee/power/fitting/service/custom/DataOptionService.java

@@ -1,15 +0,0 @@
-package com.gyee.power.fitting.service.custom;
-
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-
-
-/**
- * 数据删除、下载...
- */
-@Service
-public class DataOptionService {
-
-
-}

+ 0 - 11
power-fitting/src/main/java/com/gyee/power/fitting/service/custom/DataPointMP.java

@@ -1,11 +0,0 @@
-package com.gyee.power.fitting.service.custom;
-
-import lombok.Data;
-
-@Data
-public class DataPointMP {
-
-    private Double s;
-    private Double p;
-    private String w;
-}

+ 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;
+    }
+}

+ 2 - 1
power-fitting/src/main/java/com/gyee/power/fitting/service/custom/DataPrepareService.java

@@ -1,4 +1,4 @@
-package com.gyee.power.fitting.service.custom;
+package com.gyee.power.fitting.service.custom.curve;
 
 import com.gyee.power.fitting.common.config.GyeeConfig;
 import com.gyee.power.fitting.common.constants.Constants;
@@ -13,6 +13,7 @@ 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;

+ 9 - 2
power-fitting/src/main/java/com/gyee/power/fitting/service/custom/DataProcessService.java

@@ -1,5 +1,6 @@
-package com.gyee.power.fitting.service.custom;
+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;
@@ -63,11 +64,16 @@ public class DataProcessService {
             /** 数据预处理 **/
             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() + "_" + System.currentTimeMillis() / 1000 + ".csv";
+            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);
             }
@@ -152,4 +158,5 @@ public class DataProcessService {
         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;
+    }
+}

+ 1 - 1
power-fitting/src/main/java/com/gyee/power/fitting/service/custom/WebSocketServer.java

@@ -1,4 +1,4 @@
-package com.gyee.power.fitting.service.custom;
+package com.gyee.power.fitting.service.custom.socket;
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;

+ 4 - 1
power-fitting/src/main/java/com/gyee/power/fitting/service/impl/ModelpowerdetailsServiceImpl.java

@@ -1,5 +1,6 @@
 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;
@@ -23,8 +24,10 @@ public class ModelpowerdetailsServiceImpl extends ServiceImpl<ModelpowerdetailsM
     @Override
     public List<Modelpowerdetails> selectList() {
         List<Modelpowerdetails> list = new ArrayList<>();
+        ExcludeQueryWrapper wrapper = new ExcludeQueryWrapper();
+        wrapper.orderByAsc("speed");
         try{
-            list = baseMapper.selectList(null);
+            list = baseMapper.selectList(wrapper);
         }catch (Exception e){
             log.error("ModelpowerdetailsServiceImpl--selectList", e);
         }

+ 8 - 4
power-fitting/src/main/resources/application.yaml

@@ -40,10 +40,14 @@ spring:
     allow-bean-definition-overriding: false #当遇到同样名字的时候,是否允许覆盖注册
   datasource:
     type: com.alibaba.druid.pool.DruidDataSource
-    url: jdbc:oracle:thin:@192.168.1.105:1521:gdnxfd
-    username: nxfdprod
-    password: gdnxfd123
-    driver-class-name: oracle.jdbc.OracleDriver
+#    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:
       # 初始化大小,最小,最大

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


+ 5 - 1
power-fitting/src/main/resources/mapper/PowerfittinganalysisMapper.xml

@@ -14,11 +14,15 @@
         <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
+        ID, STATION, STATIONCN, WINDTURBINE, code, interval, TIME, PATH, TYPE, PREPAREID, CPAVG, SPEEDAVG, FREQUENCY, PCRATIO
     </sql>
 
 </mapper>