1.拆分输运模拟任务运行模块为子模块
This commit is contained in:
panbaolin 2026-04-09 14:44:52 +08:00
parent b865647b14
commit 31a3f6cb14
81 changed files with 3637 additions and 773 deletions

View File

@ -95,6 +95,12 @@
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.3.4</version>
<scope>compile</scope>
</dependency>
<!-- commons -->
<dependency>
<groupId>commons-io</groupId>
@ -214,6 +220,7 @@
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.7.0</version>
</dependency>
<!-- 代码生成器 -->
<!-- 如下载失败,请参考此文档 https://help.jeecg.com/java/setup/maven.html -->

View File

@ -0,0 +1,20 @@
package org.jeecg.common.constant;
/**
* 消息队列主题配置
*/
public interface RocketMQTopConstant {
String FORWARD_TRANSPORT_TASK_TOPIC = "topic_forward_transport_task_list";
String BACKWARD_TRANSPORT_TASK_TOPIC = "topic_backward_transport_task_list";
String SAMPLE_RESULT_TOPIC = "topic_abnormal_sample_list";
String ASSOCIATED_WAVEFORM_SAMPLE_TOPIC = "topic_associated_waveform_list";
/**
* 各服务器输运模拟任务运行状态
*/
String HOST_TASK_STATE = "host_task_state";
}

View File

@ -22,7 +22,7 @@ public enum AssociatedWaveformTaskEnum {
*/
IN_PROCESS(2),
/**
* 执行中
* 完成
*/
COMPLETE(3);

View File

@ -5,19 +5,25 @@ package org.jeecg.common.constant.enums;
*/
public enum FlexpartSpeciesType {
XE_131m(51),
XE_133(52),
XE_133m(53),
XE_135(54),
NOT_SPECIES(61);
XE_131m(51,"Xe131m"),
XE_133(52,"Xe133"),
XE_133m(53,"Xe133m"),
XE_135(54,"Xe135"),
NOT_SPECIES(61,"NONE"),;
private Integer value;
private final Integer id;
private final String nuclideName;
FlexpartSpeciesType(int value) {
this.value = value;
FlexpartSpeciesType(int id, String nuclideName) {
this.id = id;
this.nuclideName = nuclideName;
}
public Integer getValue() {
return value;
public Integer getId() {
return id;
}
public String getNuclideName() {
return nuclideName;
}
}

View File

@ -6,11 +6,11 @@ package org.jeecg.common.constant.enums;
public enum TransportSampleTypeEnum {
/**
* 正向
* 气体
*/
B,
/**
* 反向
* 颗粒物
*/
P;
}

View File

@ -13,18 +13,18 @@ public enum TransportTaskStatusEnum {
* 未开始
*/
NOT_STARTED(0),
/**
* 等待中
*/
WAITING(1),
/**
* 执行中
*/
IN_OPERATION(1),
IN_OPERATION(2),
/**
* 已完成
*/
COMPLETED(2),
/**
* 缺少气象数据
*/
LACK_MET_DATA(3);
COMPLETED(3);
private Integer value;

View File

@ -18,13 +18,21 @@ public class DataFusionProperties {
*/
private String ndcSRSPath;
/**
* srs文件的上级目录有可能是flexpart.x.ecmwf.l1或flexpart.x.ncep.l1
* srs文件的上级目录有可能是flexpart.ecmwf.l1或flexpart.ncep.l1
*/
private String idcSrmParentDir;
private String idcPSrmParentDir;
/**
* srs文件的上级目录有可能是flexpart.x.ecmwf.l1或flexpart.x.ncep.l1
* srs文件的上级目录有可能是flexpart.x.ecmwf.l1或flexpart.x.ncep.l1
*/
private String ndcSrmParentDir;
private String idcXSrmParentDir;
/**
* srs文件的上级目录有可能是flexpart.ecmwf.l1或flexpart.ncep.l1等
*/
private String ndcPSrmParentDir;
/**
* srs文件的上级目录有可能是flexpart.x.ecmwf.l1或flexpart.x.ncep.l1等
*/
private String ndcXSrmParentDir;
/**
* 浓度值过滤条件
*/

View File

@ -136,5 +136,16 @@ public class TransportSimulationProperties {
* 反演文件路径
*/
private String backwardTemplatePath;
/**
* 气象数据类型1-盘古模型2-graphcast3-cra404-ncep,5-fnl,6-t1h
*/
private Integer useMetType;
private Double z1;
private Double z2;
/**
* 粒子数量
*/
private Integer particleCount;
}

View File

@ -0,0 +1,53 @@
package org.jeecg.modules.base.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* 样品监测结果信息在消息队列中使用
*/
@Data
public class GardsSampleResultDTO implements Serializable {
/**
* 样品id
*/
private Integer sampleId;
/**
* 台站id
*/
private Integer stationId;
/**
* 样品测量开始时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date acquisitionStart;
/**
* 样品测量结束时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date acquisitionStop;
/**
* 样品类型 P颗粒物B气体
*/
private String sampleType;
/**
* 样品级别
*/
private Integer category;
/**
* 释放量
*/
private String releaseAmount;
}

View File

@ -0,0 +1,54 @@
package org.jeecg.modules.base.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import java.util.Date;
/**
* 输运模拟任务dto
*/
@Data
public class TransportTaskDTO {
/**
* ID
*/
private Integer id;
/**
* 任务名称
*/
private String taskName;
/**
* 任务模式1-正向-1-反向
*/
private Integer taskMode;
/**
* 任务类型(1-手动创建2自动触发)
*/
private Integer taskType;
/**
* 气象数据类型1-盘古模型2-graphcast3-cra404-ncep,5-fnl,6-t1h
*/
private Integer useMetType;
/**
* 模拟开始时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime startTime;
/**
* 模拟结束时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime endTime;
}

View File

@ -60,7 +60,7 @@ public class TransportTask{
private Integer taskPprogress;
/**
* 任务状态-1执行失败0未开始1运行中2已完成
* 任务状态-1执行失败0未开始1等待中2运行中3已完成
*/
@Null(message = "任务状态必须为空",groups = {InsertGroup.class, UpdateGroup.class})
@TableField(value = "task_status")

View File

@ -73,6 +73,12 @@ public class TransportTaskBackwardChild {
@TableField(value = "sample_type")
private String sampleType;
/**
* 样品级别
*/
@TableField(value = "sample_category")
private Integer sampleCategory;
/**
* 开始测量时间
*/

View File

@ -24,7 +24,7 @@ public class TransportTaskForwardSpecies {
* 物种id
*/
@TableField(value = "species_id")
private String speciesId;
private Integer speciesId;
/**
* 创建时间

View File

@ -0,0 +1,106 @@
package org.jeecg.modules.base.entity.configuration;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
@Data
@TableName("CONFIGURATION.GARDS_DETECTORS")
public class GardsDetectors implements Serializable {
/**
* 探测器id
*/
@TableId(type = IdType.INPUT)
private Integer detectorId;
/**
* 探测器编码
*/
@TableField(value = "DETECTOR_CODE")
private String detectorCode;
/**
* 经度
*/
@TableField(value = "LON")
private Double lon;
/**
* 纬度
*/
@TableField(value = "LAT")
private Double lat;
/**
* 探测器类型
*/
@TableField(value = "TYPE")
private String type;
/**
* 总道数
*/
@TableField(value = "CHANNELS")
private Double channels;
@TableField(value = "RATED_EFFICIENCY")
private Double ratedEfficiency;
@TableField(value = "RATED_RESOLUTION")
private Double ratedResolution;
/**
* 能量刻度范围keV
*/
@TableField(value = "ECAL_RANGE_MAX")
private Double ecalRangeMax;
/**
* 开始运行日期
*/
@TableField(value = "DATE_BEGIN")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date dateBegin;
/**
* 结束运行日期
*/
@TableField(value = "DATE_END")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date dateEnd;
/**
* Y在运行状态良好N停止
*/
@TableField(value = "STATUS")
private String status;
/**
* 说明
*/
@TableField(value = "DESCRIPTION")
private String description;
/**
* 操作时间
*/
@TableField(value = "MODDATE")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date moddate;
/**
* 台站id
*/
@TableField(value = "STATION_ID")
private Integer stationId;
}

View File

@ -185,7 +185,6 @@ public class GardsSampleData implements Serializable {
@TableField(value = "RNMAN_THRESHOLD")
private String rnmanThreshold;
/**
* 操作时间
*/

View File

@ -0,0 +1,33 @@
package org.jeecg.modules.base.entity.rnauto;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* 存储正演任务结果对应各个气体台站位置的模拟值浓度mBq
*/
@Data
@TableName("RNAUTO.GARDS_STATIONS_MOD_VAL")
public class GardsStationsModVal {
@TableField(value = "TASK_ID")
private Integer taskId;
@TableField(value = "STATION_ID")
private Integer stationId;
@TableField(value = "TIME_SERIES")
private Date timeSeries;
@TableField(value = "CONC")
private Double conc;
@TableField(value = "SPECIES_ID")
private Integer speciesId;
@TableField(value = "MODDATE")
private Date modDate;
}

View File

@ -8,6 +8,9 @@ import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
/**
* 反演任务输运状态记录
*/
@Data
@TableName("RNAUTO.GARDS_TRANSPORT_STATUS")
public class GardsTransportStatus {

View File

@ -0,0 +1,7 @@
package org.jeecg.modules.base.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.modules.base.entity.configuration.GardsDetectors;
public interface GardsDetectorsMapper extends BaseMapper<GardsDetectors>{
}

View File

@ -0,0 +1,7 @@
package org.jeecg.modules.base.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.modules.base.entity.original.GardsSampleData;
public interface GardsSampleDataMapper extends BaseMapper<GardsSampleData> {
}

View File

@ -0,0 +1,7 @@
package org.jeecg.modules.base.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.modules.base.entity.rnauto.GardsStationsModVal;
public interface GardsStationsModValMapper extends BaseMapper<GardsStationsModVal> {
}

View File

@ -40,7 +40,8 @@
SELECT
gwe.SAMPLE_ID as "sampleId",
gs.STATION_CODE as "stationCode",
gsd.ACQUISITION_STOP as "acqEndTime"
gsd.ACQUISITION_STOP as "acqEndTime",
gsd.SAMPLE_TYPE as sampleType
FROM
RNAUTO.GARDS_WAVEFORM_EVENT gwe
INNER JOIN ORIGINAL.GARDS_SAMPLE_DATA gsd ON gwe.SAMPLE_ID = gsd.SAMPLE_ID

View File

@ -5,14 +5,14 @@
<select id="getXeResults" resultType="java.util.Map">
SELECT
gxr.CONC as "obsValue",
gsd.ACQUISITION_START as "acquisitionStart",
gsd.ACQUISITION_STOP as "acquisitionStop"
gsd.COLLECT_START as "collectStart",
gsd.COLLECT_STOP as "collectStop"
FROM
RNAUTO.GARDS_XE_RESULTS gxr
INNER JOIN ORIGINAL.GARDS_SAMPLE_DATA gsd ON gxr.SAMPLE_ID = gsd.SAMPLE_ID
RNAUTO.GARDS_XE_RESULTS_copy1 gxr
INNER JOIN ORIGINAL.GARDS_SAMPLE_DATA_copy1 gsd ON gxr.SAMPLE_ID = gsd.SAMPLE_ID
WHERE
gsd.ACQUISITION_STOP BETWEEN #{startTime}
AND #{endTime}
gsd.COLLECT_START &gt;= #{startTime}
AND gsd.COLLECT_STOP &lt;= #{endTime}
AND gsd.STATION_ID = #{stationId}
AND gsd.DATA_TYPE = 'S'
AND gsd.SPECTRAL_QUALIFIE = 'FULL'

View File

@ -11,6 +11,10 @@ public class GardsSampleInfoVO {
* 样品id
*/
private Integer sampleId;
/**
* 样品类型PB
*/
private String sampleType;
/**
* 台站编码
*/

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-parent</artifactId>
<version>3.8.1</version>
</parent>
<artifactId>jeecg-model-consumer</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-base-core</artifactId>
<version>${jeecgboot.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,44 @@
package org.jeecg.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "server-prop")
public class ServerProperties {
/**
* 当前服务所在IP主机
*/
private String host;
/**
* 使用端口号
*/
private int port;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 172.21.170.11 ip
*/
private String ip11;
/**
* 172.21.170.12 ip
*/
private String ip12;
/**
* 172.21.170.13 ip
*/
private String ip13;
/**
* 172.21.170.14 ip
*/
private String ip14;
}

View File

@ -0,0 +1,120 @@
package org.jeecg.transport.consumer;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson2.JSON;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.consumer.DefaultLitePullConsumer;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.message.MessageExt;
import org.jeecg.common.constant.RocketMQTopConstant;
import org.jeecg.common.properties.DataFusionProperties;
import org.jeecg.common.properties.SystemStorageProperties;
import org.jeecg.common.properties.TransportSimulationProperties;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.base.dto.TransportTaskDTO;
import org.jeecg.modules.base.mapper.*;
import org.jeecg.properties.ServerProperties;
import org.jeecg.transport.consumer.china.AbstractTaskMsgHandler;
import org.jeecg.transport.consumer.china.Server11TaskHandler;
import org.jeecg.transport.service.StationDataService;
import org.jeecg.transport.service.StationsModValService;
import org.jeecg.transport.service.TransportTaskService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
* 异常样品信息消费生成flexpart任务
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class TranTaskMessageConsumerHandler{
private final RedisUtil redisUtil;
private final TransportTaskMapper transportTaskMapper;
private final TransportTaskBackwardChildMapper taskBackwardChildMapper;
private final WeatherDataMapper weatherDataMapper;
private final TransportSimulationProperties simulationProperties;
private final SystemStorageProperties systemStorageProperties;
private final DataFusionProperties dataFusionProperties;
private final ServerProperties serverProperties;
private final TransportTaskForwardSpeciesMapper taskForwardSpeciesMapper;
private final TransportTaskForwardChildMapper taskForwardChildMapper;
private final TransportTaskService transportTaskService;
private final TransportTaskForwardReleaseMapper taskForwardReleaseMapper;
private final StationDataService stationDataService;
private final StationsModValService stationsModValService;
@Value("${rocketmq.consumer.group}")
private String consumerGroup;
@Value("${rocketmq.name-server}")
private String nameServerAddress;
public void startConsumerThread(){
MessageConsumerThread messageConsumerThread = new MessageConsumerThread();
messageConsumerThread.setName("输运模拟任务处理线程");
messageConsumerThread.start();
log.info("启动输运模拟任务处理线程----------------------");
}
private class MessageConsumerThread extends Thread{
@Override
public void run() {
while (true) {
try {
//获取本机项数据如果为空表示本机没有任务在运行
boolean flag = redisUtil.hHasKey(RocketMQTopConstant.HOST_TASK_STATE, serverProperties.getHost());
if (!flag) {
//如果不存在则获取一条消息尝试执行
DefaultLitePullConsumer consumer = new DefaultLitePullConsumer();
try {
consumer.setConsumerGroup(consumerGroup);
consumer.setNamesrvAddr(nameServerAddress);
consumer.setPullBatchSize(1);
consumer.subscribe(RocketMQTopConstant.BACKWARD_TRANSPORT_TASK_TOPIC);
consumer.setAutoCommit(false);
consumer.start();
TransportTaskDTO transportTaskDTO = null;
List<MessageExt> messages = consumer.poll(5000L);
if (CollUtil.isNotEmpty(messages)) {
transportTaskDTO = JSON.parseObject(messages.get(0).getBody(),TransportTaskDTO.class);
boolean matchFlag = handlerTask(transportTaskDTO);
if (matchFlag){
consumer.commit();
}
log.info("消费一条消息:{}",transportTaskDTO);
}
}catch (MQClientException e){
log.error("消费者启动异常,原因为:{}",e.getMessage(),e);
}finally {
consumer.shutdown();
}
}
log.info("30秒钟处理一次");
TimeUnit.SECONDS.sleep(30);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
/**
* 处理输运模拟任务
*/
private boolean handlerTask(TransportTaskDTO message){
AbstractTaskMsgHandler taskMsgHandler = new Server11TaskHandler();
taskMsgHandler.init(transportTaskMapper,taskBackwardChildMapper,weatherDataMapper,
simulationProperties,systemStorageProperties,dataFusionProperties,
serverProperties,taskForwardSpeciesMapper,taskForwardChildMapper,
transportTaskService,taskForwardReleaseMapper,stationDataService,
stationsModValService);
taskMsgHandler.handler(message);
return taskMsgHandler.isMatchFlag();
}
}
}

View File

@ -0,0 +1,32 @@
package org.jeecg.transport.consumer.china;
import lombok.Getter;
import lombok.Setter;
/**
* 能谱执行链路
*/
public abstract class AbstractChain {
/**
* 上一任处理链
*/
@Setter
protected AbstractTaskMsgHandler previous;
/**
* 下一任处理链
*/
@Setter
protected AbstractTaskMsgHandler next;
/**
* 设置过滤器链
*/
protected abstract void setChina();
/**
* 是否匹配成功
*/
protected boolean matchFlag = false;
}

View File

@ -0,0 +1,138 @@
package org.jeecg.transport.consumer.china;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.enums.TransportTaskModeEnum;
import org.jeecg.common.properties.DataFusionProperties;
import org.jeecg.common.properties.SystemStorageProperties;
import org.jeecg.common.properties.TransportSimulationProperties;
import org.jeecg.modules.base.dto.TransportTaskDTO;
import org.jeecg.modules.base.mapper.*;
import org.jeecg.properties.ServerProperties;
import org.jeecg.transport.flexparttask.AbstractTaskExec;
import org.jeecg.transport.flexparttask.BackwardTaskExec;
import org.jeecg.transport.flexparttask.ForwardTaskExec;
import org.jeecg.transport.service.StationDataService;
import org.jeecg.transport.service.StationsModValService;
import org.jeecg.transport.service.TransportTaskService;
import java.util.Objects;
/**
* 处理任务策略父类
*/
@Slf4j
public abstract class AbstractTaskMsgHandler extends AbstractChain{
protected TransportTaskMapper transportTaskMapper;
protected TransportTaskBackwardChildMapper taskBackwardChildMapper;
protected WeatherDataMapper weatherDataMapper;
protected TransportSimulationProperties simulationProperties;
protected SystemStorageProperties systemStorageProperties;
protected DataFusionProperties dataFusionProperties;
protected ServerProperties serverProperties;
protected TransportTaskForwardSpeciesMapper taskForwardSpeciesMapper;
protected TransportTaskForwardChildMapper taskForwardChildMapper;
protected TransportTaskService transportTaskService;
protected TransportTaskForwardReleaseMapper taskForwardReleaseMapper;
protected StationDataService stationDataService;
protected StationsModValService stationsModValService;
/**
* 初始化bean引用
*/
public void init(TransportTaskMapper transportTaskMapper,
TransportTaskBackwardChildMapper taskBackwardChildMapper,
WeatherDataMapper weatherDataMapper,
TransportSimulationProperties simulationProperties,
SystemStorageProperties systemStorageProperties,
DataFusionProperties dataFusionProperties,
ServerProperties serverProperties,
TransportTaskForwardSpeciesMapper taskForwardSpeciesMapper,
TransportTaskForwardChildMapper taskForwardChildMapper,
TransportTaskService transportTaskService,
TransportTaskForwardReleaseMapper taskForwardReleaseMapper,
StationDataService stationDataService,
StationsModValService stationsModValService) {
this.transportTaskMapper = transportTaskMapper;
this.taskBackwardChildMapper = taskBackwardChildMapper;
this.weatherDataMapper = weatherDataMapper;
this.simulationProperties = simulationProperties;
this.systemStorageProperties = systemStorageProperties;
this.dataFusionProperties = dataFusionProperties;
this.serverProperties = serverProperties;
this.taskForwardSpeciesMapper = taskForwardSpeciesMapper;
this.taskForwardChildMapper = taskForwardChildMapper;
this.transportTaskService = transportTaskService;
this.taskForwardReleaseMapper = taskForwardReleaseMapper;
this.stationDataService = stationDataService;
this.stationsModValService = stationsModValService;
this.setChina();
}
/**
* 初始化下个节点
* @param serverProperties
*/
protected void initNext(ServerProperties serverProperties){
this.serverProperties = serverProperties;
this.setChina();
}
/**
* 处理消息
*/
public abstract void handler(TransportTaskDTO message);
/**
* 设置匹配标记
* @param matchFlag
*/
protected void setMatchFlag(boolean matchFlag) {
this.matchFlag = matchFlag;
if (Objects.nonNull(this.previous)) {
this.previous.setMatchFlag(matchFlag);
}
}
/**
* 获取匹配标记
* @return
*/
public boolean isMatchFlag() {
return this.matchFlag;
}
/**
* 运行任务
* @param transportTaskDTO
*/
protected void runTask(TransportTaskDTO transportTaskDTO){
log.info("运行任务测试");
if (TransportTaskModeEnum.BACK_FORWARD.getKey().equals(transportTaskDTO.getTaskMode())){
AbstractTaskExec taskExec = new BackwardTaskExec();
taskExec.init(weatherDataMapper,transportTaskService,transportTaskDTO,
simulationProperties,systemStorageProperties,
dataFusionProperties,serverProperties,taskBackwardChildMapper);
taskExec.setName("大气输运反演任务执行线程");
//匹配成功并且检查成功才能设置为true
boolean flag = taskExec.checkTask();
if (flag){
this.setMatchFlag(true);
taskExec.start();
}
}else if (TransportTaskModeEnum.FORWARD.getKey().equals(transportTaskDTO.getTaskMode())){
AbstractTaskExec taskExec = new ForwardTaskExec();
taskExec.init(weatherDataMapper,transportTaskService,transportTaskDTO,
simulationProperties,systemStorageProperties,serverProperties,
stationDataService,stationsModValService,taskForwardSpeciesMapper,
taskForwardChildMapper,taskForwardReleaseMapper);
taskExec.setName("大气输运正演任务执行线程");
//匹配成功并且检查成功才能设置为true
boolean flag = taskExec.checkTask();
if (flag){
this.setMatchFlag(true);
taskExec.start();
}
taskExec.start();
}
}
}

View File

@ -0,0 +1,36 @@
package org.jeecg.transport.consumer.china;
import org.jeecg.common.constant.enums.TransportTaskModeEnum;
import org.jeecg.modules.base.dto.TransportTaskDTO;
/**
* 只处理反演任务
*/
public class Server11TaskHandler extends AbstractTaskMsgHandler {
/**
* 设置过滤器链
*/
@Override
protected void setChina() {
AbstractTaskMsgHandler taskHandler = new Server12TaskHandler();
taskHandler.initNext(super.serverProperties);
taskHandler.setPrevious(this);
super.setNext(taskHandler);
}
/**
* 处理消息
*/
@Override
public void handler(TransportTaskDTO message) {
if(serverProperties.getHost().equals(serverProperties.getIp11())){
if (TransportTaskModeEnum.BACK_FORWARD.getKey().equals(message.getTaskMode())){
super.runTask(message);
}
}else {
super.next.handler(message);
}
}
}

View File

@ -0,0 +1,32 @@
package org.jeecg.transport.consumer.china;
import org.jeecg.modules.base.dto.TransportTaskDTO;
/**
* 处理反演和正演任务
*/
public class Server12TaskHandler extends AbstractTaskMsgHandler {
/**
* 设置过滤器链
*/
@Override
protected void setChina() {
AbstractTaskMsgHandler taskHandler = new Server13TaskHandler();
taskHandler.initNext(super.serverProperties);
taskHandler.setPrevious(this);
super.setNext(taskHandler);
}
/**
* 处理消息
*/
@Override
public void handler(TransportTaskDTO message) {
if(serverProperties.getHost().equals(serverProperties.getIp12())){
super.runTask(message);
}else {
super.next.handler(message);
}
}
}

View File

@ -0,0 +1,32 @@
package org.jeecg.transport.consumer.china;
import org.jeecg.modules.base.dto.TransportTaskDTO;
/**
* 处理反演和正演任务
*/
public class Server13TaskHandler extends AbstractTaskMsgHandler {
/**
* 设置过滤器链
*/
@Override
protected void setChina() {
AbstractTaskMsgHandler taskHandler = new Server14TaskHandler();
taskHandler.initNext(super.serverProperties);
taskHandler.setPrevious(this);
super.setNext(taskHandler);
}
/**
* 处理消息
*/
@Override
public void handler(TransportTaskDTO message) {
if(serverProperties.getHost().equals(serverProperties.getIp13())){
super.runTask(message);
}else {
super.next.handler(message);
}
}
}

View File

@ -0,0 +1,30 @@
package org.jeecg.transport.consumer.china;
import org.jeecg.modules.base.dto.TransportTaskDTO;
/**
* 处理反演和永久型正演任务
*/
public class Server14TaskHandler extends AbstractTaskMsgHandler {
/**
* 设置过滤器链
*/
@Override
protected void setChina() {
}
/**
* 处理消息
*/
@Override
public void handler(TransportTaskDTO message) {
if(serverProperties.getHost().equals(serverProperties.getIp14())){
//这里需要再加个判断14服务器处理反演和永久任务
// if (TransportTaskModeEnum.BACK_FORWARD.getKey().equals(message.getTaskMode())){
// super.runTask(message);
// }
}
}
}

View File

@ -1,6 +1,9 @@
package org.jeecg.task.flexparttask;
package org.jeecg.transport.flexparttask;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
@ -11,13 +14,17 @@ import org.jeecg.common.constant.enums.WeatherDataSourceEnum;
import org.jeecg.common.properties.DataFusionProperties;
import org.jeecg.common.properties.SystemStorageProperties;
import org.jeecg.common.properties.TransportSimulationProperties;
import org.jeecg.modules.base.dto.TransportTaskDTO;
import org.jeecg.modules.base.entity.TransportTask;
import org.jeecg.modules.base.entity.TransportTaskBackwardChild;
import org.jeecg.modules.base.mapper.WeatherDataMapper;
import org.jeecg.modules.base.entity.WeatherData;
import org.jeecg.modules.base.mapper.*;
import org.jeecg.properties.ServerProperties;
import org.jeecg.service.TransportTaskService;
import org.jeecg.transport.service.StationDataService;
import org.jeecg.transport.service.StationsModValService;
import org.jeecg.transport.service.TransportTaskService;
import java.io.*;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Properties;
@ -25,28 +32,44 @@ public abstract class AbstractTaskExec extends Thread{
protected WeatherDataMapper weatherDataMapper;
protected TransportTaskService transportTaskService;
protected TransportTask transportTask;
protected List<TransportTaskBackwardChild> transportTaskChildren;
protected TransportSimulationProperties simulationProperties;
protected SystemStorageProperties systemStorageProperties;
protected DataFusionProperties dataFusionProperties;
protected ServerProperties serverProperties;
protected StationDataService stationDataService;
protected StationsModValService stationsModValService;
protected TransportTaskForwardSpeciesMapper taskForwardSpeciesMapper;
protected TransportTaskForwardChildMapper taskForwardChildMapper;
protected TransportTaskForwardReleaseMapper taskForwardReleaseMapper;
protected TransportTaskBackwardChildMapper taskBackwardChildMapper;
protected TransportTask transportTask;
protected TransportTaskDTO transportTaskDTO;
/**
* 初始化
*/
public void init(WeatherDataMapper weatherDataMapper,
TransportTaskService transportTaskService,
TransportTask transportTask,
TransportTaskDTO transportTaskDTO,
TransportSimulationProperties simulationProperties,
SystemStorageProperties systemStorageProperties,
ServerProperties serverProperties){
ServerProperties serverProperties,
StationDataService stationDataService,
StationsModValService stationsModValService,
TransportTaskForwardSpeciesMapper taskForwardSpeciesMapper,
TransportTaskForwardChildMapper taskForwardChildMapper,
TransportTaskForwardReleaseMapper taskForwardReleaseMapper){
this.weatherDataMapper = weatherDataMapper;
this.transportTaskService = transportTaskService;
this.transportTask = transportTask;
this.transportTaskDTO = transportTaskDTO;
this.simulationProperties = simulationProperties;
this.systemStorageProperties = systemStorageProperties;
this.serverProperties = serverProperties;
this.stationsModValService = stationsModValService;
this.stationDataService = stationDataService;
this.taskForwardSpeciesMapper = taskForwardSpeciesMapper;
this.taskForwardChildMapper = taskForwardChildMapper;
this.taskForwardReleaseMapper = taskForwardReleaseMapper;
}
/**
@ -54,28 +77,52 @@ public abstract class AbstractTaskExec extends Thread{
*/
public void init(WeatherDataMapper weatherDataMapper,
TransportTaskService transportTaskService,
TransportTask transportTask,
List<TransportTaskBackwardChild> transportTaskChildren,
TransportTaskDTO transportTaskDTO,
TransportSimulationProperties simulationProperties,
SystemStorageProperties systemStorageProperties,
DataFusionProperties dataFusionProperties,
ServerProperties serverProperties){
ServerProperties serverProperties,
TransportTaskBackwardChildMapper taskBackwardChildMapper){
this.weatherDataMapper = weatherDataMapper;
this.transportTaskService = transportTaskService;
this.transportTask = transportTask;
this.transportTaskDTO = transportTaskDTO;
this.simulationProperties = simulationProperties;
this.systemStorageProperties = systemStorageProperties;
this.transportTaskChildren = transportTaskChildren;
this.dataFusionProperties = dataFusionProperties;
this.serverProperties = serverProperties;
this.taskBackwardChildMapper = taskBackwardChildMapper;
}
public abstract boolean checkTask();
public abstract void execute();
protected abstract void checkMetData();
protected abstract void execSimulation();
/**
* 检查气象数据
*/
protected boolean checkMetData(List<String> msgList){
String msg = "检查气象数据";
ProgressQueue.getInstance().offer(new ProgressEvent(this.transportTask.getId(),msg));
LocalDateTime startTime = this.transportTask.getStartTime();
LocalDateTime endTime = this.transportTask.getEndTime();
LambdaQueryWrapper<WeatherData> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(WeatherData::getDataSource,this.transportTask.getUseMetType());
queryWrapper.between(WeatherData::getDataStartTime,startTime,endTime);
List<WeatherData> dataList = this.weatherDataMapper.selectList(queryWrapper);
long hours = ChronoUnit.HOURS.between(startTime, endTime)/6;
//一天至少4个气象数据至少是00,06,12,18
if(CollUtil.isEmpty(dataList) || dataList.size() < hours){
String exceptionMsg = "此任务时间范围(%s - %s)参数所涉及的气象数据不完整,请核对气象数据";
String formatMsg = String.format(exceptionMsg, LocalDateTimeUtil.format(startTime, "yyyy-MM-dd hh:mm:ss"), LocalDateTimeUtil.format(endTime, "yyyy-MM-dd hh:mm:ss"));
msgList.add(formatMsg);
return false;
}
return true;
}
/**
* 获取气象数据路径
* @param dataSource
@ -160,22 +207,24 @@ public abstract class AbstractTaskExec extends Thread{
/**
* 登录
*
* @param host
* @param port
* @param username
* @param password
* @return
* @throws JSchException
*/
protected Session login(String host,int port,String username,String password) throws JSchException {
protected void login(String host, int port, String username, String password) throws JSchException {
Properties config = new Properties();
config.put("StrictHostKeyChecking","no");
session = jsch.getSession(username, host, port);
session.setPassword(password);
session.setConfig(config);
session.setServerAliveInterval(30);
session.setServerAliveCountMax(3);
session.setTimeout(0);
session.connect();
return session;
}
/**

View File

@ -1,7 +1,6 @@
package org.jeecg.task.flexparttask;
package org.jeecg.transport.flexparttask;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang3.time.StopWatch;
@ -10,24 +9,74 @@ import org.jeecg.common.constant.enums.FlexpartSpeciesType;
import org.jeecg.common.constant.enums.TransportTaskStatusEnum;
import org.jeecg.common.constant.enums.WeatherDataSourceEnum;
import org.jeecg.modules.base.entity.*;
import java.io.*;
import java.io.File;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
public class BackwardTaskExec extends AbstractTaskExec{
/**
* 反演任务线程
*/
public class BackwardTaskExec extends AbstractTaskExec {
@Override
public void run() {
this.execute();
}
/**
* 检查任务数据是否满足运行条件
* @return
*/
@Override
public boolean checkTask() {
//校验任务
AtomicBoolean flag = new AtomicBoolean(true);
List<String> msgList = new ArrayList<>();
super.transportTask = this.transportTaskService.getById(super.transportTaskDTO.getId());
//查询站点信息
LambdaQueryWrapper<TransportTaskBackwardChild> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TransportTaskBackwardChild::getTaskId,super.transportTaskDTO.getId());
queryWrapper.orderByAsc(TransportTaskBackwardChild::getId);
List<TransportTaskBackwardChild> transportTaskChildren = super.taskBackwardChildMapper.selectList(queryWrapper);
if(CollUtil.isEmpty(transportTaskChildren)){
msgList.add("配置信息缺失,请确认");
flag.set(false);
}else {
super.transportTask.setBackwardChild(transportTaskChildren);
}
transportTaskChildren.forEach(taskBackwardChild -> {
if(taskBackwardChild.getAcqStartTime().isAfter(taskBackwardChild.getAcqEndTime())){
msgList.add(taskBackwardChild.getStationCode()+"站点,样品测量开始时间不能在结束时间之后,请确认");
flag.set(false);
}
if(taskBackwardChild.getAcqStartTime().isAfter(super.transportTask.getEndTime())){
msgList.add(taskBackwardChild.getStationCode()+"站点,样品测量结束时间不能在任务模拟结束时间之后,请确认");
flag.set(false);
}
if(taskBackwardChild.getAcqStartTime().isBefore(super.transportTask.getStartTime())){
msgList.add(taskBackwardChild.getStationCode()+"站点,样品测量开始时间不能在任务模拟开始时间之前,请确认");
flag.set(false);
}
});
//检查气象数据
flag.set(super.checkMetData(msgList));
if (!flag.get()) {
if (CollUtil.isNotEmpty(msgList)) {
msgList.forEach(msg->{
ProgressQueue.getInstance().offer(new ProgressEvent(super.transportTask.getId(),msg));
});
}
}
ProgressQueue.getInstance().offer(new ProgressEvent(super.transportTask.getId(),"任务前置条件检查完毕"));
return flag.get();
}
/**
* 执行任务
*/
@ -39,12 +88,10 @@ public class BackwardTaskExec extends AbstractTaskExec{
super.transportTaskService.updateTaskStatus(super.transportTask.getId(), TransportTaskStatusEnum.IN_OPERATION.getValue());
//如果此任务已存在历史日志先清除
super.transportTaskService.deleteTaskLog(super.transportTask.getId());
//检查气象数据
this.checkMetData();
//执行模拟
this.execSimulation();
//生成SRS文件
// this.generateSRSFile();
this.generateSRSFile();
}catch (Exception e){
String taskErrorLog = "任务执行失败,原因:"+e.getMessage();
ProgressQueue.getInstance().offer(new ProgressEvent(super.transportTask.getId(),taskErrorLog));
@ -63,31 +110,6 @@ public class BackwardTaskExec extends AbstractTaskExec{
}
}
/**
* 检查气象数据
*/
protected void checkMetData(){
String msg = "检查气象数据";
ProgressQueue.getInstance().offer(new ProgressEvent(super.transportTask.getId(),msg));
LocalDateTime startTime = super.transportTask.getStartTime();
LocalDateTime endTime = super.transportTask.getEndTime();
LambdaQueryWrapper<WeatherData> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(WeatherData::getDataSource,super.transportTask.getUseMetType());
queryWrapper.between(WeatherData::getDataStartTime,startTime,endTime);
List<WeatherData> dataList = super.weatherDataMapper.selectList(queryWrapper);
long hours = ChronoUnit.HOURS.between(startTime, endTime)/6;
//一天至少4个气象数据至少是00,06,12,18
if(CollUtil.isEmpty(dataList) || dataList.size() < hours){
String exceptionMsg = "此任务时间范围(%s - %s)参数所涉及的气象数据不完整,请核对气象数据";
String formatMsg = String.format(exceptionMsg, LocalDateTimeUtil.format(startTime, "yyyy-MM-dd hh:mm:ss"), LocalDateTimeUtil.format(endTime, "yyyy-MM-dd hh:mm:ss"));
ProgressQueue.getInstance().offer(new ProgressEvent(super.transportTask.getId(),formatMsg));
throw new RuntimeException(formatMsg);
}
String finalMsg = "检查气象数据完毕";
ProgressQueue.getInstance().offer(new ProgressEvent(super.transportTask.getId(),finalMsg));
}
/**
* 执行模拟
*/
@ -112,7 +134,7 @@ public class BackwardTaskExec extends AbstractTaskExec{
paramContent.append(super.transportTask.getZ2()).append("\n");
paramContent.append(metDataPath).append("\n");
paramContent.append(super.simulationProperties.getOutputPath()+File.separator+super.transportTask.getTaskName()).append("\n");
paramContent.append(FlexpartSpeciesType.NOT_SPECIES.getValue()).append("\n");//反演固定61不显示具体核素只显示Xe
paramContent.append(FlexpartSpeciesType.NOT_SPECIES.getId()).append("\n");//反演固定61不显示具体核素只显示Xe
FileUtil.writeString(paramContent.toString(),paramConfigPath,"UTF-8");
//处理台站数据文件
List<String> stationConfigInfo = new ArrayList<>();
@ -120,7 +142,7 @@ public class BackwardTaskExec extends AbstractTaskExec{
if(!FileUtil.exist(stationsConfigPath)){
FileUtil.touch(stationsConfigPath);
}
super.transportTaskChildren.forEach(taskChild -> {
super.transportTask.getBackwardChild().forEach(taskChild -> {
String format = "%s,%f,%f,%s,%s,%s,%s,%s";
BigDecimal srcReleaseAmount = new BigDecimal(taskChild.getReleaseAmount());
BigDecimal constant = new BigDecimal("1000");
@ -178,7 +200,7 @@ public class BackwardTaskExec extends AbstractTaskExec{
* 生成SRS文件
*/
private void generateSRSFile(){
for (TransportTaskBackwardChild transportTaskChild : this.transportTaskChildren){
for (TransportTaskBackwardChild transportTaskChild : super.transportTask.getBackwardChild()){
BuildNcToSrsFile ncToSrsFile = new BuildNcToSrsFile();
ncToSrsFile.init(dataFusionProperties,simulationProperties,transportTask,transportTaskChild,transportTaskChild.getReleaseAmount());
ncToSrsFile.execute();

View File

@ -1,4 +1,4 @@
package org.jeecg.task.flexparttask;
package org.jeecg.transport.flexparttask;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;

View File

@ -0,0 +1,223 @@
package org.jeecg.transport.flexparttask;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import lombok.extern.slf4j.Slf4j;
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.rnauto.GardsStationsModVal;
import org.jeecg.modules.base.mapper.TransportTaskMapper;
import org.jeecg.transport.service.StationDataService;
import org.jeecg.transport.service.StationsModValService;
import org.jeecg.transport.service.TransportTaskService;
import org.jeecg.transport.util.BilinearInterpolatorWithMath;
import ucar.ma2.Array;
import ucar.ma2.DataType;
import ucar.ma2.InvalidRangeException;
import ucar.nc2.NetcdfFile;
import ucar.nc2.Variable;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
/**
* 处理符合度分析
*/
@Slf4j
public class ConformityAnalysis {
private Integer taskId;
private StationDataService stationDataService;
private TransportTaskMapper transportTaskMapper;
private TransportSimulationProperties simulationProperties;
private StationsModValService stationsModValService;
private TransportTaskService transportTaskService;
/**
* 初始化符合度分析需要的数据
* @param taskId
* @param transportTaskMapper
* @param stationDataService
*/
public void init(Integer taskId,TransportTaskMapper transportTaskMapper,
StationDataService stationDataService,
TransportSimulationProperties simulationProperties,
StationsModValService stationsModValService,
TransportTaskService transportTaskService){
this.taskId = taskId;
this.transportTaskMapper = transportTaskMapper;
this.stationDataService = stationDataService;
this.simulationProperties = simulationProperties;
this.stationsModValService = stationsModValService;
this.transportTaskService = transportTaskService;
}
public void exec(){
TransportTask transportTask = transportTaskMapper.selectById(taskId);
if(Objects.isNull(transportTask)){
log.error("此任务不存在,符合度分析执行结束");
return;
}
Map<Integer, String> taskSimulationSpecies = transportTaskService.getTaskSimulationSpecies(taskId);
if(CollUtil.isEmpty(taskSimulationSpecies)){
log.error("此任务物种信息不存在,符合度分析执行结束");
}
//处理模拟结果不同物种对应的结果
taskSimulationSpecies.forEach((speciesId,speciesName)->{
//获取nc文件路径
String path = this.getForwardTaskNCPath(transportTask,speciesId);
if (!FileUtil.exist(path)) {
log.error("此任务模拟结果文件不存在,符合度分析执行结束");
}
//查询台站信息
List<Map<String,Object>> stationsMap = this.stationDataService.getAllGasStations();
try (NetcdfFile ncFile = NetcdfFile.open(path.toString())) {
//找到最接近台站经纬度的值作为对比点位
List<Double> lonData = NcUtil.getNCList(ncFile, "longitude");
List<Double> latData = NcUtil.getNCList(ncFile, "latitude");
List<Double> timeData = NcUtil.getNCList(ncFile, "time");
Variable spec001Mr = ncFile.findVariable("spec001_mr");
Map<Integer,Map<LocalDateTime,Double>> allResult = new LinkedHashMap<>();
for (Map<String,Object> station:stationsMap) {
Integer stationId = Integer.parseInt(station.get("id").toString());
Double lon = Double.parseDouble(station.get("lon").toString());
Double lat = Double.parseDouble(station.get("lat").toString());
Map<LocalDateTime,Double> concMap = this.getTargetSiteConc(lonData,latData,lon,lat,transportTask.getStartTime(),timeData,spec001Mr);
allResult.put(stationId,concMap);
}
//保存模拟值
this.saveModVal(transportTask.getId(),speciesId,allResult);
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
/**
* 在步长为 0.25° 的递增经纬度数组中查找指定位置的索引
* - lons[0] 是起始经度
* - 步长严格为 0.25
* - target 一定存在
*/
private int findTargetIndex(List<Double> datas, double target) {
// 计算偏移量单位0.25°
double offset = (target - datas.get(0)) / 0.25;
// 四舍五入取整抵抗浮点误差 166.5 - 166.0 = 0.5000000001 2.000...
int index = (int) Math.round(offset);
// 安全检查可选
if (index < 0 || index >= datas.size() || Math.abs(datas.get(index) - target) > 1e-5) {
System.out.println(datas);
throw new IllegalArgumentException("经度 " + target + " 不在数组中");
}
return index;
}
/**
* 获取指定位置的浓度数据
* @param lonData nc文件的经度数据
* @param latData nc文件的纬度数据
* @param targetLon 目标位置的经度
* @param targetLat 目标位置的纬度
* @param spec001Mr nc文件浓度数据变量
* @return
* @throws InvalidRangeException
* @throws IOException
*/
private Map<LocalDateTime,Double> getTargetSiteConc(List<Double> lonData, List<Double> latData, Double targetLon, Double targetLat, LocalDateTime startTime, List<Double> timeData, Variable spec001Mr) throws InvalidRangeException, IOException {
Map<LocalDateTime,Double> concMap = new LinkedHashMap<>();
int lonIndex = this.findTargetIndex(lonData, targetLon.intValue()-0.125);
int latIndex = this.findTargetIndex(latData, targetLat.intValue()-0.125);
for (int t = 0; t < timeData.size(); t++) {
LocalDateTime newDateTime = startTime.plusSeconds(timeData.get(t).intValue());
//nageclass=1, pointspec=1, time=30, height=6, latitude=710, longitude=1430
int[] origin = {0,0,t,0, (latIndex-6),(lonIndex-6)};
int[] section = {1, 1,1,1,12,12};
Array levelData = spec001Mr.read(origin,section);
double[] pointData = (double[]) levelData.get1DJavaArray(DataType.DOUBLE);
Map<BilinearInterpolatorWithMath.Point,Double> siteData = new LinkedHashMap<>();
int nlon_patch = 12,patchLatStart = latIndex - 6,patchLonStart = lonIndex - 6;
for(int i=0;i<pointData.length;i++){
int iy_patch = i / nlon_patch; // 在子区域内的纬度偏移0~11
int ix_patch = i % nlon_patch; // 在子区域内的经度偏移0~11
// 转为全局索引用于查 lonData/latData
int global_iy = patchLatStart + iy_patch;
int global_ix = patchLonStart + ix_patch;
// 获取真实经纬度
double lon = lonData.get(global_ix);
double lat = latData.get(global_iy);
BilinearInterpolatorWithMath.Point point = new BilinearInterpolatorWithMath.Point(lon,lat);
siteData.put(point,pointData[i]);
}
BilinearInterpolatorWithMath.GridData grid = new BilinearInterpolatorWithMath.GridData(siteData, 0.25, 0.125);
Double interpolate = grid.interpolate(targetLon, targetLat);
if(interpolate > 0){
BigDecimal bg = new BigDecimal(interpolate.toString());
BigDecimal value = bg.divide(BigDecimal.valueOf(1000000),6, RoundingMode.HALF_UP);
concMap.put(newDateTime,value.doubleValue());
}else {
concMap.put(newDateTime,interpolate);
}
}
return concMap;
}
/**
* 获取正演NC结果文件路径
* @param transportTask
* @return
*/
private String getForwardTaskNCPath(TransportTask transportTask,Integer speciesId){
//拼接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(speciesId);
path.append(File.separator);
path.append("grid_conc_"+ DateUtil.format(transportTask.getStartTime(),"yyyyMMddHHmmss")+".nc");
return path.toString();
}
/**
* 保存正演结果对应的各气体站点模拟值
* @param modValMap
*/
private void saveModVal(Integer taskId,Integer speciesId,Map<Integer,Map<LocalDateTime,Double>> modValMap){
try{
if(CollUtil.isNotEmpty(modValMap)){
List<GardsStationsModVal> modValList = new ArrayList<>();
modValMap.forEach((stationId,modVal)->{
modVal.forEach((time,conc)->{
Date timeSeries = Date.from(time.atZone(ZoneId.systemDefault()).toInstant());
GardsStationsModVal stationsModVal = new GardsStationsModVal();
stationsModVal.setTaskId(taskId);
stationsModVal.setStationId(stationId);
stationsModVal.setModDate(new Date());
stationsModVal.setConc(conc);
stationsModVal.setSpeciesId(speciesId);
stationsModVal.setTimeSeries(timeSeries);
modValList.add(stationsModVal);
});
});
if(CollUtil.isNotEmpty(modValList)){
stationsModValService.saveStationsModVal(modValList);
}
}
}catch (Exception e){
log.error("保存正演结果对应的各气体站点模拟值出现异常");
}
}
}

View File

@ -1,7 +1,6 @@
package org.jeecg.task.flexparttask;
package org.jeecg.transport.flexparttask;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang3.time.StopWatch;
@ -13,19 +12,87 @@ import java.io.File;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
public class ForwardTaskExec extends AbstractTaskExec{
/**
* 正演任务线程
*/
public class ForwardTaskExec extends AbstractTaskExec {
@Override
public void run() {
this.execute();
}
/**
* 检查任务数据是否满足运行条件
* @return
*/
@Override
public boolean checkTask() {
//校验任务
AtomicBoolean flag = new AtomicBoolean(true);
List<String> msgList = new ArrayList<>();
super.transportTask = this.transportTaskService.getById(super.transportTaskDTO.getId());
//查询站点信息
LambdaQueryWrapper<TransportTaskForwardChild> siteQueryWrapper = new LambdaQueryWrapper<>();
siteQueryWrapper.eq(TransportTaskForwardChild::getTaskId,transportTask.getId());
List<TransportTaskForwardChild> stationInfoList = super.taskForwardChildMapper.selectList(siteQueryWrapper);
if (CollUtil.isEmpty(stationInfoList)) {
msgList.add("站点配置信息缺失,请确认");
flag.set(false);
}else {
super.transportTask.setForwardChild(stationInfoList);
}
//查询物种
LambdaQueryWrapper<TransportTaskForwardSpecies> speciesQueryWrapper = new LambdaQueryWrapper<>();
speciesQueryWrapper.eq(TransportTaskForwardSpecies::getTaskId,transportTask.getId());
List<TransportTaskForwardSpecies> species = super.taskForwardSpeciesMapper.selectList(speciesQueryWrapper);
if (CollUtil.isEmpty(species)) {
msgList.add("物种配置信息缺失,请确认");
flag.set(false);
}else {
super.transportTask.setSpecies(species);
}
//查询站点释放信息
LambdaQueryWrapper<TransportTaskForwardRelease> releaseQueryWrapper = new LambdaQueryWrapper<>();
releaseQueryWrapper.eq(TransportTaskForwardRelease::getTaskId,transportTask.getId());
List<TransportTaskForwardRelease> releaseInfo = super.taskForwardReleaseMapper.selectList(releaseQueryWrapper);
if (CollUtil.isEmpty(releaseInfo)) {
msgList.add("站点释放信息缺失,请确认");
flag.set(false);
}else {
if (CollUtil.isNotEmpty(stationInfoList)) {
Map<Integer, List<TransportTaskForwardRelease>> releaseMap = releaseInfo.parallelStream().collect(Collectors.groupingBy(TransportTaskForwardRelease::getForwardChildId));
stationInfoList.forEach(stationInfo->{
List<TransportTaskForwardRelease> stationReleases = releaseMap.get(stationInfo.getId());
if (CollUtil.isEmpty(stationReleases)) {
msgList.add(stationInfo.getStationCode()+"站点释放信息缺失,请确认");
flag.set(false);
}else {
List<TransportTaskForwardRelease> sortStationReleases = stationReleases.stream().sorted(Comparator.comparing(TransportTaskForwardRelease::getStartTime)).collect(Collectors.toList());
stationInfo.setForwardReleaseChild(sortStationReleases);
}
});
}
}
//检查气象数据
flag.set(super.checkMetData(msgList));
if (!flag.get()) {
if (CollUtil.isNotEmpty(msgList)) {
msgList.forEach(msg->{
ProgressQueue.getInstance().offer(new ProgressEvent(super.transportTask.getId(),msg));
});
}
}
ProgressQueue.getInstance().offer(new ProgressEvent(super.transportTask.getId(),"任务前置条件检查完毕"));
return flag.get();
}
/**
* 执行任务
*/
@ -37,10 +104,13 @@ public class ForwardTaskExec extends AbstractTaskExec{
super.transportTaskService.updateTaskStatus(super.transportTask.getId(), TransportTaskStatusEnum.IN_OPERATION.getValue());
//如果此任务已存在历史日志先清除
super.transportTaskService.deleteTaskLog(super.transportTask.getId());
//检查气象数据
// this.checkMetData();
//执行模拟
this.execSimulation();
//解析各气体台站对应的模拟值存储入库
// ConformityAnalysis conformityAnalysis = new ConformityAnalysis();
// conformityAnalysis.init(transportTask.getId(),transportTaskMapper,
// stationDataService,simulationProperties,stationsModValService,transportTaskService);
// conformityAnalysis.exec();
}catch (Exception e){
String taskErrorLog = "任务执行失败,原因:"+e.getMessage();
ProgressQueue.getInstance().offer(new ProgressEvent(super.transportTask.getId(),taskErrorLog));
@ -59,31 +129,6 @@ public class ForwardTaskExec extends AbstractTaskExec{
}
}
/**
* 检查气象数据
*/
protected void checkMetData(){
String msg = "检查气象数据";
ProgressQueue.getInstance().offer(new ProgressEvent(this.transportTask.getId(),msg));
LocalDateTime startTime = super.transportTask.getStartTime();
LocalDateTime endTime = super.transportTask.getEndTime();
LambdaQueryWrapper<WeatherData> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(WeatherData::getDataSource,super.transportTask.getUseMetType());
queryWrapper.between(WeatherData::getDataStartTime,startTime,endTime);
List<WeatherData> dataList = super.weatherDataMapper.selectList(queryWrapper);
long hours = ChronoUnit.HOURS.between(startTime, endTime)/6;
//一天至少4个气象数据至少是00,06,12,18
if(CollUtil.isEmpty(dataList) || dataList.size() < hours){
String exceptionMsg = "此任务时间范围(%s - %s)参数所涉及的气象数据不完整,请核对气象数据";
String formatMsg = String.format(exceptionMsg, LocalDateTimeUtil.format(startTime, "yyyy-MM-dd hh:mm:ss"), LocalDateTimeUtil.format(endTime, "yyyy-MM-dd hh:mm:ss"));
ProgressQueue.getInstance().offer(new ProgressEvent(super.transportTask.getId(),formatMsg));
throw new RuntimeException(formatMsg);
}
String finalMsg = "检查气象数据完毕";
ProgressQueue.getInstance().offer(new ProgressEvent(super.transportTask.getId(),finalMsg));
}
/**
* 执行模拟
*/
@ -120,7 +165,7 @@ public class ForwardTaskExec extends AbstractTaskExec{
for(int i=0;i<species.size();i++){
paramContent.append(species.get(i).getSpeciesId());
if (i != species.size()-1){
paramContent.append(",");
paramContent.append(" ");
}else {
paramContent.append("\n");
}
@ -189,11 +234,11 @@ public class ForwardTaskExec extends AbstractTaskExec{
String execScriptMsg = "执行任务脚本,开始模拟,路径为:"+scriptPath;
ProgressQueue.getInstance().offer(new ProgressEvent(super.transportTask.getId(),execScriptMsg));
//ssh连接宿主机调用flexpart
// JSchRemoteRunner jschRemoteRunner = new JSchRemoteRunner();
// jschRemoteRunner.setCommand(scriptPath);
// jschRemoteRunner.login(super.serverProperties.getHost(),super.serverProperties.getPort(),
// super.serverProperties.getUsername(),super.serverProperties.getPassword());
// jschRemoteRunner.execCommand();
JSchRemoteRunner jschRemoteRunner = new JSchRemoteRunner();
jschRemoteRunner.setCommand(scriptPath);
jschRemoteRunner.login(super.serverProperties.getHost(), super.serverProperties.getPort(),
super.serverProperties.getUsername(), super.serverProperties.getPassword());
jschRemoteRunner.execCommand();
} catch (Exception e) {
throw new RuntimeException(e);
}

View File

@ -1,7 +1,8 @@
package org.jeecg.task.flexparttask;
package org.jeecg.transport.flexparttask;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**

View File

@ -1,11 +1,11 @@
package org.jeecg.task.flexparttask;
package org.jeecg.transport.flexparttask;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.enums.TransportTaskStatusEnum;
import org.jeecg.modules.base.entity.TransportTaskLog;
import org.jeecg.service.TransportTaskService;
import org.jeecg.transport.service.TransportTaskService;
import org.springframework.stereotype.Component;
import java.util.Objects;

View File

@ -1,4 +1,4 @@
package org.jeecg.task.flexparttask;
package org.jeecg.transport.flexparttask;
import java.util.LinkedList;

View File

@ -1,4 +1,4 @@
package org.jeecg.task.nuclearfacilitiestask;
package org.jeecg.transport.nuclearfacilitiestask;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
@ -20,6 +20,7 @@ import org.jeecg.vo.SRSRecord;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
@ -197,7 +198,7 @@ public class AssociatedNuclearFacilitiesTaskExec extends Thread{
srsFilePath.append(File.separator);
srsFilePath.append(acqEndDate);
srsFilePath.append(File.separator);
srsFilePath.append(dataFusionProperties.getIdcSrmParentDir());
// srsFilePath.append(dataFusionProperties.getIdcSrmParentDir());
//构建srm.gz文件名称
StringBuilder srmFileName = new StringBuilder();
@ -225,7 +226,7 @@ public class AssociatedNuclearFacilitiesTaskExec extends Thread{
srsFilePath.append(File.separator);
srsFilePath.append(acqEndDate);
srsFilePath.append(File.separator);
srsFilePath.append(dataFusionProperties.getNdcSrmParentDir());
// srsFilePath.append(dataFusionProperties.getNdcSrmParentDir());
//构建srm.gz文件名称
StringBuilder srmFileName = new StringBuilder();

View File

@ -0,0 +1,22 @@
package org.jeecg.transport.service;
import java.util.List;
import java.util.Map;
/**
* 台站数据服务
*/
public interface StationDataService {
/**
* 获取所有核设施和反应堆信息
* @return
*/
List<Map<String,Object>> getAllNuclearFacilitiesAndReactors();
/**
* 查询所有气体站
* @return
*/
List<Map<String,Object>> getAllGasStations();
}

View File

@ -0,0 +1,27 @@
package org.jeecg.transport.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.base.entity.rnauto.GardsStationsModVal;
import java.util.List;
/**
* 台站模拟值
*/
public interface StationsModValService extends IService <GardsStationsModVal>{
/**
* 查询台站模拟值
* @param taskId
* @param stationId
* @param speciesId
* @return
*/
List<GardsStationsModVal> getStationsModVal(Integer taskId,Integer stationId,Integer speciesId);
/**
* 保存台站模拟值
* @param list
*/
void saveStationsModVal(List<GardsStationsModVal> list);
}

View File

@ -0,0 +1,46 @@
package org.jeecg.transport.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.base.entity.TransportTask;
import org.jeecg.modules.base.entity.TransportTaskLog;
import java.util.Map;
/**
* 输运模拟任务管理
*/
public interface TransportTaskService extends IService<TransportTask> {
/**
* 保存任务日志
* @param transportTaskLog
*/
void saveLog(TransportTaskLog transportTaskLog);
/**
* 修改任务耗时
* @param taskId
* @param minute
*/
void updateTaskStatusToCompleted(Integer taskId, Double minute);
/**
* 删除任务日志
* @param taskId
*/
void deleteTaskLog(Integer taskId);
/**
* 修改任务状态
* @param taskId
* @param status
*/
void updateTaskStatus(Integer taskId, Integer status);
/**
* 查询任务模拟核素数据-包含物种id和名称
* @param taskId
* @return
*/
Map<Integer,String> getTaskSimulationSpecies(Integer taskId);
}

View File

@ -0,0 +1,67 @@
package org.jeecg.transport.service.impl;
import cn.hutool.core.collection.CollUtil;
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.GardsStations;
import org.jeecg.modules.base.mapper.*;
import org.jeecg.transport.service.StationDataService;
import org.springframework.stereotype.Service;
import java.util.*;
/**
* 台站数据服务
*/
@DS("ora")
@Service
@RequiredArgsConstructor
public class StationDataServiceImpl implements StationDataService {
private final GardsStationsMapper stationsMapper;
private final RedisUtil redisUtil;
/**
* 获取所有核设施和反应堆信息
*
* @return
*/
@Override
public List<Map<String, Object>> getAllNuclearFacilitiesAndReactors() {
return stationsMapper.getAllNuclearFacilitiesAndReactors();
}
/**
* 查询所有气体站
*
* @return
*/
@Override
public List<Map<String, Object>> getAllGasStations() {
List<GardsStations> stations;
if(redisUtil.hasKey(CommonConstant.ALL_STATIONS)){
stations = (List<GardsStations>) redisUtil.get(CommonConstant.ALL_STATIONS);
}else {
stations = stationsMapper.selectList(new LambdaQueryWrapper<>());
redisUtil.set(CommonConstant.ALL_STATIONS,stations);
}
if (CollUtil.isNotEmpty(stations)) {
List<Map<String,Object>> result = new ArrayList<>();
stations.forEach(station -> {
if ("X".equalsIgnoreCase(String.valueOf(station.getStationCode().charAt(2)))
&& Objects.nonNull(station.getLon()) && Objects.nonNull(station.getLat())) {
Map<String,Object> map = new HashMap<>();
map.put("id",station.getStationId());
map.put("stationCode",station.getStationCode());
map.put("lon",station.getLon());
map.put("lat",station.getLat());
result.add(map);
}
});
return result;
}
return List.of();
}
}

View File

@ -0,0 +1,43 @@
package org.jeecg.transport.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.modules.base.entity.rnauto.GardsStationsModVal;
import org.jeecg.modules.base.mapper.GardsStationsModValMapper;
import org.jeecg.transport.service.StationsModValService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@DS("ora")
@Service
public class StationsModValServiceImpl extends ServiceImpl<GardsStationsModValMapper, GardsStationsModVal> implements StationsModValService {
/**
* 查询台站模拟值
* @param taskId
* @param stationId
* @param speciesId
* @return
*/
@Override
public List<GardsStationsModVal> getStationsModVal(Integer taskId,Integer stationId,Integer speciesId) {
LambdaQueryWrapper<GardsStationsModVal> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(GardsStationsModVal::getTaskId,taskId);
queryWrapper.eq(GardsStationsModVal::getSpeciesId,speciesId);
queryWrapper.eq(GardsStationsModVal::getStationId,stationId);
queryWrapper.orderByAsc(GardsStationsModVal::getTimeSeries);
return this.baseMapper.selectList(queryWrapper);
}
/**
* 保存台站模拟值
* @param list
*/
@Transactional(rollbackFor = RuntimeException.class)
@Override
public void saveStationsModVal(List<GardsStationsModVal> list) {
this.baseMapper.insert(list);
}
}

View File

@ -0,0 +1,111 @@
package org.jeecg.transport.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.jeecg.common.constant.enums.*;
import org.jeecg.modules.base.entity.*;
import org.jeecg.modules.base.mapper.*;
import org.jeecg.transport.service.StationDataService;
import org.jeecg.transport.service.TransportTaskService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
/**
* 输运模拟任务管理
*/
@RequiredArgsConstructor
@Service
public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,TransportTask> implements TransportTaskService {
private final TransportTaskLogMapper transportTaskLogMapper;
private final TransportTaskForwardSpeciesMapper taskForwardSpeciesMapper;
private final StationDataService stationDataService;
/**
* 保存任务日志
*
* @param transportTaskLog
*/
@Transactional(rollbackFor = RuntimeException.class)
@Override
public void saveLog(TransportTaskLog transportTaskLog) {
transportTaskLogMapper.insert(transportTaskLog);
}
/**
* 修改任务耗时
*
* @param taskId
* @param minute
*/
@Transactional(rollbackFor = RuntimeException.class)
@Override
public void updateTaskStatusToCompleted(Integer taskId, Double minute) {
TransportTask transportTask = this.baseMapper.selectById(taskId);
transportTask.setTaskStatus(TransportTaskStatusEnum.COMPLETED.getValue());
transportTask.setTimeConsuming(minute);
this.baseMapper.updateById(transportTask);
}
/**
* 删除任务日志
*
* @param taskId
*/
@Transactional(rollbackFor = RuntimeException.class)
@Override
public void deleteTaskLog(Integer taskId) {
LambdaQueryWrapper<TransportTaskLog> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TransportTaskLog::getTaskId,taskId);
transportTaskLogMapper.delete(queryWrapper);
}
/**
* 修改任务状态
* @param taskId
* @param status
*/
@Transactional(rollbackFor = RuntimeException.class)
@Override
public void updateTaskStatus(Integer taskId, Integer status) {
TransportTask transportTask = this.baseMapper.selectById(taskId);
if(Objects.isNull(transportTask)){
throw new RuntimeException("此任务不存在");
}
transportTask.setTaskStatus(status);
this.baseMapper.updateById(transportTask);
}
/**
* 查询任务模拟核素数据-包含物种id和名称
*
* @param taskId
* @return
*/
@Override
public Map<Integer, String> getTaskSimulationSpecies(Integer taskId) {
Map<Integer, String> result = new LinkedHashMap<>();
LambdaQueryWrapper<TransportTaskForwardSpecies> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TransportTaskForwardSpecies::getTaskId,taskId);
List<TransportTaskForwardSpecies> species = taskForwardSpeciesMapper.selectList(queryWrapper);
if(CollUtil.isNotEmpty(species)){
species.forEach(specie -> {
String nuclideName = "";
if (specie.getSpeciesId().equals(FlexpartSpeciesType.XE_131m.getId())){
nuclideName = FlexpartSpeciesType.XE_131m.getNuclideName();
}else if (specie.getSpeciesId().equals(FlexpartSpeciesType.XE_133.getId())){
nuclideName = FlexpartSpeciesType.XE_133.getNuclideName();
}else if (specie.getSpeciesId().equals(FlexpartSpeciesType.XE_133m.getId())){
nuclideName = FlexpartSpeciesType.XE_133m.getNuclideName();
}else if (specie.getSpeciesId().equals(FlexpartSpeciesType.XE_135.getId())){
nuclideName = FlexpartSpeciesType.XE_135.getNuclideName();
}
result.put(specie.getSpeciesId(),nuclideName);
});
}
return result;
}
}

View File

@ -0,0 +1,175 @@
package org.jeecg.transport.util;
import java.util.LinkedHashMap;
import java.util.Map;
public class BilinearInterpolatorWithMath {
public static class Point {
public final double lon;
public final double lat;
public Point(double lon, double lat) {
this.lon = lon;
this.lat = lat;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Point p = (Point) o;
// 使用 Math.abs 做浮点容差比较
double tol = 1e-9;
return Math.abs(p.lon - lon) < tol && Math.abs(p.lat - lat) < tol;
}
@Override
public int hashCode() {
// 使用 Math.floor + longBitsToDouble 生成稳定哈希可选优化
return java.util.Objects.hash(
Double.doubleToLongBits(Math.floor(lon * 1e6 + 0.5) / 1e6),
Double.doubleToLongBits(Math.floor(lat * 1e6 + 0.5) / 1e6)
);
}
}
public static class GridData {
private final Map<Point, Double> data;
private final double delta;
private final double offset;
public GridData(Map<Point, Double> data, double delta, double offset) {
this.data = data;
this.delta = delta;
this.offset = offset;
}
/**
* 计算双线性插值
*/
public Double interpolate(double lon, double lat) {
//精确匹配格点避免边界问题
Point target = new Point(lon, lat);
Double exactValue = data.get(target);
if (exactValue != null && !Double.isNaN(exactValue)) {
return exactValue; // 直接返回不插值
}
//1. 定位网格单元使用 Math.floor 确保负数正确处理
// 关键避免 (int) 强转的 truncation 问题
int i = (int) Math.floor((lon - offset) / delta);
int j = (int) Math.floor((lat - offset) / delta);
// 计算四个角点坐标
double lon0 = i * delta + offset;
double lon1 = lon0 + delta;
double lat0 = j * delta + offset;
double lat1 = lat0 + delta;
//2. 防御性检查目标点是否真的在 [lon0, lon1) × [lat0, lat1)
// 使用 Math.abs + 容差避免浮点误差导致误判
final double TOL = 1e-10;
if (lon < lon0 - TOL || lon > lon1 + TOL ||
lat < lat0 - TOL || lat > lat1 + TOL) {
System.err.printf("Warning: (%.6f, %.6f) is outside computed cell [%.3f~%.3f]×[%.3f~%.3f]%n",
lon, lat, lon0, lon1, lat0, lat1);
// 可选自动修正索引
i = (int) Math.floor((lon - offset) / delta); // 再算一次
j = (int) Math.floor((lat - offset) / delta);
lon0 = i * delta + offset;
lon1 = lon0 + delta;
lat0 = j * delta + offset;
lat1 = lat0 + delta;
}
//3. 构造四邻点并查值
Point[] points = {
new Point(lon0, lat0), // SW
new Point(lon1, lat0), // SE
new Point(lon0, lat1), // NW
new Point(lon1, lat1) // NE
};
Double[] values = new Double[4];
boolean hasMissing = false;
for (int k = 0; k < 4; k++) {
values[k] = data.get(points[k]);
if (values[k] == null || Double.isNaN(values[k])) {
hasMissing = true;
System.err.println("Missing/NaN at: " + points[k].lon + ", " + points[k].lat);
}
}
if (hasMissing) return null;
//4. 计算权重使用 Math.max/Math.min 裁剪到 [0,1]防浮点误差溢出
double wx = (lon - lon0) / delta;
double wy = (lat - lat0) / delta;
// 关键增强防止 wx/wy 因浮点误差略超 [0,1]
wx = Math.max(0.0, Math.min(1.0, wx)); // 等价于 clamp(wx, 0, 1)
wy = Math.max(0.0, Math.min(1.0, wy));
//5. 双线性插值公式核心无需 Math 复杂函数
double v00 = values[0], v10 = values[1], v01 = values[2], v11 = values[3];
double val = (1 - wx) * (1 - wy) * v00 +
wx * (1 - wy) * v10 +
(1 - wx) * wy * v01 +
wx * wy * v11;
//6. 最终检查结果是否合理
// 使用 Math.abs + isFinite NaN/Inf
if (!Double.isFinite(val)) {
System.err.println("Interpolation produced invalid value: " + val);
return null;
}
return val;
}
/**
* 批量插值高效处理多个点
* 展示 Math.copySign / Math.IEEEremainder 等高级用法可选场景
*/
public double[] interpolateBatch(double[] lons, double[] lats) {
if (lons.length != lats.length)
throw new IllegalArgumentException("Length mismatch");
double[] results = new double[lons.length];
for (int idx = 0; idx < lons.length; idx++) {
Double val = interpolate(lons[idx], lats[idx]);
results[idx] = (val != null) ? val : Double.NaN;
// 可选对经度做环绕处理全球数据常见
// 例如 -181° 映射到 179°
double adjustedLon = lons[idx];
if (Math.abs(adjustedLon) > 180.0) {
// 使用 IEEE 754 标准取余 % 更可靠
adjustedLon = Math.IEEEremainder(adjustedLon + 180.0, 360.0) - 180.0;
// 保持符号一致性-0.0 0.0
adjustedLon = Math.copySign(adjustedLon, adjustedLon);
}
// 然后用 adjustedLon 重新插值...
}
return results;
}
}
// ===== 演示Math 库增强版用法 =====
public static void main(String[] args) {
Map<Point, Double> data = new LinkedHashMap<>();
data.put(new Point(7.875, 47.875), 195.53140258789062);
data.put(new Point(8.125, 47.875), 9.2166166305542);
data.put(new Point(7.875, 48.125), 40.02995681762695);
data.put(new Point(8.125, 48.125), 11.597820281982422);
GridData grid = new GridData(data, 0.25, 0.125);
// 测试正常点
System.out.printf("Normal: %.8f%n",
grid.interpolate(7.9, 47.9));
// 测试边界点wx/wy 接近 1
// System.out.printf("Edge case: %.8f%n",
// grid.interpolate(-53.625, -36.375)); // 应等于 NE 点值
}
}

View File

@ -0,0 +1,78 @@
package org.jeecg.transport.util;
import org.jeecg.modules.base.entity.rnauto.GardsStationsModVal;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
public class PreSortedTimeRangeQuery {
private List<GardsStationsModVal> sortedList = null;
public PreSortedTimeRangeQuery(List<GardsStationsModVal> sortedList){
this.sortedList = sortedList;
}
/**
* 查询指定时间范围内的数据并求和取平均
*/
public double sumConcByTimeRange(Date startTime, Date endTime) {
int startIndex = findFirstGreaterOrEqual(startTime);
int endIndex = findLastLessOrEqual(endTime);
if (startIndex > endIndex || startIndex < 0) {
return 0.0;
}
int count = 0;
double sum = 0.0;
for (int i = startIndex; i <= endIndex; i++) {
Double conc = sortedList.get(i).getConc();
if (conc != null) {
sum += conc;
count ++;
}
}
BigDecimal bg = new BigDecimal(sum);
BigDecimal result = bg.divide(BigDecimal.valueOf(count), 6, RoundingMode.HALF_UP);
return result.doubleValue();
}
/**
* 二分查找第一个大于等于目标时间的索引
* @param target
* @return
*/
private int findFirstGreaterOrEqual(Date target) {
int left = 0, right = sortedList.size();
while (left < right) {
int mid = left + (right - left) / 2;
if (sortedList.get(mid).getTimeSeries().compareTo(target) >= 0) {
right = mid;
} else {
left = mid + 1;
}
}
return left < sortedList.size() ? left : -1;
}
/**
* 二分查找最后一个小于等于目标时间的索引
*/
private int findLastLessOrEqual(Date target) {
int left = 0, right = sortedList.size() - 1;
int result = -1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (sortedList.get(mid).getTimeSeries().compareTo(target) <= 0) {
result = mid;
left = mid + 1;
} else {
right = mid - 1;
}
}
return result;
}
}

View File

@ -1,4 +1,4 @@
package org.jeecg.task.waveformtask;
package org.jeecg.transport.waveformtask;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
@ -6,7 +6,9 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.StopWatch;
import org.apache.logging.log4j.util.Strings;
import org.jeecg.common.constant.enums.*;
import org.jeecg.common.constant.enums.AssociatedWaveformTaskEnum;
import org.jeecg.common.constant.enums.TransportSampleTypeEnum;
import org.jeecg.common.constant.enums.WaveformEventResultTypeEnum;
import org.jeecg.common.properties.DataFusionProperties;
import org.jeecg.config.datasource.DataSourceSwitcher;
import org.jeecg.modules.base.entity.copsdb.Origin;
@ -20,7 +22,10 @@ import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import java.io.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
@ -45,6 +50,7 @@ public class AssociatedWaveformTaskExec extends Thread{
private Integer sampleId;
private Date acqEndTime;
private String stationCode;
private String sampleType;
private File idcSrsFile = null;
private File ndcSrsFile = null;
private List<String> idcSrsContents;
@ -62,7 +68,8 @@ public class AssociatedWaveformTaskExec extends Thread{
GardsWaveformEventResultMapper waveformEventResultMapper,
Integer sampleId,
Date acqEndTime,
String stationCode){
String stationCode,
String sampleType){
this.transactionManager = transactionManager;
this.transactionDefinition = transactionDefinition;
this.dataFusionProperties = dataFusionProperties;
@ -72,6 +79,7 @@ public class AssociatedWaveformTaskExec extends Thread{
this.sampleId = sampleId;
this.acqEndTime = acqEndTime;
this.stationCode = stationCode;
this.sampleType = sampleType;
}
@Override
@ -194,7 +202,11 @@ public class AssociatedWaveformTaskExec extends Thread{
srsFilePath.append(File.separator);
srsFilePath.append(acqEndDate);
srsFilePath.append(File.separator);
srsFilePath.append(dataFusionProperties.getIdcSrmParentDir());
if (this.sampleType.equalsIgnoreCase(TransportSampleTypeEnum.B.name())){
srsFilePath.append(dataFusionProperties.getIdcXSrmParentDir());
}else if (this.sampleType.equalsIgnoreCase(TransportSampleTypeEnum.P.name())){
srsFilePath.append(dataFusionProperties.getIdcPSrmParentDir());
}
//构建srm.gz文件名称
StringBuilder srmFileName = new StringBuilder();
@ -222,7 +234,11 @@ public class AssociatedWaveformTaskExec extends Thread{
srsFilePath.append(File.separator);
srsFilePath.append(acqEndDate);
srsFilePath.append(File.separator);
srsFilePath.append(dataFusionProperties.getNdcSrmParentDir());
if (this.sampleType.equalsIgnoreCase(TransportSampleTypeEnum.B.name())){
srsFilePath.append(dataFusionProperties.getIdcXSrmParentDir());
}else if (this.sampleType.equalsIgnoreCase(TransportSampleTypeEnum.P.name())){
srsFilePath.append(dataFusionProperties.getIdcPSrmParentDir());
}
//构建srm.gz文件名称
StringBuilder srmFileName = new StringBuilder();

View File

@ -0,0 +1,38 @@
package org.jeecg.vo;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* 贡献分析数据VO
*/
@Data
public class ContributionAnalysisVO {
/**
* X轴台站每天的浓度值数据
*/
private Map<String,Double> stationEveryDayConcDatas;
/**
* 核设施每天的浓度值数据
*/
private Map<String,Map<String,Double>> facilityEveryDayConcDatas;
/**
* 涉及的核设施名称
*/
private List<String> nuclideNames;
/**
* 饼图数据
*/
private Map<String,Double> pipeChartData;
/**
* 总浓度值
*/
private Double totalConc;
}

View File

@ -0,0 +1,26 @@
package org.jeecg.vo;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class QueryDiffusionVO {
/**
* 任务id
*/
@NotNull(message = "任务id不能为空",groups = {QueryDiffusionVO.class})
private Integer taskId;
/**
* 时间序号
*/
@NotNull(message = "时间序号不能为空",groups = {QueryDiffusionVO.class})
private Integer time;
/**
* 物种id
*/
private Integer speciesId;
}

View File

@ -0,0 +1,40 @@
package org.jeecg.vo;
import lombok.Data;
/**
* srs记录数据
*/
@Data
public class SRSRecord {
/**
* 经度
*/
private Double lon;
/**
* 纬度
*/
private Double lat;
/**
* 处于的小时
*/
private Integer hour;
/**
* 根据样品时间-hour得到的开始时间
*/
private Long startSecond;
/**
* 测量结束时间就是模拟结束时间
*/
private Long endSecond;
/**
* 浓度值单位暂未知
*/
private String conc;
}

View File

@ -0,0 +1,17 @@
package org.jeecg.vo;
import lombok.Data;
@Data
public class TaskStationsVO {
private Integer stationId;
private Integer stationNum;
private String stationCode;
private Double lon;
private Double lat;
}

View File

@ -0,0 +1,120 @@
package org.jeecg.consumer;
import com.alibaba.fastjson2.JSON;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.ConsumeMode;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.jeecg.common.constant.RocketMQTopConstant;
import org.jeecg.common.constant.enums.TransportTaskModeEnum;
import org.jeecg.common.constant.enums.TransportTaskStatusEnum;
import org.jeecg.common.constant.enums.TransportTaskTypeEnum;
import org.jeecg.common.properties.TransportSimulationProperties;
import org.jeecg.modules.base.dto.GardsSampleResultDTO;
import org.jeecg.modules.base.dto.TransportTaskDTO;
import org.jeecg.modules.base.entity.TransportTask;
import org.jeecg.modules.base.entity.TransportTaskBackwardChild;
import org.jeecg.modules.base.entity.configuration.GardsStations;
import org.jeecg.producer.TransportTaskProducer;
import org.jeecg.service.StationDataService;
import org.jeecg.service.TransportTaskService;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* 异常样品信息消费生成flexpart 反演任务
*/
@Slf4j
@Component
@RequiredArgsConstructor
@RocketMQMessageListener(consumerGroup = "consumer-group",
topic = RocketMQTopConstant.SAMPLE_RESULT_TOPIC,
consumeMode = ConsumeMode.ORDERLY)
public class SampleMessageConsumer implements RocketMQListener<GardsSampleResultDTO> {
private final TransportTaskProducer transportTaskProducer;
private final StationDataService stationDataService;
private final TransportTaskService transportTaskService;
private final TransportSimulationProperties simulationProperties;
/**
* 消费任务信息
* @param sampleResultDTO
*/
@Override
public void onMessage(GardsSampleResultDTO sampleResultDTO) {
//查询台站信息
GardsStations stationInfo = stationDataService.getStationById(sampleResultDTO.getStationId());
if (Objects.isNull(stationInfo)) {
return;
}
String taskName = stationInfo.getStationCode()+"_"+ sampleResultDTO.getSampleId();
boolean checkResult = transportTaskService.checkTaskByName(taskName);
if (checkResult) {
//处理测量时间以及任务开始结束时间
LocalDateTime acqStartTime = sampleResultDTO.getAcquisitionStart().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
LocalDateTime acqEndTime = sampleResultDTO.getAcquisitionStop().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
//反演时间向前推14天作为开始时间
LocalDateTime startTime = acqEndTime.minusDays(14);
//设置基础参数
TransportTask transportTask = new TransportTask();
transportTask.setTaskName(taskName);
transportTask.setTaskPprogress(0);
transportTask.setTaskStatus(TransportTaskStatusEnum.WAITING.getValue());
transportTask.setTaskType(TransportTaskTypeEnum.AUTO.getKey());
transportTask.setTaskMode(TransportTaskModeEnum.BACK_FORWARD.getKey());
transportTask.setTimeConsuming(0D);
transportTask.setUseMetType(simulationProperties.getUseMetType());
transportTask.setStartTime(startTime);
transportTask.setEndTime(acqEndTime);
transportTask.setZ1(simulationProperties.getZ1());
transportTask.setZ2(simulationProperties.getZ2());
transportTask.setParticleCount(simulationProperties.getParticleCount());
//设置站点参数
List<TransportTaskBackwardChild> backwardChild = new ArrayList<>();
TransportTaskBackwardChild taskBackwardChild = new TransportTaskBackwardChild();
taskBackwardChild.setSampleId(sampleResultDTO.getSampleId());
taskBackwardChild.setAcqStartTime(acqStartTime);
taskBackwardChild.setAcqEndTime(acqEndTime);
taskBackwardChild.setStationCode(stationInfo.getStationCode());
taskBackwardChild.setLon(stationInfo.getLon());
taskBackwardChild.setLat(stationInfo.getLat());
taskBackwardChild.setReleaseAmount(sampleResultDTO.getReleaseAmount());
taskBackwardChild.setSampleCategory(sampleResultDTO.getCategory());
taskBackwardChild.setSampleType(sampleResultDTO.getSampleType());
backwardChild.add(taskBackwardChild);
transportTask.setBackwardChild(backwardChild);
//保存反演任务
transportTaskService.cteate(transportTask);
//发送消息到消息队列
if (TransportTaskModeEnum.BACK_FORWARD.getKey().equals(transportTask.getTaskMode())){
transportTaskProducer.sendBackwardMessage(buildMessage(transportTask));
}else if (TransportTaskModeEnum.FORWARD.getKey().equals(transportTask.getTaskMode())){
transportTaskProducer.sendForwardMessage(buildMessage(transportTask));
}
log.info("消费消息id为{}",sampleResultDTO.getSampleId());
}
}
/**
* 构造消息
* @param transportTask
* @return
*/
private TransportTaskDTO buildMessage(TransportTask transportTask){
TransportTaskDTO transportTaskDTO = new TransportTaskDTO();
transportTaskDTO.setId(transportTask.getId());
transportTaskDTO.setTaskName(transportTask.getTaskName());
transportTaskDTO.setTaskType(transportTask.getTaskType());
transportTaskDTO.setTaskMode(transportTask.getTaskMode());
transportTaskDTO.setUseMetType(transportTask.getUseMetType());
transportTaskDTO.setStartTime(transportTask.getStartTime());
transportTaskDTO.setEndTime(transportTask.getEndTime());
return transportTaskDTO;
}
}

View File

@ -25,6 +25,13 @@ public class StationDataController {
return Result.OK(stationDataService.getAllStations());
}
@AutoLog(value = "查询所有惰性气体台站")
@Operation(summary = "查询所有惰性气体台站")
@GetMapping("getAllGasStations")
public Result<?> getAllGasStations(){
return Result.OK(stationDataService.getAllGasStations());
}
@AutoLog(value = "查询所有设施")
@Operation(summary = "查询所有设施")
@GetMapping("getAllNuclearfacility")

View File

@ -27,21 +27,45 @@ public class TransportResultDataController {
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("getResultGlobalAttr")
public Result<?> getResultGlobalAttr(@NotNull(message = "任务id不能为空") Integer taskId) {
return Result.OK(transportResultDataService.getResultGlobalAttr(taskId));
}
@AutoLog(value = "查询符合度分析数据")
@Operation(summary = "查询符合度分析数据")
@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));
@NotNull(message = "物种id不能为空") Integer speciesId,
@NotNull(message = "核素名称不能为空") String nuclideName) {
return Result.OK(transportResultDataService.getConformityAnalysis(taskId,stationId,speciesId,nuclideName));
}
@AutoLog(value = "查询符合度分析数据-散点图")
@Operation(summary = "查询符合度分析数据-散点图")
@GetMapping("getConformityAnalysisScatterPlot")
public Result<?> getConformityAnalysisScatterPlot(@NotNull(message = "任务id不能为空") Integer taskId,
@NotBlank(message = "台站不能为空") String stationIds,
@NotNull(message = "物种id不能为空") Integer speciesId,
@NotNull(message = "核素名称不能为空") String nuclideName) {
return Result.OK(transportResultDataService.getConformityAnalysisScatterPlot(taskId,stationIds,speciesId,nuclideName));
}
@AutoLog(value = "查询任务模拟核素数据-只有核素名称-弃用")
@Operation(summary = "查询任务模拟核素数据-只有核素名称-弃用")
@GetMapping("getTaskSimulationNuclide")
public Result<?> getTaskSimulationNuclide(@NotNull(message = "任务id不能为空") Integer taskId) {
return Result.OK(transportResultDataService.getTaskSimulationNuclide(taskId));
}
@AutoLog(value = "查询任务模拟核素数据-包含物种id和名称")
@Operation(summary = "查询任务模拟核素数据-包含物种id和名称")
@GetMapping("getTaskSimulationSpecies")
public Result<?> getTaskSimulationSpecies(@NotNull(message = "任务id不能为空") Integer taskId) {
return Result.OK(transportResultDataService.getTaskSimulationSpecies(taskId));
}
@AutoLog(value = "查询贡献分析数据")
@ -91,12 +115,4 @@ public class TransportResultDataController {
public Result<?> getTaskStations(@NotNull(message = "任务id不能为空") Integer taskId) {
return Result.OK(transportResultDataService.getTaskStations(taskId));
}
@AutoLog(value = "查询任务所属NC层级数据")
@Operation(summary = "查询任务所属NC层级数据")
@GetMapping("getTaskNCHeightLevel")
public Result<?> getTaskNCHeightLevel(@NotNull(message = "任务id不能为空") Integer taskId) {
return Result.OK(transportResultDataService.getTaskNCHeightLevel(taskId));
}
}

View File

@ -14,14 +14,18 @@ import org.jeecg.common.properties.TransportSimulationProperties;
import org.jeecg.common.system.query.PageRequest;
import org.jeecg.common.validgroup.InsertGroup;
import org.jeecg.common.validgroup.UpdateGroup;
import org.jeecg.modules.base.dto.GardsSampleResultDTO;
import org.jeecg.modules.base.dto.TransportTaskDTO;
import org.jeecg.modules.base.entity.TransportTask;
import org.jeecg.modules.base.entity.TransportTaskLog;
import org.jeecg.producer.SampleResultProducer;
import org.jeecg.producer.TransportTaskProducer;
import org.jeecg.service.TransportTaskService;
import org.jeecg.vo.SiteAndReleaseDataVO;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import ucar.ma2.ArrayDouble;
import java.io.*;
import java.net.URLEncoder;
import java.time.LocalDate;
@ -40,6 +44,8 @@ public class TransportTaskController {
private final TransportTaskService transportTaskService;
private final TransportSimulationProperties transportSimulationProperties;
private final SampleResultProducer sampleResultProducer;
private final TransportTaskProducer transportTaskProducer;
@AutoLog(value = "分页查询输运任务数据")
@Operation(summary = "分页查询输运任务数据")
@ -85,11 +91,38 @@ public class TransportTaskController {
return Result.OK();
}
@AutoLog(value = "获取单个站点的排放数据")
@Operation(summary = "获取单个站点的排放数据")
@GetMapping("getReleaseDataByForwardId")
public Result<?> getReleaseDataByForwardId(@NotNull(message = "ID不能为空") Integer forwardId){
return Result.OK(transportTaskService.getReleaseDataByForwardId(forwardId));
}
@AutoLog(value = "保存单个站点及对应排放数据")
@Operation(summary = "保存单个站点及对应排放数据")
@PostMapping("saveSiteAndReleaseData")
public Result<?> saveSiteAndReleaseData(@RequestBody SiteAndReleaseDataVO siteAndReleaseDataVO){
Integer forwardChildId = transportTaskService.saveSiteAndReleaseData(siteAndReleaseDataVO);
return Result.OK(forwardChildId);
}
@AutoLog(value = "删除单个站点及对应排放数据")
@Operation(summary = "删除单个站点及对应排放数据")
@DeleteMapping("delSiteAndReleaseData")
public Result<?> delSiteAndReleaseData(@NotNull(message = "ID不能为空") Integer forwardId){
transportTaskService.delSiteAndReleaseData(forwardId);
return Result.OK();
}
@AutoLog(value = "获取输运任务日志")
@Operation(summary = "获取输运任务日志")
@GetMapping("getTaskLog")
public Result<?> getTaskLog(@NotNull(message = "任务ID不能为空") Integer taskId){
return Result.OK(transportTaskService.getTaskLog(taskId));
public Result<?> getTaskLog(@NotNull(message = "任务ID不能为空") Integer taskId,PageRequest pageRequest){
IPage<TransportTaskLog> page = transportTaskService.getTaskLog(taskId, pageRequest);
Map<String, Object> rspData = new HashMap<>();
rspData.put("rows", page.getRecords());
rspData.put("total", page.getTotal());
return Result.OK(rspData);
}
@AutoLog(value = "启动任务")
@ -130,8 +163,14 @@ public class TransportTaskController {
}
}
@GetMapping("importTask")
public Result<?> importTask(MultipartFile file){
/**
* 导入任务
* @param file
* @param taskMode
* @return
*/
@PostMapping("importTask")
public Result<?> importTask(MultipartFile file,Integer taskMode){
List<String> importResult = new ArrayList<>();
try{
importResult = transportTaskService.importTask(file);
@ -147,8 +186,55 @@ public class TransportTaskController {
return Result.error("导入失败", importResult);
}
/**
* 处理赵老师给的2014年的排放数据把内容填充到模版
* @param res
* @throws Exception
*/
@GetMapping("handleNPPExcelReleaseData")
public void handleNPPExcelReleaseData(HttpServletResponse res) throws Exception {
transportTaskService.handleExcelReleaseData(res);
}
/**
* 处理csv监测站点数据
* @param res
* @throws Exception
*/
@GetMapping("handleCSVData")
public Result<?> handleCSVData(HttpServletResponse res) throws Exception {
transportTaskService.handleCSVData(res);
return Result.OK();
}
/**
* 处理赵老师给的2014年的排放数据生成sql文件
* @throws Exception
*/
@GetMapping("handlExcelReleaseData")
public void handlExcelReleaseData() throws Exception {
transportTaskService.handlExcelReleaseData();
}
/**
* 发送样品数据到消息队列
* @throws Exception
*/
@PostMapping("testSendSampleInfoToMQ")
public void testSendSampleInfoToMQ(@RequestBody GardsSampleResultDTO sampleResultDTO) throws Exception {
sampleResultProducer.sendMessage(sampleResultDTO);
}
/**
* 发送任务数据到消息队列
* @throws Exception
*/
@PostMapping("testSendTaskInfoToMQ")
public void testSendTaskInfoToMQ(@RequestBody TransportTaskDTO transportTaskDTO) throws Exception {
if (TransportTaskModeEnum.BACK_FORWARD.getKey().equals(transportTaskDTO.getTaskMode())){
transportTaskProducer.sendBackwardMessage(transportTaskDTO);
}else if (TransportTaskModeEnum.FORWARD.getKey().equals(transportTaskDTO.getTaskMode())){
transportTaskProducer.sendForwardMessage(transportTaskDTO);
}
}
}

View File

@ -0,0 +1,32 @@
package org.jeecg.producer;
import lombok.RequiredArgsConstructor;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.rocketmq.spring.support.RocketMQHeaders;
import org.jeecg.common.constant.RocketMQTopConstant;
import org.jeecg.modules.base.vo.GardsSampleInfoVO;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;
/**
* 关联波形任务消息生产者
*/
@Component
@RequiredArgsConstructor
public class AssociatedWaveformTaskProducer {
private final RocketMQTemplate rocketMQTemplate;
/**
* 发送消息
* @param sampleInfo
*/
public void sendMessage(GardsSampleInfoVO sampleInfo) {
Message<GardsSampleInfoVO> message = MessageBuilder.withPayload(sampleInfo)
.setHeader(RocketMQHeaders.KEYS,String.valueOf(sampleInfo.getSampleId()))
.build();
String destination = RocketMQTopConstant.ASSOCIATED_WAVEFORM_SAMPLE_TOPIC+":"+sampleInfo.getSampleType();
rocketMQTemplate.syncSend(destination,message);
}
}

View File

@ -0,0 +1,32 @@
package org.jeecg.producer;
import lombok.RequiredArgsConstructor;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.rocketmq.spring.support.RocketMQHeaders;
import org.jeecg.common.constant.RocketMQTopConstant;
import org.jeecg.modules.base.dto.GardsSampleResultDTO;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;
/**
* 样品分级结果消息生产者
*/
@Component
@RequiredArgsConstructor
public class SampleResultProducer {
private final RocketMQTemplate rocketMQTemplate;
/**
* 发送消息
* @param sampleResultDTO
*/
public void sendMessage(GardsSampleResultDTO sampleResultDTO) {
Message<GardsSampleResultDTO> message = MessageBuilder.withPayload(sampleResultDTO)
.setHeader(RocketMQHeaders.KEYS,String.valueOf(sampleResultDTO.getSampleId()))
.build();
String destination = RocketMQTopConstant.SAMPLE_RESULT_TOPIC+":"+sampleResultDTO.getSampleType();
rocketMQTemplate.syncSend(destination,message);
}
}

View File

@ -0,0 +1,43 @@
package org.jeecg.producer;
import lombok.RequiredArgsConstructor;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.rocketmq.spring.support.RocketMQHeaders;
import org.jeecg.common.constant.RocketMQTopConstant;
import org.jeecg.modules.base.dto.TransportTaskDTO;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;
/**
* 输运模拟任务消息生产者
*/
@Component
@RequiredArgsConstructor
public class TransportTaskProducer {
private final RocketMQTemplate rocketMQTemplate;
/**
* 发送消息
* @param transportTaskDTO
*/
public void sendForwardMessage(TransportTaskDTO transportTaskDTO) {
Message<TransportTaskDTO> message = MessageBuilder.withPayload(transportTaskDTO)
.setHeader(RocketMQHeaders.KEYS,String.valueOf(transportTaskDTO.getId()))
.build();
String destination = RocketMQTopConstant.FORWARD_TRANSPORT_TASK_TOPIC+":"+transportTaskDTO.getTaskType();
rocketMQTemplate.syncSend(destination,message);
}
/**
* 发送消息
* @param transportTaskDTO
*/
public void sendBackwardMessage(TransportTaskDTO transportTaskDTO) {
Message<TransportTaskDTO> message = MessageBuilder.withPayload(transportTaskDTO)
.setHeader(RocketMQHeaders.KEYS,String.valueOf(transportTaskDTO.getId()))
.build();
String destination = RocketMQTopConstant.BACKWARD_TRANSPORT_TASK_TOPIC+":"+transportTaskDTO.getTaskType();
rocketMQTemplate.syncSend(destination,message);
}
}

View File

@ -37,7 +37,7 @@ public interface AssociatedWaveformService extends IService<GardsWaveformEvent>
IPage<Map<String,Object>> sampleWaveformsDetailsPage(PageRequest pageRequest, Integer sampleId,Integer type);
/**
* 样品id不能为空
* 发送需要关联的样品消息到消息队列
* @param sampleId
*/
void execAssociated(Integer sampleId);

View File

@ -1,7 +1,12 @@
package org.jeecg.service;
import org.jeecg.modules.base.entity.configuration.GardsDetectors;
import org.jeecg.modules.base.entity.configuration.GardsNuclearReactors;
import org.jeecg.modules.base.entity.configuration.GardsStations;
import org.jeecg.modules.base.entity.original.GardsSampleData;
import org.jeecg.modules.base.entity.rnauto.GardsXeResults;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
@ -31,7 +36,7 @@ public interface StationDataService {
* @param nuclideName
* @return
*/
List<Map<String, Object>> getXeResults(Integer stationId,Date startTime,Date endTime,String nuclideName);
List<Map<String, Object>> getXeResults(Integer stationId, Date startTime, Date endTime, String nuclideName);
/**
* 获取台站信息
@ -51,4 +56,17 @@ public interface StationDataService {
* @return
*/
List<Map<String,Object>> getAllResearchReactors();
List<GardsStations> getStationsList();
List<GardsDetectors> getDetectorsList();
void saveSampleData(List<GardsSampleData> sampleDataList);
void saveXeResult(List<GardsXeResults> xeResultsList);
/**
* 查询所有气体站
* @return
*/
List<Map<String,Object>> getAllGasStations();
}

View File

@ -0,0 +1,27 @@
package org.jeecg.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.base.entity.rnauto.GardsStationsModVal;
import java.util.List;
/**
* 台站模拟值
*/
public interface StationsModValService extends IService <GardsStationsModVal>{
/**
* 查询台站模拟值
* @param taskId
* @param stationId
* @param speciesId
* @return
*/
List<GardsStationsModVal> getStationsModVal(Integer taskId,Integer stationId,Integer speciesId);
/**
* 保存台站模拟值
* @param list
*/
void saveStationsModVal(List<GardsStationsModVal> list);
}

View File

@ -21,17 +21,17 @@ public interface TransportResultDataService {
* @param taskId
* @return
*/
Map<String,Object> getResultSiteNums(Integer taskId);
Map<String,Object> getResultGlobalAttr(Integer taskId);
/**
* 查询符合度分析数据
* 查询符合度分析数据-时序图
* @param taskId
* @param stationId
* @param speciesId
* @param nuclideName
* @param facilityName
* @return
*/
List<Map<String, Object>> getConformityAnalysis(Integer taskId,Integer stationId,String nuclideName,String facilityName);
List<Map<String, Object>> getConformityAnalysis(Integer taskId,Integer stationId,Integer speciesId,String nuclideName);
/**
* 查询任务所属核设施数据
@ -67,7 +67,7 @@ public interface TransportResultDataService {
* @param taskId
* @return
*/
Map<Integer, Object> getTaskNCHeightLevel(Integer taskId);
// Map<Integer, Object> getTaskNCHeightLevel(Integer taskId);
/**
* 查询反演核设施时序数据接口
@ -84,4 +84,28 @@ public interface TransportResultDataService {
* @return
*/
void handleTimingAnalysis(Integer taskId);
/**
* 查询任务模拟核素数据-只有核素名称
* @param taskId
* @return
*/
List<String> getTaskSimulationNuclide(Integer taskId);
/**
* 查询任务模拟核素数据-包含物种id和名称
* @param taskId
* @return
*/
Map<Integer,String> getTaskSimulationSpecies(Integer taskId);
/**
* 查询符合度分析数据-散点图
* @param taskId
* @param stationIds
* @param speciesId
* @param nuclideName
* @return
*/
Map<String,List<Map<String,Object>>> getConformityAnalysisScatterPlot(Integer taskId,String stationIds,Integer speciesId,String nuclideName);
}

View File

@ -5,9 +5,10 @@ import com.baomidou.mybatisplus.extension.service.IService;
import jakarta.servlet.http.HttpServletResponse;
import org.jeecg.common.system.query.PageRequest;
import org.jeecg.modules.base.entity.TransportTask;
import org.jeecg.modules.base.entity.TransportTaskForwardRelease;
import org.jeecg.modules.base.entity.TransportTaskLog;
import org.jeecg.vo.SiteAndReleaseDataVO;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.time.LocalDate;
import java.util.List;
@ -55,6 +56,13 @@ public interface TransportTaskService extends IService<TransportTask> {
*/
void delete(Integer id);
/**
* 根据任务名称校验任务是否存在
* @param taskName
* @return
*/
boolean checkTaskByName(String taskName);
/**
* 运行任务
* @param id
@ -64,9 +72,10 @@ public interface TransportTaskService extends IService<TransportTask> {
/**
* 获取任务运行日志
* @param taskId
* @param pageRequest
* @return
*/
List<TransportTaskLog> getTaskLog(Integer taskId);
IPage<TransportTaskLog> getTaskLog(Integer taskId,PageRequest pageRequest);
/**
* 保存任务日志
@ -101,4 +110,30 @@ public interface TransportTaskService extends IService<TransportTask> {
* @param file
*/
List<String> importTask(MultipartFile file) throws IOException;
/**
* 处理csv监测站点数据
* @param res
*/
void handleCSVData(HttpServletResponse res);
List<TransportTaskForwardRelease> getReleaseDataByForwardId(Integer forwardId);
/**
* 保存单个站点及对应排放数据
* @param siteAndReleaseDataVO
*/
Integer saveSiteAndReleaseData(SiteAndReleaseDataVO siteAndReleaseDataVO);
/**
* 删除单个站点及对应排放数据
* @param forwardId
*/
void delSiteAndReleaseData(Integer forwardId);
/**
* 处理赵老师给的2014年的排放数据生成sql文件
*/
void handlExcelReleaseData();
}

View File

@ -9,22 +9,18 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.jeecg.common.constant.enums.AssociatedWaveformTaskEnum;
import org.jeecg.common.properties.ArmdReportProperties;
import org.jeecg.common.properties.DataFusionProperties;
import org.jeecg.common.system.query.PageRequest;
import org.jeecg.modules.base.entity.copsdb.Origin;
import org.jeecg.modules.base.entity.rnauto.GardsWaveformEvent;
import org.jeecg.modules.base.mapper.GardsAnalysesMapper;
import org.jeecg.modules.base.mapper.GardsWaveformEventMapper;
import org.jeecg.modules.base.mapper.GardsWaveformEventResultMapper;
import org.jeecg.modules.base.mapper.OriginMapper;
import org.jeecg.modules.base.vo.GardsSampleInfoVO;
import org.jeecg.producer.AssociatedWaveformTaskProducer;
import org.jeecg.service.AssociatedWaveformService;
import org.jeecg.task.waveformtask.AssociatedWaveformTaskExec;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@ -45,11 +41,8 @@ public class AssociatedWaveformServiceImpl extends ServiceImpl<GardsWaveformEven
private final ArmdReportProperties armdReportProperties;
private final GardsAnalysesMapper analysesMapper;
private final DataFusionProperties dataFusionProperties;
private final OriginMapper originMapper;
private final DataSourceTransactionManager transactionManager;
private final TransactionDefinition transactionDefinition;
private final GardsWaveformEventResultMapper waveformEventResultMapper;
private final AssociatedWaveformTaskProducer associatedWaveformTaskProducer;
/**
* 分页查询关联波形数据
@ -90,29 +83,21 @@ public class AssociatedWaveformServiceImpl extends ServiceImpl<GardsWaveformEven
}
/**
* 样品id不能为空
* 发送需要关联的样品消息到消息队列
*
* @param sampleId
*/
@DS(value = "ora")
@Override
public void execAssociated(Integer sampleId) {
//把消息写到消息队列中
//暂且先把手动关联代码写这里
//发送消息
GardsSampleInfoVO sampleInfo = this.baseMapper.selectSampleInfoBySampleId(sampleId);
AssociatedWaveformTaskExec associatedWaveformTaskExec = new AssociatedWaveformTaskExec();
associatedWaveformTaskExec.init(
transactionManager,
transactionDefinition,
dataFusionProperties,
this.baseMapper,
originMapper,
waveformEventResultMapper,
sampleInfo.getSampleId(),
sampleInfo.getAcqEndTime(),
sampleInfo.getStationCode());
associatedWaveformTaskExec.setName("sampleAssociatedThread_"+sampleId);
associatedWaveformTaskExec.start();
associatedWaveformTaskProducer.sendMessage(sampleInfo);
//修改状态为等待中
GardsWaveformEvent waveformEvent = this.baseMapper.selectById(sampleId);
waveformEvent.setStatus(AssociatedWaveformTaskEnum.IN_LINE.getValue());
waveformEvent.setModdate(new Date());
this.baseMapper.updateById(waveformEvent);
}
/**

View File

@ -5,17 +5,14 @@ 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.CoordinateTransformUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.base.entity.configuration.GardsNuclearReactors;
import org.jeecg.modules.base.entity.configuration.GardsNuclearfacility;
import org.jeecg.modules.base.entity.configuration.GardsResearchReactors;
import org.jeecg.modules.base.entity.configuration.GardsStations;
import org.jeecg.modules.base.entity.configuration.*;
import org.jeecg.modules.base.entity.original.GardsSampleData;
import org.jeecg.modules.base.entity.rnauto.GardsXeResults;
import org.jeecg.modules.base.mapper.*;
import org.jeecg.service.StationDataService;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
/**
@ -31,6 +28,8 @@ public class StationDataServiceImpl implements StationDataService {
private final GardsResearchReactorsMapper researchReactorsMapper;
private final GardsXeResultMapper gardsXeResultMapper;
private final RedisUtil redisUtil;
private final GardsDetectorsMapper detectorsMapper;
private final GardsSampleDataMapper sampleDataMapper;
/**
* 获取所有台站
@ -153,4 +152,77 @@ public class StationDataServiceImpl implements StationDataService {
return List.of();
}
/**
* @return
*/
@Override
public List<GardsStations> getStationsList() {
LambdaQueryWrapper<GardsStations> queryWrapper = new LambdaQueryWrapper<>();
return stationsMapper.selectList(queryWrapper);
}
/**
* @return
*/
@Override
public List<GardsDetectors> getDetectorsList() {
LambdaQueryWrapper<GardsDetectors> queryWrapper = new LambdaQueryWrapper<>();
return this.detectorsMapper.selectList(queryWrapper);
}
/**
* @param sampleDataList
*/
@Transactional(rollbackFor = RuntimeException.class)
@Override
public void saveSampleData(List<GardsSampleData> sampleDataList) {
for (GardsSampleData sampleData : sampleDataList){
sampleDataMapper.insert(sampleData);
}
// sampleDataMapper.insert(sampleDataList);
}
/**
* @param xeResultsList
*/
@Transactional(rollbackFor = RuntimeException.class)
@Override
public void saveXeResult(List<GardsXeResults> xeResultsList) {
for (GardsXeResults xeResults : xeResultsList){
gardsXeResultMapper.insert(xeResults);
}
// gardsXeResultMapper.insert(xeResultsList);
}
/**
* 查询所有气体站
*
* @return
*/
@Override
public List<Map<String, Object>> getAllGasStations() {
List<GardsStations> stations;
if(redisUtil.hasKey(CommonConstant.ALL_STATIONS)){
stations = (List<GardsStations>) redisUtil.get(CommonConstant.ALL_STATIONS);
}else {
stations = stationsMapper.selectList(new LambdaQueryWrapper<>());
redisUtil.set(CommonConstant.ALL_STATIONS,stations);
}
if (CollUtil.isNotEmpty(stations)) {
List<Map<String,Object>> result = new ArrayList<>();
stations.forEach(station -> {
if ("X".equalsIgnoreCase(String.valueOf(station.getStationCode().charAt(2)))
&& Objects.nonNull(station.getLon()) && Objects.nonNull(station.getLat())) {
Map<String,Object> map = new HashMap<>();
map.put("id",station.getStationId());
map.put("stationCode",station.getStationCode());
map.put("lon",station.getLon());
map.put("lat",station.getLat());
result.add(map);
}
});
return result;
}
return List.of();
}
}

View File

@ -0,0 +1,44 @@
package org.jeecg.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.modules.base.entity.rnauto.GardsStationsModVal;
import org.jeecg.modules.base.mapper.GardsStationsModValMapper;
import org.jeecg.service.StationsModValService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@DS("ora")
@Service
public class StationsModValServiceImpl extends ServiceImpl<GardsStationsModValMapper, GardsStationsModVal> implements StationsModValService {
/**
* 查询台站模拟值
* @param taskId
* @param stationId
* @param speciesId
* @return
*/
@Override
public List<GardsStationsModVal> getStationsModVal(Integer taskId,Integer stationId,Integer speciesId) {
LambdaQueryWrapper<GardsStationsModVal> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(GardsStationsModVal::getTaskId,taskId);
queryWrapper.eq(GardsStationsModVal::getSpeciesId,speciesId);
queryWrapper.eq(GardsStationsModVal::getStationId,stationId);
queryWrapper.orderByAsc(GardsStationsModVal::getTimeSeries);
return this.baseMapper.selectList(queryWrapper);
}
/**
* 保存台站模拟值
* @param list
*/
@Transactional(rollbackFor = RuntimeException.class)
@Override
public void saveStationsModVal(List<GardsStationsModVal> list) {
this.baseMapper.insert(list);
}
}

View File

@ -2,38 +2,44 @@ package org.jeecg.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.enums.FlexpartSpeciesType;
import org.jeecg.common.constant.enums.TransportTaskModeEnum;
import org.jeecg.common.constant.enums.TransportTimingAnalysisEnum;
import org.jeecg.common.properties.TransportSimulationProperties;
import org.jeecg.common.util.NcUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.base.entity.TransportTask;
import org.jeecg.modules.base.entity.TransportTaskBackwardChild;
import org.jeecg.modules.base.entity.TransportTaskForwardChild;
import org.jeecg.modules.base.entity.*;
import org.jeecg.modules.base.entity.configuration.GardsNuclearReactors;
import org.jeecg.modules.base.entity.configuration.GardsStations;
import org.jeecg.modules.base.mapper.TransportTaskBackwardChildMapper;
import org.jeecg.modules.base.mapper.TransportTaskForwardChildMapper;
import org.jeecg.modules.base.mapper.TransportTaskMapper;
import org.jeecg.modules.base.entity.rnauto.GardsStationsModVal;
import org.jeecg.modules.base.mapper.*;
import org.jeecg.service.StationDataService;
import org.jeecg.service.StationsModValService;
import org.jeecg.service.TransportResultDataService;
import org.jeecg.util.BilinearInterpolatorWithMath;
import org.jeecg.util.PreSortedTimeRangeQuery;
import org.jeecg.vo.ContributionAnalysisVO;
import org.jeecg.vo.QueryDiffusionVO;
import org.jeecg.vo.TaskStationsVO;
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.NetcdfFile;
import ucar.nc2.Variable;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;
@ -42,11 +48,13 @@ import java.util.stream.Collectors;
@RequiredArgsConstructor
public class TransportResultDataServiceImpl implements TransportResultDataService {
private final TransportTaskForwardSpeciesMapper taskForwardSpeciesMapper;
private final TransportTaskMapper transportTaskMapper;
private final TransportSimulationProperties simulationProperties;
private final TransportTaskBackwardChildMapper backwardChildMapper;
private final TransportTaskForwardChildMapper forwardChildMapper;
private final StationDataService stationDataService;
private final StationsModValService stationsModValService;
private final RedisUtil redisUtil;
private final static String FORWARD="forward";
private final static String BACK_FORWARD="backward";
@ -79,27 +87,33 @@ public class TransportResultDataServiceImpl implements TransportResultDataServic
*/
private List<Map<String,Object>> getForwardData(TransportTask transportTask,QueryDiffusionVO queryDiffusionVO){
//获取nc文件路径
String path = this.getForwardTaskNCPath(transportTask);
String path = this.getForwardTaskNCPath(transportTask,queryDiffusionVO.getSpeciesId());
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);
int[] origin = {0, 0,queryDiffusionVO.getTime(),0, 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();
double finalValue;
if(pointData[i] > 0){
BigDecimal bg = BigDecimal.valueOf(pointData[i]);
BigDecimal value = bg.divide(BigDecimal.valueOf(1000000),6, RoundingMode.HALF_UP);
finalValue = Math.log10(value.doubleValue());
}else {
finalValue = pointData[i];
}
Map<String,Object> valMap = new HashMap<>();
valMap.put("lon",lonData.get(ix));
valMap.put("lat",latData.get(iy));
valMap.put("value",finalValue);
result.add(valMap);
}
}
return result;
@ -125,71 +139,71 @@ public class TransportResultDataServiceImpl implements TransportResultDataServic
throw new RuntimeException("此任务站点信息不存在,请确认任务配置信息");
}
List<Map<String,Object>> result = new ArrayList<>();
for(Integer pointNum : queryDiffusionVO.getPointspecs()){
//获取nc文件路径
TransportTaskBackwardChild 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);
//获取nc文件路径
TransportTaskBackwardChild transportTaskChild = transportTaskChildren.get(0);
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(),0, 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();
double finalValue;
if(pointData[i] > 0){
BigDecimal bg = BigDecimal.valueOf(pointData[i]);
BigDecimal value = bg.divide(BigDecimal.valueOf(1000000),6, RoundingMode.HALF_UP);
finalValue = Math.log10(value.doubleValue());
}else {
finalValue = pointData[i];
}
Map<String,Object> valMap = new HashMap<>();
valMap.put("lon",lonData.get(ix));
valMap.put("lat",latData.get(iy));
valMap.put("value",finalValue);
result.add(valMap);
}
} catch (IOException | InvalidRangeException e) {
throw new RuntimeException(e);
}
} 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<>();
public Map<String,Object> getResultGlobalAttr(Integer taskId) {
Map<String,Object> globalAttr = new HashMap<>();
TransportTask transportTask = this.transportTaskMapper.selectById(taskId);
if(Objects.isNull(transportTask)){
throw new RuntimeException("此任务不存在");
}
List<String> stationCodes = this.getStationCodes(transportTask.getId(),transportTask.getTaskMode());
//获取nc文件路径
String path = "";
if(TransportTaskModeEnum.FORWARD.getKey().equals(transportTask.getTaskMode())){
path = this.getForwardTaskNCPath(transportTask);
//不用考虑集合为空一定会有物种否则flexpart不能运行
LambdaQueryWrapper<TransportTaskForwardSpecies> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TransportTaskForwardSpecies::getTaskId,taskId);
List<TransportTaskForwardSpecies> transportTaskForwardSpecies = this.taskForwardSpeciesMapper.selectList(queryWrapper);
path = this.getForwardTaskNCPath(transportTask,transportTaskForwardSpecies.get(0).getSpeciesId());
}else if(TransportTaskModeEnum.BACK_FORWARD.getKey().equals(transportTask.getTaskMode())){
List<String> stationCodes = this.getStationCodes(transportTask.getId(),transportTask.getTaskMode());
path = this.getBackForwardTaskNCPath(transportTask,stationCodes.get(0));
}
if(!FileUtil.exist(path)){
throw new RuntimeException("此任务模拟结果不存在,请确认任务运行状态");
}
//本任务模拟的台站数据
Map<Integer,Object> stationNumMap = new LinkedHashMap<>();
for (int i = 0; i<stationCodes.size();i++) {
stationNumMap.put((i),stationCodes.get(i));
}
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");
@ -204,18 +218,10 @@ public class TransportResultDataServiceImpl implements TransportResultDataServic
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;
return globalAttr;
}
/**
@ -251,109 +257,36 @@ public class TransportResultDataServiceImpl implements TransportResultDataServic
}
/**
* 查询符合度分析数据
* 查询符合度分析数据-时序图
* @param taskId
* @param stationId
* @param nuclideName
* @param facilityName
* @param speciesId 物种id
* @param nuclideName 物种/核素名称
* @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);
// //获取nc文件路径
// String path = this.getForwardTaskNCPath(transportTask);
// try (NetcdfFile ncFile = NetcdfFile.open(path.toString())) {
// int pointNum = -1;
// int maxPointNum = -1;
// if (StrUtil.isNotBlank(facilityName)) {
// LambdaQueryWrapper<TransportTaskBackwardChild> queryWrapper = new LambdaQueryWrapper<>();
// queryWrapper.eq(TransportTaskBackwardChild::getTaskId,taskId);
// queryWrapper.select(TransportTaskBackwardChild::getId, TransportTaskBackwardChild::getStationCode);
// queryWrapper.orderByAsc(TransportTaskBackwardChild::getId);
// List<TransportTaskBackwardChild> 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++){
// //nageclass=1, pointspec=1, time=30, height=6, latitude=710, longitude=1430
// 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;
return null;
public List<Map<String, Object>> getConformityAnalysis(Integer taskId,Integer stationId,Integer speciesId,String nuclideName) {
List<Map<String, Object>> resultList = new ArrayList<>();
TransportTask transportTask = this.transportTaskMapper.selectById(taskId);
Date startTime = Date.from(transportTask.getStartTime().atZone(ZoneId.systemDefault()).toInstant());
Date endTime = Date.from(transportTask.getEndTime().atZone(ZoneId.systemDefault()).toInstant());
//查询时间范围内气体样品监测结果
List<Map<String, Object>> xeResults = stationDataService.getXeResults(stationId,startTime,endTime, nuclideName);
//查询正演任务模拟结果处理后的台站模拟值数据
List<GardsStationsModVal> stationsModVals = this.stationsModValService.getStationsModVal(taskId, stationId,speciesId);
xeResults.forEach(xeResult->{
Date collectStart = (Date)xeResult.get("collectStart");
Date collectStop = (Date)xeResult.get("collectStop");
double obsValue = Double.parseDouble(xeResult.get("obsValue").toString());
PreSortedTimeRangeQuery preSortedTimeRangeQuery = new PreSortedTimeRangeQuery(stationsModVals);
double modValue = preSortedTimeRangeQuery.sumConcByTimeRange(collectStart, collectStop);
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("collectStop",collectStop);
resultMap.put("obsValue",obsValue);
resultMap.put("modValue",modValue);
resultList.add(resultMap);
});
return resultList;
}
/**
@ -398,104 +331,101 @@ public class TransportResultDataServiceImpl implements TransportResultDataServic
*/
@Override
public void handleContributionAnalysis(Integer taskId) {
// //查询任务数据
// TransportTask transportTask = transportTaskMapper.selectById(taskId);
// //查询需要处理贡献分析数据的台站
// LambdaQueryWrapper<TransportTaskBackwardChild> queryWrapper = new LambdaQueryWrapper<>();
// queryWrapper.eq(TransportTaskBackwardChild::getTaskId,taskId);
// List<TransportTaskBackwardChild> stationInfos = this.transportTaskChildMapper.selectList(queryWrapper);
//
// //所以核设施数据
// List<GardsNuclearReactors> facilitys = (List<GardsNuclearReactors>) redisUtil.get(CommonConstant.ALL_NUCLEARFACILITY);
//
// NetcdfFile ncFile = null;
// try {
// for(TransportTaskBackwardChild stationInfo :stationInfos) {
// //每个台站的结果数据
// ContributionAnalysisVO contributionAnalysisVO = new ContributionAnalysisVO();
// //存储台站每天的浓度值数据
// Map<String,Double> stationEveryDayConcDatas = new LinkedHashMap<>();
// //存储核设施每天的浓度值数据
// Map<String,Map<String,Double>> facilityEveryDayConcDatas = new HashMap<>();
// //饼图数据
// Map<String,Double> pipeChartData = new HashMap<>();
// //总浓度值
// Double totalConc = 0D;
// //获取nc文件路径
// String path = this.getBackForwardTaskNCPath(transportTask,stationInfo.getStationCode());
// ncFile = NetcdfFile.open(path.toString());
// List<Double> lonData = NcUtil.getNCList(ncFile, "longitude");
// List<Double> latData = NcUtil.getNCList(ncFile, "latitude");
// List<Double> timeData = NcUtil.getNCList(ncFile, "time");
// Variable spec001Mr = ncFile.findVariable("spec001_mr");
// for(int k=0;k<timeData.size();k++){
// System.out.println(stationInfo.getStationCode()+"循环:"+k+",共"+timeData.size()+"");
// //处理日期数据
// Instant instant = transportTask.getEndTime().toInstant();
// LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
// localDateTime = localDateTime.plusSeconds(timeData.get(k).intValue());
// String dayStr = LocalDateTimeUtil.format(localDateTime, "yyyy-MM-dd");
// if (!stationEveryDayConcDatas.containsKey(dayStr)) {
// stationEveryDayConcDatas.put(dayStr,0D);
// }
// //获取台站点位取整后±1.5度内的点坐标及数据使用插值算法求台站点位的值
// Double stationConc = this.getTargetSiteConc(lonData,latData,stationInfo.getLon(),stationInfo.getLat(),k,spec001Mr);
// //累加台站位置当前天的浓度数据
// stationEveryDayConcDatas.put(dayStr,stationEveryDayConcDatas.get(dayStr)+stationConc);
//
// for (GardsNuclearReactors facility : facilitys){
// Double facilityConc = this.getTargetSiteConc(lonData,latData,facility.getLongitude(),facility.getLatitude(),k,spec001Mr);
// if (facilityConc>0){
// if (!facilityEveryDayConcDatas.containsKey(dayStr)) {
// Map<String,Double> facilityConcMap = new HashMap<>();
// facilityConcMap.put(facility.getUnitName(),facilityConc);
// facilityEveryDayConcDatas.put(dayStr,facilityConcMap);
// }else {
// Map<String,Double> facilityConcMap = facilityEveryDayConcDatas.get(dayStr);
// if (!facilityConcMap.containsKey(facility.getUnitName())) {
// facilityConcMap.put(facility.getUnitName(),facilityConc);
// }else {
// facilityConcMap.put(facility.getUnitName(),facilityConcMap.get(facility.getUnitName())+facilityConc);
// }
// }
// }
// }
// }
// //计算本模拟时间内总浓度数据
// totalConc = stationEveryDayConcDatas.values().stream().mapToDouble(Double::doubleValue).sum();
// //处理饼图数据
// if(CollUtil.isNotEmpty(facilityEveryDayConcDatas)){
// for (Map<String,Double> facilityConcMap : facilityEveryDayConcDatas.values()) {
// Set<Map.Entry<String, Double>> entries = facilityConcMap.entrySet();
// for (Map.Entry<String, Double> entry : entries) {
// if (!pipeChartData.containsKey(entry.getKey())) {
// pipeChartData.put(entry.getKey(),entry.getValue());
// }else {
// pipeChartData.put(entry.getKey(),pipeChartData.get(entry.getKey())+entry.getValue());
// }
// }
// }
// }
// //处理返回值
// contributionAnalysisVO.setTotalConc(totalConc);
// contributionAnalysisVO.setStationEveryDayConcDatas(stationEveryDayConcDatas);
// contributionAnalysisVO.setFacilityEveryDayConcDatas(facilityEveryDayConcDatas);
// contributionAnalysisVO.setNuclideNames(new ArrayList<>(pipeChartData.keySet()));
// contributionAnalysisVO.setPipeChartData(pipeChartData);
// redisUtil.set(CommonConstant.TRANSPORT_CONTRIBUTION_ANALYSIS+transportTask.getId()+":"+stationInfo.getStationCode(), contributionAnalysisVO);
// ncFile.close();
// }
// }catch (IOException | InvalidRangeException e) {
// throw new RuntimeException(e);
// }finally {
// try {
// if(ncFile !=null){
// ncFile.close();
// }
// } catch (IOException e) {
// throw new RuntimeException(e);
// }
// }
//查询任务数据
TransportTask transportTask = transportTaskMapper.selectById(taskId);
//查询需要处理贡献分析数据的台站
LambdaQueryWrapper<TransportTaskBackwardChild> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TransportTaskBackwardChild::getTaskId,taskId);
List<TransportTaskBackwardChild> stationInfos = this.backwardChildMapper.selectList(queryWrapper);
//所以核设施数据
List<GardsNuclearReactors> facilitys = (List<GardsNuclearReactors>) redisUtil.get(CommonConstant.ALL_NUCLEARFACILITY);
NetcdfFile ncFile = null;
try {
for(TransportTaskBackwardChild stationInfo :stationInfos) {
//每个台站的结果数据
ContributionAnalysisVO contributionAnalysisVO = new ContributionAnalysisVO();
//存储台站每天的浓度值数据
Map<String,Double> stationEveryDayConcDatas = new LinkedHashMap<>();
//存储核设施每天的浓度值数据
Map<String,Map<String,Double>> facilityEveryDayConcDatas = new HashMap<>();
//饼图数据
Map<String,Double> pipeChartData = new HashMap<>();
//总浓度值
double totalConc = 0D;
//获取nc文件路径
String path = this.getBackForwardTaskNCPath(transportTask,stationInfo.getStationCode());
ncFile = NetcdfFile.open(path.toString());
List<Double> lonData = NcUtil.getNCList(ncFile, "longitude");
List<Double> latData = NcUtil.getNCList(ncFile, "latitude");
List<Double> timeData = NcUtil.getNCList(ncFile, "time");
Variable spec001Mr = ncFile.findVariable("spec001_mr");
for(int k=0;k<timeData.size();k++){
System.out.println(stationInfo.getStationCode()+"循环:"+k+",共"+timeData.size()+"");
//处理日期数据
String dayStr = LocalDateTimeUtil.format(transportTask.getEndTime(), "yyyy-MM-dd");
if (!stationEveryDayConcDatas.containsKey(dayStr)) {
stationEveryDayConcDatas.put(dayStr,0D);
}
//获取台站点位取整后±1.5度内的点坐标及数据使用插值算法求台站点位的值
Double stationConc = this.getTargetSiteConc(lonData,latData,stationInfo.getLon(),stationInfo.getLat(),k,spec001Mr);
//累加台站位置当前天的浓度数据
stationEveryDayConcDatas.put(dayStr,stationEveryDayConcDatas.get(dayStr)+stationConc);
for (GardsNuclearReactors facility : facilitys){
Double facilityConc = this.getTargetSiteConc(lonData,latData,facility.getLongitude(),facility.getLatitude(),k,spec001Mr);
if (facilityConc>0){
if (!facilityEveryDayConcDatas.containsKey(dayStr)) {
Map<String,Double> facilityConcMap = new HashMap<>();
facilityConcMap.put(facility.getUnitName(),facilityConc);
facilityEveryDayConcDatas.put(dayStr,facilityConcMap);
}else {
Map<String,Double> facilityConcMap = facilityEveryDayConcDatas.get(dayStr);
if (!facilityConcMap.containsKey(facility.getUnitName())) {
facilityConcMap.put(facility.getUnitName(),facilityConc);
}else {
facilityConcMap.put(facility.getUnitName(),facilityConcMap.get(facility.getUnitName())+facilityConc);
}
}
}
}
}
//计算本模拟时间内总浓度数据
totalConc = stationEveryDayConcDatas.values().stream().mapToDouble(Double::doubleValue).sum();
//处理饼图数据
if(CollUtil.isNotEmpty(facilityEveryDayConcDatas)){
for (Map<String,Double> facilityConcMap : facilityEveryDayConcDatas.values()) {
Set<Map.Entry<String, Double>> entries = facilityConcMap.entrySet();
for (Map.Entry<String, Double> entry : entries) {
if (!pipeChartData.containsKey(entry.getKey())) {
pipeChartData.put(entry.getKey(),entry.getValue());
}else {
pipeChartData.put(entry.getKey(),pipeChartData.get(entry.getKey())+entry.getValue());
}
}
}
}
//处理返回值
contributionAnalysisVO.setTotalConc(totalConc);
contributionAnalysisVO.setStationEveryDayConcDatas(stationEveryDayConcDatas);
contributionAnalysisVO.setFacilityEveryDayConcDatas(facilityEveryDayConcDatas);
contributionAnalysisVO.setNuclideNames(new ArrayList<>(pipeChartData.keySet()));
contributionAnalysisVO.setPipeChartData(pipeChartData);
redisUtil.set(CommonConstant.TRANSPORT_CONTRIBUTION_ANALYSIS+transportTask.getId()+":"+stationInfo.getStationCode(), contributionAnalysisVO);
ncFile.close();
}
}catch (IOException | InvalidRangeException e) {
throw new RuntimeException(e);
}finally {
try {
if(ncFile !=null){
ncFile.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
/**
@ -533,53 +463,6 @@ public class TransportResultDataServiceImpl implements TransportResultDataServic
return taskStationsVOList;
}
/**
* 查询任务所属NC层级数据
*
* @param taskId
* @return
*/
@Override
public Map<Integer, Object> getTaskNCHeightLevel(Integer taskId) {
Map<Integer,Object> resultMap = new HashMap<>();
TransportTask transportTask = this.transportTaskMapper.selectById(taskId);
if(Objects.isNull(transportTask)){
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())){
LambdaQueryWrapper<TransportTaskBackwardChild> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TransportTaskBackwardChild::getTaskId,taskId);
queryWrapper.select(TransportTaskBackwardChild::getId, TransportTaskBackwardChild::getStationCode);
queryWrapper.orderByAsc(TransportTaskBackwardChild::getId);
List<TransportTaskBackwardChild> transportTaskChildren = backwardChildMapper.selectList(queryWrapper);
if(CollUtil.isEmpty(transportTaskChildren)){
throw new RuntimeException("此任务站点信息不存在,请确认任务配置信息");
}
path = this.getBackForwardTaskNCPath(transportTask,transportTaskChildren.get(0).getStationCode());
}
if(!FileUtil.exist(path)){
throw new RuntimeException("此任务模拟结果不存在,请确认任务运行状态");
}
//全局属性
try (NetcdfFile ncFile = NetcdfFile.open(path.toString())) {
Variable heightVar = ncFile.findVariable("height");
Array data = heightVar.read();
int[] shape = data.getShape();
Index index = data.getIndex();
for(int i=0;i<shape[0];i++){
resultMap.put((i),data.getDouble(index.set(i)));
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return resultMap;
}
/**
* 查询反演核设施时序数据接口
* @param taskId
@ -589,46 +472,44 @@ public class TransportResultDataServiceImpl implements TransportResultDataServic
*/
@Override
public Map<String,Double> getTimingAnalysis(Integer taskId,String stationCode,String facilityName,Integer timeNum) {
// TransportTask transportTask = transportTaskMapper.selectById(taskId);
// if(Objects.isNull(transportTask)){
// throw new RuntimeException("此任务不存在");
// }
// //包含从缓存中拿
// String key = CommonConstant.TRANSPORT_TIMING_ANALYSIS+transportTask.getId()+":"+stationCode+":"+facilityName;
// if(redisUtil.hasKey(key)){
// Map<String,Double> concValMap = (LinkedHashMap)redisUtil.get(key);
// //如果是3小时纬度直接范围因为最小是3小时
// if (TransportTimingAnalysisEnum.THREE_HOURS.getKey().equals(timeNum)) {
// concValMap.forEach((k,v)->{
// //纳克转换为毫克需除以1000000
// BigDecimal concValue = new BigDecimal(v);
// BigDecimal finalValue = concValue.divide(new BigDecimal(1000000)).setScale(5,BigDecimal.ROUND_HALF_UP);
// concValMap.put(k,finalValue.doubleValue());
// });
// return concValMap;
// }else{
// Map<String,Double> resultMap = new LinkedHashMap<>();
// Instant endTimeInstant = transportTask.getEndTime().toInstant();
// LocalDateTime endTime = LocalDateTime.ofInstant(endTimeInstant, ZoneId.systemDefault());
//
// Instant startTimeInstant = transportTask.getStartTime().toInstant();
// LocalDateTime startTime = LocalDateTime.ofInstant(startTimeInstant, ZoneId.systemDefault());
//
// boolean flag = true;
// while(flag){
// String dayTimeStr = LocalDateTimeUtil.format(startTime, "yyyy-MM-dd HH:mm:ss");
// //纳克转换为毫克需除以1000000
// BigDecimal concValue = new BigDecimal(concValMap.get(dayTimeStr));
// BigDecimal finalValue = concValue.divide(new BigDecimal(1000000)).setScale(5,BigDecimal.ROUND_HALF_UP);
// resultMap.put(dayTimeStr,finalValue.doubleValue());
// startTime = startTime.plusHours(timeNum);
// if(startTime.isEqual(endTime)){
// flag = false;
// }
// }
// return resultMap;
// }
// }
TransportTask transportTask = transportTaskMapper.selectById(taskId);
if(Objects.isNull(transportTask)){
throw new RuntimeException("此任务不存在");
}
//包含从缓存中拿
String key = CommonConstant.TRANSPORT_TIMING_ANALYSIS+transportTask.getId()+":"+stationCode+":"+facilityName;
if(redisUtil.hasKey(key)){
Map<String,Double> concValMap = (LinkedHashMap)redisUtil.get(key);
//如果是3小时纬度直接范围因为最小是3小时
if (TransportTimingAnalysisEnum.THREE_HOURS.getKey().equals(timeNum)) {
concValMap.forEach((k,v)->{
//纳克转换为毫克需除以1000000
BigDecimal concValue = BigDecimal.valueOf(v);
BigDecimal finalValue = concValue.divide(BigDecimal.valueOf(1000000)).setScale(5, RoundingMode.HALF_UP);
concValMap.put(k,finalValue.doubleValue());
});
return concValMap;
}else{
Map<String,Double> resultMap = new LinkedHashMap<>();
LocalDateTime endTime = transportTask.getEndTime();
LocalDateTime startTime = transportTask.getStartTime();
boolean flag = true;
while(flag){
String dayTimeStr = LocalDateTimeUtil.format(startTime, "yyyy-MM-dd HH:mm:ss");
//纳克转换为毫克需除以1000000
BigDecimal concValue = BigDecimal.valueOf(concValMap.get(dayTimeStr));
BigDecimal finalValue = concValue.divide(new BigDecimal(1000000)).setScale(5, RoundingMode.HALF_UP);
resultMap.put(dayTimeStr,finalValue.doubleValue());
startTime = startTime.plusHours(timeNum);
if(startTime.isEqual(endTime)){
flag = false;
}
}
return resultMap;
}
}
return Map.of();
}
@ -639,89 +520,157 @@ public class TransportResultDataServiceImpl implements TransportResultDataServic
*/
@Override
public void handleTimingAnalysis(Integer taskId) {
// TransportTask transportTask = this.transportTaskMapper.selectById(taskId);
//
// //查询需要处理数据的台站
// LambdaQueryWrapper<TransportTaskBackwardChild> queryWrapper = new LambdaQueryWrapper<>();
// queryWrapper.eq(TransportTaskBackwardChild::getTaskId,taskId);
// List<TransportTaskBackwardChild> stationInfos = this.transportTaskChildMapper.selectList(queryWrapper);
//
// //所以核设施数据
// List<GardsNuclearReactors> facilitys = (List<GardsNuclearReactors>) redisUtil.get(CommonConstant.ALL_NUCLEARFACILITY);
//
// NetcdfFile ncFile = null;
// try {
// for(TransportTaskBackwardChild stationInfo :stationInfos) {
// log.info("处理"+stationInfo.getStationCode()+"台站数据");
// Map<String,Map<String,Double>> everyFacilityConcDatas = new HashMap<>();
// //获取nc文件路径
// String path = this.getBackForwardTaskNCPath(transportTask,stationInfo.getStationCode());
// ncFile = NetcdfFile.open(path.toString());
// List<Double> lonData = NcUtil.getNCList(ncFile, "longitude");
// List<Double> latData = NcUtil.getNCList(ncFile, "latitude");
// List<Double> timeData = NcUtil.getNCList(ncFile, "time");
// Variable spec001Mr = ncFile.findVariable("spec001_mr");
// for (GardsNuclearReactors facility : facilitys){
// //存储台站每步的浓度值数据
// Map<String,Double> everyStepConcDatas = new LinkedHashMap<>();
// for(int k=0;k<timeData.size();k++){
// //处理日期数据
// Instant instant = transportTask.getEndTime().toInstant();
// LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
// localDateTime = localDateTime.plusSeconds(timeData.get(k).intValue());
// String dayTimeStr = LocalDateTimeUtil.format(localDateTime, "yyyy-MM-dd HH:mm:ss");
// //获取台站点位取整后±1.5度内的点坐标及数据使用插值算法求台站点位的值
// Double facilityConc = this.getTargetSiteConc(lonData,latData,facility.getLongitude(),facility.getLatitude(),k,spec001Mr);
// everyStepConcDatas.put(dayTimeStr,facilityConc);
// }
// everyFacilityConcDatas.put(facility.getUnitName(),everyStepConcDatas);
// }
// if(CollUtil.isNotEmpty(everyFacilityConcDatas)){
// everyFacilityConcDatas.forEach((facilityName,facilityConcData)->{
// String key = CommonConstant.TRANSPORT_TIMING_ANALYSIS+transportTask.getId()+":"+stationInfo.getStationCode()+":"+facilityName;
// redisUtil.set(key, facilityConcData);
// });
// }
// ncFile.close();
// }
// }catch (IOException | InvalidRangeException e) {
// throw new RuntimeException(e);
// }finally {
// try {
// if(ncFile !=null){
// ncFile.close();
// }
// } catch (IOException e) {
// throw new RuntimeException(e);
// }
// }
TransportTask transportTask = this.transportTaskMapper.selectById(taskId);
//查询需要处理数据的台站
LambdaQueryWrapper<TransportTaskBackwardChild> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TransportTaskBackwardChild::getTaskId,taskId);
List<TransportTaskBackwardChild> stationInfos = this.backwardChildMapper.selectList(queryWrapper);
//所以核设施数据
List<GardsNuclearReactors> facilitys = (List<GardsNuclearReactors>) redisUtil.get(CommonConstant.ALL_NUCLEARFACILITY);
NetcdfFile ncFile = null;
try {
for(TransportTaskBackwardChild stationInfo :stationInfos) {
log.info("处理"+stationInfo.getStationCode()+"台站数据");
Map<String,Map<String,Double>> everyFacilityConcDatas = new HashMap<>();
//获取nc文件路径
String path = this.getBackForwardTaskNCPath(transportTask,stationInfo.getStationCode());
ncFile = NetcdfFile.open(path.toString());
List<Double> lonData = NcUtil.getNCList(ncFile, "longitude");
List<Double> latData = NcUtil.getNCList(ncFile, "latitude");
List<Double> timeData = NcUtil.getNCList(ncFile, "time");
Variable spec001Mr = ncFile.findVariable("spec001_mr");
for (GardsNuclearReactors facility : facilitys){
//存储台站每步的浓度值数据
Map<String,Double> everyStepConcDatas = new LinkedHashMap<>();
for(int k=0;k<timeData.size();k++){
//处理日期数据
String dayTimeStr = LocalDateTimeUtil.format(transportTask.getEndTime(), "yyyy-MM-dd HH:mm:ss");
//获取台站点位取整后±1.5度内的点坐标及数据使用插值算法求台站点位的值
Double facilityConc = this.getTargetSiteConc(lonData,latData,facility.getLongitude(),facility.getLatitude(),k,spec001Mr);
everyStepConcDatas.put(dayTimeStr,facilityConc);
}
everyFacilityConcDatas.put(facility.getUnitName(),everyStepConcDatas);
}
if(CollUtil.isNotEmpty(everyFacilityConcDatas)){
everyFacilityConcDatas.forEach((facilityName,facilityConcData)->{
String key = CommonConstant.TRANSPORT_TIMING_ANALYSIS+transportTask.getId()+":"+stationInfo.getStationCode()+":"+facilityName;
redisUtil.set(key, facilityConcData);
});
}
ncFile.close();
}
}catch (IOException | InvalidRangeException e) {
throw new RuntimeException(e);
}finally {
try {
if(ncFile !=null){
ncFile.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
/**
* 找到集合中里最接近目标值的值
* @param data
* @param target
* 查询任务模拟核素数据
*
* @param taskId
* @return
*/
private Map<String,Object> getRecentValue(List<Double> data,Double target){
if(CollUtil.isEmpty(data)){
throw new RuntimeException("data集合数据为空");
@Override
public List<String> getTaskSimulationNuclide(Integer taskId) {
List<String> result = new ArrayList<>();
LambdaQueryWrapper<TransportTaskForwardSpecies> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TransportTaskForwardSpecies::getTaskId,taskId);
List<TransportTaskForwardSpecies> species = taskForwardSpeciesMapper.selectList(queryWrapper);
if(CollUtil.isNotEmpty(species)){
species.forEach(specie -> {
String nuclideName = "";
if (specie.getSpeciesId().equals(FlexpartSpeciesType.XE_131m.getId().toString())){
nuclideName = FlexpartSpeciesType.XE_131m.getNuclideName();
}else if (specie.getSpeciesId().equals(FlexpartSpeciesType.XE_135.getId().toString())){
nuclideName = FlexpartSpeciesType.XE_135.getNuclideName();
}else if (specie.getSpeciesId().equals(FlexpartSpeciesType.XE_133m.getId().toString())){
nuclideName = FlexpartSpeciesType.XE_133m.getNuclideName();
}else if (specie.getSpeciesId().equals(FlexpartSpeciesType.XE_133.getId().toString())){
nuclideName = FlexpartSpeciesType.XE_133.getNuclideName();
}
result.add(nuclideName);
});
}
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;
}
return result;
}
/**
* 查询任务模拟核素数据-包含物种id和名称
*
* @param taskId
* @return
*/
@Override
public Map<Integer, String> getTaskSimulationSpecies(Integer taskId) {
Map<Integer, String> result = new LinkedHashMap<>();
LambdaQueryWrapper<TransportTaskForwardSpecies> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TransportTaskForwardSpecies::getTaskId,taskId);
List<TransportTaskForwardSpecies> species = taskForwardSpeciesMapper.selectList(queryWrapper);
if(CollUtil.isNotEmpty(species)){
species.forEach(specie -> {
String nuclideName = "";
if (specie.getSpeciesId().equals(FlexpartSpeciesType.XE_131m.getId())){
nuclideName = FlexpartSpeciesType.XE_131m.getNuclideName();
}else if (specie.getSpeciesId().equals(FlexpartSpeciesType.XE_133.getId())){
nuclideName = FlexpartSpeciesType.XE_133.getNuclideName();
}else if (specie.getSpeciesId().equals(FlexpartSpeciesType.XE_133m.getId())){
nuclideName = FlexpartSpeciesType.XE_133m.getNuclideName();
}else if (specie.getSpeciesId().equals(FlexpartSpeciesType.XE_135.getId())){
nuclideName = FlexpartSpeciesType.XE_135.getNuclideName();
}
result.put(specie.getSpeciesId(),nuclideName);
});
}
return result;
}
/**
* 查询符合度分析数据-散点图
* @param taskId
* @param stationIds
* @param speciesId
* @param nuclideName
* @return
*/
@Override
public Map<String, List<Map<String, Object>>> getConformityAnalysisScatterPlot(Integer taskId,String stationIds,Integer speciesId,String nuclideName) {
Map<String, List<Map<String, Object>>> resultMap = new HashMap<>();
String[] stationIdsArr = stationIds.split(",");
TransportTask transportTask = this.transportTaskMapper.selectById(taskId);
Date startTime = Date.from(transportTask.getStartTime().atZone(ZoneId.systemDefault()).toInstant());
Date endTime = Date.from(transportTask.getEndTime().atZone(ZoneId.systemDefault()).toInstant());
for (String stationId : stationIdsArr) {
int stationIdInt = Integer.parseInt(stationId);
List<Map<String, Object>> stationData = new ArrayList<>();
//查询时间范围内气体样品监测结果
List<Map<String, Object>> xeResults = stationDataService.getXeResults(stationIdInt,startTime,endTime,nuclideName);
//查询正演任务模拟结果处理后的台站模拟值数据
List<GardsStationsModVal> stationsModVals = this.stationsModValService.getStationsModVal(taskId, stationIdInt,speciesId);
xeResults.forEach(xeResult->{
Date collectStart = (Date)xeResult.get("collectStart");
Date collectStop = (Date)xeResult.get("collectStop");
double obsValue = Double.parseDouble(xeResult.get("obsValue").toString());
PreSortedTimeRangeQuery preSortedTimeRangeQuery = new PreSortedTimeRangeQuery(stationsModVals);
double modValue = preSortedTimeRangeQuery.sumConcByTimeRange(collectStart, collectStop);
Map<String, Object> map = new HashMap<>();
map.put("obsValue",obsValue);
map.put("modValue",modValue);
stationData.add(map);
});
GardsStations stationInfo = stationDataService.getStationById(stationIdInt);
resultMap.put(stationInfo.getStationCode(),stationData);
}
Map<String,Object> resultMap = new HashMap<>();
resultMap.put("bestIndex",bestIndex);
resultMap.put("minDist",minDist);
return resultMap;
}
@ -730,7 +679,7 @@ public class TransportResultDataServiceImpl implements TransportResultDataServic
* @param transportTask
* @return
*/
private String getForwardTaskNCPath(TransportTask transportTask){
private String getForwardTaskNCPath(TransportTask transportTask,Integer speciesId){
//拼接nc文件路径
StringBuilder path = new StringBuilder();
path.append(simulationProperties.getOutputPath());
@ -739,6 +688,8 @@ public class TransportResultDataServiceImpl implements TransportResultDataServic
path.append(File.separator);
path.append(FORWARD);
path.append(File.separator);
path.append(speciesId.toString());
path.append(File.separator);
path.append("grid_conc_"+DateUtil.format(transportTask.getStartTime(),"yyyyMMddHHmmss")+".nc");
return path.toString();
}
@ -821,4 +772,6 @@ public class TransportResultDataServiceImpl implements TransportResultDataServic
BilinearInterpolatorWithMath.GridData grid = new BilinearInterpolatorWithMath.GridData(siteData, 0.25, 0.125);
return grid.interpolate(targetLon,targetLat);
}
}

View File

@ -1,11 +1,13 @@
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.text.csv.CsvData;
import cn.hutool.core.text.csv.CsvReader;
import cn.hutool.core.text.csv.CsvRow;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
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.extension.plugins.pagination.Page;
@ -16,33 +18,33 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jeecg.common.constant.enums.*;
import org.jeecg.common.properties.DataFusionProperties;
import org.jeecg.common.properties.SystemStorageProperties;
import org.jeecg.common.properties.TransportSimulationProperties;
import org.jeecg.common.system.query.PageRequest;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.base.dto.TransportTaskDTO;
import org.jeecg.modules.base.entity.*;
import org.jeecg.modules.base.entity.configuration.GardsNuclearReactors;
import org.jeecg.modules.base.entity.configuration.GardsDetectors;
import org.jeecg.modules.base.entity.configuration.GardsStations;
import org.jeecg.modules.base.entity.original.GardsSampleData;
import org.jeecg.modules.base.entity.rnauto.GardsXeResults;
import org.jeecg.modules.base.mapper.*;
import org.jeecg.properties.ServerProperties;
import org.jeecg.producer.TransportTaskProducer;
import org.jeecg.service.StationDataService;
import org.jeecg.service.TransportTaskService;
import org.jeecg.task.flexparttask.AbstractTaskExec;
import org.jeecg.task.flexparttask.BackwardTaskExec;
import org.jeecg.task.flexparttask.ForwardTaskExec;
import org.jeecg.vo.SiteAndReleaseDataVO;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
/**
* 输运模拟任务管理
@ -53,19 +55,14 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
private final TransportTaskBackwardChildMapper taskBackwardChildMapper;
private final TransportTaskLogMapper transportTaskLogMapper;
private final WeatherDataMapper weatherDataMapper;
private final TransportSimulationProperties simulationProperties;
private final SystemStorageProperties systemStorageProperties;
private final RedisUtil redisUtil;
private final DataFusionProperties dataFusionProperties;
private final TransportTaskForwardReleaseMapper taskForwardReleaseMapper;
private final TransportTaskForwardChildMapper taskForwardChildMapper;
private final TransportTaskForwardSpeciesMapper taskForwardSpeciesMapper;
private final ServerProperties serverProperties;
private final GardsNuclearReactorsMapper gardsNuclearReactorsMapper;
private final DataSourceTransactionManager transactionManager;
private final TransactionDefinition transactionDefinition;
private final StationDataService stationDataService;
private final TransportTaskProducer transportTaskProducer;
/**
* 分页查询任务列表
@ -176,17 +173,6 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
List<TransportTaskForwardChild> taskChildren = taskForwardChildMapper.selectList(queryWrapper);
if(CollUtil.isNotEmpty(taskChildren)){
transportTask.setForwardChild(taskChildren);
if(TransportReleaseDataSource.MANUAL_ENTRY.getKey().equals(transportTask.getReleaseDataSource())){
taskChildren.forEach(taskChild -> {
LambdaQueryWrapper<TransportTaskForwardRelease> releaseQueryWrapper = new LambdaQueryWrapper<>();
releaseQueryWrapper.eq(TransportTaskForwardRelease::getForwardChildId,taskChild.getId());
releaseQueryWrapper.orderByAsc(TransportTaskForwardRelease::getStartTime);
List<TransportTaskForwardRelease> forwardReleases = taskForwardReleaseMapper.selectList(releaseQueryWrapper);
if(CollUtil.isNotEmpty(forwardReleases)){
taskChild.setForwardReleaseChild(forwardReleases);
}
});
}
}
LambdaQueryWrapper<TransportTaskForwardSpecies> speciesQueryWrapper = new LambdaQueryWrapper<>();
speciesQueryWrapper.eq(TransportTaskForwardSpecies::getTaskId,transportTask.getId());
@ -238,29 +224,13 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
taskBackwardChildMapper.insert(transportTask.getBackwardChild());
}
}else if (TransportTaskModeEnum.FORWARD.getKey().equals(transportTask.getTaskMode())) {
//先删除再新增
LambdaQueryWrapper<TransportTaskForwardChild> delForwardChildQueryWrapper = new LambdaQueryWrapper<>();
delForwardChildQueryWrapper.eq(TransportTaskForwardChild::getTaskId,checkIdResult.getId());
taskForwardChildMapper.delete(delForwardChildQueryWrapper);
LambdaQueryWrapper<TransportTaskForwardRelease> delForwardReleaseQueryWrapper = new LambdaQueryWrapper<>();
delForwardReleaseQueryWrapper.eq(TransportTaskForwardRelease::getTaskId,checkIdResult.getId());
taskForwardReleaseMapper.delete(delForwardReleaseQueryWrapper);
LambdaQueryWrapper<TransportTaskForwardSpecies> delForwardSpeciesQueryWrapper = new LambdaQueryWrapper<>();
delForwardSpeciesQueryWrapper.eq(TransportTaskForwardSpecies::getTaskId,checkIdResult.getId());
taskForwardSpeciesMapper.delete(delForwardSpeciesQueryWrapper);
//重新新增
//这里正演并且是自动选择排放数据时需先删除再保存比较方便手动设置排放数据另写接口
if(CollUtil.isNotEmpty(transportTask.getForwardChild())){
if(TransportReleaseDataSource.MANUAL_ENTRY.getKey().equals(transportTask.getReleaseDataSource())){
for (TransportTaskForwardChild child : transportTask.getForwardChild()) {
child.setTaskId(transportTask.getId());
taskForwardChildMapper.insert(child);
child.getForwardReleaseChild().forEach(forwardReleaseChild -> {
forwardReleaseChild.setForwardChildId(child.getId());
forwardReleaseChild.setTaskId(transportTask.getId());
});
taskForwardReleaseMapper.insert(child.getForwardReleaseChild());
}
}else {
if(TransportReleaseDataSource.AUTO_SELECT.getKey().equals(transportTask.getReleaseDataSource())){
//先删除再新增
LambdaQueryWrapper<TransportTaskForwardChild> delForwardChildQueryWrapper = new LambdaQueryWrapper<>();
delForwardChildQueryWrapper.eq(TransportTaskForwardChild::getTaskId,checkIdResult.getId());
taskForwardChildMapper.delete(delForwardChildQueryWrapper);
transportTask.getForwardChild().forEach(transportTaskChild -> {
transportTaskChild.setTaskId(transportTask.getId());
});
@ -268,6 +238,9 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
}
}
if(CollUtil.isNotEmpty(transportTask.getSpecies())){
LambdaQueryWrapper<TransportTaskForwardSpecies> delForwardSpeciesQueryWrapper = new LambdaQueryWrapper<>();
delForwardSpeciesQueryWrapper.eq(TransportTaskForwardSpecies::getTaskId,checkIdResult.getId());
taskForwardSpeciesMapper.delete(delForwardSpeciesQueryWrapper);
transportTask.getSpecies().forEach(transportTaskSpecies -> {
transportTaskSpecies.setTaskId(transportTask.getId());
});
@ -304,14 +277,32 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
speciesQueryWrapper.eq(TransportTaskForwardSpecies::getTaskId,id);
this.taskForwardSpeciesMapper.delete(speciesQueryWrapper);
}
//删除任务日志
LambdaQueryWrapper<TransportTaskLog> logQueryWrapper = new LambdaQueryWrapper<>();
logQueryWrapper.eq(TransportTaskLog::getTaskId,id);
this.transportTaskLogMapper.delete(logQueryWrapper);
this.baseMapper.deleteById(id);
File resultDir = new File(this.simulationProperties.getOutputPath()+ File.separator + transportTask.getTaskName());
if (!resultDir.exists()) {
if (resultDir.exists()) {
FileUtil.del(resultDir);
}
}
}
/**
* 根据任务名称校验任务是否存在
*
* @param taskName
* @return
*/
@Override
public boolean checkTaskByName(String taskName) {
LambdaQueryWrapper<TransportTask> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TransportTask::getTaskName,taskName);
TransportTask transportTask = this.baseMapper.selectOne(queryWrapper);
return Objects.isNull(transportTask);
}
/**
* 运行任务
*
@ -330,61 +321,77 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
queryWrapper.eq(TransportTaskBackwardChild::getTaskId,id);
queryWrapper.orderByAsc(TransportTaskBackwardChild::getId);
List<TransportTaskBackwardChild> transportTaskChildren = taskBackwardChildMapper.selectList(queryWrapper);
if(Objects.isNull(transportTaskChildren)){
throw new RuntimeException("此任务对应的flexpart反演配置信息不存在,请确认");
if(CollUtil.isEmpty(transportTaskChildren)){
throw new RuntimeException("配置信息缺失,请确认");
}
AbstractTaskExec taskExec = new BackwardTaskExec();
taskExec.init(weatherDataMapper,this,
checkIdResult,transportTaskChildren,
simulationProperties,systemStorageProperties,
dataFusionProperties,serverProperties);
taskExec.setName("大气输运反演任务执行线程");
taskExec.start();
transportTaskChildren.forEach(taskBackwardChild -> {
if(taskBackwardChild.getAcqStartTime().isAfter(taskBackwardChild.getAcqEndTime())){
throw new RuntimeException(taskBackwardChild.getStationCode()+"站点,样品测量开始时间不能在结束时间之后,请确认");
}
if(taskBackwardChild.getAcqStartTime().isAfter(checkIdResult.getEndTime())){
throw new RuntimeException(taskBackwardChild.getStationCode()+"站点,样品测量结束时间不能在任务模拟结束时间之后,请确认");
}
if(taskBackwardChild.getAcqStartTime().isBefore(checkIdResult.getStartTime())){
throw new RuntimeException(taskBackwardChild.getStationCode()+"站点,样品测量开始时间不能在任务模拟开始时间之前,请确认");
}
});
}else if (TransportTaskModeEnum.FORWARD.getKey().equals(checkIdResult.getTaskMode())){
//查询物种
LambdaQueryWrapper<TransportTaskForwardSpecies> speciesQueryWrapper = new LambdaQueryWrapper<>();
speciesQueryWrapper.eq(TransportTaskForwardSpecies::getTaskId,id);
List<TransportTaskForwardSpecies> species = this.taskForwardSpeciesMapper.selectList(speciesQueryWrapper);
if (CollUtil.isNotEmpty(species)) {
checkIdResult.setSpecies(species);
if (CollUtil.isEmpty(species)) {
throw new RuntimeException("物种配置信息缺失,请确认");
}
//查询台站信息
LambdaQueryWrapper<TransportTaskForwardChild> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TransportTaskForwardChild::getTaskId,id);
List<TransportTaskForwardChild> stationInfo = taskForwardChildMapper.selectList(queryWrapper);
if (CollUtil.isNotEmpty(stationInfo)) {
stationInfo.forEach(station -> {
LambdaQueryWrapper<TransportTaskForwardRelease> releaseQueryWrapper = new LambdaQueryWrapper<>();
releaseQueryWrapper.eq(TransportTaskForwardRelease::getForwardChildId,station.getId());
releaseQueryWrapper.orderByAsc(TransportTaskForwardRelease::getStartTime);
List<TransportTaskForwardRelease> releaseList = taskForwardReleaseMapper.selectList(releaseQueryWrapper);
if (CollUtil.isNotEmpty(releaseList)) {
station.setForwardReleaseChild(releaseList);
}
});
checkIdResult.setForwardChild(stationInfo);
//查询站点信息
LambdaQueryWrapper<TransportTaskForwardChild> siteQueryWrapper = new LambdaQueryWrapper<>();
siteQueryWrapper.eq(TransportTaskForwardChild::getTaskId,id);
List<TransportTaskForwardChild> stationInfo = taskForwardChildMapper.selectList(siteQueryWrapper);
if (CollUtil.isEmpty(stationInfo)) {
throw new RuntimeException("站点配置信息缺失,请确认");
}
//查询站点释放信息
LambdaQueryWrapper<TransportTaskForwardRelease> releaseQueryWrapper = new LambdaQueryWrapper<>();
releaseQueryWrapper.eq(TransportTaskForwardRelease::getTaskId,id);
List<TransportTaskForwardRelease> releaseInfo = taskForwardReleaseMapper.selectList(releaseQueryWrapper);
if (CollUtil.isEmpty(releaseInfo)) {
throw new RuntimeException("站点释放信息缺失,请确认");
}
AbstractTaskExec taskExec = new ForwardTaskExec();
taskExec.init(weatherDataMapper,this,checkIdResult,
simulationProperties,systemStorageProperties,serverProperties);
taskExec.setName("大气输运反演任务执行线程");
taskExec.start();
}
//构造消息
TransportTaskDTO transportTaskDTO = new TransportTaskDTO();
transportTaskDTO.setId(checkIdResult.getId());
transportTaskDTO.setTaskName(checkIdResult.getTaskName());
transportTaskDTO.setTaskMode(checkIdResult.getTaskMode());
transportTaskDTO.setTaskType(checkIdResult.getTaskType());
transportTaskDTO.setUseMetType(checkIdResult.getUseMetType());
transportTaskDTO.setStartTime(checkIdResult.getStartTime());
transportTaskDTO.setEndTime(checkIdResult.getEndTime());
if (TransportTaskModeEnum.BACK_FORWARD.getKey().equals(transportTaskDTO.getTaskMode())){
transportTaskProducer.sendBackwardMessage(transportTaskDTO);
}else if (TransportTaskModeEnum.FORWARD.getKey().equals(transportTaskDTO.getTaskMode())){
transportTaskProducer.sendForwardMessage(transportTaskDTO);
}
//修改状态为等待中
checkIdResult.setTaskStatus(TransportTaskStatusEnum.WAITING.getValue());
this.baseMapper.updateById(checkIdResult);
}
/**
* 获取任务运行日志
*
* @param taskId
* @param pageRequest
* @return
*/
@Override
public List<TransportTaskLog> getTaskLog(Integer taskId) {
public IPage<TransportTaskLog> getTaskLog(Integer taskId,PageRequest pageRequest) {
LambdaQueryWrapper<TransportTaskLog> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TransportTaskLog::getTaskId,taskId);
queryWrapper.select(TransportTaskLog::getCreateTime,TransportTaskLog::getLogContent);
queryWrapper.orderByAsc(TransportTaskLog::getCreateTime);
return transportTaskLogMapper.selectList(queryWrapper);
IPage<TransportTaskLog> iPage = new Page<>(pageRequest.getPageNum(), pageRequest.getPageSize());
IPage<TransportTaskLog> result = transportTaskLogMapper.selectPage(iPage, queryWrapper);
return result;
}
/**
@ -479,7 +486,7 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
private void handleTaskBaseInfo(Workbook outputWorkBook,StringBuilder stations) throws Exception {
Sheet sheet = outputWorkBook.getSheetAt(0);
//设置任务名称
sheet.getRow(1).getCell(1).setCellValue("test");
sheet.getRow(1).getCell(1).setCellValue("ncep_2014Year_test");
//设置任务模式
sheet.getRow(1).getCell(3).setCellValue(1);
//设置气象数据来源
@ -493,11 +500,11 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
//设置开始时间
sheet.getRow(3).getCell(1).setCellValue("2014-01-01 00:00:00");
//设置结束时间
sheet.getRow(3).getCell(3).setCellValue("2014-03-30 00:00:00");
sheet.getRow(3).getCell(3).setCellValue("2014-12-31 00:00:00");
//设置释放数据来源
sheet.getRow(3).getCell(5).setCellValue(2);
//设置释放核素
sheet.getRow(4).getCell(1).setCellValue(52);
sheet.getRow(4).getCell(1).setCellValue("51,52,53,54");
//设置设施列表
String result = stations.toString();
if (result.endsWith(",")) {
@ -530,8 +537,8 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
//站点名称
stations.append(cellValue);
stations.append(",");
//排放数据
Cell releaseCell = row.getCell(7);
//排放数据 5-131mXe,6-133mXe,7-133Xe,8-135Xe
Cell releaseCell = row.getCell(8);
double releaseCellValue = releaseCell.getNumericCellValue();
Sheet releaseDataSheet = outputWorkBook.createSheet(cellValue);
@ -551,7 +558,7 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
cell2.setCellStyle(styles.get("header"));
LocalDateTime startDate = LocalDateTime.of(2014,1,1,0,0,0);
LocalDateTime endDate = LocalDateTime.of(2014,1,6,0,0,0);
LocalDateTime endDate = LocalDateTime.of(2014,12,31,0,0,0);
int rowNum = 1;
while(startDate.isBefore(endDate)) {
@ -599,8 +606,8 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
//站点名称
stations.append(cellValue);
stations.append(",");
//排放数据
Cell releaseCell = row.getCell(17);
//排放数据 17-133Xe,18-135Xe,19-131mXe,20-133mXe
Cell releaseCell = row.getCell(18);
double releaseCellValue = releaseCell.getNumericCellValue();
BigDecimal releaseCellValueBG = new BigDecimal(releaseCellValue);
BigDecimal days = new BigDecimal(365);
@ -623,7 +630,7 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
cell2.setCellStyle(styles.get("header"));
LocalDateTime startDate = LocalDateTime.of(2014,1,1,0,0,0);
LocalDateTime endDate = LocalDateTime.of(2014,1,6,0,0,0);
LocalDateTime endDate = LocalDateTime.of(2014,12,31,0,0,0);
int rowNum = 1;
while(startDate.isBefore(endDate)) {
@ -671,8 +678,8 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
//站点名称
stations.append(cellValue);
stations.append(",");
//排放数据
Cell releaseCell = row.getCell(5);
//排放数据 5-133Xe,6-135Xe,7-131mXe,8-133mXe
Cell releaseCell = row.getCell(6);
double releaseCellValue = releaseCell.getNumericCellValue();
Sheet releaseDataSheet = outputWorkBook.createSheet(cellValue);
@ -692,7 +699,7 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
cell2.setCellStyle(styles.get("header"));
LocalDateTime startDate = LocalDateTime.of(2014,1,1,0,0,0);
LocalDateTime endDate = LocalDateTime.of(2014,1,6,0,0,0);
LocalDateTime endDate = LocalDateTime.of(2014,12,31,0,0,0);
int rowNum = 1;
while(startDate.isBefore(endDate)) {
@ -751,8 +758,12 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
cell2.setCellValue("排放量");
cell2.setCellStyle(styles.get("header"));
for (int i = 1; i < sheet.getLastRowNum(); i++) {
for (int i = 1; i < 365; i++) {
Row row = sheet.getRow(i);
if (row == null) {
System.out.println("------------------"+i);
System.out.println(sheet.getSheetName());
}
Row bodyRow = releaseDataSheet.createRow(i);
Cell bodyCell0 = bodyRow.createCell(0, CellType.STRING);
releaseDataSheet.setColumnWidth(0, 20*256);
@ -766,7 +777,7 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
Cell bodyCell2 = bodyRow.createCell(2, CellType.STRING);
releaseDataSheet.setColumnWidth(2, 20*256);
bodyCell2.setCellValue(row.getCell(2).getNumericCellValue());
bodyCell2.setCellValue(row.getCell(5).getNumericCellValue());
bodyCell2.setCellStyle(styles.get("scientific"));
}
}
@ -854,20 +865,256 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
TransportTask transportTask = new TransportTask();
this.handleTaskBaseInfo(transportTask,workBook,info);
this.handleSiteReleaseInfo(transportTask,workBook,info);
//此处属于内部调用create函数的事务注解不会生效所以用手动事务
transactionStatus = transactionManager.getTransaction(transactionDefinition);
this.cteate(transportTask);
transactionManager.commit(transactionStatus);
//info有数据表示有问题不进行保存
if (CollUtil.isEmpty(info)){
//此处属于内部调用create函数的事务注解不会生效所以用手动事务
transactionStatus = transactionManager.getTransaction(transactionDefinition);
this.cteate(transportTask);
transactionManager.commit(transactionStatus);
}
}catch (Exception e){
transactionManager.rollback(transactionStatus);
if (Objects.nonNull(transactionStatus)){
transactionManager.rollback(transactionStatus);
}
e.printStackTrace();
}finally {
if (Objects.nonNull(workBook)){
workBook.close();
}
}
return info;
}
/**
* 处理csv监测站点数据
*
* @param res
*/
@Override
public void handleCSVData(HttpServletResponse res) {
String dirPath = "F://工作//五木//放射性核素监测数据综合分析及氙本底源解析系统//其他资料//排放数据//监测数据//location_1";
if (FileUtil.exist(dirPath)) {
List<File> files = FileUtil.loopFiles(dirPath);
List<GardsStations> stationsList = stationDataService.getStationsList();
List<GardsDetectors> detectorsList = stationDataService.getDetectorsList();
Map<String,String> map = new HashMap<>();
List<GardsSampleData> sampleDataList = new ArrayList<>();
List<GardsXeResults> xeResultsList = new ArrayList<>();
for (File file : files) {
//查询台站id
String stationName = file.getName().substring(0, file.getName().lastIndexOf("."));
GardsStations gardsStations = stationsList.stream().filter(station -> station.getStationCode().equals(stationName)).findFirst().get();
try(CsvReader csvReader = new CsvReader()){
CsvData data = csvReader.read(file, Charset.forName("UTF-8"));
List<CsvRow> rows = data.getRows();
if (CollUtil.isNotEmpty(rows)) {
for (int i = 1; i < rows.size(); i++) {
CsvRow row = rows.get(i);
String detectorName = row.get(1);
List<GardsDetectors> detectors = detectorsList.stream().filter(detector -> detector.getDetectorCode().equals(detectorName)).collect(Collectors.toList());
// if (CollUtil.isEmpty(collect)) {
// map.put(detectorName, "detector");
// }
if (StrUtil.isNotBlank(detectorName)) {
String sampleId = row.get(2);
String collectionStart = row.get(3);
String collectionStop = row.get(4);
String acqStart = row.get(5);
String acqStop = row.get(6);
String status = row.get(41);
GardsSampleData sampleData = new GardsSampleData();
sampleData.setStationId(gardsStations.getStationId());
sampleData.setDetectorId(detectors.get(0).getDetectorId());
sampleData.setSiteDetCode(detectorName);
sampleData.setSampleId(Integer.parseInt(sampleId));
sampleData.setCollectStart(DateUtil.parse(collectionStart,"dd-MM-yyyy HH:mm:ss"));
sampleData.setCollectStop(DateUtil.parse(collectionStop,"dd-MM-yyyy HH:mm:ss"));
sampleData.setAcquisitionStart(DateUtil.parse(acqStart,"dd-MM-yyyy HH:mm:ss"));
sampleData.setAcquisitionStop(DateUtil.parse(acqStop,"dd-MM-yyyy HH:mm:ss"));
sampleData.setStatus(status);
sampleData.setInputFileName(i+"test");
sampleData.setDataType("S");
sampleData.setSampleType("B");
sampleData.setSpectralQualifie("FULL");
sampleData.setTransmitDtg(new Date());
sampleData.setAcquisitionLiveSec(1D);
sampleData.setAcquisitionRealSec(1D);
sampleData.setQuantity(1D);
sampleData.setGeometry("1");
sampleData.setModdate(new Date());
sampleDataList.add(sampleData);
String conc = row.get(29);
String concErr = row.get(30);
String lc = row.get(31);
String mdc = row.get(33);
GardsXeResults xeResults = new GardsXeResults();
xeResults.setSampleId(Integer.parseInt(sampleId));
xeResults.setIdAnalysis(Integer.parseInt(sampleId));
xeResults.setNuclideName("Xe133");
xeResults.setConc(Double.parseDouble(conc));
xeResults.setConcErr(Double.parseDouble(concErr));
xeResults.setLc(StrUtil.isNotBlank(lc) ? Double.parseDouble(lc) : 0);
xeResults.setMdc(Double.parseDouble(mdc));
xeResults.setModdate(new Date());
xeResultsList.add(xeResults);
}
}
}
}catch (Exception e){
e.printStackTrace();
}
}
if (CollUtil.isNotEmpty(map)) {
map.forEach((k,v)->{
System.out.println(k);
});
}
stationDataService.saveSampleData(sampleDataList);
stationDataService.saveXeResult(xeResultsList);
}
}
/**
* @param forwardId
* @return
*/
@Override
public List<TransportTaskForwardRelease> getReleaseDataByForwardId(Integer forwardId) {
LambdaQueryWrapper<TransportTaskForwardRelease> releaseQueryWrapper = new LambdaQueryWrapper<>();
releaseQueryWrapper.eq(TransportTaskForwardRelease::getForwardChildId,forwardId);
releaseQueryWrapper.orderByAsc(TransportTaskForwardRelease::getStartTime);
List<TransportTaskForwardRelease> forwardReleases = taskForwardReleaseMapper.selectList(releaseQueryWrapper);
if(CollUtil.isNotEmpty(forwardReleases)){
return forwardReleases;
}
return List.of();
}
/**
* 保存单个站点及对应排放数据
*
* @param siteAndReleaseDataVO
*/
@Override
public Integer saveSiteAndReleaseData(SiteAndReleaseDataVO siteAndReleaseDataVO) {
LambdaQueryWrapper<TransportTaskForwardChild> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TransportTaskForwardChild::getTaskId,siteAndReleaseDataVO.getTaskId());
queryWrapper.eq(TransportTaskForwardChild::getStationCode,siteAndReleaseDataVO.getStationCode());
TransportTaskForwardChild queryResult = taskForwardChildMapper.selectOne(queryWrapper);
Integer forwardChildId = null;
if(Objects.isNull(queryResult)){
TransportTaskForwardChild forwardChild = new TransportTaskForwardChild();
forwardChild.setTaskId(siteAndReleaseDataVO.getTaskId());
forwardChild.setLon(siteAndReleaseDataVO.getLon());
forwardChild.setLat(siteAndReleaseDataVO.getLat());
forwardChild.setStationCode(siteAndReleaseDataVO.getStationCode());
taskForwardChildMapper.insert(forwardChild);
forwardChildId = forwardChild.getId();
}else {
forwardChildId = queryResult.getId();
}
if (CollUtil.isNotEmpty(siteAndReleaseDataVO.getForwardReleaseChild())){
if (Objects.nonNull(queryResult)){
LambdaQueryWrapper<TransportTaskForwardRelease> releaseLambdaQueryWrapper = new LambdaQueryWrapper<>();
releaseLambdaQueryWrapper.eq(TransportTaskForwardRelease::getForwardChildId,forwardChildId);
this.taskForwardReleaseMapper.delete(releaseLambdaQueryWrapper);
}
Integer finalForwardChildId = forwardChildId;
siteAndReleaseDataVO.getForwardReleaseChild().forEach(releaseChild->{
releaseChild.setTaskId(siteAndReleaseDataVO.getTaskId());
releaseChild.setForwardChildId(finalForwardChildId);
});
this.taskForwardReleaseMapper.insert(siteAndReleaseDataVO.getForwardReleaseChild());
}
return forwardChildId;
}
/**
* 删除单个站点及对应排放数据
*
* @param forwardId
*/
@Override
public void delSiteAndReleaseData(Integer forwardId) {
//删除排放数据
LambdaQueryWrapper<TransportTaskForwardRelease> releaseQueryWrapper = new LambdaQueryWrapper<>();
releaseQueryWrapper.eq(TransportTaskForwardRelease::getForwardChildId,forwardId);
taskForwardReleaseMapper.delete(releaseQueryWrapper);
//删除站点数据
this.taskForwardChildMapper.deleteById(forwardId);
}
/**
* 处理赵老师给的2014年的排放数据生成sql文件
*/
@Override
public void handlExcelReleaseData() {
String inputFilePath = "F://NPP_Releases1Year_Xe135.xlsx";
String sqlFilePath = "F://Xe135Sql.sql";
if (!FileUtil.exist(sqlFilePath)) {
FileUtil.touch(new File(sqlFilePath));
}
List<Map<String, Object>> facilities = stationDataService.getAllNuclearFacilitiesAndReactors();
try(InputStream inputFileInputStream = new FileInputStream(inputFilePath);
Workbook inputWorkBook = new XSSFWorkbook(inputFileInputStream);
FileWriter writer = new FileWriter(sqlFilePath, true)){
Iterator<Sheet> sheets = inputWorkBook.sheetIterator();
while(sheets.hasNext()) {
Sheet sheet = sheets.next();
if(sheet.getSheetName().equals("基础信息配置")){
continue;
}
String facilityName = "";
double latitude = 0D;
double longitude = 0D;
for (Map<String, Object> facility : facilities) {
if(facility.get("facilityName").equals(sheet.getSheetName())) {
facilityName = facility.get("facilityName").toString();
latitude = Double.parseDouble(facility.get("latitude").toString());
longitude = Double.parseDouble(facility.get("longitude").toString());
break;
}
}
if (StrUtil.isNotBlank(facilityName)){
for (int i = 1; i < sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
Cell startTimeCell = row.getCell(0);
String startTime = startTimeCell.getStringCellValue();
Cell endTimeCell = row.getCell(1);
String endTime = endTimeCell.getStringCellValue();
Cell releaseAmountCell = row.getCell(2);
double releaseAmount = releaseAmountCell.getNumericCellValue();
//
String sql = "INSERT INTO CONFIGURATION.GARDS_NUCLEAR_RELEASE_RECORDS(FACILITY_NAME,LATITUDE,LONGITUDE," +
"START_TIME,END_TIME,NUCLIDE,RELEASE_AMOUNT,MATTER_STATE,DATA_SOURCE,MODDATE)VALUES("
+"'"+facilityName+"'"+","
+latitude+","
+longitude+","
+"TO_TIMESTAMP('"+startTime+"','YYYY-MM-DD HH24:mi:ss')"+","
+"TO_TIMESTAMP('"+endTime+"','YYYY-MM-DD HH24:mi:ss')"+","
+"'Xe135',"+
+releaseAmount+","
+"'"+1+"'"+","
+3+","
+"TO_TIMESTAMP('"+DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss")+"','YYYY-MM-DD HH24:mi:ss')"+
");\n";
writer.write(sql);
}
}
// if(sheet.getSheetName().equals("KOEBERG-1")){
// break;
// }
}
}catch (Exception e){
e.printStackTrace();
}
}
/**
@ -945,16 +1192,16 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
String[] nuclides = releaseNuclideCellValue.split(",");
if (ArrayUtil.isNotEmpty(nuclides)){
List<TransportTaskForwardSpecies> species = new ArrayList<>();
for (String nuclidId : nuclides) {
if(FlexpartSpeciesType.XE_131m.getValue().toString().equals(nuclidId) ||
FlexpartSpeciesType.XE_133.getValue().toString().equals(nuclidId) ||
FlexpartSpeciesType.XE_133m.getValue().toString().equals(nuclidId) ||
FlexpartSpeciesType.XE_135.getValue().toString().equals(nuclidId)) {
for (String speciesId : nuclides) {
if(FlexpartSpeciesType.XE_131m.getId().toString().equals(speciesId) ||
FlexpartSpeciesType.XE_133.getId().toString().equals(speciesId) ||
FlexpartSpeciesType.XE_133m.getId().toString().equals(speciesId) ||
FlexpartSpeciesType.XE_135.getId().toString().equals(speciesId)) {
TransportTaskForwardSpecies forwardSpecies = new TransportTaskForwardSpecies();
forwardSpecies.setSpeciesId(nuclidId);
forwardSpecies.setSpeciesId(Integer.parseInt(speciesId));
species.add(forwardSpecies);
}else {
info.add("释放核素信息配置错误,没有:"+nuclidId+"这个选项");
info.add("释放核素信息配置错误,没有:"+speciesId+"这个选项");
}
}
if (CollUtil.isNotEmpty(species)) {
@ -1001,7 +1248,6 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
}
if (TransportReleaseDataSource.MANUAL_ENTRY.getKey().equals(transportTask.getReleaseDataSource())) {
int sheetNum = workBook.getNumberOfSheets();
System.out.println(sheetNum);
if (sheetNum <= 1) {
info.add("释放数据来源配置参数为:手动填写,但对应释放信息未配置");
}else {
@ -1015,13 +1261,12 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
facilityName = facilityName.replace("/","");
}
if (sheet.getSheetName().equalsIgnoreCase(facilityName)) {
// System.out.println(facilityName);
forwardChild.setStationCode(facilitie.get("facilityName").toString());
forwardChild.setLon(Double.valueOf(facilitie.get("longitude").toString()));
forwardChild.setLat(Double.valueOf(facilitie.get("latitude").toString()));
List<TransportTaskForwardRelease> releases = new ArrayList<>();
for (int j=1;j<sheet.getLastRowNum();j++) {
for (int j=1;j<=sheet.getLastRowNum();j++) {
Row row = sheet.getRow(j);
//获取开始时间
Cell startTimeCell = row.getCell(0);

View File

@ -0,0 +1,77 @@
package org.jeecg.util;
import org.jeecg.modules.base.entity.rnauto.GardsStationsModVal;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
public class PreSortedTimeRangeQuery {
private List<GardsStationsModVal> sortedList = null;
public PreSortedTimeRangeQuery(List<GardsStationsModVal> sortedList){
this.sortedList = sortedList;
}
/**
* 查询指定时间范围内的数据并求和取平均
*/
public double sumConcByTimeRange(Date startTime, Date endTime) {
int startIndex = findFirstGreaterOrEqual(startTime);
int endIndex = findLastLessOrEqual(endTime);
if (startIndex > endIndex || startIndex < 0) {
return 0.0;
}
int count = 0;
double sum = 0.0;
for (int i = startIndex; i <= endIndex; i++) {
Double conc = sortedList.get(i).getConc();
if (conc != null) {
sum += conc;
count ++;
}
}
BigDecimal bg = new BigDecimal(sum);
BigDecimal result = bg.divide(BigDecimal.valueOf(count), 6, RoundingMode.HALF_UP);
return result.doubleValue();
}
/**
* 二分查找第一个大于等于目标时间的索引
* @param target
* @return
*/
private int findFirstGreaterOrEqual(Date target) {
int left = 0, right = sortedList.size();
while (left < right) {
int mid = left + (right - left) / 2;
if (sortedList.get(mid).getTimeSeries().compareTo(target) >= 0) {
right = mid;
} else {
left = mid + 1;
}
}
return left < sortedList.size() ? left : -1;
}
/**
* 二分查找最后一个小于等于目标时间的索引
*/
private int findLastLessOrEqual(Date target) {
int left = 0, right = sortedList.size() - 1;
int result = -1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (sortedList.get(mid).getTimeSeries().compareTo(target) <= 0) {
result = mid;
left = mid + 1;
} else {
right = mid - 1;
}
}
return result;
}
}

View File

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

View File

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

View File

@ -2,8 +2,6 @@ package org.jeecg.vo;
import lombok.Data;
import java.time.LocalDateTime;
/**
* srs记录数据
*/

View File

@ -0,0 +1,33 @@
package org.jeecg.vo;
import lombok.Data;
import org.jeecg.modules.base.entity.TransportTaskForwardRelease;
import java.util.List;
@Data
public class SiteAndReleaseDataVO {
/**
* 任务id
*/
private Integer taskId;
/**
* 台站编目
*/
private String stationCode;
/**
* 经度
*/
private Double lon;
/**
* 纬度
*/
private Double lat;
/**
* 正演子表信息
*/
private List<TransportTaskForwardRelease> forwardReleaseChild;
}

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-parent</artifactId>
<version>3.8.1</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>jeecg-consumer-start</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-starter3-cloud</artifactId>
</dependency>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-system-cloud-api</artifactId>
<version>${jeecgboot.version}</version>
</dependency>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-model-consumer</artifactId>
<version>${jeecgboot.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,56 @@
package org.jeecg;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.base.BaseMap;
import org.jeecg.common.constant.GlobalConstants;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.transport.consumer.TranTaskMessageConsumerHandler;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.core.RedisTemplate;
import java.net.InetAddress;
import java.net.UnknownHostException;
@Slf4j
@SpringBootApplication
@RequiredArgsConstructor
public class JeecgConsumerCloudApplication extends SpringBootServletInitializer implements CommandLineRunner {
private final RedisTemplate<String, Object> redisTemplate;
private final TranTaskMessageConsumerHandler tranTaskMsgConsumerHandler;
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(JeecgConsumerCloudApplication.class);
}
public static void main(String[] args) throws UnknownHostException {
ConfigurableApplicationContext application = SpringApplication.run(JeecgConsumerCloudApplication.class, args);
Environment env = application.getEnvironment();
String ip = InetAddress.getLocalHost().getHostAddress();
String port = env.getProperty("server.port");
String path = oConvertUtils.getString(env.getProperty("server.servlet.context-path"));
log.info("\n----------------------------------------------------------\n\t" +
"Application STAS-Consumer is running! Access URLs:\n\t" +
"Local: \t\thttp://localhost:" + port + path + "/doc.html\n" +
"External: \thttp://" + ip + ":" + port + path + "/doc.html\n" +
"Swagger文档: \thttp://" + ip + ":" + port + path + "/doc.html\n" +
"----------------------------------------------------------");
}
@Override
public void run(String... args) {
BaseMap params = new BaseMap();
params.put(GlobalConstants.HANDLER_NAME, GlobalConstants.LODER_ROUDER_HANDLER);
//刷新网关
redisTemplate.convertAndSend(GlobalConstants.REDIS_TOPIC_NAME, params);
tranTaskMsgConsumerHandler.startConsumerThread();
}
}

View File

@ -0,0 +1,24 @@
server:
port: 8020
spring:
application:
name: jeecg-consumer
cloud:
nacos:
config:
server-addr: @config.server-addr@
group: @config.group@
namespace: @config.namespace@
username: @config.username@
password: @config.password@
discovery:
server-addr: ${spring.cloud.nacos.config.server-addr}
group: @config.group@
namespace: @config.namespace@
username: @config.username@
password: @config.password@
config:
import:
- optional:nacos:jeecg.yaml
- optional:nacos:jeecg-@profile.name@.yaml

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--定义日志文件的存储地址 -->
<property name="LOG_HOME" value="logs" />
<!--<property name="COLOR_PATTERN" value="%black(%contextName-) %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta( %replace(%caller{1}){'\t|Caller.{1}0|\r\n', ''})- %gray(%msg%xEx%n)" />-->
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期%thread表示线程名%-5level级别从左显示5个字符宽度%msg日志消息%n是换行符
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n</pattern>-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{50}:%L) - %msg%n</pattern>
</encoder>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--日志文件输出的文件名 -->
<FileNamePattern>${LOG_HOME}/stas-consumer-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
<!--日志文件保留天数 -->
<MaxHistory>30</MaxHistory>
<maxFileSize>10MB</maxFileSize>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期%thread表示线程名%-5level级别从左显示5个字符宽度%msg日志消息%n是换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n</pattern>
</encoder>
</appender>
<!--myibatis log configure -->
<logger name="com.apache.ibatis" level="TRACE" />
<logger name="java.sql.Connection" level="DEBUG" />
<logger name="java.sql.Statement" level="DEBUG" />
<logger name="java.sql.PreparedStatement" level="DEBUG" />
<!-- 日志输出级别 -->
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
</configuration>

View File

@ -92,6 +92,8 @@
<module>jeecg-module-source-rebuild</module>
<module>jeecg-module-transport</module>
<module>jeecg-module-monitor-info-database</module>
<module>jeecg-model-consumer</module>
<module>jeecg-server-cloud/jeecg-consumer-start</module>
</modules>
<repositories>