1.完成输运模拟态势功能接口、符合度分析功能接口

2.修改天气预报功能接口
This commit is contained in:
panbaolin 2025-11-12 11:28:47 +08:00
parent 528479f777
commit d324b3dfb0
25 changed files with 821 additions and 16 deletions

View File

@ -8,11 +8,11 @@ public enum TransportTaskModeEnum {
/** /**
* 正向 * 正向
*/ */
FORWARD(-1), FORWARD(1),
/** /**
* 反向 * 反向
*/ */
BACK_FORWARD(1); BACK_FORWARD(-1);
private Integer key; private Integer key;

View File

@ -0,0 +1,7 @@
package org.jeecg.common.validgroup;
/**
* 查询验证组
*/
public interface QueryGroup {
}

View File

@ -67,7 +67,7 @@ public class TransportTask{
private Integer taskStatus; private Integer taskStatus;
/** /**
* 气象数据类型1-盘古模型2-graphcast3-cra404-ncep * 气象数据类型1-盘古模型2-graphcast3-cra404-ncep,5-fnl,6-t1h
*/ */
@NotNull(message = "气象数据类型不能为空",groups = {InsertGroup.class, UpdateGroup.class}) @NotNull(message = "气象数据类型不能为空",groups = {InsertGroup.class, UpdateGroup.class})
@TableField(value = "use_met_type") @TableField(value = "use_met_type")

View File

@ -38,7 +38,7 @@ public class TransportTaskChild{
/** /**
* 台站编目 * 台站编目
*/ */
@NotBlank(message = "释放量不能为空",groups = {InsertGroup.class, UpdateGroup.class}) @NotBlank(message = "台站编码不能为空",groups = {InsertGroup.class, UpdateGroup.class})
@TableField(value = "station_code") @TableField(value = "station_code")
private String stationCode; private String stationCode;

View File

@ -42,12 +42,18 @@ public class GardsNuclearfacility implements Serializable {
@TableField(value = "LONGITUDE") @TableField(value = "LONGITUDE")
private String longitude; private String longitude;
@TableField(exist = false)
private Double lonValue;
/** /**
* 纬度 * 纬度
*/ */
@TableField(value = "LATITUDE") @TableField(value = "LATITUDE")
private String latitude; private String latitude;
@TableField(exist = false)
private Double latValue;
/** /**
* 状态 * 状态
*/ */

View File

@ -0,0 +1,16 @@
package org.jeecg.modules.base.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import io.lettuce.core.dynamic.annotation.Param;
import org.jeecg.modules.base.entity.rnauto.GardsXeResults;
import java.util.Date;
import java.util.List;
import java.util.Map;
public interface GardsXeResultMapper extends BaseMapper<GardsXeResults> {
List<Map<String, Object>> getXeResults(@Param("stationId") Integer stationId,
@Param("startTime") Date startTime,
@Param("endTime") Date endTime,
@Param("nuclideName") String nuclideName);
}

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.jeecg.modules.base.mapper.GardsXeResultMapper">
<select id="getXeResults" resultType="java.util.Map">
SELECT
gxr.CONC as "obsValue",
gsd.ACQUISITION_START as "acquisitionStart",
gsd.ACQUISITION_STOP as "acquisitionStop"
FROM
RNAUTO.GARDS_XE_RESULTS gxr
INNER JOIN ORIGINAL.GARDS_SAMPLE_DATA gsd ON gxr.SAMPLE_ID = gsd.SAMPLE_ID
WHERE
gsd.ACQUISITION_STOP BETWEEN #{startTime}
AND #{endTime}
AND gsd.STATION_ID = #{stationId}
AND gsd.DATA_TYPE = 'S'
AND gsd.SPECTRAL_QUALIFIE = 'FULL'
AND gxr.NUCLIDE_NAME = #{nuclideName}
</select>
</mapper>

View File

@ -14,7 +14,7 @@ import org.jeecg.common.api.vo.Result;
@RestController @RestController
@RequestMapping("diffusionData") @RequestMapping("diffusionData")
@RequiredArgsConstructor @RequiredArgsConstructor
public class DiffusionDataController { public class DiffusionDataController {
private final DiffusionDataService diffusionDataService; private final DiffusionDataService diffusionDataService;

View File

@ -0,0 +1,35 @@
package org.jeecg.controller;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.service.StationDataService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Validated
@RestController
@RequestMapping("station")
@RequiredArgsConstructor
public class StationDataController {
private final StationDataService stationDataService;
@AutoLog(value = "查询所有台站")
@Operation(summary = "查询所有台站")
@GetMapping("getAllStations")
public Result<?> getAllStations(){
return Result.OK(stationDataService.getAllStations());
}
@AutoLog(value = "查询所有台站")
@Operation(summary = "查询所有设施")
@GetMapping("getAllNuclearfacility")
public Result<?> getAllNuclearfacility(){
return Result.OK(stationDataService.getAllNuclearfacility());
}
}

View File

@ -0,0 +1,53 @@
package org.jeecg.controller;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.validgroup.QueryGroup;
import org.jeecg.service.TransportResultDataService;
import org.jeecg.vo.QueryDiffusionVO;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@Validated
@RestController
@RequestMapping("transportResult")
@RequiredArgsConstructor
public class TransportResultDataController {
private final TransportResultDataService transportResultDataService;
@AutoLog(value = "分页查询输运任务数据")
@Operation(summary = "分页查询输运任务数据")
@GetMapping("getDiffusionData")
public Result<?> getDiffusionData(@Validated(value= QueryGroup.class) QueryDiffusionVO queryDiffusionVO) {
return Result.OK(transportResultDataService.getDiffusionData(queryDiffusionVO));
}
@AutoLog(value = "查询模拟结果站点序号和高度层级")
@Operation(summary = "查询模拟结果站点序号和高度层级")
@GetMapping("getResultSiteAndHeightLevel")
public Result<?> getResultSiteAndHeightLevel(@NotNull(message = "任务id不能为空") Integer taskId) {
return Result.OK(transportResultDataService.getResultSiteNums(taskId));
}
@AutoLog(value = "查询符合度分析数据")
@Operation(summary = "查询符合度分析数据")
@GetMapping("getConformityAnalysis")
public Result<?> getConformityAnalysis(@NotNull(message = "任务id不能为空") Integer taskId,
@NotNull(message = "台站不能为空") Integer stationId,
@NotNull(message = "核素名称不能为空") String nuclideName,
String facilityName) {
return Result.OK(transportResultDataService.getConformityAnalysis(taskId,stationId,nuclideName,facilityName));
}
@AutoLog(value = "查询任务所属核设施数据")
@Operation(summary = "查询任务所属核设施数据")
@GetMapping("getTaskFacility")
public Result<?> getTaskFacility(@NotNull(message = "任务id不能为空") Integer taskId) {
return Result.OK(transportResultDataService.getTaskFacility(taskId));
}
}

View File

@ -29,10 +29,10 @@ public class TransportTaskController {
@AutoLog(value = "分页查询输运任务数据") @AutoLog(value = "分页查询输运任务数据")
@Operation(summary = "分页查询输运任务数据") @Operation(summary = "分页查询输运任务数据")
@GetMapping("page") @GetMapping("page")
public Result<?> page(PageRequest pageRequest, String taskName, Integer taskMode,Integer taskStatus, public Result<?> page(PageRequest pageRequest, String taskName, Integer taskMode,Integer taskStatus,Integer metType,
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate, @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) { @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {
IPage<TransportTask> page = transportTaskService.page(pageRequest,taskName,taskMode,taskStatus,startDate,endDate); IPage<TransportTask> page = transportTaskService.page(pageRequest,taskName,taskMode,taskStatus,metType,startDate,endDate);
Map<String, Object> rspData = new HashMap<>(); Map<String, Object> rspData = new HashMap<>();
rspData.put("rows", page.getRecords()); rspData.put("rows", page.getRecords());
rspData.put("total", page.getTotal()); rspData.put("total", page.getTotal());

View File

@ -0,0 +1,42 @@
package org.jeecg.service;
import org.jeecg.modules.base.entity.configuration.GardsNuclearfacility;
import org.jeecg.modules.base.entity.configuration.GardsStations;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* 台站数据服务
*/
public interface StationDataService {
/**
* 获取所有台站
* @return
*/
List<GardsStations> getAllStations();
/**
* 获取所有核设施
* @return
*/
List<GardsNuclearfacility> getAllNuclearfacility();
/**
* 获取指定样品在指定时间范围内的核素监测结果
* @param stationId
* @param startTime
* @param endTime
* @param nuclideName
* @return
*/
List<Map<String, Object>> getXeResults(Integer stationId,Date startTime,Date endTime,String nuclideName);
/**
* 获取台站信息
* @param stationId
* @return
*/
GardsStations getStationById(Integer stationId);
}

View File

@ -0,0 +1,40 @@
package org.jeecg.service;
import org.jeecg.vo.QueryDiffusionVO;
import java.util.List;
import java.util.Map;
public interface TransportResultDataService {
/**
* 获取扩散数据
* @param queryDiffusionVO
* @return
*/
List<Map<String,Object>> getDiffusionData(QueryDiffusionVO queryDiffusionVO);
/**
* 查询模拟结果站点序号和高度层级
* @param taskId
* @return
*/
Map<String,Object> getResultSiteNums(Integer taskId);
/**
* 查询符合度分析数据
* @param taskId
* @param stationId
* @param nuclideName
* @param facilityName
* @return
*/
List<Map<String, Object>> getConformityAnalysis(Integer taskId,Integer stationId,String nuclideName,String facilityName);
/**
* 查询任务所属核设施数据
* @param taskId
* @return
*/
List<String> getTaskFacility(Integer taskId);
}

View File

@ -21,11 +21,12 @@ public interface TransportTaskService extends IService<TransportTask> {
* @param taskName * @param taskName
* @param taskMode * @param taskMode
* @param taskStatus * @param taskStatus
* @param metType
* @param startDate * @param startDate
* @param endDate * @param endDate
* @return * @return
*/ */
IPage<TransportTask> page(PageRequest pageRequest,String taskName,Integer taskMode,Integer taskStatus,LocalDate startDate,LocalDate endDate); IPage<TransportTask> page(PageRequest pageRequest,String taskName,Integer taskMode,Integer taskStatus,Integer metType,LocalDate startDate,LocalDate endDate);
/** /**
* 创建输运模拟任务 * 创建输运模拟任务

View File

@ -0,0 +1,129 @@
package org.jeecg.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.base.entity.configuration.GardsNuclearfacility;
import org.jeecg.modules.base.entity.configuration.GardsStations;
import org.jeecg.modules.base.mapper.GardsNuclearfacilityMapper;
import org.jeecg.modules.base.mapper.GardsStationsMapper;
import org.jeecg.modules.base.mapper.GardsXeResultMapper;
import org.jeecg.service.StationDataService;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* 台站数据服务
*/
@DS("ora")
@Service
@RequiredArgsConstructor
public class StationDataServiceImpl implements StationDataService {
private final GardsStationsMapper stationsMapper;
private final GardsNuclearfacilityMapper nuclearfacilityMapper;
private final GardsXeResultMapper gardsXeResultMapper;
private final RedisUtil redisUtil;
/**
* 获取所有台站
* @return
*/
@Override
public List<GardsStations> getAllStations() {
if(redisUtil.hasKey(CommonConstant.ALL_STATIONS)){
return (List<GardsStations>) redisUtil.get(CommonConstant.ALL_STATIONS);
}else {
LambdaQueryWrapper<GardsStations> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.select(GardsStations::getStationId,GardsStations::getStationCode,GardsStations::getLon,GardsStations::getLat);
List<GardsStations> stations = stationsMapper.selectList(queryWrapper);
redisUtil.set(CommonConstant.ALL_STATIONS,stations);
return stations;
}
}
/**
* 获取所有核设施
* @return
*/
@Override
public List<GardsNuclearfacility> getAllNuclearfacility() {
if(redisUtil.hasKey(CommonConstant.ALL_NUCLEARFACILITY)){
return (List<GardsNuclearfacility>) redisUtil.get(CommonConstant.ALL_NUCLEARFACILITY);
}else {
LambdaQueryWrapper<GardsNuclearfacility> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.select(GardsNuclearfacility::getFacilityId, GardsNuclearfacility::getFacilityName,GardsNuclearfacility::getLongitude,GardsNuclearfacility::getLatitude);
List<GardsNuclearfacility> nuclearfacilities = nuclearfacilityMapper.selectList(queryWrapper);
nuclearfacilities.forEach(nuclearfacility -> {
//数据库经纬度存储的是反的所以这里反着处理
Double lon = this.lonAndLatConversion(nuclearfacility.getLatitude());
Double lat = this.lonAndLatConversion(nuclearfacility.getLongitude());
nuclearfacility.setLonValue(lon);
nuclearfacility.setLatValue(lat);
});
redisUtil.set(CommonConstant.ALL_NUCLEARFACILITY, nuclearfacilities);
return nuclearfacilities;
}
}
/**
* 获取指定样品在指定时间范围内的核素监测结果
*
* @param stationId
* @param startTime
* @param endTime
* @param nuclideName
* @return
*/
@Override
public List<Map<String, Object>> getXeResults(Integer stationId, Date startTime, Date endTime, String nuclideName) {
List<Map<String, Object>> xeResults = gardsXeResultMapper.getXeResults(stationId, startTime, endTime, nuclideName);
return xeResults;
}
/**
* 获取台站信息
*
* @param stationId
* @return
*/
@Override
public GardsStations getStationById(Integer stationId) {
return stationsMapper.selectById(stationId);
}
/**
* 29°4604N
* 经纬度转换29°3750N -> 29.xxxxx
* @param lonOrLatStr
* @return
*/
private Double lonAndLatConversion(String lonOrLatStr) {
if(lonOrLatStr.contains("°") && lonOrLatStr.contains("") && lonOrLatStr.contains("")){
String cleanStr = lonOrLatStr.replaceAll("[NSEW\\s]", "");
String[] parts = cleanStr.split("[°′″:\\s]+");
String deg = parts[0];
String min = parts.length > 1 && !parts[1].isEmpty() ? parts[1] : "0";
String sec = parts.length > 2 && !parts[2].isEmpty() ? parts[2] : "0";
BigDecimal degBigDecimal = new BigDecimal(deg);
BigDecimal minBigDecimal = new BigDecimal(min);
BigDecimal secBigDecimal = new BigDecimal(sec);
minBigDecimal = minBigDecimal.divide(new BigDecimal("60"), 5, BigDecimal.ROUND_HALF_UP);
secBigDecimal = secBigDecimal.divide(new BigDecimal("3600"), 5, BigDecimal.ROUND_HALF_UP);
double value = degBigDecimal.doubleValue() + minBigDecimal.doubleValue() + secBigDecimal.doubleValue();
return value;
}else {
if(lonOrLatStr.contains("°") && !lonOrLatStr.contains("") && !lonOrLatStr.contains("")){
String cleanStr = lonOrLatStr.replaceAll("[NSEW°\\s]", "");
return Double.parseDouble(cleanStr);
}
}
return 0D;
}
}

View File

@ -0,0 +1,409 @@
package org.jeecg.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import org.jeecg.common.constant.enums.TransportTaskModeEnum;
import org.jeecg.common.properties.TransportSimulationProperties;
import org.jeecg.common.util.NcUtil;
import org.jeecg.modules.base.entity.TransportTask;
import org.jeecg.modules.base.entity.TransportTaskChild;
import org.jeecg.modules.base.entity.configuration.GardsStations;
import org.jeecg.modules.base.mapper.TransportTaskChildMapper;
import org.jeecg.modules.base.mapper.TransportTaskMapper;
import org.jeecg.service.StationDataService;
import org.jeecg.service.TransportResultDataService;
import org.jeecg.vo.ConcModValVo;
import org.jeecg.vo.QueryDiffusionVO;
import org.springframework.stereotype.Service;
import ucar.ma2.Array;
import ucar.ma2.DataType;
import ucar.ma2.Index;
import ucar.ma2.InvalidRangeException;
import ucar.nc2.Attribute;
import ucar.nc2.Dimension;
import ucar.nc2.NetcdfFile;
import ucar.nc2.Variable;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class TransportResultDataServiceImpl implements TransportResultDataService {
private final TransportTaskMapper transportTaskMapper;
private final TransportSimulationProperties simulationProperties;
private final TransportTaskChildMapper transportTaskChildMapper;
private final StationDataService stationDataService;
private final static String FORWARD="forward";
private final static String BACK_FORWARD="backward";
/**
* 获取扩散数据
* @param queryDiffusionVO
* @return
*/
@Override
public List<Map<String,Object>> getDiffusionData(QueryDiffusionVO queryDiffusionVO) {
//验证任务是否存在
TransportTask transportTask = this.transportTaskMapper.selectById(queryDiffusionVO.getTaskId());
if(Objects.isNull(transportTask)){
throw new RuntimeException("此任务不存在");
}
if(TransportTaskModeEnum.FORWARD.getKey().equals(transportTask.getTaskMode())){
return this.getForwardData(transportTask,queryDiffusionVO);
}else if(TransportTaskModeEnum.BACK_FORWARD.getKey().equals(transportTask.getTaskMode())){
return this.getBackwardData(transportTask,queryDiffusionVO);
}
return List.of();
}
/**
* 获取正演数据
* @param transportTask
* @param queryDiffusionVO
* @return
*/
private List<Map<String,Object>> getForwardData(TransportTask transportTask,QueryDiffusionVO queryDiffusionVO){
//获取nc文件路径
String path = this.getForwardTaskNCPath(transportTask);
try (NetcdfFile ncFile = NetcdfFile.open(path.toString())) {
List<Double> lonData = NcUtil.getNCList(ncFile, "longitude");
List<Double> latData = NcUtil.getNCList(ncFile, "latitude");
Variable spec001Mr = ncFile.findVariable("spec001_mr");
List<Map<String,Object>> result = new ArrayList<>();
for(Integer pointNum : queryDiffusionVO.getPointspecs()){
int[] origin = {0, pointNum,queryDiffusionVO.getTime(),queryDiffusionVO.getLevel(), 0, 0};
int[] section = {1, 1,1,1,latData.size(),lonData.size()};
Array data = spec001Mr.read(origin,section);
double[] pointData = (double[]) data.get1DJavaArray(DataType.DOUBLE);
for(int i=0;i<pointData.length;i++){
if(pointData[i]>0){
int iy = i / lonData.size();
int ix = i % lonData.size();
Map<String,Object> valMap = new HashMap<>();
valMap.put("lon",lonData.get(ix));
valMap.put("lat",latData.get(iy));
valMap.put("value",pointData[i]);
result.add(valMap);
}
}
}
return result;
} catch (IOException | InvalidRangeException e) {
throw new RuntimeException(e);
}
}
/**
* 获取反演数据
* @param transportTask
* @param queryDiffusionVO
* @return
*/
private List<Map<String,Object>> getBackwardData(TransportTask transportTask,QueryDiffusionVO queryDiffusionVO){
//验证任务子信息
LambdaQueryWrapper<TransportTaskChild> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TransportTaskChild::getTaskId,queryDiffusionVO.getTaskId());
queryWrapper.select(TransportTaskChild::getId,TransportTaskChild::getStationCode);
queryWrapper.orderByAsc(TransportTaskChild::getId);
List<TransportTaskChild> transportTaskChildren = transportTaskChildMapper.selectList(queryWrapper);
if(CollUtil.isEmpty(transportTaskChildren)){
throw new RuntimeException("此任务站点信息不存在,请确认任务配置信息");
}
List<Map<String,Object>> result = new ArrayList<>();
for(Integer pointNum : queryDiffusionVO.getPointspecs()){
//获取nc文件路径
TransportTaskChild transportTaskChild = transportTaskChildren.get(pointNum);
String path = this.getBackForwardTaskNCPath(transportTask,transportTaskChild.getStationCode());
try (NetcdfFile ncFile = NetcdfFile.open(path.toString())) {
List<Double> lonData = NcUtil.getNCList(ncFile, "longitude");
List<Double> latData = NcUtil.getNCList(ncFile, "latitude");
Variable spec001Mr = ncFile.findVariable("spec001_mr");
int[] origin = {0, 0,queryDiffusionVO.getTime(),queryDiffusionVO.getLevel(), 0, 0};
int[] section = {1, 1,1,1,latData.size(),lonData.size()};
Array data = spec001Mr.read(origin,section);
double[] pointData = (double[]) data.get1DJavaArray(DataType.DOUBLE);
for(int i=0;i<pointData.length;i++){
if(pointData[i]>0){
int iy = i / lonData.size();
int ix = i % lonData.size();
Map<String,Object> valMap = new HashMap<>();
valMap.put("lon",lonData.get(ix));
valMap.put("lat",latData.get(iy));
valMap.put("value",pointData[i]);
result.add(valMap);
}
}
} catch (IOException | InvalidRangeException e) {
throw new RuntimeException(e);
}
}
return result;
}
/**
* 查询模拟结果站点序号和高度层级
* @param taskId
* @return
*/
@Override
public Map<String,Object> getResultSiteNums(Integer taskId) {
Map<String,Object> resultMap = new HashMap<>();
TransportTask transportTask = this.transportTaskMapper.selectById(taskId);
if(Objects.isNull(transportTask)){
throw new RuntimeException("此任务不存在");
}
LambdaQueryWrapper<TransportTaskChild> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TransportTaskChild::getTaskId,taskId);
queryWrapper.select(TransportTaskChild::getId,TransportTaskChild::getStationCode);
queryWrapper.orderByAsc(TransportTaskChild::getId);
List<TransportTaskChild> transportTaskChildren = transportTaskChildMapper.selectList(queryWrapper);
if(CollUtil.isEmpty(transportTaskChildren)){
throw new RuntimeException("此任务站点信息不存在,请确认任务配置信息");
}
//获取nc文件路径
String path = "";
if(TransportTaskModeEnum.FORWARD.getKey().equals(transportTask.getTaskMode())){
path = this.getForwardTaskNCPath(transportTask);
}else if(TransportTaskModeEnum.BACK_FORWARD.getKey().equals(transportTask.getTaskMode())){
path = this.getBackForwardTaskNCPath(transportTask,transportTaskChildren.get(0).getStationCode());
}
if(!FileUtil.exist(path)){
throw new RuntimeException("此任务模拟结果不存在,请确认任务运行状态");
}
//本任务模拟的台站数据
Map<Integer,Object> stationNumMap = new LinkedHashMap<>();
for (int i = 0; i<transportTaskChildren.size();i++) {
stationNumMap.put((i),transportTaskChildren.get(i).getStationCode());
}
resultMap.put("stationNum",stationNumMap);
//高度数据
Map<Integer,Object> heights = new LinkedHashMap<>();
//全局属性
Map<String,Object> globalAttr = new LinkedHashMap<>();
try (NetcdfFile ncFile = NetcdfFile.open(path.toString())) {
Attribute outlonVar = ncFile.findGlobalAttribute("outlon0");
Attribute outlatVar = ncFile.findGlobalAttribute("outlat0");
Attribute dxoutVar = ncFile.findGlobalAttribute("dxout");
Attribute dyoutVar = ncFile.findGlobalAttribute("dyout");
Variable heightVar = ncFile.findVariable("height");
Variable timeVar = ncFile.findVariable("time");
globalAttr.put("outlon",outlonVar.getNumericValue());
globalAttr.put("outlat",outlatVar.getNumericValue());
globalAttr.put("dxout",dxoutVar.getNumericValue());
globalAttr.put("dyout",dyoutVar.getNumericValue());
globalAttr.put("height",heightVar.getSize());
globalAttr.put("time",timeVar.getSize());
Array data = heightVar.read();
int[] shape = data.getShape();
Index index = data.getIndex();
for(int i=0;i<shape[0];i++){
heights.put((i),data.getDouble(index.set(i)));
}
resultMap.put("heights",heights);
resultMap.put("globalAttr",globalAttr);
} catch (IOException e) {
throw new RuntimeException(e);
}
return resultMap;
}
/**
* 查询符合度分析数据
* @param taskId
* @param stationId
* @param nuclideName
* @param facilityName
* @return
*/
@Override
public List<Map<String, Object>> getConformityAnalysis(Integer taskId,Integer stationId,String nuclideName,String facilityName) {
TransportTask transportTask = transportTaskMapper.selectById(taskId);
if(Objects.isNull(transportTask)){
throw new RuntimeException("此任务不存在");
}
List<Map<String, Object>> xeResults = stationDataService.getXeResults(stationId, transportTask.getStartTime(), transportTask.getEndTime(), nuclideName);
System.out.println(xeResults);
//获取nc文件路径
String path = this.getForwardTaskNCPath(transportTask);
try (NetcdfFile ncFile = NetcdfFile.open(path.toString())) {
int pointNum = -1;
int maxPointNum = -1;
if (StrUtil.isNotBlank(facilityName)) {
LambdaQueryWrapper<TransportTaskChild> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TransportTaskChild::getTaskId,taskId);
queryWrapper.select(TransportTaskChild::getId,TransportTaskChild::getStationCode);
queryWrapper.orderByAsc(TransportTaskChild::getId);
List<TransportTaskChild> transportTaskChildren = transportTaskChildMapper.selectList(queryWrapper);
for(int i=0;i<transportTaskChildren.size();i++){
if (transportTaskChildren.get(i).getStationCode().equals(facilityName)){
pointNum = i;
maxPointNum = i;
}
}
}else{
Dimension pointspec = ncFile.findDimension("pointspec");
maxPointNum = pointspec.getLength() -1;
}
//找到最接近台站经纬度的值作为对比点位
List<Double> lonData = NcUtil.getNCList(ncFile, "longitude");
List<Double> latData = NcUtil.getNCList(ncFile, "latitude");
List<Double> timeData = NcUtil.getNCList(ncFile, "time");
GardsStations station = this.stationDataService.getStationById(stationId);
Map<String,Object> lonRecentValMap = this.getRecentValue(lonData, station.getLon());
Map<String,Object> latRecentValMap = this.getRecentValue(latData, station.getLat());
Integer lonBestIndex = Integer.parseInt(lonRecentValMap.get("bestIndex").toString());
Integer latBestIndex = Integer.parseInt(latRecentValMap.get("bestIndex").toString());
Variable spec001Mr = ncFile.findVariable("spec001_mr");
List<ConcModValVo> modValList = new ArrayList<>();
for(int i=pointNum;i<=maxPointNum;i++){
for(int k=0;k<timeData.size();k++){
int[] origin = {0, i,k,0, latBestIndex,lonBestIndex};
int[] section = {1, 1,1,1,1,1};
Array levelData = spec001Mr.read(origin,section);
double[] pointData = (double[]) levelData.get1DJavaArray(DataType.DOUBLE);
double pointDataVal = pointData[0];
if(pointDataVal > 0){
Instant instant = transportTask.getStartTime().toInstant();
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
localDateTime = localDateTime.plusSeconds(timeData.get(k).intValue());
long second = localDateTime.atZone(ZoneId.systemDefault()).toEpochSecond();
ConcModValVo concModValVo = new ConcModValVo();
concModValVo.setSecond(second);
concModValVo.setPointDataVal(pointDataVal);
modValList.add(concModValVo);
}else {
ConcModValVo concModValVo = new ConcModValVo();
concModValVo.setSecond(0L);
concModValVo.setPointDataVal(pointDataVal);
modValList.add(concModValVo);
}
}
}
if(CollUtil.isNotEmpty(modValList)){
xeResults.parallelStream().forEach(resultMap -> {
Date acqStart = (Date)resultMap.get("acquisitionStart");
Date acqEnd = (Date)resultMap.get("acquisitionStop");
int acqStartSecond = (int)(acqStart.getTime()/1000);
int acqStopSecond = (int)(acqEnd.getTime()/1000);
int count = 0;
Double sumVodValue = 0D;
for (ConcModValVo modVal : modValList){
if (modVal.getSecond() >= acqStartSecond && modVal.getSecond() <= acqStopSecond) {
sumVodValue += modVal.getPointDataVal();
count +=1;
}
}
if (sumVodValue != 0){
//纳克转换为毫克需除以1000000
BigDecimal vodValue = new BigDecimal(sumVodValue);
BigDecimal finalVodValue = vodValue.divide(new BigDecimal(count)).divide(new BigDecimal(1000000)).setScale(5,BigDecimal.ROUND_HALF_UP);
resultMap.put("modValue", finalVodValue);
}else {
resultMap.put("modValue", sumVodValue);
}
});
}
} catch (IOException | InvalidRangeException e) {
throw new RuntimeException(e);
}
return xeResults;
}
/**
* 查询任务所属核设施数据
*
* @param taskId
* @return
*/
@Override
public List<String> getTaskFacility(Integer taskId) {
LambdaQueryWrapper<TransportTaskChild> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TransportTaskChild::getTaskId,taskId);
queryWrapper.select(TransportTaskChild::getId,TransportTaskChild::getStationCode);
queryWrapper.orderByAsc(TransportTaskChild::getId);
List<TransportTaskChild> transportTaskChildren = transportTaskChildMapper.selectList(queryWrapper);
return transportTaskChildren.stream().map(TransportTaskChild::getStationCode).collect(Collectors.toList());
}
/**
* 找到集合中里最接近目标值的值
* @param data
* @param target
* @return
*/
private Map<String,Object> getRecentValue(List<Double> data,Double target){
if(CollUtil.isEmpty(data)){
throw new RuntimeException("data集合数据为空");
}
double targetVal = target.doubleValue();
int bestIndex = 0;
double minDist = Math.abs(data.get(0).doubleValue() - targetVal);
for (int i = 1; i < data.size(); i++) {
double dist = Math.abs(data.get(i).doubleValue() - targetVal);
if (dist < minDist) {
minDist = dist;
bestIndex = i;
}
}
Map<String,Object> resultMap = new HashMap<>();
resultMap.put("bestIndex",bestIndex);
resultMap.put("minDist",minDist);
return resultMap;
}
/**
* 获取正演NC结果文件路径
* @param transportTask
* @return
*/
private String getForwardTaskNCPath(TransportTask transportTask){
//拼接nc文件路径
StringBuilder path = new StringBuilder();
path.append(simulationProperties.getOutputPath());
path.append(File.separator);
path.append(transportTask.getTaskName());
path.append(File.separator);
path.append(FORWARD);
path.append(File.separator);
path.append("grid_conc_"+DateUtil.format(transportTask.getStartTime(),"yyyyMMddHHmmss")+".nc");
return path.toString();
}
/**
* 获取反演NC结果文件路径
* @param transportTask
* @return
*/
private String getBackForwardTaskNCPath(TransportTask transportTask,String stationCode){
//拼接nc文件路径
StringBuilder path = new StringBuilder();
path.append(simulationProperties.getOutputPath());
path.append(File.separator);
path.append(transportTask.getTaskName());
path.append(File.separator);
path.append(BACK_FORWARD);
path.append(File.separator);
path.append(stationCode);
path.append(File.separator);
path.append("grid_time_"+DateUtil.format(transportTask.getEndTime(),"yyyyMMddHHmmss")+".nc");
return path.toString();
}
}

View File

@ -53,10 +53,11 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
* @return * @return
*/ */
@Override @Override
public IPage<TransportTask> page(PageRequest pageRequest, String taskName, Integer taskMode,Integer taskStatus, LocalDate startDate, LocalDate endDate) { public IPage<TransportTask> page(PageRequest pageRequest, String taskName, Integer taskMode,Integer taskStatus,Integer metType, LocalDate startDate, LocalDate endDate) {
LambdaQueryWrapper<TransportTask> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<TransportTask> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Objects.nonNull(taskMode),TransportTask::getTaskMode, taskMode); queryWrapper.eq(Objects.nonNull(taskMode),TransportTask::getTaskMode, taskMode);
queryWrapper.eq(Objects.nonNull(taskStatus),TransportTask::getTaskStatus, taskStatus); queryWrapper.eq(Objects.nonNull(taskStatus),TransportTask::getTaskStatus, taskStatus);
queryWrapper.eq(Objects.nonNull(metType),TransportTask::getUseMetType, metType);
if(Objects.nonNull(startDate) && Objects.nonNull(endDate)){ if(Objects.nonNull(startDate) && Objects.nonNull(endDate)){
LocalDateTime startDateTime = startDate.atTime(0, 0, 0); LocalDateTime startDateTime = startDate.atTime(0, 0, 0);
LocalDateTime endDateTime = endDate.atTime(23, 59, 59); LocalDateTime endDateTime = endDate.atTime(23, 59, 59);
@ -185,6 +186,7 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
} }
LambdaQueryWrapper<TransportTaskChild> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<TransportTaskChild> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TransportTaskChild::getTaskId,id); queryWrapper.eq(TransportTaskChild::getTaskId,id);
queryWrapper.orderByAsc(TransportTaskChild::getId);
List<TransportTaskChild> transportTaskChildren = transportTaskChildMapper.selectList(queryWrapper); List<TransportTaskChild> transportTaskChildren = transportTaskChildMapper.selectList(queryWrapper);
if(Objects.isNull(transportTaskChildren)){ if(Objects.isNull(transportTaskChildren)){
throw new RuntimeException("此任务对应的flexpart模型配置信息不存在请确认"); throw new RuntimeException("此任务对应的flexpart模型配置信息不存在请确认");

View File

@ -0,0 +1,11 @@
package org.jeecg.vo;
import lombok.Data;
@Data
public class ConcModValVo {
private Long second;
private Double pointDataVal;
}

View File

@ -0,0 +1,31 @@
package org.jeecg.vo;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.util.List;
@Data
public class QueryDiffusionVO {
/**
* 任务id
*/
@NotNull(message = "任务id不能为空",groups = {QueryDiffusionVO.class})
private Integer taskId;
/**
* 数据层级序号
*/
@NotNull(message = "数据层级不能为空",groups = {QueryDiffusionVO.class})
private Integer level;
/**
* 时间序号
*/
@NotNull(message = "时间序号不能为空",groups = {QueryDiffusionVO.class})
private Integer time;
/**
* 站点序号
*/
@NotNull(message = "站点序号不能为空",groups = {QueryDiffusionVO.class})
private List<Integer> pointspecs;
}

View File

@ -39,10 +39,10 @@ public class WeatherDataController {
@AutoLog(value = "分页查询气象文件数据") @AutoLog(value = "分页查询气象文件数据")
@Operation(summary = "分页查询气象文件数据") @Operation(summary = "分页查询气象文件数据")
@GetMapping("page") @GetMapping("page")
public Result<?> page(PageRequest pageRequest, String fileExt, String dataSource, public Result<?> page(PageRequest pageRequest, String fileName,String fileExt, String dataSource,
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate, @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) { @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {
IPage<WeatherData> page = weatherDataService.page(pageRequest,fileExt,dataSource,startDate,endDate); IPage<WeatherData> page = weatherDataService.page(pageRequest,fileName,fileExt,dataSource,startDate,endDate);
Map<String, Object> rspData = new HashMap<>(); Map<String, Object> rspData = new HashMap<>();
rspData.put("rows", page.getRecords()); rspData.put("rows", page.getRecords());
rspData.put("total", page.getTotal()); rspData.put("total", page.getTotal());

View File

@ -29,7 +29,7 @@ public interface WeatherDataService extends IService<WeatherData> {
* @param endDate * @param endDate
* @return * @return
*/ */
IPage<WeatherData> page(PageRequest pageRequest, String fileExt, String dataSource, LocalDate startDate, LocalDate endDate); IPage<WeatherData> page(PageRequest pageRequest,String fileName, String fileExt, String dataSource, LocalDate startDate, LocalDate endDate);
/** /**
* 验证文件是否存在 * 验证文件是否存在

View File

@ -302,7 +302,7 @@ public class WeatherDataServiceImpl extends ServiceImpl<WeatherDataMapper, Weath
* @return * @return
*/ */
@Override @Override
public IPage<WeatherData> page(PageRequest pageRequest, String fileExt, String dataSource, LocalDate startDate, LocalDate endDate) { public IPage<WeatherData> page(PageRequest pageRequest,String fileName, String fileExt, String dataSource, LocalDate startDate, LocalDate endDate) {
LocalDateTime startTime = null; LocalDateTime startTime = null;
if(Objects.nonNull(startDate)){ if(Objects.nonNull(startDate)){
startTime = LocalDateTime.of(startDate.getYear(), startDate.getMonth(), startDate.getDayOfMonth(), 0, 0, 0); startTime = LocalDateTime.of(startDate.getYear(), startDate.getMonth(), startDate.getDayOfMonth(), 0, 0, 0);
@ -322,6 +322,7 @@ public class WeatherDataServiceImpl extends ServiceImpl<WeatherDataMapper, Weath
queryWrapper.in(CollUtil.isNotEmpty(dataSources),WeatherData::getDataSource,dataSources); queryWrapper.in(CollUtil.isNotEmpty(dataSources),WeatherData::getDataSource,dataSources);
queryWrapper.between((Objects.nonNull(startTime) && Objects.nonNull(endTime)),WeatherData::getDataStartTime,startTime,endTime); queryWrapper.between((Objects.nonNull(startTime) && Objects.nonNull(endTime)),WeatherData::getDataStartTime,startTime,endTime);
queryWrapper.eq(StringUtils.isNotBlank(fileExt),WeatherData::getFileExt, fileExt); queryWrapper.eq(StringUtils.isNotBlank(fileExt),WeatherData::getFileExt, fileExt);
queryWrapper.like(StringUtils.isNotBlank(fileName),WeatherData::getFileName, fileName);
queryWrapper.select(WeatherData::getId,WeatherData::getFileName,WeatherData::getFileSize,WeatherData::getDataSource,WeatherData::getFileExt,WeatherData::getDataStartTime,WeatherData::getFilePath); queryWrapper.select(WeatherData::getId,WeatherData::getFileName,WeatherData::getFileSize,WeatherData::getDataSource,WeatherData::getFileExt,WeatherData::getDataStartTime,WeatherData::getFilePath);
IPage<WeatherData> iPage = new Page<>(pageRequest.getPageNum(),pageRequest.getPageSize()); IPage<WeatherData> iPage = new Page<>(pageRequest.getPageNum(),pageRequest.getPageSize());
return this.baseMapper.selectPage(iPage, queryWrapper); return this.baseMapper.selectPage(iPage, queryWrapper);

View File

@ -1,5 +1,5 @@
server: server:
port: 8003 port: 8004
spring: spring:
application: application:

View File

@ -1,5 +1,5 @@
server: server:
port: 8004 port: 8005
spring: spring:
application: application:

View File

@ -45,7 +45,7 @@
<commonmark.version>0.17.0</commonmark.version> <commonmark.version>0.17.0</commonmark.version>
<knife4j-spring-boot-starter.version>4.5.0</knife4j-spring-boot-starter.version> <knife4j-spring-boot-starter.version>4.5.0</knife4j-spring-boot-starter.version>
<!-- 数据库驱动 --> <!-- 数据库驱动 -->
<postgresql.version>42.2.25</postgresql.version> <postgresql.version>42.7.5</postgresql.version>
<ojdbc6.version>11.2.0.3</ojdbc6.version> <ojdbc6.version>11.2.0.3</ojdbc6.version>
<sqljdbc4.version>4.0</sqljdbc4.version> <sqljdbc4.version>4.0</sqljdbc4.version>
<mysql-connector-java.version>8.0.27</mysql-connector-java.version> <mysql-connector-java.version>8.0.27</mysql-connector-java.version>