|  |  | 
 |  |  | package com.moral.api.service.impl; | 
 |  |  |  | 
 |  |  | import com.alibaba.fastjson.JSONObject; | 
 |  |  | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | 
 |  |  | import com.moral.api.config.properties.AnnouncementProperties; | 
 |  |  | import com.moral.api.config.properties.SpecialCitiesProperties; | 
 |  |  | import com.moral.api.entity.CityAqiDaily; | 
 |  |  | import com.moral.api.entity.CityAqiMonthly; | 
 |  |  | import com.moral.api.entity.SysArea; | 
 |  |  | import com.moral.api.mapper.CityAqiMonthlyMapper; | 
 |  |  | import com.moral.api.service.CityAqiDailyService; | 
 |  |  | import com.moral.api.service.CityAqiMonthlyService; | 
 |  |  | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | 
 |  |  | import org.springframework.beans.factory.annotation.Autowired; | 
 |  |  | import org.springframework.stereotype.Service; | 
 |  |  | import com.moral.api.service.SysAreaService; | 
 |  |  | import com.moral.constant.Constants; | 
 |  |  | import com.moral.constant.RedisConstants; | 
 |  |  | import com.moral.util.AmendUtils; | 
 |  |  | import com.moral.util.ComprehensiveIndexUtils; | 
 |  |  | import com.moral.util.DateUtils; | 
 |  |  |  | 
 |  |  | import org.springframework.beans.factory.annotation.Autowired; | 
 |  |  | import org.springframework.data.redis.core.RedisTemplate; | 
 |  |  | import org.springframework.stereotype.Service; | 
 |  |  | import org.springframework.util.ObjectUtils; | 
 |  |  |  | 
 |  |  | import java.text.DecimalFormat; | 
 |  |  | import java.time.Duration; | 
 |  |  | import java.util.ArrayList; | 
 |  |  | import java.util.Arrays; | 
 |  |  | import java.util.Date; | 
 |  |  | import java.util.HashMap; | 
 |  |  | import java.util.LinkedHashMap; | 
 |  |  | import java.util.List; | 
 |  |  | import java.util.Map; | 
 |  |  | import java.util.OptionalDouble; | 
 |  |  | import java.util.stream.Collectors; | 
 |  |  | import java.util.stream.DoubleStream; | 
 |  |  |  | 
 |  |  | /** | 
 |  |  |  * <p> | 
 |  |  | 
 |  |  | public class CityAqiMonthlyServiceImpl extends ServiceImpl<CityAqiMonthlyMapper, CityAqiMonthly> implements CityAqiMonthlyService { | 
 |  |  |  | 
 |  |  |     @Autowired | 
 |  |  |     CityAqiMonthlyMapper cityAqiMonthlyMapper; | 
 |  |  |     private CityAqiMonthlyMapper cityAqiMonthlyMapper; | 
 |  |  |  | 
 |  |  |     @Autowired | 
 |  |  |     private SpecialCitiesProperties specialCitiesProperties; | 
 |  |  |  | 
 |  |  |     @Autowired | 
 |  |  |     private SysAreaService sysAreaService; | 
 |  |  |  | 
 |  |  |     @Autowired | 
 |  |  |     private CityAqiDailyService cityAqiDailyService; | 
 |  |  |  | 
 |  |  |     @Autowired | 
 |  |  |     private RedisTemplate redisTemplate; | 
 |  |  |  | 
 |  |  |     @Autowired | 
 |  |  |     private AnnouncementProperties announcementProperties; | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public List<CityAqiMonthly> getCityAqiMonthByRegionCodeAndTime(Integer regionCode, Date startDate, Date endDate) { | 
 |  |  |         QueryWrapper<CityAqiMonthly> queryWrapper = new QueryWrapper<>(); | 
 |  |  |         queryWrapper.eq("city_code",regionCode); | 
 |  |  |         queryWrapper.between("time",startDate,endDate); | 
 |  |  |         queryWrapper.eq("city_code", regionCode); | 
 |  |  |         queryWrapper.between("time", startDate, endDate); | 
 |  |  |         return cityAqiMonthlyMapper.selectList(queryWrapper); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public CityAqiMonthly getCityAqiMonthByRegionCodeAndTime(Integer regionCode, Date time) { | 
 |  |  |         time = DateUtils.getFirstDayOfMonth(time); | 
 |  |  |         QueryWrapper<CityAqiMonthly> queryWrapper = new QueryWrapper<>(); | 
 |  |  |         queryWrapper.eq("city_code", regionCode); | 
 |  |  |         queryWrapper.eq("time", time); | 
 |  |  |         return cityAqiMonthlyMapper.selectOne(queryWrapper); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public Map<String, Object> airQualityRankingAnnouncement(Integer regionCode, Date time) { | 
 |  |  |         Map<String, Object> result = new LinkedHashMap<>(); | 
 |  |  |         String month = DateUtils.getMonth(time) + ""; | 
 |  |  |         int yearMonthOfSelect = Integer.parseInt(DateUtils.dateToDateString(time, DateUtils.yyyyMM_EN)); | 
 |  |  |         int nowYearMonthOfSelect = Integer.parseInt(DateUtils.getCurDate(DateUtils.yyyyMM_EN)); | 
 |  |  |  | 
 |  |  |         if (yearMonthOfSelect > nowYearMonthOfSelect) { | 
 |  |  |             return result; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         //先根据时间和地区code从redis中获取,没有再计算后存入redis | 
 |  |  |         result = (Map<String, Object>) redisTemplate.opsForValue().get(RedisConstants.AQI_ANNOUNCEMENT + "_" + regionCode + "_" + DateUtils.dateToDateString(time, DateUtils.yyyyMM_EN)); | 
 |  |  |         if (result != null) { | 
 |  |  |             return result; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         result = new LinkedHashMap<>(); | 
 |  |  |         //获取xx市和所有县市区名字信息 | 
 |  |  |         QueryWrapper<SysArea> sysAreaQueryWrapper = new QueryWrapper<>(); | 
 |  |  |         sysAreaQueryWrapper.select("area_code", "area_name") | 
 |  |  |                 .eq("parent_code", regionCode).or() | 
 |  |  |                 .eq("area_code", regionCode); | 
 |  |  |         List<SysArea> sysAreas = sysAreaService.list(sysAreaQueryWrapper); | 
 |  |  |         Map<Integer, String> areasMap = new HashMap<>(); | 
 |  |  |         for (SysArea sysArea : sysAreas) { | 
 |  |  |             areasMap.put(sysArea.getAreaCode(), sysArea.getAreaName()); | 
 |  |  |         } | 
 |  |  |         String cityName = areasMap.remove(regionCode); | 
 |  |  |         result.put("cityName", cityName); | 
 |  |  |         result.put("areaSize", areasMap.size()); | 
 |  |  |  | 
 |  |  |         //一、空气质量排名 | 
 |  |  |         //1.本月xx市空气质量排名 | 
 |  |  |         Map<String, Object> currentRankingResult = new HashMap<>(); | 
 |  |  |  | 
 |  |  |         //获取本月xx市空气质量数据 | 
 |  |  |         QueryWrapper<CityAqiMonthly> cityAqiMonthlyQueryWrapper = new QueryWrapper<>(); | 
 |  |  |         cityAqiMonthlyQueryWrapper.select("value") | 
 |  |  |                 .eq("city_code", regionCode) | 
 |  |  |                 .eq("time", time); | 
 |  |  |         CityAqiMonthly cityAqiMonthly = cityAqiMonthlyMapper.selectOne(cityAqiMonthlyQueryWrapper); | 
 |  |  |         Double compositeIndex = null; | 
 |  |  |         String compositeIndexYearOnYear = null; | 
 |  |  |         Integer pm25 = null; | 
 |  |  |         String pm25YearOnYear = null; | 
 |  |  |         if (cityAqiMonthly != null) { | 
 |  |  |             Map<String, Object> aqiMap = JSONObject.parseObject(cityAqiMonthly.getValue(), Map.class); | 
 |  |  |  | 
 |  |  |             //1.综指 | 
 |  |  |             if (aqiMap.get("compositeIndex") != null) { | 
 |  |  |                 compositeIndex = Double.parseDouble(aqiMap.get("compositeIndex").toString()); | 
 |  |  |             } | 
 |  |  |             currentRankingResult.put("compositeIndex", compositeIndex); | 
 |  |  |  | 
 |  |  |             //2.综指同比 | 
 |  |  |             if (aqiMap.get("compositeIndex_yearOnYear") != null) { | 
 |  |  |                 compositeIndexYearOnYear = aqiMap.get("compositeIndex_yearOnYear").toString(); | 
 |  |  |             } | 
 |  |  |             currentRankingResult.put("compositeIndex_yearOnYear", compositeIndexYearOnYear); | 
 |  |  |  | 
 |  |  |             //3.PM2.5浓度 | 
 |  |  |             if (aqiMap.get("PM2_5") != null) { | 
 |  |  |                 pm25 = Integer.parseInt(aqiMap.get("PM2_5").toString()); | 
 |  |  |             } | 
 |  |  |             currentRankingResult.put("PM2_5", pm25 + "ug/m³"); | 
 |  |  |  | 
 |  |  |             //4.PM.5浓度同比 | 
 |  |  |             if (aqiMap.get("PM2_5_yearOnYear") != null) { | 
 |  |  |                 pm25YearOnYear = aqiMap.get("PM2_5_yearOnYear").toString(); | 
 |  |  |             } | 
 |  |  |             currentRankingResult.put("PM2_5_yearOnYear", pm25YearOnYear); | 
 |  |  |  | 
 |  |  |             //5.168城市排名,包括综指,综指同比,pm2.5,pm2.5同比 | 
 |  |  |             Map<String, Object> ranking168 = getOneSixEightCitiesRanking(regionCode, time); | 
 |  |  |             currentRankingResult.putAll(ranking168); | 
 |  |  |  | 
 |  |  |             //6.2+26城市排名,包括综指,综指同比,pm2.5,pm2.5同比 | 
 |  |  |             Map<String, Object> ranking28 = getTwentyEightCitiesRanking(regionCode, time); | 
 |  |  |             currentRankingResult.putAll(ranking28); | 
 |  |  |  | 
 |  |  |             //7.河北八通道城市排名,包括综指,综指同比,pm2.5,pm2.5同比 | 
 |  |  |             Map<String, Object> ranking8Channels = getHeBeiEightCitiesRanking(regionCode, time); | 
 |  |  |             currentRankingResult.putAll(ranking8Channels); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         String start = DateUtils.dateToDateString(time, DateUtils.yyyy_MM_dd_CN); | 
 |  |  |         //本月最后一日 | 
 |  |  |         String end = DateUtils.dateToDateString(DateUtils.getLastDayOfMonth(time), DateUtils.yyyy_MM_dd_CN); | 
 |  |  |         result.put("currentRanking", aqiQualityRankingResponse(start + "-" + end, cityName, currentRankingResult)); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         //2.1-x月xx市空气质量排名 | 
 |  |  |         //所有县市区codes | 
 |  |  |         List<Integer> areaCodes = new ArrayList<>(areasMap.keySet()); | 
 |  |  |         //地级市code | 
 |  |  |         areaCodes.add(regionCode); | 
 |  |  |         Map<Integer, Map<String, Object>> monthlyCumulativeResult = null; | 
 |  |  |         Double cityCompositeIndex = null; | 
 |  |  |         String cityCompositeIndexYearOnYear = null; | 
 |  |  |         Integer cityPM25 = null; | 
 |  |  |         String cityPM25YearOnYear = null; | 
 |  |  |         if (!"1".equals(month)) { | 
 |  |  |             Map<String, Object> cumulativeRankingResult = new HashMap<>(); | 
 |  |  |  | 
 |  |  |             //获取xx市和下属所有县市区1-xx月数据 | 
 |  |  |             monthlyCumulativeResult = getMonthlyCumulativeResult(time, areaCodes); | 
 |  |  |             //xx市数据 | 
 |  |  |  | 
 |  |  |             if (monthlyCumulativeResult != null) { | 
 |  |  |                 Map<String, Object> cityMap = monthlyCumulativeResult.remove(regionCode); | 
 |  |  |                 if (cityMap != null) { | 
 |  |  |                     //地级市综指 | 
 |  |  |                     cityCompositeIndex = Double.parseDouble(cityMap.get("compositeIndex").toString()); | 
 |  |  |                     if (cityMap.get("compositeIndex_yearOnYear") != null) { | 
 |  |  |                         cityCompositeIndexYearOnYear = cityMap.get("compositeIndex_yearOnYear").toString(); | 
 |  |  |                     } | 
 |  |  |                     //地级市PM2.5 | 
 |  |  |                     cityPM25 = (int) Double.parseDouble(cityMap.get("PM2_5").toString()); | 
 |  |  |                     if (cityMap.get("PM2_5_yearOnYear") != null) { | 
 |  |  |                         cityPM25YearOnYear = cityMap.get("PM2_5_yearOnYear").toString(); | 
 |  |  |                     } | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             cumulativeRankingResult.put("compositeIndex", cityCompositeIndex); | 
 |  |  |             cumulativeRankingResult.put("compositeIndex_yearOnYear", cityCompositeIndexYearOnYear); | 
 |  |  |             cumulativeRankingResult.put("PM2_5", cityPM25); | 
 |  |  |             if (cityPM25 != null) { | 
 |  |  |                 cumulativeRankingResult.put("PM2_5", cityPM25 + "ug/m³"); | 
 |  |  |             } | 
 |  |  |             cumulativeRankingResult.put("PM2_5_yearOnYear", cityPM25YearOnYear); | 
 |  |  |  | 
 |  |  |             //5.168城市排名,包括综指,综指同比,pm2.5,pm2.5同比 | 
 |  |  |             Map<String, Object> ranking168 = getOneSixEightCitiesRankingOfCumulative(regionCode, time); | 
 |  |  |             cumulativeRankingResult.putAll(ranking168); | 
 |  |  |  | 
 |  |  |             //6.2+26城市排名,包括综指,综指同比,pm2.5,pm2.5同比 | 
 |  |  |             Map<String, Object> ranking28 = getTwentyEightCitiesRankingOfCumulative(regionCode, time); | 
 |  |  |             cumulativeRankingResult.putAll(ranking28); | 
 |  |  |  | 
 |  |  |             //7.河北八通道城市排名,包括综指,综指同比,pm2.5,pm2.5同比 | 
 |  |  |             Map<String, Object> ranking8Channels = getHeBeiEightCitiesRankingOfCumulative(regionCode, time); | 
 |  |  |             cumulativeRankingResult.putAll(ranking8Channels); | 
 |  |  |             //开始时间,当年1月1日 | 
 |  |  |             start = DateUtils.dateToDateString(DateUtils.getFirstDayOfYear(time), DateUtils.yyyy_MM_dd_CN); | 
 |  |  |             //结束时间,当月最后一天 | 
 |  |  |             end = DateUtils.dateToDateString(DateUtils.getLastDayOfMonth(time), DateUtils.yyyy_MM_dd_CN); | 
 |  |  |             result.put("cumulativeRanking", aqiQualityRankingResponse(start + "-" + end, cityName, cumulativeRankingResult)); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         //二、各县市区空气质量情况结果集 | 
 |  |  |         //获取本期xx市下所有县市区数据 | 
 |  |  |         cityAqiMonthlyQueryWrapper.clear(); | 
 |  |  |         areaCodes.remove(regionCode); | 
 |  |  |         cityAqiMonthlyQueryWrapper.select("city_code", "value") | 
 |  |  |                 .eq("time", time) | 
 |  |  |                 .in("city_code", areaCodes); | 
 |  |  |         List<CityAqiMonthly> areaData = cityAqiMonthlyMapper.selectList(cityAqiMonthlyQueryWrapper); | 
 |  |  |  | 
 |  |  |         //获取本期所有县市区与中心城区(地级市)因子对比情况 | 
 |  |  |         Map<String, Object> areaCurrentMonthResult = getAreaCurrentMonthResult(areasMap, areaData, compositeIndex, compositeIndexYearOnYear, pm25, pm25YearOnYear); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         //本月县市区综指与中心城区对比 | 
 |  |  |         result.put("currentCompositeIndexContrast", compositeIndexContrastResponse(month, cityName, areaCodes.size(), areaCurrentMonthResult)); | 
 |  |  |         //本月县市区综指同比与中心城区对比 | 
 |  |  |         result.put("currentCompositeIndexYearOnYearContrast", compositeIndexYearOnYearContrastResponse(month, cityName, areaCodes.size(), areaCurrentMonthResult)); | 
 |  |  |         //本月县市区PM2.5与中心城区对比 | 
 |  |  |         result.put("currentPM25Contrast", pm25tContrastResponse(month, cityName, areaCodes.size(), areaCurrentMonthResult)); | 
 |  |  |         //本月县市区Pm2.5同比与中心城区对比 | 
 |  |  |         result.put("currentPM25YearOnYearContrast", pm25YearOnYearContrastResponse(month, cityName, areaCodes.size(), areaCurrentMonthResult)); | 
 |  |  |  | 
 |  |  |         //三、1-x月累计结果 | 
 |  |  |         List<CityAqiMonthly> cumulativeList = null; | 
 |  |  |         if (!"1".equals(month)) { | 
 |  |  |             cumulativeList = new ArrayList<>(); | 
 |  |  |             if (monthlyCumulativeResult != null) { | 
 |  |  |                 for (Map.Entry<Integer, Map<String, Object>> entry : monthlyCumulativeResult.entrySet()) { | 
 |  |  |                     CityAqiMonthly cityAqiMonthly1 = new CityAqiMonthly(); | 
 |  |  |                     cityAqiMonthly1.setCityCode(entry.getKey()); | 
 |  |  |                     cityAqiMonthly1.setValue(JSONObject.toJSONString(entry.getValue())); | 
 |  |  |                     cumulativeList.add(cityAqiMonthly1); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             month = "1-" + DateUtils.getMonth(time); | 
 |  |  |             //获取1-x月所有县市区与地级市数据对比情况 | 
 |  |  |             Map<String, Object> monthlyCumulativeListResultMap = getAreaCurrentMonthResult(areasMap, cumulativeList, cityCompositeIndex, cityCompositeIndexYearOnYear, cityPM25, cityPM25YearOnYear); | 
 |  |  |             //1-xx月份县市区综指与中心城区对比 | 
 |  |  |             result.put("cumulativeCompositeIndexContrast", compositeIndexContrastResponse(month, cityName, areaCodes.size(), monthlyCumulativeListResultMap)); | 
 |  |  |             //1-xx月份县市区综指同比与中心城区对比 | 
 |  |  |             result.put("cumulativeCompositeIndexYearOnYearContrast", compositeIndexYearOnYearContrastResponse(month, cityName, areaCodes.size(), monthlyCumulativeListResultMap)); | 
 |  |  |             //1-xx月份县市区PM2.5与中心城区对比 | 
 |  |  |             result.put("cumulativePM25Contrast", pm25tContrastResponse(month, cityName, areaCodes.size(), monthlyCumulativeListResultMap)); | 
 |  |  |             //1-xx月份县市区Pm2.5同比与中心城区对比 | 
 |  |  |             result.put("cumulativePM25YearOnYearContrast", pm25YearOnYearContrastResponse(month, cityName, areaCodes.size(), monthlyCumulativeListResultMap)); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         //四、附件 | 
 |  |  |         //1.本期综指和pm2.5考核排名报表 | 
 |  |  |         List<Map<String, Object>> airQualityRankingOfCurrentReport = airQualityRankingOfCurrentReport(areaData, areasMap); | 
 |  |  |         result.put("currentAirQualityRankingReport", airQualityRankingOfCurrentReport); | 
 |  |  |  | 
 |  |  |         //2.1-x月份累计空气质量综指和pm2.5排名报表 | 
 |  |  |         if (!"1".equals(month)) { | 
 |  |  |             List<Map<String, Object>> cumulativeAirQualityRankingReport = cumulativeAirQualityRankingReport(cumulativeList, areasMap); | 
 |  |  |             result.put("cumulativeAirQualityRankingReport", cumulativeAirQualityRankingReport); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         //3.本期五因子(PM10,SO2,NO2,CO,O3)对比报表 | 
 |  |  |         List<Map<String, Object>> currentFiveSensorsContrastReport = currentFiveSensorsContrastReport(time, areaCodes, areaData, areasMap); | 
 |  |  |         result.put("currentFiveSensorsContrastReport", currentFiveSensorsContrastReport); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         //4.1-x月份五因子(PM10,SO2,NO2,CO,O3)对比报表 | 
 |  |  |         if (!"1".equals(month)) { | 
 |  |  |             List<Map<String, Object>> cumulativeFiveSensorsContrastReport = cumulativeFiveSensorsContrastReport(cumulativeList, areasMap); | 
 |  |  |             result.put("cumulativeFiveSensorsContrastReport", cumulativeFiveSensorsContrastReport); | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         //存入redis | 
 |  |  |         redisTemplate.opsForValue().set(RedisConstants.AQI_ANNOUNCEMENT + "_" + regionCode + "_" + DateUtils.dateToDateString(time, DateUtils.yyyyMM_EN), result, Duration.ofDays(30)); | 
 |  |  |         return result; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * @param startEnd 时间 | 
 |  |  |      * @param cityName 地级市名字 | 
 |  |  |      * @param result   当月数据map | 
 |  |  |      * @description 当月排名文字拼接 | 
 |  |  |      */ | 
 |  |  |     private String aqiQualityRankingResponse(String startEnd, String cityName, Map<String, Object> result) { | 
 |  |  |         Object compositeIndex = result.get("compositeIndex"); | 
 |  |  |         Object compositeIndex_rank_168 = result.get("compositeIndex_rank_168"); | 
 |  |  |         Object compositeIndex_rank_28 = result.get("compositeIndex_rank_28"); | 
 |  |  |         Object compositeIndex_rank_8Channels = result.get("compositeIndex_rank_8Channels"); | 
 |  |  |  | 
 |  |  |         Object compositeIndexYearOnYear = result.get("compositeIndex_yearOnYear"); | 
 |  |  |         Object compositeIndexYearOnYear_rank_168 = result.get("compositeIndex_yearOnYear_rank_168"); | 
 |  |  |         Object compositeIndexYearOnYear_rank_28 = result.get("compositeIndex_yearOnYear_rank_28"); | 
 |  |  |         Object compositeIndexYearOnYear_rank_8Channels = result.get("compositeIndex_yearOnYear_rank_8Channels"); | 
 |  |  |  | 
 |  |  |         //综指排名 | 
 |  |  |         StringBuilder compositeIndexBuilder = new StringBuilder(); | 
 |  |  |         if (compositeIndex_rank_168 != null) { | 
 |  |  |             compositeIndexBuilder.append("在168城市正排第" + compositeIndex_rank_168 + "名"); | 
 |  |  |         } | 
 |  |  |         if (compositeIndex_rank_28 != null) { | 
 |  |  |             compositeIndexBuilder.append("在'2+26'城市正排第" + compositeIndex_rank_28 + "名"); | 
 |  |  |         } | 
 |  |  |         if (compositeIndex_rank_8Channels != null) { | 
 |  |  |             compositeIndexBuilder.append("在河北八通道城市正排第" + compositeIndex_rank_8Channels + "名"); | 
 |  |  |         } | 
 |  |  |         //综指同比排名 | 
 |  |  |         StringBuilder compositeIndexYearOnYearBuilder = new StringBuilder(); | 
 |  |  |         if (compositeIndexYearOnYear_rank_168 != null) { | 
 |  |  |             compositeIndexYearOnYearBuilder.append("在168城市正排第" + compositeIndexYearOnYear_rank_168 + "名"); | 
 |  |  |         } | 
 |  |  |         if (compositeIndexYearOnYear_rank_28 != null) { | 
 |  |  |             compositeIndexYearOnYearBuilder.append("在'2+26'城市正排第" + compositeIndexYearOnYear_rank_28 + "名"); | 
 |  |  |         } | 
 |  |  |         if (compositeIndexYearOnYear_rank_8Channels != null) { | 
 |  |  |             compositeIndexYearOnYearBuilder.append("在河北八通道城市正排第" + compositeIndexYearOnYear_rank_8Channels + "名"); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         Object pm2_5 = result.get("PM2_5"); | 
 |  |  |         Object pm2_5_rank_168 = result.get("PM2_5_rank_168"); | 
 |  |  |         Object pm2_5_rank_28 = result.get("PM2_5_rank_28"); | 
 |  |  |         Object pm2_5_rank_8Channels = result.get("PM2_5_rank_8Channels"); | 
 |  |  |  | 
 |  |  |         Object pm2_5YearOnYear = result.get("PM2_5_yearOnYear"); | 
 |  |  |         Object pm2_5YearOnYear_rank_168 = result.get("PM2_5_yearOnYear_rank_168"); | 
 |  |  |         Object pm2_5YearOnYear_rank_28 = result.get("PM2_5_yearOnYear_rank_28"); | 
 |  |  |         Object pm2_5YearOnYear_rank_8Channels = result.get("PM2_5_yearOnYear_rank_8Channels"); | 
 |  |  |  | 
 |  |  |         //PM2.5排名 | 
 |  |  |         StringBuilder pm25Builder = new StringBuilder(); | 
 |  |  |         if (pm2_5_rank_168 != null) { | 
 |  |  |             pm25Builder.append("在168城市正排第" + pm2_5_rank_168 + "名"); | 
 |  |  |         } | 
 |  |  |         if (pm2_5_rank_28 != null) { | 
 |  |  |             pm25Builder.append("在'2+26'城市正排第" + pm2_5_rank_28 + "名"); | 
 |  |  |         } | 
 |  |  |         if (pm2_5_rank_8Channels != null) { | 
 |  |  |             pm25Builder.append("在河北八通道城市正排第" + pm2_5_rank_8Channels + "名"); | 
 |  |  |         } | 
 |  |  |         //PM2.5同比排名 | 
 |  |  |         StringBuilder pm25YearOnYearBuilder = new StringBuilder(); | 
 |  |  |         if (pm2_5YearOnYear_rank_168 != null) { | 
 |  |  |             pm25YearOnYearBuilder.append("在168城市正排第" + pm2_5YearOnYear_rank_168 + "名"); | 
 |  |  |         } | 
 |  |  |         if (pm2_5YearOnYear_rank_28 != null) { | 
 |  |  |             pm25YearOnYearBuilder.append("在'2+26'城市正排第" + pm2_5YearOnYear_rank_28 + "名"); | 
 |  |  |         } | 
 |  |  |         if (pm2_5YearOnYear_rank_8Channels != null) { | 
 |  |  |             pm25YearOnYearBuilder.append("在河北八通道城市正排第" + pm2_5YearOnYear_rank_8Channels + "名"); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         String currentRanking = announcementProperties.getCurrentRanking(); | 
 |  |  |         currentRanking = currentRanking.replace("{start-end}", startEnd) | 
 |  |  |                 .replace("{cityName}", cityName) | 
 |  |  |                 .replace("{compositeIndex}", compositeIndex == null ? "_" : compositeIndex.toString()) | 
 |  |  |                 .replace("{compositeIndexRanking}", compositeIndexBuilder.toString().equals("") ? "_" : compositeIndexBuilder.toString()) | 
 |  |  |                 .replace("{compositeIndexYearOnYearRanking}", compositeIndexYearOnYearBuilder.toString().equals("") ? "_" : compositeIndexYearOnYearBuilder.toString()) | 
 |  |  |                 .replace("{PM2_5}", pm2_5 == null ? "_" : pm2_5.toString()) | 
 |  |  |                 .replace("{PM2_5Ranking}", pm25Builder.toString().equals("") ? "_" : pm25Builder.toString()) | 
 |  |  |                 .replace("{PM2_5YearOnYearRanking}", pm25YearOnYearBuilder.toString().equals("") ? "_" : pm25YearOnYearBuilder.toString()); | 
 |  |  |         String strCompositeIndexYearOnYear = "_"; | 
 |  |  |         if (compositeIndexYearOnYear != null) { | 
 |  |  |             if (compositeIndexYearOnYear.toString().startsWith("-")) { | 
 |  |  |                 strCompositeIndexYearOnYear = compositeIndexYearOnYear.toString().replace("-", "下降"); | 
 |  |  |             } else if (Double.parseDouble(compositeIndexYearOnYear.toString().replace("%", "")) == 0d) { | 
 |  |  |                 strCompositeIndexYearOnYear = compositeIndexYearOnYear.toString(); | 
 |  |  |             } else { | 
 |  |  |                 strCompositeIndexYearOnYear = "上升" + compositeIndexYearOnYear; | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |         String strPM25YearOnYear = "_"; | 
 |  |  |         if (pm2_5YearOnYear != null) { | 
 |  |  |             if (pm2_5YearOnYear.toString().startsWith("-")) { | 
 |  |  |                 strPM25YearOnYear = pm2_5YearOnYear.toString().replace("-", "下降"); | 
 |  |  |             } else { | 
 |  |  |                 strPM25YearOnYear = "上升" + pm2_5YearOnYear; | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |         currentRanking = currentRanking.replace("{compositeIndexYearOnYear}", strCompositeIndexYearOnYear).replace("{PM2_5YearOnYear}", strPM25YearOnYear); | 
 |  |  |  | 
 |  |  |         return currentRanking; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * @param month    月份 | 
 |  |  |      * @param cityName 地级市名字 | 
 |  |  |      * @param result   当月数据map | 
 |  |  |      * @description 县市区与中心城市对比文字拼接 | 
 |  |  |      */ | 
 |  |  |     private String compositeIndexContrastResponse(String month, String cityName, Integer areaSize, Map<String, Object> result) { | 
 |  |  |         Object compositeIndex = result.get("compositeIndex"); | 
 |  |  |         List<String> compositeIndexLowerList = (List<String>) result.get("compositeIndexLower"); | 
 |  |  |         List<String> compositeIndexHigherList = (List<String>) result.get("compositeIndexHigher"); | 
 |  |  |         List<String> compositeIndexEqualList = (List<String>) result.get("compositeIndexEqual"); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         //综指对比 | 
 |  |  |         String compositeIndexLower = compositeIndexLowerList.stream() | 
 |  |  |                 .map(String::valueOf).collect(Collectors.joining(",")); | 
 |  |  |         String compositeIndexHigher = compositeIndexHigherList.stream() | 
 |  |  |                 .map(String::valueOf).collect(Collectors.joining(",")); | 
 |  |  |         String compositeIndexEqual = compositeIndexEqualList.stream() | 
 |  |  |                 .map(String::valueOf).collect(Collectors.joining(",")); | 
 |  |  |  | 
 |  |  |         StringBuilder builder = new StringBuilder(); | 
 |  |  |         if (compositeIndexLowerList.size() != 0) { | 
 |  |  |             builder.append("有" + compositeIndexLowerList.size() + "个县(市、区)空气质量综合指数低于中心城区,分别为:").append(compositeIndexLower + ","); | 
 |  |  |         } | 
 |  |  |         if (compositeIndexEqualList.size() != 0) { | 
 |  |  |             builder.append(compositeIndexEqual + "" + compositeIndexEqualList.size() + "个县(市、区)空气质量综合指数与中心城区持平"); | 
 |  |  |         } | 
 |  |  |         if (compositeIndexHigherList.size() != 0) { | 
 |  |  |             builder.append("有" + compositeIndexHigherList.size() + "个县(市、区)空气质量综合指数高于中心城区,分别为:").append(compositeIndexHigher); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         String currentContrastCompositeIndex = announcementProperties.getContrastCompositeIndex(); | 
 |  |  |         currentContrastCompositeIndex = currentContrastCompositeIndex.replace("{month}", month) | 
 |  |  |                 .replace("{cityName}", cityName) | 
 |  |  |                 .replace("{compositeIndex}", compositeIndex == null ? "_" : compositeIndex.toString()) | 
 |  |  |                 .replace("{areaSize}", areaSize + "") | 
 |  |  |                 .replace("{details}", builder.toString().equals("") ? "_" : builder.toString()); | 
 |  |  |         return currentContrastCompositeIndex; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * @param month    月份 | 
 |  |  |      * @param cityName 地级市名字 | 
 |  |  |      * @param result   当月数据map | 
 |  |  |      * @description 当月排名文字拼接 | 
 |  |  |      */ | 
 |  |  |     private String compositeIndexYearOnYearContrastResponse(String month, String cityName, Integer areaSize, Map<String, Object> result) { | 
 |  |  |         Object compositeIndexYearOnYear = result.get("compositeIndexYearOnYear"); | 
 |  |  |         List<String> compositeIndexYearOnYearLowerList = (List<String>) result.get("compositeIndexYearOnYearLower"); | 
 |  |  |         List<String> compositeIndexYearOnYearHigherList = (List<String>) result.get("compositeIndexYearOnYearHigher"); | 
 |  |  |         List<String> compositeIndexYearOnYearEqualList = (List<String>) result.get("compositeIndexYearOnYearEqual"); | 
 |  |  |         List<String> compositeIndexYearOnYearHigherOfPositiveList = (List<String>) result.get("compositeIndexYearOnYearHigherOfPositive"); | 
 |  |  |         List<String> compositeIndexYearOnYearHigherOfNegativeList = (List<String>) result.get("compositeIndexYearOnYearHigherOfNegative"); | 
 |  |  |         List<String> compositeIndexYearOnYearHigherOfZeroList = (List<String>) result.get("compositeIndexYearOnYearHigherOfZero"); | 
 |  |  |  | 
 |  |  |         //综指同比对比 | 
 |  |  |         String compositeIndexYearOnYearLower = compositeIndexYearOnYearLowerList.stream() | 
 |  |  |                 .map(String::valueOf).collect(Collectors.joining(",")); | 
 |  |  |         String compositeIndexYearOnYearEqual = compositeIndexYearOnYearEqualList.stream() | 
 |  |  |                 .map(String::valueOf).collect(Collectors.joining(",")); | 
 |  |  |         String compositeIndexYearOnYearHigherOfPositive = compositeIndexYearOnYearHigherOfPositiveList.stream() | 
 |  |  |                 .map(String::valueOf).collect(Collectors.joining(",")); | 
 |  |  |         String compositeIndexYearOnYearHigherOfNegative = compositeIndexYearOnYearHigherOfNegativeList.stream() | 
 |  |  |                 .map(String::valueOf).collect(Collectors.joining(",")); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         StringBuilder builder = new StringBuilder(); | 
 |  |  |         if (compositeIndexYearOnYearLowerList.size() != 0) { | 
 |  |  |             builder.append("有" + compositeIndexYearOnYearLowerList.size() + "个县(市、区)空气质量综合指数同比改善幅度大于中心城区,分别为:") | 
 |  |  |                     .append(compositeIndexYearOnYearLower + ";"); | 
 |  |  |         } | 
 |  |  |         if (compositeIndexYearOnYearEqualList.size() != 0) { | 
 |  |  |             builder.append(compositeIndexYearOnYearEqual + "" + compositeIndexYearOnYearEqualList.size() + "个县(市、区)空气质量综合指数同比改善幅度与中心城区持平;"); | 
 |  |  |         } | 
 |  |  |         if (compositeIndexYearOnYearHigherList.size() != 0) { | 
 |  |  |             builder.append("有" + compositeIndexYearOnYearHigherList.size() + "个县(市、区)空气质量综合指数同比改善幅度小于中心城区,"); | 
 |  |  |             if (compositeIndexYearOnYearHigherOfPositiveList.size() != 0) { | 
 |  |  |                 builder.append("其中有" + compositeIndexYearOnYearHigherOfPositiveList.size() + "个县(市、区)空气质量综合指数同比上升,分别为:" + compositeIndexYearOnYearHigherOfPositive + ","); | 
 |  |  |             } | 
 |  |  |             if (compositeIndexYearOnYearHigherOfZeroList.size() != 0) { | 
 |  |  |                 builder.append("其中有" + compositeIndexYearOnYearHigherOfZeroList.size() + "个县(市、区)空气质量综合指数同比持平,"); | 
 |  |  |             } | 
 |  |  |             if (compositeIndexYearOnYearHigherOfNegativeList.size() != 0) { | 
 |  |  |                 builder.append("其中有" + compositeIndexYearOnYearHigherOfNegativeList.size() + "个县(市、区)空气质量综合指数同比下降,分别为:" + compositeIndexYearOnYearHigherOfNegative); | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         String strCompositeIndexYearOnYear = "_"; | 
 |  |  |         if (compositeIndexYearOnYear != null) { | 
 |  |  |             if (compositeIndexYearOnYear.toString().startsWith("-")) { | 
 |  |  |                 strCompositeIndexYearOnYear = compositeIndexYearOnYear.toString().replace("-", "下降"); | 
 |  |  |             } else if (Double.parseDouble(compositeIndexYearOnYear.toString().replace("%", "")) == 0d) { | 
 |  |  |                 strCompositeIndexYearOnYear = compositeIndexYearOnYear.toString(); | 
 |  |  |             } else { | 
 |  |  |                 strCompositeIndexYearOnYear = "上升" + compositeIndexYearOnYear; | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |         String currentContrastCompositeIndexYearOnYear = announcementProperties.getContrastCompositeIndexYearOnYear(); | 
 |  |  |         currentContrastCompositeIndexYearOnYear = currentContrastCompositeIndexYearOnYear.replace("{month}", month) | 
 |  |  |                 .replace("{cityName}", cityName) | 
 |  |  |                 .replace("{compositeIndexYearOnYear}", strCompositeIndexYearOnYear) | 
 |  |  |                 .replace("{areaSize}", areaSize + "") | 
 |  |  |                 .replace("{details}", builder.toString().equals("") ? "_" : builder.toString()); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         return currentContrastCompositeIndexYearOnYear; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * @param month    月份 | 
 |  |  |      * @param cityName 地级市名字 | 
 |  |  |      * @param result   当月数据map | 
 |  |  |      * @description PM2.5拼接 | 
 |  |  |      */ | 
 |  |  |     private String pm25tContrastResponse(String month, String cityName, Integer areaSize, Map<String, Object> result) { | 
 |  |  |         Object pm25 = result.get("PM2_5"); | 
 |  |  |         List<String> pm25LowerList = (List<String>) result.get("PM2_5Lower"); | 
 |  |  |         List<String> pm25HigherList = (List<String>) result.get("PM2_5Higher"); | 
 |  |  |         List<String> pm25EqualList = (List<String>) result.get("PM2_5Equal"); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         //PM2.5对比 | 
 |  |  |         String pm25Lower = pm25LowerList.stream() | 
 |  |  |                 .map(String::valueOf).collect(Collectors.joining(",")); | 
 |  |  |         String pm25Higher = pm25HigherList.stream() | 
 |  |  |                 .map(String::valueOf).collect(Collectors.joining(",")); | 
 |  |  |         String pm25Equal = pm25EqualList.stream() | 
 |  |  |                 .map(String::valueOf).collect(Collectors.joining(",")); | 
 |  |  |  | 
 |  |  |         StringBuilder builder = new StringBuilder(); | 
 |  |  |         if (pm25LowerList.size() != 0) { | 
 |  |  |             builder.append("有" + pm25LowerList.size() + "个县(市、区)PM2.5累计浓度低于中心城区,分别为:").append(pm25Lower); | 
 |  |  |         } | 
 |  |  |         if (pm25EqualList.size() != 0) { | 
 |  |  |             builder.append(pm25Equal + "" + pm25EqualList.size() + "个县(市、区)PM2.5累计浓度与中心城区持平,"); | 
 |  |  |         } | 
 |  |  |         if (pm25HigherList.size() != 0) { | 
 |  |  |             builder.append("有" + pm25HigherList.size() + "个县(市、区)PM2.5累计浓度高于中心城区,分别为:").append(pm25Higher); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         String propertiesCurrentContrastPm25 = announcementProperties.getContrastPm25(); | 
 |  |  |         propertiesCurrentContrastPm25 = propertiesCurrentContrastPm25.replace("{month}", month) | 
 |  |  |                 .replace("{cityName}", cityName) | 
 |  |  |                 .replace("{PM2_5}", pm25 == null ? "_" : pm25.toString()) | 
 |  |  |                 .replace("{areaSize}", areaSize + "") | 
 |  |  |                 .replace("{details}", builder.toString().equals("") ? "_" : builder.toString()); | 
 |  |  |         return propertiesCurrentContrastPm25; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * @param month    月份 | 
 |  |  |      * @param cityName 地级市名字 | 
 |  |  |      * @param result   当月数据map | 
 |  |  |      * @description PM2.5同比对比文字拼接 | 
 |  |  |      */ | 
 |  |  |     private String pm25YearOnYearContrastResponse(String month, String cityName, Integer areaSize, Map<String, Object> result) { | 
 |  |  |         Object pm25YearOnYear = result.get("PM2_5YearOnYear"); | 
 |  |  |  | 
 |  |  |         List<String> pm25YearOnYearLowerList = (List<String>) result.get("PM2_5YearOnYearLower"); | 
 |  |  |         List<String> pm25YearOnYearHigherList = (List<String>) result.get("PM2_5YearOnYearHigher"); | 
 |  |  |         List<String> pm25YearOnYearEqualList = (List<String>) result.get("PM2_5YearOnYearEqual"); | 
 |  |  |         List<String> pm25YearOnYearLowerOfPositiveList = (List<String>) result.get("pm25YearOnYearLowerOfPositive"); | 
 |  |  |         List<String> pm25YearOnYearLowerOfNegativeList = (List<String>) result.get("pm25YearOnYearLowerOfNegative"); | 
 |  |  |         List<String> pm25YearOnYearLowerOfZeroList = (List<String>) result.get("pm25YearOnYearLowerOfZero"); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         //PM2.5同比对比 | 
 |  |  |         String pm25YearOnYearHigher = pm25YearOnYearHigherList.stream() | 
 |  |  |                 .map(String::valueOf).collect(Collectors.joining(",")); | 
 |  |  |         String pm25YearOnYearEqual = pm25YearOnYearEqualList.stream() | 
 |  |  |                 .map(String::valueOf).collect(Collectors.joining(",")); | 
 |  |  |         String pm25YearOnYearLowerOfPositive = pm25YearOnYearLowerOfPositiveList.stream() | 
 |  |  |                 .map(String::valueOf).collect(Collectors.joining(",")); | 
 |  |  |         String pm25YearOnYearLowerOfNegative = pm25YearOnYearLowerOfNegativeList.stream() | 
 |  |  |                 .map(String::valueOf).collect(Collectors.joining(",")); | 
 |  |  |  | 
 |  |  |         StringBuilder builder = new StringBuilder(); | 
 |  |  |         if (pm25YearOnYearLowerList.size() != 0) { | 
 |  |  |             builder.append("有" + pm25YearOnYearLowerList.size() + "个县(市、区)PM2.5累计浓度同比改善幅度大于中心城区,"); | 
 |  |  |             if (pm25YearOnYearLowerOfNegativeList.size() != 0) { | 
 |  |  |                 builder.append("其中有" + pm25YearOnYearLowerOfNegativeList.size() + "个县(市、区)PM2.5累计浓度同比下降,分别为:") | 
 |  |  |                         .append(pm25YearOnYearLowerOfNegative); | 
 |  |  |             } | 
 |  |  |             if (pm25YearOnYearLowerOfZeroList.size() != 0) { | 
 |  |  |                 builder.append("有" + pm25YearOnYearLowerOfZeroList.size() + "个县(市、区)PM2.5累计浓度同比持平,"); | 
 |  |  |             } | 
 |  |  |             if (pm25YearOnYearLowerOfPositiveList.size() != 0) { | 
 |  |  |                 builder.append("有" + pm25YearOnYearLowerOfPositiveList.size() + "个县(市、区)PM2.5累计浓度同比上升,分别为:").append(pm25YearOnYearLowerOfPositive); | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |         if (pm25YearOnYearEqualList.size() != 0) { | 
 |  |  |             builder.append(pm25YearOnYearEqual + "" + pm25YearOnYearEqualList.size() + "个县(市、区)PM2.5累计浓度同比改善幅度与中心城区持平;"); | 
 |  |  |         } | 
 |  |  |         if (pm25YearOnYearHigherList.size() != 0) { | 
 |  |  |             builder.append("有" + pm25YearOnYearHigherList.size() + "个县(市、区)PM2.5累计浓度同比改善幅度小于中心城区,分别为:").append(pm25YearOnYearHigher); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         String strPM25IndexYearOnYear = "_"; | 
 |  |  |         if (pm25YearOnYear != null) { | 
 |  |  |             if (pm25YearOnYear.toString().startsWith("-")) { | 
 |  |  |                 strPM25IndexYearOnYear = pm25YearOnYear.toString().replace("-", "下降"); | 
 |  |  |             } else if (Double.parseDouble(pm25YearOnYear.toString().replace("%", "")) == 0d) { | 
 |  |  |                 strPM25IndexYearOnYear = pm25YearOnYear.toString(); | 
 |  |  |             } else { | 
 |  |  |                 strPM25IndexYearOnYear = "上升" + pm25YearOnYear; | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         String currentContrastPm25YearOnYear = announcementProperties.getContrastPm25YearOnYear(); | 
 |  |  |         currentContrastPm25YearOnYear = currentContrastPm25YearOnYear.replace("{month}", month) | 
 |  |  |                 .replace("{cityName}", cityName) | 
 |  |  |                 .replace("{PM2_5YearOnYear}", strPM25IndexYearOnYear) | 
 |  |  |                 .replace("{areaSize}", areaSize + "") | 
 |  |  |                 .replace("{details}", builder.toString().equals("") ? "_" : builder.toString()); | 
 |  |  |         return currentContrastPm25YearOnYear; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * @param data       数据集合 | 
 |  |  |      * @param regionCode 当前地区编码 | 
 |  |  |      * @param rankField  排名字段 | 
 |  |  |      * @description 根据某字段获取排名 | 
 |  |  |      */ | 
 |  |  |     private Integer ranking(List<CityAqiMonthly> data, Integer regionCode, String rankField) { | 
 |  |  |         Integer rank = null; | 
 |  |  |         data = data.stream().sorted((o1, o2) -> { | 
 |  |  |             Map<String, Object> map1 = JSONObject.parseObject(o1.getValue(), Map.class); | 
 |  |  |             Map<String, Object> map2 = JSONObject.parseObject(o2.getValue(), Map.class); | 
 |  |  |             Object b1 = map1.get(rankField); | 
 |  |  |             Object b2 = map2.get(rankField); | 
 |  |  |  | 
 |  |  |             if (b1 != null && b2 != null) { | 
 |  |  |                 double aDouble1 = Double.parseDouble(b1.toString().replace("%", "")); | 
 |  |  |                 double aDouble2 = Double.parseDouble(b2.toString().replace("%", "")); | 
 |  |  |                 return aDouble1 > aDouble2 ? 1 : -1; | 
 |  |  |             } else if (b1 == null && b2 == null) { | 
 |  |  |                 return 0; | 
 |  |  |             } else if (b1 == null) { | 
 |  |  |                 return -1; | 
 |  |  |             } else { | 
 |  |  |                 return 1; | 
 |  |  |             } | 
 |  |  |         }).collect(Collectors.toList()); | 
 |  |  |         for (int i = 0; i < data.size(); i++) { | 
 |  |  |             Integer cityCode = data.get(i).getCityCode(); | 
 |  |  |             if (cityCode.equals(regionCode)) { | 
 |  |  |                 Map<String, Object> map = JSONObject.parseObject(data.get(i).getValue(), Map.class); | 
 |  |  |                 if (map.get(rankField) != null) { | 
 |  |  |                     rank = i + 1; | 
 |  |  |                 } | 
 |  |  |                 break; | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |         return rank; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * @param regionCode 地区编码 | 
 |  |  |      * @param time       时间 | 
 |  |  |      * @description 本市在168城市中排名情况 | 
 |  |  |      */ | 
 |  |  |     private Map<String, Object> getOneSixEightCitiesRanking(Integer regionCode, Date time) { | 
 |  |  |         Map<String, Object> result = new HashMap<>(); | 
 |  |  |  | 
 |  |  |         if (specialCitiesProperties.isOneSixEightCities(regionCode)) { | 
 |  |  |  | 
 |  |  |             QueryWrapper<CityAqiMonthly> queryWrapper = new QueryWrapper<>(); | 
 |  |  |             List<SysArea> oneSixEightCities = specialCitiesProperties.getOneSixEightCities(); | 
 |  |  |             List<Integer> oneSixEightCitiesCodes = oneSixEightCities.stream() | 
 |  |  |                     .map(SysArea::getAreaCode) | 
 |  |  |                     .collect(Collectors.toList()); | 
 |  |  |             //获取168城市数据 | 
 |  |  |             queryWrapper.clear(); | 
 |  |  |             queryWrapper.select("city_code", "value") | 
 |  |  |                     .eq("time", time) | 
 |  |  |                     .in("city_code", oneSixEightCitiesCodes); | 
 |  |  |             List<CityAqiMonthly> monthlyData168 = cityAqiMonthlyMapper.selectList(queryWrapper); | 
 |  |  |  | 
 |  |  |             //综指168城市排名 | 
 |  |  |             Integer compositeIndexRank = ranking(monthlyData168, regionCode, "compositeIndex"); | 
 |  |  |             //综指同比168城市排名 | 
 |  |  |             Integer compositeIndexYearOnYearRank = ranking(monthlyData168, regionCode, "compositeIndex_yearOnYear"); | 
 |  |  |  | 
 |  |  |             //PM2.5浓度168城市排名 | 
 |  |  |             Integer pm25Rank = ranking(monthlyData168, regionCode, "PM2_5"); | 
 |  |  |             //PM2.5浓度同比168城市排名 | 
 |  |  |             Integer pm25YearOnYearRank = ranking(monthlyData168, regionCode, "PM2_5_yearOnYear"); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |             //存入结果集 | 
 |  |  |             result.put("compositeIndex_rank_168", compositeIndexRank == null ? "_" : compositeIndexRank); | 
 |  |  |             result.put("compositeIndex_yearOnYear_rank_168", compositeIndexYearOnYearRank == null ? "_" : compositeIndexYearOnYearRank); | 
 |  |  |             result.put("PM2_5_rank_168", pm25Rank == null ? "_" : pm25Rank); | 
 |  |  |             result.put("PM2_5_yearOnYear_rank_168", pm25YearOnYearRank == null ? "_" : pm25YearOnYearRank); | 
 |  |  |         } | 
 |  |  |         return result; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |     //1-x月168城市排名 | 
 |  |  |     private Map<String, Object> getOneSixEightCitiesRankingOfCumulative(Integer regionCode, Date time) { | 
 |  |  |         Map<String, Object> result = new HashMap<>(); | 
 |  |  |  | 
 |  |  |         if (specialCitiesProperties.isOneSixEightCities(regionCode)) { | 
 |  |  |             List<SysArea> oneSixEightCities = specialCitiesProperties.getOneSixEightCities(); | 
 |  |  |             List<Integer> oneSixEightCitiesCodes = oneSixEightCities.stream() | 
 |  |  |                     .map(SysArea::getAreaCode) | 
 |  |  |                     .collect(Collectors.toList()); | 
 |  |  |  | 
 |  |  |             //168城市1-x月累计 | 
 |  |  |             Map<Integer, Map<String, Object>> cumulative168Result = getMonthlyCumulativeResult(time, oneSixEightCitiesCodes); | 
 |  |  |             List<CityAqiMonthly> cumulativeData168 = new ArrayList<>(); | 
 |  |  |             for (Map.Entry<Integer, Map<String, Object>> entry : cumulative168Result.entrySet()) { | 
 |  |  |                 CityAqiMonthly cityAqiMonthly = new CityAqiMonthly(); | 
 |  |  |                 Integer cityCode = entry.getKey(); | 
 |  |  |                 Map<String, Object> value = entry.getValue(); | 
 |  |  |                 cityAqiMonthly.setCityCode(cityCode); | 
 |  |  |                 cityAqiMonthly.setValue(JSONObject.toJSONString(value)); | 
 |  |  |                 cumulativeData168.add(cityAqiMonthly); | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |             //综指168城市排名 | 
 |  |  |             Integer compositeIndexRank = ranking(cumulativeData168, regionCode, "compositeIndex"); | 
 |  |  |             //综指同比168城市排名 | 
 |  |  |             Integer compositeIndexYearOnYearRank = ranking(cumulativeData168, regionCode, "compositeIndex_yearOnYear"); | 
 |  |  |  | 
 |  |  |             //PM2.5浓度168城市排名 | 
 |  |  |             Integer pm25Rank = ranking(cumulativeData168, regionCode, "PM2_5"); | 
 |  |  |             //PM2.5浓度同比168城市排名 | 
 |  |  |             Integer pm25YearOnYearRank = ranking(cumulativeData168, regionCode, "PM2_5_yearOnYear"); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |             //存入结果集 | 
 |  |  |             result.put("compositeIndex_rank_168", compositeIndexRank == null ? "_" : compositeIndexRank); | 
 |  |  |             result.put("compositeIndex_yearOnYear_rank_168", compositeIndexYearOnYearRank == null ? "_" : compositeIndexYearOnYearRank); | 
 |  |  |             result.put("PM2_5_rank_168", pm25Rank == null ? "_" : pm25Rank); | 
 |  |  |             result.put("PM2_5_yearOnYear_rank_168", pm25YearOnYearRank == null ? "_" : pm25YearOnYearRank); | 
 |  |  |         } | 
 |  |  |         return result; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     //1-x月2+26城市排名 | 
 |  |  |     private Map<String, Object> getTwentyEightCitiesRankingOfCumulative(Integer regionCode, Date time) { | 
 |  |  |         Map<String, Object> result = new HashMap<>(); | 
 |  |  |  | 
 |  |  |         if (specialCitiesProperties.isTwentyEightCities(regionCode)) { | 
 |  |  |             List<SysArea> twentyCities = specialCitiesProperties.getTwentyEightCities(); | 
 |  |  |             List<Integer> twentyCitiesCodes = twentyCities.stream() | 
 |  |  |                     .map(SysArea::getAreaCode) | 
 |  |  |                     .collect(Collectors.toList()); | 
 |  |  |  | 
 |  |  |             //168城市1-x月累计 | 
 |  |  |             Map<Integer, Map<String, Object>> cumulative168Result = getMonthlyCumulativeResult(time, twentyCitiesCodes); | 
 |  |  |             List<CityAqiMonthly> cumulativeData168 = new ArrayList<>(); | 
 |  |  |             for (Map.Entry<Integer, Map<String, Object>> entry : cumulative168Result.entrySet()) { | 
 |  |  |                 CityAqiMonthly cityAqiMonthly = new CityAqiMonthly(); | 
 |  |  |                 Integer cityCode = entry.getKey(); | 
 |  |  |                 Map<String, Object> value = entry.getValue(); | 
 |  |  |                 cityAqiMonthly.setCityCode(cityCode); | 
 |  |  |                 cityAqiMonthly.setValue(JSONObject.toJSONString(value)); | 
 |  |  |                 cumulativeData168.add(cityAqiMonthly); | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |             //综指168城市排名 | 
 |  |  |             Integer compositeIndexRank = ranking(cumulativeData168, regionCode, "compositeIndex"); | 
 |  |  |             //综指同比168城市排名 | 
 |  |  |             Integer compositeIndexYearOnYearRank = ranking(cumulativeData168, regionCode, "compositeIndex_yearOnYear"); | 
 |  |  |  | 
 |  |  |             //PM2.5浓度168城市排名 | 
 |  |  |             Integer pm25Rank = ranking(cumulativeData168, regionCode, "PM2_5"); | 
 |  |  |             //PM2.5浓度同比168城市排名 | 
 |  |  |             Integer pm25YearOnYearRank = ranking(cumulativeData168, regionCode, "PM2_5_yearOnYear"); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |             //存入结果集 | 
 |  |  |             result.put("compositeIndex_rank_28", compositeIndexRank == null ? "_" : compositeIndexRank); | 
 |  |  |             result.put("compositeIndex_yearOnYear_rank_28", compositeIndexYearOnYearRank == null ? "_" : compositeIndexYearOnYearRank); | 
 |  |  |             result.put("PM2_5_rank_28", pm25Rank == null ? "_" : pm25Rank); | 
 |  |  |             result.put("PM2_5_yearOnYear_rank_28", pm25YearOnYearRank == null ? "_" : pm25YearOnYearRank); | 
 |  |  |         } | 
 |  |  |         return result; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     //1-x月河北八通道城市排名 | 
 |  |  |     private Map<String, Object> getHeBeiEightCitiesRankingOfCumulative(Integer regionCode, Date time) { | 
 |  |  |         Map<String, Object> result = new HashMap<>(); | 
 |  |  |  | 
 |  |  |         if (specialCitiesProperties.isHeBeiEightCities(regionCode)) { | 
 |  |  |             List<SysArea> heBeiEightCities = specialCitiesProperties.getHeBeiEightCities(); | 
 |  |  |             List<Integer> heBeiEightCitiesCodes = heBeiEightCities.stream() | 
 |  |  |                     .map(SysArea::getAreaCode) | 
 |  |  |                     .collect(Collectors.toList()); | 
 |  |  |  | 
 |  |  |             //168城市1-x月累计 | 
 |  |  |             Map<Integer, Map<String, Object>> cumulative168Result = getMonthlyCumulativeResult(time, heBeiEightCitiesCodes); | 
 |  |  |             List<CityAqiMonthly> cumulativeData168 = new ArrayList<>(); | 
 |  |  |             for (Map.Entry<Integer, Map<String, Object>> entry : cumulative168Result.entrySet()) { | 
 |  |  |                 CityAqiMonthly cityAqiMonthly = new CityAqiMonthly(); | 
 |  |  |                 Integer cityCode = entry.getKey(); | 
 |  |  |                 Map<String, Object> value = entry.getValue(); | 
 |  |  |                 cityAqiMonthly.setCityCode(cityCode); | 
 |  |  |                 cityAqiMonthly.setValue(JSONObject.toJSONString(value)); | 
 |  |  |                 cumulativeData168.add(cityAqiMonthly); | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |             //综指168城市排名 | 
 |  |  |             Integer compositeIndexRank = ranking(cumulativeData168, regionCode, "compositeIndex"); | 
 |  |  |             //综指同比168城市排名 | 
 |  |  |             Integer compositeIndexYearOnYearRank = ranking(cumulativeData168, regionCode, "compositeIndex_yearOnYear"); | 
 |  |  |  | 
 |  |  |             //PM2.5浓度168城市排名 | 
 |  |  |             Integer pm25Rank = ranking(cumulativeData168, regionCode, "PM2_5"); | 
 |  |  |             //PM2.5浓度同比168城市排名 | 
 |  |  |             Integer pm25YearOnYearRank = ranking(cumulativeData168, regionCode, "PM2_5_yearOnYear"); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |             //存入结果集 | 
 |  |  |             result.put("compositeIndex_rank_8channels", compositeIndexRank == null ? "_" : compositeIndexRank); | 
 |  |  |             result.put("compositeIndex_YearOnYear_rank_8channels", compositeIndexYearOnYearRank == null ? "_" : compositeIndexYearOnYearRank); | 
 |  |  |             result.put("PM2_5_rank_8channels", pm25Rank == null ? "_" : pm25Rank); | 
 |  |  |             result.put("PM2_5_yearOnYear_rank_8channels", pm25YearOnYearRank == null ? "_" : pm25YearOnYearRank); | 
 |  |  |         } | 
 |  |  |         return result; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * @param regionCode 地区编码 | 
 |  |  |      * @param time       时间 | 
 |  |  |      * @description 本市在2+26城市中排名情况 | 
 |  |  |      */ | 
 |  |  |     private Map<String, Object> getTwentyEightCitiesRanking(Integer regionCode, Date time) { | 
 |  |  |         Map<String, Object> result = new HashMap<>(); | 
 |  |  |  | 
 |  |  |         if (specialCitiesProperties.isTwentyEightCities(regionCode)) { | 
 |  |  |  | 
 |  |  |             QueryWrapper<CityAqiMonthly> queryWrapper = new QueryWrapper<>(); | 
 |  |  |             List<SysArea> twentyEightCities = specialCitiesProperties.getTwentyEightCities(); | 
 |  |  |             List<Integer> twentyEightCitiesCodes = twentyEightCities.stream() | 
 |  |  |                     .map(SysArea::getAreaCode) | 
 |  |  |                     .collect(Collectors.toList()); | 
 |  |  |             //获取2+26城市数据 | 
 |  |  |             queryWrapper.select("city_code", "value") | 
 |  |  |                     .eq("time", time) | 
 |  |  |                     .in("city_code", twentyEightCitiesCodes); | 
 |  |  |             List<CityAqiMonthly> monthlyData28 = cityAqiMonthlyMapper.selectList(queryWrapper); | 
 |  |  |  | 
 |  |  |             //综指2+26城市排名 | 
 |  |  |             Integer compositeIndexRank = ranking(monthlyData28, regionCode, "compositeIndex"); | 
 |  |  |             //综指同比2+26城市排名 | 
 |  |  |             Integer compositeIndexYearOnYearRank = ranking(monthlyData28, regionCode, "compositeIndex_yearOnYear"); | 
 |  |  |  | 
 |  |  |             //PM2.5浓度2+26城市排名 | 
 |  |  |             Integer pm25Rank = ranking(monthlyData28, regionCode, "PM2_5"); | 
 |  |  |             //PM2.5浓度同比2+26城市排名 | 
 |  |  |             Integer pm25YearOnYearRank = ranking(monthlyData28, regionCode, "PM2_5_yearOnYear"); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |             //存入结果集 | 
 |  |  |             result.put("compositeIndex_rank_28", compositeIndexRank == null ? "_" : compositeIndexRank); | 
 |  |  |             result.put("compositeIndex_yearOnYear_rank_28", compositeIndexYearOnYearRank == null ? "_" : compositeIndexYearOnYearRank); | 
 |  |  |             result.put("PM2_5_rank_28", pm25Rank == null ? "_" : pm25Rank); | 
 |  |  |             result.put("PM2_5_yearOnYear_rank_28", pm25YearOnYearRank == null ? "_" : pm25YearOnYearRank); | 
 |  |  |         } | 
 |  |  |         return result; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * @param regionCode 地区编码 | 
 |  |  |      * @param time       时间 | 
 |  |  |      * @description 本市在河北八通道城市中排名情况 | 
 |  |  |      */ | 
 |  |  |     private Map<String, Object> getHeBeiEightCitiesRanking(Integer regionCode, Date time) { | 
 |  |  |         Map<String, Object> result = new HashMap<>(); | 
 |  |  |  | 
 |  |  |         if (specialCitiesProperties.isHeBeiEightCities(regionCode)) { | 
 |  |  |             QueryWrapper<CityAqiMonthly> queryWrapper = new QueryWrapper<>(); | 
 |  |  |             List<SysArea> heBeiEightCities = specialCitiesProperties.getHeBeiEightCities(); | 
 |  |  |             List<Integer> heBeiEightCitiesCodes = heBeiEightCities.stream() | 
 |  |  |                     .map(SysArea::getAreaCode) | 
 |  |  |                     .collect(Collectors.toList()); | 
 |  |  |             //获取2+26城市数据 | 
 |  |  |             queryWrapper.select("city_code", "value") | 
 |  |  |                     .eq("time", time) | 
 |  |  |                     .in("city_code", heBeiEightCitiesCodes); | 
 |  |  |             List<CityAqiMonthly> monthlyData8Channels = cityAqiMonthlyMapper.selectList(queryWrapper); | 
 |  |  |  | 
 |  |  |             //综指八通道城市排名 | 
 |  |  |             Integer compositeIndexRank = ranking(monthlyData8Channels, regionCode, "compositeIndex"); | 
 |  |  |             //综指同比八通道城市排名 | 
 |  |  |             Integer compositeIndexYearOnYearRank = ranking(monthlyData8Channels, regionCode, "compositeIndex_yearOnYear"); | 
 |  |  |  | 
 |  |  |             //PM2.5浓度八通道城市排名 | 
 |  |  |             Integer pm25Rank = ranking(monthlyData8Channels, regionCode, "PM2_5"); | 
 |  |  |             //PM2.5浓度同比八通道城市排名 | 
 |  |  |             Integer pm25YearOnYearRank = ranking(monthlyData8Channels, regionCode, "PM2_5_yearOnYear"); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |             //存入结果集 | 
 |  |  |             result.put("compositeIndex_rank_8channels", compositeIndexRank == null ? "_" : compositeIndexRank); | 
 |  |  |             result.put("compositeIndex_yearOnYear_rank_8channels", compositeIndexYearOnYearRank == null ? "_" : compositeIndexYearOnYearRank); | 
 |  |  |             result.put("PM2_5_rank_8channels", pm25Rank == null ? "_" : pm25Rank); | 
 |  |  |             result.put("PM2_5_yearOnYear_rank_8channels", pm25YearOnYearRank == null ? "_" : pm25YearOnYearRank); | 
 |  |  |         } | 
 |  |  |         return result; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * @param areasMap                 所有县市区信息 areaCode--areaName | 
 |  |  |      * @param areaData                 所有县市区数据 | 
 |  |  |      * @param compositeIndex           中心城区(地级市)综指 | 
 |  |  |      * @param compositeIndexYearOnYear 中心城区(地级市)综指同比 | 
 |  |  |      * @param pm25                     中心城区(地级市)pm.5浓度 | 
 |  |  |      * @param pm25YearOnYear           中心城区(地级市)pm2.5同比 | 
 |  |  |      * @description 获取本期所有县市区与中心城区(地级市)因子对比情况 | 
 |  |  |      */ | 
 |  |  |     private Map<String, Object> getAreaCurrentMonthResult(Map<Integer, String> areasMap, List<CityAqiMonthly> areaData, Double compositeIndex, String compositeIndexYearOnYear, Integer pm25, String pm25YearOnYear) { | 
 |  |  |         Map<String, Object> result = new HashMap<>(); | 
 |  |  |         result.put("compositeIndex", compositeIndex); | 
 |  |  |         result.put("compositeIndexYearOnYear", compositeIndexYearOnYear); | 
 |  |  |         result.put("PM2_5", null); | 
 |  |  |         if (pm25 != null) { | 
 |  |  |             result.put("PM2_5", pm25 + "ug/m³"); | 
 |  |  |         } | 
 |  |  |         result.put("PM2_5YearOnYear", pm25YearOnYear); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         //综指低于中心城区(地级市)集合 | 
 |  |  |         List<String> compositeIndexLowerList = new ArrayList<>(); | 
 |  |  |         //综指高于中心城区(地级市)集合 | 
 |  |  |         List<String> compositeIndexHigherList = new ArrayList<>(); | 
 |  |  |         //综指等于中心城区(地级市)集合 | 
 |  |  |         List<String> compositeIndexEqualList = new ArrayList<>(); | 
 |  |  |  | 
 |  |  |         //综指同比低于中心城区(地级市)集合 | 
 |  |  |         List<String> compositeIndexYearOnYearLowerList = new ArrayList<>(); | 
 |  |  |         //综指同比高于中心城区(地级市)集合 | 
 |  |  |         List<String> compositeIndexYearOnYearHigherList = new ArrayList<>(); | 
 |  |  |         //综指同比等于中心城区(地级市)集合 | 
 |  |  |         List<String> compositeIndexYearOnYearEqualList = new ArrayList<>(); | 
 |  |  |         //综指同比高于于中心城区(地级市)的地区中综指同比为正的 | 
 |  |  |         List<String> compositeIndexYearOnYearHigherOfPositiveList = new ArrayList<>(); | 
 |  |  |         //综指同比高于于中心城区(地级市)的地区中综指同比为负的 | 
 |  |  |         List<String> compositeIndexYearOnYearHigherOfNegativeList = new ArrayList<>(); | 
 |  |  |         //综指同比高于于中心城区(地级市)的地区中综指同比为0的 | 
 |  |  |         List<String> compositeIndexYearOnYearHigherOfZeroList = new ArrayList<>(); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         //pm2.5低于中心城区(地级市)集合 | 
 |  |  |         List<String> pm25LowerList = new ArrayList<>(); | 
 |  |  |         //pm2.5高于中心城区(地级市)集合 | 
 |  |  |         List<String> pm25HigherList = new ArrayList<>(); | 
 |  |  |         //pm2.5等于中心城区(地级市)集合 | 
 |  |  |         List<String> pm25EqualList = new ArrayList<>(); | 
 |  |  |  | 
 |  |  |         //pm2.5同比低于中心城区(地级市)集合 | 
 |  |  |         List<String> pm25YearOnYearLowerList = new ArrayList<>(); | 
 |  |  |         //pm2.5同比高于于中心城区(地级市)集合 | 
 |  |  |         List<String> pm25YearOnYearHigherList = new ArrayList<>(); | 
 |  |  |         ///pm2.5同比等于中心城区(地级市)集合 | 
 |  |  |         List<String> pm25YearOnYearEqualList = new ArrayList<>(); | 
 |  |  |         //pm2.5同比低于于中心城区(地级市)的地区中综指同比为正的 | 
 |  |  |         List<String> pm25YearOnYearLowerOfPositiveList = new ArrayList<>(); | 
 |  |  |         //pm2.5同比低于于中心城区(地级市)的地区中综指同比为负的 | 
 |  |  |         List<String> pm25YearOnYearLowerOfNegativeList = new ArrayList<>(); | 
 |  |  |         //pm2.5同比低于于中心城区(地级市)的地区中综指同比0的 | 
 |  |  |         List<String> pm25YearOnYearLowerOfZeroList = new ArrayList<>(); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         Double cityCompositeIndexYearOnYear = null; | 
 |  |  |         if (compositeIndexYearOnYear != null) { | 
 |  |  |             cityCompositeIndexYearOnYear = Double.parseDouble(compositeIndexYearOnYear.replace("%", "")); | 
 |  |  |         } | 
 |  |  |         Double citypm25YearOnYear = null; | 
 |  |  |         if (pm25YearOnYear != null) { | 
 |  |  |             citypm25YearOnYear = Double.parseDouble(pm25YearOnYear.replace("%", "")); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         for (CityAqiMonthly areaDatum : areaData) { | 
 |  |  |             Integer areaCode = areaDatum.getCityCode(); | 
 |  |  |             Map<String, Object> valueMap = JSONObject.parseObject(areaDatum.getValue(), Map.class); | 
 |  |  |             double compositeIndexValue = Double.parseDouble(valueMap.get("compositeIndex").toString()); | 
 |  |  |  | 
 |  |  |             Double compositeIndexYearOnYearValue = null; | 
 |  |  |             if (valueMap.get("compositeIndex_yearOnYear") != null) { | 
 |  |  |                 compositeIndexYearOnYearValue = Double.parseDouble(valueMap.get("compositeIndex_yearOnYear").toString().replace("%", "")); | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             int pm25Value = (int) Double.parseDouble(valueMap.get("PM2_5").toString()); | 
 |  |  |             Double pm25YearOnYearValue = null; | 
 |  |  |             if (valueMap.get("PM2_5_yearOnYear") != null) { | 
 |  |  |                 pm25YearOnYearValue = Double.parseDouble(valueMap.get("PM2_5_yearOnYear").toString().replace("%", "")); | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             String areaName = areasMap.get(areaCode); | 
 |  |  |             if (compositeIndexValue < compositeIndex) { | 
 |  |  |                 compositeIndexLowerList.add(areaName + "(" + compositeIndexValue + ")"); | 
 |  |  |             } else if (compositeIndexValue > compositeIndex) { | 
 |  |  |                 compositeIndexHigherList.add(areaName + "(" + compositeIndexValue + ")"); | 
 |  |  |             } else { | 
 |  |  |                 compositeIndexEqualList.add(areaName + "(" + compositeIndexValue + ")"); | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             if (cityCompositeIndexYearOnYear != null && compositeIndexYearOnYearValue != null) { | 
 |  |  |                 String compositeIndex_yearOnYear = valueMap.get("compositeIndex_yearOnYear").toString(); | 
 |  |  |                 if (compositeIndexYearOnYearValue > 0d) { | 
 |  |  |                     compositeIndex_yearOnYear = "上升" + compositeIndex_yearOnYear; | 
 |  |  |                 } else if (compositeIndexYearOnYearValue < 0d) { | 
 |  |  |                     compositeIndex_yearOnYear = compositeIndex_yearOnYear.replace("-", "下降"); | 
 |  |  |                 } | 
 |  |  |  | 
 |  |  |                 if (compositeIndexYearOnYearValue > cityCompositeIndexYearOnYear) { | 
 |  |  |  | 
 |  |  |                     compositeIndexYearOnYearHigherList.add(areaName + "(" + compositeIndex_yearOnYear + ")"); | 
 |  |  |                     if (compositeIndexYearOnYearValue > 0) { | 
 |  |  |                         compositeIndexYearOnYearHigherOfPositiveList.add(areaName + "(" + compositeIndex_yearOnYear + ")"); | 
 |  |  |                     } else if (compositeIndexYearOnYearValue < 0) { | 
 |  |  |                         compositeIndexYearOnYearHigherOfNegativeList.add(areaName + "(" + compositeIndex_yearOnYear + ")"); | 
 |  |  |                     } else { | 
 |  |  |                         compositeIndexYearOnYearHigherOfZeroList.add(areaName + "(" + compositeIndex_yearOnYear + ")"); | 
 |  |  |                     } | 
 |  |  |                 } else if (compositeIndexYearOnYearValue < cityCompositeIndexYearOnYear) { | 
 |  |  |                     compositeIndexYearOnYearLowerList.add(areaName + "(" + compositeIndex_yearOnYear + ")"); | 
 |  |  |                 } else { | 
 |  |  |                     compositeIndexYearOnYearEqualList.add(areaName + "(" + compositeIndex_yearOnYear + ")"); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |             if (pm25Value < pm25) { | 
 |  |  |                 pm25LowerList.add(areaName + "(" + pm25Value + "ug/m³)"); | 
 |  |  |             } else if (pm25Value > pm25) { | 
 |  |  |                 pm25HigherList.add(areaName + "(" + pm25Value + "ug/m³)"); | 
 |  |  |             } else { | 
 |  |  |                 pm25EqualList.add(areaName + "(" + pm25Value + "ug/m³)"); | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             if (citypm25YearOnYear != null && pm25YearOnYearValue != null) { | 
 |  |  |                 String pm2_5_yearOnYear = valueMap.get("PM2_5_yearOnYear").toString(); | 
 |  |  |                 if (pm25YearOnYearValue > 0d) { | 
 |  |  |                     pm2_5_yearOnYear = "上升" + pm2_5_yearOnYear; | 
 |  |  |                 } else if (pm25YearOnYearValue < 0d) { | 
 |  |  |                     pm2_5_yearOnYear = pm2_5_yearOnYear.replace("-", "下降"); | 
 |  |  |                 } | 
 |  |  |  | 
 |  |  |                 if (pm25YearOnYearValue < citypm25YearOnYear) { | 
 |  |  |                     pm25YearOnYearLowerList.add(areaName + "(" + pm2_5_yearOnYear + ")"); | 
 |  |  |                     if (pm25YearOnYearValue > 0) { | 
 |  |  |                         pm25YearOnYearLowerOfPositiveList.add(areaName + "(" + pm2_5_yearOnYear + ")"); | 
 |  |  |                     } else if (pm25YearOnYearValue < 0) { | 
 |  |  |                         pm25YearOnYearLowerOfNegativeList.add(areaName + "(" + pm2_5_yearOnYear + ")"); | 
 |  |  |                     } else { | 
 |  |  |                         pm25YearOnYearLowerOfZeroList.add(areaName + "(" + pm2_5_yearOnYear + ")"); | 
 |  |  |                     } | 
 |  |  |                 } else if (pm25YearOnYearValue > citypm25YearOnYear) { | 
 |  |  |                     pm25YearOnYearHigherList.add(areaName + "(" + pm2_5_yearOnYear + ")"); | 
 |  |  |                 } else { | 
 |  |  |                     pm25YearOnYearEqualList.add(areaName + "(" + pm2_5_yearOnYear + ")"); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |         result.put("compositeIndexLower", compositeIndexLowerList); | 
 |  |  |         result.put("compositeIndexHigher", compositeIndexHigherList); | 
 |  |  |         result.put("compositeIndexEqual", compositeIndexEqualList); | 
 |  |  |         result.put("compositeIndexYearOnYearHigher", compositeIndexYearOnYearHigherList); | 
 |  |  |         result.put("compositeIndexYearOnYearLower", compositeIndexYearOnYearLowerList); | 
 |  |  |         result.put("compositeIndexYearOnYearEqual", compositeIndexYearOnYearEqualList); | 
 |  |  |         result.put("compositeIndexYearOnYearHigherOfPositive", compositeIndexYearOnYearHigherOfPositiveList); | 
 |  |  |         result.put("compositeIndexYearOnYearHigherOfNegative", compositeIndexYearOnYearHigherOfNegativeList); | 
 |  |  |         result.put("compositeIndexYearOnYearHigherOfZero", compositeIndexYearOnYearHigherOfZeroList); | 
 |  |  |  | 
 |  |  |         result.put("PM2_5Lower", pm25LowerList); | 
 |  |  |         result.put("PM2_5Higher", pm25HigherList); | 
 |  |  |         result.put("PM2_5Equal", pm25EqualList); | 
 |  |  |         result.put("PM2_5YearOnYearHigher", pm25YearOnYearHigherList); | 
 |  |  |         result.put("PM2_5YearOnYearLower", pm25YearOnYearLowerList); | 
 |  |  |         result.put("PM2_5YearOnYearEqual", pm25YearOnYearEqualList); | 
 |  |  |         result.put("pm25YearOnYearLowerOfPositive", pm25YearOnYearLowerOfPositiveList); | 
 |  |  |         result.put("pm25YearOnYearLowerOfNegative", pm25YearOnYearLowerOfNegativeList); | 
 |  |  |         result.put("pm25YearOnYearLowerOfZero", pm25YearOnYearLowerOfZeroList); | 
 |  |  |  | 
 |  |  |         return result; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     //1-x月累计结果 | 
 |  |  |     public Map<Integer, Map<String, Object>> getMonthlyCumulativeResult(Date time, List<Integer> regionCodes) { | 
 |  |  |  | 
 |  |  |         //开始时间,当年1月1日 | 
 |  |  |         Date start = DateUtils.getFirstDayOfYear(time); | 
 |  |  |         //结束时间,当月最后一天 | 
 |  |  |         Date end = DateUtils.getLastDayOfMonth(time); | 
 |  |  |  | 
 |  |  |         //获取所有地区当年1-x月的日数据 | 
 |  |  |         QueryWrapper<CityAqiDaily> cityAqiDailyQueryWrapper = new QueryWrapper<>(); | 
 |  |  |         cityAqiDailyQueryWrapper.select("city_code", "value") | 
 |  |  |                 .ge("time", start) | 
 |  |  |                 .le("time", end) | 
 |  |  |                 .in("city_code", regionCodes); | 
 |  |  |         List<CityAqiDaily> cityAqiDailyList = cityAqiDailyService.list(cityAqiDailyQueryWrapper); | 
 |  |  |         if (cityAqiDailyList.size() == 0) { | 
 |  |  |             return null; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         Map<Integer, Map<String, Object>> currentMap = getMonthCumulative(cityAqiDailyList); | 
 |  |  |  | 
 |  |  |         //获取所有地区上年1-x月的日数据,用于计算同比 | 
 |  |  |         cityAqiDailyQueryWrapper.clear(); | 
 |  |  |         cityAqiDailyQueryWrapper.select("city_code", "value") | 
 |  |  |                 .ge("time", DateUtils.addYears(start, -1)) | 
 |  |  |                 .le("time", DateUtils.addYears(end, -1)) | 
 |  |  |                 .in("city_code", regionCodes); | 
 |  |  |         List<CityAqiDaily> lastCityAqiDailyList = cityAqiDailyService.list(cityAqiDailyQueryWrapper); | 
 |  |  |         Map<Integer, Map<String, Object>> lastMap = getMonthCumulative(lastCityAqiDailyList); | 
 |  |  |  | 
 |  |  |         //计算各因子同比 | 
 |  |  |         for (Map.Entry<Integer, Map<String, Object>> entry : currentMap.entrySet()) { | 
 |  |  |             Integer regionCode = entry.getKey(); | 
 |  |  |             Map<String, Object> current = entry.getValue(); | 
 |  |  |             Map<String, Object> last = lastMap.get(regionCode); | 
 |  |  |             Map<String, Object> map = yearOnYearOfSensor(last, current); | 
 |  |  |             if (map != null) { | 
 |  |  |                 currentMap.put(regionCode, yearOnYearOfSensor(last, current)); | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |         return currentMap; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * @param last    上年数据 | 
 |  |  |      * @param current 当前数据 | 
 |  |  |      * @description 计算各因子同比 | 
 |  |  |      */ | 
 |  |  |     private Map<String, Object> yearOnYearOfSensor(Map<String, Object> last, Map<String, Object> current) { | 
 |  |  |         if (last == null) { | 
 |  |  |             return null; | 
 |  |  |         } | 
 |  |  |         //需要计算同比的因子 | 
 |  |  |         List<String> sensors = Arrays.asList("PM2_5", "PM10", "SO2", "NO2", "CO", "O3", "compositeIndex"); | 
 |  |  |         for (String sensor : sensors) { | 
 |  |  |             //上年本月该因子值 | 
 |  |  |             double lastValue = Double.parseDouble(last.get(sensor).toString()); | 
 |  |  |             //当前该因子值 | 
 |  |  |             double currentValue = Double.parseDouble(current.get(sensor).toString()); | 
 |  |  |             DecimalFormat decimalFormat = new DecimalFormat("0.00%"); | 
 |  |  |             String format = decimalFormat.format((currentValue - lastValue) / lastValue); | 
 |  |  |             current.put(sensor + "_yearOnYear", format); | 
 |  |  |             current.put(sensor + "_last", lastValue); | 
 |  |  |         } | 
 |  |  |         return current; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * @param data 各个地区的数据集合 | 
 |  |  |      * @description 计算1-x月各因子均值 | 
 |  |  |      */ | 
 |  |  |     private Map<Integer, Map<String, Object>> getMonthCumulative(List<CityAqiDaily> data) { | 
 |  |  |         Map<Integer, Map<String, Object>> result = new HashMap<>(); | 
 |  |  |         //需要均值计算的因子 | 
 |  |  |         List<String> sensors = Arrays.asList("PM2_5", "PM10", "SO2", "NO2"); | 
 |  |  |         //按city_code分组 | 
 |  |  |         Map<Integer, List<CityAqiDaily>> cityDataMap = data.stream() | 
 |  |  |                 .collect(Collectors.groupingBy(CityAqiDaily::getCityCode)); | 
 |  |  |         //1-x月均值计算 | 
 |  |  |         cityDataMap.forEach((cityCode, list) -> { | 
 |  |  |             Map<String, Object> jsonMap = new HashMap<>(); | 
 |  |  |             Map<String, Object> params = new HashMap<>(); | 
 |  |  |             List<Map<String, Object>> temp = new ArrayList<>(); | 
 |  |  |             for (CityAqiDaily cityAqiDaily : list) { | 
 |  |  |                 Map<String, Object> valueMap = JSONObject.parseObject(cityAqiDaily.getValue(), Map.class); | 
 |  |  |                 Map<String, Object> tempMap = new HashMap<>(); | 
 |  |  |                 Map<String, Object> hashMap = new HashMap<>(); | 
 |  |  |                 tempMap.put(Constants.SENSOR_CODE_CO, valueMap.get("CO")); | 
 |  |  |                 tempMap.put(Constants.SENSOR_CODE_O3, valueMap.get("O3")); | 
 |  |  |                 hashMap.put("value", JSONObject.toJSONString(tempMap)); | 
 |  |  |                 temp.add(hashMap); | 
 |  |  |             } | 
 |  |  |             params.put("data", temp); | 
 |  |  |             //1. CO 95百分位计算并修约 | 
 |  |  |             Map<String, Object> coAvgOfWeekOrMonth = AmendUtils.getCOAvgOfWeekOrMonth(params); | 
 |  |  |             if (!ObjectUtils.isEmpty(coAvgOfWeekOrMonth)) { | 
 |  |  |                 jsonMap.put("CO", coAvgOfWeekOrMonth.get(Constants.SENSOR_CODE_CO)); | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             //2. O3 90百分位计算并修约 | 
 |  |  |             Map<String, Object> o3AvgOfWeekOrMonth = AmendUtils.getO3AvgOfWeekOrMonth(params); | 
 |  |  |             if (!ObjectUtils.isEmpty(o3AvgOfWeekOrMonth)) { | 
 |  |  |                 jsonMap.put("O3", o3AvgOfWeekOrMonth.get(Constants.SENSOR_CODE_O3)); | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             sensors.forEach(sensor -> { | 
 |  |  |                 OptionalDouble optionalDouble = list.stream().flatMapToDouble(v -> { | 
 |  |  |                     Map<String, Object> dataValue = JSONObject.parseObject(v.getValue(), Map.class); | 
 |  |  |                     double aDouble = Double.parseDouble(dataValue.get(sensor).toString()); | 
 |  |  |                     return DoubleStream.of(aDouble); | 
 |  |  |                 }).average(); | 
 |  |  |                 if (optionalDouble.isPresent()) { | 
 |  |  |                     //银行家算法修约 | 
 |  |  |                     jsonMap.put(sensor, AmendUtils.sciCal(optionalDouble.getAsDouble(), 0)); | 
 |  |  |                 } | 
 |  |  |             }); | 
 |  |  |  | 
 |  |  |             //1-x月综指 | 
 |  |  |             Double compositeIndex = ComprehensiveIndexUtils.dailyData(jsonMap); | 
 |  |  |             jsonMap.put("compositeIndex", compositeIndex); | 
 |  |  |             result.put(cityCode, jsonMap); | 
 |  |  |         }); | 
 |  |  |         return result; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 1.考核排名计算公式:(空气质量综合指数绝对值排名×20%+空气质量指数改善幅度排名×30%)+(PM2.5平均浓度绝对值排名×20%+PM2.5平均浓度改善幅度排名×30%)。 | 
 |  |  |      * 2.加权得分值越小,空气质量考核综合评价越好。 | 
 |  |  |      * 3.排名位次数值相加得分相同的情况下,优先按照PM2.5月均浓度值、改善幅度确定排名先后,平均浓度值低、下降幅度大的排名靠前。 | 
 |  |  |      * | 
 |  |  |      * @param list     所有县市区数据 | 
 |  |  |      * @param areasMap 所有县市区信息 areaCode--areaName | 
 |  |  |      * @description 本期综指和pm2.5考核排名报表 | 
 |  |  |      */ | 
 |  |  |     private List<Map<String, Object>> airQualityRankingOfCurrentReport(List<CityAqiMonthly> list, Map<Integer, String> areasMap) { | 
 |  |  |         List<Map<String, Object>> result = new ArrayList<>(); | 
 |  |  |  | 
 |  |  |         Map<Integer, CityAqiMonthly> dataMap = new HashMap<>(); | 
 |  |  |         for (CityAqiMonthly cityAqiMonthly : list) { | 
 |  |  |             dataMap.put(cityAqiMonthly.getCityCode(), cityAqiMonthly); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         for (Map.Entry<Integer, String> entry : areasMap.entrySet()) { | 
 |  |  |             Map<String, Object> resultMap = new HashMap<>(); | 
 |  |  |             Integer regionCode = entry.getKey(); | 
 |  |  |             String areaName = entry.getValue(); | 
 |  |  |             resultMap.put("areaName", areaName); | 
 |  |  |  | 
 |  |  |             //本期综指 | 
 |  |  |             resultMap.put("compositeIndex", null); | 
 |  |  |             //综指同比 | 
 |  |  |             resultMap.put("compositeIndexYearOnYear", null); | 
 |  |  |             //本期PM2.5 | 
 |  |  |             resultMap.put("PM2_5", null); | 
 |  |  |             //PM2.5同比 | 
 |  |  |             resultMap.put("PM2_5YearOnYear", null); | 
 |  |  |             if (dataMap.get(regionCode) != null) { | 
 |  |  |                 Map<String, Object> valueMap = JSONObject.parseObject(dataMap.get(regionCode).getValue(), Map.class); | 
 |  |  |  | 
 |  |  |                 resultMap.put("compositeIndex", valueMap.get("compositeIndex")); | 
 |  |  |                 resultMap.put("compositeIndexYearOnYear", valueMap.get("compositeIndex_yearOnYear")); | 
 |  |  |  | 
 |  |  |                 resultMap.put("PM2_5", valueMap.get("PM2_5")); | 
 |  |  |                 resultMap.put("PM2_5YearOnYear", valueMap.get("PM2_5_yearOnYear")); | 
 |  |  |             } | 
 |  |  |             result.add(resultMap); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         //1.按综指绝对值排名 | 
 |  |  |         result.sort((o1, o2) -> { | 
 |  |  |             if (o1.get("compositeIndex") != null && o2.get("compositeIndex") != null) { | 
 |  |  |                 double compositeIndexAbs1 = Math.abs(Double.parseDouble(o1.get("compositeIndex").toString())); | 
 |  |  |                 double compositeIndexAbs2 = Math.abs(Double.parseDouble(o2.get("compositeIndex").toString())); | 
 |  |  |                 return compositeIndexAbs1 > compositeIndexAbs2 ? 1 : -1; | 
 |  |  |             } else if (o1.get("compositeIndex") == null && o2.get("compositeIndex") == null) { | 
 |  |  |                 return 0; | 
 |  |  |             } else if (o1.get("compositeIndex") == null) { | 
 |  |  |                 return -1; | 
 |  |  |             } else { | 
 |  |  |                 return 1; | 
 |  |  |             } | 
 |  |  |         }); | 
 |  |  |         //放入排名字段 | 
 |  |  |         for (int i = 0; i < result.size(); i++) { | 
 |  |  |             Map<String, Object> map = result.get(i); | 
 |  |  |             map.put("compositeIndexRank", i + 1); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         //2.按空气质量改善幅度(综指同比)排名 | 
 |  |  |         result.sort((o1, o2) -> { | 
 |  |  |             if (o1.get("compositeIndexYearOnYear") != null && o2.get("compositeIndexYearOnYear") != null) { | 
 |  |  |                 double compositeIndexYearOnYear1 = Double.parseDouble(o1.get("compositeIndexYearOnYear").toString().replace("%", "")); | 
 |  |  |                 double compositeIndexYearOnYear2 = Double.parseDouble(o2.get("compositeIndexYearOnYear").toString().replace("%", "")); | 
 |  |  |                 return compositeIndexYearOnYear1 > compositeIndexYearOnYear2 ? 1 : -1; | 
 |  |  |             } else if (o1.get("compositeIndexYearOnYear") == null && o2.get("compositeIndexYearOnYear") == null) { | 
 |  |  |                 return 0; | 
 |  |  |             } else if (o1.get("compositeIndexYearOnYear") == null) { | 
 |  |  |                 return -1; | 
 |  |  |             } else { | 
 |  |  |                 return 1; | 
 |  |  |             } | 
 |  |  |         }); | 
 |  |  |         //放入排名字段 | 
 |  |  |         for (int i = 0; i < result.size(); i++) { | 
 |  |  |             Map<String, Object> map = result.get(i); | 
 |  |  |             map.put("compositeIndexYearOnYearRank", i + 1); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         //3.按pm2.5浓度绝对值排名 | 
 |  |  |         result.sort((o1, o2) -> { | 
 |  |  |             if (o1.get("PM2_5") != null && o2.get("PM2_5") != null) { | 
 |  |  |                 double compositeIndexAbs1 = Math.abs(Double.parseDouble(o1.get("PM2_5").toString())); | 
 |  |  |                 double compositeIndexAbs2 = Math.abs(Double.parseDouble(o2.get("PM2_5").toString())); | 
 |  |  |                 return compositeIndexAbs1 > compositeIndexAbs2 ? 1 : -1; | 
 |  |  |             } else if (o1.get("PM2_5") == null && o2.get("PM2_5") == null) { | 
 |  |  |                 return 0; | 
 |  |  |             } else if (o1.get("PM2_5") == null) { | 
 |  |  |                 return -1; | 
 |  |  |             } else { | 
 |  |  |                 return 1; | 
 |  |  |             } | 
 |  |  |         }); | 
 |  |  |         //放入排名字段 | 
 |  |  |         for (int i = 0; i < result.size(); i++) { | 
 |  |  |             Map<String, Object> map = result.get(i); | 
 |  |  |             map.put("PM2_5Rank", i + 1); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         //4.按pm2.5改善幅度排名 | 
 |  |  |         result.sort((o1, o2) -> { | 
 |  |  |             if (o1.get("PM2_5YearOnYear") != null && o2.get("PM2_5YearOnYear") != null) { | 
 |  |  |                 double pm25YearOnYear1 = Double.parseDouble(o1.get("PM2_5YearOnYear").toString().replace("%", "")); | 
 |  |  |                 double pm25YearOnYear2 = Double.parseDouble(o2.get("PM2_5YearOnYear").toString().replace("%", "")); | 
 |  |  |                 return pm25YearOnYear1 > pm25YearOnYear2 ? 1 : -1; | 
 |  |  |             } else if (o1.get("PM2_5YearOnYear") == null && o2.get("PM2_5YearOnYear") == null) { | 
 |  |  |                 return 0; | 
 |  |  |             } else if (o1.get("PM2_5YearOnYear") == null) { | 
 |  |  |                 return -1; | 
 |  |  |             } else { | 
 |  |  |                 return 1; | 
 |  |  |             } | 
 |  |  |         }); | 
 |  |  |         //放入排名字段 | 
 |  |  |         for (int i = 0; i < result.size(); i++) { | 
 |  |  |             Map<String, Object> map = result.get(i); | 
 |  |  |             map.put("PM2_5YearOnYearRank", i + 1); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         //加权得分计算 | 
 |  |  |         for (Map<String, Object> map : result) { | 
 |  |  |             int compositeIndexRank = Integer.parseInt(map.get("compositeIndexRank").toString()); | 
 |  |  |             int compositeIndexYearOnYearRank = Integer.parseInt(map.get("compositeIndexYearOnYearRank").toString()); | 
 |  |  |             int pm25Rank = Integer.parseInt(map.get("PM2_5Rank").toString()); | 
 |  |  |             int pm25YearOnYearRank = Integer.parseInt(map.get("PM2_5YearOnYearRank").toString()); | 
 |  |  |  | 
 |  |  |             double score = compositeIndexRank * 0.2 + compositeIndexYearOnYearRank * 0.3 + pm25Rank * 0.2 + pm25YearOnYearRank * 0.3; | 
 |  |  |             String format = String.format("%.1f", score); | 
 |  |  |             map.put("score", Double.parseDouble(format)); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         //最终排序 | 
 |  |  |         result.sort((o1, o2) -> { | 
 |  |  |             double score1 = Double.parseDouble(o1.get("score").toString()); | 
 |  |  |             double score2 = Double.parseDouble(o2.get("score").toString()); | 
 |  |  |             if (score1 > score2) { | 
 |  |  |                 return 1; | 
 |  |  |             } else if (score1 < score2) { | 
 |  |  |                 return -1; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             //排名位次数值相加得分相同的情况下,优先按照PM2.5月均浓度值、改善幅度确定排名先后,平均浓度值低、下降幅度大的排名靠前。 | 
 |  |  |             int pm251 = Integer.parseInt(o1.get("PM2_5").toString()); | 
 |  |  |             int pm252 = Integer.parseInt(o2.get("PM2_5").toString()); | 
 |  |  |  | 
 |  |  |             if (pm251 > pm252) { | 
 |  |  |                 return 1; | 
 |  |  |             } else if (pm251 < pm252) { | 
 |  |  |                 return -1; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             //pm2.5浓度相同,再按照改善幅度排名 | 
 |  |  |             double pm25YearOnYear1 = Double.parseDouble(o1.get("PM2_5YearOnYearRank").toString().replace("%", "")); | 
 |  |  |             double pm25YearOnYear2 = Double.parseDouble(o2.get("PM2_5YearOnYearRank").toString().replace("%", "")); | 
 |  |  |             return pm25YearOnYear1 > pm25YearOnYear2 ? 1 : -1; | 
 |  |  |         }); | 
 |  |  |         //放入最终排名字段 | 
 |  |  |         for (int i = 0; i < result.size(); i++) { | 
 |  |  |             Map<String, Object> map = result.get(i); | 
 |  |  |             map.put("resultRank", i + 1); | 
 |  |  |         } | 
 |  |  |         for (Map<String, Object> map : result) { | 
 |  |  |             for (Map.Entry<String, Object> entry : map.entrySet()) { | 
 |  |  |                 if (entry.getValue() == null) { | 
 |  |  |                     map.put(entry.getKey(), ""); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         return result; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * @param list     所有县市区1-x月份数据 | 
 |  |  |      * @param areasMap 所有县市区信息 areaCode--areaName | 
 |  |  |      * @description 1-x月份累计空气质量综指和pm2.5排名报表 | 
 |  |  |      */ | 
 |  |  |     private List<Map<String, Object>> cumulativeAirQualityRankingReport(List<CityAqiMonthly> list, Map<Integer, String> areasMap) { | 
 |  |  |         List<Map<String, Object>> result = new ArrayList<>(); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         Map<Integer, CityAqiMonthly> dataMap = new HashMap<>(); | 
 |  |  |         for (CityAqiMonthly cityAqiMonthly : list) { | 
 |  |  |             dataMap.put(cityAqiMonthly.getCityCode(), cityAqiMonthly); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         for (Map.Entry<Integer, String> entry : areasMap.entrySet()) { | 
 |  |  |             Map<String, Object> resultMap = new HashMap<>(); | 
 |  |  |             Integer regionCode = entry.getKey(); | 
 |  |  |             String areaName = entry.getValue(); | 
 |  |  |             resultMap.put("areaName", areaName); | 
 |  |  |  | 
 |  |  |             //本期综指 | 
 |  |  |             resultMap.put("compositeIndex", null); | 
 |  |  |             //上期综指 | 
 |  |  |             resultMap.put("compositeIndexLast", null); | 
 |  |  |             //综指同比 | 
 |  |  |             resultMap.put("compositeIndexYearOnYear", null); | 
 |  |  |             //本期PM2.5 | 
 |  |  |             resultMap.put("PM2_5", null); | 
 |  |  |             //上期PM2.5 | 
 |  |  |             resultMap.put("PM2_5Last", null); | 
 |  |  |             //PM2.5同比 | 
 |  |  |             resultMap.put("PM2_5YearOnYear", null); | 
 |  |  |             if (dataMap.get(regionCode) != null) { | 
 |  |  |                 Map<String, Object> valueMap = JSONObject.parseObject(dataMap.get(regionCode).getValue(), Map.class); | 
 |  |  |  | 
 |  |  |                 //综指本期,上期,同比 | 
 |  |  |                 resultMap.put("compositeIndex", valueMap.get("compositeIndex")); | 
 |  |  |                 resultMap.put("compositeIndexLast", valueMap.get("compositeIndex_last")); | 
 |  |  |                 resultMap.put("compositeIndexYearOnYear", valueMap.get("compositeIndex_yearOnYear")); | 
 |  |  |  | 
 |  |  |                 //PM2.5本期,上期,同比 | 
 |  |  |                 resultMap.put("PM2_5", valueMap.get("PM2_5")); | 
 |  |  |                 resultMap.put("PM2_5Last", valueMap.get("PM2_5_last")); | 
 |  |  |                 resultMap.put("PM2_5YearOnYear", valueMap.get("PM2_5_yearOnYear")); | 
 |  |  |             } | 
 |  |  |             result.add(resultMap); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         //按pm2.5同比排名 | 
 |  |  |         result.sort((o1, o2) -> { | 
 |  |  |             if (o1.get("PM2_5YearOnYear") != null && o2.get("PM2_5YearOnYear") != null) { | 
 |  |  |                 double pm25YearOnYear1 = Double.parseDouble(o1.get("PM2_5YearOnYear").toString().replace("%", "")); | 
 |  |  |                 double pm25YearOnYear2 = Double.parseDouble(o2.get("PM2_5YearOnYear").toString().replace("%", "")); | 
 |  |  |                 return pm25YearOnYear1 > pm25YearOnYear2 ? 1 : -1; | 
 |  |  |             } else if (o1.get("PM2_5YearOnYear") == null && o2.get("PM2_5YearOnYear") == null) { | 
 |  |  |                 return 0; | 
 |  |  |             } else if (o1.get("PM2_5YearOnYear") == null) { | 
 |  |  |                 return -1; | 
 |  |  |             } else { | 
 |  |  |                 return 1; | 
 |  |  |             } | 
 |  |  |         }); | 
 |  |  |         //放入排名字段 | 
 |  |  |         for (int i = 0; i < result.size(); i++) { | 
 |  |  |             Map<String, Object> map = result.get(i); | 
 |  |  |             map.put("PM2_5YearOnYearRank", i + 1); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         //按综指变化幅度排名 | 
 |  |  |         result.sort((o1, o2) -> { | 
 |  |  |             if (o1.get("compositeIndexYearOnYear") != null && o2.get("compositeIndexYearOnYear") != null) { | 
 |  |  |                 double compositeIndexYearOnYear1 = Double.parseDouble(o1.get("compositeIndexYearOnYear").toString().replace("%", "")); | 
 |  |  |                 double compositeIndexYearOnYear2 = Double.parseDouble(o2.get("compositeIndexYearOnYear").toString().replace("%", "")); | 
 |  |  |                 return compositeIndexYearOnYear1 > compositeIndexYearOnYear2 ? 1 : -1; | 
 |  |  |             } else if (o1.get("compositeIndexYearOnYear") == null && o2.get("compositeIndexYearOnYear") == null) { | 
 |  |  |                 return 0; | 
 |  |  |             } else if (o1.get("compositeIndexYearOnYear") == null) { | 
 |  |  |                 return -1; | 
 |  |  |             } else { | 
 |  |  |                 return 1; | 
 |  |  |             } | 
 |  |  |         }); | 
 |  |  |         //放入排名字段 | 
 |  |  |         for (int i = 0; i < result.size(); i++) { | 
 |  |  |             Map<String, Object> map = result.get(i); | 
 |  |  |             map.put("compositeIndexYearOnYearRank", i + 1); | 
 |  |  |         } | 
 |  |  |         for (Map<String, Object> map : result) { | 
 |  |  |             for (Map.Entry<String, Object> entry : map.entrySet()) { | 
 |  |  |                 if (entry.getValue() == null) { | 
 |  |  |                     map.put(entry.getKey(), ""); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         return result; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * @param time      本期时间 | 
 |  |  |      * @param areaCodes 所有县市区code集合 | 
 |  |  |      * @param areaData  所有县市区本期数据 | 
 |  |  |      * @param areasMap  所有县市区信息 | 
 |  |  |      * @description 本期五因子(PM10,SO2,NO2,CO,O3)对比报表 | 
 |  |  |      */ | 
 |  |  |     private List<Map<String, Object>> currentFiveSensorsContrastReport(Date time, List<Integer> areaCodes, List<CityAqiMonthly> areaData, Map<Integer, String> areasMap) { | 
 |  |  |         List<Map<String, Object>> result = new ArrayList<>(); | 
 |  |  |  | 
 |  |  |         //本期数据 | 
 |  |  |         Map<Integer, CityAqiMonthly> dataCurrent = new HashMap<>(); | 
 |  |  |         for (CityAqiMonthly cityAqiMonthly : areaData) { | 
 |  |  |             dataCurrent.put(cityAqiMonthly.getCityCode(), cityAqiMonthly); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         //获取上年同期数据 | 
 |  |  |         QueryWrapper<CityAqiMonthly> queryWrapper = new QueryWrapper<>(); | 
 |  |  |         queryWrapper.clear(); | 
 |  |  |         queryWrapper.select("city_code", "value") | 
 |  |  |                 .eq("time", DateUtils.addYears(time, -1)) | 
 |  |  |                 .in("city_code", areaCodes); | 
 |  |  |         List<CityAqiMonthly> monthlyDataLast = cityAqiMonthlyMapper.selectList(queryWrapper); | 
 |  |  |         Map<Integer, CityAqiMonthly> dataLast = new HashMap<>(); | 
 |  |  |         for (CityAqiMonthly cityAqiMonthly : monthlyDataLast) { | 
 |  |  |             dataLast.put(cityAqiMonthly.getCityCode(), cityAqiMonthly); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         //报表中需要对比的五因子 | 
 |  |  |         List<String> sensors = Arrays.asList("PM10", "SO2", "NO2", "CO", "O3"); | 
 |  |  |         for (Map.Entry<Integer, String> entry : areasMap.entrySet()) { | 
 |  |  |             Map<String, Object> resultMap = new HashMap<>(); | 
 |  |  |             String areaName = entry.getValue(); | 
 |  |  |             Integer regionCode = entry.getKey(); | 
 |  |  |             resultMap.put("areaName", areaName); | 
 |  |  |  | 
 |  |  |             for (String sensor : sensors) { | 
 |  |  |                 resultMap.put(sensor, null); | 
 |  |  |                 resultMap.put(sensor + "YearOnYear", null); | 
 |  |  |                 if (dataCurrent.get(regionCode) != null) { | 
 |  |  |                     Map<String, Object> currentValue = JSONObject.parseObject(dataCurrent.get(regionCode).getValue(), Map.class); | 
 |  |  |                     resultMap.put(sensor, currentValue.get(sensor)); | 
 |  |  |                     resultMap.put(sensor + "YearOnYear", currentValue.get(sensor + "_yearOnYear")); | 
 |  |  |                 } | 
 |  |  |  | 
 |  |  |                 //上年同期五因子浓度 | 
 |  |  |                 resultMap.put(sensor + "Last", null); | 
 |  |  |                 if (dataLast.get(regionCode) != null) { | 
 |  |  |                     Map<String, Object> lastValue = JSONObject.parseObject(dataLast.get(regionCode).getValue(), Map.class); | 
 |  |  |                     //上年同期五因子浓度 | 
 |  |  |                     resultMap.put(sensor + "Last", lastValue.get(sensor)); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |             result.add(resultMap); | 
 |  |  |         } | 
 |  |  |         for (Map<String, Object> map : result) { | 
 |  |  |             for (Map.Entry<String, Object> entry : map.entrySet()) { | 
 |  |  |                 if (entry.getValue() == null) { | 
 |  |  |                     map.put(entry.getKey(), ""); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |         return result; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * @param areaData 所有县市区1-x月份数据,其中包含上年同期五因子浓度值 | 
 |  |  |      * @param areasMap 所有县市区信息 | 
 |  |  |      * @description 1-x月份五因子(PM10,SO2,NO2,CO,O3)对比报表 | 
 |  |  |      */ | 
 |  |  |     private List<Map<String, Object>> cumulativeFiveSensorsContrastReport(List<CityAqiMonthly> areaData, Map<Integer, String> areasMap) { | 
 |  |  |         List<Map<String, Object>> result = new ArrayList<>(); | 
 |  |  |  | 
 |  |  |         //本期数据 | 
 |  |  |         Map<Integer, CityAqiMonthly> dataCurrent = new HashMap<>(); | 
 |  |  |         for (CityAqiMonthly cityAqiMonthly : areaData) { | 
 |  |  |             dataCurrent.put(cityAqiMonthly.getCityCode(), cityAqiMonthly); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         List<String> sensors = Arrays.asList("PM10", "SO2", "NO2", "CO", "O3"); | 
 |  |  |         for (Map.Entry<Integer, String> entry : areasMap.entrySet()) { | 
 |  |  |             Map<String, Object> resultMap = new HashMap<>(); | 
 |  |  |             String areaName = entry.getValue(); | 
 |  |  |             Integer regionCode = entry.getKey(); | 
 |  |  |             resultMap.put("areaName", areaName); | 
 |  |  |             for (String sensor : sensors) { | 
 |  |  |                 resultMap.put(sensor, null); | 
 |  |  |                 resultMap.put(sensor + "Last", null); | 
 |  |  |                 resultMap.put(sensor + "YearOnYear", null); | 
 |  |  |                 if (dataCurrent.get(regionCode) != null) { | 
 |  |  |                     Map<String, Object> valueMap = JSONObject.parseObject(dataCurrent.get(regionCode).getValue(), Map.class); | 
 |  |  |                     resultMap.put(sensor, valueMap.get(sensor)); | 
 |  |  |                     resultMap.put(sensor + "Last", valueMap.get(sensor + "_last")); | 
 |  |  |                     resultMap.put(sensor + "YearOnYear", valueMap.get(sensor + "_yearOnYear")); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |             result.add(resultMap); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         for (Map<String, Object> map : result) { | 
 |  |  |             for (Map.Entry<String, Object> entry : map.entrySet()) { | 
 |  |  |                 if (entry.getValue() == null) { | 
 |  |  |                     map.put(entry.getKey(), ""); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |         return result; | 
 |  |  |     } | 
 |  |  | } |