| | |
| | | package com.moral.util; |
| | | |
| | | import org.springframework.util.ObjectUtils; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | |
| | | } |
| | | |
| | | /** |
| | | * @param list 参数,[value={"O3":12},.....] |
| | | * @param params 参数,包含数据data,类型type,下限upper,上限lower |
| | | * @return 功能:臭氧日均值计算 |
| | | */ |
| | | public static Object getO3AvgOfDay(List<Map<String, Object>> list) { |
| | | public static Map<String, Object> getO3AvgOfDay(Map<String, Object> params) { |
| | | Map<String, Object> result = new HashMap<>(); |
| | | List<Map<String, Object>> list = (List<Map<String, Object>>) params.get("data"); |
| | | Object upper = params.get("o3Upper"); |
| | | Object lower = params.get("o3Lower"); |
| | | double max; |
| | | List<Double> avgs = new ArrayList<>(); |
| | | for (int i = 8; i <= 24; i++) { |
| | |
| | | for (Map<String, Object> dataMap : list) { |
| | | Map<String, Object> dataValue = JSONObject.parseObject((String) dataMap.get("value"), Map.class); |
| | | Double o3 = Double.parseDouble(dataValue.get(Constants.SENSOR_CODE_O3).toString()); |
| | | |
| | | //O3数据标记位 |
| | | Object flag = dataValue.get(Constants.SENSOR_CODE_O3 + "-" + Constants.MARKER_BIT_KEY); |
| | | //剔除有效性不足的数据 |
| | | if (!Constants.MARKER_BIT_TRUE.equals(flag)) { |
| | | continue; |
| | | } |
| | | |
| | | //剔除超过上下限的数据 |
| | | if (!ObjectUtils.isEmpty(upper)) { |
| | | if (o3 < (Double) upper) { |
| | | continue; |
| | | } |
| | | } |
| | | if (!ObjectUtils.isEmpty(lower)) { |
| | | if (o3 > (Double) upper) { |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | int hour = DateUtils.getHour((Date) dataMap.get("time")); |
| | | if (hour == 0) { |
| | | hour = 24; |
| | |
| | | max = avgs.stream().mapToDouble(aDouble -> aDouble).summaryStatistics().getMax(); |
| | | if (avgs.size() < 14) { |
| | | if (max < 160d) { |
| | | return null; |
| | | return result; |
| | | } |
| | | } |
| | | return sciCal(max, 4); |
| | | result.put(Constants.SENSOR_CODE_O3, sciCal(max, 4)); |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * @param list 参数,[value={"风速":12,”风向“:200},.....] |
| | | * @param data 数据 time:Date类型 |
| | | * @return 功能:臭氧8小时滑动值计算 |
| | | */ |
| | | public static List<Map<String, Object>> getO3_8H(List<Map<String, Object>> data) { |
| | | Date time1 = null; |
| | | Date time2 = null; |
| | | for (Map<String, Object> datum : data) { |
| | | Date time = (Date) datum.get("time"); |
| | | if (DateUtils.getHour(time) == 0) { |
| | | time2 = DateUtils.getDate(DateUtils.dateToDateString(time, DateUtils.yyyy_MM_dd_EN)); |
| | | } else { |
| | | time1 = DateUtils.getDate(DateUtils.dateToDateString(time, DateUtils.yyyy_MM_dd_EN)); |
| | | } |
| | | } |
| | | |
| | | List<Map<String, Object>> result = new ArrayList<>(); |
| | | for (int i = 8; i <= 24; i++) { |
| | | Map<String, Object> map = new HashMap<>(); |
| | | if (i < 24) { |
| | | map.put("time", ObjectUtils.isEmpty(time1) ? null : DateUtils.addHours(time1, i)); |
| | | } else { |
| | | map.put("time", ObjectUtils.isEmpty(time2) ? null : time2); |
| | | } |
| | | List<Double> value = new ArrayList<>(); |
| | | for (Map<String, Object> dataMap : data) { |
| | | Double o3 = Double.parseDouble(dataMap.get(Constants.SENSOR_CODE_O3).toString()); |
| | | Date time = (Date) dataMap.get("time"); |
| | | int hour = DateUtils.getHour(time); |
| | | if (hour == 0) { |
| | | hour = 24; |
| | | } |
| | | if (hour <= i && hour >= i - 7) { |
| | | value.add(o3); |
| | | } |
| | | } |
| | | if (value.size() < 6) { |
| | | continue; |
| | | } |
| | | double average = value.stream().mapToDouble(aDouble -> aDouble).summaryStatistics().getAverage(); |
| | | map.put(Constants.SENSOR_CODE_O3, average); |
| | | result.add(map); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * @param params 参数 |
| | | * @return 功能:风向均值计算 |
| | | */ |
| | | public static Object getWindDirAvg(List<Map<String, Object>> list) { |
| | | double avgDir; |
| | | double sumSin = 0d; |
| | | double sumCos = 0d; |
| | | int size = 0; |
| | | for (Map<String, Object> map : list) { |
| | | public static Map<String, Object> getWindDirAvg(Map<String, Object> params) { |
| | | Map<String, Object> result = new HashMap<>(); |
| | | List<Map<String, Object>> data = (List<Map<String, Object>>) params.get("data"); |
| | | String type = params.get("type").toString(); |
| | | Object windDirUpper = params.get("windDirUpper"); |
| | | Object windDirLower = params.get("windDirLower"); |
| | | Object windSpeedUpper = params.get("windSpeedUpper"); |
| | | Object windSpeedLower = params.get("windSpeedLower"); |
| | | |
| | | Double avgDir = null; |
| | | Double sumSin = 0d; |
| | | Double sumCos = 0d; |
| | | Integer size = 0; |
| | | for (Map<String, Object> map : data) { |
| | | Map<String, Object> dataValue = JSONObject.parseObject((String) map.get("value"), Map.class); |
| | | Object wind = dataValue.get(Constants.SENSOR_CODE_WIND_DIR); |
| | | Object speed = dataValue.get(Constants.SENSOR_CODE_WIND_SPEED); |
| | | if (wind == null || speed == null) { |
| | | Object flagDir = dataValue.get(Constants.SENSOR_CODE_WIND_DIR + "-" + Constants.MARKER_BIT_KEY); |
| | | Object flagSpeed = dataValue.get(Constants.SENSOR_CODE_WIND_SPEED + "-" + Constants.MARKER_BIT_KEY); |
| | | if (!Constants.MARKER_BIT_TRUE.equals(flagDir) || !Constants.MARKER_BIT_TRUE.equals(flagSpeed)) { |
| | | continue; |
| | | } |
| | | size++; |
| | | |
| | | if (ObjectUtils.isEmpty(wind) || ObjectUtils.isEmpty(speed)) { |
| | | continue; |
| | | } |
| | | double windDir = Double.parseDouble(wind.toString()); |
| | | double windSpeed = Double.parseDouble(speed.toString()); |
| | | double sin = windSpeed * Math.sin(windDir / 180d) * Math.PI; |
| | | double cos = windSpeed * Math.cos(windDir / 180d) * Math.PI; |
| | | |
| | | //剔除风速和风向超过上下限范围的数据 |
| | | if (!ObjectUtils.isEmpty(windDirUpper)) { |
| | | if (windDir < (Double) windDirUpper) { |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | if (!ObjectUtils.isEmpty(windDirLower)) { |
| | | if (windDir > (Double) windDirLower) { |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | if (!ObjectUtils.isEmpty(windSpeedUpper)) { |
| | | if (windSpeed < (Double) windSpeedUpper) { |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | if (!ObjectUtils.isEmpty(windSpeedLower)) { |
| | | if (windSpeed > (Double) windSpeedLower) { |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | size++; |
| | | double sin = windSpeed * Math.sin(windDir / 180d * Math.PI); |
| | | double cos = windSpeed * Math.cos(windDir / 180d * Math.PI); |
| | | sumSin += sin; |
| | | sumCos += cos; |
| | | } |
| | | if (size == 0) { |
| | | return null; |
| | | return result; |
| | | } |
| | | |
| | | double avgSin = sumSin / size; |
| | | double avgCos = sumCos / size; |
| | | |
| | | if (avgSin > 0 && avgCos > 0) { |
| | | avgDir = Math.atan(avgSin / avgCos) * 180 / Math.PI; |
| | | } else if ((avgSin > 0 && avgCos < 0) || (avgSin < 0 && avgCos < 0)) { |
| | | avgDir = Math.atan(avgSin / avgCos) * 180 / Math.PI + 180; |
| | | } else { |
| | | } else if (avgSin < 0 && avgCos > 0) { |
| | | avgDir = Math.atan(avgSin / avgCos) * 180 / Math.PI + 360; |
| | | } |
| | | return sciCal(avgDir, 4); |
| | | if (!ObjectUtils.isEmpty(avgDir)) { |
| | | double v = sciCal(avgDir, 4); |
| | | result.put(Constants.SENSOR_CODE_WIND_DIR, v); |
| | | if ("hour".equals(type)) { |
| | | //有效值>=45个,打标记位 N,<45打H H:有效性不足 |
| | | if (size >= 45) { |
| | | result.put(Constants.SENSOR_CODE_WIND_DIR + "-" + Constants.MARKER_BIT_KEY, Constants.MARKER_BIT_TRUE); |
| | | } else { |
| | | result.put(Constants.SENSOR_CODE_WIND_DIR + "-" + Constants.MARKER_BIT_KEY, Constants.MARKER_BIT_FALSE); |
| | | } |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | |
| | | int n = data.size(); |
| | | Collections.sort(data); |
| | | double v = n / (100 / p); |
| | | System.out.println(n % (100 / p)); |
| | | if (n % (100 / p) == 0) { |
| | | if (v == n) { |
| | | return data.get(n - 1); |
| | |
| | | } |
| | | |
| | | //一氧化碳周月均值计算 |
| | | public static Object getCOAvgOfWeekOrMonth(List<Map<String, Object>> list) { |
| | | public static Map<String, Object> getCOAvgOfWeekOrMonth(Map<String, Object> params) { |
| | | Map<String, Object> result = new HashMap<>(); |
| | | List<Map<String, Object>> list = (List<Map<String, Object>>) params.get("data"); |
| | | Object upper = params.get("coUpper"); |
| | | Object lower = params.get("coLower"); |
| | | |
| | | List<Double> data = new ArrayList<>(); |
| | | for (Map<String, Object> dataMap : list) { |
| | | Map<String, Object> dataValue = JSONObject.parseObject((String) dataMap.get("value"), Map.class); |
| | | Object o = dataValue.get(Constants.SENSOR_CODE_CO); |
| | | if (o == null) { |
| | | Object flag = dataValue.get(Constants.SENSOR_CODE_CO + "-" + Constants.MARKER_BIT_KEY); |
| | | if (!Constants.MARKER_BIT_TRUE.equals(flag)) { |
| | | continue; |
| | | } |
| | | if (ObjectUtils.isEmpty(o)) { |
| | | continue; |
| | | } |
| | | Double co = Double.parseDouble(o.toString()); |
| | | //剔除超过上下限的数据 |
| | | if (!ObjectUtils.isEmpty(upper)) { |
| | | if (co < (Double) upper) { |
| | | continue; |
| | | } |
| | | } |
| | | if (!ObjectUtils.isEmpty(lower)) { |
| | | if (co > (Double) upper) { |
| | | continue; |
| | | } |
| | | } |
| | | data.add(co); |
| | | } |
| | | if (data.size() == 0) { |
| | | return null; |
| | | return result; |
| | | } |
| | | return percentile(data, 95); |
| | | result.put(Constants.SENSOR_CODE_CO, percentile(data, 95)); |
| | | return result; |
| | | } |
| | | |
| | | //臭氧周月均值计算 |
| | | public static Object getO3AvgOfWeekOrMonth(List<Map<String, Object>> list) { |
| | | public static Map<String, Object> getO3AvgOfWeekOrMonth(Map<String, Object> params) { |
| | | Map<String, Object> result = new HashMap<>(); |
| | | List<Map<String, Object>> list = (List<Map<String, Object>>) params.get("data"); |
| | | Object upper = params.get("o3Upper"); |
| | | Object lower = params.get("o3Lower"); |
| | | List<Double> data = new ArrayList<>(); |
| | | for (Map<String, Object> dataMap : list) { |
| | | Map<String, Object> dataValue = JSONObject.parseObject((String) dataMap.get("value"), Map.class); |
| | | Object o = dataValue.get(Constants.SENSOR_CODE_O3); |
| | | if (o == null) { |
| | | Object flag = dataValue.get(Constants.SENSOR_CODE_O3 + "-" + Constants.MARKER_BIT_KEY); |
| | | if (!Constants.MARKER_BIT_TRUE.equals(flag)) { |
| | | continue; |
| | | } |
| | | if (ObjectUtils.isEmpty(o)) { |
| | | continue; |
| | | } |
| | | Double o3 = Double.parseDouble(o.toString()); |
| | | //剔除超过上下限的数据 |
| | | if (!ObjectUtils.isEmpty(upper)) { |
| | | if (o3 < (Double) upper) { |
| | | continue; |
| | | } |
| | | } |
| | | if (!ObjectUtils.isEmpty(lower)) { |
| | | if (o3 > (Double) upper) { |
| | | continue; |
| | | } |
| | | } |
| | | data.add(o3); |
| | | } |
| | | if (data.size() == 0) { |
| | | return null; |
| | | return result; |
| | | } |
| | | return percentile(data, 90); |
| | | result.put(Constants.SENSOR_CODE_O3, percentile(data, 90)); |
| | | return result; |
| | | } |
| | | } |