From 9abccec290bc1a620a27011ffbaa3713d57e1acc Mon Sep 17 00:00:00 2001
From: kaiyu <404897439@qq.com>
Date: Fri, 11 Feb 2022 14:20:36 +0800
Subject: [PATCH] screen-api            添加优良天气对比分析接口

---
 screen-api/src/main/java/com/moral/api/service/CityAqiYearlyService.java              |   11 +
 screen-api/src/main/java/com/moral/api/service/impl/SysAreaServiceImpl.java           |    7 
 screen-api/src/main/java/com/moral/api/config/properties/SpecialCitiesProperties.java |   20 ++
 screen-api/src/main/java/com/moral/api/service/SysAreaService.java                    |    8 
 screen-api/src/main/java/com/moral/api/controller/AqiController.java                  |   27 ++
 screen-api/src/main/java/com/moral/api/service/impl/CityAqiYearlyServiceImpl.java     |  420 +++++++++++++++++++++++++++++++++++++++++
 screen-api/src/main/java/com/moral/api/service/impl/CityAqiDailyServiceImpl.java      |    2 
 screen-common/src/main/java/com/moral/util/AmendUtils.java                            |   11 
 screen-api/src/main/resources/application-specialCity.yml                             |   17 +
 screen-api/src/main/java/com/moral/api/pojo/dto/cityAQI/DataPercentRange.java         |   39 +++
 10 files changed, 551 insertions(+), 11 deletions(-)

diff --git a/screen-api/src/main/java/com/moral/api/config/properties/SpecialCitiesProperties.java b/screen-api/src/main/java/com/moral/api/config/properties/SpecialCitiesProperties.java
index 76e9c0c..2f2c2b1 100644
--- a/screen-api/src/main/java/com/moral/api/config/properties/SpecialCitiesProperties.java
+++ b/screen-api/src/main/java/com/moral/api/config/properties/SpecialCitiesProperties.java
@@ -19,5 +19,25 @@
 @ConfigurationProperties(prefix = "special-city")
 @Component
 public class SpecialCitiesProperties {
+
     private List<SysArea> twentyEightCities;
+
+    private List<SysArea> heBeiEightCities;
+
+    public boolean isTwentyEightCities(Integer cityCode){
+        for (SysArea city : twentyEightCities) {
+            if(city.getAreaCode().equals(cityCode))
+                return true;
+        }
+        return false;
+    }
+
+    public boolean isHeBeiEightCities(Integer cityCode){
+        for (SysArea city : heBeiEightCities) {
+            if(city.getAreaCode().equals(cityCode))
+                return true;
+        }
+        return false;
+    }
+
 }
diff --git a/screen-api/src/main/java/com/moral/api/controller/AqiController.java b/screen-api/src/main/java/com/moral/api/controller/AqiController.java
index 428474f..f89d725 100644
--- a/screen-api/src/main/java/com/moral/api/controller/AqiController.java
+++ b/screen-api/src/main/java/com/moral/api/controller/AqiController.java
@@ -1,7 +1,10 @@
 package com.moral.api.controller;
 
+import com.moral.api.config.properties.SpecialCitiesProperties;
+import com.moral.api.entity.SysArea;
 import com.moral.api.pojo.dto.cityAQI.CityPollutionLevel;
 import com.moral.api.pojo.dto.cityAQI.ConcentrationAndPercent;
+import com.moral.api.pojo.dto.cityAQI.DataPercentRange;
 import com.moral.api.pojo.dto.cityAQI.MonthlyPollutionLevel;
 import com.moral.api.pojo.form.aqi.*;
 import com.moral.api.pojo.vo.cityAQI.AirQualityComparisonVO;
@@ -10,11 +13,13 @@
 import com.moral.api.pojo.vo.cityAQI.PieChartOfPollutionLevelVO;
 import com.moral.api.service.CityAqiDailyService;
 
+import com.moral.api.service.CityAqiYearlyService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Required;
 import org.springframework.util.ObjectUtils;
 import org.springframework.web.bind.annotation.CrossOrigin;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -24,11 +29,13 @@
 import java.util.*;
 
 import javax.servlet.http.HttpServletRequest;
+import javax.validation.constraints.NotNull;
 
 import com.moral.api.service.CityAqiService;
 import com.moral.constant.ResponseCodeEnum;
 import com.moral.constant.ResultMessage;
 import com.moral.util.WebUtils;
+import sun.security.util.Resources_sv;
 
 @RestController
 @RequestMapping("/aqi")
@@ -275,4 +282,24 @@
         return ResultMessage.ok(datas);
     }
 
+    @Autowired
+    SpecialCitiesProperties specialCitiesProperties;
+    @Autowired
+    CityAqiYearlyService cityAqiYearlyService;
+    /**
+    * @Description: ������������������������
+            * @Param: [year, cityCode]
+            * @return: com.moral.constant.ResultMessage
+            * @Author: ���������
+            * @Date: 2022/2/10
+            */
+    @GetMapping("queryPollutionLevelAnalysis")
+    public ResultMessage queryPollutionLevelAnalysis( String year, Integer cityCode){
+        if(year==null||cityCode==null)
+            return ResultMessage.fail(ResponseCodeEnum.PARAMETERS_IS_MISSING.getCode(),
+                    ResponseCodeEnum.PARAMETERS_IS_MISSING.getMsg());
+        Map<String, DataPercentRange> result = cityAqiYearlyService.analysisPollutionLevel(year, cityCode);
+        return ResultMessage.ok(result);
+    }
+
 }
diff --git a/screen-api/src/main/java/com/moral/api/pojo/dto/cityAQI/DataPercentRange.java b/screen-api/src/main/java/com/moral/api/pojo/dto/cityAQI/DataPercentRange.java
new file mode 100644
index 0000000..56afce9
--- /dev/null
+++ b/screen-api/src/main/java/com/moral/api/pojo/dto/cityAQI/DataPercentRange.java
@@ -0,0 +1,39 @@
+package com.moral.api.pojo.dto.cityAQI;
+
+import lombok.Data;
+
+/**
+ * @ClassName
+ * @Description TODO
+ * @Author ���������
+ * @Date 2022/2/10 13:18
+ * @Version TODO
+ **/
+@Data
+public class DataPercentRange {
+
+    /*
+     * ���������������/������/������
+     * */
+    private String concentration;
+
+    /*
+     * ������
+     * */
+    private String percent;
+
+    /*
+    * ������������
+    * */
+    private Integer provinceRange;
+
+    /*
+    * 2+26������
+    * */
+    private Integer twentyEightCitiesRange;
+
+    /*
+    * ������������������
+    * */
+    private Integer provinceChannelRange;
+}
diff --git a/screen-api/src/main/java/com/moral/api/service/CityAqiYearlyService.java b/screen-api/src/main/java/com/moral/api/service/CityAqiYearlyService.java
index bcd1cba..6475990 100644
--- a/screen-api/src/main/java/com/moral/api/service/CityAqiYearlyService.java
+++ b/screen-api/src/main/java/com/moral/api/service/CityAqiYearlyService.java
@@ -2,9 +2,11 @@
 
 import com.moral.api.entity.CityAqiYearly;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.moral.api.pojo.dto.cityAQI.DataPercentRange;
 
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 
 /**
  * <p>
@@ -23,4 +25,13 @@
             * @Date: 2022/1/17
             */
     List<CityAqiYearly> getCityAqiYearlyByRegionCodeAndTime(Integer regionCode, Date startDate, Date endDate);
+
+    /** 
+    * @Description: ������������������������
+            * @Param: [year, cityCode]
+            * @return: java.util.Map<java.lang.String,com.moral.api.pojo.dto.cityAQI.DataPercentRange>
+            * @Author: ���������
+            * @Date: 2022/2/11
+            */ 
+    Map<String, DataPercentRange> analysisPollutionLevel(String year, Integer cityCode);
 }
diff --git a/screen-api/src/main/java/com/moral/api/service/SysAreaService.java b/screen-api/src/main/java/com/moral/api/service/SysAreaService.java
index 500486a..847d46a 100644
--- a/screen-api/src/main/java/com/moral/api/service/SysAreaService.java
+++ b/screen-api/src/main/java/com/moral/api/service/SysAreaService.java
@@ -28,4 +28,12 @@
             */
     List<SysArea> getChildren(Integer regionCode);
 
+    /**
+    * @Description: ���������������������������
+            * @Param: [regionCode]
+            * @return: com.moral.api.entity.SysArea
+            * @Author: ���������
+            * @Date: 2022/2/10
+            */
+    SysArea getAreaByCode(Integer regionCode);
 }
diff --git a/screen-api/src/main/java/com/moral/api/service/impl/CityAqiDailyServiceImpl.java b/screen-api/src/main/java/com/moral/api/service/impl/CityAqiDailyServiceImpl.java
index b5b1328..2ef07d2 100644
--- a/screen-api/src/main/java/com/moral/api/service/impl/CityAqiDailyServiceImpl.java
+++ b/screen-api/src/main/java/com/moral/api/service/impl/CityAqiDailyServiceImpl.java
@@ -365,6 +365,8 @@
         wrapper.between("time", startDate, endDate);
         wrapper.orderByAsc("time");
         List<CityAqiDaily> cityAqiDailies = cityAqiDailyMapper.selectList(wrapper);
+        if(ObjectUtils.isEmpty(cityAqiDailies))
+            return null;
         //���������������������������������������
         Map<String, CityAqiDaily> tmpMap = new LinkedHashMap<>();
         for (CityAqiDaily cityAqiDaily : cityAqiDailies) {
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 10b54c3..3917c5d 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,15 +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.util.Date;
-import java.util.List;
+import java.text.DateFormat;
+import java.util.*;
 
 /**
  * <p>
@@ -24,12 +38,410 @@
 
     @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);
+        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();
+            percent = (fineDays - compareFineDays) + " ���";
+        }
+        //������������������
+        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() + " ��g/m��");
+
+        Double pm10 = calculateSensorYOY(dataMap, compareDataMap, "PM10");
+        if (pm10 != null)
+            result.put("PM10", pm10.intValue() + " ��g/m��");
+
+        Double so2 = calculateSensorYOY(dataMap, compareDataMap, "SO2");
+        if (so2 != null)
+            result.put("SO2", so2.intValue() + " ��g/m��");
+
+
+        Double no2 = calculateSensorYOY(dataMap, compareDataMap, "NO2");
+        if (no2 != null)
+            result.put("NO2", no2.intValue() + " ��g/m��");
+
+
+        Double o3 = calculateSensorYOY(dataMap, compareDataMap, "O3");
+        if (o3 != null)
+            result.put("O3", o3.intValue() + " ��g/m��");
+
+
+        Double co = calculateSensorYOY(dataMap, compareDataMap, "CO");
+        if (co != null) {
+            co = AmendUtils.sciCal(co, 1);
+            result.put("CO", co + " 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 + "%");
+        }
+        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);
+    }
+
+
 }
diff --git a/screen-api/src/main/java/com/moral/api/service/impl/SysAreaServiceImpl.java b/screen-api/src/main/java/com/moral/api/service/impl/SysAreaServiceImpl.java
index a86c8f6..d5b32bc 100644
--- a/screen-api/src/main/java/com/moral/api/service/impl/SysAreaServiceImpl.java
+++ b/screen-api/src/main/java/com/moral/api/service/impl/SysAreaServiceImpl.java
@@ -103,6 +103,13 @@
         return sysAreaMapper.selectList(wrapper);
     }
 
+    @Override
+    public SysArea getAreaByCode(Integer regionCode) {
+        QueryWrapper<SysArea> wrapper = new QueryWrapper<>();
+        wrapper.eq("area_code",regionCode);
+        return sysAreaMapper.selectOne(wrapper);
+    }
+
     //������������������������
     private List<Map<String, Object>> getAreasByRecursion(SysArea sysArea, List<SysArea> sysAreas) {
         SysArea newSysArea = new SysArea();
diff --git a/screen-api/src/main/resources/application-specialCity.yml b/screen-api/src/main/resources/application-specialCity.yml
index fed579a..ac19837 100644
--- a/screen-api/src/main/resources/application-specialCity.yml
+++ b/screen-api/src/main/resources/application-specialCity.yml
@@ -56,6 +56,23 @@
       areaName: ���������
     - areaCode: 410500
       areaName: ���������
+  heBeiEightCities:
+    - areaCode: 130600
+      areaName: ���������
+    - areaCode: 130500
+      areaName: ���������
+    - areaCode: 131000
+      areaName: ���������
+    - areaCode: 130100
+      areaName: ������������
+    - areaCode: 130400
+      areaName: ���������
+    - areaCode: 131100
+      areaName: ���������
+    - areaCode: 130900
+      areaName: ���������
+    - areaCode: 130200
+      areaName: ���������
 
 
 
diff --git a/screen-common/src/main/java/com/moral/util/AmendUtils.java b/screen-common/src/main/java/com/moral/util/AmendUtils.java
index 33c985a..3c726b1 100644
--- a/screen-common/src/main/java/com/moral/util/AmendUtils.java
+++ b/screen-common/src/main/java/com/moral/util/AmendUtils.java
@@ -249,16 +249,13 @@
     public static double percentile(List<Double> data, int p) {
         int n = data.size();
         Collections.sort(data);
-        double v = n / (100 / p);
-        if (n % (100 / p) == 0) {
-            if (v == n) {
-                return data.get(n - 1);
-            }
-            return (data.get((int) v - 1) + data.get((int) v)) / 2;
-        }
+        double v = MathUtils.division(MathUtils.mul(n, p),100d,1);
+        v = Math.ceil(v)-1;
         return sciCal(data.get((int) v), 4);
     }
 
+
+
     //������������������������������
     public static Map<String, Object> getCOAvgOfWeekOrMonth(Map<String, Object> params) {
         Map<String, Object> result = new HashMap<>();

--
Gitblit v1.8.0