package com.moral.api.service.impl; 
 | 
  
 | 
import com.alibaba.fastjson.JSONObject; 
 | 
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 
 | 
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; 
 | 
import com.moral.api.entity.CityAqiDaily; 
 | 
import com.moral.api.entity.CityAqiMonthly; 
 | 
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 com.moral.constant.Constants; 
 | 
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.stereotype.Service; 
 | 
import org.springframework.util.ObjectUtils; 
 | 
  
 | 
import java.text.DecimalFormat; 
 | 
import java.util.ArrayList; 
 | 
import java.util.Arrays; 
 | 
import java.util.Date; 
 | 
import java.util.HashMap; 
 | 
import java.util.List; 
 | 
import java.util.Map; 
 | 
import java.util.OptionalDouble; 
 | 
import java.util.stream.Collectors; 
 | 
import java.util.stream.DoubleStream; 
 | 
  
 | 
/** 
 | 
 * <p> 
 | 
 * 城市aqi月数据表 服务实现类 
 | 
 * </p> 
 | 
 * 
 | 
 * @author moral 
 | 
 * @since 2021-11-04 
 | 
 */ 
 | 
@Service 
 | 
public class CityAqiMonthlyServiceImpl extends ServiceImpl<CityAqiMonthlyMapper, CityAqiMonthly> implements CityAqiMonthlyService { 
 | 
  
 | 
    @Autowired 
 | 
    private CityAqiMonthlyMapper cityAqiMonthlyMapper; 
 | 
  
 | 
    @Autowired 
 | 
    private CityAqiDailyService cityAqiDailyService; 
 | 
  
 | 
    @Override 
 | 
    public void insertCityAqiMonthly() { 
 | 
        //需要均值计算的因子 
 | 
        List<String> sensors = Arrays.asList("PM2_5", "PM10", "SO2", "NO2"); 
 | 
  
 | 
        //开始时间,上月1号 
 | 
        Date start = DateUtils.getFirstDayOfLastMonth(); 
 | 
        //上上月 
 | 
        Date lastLastMonth = DateUtils.addMonths(start, -1); 
 | 
        //结束时间,本月1号 
 | 
        Date end = DateUtils.addMonths(start, 1); 
 | 
  
 | 
        //如果是1号,先删除上月数据再统计 
 | 
        //不是1号,统计的是本月累计值,先删除本月数据 
 | 
        int day = DateUtils.getDay(new Date()); 
 | 
        UpdateWrapper<CityAqiMonthly> cityAqiMonthlyUpdateWrapper = new UpdateWrapper<>(); 
 | 
        if (day == 1) { 
 | 
            cityAqiMonthlyUpdateWrapper.eq("time", start); 
 | 
        } else { 
 | 
            start = end; 
 | 
            end = DateUtils.addMonths(start, 1); 
 | 
            lastLastMonth = DateUtils.addMonths(start, -1); 
 | 
            cityAqiMonthlyUpdateWrapper.eq("time", start); 
 | 
        } 
 | 
        cityAqiMonthlyMapper.delete(cityAqiMonthlyUpdateWrapper); 
 | 
  
 | 
  
 | 
        //获取所有城市aqi小时数据 
 | 
        QueryWrapper<CityAqiDaily> wrapper = new QueryWrapper<>(); 
 | 
        wrapper.select("city_code", "time", "value") 
 | 
                .ge("time", start) 
 | 
                .lt("time", end); 
 | 
        List<Map<String, Object>> monthlyData = cityAqiDailyService.listMaps(wrapper); 
 | 
  
 | 
        if (monthlyData.size() == 0) { 
 | 
            return; 
 | 
        } 
 | 
        //按city_code分组 
 | 
        Map<Integer, List<Map<String, Object>>> data = monthlyData.stream() 
 | 
                .collect(Collectors.groupingBy(o ->Integer.parseInt(o.get("city_code").toString()) )); 
 | 
  
 | 
        //获取上月数据,本月综指同上月对比 
 | 
        QueryWrapper<CityAqiMonthly> queryWrapper = new QueryWrapper<>(); 
 | 
        queryWrapper.select("city_code", "value") 
 | 
                .eq("time", lastLastMonth); 
 | 
        //获取上月数据 
 | 
        List<CityAqiMonthly> lastCityAqiMonthlyList = cityAqiMonthlyMapper.selectList(queryWrapper); 
 | 
        Map<Integer, CityAqiMonthly> lastMonthData = new HashMap<>(); 
 | 
        for (CityAqiMonthly cityAqiMonthly : lastCityAqiMonthlyList) { 
 | 
            lastMonthData.put(cityAqiMonthly.getCityCode(), cityAqiMonthly); 
 | 
        } 
 | 
  
 | 
  
 | 
        //获取去年本月数据 
 | 
        Date thisMonthOfLastYear = DateUtils.addYears(start, -1); 
 | 
        queryWrapper.clear(); 
 | 
        queryWrapper.select("city_code", "value") 
 | 
                .eq("time", thisMonthOfLastYear); 
 | 
        List<CityAqiMonthly> thisMonthOfLastYearList = cityAqiMonthlyMapper.selectList(queryWrapper); 
 | 
        Map<Integer, CityAqiMonthly> thisMonthOfLastYearData = new HashMap<>(); 
 | 
        for (CityAqiMonthly cityAqiMonthly : thisMonthOfLastYearList) { 
 | 
            thisMonthOfLastYearData.put(cityAqiMonthly.getCityCode(), cityAqiMonthly); 
 | 
        } 
 | 
  
 | 
  
 | 
        List<CityAqiMonthly> cityAqiMonthlyList = new ArrayList<>(); 
 | 
  
 | 
        Date finalStart = start; 
 | 
        data.forEach((cityCode, value) -> { 
 | 
            CityAqiMonthly cityAqiMonthly = new CityAqiMonthly(); 
 | 
            Map<String, Object> jsonMap = new HashMap<>(); 
 | 
            cityAqiMonthly.setCityCode(cityCode); 
 | 
            cityAqiMonthly.setTime(finalStart); 
 | 
  
 | 
            Map<String, Object> params = new HashMap<>(); 
 | 
            List<Map<String, Object>> temp = new ArrayList<>(); 
 | 
            for (Map<String, Object> map : value) { 
 | 
                Map<String, Object> sensorsValue = JSONObject.parseObject(map.get("value").toString(), Map.class); 
 | 
                Map<String, Object> tempMap = new HashMap<>(); 
 | 
                tempMap.put(Constants.SENSOR_CODE_CO, sensorsValue.get("CO")); 
 | 
                tempMap.put(Constants.SENSOR_CODE_O3, sensorsValue.get("O3")); 
 | 
                Map<String, Object> hashMap = new HashMap<>(); 
 | 
                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 = value.stream().flatMapToDouble(v -> { 
 | 
                    Map<String, Object> dataValue = JSONObject.parseObject((String) v.get("value"), 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)); 
 | 
                } 
 | 
            }); 
 | 
  
 | 
            //本月月综指计算 
 | 
            Double compositeIndex = ComprehensiveIndexUtils.dailyData(jsonMap); 
 | 
            jsonMap.put("compositeIndex", compositeIndex); 
 | 
  
 | 
            //本月综指同上月对比(综合指数环比) 
 | 
            CityAqiMonthly lastCityAqiMonthly = lastMonthData.get(cityCode); 
 | 
            if (lastCityAqiMonthly != null) { 
 | 
                Map<String, Object> map = JSONObject.parseObject(lastCityAqiMonthly.getValue(), Map.class); 
 | 
                double lastCompositeIndex = Double.parseDouble(map.get("compositeIndex").toString()); 
 | 
                DecimalFormat decimalFormat = new DecimalFormat("0.00%"); 
 | 
                String format = decimalFormat.format((compositeIndex - lastCompositeIndex) / lastCompositeIndex); 
 | 
                jsonMap.put("monthContrast", format); 
 | 
            } 
 | 
  
 | 
            //获取去年本月数据,用于计算同比 
 | 
            CityAqiMonthly thisMonthOfLastYears = thisMonthOfLastYearData.get(cityCode); 
 | 
  
 | 
            //各因子同比计算 
 | 
            Map<String, Object> yearOnYearValue = yearOnYearOfSensor(thisMonthOfLastYears, jsonMap); 
 | 
            if (yearOnYearValue != null) { 
 | 
                jsonMap.putAll(yearOnYearValue); 
 | 
            } 
 | 
  
 | 
            cityAqiMonthly.setValue(JSONObject.toJSONString(jsonMap)); 
 | 
            cityAqiMonthlyList.add(cityAqiMonthly); 
 | 
        }); 
 | 
        cityAqiMonthlyMapper.insertCityAqiMonthly(cityAqiMonthlyList); 
 | 
    } 
 | 
  
 | 
  
 | 
    /** 
 | 
     * @param thisMonthOfLastYearData 去年本月数据 
 | 
     * @param currentData             当前月该数据 
 | 
     */ 
 | 
    private Map<String, Object> yearOnYearOfSensor(CityAqiMonthly thisMonthOfLastYearData, Map<String, Object> currentData) { 
 | 
        Map<String, Object> result = null; 
 | 
        //需要计算同比的因子 
 | 
        List<String> sensors = Arrays.asList("PM2_5", "PM10", "SO2", "NO2", "CO", "O3", "compositeIndex"); 
 | 
        if (thisMonthOfLastYearData != null) { 
 | 
            result = new HashMap<>(); 
 | 
            Map<String, Object> map = JSONObject.parseObject(thisMonthOfLastYearData.getValue(), Map.class); 
 | 
            for (String sensor : sensors) { 
 | 
                //去年本月该因子值 
 | 
                double thisMonthOfLeastYearValue = Double.parseDouble(map.get(sensor).toString()); 
 | 
                //当前该因子值 
 | 
                double currentValue = Double.parseDouble(currentData.get(sensor).toString()); 
 | 
                DecimalFormat decimalFormat = new DecimalFormat("0.00%"); 
 | 
                String format = decimalFormat.format((currentValue - thisMonthOfLeastYearValue) / thisMonthOfLeastYearValue); 
 | 
                result.put(sensor + "_yearOnYear", format); 
 | 
            } 
 | 
        } 
 | 
        return result; 
 | 
    } 
 | 
} 
 |