package com.moral.api.service.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.moral.api.entity.CityAqi; import com.moral.api.entity.CityAqiDaily; import com.moral.api.entity.Forecast; import com.moral.api.entity.Organization; import com.moral.api.entity.SysArea; import com.moral.api.mapper.CityAqiMapper; import com.moral.api.mapper.ForecastMapper; import com.moral.api.service.CityAqiDailyService; import com.moral.api.service.CityAqiService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.moral.api.service.OrganizationService; import com.moral.api.service.SysAreaService; import com.moral.constant.RedisConstants; import com.moral.util.AQIUtils; import com.moral.util.AmendUtils; 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.util.*; import java.util.stream.DoubleStream; /** *

* 城市aqi实测小时数据表 服务实现类 *

* * @author moral * @since 2021-09-28 */ @Service public class CityAqiServiceImpl extends ServiceImpl implements CityAqiService { @Autowired private CityAqiMapper cityAqiMapper; @Autowired private ForecastMapper forecastMapper; @Autowired private RedisTemplate redisTemplate; @Autowired private OrganizationService organizationService; @Autowired private SysAreaService sysAreaService; @Autowired private CityAqiDailyService cityAqiDailyService; @Override public List> measuredCompareForecastOfO3(Map params) { String regionCode = params.get("regionCode").toString(); String time = params.get("time").toString(); //预测数据 QueryWrapper forecastQueryWrapper = new QueryWrapper<>(); forecastQueryWrapper.select("time", "value") .eq("city_code", regionCode) .likeRight("time", time); List> forecastData = forecastMapper.selectMaps(forecastQueryWrapper); //实测数据 QueryWrapper cityAqiQueryWrapper = new QueryWrapper<>(); cityAqiQueryWrapper.select("time", "value") .eq("city_code", regionCode) .likeRight("time", time); List> measuredData = cityAqiMapper.selectMaps(cityAqiQueryWrapper); List> result = new ArrayList<>(); for (int i = 0; i < 48; i++) { Map map = new HashMap<>(); if (i % 2 == 0) { map.put("type", "预测"); Date d = DateUtils.addHours(DateUtils.getDate(time), i / 2); map.put("time", DateUtils.dateToDateString(d, DateUtils.yyyy_MM_dd_HH_EN)); for (Map forecastDatum : forecastData) { Date date = (Date) forecastDatum.get("time"); String value = forecastDatum.get("value").toString(); Map data = JSONObject.parseObject(value, Map.class); Object o3 = data.get("o3"); if (i == DateUtils.getHour(date) * 2) { if (!ObjectUtils.isEmpty(o3)) { map.put("O3", o3); } } } } else { map.put("type", "实测"); Date d = DateUtils.addHours(DateUtils.getDate(time), (i - 1) / 2); map.put("time", DateUtils.dateToDateString(d, DateUtils.yyyy_MM_dd_HH_EN)); for (Map measuredDatum : measuredData) { Date date = (Date) measuredDatum.get("time"); String value = measuredDatum.get("value").toString(); Map data = JSONObject.parseObject(value, Map.class); Object o3 = data.get("o3"); if (i == (DateUtils.getHour(date) * 2 + 1)) { if (!ObjectUtils.isEmpty(o3)) { map.put("O3", o3); } } } } result.add(map); } return result; } @Override public Map queryCityAqiByRegionCode(Integer regionCode) { Map value = (Map) redisTemplate.opsForHash().get(RedisConstants.CITY_AQI, String.valueOf(regionCode)); if (value == null) value = queryCityAqiByRegionCodeFromDB(regionCode); //根据AQI计算污染等级 if (value == null || value.get("aqi") == null) return null; Integer aqi = Integer.parseInt(value.get("aqi").toString()); String category = AQIUtils.classOfPollutionByAqi(aqi); value.put("category", category); return value; } @Override public Map query24HoursAqiByRegionCode(Integer regionCode) { //查询最新一条数据,用于获取最新的时间 QueryWrapper lastDataWrapper = new QueryWrapper<>(); lastDataWrapper.eq("city_code", regionCode); lastDataWrapper.orderByDesc("time"); lastDataWrapper.last(true, "limit 1"); CityAqi cityAqi = cityAqiMapper.selectOne(lastDataWrapper); //算出前24小时的时间点 Date endDate = cityAqi.getTime(); Date startDate = DateUtils.addHours(endDate, -23); //查询数据 QueryWrapper wrapper = new QueryWrapper<>(); wrapper.between("time", startDate, endDate); wrapper.eq("city_code", regionCode); List cityAqis = cityAqiMapper.selectList(wrapper); //如果数据不足24小时则补全 if (cityAqis.size() != 24) { Map dateCityAqiMap = new HashMap<>(); cityAqis.forEach(value -> dateCityAqiMap.put(value.getTime(), value)); for (int i = 0; i < 24; i++) { Date date = DateUtils.addHours(startDate, i); CityAqi cityAqi1 = dateCityAqiMap.get(date); if (cityAqi1 == null) { CityAqi newCityAqi = new CityAqi(); newCityAqi.setTime(date); cityAqis.add(newCityAqi); } } //按照时间进行排序 cityAqis.sort(Comparator.comparing(CityAqi::getTime)); } //封装返回数据,map的key为HH:mm格式的时间,value为aqi的数值 Map result = new LinkedHashMap<>(); for (CityAqi aqi : cityAqis) { String key = DateUtils.dateToDateString(aqi.getTime(), "HH:mm"); String allDataJson = aqi.getValue(); if (allDataJson == null) { result.put(key, ""); continue; } Map allDataMap = JSON.parseObject(allDataJson, Map.class); Object aqiData = allDataMap.get("aqi"); if (aqiData == null) result.put(key, ""); else result.put(key, aqiData); } return result; } /** * @Description: 从数据库查询数据 * @Param: [regionCode] * @return: java.util.Map * @Author: 陈凯裕 * @Date: 2021/10/28 */ private Map queryCityAqiByRegionCodeFromDB(Integer regionCode) { QueryWrapper wrapper = new QueryWrapper(); wrapper.eq("city_code", regionCode); wrapper.orderByDesc("time"); wrapper.last(true, "limit 1"); CityAqi cityAqi = cityAqiMapper.selectOne(wrapper); if (cityAqi == null) return null; String value = cityAqi.getValue(); redisTemplate.opsForHash().put(RedisConstants.CITY_AQI, regionCode, value); return JSON.parseObject(value, Map.class); } @Override public Map provincialRanking(Integer organizationId) { //结果集 Map result = new HashMap<>(); Date now = new Date(); //昨日 Date yesterday = DateUtils.dataToTimeStampTime(DateUtils.getDateOfDay(now, -1), DateUtils.yyyy_MM_dd_EN); String dateString = DateUtils.dateToDateString(yesterday, DateUtils.yyyy_MM_dd_HH_mm_ss_EN); //获取省,市code Organization organization = organizationService.getById(organizationId); Integer provinceCode = organization.getProvinceCode(); Integer cityCode = organization.getCityCode(); //获取省内所有city_code QueryWrapper wrapper = new QueryWrapper<>(); wrapper.select("area_code").eq("parent_code", provinceCode); List cityCodes = sysAreaService.listObjs(wrapper); List> ranks = new ArrayList<>(); for (Object code : cityCodes) { Map rankMap = new HashMap<>(); rankMap.put("cityCode", code); QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.select("value").eq("city_code", code).eq("time", dateString); //1.昨日数据 CityAqiDaily one = cityAqiDailyService.getOne(queryWrapper); if (!ObjectUtils.isEmpty(one)) { String value = one.getValue(); Map valueMap = JSONObject.parseObject(value, Map.class); rankMap.put("aqi", valueMap.get("aqi")); } //2.本月累计综合指数计算,截止到昨日 queryWrapper.clear(); //开始时间:本月1号,结束时间:昨日 Date start = DateUtils.addMonths(DateUtils.getFirstDayOfLastMonth(), 1); queryWrapper.select("value").eq("city_code", code).ge("time", start).le("time", yesterday); List listMonth = cityAqiDailyService.list(queryWrapper); OptionalDouble averageMonth = listMonth.parallelStream().flatMapToDouble(v -> { Map dataValue = JSONObject.parseObject(v.getValue(), Map.class); Double compositeIndex = Double.parseDouble(dataValue.get("compositeIndex").toString()); return DoubleStream.of(compositeIndex); }).average(); if (averageMonth.isPresent()) { //银行家算法修约 double compositeIndexAvgMonth = AmendUtils.sciCal(averageMonth.getAsDouble(), 2); rankMap.put("compositeIndexMonth", compositeIndexAvgMonth); } //3.本年累计综合指数计算,截止到昨日 queryWrapper.clear(); //开始时间:本年1.1号,结束时间:昨日 String yearStart = DateUtils.dateToDateString(now, DateUtils.yyyy); queryWrapper.select("value").eq("city_code", code).ge("time", yearStart).le("time", yesterday); List listYear = cityAqiDailyService.list(queryWrapper); OptionalDouble averageYear = listYear.parallelStream().flatMapToDouble(v -> { Map dataValue = JSONObject.parseObject(v.getValue(), Map.class); Double compositeIndex = Double.parseDouble(dataValue.get("compositeIndex").toString()); return DoubleStream.of(compositeIndex); }).average(); if (averageYear.isPresent()) { //银行家算法修约 double compositeIndexAvgYear = AmendUtils.sciCal(averageYear.getAsDouble(), 2); rankMap.put("compositeIndexYear", compositeIndexAvgYear); } ranks.add(rankMap); } //日排名,按aqi排序 ranks.removeIf(o -> o.get("aqi") == null); sortByField(ranks, "aqi"); //日排名结果 Map dayMap = rankByField(ranks, cityCode, "aqi", cityCodes.size()); dayMap.put("aqi", dayMap.remove("value")); result.put("day", dayMap); //月排名,按累计综指排 ranks.removeIf(o -> o.get("compositeIndexMonth") == null); sortByField(ranks, "compositeIndexMonth"); //月排名结果 Map monthMap = rankByField(ranks, cityCode, "compositeIndexMonth", cityCodes.size()); monthMap.put("compositeIndex", monthMap.remove("value")); result.put("month", monthMap); //年排名,按累计综指排 sortByField(ranks, "compositeIndexYear"); //年排名结果 sortByField(ranks, "compositeIndexYear"); Map yearMap = rankByField(ranks, cityCode, "compositeIndexYear", cityCodes.size()); yearMap.put("compositeIndex", yearMap.remove("value")); result.put("year", yearMap); return result; } //按某字段排序 private void sortByField(List> list, String sortField) { list.sort((o1, o2) -> { double v1 = Double.parseDouble(o1.get(sortField).toString()); double v2 = Double.parseDouble(o2.get(sortField).toString()); if (v1 > v2) { return -1; } else if (v1 < v2) { return 1; } return 0; }); } //排名 private Map rankByField(List> list, Integer cityCode, String rankField, Integer size) { Map result = new HashMap<>(); for (int i = 0; i < list.size(); i++) { Map map = list.get(i); if (cityCode == (int) map.get("cityCode")) { int rank = i + 1; result.put("rank", rank + "/" + size); Object value = map.get(rankField); result.put("value", value); break; } } return result; } }