simulation-backend/src/main/java/com/hivekion/room/bean/Room.java

184 lines
4.5 KiB
Java
Raw Normal View History

2025-09-17 13:58:20 +08:00
package com.hivekion.room.bean;
2025-09-18 10:47:37 +08:00
import com.hivekion.Global;
import com.hivekion.baseData.entity.Scenario;
import com.hivekion.common.entity.ResponseCmdInfo;
import com.hivekion.common.utils;
2025-09-17 13:58:20 +08:00
import com.hivekion.common.uuid.IdUtils;
import com.hivekion.room.func.TaskAction;
2025-09-18 10:47:37 +08:00
import com.hivekion.scenario.bean.ScenarioWsParam;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
2025-09-17 13:58:20 +08:00
import java.util.Map;
2025-09-18 11:20:55 +08:00
import java.util.NavigableMap;
2025-09-17 13:58:20 +08:00
import java.util.concurrent.ConcurrentHashMap;
2025-09-18 10:47:37 +08:00
import java.util.concurrent.ConcurrentSkipListMap;
2025-09-17 13:58:20 +08:00
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import lombok.Data;
2025-09-18 10:47:37 +08:00
import lombok.extern.slf4j.Slf4j;
2025-09-17 13:58:20 +08:00
/**
* [类的简要说明]
* <p>
* [详细描述可选]
* <p>
*
* @author LiDongYU
* @since 2025/7/22
*/
@Data
2025-09-18 10:47:37 +08:00
@Slf4j
2025-09-17 13:58:20 +08:00
public class Room implements AutoCloseable {
2025-09-18 10:47:37 +08:00
/**
* 任务管理相关
*/
2025-09-17 13:58:20 +08:00
private ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
private ScheduledFuture<?> future;
2025-09-18 10:47:37 +08:00
/**
* 房间ID
*/
2025-09-17 13:58:20 +08:00
private String roomId;
2025-09-18 10:47:37 +08:00
/**
* 想定信息
*/
private Scenario scenario;
/**
* 任务容器
*/
2025-09-18 11:20:55 +08:00
private NavigableMap<Long, Map<String, TaskAction>> actionMap = new ConcurrentSkipListMap<>();
2025-09-18 10:47:37 +08:00
//日期格式化
private DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
2025-09-17 13:58:20 +08:00
//线程池
private final ExecutorService actionExecutor =
new ThreadPoolExecutor(
5, 5, // corePoolSize, maximumPoolSize
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(1000), // 有界队列只允许100个待执行任务
new ThreadPoolExecutor.AbortPolicy() // 超出直接抛异常
);
2025-09-18 10:47:37 +08:00
public Room(String roomId, Scenario scenario) {
2025-09-17 13:58:20 +08:00
this.roomId = roomId;
2025-09-18 10:47:37 +08:00
this.scenario = scenario;
2025-09-17 13:58:20 +08:00
}
/**
2025-09-18 10:47:37 +08:00
* 持续时间
2025-09-17 13:58:20 +08:00
*/
private AtomicLong duringTime = new AtomicLong(0);
private AtomicLong totalTime = new AtomicLong(0);
private int mag = 1;
2025-09-17 14:59:08 +08:00
2025-09-17 13:58:20 +08:00
/**
* 启动
*
* @param time 总时间
*/
public void start(long time) {
2025-09-17 14:59:08 +08:00
2025-09-17 13:58:20 +08:00
totalTime.set(time);
startTask();
}
/**
* 停止
*/
public void stop() {
cancelTask();
}
/**
* 暂停
*/
public void pause() {
cancelTask();
}
2025-09-18 10:47:37 +08:00
2025-09-17 13:58:20 +08:00
public void resume() {
startTask();
}
2025-09-18 10:47:37 +08:00
2025-09-18 11:38:15 +08:00
public long getDuringTime() {
return duringTime.get();
}
public long getTotalTime() {
return totalTime.get();
}
2025-09-17 13:58:20 +08:00
// 启动定时任务
private void startTask() {
if (future == null || future.isCancelled()) {
future = scheduler.scheduleAtFixedRate(() -> {
2025-09-18 10:47:37 +08:00
ScenarioWsParam magValue = Global.roomParamMap.get(this.scenario.getId() + "_" + this.roomId);
if(magValue!=null){
this.mag = magValue.getMag();
}
long curTime = duringTime.addAndGet(this.mag);
sendRemainTime((totalTime.get() - curTime));
2025-09-18 11:31:16 +08:00
NavigableMap<Long, Map<String, TaskAction>> actions = actionMap.headMap(curTime, true);
if (!actions.isEmpty() ) {
actions.forEach((key, action) -> {
action.forEach((taskAction, task) -> {
actionExecutor.submit(task::doSomeThing);
});
});
actions.clear();
2025-09-17 13:58:20 +08:00
}
}, 0, 1, TimeUnit.SECONDS);
}
}
// 取消定时任务
private void cancelTask() {
if (future != null && !future.isCancelled()) {
future.cancel(true);
}
}
public void addAction(long time, TaskAction action) {
actionMap.computeIfAbsent(time, k -> new ConcurrentHashMap<>())
.put(IdUtils.simpleUUID(), action);
2025-09-18 10:47:37 +08:00
2025-09-17 13:58:20 +08:00
}
@Override
public void close() throws Exception {
actionMap.clear();
if (future != null && !future.isCancelled()) {
future.cancel(true);
}
if (scheduler != null && !scheduler.isShutdown()) {
scheduler.shutdown();
}
}
2025-09-18 10:47:37 +08:00
private void sendRemainTime(long remainTime) {
Map<String, Object> timeMap = new HashMap<>();
timeMap.put("update_time_str",utils.formatSeconds(remainTime));
timeMap.put("remain_time",remainTime);
timeMap.put("during_time",duringTime.get());
timeMap.put("current_time",df.format(this.scenario.getStartTime().plusSeconds(duringTime.get())));
Global.sendCmdInfoQueue.add(
ResponseCmdInfo.create("update_time", this.roomId, this.scenario.getId(),
timeMap));
}
2025-09-17 13:58:20 +08:00
}