|
|
@@ -145,6 +145,181 @@ public class PowerProcessALG {
|
|
|
}
|
|
|
|
|
|
|
|
|
+ public static List<PowerPointData> dataProcess11(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) {
|
|
|
+
|
|
|
+ if (list == null || list.isEmpty()) return list;
|
|
|
+
|
|
|
+ // 并网起点时间(第一次遇到并网或者从非并网->并网时初始化)
|
|
|
+ String gridStartTime = null;
|
|
|
+
|
|
|
+ // 用索引保存 tempei / tempqf 窗口,避免存对象引用导致连带修改
|
|
|
+ List<Integer> tempeiIndex = new ArrayList<>();
|
|
|
+ List<Integer> tempqfIndex = new ArrayList<>();
|
|
|
+
|
|
|
+ // 遍历原始列表,按业务条件判断 filter(最终写回到每个 item 中)
|
|
|
+ for (int i = 0; i < list.size(); i++) {
|
|
|
+ PowerPointData item = list.get(i);
|
|
|
+ int filter = 0; // 0 保留,1 过滤
|
|
|
+
|
|
|
+ String currentTime = item.getTime();
|
|
|
+ double speed = item.getSpeed();
|
|
|
+ double power = item.getPower();
|
|
|
+ int mxzt = item.getMxzt();
|
|
|
+
|
|
|
+ // 状态判断
|
|
|
+ boolean isGrid = (mxzt == 2); // 并网
|
|
|
+ boolean isNonGrid = !isGrid; // 非并网
|
|
|
+
|
|
|
+ // ---------------------------
|
|
|
+ // 1) 过滤非并网值(如果开关 isfbw 为 true)
|
|
|
+ // 原逻辑中非并网要被过滤
|
|
|
+ // ---------------------------
|
|
|
+ if (isfbw != null && isfbw && isNonGrid) {
|
|
|
+ filter = 1;
|
|
|
+ // 标记:当发生非并网事件时,我们需要把之前记录的 tempeiIndex (并网期间的索引)标记为停机前10分钟过滤
|
|
|
+ // 这里的处理会在 istj 分支统一处理(以保持行为一致),但保留当前行为:非并网条目本身也被过滤
|
|
|
+ }
|
|
|
+
|
|
|
+ // ---------------------------
|
|
|
+ // 2) 若发现是并网且 gridStartTime 未初始化,则初始化(第一次并网或刚开始的数据)
|
|
|
+ // 这样能保证“第一条并网数据不会被误过滤”
|
|
|
+ // ---------------------------
|
|
|
+ if (isGrid && gridStartTime == null) {
|
|
|
+ gridStartTime = currentTime;
|
|
|
+ // 不对当前 item 做并网后 10 分钟过滤(作为起点)
|
|
|
+ // 注意:如果你想只在从非并网->并网才初始化,可以改为在 isNonGrid->isGrid 的过渡时初始化
|
|
|
+ }
|
|
|
+
|
|
|
+ // ---------------------------
|
|
|
+ // 3) 风速功率范围过滤(按mins/maxs/minp/maxp)
|
|
|
+ // ---------------------------
|
|
|
+ if (!Double.isNaN(speed) && !Double.isNaN(power)) {
|
|
|
+ if ((mins != null && speed < mins) || (maxs != null && speed > maxs)
|
|
|
+ || (minp != null && power < minp) || (maxp != null && power > maxp)) {
|
|
|
+ filter = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ---------------------------
|
|
|
+ // 4) 过滤非合理值(并网状态下功率小于等于 minp 或速度 < 0) - 保持与你原逻辑一致
|
|
|
+ // ---------------------------
|
|
|
+ if (filter == 0 && isfhl != null && isfhl) {
|
|
|
+ // 如果速度 < 0 且功率 <= minp 则认为不合理(参考原逻辑)
|
|
|
+ if (speed < 0 && !Double.isNaN(power) && minp != null && power <= minp) {
|
|
|
+ filter = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ---------------------------
|
|
|
+ // 5) 并网后 10 分钟过滤(isbw 开关)
|
|
|
+ // 注意:gridStartTime 必须有效(非 null),getTimeDiff 返回 -1 时不做过滤
|
|
|
+ // ---------------------------
|
|
|
+ if (filter == 0 && isbw != null && isbw && gridStartTime != null) {
|
|
|
+ int diff = getTimeDiff(currentTime, gridStartTime);
|
|
|
+ if (diff >= 0 && diff <= 10) {
|
|
|
+ filter = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ---------------------------
|
|
|
+ // 6) 停机前 10 分钟过滤(istj 开关)
|
|
|
+ // 语义:当检测到非并网(isNonGrid)时,将之前记录的并网期间最近的若干条(最多覆盖10分钟窗口)标记为过滤
|
|
|
+ // 我们通过 tempeiIndex 在并网期间保存索引;一旦发现非并网 -> 标记这些索引
|
|
|
+ // ---------------------------
|
|
|
+ if (istj != null && istj) {
|
|
|
+ if (isNonGrid) {
|
|
|
+ // 发生非并网事件:把 tempeiIndex 中的候选项都标记为过滤
|
|
|
+ for (Integer idx : tempeiIndex) {
|
|
|
+ if (idx >= 0 && idx < list.size()) {
|
|
|
+ list.get(idx).setFilter(1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 清空窗口
|
|
|
+ tempeiIndex.clear();
|
|
|
+ } else {
|
|
|
+ // 当前仍为并网:维护 tempeiIndex,使其只保存最近不超过 10 分钟的并网索引
|
|
|
+ if (!tempeiIndex.isEmpty()) {
|
|
|
+ int firstIdx = tempeiIndex.get(0);
|
|
|
+ String firstTime = list.get(firstIdx).getTime();
|
|
|
+ int diff = getTimeDiff(firstTime, currentTime);
|
|
|
+ if (diff >= 0 && diff >= 10) {
|
|
|
+ // 超过 10 分钟,则移除最旧的(可以循环移除,但原逻辑是单次检查)
|
|
|
+ tempeiIndex.remove(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 添加当前并网索引到窗口头(保持与原逻辑一致的顺序)
|
|
|
+ tempeiIndex.add(i);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ---------------------------
|
|
|
+ // 7) 欠发过滤(isqfh 开关 + qfhdj 等级判断)
|
|
|
+ // 逻辑:如果当前点满足欠发条件 -> 过滤,并把 tempqfIndex 中的索引标记为过滤
|
|
|
+ // ---------------------------
|
|
|
+ boolean needQF = false;
|
|
|
+ if (filter == 0 && isqfh != null && isqfh) {
|
|
|
+ // qfzt 为设备点的欠发状态等级
|
|
|
+ int qfzt = item.getQfzt();
|
|
|
+ if (!Double.isNaN(speed)) {
|
|
|
+ if (speed >= 6 && speed < 12.5 && qfhdj != null && qfhdj < qfzt) {
|
|
|
+ needQF = true;
|
|
|
+ } else if (speed >= 12.5 && qfhdj != null && qfhdj < 1) {
|
|
|
+ needQF = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (needQF) {
|
|
|
+ filter = 1;
|
|
|
+ for (Integer idx : tempqfIndex) {
|
|
|
+ if (idx >= 0 && idx < list.size()) {
|
|
|
+ list.get(idx).setFilter(1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新 tempqfIndex:保持一个 5 分钟窗口(与原逻辑相同)
|
|
|
+ if (!tempqfIndex.isEmpty()) {
|
|
|
+ int firstIdx = tempqfIndex.get(0);
|
|
|
+ String firstTime = list.get(firstIdx).getTime();
|
|
|
+ int diff = getTimeDiff(firstTime, currentTime);
|
|
|
+ if (diff >= 0 && diff >= 5) {
|
|
|
+ tempqfIndex.remove(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 将当前索引放到 tempqfIndex 的头部(和你原来 add(0, item) 的语义对应)
|
|
|
+ tempqfIndex.add(0, i);
|
|
|
+
|
|
|
+ // ---------------------------
|
|
|
+ // 8) 功率曲线偏差(isglpc 开关)
|
|
|
+ // 使用 map 提供的保证功率(map.get(speed))和 map.get(24.0) 作为最大保证功率
|
|
|
+ // ---------------------------
|
|
|
+ if (filter == 0 && isglpc != null && isglpc && map != null && map.containsKey(speed)) {
|
|
|
+ Double guaranteePower = map.get(speed);
|
|
|
+ Double maxGuarantee = map.get(24.0);
|
|
|
+ if (guaranteePower != null && guaranteePower > 0 && !Double.isNaN(power) && power > 0) {
|
|
|
+ double k = power / guaranteePower; // 实际功率 / 保证功率(注意:与你原 k 定义可换)
|
|
|
+ // 按你原始逻辑规则决定阈值(此处保留原来的判断条件)
|
|
|
+ if (k < 0.95 && maxGuarantee != null && maxGuarantee <= guaranteePower) filter = 1;
|
|
|
+ if (k < 0.9 && maxGuarantee != null && maxGuarantee > guaranteePower) filter = 1;
|
|
|
+ if (k < 0.85 && speed < 6 && speed > 4) filter = 1;
|
|
|
+ if (k < 0.9 && speed <= 4 && speed > 3.5) filter = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ---------------------------
|
|
|
+ // 9) 最终设置当前项的 filter(0 或 1)
|
|
|
+ // ---------------------------
|
|
|
+ item.setFilter(filter);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 返回原 list(对象被按需修改 filter 字段;但没有把对象引用放到临时集合中造成额外污染)
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* 按照给定风俗功率过滤
|
|
|
* @param list
|
|
|
@@ -356,20 +531,33 @@ public class PowerProcessALG {
|
|
|
return list;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+//
|
|
|
+// 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 int getTimeDiff(String oldTime, String newTime) {
|
|
|
- int diff = 0;
|
|
|
+ if (oldTime == null || newTime == null) return -1;
|
|
|
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);
|
|
|
+ long OTime = df.parse(oldTime).getTime();
|
|
|
+ long NTime = df.parse(newTime).getTime();
|
|
|
+ return (int) (Math.abs(NTime - OTime) / 1000 / 60);
|
|
|
} catch (ParseException e) {
|
|
|
+ // 解析失败视为无法比较
|
|
|
+ return -1;
|
|
|
}
|
|
|
-
|
|
|
- return diff;
|
|
|
}
|
|
|
}
|