package com.jiayue.biz.util; import cn.hutool.core.convert.Convert; import com.jiayue.biz.domain.ProphaseAnemometryData; import com.jiayue.biz.domain.ProphaseWeatherData; import com.jiayue.biz.domain.WindTowerCalculationData; import com.jiayue.biz.eunms.WindDirectionEnum; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.time.DateUtils; import java.math.BigDecimal; import java.math.BigInteger; import java.math.RoundingMode; import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; @Slf4j public class CalculationUtil { /** * 根据设备属性风向获取数据 * * @param filterList 过滤出的风数据 * @param height 属性名(层高) * @return */ public static List> getForHeightAndWindDirectionEnum(List> filterList, String height, WindDirectionEnum windDirectionEnum) { List> collect = new ArrayList<>(); if (windDirectionEnum.name().equals("N")) { // N的范围为 348.75 w.get("wd_ave" + height) != null && (getBigDecimal(w.get("wd_ave" + height)).compareTo(windDirectionEnum.getLower()) >= 0 && getBigDecimal(w.get("wd_ave" + height)).compareTo(new BigDecimal(360)) <= 0) || (getBigDecimal(w.get("wd_ave" + height)).compareTo(windDirectionEnum.getUpper()) < 0 && getBigDecimal(w.get("wd_ave" + height)).compareTo(new BigDecimal(0)) > 0)).collect(Collectors.toList()); } else { collect = filterList.stream().filter(w -> w.get("wd_ave" + height) != null && getBigDecimal(w.get("wd_ave" + height)).compareTo(windDirectionEnum.getLower()) >= 0 && getBigDecimal(w.get("wd_ave" + height)).compareTo(windDirectionEnum.getUpper()) < 0).collect(Collectors.toList()); } return collect; } /** * 根据设备属性风向获取数据 Todo 新数据库格式 * * @param List 过滤出的风数据 * @return */ public static List getForHeightAndWindDirectionEnum(List List, WindDirectionEnum windEnum) { List collect = new ArrayList<>(); if (windEnum.name().equals("N")) { // N的范围为 348.75 e.getWdAve() != null).filter(w -> (getBigDecimal(w.getWdAve()).compareTo(windEnum.getLower()) >= 0 && getBigDecimal(w.getWdAve()).compareTo(new BigDecimal(360)) <= 0) || (getBigDecimal(w.getWdAve()).compareTo(windEnum.getUpper()) < 0 && getBigDecimal(w.getWdAve()).compareTo(new BigDecimal(0)) > 0)).collect(Collectors.toList()); } else { collect = List.stream().filter(w -> w.getWdAve() != null && getBigDecimal(w.getWdAve()).compareTo(windEnum.getLower()) >= 0 && getBigDecimal(w.getWdAve()).compareTo(windEnum.getUpper()) < 0).collect(Collectors.toList()); } return collect; } /** * 根据层高获取风速数据 todo 旧 * * @param filterList 过滤出的风数据 * @param fieldName 属性名(层高) * @return */ public static List getWsForHeight(List> filterList, String fieldName) { List wsList = new ArrayList<>(); for (Map map : filterList) { String abnormal_type = ""; //过滤异常值 if (map.get("abnormal_type") != null) { abnormal_type = map.get("abnormal_type").toString(); } if (map.get("ws_ave" + fieldName) != null && !map.get("ws_ave" + fieldName).equals("") && (!abnormal_type.contains("wsAve" + fieldName) || !abnormal_type.contains("ws_ave" + fieldName))) { if (Double.parseDouble(map.get("ws_ave" + fieldName).toString()) < 50) { wsList.add(getBigDecimal(map.get("ws_ave" + fieldName))); } } } return wsList; } /** * 根据层高获取空气密度 * * @param filterList 过滤出的风数据 * @return */ public static List getAir(List> filterList) { List wsList = new ArrayList<>(); for (Map map : filterList) { String abnormal_type = ""; //过滤异常值 if (map.get("abnormal_type") != null) { abnormal_type = map.get("abnormal_type").toString(); } if (map.get("air_density") != null && !map.get("air_density").equals("") && (!abnormal_type.contains("air_density"))) { if (Double.parseDouble(map.get("air_density").toString()) < 50) { wsList.add(getBigDecimal(map.get("air_density"))); } } } return wsList; } /** * 根据层高获取最大风速数据 * * @param filterList 过滤出的风数据 * @param fieldName 属性名(层高) * @return */ public static List getWsMaxForHeight(List> filterList, String fieldName) { List wsMaxList = new ArrayList<>(); for (Map map : filterList) { String abnormal_type = ""; //过滤异常值 if (map.get("abnormal_type") != null) { abnormal_type = map.get("abnormal_type").toString(); } if (map.get("ws_max" + fieldName) != null && (!abnormal_type.contains("wsMax" + fieldName) || !abnormal_type.contains("ws_max" + fieldName))) { wsMaxList.add(getBigDecimal((map.get("ws_max" + fieldName)))); } } return wsMaxList; } /** * 根据层高获取标准差数据 * * @param filterList 过滤出的风数据 * @param fieldName 属性名(层高) * @return */ public static List getWsStaForHeight(List> filterList, String fieldName) { List wsStaList = new ArrayList<>(); for (Map map : filterList) { String abnormal_type = ""; //过滤异常值 if (map.get("abnormal_type") != null) { abnormal_type = map.get("abnormal_type").toString(); } if (map.get("ws_sta" + fieldName) != null && (!abnormal_type.contains("wsSta" + fieldName) || !abnormal_type.contains("ws_sta" + fieldName))) { if (Double.parseDouble(map.get("ws_sta" + fieldName).toString()) < 50) { wsStaList.add(getBigDecimal((map.get("ws_sta" + fieldName)))); } } } return wsStaList; } /** * 计算平均风速 * * @param bigDecimalList 风速数据 * @return */ public static BigDecimal getAvgWind(List bigDecimalList) { return new BigDecimal(bigDecimalList.stream().collect(Collectors.averagingDouble(BigDecimal::doubleValue))).setScale(2,RoundingMode.HALF_UP); } /** * 计算风能密度(风功率玫瑰图) todo 旧 * * @return 风能密度 */ public static BigDecimal windEnergyDensity(List anemometryData, List weatherData) { BigDecimal density = new BigDecimal(-99); try { if (anemometryData.size() == weatherData.size() && anemometryData.size() != 0) { BigDecimal count = new BigDecimal(0); for (int i = 0; i < anemometryData.size(); i++) { if (weatherData.get(i).getAirDensity() != null && anemometryData.get(i).getWsAve() != null) { if (weatherData.get(i).getTs().getTime() == anemometryData.get(i).getTs().getTime()) { //计算风功率密度 空气密度*第i点的风速值的立方 求和/2 各个层高都有 count = count.add(getWpdCalculate(getBigDecimal(weatherData.get(i).getAirDensity()), getBigDecimal(anemometryData.get(i).getWsAve()))); } else { int finalI = i; List collect = weatherData.stream().filter(w -> w.getTs().getTime() == anemometryData.get(finalI).getTs().getTime()).collect(Collectors.toList()); if (collect.size() > 0) { count = count.add(getWpdCalculate(getBigDecimal(collect.get(0).getAirDensity()), getBigDecimal(anemometryData.get(i).getWsAve()))); } } } } density = count.divide((new BigDecimal(weatherData.size())), 2, RoundingMode.HALF_UP); } } catch (Exception e) { log.error("计算风风能密度时发生错误"); } finally { return density; } } //计算风功率密度公式 public static BigDecimal getWpdCalculate(BigDecimal wsAve, BigDecimal airAve) { return airAve.multiply(power(getBigDecimal(wsAve), 3)).multiply(BigDecimal.valueOf(0.5)); } /** * @param x 参数 * @param total 指数 * @return x的total次方 */ public static BigDecimal power(BigDecimal x, Integer total) { BigDecimal power = x; for (int i = 1; i < total; i++) { power = power.multiply(x); } return power; } /** * 从 String 中提取数字 * * @param string * @return */ public static String getNumberFromString(String string) { String str = string; str = str.trim(); StringBuffer str2 = new StringBuffer(); if (str != null && !"".equals(str)) { for (int i = 0; i < str.length(); i++) { if (str.charAt(i) >= 48 && str.charAt(i) <= 57) { String s = String.valueOf(str.charAt(i)); str2.append(s); } } } return str2.toString(); } /** * 计算风切变指数 * * @param v2 高度 Z2 的风速 * @param v1 高度 Z1 的风速 * @param z2 高度 * @param z1 高度 * @return 风切变指数 */ public static BigDecimal caWindShear(BigDecimal v2, BigDecimal v1, BigDecimal z2, BigDecimal z1) { v2 = v2.setScale(4, BigDecimal.ROUND_HALF_UP); z2 = z2.setScale(4, BigDecimal.ROUND_HALF_UP); BigDecimal result = new BigDecimal(-99); try { double v = v2.divide(v1, 2, BigDecimal.ROUND_HALF_UP).doubleValue(); double v3 = 0; if (v != 0) { v3 = Math.log10(v); } double z = z2.divide(z1, 2, BigDecimal.ROUND_HALF_UP).doubleValue(); double z3 = 0; if (z != 0) { z3 = Math.log10(z); } if (z3 != 0) { result = new BigDecimal(v3).divide(new BigDecimal(z3), 2, BigDecimal.ROUND_HALF_UP); } } catch (Exception e) { e.printStackTrace(); } finally { return result; } } /** * 计算湍流强度 * * @param wsSta 风速标准差 * @param ws 风速 * @return 湍流强度 */ public static BigDecimal caTurbulenceIntensity(BigDecimal wsSta, BigDecimal ws) { BigDecimal result = new BigDecimal(-99); try { if (ws.compareTo(new BigDecimal(0)) > 0) { result = wsSta.divide(ws, 2, BigDecimal.ROUND_HALF_UP); } } catch (Exception e) { e.printStackTrace(); } finally { return result; } } /** * 封装逐小时数据集合 * * @param awsList 数据 * @return */ public static List getData24(List awsList) { Long hour = 3600000l; Date systemDate = new Date(); List results = new ArrayList<>(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH"); //获取昨日开始和结束时间 Long startTime = DateMomentUtil.getDayStartTime(DateUtils.addDays(systemDate, -1).getTime()); Long endTime = startTime + 86399000; for (Long time = startTime; time <= endTime; time += hour) { Long finalTime = time; String format = simpleDateFormat.format(finalTime); List collect = awsList.stream().filter(s -> simpleDateFormat.format(s.getTime()) .equals(format) && s.getValue().compareTo(new BigDecimal(-99)) != 0) .map(WindTowerCalculationData::getValue).collect(Collectors.toList()); BigDecimal avg = BigDecimal.ZERO; if (collect.size() > 0) { avg = collect.stream().reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(collect.size()), 4, RoundingMode.HALF_UP); } results.add(avg); } return results; } /** * Object转BigDecimal类型 * * @param value 要转的object类型 * @return 转成的BigDecimal类型数据 */ public static BigDecimal getBigDecimal(Object value) { BigDecimal ret = null; if (value != null) { if (value instanceof BigDecimal) { ret = (BigDecimal) value; } else if (value instanceof String) { ret = new BigDecimal((String) value); } else if (value instanceof BigInteger) { ret = new BigDecimal((BigInteger) value); } else if (value instanceof Number) { ret = BigDecimal.valueOf(((Number) value).doubleValue()); } else { throw new ClassCastException("不能将数据 [" + value + "] 从 " + value.getClass() + "类型转为BigDecimal类型."); } } return ret; } /** * 机型:WH6.25N-182 * * @param ws 风速 * @return 拟合功率 BigDecimal */ public static BigDecimal getBattery(BigDecimal ws) { BigDecimal battery = new BigDecimal(0); if (ws.compareTo(BigDecimal.valueOf(3)) > 0 && ws.compareTo(BigDecimal.valueOf(12.5)) < 0) { //拟合功率 = (-9.066 * e^-5 * ws^8)+ (0.01055 * ws^7) - (0.5109 * ws^6) + (13.29 * ws^5) - (200.3 * ws^4) + (1755 * ws^3) - (8549 * ws^2) + (2.152 * e^4 * ws) - (2.153 * e^4) battery = (BigDecimal.valueOf(-9.006).multiply(BigDecimal.valueOf(Math.pow(10, -5)).multiply(CalculationUtil.power(ws, 8))) .add(BigDecimal.valueOf(0.01055).multiply(CalculationUtil.power(ws, 7))) .subtract(BigDecimal.valueOf(0.5109).multiply(CalculationUtil.power(ws, 6))) .add(BigDecimal.valueOf(13.29).multiply(CalculationUtil.power(ws, 5))) .subtract(BigDecimal.valueOf(200.3).multiply(CalculationUtil.power(ws, 4))) .add(BigDecimal.valueOf(1755).multiply(CalculationUtil.power(ws, 3))) .subtract(BigDecimal.valueOf(8549).multiply(CalculationUtil.power(ws, 2))) .add(BigDecimal.valueOf(2.152).multiply(BigDecimal.valueOf(Math.pow(10, 4)).multiply(ws))) .subtract(BigDecimal.valueOf(2.153).multiply(BigDecimal.valueOf(Math.pow(10, 4))))) .setScale(4, RoundingMode.HALF_UP); } else if (ws.compareTo(BigDecimal.valueOf(12.5)) >= 0) { battery = BigDecimal.valueOf(6250); } //单个风速功率 return battery; } /** * 计算威布尔值 * * @param e e * @param d 风速 * @param K K * @param A A * @return weibull */ public static BigDecimal getBigDecimal(double e, double d, double K, double A) { BigDecimal value = BigDecimal.ZERO; //e的-(U/K)次方的K次方 if (A != 0.0 && K != 0.0) { // U/A BigDecimal UAK1 = BigDecimal.valueOf(d).divide(BigDecimal.valueOf(A), 4, RoundingMode.HALF_UP); double UAK2 = UAK1.doubleValue(); //U/A 的k次方 double UAK = Math.pow(UAK2, K); //e的负 UAK次方 double EUAK = Math.pow(e, -UAK); //K/A BigDecimal KA = BigDecimal.valueOf(K).divide(BigDecimal.valueOf(A), 4, RoundingMode.HALF_UP); BigDecimal UA1 = BigDecimal.valueOf(d).divide(BigDecimal.valueOf(A), 4, RoundingMode.HALF_UP); double v = UA1.doubleValue(); double pow = Math.pow(v, (K - 1)); BigDecimal pow1 = BigDecimal.valueOf(pow).multiply(BigDecimal.valueOf(EUAK)); value = pow1.multiply(KA).setScale(4, BigDecimal.ROUND_HALF_UP); } return value; } //计算十分钟综合风切变 public static BigDecimal getWindShear(List prophaseAnemometryData, String[] heights) { BigDecimal sumWShear = BigDecimal.ZERO; if(prophaseAnemometryData.size() > 0){ String maxHeight = heights[0]; List heightCollect = prophaseAnemometryData.stream().filter(p -> p.getLayerHeight().equals(maxHeight)).collect(Collectors.toList()); BigDecimal wsAveForMax = BigDecimal.valueOf(heightCollect.get(0).getWsAve()); BigDecimal total = BigDecimal.ZERO; for (String minHeight : heights) { if (!getNumberFromString(minHeight).equals(getNumberFromString(maxHeight))) { List sCollect = prophaseAnemometryData.stream().filter(p -> p.getLayerHeight().equals(minHeight)).collect(Collectors.toList()); BigDecimal wsAveMin = BigDecimal.valueOf(sCollect.get(0).getWsAve()); double z = new BigDecimal(getNumberFromString(maxHeight)).divide(new BigDecimal(getNumberFromString(minHeight)), 4, RoundingMode.HALF_UP).doubleValue(); double z1 = Math.log10(z); BigDecimal shear = Convert.toBigDecimal(Math.log10(Convert.toDouble(wsAveForMax.divide(wsAveMin, 8, RoundingMode.HALF_UP)))) .divide(BigDecimal.valueOf(z1), 8, RoundingMode.HALF_UP); sumWShear = sumWShear.add(shear); total = total.add(BigDecimal.ONE); } } if(total.compareTo(BigDecimal.ZERO) > 0){ sumWShear = sumWShear.divide(total,2,RoundingMode.HALF_UP); } } return sumWShear; } }