package com.hivekion.scenario.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hivekion.Global;
import com.hivekion.baseData.entity.Scenario;
import com.hivekion.baseData.entity.WeatherResource;
import com.hivekion.baseData.service.IWeatherResourceService;
import com.hivekion.baseData.service.ScenarioService;
import com.hivekion.common.entity.ResponseCmdInfo;
import com.hivekion.common.redis.RedisUtil;
import com.hivekion.scenario.entity.ScenarioTask;
import com.hivekion.scenario.mapper.ScenarioTaskMapper;
import com.hivekion.scenario.service.ScenarioTaskService;
import com.hivekion.scenario.service.TaskLogicService;
import com.hivekion.thread.SpringGlobalTaskManager;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
/**
*
* 服务实现类
*
*
* @author liDongYu
* @since 2025-09-13
*/
@Service
@Slf4j
public class ScenarioTaskServiceImpl extends
ServiceImpl implements
ScenarioTaskService {
@Resource
private SpringGlobalTaskManager springGlobalTaskManager;
@Resource
private RedisUtil redisUtil;
@Resource
private ScenarioService scenarioService;
@Resource
private IWeatherResourceService weatherResourceService;
@Resource
private TaskLogicService taskLogicService;
@Override
public void start(Integer scenarioId, String roomId) {
log.info("scenarioId::{},roomId::{}", scenarioId, roomId);
Scenario currentScenario = scenarioService.getScenarioById(scenarioId);
//想定当前持续时间
redisUtil.hset(roomId + "_" + scenarioId, "duringTime", "0");
//想定当前状态
redisUtil.hset(roomId + "_" + scenarioId, "status", "running");
//查询天气数据
List weatherList = weatherResourceService.list(
new QueryWrapper()
.eq("scenario_id", scenarioId));
//放入天气数据
redisUtil.hset(roomId + "_" + scenarioId, "weather", JSONArray.toJSONString(weatherList));
//查询任务
ScenarioTask queryTask = new ScenarioTask();
queryTask.setScenarioId(scenarioId);
redisUtil.hset(roomId + "_" + scenarioId, "taskList",
JSONArray.toJSONString(queryTaskList(queryTask)));
new Thread(() -> {
springGlobalTaskManager.startPerSecondTask(roomId + "_" + scenarioId + "_task", () -> {
//时间累计
increaseTime(currentScenario, roomId);
//天气触发
weatherTrigger(currentScenario, roomId);
//任务触发
// taskTrigger(currentScenario, roomId);
});
}).start();
}
@Override
public void stop(Integer id, String roomId) {
if (Global.roomParamMap.get(id + "_" + roomId) != null) {
Global.roomParamMap.get(id + "_" + roomId).setMag(1);
}
springGlobalTaskManager.cancelTask(roomId + "_" + id + "_task");
}
@Override
public void sleepWhile(Integer id, String roomId) {
redisUtil.hset(roomId + "_" + id, "states", "sleep");
}
@Override
public void wakeup(Integer id, String roomId) {
redisUtil.hset(roomId + "_" + id, "states", "running");
}
private void increaseTime(Scenario currentScenario, String roomId) {
try {
int mag = Global.roomParamMap.get(currentScenario.getId() + "_" + roomId) == null ? 1
: Global.roomParamMap.get(currentScenario.getId() + "_" + roomId).getMag();
//获取当前状态
Object statusObj = redisUtil.hget(roomId + "_" + currentScenario.getId(), "status");
log.info("scenario_id:{},status::{}", currentScenario.getId(), statusObj);
if (statusObj != null && statusObj.toString().equals("running")) {
int duringTime = getCurrentDuringTime(currentScenario, roomId);
duringTime = duringTime + mag;
log.info("duringTime::{}", duringTime);
redisUtil.hset(roomId + "_" + currentScenario.getId(), "duringTime", duringTime + "");
}
} catch (
Exception e) {
log.error("error::", e);
}
}
/**
* 天气触发
*
* @param currentScenario 当前想定
* @param roomId 房间ID
*/
private void weatherTrigger(Scenario currentScenario, String roomId) {
try {
String weatherResources = (String) redisUtil.hget(roomId + "_" + currentScenario.getId(),
"weather");
List weatherList = JSONArray.parseArray(weatherResources,
WeatherResource.class);
int duringTime = getCurrentDuringTime(currentScenario, roomId);
for (WeatherResource resource : weatherList) {
if ("init".equals(resource.getStatus())) {
if (currentScenario.getStartTime().plusSeconds(duringTime)
.isAfter(resource.getLastBegTime())) {
log.info("{}", "start_" + resource.getWeatherType());
resource.setStatus("running");
ResponseCmdInfo responseCmdInfo = new ResponseCmdInfo<>();
responseCmdInfo.setScenarioId(currentScenario.getId());
responseCmdInfo.setRoom(roomId);
responseCmdInfo.setCmdType("start_" + resource.getWeatherType());
responseCmdInfo.setScenarioId(currentScenario.getId());
responseCmdInfo.setRoom(roomId);
Global.sendCmdInfoQueue.add(responseCmdInfo);
}
}
if ("running".equals(resource.getStatus())) {
if (currentScenario.getStartTime().plusSeconds(duringTime)
.isAfter(resource.getLastEndTime())) {
log.info("{}", "stopped_" + resource.getWeatherType());
resource.setStatus("stopped");
ResponseCmdInfo responseCmdInfo = new ResponseCmdInfo<>();
responseCmdInfo.setScenarioId(currentScenario.getId());
responseCmdInfo.setRoom(roomId);
responseCmdInfo.setCmdType("stop_" + resource.getWeatherType());
responseCmdInfo.setScenarioId(currentScenario.getId());
responseCmdInfo.setRoom(roomId);
Global.sendCmdInfoQueue.add(responseCmdInfo);
}
}
}
redisUtil.hset(roomId + "_" + currentScenario.getId(), "weather",
JSONArray.toJSONString(weatherList));
} catch (Exception ex) {
log.error(ex.getMessage());
}
}
/**
* 获取当前想定从开始到现在时间
*
* @param scenario
* @param roomId
* @return
*/
private int getCurrentDuringTime(Scenario scenario, String roomId) {
Object duringTime = redisUtil.hget(roomId + "_" + scenario.getId(), "duringTime");
if (duringTime != null) {
return Integer.parseInt(duringTime.toString());
}
return 0;
}
private void taskTrigger(Scenario currentScenario, String roomId) {
try {
Object statusObj = redisUtil.hget(roomId + "_" + currentScenario.getId(), "status");
if (statusObj != null && statusObj.toString().equals("running")) {
Object taskListObj = redisUtil.hget(roomId + "_" + currentScenario.getId(), "taskList");
List taskList = JSONArray.parseArray(taskListObj.toString(),
ScenarioTask.class);
for (ScenarioTask scenarioTask : taskList) {
int duringTime = getCurrentDuringTime(currentScenario, roomId);
log.info("task duringTime::{},{},{}", duringTime,
currentScenario.getStartTime().plusSeconds(duringTime), scenarioTask.getStartTime());
if (currentScenario.getStartTime().plusSeconds(duringTime)
.isAfter(scenarioTask.getStartTime())) {
switch (scenarioTask.getTaskType()) {
case "1":
taskLogicService.handleMoveTask(scenarioTask, currentScenario, roomId, 18.0,
null);
break;
case "2":
Random random = new Random();
List randomIntList = new ArrayList<>();
long continueSeconds =
Duration.between(scenarioTask.getStartTime(), scenarioTask.getEndTime())
.toMinutes() * 60;
for (int i = 0; i < 5; i++) {
randomIntList.add(random.nextInt((int) continueSeconds) + 1);
}
taskLogicService.handleBattleTask(scenarioTask, currentScenario, roomId,
randomIntList);
break;
case "4":
case "5":
case "6":
case "7":
default:
log.info("start a type=7 task");
taskLogicService.supplierTask(scenarioTask, currentScenario, roomId);
}
}
}
redisUtil.hset(roomId + "_" + currentScenario.getId(), "taskList",
JSONArray.toJSONString(taskList));
}
} catch (Exception e) {
log.error("error::", e);
}
}
@Override
public List queryTaskList(ScenarioTask task) {
QueryWrapper queryWrapper = new QueryWrapper<>();
queryWrapper.eq("scenario_id", task.getScenarioId());
if (StringUtils.isNotBlank(task.getResourceId())) {
queryWrapper.eq("resource_id", task.getResourceId());
}
return this.list(queryWrapper);
}
}