Merge remote-tracking branch 'origin/test' into test
This commit is contained in:
commit
2ddedd3134
@ -26,6 +26,8 @@ public enum Project {
|
||||
DRTS,
|
||||
/** 北京交通大学项目(客流量科研) */
|
||||
BJD,
|
||||
/** 成都工业职业技术学院 */
|
||||
CGY,
|
||||
;
|
||||
|
||||
public static boolean isDefault(Project project) {
|
||||
|
@ -12,6 +12,7 @@ import club.joylink.rtss.simulation.cbtc.data.CalculateService;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.MapElement;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Section;
|
||||
import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition;
|
||||
import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
|
||||
import club.joylink.rtss.util.JsonUtils;
|
||||
import club.joylink.rtss.vo.client.PageVO;
|
||||
import club.joylink.rtss.vo.client.map.MapVO;
|
||||
@ -144,6 +145,18 @@ public class RunPlanRoutingService implements IRunPlanRoutingService {
|
||||
if (!planRunlevelService.isExisted(l)) {
|
||||
Section startSection = (Section) deviceMap.get(l.getStartSectionCode());
|
||||
Section endSection = (Section) deviceMap.get(l.getEndSectionCode());
|
||||
if((startSection.isStandTrack() && endSection.isTransferTrack()) || (endSection.isStandTrack() && startSection.isTransferTrack())){
|
||||
Float distance;
|
||||
try{
|
||||
distance = CalculateService.calculateDistance(startSection, endSection, l.getRight());
|
||||
}catch (SimulationException e){
|
||||
distance = CalculateService.calculateDistance(startSection, endSection, !l.getRight());
|
||||
}
|
||||
l.setDistance(distance);
|
||||
l.generateDefaultRunLevel();
|
||||
planRunlevelService.createUserRunlevel(l);
|
||||
return;
|
||||
}
|
||||
Float distance = CalculateService.calculateDistance(startSection, endSection, l.getRight());
|
||||
l.setDistance(distance);
|
||||
l.generateDefaultRunLevel();
|
||||
|
@ -18,6 +18,7 @@ import org.springframework.util.StringUtils;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -155,15 +156,32 @@ public interface GeneratorNew {
|
||||
// 添加步骤
|
||||
List<TrainingStepVO> steps = new ArrayList<>(stepList.size());
|
||||
stepList.forEach(operateStepVO -> {
|
||||
|
||||
|
||||
TrainingStepVO stepVO = new TrainingStepVO(operateStepVO);
|
||||
// if(StringUtils.hasText(stepVO.getCode()) && MapElement.DeviceType.ROUTE.equals(mapDevice.getDeviceType())) {
|
||||
// stepVO.setCode(((Route)mapDevice).getStart().getCode());
|
||||
// }
|
||||
if (containPlaceholder(stepVO.getTip())) {
|
||||
if (StringUtils.hasText(operateStepVO.getCodeType())) {
|
||||
TrainingConsts.CodeType codeType = TrainingConsts.CodeType.valueOf(operateStepVO.getCodeType());
|
||||
MapElement operSignal = null;
|
||||
if (Objects.nonNull(codeType) && MapElement.DeviceType.ROUTE.equals(mapDevice.getDeviceType())) {
|
||||
if (codeType == TrainingConsts.CodeType.START_SIGNAL) {
|
||||
operSignal = ((Route) mapDevice).getStart();
|
||||
} else if (codeType == TrainingConsts.CodeType.END_SIGNAL) {
|
||||
operSignal = ((Route) mapDevice).getDestination();
|
||||
} else if (codeType == TrainingConsts.CodeType.SIGNAL) {
|
||||
operSignal = ((Route) mapDevice).getStart();
|
||||
}
|
||||
}
|
||||
stepVO.setTip(replacePlaceholder(stepVO.getTip(), placeholderVOMap, Objects.isNull(operSignal) ? mapDevice : operSignal, simulation.getBuildParams().getMap()));
|
||||
} else {
|
||||
stepVO.setTip(replacePlaceholder(stepVO.getTip(), placeholderVOMap, mapDevice, simulation.getBuildParams().getMap()));
|
||||
}
|
||||
}
|
||||
if (containPlaceholder(stepVO.getVal())) {
|
||||
stepVO.setVal(replacePlaceholder(stepVO.getVal(), placeholderVOMap, mapDevice, simulation.getBuildParams().getMap()));
|
||||
stepVO.setVal(replacePlaceholder(stepVO.getVal(), placeholderVOMap,mapDevice, simulation.getBuildParams().getMap()));
|
||||
}
|
||||
steps.add(stepVO);
|
||||
});
|
||||
|
@ -76,8 +76,12 @@ public class SectionGeneratorNew implements GeneratorNew {
|
||||
case Section_Fault_Unlock:
|
||||
// 设置区段故障锁闭(这只是区故解的一种情况,后面再补其他情况)
|
||||
section.setFaultLock(true);
|
||||
section.setRouteLock(true);
|
||||
if (section.isShowLogic()) {
|
||||
section.getLogicList().forEach(s -> s.setFaultLock(true));
|
||||
section.getLogicList().forEach(s -> {
|
||||
s.setFaultLock(true);
|
||||
s.setRouteLock(true);
|
||||
});
|
||||
}
|
||||
break;
|
||||
case Section_Axis_Pre_Reset:
|
||||
|
@ -276,6 +276,10 @@ public class Stand extends MayOutOfOrderDevice {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String debugStr() {
|
||||
return String.format("%s-%s-%s(%s)", this.station.getName(),
|
||||
this.isRight()?"右行":"左行", this.getName(), this.getCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* 站台折返类型策略
|
||||
|
@ -17,7 +17,7 @@ import club.joylink.rtss.simulation.cbtc.event.SimulationDestroyEvent;
|
||||
import club.joylink.rtss.simulation.cbtc.event.SimulationResetEvent;
|
||||
import club.joylink.rtss.simulation.cbtc.event.SimulationRunAsPlanEvent;
|
||||
import club.joylink.rtss.simulation.cbtc.passenger.data.*;
|
||||
import club.joylink.rtss.util.DateTimeUtil;
|
||||
import club.joylink.rtss.simulation.cbtc.passenger.strategy.Config;
|
||||
import club.joylink.rtss.util.JsonUtils;
|
||||
import club.joylink.rtss.vo.UserVO;
|
||||
import club.joylink.rtss.vo.client.SocketMessageVO;
|
||||
@ -284,24 +284,32 @@ public class PassengerFlowSimulateService {
|
||||
//三维
|
||||
List<Map<String, Object>> sendDataList = new ArrayList<>();
|
||||
PassengerFlowData passengerFlowData = passengerFlowSimulationData.getPassengerFlowData();
|
||||
String systemTimeStr = DateTimeUtil.format(systemTime.toLocalTime());
|
||||
// 当前时间
|
||||
Map<String, StandTimePassengerFlowData> standTimePassengerFlowDataMap = passengerFlowData.queryTimeStandPFData(systemTime.toLocalTime());
|
||||
// 30s前
|
||||
Map<String, StandTimePassengerFlowData> preTimePassengerFlowDataMap = passengerFlowData.queryTimeStandPFData(systemTime.toLocalTime().minusSeconds(30));
|
||||
|
||||
List<StandPassengerFlow> allStandPassengerFlow = passengerFlowSimulationData.getAllStandPassengerFlow();
|
||||
for (StandPassengerFlow standPassengerFlow : allStandPassengerFlow) {
|
||||
Map<String, Object> sendData = new HashMap<>();
|
||||
Stand stand = standPassengerFlow.getStand();
|
||||
StandTimePassengerFlowData flowData = standTimePassengerFlowDataMap.get(stand.getCode());
|
||||
int add = flowData.getNum() - standPassengerFlow.getLastLoad();
|
||||
StandTimePassengerFlowData preData = preTimePassengerFlowDataMap.get(stand.getCode());
|
||||
int add = flowData.getNum() - preData.getNum();
|
||||
log.debug(String.format("站台[%s]增加乘客: %s", stand.debugStr(), add));
|
||||
if (add < 0) {
|
||||
// 列车拉走了站台上的人
|
||||
if (flowData.getNum() != 0 && preData.getNum() > 1000) {
|
||||
add = 80;
|
||||
} else {
|
||||
add = flowData.getNum();
|
||||
}
|
||||
}
|
||||
int total = standPassengerFlow.plus(add);
|
||||
sendData.put("standCode", stand.getCode());
|
||||
sendData.put("num", flowData.getNum());
|
||||
sendData.put("num", total);
|
||||
sendData.put("to", add);
|
||||
sendDataList.add(sendData);
|
||||
standPassengerFlow.passengerEnter(add);
|
||||
standPassengerFlow.reload(flowData.getNum());
|
||||
}
|
||||
sendStandPassengerToUser(simulation, systemTime, passengerFlowSimulationData, sendDataList);
|
||||
}
|
||||
@ -334,7 +342,7 @@ public class PassengerFlowSimulateService {
|
||||
}
|
||||
|
||||
@Async("nsExecutor")
|
||||
@Scheduled(fixedRate = 500)
|
||||
@Scheduled(fixedRate = 1000)
|
||||
public void trainPassengerFlowSimulate() {
|
||||
passengerFlowSimulationDataMap.forEach((group, passengerFlowSimulationData) -> {
|
||||
Simulation simulation = this.groupSimulationCache.getSimulationByGroup(group);
|
||||
@ -370,38 +378,34 @@ public class PassengerFlowSimulateService {
|
||||
Station station = standSection.getStation();
|
||||
TripPlan tripPlan = repository.getTripPlan(trainInfo.getServiceNumber(), trainInfo.getTripNumber());
|
||||
TripStationPassengerFlowData tripStationPassengerFlowData = passengerFlowData.queryStationTripPassengerFlowData(station.getCode(), tripPlan.getStNumber());
|
||||
if (Objects.isNull(tripStationPassengerFlowData)) {
|
||||
log.debug(String.format("车站[%s]列车车次[%s]客流数据不存在,不更新", station.debugStr(), tripPlan.debugStr()));
|
||||
continue;
|
||||
}
|
||||
Stand stand = station.getStandOf(train.isRight()).get(0);
|
||||
StandPassengerFlow standPassengerFlow = passengerFlowSimulationData.getStandPassengerFlowMap().get(stand.getCode());
|
||||
if (standPassengerFlow.getPassengerQuantity() == 0 && Objects.nonNull(trainPassengerFlow.getStation())) {
|
||||
// 已下过车且车站没人等车
|
||||
continue;
|
||||
}
|
||||
// 列车最大容量1500
|
||||
int in = Math.min(1500 - trainPassengerFlow.getPassengerQuantity(), standPassengerFlow.getPassengerQuantity());
|
||||
Map<String, Object> sendData = new HashMap<>();
|
||||
sendData.put("code", train.getGroupNumber());
|
||||
sendData.put("in", in);
|
||||
if (Objects.isNull(trainPassengerFlow.getStation())) {
|
||||
if (train.getTerminalStation().equals(station)) {
|
||||
if (trainPassengerFlow.getPassengerQuantity() > tripStationPassengerFlowData.getDown()) {
|
||||
log.warn("列车[{}]到达终点站,车上乘客人数[{}]多余下车人数[{}]", train.getGroupNumber(),
|
||||
trainPassengerFlow.getPassengerQuantity(), tripStationPassengerFlowData.getDown());
|
||||
}
|
||||
// 全部下车
|
||||
sendData.put("out", trainPassengerFlow.getPassengerQuantity());
|
||||
trainPassengerFlow.startOutboard(station, trainPassengerFlow.getPassengerQuantity());
|
||||
// 计算下车
|
||||
int down = 0;
|
||||
if (!trainPassengerFlow.isOff()) {
|
||||
if (Objects.equals(train.getTerminalStation(), station)) {
|
||||
// 到达终点站
|
||||
down = trainPassengerFlow.getPassengerQuantity();
|
||||
} else if (Objects.nonNull(tripStationPassengerFlowData)) {
|
||||
down = tripStationPassengerFlowData.getDown();
|
||||
} else {
|
||||
sendData.put("out", tripStationPassengerFlowData.getDown());
|
||||
trainPassengerFlow.startOutboard(station, tripStationPassengerFlowData.getDown());
|
||||
// 如果没有数据,默认下车5%的人
|
||||
down = (int) (trainPassengerFlow.getPassengerQuantity() * 0.05);
|
||||
}
|
||||
} else {
|
||||
sendData.put("out", 0);
|
||||
trainPassengerFlow.minus(down);
|
||||
}
|
||||
trainPassengerFlow.startBoarding(station, in);
|
||||
sendData.put("out", down);
|
||||
// 上车
|
||||
int remain = Config.TRAIN_CAPACITY - trainPassengerFlow.getPassengerQuantity();
|
||||
int up = Math.min(Config.PASSENGER_BOARD_SPEED, remain);
|
||||
Stand stand = station.getStandOf(train.isRight()).get(0);
|
||||
StandPassengerFlow standPassengerFlow = passengerFlowSimulationData.getStandPassengerFlowMap().get(stand.getCode());
|
||||
int standWait = standPassengerFlow.getPassengerQuantity();
|
||||
if (standWait < up) {
|
||||
up = standWait;
|
||||
}
|
||||
trainPassengerFlow.plus(up);
|
||||
sendData.put("in", up);
|
||||
|
||||
String json = JsonUtils.writeValueNullableFieldAsString(sendData);
|
||||
SocketMessageVO<String> message = SocketMessageFactory.build(
|
||||
@ -411,9 +415,9 @@ public class PassengerFlowSimulateService {
|
||||
// 发送站台数据变更
|
||||
Map<String, Object> sendStandData = new HashMap<>();
|
||||
sendStandData.put("standCode", stand.getCode());
|
||||
sendStandData.put("num", standPassengerFlow.getPassengerQuantity() - in);
|
||||
sendStandData.put("num", standWait - up);
|
||||
sendStandData.put("to", 0);
|
||||
standPassengerFlow.passengerGetTrain(in);
|
||||
standPassengerFlow.minus(up);
|
||||
sendStandPassengerToUser(simulation, systemTime, passengerFlowSimulationData, Collections.singletonList(sendStandData));
|
||||
}
|
||||
});
|
||||
|
@ -1,12 +1,8 @@
|
||||
package club.joylink.rtss.simulation.cbtc.passenger.data;
|
||||
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Stand;
|
||||
import club.joylink.rtss.util.RandomGenerator;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
|
||||
@Getter
|
||||
public class StandPassengerFlow {
|
||||
private int PassengerCapacity = 150;
|
||||
@ -25,13 +21,18 @@ public class StandPassengerFlow {
|
||||
this.passengerQuantity = num;
|
||||
}
|
||||
|
||||
public void passengerEnter(int add) {
|
||||
public synchronized int plus(int add) {
|
||||
this.passengerQuantity += add;
|
||||
return this.passengerQuantity;
|
||||
}
|
||||
|
||||
public void passengerGetTrain(int num) {
|
||||
public synchronized void minus(int num) {
|
||||
if (this.passengerQuantity < num) {
|
||||
this.passengerQuantity = 0;
|
||||
} else {
|
||||
this.passengerQuantity -= num;
|
||||
}
|
||||
}
|
||||
|
||||
public void reload(int num) {
|
||||
this.lastLoad = num;
|
||||
|
@ -1,6 +1,5 @@
|
||||
package club.joylink.rtss.simulation.cbtc.passenger.data;
|
||||
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Station;
|
||||
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
|
||||
import lombok.Getter;
|
||||
|
||||
@ -10,8 +9,8 @@ public class TrainPassengerFlow {
|
||||
|
||||
private int passengerQuantity = 0;
|
||||
|
||||
/** 当前执行乘降的车站 */
|
||||
private Station station;
|
||||
/** 乘客是否已经下车 */
|
||||
private boolean off;
|
||||
|
||||
public TrainPassengerFlow(VirtualRealityTrain train) {
|
||||
this.train = train;
|
||||
@ -21,27 +20,20 @@ public class TrainPassengerFlow {
|
||||
this.passengerQuantity = num;
|
||||
}
|
||||
|
||||
public void startBoarding(Station station, int up, int down, int remain) {
|
||||
this.station = station;
|
||||
this.passengerQuantity = remain;
|
||||
public void endBoarding() {
|
||||
this.off = false;
|
||||
}
|
||||
|
||||
public void startOutboard(Station station, int num) {
|
||||
this.station = station;
|
||||
public void minus(int num) {
|
||||
if (this.passengerQuantity < num) {
|
||||
this.passengerQuantity = 0;
|
||||
} else {
|
||||
this.passengerQuantity -= num;
|
||||
}
|
||||
|
||||
public void startBoarding(Station station, int num) {
|
||||
this.station = station;
|
||||
this.passengerQuantity += num;
|
||||
this.off = true;
|
||||
}
|
||||
|
||||
public void startBoarding(Station station, TripStationPassengerFlowData tripStationPassengerFlowData) {
|
||||
this.station = station;
|
||||
this.passengerQuantity = tripStationPassengerFlowData.getRemain();
|
||||
}
|
||||
|
||||
public void endBoarding() {
|
||||
this.station = null;
|
||||
public void plus(int up) {
|
||||
this.passengerQuantity += up;
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,12 @@ public final class Config {
|
||||
public static final int STAND_MAX_STOP_TIME = 90;
|
||||
/** 列车最大容量 */
|
||||
public static final int TRAIN_CAPACITY = 1500;
|
||||
/** 站台乘客上列车速度: 人/秒 (列车停站上车时间应该是总停站时间-(开关门6s+下车4s+发车前确认5s)) */
|
||||
public static final float PASSENGER_ON_SPEED = 12;
|
||||
/** 站台无效的上车时间(开关门6s+下车4s+发车前确认5s) */
|
||||
public static final int INVALID_BOARD_TIME = 15;
|
||||
/** 乘客下车速度:人/秒 */
|
||||
public static final int PASSENGER_OFF_SPEED = 36;
|
||||
/** 站台乘客上列车速度: 人/秒 */
|
||||
public static final int PASSENGER_BOARD_SPEED = 20;
|
||||
/** 列车跳停节省时间,单位 - 秒 */
|
||||
public static final int TRAIN_PASS_SAVE_TIME = 60;
|
||||
}
|
||||
|
@ -6,27 +6,36 @@ import club.joylink.rtss.simulation.cbtc.data.plan.TripPlan;
|
||||
import club.joylink.rtss.simulation.cbtc.passenger.PassengerFlowSimulateService;
|
||||
import club.joylink.rtss.simulation.cbtc.passenger.data.PassengerFlowSimulationData;
|
||||
import club.joylink.rtss.simulation.cbtc.passenger.data.StandPassengerFlow;
|
||||
import club.joylink.rtss.simulation.cbtc.passenger.strategy.data.ParkTimeStrategy;
|
||||
import club.joylink.rtss.simulation.cbtc.passenger.strategy.data.StrategyCalculateData;
|
||||
import club.joylink.rtss.websocket.StompMessageService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class LargePassengerFlowStrategyService {
|
||||
|
||||
@Autowired
|
||||
private PassengerFlowSimulateService passengerFlowSimulateService;
|
||||
|
||||
// private ExecutorService executorService = Executors.newFixedThreadPool(4);
|
||||
|
||||
@Autowired
|
||||
private StompMessageService stompMessageService;
|
||||
|
||||
@Scheduled(fixedRate = 300*1000)
|
||||
@Autowired
|
||||
private ParkTimeStrategyServiceImpl parkTimeStrategyService;
|
||||
|
||||
@Scheduled(fixedRate = 30*1000)
|
||||
public void checkLpf() {
|
||||
List<PassengerFlowSimulationData> pfSimulationList = this.passengerFlowSimulateService.getPassengerFlowSimulations();
|
||||
if (CollectionUtils.isEmpty(pfSimulationList)) {
|
||||
@ -42,18 +51,27 @@ public class LargePassengerFlowStrategyService {
|
||||
}
|
||||
}
|
||||
if (!lpfList.isEmpty()) {
|
||||
log.info(String.format("[%s]出现大客流,开始生成策略计算", lpfList.get(0).getStand().debugStr()));
|
||||
// 发现大客流,计算策略
|
||||
StrategyCalculateData strategyCalculateData = this.buildStrategyCalculateData(passengerFlowSimulationData);
|
||||
|
||||
List<ParkTimeStrategy> parkTimeStrategies = this.parkTimeStrategyService.generateStrategy(strategyCalculateData);
|
||||
for (ParkTimeStrategy parkTimeStrategy : parkTimeStrategies) {
|
||||
this.parkTimeStrategyService.calculate(strategyCalculateData.clone(), parkTimeStrategy);
|
||||
parkTimeStrategy.buildDescription();
|
||||
log.info(String.format("停站时间策略[%s]计算指标为:%s", parkTimeStrategy.getDescription(),
|
||||
parkTimeStrategy.targetDebugStr()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private StrategyCalculateData buildStrategyCalculateData(PassengerFlowSimulationData passengerFlowSimulationData) {
|
||||
Simulation simulation = this.passengerFlowSimulateService.getSimulationByGroup(passengerFlowSimulationData.getGroup());
|
||||
LocalDateTime systemTime = simulation.getSystemTime();
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
Map<String, List<TripPlan>> serviceTripsMap = repository.getServiceTripsMap();
|
||||
StrategyCalculateData strategyCalculateData = new StrategyCalculateData(
|
||||
systemTime,
|
||||
serviceTripsMap,
|
||||
repository.getRealRunRecordList(),
|
||||
passengerFlowSimulationData.getAllStandPassengerFlow(),
|
||||
|
@ -1,14 +1,186 @@
|
||||
package club.joylink.rtss.simulation.cbtc.passenger.strategy;
|
||||
|
||||
import club.joylink.rtss.simulation.cbtc.passenger.strategy.data.Strategy;
|
||||
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Stand;
|
||||
import club.joylink.rtss.simulation.cbtc.data.plan.RealRun;
|
||||
import club.joylink.rtss.simulation.cbtc.data.plan.StationPlan;
|
||||
import club.joylink.rtss.simulation.cbtc.data.plan.TripPlan;
|
||||
import club.joylink.rtss.simulation.cbtc.passenger.strategy.data.ParkTimeStrategy;
|
||||
import club.joylink.rtss.simulation.cbtc.passenger.strategy.data.StandPassenger;
|
||||
import club.joylink.rtss.simulation.cbtc.passenger.strategy.data.StrategyCalculateData;
|
||||
import club.joylink.rtss.simulation.cbtc.passenger.strategy.data.TrainPassenger;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalTime;
|
||||
import java.util.*;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class ParkTimeStrategyServiceImpl implements StrategyService {
|
||||
public class ParkTimeStrategyServiceImpl implements StrategyService<ParkTimeStrategy> {
|
||||
|
||||
@Override
|
||||
public Strategy calculate(StrategyCalculateData data) {
|
||||
public List<ParkTimeStrategy> generateStrategy(StrategyCalculateData data) {
|
||||
List<ParkTimeStrategy> list = new ArrayList<>();
|
||||
Stand stand = null;
|
||||
// 暂时按一个站大客流处理
|
||||
List<StandPassenger> standPassengerList = data.getAllStandPassengerList();
|
||||
for (StandPassenger standPassenger : standPassengerList) {
|
||||
if (standPassenger.isLpf()) {
|
||||
stand = standPassenger.getStand();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (stand == null) {
|
||||
return null;
|
||||
}
|
||||
Map<String, List<TripPlan>> planMap = data.getPlanMap();
|
||||
int planParkTime = 0; // 计划停站时间
|
||||
for (List<TripPlan> planList : planMap.values()) {
|
||||
for (TripPlan tripPlan : planList) {
|
||||
List<StationPlan> stationPlanList = tripPlan.getPlanList();
|
||||
for (StationPlan stationPlan : stationPlanList) {
|
||||
if (Objects.equals(stationPlan.getSection(), stand.getSection()) &&
|
||||
stationPlan.getParkTime() > 0) {
|
||||
planParkTime = stationPlan.getParkTime();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (planParkTime > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (planParkTime <= 0) {
|
||||
throw new IllegalArgumentException(String.format("计划或站台[%s]数据异常,找到的计划停站时间异常:为[%s]", stand.debugStr(), planParkTime));
|
||||
}
|
||||
// 最大停站时间内每隔5秒生成一个策略(策略的停站时间为计划停站时间+5*i)
|
||||
int iter = (Config.STAND_MAX_STOP_TIME - planParkTime) / 5;
|
||||
for (int i = 1; i <= iter; i++) {
|
||||
list.add(new ParkTimeStrategy(stand, planParkTime + i * 5));
|
||||
}
|
||||
log.debug(String.format("生成增大停站时间策略[%s]个", list.size()));
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void calculate(StrategyCalculateData data, ParkTimeStrategy strategy) {
|
||||
// 系统时间
|
||||
LocalTime systemTime = data.getSystemTime().toLocalTime();// 系统当前时间
|
||||
LocalTime endTime = systemTime.plusMinutes(Config.STRATEGY_CAL_TIME);// 预测计算终点
|
||||
List<TrainPassenger> trainPassengerList = data.getTrainPassengerList();
|
||||
Map<String, RealRun> trainPreviousMap = new HashMap<>(); // 列车上一个到站/发车数据
|
||||
int i = 0;
|
||||
while (systemTime.isBefore(endTime) && i<1000) { // 在计算时间内
|
||||
++i;
|
||||
if (i > 999) {
|
||||
log.error("死循环--------------------------");
|
||||
}
|
||||
LocalTime nextTime = null;
|
||||
for (TrainPassenger trainPassenger : trainPassengerList) {
|
||||
String groupNumber = trainPassenger.getGroupNumber();
|
||||
TripPlan tripPlan = data.queryTripPlan(trainPassenger.getServiceNumber(), trainPassenger.getTripNumber());
|
||||
if (tripPlan == null) { // 未找到计划,跳过
|
||||
log.warn(String.format("列车[%s-%s|%s]没有找到车次计划",
|
||||
groupNumber, trainPassenger.getServiceNumber(), trainPassenger.getTripNumber()));
|
||||
continue;
|
||||
}
|
||||
if (tripPlan.isBackup()) {
|
||||
continue;
|
||||
}
|
||||
// 上一实际到发
|
||||
RealRun realRun = trainPreviousMap.get(groupNumber);
|
||||
if (realRun == null) {
|
||||
realRun = data.queryPreviousRealRunData(groupNumber);
|
||||
if (realRun != null) {
|
||||
trainPreviousMap.put(groupNumber, realRun);
|
||||
}
|
||||
}
|
||||
List<StationPlan> planList = tripPlan.getPlanList();
|
||||
int offsetTime = 0;
|
||||
StationPlan nextStationPlan = null;
|
||||
if (realRun != null &&
|
||||
Objects.equals(tripPlan.getServiceNumber(), realRun.getServiceNumber()) &&
|
||||
Objects.equals(tripPlan.getTripNumber(), realRun.getTripNumber())) {
|
||||
// 上一实际运行数据存在且在当前计划中
|
||||
// 查询实际运行到的车站计划
|
||||
StationPlan stationPlan = tripPlan.queryStationPlanByStationCode(realRun.getStationCode());
|
||||
BusinessExceptionAssertEnum.DATA_ERROR.assertNotNull(stationPlan);
|
||||
LocalTime leaveTime = stationPlan.getLeaveTime();
|
||||
if (realRun.isArrive()) {
|
||||
// 是到达车站的计划,预测离站
|
||||
LocalTime arriveTime = stationPlan.getArriveTime();
|
||||
if (!tripPlan.isFirstPlan(stationPlan)) {
|
||||
offsetTime = realRun.getTime().toLocalTime().toSecondOfDay() - arriveTime.toSecondOfDay();
|
||||
}
|
||||
RealRun leave = this.handleTrainLeave(data, strategy, trainPassenger, tripPlan, stationPlan, offsetTime);
|
||||
|
||||
trainPreviousMap.put(groupNumber, leave);
|
||||
} else {
|
||||
offsetTime = realRun.getTime().toLocalTime().toSecondOfDay() - leaveTime.toSecondOfDay();
|
||||
}
|
||||
if (tripPlan.isLastPlan(stationPlan)) {
|
||||
// 最后一个到发计划,获取下一个折返后车次计划
|
||||
TripPlan nextTripPlan = data.queryNextTripPlan(tripPlan);
|
||||
if (nextTripPlan != null) {
|
||||
tripPlan = nextTripPlan;
|
||||
nextStationPlan = nextTripPlan.getFirstStationPlan();
|
||||
}
|
||||
} else {
|
||||
nextStationPlan = tripPlan.queryNextStationPlanByStationCode(realRun.getStationCode());
|
||||
}
|
||||
} else {
|
||||
for (StationPlan stationPlan : planList) {
|
||||
if (stationPlan.getArriveTime().compareTo(systemTime) >= 0) {
|
||||
nextStationPlan = stationPlan;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nextStationPlan != null) {
|
||||
LocalTime arriveTime = nextStationPlan.getArriveTime();
|
||||
RealRun arrive = this.buildRealRun(groupNumber, tripPlan, nextStationPlan, true, arriveTime, offsetTime, data.getSystemTime());
|
||||
data.addRealRun(arrive);
|
||||
RealRun leave = this.handleTrainLeave(data, strategy, trainPassenger, tripPlan, nextStationPlan, offsetTime);
|
||||
data.addRealRun(leave);
|
||||
trainPreviousMap.put(groupNumber, leave);
|
||||
if (nextTime == null || leave.getTime().toLocalTime().isBefore(nextTime)) {
|
||||
nextTime = leave.getTime().toLocalTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertNotNull(nextTime);
|
||||
systemTime = nextTime;
|
||||
}
|
||||
strategy.setCoTarget(strategy.getTarget1()*strategy.getW1()+strategy.getTarget2()*strategy.getW2());
|
||||
}
|
||||
|
||||
private RealRun handleTrainLeave(StrategyCalculateData data, ParkTimeStrategy strategy, TrainPassenger trainPassenger,
|
||||
TripPlan tripPlan, StationPlan stationPlan, int offsetTime) {
|
||||
Stand stand = strategy.getStand();
|
||||
int parkTime = strategy.getTime();
|
||||
LocalTime arriveTime = stationPlan.getArriveTime();
|
||||
LocalTime leaveTime = stationPlan.getLeaveTime();
|
||||
// 列车到站乘客上车,更新列车上人数
|
||||
StandPassenger standPassenger = data.getStandPassengerByStand(stationPlan.getSection().getStandList().get(0));
|
||||
int wait = standPassenger.getWait(); // 站台等待乘客数
|
||||
float predict = (parkTime - Config.INVALID_BOARD_TIME) * Config.PASSENGER_BOARD_SPEED; // 根据停站预测的可上车人数
|
||||
int remain = Config.TRAIN_CAPACITY - trainPassenger.getNum(); // 列车上剩余可载人数
|
||||
float min = Math.min(Math.min(wait, predict), remain); // 实际上车人数
|
||||
standPassenger.minus(min);
|
||||
trainPassenger.plus(min);
|
||||
// 生成预测实际运行图
|
||||
RealRun leave = this.buildRealRun(trainPassenger.getGroupNumber(), tripPlan, stationPlan, false, leaveTime, offsetTime, data.getSystemTime());
|
||||
data.addRealRun(leave);
|
||||
// 大客流站计算指标
|
||||
if (Objects.equals(stationPlan.getSection(), stand.getSection())) {
|
||||
// 时刻表偏差
|
||||
parkTime = strategy.getTime();
|
||||
leaveTime = arriveTime.plusSeconds(parkTime);
|
||||
strategy.addTarget1(parkTime - stationPlan.getParkTime());
|
||||
// 乘客等待时间(按人数统计,不考虑时间)
|
||||
strategy.addTarget2(standPassenger.getWait());
|
||||
}
|
||||
return leave;
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,33 @@
|
||||
package club.joylink.rtss.simulation.cbtc.passenger.strategy;
|
||||
|
||||
import club.joylink.rtss.simulation.cbtc.data.plan.RealRun;
|
||||
import club.joylink.rtss.simulation.cbtc.data.plan.StationPlan;
|
||||
import club.joylink.rtss.simulation.cbtc.data.plan.TripPlan;
|
||||
import club.joylink.rtss.simulation.cbtc.passenger.strategy.data.Strategy;
|
||||
import club.joylink.rtss.simulation.cbtc.passenger.strategy.data.StrategyCalculateData;
|
||||
|
||||
public interface StrategyService {
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.List;
|
||||
|
||||
Strategy calculate(StrategyCalculateData data);
|
||||
public interface StrategyService<T extends Strategy> {
|
||||
|
||||
List<T> generateStrategy(StrategyCalculateData data);
|
||||
|
||||
void calculate(StrategyCalculateData data, T strategy);
|
||||
|
||||
default RealRun buildRealRun(String groupNumber, TripPlan tripPlan,
|
||||
StationPlan nextStationPlan, boolean arrive, LocalTime time, int offsetTime,
|
||||
LocalDateTime systemTime) {
|
||||
return RealRun.builder()
|
||||
.groupNumber(groupNumber)
|
||||
.serviceNumber(tripPlan.getServiceNumber())
|
||||
.tripNumber(tripPlan.getTripNumber())
|
||||
.right(tripPlan.isRight())
|
||||
.stationCode(nextStationPlan.getStation().getCode())
|
||||
.sectionCode(nextStationPlan.getSection().getCode())
|
||||
.arrive(arrive)
|
||||
.time(time.plusSeconds(offsetTime).atDate(systemTime.toLocalDate()))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,25 @@
|
||||
package club.joylink.rtss.simulation.cbtc.passenger.strategy.data;
|
||||
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Stand;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class ParkTimeStrategy extends Strategy {
|
||||
/** 站台code */
|
||||
String standCode;
|
||||
/**
|
||||
* 站台
|
||||
*/
|
||||
Stand stand;
|
||||
/** 停站时间 */
|
||||
Integer time;
|
||||
|
||||
public ParkTimeStrategy(Stand stand, int parkTime) {
|
||||
this.stand = stand;
|
||||
this.time = parkTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildDescription() {
|
||||
this.description = "";
|
||||
return null;
|
||||
this.description = String.format("站台%s设置停站时间[%s]", stand.debugStr(), time);
|
||||
return this.description;
|
||||
}
|
||||
}
|
||||
|
@ -35,4 +35,8 @@ public class StandPassenger {
|
||||
obj.wait = this.wait;
|
||||
return obj;
|
||||
}
|
||||
|
||||
public void minus(float n) {
|
||||
this.wait -= n;
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,50 @@
|
||||
package club.joylink.rtss.simulation.cbtc.passenger.strategy.data;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public abstract class Strategy {
|
||||
|
||||
String description;
|
||||
|
||||
/** 指标1:时刻表偏差 */
|
||||
Float target1;
|
||||
int target1;
|
||||
/**
|
||||
* 权重1
|
||||
*/
|
||||
int w1 = 1;
|
||||
/** 指标2:乘客等待时间 */
|
||||
Float target2;
|
||||
int target2;
|
||||
/**
|
||||
* 权重2
|
||||
*/
|
||||
int w2 = 1;
|
||||
/** 综合指标:对指标1,2加权求和 */
|
||||
Float coTarget;
|
||||
int coTarget;
|
||||
|
||||
public abstract String buildDescription();
|
||||
|
||||
public void setTarget1(int target1) {
|
||||
this.target1 = target1;
|
||||
}
|
||||
|
||||
public void setTarget2(int target2) {
|
||||
this.target2 = target2;
|
||||
}
|
||||
|
||||
public void setCoTarget(int target) {
|
||||
this.coTarget = target;
|
||||
}
|
||||
|
||||
public void addTarget1(int i) {
|
||||
this.target1 += i;
|
||||
}
|
||||
|
||||
public void addTarget2(int wait) {
|
||||
this.target2 += wait;
|
||||
}
|
||||
|
||||
public String targetDebugStr() {
|
||||
return String.format("指标1-时刻表偏差为:[%s],指标2-等待乘客数为:[%s],综合指标为:[%s]",this.target1, this.target2, this.coTarget);
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +1,34 @@
|
||||
package club.joylink.rtss.simulation.cbtc.passenger.strategy.data;
|
||||
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Stand;
|
||||
import club.joylink.rtss.simulation.cbtc.data.plan.RealRun;
|
||||
import club.joylink.rtss.simulation.cbtc.data.plan.TripPlan;
|
||||
import club.joylink.rtss.simulation.cbtc.passenger.data.StandPassengerFlow;
|
||||
import club.joylink.rtss.simulation.cbtc.passenger.data.TrainPassengerFlow;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Slf4j
|
||||
@Getter
|
||||
public class StrategyCalculateData {
|
||||
|
||||
LocalDateTime systemTime;
|
||||
/**
|
||||
* key-服务号
|
||||
*/
|
||||
Map<String, List<TripPlan>> planMap;
|
||||
Map<String, List<TripPlan>> planMap = new ConcurrentHashMap<>();
|
||||
/**
|
||||
* key-服务车次号
|
||||
* key-列车车组号
|
||||
*/
|
||||
Map<String, List<RealRun>> runMap;
|
||||
Map<String, List<RealRun>> runMap = new ConcurrentHashMap<>();
|
||||
|
||||
Map<String, StandPassenger> standPassengerMap;
|
||||
Map<String, StandPassenger> standPassengerMap = new ConcurrentHashMap<>();
|
||||
|
||||
List<TrainPassenger> trainPassengerList;
|
||||
|
||||
@ -29,30 +36,31 @@ public class StrategyCalculateData {
|
||||
|
||||
}
|
||||
|
||||
public StrategyCalculateData(Map<String, List<TripPlan>> serviceTripsMap,
|
||||
public StrategyCalculateData(LocalDateTime systemTime,
|
||||
Map<String, List<TripPlan>> serviceTripsMap,
|
||||
List<RealRun> realRunRecordList,
|
||||
List<StandPassengerFlow> allStandPassengerFlow,
|
||||
List<TrainPassengerFlow> allTrainPassengerFlow) {
|
||||
this.planMap = new HashMap<>(serviceTripsMap);
|
||||
Map<String, List<RealRun>> realRunMap = new HashMap<>();
|
||||
this.systemTime = systemTime;
|
||||
this.planMap.putAll(serviceTripsMap);
|
||||
for (RealRun realRun : realRunRecordList) {
|
||||
String stNumber = realRun.getSTNumber();
|
||||
List<RealRun> list = realRunMap.get(stNumber);
|
||||
String groupNumber = realRun.getGroupNumber();
|
||||
List<RealRun> list = this.runMap.get(groupNumber);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
realRunMap.put(stNumber, list);
|
||||
this.runMap.put(groupNumber, list);
|
||||
}
|
||||
list.add(realRun);
|
||||
}
|
||||
this.runMap = realRunMap;
|
||||
Map<String, StandPassenger> spMap = new HashMap<>();
|
||||
for (StandPassengerFlow standPassengerFlow : allStandPassengerFlow) {
|
||||
StandPassenger standPassenger = new StandPassenger(standPassengerFlow);
|
||||
spMap.put(standPassenger.getStand().getCode(), standPassenger);
|
||||
this.standPassengerMap.put(standPassenger.getStand().getCode(), standPassenger);
|
||||
}
|
||||
this.standPassengerMap = spMap;
|
||||
List<TrainPassenger> tpList = new ArrayList<>();
|
||||
for (TrainPassengerFlow trainPassengerFlow : allTrainPassengerFlow) {
|
||||
if (!StringUtils.hasText(trainPassengerFlow.getTrain().getServiceNumber())) {
|
||||
continue;
|
||||
}
|
||||
TrainPassenger trainPassenger = new TrainPassenger(trainPassengerFlow);
|
||||
tpList.add(trainPassenger);
|
||||
}
|
||||
@ -61,8 +69,17 @@ public class StrategyCalculateData {
|
||||
|
||||
public StrategyCalculateData clone() {
|
||||
StrategyCalculateData obj = new StrategyCalculateData();
|
||||
obj.planMap = new HashMap<>(this.planMap);
|
||||
obj.runMap = new HashMap<>(this.runMap);
|
||||
obj.systemTime = this.systemTime;
|
||||
Map<String, List<TripPlan>> copyPlanMap = new ConcurrentHashMap<>();
|
||||
this.planMap.forEach((code, list) -> {
|
||||
copyPlanMap.put(code, new ArrayList<>(list));
|
||||
});
|
||||
obj.planMap = copyPlanMap;
|
||||
Map<String, List<RealRun>> copyRunMap = new ConcurrentHashMap<>();
|
||||
this.runMap.forEach((code, list) -> {
|
||||
copyRunMap.put(code, new ArrayList<>(list));
|
||||
});
|
||||
obj.runMap = copyRunMap;
|
||||
Map<String, StandPassenger> standPassengerMap = new HashMap<>();
|
||||
this.standPassengerMap.forEach((code, standPassenger) -> {
|
||||
standPassengerMap.put(code, standPassenger.clone());
|
||||
@ -76,4 +93,54 @@ public class StrategyCalculateData {
|
||||
return obj;
|
||||
}
|
||||
|
||||
public List<StandPassenger> getAllStandPassengerList() {
|
||||
return new ArrayList<>(this.standPassengerMap.values());
|
||||
}
|
||||
|
||||
public TripPlan queryTripPlan(String serviceNumber, String tripNumber) {
|
||||
List<TripPlan> tripPlanList = this.planMap.get(serviceNumber);
|
||||
if (CollectionUtils.isEmpty(tripPlanList)) {
|
||||
log.warn(String.format("服务号[%s]没有车次计划", serviceNumber));
|
||||
return null;
|
||||
}
|
||||
for (TripPlan tripPlan : tripPlanList) {
|
||||
if (Objects.equals(tripPlan.getTripNumber(), tripNumber)) {
|
||||
return tripPlan;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public RealRun queryPreviousRealRunData(String groupNumber) {
|
||||
List<RealRun> realRuns = this.runMap.get(groupNumber);
|
||||
if (!CollectionUtils.isEmpty(realRuns)) {
|
||||
realRuns.sort(Comparator.comparing(RealRun::getTime));
|
||||
return realRuns.get(realRuns.size() - 1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addRealRun(RealRun realRun) {
|
||||
List<RealRun> realRuns = this.runMap.get(realRun.getGroupNumber());
|
||||
if (realRuns == null) {
|
||||
realRuns = new ArrayList<>();
|
||||
this.runMap.put(realRun.getGroupNumber(), realRuns);
|
||||
}
|
||||
realRuns.add(realRun);
|
||||
}
|
||||
|
||||
public TripPlan queryNextTripPlan(TripPlan tripPlan) {
|
||||
List<TripPlan> planList = this.planMap.get(tripPlan.getServiceNumber());
|
||||
for (int i = 0; i < planList.size() - 1; i++) {
|
||||
TripPlan plan = planList.get(i);
|
||||
if (Objects.equals(plan, tripPlan)) {
|
||||
return planList.get(i + 1);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public StandPassenger getStandPassengerByStand(Stand stand) {
|
||||
return this.standPassengerMap.get(stand.getCode());
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ public class TrainPassenger {
|
||||
String tripNumber;
|
||||
|
||||
/** 列车上人数 */
|
||||
int remain;
|
||||
int num;
|
||||
|
||||
public TrainPassenger() {
|
||||
}
|
||||
@ -22,7 +22,7 @@ public class TrainPassenger {
|
||||
this.groupNumber = tpf.getTrain().getGroupNumber();
|
||||
this.serviceNumber = tpf.getTrain().getServiceNumber();
|
||||
this.tripNumber = tpf.getTrain().getTripNumber();
|
||||
this.remain = tpf.getPassengerQuantity();
|
||||
this.num = tpf.getPassengerQuantity();
|
||||
}
|
||||
|
||||
public TrainPassenger clone() {
|
||||
@ -30,7 +30,18 @@ public class TrainPassenger {
|
||||
obj.groupNumber = this.groupNumber;
|
||||
obj.serviceNumber = this.serviceNumber;
|
||||
obj.tripNumber = this.tripNumber;
|
||||
obj.remain = this.remain;
|
||||
obj.num = this.num;
|
||||
return obj;
|
||||
}
|
||||
|
||||
public String getSTNumber() {
|
||||
if (this.serviceNumber == null && this.tripNumber == null) {
|
||||
return null;
|
||||
}
|
||||
return String.format("%s%s", this.serviceNumber, this.tripNumber == null ? "" : this.tripNumber);
|
||||
}
|
||||
|
||||
public void plus(float n) {
|
||||
this.num += n;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user