feat(javaTest): inspect bounded route decisions on full map
This commit is contained in:
@@ -1064,9 +1064,12 @@ public final class HistoricalDispatchSimulator {
|
||||
current.execution.pathVersion = nextVersion;
|
||||
current.execution.rerouteCount++;
|
||||
current.execution.planningEvidence.addAll(newEvidence);
|
||||
events.add(event(tick, now, "REROUTE", taskId, vehicle.getVehicleId(),
|
||||
"STRICTLY_BETTER_TRAFFIC_QUALITY", oldRemaining.get(0),
|
||||
newRemaining.get(newRemaining.size() - 1)));
|
||||
// 只有预约和活动路线都提交成功后才发布前后证据,页面看到的版本一定真实生效。
|
||||
events.add(new SimulationTickEvent(tick, now, "REROUTE", taskId,
|
||||
vehicle.getVehicleId(), "STRICTLY_BETTER_TRAFFIC_QUALITY",
|
||||
oldRemaining.get(0), newRemaining.get(newRemaining.size() - 1),
|
||||
new RerouteDecisionEvidence(nextVersion, oldRemaining, newRemaining,
|
||||
oldQuality, newQuality)));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.ft546.wcs.shadow.history.simulation;
|
||||
|
||||
import com.ft546.wcs.demo.traffic.RouteQuality;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/** 成功替换交通预约时保存的重规划前后剩余路线和质量证据。 */
|
||||
public final class RerouteDecisionEvidence {
|
||||
private final int pathVersion;
|
||||
private final List<String> oldRemainingPath;
|
||||
private final List<String> newRemainingPath;
|
||||
private final RouteQuality oldQuality;
|
||||
private final RouteQuality newQuality;
|
||||
|
||||
/**
|
||||
* 固化一次已经提交的路线替换,供报告和地图检查器还原当时的业务判断。
|
||||
*
|
||||
* <p>只有预约原子替换成功后才创建该对象,因此它代表实际生效版本,而不是一次尝试候选。
|
||||
* @param pathVersion 替换成功后的路线版本。
|
||||
* @param oldRemainingPath 替换前从车辆当前位置开始的剩余路线。
|
||||
* @param newRemainingPath 替换后从车辆当前位置开始的剩余路线。
|
||||
* @param oldQuality 旧剩余路线在触发时交通快照中的质量。
|
||||
* @param newQuality 新剩余路线在同一交通快照中的质量。
|
||||
*/
|
||||
public RerouteDecisionEvidence(int pathVersion,
|
||||
List<String> oldRemainingPath,
|
||||
List<String> newRemainingPath,
|
||||
RouteQuality oldQuality,
|
||||
RouteQuality newQuality) {
|
||||
if (pathVersion <= 1 || oldRemainingPath == null || oldRemainingPath.isEmpty()
|
||||
|| newRemainingPath == null || newRemainingPath.isEmpty()
|
||||
|| oldQuality == null || newQuality == null) {
|
||||
throw new IllegalArgumentException("complete reroute evidence is required");
|
||||
}
|
||||
this.pathVersion = pathVersion;
|
||||
this.oldRemainingPath = immutable(oldRemainingPath);
|
||||
this.newRemainingPath = immutable(newRemainingPath);
|
||||
this.oldQuality = oldQuality;
|
||||
this.newQuality = newQuality;
|
||||
}
|
||||
|
||||
/** 返回原子替换成功后采用的路线版本号。 */
|
||||
public int getPathVersion() { return pathVersion; }
|
||||
|
||||
/** 返回替换前仍待车辆执行的真实路线段。 */
|
||||
public List<String> getOldRemainingPath() { return oldRemainingPath; }
|
||||
|
||||
/** 返回替换后已经取得交通预约的真实路线段。 */
|
||||
public List<String> getNewRemainingPath() { return newRemainingPath; }
|
||||
|
||||
/** 返回触发重规划时旧剩余路线的质量元组。 */
|
||||
public RouteQuality getOldQuality() { return oldQuality; }
|
||||
|
||||
/** 返回同一快照下新剩余路线的质量元组。 */
|
||||
public RouteQuality getNewQuality() { return newQuality; }
|
||||
|
||||
/** 对外暴露防御性、不可变路径,防止报告层改写仿真事实。 */
|
||||
private List<String> immutable(List<String> values) {
|
||||
return Collections.unmodifiableList(new ArrayList<String>(values));
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ public final class SimulationTickEvent {
|
||||
private final String reason;
|
||||
private final String fromSite;
|
||||
private final String toSite;
|
||||
private final RerouteDecisionEvidence rerouteDecision;
|
||||
|
||||
/**
|
||||
* 创建 {@code SimulationTickEvent} 实例并初始化其内部状态。
|
||||
@@ -26,6 +27,26 @@ public final class SimulationTickEvent {
|
||||
public SimulationTickEvent(long tick, long simulationMillis, String type,
|
||||
String taskId, String vehicleId, String reason,
|
||||
String fromSite, String toSite) {
|
||||
this(tick, simulationMillis, type, taskId, vehicleId, reason,
|
||||
fromSite, toSite, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建带结构化重规划决定的审计事件;该扩展仅用于已经成功提交的 {@code REROUTE}。
|
||||
* @param tick 事件所在仿真 tick。
|
||||
* @param simulationMillis 相对仿真时间。
|
||||
* @param type 事件类型。
|
||||
* @param taskId 任务标识。
|
||||
* @param vehicleId 执行车辆。
|
||||
* @param reason 业务原因。
|
||||
* @param fromSite 事件起点。
|
||||
* @param toSite 事件终点。
|
||||
* @param rerouteDecision 重规划前后路径与质量;普通事件为 {@code null}。
|
||||
*/
|
||||
public SimulationTickEvent(long tick, long simulationMillis, String type,
|
||||
String taskId, String vehicleId, String reason,
|
||||
String fromSite, String toSite,
|
||||
RerouteDecisionEvidence rerouteDecision) {
|
||||
this.tick = tick;
|
||||
this.simulationMillis = simulationMillis;
|
||||
this.type = type;
|
||||
@@ -34,6 +55,7 @@ public final class SimulationTickEvent {
|
||||
this.reason = reason;
|
||||
this.fromSite = fromSite;
|
||||
this.toSite = toSite;
|
||||
this.rerouteDecision = rerouteDecision;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,4 +114,7 @@ public final class SimulationTickEvent {
|
||||
* @return 本次处理产生的结果;调用方据此继续后续流程。
|
||||
*/
|
||||
public String getToSite() { return toSite; }
|
||||
|
||||
/** 返回成功重规划事件的结构化决定;非 REROUTE 事件返回 {@code null}。 */
|
||||
public RerouteDecisionEvidence getRerouteDecision() { return rerouteDecision; }
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.ft546.wcs.shadow.history.simulation.HistoricalDispatchSimulationResul
|
||||
import com.ft546.wcs.shadow.history.simulation.HistoricalSimulationInput;
|
||||
import com.ft546.wcs.shadow.history.simulation.HistoricalSimulationTask;
|
||||
import com.ft546.wcs.shadow.history.simulation.RoutePlanningEvidence;
|
||||
import com.ft546.wcs.shadow.history.simulation.RerouteDecisionEvidence;
|
||||
import com.ft546.wcs.shadow.history.simulation.SimulationInvariantSummary;
|
||||
import com.ft546.wcs.shadow.history.simulation.SimulationMetrics;
|
||||
import com.ft546.wcs.shadow.history.simulation.SimulationTaskResult;
|
||||
@@ -108,7 +109,7 @@ public final class SimulationVisualizationMapper {
|
||||
List<Map<String, Object>> tasks = new ArrayList<Map<String, Object>>();
|
||||
for (SimulationTaskResult task : orderedTasks) {
|
||||
tasks.add(task(task, definitions.get(task.getSimulationTaskId()),
|
||||
result.getAcceleration(), input.getGridMap()));
|
||||
result.getAcceleration(), input.getGridMap(), result.getEvents()));
|
||||
}
|
||||
List<Map<String, Object>> events = new ArrayList<Map<String, Object>>();
|
||||
for (SimulationTickEvent event : result.getEvents()) events.add(event(event));
|
||||
@@ -182,7 +183,8 @@ public final class SimulationVisualizationMapper {
|
||||
private Map<String, Object> task(SimulationTaskResult task,
|
||||
HistoricalSimulationTask definition,
|
||||
int acceleration,
|
||||
GridMap gridMap) {
|
||||
GridMap gridMap,
|
||||
List<SimulationTickEvent> allEvents) {
|
||||
HistoricalQueueRecord record = task.getRecord();
|
||||
List<String> historicalPath = historicalPath(record.getPathInfo());
|
||||
Long historicalDuration = historicalDuration(task);
|
||||
@@ -242,9 +244,27 @@ public final class SimulationVisualizationMapper {
|
||||
value.put("servicePlanningEvidence", planningEvidence(task,
|
||||
RoutePlanningEvidence.PlanningStage.SERVICE));
|
||||
value.put("rerouteCount", task.getRerouteCount());
|
||||
Set<Integer> pathVersions = new TreeSet<Integer>();
|
||||
for (RoutePlanningEvidence evidence : task.getPlanningEvidence()) {
|
||||
pathVersions.add(evidence.getPathVersion());
|
||||
}
|
||||
value.put("pathVersions", new ArrayList<Integer>(pathVersions));
|
||||
value.put("rerouteEvents", rerouteEvents(task.getSimulationTaskId(), allEvents));
|
||||
return value;
|
||||
}
|
||||
|
||||
/** 返回当前任务的重规划触发、拒绝和成功事件,供前端按版本还原决策链。 */
|
||||
private List<Map<String, Object>> rerouteEvents(
|
||||
String taskId, List<SimulationTickEvent> allEvents) {
|
||||
List<Map<String, Object>> values = new ArrayList<Map<String, Object>>();
|
||||
for (SimulationTickEvent event : allEvents) {
|
||||
if (!taskId.equals(event.getTaskId())
|
||||
|| !event.getType().startsWith("REROUTE")) continue;
|
||||
values.add(event(event));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
/** 按阶段转换每次实际采用的候选、质量、距离边界和版本证据。 */
|
||||
private List<Map<String, Object>> planningEvidence(
|
||||
SimulationTaskResult task, RoutePlanningEvidence.PlanningStage stage) {
|
||||
@@ -347,6 +367,19 @@ public final class SimulationVisualizationMapper {
|
||||
value.put("reason", event.getReason());
|
||||
value.put("fromSite", event.getFromSite());
|
||||
value.put("toSite", event.getToSite());
|
||||
value.put("rerouteDecision", rerouteDecision(event.getRerouteDecision()));
|
||||
return value;
|
||||
}
|
||||
|
||||
/** 把成功路线替换转换为明确的旧/新剩余路径和同快照质量。 */
|
||||
private Map<String, Object> rerouteDecision(RerouteDecisionEvidence source) {
|
||||
if (source == null) return null;
|
||||
Map<String, Object> value = new LinkedHashMap<String, Object>();
|
||||
value.put("pathVersion", source.getPathVersion());
|
||||
value.put("oldRemainingPath", source.getOldRemainingPath());
|
||||
value.put("newRemainingPath", source.getNewRemainingPath());
|
||||
value.put("oldQuality", quality(source.getOldQuality()));
|
||||
value.put("newQuality", quality(source.getNewQuality()));
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user