ke
2024-07-19 08a962d2925baa255207fdf979e6fee794f1773b
skjcmanager/skjcmanager-service/skjcmanager-sm/src/main/java/cn/gistack/sm/sjztmd/service/impl/AttResBaseServiceImpl.java
@@ -1,6 +1,7 @@
package cn.gistack.sm.sjztmd.service.impl;
import cn.gistack.sm.intelligentCall.mapper.CallTaskMapper;
import cn.gistack.sm.sjztmd.constant.RainfallConstant;
import cn.gistack.sm.sjztmd.dto.AttResBaseUserDTO;
import cn.gistack.sm.sjztmd.entity.AttAdBase;
import cn.gistack.sm.sjztmd.entity.AttResBase;
@@ -11,9 +12,20 @@
import cn.gistack.sm.sjztmd.service.IRelResLabelService;
import cn.gistack.sm.sjztmd.vo.*;
import cn.gistack.system.feign.ISysClient;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.DateUtil;
@@ -23,6 +35,7 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.*;
import java.util.stream.Collectors;
/**
 * @ClassName AttResBaseServiceImpl
@@ -31,9 +44,12 @@
 * @Date 2023/4/21 20:01
 * @Version 1.0
 */
@Slf4j
@Service
@DS("zt")
public class AttResBaseServiceImpl extends ServiceImpl<AttResBaseMapper, AttResBase> implements IAttResBaseService {
   private static final ObjectMapper objectMapper = new ObjectMapper();
   @Autowired
   private CallTaskMapper callTaskMapper;
@@ -99,6 +115,144 @@
   }
   @Override
   public List<AttResWithRainfall> getAttResByRainfall(String minRainfall, String maxRainfall, String dayIndex) {
      if (StrUtil.isNotEmpty(dayIndex) && !Arrays.asList(0,1,2).contains(Integer.parseInt(dayIndex))) {
         throw new ServiceException("无效的dayIndex");
      }
      Double minRainfallDouble = null;
      Double maxRainfallDouble = null;
      if (StrUtil.isNotEmpty(minRainfall)) {
         minRainfallDouble = Double.parseDouble(minRainfall);
      }
      if (StrUtil.isNotEmpty(minRainfall)) {
         maxRainfallDouble = Double.parseDouble(maxRainfall);
      }
      // 调用气象预报服务接口
      String resJsonNodeStr;
      try (HttpResponse httpResponse = HttpRequest.post(RainfallConstant.FORECAST_SERVICE_URL)
         .header("Content-Type", "application/json")
         .header("X-token", RainfallConstant.X_TOKEN)
         .contentType("application/json")
         .body(String.format(RainfallConstant.REQUEST_JSON_BODY, StrUtil.isEmpty(dayIndex) ? "0" : dayIndex)).execute()) {
         JsonNode resJsonNode = objectMapper.readTree(httpResponse.body());
         resJsonNodeStr = resJsonNode.toString();
      } catch (Exception e) {
         throw new ServiceException("调用气象预报服务接口失败,详情:" + e.getMessage());
      }
      RainfallGridData gridData;
      try {
         gridData = objectMapper.readValue(resJsonNodeStr, RainfallGridData.class);
      } catch (JsonProcessingException e) {
         throw new ServiceException("转换降雨栅格数据失败,详情:" + e.getMessage());
      }
      RainfallGridData.Data data = gridData.getData();
      String fileName = data.getFileName();
      RainfallGridData.GridInfo gridInfo = data.getGridInfo();
      List<List<Double>> gridDataList = data.getGridData();
      if (gridDataList == null || gridDataList.isEmpty()) {
         log.warn("gridDataList为空!");
         return new ArrayList<>();
      }
      // 获取网格信息
      int lonNum = gridInfo.getLonNum();    // 网格横向(经度)
      double lonMax = gridInfo.getLonMax();
      double lonSpan = gridInfo.getLonSpan();  // 每个网格单元的经度跨度
      double latSpan = gridInfo.getLatSpan();   // 每个网格单元的纬度跨度
      double latMin = gridInfo.getLatMin();    // 网格的最小纬度
      double lonMin = gridInfo.getLonMin();   // 网格的最小经度
      double latMax = gridInfo.getLatMax();
      int latNum = gridInfo.getLatNum();    // 网格纵向(纬度)
      // 将网格数据转换为二维数组
      double[][] grid = new double[latNum][lonNum];
      for (int i = 0; i < latNum; i++) {
         List<Double> row = gridDataList.get(i);
         for (int j = 0; j < lonNum; j++) {
            grid[i][j] = row.get(j);
         }
      }
      LambdaQueryWrapper<AttResBase> queryWrapper = Wrappers.<AttResBase>query().lambda();
      List<AttResBase> attResBases = baseMapper.selectList(queryWrapper);
       List<AttResWithRainfall> attResWithRainfallList = new ArrayList<>();
      for (AttResBase attResBase : attResBases) {
         if (null == attResBase.getCenterLat() || attResBase.getCenterLong() == null) {
            log.warn("过滤掉经度或者纬度为空的水库,水库名称:{}", attResBase.getName());
            continue;
         }
         // 横向索引(lonIndex):(站点的经度 - 网格最小经度) / 每个网格单元的经度跨度
         int lonIndex = (int) ((Double.parseDouble(attResBase.getCenterLong()) - lonMin) / lonSpan);
         //  纵向索引(latIndex):(站点的纬度 - 网格最小纬度) / 每个网格单元的纬度跨度
         int latIndex = (int) ((Double.parseDouble(attResBase.getCenterLat()) - latMin) / latSpan);
         if (lonIndex >= 0 && lonIndex < lonNum && latIndex >= 0 && latIndex < latNum) {
            double rainfall = grid[latIndex][lonIndex];
            // 降雨量 <= 最小值的站点,都过滤掉, 降雨量为0除外
            if (null != minRainfallDouble &&  rainfall != 0 && rainfall <= minRainfallDouble) {
               continue;
            }
            // 降雨量 > 最大值的站点,都过滤掉
            if (null != maxRainfallDouble &&  rainfall > maxRainfallDouble) {
               continue;
            }
            AttResWithRainfall attResWithRainfall = new AttResWithRainfall();
            BeanUtil.copyProperties(attResBase, attResWithRainfall);
            attResWithRainfall.setRainfall(String.valueOf(rainfall));
            attResWithRainfall.setFileName(fileName);
            attResWithRainfallList.add(attResWithRainfall);
         } else {
            log.warn("水库 {} 超出栅格范围. 中心点经度: {}, 中心点纬度: {}", attResBase.getName(),
                  attResBase.getCenterLong(), attResBase.getCenterLat());
         }
      }
      return attResWithRainfallList;
   }
   @Override
   public int[] getAttResNumByRainfall(String dayIndex) {
      List<AttResWithRainfall> attResByRainfall;
      // 获取站点降雨量失败或者返回站点列表为空时,直接返回空数组
      try {
         attResByRainfall = getAttResByRainfall(null, null, dayIndex);
      } catch (Exception e) {
         return RainfallConstant.EMPTY_ATT_RES_NUM_ARRAY;
      }
      if (attResByRainfall == null || attResByRainfall.isEmpty()) {
         return RainfallConstant.EMPTY_ATT_RES_NUM_ARRAY;
      }
      // 降雨范围-站点数量
      Map<String, Integer> rainfallRangeAttResNumMap = attResByRainfall.stream()
         .collect(Collectors.groupingBy(attResWithRainfall -> {
            int rainfall = Integer.parseInt(attResWithRainfall.getRainfall());
            if (rainfall > 250) {
               return "(250,+)";
            } else if (rainfall > 100) {
               return "(100,250]";
            } else if (rainfall > 50) {
               return "(50,100]";
            } else if (rainfall > 25) {
               return "(25,50]";
            } else if (rainfall > 10) {
               return "(10,25]";
            } else if (rainfall > 5) {
               return "(5,10]";
            } else if (rainfall > 0.1) {
               return "(0.1,5]";
            } else if (rainfall >= 0) {
               return "[0,0.1]";
            } else {
               throw new ServiceException("无效的降雨值:" + rainfall);
            }
         }, Collectors.collectingAndThen(Collectors.counting(), Long::intValue)));
      int[] attResNumArray = new int[RainfallConstant.RAIN_FALL_RANGES.size()];
      for (int i = 0; i < RainfallConstant.RAIN_FALL_RANGES.size(); i++) {
         String range = RainfallConstant.RAIN_FALL_RANGES.get(i);
         attResNumArray[i] = rainfallRangeAttResNumMap.getOrDefault(range, 0);
      }
      return attResNumArray;
   }
   @Override
   @Transactional(rollbackFor = Exception.class)
   public Boolean updateResBaseByGuid(AttResBase attResBase) {
      attResBase.setUpdateTime(DateUtil.now());