package com.moral.api.service.impl; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.moral.api.entity.CityAqi; import com.moral.api.entity.CityConfigWeatherForecast; import com.moral.api.entity.CityWeather; import com.moral.api.entity.CityWeatherForecast; import com.moral.api.entity.Forecast; import com.moral.api.mapper.ForecastMapper; import com.moral.api.service.CityAqiService; import com.moral.api.service.CityConfigWeatherForecastService; import com.moral.api.service.CityWeatherForecastService; import com.moral.api.service.CityWeatherService; import com.moral.api.service.ForecastService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.moral.constant.Constants; import com.moral.util.AmendUtils; import com.moral.util.DateUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.ObjectUtils; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.OptionalDouble; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.DoubleStream; import java.util.stream.Stream; /** *

* 预测小时数据 服务实现类 *

* * @author moral * @since 2021-12-31 */ @Service public class ForecastServiceImpl extends ServiceImpl implements ForecastService { @Autowired private CityWeatherForecastService cityWeatherForecastService; @Autowired private CityConfigWeatherForecastService cityConfigWeatherForecastService; @Autowired private CityWeatherService cityWeatherService; @Autowired private CityAqiService cityAqiService; @Autowired private ForecastMapper forecastMapper; private static final Map weatherScore = new HashMap<>(); static { weatherScore.put("晴", 100); weatherScore.put("雾", 90); weatherScore.put("多云", 80); weatherScore.put("霾", 70); weatherScore.put("阴", 60); weatherScore.put("扬沙", 60); weatherScore.put("浮尘", 60); weatherScore.put("阵雨", 45); weatherScore.put("雷阵雨", 40); weatherScore.put("雷阵雨转小雨", 30); weatherScore.put("阵雨转小雨", 30); weatherScore.put("小雨", 20); weatherScore.put("雨", 10); weatherScore.put("雷阵雨转中雨", 5); weatherScore.put("雷阵雨转大雨", 4); weatherScore.put("中雨", 0); weatherScore.put("大雨", 0); weatherScore.put("暴雨", 0); weatherScore.put("小雪", 0); weatherScore.put("中雪", 0); weatherScore.put("大雪", 0); weatherScore.put("暴雪", 0); weatherScore.put("雨夹雪", 0); } @Override public void forecastO3() { Date nextDay = DateUtils.addDays(new Date(), 1); String nextTime = DateUtils.dateToDateString(nextDay, DateUtils.yyyy_MM_dd_EN); //根据最近一个月历史数据来预测 Date start = DateUtils.addMonths(DateUtils.getDate(nextTime), -1); //获取要预测的城市 QueryWrapper cityConfigWeatherForecastQueryWrapper = new QueryWrapper<>(); cityConfigWeatherForecastQueryWrapper.select("city_code") .eq("is_delete", Constants.NOT_DELETE); List cityCodes = cityConfigWeatherForecastService.listObjs(cityConfigWeatherForecastQueryWrapper); //获取预测日逐小时气象数据 QueryWrapper cityWeatherForecastQueryWrapper = new QueryWrapper<>(); cityWeatherForecastQueryWrapper.likeRight("time", nextTime) .in("city_code", cityCodes); List forecasts = cityWeatherForecastService.list(cityWeatherForecastQueryWrapper); Map> cityForecast = forecasts.stream() .collect(Collectors.groupingBy(CityWeatherForecast::getCityCode)); //获取近两个月历史气象数据 QueryWrapper cityWeatherQueryWrapper = new QueryWrapper<>(); cityWeatherQueryWrapper.ge("time", start) .in("city_code", cityCodes); List historyWeather = cityWeatherService.list(cityWeatherQueryWrapper); Map> cityHistoryWeather = historyWeather.stream() .collect(Collectors.groupingBy(CityWeather::getCityCode)); //获取近两个月历史aqi数据 QueryWrapper cityAqiQueryWrapper = new QueryWrapper<>(); cityAqiQueryWrapper.ge("time", start) .in("city_code", cityCodes); List historyAqi = cityAqiService.list(cityAqiQueryWrapper); Map> cityHistoryAqi = historyAqi.stream() .collect(Collectors.groupingBy(CityAqi::getCityCode)); //获取前后一小时map Map> hours = DateUtils.getBeforeAndAfterHourDate(nextDay); List forecastList = new ArrayList<>(); Forecast forecast = new Forecast(); Map forecastMap = new HashMap<>(); for (Object obj : cityCodes) { Integer cityCode = Integer.parseInt(obj.toString()); forecast.setCityCode(cityCode); //预测 List cityWeatherForecasts = cityForecast.get(cityCode); //获取城市历史气象数据 List cityWeathers = cityHistoryWeather.get(cityCode); //获取城市历史aqi数据 List cityAqis = cityHistoryAqi.get(cityCode); Map> cityAqiMap = cityAqis.stream() .collect(Collectors.groupingBy(CityAqi::getTime)); Map>> cityHistoryMap = new HashMap<>(); for (Map.Entry> dateListEntry : hours.entrySet()) { Date date = dateListEntry.getKey(); List hourList = dateListEntry.getValue(); List> hourWeatherData = new ArrayList<>(); for (CityWeather cityWeather : cityWeathers) { Date cityWeatherTime = cityWeather.getTime(); int dataHour = DateUtils.getHour(cityWeatherTime); if (hourList.contains(dataHour)) { Map valueMap = JSONObject.parseObject(cityWeather.getValue(), Map.class); List o = cityAqiMap.get(cityWeatherTime); if (!ObjectUtils.isEmpty(o)) { String value = o.get(0).getValue(); Map aqiMap = JSONObject.parseObject(value, Map.class); valueMap.put("O3", aqiMap.get("O3")); hourWeatherData.add(valueMap); } } } cityHistoryMap.put(date, hourWeatherData); } for (CityWeatherForecast cityWeatherForecast : cityWeatherForecasts) { Date time = cityWeatherForecast.getTime(); Map value = JSONObject.parseObject(cityWeatherForecast.getValue(), Map.class); String weather = value.get("text").toString(); Integer forecastScore = weatherScore.get(weather); int min; if (forecastScore >= 80) { min = 80; } else if (forecastScore >= 40) { min = 40; } else { min = 0; } //气象 List> weatherMaps = cityHistoryMap.get(time); //根据天气分数筛选 weatherMaps.removeIf(o -> { Integer historyScore = weatherScore.get(o.get("text").toString()); return historyScore < min; }); int size = weatherMaps.size(); Double tempAvg = calculateAvg(weatherMaps, "temp"); Double o3Avg = calculateAvg(weatherMaps, "O3"); Double sum1 = calculateProduct(weatherMaps, "temp", "O3"); Double sum2 = calculateProduct(weatherMaps, "temp", "temp"); double b = (sum1 - size * tempAvg * o3Avg) / (sum2 - size * tempAvg * tempAvg); double a = o3Avg - b * tempAvg; double tempForecast = Double.parseDouble(value.get("temp").toString()); double o3Forecast = b * tempForecast + a; forecast.setTime(cityWeatherForecast.getTime()); if (!Double.isNaN(o3Forecast)) { forecastMap.put("O3", AmendUtils.sciCal(o3Forecast, 0)); forecast.setValue(JSONObject.toJSONString(forecastMap)); forecastList.add(forecast); } } } forecastMapper.insertForecast(forecastList); } private Double calculateAvg(List> list, String param) { Supplier>> supplier = list::stream; DoubleStream doubleStream = supplier.get() .flatMapToDouble(value -> { String sensorValue = value.get(param).toString(); double paramValue = Double.parseDouble(sensorValue); return DoubleStream.of(paramValue); }); Double result = null; OptionalDouble optionalDouble = doubleStream.average(); if (optionalDouble.isPresent()) { result = optionalDouble.getAsDouble(); } return result; } private Double calculateProduct(List> list, String param1, String param2) { Supplier>> supplier = list::stream; DoubleStream doubleStream = supplier.get() .flatMapToDouble(value -> { String sensorValue1 = value.get(param1).toString(); String sensorValue2 = value.get(param2).toString(); double paramValue1 = Double.parseDouble(sensorValue1); double paramValue2 = Double.parseDouble(sensorValue2); return DoubleStream.of(paramValue1 * paramValue2); }); return doubleStream.sum(); } }