package com.moral.util; import com.moral.pojo.AQI; import java.util.*; import com.moral.constant.Constants; public class AQIUtils { /*24小时浓度限值*/ private static Double[] SO2_Daily_Limit_Data = new Double[]{0d, 50d, 150d, 475d, 800d, 1600d, 2100d, 2620d}; private static Double[] NO2_Daily_Limit_Data = new Double[]{0d, 40d, 80d, 180d, 280d, 565d, 750d, 940d}; private static Double[] PM10_Daily_Limit_Data = new Double[]{0d, 50d, 150d, 250d, 350d, 420d, 500d, 600d}; private static Double[] CO_Daily_Limit_Data = new Double[]{0d, 2d, 4d, 14d, 24d, 36d, 48d, 60d}; private static Double[] PM2_5_Daily_Limit_Data = new Double[]{0d, 35d, 75d, 115d, 150d, 250d, 350d, 500d}; private static Double[] O3_Daily_Limit_Data = new Double[]{0d, 100d, 160d, 215d, 265d, 800d}; /*1小时浓度限值*/ private static Double[] SO2_Hourly_Limit_Data = new Double[]{0d, 150d, 500d, 650d, 800d}; private static Double[] NO2_Hourly_Limit_Data = new Double[]{0d, 100d, 200d, 700d, 1200d, 2340d, 3090d, 3840d}; private static Double[] PM10_Hourly_Limit_Data = new Double[]{0d, 50d, 150d, 250d, 350d, 420d, 500d, 600d}; private static Double[] CO_Hourly_Limit_Data = new Double[]{0d, 5d, 10d, 35d, 60d, 90d, 120d, 150d}; private static Double[] PM2_5_Hourly_Limit_Data = new Double[]{0d, 35d, 75d, 115d, 150d, 250d, 350d, 500d}; private static Double[] O3_Hourly_Limit_Data = new Double[]{0d, 160d, 200d, 300d, 400d, 800d, 1000d, 1200d}; /*空气质量分指数*/ private static Double[] IAQI_Array = new Double[]{0d,50d,100d,150d,200d,300d,400d,500d}; //计算6参未超标因子数 public static int standardCount(Map data){ int count = 0; if(data.get("PM2_5")!=null&&PM2_5IsStandard(Double.valueOf(data.get("PM2_5").toString()))) count++; if(data.get("PM10")!=null&&PM10IsStandard(Double.valueOf(data.get("PM10").toString()))) count++; if(data.get("SO2")!=null&&SO2IsStandard(Double.valueOf(data.get("SO2").toString()))) count++; if(data.get("NO2")!=null&&NO2IsStandard(Double.valueOf(data.get("NO2").toString()))) count++; if(data.get("CO")!=null&&COIsStandard(Double.valueOf(data.get("CO").toString()))) count++; if(data.get("O3")!=null&&O3IsStandard(Double.valueOf(data.get("O3").toString()))) count++; return count; } //判断aqi是否达标 public static boolean aqiIsStandard(int aqi){ if(aqi<=100) return true; return false; } public static boolean PM2_5IsStandard(Double pm2_5){ if(pm2_5<=75) return true; return false; } public static boolean PM10IsStandard(Double pm10){ if(pm10<=150) return true; return false; } public static boolean SO2IsStandard(Double so2){ if(so2<=500) return true; return false; } public static boolean NO2IsStandard(Double no2){ if(no2<=80) return true; return false; } public static boolean COIsStandard(Double co){ if(co<=4) return true; return false; } public static boolean O3IsStandard(Double o3){ if(o3<=200) return true; return false; } /** * @Description: 计算AQI污染等级,返回污染等级名称 * @Param: * @return: * @Author: 陈凯裕 * @Date: 2021/10/29 */ public static String classOfPollutionByAqi(Integer aqi){ if(aqi>300) return Constants.SERVER_WEATHER; if(aqi>200) return Constants.SERIOUS_WEATHER; if(aqi>150) return Constants.MIDDLE_WEATHER; if(aqi>100) return Constants.MILD_WEATHER; if(aqi>50) return Constants.GOOD_WEATHER; return Constants.EXCELLENT_WEATHER; } /** * @Description: 根据AQI计算污染等级,返回污染等级Code * @Param: [aqi] * @return: java.lang.String * @Author: 陈凯裕 * @Date: 2021/11/11 */ public static String classCodeOfPollutionByAqi(Integer aqi){ if(aqi>300) return Constants.SERVER_WEATHER_CODE; if(aqi>200) return Constants.SERIOUS_WEATHER_CODE; if(aqi>150) return Constants.MIDDLE_WEATHER_CODE; if(aqi>100) return Constants.MILD_WEATHER_CODE; if(aqi>50) return Constants.GOOD_WEATHER_CODE; return Constants.EXCELLENT_WEATHER_CODE; } /** * @Description: 24小时AQI * @Param: [paramMap] * @return: java.lang.Integer * @Author: 陈凯裕 * @Date: 2021/11/3 */ public static AQI dailyAQI(Map paramMap){ if(paramMap==null) return null; List IAQIList = new ArrayList<>(); List primaryPollutantNames = new ArrayList<>(); List primaryPollutantCodes = new ArrayList<>(); Integer PM2_5IAQI; Integer SO2IAQI; Integer NO2IAQI; Integer COIAQI; Integer PM10IAQI; Integer O3IAQI; if(paramMap.get(Constants.SENSOR_CODE_PM25)!=null){ Double PM2_5 = Double.valueOf(paramMap.get("a34004").toString()); PM2_5IAQI = calculateIAQIUniversal(PM2_5,PM2_5_Daily_Limit_Data); IAQIList.add(PM2_5IAQI); if(PM2_5IAQI>50){ primaryPollutantCodes.add(Constants.SENSOR_CODE_PM25); primaryPollutantNames.add("PM2.5"); } } if(paramMap.get(Constants.SENSOR_CODE_SO2)!=null){ Double SO2 = Double.valueOf(paramMap.get("a21026").toString()); SO2IAQI = calculateIAQIUniversal(SO2,SO2_Daily_Limit_Data); IAQIList.add(SO2IAQI); if(SO2IAQI>50){ primaryPollutantNames.add("SO2"); primaryPollutantCodes.add(Constants.SENSOR_CODE_SO2); } } if(paramMap.get(Constants.SENSOR_CODE_NO2)!=null){ Double NO2 = Double.valueOf(paramMap.get("a21004").toString()); NO2IAQI = calculateIAQIUniversal(NO2,NO2_Daily_Limit_Data); IAQIList.add(NO2IAQI); if(NO2IAQI>50){ primaryPollutantNames.add("NO2"); primaryPollutantCodes.add(Constants.SENSOR_CODE_NO2); } } if(paramMap.get(Constants.SENSOR_CODE_CO)!=null){ Double CO = Double.valueOf(paramMap.get("a21005").toString()); COIAQI = calculateIAQIUniversal(CO,CO_Daily_Limit_Data); IAQIList.add(COIAQI); if(COIAQI>50){ primaryPollutantNames.add("CO"); primaryPollutantCodes.add(Constants.SENSOR_CODE_CO); } } if(paramMap.get(Constants.SENSOR_CODE_PM10)!=null){ Double PM10 = Double.valueOf(paramMap.get("a34002").toString()); PM10IAQI = calculateIAQIUniversal(PM10,PM10_Daily_Limit_Data); IAQIList.add(PM10IAQI); if(PM10IAQI>50){ primaryPollutantNames.add("PM10"); primaryPollutantCodes.add(Constants.SENSOR_CODE_PM10); } } if(paramMap.get(Constants.SENSOR_CODE_O3)!=null){ Double O3 = Double.valueOf(paramMap.get("a05024").toString()); O3IAQI = calculateO3DailyIAQI(O3); IAQIList.add(O3IAQI); if(O3IAQI>50){ primaryPollutantNames.add("O3"); primaryPollutantCodes.add(Constants.SENSOR_CODE_O3); } } AQI aqi= new AQI(); aqi.setAQIValue(getAQIByIAQIs(IAQIList)); aqi.setPrimaryPollutantCodes(primaryPollutantCodes); aqi.setPrimaryPollutantNames(primaryPollutantNames); return aqi; } /** * @Description: 1小时AQI * @Param: [paramMap] * @return: java.lang.Integer * @Author: 陈凯裕 * @Date: 2021/11/3 */ public static AQI hourlyAQI(Map paramMap){ if(paramMap==null) return null; List IAQIList = new ArrayList<>(); List primaryPollutantNames = new ArrayList<>(); List primaryPollutantCodes = new ArrayList<>(); Integer PM2_5IAQI; Integer SO2IAQI; Integer NO2IAQI; Integer COIAQI; Integer PM10IAQI; Integer O3IAQI; if(paramMap.get("a34004")!=null){ Double PM2_5 = Double.valueOf(paramMap.get("a34004").toString()); PM2_5IAQI = calculateIAQIUniversal(PM2_5,PM2_5_Hourly_Limit_Data); IAQIList.add(PM2_5IAQI); if(PM2_5IAQI>50){ primaryPollutantCodes.add(Constants.SENSOR_CODE_PM25); primaryPollutantNames.add("PM2.5"); } } if(paramMap.get("a21026")!=null){ Double SO2 = Double.valueOf(paramMap.get("a21026").toString()); SO2IAQI = calculateSO2HourlyIAQI(SO2); IAQIList.add(SO2IAQI); if(SO2IAQI>50){ primaryPollutantNames.add("SO2"); primaryPollutantCodes.add(Constants.SENSOR_CODE_SO2); } } if(paramMap.get("a21004")!=null){ Double NO2 = Double.valueOf(paramMap.get("a21004").toString()); NO2IAQI = calculateIAQIUniversal(NO2,NO2_Hourly_Limit_Data); IAQIList.add(NO2IAQI); if(NO2IAQI>50){ primaryPollutantNames.add("NO2"); primaryPollutantCodes.add(Constants.SENSOR_CODE_NO2); } } if(paramMap.get("a21005")!=null){ Double CO = Double.valueOf(paramMap.get("a21005").toString()); COIAQI = calculateIAQIUniversal(CO,CO_Hourly_Limit_Data); IAQIList.add(COIAQI); if(COIAQI>50){ primaryPollutantNames.add("CO"); primaryPollutantCodes.add(Constants.SENSOR_CODE_CO); } } if(paramMap.get("a34002")!=null){ Double PM10 = Double.valueOf(paramMap.get("a34002").toString()); PM10IAQI = calculateIAQIUniversal(PM10,PM10_Hourly_Limit_Data); IAQIList.add(PM10IAQI); if(PM10IAQI>50){ primaryPollutantNames.add("PM10"); primaryPollutantCodes.add(Constants.SENSOR_CODE_PM10); } } if(paramMap.get("a05024")!=null){ Double O3 = Double.valueOf(paramMap.get("a05024").toString()); O3IAQI = calculateIAQIUniversal(O3,O3_Hourly_Limit_Data); IAQIList.add(O3IAQI); if(O3IAQI>50) { primaryPollutantNames.add("O3"); primaryPollutantCodes.add(Constants.SENSOR_CODE_O3); } } AQI aqi= new AQI(); aqi.setAQIValue(getAQIByIAQIs(IAQIList)); aqi.setPrimaryPollutantCodes(primaryPollutantCodes); aqi.setPrimaryPollutantNames(primaryPollutantNames); return aqi; } /** * @Description: 根据IAQI计算AQI * @Param: [IAQIs] * @return: int * @Author: 陈凯裕 * @Date: 2021/11/3 */ private static Integer getAQIByIAQIs(List IAQIs){ if(IAQIs.size()==0) return null; Optional max = IAQIs.stream().max(Comparator.comparing(Integer::intValue)); return max.get(); } /** * @Description: 除了so2的小时IAQI,O3的日IAQI外的IAQI计算公式 * @Param: [Cp, limitData] * @return: java.lang.Integer * @Author: 陈凯裕 * @Date: 2021/11/2 */ private static Integer calculateIAQIUniversal(Double Cp,Double[] limitData){ int index = getStartIndexFromArray(Cp, limitData); Double BPHi; Double BPLo; Double IAQIHi; Double IAQILo; if(index==limitData.length-1){ return 500; }else{ BPHi = limitData[index+1]; BPLo = limitData[index]; IAQIHi = IAQI_Array[index+1]; IAQILo = IAQI_Array[index]; } return calculateIAQIFormula(Cp,BPHi,BPLo,IAQIHi,IAQILo); } /** * @Description: 计算so2的小时IAQI * @Param: [Cp, limitData] * @return: java.lang.Integer * @Author: 陈凯裕 * @Date: 2021/11/2 */ private static Integer calculateSO2HourlyIAQI(Double Cp){ Double BPHi; Double BPLo; Double IAQIHi; Double IAQILo; Double[] limitData = SO2_Hourly_Limit_Data; int index = getStartIndexFromArray(Cp, limitData); //如果so2超过了小时最大限值,则采用24小时的限值标准,再计算分指数 if(index ==SO2_Hourly_Limit_Data.length-1){ limitData = SO2_Daily_Limit_Data; index = getStartIndexFromArray(Cp,limitData); } if(index==limitData.length-1){ return 500; }else{ BPHi = limitData[index+1]; BPLo = limitData[index]; IAQIHi = IAQI_Array[index+1]; IAQILo = IAQI_Array[index]; } return calculateIAQIFormula(Cp,BPHi,BPLo,IAQIHi,IAQILo); } /** * @Description: 计算O3日的IAQI * @Param: [Cp] * @return: java.lang.Integer * @Author: 陈凯裕 * @Date: 2021/11/3 */ private static Integer calculateO3DailyIAQI(Double Cp){ Double BPHi; Double BPLo; Double IAQIHi; Double IAQILo; Double[] limitData = O3_Daily_Limit_Data; int index = getStartIndexFromArray(Cp, limitData); //如果so2超过了小时最大限值,则采用24小时的限值标准,再计算分指数 if(index ==O3_Daily_Limit_Data.length-1){ limitData = O3_Hourly_Limit_Data; index = getStartIndexFromArray(Cp,limitData); } if(index==limitData.length-1){ return 500; }else{ BPHi = limitData[index+1]; BPLo = limitData[index]; IAQIHi = IAQI_Array[index+1]; IAQILo = IAQI_Array[index]; } return calculateIAQIFormula(Cp,BPHi,BPLo,IAQIHi,IAQILo); } /** * @Description: 计算IAQI的公式 * @Param: [Cp, BPHi, BPLo, IAQIHi, IAQILo] * @return: java.lang.Integer * @Author: 陈凯裕 * @Date: 2021/11/3 */ private static Integer calculateIAQIFormula(Double Cp, Double BPHi, Double BPLo, Double IAQIHi, Double IAQILo) { Double tmp1 = MathUtils.sub(IAQIHi, IAQILo); Double tmp2 = MathUtils.sub(BPHi, BPLo); Double tmp3 = MathUtils.sub(Cp, BPLo); Double tmp4 = MathUtils.division(tmp1, tmp2, 2); Double tmp5 = MathUtils.mul(tmp4, tmp3); Double IAQI = MathUtils.add(tmp5, IAQILo); return new Double(AmendUtils.sciCal(IAQI, 0)).intValue(); } /*获取数值对应数组中的索引范围的开始值 * 例如:数值:5 10 * 数组:[0,5,15,20] [0,5,8,12] * 结果:1(左闭右开) 2 * */ private static int getStartIndexFromArray(Double num, Double[] array) { for (int i = 0; i < array.length - 1; i++) { if (num >= array[i] && num < array[i + 1]) return i; if (i == array.length - 2) return i + 1; } return 0; } }