From ddaee239feb428cc426396a742c9d992d5983548 Mon Sep 17 00:00:00 2001
From: kaiyu <404897439@qq.com>
Date: Fri, 18 Feb 2022 10:42:38 +0800
Subject: [PATCH] screen-api 更改优良天变化率正负号
---
screen-api/src/main/java/com/moral/api/service/impl/CityAqiYearlyServiceImpl.java | 433 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 433 insertions(+), 0 deletions(-)
diff --git a/screen-api/src/main/java/com/moral/api/service/impl/CityAqiYearlyServiceImpl.java b/screen-api/src/main/java/com/moral/api/service/impl/CityAqiYearlyServiceImpl.java
index 10bd866..1fec4d8 100644
--- a/screen-api/src/main/java/com/moral/api/service/impl/CityAqiYearlyServiceImpl.java
+++ b/screen-api/src/main/java/com/moral/api/service/impl/CityAqiYearlyServiceImpl.java
@@ -1,10 +1,29 @@
package com.moral.api.service.impl;
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.moral.api.config.properties.SpecialCitiesProperties;
+import com.moral.api.entity.CityAqi;
+import com.moral.api.entity.CityAqiDaily;
import com.moral.api.entity.CityAqiYearly;
+import com.moral.api.entity.SysArea;
import com.moral.api.mapper.CityAqiYearlyMapper;
+import com.moral.api.pojo.dto.cityAQI.CityPollutionLevel;
+import com.moral.api.pojo.dto.cityAQI.DataPercentRange;
+import com.moral.api.service.CityAqiDailyService;
import com.moral.api.service.CityAqiYearlyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.moral.api.service.SysAreaService;
+import com.moral.constant.Constants;
+import com.moral.util.AmendUtils;
+import com.moral.util.DateUtils;
+import com.moral.util.MathUtils;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
+import org.springframework.util.ObjectUtils;
+
+import java.text.DateFormat;
+import java.util.*;
/**
* <p>
@@ -17,4 +36,418 @@
@Service
public class CityAqiYearlyServiceImpl extends ServiceImpl<CityAqiYearlyMapper, CityAqiYearly> implements CityAqiYearlyService {
+ @Autowired
+ CityAqiYearlyMapper cityAqiYearlyMapper;
+ @Autowired
+ SpecialCitiesProperties specialCitiesProperties;
+ @Autowired
+ SysAreaService sysAreaService;
+ @Autowired
+ CityAqiDailyService cityAqiDailyService;
+
+ @Override
+ public List<CityAqiYearly> getCityAqiYearlyByRegionCodeAndTime(Integer regionCode, Date startDate, Date endDate) {
+ QueryWrapper<CityAqiYearly> queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("city_code", regionCode);
+ queryWrapper.between("time", startDate, endDate);
+ return cityAqiYearlyMapper.selectList(queryWrapper);
+ }
+
+ @Override
+ public Map<String, DataPercentRange> analysisPollutionLevel(String year, Integer cityCode) {
+ //���������������������������������������������������������������������������������������������
+ boolean thisYear = isThisYear(year);
+ //������������������������
+ Date yearDate = DateUtils.getDate(year, "yyyy");
+ Date startDate = DateUtils.getFirstDayOfYear(yearDate);
+ Date endDate;
+ if (thisYear)
+ endDate = DateUtils.addDays(new Date(), -1);
+ else
+ endDate = DateUtils.getLastDayOfYear(yearDate);
+ //������������������2+26������
+ List<SysArea> twentyEightCities = null;
+ if (specialCitiesProperties.isTwentyEightCities(cityCode))
+ twentyEightCities = specialCitiesProperties.getTwentyEightCities();
+ //������������������������������������
+ List<SysArea> heBeiEightCities = null;
+ if (specialCitiesProperties.isHeBeiEightCities(cityCode))
+ heBeiEightCities = specialCitiesProperties.getHeBeiEightCities();
+ //���������������������������������
+ //������������������������������������
+ List<SysArea> cities = null;
+ if (!cityCode.toString().substring(2).equals("0000")) {
+ String provinceCode = cityCode.toString().substring(0, 2) + "0000";
+ cities = sysAreaService.getChildren(Integer.parseInt(provinceCode));
+ }
+ //������������
+ SysArea city = sysAreaService.getAreaByCode(cityCode);
+ //������������������
+ DataPercentRange fineDays = calculateFineDays(cities, twentyEightCities, heBeiEightCities, startDate, endDate, city);
+ //������6���������������������������
+ Map<String, DataPercentRange> sixParamMap = calculateSixParam(thisYear, startDate, endDate, city, cities, twentyEightCities, heBeiEightCities);
+ Map<String, DataPercentRange> result = new HashMap<>();
+ if (fineDays != null)
+ result.put("fineDays", fineDays);
+ if (sixParamMap != null)
+ result.putAll(sixParamMap);
+ if (result.size() == 0)
+ return null;
+ return result;
+ }
+
+
+ //������������������������������������������28���������������������������������
+ private DataPercentRange calculateFineDays(List<SysArea> provinceCities,
+ List<SysArea> twentyEightCities,
+ List<SysArea> heBeiEightCities,
+ Date startDate,
+ Date endDate,
+ SysArea city) {
+ DataPercentRange dataPercentRange = new DataPercentRange();
+
+ //���������������������
+ CityPollutionLevel cityPollutionLevel = cityAqiDailyService.calculateDaysByTimeAndSysArea(city, startDate, endDate);
+ if (cityPollutionLevel == null)
+ return null;
+ Integer fineDays = cityPollutionLevel.getExcellentWeatherDays() + cityPollutionLevel.getGoodWeatherDays();
+ //������������������
+ Date compareStartDate = DateUtils.addMonths(startDate, -12);
+ Date compareEndDate = DateUtils.addMonths(endDate, -12);
+ CityPollutionLevel cityPollutionLevelCompare = cityAqiDailyService.calculateDaysByTimeAndSysArea(city, compareStartDate, compareEndDate);
+ String percent = null;
+ if (cityPollutionLevelCompare != null) {
+ Integer compareFineDays = cityPollutionLevelCompare.getExcellentWeatherDays() + cityPollutionLevelCompare.getGoodWeatherDays();
+ Integer percentInt = fineDays - compareFineDays;
+ if (percentInt > 0) {
+ percent = "+" + percentInt + " ���";
+ } else {
+ percent = percentInt + " ���";
+ }
+
+ }
+ //������������������
+ Integer provinceRange = null;
+ if (provinceCities != null)
+ provinceRange = calculateFineDaysRange(provinceCities, city, startDate, endDate);
+ //������2+26������������
+ Integer twentyEightRange = null;
+ if (twentyEightCities != null)
+ twentyEightRange = calculateFineDaysRange(twentyEightCities, city, startDate, endDate);
+ //������������������������������
+ Integer provinceChannelRange = null;
+ if (heBeiEightCities != null)
+ provinceChannelRange = calculateFineDaysRange(heBeiEightCities, city, startDate, endDate);
+ dataPercentRange.setConcentration(fineDays + " ���");
+ dataPercentRange.setProvinceChannelRange(provinceChannelRange);
+ dataPercentRange.setTwentyEightCitiesRange(twentyEightRange);
+ dataPercentRange.setProvinceRange(provinceRange);
+ dataPercentRange.setPercent(percent);
+ return dataPercentRange;
+ }
+
+
+ //���������������������������������������������������������������������
+ private Map<String, DataPercentRange> calculateSixParam(boolean thisYear,
+ Date startDate,
+ Date endDate,
+ SysArea city,
+ List<SysArea> provinceCities,
+ List<SysArea> twentyEightCities,
+ List<SysArea> heBeiEightCities) {
+ Integer cityCode = city.getAreaCode();
+ Map<String, DataPercentRange> result = new HashMap<>();
+ //���������������������������������������������������������������������������������������������������������������������������������
+ Map<String, Double> concentration = getConcentration(thisYear, startDate, endDate, cityCode);
+ if (concentration == null)
+ return null;
+ //������������������
+ Date compareStartDate = DateUtils.addMonths(startDate, -12);
+ Date compareEndDate = DateUtils.addMonths(endDate, -12);
+ Map<String, Double> compareCentration = getConcentration(thisYear, compareStartDate, compareEndDate, cityCode);
+ //������6���������������������������
+ Map<String, String> compareResult = null;
+ if (compareCentration != null)
+ compareResult = calculateSixParamYOY(concentration, compareCentration);
+ //������������������
+ Map<String, Integer> provinceRangeResult = null;
+ if (provinceCities != null)
+ provinceRangeResult = sixParamRange(provinceCities, city, startDate, endDate, thisYear);
+ //������2+26������
+ Map<String, Integer> twentyEightRangeResult = null;
+ if (twentyEightCities != null)
+ twentyEightRangeResult = sixParamRange(twentyEightCities, city, startDate, endDate, thisYear);
+ //������������������������
+ Map<String, Integer> provinceChannelRangeResult = null;
+ if (heBeiEightCities != null)
+ provinceChannelRangeResult = sixParamRange(heBeiEightCities, city, startDate, endDate, thisYear);
+ //������������������
+ DataPercentRange pm2_5 = new DataPercentRange();
+ pm2_5.setConcentration(concentration.get("PM2_5").intValue() + " ��g/m��");
+ DataPercentRange PM2_5 = packageSixParam(concentration, compareResult, provinceRangeResult, twentyEightRangeResult, provinceChannelRangeResult, "PM2_5", 0, "��g/m��");
+ DataPercentRange PM10 = packageSixParam(concentration, compareResult, provinceRangeResult, twentyEightRangeResult, provinceChannelRangeResult, "PM10", 0, "��g/m��");
+ DataPercentRange SO2 = packageSixParam(concentration, compareResult, provinceRangeResult, twentyEightRangeResult, provinceChannelRangeResult, "SO2", 0, "��g/m��");
+ DataPercentRange NO2 = packageSixParam(concentration, compareResult, provinceRangeResult, twentyEightRangeResult, provinceChannelRangeResult, "NO2", 0, "��g/m��");
+ DataPercentRange O3 = packageSixParam(concentration, compareResult, provinceRangeResult, twentyEightRangeResult, provinceChannelRangeResult, "O3", 0, "��g/m��");
+ DataPercentRange CO = packageSixParam(concentration, compareResult, provinceRangeResult, twentyEightRangeResult, provinceChannelRangeResult, "CO", 1, "mg/m��");
+ DataPercentRange compositeIndex = packageSixParam(concentration, compareResult, provinceRangeResult, twentyEightRangeResult, provinceChannelRangeResult, "compositeIndex", 3, "");
+ result.put("PM2_5", PM2_5);
+ result.put("PM10", PM10);
+ result.put("SO2", SO2);
+ result.put("NO2", NO2);
+ result.put("O3", O3);
+ result.put("CO", CO);
+ result.put("compositeIndex", compositeIndex);
+ return result;
+ }
+
+ //������������������������������������������
+ private DataPercentRange packageSixParam(Map<String, Double> concentration,//������������/������
+ Map<String, String> compareResult,//������������
+ Map<String, Integer> provinceRange,//������������
+ Map<String, Integer> twentyEightRange,//2+26������
+ Map<String, Integer> heBeiEightCitiesRange,//������������������
+ String sensor,//������
+ int decimal,//���������������
+ String unit)//������
+ {
+ DataPercentRange data = new DataPercentRange();
+ if (decimal == 0)
+ data.setConcentration(concentration.get(sensor).intValue() + " " + unit);
+ else
+ data.setConcentration(AmendUtils.sciCal(concentration.get(sensor), decimal) + " " + unit);
+ if (compareResult != null)
+ data.setPercent(compareResult.get(sensor));
+ if (provinceRange != null)
+ data.setProvinceRange(provinceRange.get(sensor));
+ if (twentyEightRange != null)
+ data.setTwentyEightCitiesRange(twentyEightRange.get(sensor));
+ if (heBeiEightCitiesRange != null)
+ data.setProvinceChannelRange(heBeiEightCitiesRange.get(sensor));
+ return data;
+ }
+
+ //���������������������������������
+ private Map<String, Integer> sixParamRange(List<SysArea> cities, SysArea posCity, Date startDate, Date endDate, boolean thisYear) {
+ Map<String, Double> pm2_5Map = new HashMap<>();
+ Map<String, Double> pm10Map = new HashMap<>();
+ Map<String, Double> so2Map = new HashMap<>();
+ Map<String, Double> no2Map = new HashMap<>();
+ Map<String, Double> o3Map = new HashMap<>();
+ Map<String, Double> coMap = new HashMap<>();
+ Map<String, Double> compositeIndexMap = new HashMap<>();
+
+ for (SysArea city : cities) {
+ Map<String, Double> concentration = getConcentration(thisYear, startDate, endDate, city.getAreaCode());
+ if (concentration == null)
+ continue;
+ Object pm2_5o = concentration.get("PM2_5");
+ pm2_5Map.put(city.getAreaCode().toString(), Double.valueOf(pm2_5o.toString()));
+
+ Object pm10o = concentration.get("PM10");
+ pm10Map.put(city.getAreaCode().toString(), Double.valueOf(pm10o.toString()));
+
+ Object so2o = concentration.get("SO2");
+ so2Map.put(city.getAreaCode().toString(), Double.valueOf(so2o.toString()));
+
+ Object no2o = concentration.get("NO2");
+ no2Map.put(city.getAreaCode().toString(), Double.valueOf(no2o.toString()));
+
+ Object o3o = concentration.get("O3");
+ o3Map.put(city.getAreaCode().toString(), Double.valueOf(o3o.toString()));
+
+ Object coo = concentration.get("CO");
+ coMap.put(city.getAreaCode().toString(), Double.valueOf(coo.toString()));
+
+ Object concentrationo = concentration.get("compositeIndex");
+ compositeIndexMap.put(city.getAreaCode().toString(), Double.valueOf(concentrationo.toString()));
+ }
+ Map<String, Integer> result = new HashMap<>();
+ result.put("PM2_5", rangeMap(pm2_5Map, posCity.getAreaCode().toString()));
+ result.put("SO2", rangeMap(so2Map, posCity.getAreaCode().toString()));
+ result.put("NO2", rangeMap(no2Map, posCity.getAreaCode().toString()));
+ result.put("CO", rangeMap(coMap, posCity.getAreaCode().toString()));
+ result.put("O3", rangeMap(o3Map, posCity.getAreaCode().toString()));
+ result.put("PM10", rangeMap(pm10Map, posCity.getAreaCode().toString()));
+ result.put("compositeIndex", rangeMap(compositeIndexMap, posCity.getAreaCode().toString()));
+ return result;
+ }
+
+ //������map���value���������������������������������
+ private Integer rangeMap(Map<String, Double> map, String cityCode) {
+ Set<Map.Entry<String, Double>> entries = map.entrySet();
+ List<Map.Entry<String, Double>> list = new ArrayList<>(entries);
+ list.sort(Comparator.comparing(value -> value.getValue()));
+ for (Map.Entry<String, Double> entry : list) {
+ if (cityCode.equals(entry.getKey()))
+ return list.indexOf(entry) + 1;
+ }
+ return null;
+ }
+
+
+ //���������������������������������������������
+ private Map<String, String> calculateSixParamYOY(Map<String, Double> dataMap, Map<String, Double> compareDataMap) {
+ Map<String, String> result = new HashMap<>();
+
+ Double pm2_5 = calculateSensorYOY(dataMap, compareDataMap, "PM2_5");
+ if (pm2_5 != null)
+ result.put("PM2_5", pm2_5.intValue() > 0 ? "+" + pm2_5.intValue() + " ��g/m��" : pm2_5.intValue() + " ��g/m��");
+
+ Double pm10 = calculateSensorYOY(dataMap, compareDataMap, "PM10");
+ if (pm10 != null)
+ result.put("PM10", pm10.intValue() > 0 ? "+" + pm10.intValue() + " ��g/m��" : pm10.intValue() + " ��g/m��");
+
+ Double so2 = calculateSensorYOY(dataMap, compareDataMap, "SO2");
+ if (so2 != null)
+ result.put("SO2", so2.intValue() > 0 ? "+" + so2.intValue() + " ��g/m��" : so2.intValue() + " ��g/m��");
+
+
+ Double no2 = calculateSensorYOY(dataMap, compareDataMap, "NO2");
+ if (no2 != null)
+ result.put("NO2", no2.intValue() > 0 ? "+" + no2.intValue() + " ��g/m��" : no2.intValue() + " ��g/m��");
+
+
+ Double o3 = calculateSensorYOY(dataMap, compareDataMap, "O3");
+ if (o3 != null)
+ result.put("O3", o3.intValue() > 0 ? "+" + o3.intValue() + " ��g/m��" : o3.intValue() + " ��g/m��");
+
+
+ Double co = calculateSensorYOY(dataMap, compareDataMap, "CO");
+ if (co != null) {
+ co = AmendUtils.sciCal(co, 1);
+ result.put("CO", co.intValue() > 0 ? "+" + co.intValue() + " mg/m��" : co.intValue() + " mg/m��");
+ }
+
+ //������������������������������
+ Object compositeIndexO = dataMap.get("compositeIndex");
+ Object compareCompositeIndexO = compareDataMap.get("compositeIndex");
+ Double compositeIndex = Double.valueOf(compositeIndexO.toString());
+ Double compareCompositeIndex = Double.valueOf(compareCompositeIndexO.toString());
+ if (compositeIndex != null && compareCompositeIndex != null) {
+ Double compareResult = MathUtils.division(compositeIndex - compareCompositeIndex, compareCompositeIndex, 3);
+ compareResult = MathUtils.mul(compareResult, 100);
+ result.put("compositeIndex", compareResult > 0 ? "+" + compareResult + " %" : compareResult + " %");
+ }
+ if (result.size() != 7)
+ return null;
+
+ return result;
+ }
+
+ //���������������������������
+ private Double calculateSensorYOY(Map<String, Double> dataMap, Map<String, Double> compareDataMap, String sensor) {
+ Object dataO = dataMap.get(sensor);
+ Double data = Double.valueOf(dataO.toString());
+
+ Object cdataO = compareDataMap.get(sensor);
+ Double compareData = Double.valueOf(cdataO.toString());
+ if (data != null && compareData != null)
+ return data - compareData;
+ return null;
+ }
+
+ //���������������������������6���������������������������
+ private Map<String, Double> getConcentration(boolean thisYear, Date startDate, Date endDate, Integer cityCode) {
+ if (thisYear) {
+ List<CityAqiDaily> cityAqiDailies = cityAqiDailyService.getCityAqiDailyByRegionCodeAndTime(cityCode, startDate, endDate);
+ if (ObjectUtils.isEmpty(cityAqiDailies))
+ return null;
+ return calculate6ParamAvg(cityAqiDailies);
+ } else {
+ List<CityAqiYearly> cityAqiYearlies = getCityAqiYearlyByRegionCodeAndTime(cityCode, startDate, endDate);
+ if (ObjectUtils.isEmpty(cityAqiYearlies))
+ return null;
+ CityAqiYearly cityAqiYearly = cityAqiYearlies.get(0);
+ return JSON.parseObject(cityAqiYearly.getValue(), Map.class);
+ }
+ }
+
+ //������6������������������������������
+ private Map<String, Double> calculate6ParamAvg(List<CityAqiDaily> cityAqiList) {
+ Double co = calculatePercent(cityAqiList, "CO", 95);
+ Double pm2_5 = calculateSensorAvg(cityAqiList, "PM2_5");
+ Double pm10 = calculateSensorAvg(cityAqiList, "PM10");
+ Double so2 = calculateSensorAvg(cityAqiList, "SO2");
+ Double no2 = calculateSensorAvg(cityAqiList, "NO2");
+ Double o3 = calculatePercent(cityAqiList, "O3", 90);
+ Double compositeIndex = calculateSensorAvg(cityAqiList, "compositeIndex");
+ Map<String, Double> result = new HashMap<>();
+ result.put("CO", co);
+ result.put("NO2", no2);
+ result.put("SO2", so2);
+ result.put("O3", o3);
+ result.put("PM2_5", pm2_5);
+ result.put("PM10", pm10);
+ result.put("compositeIndex", compositeIndex);
+ return result;
+ }
+
+ //������������������������
+ private Double calculateSensorAvg(List<CityAqiDaily> cityAqiList, String sensor) {
+ Double sum = 0d;
+ int num = 0;
+ for (CityAqiDaily cityAqi : cityAqiList) {
+ String value = cityAqi.getValue();
+ if (value == null)
+ continue;
+ Map<String, Object> valueMap = JSON.parseObject(value, Map.class);
+ Object sensorValueObject = valueMap.get(sensor);
+ if (sensorValueObject == null)
+ continue;
+ Double sensorValue = Double.valueOf(sensorValueObject.toString());
+ sum = MathUtils.add(sum, sensorValue);
+ num++;
+ }
+ if (num == 0)
+ return null;
+ Double avg = MathUtils.division(sum, num, 2);
+ return avg;
+ }
+
+ //���������������
+ private Double calculatePercent(List<CityAqiDaily> cityAqiList, String sensor, int percent) {
+ List<Double> datas = new ArrayList<>();
+ for (CityAqiDaily cityAqi : cityAqiList) {
+ String value = cityAqi.getValue();
+ if (value == null)
+ continue;
+ Map<String, Object> valueMap = JSON.parseObject(value, Map.class);
+ Object sensorValueObject = valueMap.get(sensor);
+ if (sensorValueObject == null)
+ continue;
+ Double sensorValue = Double.valueOf(sensorValueObject.toString());
+ datas.add(sensorValue);
+ }
+ if (datas.size() == 0)
+ return null;
+ datas.sort(Comparator.comparing(value -> value));
+ Double avg = AmendUtils.percentile(datas, percent);
+ return avg;
+ }
+
+ //������������������������
+ private Integer calculateFineDaysRange(List<SysArea> cities, SysArea posCity, Date startDate, Date endDate) {
+ List<CityPollutionLevel> result = new ArrayList<>();
+ for (SysArea city : cities) {
+ CityPollutionLevel cityPollutionLevel = cityAqiDailyService.calculateDaysByTimeAndSysArea(city, startDate, endDate);
+ result.add(cityPollutionLevel);
+ }
+ //������
+ result.sort(Comparator.comparing(value -> value.getGoodWeatherDays() + value.getExcellentWeatherDays()));
+ //������������
+ Collections.reverse(result);
+ for (CityPollutionLevel value : result) {
+ if (value.getRegionName().equals(posCity.getAreaName()))
+ return result.indexOf(value);
+ }
+ return null;
+ }
+
+ //���������������������
+ private boolean isThisYear(String year) {
+ return DateUtils.dateToDateString(new Date(), "yyyy").equals(year);
+ }
+
+
}
--
Gitblit v1.8.0