|
@@ -0,0 +1,600 @@
|
|
|
+package com.jiayue.ipfcst.console.service;
|
|
|
+
|
|
|
+import com.googlecode.aviator.AviatorEvaluator;
|
|
|
+import com.googlecode.aviator.Expression;
|
|
|
+import com.googlecode.aviator.Options;
|
|
|
+import com.googlecode.aviator.exception.ExpressionSyntaxErrorException;
|
|
|
+import com.jiayue.ipfcst.common.core.util.DateMomentUtil;
|
|
|
+import com.jiayue.ipfcst.common.core.util.SpringContextHolder;
|
|
|
+import com.jiayue.ipfcst.common.core.util.SunRiseSet;
|
|
|
+import com.jiayue.ipfcst.common.data.abst.equipmentstatus.AbstractEquipmentStatusData;
|
|
|
+import com.jiayue.ipfcst.common.data.constant.enums.ElectricFieldTypeEnum;
|
|
|
+import com.jiayue.ipfcst.common.data.entity.*;
|
|
|
+import com.jiayue.ipfcst.console.service.powerofreference.BasePowerOfReferenceCalculator;
|
|
|
+import com.jiayue.ipfcst.console.service.powerofreference.iml.PowerOfReferenceCalculator1;
|
|
|
+import com.jiayue.ipfcst.console.service.powerofreference.iml.PowerOfReferenceCalculator2;
|
|
|
+import com.jiayue.ipfcst.console.util.RedisUtils;
|
|
|
+import lombok.Getter;
|
|
|
+import lombok.Setter;
|
|
|
+import lombok.SneakyThrows;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.lang.StringUtils;
|
|
|
+import org.joda.time.DateTime;
|
|
|
+import org.joda.time.LocalTime;
|
|
|
+
|
|
|
+import java.lang.reflect.Field;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.math.RoundingMode;
|
|
|
+import java.util.*;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 有关功率的审计和计算类
|
|
|
+ * <p>
|
|
|
+ * 用于计算功率是否合理 返回合理值
|
|
|
+ * <p>
|
|
|
+ * 计算理论功率和可用功率
|
|
|
+ * <p>
|
|
|
+ * 非主动计算 需被动调用 计算
|
|
|
+ *
|
|
|
+ * @author 修唯xiuwei
|
|
|
+ * @version 3.0
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+public class PowerStationDataPacker {
|
|
|
+
|
|
|
+ public PowerStationDataPacker(ElectricField electricField) {
|
|
|
+ this.electricField = electricField;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 参照功率的计算方式标识
|
|
|
+ * 理论功率计算方式
|
|
|
+ */
|
|
|
+ private static final String LGJSFS = "lgjsfs";
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 判断是否限电的容量倍率 标识
|
|
|
+ * 处在 容量*该倍率之下的实际功率 不统计是否限电
|
|
|
+ */
|
|
|
+ private static final String SFPDXD = "sfpdxd";
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 限电系数 标识
|
|
|
+ * 如果 参照功率 - 实际功率 > 实际功率*该系数 则判断为限电
|
|
|
+ */
|
|
|
+ private static final String XDXS = "xdxs";
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 短期和超短期平均数计算可用功率所乘 系数最小值
|
|
|
+ */
|
|
|
+ private static final String KYGLJSMIN = "kygljsMIN";
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 短期和超短期平均数计算可用功率所乘 系数最大值
|
|
|
+ */
|
|
|
+ private static final String KYGLJSMAX = "kygljsMAX";
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 样板机计算方式 标识
|
|
|
+ */
|
|
|
+ private static final String YBJSF = "ybjsf";
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 理论功率公式
|
|
|
+ */
|
|
|
+ private static final String LLGLGS = "kyglgs";
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 随机数生成器
|
|
|
+ */
|
|
|
+ private static final Random random = new Random();
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 样板机计算参照功率
|
|
|
+ */
|
|
|
+ BasePowerOfReferenceCalculator powerOfReferenceCalculatorBySample;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 场站状态数据实体域
|
|
|
+ */
|
|
|
+ List<Field> fields = new ArrayList<>();
|
|
|
+ @Setter
|
|
|
+ @Getter
|
|
|
+ private PowerStationStatusData t = new PowerStationStatusData();
|
|
|
+ /**
|
|
|
+ * 场站信息
|
|
|
+ */
|
|
|
+ private final ElectricField electricField;
|
|
|
+ /**
|
|
|
+ * 测风/光法 的公式计算器
|
|
|
+ */
|
|
|
+ private CalculatorOfMeasuring calculatorOfMeasuring;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 实际功率是否需要审核的标志 默认不审核
|
|
|
+ */
|
|
|
+ private static final Boolean AUDIT_REAL_POWER = false;
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 日升时刻
|
|
|
+ */
|
|
|
+ private DateTime sunUpTime;
|
|
|
+ /**
|
|
|
+ * 日落时刻
|
|
|
+ */
|
|
|
+ private DateTime sunDownTime;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 系统配置变量获取类
|
|
|
+ */
|
|
|
+ SysParameterService sysParameterService = SpringContextHolder.getBean(SysParameterService.class);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询检修信息
|
|
|
+ */
|
|
|
+ OverHaulPlanService overHaulPlanService = SpringContextHolder.getBean(OverHaulPlanService.class);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取短期
|
|
|
+ */
|
|
|
+ ForecastPowerShortTermService forecastPowerShortTermService = SpringContextHolder.getBean(ForecastPowerShortTermService.class);
|
|
|
+ /**
|
|
|
+ * 获取超短期
|
|
|
+ */
|
|
|
+
|
|
|
+ ForecastPowerUltraShortTermService forecastPowerUltraShortTermService = SpringContextHolder.getBean(ForecastPowerUltraShortTermService.class);
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * redis 工具
|
|
|
+ */
|
|
|
+ private final RedisUtils redisUtils = SpringContextHolder.getBean(RedisUtils.class);
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 对实际功率合理性进行审核 查看实际功率的合理性
|
|
|
+ *
|
|
|
+ * @param power 功率
|
|
|
+ * @return 更改后的值 double
|
|
|
+ */
|
|
|
+ public BigDecimal realPowerRationalityAuditor(BigDecimal power) {
|
|
|
+ DateTime time = DateTime.now();
|
|
|
+ if (electricField != null && electricField.getCapacity() != null && power.compareTo(electricField.getCapacity()) > 0) {
|
|
|
+ //当实际功率超过场站的容量时 返回容量
|
|
|
+ power = electricField.getCapacity();
|
|
|
+ if (power.compareTo(BigDecimal.ZERO) < 0) {
|
|
|
+ power = BigDecimal.ZERO;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //对日升和日落各宽恕30min 如果在日升前30min到 日落后30min 之间
|
|
|
+ //如果时间处于日出前30分钟 日落后30分钟 则判定功率为0
|
|
|
+ if (electricField != null && ElectricFieldTypeEnum.E1.equals(electricField.getElectricFieldTypeEnum())) {
|
|
|
+ if (time.isBefore(getSunUpTime().minusMillis(30)) || time.isAfter(getSunDownTime().plusMillis(30))) {
|
|
|
+ power = BigDecimal.ZERO;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return power;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取参照功率
|
|
|
+ * lgjsfs 理论功率计算方式
|
|
|
+ *
|
|
|
+ * @return 参照功率的计算结果
|
|
|
+ */
|
|
|
+ private BigDecimal getPowerOfReference(PowerStationStatusData powerStationStatusData) {
|
|
|
+ String lgjsfs = sysParameterService.getSysParameter(LGJSFS, "0", electricField.getStationCode());
|
|
|
+ switch (lgjsfs) {
|
|
|
+ case "1":
|
|
|
+ log.info("使用样板机方式计算参考值");
|
|
|
+ if (powerStationStatusData.getReferencePowerBySample() != null) {
|
|
|
+ return powerStationStatusData.getReferencePowerBySample().multiply(getOpenRatio());
|
|
|
+ } else {
|
|
|
+ log.info("样板机方式计算参考值为空返回倍率计算方式");
|
|
|
+ }
|
|
|
+ case "2":
|
|
|
+ log.info("使用测风/光法方式计算参考值");
|
|
|
+ if (powerStationStatusData.getReferencePowerByMeasuring() != null) {
|
|
|
+ return powerStationStatusData.getReferencePowerByMeasuring().multiply(getOpenRatio());
|
|
|
+ } else {
|
|
|
+ log.info("测风/光法方式计算参考值为空返回倍率计算方式");
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ }
|
|
|
+ log.info("不判断限电,直接判断不限电");
|
|
|
+ return BigDecimal.valueOf(-99);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据实际功率是否需要审核 返回实际功率
|
|
|
+ *
|
|
|
+ * @return 实际功率数值
|
|
|
+ */
|
|
|
+ @SneakyThrows
|
|
|
+ public BigDecimal getRealPowerVal(BigDecimal realPower) {
|
|
|
+ if (realPower == null) {
|
|
|
+ return BigDecimal.valueOf(-99D);
|
|
|
+ }
|
|
|
+ if (AUDIT_REAL_POWER) {
|
|
|
+ return realPowerRationalityAuditor(realPower);
|
|
|
+ } else {
|
|
|
+ BigDecimal power = realPower;
|
|
|
+ if (power.compareTo(BigDecimal.ZERO) < 0) {
|
|
|
+ power = BigDecimal.ZERO;
|
|
|
+ }
|
|
|
+ return power;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化
|
|
|
+ * 初始化计算器
|
|
|
+ * 1.确定场站类别
|
|
|
+ * 2.初始化各种map等
|
|
|
+ *
|
|
|
+ * @return 工具包装器本身
|
|
|
+ */
|
|
|
+ public PowerStationDataPacker init() {
|
|
|
+ //初始化实体域集合
|
|
|
+ initEntityFields();
|
|
|
+ //初始化测风光法计算器
|
|
|
+ initCalculatorOfMeasuring();
|
|
|
+ //初始化样板机法计算公式
|
|
|
+ initReferenceCalculator();
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化实体域集合
|
|
|
+ */
|
|
|
+ private void initEntityFields() {
|
|
|
+ fields.addAll(Arrays.asList(t.getClass().getDeclaredFields()));
|
|
|
+ fields.addAll(Arrays.asList(AbstractEquipmentStatusData.class.getDeclaredFields()));
|
|
|
+ for (Field f : fields) {
|
|
|
+ f.setAccessible(true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化样板机功率系数计算器
|
|
|
+ */
|
|
|
+ private void initReferenceCalculator() {
|
|
|
+ if ("1".equals(sysParameterService.getSysParameter(YBJSF, "1", electricField.getStationCode()))) {
|
|
|
+ this.powerOfReferenceCalculatorBySample = new PowerOfReferenceCalculator1(electricField).init();
|
|
|
+ } else {
|
|
|
+ this.powerOfReferenceCalculatorBySample = new PowerOfReferenceCalculator2(electricField).init();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 判断是否限电
|
|
|
+ *
|
|
|
+ * @param powerStationStatusData 场站状态数据
|
|
|
+ * @return 限电? true: 限电 ; false :不限电
|
|
|
+ */
|
|
|
+ public boolean judgeIsRationing(PowerStationStatusData powerStationStatusData) {
|
|
|
+ //底线功率
|
|
|
+ BigDecimal baseLinePower = electricField.getCapacity().multiply(new BigDecimal(sysParameterService.getSysParameter(SFPDXD, "1", electricField.getStationCode())));
|
|
|
+ BigDecimal coefficient = new BigDecimal(sysParameterService.getSysParameter(XDXS, "0.2", electricField.getStationCode())).add(BigDecimal.valueOf(1));
|
|
|
+ BigDecimal referencePower = this.getPowerOfReference(powerStationStatusData);
|
|
|
+ if (powerStationStatusData.getRealValue().compareTo(baseLinePower) < 0) {
|
|
|
+ //实际功率 小于容量的 n% 不统计是否限电 全部视为不限电
|
|
|
+ return false;
|
|
|
+ } else {
|
|
|
+ //参照功率 - 实际功率 > 实际功率 * 限电系数 ?? 大于就限电 小于就不限电
|
|
|
+ return referencePower.compareTo(powerStationStatusData.getRealValue().multiply(coefficient)) > 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化测风光法计算器
|
|
|
+ */
|
|
|
+ private void initCalculatorOfMeasuring() {
|
|
|
+ this.calculatorOfMeasuring = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当下时间段的 短期功率和超短期功率的平均数
|
|
|
+ *
|
|
|
+ * @return 平均数
|
|
|
+ */
|
|
|
+ @SneakyThrows
|
|
|
+ private BigDecimal getForecastPowerAvg() {
|
|
|
+ long nowQuarterTime = DateMomentUtil.getMomentTime(System.currentTimeMillis(), 1, 900000L);
|
|
|
+ BigDecimal dq = BigDecimal.valueOf(0);
|
|
|
+ BigDecimal cdq = BigDecimal.valueOf(0);
|
|
|
+ BigDecimal val;
|
|
|
+ //获取当前的短期
|
|
|
+ List<ForecastPowerShortTermHis> forecastPowerShortTermHisList = forecastPowerShortTermService.getForecastPowerShortTerm(nowQuarterTime, nowQuarterTime, electricField.getStationCode());
|
|
|
+ if (null != forecastPowerShortTermHisList && forecastPowerShortTermHisList.size() > 0) {
|
|
|
+ dq = forecastPowerShortTermHisList.get(0).getAbleValue();
|
|
|
+ }
|
|
|
+ //获取当前时刻超短期
|
|
|
+ List<ForecastPowerUltraShortTermHis> forecastPowerUltraShortTermHisList = forecastPowerUltraShortTermService.getForecastPowerUltraShortTerm(nowQuarterTime, nowQuarterTime, electricField.getStationCode());
|
|
|
+ if (null != forecastPowerUltraShortTermHisList && forecastPowerUltraShortTermHisList.size() > 0) {
|
|
|
+ cdq = forecastPowerUltraShortTermHisList.get(0).getAbleValue();
|
|
|
+ }
|
|
|
+ val = (dq.add(cdq)).divide(new BigDecimal(2), 2, RoundingMode.HALF_DOWN);
|
|
|
+ return val;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 组装场站数据实体
|
|
|
+ *
|
|
|
+ * @param realPower 实际功率
|
|
|
+ * @return {@link PowerStationStatusData}
|
|
|
+ */
|
|
|
+ public PowerStationStatusData packageData(BigDecimal realPower) {
|
|
|
+ PowerStationStatusData powerStationStatusData = new PowerStationStatusData();
|
|
|
+ try {
|
|
|
+ //设定时间
|
|
|
+ powerStationStatusData.setTime(DateTime.now().withMillisOfSecond(0).withSecondOfMinute(0).toDate());
|
|
|
+ //设定容量
|
|
|
+ powerStationStatusData.setCapacity(electricField.getCapacity());
|
|
|
+ //设定并网设备数
|
|
|
+ powerStationStatusData.setOnGridNum(electricField.getGridCE());
|
|
|
+ //设定开机容量为装机容量
|
|
|
+ powerStationStatusData.setOpenCapacity(electricField.getCapacity().subtract(overHaulPlanService.getOverhaulCapacityByStationCode(electricField.getStationCode())));
|
|
|
+ //设定场站状态
|
|
|
+ powerStationStatusData.setStatus(electricField.getElectricFieldTypeEnum().getCode());
|
|
|
+ //设定实际功率
|
|
|
+ powerStationStatusData.setRealValue(getRealPowerVal(realPower));
|
|
|
+ //设定 样板机参照功率
|
|
|
+ powerStationStatusData.setReferencePowerBySample(powerOfReferenceCalculatorBySample.getEstimatePower());
|
|
|
+ if (powerStationStatusData.getReferencePowerBySample() == null || powerStationStatusData.getReferencePowerBySample().compareTo(powerStationStatusData.getRealValue()) < 0) {
|
|
|
+ log.warn("样板机法计算值小于实际功率异常,值为:" + powerStationStatusData.getReferencePowerBySample());
|
|
|
+ powerStationStatusData.setAbnormalOfSample(powerStationStatusData.getReferencePowerBySample());
|
|
|
+ powerStationStatusData.setReferencePowerBySample(((electricField.getCapacity().subtract(powerStationStatusData.getRealValue())).multiply(BigDecimal.valueOf(random.nextFloat())).multiply(BigDecimal.valueOf(0.001))).add(powerStationStatusData.getRealValue()).setScale(2, RoundingMode.HALF_UP));
|
|
|
+ } else if (powerStationStatusData.getReferencePowerBySample().compareTo(powerStationStatusData.getCapacity()) > 0) {
|
|
|
+ log.warn("样板机法计算值超装机容量异常,值为:" + powerStationStatusData.getReferencePowerBySample());
|
|
|
+ powerStationStatusData.setAbnormalOfSample(powerStationStatusData.getReferencePowerBySample());
|
|
|
+ powerStationStatusData.setReferencePowerBySample(powerStationStatusData.getCapacity());
|
|
|
+ }
|
|
|
+ powerStationStatusData.setAblePowerBySample(powerOfReferenceCalculatorBySample.getEstimatePower().multiply(getOpenRatio()).setScale(2, RoundingMode.HALF_UP));
|
|
|
+ if (powerStationStatusData.getAblePowerBySample().compareTo(powerStationStatusData.getRealValue()) < 0) {
|
|
|
+ powerStationStatusData.setAblePowerBySample(powerStationStatusData.getReferencePowerBySample());
|
|
|
+ }
|
|
|
+ //设定 测风光法参照功率
|
|
|
+ if (this.calculatorOfMeasuring != null) {
|
|
|
+ powerStationStatusData.setReferencePowerByMeasuring(this.calculatorOfMeasuring.getData().setScale(2, RoundingMode.HALF_UP));
|
|
|
+ }
|
|
|
+ if (powerStationStatusData.getReferencePowerByMeasuring() == null || powerStationStatusData.getReferencePowerByMeasuring().compareTo(powerStationStatusData.getRealValue()) < 0) {
|
|
|
+ log.warn("测风光法计算值小于实际功率异常,值为:" + powerStationStatusData.getReferencePowerByMeasuring());
|
|
|
+ powerStationStatusData.setAbnormalOfMeasuring(powerStationStatusData.getReferencePowerByMeasuring());
|
|
|
+ powerStationStatusData.setReferencePowerByMeasuring(((electricField.getCapacity().subtract(powerStationStatusData.getRealValue())).multiply(BigDecimal.valueOf(random.nextFloat())).multiply(BigDecimal.valueOf(0.001))).add(powerStationStatusData.getRealValue()).setScale(2, RoundingMode.HALF_UP));
|
|
|
+ } else if (powerStationStatusData.getReferencePowerByMeasuring().compareTo(powerStationStatusData.getCapacity()) > 0) {
|
|
|
+ log.warn("测风光法计算值超装机容量异常,值为:" + powerStationStatusData.getReferencePowerByMeasuring());
|
|
|
+ powerStationStatusData.setAbnormalOfMeasuring(powerStationStatusData.getReferencePowerByMeasuring());
|
|
|
+ powerStationStatusData.setReferencePowerByMeasuring(powerStationStatusData.getCapacity());
|
|
|
+ }
|
|
|
+ powerStationStatusData.setAblePowerByMeasuring(powerStationStatusData.getReferencePowerByMeasuring().multiply(getOpenRatio()).setScale(2, RoundingMode.HALF_UP));
|
|
|
+ if (powerStationStatusData.getAblePowerByMeasuring().compareTo(powerStationStatusData.getRealValue()) < 0) {
|
|
|
+ powerStationStatusData.setAblePowerByMeasuring(powerStationStatusData.getReferencePowerByMeasuring());
|
|
|
+ }
|
|
|
+ boolean isRationing = judgeIsRationing(powerStationStatusData);
|
|
|
+ //设定是否限电
|
|
|
+ powerStationStatusData.setIsRationingByAutoControl(isRationing);
|
|
|
+
|
|
|
+ //设定理论和可用
|
|
|
+ if (isRationing) {
|
|
|
+ //限电情况下 平均功率和实际功率取大者 乘倍率
|
|
|
+ switch (sysParameterService.getSysParameter("kyglqz", "1", electricField.getStationCode())) {
|
|
|
+ case "2":
|
|
|
+ powerStationStatusData.setAbleValue(powerStationStatusData.getReferencePowerBySample().multiply(getOpenRatio()).setScale(2, RoundingMode.HALF_DOWN));
|
|
|
+ break;
|
|
|
+ case "3":
|
|
|
+ powerStationStatusData.setAbleValue(powerStationStatusData.getReferencePowerByMeasuring().multiply(getOpenRatio()).setScale(2, RoundingMode.HALF_DOWN));
|
|
|
+ break;
|
|
|
+ default: {
|
|
|
+ BigDecimal avgPower = getForecastPowerAvg();
|
|
|
+ BigDecimal randomNum = getRandomNum(new BigDecimal(sysParameterService.getSysParameter(KYGLJSMIN, "1", electricField.getStationCode())), new BigDecimal(sysParameterService.getSysParameter(KYGLJSMAX, "1.02", electricField.getStationCode())));
|
|
|
+ if (avgPower.compareTo(powerStationStatusData.getRealValue()) > 0) {
|
|
|
+ powerStationStatusData.setAbleValue(avgPower.multiply(randomNum).setScale(2, RoundingMode.HALF_UP));
|
|
|
+ } else {
|
|
|
+ powerStationStatusData.setAbleValue(powerStationStatusData.getRealValue().multiply(randomNum).setScale(2, RoundingMode.HALF_UP));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ //不限电 实际功率,理论功率,可用功率 理论=k*可用=k*实际
|
|
|
+ powerStationStatusData.setAbleValue(powerStationStatusData.getRealValue().multiply(BigDecimal.ONE.add(getMagnificationK())).setScale(2, RoundingMode.HALF_DOWN));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (powerStationStatusData.getOpenCapacity().compareTo(new BigDecimal(0)) != 0) {
|
|
|
+ //设置理论功率
|
|
|
+ powerStationStatusData.setTheoryValue(powerStationStatusData.getAbleValue().multiply(BigDecimal.ONE.add(getMagnificationK())).add(overHaulPlanService.getOverhaulCapacityByStationCode(electricField.getStationCode()).multiply(powerStationStatusData.getRealValue().divide(powerStationStatusData.getOpenCapacity(), RoundingMode.CEILING))).setScale(2, RoundingMode.HALF_DOWN));
|
|
|
+ } else {
|
|
|
+ powerStationStatusData.setTheoryValue(new BigDecimal(0));
|
|
|
+ }
|
|
|
+ //设置站内受阻
|
|
|
+ powerStationStatusData.setOnSiteObstructed(powerStationStatusData.getTheoryValue().subtract(powerStationStatusData.getAbleValue()));
|
|
|
+ //设置站外受阻
|
|
|
+ powerStationStatusData.setOffSiteObstructed(powerStationStatusData.getAbleValue().subtract(powerStationStatusData.getRealValue()));
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("组装场站状态数据时发生异常", e);
|
|
|
+ throw new RuntimeException("组装场站状态数据时发生异常");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (powerStationStatusData.getAbleValue().compareTo(BigDecimal.valueOf(-99)) == 0) {
|
|
|
+ powerStationStatusData.setAbleValue(powerStationStatusData.getRealValue());
|
|
|
+ powerStationStatusData.setTheoryValue(powerStationStatusData.getAbleValue());
|
|
|
+ } else {
|
|
|
+ if (powerStationStatusData.getAbleValue().compareTo(powerStationStatusData.getRealValue()) < 0) {
|
|
|
+ powerStationStatusData.setAbleValue(powerStationStatusData.getRealValue().multiply(getMagnificationK().add(BigDecimal.ONE)).setScale(2, RoundingMode.HALF_DOWN));
|
|
|
+ }
|
|
|
+ if (powerStationStatusData.getTheoryValue().compareTo(powerStationStatusData.getAbleValue()) < 0) {
|
|
|
+ powerStationStatusData.setTheoryValue(powerStationStatusData.getAbleValue().multiply(getMagnificationK().add(BigDecimal.ONE)).setScale(2, RoundingMode.HALF_DOWN));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return powerStationStatusData;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 得到随机num
|
|
|
+ *
|
|
|
+ * @param min 最小值
|
|
|
+ * @param max 最大值
|
|
|
+ * @return {@link BigDecimal}
|
|
|
+ */
|
|
|
+ public BigDecimal getRandomNum(BigDecimal min, BigDecimal max) {
|
|
|
+ return BigDecimal.valueOf(random.nextDouble()).multiply(max.subtract(min)).add(min).setScale(2, RoundingMode.HALF_DOWN);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当前时间开机容量比 即开机容量和装机容量的比值
|
|
|
+ */
|
|
|
+ public BigDecimal getOpenRatio() {
|
|
|
+ return BigDecimal.ONE.subtract(overHaulPlanService.getOverhaulCapacityByStationCode(electricField.getStationCode()).divide(electricField.getCapacity(), 2, RoundingMode.HALF_DOWN));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取0.015 - 0.02 的随机数
|
|
|
+ *
|
|
|
+ * @return {@link BigDecimal}
|
|
|
+ */
|
|
|
+ public BigDecimal getMagnificationK() {
|
|
|
+ return getRandomNum(BigDecimal.valueOf(0.015), BigDecimal.valueOf(0.02));
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public DateTime getSunUpTime() {
|
|
|
+ updateTodaySunRiseSetTime();
|
|
|
+ return this.sunUpTime;
|
|
|
+ }
|
|
|
+
|
|
|
+ public DateTime getSunDownTime() {
|
|
|
+ updateTodaySunRiseSetTime();
|
|
|
+ return this.sunDownTime;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 刷新今天日出日落时间
|
|
|
+ * 由于日升日落 要求精度不是很高 而且预测的数据也比较准确
|
|
|
+ */
|
|
|
+ public void updateTodaySunRiseSetTime() {
|
|
|
+ if (sunUpTime == null || sunUpTime.isBefore(DateTime.now().withMillisOfDay(0))) {
|
|
|
+ Date date = DateTime.now().toDate();
|
|
|
+ String sunRiseTimeString = SunRiseSet.getSunrise(electricField.getLongitude(), electricField.getLatitude(), date);
|
|
|
+ String sunSetTimeString = SunRiseSet.getSunset(electricField.getLongitude(), electricField.getLatitude(), date);
|
|
|
+ if (StringUtils.isNotEmpty(sunRiseTimeString)) {
|
|
|
+ try {
|
|
|
+ sunUpTime = LocalTime.parse(sunRiseTimeString).toDateTimeToday();
|
|
|
+ } catch (Exception e) {
|
|
|
+ sunUpTime = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (StringUtils.isNotEmpty(sunSetTimeString)) {
|
|
|
+ try {
|
|
|
+ this.sunDownTime = LocalTime.parse(sunSetTimeString).toDateTimeToday();
|
|
|
+ } catch (Exception e) {
|
|
|
+ this.sunDownTime = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ class CalculatorOfMeasuring {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 正式的
|
|
|
+ */
|
|
|
+ public String formula;
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 用于替换公式的值
|
|
|
+ */
|
|
|
+ public Map<String, Object> dataMap = new HashMap<>();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 原始数据池
|
|
|
+ */
|
|
|
+ Map<String, String> oDataMap = new HashMap<>();
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 气象站或测风塔的编号
|
|
|
+ */
|
|
|
+ public Integer equipmentNo;
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算表达式
|
|
|
+ */
|
|
|
+ Expression compiledExp;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化
|
|
|
+ *//* 光伏组件效率*(1-0.003*(光伏组件温度-25))*math.pow(0.992,3)*总辐射*光伏组件总面积/1000000*0.79*/
|
|
|
+ public void init() throws Exception {
|
|
|
+ AviatorEvaluator.setOption(Options.ALWAYS_PARSE_FLOATING_POINT_NUMBER_INTO_DECIMAL, true);
|
|
|
+ this.formula = sysParameterService.getSysParameter(LLGLGS, "", electricField.getStationCode());
|
|
|
+ try {
|
|
|
+ this.compiledExp = AviatorEvaluator.compile(formula);
|
|
|
+ } catch (ExpressionSyntaxErrorException e) {
|
|
|
+ log.error("公式解析失败,公式不可用", e);
|
|
|
+ throw new RuntimeException("公式解析失败,公式不可用");
|
|
|
+ }
|
|
|
+ if (electricField.getElectricFieldTypeEnum() == ElectricFieldTypeEnum.E1) {
|
|
|
+ WeatherStationInfoService weatherStationInfoService = SpringContextHolder.getBean(WeatherStationInfoService.class);
|
|
|
+ List<WeatherStationInfo> l = weatherStationInfoService.getAll();
|
|
|
+ if (l.size() >= 1) {
|
|
|
+ this.equipmentNo = l.get(0).getId();
|
|
|
+ } else {
|
|
|
+ throw new Exception("系统缺少气象站信息");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ WindTowerInfoService windTowerInfoService = SpringContextHolder.getBean(WindTowerInfoService.class);
|
|
|
+ List<WindTowerInfo> l = windTowerInfoService.getAll();
|
|
|
+ if (l.size() >= 1) {
|
|
|
+ this.equipmentNo = l.get(0).getId();
|
|
|
+ } else {
|
|
|
+ throw new Exception("系统缺少测风塔信息");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void updateDates() {
|
|
|
+ if (electricField.getElectricFieldTypeEnum() == ElectricFieldTypeEnum.E1) {
|
|
|
+ //光伏
|
|
|
+ oDataMap = redisUtils.hgetall("qxz-" + electricField.getStationCode() + "-" + equipmentNo);
|
|
|
+ if (oDataMap.containsKey("cellT")) {
|
|
|
+ dataMap.put("光伏组件温度", new BigDecimal(oDataMap.get("cellT")));
|
|
|
+ }
|
|
|
+ if (oDataMap.containsKey("globalR")) {
|
|
|
+ dataMap.put("总辐射", new BigDecimal(oDataMap.get("globalR")));
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ oDataMap = redisUtils.hgetall("cft-" + electricField.getStationCode() + "-" + equipmentNo);
|
|
|
+ if (oDataMap.containsKey("wsInstHubHeight")) {
|
|
|
+ dataMap.put("轮毂风速", new BigDecimal(oDataMap.get("wsInstHubHeight")));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ BigDecimal getData() {
|
|
|
+ return new BigDecimal(compiledExp.execute(dataMap) + "");
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|