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<String,Object> 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<String,Object> paramMap){
|
if(paramMap==null)
|
return null;
|
List<Integer> IAQIList = new ArrayList<>();
|
List<String> primaryPollutantNames = new ArrayList<>();
|
List<String> 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<String,Object> paramMap){
|
if(paramMap==null)
|
return null;
|
List<Integer> IAQIList = new ArrayList<>();
|
List<String> primaryPollutantNames = new ArrayList<>();
|
List<String> 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<Integer> IAQIs){
|
if(IAQIs.size()==0)
|
return null;
|
Optional<Integer> 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;
|
}
|
|
}
|