From c3f85921602f6ac3d60cac844a4b869ee033e81b Mon Sep 17 00:00:00 2001 From: hongawen <83944980@qq.com> Date: Wed, 26 Jul 2023 11:20:12 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E8=B4=A3=E4=BB=BB=E9=87=8F?= =?UTF-8?q?=E5=8C=96=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pqs-advance/advance-api/pom.xml | 17 +- .../advance/enums/AdvanceResponseEnum.java | 52 ++ .../pojo/bo/responsibility/CacheQvvrData.java | 48 + .../bo/responsibility/DealDataResult.java | 37 + .../bo/responsibility/DealUserDataResult.java | 31 + .../pojo/bo/responsibility/HKDataStruct.java | 37 + .../pojo/bo/responsibility/PDataStruct.java | 41 + .../pojo/bo/responsibility/QvvrStruct.java | 200 ++++ .../pojo/bo/responsibility/UserDataExcel.java | 47 + .../pojo/dto/responsibility/CustomerData.java | 27 + .../CustomerResponsibility.java | 28 + .../pojo/dto/responsibility/RespDataDTO.java | 29 + .../responsibility/ResponsibilityResult.java | 53 ++ .../param/ResponsibilityCalculateParam.java | 50 + .../param/ResponsibilitySecondCalParam.java | 46 + .../pojo/param/UserDataIntegrityParam.java | 19 + .../pojo/po/responsibility/RespData.java | 57 ++ .../po/responsibility/RespDataResult.java | 82 ++ .../pojo/po/responsibility/RespUserData.java | 60 ++ .../responsibility/RespUserDataIntegrity.java | 64 ++ .../ResponsibilityController.java | 95 ++ .../responsibility/UserDataController.java | 112 +++ .../mapper/responsibility/RespDataMapper.java | 25 + .../responsibility/RespDataResultMapper.java | 16 + .../RespUserDataIntegrityMapper.java | 21 + .../responsibility/RespUserDataMapper.java | 24 + .../responsibility/mapping/RespDataMapper.xml | 26 + .../mapping/RespDataResultMapper.xml | 5 + .../mapping/RespUserDataIntegrityMapper.xml | 11 + .../mapping/RespUserDataMapper.xml | 24 + .../IRespDataResultService.java | 20 + .../responsibility/IRespDataService.java | 32 + .../IRespUserDataIntegrityService.java | 19 + .../responsibility/IRespUserDataService.java | 36 + .../responsibility/impl/GetQvvrData.java | 214 +++++ .../responsibility/impl/JnaLibrary.java | 21 + .../impl/RespDataResultServiceImpl.java | 90 ++ .../impl/RespDataServiceImpl.java | 876 ++++++++++++++++++ .../RespUserDataIntegrityServiceImpl.java | 33 + .../impl/RespUserDataServiceImpl.java | 465 ++++++++++ .../njcn/advance/utils/AdvanceEnumUtil.java | 51 + .../utils/ResponsibilityCallDllOrSo.java | 31 + .../src/main/resources/harm_response.dll | Bin 0 -> 249344 bytes .../java/com/njcn/auth/utils/AuthPubUtil.java | 2 + .../njcn/common/pojo/dto/SelectOption.java | 23 + .../enums/response/CommonResponseEnum.java | 6 + .../java/com/njcn/common/utils/PubUtils.java | 75 ++ .../serializer/InstantDateDeserializer.java | 39 + .../serializer/InstantDateSerializer.java | 2 +- .../java/com/njcn/oss/constant/OssPath.java | 17 +- .../com/njcn/oss/enums/OssResponseEnum.java | 2 +- .../main/java/com/njcn/poi/util/PoiUtil.java | 5 - .../njcn/device/pq/pojo/po/LineDetail.java | 2 +- .../njcn/device/pq/pojo/vo/LineDetailVO.java | 6 + .../device/pq/mapper/mapping/LineMapper.xml | 4 + .../pq/service/impl/LineServiceImpl.java | 2 +- .../service/impl/TerminalBaseServiceImpl.java | 26 +- pqs-gateway/src/main/resources/bootstrap.yml | 8 +- pqs-harmonic/harmonic-api/pom.xml | 12 +- .../harmonic/api/HarmDataFeignClient.java | 28 + .../HarmDataFeignClientFallbackFactory.java | 39 + .../harmonic/enums/HarmonicResponseEnum.java | 2 + .../harmonic/pojo/param/HistoryHarmParam.java | 54 ++ .../njcn/harmonic/pojo/po/LimitTarget.java | 3 + pqs-harmonic/harmonic-boot/pom.xml | 50 +- .../harmonic/HarmonicBootApplication.java | 2 + .../controller/AnalyzeController.java | 4 - .../controller/HistoryResultController.java | 12 + .../PollutionSubstationController.java | 3 - .../harmonic/pojo}/QueryResultLimitVO.java | 12 +- .../service/HistoryResultService.java | 11 + .../harmonic/service/IPollutionService.java | 53 -- .../service/PollutionSubstationService.java | 9 - .../service/impl/AnalyzeServiceImpl.java | 204 ---- .../service/impl/AssesServiceImpl.java | 9 - .../service/impl/CustomReportServiceImpl.java | 129 +-- .../service/impl/HarmInHarmServiceImpl.java | 73 +- .../service/impl/HarmonicServiceImpl.java | 1 - .../impl/HistoryResultServiceImpl.java | 542 ++++++++--- .../service/impl/IntegrityServiceImpl.java | 3 - .../impl/OnlineRateDataServiceImpl.java | 4 - .../service/impl/PhotovoltaicServiceImpl.java | 238 +++-- .../service/impl/PollutionServiceImpl.java | 261 ------ .../impl/PollutionSubstationServiceImpl.java | 146 --- .../service/impl/SteadyDataServiceImpl.java | 5 - .../impl/SteadyExceedRateServiceImpl.java | 7 +- .../service/impl/THDistortionServiceImpl.java | 4 - .../service/impl/TerminalServiceImpl.java | 3 - .../src/main/resources/bootstrap.yml | 2 + .../com/njcn/influx/imapper/CommonMapper.java | 14 +- .../influx/imapper/DataHarmRateVMapper.java | 20 + .../com/njcn/influx/imapper/IDataIMapper.java | 20 + .../influx/pojo/bo/HarmonicHistoryData.java | 31 + .../pojo/constant/InfluxDBTableConstant.java | 154 +++ .../com/njcn/influx/pojo/dto/HarmData.java | 32 + .../influx/pojo/dto/HarmHistoryDataDTO.java | 24 + .../njcn/influx/service/CommonService.java | 96 +- .../influx/service/DataHarmRateVService.java | 13 + .../njcn/influx/service/IDataIService.java | 14 + .../service/impl/CommonServiceImpl.java | 60 +- .../service/impl/DataFlickerServiceImpl.java | 58 +- .../impl/DataHarmRateVServiceImpl.java | 26 + .../service/impl/IDataIServiceImpl.java | 25 + .../com/njcn/influx/utils/InfluxDbUtil.java | 376 -------- 104 files changed, 4709 insertions(+), 1670 deletions(-) create mode 100644 pqs-advance/advance-api/src/main/java/com/njcn/advance/enums/AdvanceResponseEnum.java create mode 100644 pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/CacheQvvrData.java create mode 100644 pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/DealDataResult.java create mode 100644 pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/DealUserDataResult.java create mode 100644 pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/HKDataStruct.java create mode 100644 pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/PDataStruct.java create mode 100644 pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/QvvrStruct.java create mode 100644 pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/UserDataExcel.java create mode 100644 pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/dto/responsibility/CustomerData.java create mode 100644 pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/dto/responsibility/CustomerResponsibility.java create mode 100644 pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/dto/responsibility/RespDataDTO.java create mode 100644 pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/dto/responsibility/ResponsibilityResult.java create mode 100644 pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/param/ResponsibilityCalculateParam.java create mode 100644 pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/param/ResponsibilitySecondCalParam.java create mode 100644 pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/param/UserDataIntegrityParam.java create mode 100644 pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/po/responsibility/RespData.java create mode 100644 pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/po/responsibility/RespDataResult.java create mode 100644 pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/po/responsibility/RespUserData.java create mode 100644 pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/po/responsibility/RespUserDataIntegrity.java create mode 100644 pqs-advance/advance-boot/src/main/java/com/njcn/advance/controller/responsibility/ResponsibilityController.java create mode 100644 pqs-advance/advance-boot/src/main/java/com/njcn/advance/controller/responsibility/UserDataController.java create mode 100644 pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/RespDataMapper.java create mode 100644 pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/RespDataResultMapper.java create mode 100644 pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/RespUserDataIntegrityMapper.java create mode 100644 pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/RespUserDataMapper.java create mode 100644 pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/mapping/RespDataMapper.xml create mode 100644 pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/mapping/RespDataResultMapper.xml create mode 100644 pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/mapping/RespUserDataIntegrityMapper.xml create mode 100644 pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/mapping/RespUserDataMapper.xml create mode 100644 pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/IRespDataResultService.java create mode 100644 pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/IRespDataService.java create mode 100644 pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/IRespUserDataIntegrityService.java create mode 100644 pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/IRespUserDataService.java create mode 100644 pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/GetQvvrData.java create mode 100644 pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/JnaLibrary.java create mode 100644 pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/RespDataResultServiceImpl.java create mode 100644 pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/RespDataServiceImpl.java create mode 100644 pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/RespUserDataIntegrityServiceImpl.java create mode 100644 pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/RespUserDataServiceImpl.java create mode 100644 pqs-advance/advance-boot/src/main/java/com/njcn/advance/utils/AdvanceEnumUtil.java create mode 100644 pqs-advance/advance-boot/src/main/java/com/njcn/advance/utils/ResponsibilityCallDllOrSo.java create mode 100644 pqs-advance/advance-boot/src/main/resources/harm_response.dll create mode 100644 pqs-common/common-core/src/main/java/com/njcn/common/pojo/dto/SelectOption.java create mode 100644 pqs-common/common-core/src/main/java/com/njcn/common/utils/serializer/InstantDateDeserializer.java create mode 100644 pqs-harmonic/harmonic-api/src/main/java/com/njcn/harmonic/api/HarmDataFeignClient.java create mode 100644 pqs-harmonic/harmonic-api/src/main/java/com/njcn/harmonic/api/fallback/HarmDataFeignClientFallbackFactory.java create mode 100644 pqs-harmonic/harmonic-api/src/main/java/com/njcn/harmonic/pojo/param/HistoryHarmParam.java rename pqs-harmonic/{harmonic-api/src/main/java/com/njcn/harmonic/pojo/vo => harmonic-boot/src/main/java/com/njcn/harmonic/pojo}/QueryResultLimitVO.java (63%) delete mode 100644 pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/IPollutionService.java delete mode 100644 pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/PollutionServiceImpl.java create mode 100644 pqs-influx/src/main/java/com/njcn/influx/imapper/DataHarmRateVMapper.java create mode 100644 pqs-influx/src/main/java/com/njcn/influx/imapper/IDataIMapper.java create mode 100644 pqs-influx/src/main/java/com/njcn/influx/pojo/bo/HarmonicHistoryData.java create mode 100644 pqs-influx/src/main/java/com/njcn/influx/pojo/constant/InfluxDBTableConstant.java create mode 100644 pqs-influx/src/main/java/com/njcn/influx/pojo/dto/HarmData.java create mode 100644 pqs-influx/src/main/java/com/njcn/influx/pojo/dto/HarmHistoryDataDTO.java create mode 100644 pqs-influx/src/main/java/com/njcn/influx/service/DataHarmRateVService.java create mode 100644 pqs-influx/src/main/java/com/njcn/influx/service/IDataIService.java create mode 100644 pqs-influx/src/main/java/com/njcn/influx/service/impl/DataHarmRateVServiceImpl.java create mode 100644 pqs-influx/src/main/java/com/njcn/influx/service/impl/IDataIServiceImpl.java delete mode 100644 pqs-influx/src/main/java/com/njcn/influx/utils/InfluxDbUtil.java diff --git a/pqs-advance/advance-api/pom.xml b/pqs-advance/advance-api/pom.xml index efcb1f2d2..eb06043eb 100644 --- a/pqs-advance/advance-api/pom.xml +++ b/pqs-advance/advance-api/pom.xml @@ -39,7 +39,20 @@ 3.0.9 compile - - + + com.njcn + common-poi + ${project.version} + + + com.njcn + common-oss + ${project.version} + + + com.njcn + harmonic-api + ${project.version} + diff --git a/pqs-advance/advance-api/src/main/java/com/njcn/advance/enums/AdvanceResponseEnum.java b/pqs-advance/advance-api/src/main/java/com/njcn/advance/enums/AdvanceResponseEnum.java new file mode 100644 index 000000000..909f41a62 --- /dev/null +++ b/pqs-advance/advance-api/src/main/java/com/njcn/advance/enums/AdvanceResponseEnum.java @@ -0,0 +1,52 @@ +package com.njcn.advance.enums; + +import lombok.Getter; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2021年04月13日 10:50 + */ +@Getter +public enum AdvanceResponseEnum { + + ANALYSIS_USER_DATA_ERROR("A0101","解析用采数据内容失败"), + + INTERNAL_ERROR("A0101","系统内部异常"), + + USER_DATA_EMPTY("A0101","用采数据内容为空"), + + USER_DATA_NOT_FOUND("A0101","未找到用采数据"), + + RESP_DATA_NOT_FOUND("A0101","未找到责任划分数据"), + + WIN_TIME_ERROR("A0101","限值时间小于窗口"), + + CALCULATE_INTERVAL_ERROR("A0101","对齐计算间隔值非法"), + + RESP_RESULT_DATA_NOT_FOUND("A0101","未找到责任划分缓存数据"), + + USER_DATA_P_NODE_PARAMETER_ERROR("A0101","无用采用户或所有用户的完整性均不满足条件"), + + RESPONSIBILITY_PARAMETER_ERROR("A0101","调用接口程序计算失败,参数非法") + ; + + private final String code; + + private final String message; + + AdvanceResponseEnum(String code, String message) { + this.code = code; + this.message = message; + } + + public static String getCodeByMsg(String msg){ + for (AdvanceResponseEnum userCodeEnum : AdvanceResponseEnum.values()) { + if (userCodeEnum.message.equalsIgnoreCase(msg)) { + return userCodeEnum.code; + } + } + return ""; + } + +} diff --git a/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/CacheQvvrData.java b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/CacheQvvrData.java new file mode 100644 index 000000000..852412a36 --- /dev/null +++ b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/CacheQvvrData.java @@ -0,0 +1,48 @@ +package com.njcn.advance.pojo.bo.responsibility; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.List; + +/** + * 当根据动态责任数据获取用户责任量化结果时,将需要的一些参数进行缓存 + * 比如 harmNum,pNode,HKData,FKData,HarmData,监测点的测量间隔,win窗口,最小公倍数 + * 以及FKData每个时间点的p对应的用户List + * + * @author hongawen + * @Date: 2019/4/29 16:06 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class CacheQvvrData implements Serializable { + + private int pNode; + + private int harmNum; + + private float[] harmData; + + private PDataStruct[] FKdata; + + private HKDataStruct[] HKdata; + + private List names; + + private int lineInterval; + + private int win; + + //最小公倍数 + private int minMultiple; + + //横轴时间 + private List times; + + + +} diff --git a/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/DealDataResult.java b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/DealDataResult.java new file mode 100644 index 000000000..d1d4a3ad2 --- /dev/null +++ b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/DealDataResult.java @@ -0,0 +1,37 @@ +package com.njcn.advance.pojo.bo.responsibility; + + +import lombok.Data; + +import java.io.Serializable; +import java.util.*; + +/** + * 处理用采原始数据得到的一个结果 + * + * @author hongawen + * @Date: 2019/4/26 15:57 + */ +@Data +public class DealDataResult implements Serializable { + + /*** + * String 户号@监测点号@户名 + * String yyyy-MM-dd + * Date 数据的详细日期 + * UserDataExcel 数据详细信息 + * 先以测量局号分组,再以该测量局号下每个日期分组 + */ + private Map>> totalData = new HashMap<>(); + + private List dates = new ArrayList<>(); + + /*** + * String 户号@监测点号@户名 + * String yyyy-MM-dd + * UserDataExcel 数据详细信息 + * 先以测量局号分组,再以该测量局号下每个日期分组 + */ + private Map>> totalListData = new HashMap<>(); + +} diff --git a/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/DealUserDataResult.java b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/DealUserDataResult.java new file mode 100644 index 000000000..365244dc8 --- /dev/null +++ b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/DealUserDataResult.java @@ -0,0 +1,31 @@ +package com.njcn.advance.pojo.bo.responsibility; + + +import com.njcn.advance.pojo.po.responsibility.RespUserDataIntegrity; +import lombok.Data; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * 针对天处理用采数据的结果实体 + * @author hongawen + * @Date: 2019/4/19 14:38 + */ +@Data +public class DealUserDataResult implements Serializable { + + //处理好的数据 + private List completed = new ArrayList<>(); + + //因当日完整性不足90,没有处理直接返回 + private List lack = new ArrayList<>(); + + //完整性不足时,用户信息描述 + private String detail; + + //完整性不足的具体信息 + private RespUserDataIntegrity respUserDataIntegrity; + +} diff --git a/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/HKDataStruct.java b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/HKDataStruct.java new file mode 100644 index 000000000..a4d7e74e2 --- /dev/null +++ b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/HKDataStruct.java @@ -0,0 +1,37 @@ +package com.njcn.advance.pojo.bo.responsibility; + +import com.sun.jna.Structure; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +@Data +@NoArgsConstructor +public class HKDataStruct extends Structure implements Serializable { + public float hk[] = new float[QvvrStruct.MAX_P_NODE + 1]; + + @Override + protected List getFieldOrder() { + return null; + } + + public HKDataStruct(double[] hk) { + for (int i = 0; i < hk.length; i++) { + this.hk[i] = (float) hk[i]; + } + } + + public static class ByReference extends HKDataStruct implements Structure.ByReference { + public ByReference(double[] p) { + super(p); + } + } + + public static class ByValue extends HKDataStruct implements Structure.ByValue { + public ByValue(double[] p) { + super(p); + } + } +} diff --git a/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/PDataStruct.java b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/PDataStruct.java new file mode 100644 index 000000000..d04f1cf89 --- /dev/null +++ b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/PDataStruct.java @@ -0,0 +1,41 @@ +package com.njcn.advance.pojo.bo.responsibility; + +import com.sun.jna.Structure; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.List; + +@Data +@NoArgsConstructor +public class PDataStruct extends Structure implements Serializable { + + public float p[] = new float[QvvrStruct.MAX_P_NODE]; + + @Override + protected List getFieldOrder() { + return null; + } + + public PDataStruct(double[] p) { + for (int i = 0; i < p.length; i++) { + this.p[i] = (float) p[i]; + } + } + + public static class ByReference extends PDataStruct implements Structure.ByReference { + public ByReference(double[] p) { + super(p); + } + } + + public static class ByValue extends PDataStruct implements Structure.ByValue { + public ByValue(double[] p) { + super(p); + } + } + + +} diff --git a/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/QvvrStruct.java b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/QvvrStruct.java new file mode 100644 index 000000000..119e17cc1 --- /dev/null +++ b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/QvvrStruct.java @@ -0,0 +1,200 @@ +package com.njcn.advance.pojo.bo.responsibility; + +import com.sun.jna.Structure; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.List; + +public class QvvrStruct extends Structure implements Serializable { + public static final int MAX_P_NODE= 200; //功率节点个数限制,按200个限制 + public static final int MAX_P_NUM= 96 * 100; //功率数据按15分钟间隔,100天处理 + public static final int MAX_HARM_NUM= 1440 * 100; //谐波数据按一分钟间隔,100天处理 + public static final int MAX_WIN_LEN=96 * 10; //按15分钟算10天 + public static final int MIN_WIN_LEN = 4; //按15分钟算1小时 + + + //输入参数 + public int cal_flag; //计算标志,0默认用电压和功率数据计算相关系数和责任,1用代入的动态相关系数计算责任 + public int harm_num; //谐波数据个数 + public int p_num; //功率数据个数 + public int p_node; //功率负荷节点数 + public int win; //数据窗大小 + public int res_num; //代入的责任数据个数 + public float harm_mk; //谐波电压门槛 + public float harm_data[]; //谐波数据序列 + public PDataStruct p_data[]; //功率数据序列 + public PDataStruct sim_data[]; //动态相关系数数据序列,可作为输入或者输出 + public PDataStruct FKdata[]; //不包含背景动态谐波责任数据序列,可作为输入或者输出 + public HKDataStruct HKdata[]; //包含背景动态谐波责任数据序列,可作为输入或者输出 + public float Core[]; //典则相关系数 + public float BjCore[]; //包含背景典则相关系数 + + //输出结果 + public int cal_ok; //是否计算正确标志,置位0表示未计算,置位1表示计算完成 + public float sumFKdata[];//不包含背景谐波责任 + public float sumHKdata[];//包含背景谐波责任 + + public QvvrStruct() { + cal_flag = 0; + harm_data = new float[MAX_HARM_NUM]; + p_data = new PDataStruct[MAX_P_NUM]; + sim_data = new PDataStruct[MAX_P_NUM]; + FKdata = new PDataStruct[MAX_P_NUM]; + HKdata = new HKDataStruct[MAX_P_NUM]; + Core = new float[MAX_P_NUM]; + BjCore = new float[MAX_P_NUM]; + sumFKdata = new float[MAX_P_NODE]; + sumHKdata = new float[MAX_P_NODE + 1]; + } + + public static class ByReference extends QvvrStruct implements Structure.ByReference { + + } + + public static class ByValue extends QvvrStruct implements Structure.ByValue { + + } + + + public PDataStruct[] getFKdata() { + return FKdata; + } + + public void setFKdata(PDataStruct[] FKdata) { + this.FKdata = FKdata; + } + + public HKDataStruct[] getHKdata() { + return HKdata; + } + + public void setHKdata(HKDataStruct[] HKdata) { + this.HKdata = HKdata; + } + + public float[] getSumFKdata() { + return sumFKdata; + } + + public void setSumFKdata(float[] sumFKdata) { + this.sumFKdata = sumFKdata; + } + + public float[] getSumHKdata() { + return sumHKdata; + } + + public void setSumHKdata(float[] sumHKdata) { + this.sumHKdata = sumHKdata; + } + + public int getCal_flag() { + return cal_flag; + } + + public void setCal_flag(int cal_flag) { + this.cal_flag = cal_flag; + } + + public int getHarm_num() { + return harm_num; + } + + public void setHarm_num(int harm_num) { + this.harm_num = harm_num; + } + + public float getHarm_mk() { + return harm_mk; + } + + public void setHarm_mk(float harm_mk) { + this.harm_mk = harm_mk; + } + + public float[] getHarm_data() { + return harm_data; + } + + public void setHarm_data(float[] harm_data) { + this.harm_data = harm_data; + } + + public float[] getCore() { + return Core; + } + + public void setCore(float[] core) { + Core = core; + } + + public float[] getBjCore() { + return BjCore; + } + + public void setBjCore(float[] bjCore) { + BjCore = bjCore; + } + + public int getCal_ok() { + return cal_ok; + } + + public void setCal_ok(int cal_ok) { + this.cal_ok = cal_ok; + } + + public int getP_num() { + return p_num; + } + + public void setP_num(int p_num) { + this.p_num = p_num; + } + + public int getP_node() { + return p_node; + } + + public void setP_node(int p_node) { + this.p_node = p_node; + } + + public int getWin() { + return win; + } + + public void setWin(int win) { + this.win = win; + } + + public int getRes_num() { + return res_num; + } + + public void setRes_num(int res_num) { + this.res_num = res_num; + } + + public PDataStruct[] getP_data() { + return p_data; + } + + public void setP_data(PDataStruct[] p_data) { + this.p_data = p_data; + } + + public PDataStruct[] getSim_data() { + return sim_data; + } + + public void setSim_data(PDataStruct[] sim_data) { + this.sim_data = sim_data; + } + + @Override + protected List getFieldOrder() { + return Arrays.asList(new String[]{"sumFKdata", "sumHKdata"}); + } +} diff --git a/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/UserDataExcel.java b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/UserDataExcel.java new file mode 100644 index 000000000..a6ea6a6fa --- /dev/null +++ b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/bo/responsibility/UserDataExcel.java @@ -0,0 +1,47 @@ +package com.njcn.advance.pojo.bo.responsibility; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + * 提取用采数据或者将用采数据写进excel的实体类 + * + * @author hongawen + * @date 2019/4/11 10:43 + */ +@Data +public class UserDataExcel implements Serializable, Comparable { + + @Excel(name = "时间") + private String time; + + @Excel(name = "瞬时功率") + private BigDecimal work; + + @Excel(name = "户号") + private String userId; + + @Excel(name = "测量点局号") + private String line; + + @Excel(name = "户名") + private String userName; + + + @Override + public int compareTo(UserDataExcel o) { + + if (DateUtil.parse(this.time, DatePattern.NORM_DATETIME_PATTERN).getTime() > DateUtil.parse(o.getTime(), DatePattern.NORM_DATETIME_PATTERN).getTime()) { + return 1; + } else if (DateUtil.parse(this.time, DatePattern.NORM_DATETIME_PATTERN).getTime() == DateUtil.parse(o.getTime(), DatePattern.NORM_DATETIME_PATTERN).getTime()) { + return 0; + } + return -1; + } +} diff --git a/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/dto/responsibility/CustomerData.java b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/dto/responsibility/CustomerData.java new file mode 100644 index 000000000..0b3a4d3d2 --- /dev/null +++ b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/dto/responsibility/CustomerData.java @@ -0,0 +1,27 @@ +package com.njcn.advance.pojo.dto.responsibility; + +import lombok.Data; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * @author hongawen + * @Date: 2019/4/3 13:34 + */ +@Data +public class CustomerData implements Serializable { + + /*** + * 用户名称 + */ + private String customerName; + + + /*** + * 每时刻的数据 + */ + private List valueDatas=new ArrayList<>(); + +} diff --git a/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/dto/responsibility/CustomerResponsibility.java b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/dto/responsibility/CustomerResponsibility.java new file mode 100644 index 000000000..bb585e377 --- /dev/null +++ b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/dto/responsibility/CustomerResponsibility.java @@ -0,0 +1,28 @@ +package com.njcn.advance.pojo.dto.responsibility; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * @author hongawen + * @Date: 2019/4/3 13:35 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class CustomerResponsibility implements Serializable { + + /*** + * 用户名 + */ + private String customerName; + + /*** + * 责任值 + */ + private float responsibilityData; + +} diff --git a/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/dto/responsibility/RespDataDTO.java b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/dto/responsibility/RespDataDTO.java new file mode 100644 index 000000000..a537d8c24 --- /dev/null +++ b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/dto/responsibility/RespDataDTO.java @@ -0,0 +1,29 @@ +package com.njcn.advance.pojo.dto.responsibility; + +import com.njcn.advance.pojo.po.responsibility.RespData; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年07月24日 17:49 + */ +@Data +public class RespDataDTO extends RespData implements Serializable { + + private String userDataName; + + private String gdName; + + private String subName; + + private String devName; + + private String ip; + + private String lineName; + + +} diff --git a/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/dto/responsibility/ResponsibilityResult.java b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/dto/responsibility/ResponsibilityResult.java new file mode 100644 index 000000000..7d8f0a4a5 --- /dev/null +++ b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/dto/responsibility/ResponsibilityResult.java @@ -0,0 +1,53 @@ +package com.njcn.advance.pojo.dto.responsibility; + +import lombok.Data; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * 谐波责任量化最终结果,包括动态数据和责任量化结果 + * + * @author hongawen + * @Date: 2019/4/3 15:00 + */ +@Data +public class ResponsibilityResult implements Serializable { + + /*** + * 限值 + */ + private String limitValue; + + /*** + * 指定起始时间 + */ + private String limitSTime; + + /*** + * 指定结束时间 + */ + private String limitETime; + + /*** + * 责任划分结果存库数据 + */ + private String responsibilityDataIndex; + + /*** + * 每个用户的详细时刻的责任数据 + */ + private List datas; + + /*** + * 时间轴 + */ + private List timeDatas=new ArrayList<>(); + + /*** + * 用户责任的表格数据 + */ + private List responsibilities; + +} diff --git a/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/param/ResponsibilityCalculateParam.java b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/param/ResponsibilityCalculateParam.java new file mode 100644 index 000000000..f624a72aa --- /dev/null +++ b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/param/ResponsibilityCalculateParam.java @@ -0,0 +1,50 @@ +package com.njcn.advance.pojo.param; + +import com.njcn.common.pojo.constant.PatternRegex; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import java.io.Serializable; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年07月21日 10:20 + */ +@Data +public class ResponsibilityCalculateParam implements Serializable { + + + @ApiModelProperty("开始时间") + @NotBlank(message = "参数不能为空") + @Pattern(regexp = PatternRegex.TIME_FORMAT, message = "时间格式错误") + private String searchBeginTime; + + @ApiModelProperty("结束时间") + @NotBlank(message = "参数不能为空") + @Pattern(regexp = PatternRegex.TIME_FORMAT, message = "时间格式错误") + private String searchEndTime; + + @NotBlank(message = "参数不能为空") + @ApiModelProperty("监测点索引") + private String lineId; + + @NotBlank(message = "参数不能为空") + @ApiModelProperty("用采数据索引") + private String userDataId; + + @Min(0) + @Max(1) + @ApiModelProperty("0-电流 1-电压") + private int type; + + @Min(2) + @Max(50) + @ApiModelProperty("谐波次数") + private Integer time; + +} diff --git a/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/param/ResponsibilitySecondCalParam.java b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/param/ResponsibilitySecondCalParam.java new file mode 100644 index 000000000..35a762497 --- /dev/null +++ b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/param/ResponsibilitySecondCalParam.java @@ -0,0 +1,46 @@ +package com.njcn.advance.pojo.param; + +import com.njcn.common.pojo.constant.PatternRegex; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import java.io.Serializable; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年07月24日 15:47 + */ +@Data +public class ResponsibilitySecondCalParam implements Serializable { + + @NotBlank(message = "参数不能为空") + @ApiModelProperty("责任数据索引") + private String resDataId; + + @Min(2) + @Max(50) + @ApiModelProperty("谐波次数") + private Integer time; + + @Min(0) + @Max(1) + @ApiModelProperty("0-电流 1-电压") + private int type; + + @ApiModelProperty("限值") + private float limitValue; + + @ApiModelProperty("开始时间(yyyy-MM-dd HH:mm:ss)") + @NotBlank(message = "参数不能为空") + private String limitStartTime; + + @ApiModelProperty("结束时间(yyyy-MM-dd HH:mm:ss)") + @NotBlank(message = "参数不能为空") + private String limitEndTime; + +} diff --git a/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/param/UserDataIntegrityParam.java b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/param/UserDataIntegrityParam.java new file mode 100644 index 000000000..cc8c03636 --- /dev/null +++ b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/param/UserDataIntegrityParam.java @@ -0,0 +1,19 @@ +package com.njcn.advance.pojo.param; + +import com.njcn.web.pojo.param.BaseParam; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年07月25日 14:14 + */ +@Data +public class UserDataIntegrityParam extends BaseParam implements Serializable { + + + private String userDataId; + +} diff --git a/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/po/responsibility/RespData.java b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/po/responsibility/RespData.java new file mode 100644 index 000000000..3ea329aa3 --- /dev/null +++ b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/po/responsibility/RespData.java @@ -0,0 +1,57 @@ +package com.njcn.advance.pojo.po.responsibility; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.njcn.db.bo.BaseEntity; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Getter; +import lombok.Setter; + +/** + * + * @author hongawen + * @since 2023-07-21 + */ +@Getter +@Setter +@TableName("pqs_resp_data") +public class RespData extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 责任量化数据结果 + */ + private String id; + + /** + * 监测点索引 + */ + private String lineId; + + /** + * 用采数据索引 + */ + private String userDataId; + + /** + * 谐波类型(谐波电压、谐波电流) + */ + private String dataType; + + /** + * 谐波次数 + */ + private String dataTimes; + + /** + * 计算的时间窗口 + */ + private String timeWindow; + + /** + * 状态(0 删除 1正常) + */ + private Integer state; + +} diff --git a/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/po/responsibility/RespDataResult.java b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/po/responsibility/RespDataResult.java new file mode 100644 index 000000000..382145390 --- /dev/null +++ b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/po/responsibility/RespDataResult.java @@ -0,0 +1,82 @@ +package com.njcn.advance.pojo.po.responsibility; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.njcn.db.bo.BaseEntity; +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Date; + +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * + *

+ * + * @author hongawen + * @since 2023-07-24 + */ +@Getter +@Setter +@TableName("pqs_resp_data_result") +public class RespDataResult extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 责任划分结果数据文件保存记录表 + */ + private String id; + + /** + * 责任划分结果表id + */ + private String resDataId; + + /** + * 限值 + */ + private Float limitValue; + + /*** + * 起始时间 + */ + private Date startTime; + + /*** + * 结束时间 + */ + private Date endTime; + + /** + * 谐波次数 + */ + private Integer time; + + /** + * 用户责任数据地址 + */ + private String userDetailData; + + /** + * 用户责任时间数据地址 + */ + private String timeData; + + /** + * 前10用户的每刻对应的责任数据地址 + */ + private String userResponsibility; + + /** + * 调用高级算法后的数据结果地址,提供二次计算 + */ + private String qvvrData; + + /** + * 状态(0 删除 1正常) + */ + private Integer state; + +} diff --git a/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/po/responsibility/RespUserData.java b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/po/responsibility/RespUserData.java new file mode 100644 index 000000000..5d967f44b --- /dev/null +++ b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/po/responsibility/RespUserData.java @@ -0,0 +1,60 @@ +package com.njcn.advance.pojo.po.responsibility; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.njcn.db.bo.BaseEntity; + +import java.io.Serializable; +import java.time.LocalDate; +import java.time.LocalDateTime; + +import lombok.Getter; +import lombok.Setter; + +/** + * + * @author hongawen + * @since 2023-07-13 + */ +@Getter +@Setter +@TableName("pqs_resp_user_data") +public class RespUserData extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 用采数据表id + */ + private String id; + + /** + * 用采数据名称 + */ + private String name; + + /** + * 起始日期 + */ + private LocalDate startTime; + + /** + * 截止日期 + */ + private LocalDate endTime; + + /** + * 0 存在数据不完整的;1 存在数据完整 + */ + private Integer integrity = 1; + + /** + * 用采数据存放地址 + */ + private String dataPath; + + /** + * 状态(0 删除 1正常) + */ + private Integer state; + +} diff --git a/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/po/responsibility/RespUserDataIntegrity.java b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/po/responsibility/RespUserDataIntegrity.java new file mode 100644 index 000000000..d8a20195f --- /dev/null +++ b/pqs-advance/advance-api/src/main/java/com/njcn/advance/pojo/po/responsibility/RespUserDataIntegrity.java @@ -0,0 +1,64 @@ +package com.njcn.advance.pojo.po.responsibility; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.njcn.db.bo.BaseEntity; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Getter; +import lombok.Setter; + +/** + * + * @author hongawen + * @since 2023-07-13 + */ +@Getter +@Setter +@TableName("pqs_resp_user_data_integrity") +public class RespUserDataIntegrity extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 用采数据完整不足表Id + */ + private String id; + + /** + * 用采数据表id + */ + private String userDataId; + + /** + * 用户名称 + */ + private String userName; + + /** + * 用户户号 + */ + private String userNo; + + /** + * 测量点局号 + */ + private String lineNo; + + /** + * 数据不完整的日期 + */ + private LocalDate lackDate; + + /** + * 完整率(低于90%会记录) + */ + private BigDecimal integrity; + + /** + * 状态(0 删除 1正常) + */ + private Integer state; + +} diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/controller/responsibility/ResponsibilityController.java b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/controller/responsibility/ResponsibilityController.java new file mode 100644 index 000000000..9b9a754b5 --- /dev/null +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/controller/responsibility/ResponsibilityController.java @@ -0,0 +1,95 @@ +package com.njcn.advance.controller.responsibility; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.njcn.advance.pojo.dto.responsibility.RespDataDTO; +import com.njcn.advance.pojo.dto.responsibility.ResponsibilityResult; +import com.njcn.advance.pojo.param.ResponsibilityCalculateParam; +import com.njcn.advance.pojo.param.ResponsibilitySecondCalParam; +import com.njcn.advance.service.responsibility.IRespDataResultService; +import com.njcn.advance.service.responsibility.IRespDataService; +import com.njcn.common.pojo.annotation.OperateInfo; +import com.njcn.common.pojo.enums.common.LogEnum; +import com.njcn.common.pojo.enums.response.CommonResponseEnum; +import com.njcn.common.pojo.response.HttpResult; +import com.njcn.common.utils.HttpResultUtil; +import com.njcn.web.controller.BaseController; +import com.njcn.web.pojo.param.BaseParam; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年07月21日 10:06 + */ +@RestController +@RequestMapping("responsibility") +@Api(tags = "谐波责任划分-谐波责任数据处理") +@RequiredArgsConstructor +public class ResponsibilityController extends BaseController { + + private final IRespDataService respDataService; + + private final IRespDataResultService respDataResultService; + + @OperateInfo(info = LogEnum.BUSINESS_COMMON) + @PostMapping("/responsibilityList") + @ApiOperation("列表分页") + @ApiImplicitParam(name = "queryParam", value = "查询参数", required = true) + public HttpResult> responsibilityList(@RequestBody @Validated BaseParam queryParam) { + String methodDescribe = getMethodDescribe("responsibilityList"); + Page list = respDataService.responsibilityList(queryParam); + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, list, methodDescribe); + } + + @OperateInfo(info = LogEnum.BUSINESS_COMMON) + @PostMapping("/deleteByIds") + @ApiOperation("删除责任划分数据") + @ApiImplicitParam(name = "ids", value = "待删除的责任id集合", required = true) + public HttpResult> deleteByIds(@RequestBody List ids) { + String methodDescribe = getMethodDescribe("deleteByIds"); + respDataService.deleteByIds(ids); + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe); + } + + + + @PostMapping("getDynamicData") + @OperateInfo(info = LogEnum.BUSINESS_COMMON) + @ApiOperation("动态谐波责任划分") + @ApiImplicitParam(name = "responsibilityCalculateParam", value = "谐波责任动态划分参数", required = true) + public HttpResult getDynamicData(@RequestBody @Validated ResponsibilityCalculateParam responsibilityCalculateParam) { + String methodDescribe = getMethodDescribe("getDynamicData"); + ResponsibilityResult datas = respDataService.getDynamicData(responsibilityCalculateParam); + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, datas, methodDescribe); + } + + @PostMapping("getResponsibilityData") + @OperateInfo(info = LogEnum.BUSINESS_COMMON) + @ApiOperation("二次计算责任划分") + @ApiImplicitParam(name = "responsibilitySecondCalParam", value = "二次计算责任划分参数", required = true) + public HttpResult getResponsibilityData(@RequestBody @Validated ResponsibilitySecondCalParam responsibilitySecondCalParam) { + String methodDescribe = getMethodDescribe("getResponsibilityData"); + ResponsibilityResult datas = respDataService.getResponsibilityData(responsibilitySecondCalParam); + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, datas, methodDescribe); + } + + + @GetMapping("displayHistoryData") + @OperateInfo(info = LogEnum.BUSINESS_COMMON) + @ApiOperation("回显历史责任划分结果") + @ApiImplicitParam(name = "id", value = "责任数据id", required = true) + public HttpResult> displayHistoryData(String id,Integer time) { + String methodDescribe = getMethodDescribe("displayHistoryData"); + List datas = respDataResultService.displayHistoryData(id,time); + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, datas, methodDescribe); + } + +} diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/controller/responsibility/UserDataController.java b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/controller/responsibility/UserDataController.java new file mode 100644 index 000000000..7c48cbeae --- /dev/null +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/controller/responsibility/UserDataController.java @@ -0,0 +1,112 @@ +package com.njcn.advance.controller.responsibility; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.njcn.advance.pojo.dto.responsibility.RespDataDTO; +import com.njcn.advance.pojo.param.UserDataIntegrityParam; +import com.njcn.advance.pojo.po.responsibility.RespUserData; +import com.njcn.advance.pojo.po.responsibility.RespUserDataIntegrity; +import com.njcn.advance.service.responsibility.IRespUserDataIntegrityService; +import com.njcn.advance.service.responsibility.IRespUserDataService; +import com.njcn.common.pojo.annotation.OperateInfo; +import com.njcn.common.pojo.dto.SelectOption; +import com.njcn.common.pojo.enums.common.LogEnum; +import com.njcn.common.pojo.enums.response.CommonResponseEnum; +import com.njcn.common.pojo.exception.BusinessException; +import com.njcn.common.pojo.response.HttpResult; +import com.njcn.common.utils.HttpResultUtil; +import com.njcn.web.controller.BaseController; +import com.njcn.web.pojo.param.BaseParam; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.util.List; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年07月13日 14:11 + */ +@RestController +@RequestMapping("responsibility") +@Api(tags = "谐波责任划分-用采数据处理") +@RequiredArgsConstructor +public class UserDataController extends BaseController { + + + private final IRespUserDataService respUserDataService; + + private final IRespUserDataIntegrityService respUserDataIntegrityService; + + + @OperateInfo(info = LogEnum.BUSINESS_COMMON) + @PostMapping("/userDataList") + @ApiOperation("列表分页") + @ApiImplicitParam(name = "queryParam", value = "查询参数", required = true) + public HttpResult> userDataList(@RequestBody @Validated BaseParam queryParam) { + String methodDescribe = getMethodDescribe("userDataList"); + Page list = respUserDataService.userDataList(queryParam); + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, list, methodDescribe); + } + + + @OperateInfo(info = LogEnum.BUSINESS_COMMON) + @GetMapping("/userDataIntegrityList") + @ApiOperation("用采完整性不足列表") + @ApiImplicitParam(name = "userDataIntegrityParam", value = "查询参数", required = true) + public HttpResult> userDataIntegrityList(@RequestBody @Validated UserDataIntegrityParam userDataIntegrityParam) { + String methodDescribe = getMethodDescribe("userDataIntegrityList"); + Page list = respUserDataIntegrityService.userDataIntegrityList(userDataIntegrityParam); + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, list, methodDescribe); + } + + @OperateInfo(info = LogEnum.BUSINESS_COMMON) + @PostMapping("/deleteUserDataByIds") + @ApiOperation("删除用采数据") + @ApiImplicitParam(name = "ids", value = "待删除用采数据id集合", required = true) + public HttpResult> deleteUserDataByIds(@RequestBody List ids) { + String methodDescribe = getMethodDescribe("deleteUserDataByIds"); + respUserDataService.deleteUserDataByIds(ids); + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe); + } + + + @OperateInfo(info = LogEnum.BUSINESS_COMMON) + @GetMapping("/userDataSelect") + @ApiOperation("用采数据下拉") + public HttpResult> userDataSelect() { + String methodDescribe = getMethodDescribe("userDataSelect"); + List listOption = respUserDataService.userDataSelect(); + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, listOption, methodDescribe); + } + + /** + * 上传用采数据,并对用采数据进行数据分析并缓存 + * + * @param file 上传的表格 + */ + @PostMapping("uploadUserData") + @OperateInfo(info = LogEnum.BUSINESS_COMMON) + @ApiOperation("上传用采数据") + public HttpResult uploadUserData(@ApiParam(value = "文件", required = true) @RequestPart("file") MultipartFile file, HttpServletResponse response) { + String methodDescribe = getMethodDescribe("uploadUserData"); + String fileName = file.getOriginalFilename(); + long fileSize = file.getSize() / 1024; + //判断文件大小 + if (fileSize > 3072) { + throw new BusinessException(CommonResponseEnum.FILE_SIZE_ERROR); + } + if (!fileName.matches("^.+\\.(?i)(xlsx)$") && !fileName.matches("^.+\\.(?i)(xls)$")) { + throw new BusinessException(CommonResponseEnum.FILE_XLSX_ERROR); + } + respUserDataService.uploadUserData(file, response); + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe); + } + +} diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/RespDataMapper.java b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/RespDataMapper.java new file mode 100644 index 000000000..543be4fbd --- /dev/null +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/RespDataMapper.java @@ -0,0 +1,25 @@ +package com.njcn.advance.mapper.responsibility; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.njcn.advance.pojo.dto.responsibility.RespDataDTO; +import com.njcn.advance.pojo.po.responsibility.RespData; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author hongawen + * @since 2023-07-21 + */ +public interface RespDataMapper extends BaseMapper { + + Page page(@Param("page") Page objectPage, @Param("ew")QueryWrapper queryWrapper); + + void deleteByIds(@Param("ids") List ids); +} diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/RespDataResultMapper.java b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/RespDataResultMapper.java new file mode 100644 index 000000000..1736bf9b3 --- /dev/null +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/RespDataResultMapper.java @@ -0,0 +1,16 @@ +package com.njcn.advance.mapper.responsibility; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.njcn.advance.pojo.po.responsibility.RespDataResult; + +/** + *

+ * Mapper 接口 + *

+ * + * @author hongawen + * @since 2023-07-24 + */ +public interface RespDataResultMapper extends BaseMapper { + +} diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/RespUserDataIntegrityMapper.java b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/RespUserDataIntegrityMapper.java new file mode 100644 index 000000000..648e61125 --- /dev/null +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/RespUserDataIntegrityMapper.java @@ -0,0 +1,21 @@ +package com.njcn.advance.mapper.responsibility; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.njcn.advance.pojo.po.responsibility.RespUserDataIntegrity; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author hongawen + * @since 2023-07-13 + */ +public interface RespUserDataIntegrityMapper extends BaseMapper { + + Page page(@Param("page") Page objectPage, @Param("ew") QueryWrapper lambdaQueryWrapper); +} diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/RespUserDataMapper.java b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/RespUserDataMapper.java new file mode 100644 index 000000000..d06912916 --- /dev/null +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/RespUserDataMapper.java @@ -0,0 +1,24 @@ +package com.njcn.advance.mapper.responsibility; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.njcn.advance.pojo.po.responsibility.RespUserData; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author hongawen + * @since 2023-07-13 + */ +public interface RespUserDataMapper extends BaseMapper { + + Page page(@Param("page")Page objectPage, @Param("ew")QueryWrapper respUserDataQueryWrapper); + + void deleteUserDataByIds(@Param("ids") List ids); +} diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/mapping/RespDataMapper.xml b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/mapping/RespDataMapper.xml new file mode 100644 index 000000000..886e4e7d1 --- /dev/null +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/mapping/RespDataMapper.xml @@ -0,0 +1,26 @@ + + + + + + + + update + pqs_resp_data + set state = 0 + where + id + in + + #{item} + + + + diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/mapping/RespDataResultMapper.xml b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/mapping/RespDataResultMapper.xml new file mode 100644 index 000000000..911a33503 --- /dev/null +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/mapping/RespDataResultMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/mapping/RespUserDataIntegrityMapper.xml b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/mapping/RespUserDataIntegrityMapper.xml new file mode 100644 index 000000000..49c4619f7 --- /dev/null +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/mapping/RespUserDataIntegrityMapper.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/mapping/RespUserDataMapper.xml b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/mapping/RespUserDataMapper.xml new file mode 100644 index 000000000..88e957b2b --- /dev/null +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/mapper/responsibility/mapping/RespUserDataMapper.xml @@ -0,0 +1,24 @@ + + + + + + + + update + pqs_resp_user_data + set state = 0 + where + id + in + + #{item} + + + + + diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/IRespDataResultService.java b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/IRespDataResultService.java new file mode 100644 index 000000000..ebb6a0b88 --- /dev/null +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/IRespDataResultService.java @@ -0,0 +1,20 @@ +package com.njcn.advance.service.responsibility; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.njcn.advance.pojo.dto.responsibility.ResponsibilityResult; +import com.njcn.advance.pojo.po.responsibility.RespDataResult; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author hongawen + * @since 2023-07-24 + */ +public interface IRespDataResultService extends IService { + + List displayHistoryData(String id, Integer time); +} diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/IRespDataService.java b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/IRespDataService.java new file mode 100644 index 000000000..d02d0a8ef --- /dev/null +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/IRespDataService.java @@ -0,0 +1,32 @@ +package com.njcn.advance.service.responsibility; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.njcn.advance.pojo.dto.responsibility.RespDataDTO; +import com.njcn.advance.pojo.dto.responsibility.ResponsibilityResult; +import com.njcn.advance.pojo.param.ResponsibilityCalculateParam; +import com.njcn.advance.pojo.param.ResponsibilitySecondCalParam; +import com.njcn.advance.pojo.po.responsibility.RespData; +import com.njcn.web.pojo.param.BaseParam; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author hongawen + * @since 2023-07-21 + */ +public interface IRespDataService extends IService { + + ResponsibilityResult getDynamicData(ResponsibilityCalculateParam responsibilityCalculateParam); + + ResponsibilityResult getResponsibilityData(ResponsibilitySecondCalParam responsibilitySecondCalParam); + + Page responsibilityList(BaseParam queryParam); + + void deleteByIds(List ids); + +} diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/IRespUserDataIntegrityService.java b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/IRespUserDataIntegrityService.java new file mode 100644 index 000000000..fe10b117c --- /dev/null +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/IRespUserDataIntegrityService.java @@ -0,0 +1,19 @@ +package com.njcn.advance.service.responsibility; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.njcn.advance.pojo.param.UserDataIntegrityParam; +import com.njcn.advance.pojo.po.responsibility.RespUserDataIntegrity; + +/** + *

+ * 服务类 + *

+ * + * @author hongawen + * @since 2023-07-13 + */ +public interface IRespUserDataIntegrityService extends IService { + + Page userDataIntegrityList(UserDataIntegrityParam userDataIntegrityParam); +} diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/IRespUserDataService.java b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/IRespUserDataService.java new file mode 100644 index 000000000..e75e7d5b9 --- /dev/null +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/IRespUserDataService.java @@ -0,0 +1,36 @@ +package com.njcn.advance.service.responsibility; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.njcn.advance.pojo.po.responsibility.RespUserData; +import com.njcn.common.pojo.dto.SelectOption; +import com.njcn.web.pojo.param.BaseParam; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author hongawen + * @since 2023-07-13 + */ +public interface IRespUserDataService extends IService { + + /** + * 解析用采数据并保存 + * @author hongawen + * @date 2023/7/13 19:48 + * @param file 用采数据 + */ + void uploadUserData(MultipartFile file, HttpServletResponse response); + + Page userDataList(BaseParam queryParam); + + List userDataSelect(); + + void deleteUserDataByIds(List ids); +} diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/GetQvvrData.java b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/GetQvvrData.java new file mode 100644 index 000000000..9048f33e4 --- /dev/null +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/GetQvvrData.java @@ -0,0 +1,214 @@ +package com.njcn.advance.service.responsibility.impl; + +import com.njcn.advance.pojo.bo.responsibility.PDataStruct; +import com.njcn.advance.pojo.bo.responsibility.QvvrStruct; +import org.springframework.stereotype.Component; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年07月21日 15:00 + */ +@Component +public class GetQvvrData { + + public QvvrStruct getResponsibilityResult(QvvrStruct qvvrStruct){ + JnaLibrary instance = JnaLibrary.INSTANCE; + instance.harm_response(qvvrStruct); + return qvvrStruct; + + } + + //加载DLL + public QvvrStruct loadDll() { + QvvrStruct qvvrStruct = new QvvrStruct(); + QvvrStruct qvvr = new QvvrStruct(); + setBaseData(qvvr); + setPData(qvvrStruct); + setHarmData(qvvrStruct); + JnaLibrary instance = JnaLibrary.INSTANCE; + // 方法一 + int harmtime = 3; //谐波数据统计间隔 + int ptime = 15; //功率数据统计间隔 + //传入前做对齐处理 + int length = getLCM(harmtime, ptime); //根据测试数据做处理 + int offset = length / harmtime; //步长 + int k = 0; + + for (int i = 0; i < qvvrStruct.harm_data.length; i += offset) { + float sum = 0f; + for (int j = 0; j < offset; j++) { + sum += qvvrStruct.harm_data[i + j]; + } + qvvr.harm_data[k++] = sum / offset; + } + + qvvr.p_data = qvvrStruct.p_data; + + instance.harm_response(qvvr); + return qvvr; + } + + double[][] setArra() { + double harm_data[][] = new double[][]{ + //95%概率值,平均值 + {0.421182, 0.376303}, {0.443116, 0.392892}, {0.480774, 0.436424}, {0.5, 0.454237}, {0.514357, 0.460666}, {0.47809, 0.4224}, {0.5, 0.431136}, {0.507734, 0.455647}, {0.492801, 0.445712}, {0.453009, 0.412874}, {0.538021, 0.491503}, {0.487864, 0.450006}, {0.511345, 0.470324}, {0.526905, 0.481789}, {0.567498, 0.526258}, {0.559482, 0.519199}, {0.582407, 0.537011}, {0.524541, 0.484456}, {0.550445, 0.5}, {0.539187, 0.508035}, {0.5115, 0.475022}, {0.5, 0.460443}, {0.523108, 0.471858}, {0.541809, 0.499365}, {0.551924, 0.53286}, {0.518123, 0.470654}, {0.484079, 0.441841}, {0.519438, 0.468844}, + {0.538355, 0.493866}, {0.591741, 0.512794}, {0.602721, 0.516009}, {0.618723, 0.565805}, {0.609223, 0.546094}, {0.626051, 0.597788}, {0.632599, 0.569386}, {0.642238, 0.591324}, {0.588453, 0.557379}, {0.609521, 0.575329}, {0.581417, 0.546641}, {0.620059, 0.583734}, {0.627244, 0.596761}, {0.582457, 0.548869}, {0.58198, 0.545444}, {0.584733, 0.540609}, {0.614767, 0.543977}, {0.616507, 0.561557}, {0.598696, 0.536282}, {0.55535, 0.503941}, {0.555734, 0.505007}, {0.565363, 0.507497}, {0.601644, 0.552777}, {0.630807, 0.555282}, {0.562041, 0.508278}, {0.624497, 0.559969}, {0.630729, 0.565793}, {0.64554, 0.569383}, {0.588943, 0.517816}, {0.483016, 0.455107}, {0.46585, 0.438096}, {0.407376, 0.376834}, {0.484804, 0.456636}, + {0.523197, 0.471095}, {0.555807, 0.503968}, {0.607369, 0.550249}, {0.616805, 0.563411}, {0.552482, 0.456023}, {0.554987, 0.478333}, {0.47769, 0.401411}, {0.4998, 0.424089}, {0.518657, 0.460121}, {0.525532, 0.470562}, {0.498279, 0.449613}, {0.504881, 0.453663}, {0.520127, 0.470225}, {0.539036, 0.485645}, {0.560022, 0.5}, {0.577862, 0.523032}, {0.569663, 0.512485}, {0.581339, 0.497728}, {0.550951, 0.508571}, {0.543246, 0.499452}, {0.517934, 0.478775}, {0.523387, 0.479416}, {0.542646, 0.461374}, {0.554923, 0.481816}, {0.542126, 0.480768}, {0.476449, 0.405646}, {0.44047, 0.386011}, {0.462506, 0.401058}, {0.491334, 0.414671}, {0.47879, 0.417633}, {0.429966, 0.392107}, {0.5, 0.447939}, + {0.453461, 0.418106}, {0.499137, 0.434616}, {0.544004, 0.475149}, {0.522932, 0.467976}, {0.463644, 0.400073}, {0.443839, 0.384063}, {0.467672, 0.402044}, {0.529797, 0.472755}, {0.54869, 0.460646}, {0.577975, 0.5}, {0.518761, 0.434722}, {0.468482, 0.412333}, {0.509798, 0.441707}, {0.479864, 0.423142}, {0.464665, 0.387774}, {0.469049, 0.415868}, {0.533361, 0.469168}, {0.533403, 0.447077}, {0.496622, 0.438827}, {0.524557, 0.468724}, {0.507505, 0.441028}, {0.442116, 0.379901}, {0.425815, 0.33589}, {0.380761, 0.303592}, {0.375508, 0.312206}, {0.401516, 0.355122}, {0.37918, 0.337434}, {0.427144, 0.36633}, {0.445274, 0.416885}, {0.46856, 0.455736}, {0.482769, 0.435905}, {0.483235, 0.454334}, {0.487906, 0.465239}, {0.499212, 0.460211}, {0.449448, 0.431084}, + {0.46084, 0.441158}, {0.42006, 0.390422}, {0.371453, 0.345079}, {0.404723, 0.369972}, {0.410122, 0.382584}, {0.414845, 0.378829}, {0.405413, 0.367723}, {0.340834, 0.319235}, {0.388672, 0.351682}, {0.419939, 0.377351}, {0.36093, 0.30654}, {0.327308, 0.298369}, {0.366467, 0.334424}, {0.393113, 0.354026}, {0.36901, 0.327083}, {0.330016, 0.307346}, {0.315253, 0.29403}, {0.339087, 0.310131}, {0.318166, 0.302134}, {0.318716, 0.284097}, {0.3301, 0.26928}, {0.263012, 0.238406}, {0.245838, 0.193465}, {0.212407, 0.1777}, {0.220019, 0.182927}, {0.18744, 0.173439}, {0.20273, 0.184762}, {0.198372, 0.183279}, {0.197934, 0.18051}, {0.207479, 0.18146}, {0.214699, 0.196859}, {0.206577, 0.188506}, {0.196669, 0.17833}, {0.204951, 0.191389}, {0.20339, 0.187701}, + {0.193287, 0.17535}, {0.197431, 0.164326}, {0.194091, 0.16902}, {0.174527, 0.160805}, {0.206088, 0.189066}, {0.211934, 0.185604}, {0.223406, 0.208212}, {0.243066, 0.213813}, {0.238082, 0.218931}, {0.246116, 0.226238}, {0.243768, 0.225719}, {0.238501, 0.220668}, {0.23914, 0.219781}, {0.240534, 0.219224}, {0.253768, 0.229355}, {0.255755, 0.235939}, {0.227658, 0.209659}, {0.210573, 0.198015}, {0.224594, 0.215403}, {0.236112, 0.222425}, {0.249645, 0.232064}, {0.252415, 0.231874}, {0.257889, 0.238002}, {0.257772, 0.247031}, {0.255062, 0.239813}, {0.251417, 0.239162}, {0.257391, 0.240333}, {0.262569, 0.245791}, {0.257219, 0.242321}, {0.247257, 0.232114}, {0.252359, 0.233225}, {0.245803, 0.233074}, {0.246123, 0.230136}, {0.240798, 0.228197}, {0.251897, 0.238628}, + {0.256143, 0.24055}, {0.266466, 0.246405}, {0.237236, 0.223265}, {0.24894, 0.234627}, {0.261375, 0.24079}, {0.254242, 0.24326}, {0.24775, 0.226868}, {0.233592, 0.218866}, {0.23107, 0.214886}, {0.230155, 0.212598}, {0.237625, 0.219617}, {0.230664, 0.220104}, {0.230458, 0.213424}, {0.237349, 0.220088}, {0.242364, 0.216887}, {0.237915, 0.2267}, {0.229748, 0.212146}, {0.219177, 0.204241}, {0.225841, 0.209306}, {0.233535, 0.215846}, {0.240921, 0.221957}, {0.242329, 0.228333}, {0.250354, 0.233877}, {0.23753, 0.225154}, {0.223955, 0.212844}, {0.233343, 0.214018}, {0.233295, 0.219444}, {0.24112, 0.226227}, {0.250625, 0.233258}, {0.240264, 0.221393}, {0.234682, 0.220871}, {0.237586, 0.222812}, {0.234913, 0.225059}, + {0.220496, 0.205628}, {0.228863, 0.209626}, {0.213008, 0.202162}, {0.195847, 0.185185}, {0.198353, 0.186126}, {0.206804, 0.195191}, {0.211648, 0.201479}, {0.220213, 0.208657}, {0.225221, 0.20975}, {0.226414, 0.209176}, {0.210799, 0.202585}, {0.228444, 0.214508}, {0.238625, 0.226136}, {0.235173, 0.22402}, {0.233078, 0.219732}, {0.236726, 0.227129}, {0.242611, 0.234865}, {0.247075, 0.235196}, {0.237849, 0.227394}, {0.226909, 0.213198}, {0.239201, 0.225276}, {0.251326, 0.236187}, {0.25857, 0.243628}, {0.239532, 0.229661}, {0.252561, 0.2353}, {0.250934, 0.232273}, {0.234755, 0.218447}, {0.230927, 0.21828}, {0.221736, 0.211953}, {0.235807, 0.21878}, {0.233727, 0.220972}, {0.22405, 0.210502}, + {0.219727, 0.20933}, {0.228842, 0.214952}, {0.243605, 0.232698}, {0.236741, 0.222285}, {0.240326, 0.221328}, {0.243558, 0.218158}, {0.225166, 0.213072}, {0.228669, 0.214204}, {0.209442, 0.190643}, {0.19711, 0.184118}, {0.201937, 0.191768}, {0.213564, 0.188846}, {0.191817, 0.178616}, {0.209333, 0.192461}, {0.221065, 0.201867}, {0.201748, 0.191764}, {0.19846, 0.187052}, {0.202501, 0.187999}, {0.196366, 0.180029}, {0.184804, 0.164625}, {0.169156, 0.152679}, {0.164534, 0.146607}, {0.18738, 0.160903}, {0.152631, 0.138239}, {0.164935, 0.145286}, {0.163678, 0.149477}, {0.173508, 0.164349}, {0.175839, 0.166297}, {0.177457, 0.162255}, {0.170088, 0.154275}, {0.169628, 0.15597}, {0.176009, 0.155288}, {0.166454, 0.155766}, + {0.172568, 0.147663}, {0.176941, 0.161373}, {0.162015, 0.149444}, {0.161497, 0.144322}, {0.180245, 0.153109}, {0.193829, 0.177764}, {0.187128, 0.173117}, {0.18271, 0.171906}, {0.211863, 0.184382}, {0.183494, 0.165723}, {0.175513, 0.158287}, {0.160778, 0.144604}, {0.17295, 0.157631}, {0.167681, 0.151814}, {0.15489, 0.141056}, {0.166922, 0.150574}, {0.180741, 0.168346}, {0.178823, 0.163508}, {0.176291, 0.162042}, {0.174693, 0.159311}, {0.189821, 0.163844}, {0.169894, 0.155251}, {0.190969, 0.167618}, {0.186121, 0.163008}, {0.165922, 0.149759}, {0.172454, 0.155052}, {0.171777, 0.153449}, {0.162387, 0.15258}, {0.15151, 0.139361}, {0.147468, 0.136015}, {0.152005, 0.136971}, {0.146811, 0.132335}, {0.136256, 0.123485}, + {0.14432, 0.127967}, {0.135773, 0.122041}, {0.141036, 0.121208}, {0.155404, 0.132159}, {0.146916, 0.134459}, {0.142293, 0.124923}, {0.140416, 0.129312}, {0.150519, 0.13937}, {0.148458, 0.136749}, {0.152768, 0.141678}, {0.159225, 0.139103}, {0.152194, 0.136669}, {0.142653, 0.128965}, {0.154166, 0.138626}, {0.15818, 0.145939}, {0.161268, 0.149564}, {0.158277, 0.142801}, {0.16128, 0.149161}, {0.173898, 0.15968}, {0.17485, 0.160224}, {0.171942, 0.161618}, {0.165922, 0.14929}, {0.16008, 0.146344}, {0.189878, 0.166926}, {0.19424, 0.176669}, {0.18796, 0.172037}, {0.193344, 0.174043}, {0.187129, 0.174177}, {0.197465, 0.183027}, {0.202412, 0.188163}, {0.204287, 0.188413}, {0.210204, 0.197558}, {0.22259, 0.211319}, + {0.216285, 0.202288}, {0.219443, 0.205887}, {0.231072, 0.214069}, {0.235469, 0.218708}, {0.240179, 0.218601}, {0.233126, 0.222686}, {0.23866, 0.225621}, {0.246887, 0.229693}, {0.223049, 0.206965}, {0.231918, 0.214563}, {0.226944, 0.204329}, {0.22922, 0.205035}, {0.227151, 0.214745}, {0.247992, 0.228885}, {0.223265, 0.20742}, {0.234115, 0.212651}, {0.238683, 0.220068}, {0.235093, 0.22265}, {0.225259, 0.214613}, {0.219544, 0.207477}, {0.228725, 0.209466}, {0.218864, 0.198842}, {0.177282, 0.161237}, {0.16597, 0.146212}, {0.182446, 0.167677}, {0.186993, 0.176736}, {0.204163, 0.191434}, {0.214114, 0.201798}, {0.217216, 0.195598}, {0.179991, 0.1689}, {0.187686, 0.162794}, {0.199676, 0.189375}, {0.204391, 0.187223}, {0.202374, 0.176889}, {0.220633, 0.198128}, {0.21875, 0.208919}, {0.207812, 0.186273}, {0.204286, 0.187378}, {0.199194, 0.188072}, {0.194087, 0.181686}, {0.186233, 0.177195}, {0.209638, 0.195317}, {0.218003, 0.199507}, {0.20797, 0.191844}, {0.214187, 0.198068}, {0.20922, 0.194146}, {0.223887, 0.207361}, {0.217174, 0.206039}, {0.226457, 0.202169}, {0.236901, 0.202093}, {0.212731, 0.195643}, {0.181423, 0.167587}, {0.188487, 0.177714}, {0.193442, 0.182009}, {0.248524, 0.206543}, {0.2544, 0.24122}, {0.249019, 0.235919}, + {0.239922, 0.226271}, {0.22293, 0.201309}, {0.215308, 0.205072}, {0.221291, 0.206816}, {0.21243, 0.19884}, {0.251735, 0.224586}, {0.256491, 0.245859}, {0.2739, 0.256678}, {0.2511, 0.219579}, {0.233134, 0.216854}, {0.218466, 0.205217}, {0.227724, 0.217614}, {0.240949, 0.224521}, {0.227147, 0.215759}, {0.218221, 0.206185}, {0.221939, 0.206897}, {0.246645, 0.229124}, {0.240102, 0.222841}, {0.227908, 0.216006}, {0.233321, 0.217824}, {0.236728, 0.192326}, {0.164319, 0.153653}, {0.178124, 0.163764}, {0.179019, 0.153135}, {0.156981, 0.146881}, {0.187198, 0.157238}, {0.19062, 0.165146}, {0.196905, 0.18278}, {0.189542, 0.177882}, {0.199086, 0.18356}, {0.183394, 0.16363}, {0.178703, 0.161268}, {0.177477, 0.16235}, {0.188376, 0.175166}, {0.191094, 0.180351}, {0.189486, 0.170504}, {0.178688, 0.165567}, {0.190095, 0.163828}, {0.197259, 0.174446}, {0.198965, 0.168191}, {0.223467, 0.204276}, + {0.220976, 0.208839}, {0.233705, 0.222574}, {0.239038, 0.224511}, {0.261951, 0.246335}, {0.241004, 0.214832}, {0.242177, 0.222397}, {0.238796, 0.22659}, {0.233301, 0.216981}, {0.285964, 0.237934}, {0.289405, 0.270191}, {0.271462, 0.254545}, {0.226939, 0.195758}, {0.166201, 0.156417}, {0.239686, 0.184604}, {0.278307, 0.254105}, {0.263567, 0.241243}, {0.286406, 0.272604}, {0.286242, 0.270799}, {0.29057, 0.279378}, {0.372699, 0.340763}, {0.386973, 0.370736}, {0.376006, 0.356402}, {0.361862, 0.351453}, {0.37446, 0.361288}, {0.383746, 0.35643}, {0.388395, 0.341351}, {0.372339, 0.341113}, {0.339603, 0.326072}, {0.325363, 0.315546}, {0.337821, 0.321393}, {0.336637, 0.316094}, {0.370589, 0.352973}, {0.404361, 0.383465}, {0.370073, 0.324813}, {0.306259, 0.293561}, {0.301162, 0.292064}, {0.373354, 0.346376}, {0.382712, 0.363426}, {0.393655, 0.370275}, {0.388649, 0.372012}, {0.422221, 0.394562}, {0.430174, 0.414176}, {0.43871, 0.404679}, {0.420628, 0.400281}, {0.434745, 0.408691}, {0.40837, 0.39272}, {0.417839, 0.401282}, {0.430143, 0.37395}, {0.369299, 0.335339}, {0.356682, 0.342154}, {0.369892, 0.348809}, {0.391148, 0.367134}, {0.405555, 0.379744}, {0.369945, 0.360558}, {0.386083, 0.361355}, {0.394281, 0.373477}, {0.368804, 0.349045}, {0.363803, 0.324651}, {0.33211, 0.297263}, {0.363958, 0.33974}, {0.312475, 0.284267}, {0.269313, 0.251222}, {0.296505, 0.275687}, {0.290996, 0.279131}, {0.297931, 0.284196}, {0.304289, 0.289648}, {0.302365, 0.285597}, {0.310045, 0.289755}, {0.309761, 0.287844}, {0.33606, 0.325243}, {0.342453, 0.304549}, {0.281685, 0.264762}, {0.27269, 0.253986}, {0.264901, 0.244228}, {0.291342, 0.24908}, {0.287928, 0.274009}, {0.292762, 0.27117}, {0.247664, 0.214161}, {0.226292, 0.210227}, {0.222594, 0.204725}, {0.192156, 0.173312}, {0.255183, 0.190985}, {0.288839, 0.238156}, + {0.202443, 0.184253}, {0.279606, 0.226902}, {0.291613, 0.265214}, {0.318036, 0.291855}, {0.315816, 0.295782}, {0.315338, 0.296789}, {0.321272, 0.291736}, {0.311033, 0.296177}, {0.320741, 0.301768}, {0.330261, 0.305327}, {0.331024, 0.309082}, {0.340849, 0.315079}, {0.310502, 0.28647}, {0.294187, 0.278247}, {0.291642, 0.266644}, {0.298142, 0.284726}, {0.294694, 0.280252}, {0.324366, 0.296874}, {0.35545, 0.33866}, {0.357356, 0.285616}, {0.272704, 0.245387}, {0.336482, 0.306798}, {0.348524, 0.319703}, {0.332005, 0.312534}, {0.261513, 0.242122}, {0.241422, 0.224165}, {0.275129, 0.258587}, {0.255719, 0.239587}, {0.291192, 0.239963}, {0.29548, 0.27355}, {0.267593, 0.251909}, {0.264177, 0.247136}, {0.309179, 0.292042}, {0.298386, 0.278887}, {0.285263, 0.268809}, {0.27454, 0.255144}, {0.292567, 0.269762}, {0.321697, 0.302918}, {0.322473, 0.304375}, {0.322781, 0.305542}, {0.316763, 0.303494}, + {0.305252, 0.293228}, {0.300733, 0.286569}, {0.299452, 0.28738}, {0.307246, 0.290465}, {0.291247, 0.28235}, {0.336112, 0.32334}, {0.338988, 0.313663}, {0.329394, 0.306525}, {0.358552, 0.33284}, {0.353876, 0.337975}, {0.344794, 0.320814}, {0.318828, 0.302096}, {0.317194, 0.287986}, {0.310334, 0.273498}, {0.267861, 0.23982}, {0.252966, 0.231039}, {0.263492, 0.241593}, {0.291478, 0.257672}, {0.27575, 0.258514}, {0.319017, 0.284679}, {0.322512, 0.304512}, {0.313642, 0.288142}, {0.318502, 0.298701}, {0.332831, 0.29853}, {0.28124, 0.264095}, {0.325633, 0.297134}, {0.342627, 0.325642}, {0.367735, 0.343831}, {0.358511, 0.342522}, {0.347544, 0.326096}, {0.352417, 0.332682}, {0.353948, 0.339196}, {0.336863, 0.315851}, {0.308775, 0.292804}, {0.337708, 0.3234}, {0.326456, 0.309465}, {0.297819, 0.278425}, {0.307142, 0.294849}, {0.306098, 0.292181}, {0.309016, 0.294921}, {0.288254, 0.269049}, + {0.291336, 0.274014}, {0.277688, 0.262816}, {0.277642, 0.257323}, {0.260515, 0.246756}, {0.250313, 0.231751}, {0.280935, 0.240432}, {0.369548, 0.320905}, {0.375476, 0.346752}, {0.323906, 0.30272}, {0.370831, 0.338933}, {0.401767, 0.370326}, {0.363678, 0.329439}, {0.32919, 0.284333}, {0.309267, 0.283258}, {0.335987, 0.304786}, {0.332426, 0.286169}, {0.335812, 0.289459}, {0.359583, 0.311718}, {0.293007, 0.258411}, {0.309045, 0.273992}, {0.313766, 0.285657}, {0.291873, 0.249308}, {0.270368, 0.229868}, {0.32976, 0.282048}, {0.324873, 0.286651}, {0.320104, 0.28768}, {0.352896, 0.328657}, {0.373546, 0.324517}, {0.388009, 0.338782}, {0.358612, 0.318752}, {0.343836, 0.298782}, {0.285577, 0.248337}, {0.26622, 0.239405}, {0.297692, 0.266802}, {0.289974, 0.263987}, {0.336948, 0.296551}, {0.349037, 0.307811}, {0.303511, 0.269665}, {0.337613, 0.304315}, {0.360336, 0.33373}, {0.349773, 0.31566}, + {0.328797, 0.300475}, {0.309233, 0.273003}, {0.283246, 0.254893}, {0.274503, 0.245292}, {0.27789, 0.247498}, {0.28538, 0.257905}, {0.29829, 0.25643}, {0.289136, 0.252718}, {0.267904, 0.238913}, {0.239569, 0.214504}, {0.223609, 0.196023}, {0.260025, 0.212787}, {0.190141, 0.149117}, {0.206047, 0.168703}, {0.187694, 0.142291}, {0.229095, 0.176889}, {0.254062, 0.22647}, {0.297008, 0.261282}, {0.293264, 0.254861}, {0.270847, 0.245454}, {0.275136, 0.228237}, {0.243292, 0.215309}, {0.292864, 0.255345}, {0.293742, 0.25723}, {0.307466, 0.262106}, {0.329303, 0.302909}, {0.376331, 0.337664}, {0.400529, 0.374218}, {0.365348, 0.328427}, {0.324355, 0.256009}, {0.263968, 0.230136}, {0.255935, 0.227294}, {0.322001, 0.283753}, {0.331204, 0.300163}, {0.343343, 0.303748}, {0.371459, 0.333392}, {0.37128, 0.322152}, {0.297069, 0.274913}, {0.284353, 0.261349}, {0.302072, 0.275622}, {0.283124, 0.261858}, {0.295636, 0.276263}, {0.293501, 0.256853}, {0.295682, 0.265652}, {0.387293, 0.344303}, {0.316668, 0.288592}, {0.358624, 0.318055}, {0.340287, 0.31648}, {0.367002, 0.346892}, {0.360042, 0.331293}, {0.339225, 0.312844}, {0.372399, 0.337469}, {0.339429, 0.316097}, {0.350935, 0.324333}, {0.365339, 0.349729}, {0.37357, 0.346942}, {0.347497, 0.331054}, {0.36603, 0.3388}, {0.380055, 0.353265}, {0.373033, 0.344078}, {0.380213, 0.350827}, {0.351179, 0.333086}, {0.365324, 0.342232}, {0.368302, 0.349075}, {0.383816, 0.356771}, {0.376066, 0.355695}, {0.363852, 0.334578}, {0.368189, 0.349663}, {0.361988, 0.338079}, {0.367333, 0.34212}, {0.343782, 0.321325}, {0.370939, 0.34305}, {0.371127, 0.335415}, {0.403087, 0.373655}, {0.427343, 0.407802}, {0.430894, 0.407344}, {0.420599, 0.384669}, {0.409053, 0.38268}, {0.387683, 0.368241}, {0.378625, 0.362048}, {0.369629, 0.322266}, {0.384669, 0.352805}, {0.387653, 0.353361}, {0.373097, 0.331348}, {0.345351, 0.320154}, {0.329761, 0.305343}, {0.347823, 0.317789}, {0.301825, 0.281896}, {0.288031, 0.266913}, {0.297676, 0.275993}, {0.298724, 0.285629}, {0.29881, 0.279996}, {0.294846, 0.269495}, {0.292018, 0.266283}, {0.295321, 0.26208}, {0.287997, 0.25804}, {0.298674, 0.278638}, {0.282183, 0.261196}, {0.268649, 0.236609}, {0.290192, 0.265927}, {0.303826, 0.28}, {0.321899, 0.277529}, {0.364937, 0.331407}, {0.372401, 0.325812}, {0.321078, 0.294629}, {0.334786, 0.311853}, {0.29484, 0.259977}, {0.280517, 0.260442}, {0.301789, 0.283954}, {0.298576, 0.255971}, {0.283562, 0.255353}, {0.298173, 0.267593}, {0.304165, 0.288817}, {0.323779, 0.297315}, {0.323846, 0.304175}, {0.326846, 0.3102}, {0.341265, 0.312237}, {0.327004, 0.299716}, {0.341617, 0.30845}, {0.326068, 0.296064}, {0.326636, 0.2947}, {0.308147, 0.267845}, {0.266438, 0.243046}, {0.279886, 0.241874}, {0.291787, 0.267915}, {0.303702, 0.2749}, {0.299753, 0.273613}, {0.252581, 0.217536}, {0.245674, 0.218585}, {0.286192, 0.252054}, {0.298088, 0.26846}, {0.306473, 0.269683}, {0.314942, 0.291444}, {0.304038, 0.287126}, {0.304145, 0.271258}, {0.265417, 0.24557}, {0.270432, 0.241406}, {0.289709, 0.255829}, {0.281587, 0.260081}, {0.262281, 0.237217}, {0.243559, 0.22711}, {0.25313, 0.230604}, {0.277256, 0.250974}, {0.276545, 0.259195}, {0.275277, 0.229598}, {0.249331, 0.234145}, + {0.257448, 0.24044}, {0.263217, 0.238706}, {0.273547, 0.253362}, {0.291418, 0.262012}, {0.326324, 0.293477}, {0.291758, 0.269218}, {0.2802, 0.249886}, {0.297445, 0.264722}, {0.319088, 0.266785}, {0.301037, 0.279816}, {0.319664, 0.279273}, {0.274155, 0.251243}, {0.335662, 0.310764}, {0.34039, 0.309537}, {0.397571, 0.353868}, {0.377456, 0.353011}, {0.393919, 0.35666}, {0.412671, 0.390438}, {0.41048, 0.379504}, {0.417154, 0.381316}, {0.405149, 0.38245}, {0.410367, 0.3503}, {0.417862, 0.338405}, {0.416525, 0.380748}, {0.388613, 0.36515}, {0.427941, 0.398827}, {0.441894, 0.402339}, {0.389658, 0.35715}, {0.412591, 0.389575}, {0.425955, 0.390584}, {0.389658, 0.35715}, {0.455432, 0.421026}, {0.452355, 0.425073}, {0.456528, 0.433725}, {0.448065, 0.421165}, {0.450408, 0.424315}, {0.397535, 0.364162}, {0.3903, 0.362115}, {0.396668, 0.365791}, {0.423064, 0.386066}, + {0.424227, 0.397627}, {0.401368, 0.380254}, {0.397957, 0.373047}, {0.40201, 0.371677}, {0.389658, 0.35715}, {0.386188, 0.359802},}; + return harm_data; + } + + double[][] setArrb() { + double aaa[][] = new double[][]{ + {2.69, 3.2, 7.93, 296.2, 0, 8.4, 175, 26.4, 81.2, 438.02, 1.87, 0.36, 19.7, 4.9, 10.7, 246, 214, 9.32, 1.87, 0, 0}, {2.74, 1.9, 17.6, 291.6, 0, 7.44, 397, 26.5, 142, 491.67, 1.87, 0.36, 0.001, 3.22, 12.2, 251, 172, 31, 5.06, 0, 0}, {2.68, 1.88, 9.86, 283.8, 0, 4.08, 435, 24.9, 114, 473.05, 1.87, 0.41, 0.001, 5.03, 11.4, 243, 181, 11.6, 1.54, 0, 0}, {2.77, 1.64, 27.7, 235.3, 0, 4.08, 222, 54.1, 189, 402.01, 2.1, 0.17, 13.7, 5.54, 12.9, 226, 215, 11.3, 2.19, 0, 0}, {2.68, 1.71, 21.9, 220, 0, 4.08, 485, 25.1, 200, 520.885, 2.09, 0.17, 9.95, 7.13, 6.52, 205, 194, 12.2, 3.42, 0, 0}, {4.13, 1.71, 21, 131.5, 0, 4.16, 124, 24.7, 135, 532.982, 2.06, 0.13, 12.5, 3.14, 5.76, 186, 220, 8.15, 1.57, 0, 0}, {2.69, 2.12, 21.5, 153.6, 0, 4.08, 335, 24.6, 134, 513.939, 2.04, 0.13, 12.9, 4.94, 7.63, 183, 228, 10.5, 2.6, 0, 0}, {2.72, 1.72, 18.5, 197.9, 0, 4, 435, 24.5, 70.7, 442, 2.38, 0.13, 0.001, 7.02, 6.31, 167, 179, 7.89, 1.74, 0, 0}, {2.63, 1.71, 21.2, 197, 0, 4.08, 423, 24.6, 170, 475.887, 1.98, 0.13, 11, 8.45, 6.29, 106, 173, 7.6, 1.24, 0, 0}, + {2.69, 1.82, 17.9, 199.6, 0, 4.08, 298, 26.2, 197, 593.887, 1.93, 0.13, 0.002, 5.42, 5.46, 136, 183, 6.78, 0.997, 0, 0}, {2.64, 2.59, 25.8, 190, 0, 4.08, 271, 24.5, 152, 555.937, 1.89, 0.13, 0.001, 5.3, 5.22, 129, 190, 6.41, 2.05, 0, 0}, {2.87, 1.79, 25.2, 115.9, 0, 4, 295, 26.1, 140, 614.999, 1.86, 0.13, 0.001, 3.44, 9.41, 140, 176, 7.65, 2.63, 0, 0}, {2.74, 1.73, 25.8, 180.9, 0, 4, 466, 24.5, 91.5, 478.888, 1.82, 0.13, 9.08, 2.82, 4.39, 129, 174, 8.26, 1.69, 0, 0}, {2.74, 1.75, 24.6, 194.6, 0, 4, 88.3, 24.7, 231, 562.962, 1.8, 0.13, 0.001, 2.75, 6.5, 137, 211, 8.77, 1.39, 0, 0}, {2.68, 1.72, 24.7, 167.1, 0, 4.08, 74.2, 24.8, 220, 613, 1.74, 0.18, 0.001, 2.78, 4.75, 142, 233, 8.7, 4.25, 0, 0}, {2.78, 1.72, 13.7, 115.4, 0, 4.08, 504, 25, 146, 576.983, 1.69, 0.17, 9.7, 2.61, 4.76, 147, 222, 14.9, 1.05, 0, 0}, {2.69, 1.76, 21.8, 118.2, 0, 4.08, 514, 25.1, 134, 579.973, 1.65, 0.13, 0.002, 4.38, 4.47, 146, 217, 6.22, 1.13, 0, 0}, + {2.7, 2.31, 5.73, 133, 0, 4, 522, 25, 113, 551.08, 1.91, 0.13, 17.5, 6.43, 4.89, 125, 208, 8.37, 1.51, 0, 0}, {4.27, 1.81, 25.5, 206.7, 0, 4, 397, 10.1, 158, 655.01, 1.54, 0.13, 9.56, 3.31, 4.78, 132, 164, 12.5, 2.56, 0, 0}, {4.35, 1.73, 5.8, 90.8, 0, 4, 532, 25, 175, 615.969, 1.5, 0.13, 0.001, 2.92, 4.85, 134, 179, 9.43, 1.46, 0, 0}, {4.26, 1.89, 5.98, 191.5, 0, 4, 142, 24.9, 156, 584.16, 1.5, 0.13, 10.8, 2.64, 6.63, 132, 189, 10.5, 2.09, 0, 0}, {4.48, 1.73, 5.69, 194.9, 0, 3.92, 513, 10.1, 121, 541.69, 1.49, 0.13, 9.03, 5.87, 10.4, 148, 192, 10, 1.12, 0, 0}, {7.63, 1.67, 5.58, 121.6, 0, 4, 465, 25.2, 83.9, 445.05, 1.49, 0.13, 0.001, 4.37, 4.95, 137, 230, 11.1, 1.03, 0, 0}, {6.14, 1.67, 24, 114.2, 0, 4.08, 111, 25.3, 13.3, 438.02, 1.49, 0.13, 0.001, 4.5, 8.76, 169, 203, 10.4, 2, 0, 0}, {3.89, 1.85, 19.6, 196.4, 0, 4.08, 86.3, 10.1, 12.9, 379.04, 1.48, 0.13, 9.21, 3.98, 5.56, 153, 216, 11.7, 3.72, 0, 0}, {3.98, 1.71, 5.33, 191, 0, 4, 78.5, 10.7, 10.3, 322.26, 1.48, 0.13, 11.4, 2.68, 5.11, 143, 163, 14, 3.65, 0, 0}, {2.79, 1.64, 23.1, 188.5, 541, 4, 61.2, 12.9, 89.5, 143.94, 12.73, 0.26, 9.93, 7.57, 8.22, 167, 215, 12.5, 3.68, 263, 0.152}, {2.65, 3.41, 25.5, 183.2, 323, 9.04, 31.2, 10.1, 20.5, 233.43, 12.336, 0.24, 12.3, 2.54, 9.08, 193, 173, 9.22, 3.6, 268, 0.156}, {2.82, 5.47, 36.6, 50, 606, 8.72, 66, 10.6, 95.1, 227.17, 13.536, 0.24, 11.5, 11.9, 6.55, 260, 153, 11, 4.44, 219, 0.151}, {2.68, 3.3, 22, 44.2, 84.9, 7.36, 32.9, 26.1, 70.5, 129.4, 12.336, 0.19, 15.6, 8.38, 18.3, 303, 212, 7.06, 1.62, 141, 0.141}, {2.66, 3.27, 5.87, 31.89, 91.6, 3.84, 65, 25.6, 92.3, 102.87, 12.696, 0.19, 14.9, 2.71, 9.98, 290, 172, 15.5, 4.12, 195, 0.135}, {2.57, 1.86, 8.57, 28.13, 52.6, 3.84, 42.6, 2.33, 54.71, 12.09, 11.728, 0.19, 11.8, 10.2, 7.24, 294, 302, 20, 3.44, 166, 0.135}, + {2.66, 1.68, 11.6, 28.04, 82.3, 3.92, 58.6, 2.36, 152.7, 55.98, 14.196, 0.19, 0.001, 8.75, 10.5, 331, 258, 20.4, 3.12, 147, 0.138}, {2.56, 0.472, 7.55, 32.15, 49.4, 3.92, 48.5, 2.35, 118.8, 92.048, 18.5, 0.19, 0.001, 7.09, 8.53, 329, 229, 19.3, 5.99, 201, 0.129}, {2.69, 2.05, 9.08, 29.55, 41.7, 3.92, 31, 2.32, 46.61, 6.272, 18.53, 0.19, 18, 2.67, 16, 352, 281, 11.9, 7.57, 323, 0.129}, + {2.6, 1.64, 9.37, 31.07, 40.3, 3.84, 32.5, 3.96, 61.14, 52.23, 20.63, 0.19, 0.001, 6.38, 9.95, 378, 368, 17.3, 5.87, 330, 0.127}, + {2.6, 1.72, 7.99, 33.38, 105, 3.84, 77.9, 11.6, 115.3, 121.636, 21.07, 0.19, 21.1, 7.69, 9.69, 456, 331, 14.6, 5.45, 330, 0.127}, {2.65, 3.42, 13.2, 42.05, 30.3, 3.84, 52.9, 9.96, 107.1, 44.21, 16.18, 0.19, 16.8, 11, 12.5, 439, 312, 18, 3.61, 337, 0.125}, {4.75, 1.61, 8.22, 35.93, 54.9, 3.92, 46.7, 27, 54.7, 7.99, 14.9, 0.19, 23.1, 6.02, 13.6, 434, 303, 23.1, 4.7, 151, 0.125}, {2.54, 1.68, 10.8, 41.62, 84.7, 4.08, 28.8, 2.36, 126.5, 53.52, 14.3, 0.23, 0.001, 8.07, 17, 459, 302, 26.6, 5.04, 306, 0.128}, {2.69, 1.78, 14.6, 73.85, 67.3, 4.08, 66.7, 2.86, 100.8, 5.725, 9.79, 0.23, 27.8, 7.64, 18.6, 516, 325, 30.2, 3.01, 390, 0.131}, {2.6, 2.42, 27.6, 155.3, 33.3, 4.08, 26, 4.76, 93.6, 5.617, 9.49, 0, 0.001, 10.3, 18.2, 552, 301, 17.2, 2.92, 187, 0.126}, {2.6, 3.71, 18.2, 134.9, 55, 7.76, 46.7, 2.08, 109.8, 5.526, 8.44, 0.23, 0.001, 5.74, 19.9, 578, 289, 15.3, 3.74, 162, 0.128}, {2.69, 3.61, 8.74, 100.3, 13.2, 8.64, 12.9, 2.12, 218.7, 6.89, 8.86, 0.19, 0.001, 7.37, 18.1, 583, 357, 20.3, 4.02, 147, 0.126}, {4.2, 6.28, 5.58, 95.8, 13.2, 4.08, 67.3, 4.77, 160.8, 5.503, 7.64, 0.24, 30.4, 11.9, 17, 619, 320, 19.2, 5.12, 147, 0.129}, {4.12, 2.39, 4.24, 55.41, 23, 4, 28.8, 2.11, 47.6, 5.687, 5.424, 0.24, 38.8, 12.1, 23.8, 610, 197, 14.7, 3.88, 161, 0.126}, {7.1, 5.2, 3.83, 95.2, 7.68, 3.92, 34.7, 2.08, 58, 5.544, 6.924, 0.24, 20.4, 8.83, 16.2, 610, 33.1, 21.5, 5.04, 100, 0.129}, + {2.68, 4, 4, 52.51, 46.6, 4, 7.51, 2.11, 29.55, 5.587, 6.19, 0.11, 22.8, 9.05, 20.6, 646, 32.5, 25, 5.56, 71.4, 0.127}, {2.66, 2.59, 3.68, 42.98, 42.8, 4.08, 1.79, 4.59, 69.1, 5.555, 5.852, 0.11, 0.001, 9.9, 22.1, 637, 188, 15.6, 2.74, 57.3, 0.129}, {4.89, 1.53, 3.89, 46.7, 22.4, 4, -2.25, 4.51, 24.08, 6.005, 5.552, 0.11, 0.001, 9.12, 21.3, 547, 197, 9.07, 4.11, 41.1, 0.128}, {2.6, 2.78, 8.34, 73, 27.4, 3.92, 27.1, 2.82, 48.1, 6.28, 5.56, 0.11, 0.001, 9.36, 23.3, 577, 204, 9.98, 3.18, 61.2, 0.129}, {4.1, 2.25, 3.64, 73.4, 29.5, 3.92, 16.2, 2.19, 15.3, 5.876, 5.552, 0.11, 24.2, 3.16, 19.1, 562, 271, 7.45, 2.81, 60, 0.126}, {2.61, 2.16, 4.01, 44.94, 35.4, 3.92, 13, 2.19, 51.5, 5.887, 5.9, 0.11, 0.002, 4.79, 17.7, 672, 285, 7.53, 3.65, 37.8, 0.131}, {2.63, 6.74, 7.37, 41.3, 32.2, 51.3, 21.8, 3.79, 41.48, 6.24, 5.82, 0.11, 16.5, 7.81, 7.67, 573, 375, 5.82, 3.24, 69.3, 0.128}, {2.85, 2, 3.77, 36.13, 14, 215, 10.6, 2.14, 49.28, 5.476, 7.288, 0.16, 0.002, 6.99, 11.9, 560, 322, 8.8, 3.5, 72.3, 0.128}, {4.01, 1.85, 3.36, 33.87, 29.2, 176, 19.4, 2.14, 8.52, 5.7, 5.764, 0.15, 20.5, 2.9, 8.85, 602, 349, 13.7, 3.59, 64.8, 0.129}, + {3, 2.59, 4.05, 25.99, 4.7, 49.6, 23.4, 2.1, 48.88, 6.758, 5.74, 0.11, 0.001, 3.12, 11.4, 614, 354, 17, 3.22, 123, 0.126}, {4.3, 1.95, 7.33, 28.15, 4.67, 36.9, 18.4, 2.14, 8.02, 5.646, 5.668, 0.11, 20.8, 3.19, 8.37, 587, 378, 16.8, 2.78, 101, 0.128}, {3.13, 1.88, 3.24, 25.15, 4.8, 56.9, 6.12, 2.17, 23.67, 5.965, 5.628, 0.11, 17.9, 8.07, 9.32, 599, 258, 20.2, 1.12, 171, 0.129}, {3.1, 3.38, 3.56, 22.21, 4.73, 31.5, 20.8, 2.16, 44.92, 6.356, 5.58, 0.11, 20.8, 8.14, 11.9, 598, 310, 15.6, 1.11, 117, 0.127}, {5.24, 0.736, 3.89, 26.12, 8.23, 51.4, 10, 2.13, 143.8, 5.783, 6.732, 0.12, 0.001, 5.4, 12.6, 574, 345, 12.2, 1.65, 280, 0.128}, {3.07, 2.77, 8.02, 71.3, 7.06, 30.7, 12, 3.8, 151.2, 7.97, 7.316, 0.11, 16.9, 5.8, 11.4, 645, 335, 14.7, 1.01, 117, 0.136}, {8.2, 0.696, 7.03, 82.3, 3.64, 30.3, 8.41, 2.73, 140.1, 5.899, 5.5, 0.11, 0.001, 10.1, 10.5, 638, 274, 9.89, 1.22, 144, 0.137}, {6.44, 0.88, 13.5, 42.1, 3.57, 20, 6.85, 2.16, 129.9, 4.693, 5.784, 0.11, 15.7, 4.64, 8.01, 650, 289, 12.9, 1.89, 252, 0.134}, {5.84, 0.7, 12.7, 23.7, 3.57, 56, 29, 2.16, 297, 4.721, 5.76, 0.15, 0.002, 10.6, 11.2, 683, 354, 13.3, 4.18, 233, 0.136}, {7.06, 0.572, 11.3, 34.3, 3.56, 24.7, 19.5, 2.16, 287, 4.559, 7.32, 0.16, 0.001, 6.99, 10.5, 663, 269, 18.3, 4.26, 218, 0.135}, {6.73, 0.596, 10.6, 95.3, 3.63, 22.8, 0.362, 3.8, 268.6, 4.594, 6.044, 0.11, 0.001, 6.21, 11.2, 707, 270, 20.6, 4.2, 253, 0.135}, + {5.62, 2.09, 14.3, 38.05, 3.49, 23.8, 22.1, 4.34, 272, 5.367, 4.128, 0.11, 17, 5.77, 12.5, 613, 330, 18.1, 2.29, 107, 0.133}, {4.21, 0.468, 12.2, 38.55, 3.55, 37, 5.75, 2.12, 243.2, 4.588, 5.036, 0.15, 0.001, 5.85, 16.2, 736, 270, 14.3, 4.02, 96.3, 0.148}, {6.41, 0.644, 11.8, 51.5, 3.58, 70, 3.34, 2.2, 211.9, 5.248, 10.956, 0.16, 0.001, 8.98, 12.6, 683, 260, 21.5, 3.42, 74.1, 0.148}, {5.18, 0.712, 10.9, 54.6, 3.59, 49.5, 24.8, 2.22, 231, 9.9, 5.33, 0.16, 27.1, 9.8, 17.6, 707, 297, 23.9, 2.28, 51.3, 0.154}, {3.45, 2.8, 8.69, 35.31, 3.59, 23.9, 10.6, 3.89, 200.2, 9.07, 5.408, 0.2, 21.2, 7.67, 23, 713, 271, 18.8, 3.05, 51, 0.15}, {3.43, 1.84, 10, 36.16, 3.59, 20, 5.36, 2.26, 231.8, 10.77, 11.952, 0.27, 0.001, 12.4, 17.8, 684, 264, 11.8, 2.9, 62.1, 0.156}, {3.46, 1.77, 8.62, 41.35, 3.61, 6.24, 3.12, 2.25, 250.6, 7.73, 12.252, 0.34, 0.001, 6.9, 15.9, 666, 319, 13.8, 7.16, 30.6, 0.153}, {5.14, 2.64, 5.04, 44.95, 3.59, 10.7, 2.98, 2.24, 246.7, 7.83, 5.352, 2.97, 30.1, 11.4, 16.9, 783, 252, 20.4, 1.98, 38.4, 0.156}, {3.35, 3.36, 25, 37.97, 3.6, 12, 2.93, 2.26, 208, 11.11, 5.044, 0.32, 0.002, 8.59, 24, 733, 314, 26, 1.52, 38.4, 0.153}, {3.58, 1.8, 4.63, 47.8, 3.55, 10.4, 3.35, 2.92, 408.2, 10.43, 5.036, 0.32, 17.1, 12.7, 18.9, 754, 300, 27.3, 3.81, 55.2, 0.153}, + {3.56, 3.58, 4.6, 38.98, 3.55, 6.8, 3.32, 3.05, 402, 5.372, 5.336, 0.2, 0.001, 10.2, 21.2, 646, 279, 19.4, 1.25, 60.3, 0.153}, {5.67, 3.54, 5.79, 33.09, 3.52, 5.12, 6.14, 3.22, 471, 5.26, 5.344, 0.2, 34.3, 4.76, 19.2, 640, 303, 26.4, 2.03, 262, 0.157}, {6.43, 2.52, 8.16, 41.06, 6.98, 5.04, 7.53, 2.24, 443, 5.317, 5.636, 0.2, 0.001, 8.55, 16.3, 662, 241, 24.4, 4.59, 80.4, 0.156}, {5.09, 2.09, 4.65, 34.93, 3.62, 4.96, 10.8, 3.85, 483, 5.298, 5.636, 0.2, 21.5, 5.2, 16.2, 656, 169, 27.7, 2.76, 85.5, 0.153}, {5.98, 1.94, 5.26, 49.3, 0, 10.8, 3.3, 2.15, 107, 5.225, 0.496, 0.2, 0.001, 11.7, 23.1, 752, 192, 26.8, 5.2, 0, 0}, + {5.21, 2.03, 9.37, 120, 0, 10.4, 3.31, 2.17, 103, 6.52, 0.464, 0.2, 25.9, 9.94, 19.3, 704, 181, 18.5, 6.09, 0, 0}, {4.35, 2.09, 9.37, 121.6, 0, 4.96, 4.52, 2.16, 115, 5.344, 0.448, 0.24, 19, 4.68, 15.7, 674, 200, 24.6, 4.51, 0, 0}, {4.39, 2.05, 12.4, 140.5, 0, 4.96, 3.29, 2.19, 173, 5.037, 1.1, 0.39, 20.2, 7.74, 17, 686, 163, 18.9, 2.36, 0, 0}, {4.23, 2.11, 9.45, 146.8, 0, 4.96, 12.3, 3.23, 250, 4.943, 1.1, 0.34, 26.8, 5.64, 18.3, 730, 230, 24, 3.3, 0, 0}, + {4.13, 2.51, 9.12, 131.2, 0, 5.04, 3.37, 2.21, 251, 5.002, 1.06, 0.65, 17.6, 6.32, 8.15, 665, 171, 26.3, 5.85, 0, 0}, {4.24, 5.34, 8.85, 115.6, 0, 8.88, 8.85, 2.2, 177, 5.12, 1.06, 0.77, 16.5, 9.57, 9.64, 666, 188, 31.3, 4.27, 0, 0}, {4.19, 2.26, 14, 179, 0, 8.88, 6.9, 2.2, 137, 5.328, 1.06, 0.77, 0.001, 5.55, 10.1, 645, 207, 35.4, 4.56, 0, 0}, {3, 4, 22.7, 171.8, 0, 8.56, 3.34, 2.2, 158, 5.241, 1.51, 0.77, 0.002, 3.95, 13.8, 662, 178, 16.2, 2.81, 0, 0}, {3.09, 3.7, 13.3, 173.5, 0, 9.36, 3.32, 2.22, 209, 5.387, 1.51, 0.79, 31.9, 7.96, 10.2, 641, 222, 18.8, 4.9, 0, 0}, + {3, 3.71, 8.24, 119.4, 0, 8.56, 5.56, 2.22, 193, 10.01, 1.52, 0.79, 21.3, 7.65, 8.78, 457, 266, 8.98, 4.57, 0, 0}, {3.1, 3.56, 7.65, 116.2, 0, 3.76, 10.4, 2.16, 199, 5.425, 1.51, 0.77, 0.003, 6.83, 11.6, 344, 189, 7.44, 3.9, 0, 0}, {3.03, 2.84, 10, 111, 0, 3.76, 12.3, 2.18, 106, 5.147, 1.66, 0.83, 13.7, 6.07, 13.4, 293, 152, 14.5, 3.86, 0, 0}, {2.98, 2.82, 9.02, 108.6, 0, 3.76, 12.8, 2.17, 102, 5.158, 1.78, 0.59, 0.001, 11.5, 8.27, 275, 144, 11.3, 3.76, 0, 0}, {2.98, 2.69, 11, 203, 0, 3.92, 4.15, 2.18, 184, 5.64, 1.78, 0.41, 24, 4.44, 8.99, 256, 205, 8.96, 5.71, 0, 0}, {3.12, 1.75, 7.7, 193.4, 0, 3.84, 7.24, 2.15, 211, 5.53, 1.34, 0.41, 0.001, 4.51, 9.82, 242, 193, 12.2, 1.86, 0, 0}, + {2.98, 1.75, 7.86, 198.1, 0, 3.76, 11.6, 3.81, 212, 5.296, 1.34, 0.41, 0.001, 4.56, 12.1, 223, 193, 13.1, 3.49, 0, 0}, {2.98, 1.8, 22, 188.9, 0, 3.76, 11.9, 2.18, 191, 5.302, 1.34, 0.4, 14.7, 7.36, 7.33, 210, 215, 7.96, 1.12, 0, 0}, {2.93, 1.7, 7.49, 193, 0, 3.76, 3.37, 2.15, 92.3, 5.395, 1.34, 2.12, 13, 4.39, 9.83, 210, 172, 6.43, 2.84, 0, 0}, {2.98, 1.74, 7.16, 266.6, 0, 3.84, 10.3, 2.21, 62.3, 6.56, 1.34, 0.45, 13.4, 4.45, 7.37, 209, 166, 4.73, 3.44, 0, 0}, {3.05, 3.48, 8.81, 261.2, 0, 3.92, 12, 2.18, 208, 5.322, 1.35, 0.4, 13.1, 6.79, 6, 188, 177, 6.04, 3.28, 0, 0}, {3.03, 1.7, 4, 211.2, 0, 3.84, 12.9, 2.23, 202, 5.329, 1.36, 0.4, 12.1, 6.41, 4.99, 131, 157, 4.94, 2.86, 0, 0}, {2.89, 1.62, 4.34, 125.2, 0, 3.84, 3.38, 2.17, 205, 5.368, 1.34, 0.41, 9.75, 4.53, 5.88, 120, 199, 9.31, 2.98, 0, 0}, {2.9, 1.69, 4.23, 100.5, 0, 3.84, 3.36, 2.15, 140, 5.111, 0.704, 2.14, 0.001, 7.85, 5.68, 116, 201, 4.81, 1.04, 0, 0}, + {2.82, 1.76, 4.01, 122.9, 0, 3.84, 4.59, 2.14, 144, 5.121, 1.07, 0.39, 0.002, 2.82, 5.77, 141, 149, 8.06, 1.53, 0, 0}, {2.78, 1.62, 3.99, 102.6, 0, 3.76, 3.35, 2.93, 91.6, 5.127, 1.06, 2.04, 12.2, 6.57, 5.93, 114, 168, 8.57, 1.72, 0, 0}, {2.87, 1.8, 18.4, 127, 0, 3.76, 3.35, 2.17, 177, 5.234, 0.704, 3.52, 11.8, 2.82, 6.03, 112, 170, 4.9, 1.68, 0, 0}, {2.82, 2.17, 7.7, 105.2, 0, 3.76, 10.9, 2.19, 185, 5.342, 0.704, 0.25, 0.001, 2.89, 7.57, 111, 173, 4.11, 0.946, 0, 0}, {2.77, 1.62, 3.63, 159.8, 0, 3.84, 3.35, 2.19, 186, 5.265, 0.712, 0.24, 0.001, 2.67, 9.36, 119, 185, 4.04, 0.953, 0, 0}, {2.87, 1.62, 4.63, 158.8, 0, 3.92, 12.5, 2.2, 121, 5.134, 0.712, 0.24, 9.34, 6.13, 4.36, 121, 215, 6.01, 1.66, 0, 0}, {2.81, 1.68, 4.18, 160.8, 0, 3.76, 3.37, 2.2, 169, 5.216, 0.72, 0.23, 0.001, 6, 4.64, 110, 171, 7.78, 2.09, 0, 0}, {2.96, 1.62, 4.11, 112.3, 0, 3.76, 3.37, 2.2, 179, 5.152, 0.72, 0.14, 0.001, 2.66, 4.07, 113, 189, 7.4, 2.81, 0, 0}, {4.54, 3.66, 4.08, 110.4, 0, 8.88, 3.5, 2.2, 214, 5.164, 0.712, 0.13, 9.34, 4.46, 6.11, 109, 163, 8.6, 1.03, 0, 0}, + {4.49, 1.76, 4.34, 115, 0, 7.52, 8.43, 3.88, 200, 5.343, 0.688, 0.13, 0.002, 2.7, 4.43, 104, 220, 5.49, 1.46, 0, 0}, {4.54, 1.76, 4.22, 141.3, 0, 7.36, 8.92, 2.22, 179, 5.61, 0.624, 0.18, 9.86, 5.19, 5.1, 87, 163, 6.59, 1.66, 0, 0}, {4.78, 1.62, 17.5, 106, 0, 3.76, 3.39, 2.21, 145, 5.391, 0.576, 0.17, 12.2, 2.56, 4.44, 122, 175, 4.59, 1.11, 0, 0}, {4.72, 1.7, 4.48, 107.9, 0, 3.76, 3.4, 2.21, 65.9, 5.235, 0.536, 0.13, 0.002, 2.59, 6.13, 122, 133, 9.09, 1.01, 0, 0}, {4.65, 1.69, 3.99, 105.5, 0, 3.76, 3.4, 2.22, 51.9, 5.205, 0.504, 0.13, 11.2, 2.55, 5.91, 110, 171, 11.7, 1.01, 0, 0}, {4.7, 1.63, 8.96, 117.9, 0, 3.84, 3.4, 2.24, 56, 226.836, 0.488, 0.13, 0.001, 2.54, 5.25, 136, 136, 10.4, 1.73, 0, 0}, {3.11, 1.69, 8.06, 115.1, 0, 3.76, 3.41, 2.22, 32.6, 227.37, 0.824, 0.13, 8.13, 4.23, 6.79, 118, 162, 14.9, 1.07, 0, 0}, + {3.09, 1.68, 7.75, 127.7, 0, 3.76, 3.39, 2.22, 49.1, 223.745, 0.448, 0.13, 0.001, 4.33, 4.86, 139, 195, 14.5, 0.964, 0, 0}, {3.13, 3.2, 8.06, 132.5, 4.15, 3.68, 6.09, 4.53, 142.1, 171.55, 5.28, 0.13, 0.001, 8.57, 8.73, 122, 167, 12.6, 2.85, 860, 0.152}, {5.31, 1.84, 7.66, 121.6, 8.58, 3.68, 6.37, 2.76, 128.9, 98.52, 4.86, 0.12, 12.6, 9.34, 8.78, 255, 215, 14.4, 1.64, 140, 0.177}, {5.07, 2.14, 8.04, 191.5, 14.9, 3.76, 10, 13.9, 204.8, 167.791, 4.544, 0.12, 10.7, 7.63, 7.55, 300, 206, 14.5, 1.52, 204, 3.24}, {3.79, 1.58, 43.7, 50.9, 70, 3.68, 14.7, 257, 231.9, 191.71, 4.544, 0.12, 14.6, 25.6, 8.98, 304, 172, 30.9, 2.56, 174, 11.3}, {30, 2.56, 35.9, 76.9, 582, 3.6, 59, 210, 242.5, 444, 6.336, 1.54, 14.1, 116, 27.2, 300, 283, 31.8, 3.96, 125, 17.9}, {15, 2.99, 45.5, 167.3, 646, 4, 22.6, 255, 328, 426.8, 23.78, 0.16, 20.7, 141, 35.5, 295, 355, 51.9, 5.73, 226, 82.9}, {7.7, 1.86, 32.4, 126.3, 719, 8.16, 70.2, 41.6, 420, 491, 22.264, 0.15, 0.001, 156, 81.1, 280, 306, 46.8, 10.1, 184, 51.8}, + {12.5, 4.12, 51.2, 138.4, 713, 27.2, 56.2, 31.1, 338, 596, 24.296, 0.11, 45.5, 117, 85.8, 353, 304, 39, 11, 263, 22.2}, {12.7, 3.43, 63.3, 285.8, 711, 14.6, 69.9, 26.4, 410, 589.8, 35.396, 0.11, 39.7, 141, 85.6, 346, 294, 44.8, 14.3, 278, 51.1}, {7.54, 3.31, 57, 179.3, 124, 25.6, 90.8, 278, 368, 606.5, 32.324, 0.1, 42.4, 144, 90.8, 364, 386, 50.6, 12.6, 410, 26.4}, {10.6, 3.56, 52.7, 126.1, 1060, 20.5, 83.7, 260, 328.8, 620.8, 32.132, 0.1, 48.3, 182, 89.9, 409, 318, 60.1, 11.9, 301, 17.9}, {12.4, 3.43, 56.9, 173.3, 1070, 23.6, 84.3, 265, 343.9, 436.4, 32.34, 0.1, 49.6, 118, 107, 413, 344, 54.7, 15.2, 326, 24.7}, {14.9, 0.964, 55.3, 215.9, 513, 14.4, 80.3, 25.5, 298.3, 366.2, 34.816, 0.1, 46.8, 125, 83.3, 453, 354, 54, 8.85, 274, 104}, {7.2, 2.84, 64.6, 150.8, 402, 42.2, 77.8, 248, 346, 443.9, 35.78, 0.1, 53, 153, 97, 454, 354, 67, 11.9, 235, 91.5}, {11, 2.43, 42.3, 163.7, 311, 31.6, 74.4, 238, 407.6, 402.9, 31.748, 0.1, 54.7, 151, 105, 562, 344, 58.8, 10.1, 239, 94.3}, {5.39, 3.14, 63, 156.2, 340, 33.4, 82.3, 260, 349.2, 395.9, 32.92, 0.15, 0.001, 115, 91.6, 456, 378, 60.7, 15.9, 214, 85.3}, {9.35, 4.98, 61.6, 139.1, 365, 32.4, 66.6, 246, 343.5, 325.7, 41.51, 0.15, 67.7, 156, 123, 500, 334, 65.3, 7.98, 230, 22.1}, {16.6, 3.08, 54, 174.8, 482, 22, 78.4, 258, 371, 525, 36.16, 0.11, 56.4, 140, 82.5, 571, 328, 62.1, 12.6, 229, 24.9}, + {16.8, 3.2, 54.4, 137.3, 222, 22.2, 66.5, 24.8, 242.8, 531, 43.31, 0.11, 0.002, 180, 74, 480, 337, 59, 9.05, 262, 95.9}, {9.16, 2.65, 22.4, 128.3, 204, 22.8, 84, 242, 208.4, 291.3, 39.484, 0.11, 0.001, 116, 176, 451, 324, 55.9, 11.5, 173, 22.4}, {12.6, 5.3, 17.4, 90.5, 245, 31.6, 91.7, 244, 118.5, 344.11, 32.276, 0.11, 48.1, 47.9, 169, 667, 241, 67.9, 10.3, 130, 0.707}, {5.09, 7.98, 6.99, 94, 171, 10.4, 23.5, 18.2, 107.54, 270.52, 22.676, 0.1, 0.001, 23, 101, 496, 281, 39.3, 9.05, 98.7, 0.132}, {4.31, 1.82, 9, 74.9, 247, 13.5, 10.3, 21.9, 107.52, 333.2, 16.15, 0.1, 49.2, 18.3, 103, 530, 271, 23.8, 9.1, 37.5, 0.129}, {6.25, 0.78, 6.17, 66, 134, 9.76, 3.94, 17.6, 7.55, 306.73, 15.988, 0.11, 0.001, 38.5, 24.3, 480, 276, 24.4, 5.92, 37.5, 0.13}, {6.1, 0.704, 23.3, 54.3, 100, 19, 14.5, 18, 7.54, 382.548, 20.78, 0.16, 0.001, 11, 22, 521, 299, 33.3, 4.04, 53.7, 0.809}, {4.05, 1.28, 25.8, 32.18, 784, 15.9, 3.45, 19.6, 122.86, 274.01, 18.988, 0.15, 0.001, 28.9, 23.2, 520, 332, 31.9, 4.88, 55.2, 0.803}, + {4.09, 1.09, 26.8, 62.1, 764, 10.4, 13.5, 232, 167.45, 317.985, 18.988, 0.15, 15.8, 89.5, 21, 494, 301, 32.7, 4.4, 55.2, 5.87}, {9.52, 1.08, 47.8, 113.7, 139, 9.6, 56.2, 252, 228.8, 403.8, 27.372, 0.1, 14.8, 109, 17.2, 495, 318, 36.8, 5.29, 69, 90.5}, {17.9, 1.22, 68.1, 150.2, 157, 20, 70.8, 246, 165.71, 620, 77.56, 0.1, 0.001, 105, 130, 510, 326, 38, 4.95, 183, 76.5}, {16, 3.88, 51.5, 80.5, 97.8, 16.1, 78.6, 49.4, 246, 381.7, 90.04, 0.1, 14.5, 74.1, 145, 515, 309, 45, 5.52, 196, 86.8}, {17.2, 2.6, 60.5, 153.5, 452, 19.4, 71.2, 48.3, 302.6, 614, 34.65, 0.1, 24.5, 121, 100, 552, 319, 58.3, 10.1, 222, 32.9}, {16, 4.71, 78.7, 176.5, 381, 24.8, 68.9, 45, 289.1, 561, 33.944, 0.1, 43.2, 131, 139, 558, 316, 59.5, 12.2, 207, 27.7}, {15.3, 1.77, 64.7, 171.8, 414, 15.2, 32.7, 278, 301.4, 455.9, 35.736, 0.1, 34.8, 187, 96.9, 513, 333, 45.4, 13.9, 234, 20.6}, {42.8, 1.7, 61, 176.1, 430, 19.6, 74.6, 301, 281.4, 490, 36.752, 0.15, 0.001, 149, 170, 515, 349, 52.7, 15.2, 192, 18}, {14, 1.7, 61.6, 202.2, 436, 10.8, 67.1, 281, 269.4, 461, 36.76, 0.14, 39.9, 159, 162, 559, 399, 42.9, 16.4, 224, 34.6}, {16.1, 1.84, 34.4, 186, 392, 16.4, 56, 275, 304, 425, 27.752, 0.11, 0.001, 185, 118, 527, 318, 50.7, 12.8, 191, 72.2}, {18.8, 2.35, 47.6, 155.2, 356, 23.6, 88.3, 303, 259, 516, 26.268, 0.11, 48.2, 204, 94.6, 563, 323, 61.3, 13.5, 196, 31.5}, + {27.5, 0.676, 41.8, 127.7, 419, 18, 29.7, 47.2, 334, 584, 29.19, 0.11, 48.5, 201, 136, 531, 311, 60.2, 9.98, 148, 99.1}, {9.31, 0.708, 51, 116, 479, 23.3, 34.4, 318, 264, 235, 28.968, 0.1, 48.7, 163, 105, 613, 292, 54.2, 15.7, 214, 101}, {36, 4, 61.6, 136.7, 410, 14, 31.3, 286, 368.2, 425.7, 31.51, 2.58, 0.001, 128, 111, 603, 341, 55.6, 15.1, 223, 86.8}, {11.9, 0.6, 63, 154.6, 421, 21.2, 79.2, 311, 345.3, 370.1, 32.292, 0.08, 45.2, 147, 166, 606, 301, 52.8, 12.6, 198, 23.6}, {13, 0.788, 46.2, 130.3, 407, 19.6, 79.2, 115, 382.3, 420.9, 30.45, 0.08, 0.001, 165, 67.3, 562, 314, 55.3, 16.7, 237, 104}, {29.8, 2.02, 45.5, 129.8, 362, 25.3, 57.5, 104, 373.4, 352.2, 35.11, 0.08, 63.5, 217, 76.6, 634, 277, 59.1, 16.4, 204, 108}, {4.99, 4.3, 37, 135.3, 419, 14, 161, 347, 358.5, 460.1, 27.48, 0.09, 52.1, 200, 167, 707, 246, 61.8, 11.1, 221, 106}, {5.01, 2.68, 24, 140.1, 240, 26.8, 137, 323, 304, 557.8, 20.61, 0.09, 60.3, 138, 82.9, 684, 313, 60.6, 10.7, 132, 104}, {4.99, 3.72, 26.1, 141, 260, 22.8, 157, 323, 218, 591.6, 16.624, 0.11, 0.001, 186, 178, 692, 245, 40.4, 13.9, 107, 102}, {5.02, 1.96, 23.5, 131.4, 207, 33.9, 154, 126, 350, 664, 18, 0.11, 0.001, 219, 77.2, 687, 317, 60.6, 14.2, 84.6, 0.149}, + {11.5, 3.5, 22.9, 109.3, 209, 29.3, 147, 113, 334, 782.4, 8.764, 0.11, 39.3, 171, 113, 669, 275, 48.4, 9.87, 39.3, 0.151}, {10.9, 1.53, 22, 60.3, 219, 23.6, 157, 344, 317, 580.88, 8.156, 0.11, 27.9, 205, 149, 773, 292, 54.2, 11.7, 75.6, 0.154}, {12.8, 1.39, 22.3, 70, 219, 36.7, 53, 116, 282.7, 611.41, 7.856, 0.11, 0.001, 134, 60.2, 641, 311, 36.3, 12.4, 78.9, 0.149}, {31.2, 1.55, 23.8, 69.4, 214, 25.1, 374, 326, 607, 657.6, 7.856, 0.11, 0.001, 140, 92.2, 722, 312, 54.5, 14.5, 73.5, 0.151}, {9.83, 1.89, 14.4, 59.6, 139, 23.3, 395, 317, 494, 602.17, 13.9, 0.11, 0.001, 147, 21, 694, 362, 46.4, 11.7, 160, 0.152}, {10.4, 2.06, 23.7, 64.5, 109, 15, 403, 248, 595, 464.41, 16.408, 0.11, 0.001, 118, 25.5, 675, 312, 51.8, 10.9, 176, 0.149}, {12.7, 2.38, 12.3, 79.1, 242, 22.4, 132, 436, 606, 584.27, 16.4, 0.11, 0.001, 114, 31.7, 626, 268, 54.9, 15.2, 1140, 0.151}, {13.3, 2.43, 38.7, 86, 103, 16.9, 327, 76.7, 586, 442.56, 14.144, 0.11, 0.001, 184, 30.4, 636, 303, 56.8, 17, 1590, 0.153}, {11.4, 4.18, 26.6, 140.2, 0, 18.8, 404, 515, 197, 630.55, 0.8, 0.11, 0.002, 159, 23.7, 649, 296, 56.2, 16, 0, 0}, {29.4, 5.93, 18.4, 165, 0, 10, 187, 387, 71.6, 604.08, 2.31, 0.11, 47.2, 51, 25.4, 717, 304, 50.8, 13.5, 0, 0}, {9.93, 4.94, 26.2, 146.4, 0, 9.92, 313, 510, 111, 689.85, 0.944, 0.11, 0.001, 30.5, 19.8, 659, 265, 62.8, 13.5, 0, 0}, + {35.2, 4.04, 25.7, 167.9, 0, 9.28, 350, 547, 181, 481.944, 0.952, 0.11, 0.001, 21.8, 27.3, 724, 321, 61, 12.6, 0, 0}, {15, 2.31, 23.7, 146.1, 0, 10.5, 376, 571, 257, 610.11, 0.952, 0.11, 0.001, 22.8, 25.6, 682, 306, 59, 11.9, 0, 0}, {13.4, 7.28, 15.1, 152.3, 0, 17.8, 106, 576, 248, 551.07, 0.968, 0.11, 43.3, 22.7, 25.1, 586, 306, 50.5, 11.6, 0, 0}, {3.43, 6.13, 14.3, 208.9, 0, 24.8, 415, 368, 235, 453.986, 0.968, 0.11, 47.3, 21.2, 24.3, 645, 316, 44, 6.36, 0, 0}, {3.58, 4, 16, 214.5, 0, 15.7, 402, 319, 228, 621.04, 0.936, 0.11, 44.9, 23.9, 17.9, 562, 283, 44.7, 6.65, 0, 0}, {5.75, 2.05, 14.7, 192.6, 0, 9.84, 122, 385, 70.2, 593.04, 2.02, 0.11, 32.8, 18.6, 16.6, 503, 318, 48.4, 5.53, 0, 0}, {3.47, 2.01, 26.9, 140.1, 0, 9.76, 163, 400, 211, 472.08, 2.32, 0.11, 32.8, 17.6, 17.7, 462, 361, 45.5, 6.93, 0, 0}, {3.04, 5.18, 27.1, 149.4, 0, 10.5, 250, 374, 215, 654.969, 1.92, 0.11, 0.002, 18.8, 13.6, 334, 301, 43.2, 3.61, 0, 0}, {2.81, 2.43, 14, 216.7, 0, 9.76, 263, 44.6, 211, 522.979, 1.86, 0.11, 0.001, 16.9, 14.8, 296, 270, 39.6, 3.4, 0, 0}, {4.97, 1.98, 23, 204.9, 0, 9.68, 434, 353, 201, 531.53, 1.84, 0.11, 28.5, 17.8, 12.2, 269, 244, 25.2, 3.9, 0, 0}, {2.91, 2.91, 18.5, 202.7, 0, 8.8, 350, 346, 200, 683.877, 1.8, 0.11, 0.001, 15.9, 11.1, 250, 251, 29, 1.75, 0, 0}, {5.01, 1.31, 25.7, 203, 0, 17.2, 184, 596, 16, 429.809, 1.46, 0.11, 23.6, 11.4, 12.1, 203, 233, 33.2, 3.72, 0, 0}, {2.86, 1.3, 17.8, 189.6, 0, 10.1, 287, 650, 174, 613.887, 1.46, 0.11, 30.8, 6.01, 9.37, 175, 200, 31, 1.41, 0, 0}, {2.85, 1.2, 23.4, 197.6, 0, 8.4, 346, 339, 209, 470.918, 1.46, 0.11, 20.5, 6.03, 6.18, 197, 243, 40.5, 1.48, 0, 0}, + {2.74, 1.27, 18.4, 186.5, 0, 17, 403, 610, 170, 440.865, 1.46, 0.11, 13.4, 10.1, 7.88, 203, 229, 23.1, 3.02, 0, 0}, {2.7, 1.54, 6.27, 261.7, 0, 6.96, 193, 593, 206, 476.758, 1.79, 0.11, 13.4, 6.23, 8.68, 216, 247, 21.3, 5.67, 0, 0}, {2.84, 1.27, 10.5, 256.3, 0, 5.44, 370, 69.4, 105, 624.847, 1.45, 0.11, 0.001, 14.4, 7.16, 200, 175, 25.4, 3.85, 0, 0}, {2.78, 1.28, 27.8, 214.3, 0, 16, 529, 640, 104, 526.887, 1.43, 0.11, 10.4, 12.3, 8.24, 153, 193, 31, 3.79, 0, 0}, {2.69, 1.95, 6.6, 214.1, 0, 6.4, 109, 640, 205, 649.91, 1.42, 0.11, 0.002, 16.8, 6.68, 172, 193, 19.3, 5.5, 0, 0}, {2.69, 1.86, 18, 208.7, 0, 10.3, 200, 306, 171, 716.83, 1.41, 0.11, 0.001, 14.8, 7.24, 158, 210, 22.7, 3.78, 0, 0}, {2.74, 1.88, 18, 195.1, 0, 6, 501, 655, 171, 607.48, 1.4, 0.11, 12.2, 14, 7.13, 163, 214, 29.7, 1.82, 0, 0}, + {2.69, 1.8, 6.13, 218.6, 0, 16.1, 201, 614, 145, 503.892, 1.4, 0.11, 0.001, 14.1, 6.36, 166, 248, 21.2, 1.71, 0, 0}, {2.8, 1.78, 18.5, 190, 0, 7.92, 501, 320, 130, 560.751, 1.4, 0.11, 11.8, 16.9, 6.94, 149, 203, 25.5, 1.69, 0, 0}, {2.79, 1.76, 22.2, 214.9, 0, 21.4, 413, 335, 83, 498.75, 1.38, 0.11, 0.001, 12.4, 5.43, 130, 202, 27.9, 1.56, 0, 0}, {2.75, 1.81, 22, 187.6, 0, 11.9, 336, 332, 172, 602.872, 1.34, 0.11, 0.001, 15.4, 5.29, 148, 230, 23.4, 1, 0, 0}, {2.7, 1.78, 26.4, 232, 0, 10.9, 201, 329, 177, 596.75, 1.65, 0.11, 14.3, 13.4, 8.04, 125, 200, 37.1, 1.08, 0, 0}, {2.69, 1.64, 26.6, 111.5, 0, 7.52, 344, 322, 151, 653.75, 1.3, 0.11, 0.001, 12.4, 6.74, 145, 193, 31.3, 1.27, 0, 0}, {2.89, 1.82, 15.9, 111.8, 0, 7.68, 441, 53.4, 190, 441.852, 1.28, 0.11, 10.5, 11.1, 5.46, 179, 202, 25.8, 1.08, 0, 0}, {2.84, 1.8, 22.1, 192.3, 0, 8.08, 491, 39.3, 168, 530.796, 1.28, 0.11, 0.001, 13.9, 4.91, 128, 235, 26.9, 1.45, 0, 0}, + {4.48, 1.64, 25.5, 200, 0, 9.76, 310, 10.6, 161, 555.35, 1.27, 0.11, 0.001, 10.5, 4.61, 124, 213, 25.2, 2.71, 0, 0}, {4.36, 1.72, 9.47, 174.2, 0, 7.44, 244, 4.88, 215, 539.823, 1.26, 0.11, 0.001, 14.9, 5.71, 129, 204, 29.8, 1.05, 0, 0}, {4.39, 1.7, 9.96, 175.8, 0, 6.88, 367, 3.45, 212, 651.668, 1.26, 0.11, 0.001, 11.4, 8.32, 128, 202, 19.6, 1.25, 0, 0}, {6.39, 2.18, 14.3, 178.5, 0, 10.4, 431, 3.47, 210, 505.703, 1.26, 0.11, 0.001, 15.3, 7.56, 125, 217, 24, 1.04, 0, 0}, {6.46, 1.82, 20.7, 179.1, 0, 7.44, 153, 3.48, 60.6, 704.66, 1.26, 0.11, 14.2, 12, 5.23, 184, 186, 27.2, 2.78, 0, 0}, {4.48, 1.78, 14.7, 172.6, 0, 6.96, 117, 3.51, 81.8, 620.36, 1.24, 0.11, 0.001, 17, 7.07, 186, 205, 27.6, 1.09, 0, 0}, {3, 1.72, 25.8, 176.8, 0, 7.12, 377, 3.51, 193, 544.98, 1.24, 0.11, 0.001, 12.6, 5.26, 154, 172, 21, 3.64, 0, 0}, {5.15, 1.65, 14.2, 188.7, 0, 8.64, 200, 2.95, 197, 586.49, 1.26, 0.11, 0.002, 13.7, 5.05, 149, 253, 27.2, 3.59, 0, 0}, {2.92, 1.72, 6.48, 199, 0, 16, 565, 3.99, 198, 477.14, 1.23, 0.11, 11.7, 18.9, 8.52, 169, 240, 16.9, 1.15, 0, 0}, {6.12, 1.71, 6.23, 121.4, 274, 7.76, 110, 2.38, 242, 351.526, 16.12, 0.1, 11.3, 16.2, 8.42, 157, 210, 19.6, 1.97, 924, 0.152}, {4.07, 4.9, 18.2, 119, 173, 6.56, 113, 3.32, 174, 413.89, 8.64, 0.09, 0.001, 22.8, 12.8, 285, 234, 27.9, 1.6, 328, 0.179}, {6.44, 5.61, 29.5, 30.15, 173, 14.7, 149, 32.1, 110, 461.662, 51.18, 0.09, 0.002, 38.4, 10.6, 263, 220, 21.4, 1.01, 177, 4.06}, + {2.76, 1.92, 34, 134.8, 287, 7.04, 122, 278, 202, 428.6, 56.124, 0.08, 0.001, 23.9, 68.4, 301, 197, 26.8, 1.67, 219, 19.4}, {5.87, 1.22, 38.3, 141.6, 727, 6.96, 136, 302, 269, 374.3, 76.224, 0.08, 19, 124, 74.8, 290, 277, 57.7, 3.78, 285, 96.6}, {27.6, 3.52, 49.7, 165.9, 722, 6.4, 175, 300, 274, 481, 78.016, 0.08, 0.003, 128, 98.2, 273, 375, 48.6, 4.72, 248, 104}, {12.5, 4.41, 57, 132.1, 756, 8, 190, 27.5, 261, 479.7, 91.628, 0.08, 24.6, 129, 103, 292, 308, 57.1, 9.62, 192, 36}, {11.6, 3.29, 46.4, 170.3, 679, 17.7, 271, 31.3, 254, 575.7, 85.328, 0.08, 0.001, 120, 139, 364, 305, 57.3, 13.9, 310, 88.2}, {36.3, 1.56, 66.1, 158.4, 966, 15.7, 246, 29.8, 311, 483.4, 97.636, 0.08, 0.001, 115, 144, 294, 310, 58.2, 12.6, 406, 107}, {14.4, 3.81, 41, 172.9, 296, 15.6, 238, 26.2, 309, 600.2, 88.044, 0.08, 0.001, 100, 146, 347, 319, 55, 13.5, 438, 104}, {13.5, 4.37, 48.2, 150.4, 866, 8.32, 247, 18.9, 290, 599, 87.94, 0.08, 39.6, 131, 98.4, 346, 319, 62.2, 15.1, 329, 23.3}, {42.3, 3.15, 37.3, 145.8, 903, 17.1, 178, 22.2, 327, 677.7, 99.35, 0.08, 0.001, 131, 137, 398, 308, 53.8, 12.5, 365, 13.4}, {15.2, 2.67, 53.6, 140, 965, 9.2, 178, 82.6, 359, 663.7, 77.57, 0.08, 0.001, 124, 122, 429, 312, 60.9, 13.4, 338, 94.9}, {11.5, 2.72, 59.4, 137.5, 928, 17.7, 270, 41.9, 385, 633.2, 79.4, 0.08, 0.001, 120, 117, 438, 286, 55.5, 24.8, 112, 95.7}, {9.79, 3.22, 63.5, 117.3, 946, 11.9, 241, 233, 392.5, 534.6, 65.58, 0.08, 0.002, 143, 167, 473, 307, 55.3, 9.31, 164, 103}, {38.4, 2.7, 51, 143.5, 928, 10.1, 205, 272, 525, 544.4, 122.51, 0.08, 39.4, 165, 165, 525, 286, 61, 14.5, 137, 19.6}, {11.9, 2.47, 64.3, 146.1, 1030, 19.2, 279, 282, 559, 531.7, 102.26, 0.08, 0.001, 136, 128, 608, 269, 56.3, 19, 269, 16.7}, {19.6, 5.38, 51, 151.7, 963, 8.24, 227, 283, 525, 587.4, 112.28, 0.08, 0.001, 136, 105, 587, 332, 57.8, 16.3, 397, 92.9}, + {16.7, 3.98, 50.8, 143.5, 963, 10, 202, 261, 515, 531.5, 112.23, 0.08, 37.2, 149, 127, 543, 342, 51.9, 13.6, 501, 92.9}, {12.6, 2.5, 32.1, 112.6, 256, 8.4, 156, 268, 294, 352.16, 88.212, 0.08, 32.6, 162, 177, 488, 337, 62.2, 12.9, 531, 12.8}, {13.3, 4.31, 25.7, 89.8, 195, 16.1, 171, 251, 192.5, 375.67, 100.89, 0.08, 32.5, 73.4, 166, 506, 203, 68.5, 13.9, 507, 0.618}, {4.87, 2.67, 28.4, 66.5, 107, 12, 101, 12, 117.4, 370.873, 69.6, 0.08, 38.4, 46.2, 138, 532, 304, 30.2, 15.7, 417, 0.196}, {4.35, 2.58, 11.8, 82.1, 735, 7.6, 43.3, 9.36, 110.9, 349.843, 64.84, 0.08, 36.5, 53.7, 55.5, 517, 288, 25.1, 10.7, 218, 0.194}, {3.8, 3.43, 10.5, 75.7, 640, 8.96, 45.7, 11.1, 99.5, 348.847, 56.34, 0.08, 43.9, 39.3, 36.1, 535, 297, 32.4, 7.85, 74.7, 0.194}, {3.82, 2.75, 24.5, 73.6, 696, 17.3, 47.2, 9.45, 91.5, 345, 81.8, 0.08, 28.5, 28.3, 20.5, 619, 281, 38.6, 7.57, 169, 0.214}, {4.07, 1.8, 26.7, 61.6, 695, 8.8, 27.6, 9, 268, 320.97, 68.86, 0.08, 0.001, 47.9, 16.3, 530, 343, 35.6, 11.7, 101, 1.45}, {5.9, 5.56, 40, 138.8, 642, 8.64, 37.8, 28.6, 319, 331.19, 67.61, 0.08, 14.3, 140, 14.3, 482, 243, 45.6, 11.9, 354, 3.75}, {29.4, 1.71, 52, 63, 680, 16.8, 69.3, 30, 300, 404.4, 65.13, 0.08, 14.2, 211, 10.5, 439, 317, 44.4, 10.5, 99.9, 90.8}, {5.96, 1.62, 63.6, 102.6, 713, 9.92, 83.6, 274, 382, 483.2, 96.9, 0.08, 0.001, 196, 28.2, 465, 292, 37.2, 13.2, 118, 87.9}, {5.15, 3.95, 42.7, 123.7, 166, 9.6, 94.4, 265, 342.5, 441.2, 89.11, 0.08, 19.2, 152, 166, 518, 312, 39.8, 14.6, 120, 99.9}, {9.2, 3.15, 57.8, 189.2, 698, 10.6, 87.5, 249, 481, 556.5, 64.84, 0.08, 20.9, 160, 112, 506, 311, 53.9, 19.5, 142, 97.9}, + {5.08, 2.15, 43.5, 182.6, 791, 20.4, 138, 247, 425, 393, 80.12, 0.08, 42.9, 165, 121, 473, 338, 61.8, 17.4, 141, 103}, {5.03, 1.6, 57.5, 180, 797, 18, 91, 267, 453, 435.7, 72.08, 0.08, 0.001, 257, 167, 470, 327, 60.8, 14.4, 109, 22.1}, {12.8, 1.99, 60, 147.4, 146, 20.8, 101, 80.5, 346.7, 285.9, 96.08, 0.08, 45.1, 147, 196, 474, 364, 64.3, 20, 331, 91.1}, {7.36, 3.36, 57.7, 161.6, 462, 29, 83.5, 295, 440, 325.2, 92.24, 0.08, 37.2, 122, 197, 500, 344, 61.2, 20.6, 168, 31.9}, {9.4, 0.868, 56, 189.4, 182, 17.2, 157, 256, 480, 416.2, 78.54, 0.08, 0.002, 144, 193, 472, 370, 64.1, 13.7, 231, 15.6}, {36, 0.732, 54.1, 168.2, 440, 14.4, 66, 247, 405, 407.3, 82.25, 0.08, 0.001, 163, 152, 522, 342, 54, 15.5, 181, 24.2}, {9.25, 0.7, 62.8, 142.8, 424, 14.8, 121, 37.7, 326.7, 380.5, 78.08, 0.08, 42.3, 174, 148, 492, 336, 50, 22.7, 145, 105}, {11, 0.7, 40.7, 133.3, 424, 16.8, 137, 30.8, 473, 269.8, 86.78, 0.08, 0.002, 155, 107, 522, 305, 52.7, 16.6, 192, 105}, {30.4, 1.07, 55, 127.4, 451, 18.2, 95, 265, 520, 301, 100.87, 0.08, 48.3, 139, 137, 503, 331, 72.3, 19.2, 340, 89.6}, {34, 1.2, 59.7, 129, 453, 34.8, 228, 329, 445.6, 338.9, 92.78, 0.08, 45.9, 201, 193, 550, 341, 66.7, 15.9, 445, 93.4}, {4.79, 2.38, 52.2, 196, 446, 30.4, 269, 323, 435, 368.2, 96.71, 0.08, 0.001, 167, 170, 629, 350, 64.5, 17.9, 347, 13.9}, {6.5, 3.73, 76.9, 100.2, 416, 16.5, 184, 338, 407.7, 345.1, 92.16, 0.08, 0.001, 139, 174, 593, 334, 64.4, 18, 159, 97.4}, {4.96, 4.4, 36, 200.3, 416, 23.3, 253, 308, 404.7, 488.8, 106.24, 0.08, 60.4, 126, 99.4, 617, 255, 61.8, 14.6, 123, 24}, {4.91, 3.48, 41.4, 148, 435, 14.4, 190, 383, 275.8, 474.3, 67.4, 0.09, 56.9, 189, 161, 636, 292, 62.5, 17.5, 133, 93.6}, {5.26, 3.8, 34.6, 119.7, 96.2, 19.2, 239, 122, 292.4, 528.4, 90.49, 0.1, 59.7, 127, 208, 673, 294, 48.4, 27.6, 120, 0.374}, + }; + return aaa; + } + + int getLCM(int harmtime, int ptime) { + int gcd = getGCd(harmtime, ptime); + int result = harmtime * ptime / gcd; + return result; + } + + int getGCd(int harmtime, int ptime) { //求最大公约数 + while (ptime > 0) { + int temp = harmtime % ptime; + harmtime = ptime; + ptime = temp; + } + return harmtime; + } + + + //模拟数据仅供测试使用 //95%概率值,平均值 + void setHarmData(QvvrStruct qvvrStruct) { + double harm_data[][] = new double[][]{{0.392503, 0.375256}, {0.416966, 0.391282}, {0.399125, 0.374001}, {0.400342, 0.381616}, {0.395763, 0.354769}, {0.338718, 0.310073}, {0.354029, 0.315348}, {0.321072, 0.277353}, {0.268696, 0.244527}, {0.279931, 0.24556}, {0.266101, 0.241335}, {0.281377, 0.261063}, {0.302527, 0.273781}, {0.302895, 0.266885}, {0.281642, 0.24906}, {0.310485, 0.273715}, {0.328971, 0.302569}, {0.288167, 0.265745}, {0.293203, 0.268007}, {0.312182, 0.264764}, {0.253516, 0.232282}, {0.276051, 0.252694}, {0.272313, 0.245945}, {0.249585, 0.219453}, {0.305057, 0.25734}, {0.258173, 0.232493}, {0.254261, 0.214109}, {0.268922, 0.234524}, {0.281335, 0.245216}, {0.264975, 0.239691}, {0.267699, 0.23231}, {0.271839, 0.241514}, {0.279397, 0.24558}, {0.267083, 0.231503}, + {0.259468, 0.214037}, {0.267365, 0.233264}, {0.293222, 0.246721}, {0.305931, 0.283302}, {0.353572, 0.30591}, {0.31936, 0.277963}, {0.333905, 0.290394}, {0.332367, 0.306329}, {0.366738, 0.32567}, {0.320323, 0.287947}, {0.350888, 0.304745}, {0.304484, 0.267351}, {0.346143, 0.2938}, {0.35754, 0.325232}, {0.351343, 0.321786}, {0.356708, 0.324975}, {0.318892, 0.283088}, {0.35255, 0.284014}, {0.269734, 0.250074}, {0.302164, 0.258861}, {0.273729, 0.242562}, {0.279737, 0.258363}, {0.332897, 0.27378}, {0.294254, 0.241373}, {0.270873, 0.227934}, {0.300656, 0.254726}, {0.298719, 0.251887}, {0.312011, 0.271408}, {0.312045, 0.277342}, {0.278206, 0.213395}, {0.252544, 0.22504}, {0.276976, 0.249022}, {0.30677, 0.271645}, {0.316218, 0.280276}, {0.34208, 0.32003}, {0.344275, 0.301978}, {0.317163, 0.285708}, {0.291483, 0.265577}, {0.321766, 0.291432}, {0.304463, 0.255769}, {0.287847, 0.254365}, + {0.281, 0.251108}, {0.248278, 0.211806}, {0.275872, 0.222685}, {0.320102, 0.282848}, {0.320179, 0.291016}, {0.310622, 0.288037}, {0.354913, 0.317823}, {0.362982, 0.323102}, {0.382634, 0.347439}, {0.436671, 0.393897}, {0.400225, 0.355155}, {0.378951, 0.330732}, {0.40852, 0.36693}, {0.396694, 0.353134}, {0.384914, 0.332098}, {0.400694, 0.335649}, {0.434291, 0.376717}, {0.4574, 0.377063}, {0.40749, 0.352026}, {0.377086, 0.34527}, {0.356947, 0.31856}, {0.407151, 0.363988}, {0.365293, 0.310684}, {0.36517, 0.30981}, {0.322618, 0.295969}, {0.347551, 0.316364}, {0.356092, 0.33072}, {0.328048, 0.286273}, {0.303233, 0.262116}, {0.327298, 0.291961}, {0.33967, 0.306321}, {0.347209, 0.30945}, {0.423324, 0.373762}, {0.467451, 0.427065}, {0.485102, 0.442639}, {0.482161, 0.435285}, {0.526462, 0.462317}, {0.494175, 0.44011}, {0.485902, 0.44056}, {0.514893, 0.468123}, {0.498827, 0.421454}, {0.416001, 0.376464}, {0.434326, 0.370704}, {0.41154, 0.375531}, {0.420539, 0.374721}, {0.352145, 0.314271}, {0.369387, 0.329345}, {0.313224, 0.253729}, {0.252535, 0.19566}, {0.239264, 0.18537}, {0.297509, 0.226964}, {0.300446, 0.253653}, {0.312377, 0.235445}, {0.354414, 0.296453}, {0.407046, 0.349423}, {0.404036, 0.326566}, {0.359767, 0.314858}, {0.383377, 0.332781}, {0.384119, 0.344249}, {0.417139, 0.35882}, {0.41976, 0.388646}, {0.47234, 0.431978}, {0.435501, 0.395514}, {0.449849, 0.383208}, {0.405343, 0.380153}, {0.41271, 0.379378}, {0.405434, 0.359726}, {0.431922, 0.389831}, {0.444205, 0.387251}, {0.452258, 0.411281}, {0.468865, 0.410314}, {0.449253, 0.40872}, {0.453405, 0.407649}, {0.424127, 0.373768}, + {0.457375, 0.401247}, {0.439841, 0.403642}, {0.434655, 0.395074}, {0.440095, 0.399226}, {0.418713, 0.379565}, {0.452229, 0.411287}, {0.464873, 0.422529}, {0.418626, 0.380357}, {0.461278, 0.415438}, {0.464783, 0.417884}, {0.41241, 0.372524}, {0.433551, 0.377912}, {0.418152, 0.387574}, {0.393969, 0.344032}, {0.408605, 0.354252}, {0.418879, 0.37744}, {0.473749, 0.425549}, {0.448801, 0.400045}, {0.410327, 0.367675}, {0.408166, 0.364535}, {0.424311, 0.390303}, {0.456071, 0.412096}, {0.39573, 0.358575}, {0.475622, 0.419184}, {0.425768, 0.370324}, {0.404307, 0.369082}, {0.410716, 0.375892}, {0.436092, 0.389484}, {0.467865, 0.413464}, {0.417549, 0.373848}, {0.400836, 0.359993}, {0.421958, 0.356111}, {0.407149, 0.345115}, {0.367868, 0.32465}, {0.355686, 0.312409}, {0.372136, 0.318128}, {0.388107, 0.342633}, {0.376581, 0.334347}, {0.357142, 0.308377}, {0.393781, 0.343574}, {0.389148, 0.336873}, {0.383095, 0.331742}, {0.387628, 0.34379}, {0.386451, 0.346884}, {0.428929, 0.373297}, {0.453151, 0.422745}, {0.442739, 0.400585}, {0.423663, 0.385654}, {0.38419, 0.352462}, {0.361816, 0.318684}, {0.319557, 0.276947}, {0.334841, 0.282904}, {0.358805, 0.293001}, {0.263002, 0.221148}, {0.336325, 0.26906}, {0.320274, 0.282138}, {0.310336, 0.281805}, {0.386992, 0.321001}, {0.380808, 0.338502}, {0.365934, 0.317627}, {0.357173, 0.313179}, {0.345997, 0.309053}, {0.339218, 0.313242}, {0.307611, 0.281644}, {0.30468, 0.274143}, {0.337673, 0.272039}, {0.34802, 0.287986}, {0.29084, 0.262597}, {0.275486, 0.248903}, {0.288169, 0.248672}, {0.309869, 0.256865}, {0.306503, 0.273067}, {0.310869, 0.285479}, {0.301604, 0.260129}, {0.325206, 0.266986}, {0.331112, 0.278593}, {0.316342, 0.273716}, {0.301492, 0.268069}, {0.30926, 0.289613}, {0.293895, 0.264782}, {0.323495, 0.29071}, {0.3496, 0.314575}, {0.379828, 0.33118}, {0.364383, 0.326056}, {0.373069, 0.335372}, {0.350771, 0.302185}, {0.32211, 0.303163}, {0.33461, 0.304562}, {0.341483, 0.327248}, {0.372234, 0.332915}, {0.305097, 0.285193}, {0.32306, 0.287671}, {0.314559, 0.288247}, {0.292955, 0.263162}, + {0.32562, 0.300697}, {0.369516, 0.338374}, {0.310198, 0.291545}, {0.322811, 0.264819}, {0.3153, 0.286413}, {0.310632, 0.274186}, {0.326504, 0.281206}, {0.325713, 0.254737}, {0.306735, 0.273654}, {0.362462, 0.315703}, {0.339372, 0.30779}, {0.349886, 0.308428}, {0.260873, 0.240118}, {0.350755, 0.273223}, {0.365283, 0.329108}, {0.359394, 0.334915}, {0.351896, 0.319845}, {0.326027, 0.301458}, {0.34261, 0.304912}, {0.378681, 0.315477}, {0.370678, 0.345281}, {0.390978, 0.365994}, {0.425115, 0.400529}, {0.408409, 0.383547}, {0.379097, 0.356681}, {0.356066, 0.330234}, {0.332365, 0.314499}, {0.350802, 0.325967}, {0.369848, 0.343836}, {0.374704, 0.346387}, {0.352953, 0.316034}, {0.36829, 0.335749}, {0.35213, 0.315018}, {0.360394, 0.319941}, {0.330721, 0.308945}, {0.313873, 0.284113}, {0.354149, 0.307163}, {0.281229, 0.240843}, {0.284547, 0.258219}, {0.295196, 0.273082}, {0.324978, 0.300959}, {0.42831, 0.371798}, {0.394009, 0.360934}, {0.380378, 0.348531}, {0.330981, 0.299271}, {0.320372, 0.286036}, {0.329833, 0.296286}, {0.340044, 0.314983}, {0.362164, 0.332621}, {0.365584, 0.345534}, {0.390139, 0.359282}, {0.363232, 0.329742}, {0.314391, 0.295122}, {0.324831, 0.277573}, {0.29437, 0.264554}, {0.32574, 0.305068}, {0.34144, 0.306296}, {0.318744, 0.293875}, {0.323529, 0.302829}, {0.325934, 0.307876}, {0.328336, 0.310774}, {0.317785, 0.294552}, {0.347917, 0.325183}, {0.341312, 0.31469}, {0.351052, 0.323637}, {0.370319, 0.33893}, {0.345865, 0.313735}, {0.347259, 0.322909}, {0.36862, 0.345225}, {0.357584, 0.336116}, {0.361039, 0.343969}, {0.366018, 0.333574}, {0.363498, 0.342153}, {0.362328, 0.341936}, {0.366455, 0.341359}, {0.378764, 0.355361}, {0.405655, 0.370895}, {0.418312, 0.375054}, {0.413619, 0.381392}, {0.423664, 0.399496}, {0.411059, 0.372585}, {0.417625, 0.383807}, {0.40319, 0.383619}, {0.382877, 0.35503}, {0.395012, 0.370283}, {0.384574, 0.366609}, {0.369238, 0.348355}, {0.355004, 0.334509}, {0.318713, 0.298255}, {0.39618, 0.353544}, {0.38012, 0.340015}, {0.387309, 0.342449}, {0.369716, 0.343017}, {0.371042, 0.350674}, {0.374843, 0.34144}, {0.361847, 0.335541}, {0.375508, 0.343188}, {0.315871, 0.285697}, {0.348014, 0.316022}, {0.394237, 0.367946}, {0.374711, 0.351039}, {0.412328, 0.375617}, {0.422141, 0.398207}, {0.438174, 0.411553}, {0.432537, 0.412369}, {0.462693, 0.439637}, {0.445593, 0.420806}, {0.424173, 0.382669}, {0.356423, 0.325932}, {0.398459, 0.363847}, {0.38278, 0.354968}, {0.389003, 0.36698}, {0.383767, 0.368211}, {0.394789, 0.372225}, {0.400366, 0.379074}, + {0.382966, 0.368313}, {0.395008, 0.370541}, {0.385423, 0.359639}, {0.393429, 0.368295}, {0.404077, 0.377931}, {0.426499, 0.39576}, {0.404368, 0.374018}, {0.374234, 0.338259}, {0.344772, 0.321633}, {0.366517, 0.345099}, {0.358641, 0.339025}, {0.343616, 0.31247}, {0.329817, 0.314183}, {0.363155, 0.328584}, {0.345038, 0.281568}, {0.328362, 0.301723}, {0.405884, 0.374268}, {0.378924, 0.360103}, {0.377628, 0.335302}, {0.354274, 0.325117}, {0.357565, 0.326202}, {0.344593, 0.309925}, {0.309939, 0.279319}, {0.292597, 0.267561}, {0.276516, 0.245052}, {0.26571, 0.237926}, {0.340131, 0.312531}, {0.391746, 0.34058}, {0.35758, 0.331176}, {0.354637, 0.326849}, {0.347816, 0.319134}, {0.33877, 0.303463}, {0.309103, 0.275891}, {0.312833, 0.27785}, {0.323623, 0.288525}, {0.33292, 0.299599}, {0.331855, 0.307543}, {0.371349, 0.332637}, {0.374663, 0.347059}, {0.34817, 0.313103}, {0.32204, 0.287933}, {0.279036, 0.254919}, {0.277282, 0.249513}, {0.29063, 0.256939}, {0.297394, 0.269875}, {0.270069, 0.241505}, {0.246459, 0.228309}, {0.28125, 0.236651}, {0.297362, 0.252546}, {0.294296, 0.269104}, {0.30494, 0.27586}, {0.321745, 0.279112}, {0.369607, 0.330854}, {0.357406, 0.306494}, {0.290853, 0.267935}, {0.311066, 0.268468}, {0.287413, 0.255659}, {0.249147, 0.227482}, {0.306527, 0.268163}, {0.260049, 0.234014}, {0.272682, 0.245516}, {0.3063, 0.283215}, {0.3063, 0.283215}, {0.3063, 0.283215}, {0.3063, 0.283215}, {0.358634, 0.334849}, {0.355544, 0.333752}, {0.360269, 0.32463}, {0.34264, 0.309022}, {0.345387, 0.326733}, {0.322464, 0.299376}, {0.320641, 0.286444}, {0.319691, 0.288205}, {0.329447, 0.305921}, {0.3063, 0.283215}, {0.330278, 0.306256}, {0.323037, 0.285172}, {0.315152, 0.273667}, {0.312538, 0.282496}, {0.331332, 0.300567}, {0.376953, 0.321656}, {0.352657, 0.314588}, {0.340712, 0.318342}, {0.359152, 0.337689}, {0.394462, 0.3654}, {0.408728, 0.381945}, {0.401355, 0.371609}, {0.393315, 0.361136}, {0.373032, 0.352742}, {0.399773, 0.371699}, {0.397179, 0.370996}, {0.386826, 0.367324}, {0.397828, 0.37586}, {0.420839, 0.391106}, {0.449118, 0.417142}, {0.450047, 0.421478}, {0.459429, 0.439292}, {0.466778, 0.442081}, {0.457061, 0.431377}, {0.461494, 0.436802}, {0.438678, 0.408775}, {0.428804, 0.399832}, {0.454245, 0.432662}, {0.44105, 0.41422}, + {0.471559, 0.440804}, {0.457061, 0.433455}, {0.49626, 0.464378}, {0.470757, 0.441454}, {0.463686, 0.441071}, {0.462199, 0.4361}, {0.4662, 0.435212}, {0.47616, 0.441495}, {0.44801, 0.429987}, {0.458415, 0.438664}, {0.43608, 0.41143}, {0.44956, 0.421996}, {0.415993, 0.393869}, {0.38827, 0.375995}, {0.399817, 0.375388}, {0.378578, 0.350996}, {0.366947, 0.348341}, {0.384007, 0.35838}, {0.376473, 0.346557}, {0.326399, 0.308269}, {0.345603, 0.32461}, {0.36123, 0.33645}, {0.341729, 0.313373}, {0.338542, 0.322909}, {0.389431, 0.369919}, {0.386447, 0.364246}, {0.38867, 0.363128}, {0.348056, 0.330882}, {0.34055, 0.311337}, {0.330701, 0.297965}, {0.363628, 0.315222}, {0.35535, 0.323633}, {0.32092, 0.299112}, {0.30777, 0.280638}, {0.327398, 0.286482}, {0.319297, 0.295685}, {0.279409, 0.261628}, {0.306132, 0.27366}, {0.30388, 0.277223}, {0.323293, 0.299218}, {0.27328, 0.23496}, {0.319629, 0.28861}, {0.317125, 0.291309}, {0.325614, 0.300112}, {0.328471, 0.300215}, {0.336013, 0.284126}, {0.270958, 0.239704}, {0.308582, 0.257596}, {0.332009, 0.292736}, {0.302842, 0.274857}, {0.30678, 0.273195}, {0.325034, 0.287859}, {0.355354, 0.320754}, {0.340265, 0.315973}, {0.352482, 0.328707}, {0.344925, 0.311149}, {0.339387, 0.308025}, {0.302581, 0.264534}, {0.373754, 0.320115}, {0.315363, 0.276574}, {0.297239, 0.277708}, {0.27604, 0.239365}, {0.290292, 0.246094}, {0.255742, 0.221793}, {0.328959, 0.265471}, {0.324085, 0.274847}, {0.264871, 0.228372}, {0.272468, 0.237902}, {0.265469, 0.238249}, {0.252341, 0.221333}, {0.244323, 0.20677}, {0.266341, 0.211852}, {0.257965, 0.20948}, {0.278218, 0.238526}, {0.333001, 0.286999}, {0.302655, 0.265795}, {0.317095, 0.270289}, {0.35549, 0.296224}, {0.326148, 0.290374}, {0.329238, 0.292815}, {0.380009, 0.339708}, {0.398882, 0.357047}, {0.370007, 0.333938}, {0.339661, 0.295817}, {0.356598, 0.310311}, {0.339891, 0.303176}, {0.373124, 0.334197}, {0.35616, 0.318783}, {0.336374, 0.302525}, {0.336108, 0.291575}, {0.266251, 0.229119}, {0.288503, 0.254435}, {0.341413, 0.304008}, {0.311688, 0.24523}, {0.239355, 0.20491}, {0.238168, 0.179219}, {0.238128, 0.191044}, {0.2763, 0.218628}, {0.299374, 0.252803}, {0.355011, 0.291467}, {0.396597, 0.293806}, {0.435119, 0.356502}, {0.484872, 0.414269}, {0.436239, 0.372832}, {0.408486, 0.334832}, {0.352318, 0.301372}, {0.358584, 0.314837}, {0.320424, 0.281008}, {0.318422, 0.242133}, {0.305288, 0.232088}, {0.292282, 0.24242}, {0.270574, 0.227352}, {0.244659, 0.207785}, {0.214509, 0.161553}, {0.290777, 0.222099}, {0.301869, 0.261401}, {0.300802, 0.260615}, {0.265479, 0.227106}, {0.265924, 0.220548}, {0.275963, 0.24331}, {0.285168, 0.245183}, {0.302318, 0.26372}, {0.329648, 0.283626}, {0.31536, 0.275239}, + {0.319755, 0.283885}, {0.302946, 0.249998}, {0.23451, 0.208417}, {0.237979, 0.20009}, {0.278087, 0.234326}, {0.349772, 0.267915}, {0.349622, 0.297464}, {0.332118, 0.291638}, {0.322073, 0.283554}, {0.363772, 0.288675}, {0.264939, 0.210548}, {0.233288, 0.181551}, {0.295209, 0.24732}, {0.328271, 0.294317}, {0.30648, 0.247738}, {0.291785, 0.243838}, {0.300416, 0.238145}, {0.276949, 0.223473}, {0.278376, 0.234067}, {0.285587, 0.222088}, {0.349336, 0.2709}, {0.349241, 0.30195}, {0.343975, 0.269072}, {0.244725, 0.202664}, {0.283995, 0.24012}, {0.256025, 0.220353}, {0.325584, 0.269216}, {0.367386, 0.31738}, {0.374273, 0.308344}, {0.356721, 0.30568}, {0.342774, 0.293458}, {0.357583, 0.302664}, {0.361221, 0.320232}, {0.380577, 0.330386}, {0.390984, 0.345065}, {0.398606, 0.342157}, {0.381841, 0.309518}, {0.355597, 0.268696}, {0.301706, 0.248095}, {0.285225, 0.234619}, {0.30263, 0.234544}, {0.287399, 0.235807}, {0.309619, 0.220345}, {0.322904, 0.237275}, {0.297008, 0.227937}, {0.254815, 0.212848}, {0.259985, 0.20424}, {0.293004, 0.227877}, {0.316328, 0.255436}, {0.316965, 0.279818}, {0.394202, 0.333259}, {0.447769, 0.36851}, {0.470049, 0.419559}, {0.448298, 0.371132}, {0.401432, 0.343177}, {0.377439, 0.327103}, {0.377269, 0.300522}, {0.352342, 0.307281}, {0.38024, 0.336864}, {0.394774, 0.357728}, {0.44012, 0.375308}, {0.511486, 0.455011}, {0.482609, 0.435611}, {0.518963, 0.438291}, {0.559542, 0.5}, {0.5, 0.453278}, {0.544186, 0.49267}, {0.492429, 0.445766}, {0.520319, 0.45064}, {0.536619, 0.479712}, {0.471731, 0.416865}, {0.543644, 0.443693}, {0.526329, 0.481787}, {0.485463, 0.456071}, {0.507579, 0.452616}, {0.52261, 0.460043}, {0.473417, 0.427828}, {0.443149, 0.37927}, {0.416547, 0.359899}, {0.400435, 0.338079}, {0.381916, 0.331414}, {0.419236, 0.360157}, {0.39162, 0.358251}, {0.407147, 0.365604}, {0.379914, 0.317121}, {0.382633, 0.296757}, {0.363915, 0.30045}, {0.351729, 0.29296}, {0.359075, 0.304135}, {0.414869, 0.344679}, {0.422425, 0.373013}, {0.44009, 0.37934}, {0.413981, 0.358401}, {0.389412, 0.336103}, {0.412572, 0.349402}, {0.400958, 0.334054}, {0.416153, 0.369312}, {0.402553, 0.33716}, {0.457163, 0.404032}, {0.473496, 0.414769}, {0.456239, 0.392937}, {0.423052, 0.376017}, {0.396126, 0.355687}, {0.461696, 0.396039}, {0.428846, 0.371749}, {0.426949, 0.367741}, {0.358497, 0.318243}, {0.416522, 0.350196}, {0.438035, 0.381315}, {0.446391, 0.39349}, {0.374761, 0.348329}, {0.368378, 0.337527}, {0.390005, 0.347201}, {0.371532, 0.331729}, {0.42225, 0.372823}, {0.420439, 0.373111}, {0.374305, 0.282836}, {0.334445, 0.282384}, {0.308988, 0.264015}, {0.367898, 0.320822}, {0.380566, 0.329728}, {0.397995, 0.341424}, {0.428368, 0.382006}, {0.402137, 0.345929}, {0.348813, 0.304654}, {0.387966, 0.322068}, {0.40455, 0.369715}, {0.372291, 0.340847}, {0.363427, 0.322792}, {0.331698, 0.286509}, {0.308877, 0.267521}, {0.289303, 0.246546}, {0.284947, 0.241408}, {0.297149, 0.243535}, {0.280611, 0.228787}, {0.261652, 0.228516}, + {0.274803, 0.24712}, {0.313549, 0.289173}, {0.355521, 0.314822}, {0.31492, 0.293063}, {0.314952, 0.265615}, {0.296103, 0.251899}, {0.299861, 0.257725}, {0.282441, 0.240922}, {0.284398, 0.233884}, {0.28111, 0.231627}, {0.319162, 0.274913}, {0.271781, 0.229954}, {0.288321, 0.23603}, {0.298013, 0.258716}, {0.309041, 0.269323}, {0.294164, 0.253131}, {0.284183, 0.252174}, {0.304091, 0.269127}, {0.311153, 0.281941}, {0.292154, 0.258239}, {0.334401, 0.272131}, {0.278442, 0.242096}, {0.285026, 0.24584}, {0.33648, 0.303047}, {0.306345, 0.266234}, {0.268951, 0.23933}, {0.276602, 0.247522}, {0.317519, 0.295897}, {0.313057, 0.242112}, {0.256129, 0.233391}, {0.273717, 0.249697}, {0.335988, 0.304282}, {0.337168, 0.311012}, {0.30669, 0.275304}, {0.343944, 0.297188}, {0.369285, 0.328681}, {0.332887, 0.297593}, {0.28402, 0.261164}, {0.292001, 0.24421}, {0.302369, 0.283635}, {0.343031, 0.307335}, {0.280527, 0.252404}, {0.337244, 0.266114}, {0.305768, 0.273632}, {0.315603, 0.280284}, {0.256539, 0.229555}, {0.240216, 0.213221}, {0.247806, 0.226073}, {0.279347, 0.231927}, {0.294937, 0.233077}, {0.311297, 0.273794}, {0.330423, 0.298344}, {0.376994, 0.332218}, {0.323586, 0.278236}, {0.300735, 0.27649}, {0.327249, 0.302806}, {0.335393, 0.306737}, {0.321386, 0.291464}, {0.368057, 0.309653}, {0.396459, 0.351874}, {0.372025, 0.339769}, {0.389331, 0.365001}, {0.397023, 0.370313}, {0.394986, 0.371733}, {0.403411, 0.359192}, {0.353303, 0.323699}, {0.373505, 0.329445}, {0.317569, 0.291187}, {0.312845, 0.287383}, {0.332799, 0.285739}, {0.332857, 0.293195}, {0.317847, 0.283798}, {0.314955, 0.28019}, {0.323306, 0.288911}, {0.303748, 0.269893}, {0.308124, 0.28692}, {0.310973, 0.290188}, {0.292473, 0.276218}, {0.325299, 0.282435}, {0.333984, 0.315216}, {0.362119, 0.32631}, {0.403215, 0.355685}, {0.384081, 0.352206}, {0.393905, 0.364867}, {0.357601, 0.335532}, {0.363832, 0.331741}, {0.343913, 0.316039}, {0.353235, 0.324816}, {0.331445, 0.284887}, {0.301191, 0.276285}, {0.330925, 0.298972}, {0.280236, 0.262722}, {0.291047, 0.271654}, {0.360953, 0.319177}, {0.312047, 0.29744}, {0.331555, 0.301649}, {0.347913, 0.315363}, {0.357004, 0.31239}, {0.33157, 0.310234}, {0.327905, 0.304609}, {0.330489, 0.296458}, {0.31196, 0.278844}, {0.313553, 0.291464}, {0.333939, 0.310498}, {0.354699, 0.322672}, {0.346761, 0.312418}, {0.346551, 0.317405}, {0.357948, 0.320939}, {0.40448, 0.362603}, {0.366496, 0.344748}, {0.405228, 0.353301}, {0.348669, 0.327908}, {0.341353, 0.311164}, {0.342301, 0.323657}, {0.338674, 0.316579}, {0.323278, 0.299039}, {0.327392, 0.292268}, {0.333522, 0.314061}, {0.325305, 0.303541}, {0.334558, 0.316532}, {0.356128, 0.333532}, {0.339305, 0.321171}, {0.374706, 0.330997}, {0.387365, 0.331467}, {0.295214, 0.279101}, {0.370209, 0.323464}, {0.37239, 0.331075}, {0.406603, 0.371061}, {0.397155, 0.368488}, {0.359564, 0.326735}, + {0.396735, 0.364928}, {0.407402, 0.353896}, {0.339983, 0.316161}, {0.337691, 0.30944}, {0.335062, 0.312444}, {0.344477, 0.315125}, {0.324904, 0.290875}, {0.342876, 0.309724}, {0.332467, 0.304046}, {0.323388, 0.280904}, {0.338406, 0.310311}, {0.358475, 0.319245}, {0.329663, 0.29733}, {0.34955, 0.319836}, {0.347046, 0.324598}, {0.349195, 0.329339}, {0.351288, 0.322526}, {0.342537, 0.31311}, {0.314061, 0.294881}, {0.334163, 0.306759}, {0.356635, 0.321101}, {0.340561, 0.319622}, {0.316049, 0.29803}, {0.325966, 0.301187}, {0.301945, 0.289938}, {0.307711, 0.290303}, {0.29374, 0.264891}, {0.311767, 0.288423}, {0.299973, 0.272212}, {0.336101, 0.299864}, {0.319491, 0.270424}, {0.311806, 0.284673}, {0.339994, 0.29359}, {0.337558, 0.291967}, {0.333577, 0.309179}, {0.328045, 0.304475}, {0.333526, 0.308766}, {0.363946, 0.332936}, {0.358775, 0.33132}, {0.338017, 0.316481}, {0.364369, 0.330791}, {0.347953, 0.317711}, {0.32126, 0.297356}, {0.324742, 0.302466}, {0.313008, 0.284299}, {0.317745, 0.286277}, {0.306609, 0.261197}, {0.303667, 0.273478}, {0.321373, 0.297077}, {0.318386, 0.295585}, {0.319261, 0.293789}, {0.337351, 0.311475}, {0.353527, 0.336349}, {0.361473, 0.326766}, {0.330572, 0.304269}, {0.322304, 0.292783}, {0.30036, 0.278078}, {0.289862, 0.270849}, {0.297179, 0.275804}, {0.332243, 0.299967}, {0.313836, 0.286358}, {0.296416, 0.279615}, {0.324682, 0.306503}, {0.317861, 0.292605}, {0.312889, 0.276725}, {0.293932, 0.266422}, {0.290725, 0.261675}, {0.295932, 0.265523}, {0.303207, 0.274415}, {0.320263, 0.276544}, {0.274754, 0.252179}, {0.293007, 0.260706}, {0.324288, 0.297237}, {0.312856, 0.277841}, {0.273123, 0.260903}, {0.280522, 0.261232}, {0.290857, 0.266053}, {0.286099, 0.25112}, {0.285037, 0.265604}, {0.295781, 0.270652}, {0.314611, 0.27642}, {0.344567, 0.316825}, {0.337934, 0.320042}, {0.322563, 0.28993}, {0.297702, 0.270816}, {0.340585, 0.301813}, {0.35022, 0.313813}, {0.392459, 0.353658}, {0.378034, 0.356742}, {0.40965, 0.383408}, {0.414993, 0.377545}, {0.402939, 0.378299}, {0.384948, 0.361222}, {0.389606, 0.365571}, {0.405834, 0.379863}, {0.389301, 0.361122}, {0.367138, 0.329679}, {0.357649, 0.32524}, {0.356769, 0.327169}, {0.366614, 0.332374}, {0.388547, 0.348327}, {0.346342, 0.320241}, {0.337731, 0.311053}, {0.37636, 0.327369}, {0.368719, 0.340776}, {0.370046, 0.346417}, {0.351399, 0.32212}, {0.370414, 0.350551}, {0.380806, 0.332679}, {0.328986, 0.298951}, {0.354214, 0.33116}, {0.371723, 0.348172}, {0.375295, 0.336048}, {0.366785, 0.341522}, {0.316994, 0.290389}, {0.337215, 0.302148}, {0.337263, 0.309368}, {0.307249, 0.284054}, {0.282687, 0.253204}, {0.272018, 0.249573}, {0.324478, 0.26039}, {0.326717, 0.298343}, {0.331261, 0.298644}, {0.308865, 0.289441}, {0.315927, 0.283236}, {0.299669, 0.282163}, {0.338079, 0.278863}, {0.304251, 0.269638}, {0.321703, 0.274735}, {0.312739, 0.288844}, {0.313288, 0.279261}, {0.307109, 0.278321}, {0.304794, 0.281146}, {0.304506, 0.271623}, {0.305802, 0.287124}, {0.321135, 0.284219}, {0.270856, 0.243317}, {0.252583, 0.229435}, {0.235338, 0.214102}, {0.282535, 0.254056}, {0.321693, 0.284768}, {0.322531, 0.280912}, {0.34682, 0.315427}, {0.312508, 0.292964}, {0.32088, 0.292563}, {0.370708, 0.331705}, {0.365146, 0.317456}, {0.341678, 0.308341}, {0.369915, 0.332028}, {0.373425, 0.326817}, {0.340127, 0.307729}, {0.300231, 0.276413}, {0.337389, 0.288163}, {0.358569, 0.309567}, {0.318835, 0.274604}, {0.372181, 0.304529}, {0.315659, 0.26968}, {0.316269, 0.276621}, {0.302617, 0.28225}, {0.354125, 0.316934}, {0.323515, 0.289507}, {0.306258, 0.283222}, {0.405195, 0.337789}, {0.388684, 0.361708}, {0.396203, 0.353994}, {0.385857, 0.34429}, {0.345379, 0.307753}, {0.354235, 0.313538}, {0.356817, 0.310868}, {0.356968, 0.317072}, {0.354337, 0.312885}, {0.361054, 0.312337}, {0.309061, 0.283838}, {0.363458, 0.316187}, {0.353571, 0.314808}, {0.360945, 0.322496}, {0.356489, 0.327936}, {0.369631, 0.322265}, {0.353975, 0.319973}, {0.391002, 0.341438}, {0.370131, 0.325068}, {0.370647, 0.340792}, {0.336711, 0.304105}, {0.335072, 0.299636}, {0.398934, 0.358421}, {0.388425, 0.345039}, {0.357132, 0.311645}, {0.349233, 0.305014}, + {0.344537, 0.299961}, {0.357206, 0.308042}, {0.399579, 0.34798}, {0.351375, 0.309566}, {0.378029, 0.333347}, {0.367484, 0.318773}, {0.359317, 0.308931}, {0.364145, 0.296936}, {0.328989, 0.271796}, {0.301328, 0.241501}, {0.299659, 0.227111}, {0.240603, 0.192101}, {0.323435, 0.260601}, {0.272736, 0.227983}, {0.331991, 0.256815}, {0.35638, 0.309467}, {0.324201, 0.258069}, {0.313958, 0.257408}, {0.318118, 0.245767}, {0.292587, 0.237573}, {0.303014, 0.235195}, {0.321409, 0.268883}, {0.314619, 0.242741}, {0.305406, 0.236496}, {0.348237, 0.279844}, {0.26902, 0.217109}, {0.338705, 0.279967}, {0.433446, 0.370928}, {0.416625, 0.360315}, {0.404118, 0.357603}, {0.417126, 0.364009}, {0.436022, 0.376953}, {0.389294, 0.331293}, {0.369903, 0.325412}, {0.409513, 0.362285}, {0.447908, 0.399894}, {0.462946, 0.414597}, {0.459251, 0.37288}, {0.441342, 0.372509}, {0.428964, 0.378794}, {0.485066, 0.425122}, {0.452048, 0.403339}, {0.443457, 0.393962}, {0.43287, 0.374859}, {0.453134, 0.387599}, {0.361266, 0.279143}, {0.333468, 0.277536}, {0.347985, 0.29911}, {0.355828, 0.307958}, {0.378617, 0.323448}, {0.397817, 0.334466}, {0.340607, 0.28852}, {0.361751, 0.323805}, {0.364061, 0.330576}, {0.408111, 0.352832}, {0.413472, 0.373421}, {0.431926, 0.393082}, {0.456396, 0.407554}, {0.402019, 0.359589}, {0.38838, 0.343889}, {0.392386, 0.334699}, {0.37935, 0.308494}, {0.377399, 0.326991}, {0.400469, 0.352825}, {0.45332, 0.399616}, {0.479995, 0.436812}, {0.431473, 0.356361}, {0.429621, 0.375194}, {0.427767, 0.388697}, {0.424873, 0.379458}, {0.400537, 0.358381}, {0.433106, 0.391602}, {0.414462, 0.357068}, {0.375942, 0.329217}, {0.388735, 0.332708}, {0.38896, 0.333774}, {0.403386, 0.341531}, {0.406096, 0.369446}, {0.417341, 0.360568}, {0.395676, 0.311997}, {0.362, 0.300851}, {0.373337, 0.324211}, {0.384212, 0.321777}, {0.420922, 0.355665}, {0.45793, 0.400755}, {0.483549, 0.404034}, {0.505941, 0.469434}, {0.520446, 0.488176}, {0.528091, 0.492897}, {0.5, 0.433988}, {0.468075, 0.424156}, {0.473863, 0.40494}, {0.453756, 0.403287}, {0.39419, 0.344551}, {0.371112, 0.314974}, {0.346079, 0.291445}, {0.353375, 0.287557}, {0.344978, 0.293839}, {0.353907, 0.308442}, {0.423628, 0.35982}, {0.380125, 0.344312}, {0.381031, 0.342361}, {0.379351, 0.339364}, {0.461921, 0.394864}, {0.396079, 0.329269}, {0.452309, 0.370726}, {0.466838, 0.404989}, {0.45596, 0.39748}, {0.433707, 0.374123}, {0.469973, 0.401185}, {0.486984, 0.421638}, {0.486307, 0.427453}, {0.485814, 0.416943}, {0.471276, 0.409588}, {0.508884, 0.451396}, {0.516399, 0.480642}, {0.504895, 0.471821}, {0.486172, 0.455104}, {0.482379, 0.430445}, {0.492701, 0.428543}, {0.485616, 0.424503}, {0.5, 0.438292}, {0.519791, 0.460101}, {0.48997, 0.427064}, {0.473996, 0.412686}, {0.476602, 0.422191}, + {0.436934, 0.372345}, {0.404741, 0.340169}, {0.46579, 0.389599}, {0.476399, 0.388878}, {0.498278, 0.433267}, {0.484851, 0.4254}, {0.417916, 0.341772}, {0.439476, 0.357638}, {0.323998, 0.270746}, {0.34442, 0.290664}, {0.382291, 0.328549}, {0.392728, 0.339118}, {0.379795, 0.316028}, {0.365944, 0.30779}, {0.386948, 0.329375}, {0.476259, 0.396194}, {0.401749, 0.336985}, {0.400543, 0.332401}, {0.377343, 0.31153}, {0.396877, 0.318554}, {0.361702, 0.305318}, {0.357168, 0.308851}, {0.351094, 0.28497}, {0.339513, 0.282309}, {0.353124, 0.306763}, {0.330926, 0.287643}, {0.315131, 0.265473}, {0.337064, 0.281903}, {0.355478, 0.298351}, {0.313472, 0.267663}, {0.348983, 0.322811}, {0.38296, 0.355069}, {0.36128, 0.323274}, {0.335466, 0.304605}, {0.361264, 0.334873}, {0.405183, 0.379681}, {0.39614, 0.374433}, {0.427109, 0.381265}, {0.363939, 0.345026}, {0.375785, 0.354004}, {0.388179, 0.362242}, {0.377565, 0.333131}, {0.309756, 0.285503}, {0.295532, 0.277514}, {0.291084, 0.247168}, {0.23759, 0.211247}, {0.247437, 0.208788}, {0.348057, 0.316948}, {0.36929, 0.306641}, {0.279716, 0.230896}, {0.280417, 0.251693}, {0.322605, 0.276023}, {0.354214, 0.316451}, {0.277251, 0.25791}, {0.359051, 0.32855}, {0.363854, 0.33917}, {0.356816, 0.322871}, {0.345293, 0.313002}, {0.326194, 0.295637}, {0.321431, 0.296353}, {0.352783, 0.331635}, {0.363849, 0.331639}, {0.360194, 0.317207}, {0.337669, 0.300658}, {0.333887, 0.295929}, {0.329712, 0.288377}, {0.300626, 0.255849}, {0.307332, 0.269592}, {0.289062, 0.262805}, {0.284357, 0.258116}, {0.292298, 0.266754}, {0.311827, 0.282825}, {0.358012, 0.307772}, {0.361376, 0.331052}, {0.372882, 0.343282}, {0.347374, 0.324855}, {0.396329, 0.353117}, {0.360793, 0.319742}, {0.336986, 0.313879}, {0.360898, 0.322524}, {0.339929, 0.309961}, {0.361884, 0.322261}, {0.362043, 0.330166}, {0.383878, 0.328616}, {0.367912, 0.338045}, {0.375896, 0.352516}, {0.356594, 0.327735}, {0.371368, 0.345052}, {0.363281, 0.340357}, {0.357894, 0.316122}, {0.325537, 0.307009}, {0.330698, 0.293444}, {0.301507, 0.276586}, {0.320306, 0.290305}, {0.351837, 0.337122}, {0.381455, 0.34618}, {0.389927, 0.336841}, {0.31276, 0.285317}, {0.315938, 0.277476}, {0.263734, 0.234364}, {0.325043, 0.269279}, {0.329103, 0.298183}, {0.305081, 0.285632}, {0.29952, 0.279488}, {0.310286, 0.280128}, {0.301528, 0.272893}, {0.304711, 0.270025}, {0.280953, 0.253417}, {0.293375, 0.242939}, {0.309132, 0.282681}, {0.334197, 0.300781}, {0.325581, 0.30045}, {0.364716, 0.324348}, {0.403534, 0.360775}, {0.383734, 0.351884}, {0.397489, 0.364397}, {0.393437, 0.371684}, {0.405689, 0.379918}, {0.395633, 0.36067}, {0.381191, 0.348318}, {0.382805, 0.352437}, {0.349265, 0.307368}, {0.331958, 0.312264}, {0.3682, 0.339841}, {0.344555, 0.322647}, {0.375668, 0.324819}, {0.378662, 0.344647}, {0.395177, 0.360866}, {0.409074, 0.37624}, {0.394947, 0.3588}, {0.389117, 0.334498}, {0.312024, 0.278881}, {0.316128, 0.271881}, {0.341077, 0.311451}, {0.365546, 0.33146}, {0.36253, 0.34272}, {0.39097, 0.338029}, {0.357747, 0.331962}, {0.348614, 0.321956}, {0.344938, 0.319531}, {0.346283, 0.31977}, {0.340858, 0.309128}, {0.328677, 0.311774}, {0.347576, 0.311887}, {0.346623, 0.318552}, {0.319391, 0.290292}, {0.332446, 0.303139}, {0.340253, 0.314586}, {0.34801, 0.333838}, {0.354091, 0.321932}, {0.33902, 0.323717}, {0.322469, 0.300012}, {0.319073, 0.3048}, {0.353963, 0.325026}, {0.371536, 0.328346}, {0.355528, 0.341148}, {0.369203, 0.348545}, {0.363409, 0.347329}, {0.365134, 0.347569}, {0.394926, 0.361508}, {0.389094, 0.365896}, {0.361684, 0.340203}, {0.368379, 0.336997}, {0.349815, 0.337638}, {0.367671, 0.345826}, {0.379495, 0.343662}, {0.348797, 0.323684}, {0.348333, 0.312145}, {0.304929, 0.261683}, {0.298963, 0.268826}, {0.301773, 0.275301}, {0.322827, 0.293101}, {0.293253, 0.26011}, {0.218763, 0.199949}, {0.235996, 0.216939}, {0.236181, 0.218336}, {0.238686, 0.213252}, {0.248909, 0.226485}, {0.246516, 0.219095}, {0.253175, 0.220655}, {0.265768, 0.232046}, {0.258753, 0.218507}, + {0.231868, 0.210166}, {0.230913, 0.20202}, {0.258398, 0.235433}, {0.24403, 0.218888}, {0.290929, 0.2592}, {0.27944, 0.254196}, {0.268507, 0.244663}, {0.287313, 0.254178}, {0.289219, 0.260989}, {0.33022, 0.260346}, {0.275762, 0.23632}, {0.287141, 0.252845}, {0.265789, 0.233293}, {0.274078, 0.248113}, {0.305765, 0.264333}, {0.296331, 0.259831}, {0.27074, 0.245102}, {0.301369, 0.266781}, {0.312921, 0.291007}, {0.320014, 0.301557}, {0.321889, 0.296708}, {0.318782, 0.301044}, {0.300691, 0.277877}, {0.276399, 0.262372}, {0.263033, 0.242698}, {0.308602, 0.279023}, {0.303583, 0.279074}, {0.300051, 0.27371}, {0.27851, 0.25867}, {0.309399, 0.275027}, {0.340588, 0.320872}, {0.342236, 0.315454}, {0.33325, 0.31453}, {0.330183, 0.311073}, {0.34861, 0.311274}, {0.361381, 0.315784}, {0.320261, 0.28198}, {0.332245, 0.305308}, {0.334411, 0.294873}, {0.312893, 0.289675}, {0.340797, 0.300464}, {0.282001, 0.254708}, {0.314316, 0.284267}, {0.300557, 0.27964}, {0.309866, 0.278854}, {0.302507, 0.280192}, {0.297805, 0.274654}, {0.292381, 0.263991}, {0.275258, 0.251865}, {0.300693, 0.281579}, {0.316141, 0.294227}, {0.319138, 0.297814}, {0.304059, 0.283549}, {0.331722, 0.300429}, {0.306148, 0.271471}, {0.312387, 0.278232}, {0.31964, 0.290364}, {0.303638, 0.276001}, {0.332715, 0.292113}, {0.355435, 0.323049}, {0.361136, 0.338276}, {0.352519, 0.332474}, {0.411477, 0.375797}, {0.408041, 0.375317}, {0.406958, 0.364211}, {0.407038, 0.359675}, {0.390486, 0.368013}, {0.364026, 0.333367}, {0.399735, 0.345391}, {0.397439, 0.358031}, {0.401706, 0.364041}, {0.43124, 0.397996}, {0.433992, 0.398916}, {0.439204, 0.414826}, {0.457828, 0.43147}, {0.504567, 0.466483}, {0.493663, 0.469288}, {0.521837, 0.486713}, {0.522617, 0.445287}, {0.447596, 0.421748}, {0.460062, 0.424102}, {0.445618, 0.411493}, {0.426001, 0.400346}, {0.437917, 0.412459}, {0.411072, 0.375903}, {0.431964, 0.405133}, {0.433132, 0.412735}, {0.430632, 0.405787}, {0.434942, 0.402202}, {0.446416, 0.41534}, {0.410718, 0.378378}, {0.393515, 0.368104}, {0.439514, 0.403525}, {0.460773, 0.402853}, {0.431798, 0.408093}, {0.449206, 0.419576}, {0.42502, 0.407469}, {0.438516, 0.396678}, {0.379852, 0.352185}, {0.361657, 0.333885}, {0.348209, 0.27982}, {0.278984, 0.254731}, {0.263409, 0.225405}, {0.311245, 0.26857}, {0.307282, 0.281846}, {0.365057, 0.318352}, {0.351344, 0.332828}, {0.380034, 0.346503}, {0.369982, 0.335633}, {0.349201, 0.313171}, {0.301481, 0.272278}, {0.295407, 0.274908}, {0.299809, 0.275685}, {0.290269, 0.258719}, {0.318643, 0.282689}, {0.338804, 0.292835}, {0.32051, 0.292374}, {0.313948, 0.287569}, {0.306397, 0.274751}, {0.298433, 0.268582}, {0.296676, 0.278019}, {0.322958, 0.295267}, {0.306717, 0.281974}, {0.279188, 0.258073}, {0.288947, 0.261671}, {0.346536, 0.310081}, {0.329351, 0.307305}, {0.313893, 0.297539}, {0.358375, 0.324003}, {0.355362, 0.326172}, {0.319795, 0.300639}, {0.356252, 0.314555}, {0.331434, 0.303863}, {0.309747, 0.286512}, {0.396576, 0.334384}, {0.325386, 0.296871}, {0.336291, 0.300906}, {0.342658, 0.316801}, {0.349532, 0.314106}, {0.354185, 0.319333}, {0.368402, 0.313591}, {0.297419, 0.256327}, {0.29686, 0.259869}, {0.330659, 0.290939}, {0.320013, 0.290854}, {0.302734, 0.231339}, {0.326436, 0.288925}, {0.323011, 0.277895}, {0.265369, 0.223625}, {0.241579, 0.214559}, {0.24025, 0.214469}, + {0.259072, 0.235491}, {0.307785, 0.269806}, {0.278753, 0.250229}, {0.286384, 0.251786}, {0.294949, 0.24918}, {0.230292, 0.192876}, {0.392681, 0.31188}, {0.388076, 0.353897}, {0.396681, 0.366906}, {0.392647, 0.35689}, {0.372875, 0.336537}, {0.372537, 0.336309}, {0.412217, 0.377151}, {0.404014, 0.352842}, {0.415036, 0.378778}, {0.410219, 0.376986}, {0.386226, 0.356872}, {0.388954, 0.358256}, {0.387231, 0.346007}, {0.376972, 0.349049}, {0.406397, 0.371109}, {0.428401, 0.393732}, {0.432486, 0.39027}, {0.367025, 0.334839}, {0.434084, 0.372001}, {0.481822, 0.42584}, {0.49228, 0.427334}, {0.430329, 0.377251}, {0.448348, 0.393633}, {0.480033, 0.423673}, {0.468495, 0.421004}, {0.513243, 0.452145}, {0.537417, 0.476956}, {0.512882, 0.445679}, {0.482192, 0.437989}, {0.485275, 0.376608}, {0.414481, 0.366609}, {0.467655, 0.405425}, {0.473466, 0.435992}, {0.48116, 0.423669}, {0.449643, 0.404694}, {0.396158, 0.299226}, {0.398469, 0.322296}, {0.408017, 0.3521}, {0.411923, 0.370378}, {0.460129, 0.397543}, {0.5, 0.449468}, {0.554214, 0.491246}, {0.585858, 0.521091}, {0.555215, 0.518722}, {0.530318, 0.5}, {0.525912, 0.474361}, {0.521168, 0.48373}, {0.539598, 0.51476}, {0.550734, 0.524394}, {0.561306, 0.5}, {0.530819, 0.472995}, {0.54731, 0.498459}, {0.530974, 0.481783}, {0.50462, 0.452559}, {0.5, 0.450428}, {0.5, 0.468096}, {0.496447, 0.443477}, {0.448849, 0.420332}, {0.477947, 0.416612}, {0.461466, 0.420446}, {0.478457, 0.41897}, {0.448849, 0.416831}, {0.406936, 0.350384}, {0.36808, 0.337379}, {0.404271, 0.303766}, {0.434787, 0.398749}, {0.4728, 0.411665}, {0.457341, 0.400515}, {0.440786, 0.386057}, {0.431618, 0.38194}, {0.41475, 0.34133}, {0.485975, 0.41805}, {0.52609, 0.477612}, {0.514715, 0.472893}, {0.571056, 0.507194}, {0.591464, 0.532788}, {0.559057, 0.522819}, {0.563549, 0.523253}, {0.575025, 0.531975}, {0.570048, 0.523438}, {0.576198, 0.535001}, {0.584458, 0.532489}, {0.562772, 0.509735}, {0.528433, 0.482579}, {0.513763, 0.467369}, {0.479921, 0.420101}, {0.439694, 0.393244}, {0.41006, 0.360914}, {0.437712, 0.387859}, {0.465736, 0.432362}, {0.445326, 0.411065}, {0.411851, 0.379001}, {0.491688, 0.424814}, {0.541956, 0.511289}, {0.553822, 0.512043}, {0.562961, 0.510578}, {0.578743, 0.542927}, {0.603044, 0.565705}, {0.550053, 0.531351}, {0.607392, 0.567027}, {0.563995, 0.527653}, {0.548279, 0.516061}, {0.565666, 0.529113}, {0.59398, 0.551625}, {0.587595, 0.5463}, {0.593816, 0.553707}, {0.521049, 0.483625}, {0.50681, 0.477546}, {0.476556, 0.449412}, {0.555579, 0.507148}, {0.495762, 0.456237}, {0.532787, 0.5}, {0.562814, 0.517415}, {0.531749, 0.489375}, {0.533343, 0.496737}, {0.524842, 0.480797}, {0.468197, 0.443832}, {0.463854, 0.418362}, {0.439915, 0.410216}, {0.517997, 0.477252}, {0.527342, 0.478802}, {0.451168, 0.412878}, {0.521436, 0.451334}, {0.454679, 0.408051}, {0.471012, 0.433979}, {0.432099, 0.392419}, {0.466882, 0.409788}, {0.426035, 0.37981}, {0.460357, 0.408648}, {0.457598, 0.401578}, {0.463456, 0.425247}, {0.471177, 0.425722}, {0.497938, 0.450066}, {0.505945, 0.461523}, {0.508894, 0.457166}, {0.477278, 0.425172}, {0.401211, 0.343873}, {0.377348, 0.350357}, {0.375063, 0.34419}, {0.404559, 0.349566}, {0.428276, 0.389575}, {0.451113, 0.401348}, {0.437179, 0.385405}, {0.443156, 0.397316}, {0.438625, 0.398008}, {0.424849, 0.397758}, {0.398646, 0.357983}, {0.465796, 0.404335}, {0.466667, 0.412934}, {0.471173, 0.409016}, {0.473544, 0.422862}, {0.536011, 0.478236}, {0.546619, 0.477378}, {0.558662, 0.506801}, {0.535721, 0.488182}, {0.549117, 0.5}, {0.509766, 0.470773}, {0.533915, 0.493958}, {0.532605, 0.493132}, {0.533682, 0.488185}, {0.520423, 0.471158}, {0.508225, 0.461668}, {0.476699, 0.433338}, {0.472922, 0.424689}, {0.481935, 0.425715}, {0.444193, 0.40694}, {0.474658, 0.437062}, {0.48904, 0.4367}, {0.5, 0.448846}, {0.51639, 0.468547}, {0.513885, 0.479094}, {0.48577, 0.444532}, {0.506392, 0.453751}, {0.535608, 0.483211}, {0.52218, 0.480553}, {0.514757, 0.441924}, {0.473528, 0.42601}, {0.458663, 0.401191}, {0.444875, 0.408989}, {0.424518, 0.374138}, {0.414156, 0.371224}, {0.41007, 0.376034}, {0.417356, 0.377583}, {0.389467, 0.339614}, {0.372998, 0.326826}, {0.399307, 0.350115}, {0.383355, 0.351344}, {0.362128, 0.336406}, {0.381101, 0.330422}, {0.362003, 0.323303}, {0.382241, 0.335195}, {0.378793, 0.326961}, {0.354334, 0.315329}, {0.391586, 0.353733}, {0.423968, 0.374796}, + {0.439933, 0.392055}, {0.428118, 0.396895}, {0.406171, 0.379928}, {0.403901, 0.376356}, {0.391983, 0.350311}, {0.357484, 0.332947}, {0.408336, 0.365395}, {0.384686, 0.344439}, {0.348313, 0.322706}, {0.35215, 0.329047}, {0.359218, 0.330931}, {0.375122, 0.347425}, {0.381755, 0.35367}, {0.3882, 0.359328}, {0.392119, 0.360099}, {0.351049, 0.317302}, {0.378325, 0.346213}, {0.376707, 0.344458}, {0.364739, 0.331523}, {0.405194, 0.371285}, {0.435415, 0.386427}, {0.429817, 0.391981}, {0.4286, 0.401051}, {0.436755, 0.416479}, {0.460363, 0.430426}, {0.458917, 0.44065}, {0.462099, 0.42274}, {0.466779, 0.438371}, {0.453761, 0.433466}, {0.481936, 0.429156}, {0.41326, 0.381576}, {0.382519, 0.356257}, {0.405283, 0.371331}, {0.398507, 0.356723}, {0.3863, 0.342564}, {0.331846, 0.298576}, {0.296897, 0.269168}, {0.302766, 0.282435}, {0.322956, 0.294543}, {0.332361, 0.303391}, {0.338502, 0.30793}, {0.366723, 0.316163}, {0.341197, 0.307628}, {0.365074, 0.31421}, {0.367462, 0.346744}, {0.387038, 0.354228}, {0.388753, 0.354332}, {0.421167, 0.385666}, {0.392305, 0.363741}, {0.348527, 0.332883}, {0.38134, 0.357638}, {0.366726, 0.330057}, {0.414112, 0.36173}, {0.374717, 0.333589}, {0.383527, 0.34896}, {0.351766, 0.315107}, {0.326611, 0.300855}, {0.368765, 0.337734}, {0.435284, 0.377153}, {0.424327, 0.390868}, {0.411477, 0.392371}, {0.425382, 0.401389}, {0.444317, 0.421139}, {0.430862, 0.403761}, {0.425937, 0.391143}, {0.415304, 0.380243}, {0.404078, 0.369226}, {0.405785, 0.377867}, {0.402532, 0.377666}, {0.419837, 0.38219}, {0.391013, 0.363539}, {0.379324, 0.347091}, {0.400556, 0.36809}, {0.382105, 0.353837}, {0.356534, 0.330922}, {0.364724, 0.334948}, {0.336603, 0.318312}, {0.346061, 0.322993}, {0.328305, 0.306639}, {0.30112, 0.275183}, {0.344774, 0.289072}, {0.337495, 0.3033}, {0.387431, 0.334581}, {0.391413, 0.361605}, {0.383222, 0.343112}, {0.345448, 0.317626}, {0.349783, 0.324943}, {0.380459, 0.350108}, {0.43752, 0.405297}, {0.413833, 0.392457}, {0.416552, 0.389643}, {0.410516, 0.372189}, {0.405758, 0.374859}, {0.429145, 0.389792}, {0.413632, 0.390289}, {0.421632, 0.393214}, {0.402919, 0.381956}, {0.409227, 0.386128}, {0.408833, 0.386159}, {0.416777, 0.383717}, {0.441322, 0.407172}, {0.455662, 0.40031}, {0.414804, 0.376334}, {0.396411, 0.370953}, {0.386597, 0.363829}, {0.397108, 0.373488}, {0.379316, 0.351848}, {0.405907, 0.367845}, {0.422149, 0.400582}, {0.46337, 0.405575}, {0.477236, 0.446903}, {0.463717, 0.395636}, {0.470249, 0.410076}, {0.382448, 0.350085}, {0.40487, 0.354929}, {0.384047, 0.344275}, {0.39107, 0.349488}, {0.380933, 0.359558}, {0.367949, 0.329203}, {0.358978, 0.315842}, {0.35682, 0.326583}, {0.375113, 0.353001}, {0.441676, 0.384343}, {0.434164, 0.397523}, {0.399754, 0.36286}, {0.388533, 0.366603}, {0.385643, 0.34128}, {0.393773, 0.350061}, {0.362166, 0.318328}, {0.349316, 0.311217}, {0.361731, 0.337928}, {0.357642, 0.327618}, {0.352746, 0.333221}, {0.354494, 0.326434}, {0.415535, 0.391641}, {0.395101, 0.370306}, {0.41782, 0.380161}, {0.429772, 0.40857}, {0.408404, 0.344225}, {0.379046, 0.341267}, {0.423526, 0.385227}, {0.374532, 0.349566}, {0.424613, 0.370803}, {0.391794, 0.312267}, {0.357134, 0.332997}, {0.349411, 0.328959}, {0.372711, 0.352369}, {0.380316, 0.340696}, {0.348689, 0.331231}, {0.348981, 0.332686}, {0.353117, 0.309507}, {0.367484, 0.33914}, {0.359227, 0.32321}, {0.371637, 0.344}, {0.339349, 0.324826}, {0.378704, 0.349842}, {0.365484, 0.340171}, {0.378419, 0.352145}, {0.383336, 0.365752}, {0.373484, 0.337929}, {0.391316, 0.353708}, {0.346289, 0.313983}, {0.303555, 0.285542}, {0.338085, 0.309266}, {0.384005, 0.354291}, {0.357659, 0.327392}, {0.357077, 0.328499}, {0.328697, 0.315634}, {0.34347, 0.322113}, {0.352372, 0.329378}, {0.351207, 0.320451}, {0.310281, 0.284707}, {0.32695, 0.294922}, {0.358405, 0.334358}, {0.342011, 0.317141}, {0.336113, 0.315831}, {0.336264, 0.304761}, {0.341323, 0.31807}, {0.349865, 0.315803}, {0.363099, 0.34235}, {0.357595, 0.336709}, {0.343433, 0.320515}, {0.340577, 0.317947}, {0.38255, 0.351573}, {0.403996, 0.376425}, {0.430234, 0.402124}, {0.426145, 0.401481}, {0.409725, 0.385603}, {0.397694, 0.382369}, {0.420088, 0.396452}, {0.408851, 0.367419}, {0.437307, 0.387305}, {0.407431, 0.389139}, {0.408254, 0.369305}, {0.361126, 0.335523}, {0.392935, 0.369275}, {0.401646, 0.37431}, {0.360348, 0.334125}, {0.340268, 0.308834}, {0.319347, 0.292849}, {0.320507, 0.303296}, {0.397211, 0.32867}, {0.390523, 0.373138}, {0.355737, 0.338599}, {0.376042, 0.360275}, {0.348809, 0.333984}, {0.355691, 0.331683}, {0.331343, 0.313446}, {0.337904, 0.32359}, {0.317382, 0.298869}, {0.315057, 0.294053}, {0.334123, 0.312034}, {0.325711, 0.283479}, {0.32275, 0.285468}, {0.311332, 0.291454}, {0.314197, 0.289916}, {0.313002, 0.295027}, {0.315208, 0.285684}, {0.345688, 0.312304}, {0.312707, 0.294624}, {0.337791, 0.301375}, {0.291495, 0.273485}, {0.273879, 0.249743}, {0.304171, 0.282013}, {0.301835, 0.271962}, {0.255609, 0.234088}, {0.303422, 0.247669}, {0.311134, 0.274716}, {0.294321, 0.266311}, {0.281164, 0.245265}, {0.271301, 0.238259}, {0.283118, 0.256966}, {0.273623, 0.249963}, {0.291791, 0.271183}, {0.297906, 0.263196}, {0.27354, 0.195544}, + {0.206079, 0.176111}, {0.201774, 0.1749}, {0.220635, 0.185161}, {0.251254, 0.199919}, {0.251147, 0.204777}, {0.262351, 0.216577}, {0.265352, 0.210641}, {0.269882, 0.224899}, {0.264513, 0.217461}, {0.223183, 0.192277}, {0.23752, 0.207165}, {0.255893, 0.223292}, {0.266214, 0.224236}, {0.246546, 0.189946}, {0.259152, 0.220286}, {0.265652, 0.224646}, {0.239434, 0.212218}, {0.237762, 0.197158}, {0.249327, 0.208907}, {0.236548, 0.208333}, {0.240375, 0.210352}, {0.250753, 0.223428}, {0.304178, 0.269197}, {0.327537, 0.287903}, {0.309438, 0.264255}, {0.275493, 0.224626}, {0.298664, 0.258949}, {0.355045, 0.2949}, {0.350746, 0.286808}, {0.341884, 0.29473}, {0.334751, 0.285728}, {0.332185, 0.289519}, {0.343645, 0.312518}, {0.351592, 0.30524}, {0.337324, 0.296429}, {0.360622, 0.312931}, {0.362183, 0.319478}, {0.360212, 0.326796}, {0.38322, 0.322558}, {0.360697, 0.317028}, {0.393994, 0.349587}, {0.395278, 0.333393}, {0.39867, 0.370395}, {0.3941, 0.347129}, {0.379954, 0.347995}, {0.42587, 0.348991}, {0.396666, 0.359383}, {0.418047, 0.369612}, {0.42501, 0.381164}, {0.384888, 0.343438}, {0.403176, 0.358068}, {0.438434, 0.375347}, {0.458176, 0.396232}, {0.458643, 0.421139}, {0.477084, 0.441787}, {0.48879, 0.434186}, {0.45722, 0.419752}, {0.5, 0.432509}, {0.448858, 0.410363}, {0.44423, 0.409354}, {0.329631, 0.298312}, {0.393579, 0.348674}, {0.450944, 0.409175}, {0.460265, 0.411319}, {0.449899, 0.394016}, {0.440847, 0.389515}, {0.486991, 0.423626}, {0.386741, 0.354365}, {0.349645, 0.3013}, {0.336144, 0.292913}, {0.334128, 0.293523}, {0.362853, 0.315601}, {0.365986, 0.316974}, {0.324851, 0.277338}, {0.339969, 0.287233}, {0.32434, 0.289038}, {0.405842, 0.347656}, {0.397131, 0.352921}, {0.403751, 0.362736}, {0.414262, 0.36798}, {0.457925, 0.410901}, {0.457523, 0.393284}, {0.445127, 0.412973}, {0.479933, 0.441662}, {0.464732, 0.425524}, {0.473066, 0.434181}, {0.465982, 0.430234}, {0.438663, 0.411469}, {0.511922, 0.465882}, {0.507377, 0.464541}, {0.491891, 0.446521}, {0.464893, 0.431955}, {0.455475, 0.431999}, {0.477133, 0.432501}, {0.463561, 0.430764}, {0.444242, 0.409253}, {0.508224, 0.444935}, {0.459079, 0.406675}, {0.464876, 0.412109}, {0.5, 0.442208}, {0.42624, 0.3797}, {0.453364, 0.387713}, {0.554347, 0.506893}, {0.516931, 0.366094}, {0.325292, 0.280957}, {0.332211, 0.281671}, {0.361255, 0.305691}, {0.371081, 0.298444}, {0.411453, 0.361159}, {0.397299, 0.349609}, {0.536221, 0.436996}, {0.539465, 0.450811}, {0.52279, 0.441959}, {0.52346, 0.463914}, {0.476128, 0.428746}, {0.5, 0.446474}, {0.554242, 0.468908}, {0.524225, 0.47497}, {0.545477, 0.506003}, {0.508793, 0.46109}, {0.512603, 0.442446}, {0.446223, 0.387137}, {0.415409, 0.369858}, {0.402332, 0.356133}, {0.376569, 0.323295}, {0.414666, 0.362865}, {0.451221, 0.405703}, {0.427659, 0.385679}, {0.422402, 0.381762}, {0.49307, 0.424916}, {0.5, 0.430176}, {0.497292, 0.44605}, {0.510604, 0.460075}, {0.481788, 0.440188}, {0.540757, 0.5}, {0.569735, 0.521016}, {0.581469, 0.520133}, {0.542081, 0.5}, {0.525393, 0.465882}, {0.465252, 0.405357}, {0.430632, 0.369954}, {0.420841, 0.36898}, {0.394267, 0.343749}, {0.491403, 0.380049}, {0.458558, 0.40701}, {0.50471, 0.437059}, {0.418355, 0.351056}, {0.314424, 0.273044}, {0.323217, 0.283954}, {0.345545, 0.307427}, {0.336509, 0.310378}, {0.353675, 0.325969}, {0.402184, 0.364406}, {0.334804, 0.30148}, {0.318993, 0.2693}, {0.26432, 0.223441}, {0.300435, 0.258106}, {0.298828, 0.26217}, {0.29103, 0.230657}, {0.314008, 0.275174}, {0.299569, 0.261319}, {0.309137, 0.265467}, {0.268052, 0.229784}, {0.269611, 0.22126}, {0.265611, 0.226731}, {0.33939, 0.27097}, {0.373159, 0.315397}, {0.469763, 0.362051}, {0.323875, 0.276418}, {0.306322, 0.265147}, {0.31631, 0.275481}, {0.343333, 0.310194}, {0.350947, 0.295699}, {0.359183, 0.293387}, {0.240652, 0.200489}, {0.212831, 0.184937}, {0.217433, 0.180929}, {0.274426, 0.20293}, {0.450593, 0.349671}, {0.323484, 0.285302}, {0.358387, 0.307475}, {0.348032, 0.309112}, {0.408516, 0.358877}, {0.380529, 0.309694}, {0.335589, 0.301659}, {0.339662, 0.305391}, {0.420859, 0.364238}, {0.462259, 0.411233}, {0.433382, 0.39576}, {0.43205, 0.404657}, {0.417443, 0.383974}, {0.4618, 0.419481}, {0.4512, 0.406135}, {0.496862, 0.448459}, {0.4794, 0.434684}, {0.476366, 0.423936}, {0.523679, 0.496396}, {0.518323, 0.479408}, {0.569542, 0.536714}, {0.560895, 0.525082}, {0.58333, 0.554792}, {0.531016, 0.5}, {0.5, 0.469602}, {0.488376, 0.456864}, {0.490352, 0.460999}, {0.484926, 0.428856}, {0.432623, 0.382846}, {0.422468, 0.377685}, {0.411921, 0.375671}, {0.433518, 0.365809}, {0.450779, 0.404331}, {0.518024, 0.467458}, {0.544008, 0.491441}, {0.523881, 0.482802}, {0.518176, 0.448221}, {0.449139, 0.377163}, + {0.410306, 0.354878}, {0.427293, 0.343572}, {0.438553, 0.359458}, {0.423735, 0.37678}, {0.561294, 0.460299}, {0.579007, 0.506681}, {0.463899, 0.401581}, {0.457543, 0.431319}, {0.468719, 0.43008}, {0.461572, 0.421385}, {0.449861, 0.416535}, {0.464351, 0.426358}, {0.470693, 0.449993}, {0.4617, 0.435347}, {0.44938, 0.391794}, {0.372331, 0.353873}, {0.391467, 0.368627}, {0.443525, 0.386307}, {0.367662, 0.344003}, {0.38743, 0.354103}, {0.427425, 0.378725}, {0.470693, 0.449993}, {0.498714, 0.434733}, {0.408041, 0.378661}, {0.375075, 0.338597}, {0.340274, 0.317472}, {0.419198, 0.36145}, {0.424782, 0.382217}, {0.400864, 0.368948}, {0.412124, 0.372442}, {0.378299, 0.353816}, {0.421653, 0.375929}, {0.390756, 0.349207}, {0.394387, 0.358471}, {0.39118, 0.367244}, {0.404532, 0.381487}, {0.372963, 0.352406}, {0.362223, 0.344601}, {0.374446, 0.348757}, {0.339446, 0.319911}, {0.354147, 0.330823}, {0.385083, 0.363449}, {0.400992, 0.382852}, {0.396634, 0.359858}, {0.420527, 0.384631}, {0.436058, 0.400068}, {0.437442, 0.418827}, {0.44858, 0.424424}, {0.436125, 0.415013}, {0.414511, 0.353966}, {0.391431, 0.346318}, {0.406313, 0.379244}, {0.379, 0.362403}, {0.377282, 0.352548}, {0.390204, 0.360441}, {0.404863, 0.377645}, {0.381449, 0.358916}, {0.420795, 0.391385}, {0.425844, 0.377903}, {0.39337, 0.369056}, {0.365607, 0.34735}, {0.381351, 0.354964}, {0.39653, 0.373483}, {0.403945, 0.376852}, {0.37426, 0.346704}, {0.377605, 0.352549}, {0.401441, 0.380416}, {0.43197, 0.397407}, {0.449423, 0.42024}, {0.380057, 0.320463}, {0.342304, 0.313236}, {0.352678, 0.331054}, {0.352021, 0.328752}, {0.385981, 0.355744}, {0.384889, 0.358079}, {0.355514, 0.314907}, {0.32916, 0.300058}, {0.371445, 0.340978}, {0.36169, 0.338663}, {0.37317, 0.340857}, {0.429334, 0.380621}, {0.401412, 0.362418}, {0.406309, 0.375}, {0.394612, 0.369019}, {0.403163, 0.376387}, {0.40809, 0.385237}, {0.407223, 0.366998}, {0.389856, 0.360412}, {0.374511, 0.348876}, {0.380234, 0.35008}, {0.385296, 0.346294}, {0.402792, 0.366547}, {0.393403, 0.361719}, {0.356059, 0.342479}, {0.34356, 0.327832}, {0.347235, 0.318396}, {0.367534, 0.34146}, {0.366656, 0.330061}, {0.377822, 0.339634}, {0.374802, 0.344433}, {0.339345, 0.305846}, {0.326279, 0.297796}, {0.362546, 0.328062}, {0.375091, 0.32965}, {0.376532, 0.3404}, {0.350744, 0.326186}, {0.333963, 0.313042}, {0.334975, 0.294714}, {0.303997, 0.278726}, {0.32339, 0.296988}, {0.351025, 0.314959}, {0.358684, 0.328669}, {0.345589, 0.325563}, {0.333401, 0.301465}, {0.301106, 0.273575}, {0.325705, 0.291458}, {0.348558, 0.317605}, {0.355604, 0.324603}, {0.360552, 0.327334}, {0.365273, 0.334292}, {0.378787, 0.349655}, {0.397816, 0.366009}, {0.377084, 0.352879}, {0.359965, 0.323841}, {0.351956, 0.326742}, {0.377376, 0.344097}, {0.402213, 0.368635}, {0.369378, 0.348054}, {0.349949, 0.32618}, {0.346259, 0.320476}, {0.335359, 0.302984}, {0.33343, 0.296789}, {0.320907, 0.292838}, {0.313643, 0.282093}, {0.304472, 0.276561}, {0.306581, 0.273719}, {0.294287, 0.264781}, {0.335078, 0.280009}, {0.309059, 0.270794}, {0.279718, 0.243049}, {0.304645, 0.260978}, {0.320344, 0.273145}, {0.304614, 0.275376}, {0.289606, 0.252329}, {0.378392, 0.305631}, {0.411355, 0.349738}, {0.402237, 0.346534}, {0.414272, 0.346624}, {0.343194, 0.306066}, {0.313827, 0.281765}, {0.3634, 0.323487}, {0.37374, 0.293556}, {0.260839, 0.232617}, {0.282931, 0.223388}, {0.321369, 0.273874}, {0.285329, 0.240661}, {0.270081, 0.230829}, {0.30978, 0.274606}, {0.311315, 0.290323}, + {0.309747, 0.28242}, {0.313914, 0.292437}, {0.315989, 0.282129}, {0.304827, 0.278794}, {0.307625, 0.27433}, {0.311359, 0.283783}, {0.335017, 0.312224}, {0.306741, 0.286119}, {0.310367, 0.284093}, {0.292396, 0.265269}, {0.282308, 0.252321}, {0.297987, 0.276514}, {0.317903, 0.289344}, {0.309805, 0.286895}, {0.35005, 0.330835}, {0.374876, 0.349192}, {0.358338, 0.317917}, {0.352662, 0.327161}, {0.359261, 0.340806}, {0.358026, 0.335445}, {0.299169, 0.277943}, {0.307069, 0.288607}, {0.342923, 0.31882}, {0.343747, 0.320535}, {0.345743, 0.314692}, {0.34582, 0.326714}, {0.318625, 0.300804}, {0.348586, 0.319236}, {0.335061, 0.316152}, {0.341752, 0.314814}, {0.331122, 0.303136}, {0.322015, 0.297992}, {0.30513, 0.279094}, {0.316959, 0.293123}, {0.304063, 0.290638}, {0.3319, 0.304093}, {0.288296, 0.260203}, {0.273452, 0.250441}, {0.278403, 0.250578}, {0.252412, 0.238153}, {0.273176, 0.236124}, {0.285702, 0.253844}, {0.277639, 0.231261}, {0.255672, 0.223402}, {0.270101, 0.247061}, {0.29995, 0.274264}, {0.333946, 0.288382}, {0.339503, 0.296012}, {0.289597, 0.269704}, {0.291078, 0.272693}, {0.278939, 0.258974}, {0.289931, 0.259317}, {0.285215, 0.256622}, {0.285661, 0.262614}, {0.291808, 0.261178}, {0.260527, 0.24945}, {0.295121, 0.274564}, {0.314834, 0.282126}, {0.298653, 0.283376}, {0.351301, 0.306976}, {0.336744, 0.315169}, {0.34567, 0.31897}, {0.356768, 0.333439}, {0.385322, 0.35004}, {0.389827, 0.3715}, {0.347203, 0.320347}, {0.331715, 0.300008}, {0.331874, 0.296585}, {0.325093, 0.298973}, {0.337084, 0.314923}, {0.347656, 0.311837}, {0.336931, 0.317851}, {0.361815, 0.338244}, {0.393354, 0.376568}, {0.379606, 0.349234}, {0.373947, 0.352805}, {0.346732, 0.325068}, {0.349192, 0.327447}, {0.372031, 0.344453}, {0.336624, 0.314887}, {0.340819, 0.321453}, {0.36538, 0.344458}, {0.390871, 0.353138}, {0.381377, 0.357422}, {0.372267, 0.355734}, {0.379593, 0.358871}, {0.369977, 0.349584}, {0.377984, 0.34778}, {0.35996, 0.33088}, {0.335465, 0.308939}, {0.345463, 0.312104}, {0.362474, 0.337903}, {0.343924, 0.314074}, {0.334552, 0.310985}, {0.307632, 0.287358}, {0.342321, 0.30652}, {0.351397, 0.326275}, {0.320464, 0.288955}, {0.300281, 0.259319}, {0.267767, 0.24485}, {0.241184, 0.215653}, {0.208623, 0.175674}, {0.232154, 0.19426}, {0.250078, 0.211863}, {0.285402, 0.255957}, {0.32573, 0.272275}, {0.343154, 0.311464}, {0.313195, 0.278474}, {0.25943, 0.230673}, {0.272109, 0.229843}, {0.272929, 0.229996}, {0.256302, 0.233265}, {0.31576, 0.285405}, {0.286958, 0.251092}, {0.269264, 0.240381}, {0.289888, 0.258769}, {0.273923, 0.247824}, {0.29131, 0.255868}, {0.303636, 0.264365}, {0.284285, 0.253076}, {0.292206, 0.246367}, {0.330068, 0.301207}, {0.302541, 0.261771}, {0.329573, 0.304413}, {0.346732, 0.307831}, {0.328056, 0.284983}, {0.334311, 0.303223}, {0.342101, 0.309361}, {0.372145, 0.319525}, {0.379509, 0.345502}, {0.381733, 0.350427}, {0.358703, 0.315895}, {0.41631, 0.378223}, {0.358587, 0.324708}, {0.368735, 0.333209}, {0.345495, 0.312056}, + {0.345398, 0.291572}, {0.388359, 0.316634}, {0.362138, 0.319596}, {0.361871, 0.313065}, {0.301829, 0.260079}, {0.277208, 0.241614}, {0.341904, 0.307457}, {0.315899, 0.282777}, {0.373071, 0.335972}, {0.402279, 0.341604}, {0.378447, 0.334377}, {0.404927, 0.361421}, {0.420301, 0.372214}, {0.396269, 0.350277}, {0.359633, 0.305092}, {0.331355, 0.2799}, {0.410348, 0.338413}, {0.395268, 0.355992}, {0.419338, 0.378998}, {0.427499, 0.389264}, {0.433487, 0.400806}, {0.432302, 0.388496}, {0.442892, 0.404041}, {0.460297, 0.420368}, {0.414395, 0.378872}, {0.385933, 0.344406}, {0.373905, 0.325472}, {0.386961, 0.346639}, {0.418898, 0.378725}, {0.445012, 0.403088}, {0.482304, 0.452176}, {0.475122, 0.451526}, {0.458967, 0.427788}, {0.469966, 0.421973}, {0.436953, 0.405385}, {0.536859, 0.442941}, {0.539355, 0.489883}, {0.604257, 0.513721}, {0.532687, 0.490498}, {0.550657, 0.492771}, {0.542822, 0.515699}, {0.601641, 0.512542}, {0.533844, 0.495212}, {0.5, 0.465183}, {0.510916, 0.469105}, {0.552108, 0.504302}, {0.486205, 0.440625}, {0.491226, 0.451053}, {0.496974, 0.470696}, {0.508406, 0.441325} + }; + + double aaa[][] = setArra(); + + for (int i = 0; i < aaa.length; i++) { + qvvrStruct.harm_data[i] = (float) aaa[i][1]; + } + + for (int i = 0; i < harm_data.length; i++) { + qvvrStruct.harm_data[aaa.length + i] = (float) harm_data[i][1]; + } + } + + //模拟数据仅供测试使用 + void setPData(QvvrStruct qvvrStruct) { + double b[][] = new double[][]{{3.36, 3.52, 25, 195.9, 47.4, 19.2, 139, 419, 310.39, 562.2, 67.58, 0.11, 0.001, 119, 185, 651, 281, 55.7, 12.2, 81.9, 0.216}, {3.98, 3.38, 23.3, 101, 47, 22.4, 153, 360, 294.13, 568.54, 75.04, 0.11, 38.9, 161, 198, 631, 364, 48.8, 16.6, 109, 0.219}, {5.66, 3.29, 24.5, 60.3, 15.9, 18.2, 158, 657, 222, 616.44, 66.96, 0.1, 0.001, 138, 39.2, 657, 320, 55.3, 13.5, 140, 0.221}, {5.56, 5.22, 26.7, 88.8, 42.3, 19.7, 156, 385, 285.6, 589.97, 87.93, 0.1, 38.8, 174, 42.9, 635, 348, 70.5, 19.6, 113, 0.219}, {6.74, 5.45, 32.7, 62.4, 41.9, 34.6, 377, 347, 245, 572.7, 84.01, 0.1, 34.8, 148, 54.5, 667, 370, 59.9, 18.8, 95.4, 0.216}, {5.57, 1.75, 13, 67.9, 19.6, 24.8, 273, 621, 455, 527.43, 75.37, 0.1, 48.6, 152, 28.1, 666, 334, 80, 10.5, 310, 0.218}, {5.68, 4.42, 24.7, 157.2, 20.5, 40.9, 173, 674, 483, 452.18, 83.788, 0.1, 49, 102, 28.5, 621, 292, 58.8, 17.3, 177, 0.216}, {3.53, 1.02, 37.6, 128.2, 147, 29.4, 268, 382, 542, 372.19, 111.02, 0.1, 39.6, 122, 29.5, 629, 245, 62.3, 16.1, 141, 0.216}, {3.34, 4, 21.6, 117, 128, 33.9, 187, 607, 523, 458.18, 99.08, 0.1, 0.001, 109, 37.2, 682, 303, 83.3, 15.5, 951, 0.218}, {3.48, 3.48, 5.92, 69.7, 0, 22.3, 383, 92.6, 222, 524.03, 0.68, 0.1, 0.001, 95.8, 28.5, 607, 254, 64.5, 10.2, 0, 0}, {3.5, 1.9, 15.6, 55, 0, 38.8, 342, 747, 198, 572.03, 0.68, 0.1, 0.001, 21.6, 29.6, 638, 327, 63, 21.3, 0, 0}, {3.97, 2.15, 15.5, 110.6, 0, 39.2, 369, 763, 195, 485.896, 0.672, 0.1, 42.9, 20.7, 29.6, 631, 327, 68.2, 15.5, 0, 0}, {3.01, 2.31, 21.7, 92.2, 0, 93, 353, 393, 120, 512.884, 0.688, 0.1, 49.8, 18.3, 31.1, 586, 296, 63.2, 20.2, 0, 0}, {3.07, 2.07, 19.8, 50.38, 0, 132, 433, 712, 117, 589.864, 0.688, 0.1, 0.001, 18.4, 24.4, 622, 262, 49.9, 17.6, 0, 0}, {2.82, 2.19, 18.5, 130.5, 0, 97.2, 526, 688, 245, 394.819, 0.696, 0.1, 49.2, 19.8, 28.2, 634, 273, 48, 12.6, 0, 0}, {2.74, 3.01, 26.4, 141.7, 0, 68.2, 381, 654, 246, 559.877, 0.68, 0.1, 51.2, 25, 22.1, 578, 271, 46.8, 10.5, 0, 0}, {2.74, 3.97, 10.5, 156.4, 0, 61.6, 380, 631, 214, 557.941, 0.656, 0.1, 0.001, 27.6, 23.5, 538, 290, 43.2, 11.3, 0, 0}, + {2.88, 2.04, 26, 138.5, 0, 67.6, 520, 654, 208, 506.16, 0.632, 0.1, 0.001, 22.2, 20.9, 533, 302, 51.3, 7.25, 0, 0}, {2.83, 3.16, 25.7, 153.4, 0, 70.2, 476, 360, 186, 610.1, 0.568, 0.1, 0.001, 20, 22.2, 450, 322, 41, 7.67, 0, 0}, {2.74, 5.16, 22.1, 245.4, 0, 54.4, 194, 375, 47.8, 460.59, 0.504, 0.1, 0.001, 20.2, 15.4, 370, 298, 48.6, 4.53, 0, 0}, {2.74, 5.75, 17.4, 225.2, 0, 75, 492, 690, 156, 482.999, 0.64, 0.1, 0.001, 17.7, 16.9, 283, 232, 41.2, 6.03, 0, 0}, {2.89, 6.8, 21, 127.1, 0, 87.1, 184, 363, 203, 367.09, 0.584, 0.11, 0.001, 15.3, 15.5, 262, 239, 39.8, 4.09, 0, 0}, {2.84, 5.68, 20.8, 209.4, 0, 118, 532, 343, 176, 381.03, 0.56, 0.11, 29.3, 15.8, 13.5, 231, 223, 34.7, 6.25, 0, 0}, {2.71, 5.52, 21.3, 160.2, 0, 84.9, 241, 372, 178, 686.1, 0.52, 0.1, 23.6, 7.35, 10.2, 229, 246, 31.9, 4.18, 0, 0}, {2.77, 5.39, 28.2, 160.3, 0, 69.2, 237, 357, 118, 625.06, 0.52, 0.1, 19.3, 12.4, 11.4, 220, 245, 30.7, 7.22, 0, 0}, {2.75, 3.66, 20.8, 154.9, 0, 72.1, 257, 46.8, 192, 544.01, 0.52, 0.1, 0.001, 7.91, 9.55, 188, 219, 31.3, 5.48, 0, 0}, {2.81, 2.14, 23.9, 162.5, 0, 84, 438, 326, 19.6, 395, 0.52, 0.1, 14.5, 7.69, 7.96, 198, 209, 23.2, 6, 0, 0}, {2.71, 2.11, 24.6, 180.4, 0, 57.8, 461, 640, 148, 504.93, 0.512, 0.1, 19.1, 15.9, 8.39, 192, 222, 17.4, 3.56, 0, 0}, {2.77, 1.95, 25.3, 86.8, 0, 64.4, 334, 645, 173, 726.58, 0.864, 0.1, 0.001, 17.3, 7.55, 176, 175, 19.8, 4.51, 0, 0}, {2.71, 3.88, 23.7, 174, 0, 52.8, 112, 655, 209, 628, 0.504, 0.1, 13.7, 15.5, 10.9, 124, 219, 18.2, 7.05, 0, 0}, {2.8, 1.84, 24.9, 151.3, 0, 62.9, 581, 671, 175, 626.924, 0.48, 0.11, 0.001, 15.9, 7.73, 130, 216, 28, 4.13, 0, 0}, {2.75, 3.63, 24.2, 222.8, 0, 48.8, 600, 660, 183, 692.926, 0.448, 0.11, 13.3, 15.5, 9.99, 120, 190, 21.4, 4.16, 0, 0}, {2.71, 1.77, 23.4, 159.4, 0, 97.5, 582, 616, 92.2, 704.971, 0.424, 0.1, 0.001, 15.1, 7.29, 129, 263, 23.4, 4.11, 0, 0}, + {2.65, 1.71, 29.1, 158.5, 0, 132, 459, 612, 86.9, 668.53, 0.76, 0.1, 0.001, 15.8, 7.52, 137, 216, 20.2, 3.42, 0, 0}, {2.65, 1.69, 21, 150.5, 0, 89, 215, 323, 193, 666.911, 0.392, 0.1, 0.001, 16.5, 8.67, 130, 206, 19.7, 4.29, 0, 0}, {2.81, 1.76, 27, 155.6, 0, 77.1, 350, 320, 176, 701.04, 0.392, 0.11, 9.95, 15.8, 8.36, 144, 217, 24.3, 3.98, 0, 0}, {2.66, 1.85, 15.8, 165.1, 0, 65.4, 648, 328, 187, 346.07, 0.384, 0.11, 10.4, 16, 6.98, 158, 211, 24, 4.46, 0, 0}, {2.66, 1.88, 17.6, 158.9, 0, 70.3, 646, 321, 211, 489.61, 0.384, 0.11, 0.001, 14, 7.33, 128, 192, 29.2, 3.76, 0, 0}, {2.66, 3.74, 20.4, 152.8, 0, 309, 555, 40.6, 237, 428.998, 0.376, 0.11, 13.1, 17.2, 6.6, 127, 164, 32.3, 4.43, 0, 0}, {2.71, 1.83, 16.8, 159.3, 0, 283, 526, 29, 160, 513.05, 0.728, 0.11, 16.6, 16.6, 7.18, 108, 204, 17.9, 4.33, 0, 0}, {2.75, 1.69, 20.8, 220.5, 0, 274, 321, 4.79, 194, 529.03, 0.368, 0.11, 0.001, 14.7, 6.18, 99.3, 155, 21.9, 4.44, 0, 0}, {2.66, 3.23, 20.6, 128.5, 0, 68.8, 550, 3.22, 230, 595.67, 0.368, 0.11, 15.1, 13.7, 6.76, 111, 170, 21.9, 5.97, 0, 0}, {2.72, 1.92, 21, 123.2, 0, 30, 573, 3.21, 218, 730.988, 0.368, 0.11, 14.2, 13.9, 6.56, 117, 189, 16.7, 3.95, 0, 0}, {2.66, 3.56, 20.6, 101.5, 0, 21.4, 336, 3.2, 205, 553.965, 0.376, 0.11, 0.001, 12.6, 5.53, 125, 203, 33.9, 4.35, 0, 0}, {4.3, 2.33, 17.2, 124, 0, 31, 495, 10.5, 169, 734.782, 0.368, 0.11, 0.001, 11.6, 7.24, 122, 193, 23.9, 4.03, 0, 0}, {8.54, 1.9, 20.2, 204, 0, 29.6, 198, 10.5, 141, 562.96, 0.72, 0.11, 14.7, 16.2, 5.18, 122, 195, 21.9, 5, 0, 0}, {4.57, 2.78, 17.2, 131.1, 0, 132, 386, 10.8, 97.2, 675.96, 0.368, 0.1, 0.001, 11.5, 5.98, 114, 222, 29.8, 3.84, 0, 0}, {5.86, 1.82, 20, 121.4, 0, 82, 467, 10.8, 174, 499.06, 0.36, 0.11, 9.87, 14.6, 5.01, 103, 203, 24.3, 3.18, 0, 0}, {2.99, 2.94, 17.7, 139.3, 0, 71.6, 224, 4.89, 230, 595.23, 0.36, 0.11, 0.001, 16.5, 7.73, 109, 192, 20, 3.99, 0, 0}, {3.13, 2.71, 16.8, 56.3, 0, 65.1, 171, 2.7, 241, 580.614, 0.36, 0.11, 10.9, 13.8, 7.24, 135, 214, 22.2, 5.77, 0, 0}, + {3.09, 1.69, 21.7, 25.83, 342, 61.9, 161, 2.16, 365, 418.603, 40.568, 0.11, 13.4, 16.7, 9.85, 135, 243, 26.6, 6.23, 961, 0.221}, {6.65, 1.79, 38.6, 56.3, 124, 64.9, 115, 2.29, 297.8, 441.9, 48.312, 0.1, 16.7, 18.8, 10.8, 184, 218, 30, 3.28, 519, 0.245}, {4.36, 3.48, 35, 42.8, 300, 60.2, 184, 20.9, 250, 355.46, 48.904, 0.09, 20.1, 17.4, 7.08, 246, 241, 29.7, 3.71, 251, 3.84}, {3.33, 5.66, 15.1, 74.9, 174, 50.5, 154, 60.3, 565, 544.3, 48.248, 0.09, 0.001, 22.6, 81.2, 245, 212, 22.8, 3.75, 201, 9.09}, {29, 3.72, 25.4, 131.1, 800, 47.7, 172, 99, 577, 756, 46.44, 0.09, 19.3, 101, 85, 233, 226, 44.4, 4.32, 250, 80.8}, {13.5, 3.04, 44.7, 171.4, 806, 56.8, 157, 263, 612, 583.4, 57.84, 0.08, 0.001, 95.1, 105, 239, 334, 44, 5.47, 241, 22.5}, {18.6, 2.13, 36.4, 169.3, 840, 49.4, 183, 245, 678, 845, 77.632, 0.08, 0.001, 154, 130, 253, 278, 54.2, 13.1, 247, 23.7}, {12.5, 1.81, 61.7, 247.2, 770, 49.9, 170, 29, 705, 608, 95.632, 0.08, 43.8, 181, 115, 267, 318, 47.8, 12.4, 307, 112}, {16.1, 0.932, 42.2, 229, 775, 56.2, 246, 262, 687, 669, 97.732, 0.08, 31.8, 142, 99.8, 308, 287, 71.4, 19.5, 468, 31.6}, {15, 2.74, 87, 252.9, 844, 137, 260, 290, 662, 706, 97.572, 0.08, 0.001, 135, 113, 353, 316, 54.5, 20.1, 322, 105}, {9.11, 4.78, 57.4, 195.9, 844, 42.4, 230, 278, 561, 584, 97.228, 0.08, 37.7, 139, 128, 395, 328, 50.7, 15.2, 252, 104}, {10.3, 1.54, 42.8, 229.5, 768, 52, 181, 71.7, 622, 527.6, 118.336, 0.08, 0.001, 164, 109, 400, 287, 61.8, 16.1, 399, 112}, {13.7, 1.63, 49.8, 240.5, 179, 50.7, 280, 250, 752, 780, 92.588, 0.08, 37.6, 146, 150, 391, 334, 56.9, 18.1, 452, 101}, {13.7, 2.8, 65.3, 227.3, 785, 41.9, 255, 253, 742, 684, 96.524, 0.08, 0.001, 155, 86.7, 462, 293, 55.2, 16.6, 198, 23.4}, {10.8, 2.79, 74.9, 210.4, 783, 37.2, 195, 254, 709, 689, 103.936, 0.08, 52, 134, 66.4, 470, 288, 50.2, 20.1, 235, 20.1}, {16.2, 4.69, 61.5, 199.7, 747, 40.3, 201, 265, 733, 786, 93.868, 0.08, 0.001, 177, 98.6, 515, 278, 63.3, 14.5, 327, 107}, + {14.8, 3.01, 52, 211.4, 116, 46.3, 176, 29.8, 475, 747, 113.15, 0.08, 40.2, 127, 112, 529, 263, 52.9, 17.1, 212, 107}, {8.48, 3.31, 84.8, 190.8, 777, 40.4, 219, 33.6, 421, 609, 103.624, 0.08, 48, 139, 131, 484, 331, 61.1, 18.1, 169, 102}, {10, 4.68, 67.5, 161.3, 777, 33.7, 178, 176, 456, 755, 96.196, 0.08, 0.002, 159, 144, 485, 336, 68.5, 15.8, 283, 85.5}, {5.81, 2.06, 44.5, 101.9, 706, 30.8, 240, 258, 327.1, 413.69, 116.544, 0.08, 39.3, 164, 125, 500, 333, 72, 16.7, 243, 23.2}, {5.51, 3.22, 29.2, 117, 94.8, 40.1, 239, 28.9, 223, 504.73, 92.312, 0.08, 44.8, 75.9, 137, 551, 253, 85.9, 16.5, 181, 0.616}, {5.73, 4.58, 15.4, 114.5, 110, 28.6, 198, 19.2, 93.8, 382.864, 68.28, 0.08, 48.7, 56.9, 228, 534, 319, 47.3, 12.9, 84.6, 0.14}, {6.47, 1.44, 5.23, 71.6, 58.5, 35.7, 133, 16.3, 188.2, 422.604, 69.82, 0.08, 0.001, 30.2, 143, 541, 301, 22.4, 10, 40.8, 0.142}, {3.19, 4.89, 15.4, 70.6, 749, 24.8, 98.3, 16.2, 160.7, 457.58, 87.52, 0.08, 0.001, 20.4, 25.2, 544, 281, 19.9, 7.33, 40.5, 0.14}, {3.1, 3.01, 27.6, 50.8, 720, 20.2, 75.7, 4.5, 221, 298.18, 83.68, 0.08, 29.6, 13.5, 19.9, 497, 271, 23.3, 9.85, 40.2, 0.14}, {5.23, 4.32, 22.3, 68.4, 691, 12.3, 98.5, 9.52, 228, 188.873, 56.38, 0.08, 26.7, 29.4, 18.8, 486, 282, 33.8, 6.75, 38.1, 4.72}, {3.67, 3.03, 30.6, 48.8, 102, 19.6, 141, 8.46, 137.8, 377.76, 73.18, 0.08, 0.002, 133, 11.7, 490, 274, 50.3, 8.22, 48.9, 5.5}, {6.02, 3.36, 46.9, 116.9, 729, 11.6, 163, 9.09, 263.2, 407.49, 108.872, 0.08, 19.5, 132, 15.3, 473, 335, 31.9, 7.29, 137, 97.6}, {5.96, 2.24, 62.3, 193.8, 661, 25.3, 94, 4.19, 383.8, 626, 89.956, 0.08, 0.001, 118, 79.9, 546, 334, 46.7, 13.5, 230, 119}, {32.1, 3.32, 44.5, 181.3, 732, 20.7, 125, 20.5, 390, 586, 89.4, 0.08, 0.001, 177, 113, 501, 320, 53.8, 8.1, 253, 114}, {6.14, 2.56, 80.9, 213.9, 736, 25.7, 158, 48.9, 465, 541, 118.608, 0.08, 28.6, 141, 95.2, 526, 284, 57.2, 11.4, 246, 97.1}, {13.2, 3.93, 90.3, 247, 733, 18.8, 146, 46.6, 407.3, 544, 84.008, 0.08, 48.2, 185, 117, 651, 326, 53.3, 11.6, 167, 103}, {9.51, 2.22, 82.6, 180.7, 630, 21.8, 72, 11.4, 376, 558, 86.736, 0.08, 0.001, 138, 178, 612, 261, 59.2, 11.3, 177, 20.6}, {6.89, 2.19, 83, 191.1, 79.4, 25.2, 145, 9.82, 341, 475, 94.328, 0.08, 56.1, 154, 132, 547, 356, 63.9, 11.3, 409, 18.5}, + {15.6, 5.74, 90.9, 176.1, 443, 37.5, 192, 41.5, 382, 461, 100.16, 0.08, 49.2, 159, 198, 542, 304, 47.9, 13.7, 416, 18.1}, {12.7, 4.17, 93.3, 143.6, 508, 22.1, 225, 29.4, 351.8, 629, 116.21, 0.08, 0.001, 142, 170, 572, 294, 51, 10.8, 159, 14.1}, {13.2, 2.64, 57.3, 201.3, 443, 17.2, 255, 7.96, 339.1, 531, 97.18, 0.08, 48.2, 264, 167, 543, 305, 57.2, 15.2, 348, 29.3}, {9.5, 3.1, 82.6, 179.2, 400, 33.2, 242, 19, 293.6, 544, 106.824, 0.08, 52.4, 129, 94.5, 602, 290, 51.4, 13.8, 111, 17.3}, {37.7, 7.47, 52.6, 123.8, 400, 21.6, 193, 14.2, 334.7, 582, 106.56, 0.08, 0.001, 183, 157, 611, 255, 53.8, 15.2, 111, 61.8}, {11.8, 2.25, 61.7, 145.2, 417, -313, 207, 30, 480, 402.7, 88.14, 0.08, 46.4, 153, 132, 504, 274, 61, 14.5, 116, 80.3}, {12.7, 2.24, 83.5, 123.5, 410, -326, 252, 43.8, 505, 545, 119.608, 0.08, 0.001, 156, 165, 574, 247, 61.6, 17.6, 139, 21.9}, {8.88, 3.81, 52.9, 149, 406, 270, 199, 53.8, 557, 557, 86.984, 0.08, 58.2, 144, 174, 601, 295, 73.5, 19.1, 165, 16.1}, {18.2, 1.88, 59, 181.3, 50.5, 173, 203, 32, 468.6, 629, 85.14, 0.08, 61.2, 169, 215, 629, 241, 73.5, 13.3, 213, 85.8}, {10.2, 2.7, 47.6, 127.1, 35.9, 226, 146, 37.5, 405.5, 577, 75.364, 0.09, 53.1, 110, 197, 595, 230, 72.4, 15.1, 148, 80.4}, {6.53, 3.17, 37.9, 140.3, 85.3, 168, 187, 126, 246.8, 725, 76.688, 0.09, 49, 134, 179, 609, 325, 65.7, 11.7, 126, 14}, {9.92, 3.55, 55, 123.4, 88, 115, 206, 97.8, 239.84, 763, 77.944, 0.1, 0.001, 186, 152, 646, 270, 58, 11.9, 159, 0.151}, {5.39, 2.54, 39.8, 109, 76.3, 113, 133, 105, 318.59, 675, 77.952, 0.11, 58.2, 145, 107, 684, 249, 53.2, 9.08, 159, 0.149}, {10.5, 4.69, 32, 93.5, 69, 93, 101, 509, 269.6, 452.8, 74.344, 2.64, 0.001, 150, 113, 662, 273, 51.8, 8.26, 105, 0.152}, {9.39, 5.26, 29.4, 89.2, 73.4, 143, 88.5, 525, 213.6, 499.59, 96.236, 0.1, 38.3, 123, 94.5, 607, 294, 63, 7.27, 79.5, 0.151}, + {7.48, 3.23, 30.8, 65.7, 74.8, 131, 127, 521, 127.57, 545.65, 91.788, 0.1, 34.6, 143, 93.7, 797, 300, 57.8, 9.13, 70.2, 0.15}, {11.2, 2.29, 33.7, 116.9, 51.6, 101, 327, 793, 150.58, 553.68, 78.236, 0.1, 34.5, 102, 62.2, 632, 333, 67, 11.9, 88.5, 0.152}, {9.55, 2.32, 14.3, 106.4, 68.9, 82, 472, 721, 229.57, 532.87, 96.236, 0.1, 44.8, 124, 32.7, 683, 368, 55, 10.6, 107, 0.148}, {28.7, 1.17, 31, 114.7, 63.2, 81, 548, 727, 238.56, 487.34, 93.752, 0.1, 42.5, 98.9, 33, 751, 312, 53.6, 7.76, 164, 0.152}, {29.8, 1.64, 24, 133.4, 74.8, 134, 514, 826, 214.57, 370.3, 82.644, 0.1, 40.1, 111, 34.7, 651, 329, 68.6, 10.7, 148, 0.15}, {22.7, 1.15, 24.2, 87.1, 62, 112, 361, 752, 209.58, 391.28, 132.1, 0.1, 0.001, 172, 25.3, 681, 335, 71.4, 11.1, 1170, 0.152}, {36.1, 1.72, 26.5, 100.9, 0, 146, 387, 800, 160, 352.14, 0.632, 0.1, 36.5, 139, 27.3, 697, 300, 59.5, 8.55, 0, 0}, {14.4, 3.52, 22.8, 145, 0, 109, 217, 714, 159, 482.1, 0.752, 0.1, 34, 29.6, 25.8, 728, 318, 70.2, 8.49, 0, 0}, {12, 4.84, 26.6, 157.4, 0, 142, 557, 727, 128, 262.27, 0.536, 0.1, 36.5, 27.4, 23.8, 671, 319, 67.8, 8.66, 0, 0}, {11.9, 1.74, 27.8, 146.9, 0, 151, 429, 519, 220, 552.22, 0.488, 0.1, 38.3, 25.1, 28, 683, 337, 54.2, 9.2, 0, 0}, {10.5, 0.516, 10.9, 146, 0, 171, 188, 518, 262, 469.27, 0.472, 0.1, 0.001, 25.2, 30, 651, 368, 55.6, 9.84, 0, 0}, {13.7, 2.42, 20.6, 195, 0, 152, 406, 500, 216, 550.68, 0.464, 0.1, 0.002, 25.2, 23.3, 624, 318, 42.6, 10.3, 0, 0}, {3.77, 3.79, 10.5, 173.6, 0, 112, 477, 770, 179, 550.47, 0.44, 0.1, 43.1, 22.2, 25.4, 617, 334, 44.8, 6.39, 0, 0}, {5.48, 2.18, 28.2, 133.6, 0, 142, 538, 789, 168, 478.03, 0.44, 0.1, 40.1, 20.4, 22.1, 563, 358, 55, 4.5, 0, 0}, {3.82, 5.28, 25.9, 142.3, 0, 225, 230, 755, 123, 563.07, 0.432, 0.1, 0.002, 15.6, 14.2, 574, 337, 62, 4.25, 0, 0}, {3.63, 5.36, 15.1, 142.3, 0, 90.8, 376, 716, 204, 609.949, 0.432, 0.11, 0.001, 14.3, 13.9, 489, 215, 39.9, 3.17, 0, 0}, + {3.64, 3.51, 17.7, 122.8, 0, 89, 386, 736, 181, 636.897, 0.424, 0.1, 0.001, 13.4, 16.5, 444, 186, 36.2, 5.37, 0, 0}, {4.64, 2.99, 22.8, 168.4, 0, 134, 528, 713, 201, 635.898, 0.464, 0.1, 0.001, 15, 11.9, 315, 297, 43, 6.47, 0, 0}, {4.53, 1.94, 24.8, 118.6, 0, 123, 250, 762, 122, 598.03, 1.02, 0.11, 0.001, 14.2, 13, 299, 272, 26.6, 4.87, 0, 0}, {4.39, 4.7, 16.6, 188.1, 0, 128, 270, 766, 101, 594.961, 1.02, 0.1, 22.8, 12.1, 10.4, 255, 270, 26, 2.37, 0, 0}, {4.2, 4.14, 10, 144.6, 0, 78, 286, 447, 142, 486.01, 1.04, 0.11, 24.2, 14.3, 15.5, 216, 201, 27.5, 2.42, 0, 0}, {4.16, 1.96, 14, 129, 0, 82.8, 147, 59, 125, 375.961, 1.03, 0.1, 20.8, 12.7, 9.7, 292, 244, 26.7, 2.5, 0, 0}, {4.15, 3.62, 25.4, 110.8, 0, 68.3, 199, 373, 179, 441.994, 1.05, 0.1, 0.001, 7.52, 6.28, 229, 233, 23.3, 2.46, 0, 0}, {4.14, 1.94, 25.5, 197.6, 0, 71.6, 424, 777, 178, 489.942, 1.04, 0.1, 22.5, 12.4, 8.89, 189, 262, 24.7, 2.18, 0, 0}, {4.09, 1.78, 21.1, 178.2, 0, 60.7, 372, 723, 168, 742.858, 1.18, 0.1, 0.002, 6.95, 8.49, 193, 209, 17, 2.09, 0, 0}, {3.99, 1.65, 25, 244, 0, 64.1, 572, 734, 110, 673.858, 1.18, 0.11, 0.001, 12.6, 5.33, 192, 177, 20.5, 2.36, 0, 0}, {2.95, 1.71, 21, 179.5, 0, 57.4, 319, 735, 86.4, 554.979, 1.18, 0.11, 11.4, 12.4, 8.55, 181, 208, 29.8, 2.03, 0, 0}, {2.8, 1.71, 10.1, 182.4, 0, 80.1, 311, 748, 81.5, 646.926, 1.19, 0.1, 11.6, 13.6, 11.7, 176, 186, 29.5, 2.51, 0, 0}, {2.84, 1.71, 5.6, 172.5, 0, 233, 345, 688, 176, 680.46, 1.53, 0.11, 11.1, 12.2, 6.18, 184, 221, 15.7, 1.91, 0, 0}, {2.9, 3.34, 15.3, 108.9, 0, 228, 501, 339, 176, 644.85, 1.18, 0.1, 13.2, 11.8, 5.97, 190, 203, 24.2, 1.35, 0, 0}, {2.81, 1.72, 21.3, 102, 0, 228, 432, 348, 169, 634.89, 1.18, 0.11, 0.001, 13.3, 5.25, 168, 244, 23.6, 1.55, 0, 0}, {2.81, 1.79, 28.4, 180.3, 0, 120, 341, 706, 108, 475.855, 1.18, 0.11, 12.5, 16.3, 6.1, 133, 189, 19.8, 3.21, 0, 0}, + {2.87, 1.72, 22, 208.6, 0, 181, 450, 766, 108, 535.852, 1.52, 0.11, 10.9, 14.7, 5.6, 110, 181, 29.6, 1.45, 0, 0}, {2.93, 0.548, 21.5, 176.9, 0, 134, 399, 719, 123, 578.923, 1.18, 0.11, 0.001, 14.5, 6.29, 113, 157, 25.8, 1.29, 0, 0}, {2.76, 2.28, 14, 181.5, 0, 79.2, 554, 688, 177, 607.995, 1.18, 0.11, 11.1, 18.5, 4.95, 117, 198, 23.3, 1.3, 0, 0}, {2.77, 0.572, 23.2, 189, 0, 103, 545, 737, 180, 494.953, 1.18, 0.11, 0.001, 15.2, 5.42, 128, 185, 22, 1.5, 0, 0}, {2.83, 0.644, 20.4, 185.4, 0, 82.8, 508, 661, 162, 520.54, 1.18, 0.11, 9.11, 12.4, 5.11, 115, 201, 24.9, 3.27, 0, 0}, {2.87, 1.56, 20.5, 179.6, 0, 78.4, 156, 729, 184, 492.807, 1.18, 0.11, 0.001, 14.5, 4.62, 102, 192, 25.3, 1.82, 0, 0}, {4.54, 0.608, 22.1, 238.7, 0, 114, 359, 682, 108, 675.789, 1.19, 0.11, 14.8, 14.3, 4.59, 120, 197, 25.4, 1.31, 0, 0}, {4.51, 1.69, 17.8, 174.9, 0, 117, 581, 332, 225, 620.814, 1.19, 0.11, 0.001, 17, 5.01, 113, 183, 17.1, 1.93, 0, 0}, {4.51, 1.84, 21.4, 218, 0, 57.6, 485, 425, 218, 542.28, 1.2, 0.11, 16.4, 14.4, 5.5, 127, 210, 19.3, 1.95, 0, 0}, {5.08, 1.85, 21.8, 239.7, 0, 140, 331, 424, 208, 615.662, 1.19, 0.11, 15.2, 13.1, 5.81, 135, 192, 30.3, 1.9, 0, 0}, {5.72, 1.78, 17.6, 202.8, 0, 87.6, 278, 434, 184, 368.653, 1.19, 0.11, 14.3, 16, 7.66, 128, 181, 31.4, 1.72, 0, 0}, {7.62, 1.75, 21.2, 176.5, 0, 89.6, 308, 436, 125, 511.83, 1.2, 0.11, 0.001, 16.8, 8.13, 115, 183, 25.8, 1.73, 0, 0}, {4.56, 1.72, 24, 234.5, 0, 86, 385, 31.3, 101, 600.85, 1.56, 0.11, 0.002, 11.5, 11.2, 127, 198, 24.4, 1.88, 0, 0}, {3.14, 1.72, 14.7, 241.4, 0, 79.2, 262, 25.3, 157, 396.96, 1.22, 0.11, 10.8, 20, 5.18, 116, 203, 17.9, 1.92, 0, 0}, {3.23, 1.65, 9.13, 122.8, 0, 104, 186, 26, 210, 421.654, 1.22, 0.11, 0.001, 19.4, 8.46, 121, 201, 17.8, 1.9, 0, 0}, {5.3, 1.74, 24.9, 203.8, 266, 83.8, 162, 25.4, 235.36, 466.559, 54.876, 0.11, 0.001, 20.3, 9.73, 113, 152, 24.8, 1.79, 1650, 0.152}, {2.98, 1.77, 21.7, 170.3, 122, 57.2, 159, 94, 190.2, 410.638, 53.896, 0.1, 12.9, 16.5, 13.1, 256, 183, 24.8, 1.92, 531, 0.175}, {5.03, 3.23, 25.5, 116, 204, 88.1, 137, 70.3, 99.6, 543, 38.872, 0.09, 0.001, 16.1, 9.38, 258, 243, 23.1, 1.37, 154, 4.27}, {30.4, 3.76, 18.2, 42.3, 178, 65.2, 169, 50.8, 147.9, 420.53, 90.92, 0.09, 0.001, 30.9, 33.2, 323, 185, 31.1, 1.35, 124, 73.4}, {7.67, 2.24, 26.7, 92.4, 757, 54.8, 189, 193, 309.3, 653, 73.18, 0.09, 19.7, 165, 25.2, 344, 233, 47.4, 1.73, 198, 86.9}, {27.3, 5.92, 59.9, 104.8, 684, 44.1, 195, 65, 363.5, 641, 77.04, 0.09, 20.5, 196, 176, 318, 256, 45.7, 2.69, 243, 81.9}, {21.9, 2.34, 67.6, 132.6, 698, 55.3, 193, 274, 323.9, 686, 77.32, 0.08, 0.001, 143, 184, 306, 382, 61.2, 7.52, 179, 80.3}, {19.7, 3.31, 42.2, 212.9, 115, 59, 165, 277, 320.6, 535.1, 85.06, 0.08, 0.001, 155, 171, 349, 330, 67.6, 10.1, 126, 78.2}, {15.7, 6.14, 54.9, 347, 104, 74.4, 223, 286, 395.9, 640, 112.8, 0.08, 0.002, 168, 163, 338, 376, 57, 10.1, 311, 23.2}, {22.5, 6.71, 40.6, 296.8, 688, 56.5, 173, 257, 366.4, 601, 105.95, 0.08, 43.1, 177, 186, 399, 373, 57.7, 11.9, 538, 12.8}, + {18.3, 4.57, 65, 346.6, 741, 44, 214, 263, 329.4, 591, 125.34, 0.08, 44.9, 162, 153, 435, 383, 66.8, 11.1, 538, 20.5}, {22.6, 2, 49, 245.9, 722, 40.3, 222, 48.1, 336, 665, 107.18, 0.08, 46.3, 193, 180, 461, 332, 65, 12.4, 241, 21.3}, {45.8, 0.984, 51.5, 157.8, 673, 29.5, 221, 55.5, 359, 714, 139.7, 0.08, 0.001, 147, 110, 447, 381, 52.7, 13.5, 265, 12.4}, {42.1, 1.07, 42.7, 203.5, 694, 37.1, 176, 48.3, 328.7, 516, 109.67, 0.08, 51.9, 163, 161, 503, 361, 48.4, 12.8, 328, 83.3}, {13.9, 1.06, 77.7, 156.5, 147, 42.4, 161, 277, 371.5, 619, 107.2, 0.08, 0.002, 163, 236, 552, 392, 61.4, 15.7, 321, 79.1}, {20.8, 2.73, 59.7, 228, 103, 36, 208, 277, 419.4, 636, 110.46, 0.08, 56.1, 124, 198, 578, 356, 56.3, 15.1, 493, 71.2}, {18.9, 2.07, 60.9, 228.7, 738, 48.9, 177, 284, 367, 675, 118.01, 0.08, 0.001, 221, 138, 620, 379, 49.8, 18.6, 305, 75.8}, {41.3, 3.28, 35.5, 154.7, 739, 46.8, 127, 239, 384.1, 630, 99.14, 0.08, 51.3, 159, 138, 569, 375, 59.1, 13.3, 340, 82.6}, {25.1, 2.5, 55.7, 167.8, 739, 44.1, 162, 265, 335.1, 631, 184.77, 0.08, 40.8, 172, 179, 551, 377, 66.7, 13.7, 340, 82.6}, {25.8, 1.15, 31.6, 167.8, 681, 52.8, 206, 268, 226.8, 369.963, 124.85, 0.08, 0.001, 211, 247, 540, 346, 68.5, 15.5, 395, 8.18}, {17, 1.39, 35.2, 137.9, 106, 55.6, 202, 255, 105.8, 332.06, 104.04, 0.08, 0.001, 49.5, 165, 517, 247, 76.8, 16.3, 197, 0.817}, {18, 2.87, 23.8, 96.9, 138, 32.4, 179, 15.9, 133.6, 396.06, 93.38, 0.08, 0.002, 22.9, 134, 520, 257, 61.3, 13.7, 139, 0.772}, {5.1, 4.44, 13.9, 83.4, 101, 41.1, 145, 9.49, 72.35, 368.535, 92.7, 0.08, 59.6, 23.2, 133, 521, 321, 38.2, 8.56, 85.8, 0.306}, {7.84, 2.75, 14.7, 49.3, 69.5, 11.9, 120, 9.54, 99.8, 337.553, 76.78, 0.08, 0.001, 19.6, 29.3, 523, 289, 18.6, 6.93, 150, 0.305}, {5.87, 1.2, 17.7, 50.8, 36, 20.9, 138, 9.54, 138.86, 410.551, 56.63, 0.08, 0.001, 29.8, 28, 534, 309, 36.7, 6.61, 176, 0.31}, {5.87, 2.58, 14.7, 76.9, 27.9, 11.7, 122, 9.5, 168.7, 346.37, 58.548, 0.08, 25, 51.4, 16.2, 559, 322, 24.8, 9.03, 63.9, 0.307}, {3.64, 1.09, 12.6, 50.1, 99.8, 19.1, 60, 47, 247.85, 344.01, 62.708, 0.08, 0.001, 121, 19.7, 572, 353, 42.5, 9.82, 112, 1.71}, {10.3, 0.932, 39.5, 82.2, 21, 18.4, 170, 263, 225.79, 371.89, 68.408, 0.08, 0.001, 162, 15.1, 508, 358, 34.9, 7.49, 96.6, 7.41}, {41, 2.94, 37.8, 181.9, 36.2, 28.4, 194, 257, 268.38, 437.5, 84.152, 0.08, 19, 188, 99.2, 607, 392, 57.9, 7.6, 255, 87.4}, {43.5, 0.948, 54.1, 194.6, 65.2, 26.9, 115, 272, 306.84, 602, 81.32, 0.08, 19.2, 121, 149, 524, 341, 47.3, 8.6, 292, 87.9}, {40.9, 1.18, 45.9, 179.1, 30.5, 16.7, 126, 271, 322.74, 565, 68.12, 0.08, 29.3, 130, 85.9, 505, 370, 52.7, 10.2, 325, 82.5}, {17, 0.98, 87, 231.8, 341, 34.6, 117, 267, 255.14, 642, 81.76, 0.08, 0.001, 180, 116, 527, 370, 59.6, 13.3, 153, 16}, {23.2, 1.15, 41.8, 183.9, 270, 30.1, 180, 270, 303.7, 518, 81.07, 0.08, 0.001, 204, 143, 571, 347, 63.8, 14.5, 457, 86}, {47, 1.05, 99.1, 194.3, 195, 25.1, 159, 291, 232.6, 544, 99.12, 0.08, 0.001, 169, 169, 554, 433, 65.9, 15.9, 360, 27}, + {23, 0.9, 54.1, 148.3, 172, 26.4, 154, 59.2, 289.38, 597, 82.31, 0.08, 47.3, 169, 150, 563, 391, 62.5, 12.4, 248, 84.2}, {18, 0.884, 55.2, 139.9, 433, 26.2, 98.5, 57.8, 284.08, 563, 109.32, 0.08, 49.8, 152, 203, 584, 394, 61.3, 14.9, 342, 96.8}, {21.9, 0.936, 72.8, 131.6, 725, 16.2, 220, 253, 337.56, 317.3, 81.21, 0.08, 0.001, 136, 191, 678, 341, 55.5, 11.6, 383, 94.2}, {40.4, 0.808, 61.5, 153.7, 552, -316, 227, 285, 280.96, 434.3, 82.21, 0.08, 0.001, 130, 150, 579, 361, 59.2, 15.4, 245, 84.9}, {51, 0.864, 45.5, 153.9, 644, 206, 243, 278, 240.84, 350.3, 83.17, 0.08, 0.001, 144, 91.5, 603, 405, 67.3, 14.9, 384, 15.9}, {16.5, 2.22, 86, 167.7, 566, 153, 282, 256, 401.44, 389.2, 83.94, 0.08, 0.002, 141, 163, 606, 343, 57.6, 12.4, 380, 83.3}, {50.6, 1.36, 39.8, 139.6, 517, 100, 266, 263, 431.59, 284.7, 77.32, 0.08, 52.8, 185, 111, 543, 360, 69.5, 21.1, 447, 92}, {26.8, 2.21, 54.7, 179.8, 589, 96.8, 274, 336, 459.82, 615, 82.33, 0.08, 0.001, 163, 173, 606, 346, 64.9, 12.2, 465, 91.6}, {13.8, 2.31, 67.6, 191.7, 531, 78.8, 220, 377, 442.66, 536, 98.17, 0.08, 64.8, 212, 168, 634, 300, 69.1, 13.8, 450, 93.1}, {9.53, 1.26, 28.5, 157.9, 568, 57.3, 277, 626, 362.1, 375.6, 62.4, 0.09, 0.001, 172, 111, 616, 253, 82.6, 17, 221, 87.4}, {5.44, 2.74, 26, 114.4, 481, 71, 300, 96.2, 302.42, 804, 63.956, 0.09, 0.001, 174, 177, 658, 347, 72.4, 16.1, 136, 21.4}, {7.18, 5.32, 27.6, 191.6, 681, 50.8, 237, 101, 236.43, 766, 58.604, 0.1, 0.001, 156, 180, 806, 363, 44.9, 13.4, 135, 4.4}, {9.79, 3.01, 27.4, 78.5, 508, 103, 172, 511, 355.47, 856, 49.312, 0.1, 0.003, 132, 163, 729, 323, 63.2, 9.82, 254, 0.219}, {21.9, 1.65, 34.2, 104.2, 589, 55, 117, 435, 216.78, 459.73, 48.112, 0.1, 43, 225, 147, 677, 313, 77.6, 11.2, 126, 0.216}, {23.6, 1.49, 30.9, 48.5, 610, 90.7, 84.7, 485, 235.79, 622.05, 67.312, 0.1, 0.001, 112, 83.4, 767, 367, 45.6, 12.2, 140, 0.219}, {23.9, 2.94, 37.7, 56.3, 514, 56.6, 189, 454, 198.25, 573.99, 73.012, 0.1, 26.6, 160, 40.9, 721, 345, 52.9, 15, 128, 0.217}, {20, 1.35, 27.9, 62.4, 60.6, 76.5, 336, 438, 103.66, 483.78, 92.204, 0.1, 0.002, 112, 45.4, 668, 329, 58.5, 11.7, 57.9, 0.217}, {51.5, 5.07, 15.2, 60.5, 476, 85.2, 439, 461, 107.64, 414.04, 92.512, 0.1, 37.6, 134, 34.3, 738, 324, 54, 10.1, 131, 0.214}, {18, 1.6, 31.6, 64.8, 492, 76.7, 501, 412, 225.37, 513.14, 71.504, 0.1, 40.2, 132, 35.1, 679, 368, 60, 12.4, 556, 0.216}, {26, 2.7, 33.4, 72.4, 488, 72.4, 338, 475, 241.4, 486.93, 78.404, 0.1, 38.6, 96.4, 22.6, 711, 315, 49.7, 9, 180, 0.217}, + {24.5, 2.79, 29.9, 65.5, 775, 108, 399, 491, 250.5, 551.04, 46.696, 0.1, 38.2, 108, 27.5, 758, 331, 49.9, 9.02, 1730, 0.219}, {18, 4.42, 22.4, 66, 0, 65.9, 534, 58.1, 0, 480.06, 0.464, 0.1, 37.9, 97.9, 28.9, 684, 382, 54.9, 11.3, 0, 0}, {47.4, 4.48, 27, 65.3, 0, 68.4, 414, 59.3, 0, 494.83, 0.44, 0.1, 37, 29.7, 24.8, 732, 317, 55.5, 8.28, 0, 0}, {5.34, 4.47, 22.3, 81.4, 0, 43.7, 415, 432, 0, 487.35, 0.416, 0.1, 0.001, 27.1, 33.1, 698, 386, 72.7, 7.37, 0, 0}, {36.8, 4.93, 14.7, 84.4, 0, 64.6, 587, 465, 0, 521.16, 0.408, 0.11, 40.6, 25.4, 28.8, 722, 325, 42.9, 7.38, 0, 0}, {8.8, 5.68, 22.6, 174, 0, 32.6, 387, 510, 0, 531.81, 0.4, 0.1, 0.001, 38.3, 26.6, 704, 269, 40.5, 7.69, 0, 0}, {4.49, 2.6, 18.4, 157.8, 0, 104, 415, 499, 0, 520.861, 0.392, 0.1, 0.001, 50.4, 26.6, 748, 319, 42.4, 9.39, 0, 0}, {3.15, 3.98, 23.5, 183.5, 0, 104, 251, 478, 0, 547.902, 0.36, 0.1, 41.5, 22.5, 19.5, 688, 294, 40, 11.3, 0, 0}, {5.08, 3.83, 11.7, 180.7, 0, 100, 344, 464, 0, 616.853, 0.704, 0.1, 0.001, 16.5, 17, 660, 325, 25.7, 8.93, 0, 0}, {2.85, 4.04, 13, 190.2, 0, 76.2, 549, 440, 0, 620.838, 0.36, 0.1, 0.002, 15.3, 18.1, 523, 309, 28.2, 8.86, 0, 0}, {2.84, 2.05, 22.8, 179, 0, 81.5, 352, 445, 0, 349.855, 0.352, 0.1, 32, 23.2, 12.2, 478, 298, 30.7, 7.05, 0, 0}, {2.84, 2.51, 24.4, 284.7, 0, 62.1, 519, 48.4, 0, 419.837, 0.544, 0.1, 37.5, 16.7, 13.5, 447, 338, 22.1, 3.69, 0, 0}, {2.79, 3.39, 34.7, 231.6, 0, 171, 521, 42, 0, 503.911, 1.26, 0.1, 0.001, 19.6, 11.1, 345, 239, 21.3, 3.37, 0, 0}, {2.74, 3.2, 19, 204.7, 0, 109, 408, 50.3, 0, 503.932, 1.26, 0.1, 34.4, 20.6, 8.06, 264, 253, 23.5, 4.21, 0, 0}, + {2.84, 3.44, 18.4, 193.8, 0, 128, 329, 80.2, 297, 516.917, 1.26, 0.1, 22.9, 20.3, 7.43, 258, 232, 19.9, 5.05, 0, 0}, {2.75, 1.64, 18.1, 194.7, 0, 130, 210, 88.3, 186, 466.909, 1.26, 0.1, 24.7, 9.47, 12.4, 218, 260, 19.3, 7.01, 0, 0}, {2.8, 1.58, 22.5, 183.7, 0, 111, 153, 37, 69.3, 545.961, 1.26, 0.11, 25.5, 6.78, 7.68, 470, 257, 19.8, 6.17, 0, 0}, {2.71, 3.36, 12.9, 166.2, 0, 117, 460, 205, 75.9, 441.955, 1.58, 0.1, 0.002, 5.7, 8.45, 411, 230, 9.92, 6.06, 0, 0}, {2.8, 1.84, 28.9, 166.4, 0, 83, 393, 52.7, 57, 450.998, 1.26, 0.11, 14.9, 5.07, 8.45, 474, 189, 13.2, 4.36, 0, 0}, {2.72, 1.76, 26, 166.9, 0, 84.8, 576, 395, 51.1, 509.07, 1.26, 0.11, 23.6, 17.6, 8.55, 457, 242, 13.1, 4.39, 0, 0}, {2.77, 1.67, 25.7, 168.4, 0, 68.5, 505, 445, 88.5, 482.61, 1.27, 0.1, 0.001, 17.3, 7.46, 471, 296, 7.42, 2.47, 0, 0}, {2.71, 1.62, 25.2, 182.7, 0, 72.2, 393, 453, 125, 483.863, 1.28, 0.1, 16.6, 18.7, 5.05, 438, 195, 7.06, 5.4, 0, 0}, {2.81, 1.62, 24.9, 172, 0, 77.8, 285, 458, 183, 613.969, 1.27, 0.11, 14.5, 20.9, 4.8, 476, 219, 6.17, 2.23, 0, 0}, {2.71, 1.56, 22.9, 229.8, 0, 80.3, 331, 412, 247, 637.919, 1.69, 0.11, 0.001, 17.6, 6.06, 488, 268, 7.22, 2.23, 0, 0}, {4.89, 1.7, 18.5, 170.4, 0, 121, 586, 443, 240, 615.919, 1.69, 0.11, 12, 15.5, 4.54, 448, 235, 6.96, 3.5, 0, 0}, {2.71, 2.56, 13.3, 167.5, 0, 138, 318, 423, 233, 583.924, 1.7, 0.11, 11.5, 16.2, 5.33, 491, 232, 5.73, 1.63, 0, 0}, {2.8, 1.54, 25.2, 181.9, 0, 99.5, 512, 435, 276, 545.04, 2.06, 0.11, 9.97, 21, 4.59, 497, 204, 8.98, 1.64, 0, 0}, {2.7, 1.61, 25, 174.4, 0, 100, 377, 441, 272, 530.922, 1.7, 0.11, 12.2, 20.5, 6.19, 492, 260, 7.28, 1.55, 0, 0}, {2.75, 1.74, 20.9, 163.3, 0, 76.5, 327, 423, 288, 451.922, 1.7, 0.11, 12.2, 13, 5.82, 472, 239, 5.27, 1.45, 0, 0}, {2.71, 2.32, 34, 241.1, 0, 77.6, 389, 414, 261, 666.924, 2.06, 0.11, 0.002, 15.1, 4.45, 437, 206, 6.76, 3.2, 0, 0}, {2.81, 1.61, 21.6, 199.3, 0, 86, 396, 438, 265, 511.97, 1.71, 0.11, 0.001, 14.8, 6.54, 441, 203, 13.5, 1.59, 0, 0}, {2.72, 1.76, 18.2, 190.8, 0, 94, 349, 436, 282, 533.896, 1.72, 0.11, 9.96, 16.6, 4.48, 497, 250, 9.95, 1.4, 0, 0}, {2.75, 1.67, 16.7, 181.3, 0, 173, 249, 437, 327, 590.952, 1.73, 0.11, 0.001, 14.7, 4.86, 471, 249, 10.3, 3.24, 0, 0}, {4.31, 1.54, 9.65, 169.4, 0, 45.2, 178, 418, 273, 493.03, 1.7, 0.11, 0.001, 14.8, 7.35, 518, 236, 11.4, 3.17, 0, 0}, + {4.27, 1.54, 22.3, 102.8, 0, 32.3, 401, 431, 260, 524.795, 1.68, 0.11, 0.001, 16.1, 5.42, 489, 208, 13.4, 1.51, 0, 0}, {4.42, 1.62, 18, 208.4, 0, 37.7, 321, 426, 379, 445.75, 1.66, 0.11, 14.7, 14.2, 4.66, 509, 291, 7.94, 4.98, 0, 0}, {5.05, 2.16, 21.4, 191.2, 0, 149, 232, 443, 376, 377.98, 1.99, 0.11, 0.002, 12.6, 8.88, 462, 232, 8.25, 1.49, 0, 0}, {5.98, 1.61, 20.2, 192.9, 0, 205, 323, 412, 384, 545.57, 1.64, 0.11, 0.002, 13, 4.69, 443, 236, 7.79, 1.26, 0, 0}, {4.52, 2.28, 13.2, 231.4, 0, 103, 286, 461, 381, 395.01, 1.62, 0.11, 0.002, 16.3, 3.61, 445, 196, 9.6, 2.04, 0, 0}, {3, 1.72, 18, 217.6, 0, 124, 118, 442, 380, 442.97, 1.62, 0.11, 10.1, 11.2, 6.13, 506, 229, 9.56, 3.76, 0, 0}, {3.09, 1.56, 18.5, 208.4, 0, 112, 112, 441, 310, 561.74, 1.62, 0.11, 0.002, 15.2, 4.92, 524, 190, 17.9, 3.17, 0, 0}, {3.05, 2.11, 11.9, 115.8, 0, 119, 143, 438, 271, 513.618, 1.6, 0.11, 0.001, 16.2, 8.29, 522, 222, 12.5, 1.28, 0, 0}, {4.17, 1.62, 36.5, 204.4, 281, 132, 125, 18.5, 208.59, 327.589, 50.8, 0.11, 0.001, 18.8, 9.42, 564, 200, 9.53, 3.67, 757, 0.225}, {2.98, 1.55, 15.9, 131, 130, 94.4, 138, 10.9, 2.59, 342.82, 40.76, 0.11, 0.001, 21.3, 7.31, 543, 241, 11.4, 2.59, 272, 0.245}, {5.02, 3.06, 14.2, 38.5, 130, 59.7, 132, 35.8, 3.16, 438.505, 50.856, 0.09, 0.001, 23.8, 8.61, 539, 297, 12.6, 1.51, 171, 2.62}, {27.5, 3.38, 5.72, 51.3, 159, 96.5, 147, 58.1, 15.1, 448.69, 68.256, 0.09, 0.001, 32.5, 29.4, 597, 211, 15.7, 3.51, 168, 72.7}, {8.79, 3.14, 37.3, 88.9, 787, 94.5, 103, 103, 14, 620, 73.616, 0.09, 0.001, 80.6, 82.9, 621, 303, 26, 2.19, 136, 100}, {13.4, 1.55, 69.7, 142.3, 715, 47, 247, 64.4, 17.2, 633, 76.48, 0.08, 0.001, 104, 86.5, 559, 357, 28.2, 7.04, 67.2, 77.5}, {51.2, 3.6, 29.2, 160.8, 765, 32, 226, 269, 18.4, 671, 85, 0.08, 0.001, 171, 136, 630, 349, 40.2, 10, 67.2, 91}, {29.7, 5.56, 50.4, 318.8, 868, 30.5, 191, 248, 11, 641, 92.39, 0.08, 48.8, 157, 135, 621, 286, 43.4, 8.42, 180, 77.7}, {25.1, 4.52, 50.4, 239.8, 878, 61.2, 243, 295, 11.2, 685, 98.17, 0.08, 57.4, 141, 90.3, 314, 326, 43.2, 7.74, 262, 93}, {45.3, 2.65, 64.9, 203.3, 761, 51.6, 185, 287, 10.3, 571, 109.17, 0.08, 48, 112, 97.9, 402, 353, 34.6, 9.15, 479, 87.8}, {22, 2.42, 28, 184, 761, 58.5, 182, 302, 6.73, 739, 125.77, 0.08, 0.001, 129, 63.8, 300, 306, 38.2, 9.08, 181, 22.6}, + {47.7, 2.41, 53.7, 268, 770, 32.7, 179, 273, 12, 828, 111.88, 0.08, 43.6, 106, 113, 351, 382, 44.2, 10.5, 231, 104}, {22.8, 2.18, 48.8, 175.7, 791, 36.8, 91, 49.9, 17.7, 747, 100.52, 0.08, 0.001, 103, 93.3, 0, 357, 43.3, 16.4, 392, 94.5}, {19.9, 2.76, 63.9, 211.4, 807, 16.4, 86.9, 85.7, 11.6, 686, 109.22, 0.08, 58.4, 99.2, 108, 0, 357, 46.5, 11.9, 199, 90.6}, {23, 4.35, 40.8, 210.2, 822, 48.1, 96, 309, 13.9, 667, 129.22, 0.08, 0.001, 124, 63.4, 0, 343, 48.8, 19.2, 435, 95.1}, {42.9, 7.02, 54, 214.4, 740, 19.7, 126, 341, 12.8, 699, 113.22, 0.08, 60, 146, 122, 0, 352, 55.8, 14.9, 399, 31.9}, {32.5, 7.76, 30, 259.3, 729, 22.4, 112, 302, 11.9, 634, 94.156, 0.08, 0.001, 140, 130, 0, 361, 51.8, 23.1, 237, 90.9}, {26.6, 5.54, 56.4, 158, 772, 21.2, 113, 326, 2.34, 582, 109.19, 0.08, 0.002, 116, 115, 0, 346, 50.6, 18.4, 455, 80.4}, {51.6, 6.08, 55.9, 173.9, 772, 17.6, 165, 312, 2.34, 688, 136.17, 0.08, 63.5, 172, 114, 0, 319, 49.6, 21.8, 455, 105}, {23.7, 4.99, 57.8, 107.3, 475, 45.9, 138, 246, 2.31, 453.45, 115.34, 0.08, 59, 154, 106, 0, 327, 52.8, 25.2, 255, 8.05}, {26, 3.82, 26.7, 107.1, 102, 19.2, 181, 134, 2.37, 338.769, 105.448, 0.08, 0.001, 82.7, 72.9, 0, 299, 49.1, 16.7, 187, 1.29}, {5.65, 3.58, 31.9, 93.1, 88.7, 15.6, 326, 30.3, 2.42, 405.3, 81.456, 0.08, 0.001, 36.3, 98.3, 0, 290, 42.6, 8.47, 218, 0.205}, {8.12, 5.61, 9.09, 56.5, 88.7, 11.8, 93.7, 49.3, 2.41, 407.441, 79.01, 0.08, 0.001, 27.6, 95.7, 0, 258, 28.2, 4.9, 147, 0.202}, {8.23, 3.09, 8.89, 36.84, 745, 41.1, 326, 71.5, 2.4, 347.493, 68.556, 0.08, 54.1, 48, 28, 0, 211, 24.3, 3.78, 82.2, 0.194}, {4.16, 2.59, 13.3, 33.12, 763, 9.36, 97.4, 16.8, 2.42, 175.682, 81.65, 0.08, 32.9, 19.8, 16.9, 0, 336, 16, 2.94, 96, 0.205}, {4.18, 2.3, 21.3, 30.65, 745, 11.1, 323, 21.4, 2.37, 350.86, 87.01, 0.08, 22.1, 19.5, 18.1, 0, 319, 19.5, 6.62, 78, 0.202}, {4.12, 2.72, 29, 107.1, 735, 18.6, 331, 258, 2.33, 407.945, 86.96, 0.08, 25.1, 135, 14.2, 0, 301, 24.8, 4.91, 78, 2.92}, {12.8, 0.992, 48.6, 70.2, 669, 13.2, 331, 250, 2.29, 561.2, 80.44, 0.08, 17.3, 92.7, 18.6, 0, 342, 30.1, 4.75, 86.4, 18}, {42.9, 3.62, 34, 159.1, 769, 21.4, 401, 335, 2.27, 690, 78.448, 0.08, 0.001, 131, 86.2, 0, 357, 30, 8.44, 354, 90}, + {25.4, 3.81, 56.1, 260.7, 651, 25.7, 128, 309, 2.26, 654, 85.916, 0.08, 33, 175, 87.6, 0, 293, 30.9, 7.47, 290, 87}, {25.7, 2.96, 42.6, 226, 687, 36.3, 153, 297, 2.25, 599, 95.136, 0.08, 0.001, 132, 58.7, 0, 326, 37.5, 13.5, 330, 94.7}, {15.1, 4.02, 41.3, 212.7, 957, 25.2, 166, 284, 2.4, 635, 93.344, 0.08, 56.7, 151, 85, 0, 327, 45.9, 8.97, 380, 91.9}, {19.9, 3.92, 30.2, 245.5, 931, 22.8, 153, 322, 12.9, 660, 90.62, 0.08, 0.001, 164, 133, 0, 341, 45, 10.2, 192, 96.8}, {44.4, 2.14, 44.8, 157.5, 955, 18.7, 145, 87.2, 12.6, 675, 94.504, 0.08, 51.1, 172, 98.4, 0, 376, 44.6, 16.4, 268, 87.7}, {46.3, 3.69, 54, 193.6, 255, 46.4, 166, 304, 13.3, 631, 70.44, 0.08, 52.1, 185, 94.1, 0, 371, 42.2, 13.1, 201, 84.5}, {42.3, 1.85, 44.4, 132.5, 684, 25.3, 186, 276, 4.87, 629, 91.796, 0.08, 0.001, 125, 60.8, 0, 316, 49, 16.4, 174, 79.6}, {40, 1.95, 23.7, 132.9, 599, 155, 137, 259, 4.86, 578, 131.07, 0.08, 47.4, 150, 93.6, 0, 355, 49.3, 11.2, 378, 16}, {22, 2.07, 47.4, 146.2, 657, 120, 175, 259, 12.9, 678, 107.14, 0.08, 51.7, 116, 63.3, 0, 400, 50.2, 13.7, 107, 80.9}, {16.2, 3.52, 22.8, 116.1, 576, 98, 200, 268, 12.5, 665, 79.5, 0.08, 46.4, 126, 98.9, 0, 339, 56.5, 17.4, 378, 83.7}, {21.3, 3.39, 59.6, 170.9, 609, 93.6, 153, 258, 2.34, 865, 82.67, 0.08, 51.8, 131, 84, 0, 380, 53.9, 8.58, 512, 14}, {24.9, 4.12, 28.7, 152.7, 663, 65.6, 160, 59.1, 2.33, 825, 84.37, 0.09, 52.7, 182, 128, 0, 425, 44.3, 13.4, 321, 11.2}, {26.9, 2.61, 59, 159.3, 551, 113, 157, 20.1, 2.57, 625, 78.08, 0.09, 0.001, 154, 82.5, 0, 433, 46.2, 14, 172, 12.6}, {19.1, 4.32, 70.5, 184.6, 587, 87.5, 145, 260, 3.4, 622, 84.344, 0.09, 48.6, 68.2, 131, 0, 307, 51.3, 11.1, 102, 19.1}, {32.1, 5.88, 13.8, 133.7, 583, 51.1, 158, 269, 2.61, 872, 61.576, 0.09, 59.3, 51, 157, 0, 312, 58.9, 18.4, 131, 15.5}, {9.28, 4.91, 26, 112.3, 578, 64.6, 145, 28.1, 2.64, 784, 51.052, 0.09, 0.001, 60.6, 121, 0, 371, 53.9, 13.7, 78.3, 9.02}, {10.9, 6.35, 22.5, 98.6, 40.5, 43.3, 168, 28.8, 2.67, 869, 53.8, 0.11, 74.1, 42.6, 107, 0, 308, 50.3, 12.2, 114, 2.74}, {11.2, 2.26, 21.3, 91.6, 131, 65, 60.4, 437, 2.48, 886, 43.892, 0.11, 60.3, 39.8, 163, 0, 303, 41.2, 9.45, 70.8, 0.218}, {16.9, 4.02, 19, 74.3, 99.9, 80, 163, 453, 247.49, 506.9, 51.7, 0.1, 48.9, 56.8, 155, 660, 376, 37.4, 10.2, 93.6, 0.221}, {18.8, 2.34, 32.4, 71.5, 265, 60.6, 130, 415, 199.51, 600.96, 60.392, 0.11, 0.001, 40.8, 102, 617, 373, 34.6, 7.48, 64.5, 0.219}, {12.8, 2.43, 19.8, 75.9, 304, 81.6, 126, 434, 208.62, 642.55, 65.192, 0.1, 22.1, 36.7, 68, 630, 338, 23.8, 7.37, 84.6, 0.218}, {17.7, 2.31, 25.2, 93.6, 304, 51, 331, 743, 190.6, 466.35, 70.884, 0.11, 0.001, 35.7, 91.1, 638, 352, 29.6, 8.16, 69.9, 0.217}, + {19, 4.22, 9.46, 65.1, 424, 93.9, 450, 686, 137.59, 479.83, 62.508, 0.11, 0.001, 21.2, 24.5, 617, 366, 31.3, 9.22, 70.2, 0.218}, {33.8, 2.4, 21.3, 142.2, 71.6, 110, 277, 677, 203.59, 562.943, 81.084, 0.11, 28.6, 23.4, 34.1, 631, 285, 26.5, 8.53, 79.5, 0.219}, {30.6, 0.84, 9.24, 151.8, 372, 49.2, 482, 734, 222.59, 513.19, 101.38, 0.11, 0.001, 22.7, 28.1, 620, 309, 23.7, 6.23, 135, 0.217}, {17.3, 0.872, 17.5, 161.8, 555, 140, 529, 699, 282.58, 600.19, 93.42, 0.11, 40.3, 26.1, 21.3, 758, 295, 25, 7.55, 310, 0.216}, {10.9, 0.824, 21, 145.8, 0, 53.5, 456, 759, 278, 470.971, 0.384, 0.11, 0.001, 24.6, 26.6, 683, 320, 19.6, 6.08, 0, 0}, {28, 0.764, 10.7, 210, 0, 52.5, 212, 686, 163, 427.08, 0.376, 0.11, 0.001, 26.7, 19.4, 674, 317, 28.3, 9.28, 0, 0}, {5.5, 1.78, 26.1, 125.8, 0, 38.9, 345, 754, 129, 504.01, 0.384, 0.1, 39.4, 28.4, 19.2, 661, 344, 31.3, 6.85, 0, 0}, {8.45, 1.92, 10.1, 180.8, 0, 125, 363, 740, 83.6, 478.63, 0.376, 0.11, 0.001, 28.6, 18, 671, 284, 18.1, 6.86, 0, 0}, {7.63, 1.88, 25.6, 165.4, 0, 114, 369, 299, 209, 460.33, 0.384, 0.11, 33.6, 23.2, 19.1, 714, 317, 34.7, 5.12, 0, 0}, {7.47, 3.63, 9.61, 167, 0, 110, 457, 731, 200, 474.16, 0.384, 0.1, 39.8, 24.3, 16.4, 620, 293, 27.4, 5.24, 0, 0}, {6.68, 1.64, 24.8, 137.9, 0, 86, 415, 318, 171, 450.1, 0.392, 0.11, 0.001, 30.4, 14.9, 624, 265, 22.1, 6.28, 0, 0}, {3.75, 2.04, 16.5, 128.3, 0, 115, 335, 715, 162, 488.1, 0.72, 0.1, 41.8, 22.2, 13.4, 620, 335, 33.3, 4.12, 0, 0}, {3.64, 2.06, 20.9, 220.5, 0, 70.5, 469, 727, 96.7, 494.09, 1.04, 0.11, 41.6, 16.6, 16.1, 482, 291, 22.2, 2.91, 0, 0}, {3.68, 2.01, 5.08, 247.9, 0, 61.4, 484, 647, 63.5, 479.02, 1.05, 0.11, 40.9, 17.3, 13.6, 452, 257, 20.2, 3.89, 0, 0}, + {3.56, 1.91, 5.07, 244.3, 0, 82.5, 152, 776, 171, 491.892, 1.05, 0.11, 47.3, 18.4, 13.3, 431, 251, 17.9, 2.19, 0, 0}, {3.51, 2.76, 5.95, 197.9, 0, 97.9, 428, 744, 182, 516.96, 1.03, 0.11, 51.4, 16.7, 6.39, 305, 293, 13.5, 3.37, 0, 0}, {3.07, 4.2, 20.5, 203.8, 0, 96.5, 211, 593, 183, 426.937, 1.03, 0.11, 48.2, 19.4, 13.8, 314, 268, 13.8, 3.92, 0, 0}, {2.95, 3.39, 20.4, 194.9, 0, 80.4, 347, 439, 156, 493.888, 1.43, 0.11, 0.001, 15.1, 8.38, 255, 265, 12.5, 3.56, 0, 0}, {3.04, 1.73, 19.9, 113.5, 0, 69.7, 169, 35.8, 105, 432.48, 1.45, 0.11, 0.001, 9.22, 10.2, 224, 291, 14.7, 4.16, 0, 0}, {3.02, 1.56, 20.4, 194.3, 0, 70.6, 111, 27.9, 99.4, 592.888, 1.46, 0.11, 0.002, 7.4, 5.48, 189, 257, 14, 1.95, 0, 0}, {2.96, 1.62, 27.3, 207.1, 0, 63.6, 320, 449, 175, 484.935, 1.47, 0.11, 18.9, 11.2, 6.61, 174, 209, 15, 1.97, 0, 0}, {3.16, 1.69, 20.1, 242.8, 0, 60, 302, 440, 185, 582.958, 1.45, 0.11, 15.9, 4.73, 5.97, 175, 232, 9.53, 2.08, 0, 0}, {2.93, 1.7, 12.2, 187.4, 0, 49.6, 491, 714, 178, 521.885, 1.45, 0.11, 12.2, 7.9, 8.18, 173, 218, 8.46, 2, 0, 0}, {2.93, 1.76, 12.8, 216.6, 0, 56.2, 423, 709, 123, 427.883, 1.45, 0.11, 16.3, 20.2, 8.98, 152, 227, 5.28, 1.87, 0, 0}, {3.07, 1.68, 41, 197.1, 0, 92.1, 326, 727, 73.8, 571.93, 1.44, 0.11, 0.001, 17.1, 6.22, 156, 239, 8.53, 1.98, 0, 0}, {2.93, 3.66, 21.3, 186.6, 0, 118, 501, 712, 76.1, 613.881, 1.45, 0.11, 12.7, 17, 7.37, 141, 182, 4.63, 1.86, 0, 0}, {3.02, 2.08, 20.6, 186.3, 0, 101, 303, 731, 167, 501.948, 1.44, 0.11, 12.5, 15.9, 5.23, 145, 225, 6.2, 1.41, 0, 0}, {5.06, 1.66, 21.7, 204, 0, 66.9, 556, 475, 250, 469.923, 1.79, 0.11, 0.001, 18.6, 4.61, 90.9, 205, 6.37, 4.47, 0, 0}, {2.99, 2.48, 16.8, 223.9, 0, 68.5, 433, 335, 251, 445.01, 1.45, 0.11, 0.002, 17, 5.75, 84, 196, 14.3, 2.83, 0, 0}, {3.01, 2.49, 12.2, 179.2, 0, 79.9, 384, 705, 190, 441.89, 1.45, 0.11, 0.001, 13.7, 7.06, 94.2, 217, 7.29, 1.08, 0, 0}, {2.92, 3.24, 20.7, 180.8, 0, 67, 444, 713, 158, 563.889, 1.46, 0.11, 11.9, 16.2, 5.38, 101, 202, 6.69, 1.07, 0, 0}, {3, 1.78, 9.68, 197.8, 0, 224, 334, 446, 152, 503.888, 1.45, 0.11, 9.28, 15.9, 4.21, 98.4, 232, 4.81, 1.22, 0, 0}, {2.98, 1.64, 20.8, 105.5, 0, 162, 430, 426, 190, 531.853, 1.45, 0.11, 10.4, 16.1, 6.62, 110, 236, 8.05, 1.15, 0, 0}, {29.7, 1.61, 20.5, 107.2, 0, 94.6, 349, 482, 215, 431.804, 1.46, 0.11, 10.8, 12.8, 3.82, 111, 207, 8.46, 3.66, 0, 0}, {11.7, 1.61, 27.8, 183.8, 0, 66.5, 459, 57.4, 193, 489.869, 1.45, 0.11, 0.001, 13.7, 4.11, 121, 207, 9.14, 3.12, 0, 0}, {34.7, 1.55, 24.2, 183.6, 0, 49.4, 255, 84.6, 132, 469.801, 1.46, 0.11, 0.001, 14.1, 8.46, 115, 162, 9.07, 3.04, 0, 0}, {7.25, 3.36, 24.9, 200, 0, 50.4, 248, 439, 163, 637.847, 1.46, 0.11, 0.001, 15.6, 3.44, 112, 219, 9.52, 3.09, 0, 0}, {9.01, 1.71, 32, 178.9, 0, 168, 296, 432, 131, 646.797, 1.46, 0.11, 15, 14.3, 3.97, 121, 240, 9.5, 3.01, 0, 0}, + {9.42, 1.62, 11, 181.4, 0, 180, 290, 710, 191, 668.583, 1.47, 0.11, 12.8, 14.8, 4.61, 122, 202, 9.79, 0.955, 0, 0}, {8.65, 1.78, 28.2, 184, 0, 156, 295, 299, 173, 670.18, 1.47, 0.11, 0.001, 15.3, 4.7, 114, 200, 10, 1.18, 0, 0}, {14.4, 1.7, 21.4, 180.6, 0, 115, 413, 304, 166, 606.626, 1.47, 0.11, 13.7, 22, 5.81, 106, 198, 10.9, 1.07, 0, 0}, {9.83, 1.63, 24.1, 258, 0, 108, 277, 348, 45.7, 559.646, 1.47, 0.11, 0.001, 14.1, 7.24, 115, 202, 7.96, 2.81, 0, 0}, {8.18, 1.64, 22.7, 109.2, 0, 108, 166, 4.45, 26.1, 616.58, 1.47, 0.11, 0.001, 14.6, 5, 114, 172, 13, 1.61, 0, 0}, {13.7, 1.71, 26, 242.8, 0, 100, 130, 3.93, 127, 620.84, 1.5, 0.11, 0.001, 15.1, 5.39, 147, 247, 9.72, 5.05, 0, 0}, {15.5, 1.73, 16.9, 233, 0, 135, 197, 3.88, 189, 453.635, 1.46, 0.11, 0.001, 16.6, 4.56, 168, 204, 9.01, 1.26, 0, 0}, {38.1, 1.63, 10, 261.2, 113, 166, 201, 3.12, 197.58, 553.578, 34.8, 0.11, 0.001, 24, 5.71, 108, 279, 14, 2.36, 210, 0.224}, {10.6, 3.23, 17, 194, 151, 105, 80.8, 2.34, 271.57, 406.558, 39.044, 0.11, 0.001, 22.4, 7.97, 192, 213, 6.11, 2.18, 192, 0.222}, {32.7, 3.44, 7.43, 139.2, 187, 119, 104, 3.99, 160.56, 441.05, 46.844, 0.09, 0.002, 18.4, 8.5, 211, 214, 9.09, 2.16, 225, 1.76}, {13.5, 3.62, 6.01, 91.8, 329, 90, 118, 3.13, 218.58, 384.55, 44.05, 0.09, 0.001, 14.2, 60.3, 213, 211, 13.7, 2.79, 153, 1.19}, {8.87, 3.15, 10.6, 163.4, 796, 91.7, 124, 46.4, 189.6, 577, 61.536, 0.09, 0.001, 158, 120, 259, 247, 24.5, 4.12, 176, 7.73}, {10.7, 3.72, 24.8, 99.2, 712, 82.4, 67.9, 10.1, 221.5, 465.4, 62.736, 0.09, 24, 145, 135, 291, 388, 35.9, 2.19, 154, 10.3}, {33.9, 0.38, 28.7, 136, 776, 86.8, 117, 9.4, 231.3, 617, 98.428, 0.09, 27.8, 149, 96.8, 233, 298, 55.8, 6.77, 117, 19.5}, {41.5, 4.48, 25.3, 144.6, 827, 94.5, 186, 14.4, 322.2, 670, 92.764, 0.09, 0.001, 124, 85.4, 259, 368, 53.9, 9.29, 123, 18.7}, {48.7, 2.13, 11.3, 122, 733, 88.3, 240, 16.8, 318.9, 724.7, 79.528, 0.08, 0.001, 145, 111, 294, 356, 41.1, 9.96, 122, 18.1}, {20.6, 1.97, 42.8, 125.2, 823, 227, 239, 36, 304.8, 474.9, 79.236, 0.08, 0.001, 100, 134, 284, 332, 46.1, 11.1, 139, 13.9}, {39, 2.16, 69.5, 159.2, 840, 168, 171, 17.4, 281.8, 689, 83.04, 0.08, 48.1, 77.7, 149, 344, 300, 47.3, 17.6, 402, 13.9}, {24, 4.08, 43, 135, 811, 135, 220, 20, 379.4, 673, 92.088, 0.08, 0.001, 96.6, 140, 369, 341, 41.2, 13.2, 216, 12.9}, {16.9, 2.32, 24.9, 158.9, 774, 117, 183, 33.5, 352.2, 729, 80.088, 0.08, 56.1, 101, 139, 401, 382, 46.5, 13.3, 278, 10.9}, {51.4, 5.86, 45.6, 133.9, 149, 92.6, 260, 139, 294.4, 613, 86.98, 0.08, 52.2, 108, 58.2, 440, 396, 44.6, 17.1, 579, 11.7}, {26, 2.46, 44.9, 143.8, 147, 95.1, 192, 126, 262.6, 463.8, 78.588, 0.08, 59.6, 123, 153, 440, 396, 38.5, 17.1, 243, 16.6}, {26.2, 2.43, 53.3, 151.4, 760, 93.2, 178, 129, 286.45, 459.2, 86.688, 0.08, 68.2, 129, 98.7, 434, 335, 52.1, 20.4, 267, 8.96}, {24.5, 5.21, 34.7, 162.2, 761, 91.4, 235, 100, 282.9, 654, 93.588, 0.08, 63.2, 188, 105, 487, 317, 47.5, 14.8, 119, 13.7}, {28, 3.96, 59.6, 135.9, 811, 52.3, 212, 105, 291.52, 904, 61.788, 0.08, 0.001, 151, 51.2, 487, 343, 55, 13.9, 328, 10.4}, {27.6, 3.58, 68.3, 236.5, 750, 44.9, 154, 156, 255.61, 820, 61.788, 0.08, 0.001, 119, 102, 546, 323, 52.9, 14.6, 451, 11.1}, {26.1, 5.82, 39.2, 163.5, 149, 60.6, 204, 93.5, 147.2, 386.68, 76.424, 0.08, 61.8, 108, 40.5, 549, 316, 50.8, 19.1, 198, 14.8}, + {16, 3.18, 37.5, 127.4, 101, 51.6, 213, 94.9, 87.44, 398.516, 80.364, 0.08, 51.5, 42, 71.1, 526, 298, 60.6, 18.2, 127, 9.22}, {33.2, 6.24, 16, 103.5, 94.4, 135, 445, 68, 67.76, 419.696, 57.76, 0.08, 0.001, 30.5, 99.2, 443, 261, 37.4, 13.2, 92.4, 0.219}, {8.65, 4.13, 18.2, 82.3, 309, 63.6, 386, 68.8, 68.87, 338.88, 54.532, 0.08, 0.001, 15.3, 44.2, 475, 315, 24.4, 9.72, 87.6, 0.224}, {6.16, 6.28, 26.7, 43.7, 786, 67.2, 371, 70.1, 97.87, 329.77, 54.832, 0.08, 0.001, 8.57, 29.9, 466, 309, 15.8, 6.16, 48.6, 0.221}, {4.15, 4.9, 25.8, 55.4, 725, 52.8, 384, 97.5, 72.4, 328.645, 68.624, 0.08, 35.4, 13.4, 31.9, 453, 290, 21.6, 10.1, 89.1, 0.258}, {28, 2.18, 26, 60.8, 113, 42.2, 355, 67.9, 206.2, 421.779, 48.524, 0.08, 0.001, 27.7, 17.4, 454, 335, 17.6, 14.7, 70.5, 4.12}, {30.6, 6.94, 35.5, 77, 113, 39.7, 287, 19.5, 131.9, 490.43, 48.532, 0.08, 23.7, 93.6, 18.1, 458, 309, 22.9, 9.16, 63, 4.12}, {4.52, 3.27, 55, 55.3, 122, 45.2, 402, 115, 164.3, 490.88, 73.424, 0.08, 23.4, 168, 18.4, 495, 319, 21.3, 10.9, 87.9, 8.59}, {49, 3.68, 41, 133.3, 411, 39.6, 372, 140, 336, 820, 92.016, 0.08, 25.4, 154, 88, 524, 388, 26.4, 9.64, 110, 22.8}, {28.6, 4.24, 39.2, 131, 639, 41.3, 421, 44.9, 329, 638.5, 89.024, 0.08, 0.001, 112, 41.5, 537, 359, 33.8, 7.49, 126, 9.57}, + {31, 2.09, 44, 187.4, 126, 74.4, 408, 107, 394, 829, 80.624, 0.08, 30.6, 110, 46.8, 530, 314, 37.8, 10.1, 128, 16.6}, {46.9, 5.3, 57.9, 223.7, 352, 47.5, 225, 67.4, 406, 887, 77.624, 0.08, 0.001, 125, 60, 555, 352, 42.2, 7.13, 158, 42.1}, {20.3, 1.9, 55.7, 207, 302, 55, 206, 62.3, 413, 807, 78.224, 0.08, 0.001, 125, 91.7, 498, 351, 36.8, 6.93, 176, 16.6}, {20.7, 1.82, 98.3, 158.9, 266, 44.7, 169, 87.4, 393, 838, 74.024, 0.08, 50.9, 134, 92.2, 503, 361, 46.4, 10.8, 184, 17.2}, {16.2, 1.78, 53.5, 202.3, 504, 197, 229, 52.6, 397, 850, 75.524, 0.08, 0.001, 125, 97.4, 486, 384, 44.8, 10, 149, 13.3}, {12.9, 2.03, 44.3, 155.5, 556, 223, 196, 24.1, 385, 773, 61.124, 0.08, 0.001, 130, 187, 484, 336, 40.9, 10.1, 153, 16.1}, {11.3, 2.5, 63.9, 159.2, 586, 158, 295, 92.6, 402, 673.6, 80.04, 0.08, 46.7, 126, 147, 509, 349, 39.5, 8.75, 135, 11.9}, {20.8, 0.704, 51.8, 161.8, 426, 80, 268, 40.2, 372, 459.2, 91.44, 0.08, 45, 139, 114, 544, 386, 36.1, 9.98, 87.3, 13.8}, {32.2, 1.33, 20.8, 170.5, 591, 171, 202, 25.1, 420, 489.8, 91.416, 0.08, 0.001, 150, 120, 577, 301, 49.4, 13.4, 277, 14.5}, {45, 1.95, 57.1, 152, 494, 121, 209, 67, 502, 600.6, 72.56, 0.08, 47, 163, 150, 573, 357, 39.4, 13.9, 150, 11.6}, {21.2, 3.54, 34.6, 165.4, 571, 90.6, 233, 32.8, 467, 764, 94.116, 0.08, 0.001, 145, 153, 601, 295, 42.6, 12, 310, 5.79}, {19.7, 4.17, 34.8, 245.7, 507, 58.5, 190, 23.7, 499, 673, 73.424, 0.09, 44.6, 124, 115, 625, 340, 45.6, 12.3, 305, 15.2}, {47, 6.12, 83.8, 177.8, 602, 83.6, 194, 48.5, 448, 740, 66.272, 0.09, 52.8, 106, 68.4, 614, 310, 53.1, 11.8, 106, 9.53}, {20.2, 3.63, 20.3, 194.9, 485, 44.2, 218, 70.8, 392, 828, 65.372, 0.09, 0.001, 118, 102, 612, 292, 50.4, 10.9, 80.1, 7.99}, {4.48, 3.7, 14.3, 155.2, 94.9, 44.5, 266, 61.3, 262, 688, 48.916, 0.09, 43.7, 119, 116, 616, 332, 55.5, 17.8, 143, 4.74}, {5.49, 3.74, 23.9, 141.8, 57.9, 40.5, 191, 52.1, 271, 634, 47.428, 0.1, 52.3, 116, 78.2, 615, 309, 40, 13.9, 126, 5.25}, + {4.34, 2.01, 16.8, 158.2, 63.8, 37.7, 177, 470, 339, 808, 60.636, 0.1, 36, 150, 67.4, 672, 315, 47.7, 13.1, 58.5, 0.149}, {7.58, 3.48, 13.9, 92.6, 458, 40.5, 98.8, 395, 269.3, 554.78, 45.22, 0.1, 0.001, 138, 66.1, 636, 309, 30, 11.6, 69.9, 0.152}, {4.48, 1.89, 31.2, 79.7, 367, 55.5, 116, 562, 218, 539.67, 71.92, 0.1, 0.001, 176, 65.8, 618, 408, 27.8, 8.79, 57.3, 0.152}, {4.2, 3.56, 33.4, 66.3, 500, 57.5, 118, 757, 233, 534.21, 63.812, 0.1, 0.001, 128, 66.7, 655, 370, 47.4, 9.99, 82.2, 0.151}, {4.25, 1.95, 23.8, 115.9, 375, 71.5, 189, 664, 227.2, 509.09, 56.332, 0.11, 32.2, 112, 49.8, 671, 293, 46.9, 11.4, 65.7, 0.148}, {6.22, 1.77, 14.5, 84.5, 107, 253, 570, 757, 465.6, 524.37, 72.404, 0.11, 33.9, 133, 30.7, 662, 367, 43.7, 7.82, 67.2, 0.15}, {6.71, 1.78, 30, 96.7, 66.2, 105, 566, 733, 577, 481.43, 77.504, 0.11, 29.6, 168, 30.8, 663, 333, 41.2, 11.8, 498, 0.152}, {6.28, 2.18, 16.2, 87.8, 67.3, 88.5, 200, 767, 575, 509.74, 109.704, 0.11, 0.002, 152, 30, 679, 288, 39.2, 8.37, 143, 0.152}, {7.24, 2.14, 15.7, 121.2, 367, 79, 400, 791, 570, 552.39, 104.704, 0.11, 30.4, 124, 34.9, 654, 345, 41.4, 10.1, 639, 0.152}, {6.81, 2.21, 13.8, 93.3, 0, 64.2, 382, 482, 127, 642.28, 0.704, 0.11, 25.6, 94.9, 31, 696, 354, 45.8, 7.3, 0, 0}, {6.23, 0.996, 27.8, 104.3, 0, 68.8, 431, 659, 117, 516.37, 0.712, 0.11, 27.7, 24.3, 32.3, 635, 339, 52, 9.78, 0, 0}, {3.98, 1.09, 13.7, 68.9, 0, 72.2, 406, 453, 154, 538.87, 0.712, 0.11, 0.001, 24.9, 24.1, 659, 332, 47.9, 7.66, 0, 0}, {4.71, 2.52, 15.4, 74.2, 0, 109, 494, 779, 195, 399.45, 0.72, 0.11, 31.3, 19.8, 32, 681, 312, 46.9, 8.34, 0, 0}, {3.89, 2.13, 14.1, 68.5, 0, 169, 385, 818, 187, 488.58, 0.72, 0.11, 0.002, 26, 23.5, 558, 302, 35.7, 10.5, 0, 0}, {7.64, 2.16, 13.8, 151.4, 0, 136, 333, 759, 209, 504.62, 0.728, 0.11, 35.1, 25.2, 18.3, 588, 325, 43.2, 6.31, 0, 0}, {3.57, 4, 13.9, 152.8, 0, 108, 470, 737, 125, 562.51, 0.728, 0.11, 0.001, 21.6, 14.8, 567, 271, 35, 7.72, 0, 0}, {3.95, 2.26, 32, 152, 0, 82.4, 453, 781, 122, 632.61, 0.736, 0.11, 34.3, 26.1, 13.5, 511, 253, 30.2, 7.29, 0, 0}, {3.61, 2.36, 5.62, 149.7, 0, 82, 363, 966, 120, 671.55, 0.728, 0.11, 33.1, 21.4, 17.5, 469, 256, 30, 5.42, 0, 0}, {3.58, 2.88, 17.7, 141.4, 0, 78.4, 502, 732, 168, 507.2, 0.944, 0.11, 30.1, 22.1, 18.5, 426, 256, 35.2, 5.02, 0, 0}, {3.57, 3.06, 22, 236.9, 0, 72.8, 486, 779, 195, 448.31, 0.856, 0.11, 31, 17.2, 12.1, 362, 277, 28, 2.47, 0, 0}, {3.74, 3.73, 22.3, 269.5, 0, 66.6, 409, 765, 175, 436.33, 0.784, 0.11, 0.001, 17.5, 9.84, 240, 258, 18.2, 2.59, 0, 0}, {3.52, 1.85, 21.2, 203.3, 0, 98, 225, 768, 64, 318.76, 0.728, 0.11, 0.001, 18.4, 8.48, 235, 242, 14.5, 4.91, 0, 0}, {3.44, 3.45, 21.6, 222.5, 0, 100, 370, 735, 53.2, 554.09, 0.688, 0.11, 22.1, 17.5, 9.85, 251, 190, 15.4, 6.64, 0, 0} + }; + + double bbb[][] = setArrb(); + + for (int i = 0; i < bbb.length; i++) { + qvvrStruct.p_data[i] = new PDataStruct(bbb[i]); + } + + for (int i = 0; i < b.length; i++) { + qvvrStruct.p_data[i + bbb.length] = new PDataStruct(b[i]); + } + } + + void setBaseData(QvvrStruct qvvrStruct) { + qvvrStruct.harm_num = /*3355*/671; + qvvrStruct.p_num = 671; + qvvrStruct.p_node = 21; + qvvrStruct.win = 96; + qvvrStruct.harm_mk = 0.0f; + qvvrStruct.cal_flag = 0; + } + + + public static void main(String[] args) { + GetQvvrData getQvvrData = new GetQvvrData(); + getQvvrData.loadDll(); + } +} diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/JnaLibrary.java b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/JnaLibrary.java new file mode 100644 index 000000000..2d8135a1b --- /dev/null +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/JnaLibrary.java @@ -0,0 +1,21 @@ +package com.njcn.advance.service.responsibility.impl; + +import com.njcn.advance.pojo.bo.responsibility.QvvrStruct; +import com.sun.jna.Library; +import com.sun.jna.Native; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2021年07月14日 16:17 + */ +public interface JnaLibrary extends Library { + + JnaLibrary INSTANCE = (JnaLibrary) + Native.loadLibrary(JnaLibrary.class.getResource("/harm_response.dll") + .getPath() + .substring(1),// substring(1)的原因是在Windows下获取到的路径前面会多一个斜杠,但在Linux下不会, + JnaLibrary.class); + + void harm_response(QvvrStruct outData); +} diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/RespDataResultServiceImpl.java b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/RespDataResultServiceImpl.java new file mode 100644 index 000000000..894b4aa5c --- /dev/null +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/RespDataResultServiceImpl.java @@ -0,0 +1,90 @@ +package com.njcn.advance.service.responsibility.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.text.StrPool; +import cn.hutool.core.util.CharsetUtil; +import com.alibaba.fastjson.JSONArray; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.njcn.advance.mapper.responsibility.RespDataResultMapper; +import com.njcn.advance.pojo.bo.responsibility.UserDataExcel; +import com.njcn.advance.pojo.dto.responsibility.CustomerData; +import com.njcn.advance.pojo.dto.responsibility.CustomerResponsibility; +import com.njcn.advance.pojo.dto.responsibility.ResponsibilityResult; +import com.njcn.advance.pojo.po.responsibility.RespData; +import com.njcn.advance.pojo.po.responsibility.RespDataResult; +import com.njcn.advance.service.responsibility.IRespDataResultService; +import com.njcn.advance.service.responsibility.IRespDataService; +import com.njcn.oss.utils.FileStorageUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + *

+ * 服务实现类 + *

+ * + * @author hongawen + * @since 2023-07-24 + */ +@Service +public class RespDataResultServiceImpl extends ServiceImpl implements IRespDataResultService { + + @Resource + private FileStorageUtil fileStorageUtil; + + @Lazy + @Resource + private IRespDataService respDataService; + + @Override + public List displayHistoryData(String id, Integer time) { + List responsibilityResults = new ArrayList<>(); + if (Objects.isNull(time)) { + RespData respData = respDataService.getById(id); + String[] split = respData.getDataTimes().split(StrPool.COMMA); + time = Integer.parseInt(split[0]); + } + LambdaQueryWrapper respDataResultLambdaQueryWrapper = new LambdaQueryWrapper<>(); + respDataResultLambdaQueryWrapper.eq(RespDataResult::getResDataId, id) + .eq(RespDataResult::getTime, time); + List respDataResults = this.baseMapper.selectList(respDataResultLambdaQueryWrapper); + if (CollectionUtil.isNotEmpty(respDataResults)) { + ResponsibilityResult responsibilityResult; + for (RespDataResult respDataResult : respDataResults) { + responsibilityResult = new ResponsibilityResult(); + responsibilityResult.setLimitValue(String.valueOf(respDataResult.getLimitValue())); + responsibilityResult.setLimitSTime(DateUtil.format(respDataResult.getStartTime(), DatePattern.NORM_DATETIME_PATTERN)); + responsibilityResult.setLimitETime(DateUtil.format(respDataResult.getEndTime(), DatePattern.NORM_DATETIME_PATTERN)); + responsibilityResult.setResponsibilityDataIndex(respDataResult.getResDataId()); + //处理时间轴数据 + InputStream timeDataStream = fileStorageUtil.getFileStream(respDataResult.getTimeData()); + String timeDataStr = IoUtil.read(timeDataStream, CharsetUtil.UTF_8); + List timeData = JSONArray.parseArray(timeDataStr, Long.class); + responsibilityResult.setTimeDatas(timeData); + //处理用户详细数据 + InputStream userDetailStream = fileStorageUtil.getFileStream(respDataResult.getUserDetailData()); + String userDetailStr = IoUtil.read(userDetailStream, CharsetUtil.UTF_8); + List customerData = JSONArray.parseArray(userDetailStr, CustomerData.class); + responsibilityResult.setDatas(customerData); + //处理排名前10数据 + InputStream respStream = fileStorageUtil.getFileStream(respDataResult.getUserResponsibility()); + String respStr = IoUtil.read(respStream, CharsetUtil.UTF_8); + List respData = JSONArray.parseArray(respStr, CustomerResponsibility.class); + responsibilityResult.setResponsibilities(respData); + responsibilityResults.add(responsibilityResult); + } + } + return responsibilityResults; + } +} diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/RespDataServiceImpl.java b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/RespDataServiceImpl.java new file mode 100644 index 000000000..7f59052cf --- /dev/null +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/RespDataServiceImpl.java @@ -0,0 +1,876 @@ +package com.njcn.advance.service.responsibility.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.text.StrPool; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.njcn.advance.enums.AdvanceResponseEnum; +import com.njcn.advance.mapper.responsibility.RespDataMapper; +import com.njcn.advance.pojo.bo.responsibility.*; +import com.njcn.advance.pojo.dto.responsibility.CustomerData; +import com.njcn.advance.pojo.dto.responsibility.CustomerResponsibility; +import com.njcn.advance.pojo.dto.responsibility.RespDataDTO; +import com.njcn.advance.pojo.dto.responsibility.ResponsibilityResult; +import com.njcn.advance.pojo.param.ResponsibilityCalculateParam; +import com.njcn.advance.pojo.param.ResponsibilitySecondCalParam; +import com.njcn.advance.pojo.po.responsibility.RespData; +import com.njcn.advance.pojo.po.responsibility.RespDataResult; +import com.njcn.advance.pojo.po.responsibility.RespUserData; +import com.njcn.advance.service.responsibility.IRespDataResultService; +import com.njcn.advance.service.responsibility.IRespDataService; +import com.njcn.advance.service.responsibility.IRespUserDataService; +import com.njcn.advance.utils.JnaCallBalance; +import com.njcn.advance.utils.JnaCallDllOrSo; +import com.njcn.advance.utils.ResponsibilityCallDllOrSo; +import com.njcn.common.pojo.enums.common.DataStateEnum; +import com.njcn.common.pojo.exception.BusinessException; +import com.njcn.common.pojo.response.HttpResult; +import com.njcn.common.utils.FileUtil; +import com.njcn.common.utils.PubUtils; +import com.njcn.db.constant.DbConstant; +import com.njcn.device.biz.pojo.po.Overlimit; +import com.njcn.device.pq.api.LineFeignClient; +import com.njcn.device.pq.pojo.vo.LineDetailDataVO; +import com.njcn.device.pq.pojo.vo.LineDetailVO; +import com.njcn.harmonic.api.HarmDataFeignClient; +import com.njcn.harmonic.pojo.param.HistoryHarmParam; +import com.njcn.influx.pojo.dto.HarmData; +import com.njcn.influx.pojo.dto.HarmHistoryDataDTO; +import com.njcn.oss.constant.OssPath; +import com.njcn.oss.enums.OssResponseEnum; +import com.njcn.oss.utils.FileStorageUtil; +import com.njcn.system.pojo.vo.DictDataVO; +import com.njcn.web.factory.PageFactory; +import com.njcn.web.pojo.param.BaseParam; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.io.*; +import java.math.BigDecimal; +import java.text.DecimalFormat; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + *

+ * 服务实现类 + *

+ * + * @author hongawen + * @since 2023-07-21 + */ +@Service +@RequiredArgsConstructor +public class RespDataServiceImpl extends ServiceImpl implements IRespDataService { + + private final IRespUserDataService iRespUserDataService; + + private final FileStorageUtil fileStorageUtil; + + private final LineFeignClient lineFeignClient; + + private final HarmDataFeignClient harmDataFeignClient; + + private final GetQvvrData getQvvrData; + + private final IRespDataResultService respDataResultService; + + @Override + public Page responsibilityList(BaseParam queryParam) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + if (ObjectUtil.isNotNull(queryParam)) { + //查询参数不为空,进行条件填充 + if (StrUtil.isNotBlank(queryParam.getSearchValue())) { + //仅提供用采名称 + queryWrapper.and(param -> param.like("pqs_resp_user_data.name", queryParam.getSearchValue())); + } + //排序 + if (ObjectUtil.isAllNotEmpty(queryParam.getSortBy(), queryParam.getOrderBy())) { + queryWrapper.orderBy(true, queryParam.getOrderBy().equals(DbConstant.ASC), StrUtil.toUnderlineCase(queryParam.getSortBy())); + } else { + //没有排序参数,默认根据sort字段排序,没有排序字段的,根据updateTime更新时间排序 + queryWrapper.orderBy(true, false, "pqs_resp_data.create_time"); + } + queryWrapper.between("pqs_resp_data.create_time",queryParam.getSearchBeginTime(),queryParam.getSearchEndTime()); + } + queryWrapper.eq("pqs_resp_data.state", DataStateEnum.ENABLE.getCode()); + Page page = this.baseMapper.page(new Page<>(PageFactory.getPageNum(queryParam), PageFactory.getPageSize(queryParam)), queryWrapper); + List records = page.getRecords(); + if(CollectionUtil.isNotEmpty(records)){ + //获取该监测点的详细信息 + for (RespDataDTO respDataDTO : records) { + LineDetailVO lineSubGdDetail = lineFeignClient.getLineSubGdDetail(respDataDTO.getLineId()).getData(); + BeanUtil.copyProperties(lineSubGdDetail,respDataDTO); + } + } + return page.setRecords(records); + } + + + /*** + * 批量逻辑删除责任划分数据 + * @author hongawen + * @date 2023/7/24 19:16 + */ + @Override + public void deleteByIds(List ids) { + this.baseMapper.deleteByIds(ids); + } + + + + @Override + public ResponsibilityResult getDynamicData(ResponsibilityCalculateParam responsibilityCalculateParam) { + ResponsibilityResult result = new ResponsibilityResult(); + //调用c++依赖需要待初始化的参数 + int pNode, pNum, win, harmNum; + float harmMk; + LambdaQueryWrapper userDataLambdaQueryWrapper = new LambdaQueryWrapper<>(); + userDataLambdaQueryWrapper.eq(RespUserData::getId, responsibilityCalculateParam.getUserDataId()).eq(RespUserData::getState, DataStateEnum.ENABLE.getCode()); + RespUserData respUserData = iRespUserDataService.getOne(userDataLambdaQueryWrapper); + if (Objects.isNull(respUserData)) { + throw new BusinessException(AdvanceResponseEnum.USER_DATA_NOT_FOUND); + } + InputStream fileStream = fileStorageUtil.getFileStream(respUserData.getDataPath()); + String excelDataStr = IoUtil.read(fileStream, CharsetUtil.UTF_8); + //将文件流转为list集合 + List userDataExcels = JSONArray.parseArray(excelDataStr, UserDataExcel.class); + if (CollectionUtils.isEmpty(userDataExcels)) { + throw new BusinessException(AdvanceResponseEnum.USER_DATA_NOT_FOUND); + } + + //开始处理,根据接口参数需求,需要节点数(用户数,用户名+监测点号为一个用户),时间范围内功率数据 + DealDataResult dealDataResult = RespUserDataServiceImpl.getStanderData(userDataExcels, 1); + Map>> totalData = dealDataResult.getTotalListData(); + Map>> finalData = new HashMap<>(); + /*第一个参数pNode 如果时间范围内完整性不足90%的节点,不参与责任量化统计,因为之前处理过用采数据,此时只需要判断是否满足100%就可以判断*/ + //根据时间天数,获取理论上多少次用采数据 + List dateStr = PubUtils.getTimes(DateUtil.parse(responsibilityCalculateParam.getSearchBeginTime(), DatePattern.NORM_DATE_PATTERN), DateUtil.parse(responsibilityCalculateParam.getSearchEndTime(), DatePattern.NORM_DATE_PATTERN)); + int dueCounts = dateStr.size() * 96; + Set userNames = totalData.keySet(); + for (String userName : userNames) { + int realCounts = 0; + Map> temp = totalData.get(userName); + for (String date : dateStr) { + if (CollectionUtil.isNotEmpty(temp.get(date))) { + realCounts = realCounts + temp.get(date).size(); + } + } + if (realCounts == dueCounts) { + //只有期望和实际数量一致的时候才作为计算用户 + finalData.put(userName, temp); + } + } + //至此,finalData便是我们最终获得的用于计算责任数据,第一个参数节点数值pNode获取到 + pNode = finalData.size(); + if (pNode < 1) { + //没有合理的用采数据直接返回 + throw new BusinessException(AdvanceResponseEnum.USER_DATA_P_NODE_PARAMETER_ERROR); + } + //第二个参数pNum,根据起始时间和截止时间以及监测点测量间隔计算数量 + LineDetailDataVO lineDetailData = lineFeignClient.getLineDetailData(responsibilityCalculateParam.getLineId()).getData(); + int lineInterval = lineDetailData.getTimeInterval(); + int userIntervalTime; + if (lineInterval == 1 || lineInterval == 3 || lineInterval == 5) { + userIntervalTime = 15; + pNum = dateStr.size() * 96; + } else { + userIntervalTime = 30; + pNum = dateStr.size() * 48; + finalData = dealFinalDataByLineInterval(finalData); + } + //第三个参数win,根据起始时间和截止时间的间隔 + if (dateStr.size() > 1) { + win = 96; + } else { + win = 4; + } + //第四个参数harmMk,默认为0f + harmMk = 0f; + //第五个参数harmNum,与功率数据保持一致 + harmNum = pNum; + //至此基础数据组装完毕,开始组装功率数据和谐波数据 + //先做谐波数据,理论上到这步的时候,谐波数据是满足完整性并已经补充完整性到100%,此处需要将谐波数据与功率数据长度匹配上 + HarmHistoryDataDTO data = harmDataFeignClient.getHistoryHarmData(new HistoryHarmParam(responsibilityCalculateParam.getSearchBeginTime(), responsibilityCalculateParam.getSearchEndTime(), responsibilityCalculateParam.getLineId(), responsibilityCalculateParam.getType(), responsibilityCalculateParam.getTime())).getData(); + List historyData = data.getHistoryData(); + historyData = getDataWithLineInterval(historyData, lineInterval); + //理论上此处的historyData的长度等于pNum,开始填充harm_data + float[] harmData = new float[144000]; + //谐波波形的横轴时间集合 + List harmTime = new ArrayList<>(); + for (int i = 0; i < historyData.size(); i++) { + Float value = historyData.get(i).getValue(); + if (value != null) { + value = value * 1000; + } + harmData[i] = value; + harmTime.add(PubUtils.instantToDate(historyData.get(i).getTime()).getTime()); + } + //harmData填充完毕后,开始组装功率数据 + //首先获取当前时间内的各个用户的数据 + Map> originalPData = new HashMap<>(); + List names = new ArrayList<>(); + Set userNamesFinal = finalData.keySet(); + for (String userName : userNamesFinal) { + List tempData = new ArrayList<>(); + //根据日期将日期数据全部获取出来 + Map> tempResult = finalData.get(userName); + for (String date : dateStr) { + tempData.addAll(tempResult.get(date)); + } + //按日期排序 + Collections.sort(tempData); + originalPData.put(userName, tempData); + names.add(userName); + } + //然后开始组装数据 + PDataStruct[] pData = new PDataStruct[QvvrStruct.MAX_P_NUM]; + for (int i = 0; i < names.size(); i++) { + //当前某用户测量节点的所有数据 + List userDataExcelBodies1 = originalPData.get(names.get(i)); + for (int k = 0; k < userDataExcelBodies1.size(); k++) { + PDataStruct pDataStruct = pData[k]; + if (pDataStruct == null) { + pDataStruct = new PDataStruct(); + } + float[] p = pDataStruct.getP(); + p[i] = userDataExcelBodies1.get(k).getWork().floatValue(); + pData[k] = pDataStruct; + } + } + //至此功率数据也组装完毕,调用友谊提供的接口 + QvvrStruct qvvrStruct = new QvvrStruct(); + qvvrStruct.cal_flag = 0; + qvvrStruct.p_node = pNode; + qvvrStruct.p_num = pNum; + qvvrStruct.win = win; + qvvrStruct.harm_num = harmNum; + qvvrStruct.harm_mk = harmMk; + qvvrStruct.p_data = pData; + qvvrStruct.harm_data = harmData; + + ResponsibilityCallDllOrSo responsibilityCallDllOrSo = new ResponsibilityCallDllOrSo("harm_response.dll"); + responsibilityCallDllOrSo.setPath(); + ResponsibilityCallDllOrSo.ResponsibilityLibrary responsibilityLibrary = ResponsibilityCallDllOrSo.ResponsibilityLibrary.INSTANTCE; + responsibilityLibrary.harm_response(qvvrStruct); + //至此接口调用结束,开始组装动态责任数据和用户责任量化结果 + //首先判断cal_ok的标识位是否为1,为0表示程序没有计算出结果 + if (qvvrStruct.cal_ok == 0) { + throw new BusinessException(AdvanceResponseEnum.RESPONSIBILITY_PARAMETER_ERROR); + } + //没问题后,先玩动态责任数据 + CustomerData[] customerDatas = new CustomerData[qvvrStruct.p_node]; + PDataStruct[] fKdata/*无背景的动态责任数据*/ = qvvrStruct.getFKdata(); + //第一个时间节点是起始时间+win窗口得到的时间 + Date sTime = DateUtil.parse(dateStr.get(0).concat(" 00:00:00"), DatePattern.NORM_DATETIME_PATTERN); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(sTime); + calendar.add(Calendar.MINUTE, (win - 1) * userIntervalTime); + List timeDatas = new ArrayList<>(); + for (int i = 0; i < qvvrStruct.p_num - qvvrStruct.win; i++) { + calendar.add(Calendar.MINUTE, userIntervalTime); + //一个时间点所有的用户数据 + PDataStruct fKdatum = fKdata[i]; + for (int k = 0; k < qvvrStruct.p_node; k++) { + CustomerData customerData = customerDatas[k]; + if (null == customerData) { + customerData = new CustomerData(); + customerData.setCustomerName(names.get(k)); + } + List valueDatas = customerData.getValueDatas(); + Float valueTemp = fKdatum.getP()[k]; + if (valueTemp.isNaN()) { + valueTemp = 0.0f; + } + valueDatas.add(valueTemp); + customerData.setValueDatas(valueDatas); + customerDatas[k] = customerData; + } + timeDatas.add(calendar.getTimeInMillis()); + } + //OK拿到所有测量点的数据了,现在就是看如何将相同户号的动态数据进行算术和求值,之前的用户name为:户号@测量点号@用户名 + Map> customerDataTemp = new HashMap<>(); + for (int i = 0; i < customerDatas.length; i++) { + String customerName = customerDatas[i].getCustomerName(); + String[] customerInfo = customerName.split("@"); + String name = customerInfo[2] + "(" + customerInfo[0] + ")"; + List customerData = customerDataTemp.get(name); + CustomerData temp = customerDatas[i]; + temp.setCustomerName(name); + if (CollectionUtils.isEmpty(customerData)) { + customerData = new ArrayList<>(); + } + customerData.add(temp); + customerDataTemp.put(name, customerData); + } + //动态数据组装完成后,开始组装责任数据 + List customerResponsibilities = getCustomerResponsibilityData(names, qvvrStruct.sumFKdata, qvvrStruct.p_node); + //根据前十的用户数据,获取这些用户的动态责任数据 + List customerData = new ArrayList<>(); + for (CustomerResponsibility customerResponsibility : customerResponsibilities) { + String cusName = customerResponsibility.getCustomerName(); + List customerData1 = customerDataTemp.get(cusName); + if (CollectionUtils.isEmpty(customerData1)) { + continue; + } + if (customerData1.size() == 1) { + //表示用户唯一的 + customerData.add(customerData1.get(0)); + } else { + //表示用户可能包含多个监测点号,需要进行数据累加 + CustomerData customerDataT = new CustomerData(); + customerDataT.setCustomerName(cusName); + //进行数值累加 + List valueDatas = new ArrayList<>(); + for (int i = 0; i < customerData1.get(0).getValueDatas().size(); i++) { + float original = 0.0f; + for (int k = 0; k < customerData1.size(); k++) { + original = original + customerData1.get(k).getValueDatas().get(i); + } + valueDatas.add(original); + } + customerDataT.setValueDatas(valueDatas); + customerData.add(customerDataT); + } + } + result.setDatas(customerData); + result.setTimeDatas(timeDatas); + result.setResponsibilities(customerResponsibilities); + //此次的操作进行入库操作responsibilityData表数据 + //根据监测点名称+谐波框选的时间来查询,是否做过责任量化 + String timeWin = responsibilityCalculateParam.getSearchBeginTime().replaceAll(StrPool.DASHED, "").concat(StrPool.DASHED).concat(responsibilityCalculateParam.getSearchEndTime().replaceAll(StrPool.DASHED, "")); + String type = responsibilityCalculateParam.getType() == 0 ? "谐波电流" : "谐波电压"; + //为了避免有监测点名称重复的,最终还是选择使用监测点索引来判断唯一性 + LambdaQueryWrapper respDataLambdaQueryWrapper = new LambdaQueryWrapper<>(); + respDataLambdaQueryWrapper.eq(RespData::getLineId, responsibilityCalculateParam.getLineId()) + .eq(RespData::getUserDataId, responsibilityCalculateParam.getUserDataId()) + .eq(RespData::getTimeWindow, timeWin) + .eq(RespData::getDataType, type) + .eq(RespData::getState, DataStateEnum.ENABLE.getCode()); + List responsibilityDataTemp = this.baseMapper.selectList(respDataLambdaQueryWrapper); + RespData responsibilityData; + if (CollectionUtils.isEmpty(responsibilityDataTemp)) { + responsibilityData = new RespData(); + //库中没有记录则可以新建数据进行插入 + responsibilityData.setLineId(responsibilityCalculateParam.getLineId()); + responsibilityData.setUserDataId(responsibilityCalculateParam.getUserDataId()); + responsibilityData.setDataType(type); + responsibilityData.setDataTimes(responsibilityCalculateParam.getTime().toString()); + responsibilityData.setTimeWindow(timeWin); + responsibilityData.setState(DataStateEnum.ENABLE.getCode()); + //进行插入操作 + this.baseMapper.insert(responsibilityData); + } else { + //库中存在记录只需要判断次数进行数据更新 + responsibilityData = responsibilityDataTemp.get(0); + String times = responsibilityData.getDataTimes(); + List timesList = Stream.of(times.split(StrPool.COMMA)).collect(Collectors.toList()); + Integer time = responsibilityCalculateParam.getTime(); + if (!timesList.contains(time.toString())) { + timesList.add(time.toString()); + timesList = timesList.stream().sorted().collect(Collectors.toList()); + responsibilityData.setDataTimes(String.join(StrPool.COMMA, timesList)); + } + //执行更新操作 + this.baseMapper.updateById(responsibilityData); + } + //入库完毕之后,需要将必要数据进行序列化存储,方便后期的重复利用 + /** + * 需要序列化三种数据结构 1 cal_flag置为1时需要的一些列参数的CacheQvvrData 2 cal_flag为0时的,动态结果。3 用户责任量化结果 + * 其中1/2都只需要一个文件即可 + * 3因为用户限值的变化调整,可能存在很多个文件,具体根据用户的选择而定 + * + * 路径的结构为,temPath+userData+excelName+type+timeWin+lineIndex+time+文件名 + * 用户责任量化结果,需要再细化到限值 + */ + //首先判断有没有存储记录,没有则存储,有就略过 指定测点、时间窗口、谐波类型、谐波次数判断唯一性 + LambdaQueryWrapper respDataResultLambdaQueryWrapper = new LambdaQueryWrapper<>(); + respDataResultLambdaQueryWrapper.eq(RespDataResult::getResDataId, responsibilityData.getId()) + .eq(RespDataResult::getTime, responsibilityCalculateParam.getTime()) + .eq(RespDataResult::getStartTime, DateUtil.parse(responsibilityCalculateParam.getSearchBeginTime()+" 00:00:00",DatePattern.NORM_DATETIME_PATTERN)) + .eq(RespDataResult::getEndTime, DateUtil.parse(responsibilityCalculateParam.getSearchEndTime()+" 23:59:59",DatePattern.NORM_DATETIME_PATTERN)) + .eq(RespDataResult::getLimitValue, data.getOverLimit()); + RespDataResult respDataResult = respDataResultService.getOne(respDataResultLambdaQueryWrapper); + if (Objects.isNull(respDataResult)) { + respDataResult = new RespDataResult(); + respDataResult.setResDataId(responsibilityData.getId()); + respDataResult.setTime(responsibilityCalculateParam.getTime()); + respDataResult.setStartTime(DateUtil.parse(responsibilityCalculateParam.getSearchBeginTime()+" 00:00:00",DatePattern.NORM_DATETIME_PATTERN)); + respDataResult.setEndTime(DateUtil.parse(responsibilityCalculateParam.getSearchEndTime()+" 23:59:59",DatePattern.NORM_DATETIME_PATTERN)); + respDataResult.setLimitValue(data.getOverLimit()); + //时间横轴数据 timeDatas + JSONArray timeDataJson = JSONArray.parseArray(JSON.toJSONString(timeDatas)); + InputStream timeDataStream = IoUtil.toStream(timeDataJson.toString(), CharsetUtil.UTF_8); + String timeDataPath = fileStorageUtil.uploadStream(timeDataStream, OssPath.RESPONSIBILITY_USER_RESULT_DATA, FileUtil.generateFileName("json")); + respDataResult.setTimeData(timeDataPath); + //用户每时刻对应的责任数据 + JSONArray customerDataJson = JSONArray.parseArray(JSON.toJSONString(customerData)); + InputStream customerStream = IoUtil.toStream(customerDataJson.toString(), CharsetUtil.UTF_8); + String customerPath = fileStorageUtil.uploadStream(customerStream, OssPath.RESPONSIBILITY_USER_RESULT_DATA, FileUtil.generateFileName("json")); + respDataResult.setUserDetailData(customerPath); + //调用qvvr生成的中间数据 + CacheQvvrData cacheQvvrData = new CacheQvvrData(qvvrStruct.getP_node(), qvvrStruct.getHarm_num(), qvvrStruct.getHarm_data(), qvvrStruct.FKdata, qvvrStruct.HKdata, names, userIntervalTime, qvvrStruct.win, userIntervalTime, harmTime); + JSONObject cacheQvvrDataDataJson = (JSONObject) JSONObject.toJSON(cacheQvvrData); + InputStream cacheQvvrDataStream = IoUtil.toStream(cacheQvvrDataDataJson.toString(), CharsetUtil.UTF_8); + String cacheQvvrDataPath = fileStorageUtil.uploadStream(cacheQvvrDataStream, OssPath.RESPONSIBILITY_USER_RESULT_DATA, FileUtil.generateFileName("json")); + respDataResult.setQvvrData(cacheQvvrDataPath); + //用户前10数据存储 + JSONArray customerResJson = JSONArray.parseArray(JSON.toJSONString(customerResponsibilities)); + InputStream customerResStream = IoUtil.toStream(customerResJson.toString(), CharsetUtil.UTF_8); + String customerResPath = fileStorageUtil.uploadStream(customerResStream, OssPath.RESPONSIBILITY_USER_RESULT_DATA, FileUtil.generateFileName("json")); + respDataResult.setUserResponsibility(customerResPath); + respDataResultService.save(respDataResult); + } + //防止过程中创建了大量的对象,主动调用下GC处理 + System.gc(); + result.setResponsibilityDataIndex(responsibilityData.getId()); + return result; + } + + @Override + public ResponsibilityResult getResponsibilityData(ResponsibilitySecondCalParam responsibilitySecondCalParam) { + ResponsibilityResult result = new ResponsibilityResult(); + //根据时间天数,获取理论上多少次用采数据 + RespData responsibilityData = this.baseMapper.selectById(responsibilitySecondCalParam.getResDataId()); + if (Objects.isNull(responsibilityData)) { + throw new BusinessException(AdvanceResponseEnum.RESP_DATA_NOT_FOUND); + } + Overlimit overlimit = lineFeignClient.getOverLimitData(responsibilityData.getLineId()).getData(); + //获取总数据 + LambdaQueryWrapper respDataResultLambdaQueryWrapper = new LambdaQueryWrapper<>(); + respDataResultLambdaQueryWrapper.eq(RespDataResult::getResDataId, responsibilityData.getId()) + .eq(RespDataResult::getTime, responsibilitySecondCalParam.getTime()); + if (responsibilitySecondCalParam.getType() == 0) { + respDataResultLambdaQueryWrapper.eq(RespDataResult::getLimitValue, PubUtils.getValueByMethod(overlimit, "getIharm", responsibilitySecondCalParam.getTime())); + } else { + respDataResultLambdaQueryWrapper.eq(RespDataResult::getLimitValue, PubUtils.getValueByMethod(overlimit, "getUharm", responsibilitySecondCalParam.getTime())); + } + RespDataResult respDataResultTemp = respDataResultService.getOne(respDataResultLambdaQueryWrapper); + if (Objects.isNull(respDataResultTemp)) { + throw new BusinessException(AdvanceResponseEnum.RESP_DATA_NOT_FOUND); + } + CacheQvvrData cacheQvvrData; + try { + InputStream fileStream = fileStorageUtil.getFileStream(respDataResultTemp.getQvvrData()); + String qvvrDataStr = IoUtil.read(fileStream, CharsetUtil.UTF_8); + cacheQvvrData = JSONObject.parseObject(qvvrDataStr, CacheQvvrData.class); + } catch (Exception exception) { + throw new BusinessException(AdvanceResponseEnum.RESP_RESULT_DATA_NOT_FOUND); + } + //获取成功后,延长该缓存的生命周期为初始生命时长 + int win = cacheQvvrData.getWin(); + //不管窗口为4或者96,都需要考虑最小公倍数 + //最小公倍数根据监测点测量间隔来获取,可以考虑也由第一步操作缓存起来 + int minMultiple = cacheQvvrData.getMinMultiple(); + //谐波横轴所有的时间 + List times = cacheQvvrData.getTimes(); + //首先根据窗口判断限值时间范围是否满足最小窗口 + Long limitSL = DateUtil.parse(responsibilitySecondCalParam.getLimitStartTime(),DatePattern.NORM_DATETIME_PATTERN).getTime(); + Long limitEL = DateUtil.parse(responsibilitySecondCalParam.getLimitEndTime(),DatePattern.NORM_DATETIME_PATTERN).getTime(); + List temp = getTimes(times, limitSL, limitEL); + //在动态责任数据中,时间的起始索引位置和截止索引位置 + Integer timeStartIndex = temp.get(0); + Integer timeEndIndex = temp.get(1); + //间隔中的时间长度 + int minus = timeEndIndex - timeStartIndex + 1; + //组装参数 + QvvrStruct qvvrStruct = new QvvrStruct(); + qvvrStruct.cal_flag = 1; + qvvrStruct.p_node = cacheQvvrData.getPNode(); + qvvrStruct.harm_mk = responsibilitySecondCalParam.getLimitValue(); + qvvrStruct.win = win; + int resNum; + PDataStruct[] FKdata = new PDataStruct[9600]; + HKDataStruct[] HKdata = new HKDataStruct[9600]; + float[] harmData = new float[1440 * 100]; + PDataStruct[] fKdataOriginal = cacheQvvrData.getFKdata(); + HKDataStruct[] hKdataOriginal = cacheQvvrData.getHKdata(); + float[] harmDataOriginal = cacheQvvrData.getHarmData(); + //如果起始索引与截止索引的差值等于时间轴的长度,则说明用户没有选择限值时间,直接带入全部的原始数据,参与计算即可 + if (minus == times.size()) { + qvvrStruct.harm_num = cacheQvvrData.getHarmNum(); + qvvrStruct.res_num = cacheQvvrData.getHarmNum() - cacheQvvrData.getWin(); + qvvrStruct.setFKdata(cacheQvvrData.getFKdata()); + qvvrStruct.setHKdata(cacheQvvrData.getHKdata()); + qvvrStruct.harm_data = cacheQvvrData.getHarmData(); + } else { + if (win == 4) { + //当窗口为4时,两个时间限制范围在最小公倍数为15时,最起码有5个有效时间点,在最小公倍数为30时,最起码有3个有效时间点 + if (minMultiple == 15) { + if (minus < 5) { + throw new BusinessException(AdvanceResponseEnum.WIN_TIME_ERROR); + } + resNum = minus - 4; + + } else if (minMultiple == 30) { + if (minus < 3) { + throw new BusinessException(AdvanceResponseEnum.WIN_TIME_ERROR); + } + resNum = minus - 2; + } else { + throw new BusinessException(AdvanceResponseEnum.CALCULATE_INTERVAL_ERROR); + } + } else if (win == 96) { + //当窗口为96时,两个时间限值范围在最小公倍数为15时,最起码有97个有效时间点,在最小公倍数为30时,最起码有49个有效时间点 + if (minMultiple == 15) { + if (minus < 97) { + throw new BusinessException(AdvanceResponseEnum.WIN_TIME_ERROR); + } + resNum = minus - 96; + } else if (minMultiple == 30) { + if (minus < 49) { + throw new BusinessException(AdvanceResponseEnum.WIN_TIME_ERROR); + } + resNum = minus - 48; + } else { + throw new BusinessException(AdvanceResponseEnum.CALCULATE_INTERVAL_ERROR); + } + } else { + throw new BusinessException(AdvanceResponseEnum.CALCULATE_INTERVAL_ERROR); + } + qvvrStruct.res_num = resNum; + qvvrStruct.harm_num = minus; + //因为限值时间实际是含头含尾的,所以harmNum需要索引差值+1 + for (int i = timeStartIndex; i <= timeEndIndex; i++) { + harmData[i - timeStartIndex] = harmDataOriginal[i]; + } + qvvrStruct.harm_data = harmData; + //FKData与HKData的值则等于resNum + for (int i = timeStartIndex; i < timeStartIndex + resNum; i++) { + FKdata[i - timeStartIndex] = fKdataOriginal[i]; + HKdata[i - timeStartIndex] = hKdataOriginal[i]; + } + + qvvrStruct.setFKdata(FKdata); + qvvrStruct.setHKdata(HKdata); + } + qvvrStruct = getQvvrData.getResponsibilityResult(qvvrStruct); + if (qvvrStruct.cal_ok == 0) { + throw new BusinessException(AdvanceResponseEnum.RESPONSIBILITY_PARAMETER_ERROR); + } + //没问题后,先玩动态责任数据 + List names = cacheQvvrData.getNames(); + CustomerData[] customerDatas = new CustomerData[qvvrStruct.p_node]; + PDataStruct[] fKdata/*无背景的动态责任数据*/ = qvvrStruct.getFKdata(); + //第一个时间节点是起始时间+win窗口得到的时间 + Date sTime = new Date(); + sTime.setTime(times.get(timeStartIndex)); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(sTime); + calendar.add(Calendar.MINUTE, (win - 1) * minMultiple); + List timeDatas = new ArrayList<>(); + for (int i = 0; i < qvvrStruct.harm_num - qvvrStruct.win; i++) { + calendar.add(Calendar.MINUTE, minMultiple); + //一个时间点所有的用户数据 + PDataStruct fKdatum = fKdata[i]; + for (int k = 0; k < qvvrStruct.p_node; k++) { + CustomerData customerData = customerDatas[k]; + if (null == customerData) { + customerData = new CustomerData(); + customerData.setCustomerName(names.get(k)); + } + List valueDatas = customerData.getValueDatas(); + Float valueTemp = fKdatum.getP()[k]; + if (valueTemp.isNaN()) { + valueTemp = 0.0f; + } + valueDatas.add(valueTemp); + customerData.setValueDatas(valueDatas); + customerDatas[k] = customerData; + } + timeDatas.add(calendar.getTimeInMillis()); + } + //OK拿到所有测量点的数据了,现在就是看如何将相同户号的动态数据进行算术和求值,之前的用户name为:户号@测量点号@用户名 + Map> customerDataTemp = new HashMap<>(); + for (int i = 0; i < customerDatas.length; i++) { + String customerName = customerDatas[i].getCustomerName(); + String[] customerInfo = customerName.split("@"); + String name = customerInfo[2] + "(" + customerInfo[0] + ")"; + List customerData = customerDataTemp.get(name); + CustomerData customerTemp = customerDatas[i]; + customerTemp.setCustomerName(name); + if (CollectionUtils.isEmpty(customerData)) { + customerData = new ArrayList<>(); + } + customerData.add(customerTemp); + customerDataTemp.put(name, customerData); + } + //调用程序接口后,首先组装责任量化结果 + float[] sumFKdata = qvvrStruct.sumFKdata; + List customerResponsibilities = getCustomerResponsibilityData(names, sumFKdata, qvvrStruct.p_node); + //根据前十的用户数据,获取这些用户的动态责任数据 + List customerData = new ArrayList<>(); + + for (CustomerResponsibility customerResponsibility : customerResponsibilities) { + String cusName = customerResponsibility.getCustomerName(); + List customerData1 = customerDataTemp.get(cusName); + if (CollectionUtils.isEmpty(customerData1)) { + continue; + } + if (customerData1.size() == 1) { + //表示用户唯一的 + customerData.add(customerData1.get(0)); + } else { + //表示用户可能包含多个监测点号,需要进行数据累加 + CustomerData customerDataT = new CustomerData(); + customerDataT.setCustomerName(cusName); + //进行数值累加 + List valueDatas = new ArrayList<>(); + for (int i = 0; i < customerData1.get(0).getValueDatas().size(); i++) { + float original = 0.0f; + for (int k = 0; k < customerData1.size(); k++) { + original = original + customerData1.get(k).getValueDatas().get(i); + } + valueDatas.add(original); + } + customerDataT.setValueDatas(valueDatas); + customerData.add(customerDataT); + } + } + //接着组装动态数据结果 + result.setResponsibilities(customerResponsibilities); + result.setDatas(customerData); + result.setTimeDatas(timeDatas); + + //首先判断有没有存储记录,没有则存储,有就略过 指定测点、时间窗口、谐波类型、谐波次数判断唯一性 + LambdaQueryWrapper respDataResultLambdaQueryWrapper1 = new LambdaQueryWrapper<>(); + respDataResultLambdaQueryWrapper1.eq(RespDataResult::getResDataId, responsibilityData.getId()) + .eq(RespDataResult::getTime, responsibilitySecondCalParam.getTime()) + .eq(RespDataResult::getStartTime, DateUtil.parse(responsibilitySecondCalParam.getLimitStartTime(),DatePattern.NORM_DATETIME_PATTERN)) + .eq(RespDataResult::getEndTime, DateUtil.parse(responsibilitySecondCalParam.getLimitEndTime(),DatePattern.NORM_DATETIME_PATTERN)) + .eq(RespDataResult::getLimitValue, responsibilitySecondCalParam.getLimitValue()); + RespDataResult respDataResult = respDataResultService.getOne(respDataResultLambdaQueryWrapper1); + if (Objects.isNull(respDataResult)) { + respDataResult = new RespDataResult(); + respDataResult.setResDataId(responsibilityData.getId()); + respDataResult.setTime(responsibilitySecondCalParam.getTime()); + respDataResult.setStartTime(DateUtil.parse(responsibilitySecondCalParam.getLimitStartTime(),DatePattern.NORM_DATETIME_PATTERN)); + respDataResult.setEndTime(DateUtil.parse(responsibilitySecondCalParam.getLimitEndTime(),DatePattern.NORM_DATETIME_PATTERN)); + respDataResult.setLimitValue(responsibilitySecondCalParam.getLimitValue()); + //时间横轴数据 timeDatas + JSONArray timeDataJson = JSONArray.parseArray(JSON.toJSONString(timeDatas)); + InputStream timeDataStream = IoUtil.toStream(timeDataJson.toString(), CharsetUtil.UTF_8); + String timeDataPath = fileStorageUtil.uploadStream(timeDataStream, OssPath.RESPONSIBILITY_USER_RESULT_DATA, FileUtil.generateFileName("json")); + respDataResult.setTimeData(timeDataPath); + //用户每时刻对应的责任数据 + JSONArray customerDataJson = JSONArray.parseArray(JSON.toJSONString(customerData)); + InputStream customerStream = IoUtil.toStream(customerDataJson.toString(), CharsetUtil.UTF_8); + String customerPath = fileStorageUtil.uploadStream(customerStream, OssPath.RESPONSIBILITY_USER_RESULT_DATA, FileUtil.generateFileName("json")); + respDataResult.setUserDetailData(customerPath); + //用户前10数据存储 + JSONArray customerResJson = JSONArray.parseArray(JSON.toJSONString(customerResponsibilities)); + InputStream customerResStream = IoUtil.toStream(customerResJson.toString(), CharsetUtil.UTF_8); + String customerResPath = fileStorageUtil.uploadStream(customerResStream, OssPath.RESPONSIBILITY_USER_RESULT_DATA, FileUtil.generateFileName("json")); + respDataResult.setUserResponsibility(customerResPath); + respDataResultService.save(respDataResult); + } + //防止过程中创建了大量的对象,主动调用下GC处理 + System.gc(); + result.setResponsibilityDataIndex(responsibilityData.getId()); + return result; + } + + + + /** + * 监测点测量间隔获取最后用于计算的功率数据 + * + * @param finalData 参数计算的功率数据 + */ + private Map>> dealFinalDataByLineInterval(Map>> finalData) { + DecimalFormat decimalFormat = new DecimalFormat("0.0000"); + Map>> result; + //当监测点测量间隔为10分钟时,功率数据需要调整为30分钟数据 + result = new HashMap<>(); + Set userNames = finalData.keySet(); + for (String userName : userNames) { + Map> temp = new HashMap<>(); + Map> original = finalData.get(userName); + Set dates = original.keySet(); + for (String date : dates) { + List single = original.get(date);//某当天的数据 + //先根据事时间排序 + Collections.sort(single); + //此时根据当天所有的数据,重新计算出所有时间点的数据,担心这个过程会消耗过长时间 + List tempDatas = new ArrayList<>(); + for (int i = 0; i < 96; i = i + 2) { + //30分钟内的2个15分钟功率数据相加作平均计算30分钟内的功率数据,最终的数据序列时间间隔30分钟。by 友谊文档 + UserDataExcel tempData = new UserDataExcel(); + tempData.setUserName(single.get(i).getUserName()); + tempData.setUserId(single.get(i).getUserId()); + tempData.setLine(single.get(i).getLine()); + tempData.setTime(single.get(i).getTime()); + //功率为 2个15分钟功率数据相加作平均 + double work = single.get(i).getWork().doubleValue() + single.get(i + 1).getWork().doubleValue(); + tempData.setWork(new BigDecimal(decimalFormat.format(work / 2.0))); + tempDatas.add(tempData); + } + temp.put(date, tempDatas); + } + result.put(userName, temp); + } + return result; + } + + /** + * 通过监测点测量间隔计算对齐后的谐波数据 + * 暂且认为最小公倍数就15、30两种可能 + * + * @param historyData 原始的谐波数据 + * @param lineInterval 测量间隔 + */ + private List getDataWithLineInterval(List historyData, int lineInterval) { + List result = new ArrayList<>(); + switch (lineInterval) { + case 1: + result = getHarmResultByTimes(historyData, 15); + break; + case 3: + result = getHarmResultByTimes(historyData, 5); + break; + case 5: + case 10: + result = getHarmResultByTimes(historyData, 3); + break; + } + return result.stream().sorted(Comparator.comparing(HarmData::getTime)).collect(Collectors.toList()); + } + + /** + * 通过监测点测量间隔计算对齐后的谐波数据 + * + * @param historyData 原始的谐波数据 + */ + private List getHarmResultByTimes(List historyData, int times) { + List result = new ArrayList<>(); + DecimalFormat decimalFormat = new DecimalFormat("0.0000"); + for (int i = 0; i < historyData.size(); i = i + times) { + float temp = 0.0f; + for (int j = 0; j < times; j++) { + int index = i + j; + temp = temp + historyData.get(index).getValue(); + } + //求平均值 + temp = Float.parseFloat(decimalFormat.format(temp / (float) times)); + HarmData resTemp = new HarmData(); + resTemp.setTime(historyData.get(i).getTime()); + resTemp.setValue(temp); + result.add(resTemp); + } + return result; + } + + /** + * 根据接口返回值组装需要显示的责任量化数据 + */ + private List getCustomerResponsibilityData(List names, float[] sumFKdata, int pNode) { + Map customerResponsibilityMap = new HashMap<>(); + for (int i = 0; i < pNode; i++) { + String[] customerInfo = names.get(i).split("@");/*用户ID 测量点ID 用户名*/ + String name = customerInfo[2] + "(" + customerInfo[0] + ")"; + CustomerResponsibility customerResponsibility; + if (customerResponsibilityMap.containsKey(name)) { + customerResponsibility = customerResponsibilityMap.get(name); + customerResponsibility.setResponsibilityData(customerResponsibility.getResponsibilityData() + sumFKdata[i]); + } else { + customerResponsibility = new CustomerResponsibility(); + customerResponsibility.setCustomerName(name); + customerResponsibility.setResponsibilityData(sumFKdata[i]); + } + customerResponsibilityMap.put(name, customerResponsibility); + } + //map转为list + List customerResponsibilities = new ArrayList<>(); + Set cusNames = customerResponsibilityMap.keySet(); + for (String cusName : cusNames) { + customerResponsibilities.add(customerResponsibilityMap.get(cusName)); + } + //取出前十的用户责任数据 + customerResponsibilities = customerResponsibilities.stream().sorted(Comparator.comparing(CustomerResponsibility::getResponsibilityData).reversed()).collect(Collectors.toList()); + if (customerResponsibilities.size() > 10) { + //当用户超出10,将前十用户保留,然后剩余归类为其他用户 + float tenTotal = 0.0f; + for (int i = 0; i < 10; i++) { + float temp = PubUtils.floatRound(3, customerResponsibilities.get(i).getResponsibilityData()); + tenTotal = tenTotal + temp; + } + int size = customerResponsibilities.size() - 10; + customerResponsibilities = customerResponsibilities.subList(0, 10); + CustomerResponsibility others = new CustomerResponsibility(); + others.setCustomerName("其他用户(" + size + ")"); + others.setResponsibilityData(PubUtils.floatRound(3, 100.0f - tenTotal)); + customerResponsibilities.add(others); + } + return customerResponsibilities; + } + + /** + * 根据起始时间获取在集合中最接近的起始和截止值 + * + * @param times 时间集合 + * @param limitSL 起始值 + * @param limitEL 截止值 + */ + private List getTimes(List times, Long limitSL, Long limitEL) { + List result = new ArrayList<>(); + Integer temps = null; + Integer tempe = null; + //因为可以知道times是为4的倍数,所以长度肯定是偶数,不会出现索引越界的异常 + if (limitSL < times.get(0)) { + temps = 0; + } + if (limitEL > times.get(times.size() - 1)) { + tempe = times.size() - 1; + } + for (int i = 0; i < times.size() - 1; i++) { + if (temps != null & tempe != null) { + //判断都已经赋值后,跳出循环 + break; + } + //锁定前值 + if (times.get(i).equals(limitSL)) { + //相等则给起始时间赋值 + temps = i; + } else if (times.get(i + 1).equals(limitSL)) { + temps = i + 1; + } else if (times.get(i) < limitSL & times.get(i + 1) > limitSL) { + //当起始时间处于中间时,将后值赋值给temps + temps = i + 1; + } + //锁定后值 + if (times.get(i).equals(limitEL)) { + //相等则给起始时间赋值 + tempe = i; + } else if (times.get(i + 1).equals(limitEL)) { + tempe = i + 1; + } else if (times.get(i) < limitEL & times.get(i + 1) > limitEL) {// + //当起始时间处于中间时,将前值赋值给temps + tempe = i; + } + } + if (temps == null) { + temps = 0; + } + if (tempe == null) { + tempe = times.size() - 1; + } + result.add(temps); + result.add(tempe); + return result; + } +} diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/RespUserDataIntegrityServiceImpl.java b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/RespUserDataIntegrityServiceImpl.java new file mode 100644 index 000000000..95e4f074c --- /dev/null +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/RespUserDataIntegrityServiceImpl.java @@ -0,0 +1,33 @@ +package com.njcn.advance.service.responsibility.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.njcn.advance.mapper.responsibility.RespUserDataIntegrityMapper; +import com.njcn.advance.pojo.param.UserDataIntegrityParam; +import com.njcn.advance.pojo.po.responsibility.RespUserDataIntegrity; +import com.njcn.advance.service.responsibility.IRespUserDataIntegrityService; +import com.njcn.web.factory.PageFactory; +import org.springframework.stereotype.Service; + + +/** + *

+ * 服务实现类 + *

+ * + * @author hongawen + * @since 2023-07-13 + */ +@Service +public class RespUserDataIntegrityServiceImpl extends ServiceImpl implements IRespUserDataIntegrityService { + + @Override + public Page userDataIntegrityList(UserDataIntegrityParam userDataIntegrityParam) { + QueryWrapper lambdaQueryWrapper = new QueryWrapper<>(); + lambdaQueryWrapper.eq("pqs_resp_user_data_integrity.user_data_id", userDataIntegrityParam.getUserDataId()) + .orderByDesc("pqs_resp_user_data_integrity.create_time"); + return this.baseMapper.page(new Page<>(PageFactory.getPageNum(userDataIntegrityParam), PageFactory.getPageSize(userDataIntegrityParam)), lambdaQueryWrapper); + } +} diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/RespUserDataServiceImpl.java b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/RespUserDataServiceImpl.java new file mode 100644 index 000000000..fa9b3ab29 --- /dev/null +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/service/responsibility/impl/RespUserDataServiceImpl.java @@ -0,0 +1,465 @@ +package com.njcn.advance.service.responsibility.impl; + +import cn.afterturn.easypoi.excel.ExcelImportUtil; +import cn.afterturn.easypoi.excel.entity.ImportParams; +import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult; +import cn.afterturn.easypoi.handler.inter.IReadHandler; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.text.StrPool; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.njcn.advance.enums.AdvanceResponseEnum; +import com.njcn.advance.mapper.responsibility.RespUserDataMapper; +import com.njcn.advance.pojo.bo.responsibility.DealDataResult; +import com.njcn.advance.pojo.bo.responsibility.DealUserDataResult; +import com.njcn.advance.pojo.bo.responsibility.UserDataExcel; +import com.njcn.advance.pojo.po.responsibility.RespUserData; +import com.njcn.advance.pojo.po.responsibility.RespUserDataIntegrity; +import com.njcn.advance.service.responsibility.IRespUserDataIntegrityService; +import com.njcn.advance.service.responsibility.IRespUserDataService; +import com.njcn.common.pojo.dto.SelectOption; +import com.njcn.common.pojo.enums.common.DataStateEnum; +import com.njcn.common.pojo.exception.BusinessException; +import com.njcn.common.utils.FileUtil; +import com.njcn.common.utils.PubUtils; +import com.njcn.db.constant.DbConstant; +import com.njcn.oss.constant.OssPath; +import com.njcn.oss.utils.FileStorageUtil; +import com.njcn.poi.util.PoiUtil; +import com.njcn.web.factory.PageFactory; +import com.njcn.web.pojo.param.BaseParam; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.io.InputStream; +import java.math.BigDecimal; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.util.*; +import java.util.stream.Collectors; + +/** + *

+ * 服务实现类 + *

+ * + * @author hongawen + * @since 2023-07-13 + */ +@Service +@RequiredArgsConstructor +public class RespUserDataServiceImpl extends ServiceImpl implements IRespUserDataService { + + private final FileStorageUtil fileStorageUtil; + + private final IRespUserDataIntegrityService respUserDataIntegrityService; + + @Override + public void uploadUserData(MultipartFile file, HttpServletResponse response) { + ImportParams params = new ImportParams(); + List userDataExcels = new ArrayList<>(); + try { + ExcelImportUtil.importExcelBySax(file.getInputStream(), UserDataExcel.class, params, new IReadHandler() { + @Override + public void handler(UserDataExcel o) { + userDataExcels.add(o); + } + + @Override + public void doAfterAll() { + + } + }); + //处理用户上传的用采数据内容 + analysisUserData(userDataExcels, file.getOriginalFilename()); + } catch (Exception e) { + throw new BusinessException(AdvanceResponseEnum.ANALYSIS_USER_DATA_ERROR); + } + } + + @Override + public Page userDataList(BaseParam queryParam) { + QueryWrapper respUserDataQueryWrapper = new QueryWrapper<>(); + if (ObjectUtil.isNotNull(queryParam)) { + //查询参数不为空,进行条件填充 + if (StrUtil.isNotBlank(queryParam.getSearchValue())) { + //仅提供用采名称 + respUserDataQueryWrapper.and(param -> param.like("pqs_resp_user_data.name", queryParam.getSearchValue())); + } + //排序 + if (ObjectUtil.isAllNotEmpty(queryParam.getSortBy(), queryParam.getOrderBy())) { + respUserDataQueryWrapper.orderBy(true, queryParam.getOrderBy().equals(DbConstant.ASC), StrUtil.toUnderlineCase(queryParam.getSortBy())); + } else { + //没有排序参数,默认根据sort字段排序,没有排序字段的,根据updateTime更新时间排序 + respUserDataQueryWrapper.orderBy(true, false, "pqs_resp_user_data.update_time"); + } + } else { + respUserDataQueryWrapper.orderBy(true, false, "pqs_resp_user_data.update_time"); + } + respUserDataQueryWrapper.eq("pqs_resp_user_data.state", DataStateEnum.ENABLE.getCode()); + return this.baseMapper.page(new Page<>(PageFactory.getPageNum(queryParam), PageFactory.getPageSize(queryParam)), respUserDataQueryWrapper); + } + + @Override + public List userDataSelect() { + List selectOptions = new ArrayList<>(); + LambdaQueryWrapper respUserDataLambdaQueryWrapper = new LambdaQueryWrapper<>(); + respUserDataLambdaQueryWrapper.eq(RespUserData::getState, DataStateEnum.ENABLE.getCode()) + .orderByDesc(RespUserData::getUpdateTime); + List respUserData = this.baseMapper.selectList(respUserDataLambdaQueryWrapper); + if (CollectionUtil.isNotEmpty(respUserData)) { + selectOptions = respUserData.stream().map(temp -> new SelectOption(temp.getName(), temp.getId())).collect(Collectors.toList()); + } + return selectOptions; + } + + @Override + public void deleteUserDataByIds(List ids) { + this.baseMapper.deleteUserDataByIds(ids); + } + + + /** + * 根据流获取出用采有功功率数据 + */ + private void analysisUserData(List userDataExcelList, String fileName) { + List exportExcelList = new ArrayList<>(); + RespUserData respUserData; + //判断数据提取情况 + if (CollectionUtils.isEmpty(userDataExcelList)) { + throw new BusinessException(AdvanceResponseEnum.USER_DATA_EMPTY); + } + DealDataResult dealDataResult = getStanderData(userDataExcelList, 0); + Map>> totalData = dealDataResult.getTotalData(); + //收集所有的日期,以便获取起始日期和截止日期 + List dates = dealDataResult.getDates(); + //将前面获取出来的日期进行排序,提供入库 + List resultDates = getSortDate(dates); + LocalDate endTime = resultDates.get(resultDates.size() - 1); + LocalDate startTime = resultDates.get(0); + //针对每个用户的数据进行完整度的判断 todo 暂且认为所有用户的时间跨度是一样的,比如都是15天或者都是30天,不存在有的用户5天数据,有的用户10天数据 + Map> tempResult = new HashMap<>(); + List respUserDataIntegrities = new ArrayList<>(); + Set userNames = totalData.keySet(); + for (String name : userNames) { + Map> userDataTemp = totalData.get(name); + //现在数据拿到了,但是因为是hashkey,所以日期顺序是乱的-->怎么变成有序的呢 + Set times = userDataTemp.keySet(); + //循环日期处理数据 + for (String time : times) { + DealUserDataResult dealtData = dealUserData(name, userDataTemp.get(time), time, 15); + List UserDataExcelTemp = dealtData.getCompleted(); + List UserDataExcel; + if (CollectionUtils.isEmpty(UserDataExcelTemp) && Objects.nonNull(dealtData.getRespUserDataIntegrity())) { + //为空,说明补齐操作没有进行,选择填充缺失数据即可 + respUserDataIntegrities.add(dealtData.getRespUserDataIntegrity()); + UserDataExcel = dealtData.getLack(); + } else { + //填充补齐完整性后的数据 + UserDataExcel = UserDataExcelTemp; + } + List userDatas = tempResult.get(name); + if (CollectionUtil.isNotEmpty(UserDataExcel)) { + if (CollectionUtils.isEmpty(userDatas)) { + userDatas = new ArrayList<>(UserDataExcel); + } else { + userDatas.addAll(UserDataExcel); + } + } + tempResult.put(name, userDatas); + } + } + //完成后,开始将数据按公司排序,然后输出到指定表格中,方便下次使用 + for (String name : userNames) { + List tempUserData = tempResult.get(name); + //按时间排序 + Collections.sort(tempUserData); + exportExcelList.addAll(tempUserData); + } + //输出到报表中 + String fileNameWithOutSuffix = fileName.substring(0, fileName.indexOf('.')); + fileNameWithOutSuffix = fileNameWithOutSuffix.concat(LocalDateTimeUtil.format(startTime, DatePattern.PURE_DATE_PATTERN)).concat(StrPool.DASHED).concat(LocalDateTimeUtil.format(endTime, DatePattern.PURE_DATE_PATTERN)); + //处理完后的用采数据,生成json文件流到oss服务器 + JSONArray finalUserData = JSONArray.parseArray(JSON.toJSONString(exportExcelList)); + InputStream reportStream = IoUtil.toStream(finalUserData.toString(), CharsetUtil.UTF_8); + String ossPath = fileStorageUtil.uploadStream(reportStream, OssPath.RESPONSIBILITY_USER_DATA, FileUtil.generateFileName("json")); + //入库前进行查询操作,存在则更新,不存在则插入 + LambdaQueryWrapper respUserDataLambdaQueryWrapper = new LambdaQueryWrapper<>(); + respUserDataLambdaQueryWrapper.eq(RespUserData::getName, fileNameWithOutSuffix) + .eq(RespUserData::getStartTime, startTime) + .eq(RespUserData::getEndTime, endTime) + .eq(RespUserData::getState, DataStateEnum.ENABLE.getCode()); + respUserData = this.baseMapper.selectOne(respUserDataLambdaQueryWrapper); + //不存在则插入 + if (Objects.isNull(respUserData)) { + respUserData = new RespUserData(); + respUserData.setEndTime(endTime); + respUserData.setStartTime(startTime); + respUserData.setName(fileNameWithOutSuffix); + respUserData.setDataPath(ossPath); + respUserData.setState(DataStateEnum.ENABLE.getCode()); + this.baseMapper.insert(respUserData); + if (CollectionUtil.isNotEmpty(respUserDataIntegrities)) { + //关联插入数据 户号,监测点号,户名,时间,完整性 + for (RespUserDataIntegrity respUserDataIntegrity : respUserDataIntegrities) { + respUserDataIntegrity.setUserDataId(respUserData.getId()); + } + //插入操作 + respUserDataIntegrityService.saveBatch(respUserDataIntegrities); + respUserData.setIntegrity(1); + } else { + respUserData.setIntegrity(0); + } + this.baseMapper.updateById(respUserData); + } else { + //存在则更新,需要删除之前的oss文件 + fileStorageUtil.deleteFile(respUserData.getDataPath()); + if (CollectionUtil.isNotEmpty(respUserDataIntegrities)) { + LambdaQueryWrapper respUserDataIntegrityLambdaQueryWrapper = new LambdaQueryWrapper<>(); + respUserDataIntegrityLambdaQueryWrapper.eq(RespUserDataIntegrity::getUserDataId, respUserData.getId()); + respUserDataIntegrityService.remove(respUserDataIntegrityLambdaQueryWrapper); + for (RespUserDataIntegrity respUserDataIntegrity : respUserDataIntegrities) { + respUserDataIntegrity.setUserDataId(respUserData.getId()); + } + //插入操作 + respUserDataIntegrityService.saveBatch(respUserDataIntegrities); + respUserData.setIntegrity(1); + } else { + respUserData.setIntegrity(0); + } + respUserData.setDataPath(ossPath); + this.baseMapper.updateById(respUserData); + } + + } + + /** + * 解析用采数据为一个标准格式 + */ + public static DealDataResult getStanderData(List userDataExcelBodies, int flag) { + DealDataResult result = new DealDataResult(); + //收集所有的日期,以便获取起始日期和截止日期 + List dates = new ArrayList<>(); + Map>> totalData = new HashMap<>(); + Map>> totalListData = new HashMap<>(); + for (UserDataExcel UserDataExcel : userDataExcelBodies) { + //第一个key + String key = UserDataExcel.getUserId() + "@" + UserDataExcel.getLine() + "@" + UserDataExcel.getUserName(); + String time = UserDataExcel.getTime().substring(0, 10); + if (!dates.contains(time)) { + dates.add(time); + } + if (!totalData.containsKey(key)) { + if (flag == 0) { + //Map形式,避免后面补齐数据嵌套循环 + Map userDatas = new HashMap<>(); + userDatas.put(PubUtils.getSecondsAsZero(DateUtil.parse(UserDataExcel.getTime(), DatePattern.NORM_DATETIME_PATTERN)), UserDataExcel); + Map> dataToUserDatas = new HashMap<>(); + dataToUserDatas.put(time, userDatas); + totalData.put(key, dataToUserDatas); + } else if (flag == 1) { + //List形式,避免后面责任数据提取嵌套循环 + List userListDatas = new ArrayList<>(); + userListDatas.add(UserDataExcel); + Map> dataToUserListDatas = new HashMap<>(); + dataToUserListDatas.put(time, userListDatas); + totalData.put(key, new HashMap<>()); + totalListData.put(key, dataToUserListDatas); + } + } else { + if (flag == 0) { + //Map形式,避免后面补齐数据嵌套循环 + Map> dataToUserDatas = totalData.get(key); + Map userDatas = dataToUserDatas.get(time); + //某日凌晨,还没存放该日的数据 + if (CollectionUtils.isEmpty(userDatas)) { + userDatas = new HashMap<>(); + userDatas.put(PubUtils.getSecondsAsZero(DateUtil.parse(UserDataExcel.getTime(), DatePattern.NORM_DATETIME_PATTERN)), UserDataExcel); + dataToUserDatas.put(time, userDatas); + } else { + //累加该日的数据 + userDatas.put(PubUtils.getSecondsAsZero(DateUtil.parse(UserDataExcel.getTime(), DatePattern.NORM_DATETIME_PATTERN)), UserDataExcel); + dataToUserDatas.put(time, userDatas); + } + totalData.put(key, dataToUserDatas); + } else if (flag == 1) { + //List形式,避免后面责任数据提取嵌套循环 + Map> dataToUserListDatas = totalListData.get(key); + List userListDatas = dataToUserListDatas.get(time); + if (CollectionUtils.isEmpty(userListDatas)) { + userListDatas = new ArrayList<>(); + userListDatas.add(UserDataExcel); + dataToUserListDatas.put(time, userListDatas); + } else { + userListDatas.add(UserDataExcel); + dataToUserListDatas.put(time, userListDatas); + } + totalListData.put(key, dataToUserListDatas); + } + } + + } + result.setDates(dates); + result.setTotalData(totalData); + result.setTotalListData(totalListData); + return result; + } + + /** + * 将日期排序后返回 + */ + private List getSortDate(List dates) { + List result = new ArrayList<>(); + for (String date : dates) { + LocalDate temp = LocalDateTimeUtil.parseDate(date, DatePattern.NORM_DATE_PATTERN); + result.add(temp); + } + if (!CollectionUtils.isEmpty(result)) { + Collections.sort(result); + } + return result; + } + + + /** + * 处理用户每日数据 + * + * @param name 用户名 + * @param beforeDeal 处理前的用户数据 + */ + private DealUserDataResult dealUserData(String name, Map beforeDeal, String time, int step) { + DealUserDataResult result = new DealUserDataResult(); + String[] userFlag = name.split("@"); + //每天的最开是的数据是从00:00:00开始的,所以起始时间为time + 00:00:00 + List completed = new ArrayList<>(); + List lack = new ArrayList<>(); + if (CollectionUtils.isEmpty(beforeDeal)) { + return result; + } else { + String timeTemp = time + " 00:00:00"; + Date date = DateUtil.parse(timeTemp, DatePattern.NORM_DATETIME_PATTERN); + int count = 24 * 60 / 15; + if ((float) beforeDeal.size() / (float) count < 0.9) { + Set dates = beforeDeal.keySet(); + for (Date tempDate : dates) { + UserDataExcel UserDataExcel = beforeDeal.get(tempDate); + if (UserDataExcel.getWork() != null) { + lack.add(UserDataExcel); + } + } + RespUserDataIntegrity respUserDataIntegrity = new RespUserDataIntegrity(); + respUserDataIntegrity.setIntegrity(BigDecimal.valueOf((double) lack.size() / 96.0)); + respUserDataIntegrity.setLackDate(LocalDateTimeUtil.parseDate(time, DatePattern.NORM_DATE_PATTERN)); + respUserDataIntegrity.setUserName(userFlag[2]); + respUserDataIntegrity.setLineNo(userFlag[1]); + respUserDataIntegrity.setUserNo(userFlag[0]); + result.setLack(lack); + result.setRespUserDataIntegrity(respUserDataIntegrity); + return result; + } else { + for (int i = 0; i < count; i++) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.add(Calendar.MINUTE, step * i); + UserDataExcel UserDataExcel = beforeDeal.get(calendar.getTime()); + if (UserDataExcel != null && UserDataExcel.getWork() != null) { + completed.add(UserDataExcel); + } else { + //找到前一个时间点值 + Float perValue = getPreValue(date, calendar.getTime(), beforeDeal); + //找到后一个时间点值 + Float appendValue = getAppendValue(date, count, step, calendar.getTime(), beforeDeal); + UserDataExcel temp = new UserDataExcel(); + SimpleDateFormat sdf = new SimpleDateFormat(DatePattern.NORM_DATETIME_PATTERN); + temp.setTime(sdf.format(calendar.getTime())); + temp.setUserId(userFlag[0]); + temp.setLine(userFlag[1]); + temp.setUserName(userFlag[2]); + //还需要判断前值和后值为空的情况 + if (null == perValue && null == appendValue) { + temp.setWork(new BigDecimal("0.0")); + } else if (null == perValue) { + temp.setWork(new BigDecimal(appendValue)); + } else if (null == appendValue) { + temp.setWork(new BigDecimal(perValue)); + } else { + temp.setWork(BigDecimal.valueOf((perValue + appendValue) / 2)); + } + completed.add(temp); + } + } + } + } + result.setCompleted(completed); + return result; + } + + /** + * 递归找前值 + * + * @param date 起始时间 + * @param time 当前时间 + * @param beforeDeal 处理前的数据 + */ + private Float getPreValue(Date date, Date time, Map beforeDeal) { + Float result; + if (date.equals(time)) { + return null; + } else { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(time); + calendar.add(Calendar.MINUTE, -15); + UserDataExcel temp = beforeDeal.get(calendar.getTime()); + if (temp == null || temp.getWork() == null) { + result = getPreValue(date, calendar.getTime(), beforeDeal); + } else { + result = temp.getWork().floatValue(); + } + } + return result; + } + + /** + * 递归找后置 + * + * @param date 起始时间 + * @param count 一天时间的总计数 + * @param step 间隔分钟 + * @param time 截止时间 + */ + private Float getAppendValue(Date date, int count, int step, Date time, Map beforeDeal) { + Float result; + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.set(Calendar.MINUTE, (count - 1) * step); + if (time.equals(calendar.getTime())) { + return null; + } else { + Calendar calendar1 = Calendar.getInstance(); + calendar1.setTime(time); + calendar1.add(Calendar.MINUTE, 15); + UserDataExcel temp = beforeDeal.get(calendar1.getTime()); + if (temp == null || temp.getWork() == null) { + result = getAppendValue(date, count, step, calendar1.getTime(), beforeDeal); + } else { + result = temp.getWork().floatValue(); + } + } + return result; + } + +} diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/utils/AdvanceEnumUtil.java b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/utils/AdvanceEnumUtil.java new file mode 100644 index 000000000..71a7ef3c8 --- /dev/null +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/utils/AdvanceEnumUtil.java @@ -0,0 +1,51 @@ +package com.njcn.advance.utils; + +import cn.hutool.core.util.StrUtil; +import com.njcn.advance.enums.AdvanceResponseEnum; +import com.njcn.common.pojo.enums.response.CommonResponseEnum; +import com.njcn.common.pojo.exception.BusinessException; +import com.njcn.common.pojo.response.HttpResult; +import com.njcn.common.utils.EnumUtils; +import com.njcn.device.biz.enums.DeviceResponseEnum; + +import javax.validation.constraints.NotNull; +import java.util.Objects; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2021年12月20日 10:03 + */ +public class AdvanceEnumUtil { + + + /** + * 获取UserResponseEnum实例 + */ + public static AdvanceResponseEnum getDeviceEnumResponseEnumByMessage(@NotNull Object value) { + AdvanceResponseEnum advanceResponseEnum; + try { + String message = value.toString(); + if(message.indexOf(StrUtil.C_COMMA)>0){ + value = message.substring(message.indexOf(StrUtil.C_COMMA)+1); + } + advanceResponseEnum = EnumUtils.valueOf(AdvanceResponseEnum.class, value, AdvanceResponseEnum.class.getMethod(BusinessException.GET_MESSAGE_METHOD)); + return Objects.isNull(advanceResponseEnum) ? AdvanceResponseEnum.INTERNAL_ERROR : advanceResponseEnum; + } catch (NoSuchMethodException e) { + throw new BusinessException(CommonResponseEnum.INTERNAL_ERROR); + } + } + + public static Enum getExceptionEnum(HttpResult result){ + //如果返回错误,且为内部错误,则直接抛出异常 + CommonResponseEnum commonResponseEnum = EnumUtils.getCommonResponseEnumByCode(result.getCode()); + if (commonResponseEnum == CommonResponseEnum.ADVANCE_RESPONSE_ENUM) { + return getDeviceEnumResponseEnumByMessage(result.getMessage()); + } + return commonResponseEnum; + } + + + + +} diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/utils/ResponsibilityCallDllOrSo.java b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/utils/ResponsibilityCallDllOrSo.java new file mode 100644 index 000000000..fbafc9a85 --- /dev/null +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/utils/ResponsibilityCallDllOrSo.java @@ -0,0 +1,31 @@ +package com.njcn.advance.utils; + +import com.njcn.advance.pojo.bo.responsibility.QvvrStruct; +import com.sun.jna.Library; +import com.sun.jna.Native; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年07月24日 14:12 + */ +public class ResponsibilityCallDllOrSo extends JnaCallDllOrSo { + + public static String strpath; + + public ResponsibilityCallDllOrSo(String name) { + super(name); + } + + @Override + public void setPath() { + ResponsibilityCallDllOrSo.strpath = super.getStrpath(); + } + + public interface ResponsibilityLibrary extends Library { + // 加载Lib库 + ResponsibilityCallDllOrSo.ResponsibilityLibrary INSTANTCE = (ResponsibilityCallDllOrSo.ResponsibilityLibrary) Native.loadLibrary(ResponsibilityCallDllOrSo.strpath, ResponsibilityCallDllOrSo.ResponsibilityLibrary.class); + // 定义方法--->与C方法相对应 + void harm_response(QvvrStruct outData); + } +} diff --git a/pqs-advance/advance-boot/src/main/resources/harm_response.dll b/pqs-advance/advance-boot/src/main/resources/harm_response.dll new file mode 100644 index 0000000000000000000000000000000000000000..09eb4881e0d1a6f3f115f9699c5b5500107aec43 GIT binary patch literal 249344 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 getTimes(Date startTime, Date endTime) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + List result = new ArrayList<>(); + Calendar start = Calendar.getInstance(); + start.setTime(startTime); + Calendar end = Calendar.getInstance(); + end.setTime(endTime); + end.set(end.get(Calendar.YEAR), end.get(Calendar.MONTH), end.get(Calendar.DAY_OF_MONTH), 0, 0, 0); + long interval = end.getTimeInMillis() - start.getTimeInMillis(); + result.add(sdf.format(start.getTime())); + if (interval > 0) { + int days = (int) (interval / 86400000); + for (int i = 0; i < days; i++) { + start.add(Calendar.DAY_OF_MONTH, 1); + result.add(sdf.format(start.getTime())); + } + } + return result; + } + + /*** + * 将instant转为date 处理8小时误差 + * @author hongawen + * @date 2023/7/20 15:58 + * @param instant 日期 + * @return Instant + */ + public static Date instantToDate(Instant instant){ + return Date.from(instant.minusMillis(TimeUnit.HOURS.toMillis(8))); + } + + /*** + * 将date转为instant 处理8小时误差 + * @author hongawen + * @date 2023/7/20 15:58 + * @param date 日期 + * @return Instant + */ + public static Instant dateToInstant(Date date){ + return date.toInstant().plusMillis(TimeUnit.HOURS.toMillis(8)); + } + + + /** + * 根据参数返回float的四舍五入值 + * + * @param i 保留的位数 + * @param value float原值 + */ + public static Float floatRound(int i, float value) { + BigDecimal bp = new BigDecimal(value); + return bp.setScale(i, BigDecimal.ROUND_HALF_UP).floatValue(); + } + //*****************************************xuyang添加,用于App******************************************************** /** * 正则表达式字符串 diff --git a/pqs-common/common-core/src/main/java/com/njcn/common/utils/serializer/InstantDateDeserializer.java b/pqs-common/common-core/src/main/java/com/njcn/common/utils/serializer/InstantDateDeserializer.java new file mode 100644 index 000000000..4695e4b25 --- /dev/null +++ b/pqs-common/common-core/src/main/java/com/njcn/common/utils/serializer/InstantDateDeserializer.java @@ -0,0 +1,39 @@ +package com.njcn.common.utils.serializer; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.njcn.common.utils.PubUtils; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.time.Instant; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年07月24日 13:33 + */ +@Component +public class InstantDateDeserializer extends StdDeserializer { + + + public InstantDateDeserializer() { + this(null); + } + + + protected InstantDateDeserializer(Class vc) { + super(vc); + } + + + @Override + public Instant deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { + String text = p.getValueAsString(); + return PubUtils.dateToInstant(DateUtil.parse(text,DatePattern.NORM_DATETIME_PATTERN)); + } +} diff --git a/pqs-common/common-core/src/main/java/com/njcn/common/utils/serializer/InstantDateSerializer.java b/pqs-common/common-core/src/main/java/com/njcn/common/utils/serializer/InstantDateSerializer.java index f5d02ee3d..369af0e3c 100644 --- a/pqs-common/common-core/src/main/java/com/njcn/common/utils/serializer/InstantDateSerializer.java +++ b/pqs-common/common-core/src/main/java/com/njcn/common/utils/serializer/InstantDateSerializer.java @@ -42,7 +42,7 @@ public class InstantDateSerializer extends StdSerializer { if (instant == null) { return; } - String jsonValue = format.format(instant.atZone(ZoneId.systemDefault())); + String jsonValue = format.format(instant.atZone(ZoneId.of("+00:00"))); jsonGenerator.writeString(jsonValue); } } \ No newline at end of file diff --git a/pqs-common/common-oss/src/main/java/com/njcn/oss/constant/OssPath.java b/pqs-common/common-oss/src/main/java/com/njcn/oss/constant/OssPath.java index 18bc54487..cc75d2b64 100644 --- a/pqs-common/common-oss/src/main/java/com/njcn/oss/constant/OssPath.java +++ b/pqs-common/common-oss/src/main/java/com/njcn/oss/constant/OssPath.java @@ -27,6 +27,11 @@ public interface OssPath { */ String ALGORITHM="algorithm/"; + /*** + * 装置模板 + */ + String DEV_MODEL = "algorithm/devModel/"; + /*** * process模块中干扰源入网报告的上传路径 */ @@ -63,10 +68,6 @@ public interface OssPath { */ String EDDATA = "edData/"; - /*** - * 装置模板 - */ - String DEV_MODEL = "algorithm/devModel/"; /*** * 资源管理文件 @@ -93,7 +94,15 @@ public interface OssPath { */ String WIRING_DIAGRAM = "wiringDiagram/"; + /*** + * 高级算法责任量化用采数据保存地址 + */ + String RESPONSIBILITY_USER_DATA="advance/responsibility/userData/"; + /*** + * 高级算法责任量化结果数据保存地址 + */ + String RESPONSIBILITY_USER_RESULT_DATA="advance/responsibility/userData/result/"; } diff --git a/pqs-common/common-oss/src/main/java/com/njcn/oss/enums/OssResponseEnum.java b/pqs-common/common-oss/src/main/java/com/njcn/oss/enums/OssResponseEnum.java index 03af0291f..822de57dd 100644 --- a/pqs-common/common-oss/src/main/java/com/njcn/oss/enums/OssResponseEnum.java +++ b/pqs-common/common-oss/src/main/java/com/njcn/oss/enums/OssResponseEnum.java @@ -15,7 +15,7 @@ public enum OssResponseEnum { */ UPLOAD_FILE_ERROR("A00551","上传文件服务器错误,请检查数据"), DOWNLOAD_FILE_URL_ERROR("A00554","下载文件URL不存在,请检查数据"), - DOWNLOAD_FILE_STREAM_ERROR("A00555","文件服务器下载文件流异常"), + DOWNLOAD_FILE_STREAM_ERROR("A00555","文件服务器下载文件流为空"), DOWNLOAD_FILE_ERROR("A00556","文件服务器下载异常") ; diff --git a/pqs-common/common-poi/src/main/java/com/njcn/poi/util/PoiUtil.java b/pqs-common/common-poi/src/main/java/com/njcn/poi/util/PoiUtil.java index 25c367a7e..9d00a1141 100644 --- a/pqs-common/common-poi/src/main/java/com/njcn/poi/util/PoiUtil.java +++ b/pqs-common/common-poi/src/main/java/com/njcn/poi/util/PoiUtil.java @@ -1,7 +1,5 @@ package com.njcn.poi.util; -import cn.afterturn.easypoi.excel.ExcelExportUtil; -import cn.afterturn.easypoi.excel.entity.ExportParams; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.CharsetUtil; import com.njcn.common.pojo.enums.response.CommonResponseEnum; @@ -12,10 +10,7 @@ import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; import java.net.URLEncoder; -import java.util.Collection; /** * @author hongawen diff --git a/pqs-device/pq-device/pq-device-api/src/main/java/com/njcn/device/pq/pojo/po/LineDetail.java b/pqs-device/pq-device/pq-device-api/src/main/java/com/njcn/device/pq/pojo/po/LineDetail.java index ecb9b7a6b..abc5154cf 100644 --- a/pqs-device/pq-device/pq-device-api/src/main/java/com/njcn/device/pq/pojo/po/LineDetail.java +++ b/pqs-device/pq-device/pq-device-api/src/main/java/com/njcn/device/pq/pojo/po/LineDetail.java @@ -163,7 +163,7 @@ public class LineDetail{ /** * 接线图 */ - private String wiringDiagram; + private String wireDiagram; } diff --git a/pqs-device/pq-device/pq-device-api/src/main/java/com/njcn/device/pq/pojo/vo/LineDetailVO.java b/pqs-device/pq-device/pq-device-api/src/main/java/com/njcn/device/pq/pojo/vo/LineDetailVO.java index 4ab122ba4..644301113 100644 --- a/pqs-device/pq-device/pq-device-api/src/main/java/com/njcn/device/pq/pojo/vo/LineDetailVO.java +++ b/pqs-device/pq-device/pq-device-api/src/main/java/com/njcn/device/pq/pojo/vo/LineDetailVO.java @@ -18,6 +18,12 @@ public class LineDetailVO implements Serializable { @ApiModelProperty("变电站名称") private String subName; + @ApiModelProperty("终端名称") + private String devName; + + @ApiModelProperty("网络参数") + private String ip; + @ApiModelProperty("监测点名称") private String lineName; } diff --git a/pqs-device/pq-device/pq-device-boot/src/main/java/com/njcn/device/pq/mapper/mapping/LineMapper.xml b/pqs-device/pq-device/pq-device-boot/src/main/java/com/njcn/device/pq/mapper/mapping/LineMapper.xml index 7553bebcf..b9fbb3ce6 100644 --- a/pqs-device/pq-device/pq-device-boot/src/main/java/com/njcn/device/pq/mapper/mapping/LineMapper.xml +++ b/pqs-device/pq-device/pq-device-boot/src/main/java/com/njcn/device/pq/mapper/mapping/LineMapper.xml @@ -612,16 +612,20 @@ diff --git a/pqs-device/pq-device/pq-device-boot/src/main/java/com/njcn/device/pq/service/impl/LineServiceImpl.java b/pqs-device/pq-device/pq-device-boot/src/main/java/com/njcn/device/pq/service/impl/LineServiceImpl.java index 3c89b6fb3..0f18a108a 100644 --- a/pqs-device/pq-device/pq-device-boot/src/main/java/com/njcn/device/pq/service/impl/LineServiceImpl.java +++ b/pqs-device/pq-device/pq-device-boot/src/main/java/com/njcn/device/pq/service/impl/LineServiceImpl.java @@ -145,7 +145,7 @@ public class LineServiceImpl extends ServiceImpl implements Li lineDetailDataVO.setOwner(lineDetail.getOwner()); lineDetailDataVO.setOwnerDuty(lineDetail.getOwnerDuty()); lineDetailDataVO.setOwnerTel(lineDetail.getOwnerTel()); - lineDetailDataVO.setWiringDiagram(lineDetail.getWiringDiagram()); + lineDetailDataVO.setWiringDiagram(lineDetail.getWireDiagram()); return lineDetailDataVO; } diff --git a/pqs-device/pq-device/pq-device-boot/src/main/java/com/njcn/device/pq/service/impl/TerminalBaseServiceImpl.java b/pqs-device/pq-device/pq-device-boot/src/main/java/com/njcn/device/pq/service/impl/TerminalBaseServiceImpl.java index cfeaf51db..4c5c9ca7a 100644 --- a/pqs-device/pq-device/pq-device-boot/src/main/java/com/njcn/device/pq/service/impl/TerminalBaseServiceImpl.java +++ b/pqs-device/pq-device/pq-device-boot/src/main/java/com/njcn/device/pq/service/impl/TerminalBaseServiceImpl.java @@ -1678,8 +1678,8 @@ public class TerminalBaseServiceImpl extends ServiceImpl imple throw new BusinessException(DeviceResponseEnum.LINE_NO); } String[] urls = new String[0]; - if(StrUtil.isNotBlank(lineDetailValid.getWiringDiagram())){ - urls = lineDetailValid.getWiringDiagram().split(StrUtil.COMMA); + if(StrUtil.isNotBlank(lineDetailValid.getWireDiagram())){ + urls = lineDetailValid.getWireDiagram().split(StrUtil.COMMA); } if (urls.length + files.length > 2) { @@ -1699,7 +1699,7 @@ public class TerminalBaseServiceImpl extends ServiceImpl imple } LineDetail lineDetail = new LineDetail(); - lineDetail.setWiringDiagram(strBuilder.toString()); + lineDetail.setWireDiagram(strBuilder.toString()); lineDetail.setId(lineId); lineDetailMapper.updateById(lineDetail); return true; @@ -1712,11 +1712,11 @@ public class TerminalBaseServiceImpl extends ServiceImpl imple if (Objects.isNull(detail)) { throw new BusinessException(DeviceResponseEnum.LINE_NO); } - if (StrUtil.isBlank(detail.getWiringDiagram())) { + if (StrUtil.isBlank(detail.getWireDiagram())) { return result; } - String[] urlStr = detail.getWiringDiagram().split(StrUtil.COMMA); + String[] urlStr = detail.getWireDiagram().split(StrUtil.COMMA); for (String url : urlStr) { LineWiringDiagramVO lineWiringDiagramVO = new LineWiringDiagramVO(); String realUrl = fileStorageUtil.getFileUrl(url); @@ -1734,14 +1734,14 @@ public class TerminalBaseServiceImpl extends ServiceImpl imple if (Objects.isNull(detail)) { throw new BusinessException(DeviceResponseEnum.LINE_NO); } - if (StrUtil.isBlank(detail.getWiringDiagram())) { + if (StrUtil.isBlank(detail.getWireDiagram())) { throw new BusinessException(DeviceResponseEnum.LINE_WIRING_DEL); } - if (!detail.getWiringDiagram().contains(wiringDiagramName)) { + if (!detail.getWireDiagram().contains(wiringDiagramName)) { throw new BusinessException(DeviceResponseEnum.LINE_WIRING_NO); } - String[] urlArr = detail.getWiringDiagram().split(StrUtil.COMMA); + String[] urlArr = detail.getWireDiagram().split(StrUtil.COMMA); List newUrlList = Arrays.stream(urlArr).filter(s -> !s.equalsIgnoreCase(wiringDiagramName)).collect(Collectors.toList()); if (newUrlList.size() > 1) { @@ -1763,7 +1763,7 @@ public class TerminalBaseServiceImpl extends ServiceImpl imple LineDetail lineDetail = new LineDetail(); lineDetail.setId(detail.getId()); - lineDetail.setWiringDiagram(strBuilder.toString()); + lineDetail.setWireDiagram(strBuilder.toString()); lineDetailMapper.updateById(lineDetail); return true; } @@ -1774,15 +1774,15 @@ public class TerminalBaseServiceImpl extends ServiceImpl imple if (Objects.isNull(detail)) { throw new BusinessException(DeviceResponseEnum.LINE_NO); } - if (StrUtil.isBlank(detail.getWiringDiagram())) { + if (StrUtil.isBlank(detail.getWireDiagram())) { throw new BusinessException(DeviceResponseEnum.LINE_WIRING_DEL); } - if (!detail.getWiringDiagram().contains(wiringDiagramName)) { + if (!detail.getWireDiagram().contains(wiringDiagramName)) { throw new BusinessException(DeviceResponseEnum.LINE_WIRING_NO); } fileStorageUtil.deleteFile(wiringDiagramName); - String[] urlArr = detail.getWiringDiagram().split(StrUtil.COMMA); + String[] urlArr = detail.getWireDiagram().split(StrUtil.COMMA); List newUrlList = Arrays.stream(urlArr).filter(s -> !s.equalsIgnoreCase(wiringDiagramName)).collect(Collectors.toList()); StrBuilder strBuilder = new StrBuilder(); for (int i = 0; i < newUrlList.size(); i++) { @@ -1794,7 +1794,7 @@ public class TerminalBaseServiceImpl extends ServiceImpl imple } LineDetail lineDetail = new LineDetail(); lineDetail.setId(detail.getId()); - lineDetail.setWiringDiagram(strBuilder.toString()); + lineDetail.setWireDiagram(strBuilder.toString()); lineDetailMapper.updateById(lineDetail); return true; } diff --git a/pqs-gateway/src/main/resources/bootstrap.yml b/pqs-gateway/src/main/resources/bootstrap.yml index 222cecb0a..3a2befcf0 100644 --- a/pqs-gateway/src/main/resources/bootstrap.yml +++ b/pqs-gateway/src/main/resources/bootstrap.yml @@ -109,7 +109,6 @@ spring: filters: - SwaggerHeaderFilter - StripPrefix=1 - - id: process-boot uri: lb://process-boot predicates: @@ -117,7 +116,6 @@ spring: filters: - SwaggerHeaderFilter - StripPrefix=1 - - id: prepare-boot uri: lb://prepare-boot predicates: @@ -167,10 +165,10 @@ spring: filters: - SwaggerHeaderFilter - StripPrefix=1 - - id: access-boot - uri: lb://access-boot + - id: advance-boot + uri: lb://advance-boot predicates: - - Path=/access-boot/** + - Path=/advance-boot/** filters: - SwaggerHeaderFilter - StripPrefix=1 diff --git a/pqs-harmonic/harmonic-api/pom.xml b/pqs-harmonic/harmonic-api/pom.xml index 246ddc258..46f38cced 100644 --- a/pqs-harmonic/harmonic-api/pom.xml +++ b/pqs-harmonic/harmonic-api/pom.xml @@ -49,8 +49,16 @@ ${project.version} - org.influxdb - influxdb-java + com.njcn + pqs-influx + 0.0.1-SNAPSHOT + + + + com.squareup.okhttp3 + * + + com.njcn diff --git a/pqs-harmonic/harmonic-api/src/main/java/com/njcn/harmonic/api/HarmDataFeignClient.java b/pqs-harmonic/harmonic-api/src/main/java/com/njcn/harmonic/api/HarmDataFeignClient.java new file mode 100644 index 000000000..26edee404 --- /dev/null +++ b/pqs-harmonic/harmonic-api/src/main/java/com/njcn/harmonic/api/HarmDataFeignClient.java @@ -0,0 +1,28 @@ +package com.njcn.harmonic.api; + +import com.njcn.common.pojo.constant.ServerInfo; +import com.njcn.common.pojo.response.HttpResult; +import com.njcn.harmonic.api.fallback.HarmDataFeignClientFallbackFactory; +import com.njcn.harmonic.pojo.param.HistoryHarmParam; +import com.njcn.influx.pojo.dto.HarmHistoryDataDTO; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +@FeignClient( + value = ServerInfo.HARMONIC, + path = "/harmonic", + fallbackFactory = HarmDataFeignClientFallbackFactory.class, + contextId = "harmonic") +public interface HarmDataFeignClient { + + + /** + * 获取监测点信息 + * @param historyHarmParam 请求查询参数 + * @return 结果 + */ + @PostMapping("/getHistoryHarmData") + HttpResult getHistoryHarmData(@RequestBody HistoryHarmParam historyHarmParam); + +} diff --git a/pqs-harmonic/harmonic-api/src/main/java/com/njcn/harmonic/api/fallback/HarmDataFeignClientFallbackFactory.java b/pqs-harmonic/harmonic-api/src/main/java/com/njcn/harmonic/api/fallback/HarmDataFeignClientFallbackFactory.java new file mode 100644 index 000000000..c1c960724 --- /dev/null +++ b/pqs-harmonic/harmonic-api/src/main/java/com/njcn/harmonic/api/fallback/HarmDataFeignClientFallbackFactory.java @@ -0,0 +1,39 @@ +package com.njcn.harmonic.api.fallback; + +import com.njcn.common.pojo.enums.response.CommonResponseEnum; +import com.njcn.common.pojo.exception.BusinessException; +import com.njcn.common.pojo.response.HttpResult; +import com.njcn.device.biz.utils.DeviceEnumUtil; +import com.njcn.harmonic.api.HarmDataFeignClient; +import com.njcn.harmonic.pojo.param.HistoryHarmParam; +import com.njcn.influx.pojo.dto.HarmHistoryDataDTO; +import feign.hystrix.FallbackFactory; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年07月21日 14:31 + */ +@Slf4j +@Component +public class HarmDataFeignClientFallbackFactory implements FallbackFactory { + @Override + public HarmDataFeignClient create(Throwable throwable) { + //判断抛出异常是否为解码器抛出的业务异常 + Enum exceptionEnum = CommonResponseEnum.SERVICE_FALLBACK; + if (throwable.getCause() instanceof BusinessException) { + BusinessException businessException = (BusinessException) throwable.getCause(); + exceptionEnum = DeviceEnumUtil.getExceptionEnum(businessException.getResult()); + } + Enum finalExceptionEnum = exceptionEnum; + return new HarmDataFeignClient() { + @Override + public HttpResult getHistoryHarmData(HistoryHarmParam historyHarmParam) { + log.error("{}异常,降级处理,异常为:{}", "获取谐波历史数据", throwable.toString()); + throw new BusinessException(finalExceptionEnum); + } + }; + } +} diff --git a/pqs-harmonic/harmonic-api/src/main/java/com/njcn/harmonic/enums/HarmonicResponseEnum.java b/pqs-harmonic/harmonic-api/src/main/java/com/njcn/harmonic/enums/HarmonicResponseEnum.java index bd60e8316..c7466c90a 100644 --- a/pqs-harmonic/harmonic-api/src/main/java/com/njcn/harmonic/enums/HarmonicResponseEnum.java +++ b/pqs-harmonic/harmonic-api/src/main/java/com/njcn/harmonic/enums/HarmonicResponseEnum.java @@ -30,6 +30,8 @@ public enum HarmonicResponseEnum { REPORT_DOWNLOAD_ERROR("A00559","报表文件下载异常"), REPORT_TEMPLATE_DOWNLOAD_ERROR("A00560","报表模板下载异常"), + NO_DATA("A00561","时间范围内暂无谐波数据"), + INSUFFICIENCY_OF_INTEGRITY("A00561","时间范围内谐波数据完整性不足"), ; private final String code; diff --git a/pqs-harmonic/harmonic-api/src/main/java/com/njcn/harmonic/pojo/param/HistoryHarmParam.java b/pqs-harmonic/harmonic-api/src/main/java/com/njcn/harmonic/pojo/param/HistoryHarmParam.java new file mode 100644 index 000000000..73fe9cbee --- /dev/null +++ b/pqs-harmonic/harmonic-api/src/main/java/com/njcn/harmonic/pojo/param/HistoryHarmParam.java @@ -0,0 +1,54 @@ +package com.njcn.harmonic.pojo.param; + +import com.njcn.common.pojo.constant.PatternRegex; +import com.njcn.harmonic.constant.HarmonicValidMessage; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import java.io.Serializable; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年07月19日 09:23 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class HistoryHarmParam implements Serializable { + + + @ApiModelProperty("开始时间") + @NotBlank(message = HarmonicValidMessage.DATA_NOT_BLANK) + @Pattern(regexp = PatternRegex.TIME_FORMAT, message = "时间格式错误") + private String searchBeginTime; + + @ApiModelProperty("结束时间") + @NotBlank(message = HarmonicValidMessage.DATA_NOT_BLANK) + @Pattern(regexp = PatternRegex.TIME_FORMAT, message = "时间格式错误") + private String searchEndTime; + + @NotBlank(message = HarmonicValidMessage.DATA_NOT_BLANK) + @ApiModelProperty("监测点索引") + private String lineId; + + + @Max(1) + @Min(0) + @ApiModelProperty("0-电流 1-电压") + private int type; + + @Max(50) + @Min(2) + @ApiModelProperty("谐波次数") + private Integer time; + + + +} diff --git a/pqs-harmonic/harmonic-api/src/main/java/com/njcn/harmonic/pojo/po/LimitTarget.java b/pqs-harmonic/harmonic-api/src/main/java/com/njcn/harmonic/pojo/po/LimitTarget.java index 471166db7..9d8d5c69c 100644 --- a/pqs-harmonic/harmonic-api/src/main/java/com/njcn/harmonic/pojo/po/LimitTarget.java +++ b/pqs-harmonic/harmonic-api/src/main/java/com/njcn/harmonic/pojo/po/LimitTarget.java @@ -1,5 +1,7 @@ package com.njcn.harmonic.pojo.po; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.njcn.common.utils.serializer.InstantDateSerializer; import lombok.Data; import org.influxdb.annotation.Column; import org.influxdb.annotation.Measurement; @@ -18,6 +20,7 @@ import java.time.Instant; public class LimitTarget { @Column(name = "time") + @JsonSerialize(using = InstantDateSerializer.class) private Instant time; @Column(name = "line_id") diff --git a/pqs-harmonic/harmonic-boot/pom.xml b/pqs-harmonic/harmonic-boot/pom.xml index f363b0aa1..d20f08edd 100644 --- a/pqs-harmonic/harmonic-boot/pom.xml +++ b/pqs-harmonic/harmonic-boot/pom.xml @@ -27,32 +27,12 @@ com.njcn common-web ${project.version} - - - - - - - - - - - - - - com.njcn common-swagger ${project.version} - - com.njcn - common-influxDB - ${project.version} - compile - com.njcn pq-device-api @@ -67,28 +47,34 @@ com.njcn user-api 1.0.0 - compile com.njcn event-api ${project.version} - - - - - - org.springframework.boot - spring-boot-configuration-processor - true - - - com.njcn common-oss ${project.version} + + + com.squareup.okhttp3 + okhttp + + + + + + com.squareup.okhttp3 + okhttp + 4.8.1 + + + + com.squareup.okhttp3 + logging-interceptor + 4.8.1 diff --git a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/HarmonicBootApplication.java b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/HarmonicBootApplication.java index b68a35a36..2e7a42aa6 100644 --- a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/HarmonicBootApplication.java +++ b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/HarmonicBootApplication.java @@ -5,6 +5,7 @@ import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.context.annotation.DependsOn; /** @@ -16,6 +17,7 @@ import org.springframework.cloud.openfeign.EnableFeignClients; * @date 2021/12/27 11:38 */ @Slf4j +@DependsOn("proxyMapperRegister") @MapperScan("com.njcn.**.mapper") @EnableFeignClients(basePackages = "com.njcn") @SpringBootApplication(scanBasePackages = "com.njcn") diff --git a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/controller/AnalyzeController.java b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/controller/AnalyzeController.java index 32149e277..e53e1e893 100644 --- a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/controller/AnalyzeController.java +++ b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/controller/AnalyzeController.java @@ -8,12 +8,10 @@ import com.njcn.common.pojo.enums.response.CommonResponseEnum; import com.njcn.common.pojo.response.HttpResult; import com.njcn.common.utils.HttpResultUtil; import com.njcn.common.utils.LogUtil; -import com.njcn.device.pq.pojo.dto.PollutionLineDTO; import com.njcn.harmonic.pojo.param.HarmonicPublicParam; import com.njcn.harmonic.pojo.vo.*; import com.njcn.harmonic.service.IAnalyzeService; import com.njcn.harmonic.service.IHarmonicService; -import com.njcn.harmonic.service.IPollutionService; import com.njcn.poi.util.PoiUtil; import com.njcn.web.controller.BaseController; import io.swagger.annotations.Api; @@ -44,8 +42,6 @@ public class AnalyzeController extends BaseController { private final IAnalyzeService IAnalyzeService; - private final IPollutionService pollutionService; - private final IHarmonicService harmonicService; diff --git a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/controller/HistoryResultController.java b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/controller/HistoryResultController.java index be4c3d682..6819549e0 100644 --- a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/controller/HistoryResultController.java +++ b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/controller/HistoryResultController.java @@ -6,11 +6,13 @@ import com.njcn.common.pojo.enums.response.CommonResponseEnum; import com.njcn.common.pojo.param.StatisticsBizBaseParam; import com.njcn.common.pojo.response.HttpResult; import com.njcn.common.utils.HttpResultUtil; +import com.njcn.harmonic.pojo.param.HistoryHarmParam; import com.njcn.harmonic.pojo.param.HistoryParam; import com.njcn.harmonic.pojo.param.NormHistoryParam; import com.njcn.harmonic.pojo.vo.HistoryDataResultVO; import com.njcn.harmonic.pojo.vo.StatHarmonicOrgVO; import com.njcn.harmonic.service.HistoryResultService; +import com.njcn.influx.pojo.dto.HarmHistoryDataDTO; import com.njcn.web.controller.BaseController; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; @@ -70,4 +72,14 @@ public class HistoryResultController extends BaseController { return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, list, methodDescribe); } + + @OperateInfo(info = LogEnum.BUSINESS_COMMON) + @PostMapping("/getHistoryHarmData") + @ApiOperation("获取谐波历史数据") + @ApiImplicitParam(name = "historyHarmParam", value = "谐波历史数据请求参数", required = true) + public HttpResult getHistoryHarmData(@RequestBody @Validated HistoryHarmParam historyHarmParam) { + String methodDescribe = getMethodDescribe("getHistoryHarmData"); + HarmHistoryDataDTO harmHistoryDataDTO = historyResultService.getHistoryHarmData(historyHarmParam); + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, harmHistoryDataDTO, methodDescribe); + } } diff --git a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/controller/PollutionSubstationController.java b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/controller/PollutionSubstationController.java index 5f2afdec7..031d4bb10 100644 --- a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/controller/PollutionSubstationController.java +++ b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/controller/PollutionSubstationController.java @@ -12,7 +12,6 @@ import com.njcn.harmonic.pojo.param.HarmonicPublicParam; import com.njcn.harmonic.pojo.param.PollutionSubstationQuryParam; import com.njcn.harmonic.pojo.vo.PollutionSubstationVO; import com.njcn.harmonic.pojo.vo.PollutionVO; -import com.njcn.harmonic.service.IPollutionService; import com.njcn.harmonic.service.PollutionSubstationService; import com.njcn.web.controller.BaseController; import io.swagger.annotations.Api; @@ -46,8 +45,6 @@ public class PollutionSubstationController extends BaseController { private final PollutionSubstationService pollutionSubstationService; - private final IPollutionService pollutionService; - @OperateInfo(info = LogEnum.BUSINESS_COMMON) @PostMapping("/getPollutionSubstationData") diff --git a/pqs-harmonic/harmonic-api/src/main/java/com/njcn/harmonic/pojo/vo/QueryResultLimitVO.java b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/pojo/QueryResultLimitVO.java similarity index 63% rename from pqs-harmonic/harmonic-api/src/main/java/com/njcn/harmonic/pojo/vo/QueryResultLimitVO.java rename to pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/pojo/QueryResultLimitVO.java index 2a5809ed8..b64ead263 100644 --- a/pqs-harmonic/harmonic-api/src/main/java/com/njcn/harmonic/pojo/vo/QueryResultLimitVO.java +++ b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/pojo/QueryResultLimitVO.java @@ -1,5 +1,6 @@ -package com.njcn.harmonic.pojo.vo; +package com.njcn.harmonic.pojo; +import com.njcn.influx.pojo.bo.HarmonicHistoryData; import lombok.Data; import org.influxdb.dto.QueryResult; @@ -7,13 +8,14 @@ import java.io.Serializable; import java.util.List; /** - * @author denghuajun - * @date 2022/3/15 - * 存值 + * @author denghuajun + * @date 2022/3/15 + * 存值 */ @Data public class QueryResultLimitVO implements Serializable { - private QueryResult queryResult; + private QueryResult queryResult; + private List harmonicHistoryDataList; private Float topLimit; private Float lowerLimit; private String lineName; diff --git a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/HistoryResultService.java b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/HistoryResultService.java index 21abaf40c..3934d60ce 100644 --- a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/HistoryResultService.java +++ b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/HistoryResultService.java @@ -1,10 +1,12 @@ package com.njcn.harmonic.service; import com.njcn.common.pojo.param.StatisticsBizBaseParam; +import com.njcn.harmonic.pojo.param.HistoryHarmParam; import com.njcn.harmonic.pojo.param.HistoryParam; import com.njcn.harmonic.pojo.param.NormHistoryParam; import com.njcn.harmonic.pojo.vo.HistoryDataResultVO; import com.njcn.harmonic.pojo.vo.StatHarmonicOrgVO; +import com.njcn.influx.pojo.dto.HarmHistoryDataDTO; import java.util.List; @@ -36,4 +38,13 @@ public interface HistoryResultService { * @return 结果 */ List getHarmonicProportion(StatisticsBizBaseParam statisticsBizBaseParam); + + /*** + * 按次、监测点获取指定历史谐波数据 + * @author hongawen + * @date 2023/7/19 9:56 + * @param historyHarmParam 请求历史谐波数据参数 + * @return HarmHistoryDataDTO + */ + HarmHistoryDataDTO getHistoryHarmData(HistoryHarmParam historyHarmParam); } diff --git a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/IPollutionService.java b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/IPollutionService.java deleted file mode 100644 index 82591c8e7..000000000 --- a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/IPollutionService.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.njcn.harmonic.service; - -import com.njcn.device.pq.pojo.dto.PollutionLineDTO; -import com.njcn.device.pq.pojo.dto.PollutionSubstationDTO; -import com.njcn.harmonic.pojo.param.HarmonicPublicParam; -import com.njcn.harmonic.pojo.vo.PollutionVO; - -import java.util.List; - -/** - * @author 徐扬 - */ -public interface IPollutionService { - - /** - * 功能描述: 获取部门变电站关系 - * - * @param param - * @return java.util.List - * @author xy - * @date 2022/2/21 16:48 - */ - // List getDeptSubstationRelations(HarmonicPublicParam param); - - /** - * 功能描述: 根据部门获取变电站详情 - * - * @param param 部门参数 - * @return java.util.List - * @author xy - * @date 2022/2/21 20:51 - */ - //List getSubstationInfoById(HarmonicPublicParam param); - - /** - * 功能描述: 根据变电站获取监测点详情 - * @param param - * @return java.util.List - * @author xy - * @date 2022/2/21 20:51 - */ - // List getLineInfoById(HarmonicPublicParam param); - - /** - * 功能描述:获取排名前10的监测点 - * @param param - * - * @return java.util.List - * @author xy - * @date 2022/2/22 10:04 - */ - // List getLineRank(HarmonicPublicParam param); -} diff --git a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/PollutionSubstationService.java b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/PollutionSubstationService.java index 8130557d2..480b5ce3c 100644 --- a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/PollutionSubstationService.java +++ b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/PollutionSubstationService.java @@ -56,15 +56,6 @@ public interface PollutionSubstationService extends IService getLineInfoById(HarmonicPublicParam param); - /*** - * 获取前十监测点排名 - * @author wr - * @date 2023-03-03 16:21 - * @param param - * @return List - */ - List getLineRank(HarmonicPublicParam param); - List getLineRankTop10(HarmonicPublicParam param); diff --git a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/AnalyzeServiceImpl.java b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/AnalyzeServiceImpl.java index 7986ac388..eb0b8eca8 100644 --- a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/AnalyzeServiceImpl.java +++ b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/AnalyzeServiceImpl.java @@ -36,7 +36,6 @@ import com.njcn.harmonic.pojo.vo.OverAreaLimitVO; import com.njcn.harmonic.pojo.vo.OverAreaVO; import com.njcn.harmonic.pojo.vo.WarningSubstationVO; import com.njcn.harmonic.service.IAnalyzeService; -import com.njcn.influxdb.utils.InfluxDbUtils; import com.njcn.poi.excel.ExcelUtil; import com.njcn.system.api.DicDataFeignClient; import com.njcn.system.enums.DicDataEnum; @@ -76,8 +75,6 @@ public class AnalyzeServiceImpl implements IAnalyzeService { private final HarmonicServiceImpl harmonicService; - private final InfluxDbUtils influxDbUtils; - private final LineFeignClient lineFeignClient; private final RStatLimitRateDMapper rateDMapper; @@ -371,147 +368,6 @@ public class AnalyzeServiceImpl implements IAnalyzeService { return page; } return page; -// if (!CollectionUtils.isEmpty(lineList)){ -// page.setTotal(lineList.size()); -// int pages = (int)Math.ceil(lineList.size()*1.0/param.getPageSize()); -// page.setPages(pages); -// List> pageList = Lists.partition(lineList,param.getPageSize()); -// List temList = pageList.get(param.getPageNum()-1); -// List limitTargetList = getOverDays(temList,param.getSearchBeginTime(),param.getSearchEndTime()); -// Map> map = limitTargetList.stream().collect(Collectors.groupingBy(LimitTarget::getLineId)); -// PollutionParamDTO pollutionParamDTO = new PollutionParamDTO(); -// pollutionParamDTO.setLineList(temList); -// List overLimitLineList = lineFeignClient.getOverLimitLineInfo(pollutionParamDTO).getData(); -// overLimitLineList.forEach(item->{ -// int overDay=0,freqOverDay=0,volDevOverDay=0,threeUnbalance=0,flickerOverDay=0,negativeOverDay=0,harmVolOverDay=0,volDisOverDay=0,volContainOverDay=0,harmCurOverDay=0,intHarmOverDay=0; -// int overVolThreeTimes=0,overVolFiveTimes=0,overVolSevenTimes=0,overVolElevenTimes=0,overVolThirteenTimes=0,overVolTwentyThreeTimes=0,overVolTwentyFiveTimes=0,overVolOtherTimes=0; -// int overCurThreeTimes=0,overCurFiveTimes=0,overCurSevenTimes=0,overCurElevenTimes=0,overCurThirteenTimes=0,overCurTwentyThreeTimes=0,overCurTwentyFiveTimes=0,overCurOtherTimes=0; -// MonitorOverLimitVO monitorOverLimitVO = new MonitorOverLimitVO(); -// BeanUtil.copyProperties(item,monitorOverLimitVO); -// List l1 = map.get(item.getId()); -// if (!CollectionUtils.isEmpty(l1)) { -// for (LimitTarget item2 : l1) { -// if (item2.getFreqDevOverTime()+item2.getVoltageDevOverTime()+item2.getUBalanceOverTime()+item2.getFlickerOverTime()+item2.getINegOverTime()+item2.getUAberranceOverTime()+item2.getUHarmAllOverTime()+item2.getIHarmAllOverTime()+item2.getInuharmAllOverTime() > 0){ -// overDay++; -// } -// if (item2.getFreqDevOverTime()>0){ -// freqOverDay++; -// } -// if (item2.getVoltageDevOverTime()>0){ -// volDevOverDay++; -// } -// if (item2.getUBalanceOverTime()>0){ -// threeUnbalance++; -// } -// if (item2.getFlickerOverTime()>0){ -// flickerOverDay++; -// } -// if (item2.getINegOverTime()>0){ -// negativeOverDay++; -// } -// if (item2.getUAberranceOverTime()+item2.getUHarmAllOverTime()>0){ -// harmVolOverDay++; -// } -// if (item2.getUAberranceOverTime()>0){ -// volDisOverDay++; -// } -// if (item2.getUHarmAllOverTime()>0){ -// volContainOverDay++; -// } -// if (item2.getIHarmAllOverTime()>0){ -// harmCurOverDay++; -// } -// if (item2.getInuharmAllOverTime()>0){ -// intHarmOverDay++; -// } -// if (item2.getUHarm3OverTime()>0){ -// overVolThreeTimes++; -// } -// if (item2.getUHarm5OverTime()>0){ -// overVolFiveTimes++; -// } -// if (item2.getUHarm7OverTime()>0){ -// overVolSevenTimes++; -// } -// if (item2.getUHarm11OverTime()>0){ -// overVolElevenTimes++; -// } -// if (item2.getUHarm13OverTime()>0){ -// overVolThirteenTimes++; -// } -// if (item2.getUHarm23OverTime()>0){ -// overVolTwentyThreeTimes++; -// } -// if (item2.getUHarm25OverTime()>0){ -// overVolTwentyFiveTimes++; -// } -// if (item2.getUHarmAllOverTime()>0){ -// overVolOtherTimes++; -// } -// if (item2.getIHarm3OverTime()>0){ -// overCurThreeTimes++; -// } -// if (item2.getIHarm5OverTime()>0){ -// overCurFiveTimes++; -// } -// if (item2.getIHarm7OverTime()>0){ -// overCurSevenTimes++; -// } -// if (item2.getIHarm11OverTime()>0){ -// overCurElevenTimes++; -// } -// if (item2.getIHarm13OverTime()>0){ -// overCurThirteenTimes++; -// } -// if (item2.getIHarm23OverTime()>0){ -// overCurTwentyThreeTimes++; -// } -// if (item2.getIHarm25OverTime()>0){ -// overCurTwentyFiveTimes++; -// } -// if (item2.getIHarmAllOverTime()>0){ -// overCurOtherTimes++; -// } -// } -// } -// monitorOverLimitVO.setOverDay(overDay); -// monitorOverLimitVO.setFreqOverDay(freqOverDay); -// monitorOverLimitVO.setVolDevOverDay(volDevOverDay); -// monitorOverLimitVO.setThreeUnbalance(threeUnbalance); -// monitorOverLimitVO.setFlickerOverDay(flickerOverDay); -// monitorOverLimitVO.setNegativeOverDay(negativeOverDay); -// monitorOverLimitVO.setHarmVolOverDay(harmVolOverDay); -// monitorOverLimitVO.setVolDisOverDay(volDisOverDay); -// monitorOverLimitVO.setVolContainOverDay(volContainOverDay); -// monitorOverLimitVO.setHarmCurOverDay(harmCurOverDay); -// monitorOverLimitVO.setIntHarmOverDay(intHarmOverDay); -// monitorOverLimitVO.setOverVolThreeTimes(overVolThreeTimes); -// monitorOverLimitVO.setOverVolFiveTimes(overVolFiveTimes); -// monitorOverLimitVO.setOverVolSevenTimes(overVolSevenTimes); -// monitorOverLimitVO.setOverVolElevenTimes(overVolElevenTimes); -// monitorOverLimitVO.setOverVolThirteenTimes(overVolThirteenTimes); -// monitorOverLimitVO.setOverVolTwentyThreeTimes(overVolTwentyThreeTimes); -// monitorOverLimitVO.setOverVolTwentyFiveTimes(overVolTwentyFiveTimes); -// monitorOverLimitVO.setOverVolOtherTimes(overVolOtherTimes); -// monitorOverLimitVO.setOverCurThreeTimes(overCurThreeTimes); -// monitorOverLimitVO.setOverCurFiveTimes(overCurFiveTimes); -// monitorOverLimitVO.setOverCurSevenTimes(overCurSevenTimes); -// monitorOverLimitVO.setOverCurElevenTimes(overCurElevenTimes); -// monitorOverLimitVO.setOverCurThirteenTimes(overCurThirteenTimes); -// monitorOverLimitVO.setOverCurTwentyThreeTimes(overCurTwentyThreeTimes); -// monitorOverLimitVO.setOverCurTwentyFiveTimes(overCurTwentyFiveTimes); -// monitorOverLimitVO.setOverCurOtherTimes(overCurOtherTimes); -// result.add(monitorOverLimitVO); -// }); -// } -// if (!CollectionUtils.isEmpty(result)){ -// List recordList = new ArrayList<>(); -// //默认 根据在线监测点个数 倒叙排序 -// recordList = result.stream().sorted(Comparator.comparing(MonitorOverLimitVO::getOverDay).reversed()).collect(Collectors.toList()); -// page.setRecords(recordList); -// return page; -// } -// return page; } private boolean filterNotQualifiedHarmVolData(RStatLimitTargetDPO t) { @@ -781,64 +637,4 @@ public class AnalyzeServiceImpl implements IAnalyzeService { condMap.put(DicDataEnum.VOLTAGE_RISE.getCode(), dictMap.get(DicDataEnum.VOLTAGE_RISE.getCode())); //电压暂升 return eventDetailFeignClient.getEventDetailCount(condMap).getData(); } - - public List getOverDays(List list, String startTime, String endTime) { - StringBuilder stringBuilder = new StringBuilder(); - StringBuilder stringBuilder1 = new StringBuilder(); - stringBuilder.append(Param.TIME + " >= '").append(startTime).append("' and ").append(Param.TIME).append(" <= '").append(endTime).append("' and ("); - for (int i = 0; i < list.size(); i++) { - if (list.size() - i != 1) { - stringBuilder.append(Param.LINE_ID + "='").append(list.get(i)).append("' or "); - } else { - stringBuilder.append(Param.LINE_ID + "='").append(list.get(i)).append("')"); - } - } - stringBuilder.append(" group by line_id tz('Asia/Shanghai')"); - stringBuilder1.append("freq_dev_overtime AS freq_dev_overtime,voltage_dev_overtime AS voltage_dev_overtime,ubalance_overtime AS ubalance_overtime,flicker_overtime AS flicker_overtime,i_neg_overtime AS i_neg_overtime,uaberrance_overtime AS uaberrance_overtime,"); - for (int i = 2; i <= 25; i++) { - if (i == 25) { - stringBuilder1.append("uharm_").append(i).append("_overtime AS uharm_all_overtime,"); - } else { - stringBuilder1.append("uharm_").append(i).append("_overtime+"); - } - } - for (int i = 2; i <= 25; i++) { - if (i == 25) { - stringBuilder1.append("iharm_").append(i).append("_overtime AS iharm_all_overtime,"); - } else { - stringBuilder1.append("iharm_").append(i).append("_overtime+"); - } - } - for (int i = 1; i <= 16; i++) { - if (i == 16) { - stringBuilder1.append("inuharm_").append(i).append("_overtime AS inuharm_all_overtime,"); - } else { - stringBuilder1.append("inuharm_").append(i).append("_overtime+"); - } - } - stringBuilder1.append("uharm_3_overtime,uharm_5_overtime,uharm_7_overtime,uharm_11_overtime,uharm_13_overtime,uharm_23_overtime,uharm_25_overtime,"); - for (int i = 2; i <= 25; i++) { - if (i != 3 && i != 5 && i != 7 && i != 11 && i != 13 && i != 23 && i != 25) { - if (i == 24) { - stringBuilder1.append("uharm_").append(i).append("_overtime AS uOtherTimes,"); - } else { - stringBuilder1.append("uharm_").append(i).append("_overtime+"); - } - } - } - stringBuilder1.append("iharm_3_overtime,iharm_5_overtime,iharm_7_overtime,iharm_11_overtime,iharm_13_overtime,iharm_23_overtime,iharm_25_overtime,"); - for (int i = 2; i <= 25; i++) { - if (i != 3 && i != 5 && i != 7 && i != 11 && i != 13 && i != 23 && i != 25) { - if (i == 24) { - stringBuilder1.append("iharm_").append(i).append("_overtime AS iOtherTimes"); - } else { - stringBuilder1.append("iharm_").append(i).append("_overtime+"); - } - } - } - String sql = "select " + stringBuilder1 + " from limit_target where " + stringBuilder; - QueryResult sqlResult = influxDbUtils.query(sql); - InfluxDBResultMapper resultMapper = new InfluxDBResultMapper(); - return resultMapper.toPOJO(sqlResult, LimitTarget.class); - } } diff --git a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/AssesServiceImpl.java b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/AssesServiceImpl.java index 5aee8e996..7c99e53a7 100644 --- a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/AssesServiceImpl.java +++ b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/AssesServiceImpl.java @@ -7,15 +7,10 @@ import com.njcn.harmonic.mapper.RStatComassesDMapper; import com.njcn.harmonic.pojo.po.PQSComAssesPO; import com.njcn.harmonic.pojo.vo.AssesVO; import com.njcn.harmonic.service.AssesService; -import com.njcn.harmonic.service.ComAssessService; -import com.njcn.influxdb.param.InfluxDBPublicParam; -import com.njcn.influxdb.utils.InfluxDbUtils; import com.njcn.web.utils.ComAssesUtil; import com.njcn.web.utils.PqsComasses; import lombok.AllArgsConstructor; import org.apache.commons.lang.StringUtils; -import org.influxdb.dto.QueryResult; -import org.influxdb.impl.InfluxDBResultMapper; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; @@ -32,7 +27,6 @@ import java.util.List; @AllArgsConstructor public class AssesServiceImpl implements AssesService { - private final InfluxDbUtils influxDbUtils; private final ComAssesUtil comAssesUtil; @@ -51,12 +45,9 @@ public class AssesServiceImpl implements AssesService { } /** - * influxDB相关操作 * 查询监测点的数据完整性 */ private Float getCondition(String lineList, String startTime, String endTime) { - - float synData; if (!lineList.isEmpty()) { List avgCount = rStatComassesDMapper.getAvgCount(Arrays.asList(lineList), diff --git a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/CustomReportServiceImpl.java b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/CustomReportServiceImpl.java index 3cee4988b..0ac609327 100644 --- a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/CustomReportServiceImpl.java +++ b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/CustomReportServiceImpl.java @@ -3,7 +3,6 @@ package com.njcn.harmonic.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.io.IoUtil; -import cn.hutool.core.text.StrPool; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.*; @@ -20,6 +19,10 @@ import com.njcn.harmonic.mapper.ExcelRptTempMapper; import com.njcn.harmonic.pojo.dto.ReportTemplateDTO; import com.njcn.harmonic.pojo.param.ReportSearchParam; import com.njcn.harmonic.pojo.param.ReportTemplateParam; +import com.njcn.influx.constant.InfluxDbSqlConstant; +import com.njcn.influx.pojo.constant.InfluxDBTableConstant; +import com.njcn.influx.pojo.dto.StatisticalDataDTO; +import com.njcn.influx.service.CommonService; import com.njcn.system.pojo.po.EleEpdPqd; import com.njcn.harmonic.pojo.po.ExcelRpt; import com.njcn.harmonic.pojo.po.ExcelRptTemp; @@ -28,34 +31,22 @@ import com.njcn.harmonic.pojo.vo.ReportTemplateVO; import com.njcn.harmonic.pojo.vo.ReportTreeVO; import com.njcn.harmonic.pojo.vo.SysDeptTempVO; import com.njcn.harmonic.service.CustomReportService; -import com.njcn.influxdb.param.InfluxDBSqlConstant; -import com.njcn.influxdb.param.InfluxDBTableConstant; -import com.njcn.influxdb.utils.InfluxDbUtils; import com.njcn.oss.constant.OssPath; -import com.njcn.oss.enums.OssResponseEnum; import com.njcn.oss.utils.FileStorageUtil; -import com.njcn.system.api.DicDataFeignClient; import com.njcn.user.api.DeptFeignClient; import com.njcn.user.pojo.dto.DeptDTO; import com.njcn.web.utils.WebUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.fileupload.FileItem; -import org.apache.commons.fileupload.disk.DiskFileItemFactory; -import org.apache.tomcat.util.http.fileupload.IOUtils; import org.apache.commons.lang.StringUtils; import org.influxdb.dto.QueryResult; import org.springframework.beans.BeanUtils; -import org.springframework.http.MediaType; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; -import org.springframework.web.multipart.commons.CommonsMultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.*; -import java.net.URL; -import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -83,16 +74,12 @@ public class CustomReportServiceImpl implements CustomReportService { private final EleEpdMapper eleEpdMapper; - private final InfluxDbUtils influxDbUtils; - - private final DicDataFeignClient dicDataFeignClient; - private final DeptTempMapper deptTempMapper; - private final GeneralInfo generalInfo; - private final FileStorageUtil fileStorageUtil; + private final CommonService commonService; + @Override public boolean addCustomReportTemplate(ReportTemplateParam reportTemplateParam) { @@ -406,7 +393,6 @@ public class CustomReportServiceImpl implements CustomReportService { reportTemplateDTO.setStatMethod(vItem[1].toUpperCase()); reportTemplateDTO.setClassId(vItem[2]); } - reportTemplateDTOList.add(reportTemplateDTO); } } @@ -421,15 +407,15 @@ public class CustomReportServiceImpl implements CustomReportService { if (CollUtil.isNotEmpty(reportTemplateDTOList)) { //开始组织sql reportTemplateDTOList.stream().forEach(data -> { - StringBuilder sql = new StringBuilder(InfluxDBSqlConstant.SELECT); - if (InfluxDBTableConstant.MAX.equalsIgnoreCase(data.getStatMethod())) { - assSql(data, sql, endList, InfluxDBSqlConstant.MAX, reportSearchParam); - } else if (InfluxDBTableConstant.MIN.equalsIgnoreCase(data.getStatMethod())) { - assSql(data, sql, endList, InfluxDBSqlConstant.MIN, reportSearchParam); - } else if (InfluxDBTableConstant.AVG.equalsIgnoreCase(data.getStatMethod())) { - assSql(data, sql, endList, InfluxDBSqlConstant.AVG, reportSearchParam); - } else if (InfluxDBTableConstant.CP95.equalsIgnoreCase(data.getStatMethod())) { - assSql(data, sql, endList, InfluxDBSqlConstant.CP95, reportSearchParam); + StringBuilder sql = new StringBuilder(InfluxDbSqlConstant.SELECT); + if (InfluxDbSqlConstant.MAX.equalsIgnoreCase(data.getStatMethod())) { + assSql(data, sql, endList, InfluxDbSqlConstant.MAX, reportSearchParam); + } else if (InfluxDbSqlConstant.MIN.equalsIgnoreCase(data.getStatMethod())) { + assSql(data, sql, endList, InfluxDbSqlConstant.MIN, reportSearchParam); + } else if (InfluxDbSqlConstant.AVG.equalsIgnoreCase(data.getStatMethod())) { + assSql(data, sql, endList, InfluxDbSqlConstant.AVG, reportSearchParam); + } else if (InfluxDbSqlConstant.CP95.equalsIgnoreCase(data.getStatMethod())) { + assSql(data, sql, endList, InfluxDbSqlConstant.CP95, reportSearchParam); } }); } @@ -492,93 +478,68 @@ public class CustomReportServiceImpl implements CustomReportService { //sql拼接示例:select MAX(IHA2) as IHA2 from power_quality_data where Phase = 'A' and LineId='1324564568' and Stat_Method='max' tz('Asia/Shanghai') //cp95函数特殊处理 PERCENTILE(field_key, N) - if (InfluxDBSqlConstant.CP95.equals(method)) { + if (InfluxDbSqlConstant.CP95.equals(method)) { sql.append(method) - .append(InfluxDBSqlConstant.LBK) + .append(InfluxDbSqlConstant.LBK) .append(data.getTemplateName()) - .append(InfluxDBSqlConstant.NUM_95) - .append(InfluxDBSqlConstant.RBK) - .append(InfluxDBSqlConstant.AS_VALUE); + .append(InfluxDbSqlConstant.NUM_95) + .append(InfluxDbSqlConstant.RBK) + .append(InfluxDbSqlConstant.AS_VALUE); } else { sql.append(method) - .append(InfluxDBSqlConstant.LBK) + .append(InfluxDbSqlConstant.LBK) .append(data.getTemplateName()) - .append(InfluxDBSqlConstant.RBK) - .append(InfluxDBSqlConstant.AS_VALUE); + .append(InfluxDbSqlConstant.RBK) + .append(InfluxDbSqlConstant.AS_VALUE); } - sql.append(InfluxDBSqlConstant.FROM) + sql.append(InfluxDbSqlConstant.FROM) .append(data.getClassId()) - .append(InfluxDBSqlConstant.WHERE) + .append(InfluxDbSqlConstant.WHERE) .append(InfluxDBTableConstant.LINE_ID) - .append(InfluxDBSqlConstant.EQ) - .append(InfluxDBSqlConstant.QM) + .append(InfluxDbSqlConstant.EQ) + .append(InfluxDbSqlConstant.QM) .append(reportSearchParam.getLineId()) - .append(InfluxDBSqlConstant.QM); + .append(InfluxDbSqlConstant.QM); //相别特殊处理 if (!InfluxDBTableConstant.NO_PHASE.equals(data.getPhase())) { - sql.append(InfluxDBSqlConstant.AND) + sql.append(InfluxDbSqlConstant.AND) .append(InfluxDBTableConstant.PHASIC_TYPE) - .append(InfluxDBSqlConstant.EQ) - .append(InfluxDBSqlConstant.QM) + .append(InfluxDbSqlConstant.EQ) + .append(InfluxDbSqlConstant.QM) .append(data.getPhase()) - .append(InfluxDBSqlConstant.QM); + .append(InfluxDbSqlConstant.QM); } //data_flicker、data_fluc、data_plt 无 value_type if (!InfluxDBTableConstant.DATA_FLICKER.equals(data.getClassId()) && !InfluxDBTableConstant.DATA_FLUC.equals(data.getClassId()) && !InfluxDBTableConstant.DATA_PLT.equals(data.getClassId())) { - sql.append(InfluxDBSqlConstant.AND) + sql.append(InfluxDbSqlConstant.AND) .append(InfluxDBTableConstant.VALUE_TYPE) - .append(InfluxDBSqlConstant.EQ) - .append(InfluxDBSqlConstant.QM) + .append(InfluxDbSqlConstant.EQ) + .append(InfluxDbSqlConstant.QM) .append(data.getStatMethod()) - .append(InfluxDBSqlConstant.QM); + .append(InfluxDbSqlConstant.QM); } //频率和频率偏差仅统计T相 if(data.getTemplateName().equals("freq_dev") || data.getTemplateName().equals("freq")){ - sql.append(InfluxDBSqlConstant.AND) + sql.append(InfluxDbSqlConstant.AND) .append(InfluxDBTableConstant.PHASIC_TYPE) - .append(InfluxDBSqlConstant.EQ) + .append(InfluxDbSqlConstant.EQ) .append(InfluxDBTableConstant.PHASE_TYPE_T); } - //时间范围处理 sql - .append(InfluxDBSqlConstant.AND) - .append(InfluxDBSqlConstant.TIME).append(InfluxDBSqlConstant.GE).append(InfluxDBSqlConstant.QM).append(reportSearchParam.getStartTime()).append(InfluxDBSqlConstant.START_TIME).append(InfluxDBSqlConstant.QM) - .append(InfluxDBSqlConstant.AND) - .append(InfluxDBSqlConstant.TIME).append(InfluxDBSqlConstant.LT).append(InfluxDBSqlConstant.QM).append(reportSearchParam.getEndTime()).append(InfluxDBSqlConstant.END_TIME).append(InfluxDBSqlConstant.QM); + .append(InfluxDbSqlConstant.AND) + .append(InfluxDbSqlConstant.TIME).append(InfluxDbSqlConstant.GE).append(InfluxDbSqlConstant.QM).append(reportSearchParam.getStartTime()).append(InfluxDbSqlConstant.START_TIME).append(InfluxDbSqlConstant.QM) + .append(InfluxDbSqlConstant.AND) + .append(InfluxDbSqlConstant.TIME).append(InfluxDbSqlConstant.LT).append(InfluxDbSqlConstant.QM).append(reportSearchParam.getEndTime()).append(InfluxDbSqlConstant.END_TIME).append(InfluxDbSqlConstant.QM); - sql.append(InfluxDBSqlConstant.TZ); - - if(data.getClassId().equals(InfluxDBTableConstant.DATA_PLT)){ - System.out.println(sql); - } + sql.append(InfluxDbSqlConstant.TZ); //根据不同的库表赋值 - QueryResult queryResult = influxDbUtils.query(String.valueOf(sql)); - - //剖析influx数据,填入value - List results = queryResult.getResults(); - if (results.size() != 0) { - QueryResult.Result result = results.get(0); - if (result.getSeries() != null) { - List seriess = result.getSeries(); - if (seriess.size() != 0) { - QueryResult.Series series = seriess.get(0); - List columns = series.getColumns(); - List> values = series.getValues(); - for (List columnValue : values) { - for (int i = 0; i < columnValue.size(); i++) { - if (columns.get(i).equals("value")) { - data.setValue(String.format("%.3f", columnValue.get(i))); - } - } - } - } - } - } + StatisticalDataDTO statisticalDataDTO = commonService.selectBySql(sql); + data.setValue(String.format("%.3f",statisticalDataDTO.getValue())); endList.add(data); } diff --git a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/HarmInHarmServiceImpl.java b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/HarmInHarmServiceImpl.java index c59a40053..3c3f749a1 100644 --- a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/HarmInHarmServiceImpl.java +++ b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/HarmInHarmServiceImpl.java @@ -1,5 +1,7 @@ package com.njcn.harmonic.service.impl; +import cn.hutool.core.util.StrUtil; +import com.njcn.common.utils.HarmonicTimesUtil; import com.njcn.common.utils.PubUtils; import com.njcn.device.pq.api.LineFeignClient; import com.njcn.device.biz.pojo.po.Overlimit; @@ -7,7 +9,12 @@ import com.njcn.harmonic.constant.Param; import com.njcn.harmonic.pojo.param.HarmInHarmParam; import com.njcn.harmonic.pojo.vo.HarmInHarmVO; import com.njcn.harmonic.service.HarmInHarmService; -import com.njcn.influxdb.utils.InfluxDbUtils; +import com.njcn.influx.pojo.constant.InfluxDBTableConstant; +import com.njcn.influx.pojo.po.DataHarmRateV; +import com.njcn.influx.pojo.po.DataI; +import com.njcn.influx.query.InfluxQueryWrapper; +import com.njcn.influx.service.DataHarmRateVService; +import com.njcn.influx.service.IDataIService; import lombok.AllArgsConstructor; import org.influxdb.dto.QueryResult; import org.springframework.stereotype.Service; @@ -15,6 +22,7 @@ import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * 类的介绍 @@ -29,7 +37,10 @@ public class HarmInHarmServiceImpl implements HarmInHarmService { private final LineFeignClient lineFeignClient; - private final InfluxDbUtils influxDbUtils; + private final DataHarmRateVService dataHarmRateVService; + + private final IDataIService dataIService; + @Override public HarmInHarmVO getHarmInHarmData(HarmInHarmParam harmInHarmParam) { @@ -64,47 +75,35 @@ public class HarmInHarmServiceImpl implements HarmInHarmService { */ private List getCondition(String startTime, String endTime, String lineId, Integer harmState) { List floatList = new ArrayList<>(); - QueryResult queryResult; - if (!lineId.isEmpty()) { - //组装sql语句 - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(Param.TIME + " >= '").append(startTime).append(Param.START_TIME).append("' and ").append(Param.TIME).append(" <= '").append(endTime).append(Param.END_TIME).append("' and ("); - //sql语句 - stringBuilder.append(Param.LINE_ID + "='").append(lineId).append("')"); - stringBuilder.append(" and ").append(Param.VALUETYPE + "='").append("CP95").append("'"); - String sql = ""; + if (StrUtil.isNotBlank(lineId)) { if (harmState == 0) { - sql = "SELECT MEAN(v_2) as V2, MEAN(v_3) as V3, MEAN(v_4) as V4, MEAN(v_5) as V5, MEAN(v_6) as V6, MEAN(v_7) as V7," + - " MEAN(v_8) as V8, MEAN(v_9) as V9, MEAN(v_10) as V10, MEAN(v_11) as V11, MEAN(v_12) as V12, MEAN(v_13) as V13," + - " MEAN(v_14) as V14, MEAN(v_15) as V15, MEAN(v_16) as V16, MEAN(v_17) as V17, MEAN(v_18) as V18," + - " MEAN(v_19) as V19, MEAN(v_20) as V20, MEAN(v_21) as V21," + - " MEAN(v_22) as V22, MEAN(v_23) as V23, MEAN(v_24) as V24, MEAN(v_25) as V25, MEAN(v_26) as V25, MEAN(v_27) as V27, MEAN(v_28) as V28," + - " MEAN(v_29) as V29, MEAN(v_30) as V30, MEAN(v_31) as V31, MEAN(v_32) as V32, MEAN(v_33) as V33, MEAN(v_34) as V34, MEAN(v_35) as V35," + - " MEAN(v_36) as V36, MEAN(v_37) as V37, MEAN(v_38) as V38, MEAN(v_39) as V39, MEAN(v_40) as V40, MEAN(v_41) as V41, MEAN(v_42) as V42," + - " MEAN(v_43) as V43, MEAN(v_44) as V44, MEAN(v_45) as V45, MEAN(v_46) as V46, MEAN(v_47) as V47, MEAN(v_48) as V48, MEAN(v_49) as V49," + - " MEAN(v_50) as V50 FROM data_harmrate_v WHERE " + stringBuilder.toString() + " and phasic_type !='T' order by time asc tz('Asia/Shanghai');"; + InfluxQueryWrapper influxQueryWrapper = new InfluxQueryWrapper(DataHarmRateV.class); + influxQueryWrapper.meanSamePrefixAndSuffix("v_","", HarmonicTimesUtil.harmonicTimesList(2,50,1)) + .between(DataHarmRateV::getTime,startTime,endTime) + .eq(DataHarmRateV::getLineId,lineId) + .eq(DataHarmRateV::getValueType, InfluxDBTableConstant.CP95) + .ne(DataHarmRateV::getPhaseType,InfluxDBTableConstant.PHASE_TYPE_T); + DataHarmRateV dataHarmRateV = dataHarmRateVService.getMeanAllTimesData(influxQueryWrapper); + if(Objects.nonNull(dataHarmRateV)){ + for (int i = 2; i < 51; i++) { + floatList.add(PubUtils.getValueByMethod(dataHarmRateV, "getV", i)); + } + } } else { - sql = "SELECT MEAN(i_2) as I2, MEAN(i_3) as I3, MEAN(i_4) as I4, MEAN(i_5) as I5, MEAN(i_6) as I6, MEAN(i_7) as I7," + - " MEAN(i_8) as I8, MEAN(i_9) as I9, MEAN(i_10) as I10, MEAN(i_11) as I11, MEAN(i_12) as I12, MEAN(i_13) as I13," + - " MEAN(i_14) as I14, MEAN(i_15) as I15, MEAN(i_16) as I16, MEAN(i_17) as I17, MEAN(i_18) as I18," + - " MEAN(i_19) as I19, MEAN(i_20) as I20, MEAN(i_21) as I21," + - " MEAN(i_22) as I22, MEAN(i_23) as I23, MEAN(i_24) as I24, MEAN(i_25) as I25, MEAN(i_26) as I25, MEAN(i_27) as I27, MEAN(i_28) as I28," + - " MEAN(i_29) as I29, MEAN(i_30) as I30, MEAN(i_31) as I31, MEAN(i_32) as I32, MEAN(i_33) as I33, MEAN(i_34) as I34, MEAN(i_35) as I35," + - " MEAN(i_36) as I36, MEAN(i_37) as I37, MEAN(i_38) as I38, MEAN(i_39) as I39, MEAN(i_40) as I40, MEAN(i_41) as I41, MEAN(i_42) as I42," + - " MEAN(i_43) as I43, MEAN(i_44) as I44, MEAN(i_45) as I45, MEAN(i_46) as I46, MEAN(i_47) as I47, MEAN(i_48) as I48, MEAN(i_49) as I49," + - " MEAN(i_50) as I50 FROM data_i WHERE " + stringBuilder.toString() + " and phasic_type !='T' order by time asc tz('Asia/Shanghai');"; - } - queryResult = influxDbUtils.query(sql); - if (queryResult.getResults().get(0).getSeries() != null) { - List resultList = queryResult.getResults().get(0).getSeries().get(0).getValues().get(0); - if (resultList.size() != 0) { - for (int i = 1; i < resultList.size(); i++) { - floatList.add(BigDecimal.valueOf(Float.parseFloat(resultList.get(i).toString())).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue()); + InfluxQueryWrapper influxQueryWrapper = new InfluxQueryWrapper(DataI.class); + influxQueryWrapper.meanSamePrefixAndSuffix("i_","", HarmonicTimesUtil.harmonicTimesList(2,50,1)) + .between(DataHarmRateV::getTime,startTime,endTime) + .eq(DataHarmRateV::getLineId,lineId) + .eq(DataHarmRateV::getValueType, InfluxDBTableConstant.CP95) + .ne(DataHarmRateV::getPhaseType,InfluxDBTableConstant.PHASE_TYPE_T); + DataI dataI = dataIService.getMeanAllTimesData(influxQueryWrapper); + if(Objects.nonNull(dataI)){ + for (int i = 2; i < 51; i++) { + floatList.add(PubUtils.getValueByMethod(dataI, "getI", i)); } } } } - return floatList; } } diff --git a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/HarmonicServiceImpl.java b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/HarmonicServiceImpl.java index e1534afb8..454982578 100644 --- a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/HarmonicServiceImpl.java +++ b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/HarmonicServiceImpl.java @@ -25,7 +25,6 @@ import com.njcn.harmonic.pojo.vo.HarmonicLineVO; import com.njcn.harmonic.pojo.vo.HarmonicSubstationVO; import com.njcn.harmonic.pojo.vo.PollutionVO; import com.njcn.harmonic.service.IHarmonicService; -import com.njcn.influxdb.utils.InfluxDbUtils; import com.njcn.system.enums.DicDataEnum; import com.njcn.web.utils.RequestUtil; import lombok.AllArgsConstructor; diff --git a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/HistoryResultServiceImpl.java b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/HistoryResultServiceImpl.java index f1a230415..08cf1be7f 100644 --- a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/HistoryResultServiceImpl.java +++ b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/HistoryResultServiceImpl.java @@ -1,8 +1,12 @@ package com.njcn.harmonic.service.impl; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; import com.njcn.common.pojo.constant.BizParamConstant; +import com.njcn.common.pojo.exception.BusinessException; import com.njcn.common.pojo.param.StatisticsBizBaseParam; import com.njcn.common.utils.PubUtils; import com.njcn.device.pq.api.LineFeignClient; @@ -10,46 +14,55 @@ import com.njcn.device.biz.pojo.po.Overlimit; import com.njcn.device.pq.pojo.vo.LineDetailDataVO; import com.njcn.event.api.EventDetailFeignClient; import com.njcn.event.pojo.po.EventDetail; -import com.njcn.harmonic.constant.Param; +import com.njcn.harmonic.enums.HarmonicResponseEnum; import com.njcn.harmonic.mapper.StatHarmonicOrgDMapper; import com.njcn.harmonic.mapper.StatHarmonicOrgMMapper; import com.njcn.harmonic.mapper.StatHarmonicOrgQMapper; import com.njcn.harmonic.mapper.StatHarmonicOrgYMapper; +import com.njcn.harmonic.pojo.QueryResultLimitVO; +import com.njcn.harmonic.pojo.param.HistoryHarmParam; import com.njcn.harmonic.pojo.param.HistoryParam; import com.njcn.harmonic.pojo.param.NormHistoryParam; import com.njcn.harmonic.pojo.vo.EventDetailVO; import com.njcn.harmonic.pojo.vo.HistoryDataResultVO; -import com.njcn.harmonic.pojo.vo.QueryResultLimitVO; import com.njcn.harmonic.pojo.vo.StatHarmonicOrgVO; import com.njcn.harmonic.service.HistoryResultService; -import com.njcn.influxdb.param.InfluxDBPublicParam; -import com.njcn.influxdb.utils.InfluxDbUtils; +import com.njcn.influx.imapper.CommonMapper; +import com.njcn.influx.imapper.DataHarmRateVMapper; +import com.njcn.influx.imapper.IDataIMapper; +import com.njcn.influx.pojo.bo.HarmonicHistoryData; +import com.njcn.influx.pojo.constant.InfluxDBTableConstant; +import com.njcn.influx.pojo.dto.HarmData; +import com.njcn.influx.pojo.dto.HarmHistoryDataDTO; +import com.njcn.influx.pojo.po.DataHarmRateV; +import com.njcn.influx.pojo.po.DataI; +import com.njcn.influx.query.InfluxQueryWrapper; import com.njcn.user.api.DeptFeignClient; import com.njcn.user.pojo.dto.DeptDTO; import com.njcn.web.utils.WebUtil; import lombok.AllArgsConstructor; import lombok.SneakyThrows; -import org.influxdb.dto.QueryResult; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import java.math.BigDecimal; -import java.text.DateFormat; +import java.math.RoundingMode; import java.text.SimpleDateFormat; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * @author denghuajun * @date 2022/3/14 */ +@Slf4j @Service @AllArgsConstructor public class HistoryResultServiceImpl implements HistoryResultService { - private final InfluxDbUtils influxDbUtils; - private final LineFeignClient lineFeignClient; private final EventDetailFeignClient eventDetailFeignClient; @@ -64,6 +77,13 @@ public class HistoryResultServiceImpl implements HistoryResultService { private final StatHarmonicOrgDMapper statHarmonicOrgDMapper; + private final CommonMapper commonMapper; + + private final IDataIMapper dataIMapper; + + private final DataHarmRateVMapper dataHarmRateVMapper; + + @Override public List getHistoryResult(HistoryParam historyParam) { List historyDataResultVOList = new ArrayList<>(); @@ -123,31 +143,32 @@ public class HistoryResultServiceImpl implements HistoryResultService { private HistoryDataResultVO getCondition(String startTime, String endTime, String lineId, String contion, Integer number, Integer valueType, Integer ptType) { HistoryDataResultVO historyDataResultVO = new HistoryDataResultVO(); QueryResultLimitVO queryResultLimitVO = getQueryResult(startTime, endTime, lineId, contion, number, valueType, ptType); - QueryResult queryResult = queryResultLimitVO.getQueryResult(); + List harmonicHistoryDataList = queryResultLimitVO.getHarmonicHistoryDataList(); BeanUtil.copyProperties(queryResultLimitVO, historyDataResultVO); - List list = queryResult.getResults().get(0).getSeries(); + //时间轴 List time = new ArrayList<>(); - List aValue = new ArrayList<>(); + //A相值 + List aValue; + //B相值 List bValue = new ArrayList<>(); + //C相值 List cValue = new ArrayList<>(); + //针对统计相别为T时存放的数据 List fValue = new ArrayList<>(); List> objectListData = new ArrayList<>(); - if (!CollectionUtils.isEmpty(list)) { - if (list.size() == 1) { - List> listData = queryResult.getResults().get(0).getSeries().get(0).getValues(); - for (int i = 0; i < listData.size(); i++) { - List objectList = listData.get(i); - DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX"); - TimeZone tx = TimeZone.getTimeZone("Asia/Shanghai"); - formatter.setTimeZone(tx); - Date d = formatter.parse(objectList.get(0).toString()); - time.add(d); - fValue.add(BigDecimal.valueOf(Float.parseFloat(objectList.get(1).toString())).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue()); + if (CollectionUtil.isNotEmpty(harmonicHistoryDataList)) { + //相别统计为T时,业务数据处理 + if (StrUtil.isBlank(harmonicHistoryDataList.get(0).getPhasicType()) || harmonicHistoryDataList.get(0).getPhasicType().equalsIgnoreCase("t")) { + for (HarmonicHistoryData harmonicHistoryData : harmonicHistoryDataList) { + time.add(new Date(harmonicHistoryData.getTime().toEpochMilli())); + fValue.add(BigDecimal.valueOf(harmonicHistoryData.getAValue()).setScale(4, RoundingMode.HALF_UP).floatValue()); + //返回结果有多个值,需要额外处理下 if (Integer.parseInt(contion) == 14) { - bValue.add(BigDecimal.valueOf(Float.parseFloat(objectList.get(2).toString())).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue()); - cValue.add(BigDecimal.valueOf(Float.parseFloat(objectList.get(3).toString())).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue()); + bValue.add(BigDecimal.valueOf(harmonicHistoryData.getBValue()).setScale(4, RoundingMode.HALF_UP).floatValue()); + cValue.add(BigDecimal.valueOf(harmonicHistoryData.getCValue()).setScale(4, RoundingMode.HALF_UP).floatValue()); } } + //组装二维数组 for (int i = 0; i < time.size(); i++) { List objects = new ArrayList<>(); objects.add(time.get(i)); @@ -163,28 +184,33 @@ public class HistoryResultServiceImpl implements HistoryResultService { historyDataResultVO.setMinValue(Collections.min(fValue)); historyDataResultVO.setMaxValue(Collections.max(fValue)); historyDataResultVO.setValue(objectListData); - } else { - for (int i = 0; i < list.size(); i++) { - List> values = list.get(i).getValues(); - for (int j = 0; j < values.size(); j++) { - List objectList = values.get(j); - if (i == 0) { - SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX"); - TimeZone tx = TimeZone.getTimeZone("Asia/Shanghai"); - formatter.setTimeZone(tx); - Date d = formatter.parse(objectList.get(0).toString()); - time.add(d); - aValue.add(BigDecimal.valueOf(Float.parseFloat(objectList.get(1).toString())).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue()); - } else if (i == 1) { - bValue.add(BigDecimal.valueOf(Float.parseFloat(objectList.get(1).toString())).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue()); - } else { - cValue.add(BigDecimal.valueOf(Float.parseFloat(objectList.get(1).toString())).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue()); - } - } - } + //按相别分为3组 + List aList = harmonicHistoryDataList.stream() + .filter(temp -> temp.getPhasicType().equalsIgnoreCase(InfluxDBTableConstant.PHASE_TYPE_A)) + .collect(Collectors.toList()); + List bList = harmonicHistoryDataList.stream() + .filter(temp -> temp.getPhasicType().equalsIgnoreCase(InfluxDBTableConstant.PHASE_TYPE_B)) + .collect(Collectors.toList()); + List cList = harmonicHistoryDataList.stream() + .filter(temp -> temp.getPhasicType().equalsIgnoreCase(InfluxDBTableConstant.PHASE_TYPE_C)) + .collect(Collectors.toList()); + time = aList.stream() + .map(temp -> new Date(temp.getTime().toEpochMilli())) + .collect(Collectors.toList()); + aValue = aList.stream() + .map(temp -> BigDecimal.valueOf(temp.getAValue()).setScale(4, RoundingMode.HALF_UP).floatValue()) + .collect(Collectors.toList()); + bValue = bList.stream() + .map(temp -> BigDecimal.valueOf(temp.getAValue()).setScale(4, RoundingMode.HALF_UP).floatValue()) + .collect(Collectors.toList()); + cValue = cList.stream() + .map(temp -> BigDecimal.valueOf(temp.getAValue()).setScale(4, RoundingMode.HALF_UP).floatValue()) + .collect(Collectors.toList()); + //组装二维数组 for (int i = 0; i < time.size(); i++) { List objects = new ArrayList<>(); + //指定 objects.add(time.get(i)); objects.add(aValue.get(i)); objects.add(bValue.get(i)); @@ -198,7 +224,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { Float bValueMax = Collections.max(bValue); Float cValueMax = Collections.max(cValue); historyDataResultVO.setMinValue((aValueMin < bValueMin) ? ((aValueMin < cValueMin) ? aValueMin : cValueMin) : ((bValueMin < cValueMin) ? bValueMin : cValueMin)); - historyDataResultVO.setMaxValue(aValueMax > bValueMax ? (aValueMax > cValueMax ? aValueMax : bValueMax) : (bValueMax > cValueMax ? bValueMax : cValueMax )); + historyDataResultVO.setMaxValue(aValueMax > bValueMax ? (aValueMax > cValueMax ? aValueMax : bValueMax) : (bValueMax > cValueMax ? bValueMax : cValueMax)); historyDataResultVO.setTopLimit(queryResultLimitVO.getTopLimit()); historyDataResultVO.setLowerLimit(queryResultLimitVO.getLowerLimit()); historyDataResultVO.setValue(objectListData); @@ -212,7 +238,6 @@ public class HistoryResultServiceImpl implements HistoryResultService { private QueryResultLimitVO getQueryResult(String startTime, String endTime, String lineList, String contion, Integer number, Integer valueType, Integer ptType) { QueryResultLimitVO queryResultLimitVO = new QueryResultLimitVO(); - QueryResult queryResult; if (!lineList.isEmpty()) { Float topLimit = 0f; Float lowerLimit = 0f; @@ -222,9 +247,9 @@ public class HistoryResultServiceImpl implements HistoryResultService { LineDetailDataVO lineDetailDataVO = lineFeignClient.getLineDetailData(lineList).getData(); //组装sql语句 StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(InfluxDBPublicParam.TIME + " >= '").append(startTime).append(InfluxDBPublicParam.START_TIME).append("' and ").append(InfluxDBPublicParam.TIME).append(" <= '").append(endTime).append(InfluxDBPublicParam.END_TIME).append("' and ("); + stringBuilder.append(InfluxDBTableConstant.TIME + " >= '").append(startTime).append(InfluxDBTableConstant.START_TIME).append("' and ").append(InfluxDBTableConstant.TIME).append(" <= '").append(endTime).append(InfluxDBTableConstant.END_TIME).append("' and ("); //sql语句 - stringBuilder.append(InfluxDBPublicParam.LINE_ID + "='").append(lineList).append("')"); + stringBuilder.append(InfluxDBTableConstant.LINE_ID + "='").append(lineList).append("')"); String valueTypeName = ""; switch (valueType) { case 1: @@ -243,7 +268,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; } if (!Integer.valueOf(contion).equals(60) && !Integer.valueOf(contion).equals(61) && !Integer.valueOf(contion).equals(62)) { - stringBuilder.append(" and ").append(InfluxDBPublicParam.VALUETYPE + "='").append(valueTypeName).append("'"); + stringBuilder.append(" and ").append(InfluxDBTableConstant.VALUE_TYPE + "='").append(valueTypeName).append("'"); } String sql = ""; List phasicType = new ArrayList<>(); @@ -252,7 +277,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { switch (Integer.parseInt(contion)) { case 10: //相电压有效值 - sql = "SELECT time as time, rms as aValue FROM data_v WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, rms as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_v WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; phasicType.add("A相"); phasicType.add("B相"); @@ -262,7 +287,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 11: //线电压有效值 - sql = "SELECT time as time, rms_lvr as aValue FROM data_v WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, rms_lvr as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_v WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; phasicType.add("AB相"); phasicType.add("BC相"); @@ -272,7 +297,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 12: //电压偏差 - sql = "SELECT time as time, vu_dev as aValue FROM data_v WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, vu_dev as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_v WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; topLimit = overlimit.getVoltageDev(); lowerLimit = overlimit.getUvoltageDev(); @@ -290,7 +315,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 13: //三相电压不平衡度 - sql = "SELECT time as time, v_unbalance as aValue FROM data_v WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, v_unbalance as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_v WHERE " + stringBuilder + " and phasic_type ='T' order by time asc tz('Asia/Shanghai');"; topLimit = overlimit.getUbalance(); phasicType.add("三相电压不平衡度"); @@ -299,7 +324,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 14: //电压不平衡 - sql = "SELECT time as time, v_zero as aValue, v_pos as bValue, v_neg as cValue FROM data_v WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, v_zero as aValue, v_pos as bValue, v_neg as cValue ," + InfluxDBTableConstant.PHASIC_TYPE + "FROM data_v WHERE " + stringBuilder + " and (phasic_type ='T') group by phasic_type order by time asc tz('Asia/Shanghai');"; phasicType.add("零序电压"); phasicType.add("正序电压"); @@ -311,7 +336,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 15: //电压总谐波畸变率 - sql = "SELECT time as time, v_thd as aValue FROM data_v WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, v_thd as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_v WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; topLimit = overlimit.getUaberrance(); if (ptType == 0) { @@ -328,7 +353,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 20: //电流有效值 - sql = "SELECT time as time, rms as aValue FROM data_i WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, rms as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_i WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; phasicType.add("A相"); phasicType.add("B相"); @@ -338,7 +363,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 21: //电流总畸变率 - sql = "SELECT time as time, i_thd as aValue FROM data_i WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, i_thd as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_i WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; phasicType.add("A相"); phasicType.add("B相"); @@ -348,7 +373,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 22: //负序电流 - sql = "SELECT time as time, i_neg as aValue FROM data_i WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, i_neg as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_i WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; topLimit = overlimit.getINeg(); phasicType.add("负序电流"); @@ -357,7 +382,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 30: //频率 V9暂时代表Freq - sql = "SELECT time as time, freq as aValue FROM data_v WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, freq as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_v WHERE " + stringBuilder + " and phasic_type ='T' order by time asc tz('Asia/Shanghai');"; topLimit = 50 + overlimit.getFreqDev(); lowerLimit = 50 - overlimit.getFreqDev(); @@ -368,10 +393,10 @@ public class HistoryResultServiceImpl implements HistoryResultService { case 40: //谐波电压含有率 if (number == 1) { - sql = "SELECT time as time, v as aValue FROM data_harmrate_v WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, v as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_harmrate_v WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; } else { - sql = "SELECT time as time, v_" + number + " as aValue FROM data_harmrate_v WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, v_" + number + " as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_harmrate_v WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; if (number < 26) { topLimit = PubUtils.getValueByMethod(overlimit, "getUharm", number); @@ -392,10 +417,10 @@ public class HistoryResultServiceImpl implements HistoryResultService { case 41: //谐波电流含有率 if (number == 1) { - sql = "SELECT time as time, i as aValue FROM data_harmrate_i WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, i as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_harmrate_i WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; } else { - sql = "SELECT time as time, i_" + number + " as aValue FROM data_harmrate_i WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, i_" + number + " as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_harmrate_i WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; } phasicType.add("A相"); @@ -407,10 +432,10 @@ public class HistoryResultServiceImpl implements HistoryResultService { case 42: //谐波电压幅值 if (number == 1) { - sql = "SELECT time as time, v as aValue FROM data_v WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, v as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_v WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; } else { - sql = "SELECT time as time, v_" + number + " as aValue FROM data_v WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, v_" + number + " as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_v WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; } if (ptType == 0) { @@ -432,10 +457,10 @@ public class HistoryResultServiceImpl implements HistoryResultService { case 43: //谐波电流幅值 if (number == 1) { - sql = "SELECT time as time, i as aValue FROM data_i WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, i as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_i WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; } else { - sql = "SELECT time as time, i_" + number + " as aValue FROM data_i WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, i_" + number + " as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_i WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; if (number < 26) { topLimit = PubUtils.getValueByMethod(overlimit, "getIharm", number); @@ -450,10 +475,10 @@ public class HistoryResultServiceImpl implements HistoryResultService { case 44: //谐波电压相角 if (number == 1) { - sql = "SELECT time as time, v as aValue FROM data_harmphasic_v WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, v as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_harmphasic_v WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; } else { - sql = "SELECT time as time, v_" + number + " as aValue FROM data_harmphasic_v WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, v_" + number + " as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_harmphasic_v WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; } if (ptType == 0) { @@ -471,10 +496,10 @@ public class HistoryResultServiceImpl implements HistoryResultService { case 45: //谐波电流相角 if (number == 1) { - sql = "SELECT time as time, i as aValue FROM data_harmphasic_i WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, i as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_harmphasic_i WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; } else { - sql = "SELECT time as time, i_" + number + " as aValue FROM data_harmphasic_i WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, i_" + number + " as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_harmphasic_i WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; } phasicType.add("A相"); @@ -485,7 +510,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 46: //间谐波电压含有率 - sql = "SELECT time as time, v_" + number + " as aValue FROM data_inharmrate_v WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, v_" + number + " as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_inharmrate_v WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; topLimit = PubUtils.getValueByMethod(overlimit, "getInuharm", number); if (ptType == 0) { @@ -502,7 +527,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 47: //间谐波电流含有率 - sql = "SELECT time as time, i_" + number + " as aValue FROM data_inharmrate_i WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, i_" + number + " as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_inharmrate_i WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; phasicType.add("A相"); phasicType.add("B相"); @@ -512,7 +537,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 48: //间谐波电压幅值 - sql = "SELECT time as time, v_" + number + " as aValue FROM data_inharm_v WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, v_" + number + " as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_inharm_v WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; targetName = "间谐波电压幅值"; if (ptType == 0) { @@ -528,7 +553,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 49: //间谐波电流幅值 - sql = "SELECT time as time, i_" + number + " as aValue FROM data_inharm_i WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, i_" + number + " as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_inharm_i WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; phasicType.add("A相"); phasicType.add("B相"); @@ -538,7 +563,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 50: //谐波有功功率 - sql = "SELECT time as time, p_" + number + " as aValue FROM data_harmpower_p WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, p_" + number + " as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_harmpower_p WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; phasicType.add("A相"); phasicType.add("B相"); @@ -552,7 +577,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 51: //谐波无功功率 - sql = "SELECT time as time, q_" + number + " as aValue FROM data_harmpower_q WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, q_" + number + " as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_harmpower_q WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; phasicType.add("A相"); phasicType.add("B相"); @@ -566,7 +591,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 52: //谐波视在功率 - sql = "SELECT time as time, s_" + number + " as aValue FROM data_harmpower_s WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, s_" + number + " as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_harmpower_s WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; phasicType.add("A相"); phasicType.add("B相"); @@ -580,7 +605,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 53: //三相有功功率 - sql = "SELECT time as time, p as aValue FROM data_harmpower_p WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, p as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_harmpower_p WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; phasicType.add("A相"); phasicType.add("B相"); @@ -590,7 +615,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 54: //三相无功功率 - sql = "SELECT time as time, q as aValue FROM data_harmpower_q WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, q as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_harmpower_q WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; phasicType.add("A相"); phasicType.add("B相"); @@ -600,7 +625,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 55: //三相视在功率 - sql = "SELECT time as time, s as aValue FROM data_harmpower_s WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, s as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_harmpower_s WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; phasicType.add("A相"); phasicType.add("B相"); @@ -610,7 +635,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 56: //三相总有功功率 - sql = "SELECT time as time, p as aValue FROM data_harmpower_p WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, p as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_harmpower_p WHERE " + stringBuilder + " and phasic_type ='T' order by time asc tz('Asia/Shanghai');"; phasicType.add("三相总有功功率"); unit.add("kW"); @@ -618,7 +643,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 57: //三相总无功功率 - sql = "SELECT time as time, q as aValue FROM data_harmpower_q WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, q as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_harmpower_q WHERE " + stringBuilder + " and phasic_type ='T' order by time asc tz('Asia/Shanghai');"; phasicType.add("三相总无功功率"); unit.add("kVar"); @@ -626,7 +651,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 58: //三相总视在功率 - sql = "SELECT time as time, s as aValue FROM data_harmpower_s WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, s as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_harmpower_s WHERE " + stringBuilder + " and phasic_type ='T' order by time asc tz('Asia/Shanghai');"; phasicType.add("三相总视在功率"); unit.add("kVA"); @@ -634,7 +659,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 59: //视在功率因数 - sql = "SELECT time as time, pf as aValue FROM data_harmpower_p WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, pf as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_harmpower_p WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; phasicType.add("A相"); phasicType.add("B相"); @@ -643,7 +668,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 591: //位移功率因数 - sql = "SELECT time as time, df as aValue FROM data_harmpower_p WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, df as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_harmpower_p WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; phasicType.add("A相"); phasicType.add("B相"); @@ -652,21 +677,21 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 592: //总视在功率因数 - sql = "SELECT time as time, pf as aValue FROM data_harmpower_p WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, pf as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_harmpower_p WHERE " + stringBuilder + " and phasic_type ='T' order by time asc tz('Asia/Shanghai');"; phasicType.add("总视在功率因数"); targetName = "总视在功率因数"; break; case 593: //总位移功率因数 - sql = "SELECT time as time, df as aValue FROM data_harmpower_p WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, df as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_harmpower_p WHERE " + stringBuilder + " and phasic_type ='T' order by time asc tz('Asia/Shanghai');"; phasicType.add("总位移功率因数"); targetName = "总位移功率因数"; break; case 61: //长时闪变 - sql = "SELECT time as time, plt as aValue FROM data_plt WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, plt as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_plt WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; if (ptType == 0) { phasicType.add("A相"); @@ -682,7 +707,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 60: //短时闪变 - sql = "SELECT time as time, pst as aValue FROM data_flicker WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, pst as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_flicker WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; topLimit = overlimit.getFlicker(); if (ptType == 0) { @@ -698,7 +723,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 62: //电压波动 - sql = "SELECT time as time, fluc as aValue FROM data_fluc WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, fluc as aValue ," + InfluxDBTableConstant.PHASIC_TYPE + " FROM data_fluc WHERE " + stringBuilder + " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; if (ptType == 0) { phasicType.add("A相"); @@ -714,8 +739,12 @@ public class HistoryResultServiceImpl implements HistoryResultService { default: break; } - queryResult = influxDbUtils.query(sql); - queryResultLimitVO.setQueryResult(queryResult); + //大致有3种类型 + //1、一次查询返回3条记录,分别为A/B/C三相的结果 + //2、一次查询返回一条记录,以T相为条件,返回某3个指标值 + //3、一次查询返回一条记录,以T相为条件,返回某1个指标值 + List harmonicHistoryData = commonMapper.getHistoryResult(sql); + queryResultLimitVO.setHarmonicHistoryDataList(harmonicHistoryData); queryResultLimitVO.setTopLimit(topLimit); queryResultLimitVO.setLowerLimit(lowerLimit); queryResultLimitVO.setPhaiscType(phasicType); @@ -733,7 +762,6 @@ public class HistoryResultServiceImpl implements HistoryResultService { private QueryResultLimitVO getQueryNormDataResult(NormHistoryParam normHistoryParam) { QueryResultLimitVO queryResultLimitVO = new QueryResultLimitVO(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - QueryResult queryResult = null; if (!normHistoryParam.getLineId().isEmpty()) { Float topLimit = 0f; Float lowerLimit = 0f; @@ -747,9 +775,9 @@ public class HistoryResultServiceImpl implements HistoryResultService { LineDetailDataVO lineDetailDataVO = lineFeignClient.getLineDetailData(lineList).getData(); //组装sql语句 StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(Param.TIME + " >= '").append(startTime).append("' and ").append(Param.TIME).append(" <= '").append(endTime).append("' and ("); + stringBuilder.append(InfluxDBTableConstant.TIME + " >= '").append(startTime).append("' and ").append(InfluxDBTableConstant.TIME).append(" <= '").append(endTime).append("' and ("); //sql语句 - stringBuilder.append(Param.LINE_ID + "='").append(lineList).append("')"); + stringBuilder.append(InfluxDBTableConstant.LINE_ID + "='").append(lineList).append("')"); String valueTypeName = ""; String phasicType = ""; switch (valueType) { @@ -768,15 +796,15 @@ public class HistoryResultServiceImpl implements HistoryResultService { default: break; } - if ("A".equals(normHistoryParam.getPhaseType()) || "AB".equals(normHistoryParam.getPhaseType())) { + if ("A".equalsIgnoreCase(normHistoryParam.getPhaseType()) || "AB".equalsIgnoreCase(normHistoryParam.getPhaseType())) { phasicType = "A"; - } else if ("B".equals(normHistoryParam.getPhaseType()) || "BC".equals(normHistoryParam.getPhaseType())) { + } else if ("B".equalsIgnoreCase(normHistoryParam.getPhaseType()) || "BC".equalsIgnoreCase(normHistoryParam.getPhaseType())) { phasicType = "B"; - } else if ("C".equals(normHistoryParam.getPhaseType()) || "CA".equals(normHistoryParam.getPhaseType())) { + } else if ("C".equalsIgnoreCase(normHistoryParam.getPhaseType()) || "CA".equalsIgnoreCase(normHistoryParam.getPhaseType())) { phasicType = "C"; } if (Integer.parseInt(normHistoryParam.getTargetCode()) != 60 || Integer.parseInt(normHistoryParam.getTargetCode()) != 61 || Integer.parseInt(normHistoryParam.getTargetCode()) != 62) { - stringBuilder.append(" and ").append(Param.VALUETYPE + "='").append(valueTypeName).append("'"); + stringBuilder.append(" and ").append(InfluxDBTableConstant.VALUE_TYPE + "='").append(valueTypeName).append("'"); } stringBuilder.append(" and ").append("phasic_type ='").append(phasicType).append("'"); String sql = ""; @@ -786,7 +814,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { switch (Integer.parseInt(normHistoryParam.getTargetCode())) { case 12: //电压偏差 - sql = "SELECT time as time, vu_dev as aValue FROM data_v WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, vu_dev as aValue FROM data_v WHERE " + stringBuilder + " order by time asc tz('Asia/Shanghai');"; topLimit = overlimit.getVoltageDev(); lowerLimit = overlimit.getUvoltageDev(); @@ -795,7 +823,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 13: //三相电压不平衡度 - sql = "SELECT time as time, v_unbalance as aValue FROM data_v WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, v_unbalance as aValue FROM data_v WHERE " + stringBuilder + " order by time asc tz('Asia/Shanghai');"; topLimit = overlimit.getUbalance(); unit.add("%"); @@ -803,7 +831,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 15: //电压总谐波畸变率 - sql = "SELECT time as time, v_thd as aValue FROM data_v WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, v_thd as aValue FROM data_v WHERE " + stringBuilder + " order by time asc tz('Asia/Shanghai');"; topLimit = overlimit.getUaberrance(); unit.add("%"); @@ -811,7 +839,7 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 22: //负序电流 - sql = "SELECT time as time, i_neg as aValue FROM data_i WHERE " + stringBuilder.toString() + + sql = "SELECT time as time, i_neg as aValue FROM data_i WHERE " + stringBuilder + " order by time asc tz('Asia/Shanghai');"; topLimit = overlimit.getINeg(); unit.add("A"); @@ -819,8 +847,8 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 30: //频率 V9暂时代表Freq - sql = "SELECT time as time, freq as aValue FROM data_v WHERE " + stringBuilder.toString() + - " and phasic_type ='T' order by time asc tz('Asia/Shanghai');"; + sql = "SELECT time as time, freq as aValue FROM data_v WHERE " + stringBuilder + + " order by time asc tz('Asia/Shanghai');"; topLimit = 50 + overlimit.getFreqDev(); lowerLimit = 50 - overlimit.getFreqDev(); unit.add("Hz"); @@ -828,23 +856,23 @@ public class HistoryResultServiceImpl implements HistoryResultService { break; case 40: //谐波电压含有率 - sql = "SELECT time as time, v_" + number + " as aValue FROM data_harmrate_v WHERE " + stringBuilder.toString() + - " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; + sql = "SELECT time as time, v_" + number + " as aValue FROM data_harmrate_v WHERE " + stringBuilder + + " order by time asc tz('Asia/Shanghai');"; topLimit = PubUtils.getValueByMethod(overlimit, "getUharm", number); unit.add("%"); targetName = "谐波电压含有率"; break; case 41: //谐波电流含有率 - sql = "SELECT time as time, i_" + number + " as aValue FROM data_harmrate_i WHERE " + stringBuilder.toString() + - " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; + sql = "SELECT time as time, i_" + number + " as aValue FROM data_harmrate_i WHERE " + stringBuilder + + " order by time asc tz('Asia/Shanghai');"; unit.add("%"); targetName = "谐波电流含有率"; break; case 43: //谐波电流幅值 - sql = "SELECT time as time, i_" + number + " as aValue FROM data_i WHERE " + stringBuilder.toString() + - " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; + sql = "SELECT time as time, i_" + number + " as aValue FROM data_i WHERE " + stringBuilder + + " order by time asc tz('Asia/Shanghai');"; topLimit = PubUtils.getValueByMethod(overlimit, "getIharm", number); unit.add("A"); targetName = "谐波电流幅值"; @@ -852,24 +880,24 @@ public class HistoryResultServiceImpl implements HistoryResultService { case 46: //间谐波电压含有率 - sql = "SELECT time as time, v_" + number + " as aValue FROM data_inharmrate_v WHERE " + stringBuilder.toString() + - " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; + sql = "SELECT time as time, v_" + number + " as aValue FROM data_inharmrate_v WHERE " + stringBuilder + + " order by time asc tz('Asia/Shanghai');"; topLimit = PubUtils.getValueByMethod(overlimit, "getInuharm", number); unit.add("%"); targetName = "间谐波电压含有率"; break; case 61: //长时闪变 - sql = "SELECT time as time, plt as aValue FROM data_plt WHERE " + stringBuilder.toString() + - " and (phasic_type ='A' or phasic_type ='B' or phasic_type ='C') group by phasic_type order by time asc tz('Asia/Shanghai');"; + sql = "SELECT time as time, plt as aValue FROM data_plt WHERE " + stringBuilder + + " order by time asc tz('Asia/Shanghai');"; targetName = "长时闪变"; topLimit = overlimit.getFlicker(); break; default: break; } - queryResult = influxDbUtils.query(sql); - queryResultLimitVO.setQueryResult(queryResult); + List harmonicHistoryData = commonMapper.getHistoryResult(sql); + queryResultLimitVO.setHarmonicHistoryDataList(harmonicHistoryData); queryResultLimitVO.setTopLimit(topLimit); queryResultLimitVO.setLowerLimit(lowerLimit); queryResultLimitVO.setPhaiscType(Collections.singletonList(phasicType)); @@ -891,22 +919,16 @@ public class HistoryResultServiceImpl implements HistoryResultService { private HistoryDataResultVO getNormCondition(NormHistoryParam normHistoryParam) { HistoryDataResultVO historyDataResultVO = new HistoryDataResultVO(); QueryResultLimitVO queryResultLimitVO = getQueryNormDataResult(normHistoryParam); - QueryResult queryResult = queryResultLimitVO.getQueryResult(); BeanUtil.copyProperties(queryResultLimitVO, historyDataResultVO); - List list = queryResult.getResults().get(0).getSeries(); + //获取查询返回的结果集 + List harmonicHistoryDataList = queryResultLimitVO.getHarmonicHistoryDataList(); List time = new ArrayList<>(); List fValue = new ArrayList<>(); List> objectListData = new ArrayList<>(); - if (!CollectionUtils.isEmpty(list)) { - List> listData = queryResult.getResults().get(0).getSeries().get(0).getValues(); - for (int i = 0; i < listData.size(); i++) { - List objectList = listData.get(i); - DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX"); - TimeZone tx = TimeZone.getTimeZone("Asia/Kolkata"); - formatter.setTimeZone(tx); - Date d = formatter.parse(objectList.get(0).toString()); - time.add(d); - fValue.add(BigDecimal.valueOf(Float.parseFloat(objectList.get(1).toString())).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue()); + if (CollectionUtil.isNotEmpty(harmonicHistoryDataList)) { + for (HarmonicHistoryData harmonicHistoryData : harmonicHistoryDataList) { + time.add(new Date(harmonicHistoryData.getTime().toEpochMilli())); + fValue.add(BigDecimal.valueOf(harmonicHistoryData.getAValue()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue()); } for (int i = 0; i < time.size(); i++) { List objects = new ArrayList<>(); @@ -961,6 +983,103 @@ public class HistoryResultServiceImpl implements HistoryResultService { return statHarmonicOrgVOS; } + @Override + public HarmHistoryDataDTO getHistoryHarmData(HistoryHarmParam historyHarmParam) { + List historyData; + float overLimit; + Overlimit overlimit = lineFeignClient.getOverLimitData(historyHarmParam.getLineId()).getData(); + //判断是电流还是电压谐波 + if (historyHarmParam.getType() == 0) { + historyData = getIHistoryData(historyHarmParam); + overLimit = PubUtils.getValueByMethod(overlimit, "getIharm", historyHarmParam.getTime()); + } else { + historyData = getVHistoryData(historyHarmParam); + overLimit = PubUtils.getValueByMethod(overlimit, "getUharm", historyHarmParam.getTime()); + } + return new HarmHistoryDataDTO(historyData, overLimit); + } + + /*** + * 获取指定次数 监测点的历史谐波电流数据 + * @author hongawen + * @date 2023/7/19 10:03 + */ + private List getIHistoryData(HistoryHarmParam historyHarmParam) { + LineDetailDataVO lineDetailData = lineFeignClient.getLineDetailData(historyHarmParam.getLineId()).getData(); + List historyData; + InfluxQueryWrapper influxQueryWrapper = new InfluxQueryWrapper(DataI.class, HarmData.class); + influxQueryWrapper + .select(DataI::getTime) + .max("i_" + historyHarmParam.getTime(), "value") + .between(DataI::getTime, historyHarmParam.getSearchBeginTime().concat(" 00:00:00"), historyHarmParam.getSearchEndTime().concat(" 23:59:59")) + .eq(DataI::getLineId, historyHarmParam.getLineId()) + .or(DataI::getPhaseType, Stream.of(InfluxDBTableConstant.PHASE_TYPE_A, InfluxDBTableConstant.PHASE_TYPE_B, InfluxDBTableConstant.PHASE_TYPE_C).collect(Collectors.toList())) + //以时间分组时,需要加上时间间隔,比如此处需要加上监测点的采样间隔 + .groupBy("time(" + lineDetailData.getTimeInterval() + "m)") + .timeAsc(); + historyData = dataIMapper.getIHistoryData(influxQueryWrapper); + if (CollectionUtils.isEmpty(historyData)) { + //如果数据为空,则提示给用户暂无数据 + throw new BusinessException(HarmonicResponseEnum.NO_DATA); + } + //最新两条数据的间隔与监测点查出的间隔做对比,返回一个合理的间隔 + int lineInterval = getInterval(lineDetailData.getTimeInterval(), PubUtils.instantToDate(historyData.get(historyData.size() - 1).getTime()), PubUtils.instantToDate(historyData.get(historyData.size() - 2).getTime())); + historyData = dealHistoryData(historyData, lineInterval); + if (CollectionUtils.isEmpty(historyData)) { + //如果数据为空,则提示给用户暂无数据 + throw new BusinessException(HarmonicResponseEnum.NO_DATA); + } + //根据时间天数,获取理论上多少次用采数据 + List dateStr = PubUtils.getTimes(DateUtil.beginOfDay(DateUtil.parse(historyHarmParam.getSearchBeginTime())), DateUtil.endOfDay(DateUtil.parse(historyHarmParam.getSearchEndTime()))); + int dueTimes = dateStr.size() * 1440 / lineInterval; + int realTimes = historyData.size(); + if (dueTimes != realTimes) { + //期待值与实际值不等,则提示用户时间范围内谐波数据完整性不足 + throw new BusinessException(HarmonicResponseEnum.INSUFFICIENCY_OF_INTEGRITY); + } + return historyData.stream().sorted(Comparator.comparing(HarmData::getTime)).collect(Collectors.toList()); + } + + /** + * 获取谐波电压的数据 + *

+ * 因历史谐波表data_harmrate_v + */ + private List getVHistoryData(HistoryHarmParam historyHarmParam) { + LineDetailDataVO lineDetailData = lineFeignClient.getLineDetailData(historyHarmParam.getLineId()).getData(); + List historyData; + InfluxQueryWrapper influxQueryWrapper = new InfluxQueryWrapper(DataHarmRateV.class, HarmData.class); + influxQueryWrapper + .select(DataHarmRateV::getTime) + .max("v_" + historyHarmParam.getTime(), "value") + .between(DataHarmRateV::getTime, historyHarmParam.getSearchBeginTime().concat(" 00:00:00"), historyHarmParam.getSearchEndTime().concat(" 23:59:59")) + .eq(DataHarmRateV::getLineId, historyHarmParam.getLineId()) + .or(DataHarmRateV::getPhaseType, Stream.of(InfluxDBTableConstant.PHASE_TYPE_A, InfluxDBTableConstant.PHASE_TYPE_B, InfluxDBTableConstant.PHASE_TYPE_C).collect(Collectors.toList())) + .groupBy("time(" + lineDetailData.getTimeInterval() + "m)") + .timeAsc(); + historyData = dataHarmRateVMapper.getHarmRateVHistoryData(influxQueryWrapper); + if (CollectionUtils.isEmpty(historyData)) { + //如果数据为空,则提示给用户暂无数据 + throw new BusinessException(HarmonicResponseEnum.NO_DATA); + } + int lineInterval = getInterval(lineDetailData.getTimeInterval(), PubUtils.instantToDate(historyData.get(historyData.size() - 1).getTime()), PubUtils.instantToDate(historyData.get(historyData.size() - 2).getTime())); + //最新两条数据的间隔与监测点查出的间隔做对比,返回一个合理的间隔 + historyData = dealHistoryData(historyData, lineInterval); + if (CollectionUtils.isEmpty(historyData)) { + //如果数据为空,则提示给用户暂无数据 + throw new BusinessException(HarmonicResponseEnum.NO_DATA); + } + //根据时间天数,获取理论上多少次用采数据 + List dateStr = PubUtils.getTimes(DateUtil.beginOfDay(DateUtil.parse(historyHarmParam.getSearchBeginTime())), DateUtil.endOfDay(DateUtil.parse(historyHarmParam.getSearchEndTime()))); + int dueTimes = dateStr.size() * 1440 / lineInterval; + int realTimes = historyData.size(); + if (dueTimes != realTimes) { + //期待值与实际值不等,则提示用户时间范围内谐波数据完整性不足 + throw new BusinessException(HarmonicResponseEnum.INSUFFICIENCY_OF_INTEGRITY); + } + return historyData.stream().sorted(Comparator.comparing(HarmData::getTime)).collect(Collectors.toList()); + } + /** * 使用流对象的方法插入数据 */ @@ -981,6 +1100,149 @@ public class HistoryResultServiceImpl implements HistoryResultService { return list; } + + /** + * 根据库中查询的数据,进行数据补齐操作 + * + * @param beforeDeal 库中实际的历史谐波数据 + */ + private List dealHistoryData(List beforeDeal, int lineInterval) { + List result = new ArrayList<>(); + try { + if (CollectionUtils.isEmpty(beforeDeal)) { + return result; + } else { + //先将查询数据按日进行收集 + Map/*当前天的所有谐波数据*/> dayHistoryDatas = new HashMap<>(); + for (HarmData harmData : beforeDeal) { + Date time = PubUtils.instantToDate(harmData.getTime()); + String date = DateUtil.format(time, DatePattern.NORM_DATE_PATTERN); + if (dayHistoryDatas.containsKey(date)) { + Map harmDataMap = dayHistoryDatas.get(date); + harmDataMap.put(PubUtils.getSecondsAsZero(PubUtils.instantToDate(harmData.getTime())), harmData); + dayHistoryDatas.put(date, harmDataMap); + } else { + Map harmDataMap = new HashMap<>(); + harmDataMap.put(PubUtils.getSecondsAsZero(PubUtils.instantToDate(harmData.getTime())), harmData); + dayHistoryDatas.put(date, harmDataMap); + } + } + //将数据按日期处理后,开始进行完整性判断,满足完整性则进行补齐,否则返回空数据 + Set days = dayHistoryDatas.keySet(); + for (String day : days) { + //获取出当天的历史谐波数据 + Map harmDataMap = dayHistoryDatas.get(day); + if (CollectionUtils.isEmpty(harmDataMap)) { + continue; + } + int dueTimes = 1440 / lineInterval; + int realTimes = harmDataMap.size(); + double integrity = (double) realTimes / (double) dueTimes; + if (integrity < 0.9 || integrity >= 1.0) { + //完整性不足,则返回原数据 + Set dates = harmDataMap.keySet(); + for (Date time : dates) { + result.add(harmDataMap.get(time)); + } + } else if (integrity < 1.0) { + //进行数据补齐,数据补齐需要根据监测点测量间隔,最好是MAP格式 map的key是yyyy-MM-dd HH:mm + List afterDeal = new ArrayList<>(); + String timeTemp = day + " 00:00:00"; + Date date = DateUtil.parse(timeTemp, DatePattern.NORM_DATETIME_PATTERN); + for (int i = 0; i < dueTimes; i++) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.add(Calendar.MINUTE, lineInterval * i); + HarmData temp = harmDataMap.get(calendar.getTime()); + if (temp != null && temp.getValue() != null) { + afterDeal.add(temp); + } else { + //递归找到前面的值 + Float preValue = getPreHarmValue(date, calendar.getTime(), harmDataMap, lineInterval); + //递归找到后面的值 + Float appendValue = getAppendHarmValue(date, calendar.getTime(), harmDataMap, lineInterval); + HarmData harmData = new HarmData(); + harmData.setTime(PubUtils.dateToInstant(calendar.getTime())); + //还需要判断前值和后值为空的情况 + if (null == preValue && null == appendValue) { + harmData.setValue(0.0f); + } else if (null == preValue) { + harmData.setValue(appendValue); + } else if (null == appendValue) { + harmData.setValue(preValue); + } else { + harmData.setValue((preValue + appendValue) / 2); + } + afterDeal.add(harmData); + } + } + result.addAll(afterDeal); + } + } + } + } catch (Exception e) { + log.error("开始处理历史电压谐波数据失败,失败原因:{}", e.toString()); + throw new BusinessException(HarmonicResponseEnum.INSUFFICIENCY_OF_INTEGRITY); + } + return result; + } + + + /** + * 递归找前值 谐波数据 + * + * @param date 起始时间 + * @param time 当前事件 + * @param beforeDeal 处理前的数据 + */ + private Float getPreHarmValue(Date date, Date time, Map beforeDeal, int interval) { + Float result; + if (date.getTime() >= time.getTime()) { + return null; + } else { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(time); + interval = -interval; + calendar.add(Calendar.MINUTE, interval); + HarmData temp = beforeDeal.get(calendar.getTime()); + if (temp == null || temp.getValue() == null) { + result = getPreHarmValue(date, calendar.getTime(), beforeDeal, Math.abs(interval)); + } else { + result = temp.getValue(); + } + } + return result; + } + + /** + * 递归找后置 谐波数据 + * + * @param date 起始时间 + * @param time 截止时间 + */ + private Float getAppendHarmValue(Date date, Date time, Map beforeDeal, int interval) { + Float result; + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.add(Calendar.DAY_OF_MONTH, 1); + calendar.add(Calendar.MINUTE, -interval); + if (calendar.getTimeInMillis() <= time.getTime()) { + return null; + } else { + Calendar calendar1 = Calendar.getInstance(); + calendar1.setTime(time); + calendar1.add(Calendar.MINUTE, interval); + HarmData temp = beforeDeal.get(calendar1.getTime()); + if (temp == null || temp.getValue() == null) { + result = getAppendHarmValue(date, calendar1.getTime(), beforeDeal, interval); + } else { + result = temp.getValue(); + } + } + return result; + } + + // /** // * 获取季度时间段 // * @param date @@ -1037,4 +1299,26 @@ public class HistoryResultServiceImpl implements HistoryResultService { // return result; // } + /** + * 获取合理的测量间隔 + */ + private int getInterval(int lineInterval, Date lastOne, Date lastTwo) { + int interval = 0; + Calendar one = Calendar.getInstance(); + one.setTime(lastOne); + Calendar two = Calendar.getInstance(); + two.setTime(lastTwo); + long oneTime = lastOne.getTime(); + long twoTime = lastTwo.getTime(); + long intvalTime = oneTime - twoTime; + long databaseInterval = lineInterval * 60 * 1000; + if (oneTime < twoTime || intvalTime >= databaseInterval) { + interval = lineInterval; + } + if (intvalTime < databaseInterval) { + interval = (int) (intvalTime / (1000 * 60)); + } + return interval; + } + } diff --git a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/IntegrityServiceImpl.java b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/IntegrityServiceImpl.java index e5a480c53..1769ed3ff 100644 --- a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/IntegrityServiceImpl.java +++ b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/IntegrityServiceImpl.java @@ -21,7 +21,6 @@ import com.njcn.harmonic.pojo.dto.PublicDTO; import com.njcn.harmonic.pojo.vo.IntegrityIconVO; import com.njcn.harmonic.pojo.vo.IntegrityVO; import com.njcn.harmonic.service.IntegrityService; -import com.njcn.influxdb.utils.InfluxDbUtils; import com.njcn.poi.excel.ExcelUtil; import com.njcn.poi.pojo.bo.BaseLineExcelBody; import com.njcn.poi.pojo.bo.BaseLineProExcelBody; @@ -54,8 +53,6 @@ public class IntegrityServiceImpl implements IntegrityService { private final IntegrityMapper integrityMapper; - private final InfluxDbUtils influxDbUtils; - private final GeneralDeviceInfoClient generalDeviceInfoClient; private final GeneralInfo generalInfo; diff --git a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/OnlineRateDataServiceImpl.java b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/OnlineRateDataServiceImpl.java index 2b33aacfe..b165fac5f 100644 --- a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/OnlineRateDataServiceImpl.java +++ b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/OnlineRateDataServiceImpl.java @@ -8,16 +8,13 @@ import com.njcn.device.pq.api.GeneralDeviceInfoClient; import com.njcn.device.pq.pojo.dto.GeneralDeviceDTO; import com.njcn.device.pq.pojo.param.DeviceInfoParam; import com.njcn.device.pq.pojo.param.OnlineRateParam; -import com.njcn.device.pq.pojo.po.OnlineRate; import com.njcn.device.pq.pojo.vo.RStatOnlinerateVO; import com.njcn.harmonic.mapper.OnlineRateDataMapper; import com.njcn.harmonic.pojo.dto.PublicDTO; import com.njcn.harmonic.pojo.vo.OnlineRateCensusVO; import com.njcn.harmonic.pojo.vo.OnlineRateVO; import com.njcn.harmonic.service.OnlineRateDataService; -import com.njcn.influxdb.utils.InfluxDbUtils; import lombok.AllArgsConstructor; -import org.influxdb.dto.QueryResult; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; @@ -27,7 +24,6 @@ import java.util.List; import java.util.Objects; import java.util.stream.Collectors; -import static com.njcn.influxdb.param.InfluxDBPublicParam.*; /** * 类的介绍: diff --git a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/PhotovoltaicServiceImpl.java b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/PhotovoltaicServiceImpl.java index 3b39d2c5a..1ae9c68df 100644 --- a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/PhotovoltaicServiceImpl.java +++ b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/PhotovoltaicServiceImpl.java @@ -8,7 +8,6 @@ import com.njcn.device.pq.api.LineFeignClient; import com.njcn.device.pq.pojo.dto.GeneralDeviceDTO; import com.njcn.device.pq.pojo.dto.OverLimitLineDTO; import com.njcn.device.pq.pojo.dto.PollutionParamDTO; -import com.njcn.device.pq.pojo.dto.WarningSubstationDTO; import com.njcn.harmonic.constant.Param; import com.njcn.harmonic.enums.HarmonicResponseEnum; import com.njcn.harmonic.pojo.photoVO.WarningAreaVO; @@ -18,7 +17,7 @@ import com.njcn.harmonic.pojo.po.LimitRate; import com.njcn.harmonic.pojo.po.LimitTarget; import com.njcn.harmonic.pojo.vo.OverAreaVO; import com.njcn.harmonic.service.PhotovoltaicService; -import com.njcn.influxdb.utils.InfluxDbUtils; +import com.njcn.influx.imapper.CommonMapper; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.influxdb.dto.QueryResult; @@ -45,89 +44,89 @@ public class PhotovoltaicServiceImpl implements PhotovoltaicService { private final GeneralDeviceInfoClient generalDeviceInfoClient; - private final InfluxDbUtils influxDbUtils; - private final LineFeignClient lineFeignClient; + private final CommonMapper commonMapper; + @Override @SuppressWarnings("unchecked") public Page areaWarningManage(OverAreaVO param) { List line = new ArrayList<>(); - Map> map = new HashMap<>(); - Map> map2 = new HashMap<>(); + Map> map = new HashMap<>(); + Map> map2 = new HashMap<>(); Page page = new Page<>(); List list = new ArrayList<>(); page.setSize(param.getPageSize()); page.setCurrent(param.getPageNum()); List subList = generalDeviceInfoClient.getPracticalRunDeviceInfo(param).getData(); - if (!CollectionUtils.isEmpty(subList)){ + if (!CollectionUtils.isEmpty(subList)) { page.setTotal(subList.size()); - int pages = (int)Math.ceil(subList.size()*1.0/param.getPageSize()); + int pages = (int) Math.ceil(subList.size() * 1.0 / param.getPageSize()); page.setPages(pages); - List> pageList = Lists.partition(subList,param.getPageSize()); - List temList = pageList.get(param.getPageNum()-1); - temList.forEach(item->{ + List> pageList = Lists.partition(subList, param.getPageSize()); + List temList = pageList.get(param.getPageNum() - 1); + temList.forEach(item -> { line.addAll(item.getLineIndexes()); }); - if (!CollectionUtils.isEmpty(line)){ - List limitRateList = (List)getAllData(line,param.getSearchBeginTime(),param.getSearchEndTime(), Param.LIMIT_RATE); - if (!CollectionUtils.isEmpty(limitRateList)){ + if (!CollectionUtils.isEmpty(line)) { + List limitRateList = (List) getAllData(line, param.getSearchBeginTime(), param.getSearchEndTime(), Param.LIMIT_RATE); + if (!CollectionUtils.isEmpty(limitRateList)) { map = limitRateList.stream().collect(Collectors.groupingBy(LimitRate::getLineId)); } - List eventDetailList = getEventDetail(line,param.getSearchBeginTime(),param.getSearchEndTime()); - if (!CollectionUtils.isEmpty(eventDetailList)){ + List eventDetailList = getEventDetail(line, param.getSearchBeginTime(), param.getSearchEndTime()); + if (!CollectionUtils.isEmpty(eventDetailList)) { map2 = eventDetailList.stream().collect(Collectors.groupingBy(EventDetail::getLineId)); } } - if (!CollectionUtils.isEmpty(temList)){ + if (!CollectionUtils.isEmpty(temList)) { for (GeneralDeviceDTO item : temList) { - int onlineMonitorCount = 0,alertMonitorCount = 0,alertCount = 0,freqCount = 0,voltageCount = 0,ubalanceCount = 0,flickerCount = 0,iNegCount = 0,uharmCount = 0,iharmCount = 0,inuharmCount = 0; - int freqCounts = 0,voltageCounts = 0,uharmCounts = 0,iharmCounts = 0,ubalanceCounts = 0,flickerCounts = 0,inuharmCounts = 0,iNegCounts = 0; - int eventUp = 0,eventDown = 0,eventInterrupt = 0,eventUps = 0,eventDowns = 0,eventInterrupts = 0; + int onlineMonitorCount = 0, alertMonitorCount = 0, alertCount = 0, freqCount = 0, voltageCount = 0, ubalanceCount = 0, flickerCount = 0, iNegCount = 0, uharmCount = 0, iharmCount = 0, inuharmCount = 0; + int freqCounts = 0, voltageCounts = 0, uharmCounts = 0, iharmCounts = 0, ubalanceCounts = 0, flickerCounts = 0, inuharmCounts = 0, iNegCounts = 0; + int eventUp = 0, eventDown = 0, eventInterrupt = 0, eventUps = 0, eventDowns = 0, eventInterrupts = 0; WarningAreaVO warningAreaVO = new WarningAreaVO(); //单位id warningAreaVO.setId(item.getIndex()); //单位名称 warningAreaVO.setName(item.getName()); - if (!CollectionUtils.isEmpty(item.getLineIndexes())){ + if (!CollectionUtils.isEmpty(item.getLineIndexes())) { for (String item2 : item.getLineIndexes()) { //谐波统计 - if (!CollectionUtils.isEmpty(map.get(item2))){ + if (!CollectionUtils.isEmpty(map.get(item2))) { LimitRate limitRate = map.get(item2).get(0); - if (!Objects.isNull(limitRate)){ + if (!Objects.isNull(limitRate)) { onlineMonitorCount++; - if (limitRate.getFreqDevOverTime() > 0 || limitRate.getVoltageDevOverTime() > 0 || limitRate.getUBalanceOverTime() > 0 || limitRate.getFlickerOverTime() > 0 || limitRate.getINegOverTime() > 0 || limitRate.getUHarm2OverTime() > 0 || limitRate.getIHarm2OverTime() > 0 || limitRate.getInuHarm1OverTime() > 0){ + if (limitRate.getFreqDevOverTime() > 0 || limitRate.getVoltageDevOverTime() > 0 || limitRate.getUBalanceOverTime() > 0 || limitRate.getFlickerOverTime() > 0 || limitRate.getINegOverTime() > 0 || limitRate.getUHarm2OverTime() > 0 || limitRate.getIHarm2OverTime() > 0 || limitRate.getInuHarm1OverTime() > 0) { alertMonitorCount++; } - if (limitRate.getFreqDevOverTime() > 0){ + if (limitRate.getFreqDevOverTime() > 0) { freqCount++; freqCounts = freqCounts + limitRate.getFreqDevOverTime(); } - if (limitRate.getVoltageDevOverTime() > 0){ + if (limitRate.getVoltageDevOverTime() > 0) { voltageCount++; voltageCounts = voltageCounts + limitRate.getVoltageDevOverTime(); } - if (limitRate.getUHarm2OverTime() > 0){ + if (limitRate.getUHarm2OverTime() > 0) { uharmCount++; uharmCounts = uharmCounts + limitRate.getUHarm2OverTime(); } - if (limitRate.getIHarm2OverTime() > 0){ + if (limitRate.getIHarm2OverTime() > 0) { iharmCount++; iharmCounts = iharmCounts + limitRate.getIHarm2OverTime(); } - if (limitRate.getUBalanceOverTime() > 0){ + if (limitRate.getUBalanceOverTime() > 0) { ubalanceCount++; ubalanceCounts = ubalanceCounts + limitRate.getUBalanceOverTime(); } - if (limitRate.getFlickerOverTime() > 0){ + if (limitRate.getFlickerOverTime() > 0) { flickerCount++; flickerCounts = flickerCounts + limitRate.getFlickerOverTime(); } - if (limitRate.getInuHarm1OverTime() > 0){ + if (limitRate.getInuHarm1OverTime() > 0) { inuharmCount++; inuharmCounts = inuharmCounts + limitRate.getInuHarm1OverTime(); } - if (limitRate.getINegOverTime() > 0){ + if (limitRate.getINegOverTime() > 0) { iNegCount++; iNegCounts = iNegCounts + limitRate.getINegOverTime(); } @@ -138,68 +137,68 @@ public class PhotovoltaicServiceImpl implements PhotovoltaicService { } } //暂降统计 - if (!CollectionUtils.isEmpty(map2.get(item2))){ + if (!CollectionUtils.isEmpty(map2.get(item2))) { List eventDetailList = map2.get(item2); - if (!CollectionUtils.isEmpty(eventDetailList)){ + if (!CollectionUtils.isEmpty(eventDetailList)) { for (EventDetail item3 : eventDetailList) { - if (item3.getWaveType() == 1){ + if (item3.getWaveType() == 1) { eventDowns++; - } else if (item3.getWaveType() == 2){ + } else if (item3.getWaveType() == 2) { eventUps++; - } else if (item3.getWaveType() == 3){ + } else if (item3.getWaveType() == 3) { eventInterrupts++; } } } } - if (eventDowns > 0){ + if (eventDowns > 0) { eventDown++; } - if (eventUps > 0){ + if (eventUps > 0) { eventUp++; } - if (eventInterrupts > 0){ + if (eventInterrupts > 0) { eventInterrupt++; } } } //在线监测点数量(个) warningAreaVO.setOnlineMonitorCounts(onlineMonitorCount); - if (onlineMonitorCount != 0){ + if (onlineMonitorCount != 0) { //告警监测点数量(个) warningAreaVO.setAlertMonitorCounts(alertMonitorCount); //告警次数 warningAreaVO.setAlertCounts(alertCount); //告警频次(次/点) - warningAreaVO.setAlertAlarmFrequency(alertMonitorCount==0?0: BigDecimal.valueOf(alertCount*1.0/alertMonitorCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningAreaVO.setAlertAlarmFrequency(alertMonitorCount == 0 ? 0 : BigDecimal.valueOf(alertCount * 1.0 / alertMonitorCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); //频率偏差 - warningAreaVO.setFrequencyDeviation(freqCount==0?0:BigDecimal.valueOf(freqCounts*1.0/freqCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningAreaVO.setFrequencyDeviation(freqCount == 0 ? 0 : BigDecimal.valueOf(freqCounts * 1.0 / freqCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); //电压偏差 - warningAreaVO.setVoltageDeviation(voltageCount==0?0:BigDecimal.valueOf(voltageCounts*1.0/voltageCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningAreaVO.setVoltageDeviation(voltageCount == 0 ? 0 : BigDecimal.valueOf(voltageCounts * 1.0 / voltageCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); //谐波电压 - warningAreaVO.setHarmonicVoltage(uharmCount==0?0:BigDecimal.valueOf(uharmCounts*1.0/uharmCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningAreaVO.setHarmonicVoltage(uharmCount == 0 ? 0 : BigDecimal.valueOf(uharmCounts * 1.0 / uharmCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); //谐波电流 - warningAreaVO.setHarmonicCurrent(iharmCount==0?0:BigDecimal.valueOf(iharmCounts*1.0/iharmCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningAreaVO.setHarmonicCurrent(iharmCount == 0 ? 0 : BigDecimal.valueOf(iharmCounts * 1.0 / iharmCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); //三相电压不平衡 - warningAreaVO.setThreePhaseVoltageUnbalance(ubalanceCount==0?0:BigDecimal.valueOf(ubalanceCounts*1.0/ubalanceCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningAreaVO.setThreePhaseVoltageUnbalance(ubalanceCount == 0 ? 0 : BigDecimal.valueOf(ubalanceCounts * 1.0 / ubalanceCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); //闪变 - warningAreaVO.setFlicker(flickerCount==0?0:BigDecimal.valueOf(flickerCounts*1.0/flickerCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningAreaVO.setFlicker(flickerCount == 0 ? 0 : BigDecimal.valueOf(flickerCounts * 1.0 / flickerCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); //间谐波电压 - warningAreaVO.setInterHarmonic(inuharmCount==0?0:BigDecimal.valueOf(inuharmCounts*1.0/inuharmCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningAreaVO.setInterHarmonic(inuharmCount == 0 ? 0 : BigDecimal.valueOf(inuharmCounts * 1.0 / inuharmCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); //负序电流 - warningAreaVO.setNegative(iNegCount==0?0:BigDecimal.valueOf(iNegCounts*1.0/iNegCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningAreaVO.setNegative(iNegCount == 0 ? 0 : BigDecimal.valueOf(iNegCounts * 1.0 / iNegCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); //电压暂降 - warningAreaVO.setVoltageDip(eventDown==0?0:BigDecimal.valueOf(eventDowns*1.0/eventDown).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningAreaVO.setVoltageDip(eventDown == 0 ? 0 : BigDecimal.valueOf(eventDowns * 1.0 / eventDown).setScale(2, RoundingMode.HALF_UP).doubleValue()); //电压暂升 - warningAreaVO.setVoltageSwell(eventUp==0?0:BigDecimal.valueOf(eventUps*1.0/eventUp).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningAreaVO.setVoltageSwell(eventUp == 0 ? 0 : BigDecimal.valueOf(eventUps * 1.0 / eventUp).setScale(2, RoundingMode.HALF_UP).doubleValue()); //短时中断 - warningAreaVO.setShortInterruption(eventInterrupt==0?0:BigDecimal.valueOf(eventInterrupts*1.0/eventInterrupt).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningAreaVO.setShortInterruption(eventInterrupt == 0 ? 0 : BigDecimal.valueOf(eventInterrupts * 1.0 / eventInterrupt).setScale(2, RoundingMode.HALF_UP).doubleValue()); } list.add(warningAreaVO); } } } - if (!CollectionUtils.isEmpty(list)){ + if (!CollectionUtils.isEmpty(list)) { List recordList = new ArrayList<>(); //默认 在线监测点数量 倒叙排序 recordList = list.stream().sorted(Comparator.comparing(WarningAreaVO::getOnlineMonitorCounts).reversed().thenComparing(WarningAreaVO::getName)).collect(Collectors.toList()); @@ -212,84 +211,84 @@ public class PhotovoltaicServiceImpl implements PhotovoltaicService { @Override @SuppressWarnings("unchecked") public Page monitorWarningManage(OverAreaVO param) { - List line = new ArrayList<>(),temList = new ArrayList<>(); - Map> map = new HashMap<>(); - Map> map2 = new HashMap<>(); + List line = new ArrayList<>(), temList = new ArrayList<>(); + Map> map = new HashMap<>(); + Map> map2 = new HashMap<>(); Page page = new Page<>(); List list = new ArrayList<>(); page.setSize(param.getPageSize()); page.setCurrent(param.getPageNum()); List areaList = generalDeviceInfoClient.getPracticalRunDeviceInfo(param).getData(); - if (!CollectionUtils.isEmpty(areaList)){ - areaList.forEach(item->{ + if (!CollectionUtils.isEmpty(areaList)) { + areaList.forEach(item -> { line.addAll(item.getLineIndexes()); }); - if (!CollectionUtils.isEmpty(line)){ + if (!CollectionUtils.isEmpty(line)) { page.setTotal(line.size()); - int pages = (int)Math.ceil(line.size()*1.0/param.getPageSize()); + int pages = (int) Math.ceil(line.size() * 1.0 / param.getPageSize()); page.setPages(pages); - List> pageList = Lists.partition(line,param.getPageSize()); - temList = pageList.get(param.getPageNum()-1); + List> pageList = Lists.partition(line, param.getPageSize()); + temList = pageList.get(param.getPageNum() - 1); } - if (!CollectionUtils.isEmpty(temList)){ - List limitRateList = (List)getAllData(temList,param.getSearchBeginTime(),param.getSearchEndTime(), Param.LIMIT_RATE); - if (!CollectionUtils.isEmpty(limitRateList)){ + if (!CollectionUtils.isEmpty(temList)) { + List limitRateList = (List) getAllData(temList, param.getSearchBeginTime(), param.getSearchEndTime(), Param.LIMIT_RATE); + if (!CollectionUtils.isEmpty(limitRateList)) { map = limitRateList.stream().collect(Collectors.groupingBy(LimitRate::getLineId)); } - List eventDetailList = getEventDetail(temList,param.getSearchBeginTime(),param.getSearchEndTime()); - if (!CollectionUtils.isEmpty(eventDetailList)){ + List eventDetailList = getEventDetail(temList, param.getSearchBeginTime(), param.getSearchEndTime()); + if (!CollectionUtils.isEmpty(eventDetailList)) { map2 = eventDetailList.stream().collect(Collectors.groupingBy(EventDetail::getLineId)); } PollutionParamDTO pollutionParamDTO = new PollutionParamDTO(); pollutionParamDTO.setLineList(temList); List overLimitLineList = lineFeignClient.getOverLimitLineInfo(pollutionParamDTO).getData(); - for (OverLimitLineDTO pojo:overLimitLineList) { + for (OverLimitLineDTO pojo : overLimitLineList) { String item = pojo.getId(); String name = pojo.getLineName(); - int alertMonitorCount = 0,alertCount = 0,freqCount = 0,voltageCount = 0,ubalanceCount = 0,flickerCount = 0,iNegCount = 0,uharmCount = 0,iharmCount = 0,inuharmCount = 0; - int freqCounts = 0,voltageCounts = 0,uharmCounts = 0,iharmCounts = 0,ubalanceCounts = 0,flickerCounts = 0,inuharmCounts = 0,iNegCounts = 0; - int eventUp = 0,eventDown = 0,eventInterrupt = 0,eventUps = 0,eventDowns = 0,eventInterrupts = 0; + int alertMonitorCount = 0, alertCount = 0, freqCount = 0, voltageCount = 0, ubalanceCount = 0, flickerCount = 0, iNegCount = 0, uharmCount = 0, iharmCount = 0, inuharmCount = 0; + int freqCounts = 0, voltageCounts = 0, uharmCounts = 0, iharmCounts = 0, ubalanceCounts = 0, flickerCounts = 0, inuharmCounts = 0, iNegCounts = 0; + int eventUp = 0, eventDown = 0, eventInterrupt = 0, eventUps = 0, eventDowns = 0, eventInterrupts = 0; WarningMonitorVO warningMonitorVO = new WarningMonitorVO(); //监测点id warningMonitorVO.setId(item); //监测点名称 warningMonitorVO.setName(name); //谐波统计 - if (!CollectionUtils.isEmpty(map.get(item))){ + if (!CollectionUtils.isEmpty(map.get(item))) { LimitRate limitRate = map.get(item).get(0); - if (!Objects.isNull(limitRate)){ - if (limitRate.getFreqDevOverTime() > 0 || limitRate.getVoltageDevOverTime() > 0 || limitRate.getUBalanceOverTime() > 0 || limitRate.getFlickerOverTime() > 0 || limitRate.getINegOverTime() > 0 || limitRate.getUHarm2OverTime() > 0 || limitRate.getIHarm2OverTime() > 0 || limitRate.getInuHarm1OverTime() > 0){ + if (!Objects.isNull(limitRate)) { + if (limitRate.getFreqDevOverTime() > 0 || limitRate.getVoltageDevOverTime() > 0 || limitRate.getUBalanceOverTime() > 0 || limitRate.getFlickerOverTime() > 0 || limitRate.getINegOverTime() > 0 || limitRate.getUHarm2OverTime() > 0 || limitRate.getIHarm2OverTime() > 0 || limitRate.getInuHarm1OverTime() > 0) { alertMonitorCount++; } - if (limitRate.getFreqDevOverTime() > 0){ + if (limitRate.getFreqDevOverTime() > 0) { freqCount++; freqCounts = freqCounts + limitRate.getFreqDevOverTime(); } - if (limitRate.getVoltageDevOverTime() > 0){ + if (limitRate.getVoltageDevOverTime() > 0) { voltageCount++; voltageCounts = voltageCounts + limitRate.getVoltageDevOverTime(); } - if (limitRate.getUHarm2OverTime() > 0){ + if (limitRate.getUHarm2OverTime() > 0) { uharmCount++; uharmCounts = uharmCounts + limitRate.getUHarm2OverTime(); } - if (limitRate.getIHarm2OverTime() > 0){ + if (limitRate.getIHarm2OverTime() > 0) { iharmCount++; iharmCounts = iharmCounts + limitRate.getIHarm2OverTime(); } - if (limitRate.getUBalanceOverTime() > 0){ + if (limitRate.getUBalanceOverTime() > 0) { ubalanceCount++; ubalanceCounts = ubalanceCounts + limitRate.getUBalanceOverTime(); } - if (limitRate.getFlickerOverTime() > 0){ + if (limitRate.getFlickerOverTime() > 0) { flickerCount++; flickerCounts = flickerCounts + limitRate.getFlickerOverTime(); } - if (limitRate.getInuHarm1OverTime() > 0){ + if (limitRate.getInuHarm1OverTime() > 0) { inuharmCount++; inuharmCounts = inuharmCounts + limitRate.getInuHarm1OverTime(); } - if (limitRate.getINegOverTime() > 0){ + if (limitRate.getINegOverTime() > 0) { iNegCount++; iNegCounts = iNegCounts + limitRate.getINegOverTime(); } @@ -300,59 +299,59 @@ public class PhotovoltaicServiceImpl implements PhotovoltaicService { } } //暂降统计 - if (!CollectionUtils.isEmpty(map2.get(item))){ + if (!CollectionUtils.isEmpty(map2.get(item))) { List eventDetailList2 = map2.get(item); - if (!CollectionUtils.isEmpty(eventDetailList2)){ + if (!CollectionUtils.isEmpty(eventDetailList2)) { for (EventDetail item3 : eventDetailList2) { - if (item3.getWaveType() == 1){ + if (item3.getWaveType() == 1) { eventDowns++; - } else if (item3.getWaveType() == 2){ + } else if (item3.getWaveType() == 2) { eventUps++; - } else if (item3.getWaveType() == 3){ + } else if (item3.getWaveType() == 3) { eventInterrupts++; } } } } - if (eventDowns > 0){ + if (eventDowns > 0) { eventDown++; } - if (eventUps > 0){ + if (eventUps > 0) { eventUp++; } - if (eventInterrupts > 0){ + if (eventInterrupts > 0) { eventInterrupt++; } //告警次数 warningMonitorVO.setAlertCounts(alertCount); //告警频次(次/点) - warningMonitorVO.setAlertAlarmFrequency(alertMonitorCount==0?0: BigDecimal.valueOf(alertCount*1.0/alertMonitorCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningMonitorVO.setAlertAlarmFrequency(alertMonitorCount == 0 ? 0 : BigDecimal.valueOf(alertCount * 1.0 / alertMonitorCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); //频率偏差 - warningMonitorVO.setFrequencyDeviation(freqCount==0?0:BigDecimal.valueOf(freqCounts*1.0/freqCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningMonitorVO.setFrequencyDeviation(freqCount == 0 ? 0 : BigDecimal.valueOf(freqCounts * 1.0 / freqCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); //电压偏差 - warningMonitorVO.setVoltageDeviation(voltageCount==0?0:BigDecimal.valueOf(voltageCounts*1.0/voltageCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningMonitorVO.setVoltageDeviation(voltageCount == 0 ? 0 : BigDecimal.valueOf(voltageCounts * 1.0 / voltageCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); //谐波电压 - warningMonitorVO.setHarmonicVoltage(uharmCount==0?0:BigDecimal.valueOf(uharmCounts*1.0/uharmCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningMonitorVO.setHarmonicVoltage(uharmCount == 0 ? 0 : BigDecimal.valueOf(uharmCounts * 1.0 / uharmCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); //谐波电流 - warningMonitorVO.setHarmonicCurrent(iharmCount==0?0:BigDecimal.valueOf(iharmCounts*1.0/iharmCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningMonitorVO.setHarmonicCurrent(iharmCount == 0 ? 0 : BigDecimal.valueOf(iharmCounts * 1.0 / iharmCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); //三相电压不平衡 - warningMonitorVO.setThreePhaseVoltageUnbalance(ubalanceCount==0?0:BigDecimal.valueOf(ubalanceCounts*1.0/ubalanceCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningMonitorVO.setThreePhaseVoltageUnbalance(ubalanceCount == 0 ? 0 : BigDecimal.valueOf(ubalanceCounts * 1.0 / ubalanceCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); //闪变 - warningMonitorVO.setFlicker(flickerCount==0?0:BigDecimal.valueOf(flickerCounts*1.0/flickerCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningMonitorVO.setFlicker(flickerCount == 0 ? 0 : BigDecimal.valueOf(flickerCounts * 1.0 / flickerCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); //间谐波电压 - warningMonitorVO.setInterHarmonic(inuharmCount==0?0:BigDecimal.valueOf(inuharmCounts*1.0/inuharmCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningMonitorVO.setInterHarmonic(inuharmCount == 0 ? 0 : BigDecimal.valueOf(inuharmCounts * 1.0 / inuharmCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); //负序电流 - warningMonitorVO.setNegative(iNegCount==0?0:BigDecimal.valueOf(iNegCounts*1.0/iNegCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningMonitorVO.setNegative(iNegCount == 0 ? 0 : BigDecimal.valueOf(iNegCounts * 1.0 / iNegCount).setScale(2, RoundingMode.HALF_UP).doubleValue()); //电压暂降 - warningMonitorVO.setVoltageDip(eventDown==0?0:BigDecimal.valueOf(eventDowns*1.0/eventDown).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningMonitorVO.setVoltageDip(eventDown == 0 ? 0 : BigDecimal.valueOf(eventDowns * 1.0 / eventDown).setScale(2, RoundingMode.HALF_UP).doubleValue()); //电压暂升 - warningMonitorVO.setVoltageSwell(eventUp==0?0:BigDecimal.valueOf(eventUps*1.0/eventUp).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningMonitorVO.setVoltageSwell(eventUp == 0 ? 0 : BigDecimal.valueOf(eventUps * 1.0 / eventUp).setScale(2, RoundingMode.HALF_UP).doubleValue()); //短时中断 - warningMonitorVO.setShortInterruption(eventInterrupt==0?0:BigDecimal.valueOf(eventInterrupts*1.0/eventInterrupt).setScale(2, RoundingMode.HALF_UP).doubleValue()); + warningMonitorVO.setShortInterruption(eventInterrupt == 0 ? 0 : BigDecimal.valueOf(eventInterrupts * 1.0 / eventInterrupt).setScale(2, RoundingMode.HALF_UP).doubleValue()); list.add(warningMonitorVO); } } - if (!CollectionUtils.isEmpty(list)){ + if (!CollectionUtils.isEmpty(list)) { List recordList = new ArrayList<>(); //默认 监测点告警次数 倒叙排序 recordList = list.stream().sorted(Comparator.comparing(WarningMonitorVO::getAlertCounts).reversed()).collect(Collectors.toList()); @@ -366,18 +365,19 @@ public class PhotovoltaicServiceImpl implements PhotovoltaicService { /** * 功能描述: 处理区域在线监测点数、超标监测点数 + * * @param list 集合 * @return * @author xy * @date 2022/2/25 15:05 */ - private List getAllData(List list, String startTime, String endTime, String databaseName){ + private List getAllData(List list, String startTime, String endTime, String databaseName) { List result = new ArrayList<>(); StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder1 = new StringBuilder(); stringBuilder.append(Param.TIME + " >= '").append(startTime).append("' and ").append(Param.TIME).append(" <= '").append(endTime).append("' and ("); - for (int i=0;i getEventDetail(List list, String startTime, String endTime){ + public List getEventDetail(List list, String startTime, String endTime) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(Param.TIME + " >= '").append(startTime).append("' and ").append(Param.TIME).append(" <= '").append(endTime).append("' and ("); - for (int i=0;i getDeptSubstationRelations(HarmonicPublicParam harmonicPublicParam) { - //用于区分是pms 还是 pq - List list = new ArrayList<>(); - List lineList = new ArrayList<>(); - List lineInfo = new ArrayList<>(); - PollutionParamDTO paramDTO = new PollutionParamDTO(); - harmonicPublicParam.setServerName(generalInfo.getMicroServiceName()); - if (StringUtils.isBlank(RequestUtil.getDeptIndex())) { - return list; - } - List deviceList = generalDeviceInfoClient.getPracticalRunDeviceInfo(harmonicPublicParam).getData(); - deviceList.forEach(dept -> { - lineList.addAll(dept.getLineIndexes()); - }); - - if (!CollectionUtils.isEmpty(lineList)) { - paramDTO.setLineList(lineList); - lineInfo = lineFeignClient.getLineInfo(paramDTO).getData(); - - List lineData = getLineDate(lineList, harmonicPublicParam.getSearchBeginTime(), harmonicPublicParam.getSearchEndTime(), harmonicPublicParam.getStatisticalType().getCode()); - - if (!CollectionUtils.isEmpty(lineData)) { - lineInfo.stream().map(list1 -> lineData.stream().filter(list2 -> Objects.equals(list1.getId(), list2.getId())).findAny().map(m -> { - list1.setData(m.getData()); - return list1; - })).collect(Collectors.toList()); - } - } - Map> map = lineInfo.stream().collect(Collectors.groupingBy(PollutionLineDTO::getSubstationId)); - deviceList.forEach(dept -> { - List childrenList = new ArrayList<>(); - PollutionVO pollutionVO = new PollutionVO(); - pollutionVO.setId(dept.getIndex()); - pollutionVO.setName(dept.getName()); - if (!CollectionUtils.isEmpty(dept.getSubIndexes())) { - dept.getSubIndexes().forEach(sub -> { - List l1 = map.get(sub); - PollutionVO children = new PollutionVO(); - children.setId(sub); - children.setPid(dept.getIndex()); - children.setName(l1.get(0).getSubstation()); - children.setData(l1.stream().max(Comparator.comparing(PollutionLineDTO::getData)).get().getData()); - childrenList.add(children); - }); - } - if (!CollectionUtils.isEmpty(childrenList)) { - pollutionVO.setChildren(childrenList.stream().sorted(Comparator.comparing(PollutionVO::getData).reversed()).collect(Collectors.toList())); - pollutionVO.setData(childrenList.stream().max(Comparator.comparing(PollutionVO::getData)).get().getData()); - } - list.add(pollutionVO); - }); - if (!CollectionUtils.isEmpty(list)) { - return list.stream().sorted(Comparator.comparing(PollutionVO::getData).reversed().thenComparing(PollutionVO::getName)).collect(Collectors.toList()); - } - return list; - } - - @Override - public List getSubstationInfoById(HarmonicPublicParam deptParam) { - List list = new ArrayList<>(); - deptParam.setServerName(generalInfo.getMicroServiceName()); - List sub = generalDeviceInfoClient.getPracticalRunDeviceInfoAsSubstation(deptParam).getData(); - sub.forEach(item -> { - PollutionSubstationDTO pollutionSubstationDTO = lineFeignClient.getSubstationInfo(item.getIndex()).getData(); - if (!CollectionUtils.isEmpty(item.getLineIndexes())) { - List lineData = getLineDate(item.getLineIndexes(), deptParam.getSearchBeginTime(), deptParam.getSearchEndTime(), deptParam.getStatisticalType().getCode()); - if (!CollectionUtils.isEmpty(lineData)) { - pollutionSubstationDTO.setData(lineData.stream().max(Comparator.comparing(PublicDTO::getData)).get().getData()); - } - } - list.add(pollutionSubstationDTO); - }); - if (!CollectionUtils.isEmpty(list)) { - return list.stream().sorted(Comparator.comparing(PollutionSubstationDTO::getData).reversed().thenComparing(PollutionSubstationDTO::getName)).collect(Collectors.toList()); - } - return list; - } - - @Override - public List getLineInfoById(HarmonicPublicParam harmonicPublicParam) { - harmonicPublicParam.setServerName(generalInfo.getMicroServiceName()); - List list = new ArrayList<>(); - List line = new ArrayList<>(); - PollutionParamDTO paramDTO = new PollutionParamDTO(); - if (StringUtils.isBlank(RequestUtil.getDeptIndex())) { - return list; - } - List sub = generalDeviceInfoClient.getPracticalRunDeviceInfoAsSubstation(harmonicPublicParam).getData(); - sub.forEach(item -> { - if (Objects.equals(harmonicPublicParam.getId(), item.getIndex())) { - if (!CollectionUtils.isEmpty(item.getLineIndexes())) { - line.addAll(item.getLineIndexes()); - } - } - }); - if (!CollectionUtils.isEmpty(line)) { - paramDTO.setLineList(line); - list = lineFeignClient.getLineInfo(paramDTO).getData(); - List lineData = getLineDate(line, harmonicPublicParam.getSearchBeginTime(), harmonicPublicParam.getSearchEndTime(), harmonicPublicParam.getStatisticalType().getCode()); - if (!CollectionUtils.isEmpty(lineData)) { - list.stream().map(list1 -> lineData.stream().filter(list2 -> Objects.equals(list1.getId(), list2.getId())).findAny().map(m -> { - list1.setData(m.getData()); - return list1; - })).collect(Collectors.toList()); - } - } else { - return list; - } - return list.stream().sorted(Comparator.comparing(PollutionLineDTO::getData).reversed().thenComparing(PollutionLineDTO::getName)).collect(Collectors.toList()); - } -*/ - /* @Override - public List getLineRank(HarmonicPublicParam harmonicPublicParam) { - harmonicPublicParam.setServerName(generalInfo.getMicroServiceName()); - List list = new ArrayList<>(); - List lineList = new ArrayList<>(); - PollutionParamDTO paramDTO = new PollutionParamDTO(); - if (StringUtils.isBlank(RequestUtil.getDeptIndex())) { - return list; - } - List deviceList = generalDeviceInfoClient.getPracticalRunDeviceInfo(harmonicPublicParam).getData(); - deviceList.forEach(item -> { - if (!CollectionUtils.isEmpty(item.getLineIndexes())) { - lineList.addAll(item.getLineIndexes()); - } - }); - if (!CollectionUtils.isEmpty(lineList)) { - paramDTO.setLineList(lineList); - list = lineFeignClient.getLineInfo(paramDTO).getData(); - List result = getLineDate(lineList, harmonicPublicParam.getSearchBeginTime(), harmonicPublicParam.getSearchEndTime(), harmonicPublicParam.getStatisticalType().getCode()); - if (!CollectionUtils.isEmpty(result)) { - list.stream().map(list1 -> result.stream().filter(list2 -> Objects.equals(list1.getId(), list2.getId())).findAny().map(m -> { - list1.setData(m.getData()); - return list1; - })).collect(Collectors.toList()); - } - } - list.sort((item1, item2) -> item2.getData().compareTo(item1.getData())); - if (list.size() > Param.UP_LIMIT) { - return list.subList(Param.DOWN_LIMIT, Param.UP_LIMIT); - } - return list; - }*/ - - - /** - * 功能描述:根据监测点id查询influxDB污染指数 - * - * @param line 监测点集合 - * startTime 开始时间 - * endTime 结束时间 - * type 指标参数 - * @return - * @author xy - * @date 2022/2/21 20:08 - */ - private List getLineDate(List line, String startTime, String endTime, String type) { - List result = new ArrayList<>(); - String quota = ""; - if (Objects.equals(type, DicDataEnum.XBDY_ENUM.getCode())) { - quota = "harmonic_v"; - } else if (Objects.equals(type, DicDataEnum.XBDL_ENUM.getCode())) { - quota = "harmonic_i"; - } - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(Param.TIME).append(" >= '").append(startTime).append(Param.START_TIME).append("' and ").append(Param.TIME).append(" <= '").append(endTime).append(Param.END_TIME).append("' and ("); - for (int i = 0; i < line.size(); i++) { - if (line.size() - i != 1) { - stringBuilder.append(Param.LINE_ID).append("='").append(line.get(i)).append("' or "); - } else { - stringBuilder.append(Param.LINE_ID).append("='").append(line.get(i)).append("')"); - } - } - stringBuilder.append(" group by line_id order by time desc limit 1 tz('Asia/Shanghai')"); - String sql = "SELECT line_id," + quota + " FROM harmonic_pollution where " + stringBuilder; - QueryResult sqlResult = influxDbUtils.query(sql); - List list = sqlResult.getResults().get(0).getSeries(); - if (!CollectionUtils.isEmpty(list)) { - list.forEach(po -> { - String index = po.getTags().get(Param.LINE_ID); - List> valueList = po.getValues(); - if (!CollectionUtils.isEmpty(valueList)) { - for (List value : valueList) { - PublicDTO publicDTO = new PublicDTO(); - Double data = value.get(2) == null ? 0.0 : BigDecimal.valueOf(Double.parseDouble(value.get(2).toString())).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); - publicDTO.setId(index); - publicDTO.setData(data); - result.add(publicDTO); - } - } - }); - } - return result; - } -} diff --git a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/PollutionSubstationServiceImpl.java b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/PollutionSubstationServiceImpl.java index 6ace633fb..bc564794b 100644 --- a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/PollutionSubstationServiceImpl.java +++ b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/PollutionSubstationServiceImpl.java @@ -30,15 +30,12 @@ import com.njcn.harmonic.pojo.po.*; import com.njcn.harmonic.pojo.vo.PollutionSubstationVO; import com.njcn.harmonic.pojo.vo.PollutionVO; import com.njcn.harmonic.service.PollutionSubstationService; -import com.njcn.influxdb.utils.InfluxDbUtils; -import com.njcn.system.enums.DicDataEnum; import com.njcn.user.api.DeptFeignClient; import com.njcn.user.pojo.po.Dept; import com.njcn.web.utils.RequestUtil; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.influxdb.dto.QueryResult; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; @@ -91,7 +88,6 @@ public class PollutionSubstationServiceImpl extends ServiceImpl getLineRank(HarmonicPublicParam param) { - List list= new ArrayList<>(); - String pollutionType = param.getStatisticalType ( ).getId (); - String searchBeginTime = ""; - if(Objects.equals (param.getReportFlag (),BizParamConstant.STAT_BIZ_YEAR) ){ - searchBeginTime = param.getSearchBeginTime ( ).substring (0, 4)+"%"; - - }else if(Objects.equals (param.getReportFlag (),BizParamConstant.STAT_BIZ_MONTH)){ - searchBeginTime = param.getSearchBeginTime ( ).substring (0, 7)+"%"; - - - }else if(Objects.equals (param.getReportFlag (),BizParamConstant.STAT_BIZ_DAY)) { - searchBeginTime = param.getSearchBeginTime ( ).substring (0, 10)+"%"; - } - - if(param.getType()==0) { - param.setServerName(generalInfo.getMicroServiceName()); - List lineList = new ArrayList<>(); - PollutionParamDTO paramDTO = new PollutionParamDTO(); - if (StringUtils.isBlank(RequestUtil.getDeptIndex())) { - return list; - } - List deviceList = generalDeviceInfoClient.getPracticalRunDeviceInfo(param).getData(); - deviceList.forEach(item -> { - if (!CollectionUtils.isEmpty(item.getLineIndexes())) { - lineList.addAll(item.getLineIndexes()); - } - }); - if (!CollectionUtils.isEmpty(lineList)) { - paramDTO.setLineList(lineList); - list = lineFeignClient.getLineInfo(paramDTO).getData(); - List result = getLineDate(lineList, param.getSearchBeginTime(), param.getSearchEndTime(), param.getStatisticalType().getCode()); - if (!CollectionUtils.isEmpty(result)) { - list.stream().map(list1 -> result.stream().filter(list2 -> Objects.equals(list1.getId(), list2.getId())).findAny().map(m -> { - list1.setData(m.getData()); - return list1; - })).collect(Collectors.toList()); - } - } - list.sort((item1, item2) -> item2.getData().compareTo(item1.getData())); - if (list.size() > Param.UP_LIMIT) { - return list.subList(Param.DOWN_LIMIT, Param.UP_LIMIT); - } - return list; - } - PmsDeviceInfoParam pmsDeviceInfoParam = new PmsDeviceInfoParam(); - pmsDeviceInfoParam.setDeptIndex(param.getDeptIndex()); - //获取统计类型 - pmsDeviceInfoParam.setStatisticalType(param.getStatisticalType()); - //获取主网台账信息 - List deviceList = pmsGeneralDeviceInfoClient.getPmsDeviceInfoWithInOrg(pmsDeviceInfoParam).getData(); - List monitorIdList=new ArrayList<>(); - deviceList.forEach(dept -> { - monitorIdList.addAll(dept.getMonitorIdList()); - }); - - if(CollectionUtil.isNotEmpty(monitorIdList)){ - //获取监测点数据 - List lineData = rMpPollutionDPOMapper.selectMaxList ( monitorIdList,pollutionType,searchBeginTime); - - if(CollectionUtil.isEmpty(lineData)){ - return list; - } - - //获取主网监测点信息 - List data = monitorClient.getMonitorList(monitorIdList).getData(); - Map monitorMap = data.stream().collect(Collectors.toMap(Monitor::getId, Function.identity(), (key1, kye2) -> key1)); - lineData.sort((item1, item2) -> item2.getValue().compareTo(item1.getValue())); - if (lineData.size() > Param.UP_LIMIT) { - lineData = lineData.subList(Param.DOWN_LIMIT, Param.UP_LIMIT); - } - - PollutionLineDTO dto; - for (RMpPollutionDPO lineDatum : lineData) { - if(monitorMap.containsKey(lineDatum.getLineId())){ - Monitor monitor = monitorMap.get(lineDatum.getLineId()); - dto=new PollutionLineDTO(); - dto.setId(monitor.getId()); - dto.setName(monitor.getName()); - dto.setPowerCompany(monitor.getOrgName()); - dto.setSubstation(monitor.getPowerrId()); - dto.setSubstationId(monitor.getPowerrName()); - dto.setBusBar(monitor.getLineName()); - dto.setData(lineDatum.getValue()); - list.add(dto); - } - } - } - return list; - } - - @Override public List getLineRankTop10 (HarmonicPublicParam param) { @@ -752,53 +655,4 @@ public class PollutionSubstationServiceImpl extends ServiceImpl getLineDate(List line, String startTime, String endTime, String type) { - List result = new ArrayList<>(); - String quota = ""; - if (Objects.equals(type, DicDataEnum.V_HARMONIC.getCode())) { - quota = ",harmonic_v"; - } else if (Objects.equals(type, DicDataEnum.I_ALL.getCode())) { - quota = ",harmonic_i"; - } - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(Param.TIME).append(" >= '").append(startTime).append(Param.START_TIME).append("' and ").append(Param.TIME).append(" <= '").append(endTime).append(Param.END_TIME).append("' and ("); - for (int i = 0; i < line.size(); i++) { - if (line.size() - i != 1) { - stringBuilder.append(Param.LINE_ID).append("='").append(line.get(i)).append("' or "); - } else { - stringBuilder.append(Param.LINE_ID).append("='").append(line.get(i)).append("')"); - } - } - stringBuilder.append(" group by line_id order by time desc limit 1 tz('Asia/Shanghai')"); - String sql = "SELECT line_id" + quota + " FROM harmonic_pollution where " + stringBuilder; - QueryResult sqlResult = influxDbUtils.query(sql); - List list = sqlResult.getResults().get(0).getSeries(); - if (!CollectionUtils.isEmpty(list)) { - list.forEach(po -> { - String index = po.getTags().get(Param.LINE_ID); - List> valueList = po.getValues(); - if (!CollectionUtils.isEmpty(valueList)) { - for (List value : valueList) { - PublicDTO publicDTO = new PublicDTO(); - Double data = value.get(2) == null ? 0.0 : BigDecimal.valueOf(Double.parseDouble(value.get(2).toString())).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); - publicDTO.setId(index); - publicDTO.setData(data); - result.add(publicDTO); - } - } - }); - } - return result; - } } diff --git a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/SteadyDataServiceImpl.java b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/SteadyDataServiceImpl.java index c3d20a170..c6687c30e 100644 --- a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/SteadyDataServiceImpl.java +++ b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/SteadyDataServiceImpl.java @@ -8,14 +8,10 @@ import com.njcn.harmonic.mapper.RStatLimitRateDMapper; import com.njcn.harmonic.pojo.vo.RStatLimitRateDVO; import com.njcn.harmonic.pojo.vo.SteadyInfoData; import com.njcn.harmonic.service.SteadyDataService; -import com.njcn.influxdb.param.InfluxDBPublicParam; -import com.njcn.influxdb.utils.InfluxDbUtils; import com.njcn.web.pojo.vo.SteadyDataVO; import lombok.AllArgsConstructor; import org.apache.commons.lang.StringUtils; -import org.influxdb.dto.QueryResult; import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; import java.math.BigDecimal; import java.text.DecimalFormat; @@ -32,7 +28,6 @@ import java.util.List; @AllArgsConstructor public class SteadyDataServiceImpl implements SteadyDataService { - private final InfluxDbUtils influxDbUtils; private final RStatLimitRateDMapper rateDMapper; @Override diff --git a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/SteadyExceedRateServiceImpl.java b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/SteadyExceedRateServiceImpl.java index 970a588a1..2f9782ac3 100644 --- a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/SteadyExceedRateServiceImpl.java +++ b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/SteadyExceedRateServiceImpl.java @@ -23,8 +23,7 @@ import com.njcn.harmonic.pojo.vo.SteadyExceedRateVO; import com.njcn.harmonic.service.IRStatLimitRateDService; import com.njcn.harmonic.service.SteadyExceedRateService; import com.njcn.harmonic.utils.PubUtils; -import com.njcn.influxdb.param.InfluxDBPublicParam; -import com.njcn.influxdb.utils.InfluxDbUtils; +import com.njcn.influx.pojo.constant.InfluxDBTableConstant; import lombok.AllArgsConstructor; import lombok.SneakyThrows; import org.springframework.stereotype.Service; @@ -47,8 +46,6 @@ public class SteadyExceedRateServiceImpl implements SteadyExceedRateService { private final SteadyExceedRateMapper steadyExceedRateMapper; - private final InfluxDbUtils influxDbUtils; - private final IRStatLimitRateDService rateDService; private final RStatLimitRateDMapper rateDMapper; @@ -472,7 +469,7 @@ public class SteadyExceedRateServiceImpl implements SteadyExceedRateService { List limitRatePOS = new ArrayList<>(); List limitRates = rateDService.list(new LambdaQueryWrapper() .in(RStatLimitRateDPO::getLineId, lineIndexes) - .eq(RStatLimitRateDPO::getPhasicType,InfluxDBPublicParam.PHASIC_TYPET) + .eq(RStatLimitRateDPO::getPhasicType, InfluxDBTableConstant.PHASE_TYPE_T) .ge(StrUtil.isNotBlank(startTime), RStatLimitRateDPO::getTime, DateUtil.beginOfDay(DateUtil.parse(startTime))) .le(StrUtil.isNotBlank(endTime), RStatLimitRateDPO::getTime, DateUtil.endOfDay(DateUtil.parse(endTime))) ); diff --git a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/THDistortionServiceImpl.java b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/THDistortionServiceImpl.java index 5032ab6d7..9a3d6d930 100644 --- a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/THDistortionServiceImpl.java +++ b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/THDistortionServiceImpl.java @@ -3,7 +3,6 @@ package com.njcn.harmonic.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.njcn.common.config.GeneralInfo; import com.njcn.common.pojo.dto.SimpleDTO; @@ -14,19 +13,16 @@ import com.njcn.device.pq.enums.LineBaseEnum; import com.njcn.device.pq.pojo.dto.GeneralDeviceDTO; import com.njcn.device.pq.pojo.param.DeviceInfoParam; import com.njcn.device.pq.pojo.vo.LineDetailDataVO; -import com.njcn.harmonic.constant.Param; import com.njcn.harmonic.mapper.RMpVThdMapper; import com.njcn.harmonic.mapper.THDistortionMapper; import com.njcn.harmonic.pojo.dto.PublicDTO; import com.njcn.harmonic.pojo.po.RMpVThd; -import com.njcn.harmonic.pojo.po.RStatDataVD; import com.njcn.harmonic.pojo.vo.RMpVThdVO; import com.njcn.harmonic.pojo.vo.THDistortionCensusVO; import com.njcn.harmonic.pojo.vo.THDistortionVO; import com.njcn.harmonic.service.IRStatDataVDService; import com.njcn.harmonic.service.THDistortionService; import com.njcn.harmonic.utils.PubUtils; -import com.njcn.influxdb.utils.InfluxDbUtils; import lombok.AllArgsConstructor; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; diff --git a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/TerminalServiceImpl.java b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/TerminalServiceImpl.java index f938395e3..0a723a7c4 100644 --- a/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/TerminalServiceImpl.java +++ b/pqs-harmonic/harmonic-boot/src/main/java/com/njcn/harmonic/service/impl/TerminalServiceImpl.java @@ -14,7 +14,6 @@ import com.njcn.harmonic.pojo.vo.TerminalCensusVO; import com.njcn.harmonic.pojo.vo.TerminalVO; import com.njcn.harmonic.service.TerminalService; import com.njcn.harmonic.utils.PubUtils; -import com.njcn.influxdb.utils.InfluxDbUtils; import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; @@ -41,8 +40,6 @@ public class TerminalServiceImpl implements TerminalService { private final TerminalDataMapper terminalDataMapper; - private final InfluxDbUtils influxDbUtils; - @Override public List getTerminalData(DeviceInfoParam.BusinessParam terminalParam) { List terminalList = new ArrayList<>(); diff --git a/pqs-harmonic/harmonic-boot/src/main/resources/bootstrap.yml b/pqs-harmonic/harmonic-boot/src/main/resources/bootstrap.yml index 93c421f80..1f3027913 100644 --- a/pqs-harmonic/harmonic-boot/src/main/resources/bootstrap.yml +++ b/pqs-harmonic/harmonic-boot/src/main/resources/bootstrap.yml @@ -38,6 +38,8 @@ spring: multipart: max-file-size: 100MB max-request-size: 100MB + jackson: + time-zone: GMT+8 #项目日志的配置 diff --git a/pqs-influx/src/main/java/com/njcn/influx/imapper/CommonMapper.java b/pqs-influx/src/main/java/com/njcn/influx/imapper/CommonMapper.java index c53833c3d..2e52137e6 100644 --- a/pqs-influx/src/main/java/com/njcn/influx/imapper/CommonMapper.java +++ b/pqs-influx/src/main/java/com/njcn/influx/imapper/CommonMapper.java @@ -1,6 +1,9 @@ package com.njcn.influx.imapper; +import com.njcn.influx.ano.Param; +import com.njcn.influx.ano.Select; import com.njcn.influx.base.InfluxDbBaseMapper; +import com.njcn.influx.pojo.bo.HarmonicHistoryData; import com.njcn.influx.pojo.dto.StatisticalDataDTO; import com.njcn.influx.pojo.po.PowerQualityData; import com.njcn.influx.query.InfluxQueryWrapper; @@ -17,8 +20,6 @@ import java.util.List; public interface CommonMapper extends InfluxDbBaseMapper { - List getStatistical(InfluxQueryWrapper influxQueryWrapper); - StatisticalDataDTO getLineRtData(InfluxQueryWrapper influxQueryWrapper); List getDeviceRtData(InfluxQueryWrapper influxQueryWrapper); @@ -26,4 +27,13 @@ public interface CommonMapper extends InfluxDbBaseMapper { List getDeviceRtDataByTime(InfluxQueryWrapper influxQueryWrapper); StatisticalDataDTO getLineHistoryData(InfluxQueryWrapper influxQueryWrapper); + + @Select(value = "#{sql}",resultType = StatisticalDataDTO.class) + StatisticalDataDTO selectBySql(@Param("sql") StringBuilder sql); + + @Select(value = "#{sql}",resultType = StatisticalDataDTO.class) + List selectLimitTargetBySql(@Param("sql")String sql); + + @Select(value = "#{sql}",resultType = HarmonicHistoryData.class) + List getHistoryResult(@Param("sql")String sql); } diff --git a/pqs-influx/src/main/java/com/njcn/influx/imapper/DataHarmRateVMapper.java b/pqs-influx/src/main/java/com/njcn/influx/imapper/DataHarmRateVMapper.java new file mode 100644 index 000000000..fad5f78c5 --- /dev/null +++ b/pqs-influx/src/main/java/com/njcn/influx/imapper/DataHarmRateVMapper.java @@ -0,0 +1,20 @@ +package com.njcn.influx.imapper; + +import com.njcn.influx.base.InfluxDbBaseMapper; +import com.njcn.influx.pojo.dto.HarmData; +import com.njcn.influx.pojo.po.DataHarmRateV; +import com.njcn.influx.query.InfluxQueryWrapper; + +import java.util.List; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年07月17日 11:03 + */ +public interface DataHarmRateVMapper extends InfluxDbBaseMapper { + + DataHarmRateV getMeanAllTimesData(InfluxQueryWrapper influxQueryWrapper); + + List getHarmRateVHistoryData(InfluxQueryWrapper influxQueryWrapper); +} diff --git a/pqs-influx/src/main/java/com/njcn/influx/imapper/IDataIMapper.java b/pqs-influx/src/main/java/com/njcn/influx/imapper/IDataIMapper.java new file mode 100644 index 000000000..4eff221ec --- /dev/null +++ b/pqs-influx/src/main/java/com/njcn/influx/imapper/IDataIMapper.java @@ -0,0 +1,20 @@ +package com.njcn.influx.imapper; + +import com.njcn.influx.base.InfluxDbBaseMapper; +import com.njcn.influx.pojo.dto.HarmData; +import com.njcn.influx.pojo.po.DataI; +import com.njcn.influx.query.InfluxQueryWrapper; + +import java.util.List; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年07月17日 11:05 + */ +public interface IDataIMapper extends InfluxDbBaseMapper { + + DataI getMeanAllTimesData(InfluxQueryWrapper influxQueryWrapper); + + List getIHistoryData(InfluxQueryWrapper influxQueryWrapper); +} diff --git a/pqs-influx/src/main/java/com/njcn/influx/pojo/bo/HarmonicHistoryData.java b/pqs-influx/src/main/java/com/njcn/influx/pojo/bo/HarmonicHistoryData.java new file mode 100644 index 000000000..80031f053 --- /dev/null +++ b/pqs-influx/src/main/java/com/njcn/influx/pojo/bo/HarmonicHistoryData.java @@ -0,0 +1,31 @@ +package com.njcn.influx.pojo.bo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.njcn.common.utils.serializer.InstantDateSerializer; +import lombok.Data; +import org.influxdb.annotation.Column; + +import java.io.Serializable; +import java.time.Instant; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年07月17日 16:25 + */ +@Data +public class HarmonicHistoryData implements Serializable { + + + @JsonSerialize(using = InstantDateSerializer.class) + private Instant time; + + @Column(name = "phasic_type") + private String phasicType; + + private Float aValue; + + private Float bValue; + + private Float cValue; +} diff --git a/pqs-influx/src/main/java/com/njcn/influx/pojo/constant/InfluxDBTableConstant.java b/pqs-influx/src/main/java/com/njcn/influx/pojo/constant/InfluxDBTableConstant.java new file mode 100644 index 000000000..64409c25e --- /dev/null +++ b/pqs-influx/src/main/java/com/njcn/influx/pojo/constant/InfluxDBTableConstant.java @@ -0,0 +1,154 @@ +package com.njcn.influx.pojo.constant; + +/** + * 数据表相关常量 + * @author hongawen + * @version 1.0.0 + * @date 2022年10月14日 14:02 + */ +public interface InfluxDBTableConstant { + + /** + * 电压波动闪变表 + */ + String DATA_FLICKER = "data_flicker"; + + /** + * 电压波动表 + */ + String DATA_FLUC = "data_fluc"; + + /** + * 谐波电流角度表 + */ + String DATA_HARM_PHASIC_I = "data_harmphasic_i"; + + /** + * 谐波电压角度表 + */ + String DATA_HARM_PHASIC_V = "data_harmphasic_v"; + + /** + * 有功功率表 + */ + String DATA_HARM_POWER_P = "data_harmpower_p"; + + /** + * 无功功率表 + */ + String DATA_HARM_POWER_Q = "data_harmpower_q"; + + /** + * 视在功率表 + */ + String DATA_HARM_POWER_S = "data_harmpower_s"; + + /** + * 谐波电流含有率表 + */ + String DATA_HARM_RATE_I = "data_harmrate_i"; + + /** + * 谐波电压含有率表 + */ + String DATA_HARM_RATE_V = "data_harmrate_v"; + + /** + * 电流表 + */ + String DATA_I = "data_i"; + + /** + * 电流间谐波幅值表 + */ + String DATA_IN_HARM_I = "data_inharm_i"; + + /** + * 电压间谐波幅值表 + */ + String DATA_IN_HARM_V = "data_inharm_v"; + + /** + * 长时闪变表 + */ + String DATA_PLT = "data_plt"; + + /** + * 电压表 + */ + String DATA_V = "data_v"; + + + /** + * 时间 + */ + String TIME = "time"; + + /** + * 数据线路号 + */ + String LINE_ID = "line_id"; + + /** + * 装置ID + */ + String DEV_ID = "dev_id"; + + /** + * 数据类型 + */ + String PHASIC_TYPE = "phasic_type"; + + /** + * 指标类型 + */ + String VALUE_TYPE = "value_type"; + + /** + * 统计结果 + */ + String VALUE = "value_type"; + + /** + * 统计结果最大值 + */ + String MAX_VALUE = "maxValue"; + + /** + * 统计结果最小值 + */ + String MIN_VALUE = "minValue"; + + /** + * 数据质量标志 + */ + String QUALITY_FLAG = "quality_flag"; + + String CP95 = "CP95"; + + /** + * 相别 + */ + String NO_PHASE = "M"; + String PHASE_TYPE_A = "A"; + String PHASE_TYPE_AB = "AB"; + String PHASE_TYPE_B = "B"; + String PHASE_TYPE_BC = "BC"; + String PHASE_TYPE_C = "C"; + String PHASE_TYPE_C0 = "C0"; + String PHASE_TYPE_C1 = "C1"; + String PHASE_TYPE_C2 = "C2"; + String PHASE_TYPE_CA = "CA"; + String PHASE_TYPE_T = "T"; + + /** + * 日起始时间 + */ + String START_TIME = " 00:00:00"; + + /** + * 日结束时间 + */ + String END_TIME = " 23:59:59"; + +} diff --git a/pqs-influx/src/main/java/com/njcn/influx/pojo/dto/HarmData.java b/pqs-influx/src/main/java/com/njcn/influx/pojo/dto/HarmData.java new file mode 100644 index 000000000..4a85f7fd8 --- /dev/null +++ b/pqs-influx/src/main/java/com/njcn/influx/pojo/dto/HarmData.java @@ -0,0 +1,32 @@ +package com.njcn.influx.pojo.dto; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.njcn.common.utils.serializer.InstantDateDeserializer; +import com.njcn.common.utils.serializer.InstantDateSerializer; +import com.njcn.influx.ano.IgnoreData; +import lombok.Data; +import org.influxdb.annotation.Column; + +import java.io.Serializable; +import java.time.Instant; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年07月19日 09:43 + */ +@Data +public class HarmData implements Serializable{ + + + @Column(name = "time") + @JsonSerialize(using = InstantDateSerializer.class) + @JsonDeserialize(using = InstantDateDeserializer.class) + private Instant time; + + @IgnoreData(value = true) + private Float value; + + +} diff --git a/pqs-influx/src/main/java/com/njcn/influx/pojo/dto/HarmHistoryDataDTO.java b/pqs-influx/src/main/java/com/njcn/influx/pojo/dto/HarmHistoryDataDTO.java new file mode 100644 index 000000000..cc935fc67 --- /dev/null +++ b/pqs-influx/src/main/java/com/njcn/influx/pojo/dto/HarmHistoryDataDTO.java @@ -0,0 +1,24 @@ +package com.njcn.influx.pojo.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年07月19日 09:40 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class HarmHistoryDataDTO implements Serializable { + + private List historyData = new ArrayList<>(); + + private float overLimit; +} diff --git a/pqs-influx/src/main/java/com/njcn/influx/service/CommonService.java b/pqs-influx/src/main/java/com/njcn/influx/service/CommonService.java index 47980a6b8..3efc5f720 100644 --- a/pqs-influx/src/main/java/com/njcn/influx/service/CommonService.java +++ b/pqs-influx/src/main/java/com/njcn/influx/service/CommonService.java @@ -12,54 +12,60 @@ import java.util.List; * @version V1.0.0 */ public interface CommonService { - List commonquery(String lineId, String tableName, String columnName); - /** - * 根据条件获取监测点数据 - * @param lineId 监测点Id - * @param tableName 表名 - * @param columnName 字段名 - * @param phasic 相别 - * @param dataType 数据类型 - * @return - */ - StatisticalDataDTO getLineRtData(String lineId, String tableName, String columnName, String phasic, String dataType); + /** + * 根据条件获取监测点数据 + * + * @param lineId 监测点Id + * @param tableName 表名 + * @param columnName 字段名 + * @param phasic 相别 + * @param dataType 数据类型 + * @return + */ + StatisticalDataDTO getLineRtData(String lineId, String tableName, String columnName, String phasic, String dataType); - /** - * 根据条件获取监测点数据 - * @param lineIds 监测点Id - * @param tableName 表名 - * @param columnName 字段名 - * @param phasic 相别 - * @param dataType 数据类型 - * @return - */ - List getDeviceRtData(List lineIds, String tableName, String columnName, String phasic, String dataType); - /** - * @Description: getDeviceRtDataByTime - * @param lineIds 监测点Id - * @param tableName 表名 - * @param columnName 字段名 - * @param phasic 相别 - * @param dataType 数据类型 - *@param startTime start time - * @param endTime end time - * @return: java.util.List - * @Author: clam - * @Date: 2023/6/13 - */ - List getDeviceRtDataByTime(List lineIds, String tableName, String columnName, String phasic, String dataType,String startTime, String endTime); + /** + * 根据条件获取监测点数据 + * + * @param lineIds 监测点Id + * @param tableName 表名 + * @param columnName 字段名 + * @param phasic 相别 + * @param dataType 数据类型 + */ + List getDeviceRtData(List lineIds, String tableName, String columnName, String phasic, String dataType); - /** - * 根据条件获取监测点时间范围内的最大最小值 - * @param lineId 监测点Id - * @param tableName 表名 - * @param columnName 字段名 - * @param phasic 相别 - * @param dataType 数据类型 - * @return - */ - StatisticalDataDTO getLineHistoryData(String lineId, String tableName, String columnName, String startTime, String endTime); + /** + * @param lineIds 监测点Id + * @param tableName 表名 + * @param columnName 字段名 + * @param phasic 相别 + * @param dataType 数据类型 + * @param startTime start time + * @param endTime end time + * @Description: getDeviceRtDataByTime + * @return: java.util.List + * @Author: clam + * @Date: 2023/6/13 + */ + List getDeviceRtDataByTime(List lineIds, String tableName, String columnName, String phasic, String dataType, String startTime, String endTime); + /** + * 根据条件获取监测点时间范围内的最大最小值 + * + * @param lineId 监测点Id + * @param tableName 表名 + * @param columnName 字段名 + */ + StatisticalDataDTO getLineHistoryData(String lineId, String tableName, String columnName, String startTime, String endTime); + /*** + * 当表名、字段、统计方式均不确定时,代码拼接好sql + * @author hongawen + * @date 2023/7/14 15:23 + * @param sql influx-sql语句 + * @return StatisticalDataDTO + */ + StatisticalDataDTO selectBySql(StringBuilder sql); } diff --git a/pqs-influx/src/main/java/com/njcn/influx/service/DataHarmRateVService.java b/pqs-influx/src/main/java/com/njcn/influx/service/DataHarmRateVService.java new file mode 100644 index 000000000..f0c39fd6e --- /dev/null +++ b/pqs-influx/src/main/java/com/njcn/influx/service/DataHarmRateVService.java @@ -0,0 +1,13 @@ +package com.njcn.influx.service; + +import com.njcn.influx.pojo.po.DataHarmRateV; +import com.njcn.influx.query.InfluxQueryWrapper; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年07月17日 11:01 + */ +public interface DataHarmRateVService { + DataHarmRateV getMeanAllTimesData(InfluxQueryWrapper influxQueryWrapper); +} diff --git a/pqs-influx/src/main/java/com/njcn/influx/service/IDataIService.java b/pqs-influx/src/main/java/com/njcn/influx/service/IDataIService.java new file mode 100644 index 000000000..9c99b7911 --- /dev/null +++ b/pqs-influx/src/main/java/com/njcn/influx/service/IDataIService.java @@ -0,0 +1,14 @@ +package com.njcn.influx.service; + +import com.njcn.influx.pojo.po.DataI; +import com.njcn.influx.query.InfluxQueryWrapper; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年07月17日 11:04 + */ +public interface IDataIService { + + DataI getMeanAllTimesData(InfluxQueryWrapper influxQueryWrapper); +} diff --git a/pqs-influx/src/main/java/com/njcn/influx/service/impl/CommonServiceImpl.java b/pqs-influx/src/main/java/com/njcn/influx/service/impl/CommonServiceImpl.java index 4493aac2f..2f3f7402c 100644 --- a/pqs-influx/src/main/java/com/njcn/influx/service/impl/CommonServiceImpl.java +++ b/pqs-influx/src/main/java/com/njcn/influx/service/impl/CommonServiceImpl.java @@ -1,15 +1,8 @@ package com.njcn.influx.service.impl; -import com.njcn.common.pojo.constant.PatternRegex; -import com.njcn.common.pojo.enums.response.CommonResponseEnum; -import com.njcn.common.pojo.exception.BusinessException; -import com.njcn.common.pojo.response.HttpResult; -import com.njcn.common.utils.HttpResultUtil; -import com.njcn.common.utils.PubUtils; -import com.njcn.influx.ano.Select; import com.njcn.influx.imapper.CommonMapper; +import com.njcn.influx.pojo.constant.InfluxDBTableConstant; import com.njcn.influx.pojo.dto.StatisticalDataDTO; -import com.njcn.influx.pojo.po.HarmonicRatioData; import com.njcn.influx.query.InfluxQueryWrapper; import com.njcn.influx.service.CommonService; import com.njcn.influx.utils.ReflectUitl; @@ -29,23 +22,9 @@ import java.util.List; @Service @RequiredArgsConstructor public class CommonServiceImpl implements CommonService { + private final CommonMapper commonMapper; - @Override - public List commonquery(String lineId ,String tableName, String columnName) { - HashMap> entityClassesByAnnotation = ReflectUitl.getEntityClassesByAnnotation(); - Class aClass = entityClassesByAnnotation.get(tableName); - InfluxQueryWrapper influxQueryWrapper = new InfluxQueryWrapper(aClass,StatisticalDataDTO.class); - influxQueryWrapper.eq("LineId",lineId). - last(columnName,"statisticalData"). - groupBy(StatisticalDataDTO::getLineId, StatisticalDataDTO::getValueType, StatisticalDataDTO::getPhaseType); - - List statistical = commonMapper.getStatistical(influxQueryWrapper); - - return statistical; - - } - @Override public StatisticalDataDTO getLineRtData(String lineId, String tableName, String columnName, String phasic, String dataType) { InfluxQueryWrapper influxQueryWrapper = new InfluxQueryWrapper(tableName,StatisticalDataDTO.class); @@ -53,9 +32,9 @@ public class CommonServiceImpl implements CommonService { .select(StatisticalDataDTO::getPhaseType) .select(StatisticalDataDTO::getValueType) .last(columnName) - .eq("line_id",lineId) - .eq("phasic_type",phasic) - .eq("value_type",dataType); + .eq(InfluxDBTableConstant.LINE_ID,lineId) + .eq(InfluxDBTableConstant.PHASIC_TYPE,phasic) + .eq(InfluxDBTableConstant.VALUE_TYPE,dataType); return commonMapper.getLineRtData(influxQueryWrapper); } @@ -66,9 +45,9 @@ public class CommonServiceImpl implements CommonService { .select(StatisticalDataDTO::getPhaseType) .select(StatisticalDataDTO::getValueType) .last(columnName) - .or("line_id",lineIds) - .eq("phasic_type",phasic) - .eq("value_type",dataType).groupBy("line_id"); + .or(InfluxDBTableConstant.LINE_ID,lineIds) + .eq(InfluxDBTableConstant.PHASIC_TYPE,phasic) + .eq(InfluxDBTableConstant.VALUE_TYPE,dataType).groupBy(InfluxDBTableConstant.LINE_ID); return commonMapper.getDeviceRtData(influxQueryWrapper); } @@ -78,21 +57,26 @@ public class CommonServiceImpl implements CommonService { influxQueryWrapper.select(StatisticalDataDTO::getLineId) .select(StatisticalDataDTO::getPhaseType) .select(StatisticalDataDTO::getValueType) - .select(columnName,"value") - .or("line_id",lineIds) - .eq("phasic_type",phasic) - .between("time", startTime, endTime) - .eq("value_type",dataType); + .select(columnName,InfluxDBTableConstant.VALUE) + .or(InfluxDBTableConstant.LINE_ID,lineIds) + .eq(InfluxDBTableConstant.PHASIC_TYPE,phasic) + .between(InfluxDBTableConstant.TIME, startTime, endTime) + .eq(InfluxDBTableConstant.VALUE_TYPE,dataType); return commonMapper.getDeviceRtDataByTime(influxQueryWrapper); } @Override public StatisticalDataDTO getLineHistoryData(String lineId, String tableName, String columnName, String startTime, String endTime) { InfluxQueryWrapper influxQueryWrapper = new InfluxQueryWrapper(tableName,StatisticalDataDTO.class); - influxQueryWrapper.max(columnName,"maxValue") - .min(columnName,"minValue") - .eq("line_id",lineId) - .between("time", startTime, endTime); + influxQueryWrapper.max(columnName,InfluxDBTableConstant.MAX_VALUE) + .min(columnName,InfluxDBTableConstant.MIN_VALUE) + .eq(InfluxDBTableConstant.LINE_ID,lineId) + .between(InfluxDBTableConstant.TIME, startTime, endTime); return commonMapper.getLineHistoryData(influxQueryWrapper); } + + @Override + public StatisticalDataDTO selectBySql(StringBuilder sql) { + return commonMapper.selectBySql(sql); + } } diff --git a/pqs-influx/src/main/java/com/njcn/influx/service/impl/DataFlickerServiceImpl.java b/pqs-influx/src/main/java/com/njcn/influx/service/impl/DataFlickerServiceImpl.java index 22c24b9e9..148f49ce4 100644 --- a/pqs-influx/src/main/java/com/njcn/influx/service/impl/DataFlickerServiceImpl.java +++ b/pqs-influx/src/main/java/com/njcn/influx/service/impl/DataFlickerServiceImpl.java @@ -7,9 +7,6 @@ import com.njcn.influx.pojo.dto.DataFlickerDTO; import com.njcn.influx.pojo.po.DataFlicker; import com.njcn.influx.query.InfluxQueryWrapper; import com.njcn.influx.service.DataFlickerService; -import com.njcn.influx.utils.InfluxDbUtil; -import org.influxdb.dto.QueryResult; -import org.influxdb.impl.InfluxDBResultMapper; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -30,49 +27,6 @@ public class DataFlickerServiceImpl implements DataFlickerService { @Override public List getDataFlicker(String lineIndex, String startTime, String endTime) { - InfluxDbUtil influxDbUtils = new InfluxDbUtil("admin", "123456", "http://192.168.1.16:8086", "pqsbase_sjzx", "autogen"); - - List result = new ArrayList<>(); - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("line_id='").append(lineIndex).append("' and "); - //最小值 - String sql1 = "select min(fluc) AS fluc,min(plt) AS plt,min(pst) AS pst from data_flicker where " + stringBuilder + " time >= '" + startTime + "' and time <= '" + endTime + "' group by line_id,phasic_type,quality_flag tz('Asia/Shanghai')"; - QueryResult sqlResult1 = influxDbUtils.query(sql1); - InfluxDBResultMapper resultMapper1 = new InfluxDBResultMapper(); - List list1 = resultMapper1.toPOJO(sqlResult1, DataFlickerDTO.class); - list1.forEach(item -> { - item.setValueType("MIN"); - }); - //最大值 - String sql2 = "select max(fluc) AS fluc,max(plt) AS plt,max(pst) AS pst from data_flicker where " + stringBuilder + " time >= '" + startTime + "' and time <= '" + endTime + "' group by line_id,phasic_type,quality_flag tz('Asia/Shanghai')"; - QueryResult sqlResult2 = influxDbUtils.query(sql2); - InfluxDBResultMapper resultMapper2 = new InfluxDBResultMapper(); - List list2 = resultMapper2.toPOJO(sqlResult2, DataFlickerDTO.class); - list2.forEach(item -> { - item.setValueType("MAX"); - }); - //平均值 - String sql3 = "select mean(fluc) AS fluc,mean(plt) AS plt,mean(pst) AS pst from data_flicker where " + stringBuilder + " time >= '" + startTime + "' and time <= '" + endTime + "' group by line_id,phasic_type,quality_flag tz('Asia/Shanghai')"; - QueryResult sqlResult3 = influxDbUtils.query(sql3); - InfluxDBResultMapper resultMapper3 = new InfluxDBResultMapper(); - List list3 = resultMapper3.toPOJO(sqlResult3, DataFlickerDTO.class); - list3.forEach(item -> { - item.setValueType("AVG"); - }); - //CP95值 - String sql4 = "select percentile(fluc,95) AS fluc,percentile(plt,95) AS plt,percentile(pst,95) AS pst from data_flicker where " + stringBuilder + " time >= '" + startTime + "' and time <= '" + endTime + "' group by line_id,phasic_type,quality_flag tz('Asia/Shanghai')"; - QueryResult sqlResult4 = influxDbUtils.query(sql4); - InfluxDBResultMapper resultMapper4 = new InfluxDBResultMapper(); - List list4 = resultMapper4.toPOJO(sqlResult4, DataFlickerDTO.class); - list4.forEach(item -> { - item.setValueType("CP95"); - }); - result.addAll(list1); - result.addAll(list2); - result.addAll(list3); - result.addAll(list4); - - /////改造前↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑改造后↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ //最小值 List result1 ; InfluxQueryWrapper influxQueryWrapper = new InfluxQueryWrapper(DataFlicker.class, DataFlickerDTO.class); @@ -125,16 +79,14 @@ public class DataFlickerServiceImpl implements DataFlickerService { result4.forEach(item -> { item.setValueType("CP95"); }); - List result5 = new ArrayList<>(); - result5.addAll(result1); - result5.addAll(result2); - result5.addAll(result3); - result5.addAll(result4); - + List result = new ArrayList<>(); + result.addAll(result1); + result.addAll(result2); + result.addAll(result3); + result.addAll(result4); ObjectMapper objectMapper = new ObjectMapper(); try { System.out.println(objectMapper.writeValueAsString(result)); - System.out.println(objectMapper.writeValueAsString(result5)); } catch (JsonProcessingException e) { throw new RuntimeException(e); } diff --git a/pqs-influx/src/main/java/com/njcn/influx/service/impl/DataHarmRateVServiceImpl.java b/pqs-influx/src/main/java/com/njcn/influx/service/impl/DataHarmRateVServiceImpl.java new file mode 100644 index 000000000..77757f383 --- /dev/null +++ b/pqs-influx/src/main/java/com/njcn/influx/service/impl/DataHarmRateVServiceImpl.java @@ -0,0 +1,26 @@ +package com.njcn.influx.service.impl; + +import com.njcn.influx.imapper.DataHarmRateVMapper; +import com.njcn.influx.pojo.po.DataHarmRateV; +import com.njcn.influx.query.InfluxQueryWrapper; +import com.njcn.influx.service.DataHarmRateVService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年07月17日 11:02 + */ +@Service +@RequiredArgsConstructor +public class DataHarmRateVServiceImpl implements DataHarmRateVService { + + private final DataHarmRateVMapper dataHarmRateVMapper; + + + @Override + public DataHarmRateV getMeanAllTimesData(InfluxQueryWrapper influxQueryWrapper) { + return dataHarmRateVMapper.getMeanAllTimesData(influxQueryWrapper); + } +} diff --git a/pqs-influx/src/main/java/com/njcn/influx/service/impl/IDataIServiceImpl.java b/pqs-influx/src/main/java/com/njcn/influx/service/impl/IDataIServiceImpl.java new file mode 100644 index 000000000..9b5e97431 --- /dev/null +++ b/pqs-influx/src/main/java/com/njcn/influx/service/impl/IDataIServiceImpl.java @@ -0,0 +1,25 @@ +package com.njcn.influx.service.impl; + +import com.njcn.influx.imapper.IDataIMapper; +import com.njcn.influx.pojo.po.DataI; +import com.njcn.influx.query.InfluxQueryWrapper; +import com.njcn.influx.service.IDataIService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年07月17日 11:05 + */ +@Service +@RequiredArgsConstructor +public class IDataIServiceImpl implements IDataIService { + + private final IDataIMapper dataIMapper; + + @Override + public DataI getMeanAllTimesData(InfluxQueryWrapper influxQueryWrapper) { + return dataIMapper.getMeanAllTimesData(influxQueryWrapper); + } +} diff --git a/pqs-influx/src/main/java/com/njcn/influx/utils/InfluxDbUtil.java b/pqs-influx/src/main/java/com/njcn/influx/utils/InfluxDbUtil.java deleted file mode 100644 index e7be28306..000000000 --- a/pqs-influx/src/main/java/com/njcn/influx/utils/InfluxDbUtil.java +++ /dev/null @@ -1,376 +0,0 @@ -package com.njcn.influx.utils; - -import lombok.Data; -import lombok.extern.slf4j.Slf4j; -import okhttp3.OkHttpClient; -import org.influxdb.InfluxDB; -import org.influxdb.InfluxDB.ConsistencyLevel; -import org.influxdb.InfluxDBFactory; -import org.influxdb.dto.*; -import org.influxdb.dto.Point.Builder; - -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; -import java.time.temporal.ChronoField; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -/** - * 类的介绍: - * - * @author xuyang - * @version 1.0.0 - * @createTime 2021/11/16 10:20 - */ -@Slf4j -@Data -public class InfluxDbUtil { - static OkHttpClient.Builder client = new OkHttpClient.Builder() - .connectTimeout(1000,TimeUnit.SECONDS) - .readTimeout(1000, TimeUnit.SECONDS) - .writeTimeout(1000, TimeUnit.SECONDS); - private static final int FRACTION_MIN_WIDTH = 0; - private static final int FRACTION_MAX_WIDTH = 9; - private static final boolean ADD_DECIMAL_POINT = true; - private static final DateTimeFormatter RFC3339_FORMATTER = new DateTimeFormatterBuilder() - .appendPattern("yyyy-MM-dd'T'HH:mm:ss") - .appendFraction(ChronoField.NANO_OF_SECOND, FRACTION_MIN_WIDTH, FRACTION_MAX_WIDTH, ADD_DECIMAL_POINT) - .appendZoneOrOffsetId() - .toFormatter(); - - /**用户名*/ - private String username; - /**密码*/ - private String password; - /**链接地址*/ - private String openurl; - /**数据库*/ - private String dbName; - /**保留策略*/ - private String retentionPolicy; - - private InfluxDB influxDB; - - public InfluxDbUtil(String username, String password, String url, String dbName, String retentionPolicy) { - this.username = username; - this.password = password; - this.openurl = url; - this.dbName = dbName; - this.retentionPolicy = retentionPolicy == null || retentionPolicy.equals("") ? "autogen" : retentionPolicy; - influxDbBuild(); - } - - - /** - * 连接时序数据库 ,若不存在则创建 - * - * @return - */ - public InfluxDB influxDbBuild() { - if (influxDB == null) { - influxDB = InfluxDBFactory.connect(openurl, username, password,client); - } - try { - // if (!influxDB.databaseExists(database)) { - // influxDB.createDatabase(database); - // } - } catch (Exception e) { - // 该数据库可能设置动态代理,不支持创建数据库 - // e.printStackTrace(); - } finally { - influxDB.setRetentionPolicy(retentionPolicy); - } - influxDB.setLogLevel(InfluxDB.LogLevel.NONE); - return influxDB; - } - - - - - /** - * 创建数据库 - * - * @param dbName - */ - @SuppressWarnings("deprecation") - public void createDB(String dbName) { - influxDB.createDatabase(dbName); - } - - /** - * 删除数据库 - * - * @param dbName - */ - @SuppressWarnings("deprecation") - public void deleteDB(String dbName) { - influxDB.deleteDatabase(dbName); - } - - /** - * 测试连接是否正常 - * - * @return true 正常 - */ - public boolean ping() { - boolean isConnected = false; - Pong pong; - try { - pong = influxDB.ping(); - if (pong != null) { - isConnected = true; - } - } catch (Exception e) { - e.printStackTrace(); - } - return isConnected; - } - - /** - * 创建自定义保留策略 - * - * @param policyName 策略名 - * @param days 保存天数 - * @param replication 保存副本数量 - * @param isDefault 是否设为默认保留策略 - */ - public void createRetentionPolicy(String dataBaseName, String policyName, int days, int replication, - Boolean isDefault) { - String sql = String.format("CREATE RETENTION POLICY \"%s\" ON \"%s\" DURATION %sd REPLICATION %s ", policyName, - dataBaseName, days, replication); - if (isDefault) { - sql = sql + " DEFAULT"; - } - query(sql); - } - - /** - * 创建默认的保留策略 - * - * 策略名:hour,保存天数:30天,保存副本数量:1,设为默认保留策略 - */ - public void createDefaultRetentionPolicy() { - String command = String - .format("CREATE RETENTION POLICY \"%s\" ON \"%s\" DURATION %s REPLICATION %s DEFAULT", "hour", dbName, - "30d", 1); - this.query(command); - } - - /** - * 查询 - * - * @param command 查询语句 - * @return - */ - public QueryResult query(String command) { - return influxDB.query(new Query(command, dbName)); - } - - /** - * 插入 - * - * @param measurement 表 - * @param tags 标签 - * @param fields 字段 - */ - public void insert(String measurement, Map tags, Map fields, long time, - TimeUnit timeUnit) { - Builder builder = Point.measurement(measurement); - builder.tag(tags); - builder.fields(fields); - if (0 != time) { - builder.time(time, timeUnit); - } - influxDB.write(dbName, retentionPolicy, builder.build()); - } - - - - /** - * 批量写入测点 - * - * @param batchPoints - */ - public void batchInsert(BatchPoints batchPoints, TimeUnit timeUnit) { - influxDB.write(batchPoints); - // influxDB.enableGzip(); - // influxDB.enableBatch(2000,100,timeUnit); - // influxDB.disableGzip(); - // influxDB.disableBatch(); - } - - /** - * 批量写入数据 - * - * @param database 数据库 - * @param retentionPolicy 保存策略 - * @param consistency 一致性 - * @param records 要保存的数据(调用BatchPoints.lineProtocol()可得到一条record) - */ - public void batchInsert(final String database, final String retentionPolicy, final ConsistencyLevel consistency,TimeUnit timeUnit, final List records) { - influxDB.write(database, retentionPolicy, consistency, records); - } - - /** - * 批量写入数据 - * - * @param database 数据库 - * @param retentionPolicy 保存策略 - * @param consistency 一致性 - * @param records 要保存的数据(调用BatchPoints.lineProtocol()可得到一条record) - */ - public void batchInsert(final String database, final String retentionPolicy, final ConsistencyLevel consistency, final List records) { - influxDB.write(database, retentionPolicy, consistency, records); - } - - - /** - * 删除 - * - * @param command 删除语句 - * @return 返回错误信息 - */ - public String deleteMeasurementData(String command) { - QueryResult result = influxDB.query(new Query(command, dbName)); - return result.getError(); - } - - /** - * 关闭数据库 - */ - public void close() { - influxDB.close(); - } - - /** - * 构建Point - * - * @param measurement - * @param time - * @param fields - * @return - */ - public Point pointBuilder(String measurement, long time, TimeUnit timeUnit, Map tags, - Map fields) { - Point point = Point.measurement(measurement).time(time, timeUnit).tag(tags).fields(fields).build(); - return point; - } - - - - - - //单条查询语句封装 - /** - * 查询结果封装到map - * @param commond 单条sql语句 - * @return 查询结果 - */ - @Deprecated - public List> getResult(String commond){ - List> retList = new ArrayList<>(); - QueryResult queryResult = influxDB.query(new Query(commond,dbName)); - List results = queryResult.getResults(); - if (results==null||results.isEmpty()){ - return retList; - } - QueryResult.Result result = results.get(0); - List seriess = result.getSeries(); - if (seriess==null||seriess.isEmpty()){ - return retList; - } - QueryResult.Series series = seriess.get(0); - List columns = series.getColumns(); - List> values = series.getValues(); - for (List columnValue :values){ - Map map = new HashMap<>(1); - for (int i=0;i> getResult(String commond, String type){ - - List> retList = new ArrayList<>(); - QueryResult queryResult = influxDB.query(new Query(commond,dbName)); - List results = queryResult.getResults(); - if (results==null||results.isEmpty()){ - return retList; - } - QueryResult.Result result = results.get(0); - List seriess = result.getSeries(); - if (seriess==null||seriess.isEmpty()){ - return retList; - } - QueryResult.Series series = seriess.get(0); - List columns = series.getColumns(); - List> values = series.getValues(); - for (List columnValue :values){ - Map map = new HashMap<>(1); - for (int i=0;i> getMapResult(String commond){ - - List> retList = new ArrayList<>(); - QueryResult queryResult = influxDB.query(new Query(commond,dbName)); - List results = queryResult.getResults(); - if (results==null||results.isEmpty()){ - return retList; - } - QueryResult.Result result = results.get(0); - List seriess = result.getSeries(); - if (seriess==null||seriess.isEmpty()){ - return retList; - } - QueryResult.Series series = seriess.get(0); - List columns = series.getColumns(); - List> values = series.getValues(); - for (List columnValue :values){ - Map map = new HashMap<>(1); - for (int i=0;i