docs(javaTest): document every Java method

This commit is contained in:
zgw
2026-08-04 10:24:25 +08:00
parent 1bcea41c5e
commit 4051e3f446
107 changed files with 5638 additions and 0 deletions

View File

@@ -34,13 +34,30 @@ import java.util.LinkedHashSet;
public final class DemoApplication {
/**
* 创建 {@code DemoApplication} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code DemoApplication},用于保持当前模块的职责边界清晰。
*/
private DemoApplication() {
}
/**
* 执行“main”所表示的处理流程。
*
* <p>该方法属于 {@code DemoApplication},用于保持当前模块的职责边界清晰。
* @param args 执行该处理所需的 args 输入。
*/
public static void main(String[] args) {
runScenario(System.out);
}
/**
* 执行“run scenario”所表示的处理流程。
*
* <p>该方法属于 {@code DemoApplication},用于保持当前模块的职责边界清晰。
* @param out 执行该处理所需的 out 输入。
*/
public static void runScenario(PrintStream out) {
if (out == null) {
throw new IllegalArgumentException("output must not be null");
@@ -100,12 +117,26 @@ public final class DemoApplication {
printOfflineShadowSummary(out);
}
/**
* 执行“print cycle”所表示的处理流程。
*
* <p>该方法属于 {@code DemoApplication},用于保持当前模块的职责边界清晰。
* @param out 执行该处理所需的 out 输入。
* @param result 执行该处理所需的 result 输入。
*/
private static void printCycle(PrintStream out, CycleResult result) {
for (String event : result.getEvents()) {
out.println(event);
}
}
/**
* 执行“print cross floor assignment check”所表示的处理流程。
*
* <p>该方法属于 {@code DemoApplication},用于保持当前模块的职责边界清晰。
* @param out 执行该处理所需的 out 输入。
* @param map 执行该处理所需的 map 输入。
*/
private static void printCrossFloorAssignmentCheck(PrintStream out, GridMap map) {
DispatchTask checkTask = new DispatchTask(
"CHECK-CROSS-FLOOR",
@@ -130,6 +161,12 @@ public final class DemoApplication {
);
}
/**
* 执行“create map”所表示的处理流程。
*
* <p>该方法属于 {@code DemoApplication},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private static GridMap createMap() {
GridMap map = new GridMap();
map.addSite(new Site("A", 1, 0, 0, "START"));
@@ -148,10 +185,24 @@ public final class DemoApplication {
return map;
}
/**
* 执行“vehicle”所表示的处理流程。
*
* <p>该方法属于 {@code DemoApplication},用于保持当前模块的职责边界清晰。
* @param id 执行该处理所需的 id 输入。
* @param site 执行该处理所需的 site 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private static VehicleSnapshot vehicle(String id, String site) {
return new VehicleSnapshot(id, 1, site, 5, 1, 80, true, true, false);
}
/**
* 执行“print offline shadow summary”所表示的处理流程。
*
* <p>该方法属于 {@code DemoApplication},用于保持当前模块的职责边界清晰。
* @param out 执行该处理所需的 out 输入。
*/
private static void printOfflineShadowSummary(PrintStream out) {
LinkedHashSet<String> nodes = new LinkedHashSet<String>(Arrays.asList("A", "B", "C"));
LinkedHashSet<TrafficMapCompiler.EdgeDefinition> edges =

View File

@@ -9,6 +9,14 @@ public final class CycleResult {
private final List<String> processedVehicleIds;
private final List<String> events;
/**
* 创建 {@code CycleResult} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code CycleResult},用于保持当前模块的职责边界清晰。
* @param cycleNumber 执行该处理所需的 cycle number 输入。
* @param processedVehicleIds 执行该处理所需的 processed vehicle ids 输入。
* @param events 执行该处理所需的 events 输入。
*/
public CycleResult(
int cycleNumber,
List<String> processedVehicleIds,
@@ -21,14 +29,32 @@ public final class CycleResult {
this.events = Collections.unmodifiableList(new ArrayList<String>(events));
}
/**
* 返回当前对象保存的“cycle number”信息。
*
* <p>该方法属于 {@code CycleResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getCycleNumber() {
return cycleNumber;
}
/**
* 返回当前对象保存的“processed vehicle ids”信息。
*
* <p>该方法属于 {@code CycleResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<String> getProcessedVehicleIds() {
return processedVehicleIds;
}
/**
* 返回当前对象保存的“events”信息。
*
* <p>该方法属于 {@code CycleResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<String> getEvents() {
return events;
}

View File

@@ -20,6 +20,15 @@ public final class LegacyDispatchCenter {
private final TrafficController traffic;
private final SimulatedProtocolAdapter protocol;
/**
* 创建 {@code LegacyDispatchCenter} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code LegacyDispatchCenter},用于保持当前模块的职责边界清晰。
* @param state 执行该处理所需的 state 输入。
* @param admission 执行该处理所需的 admission 输入。
* @param traffic 执行该处理所需的 traffic 输入。
* @param protocol 执行该处理所需的 protocol 输入。
*/
public LegacyDispatchCenter(
InMemoryWcsState state,
QueueAdmission admission,
@@ -37,6 +46,12 @@ public final class LegacyDispatchCenter {
this.protocol = protocol;
}
/**
* 执行“run cycle”所表示的处理流程。
*
* <p>该方法属于 {@code LegacyDispatchCenter},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public CycleResult runCycle() {
int eventStart = state.getEvents().size();
int cycleNumber = state.nextCycle();
@@ -45,6 +60,14 @@ public final class LegacyDispatchCenter {
List<VehicleSnapshot> vehicles =
new ArrayList<VehicleSnapshot>(state.getVehicles());
Collections.sort(vehicles, new Comparator<VehicleSnapshot>() {
/**
* 执行“compare”所表示的处理流程。
*
* <p>该方法属于 {@code 匿名类型},用于保持当前模块的职责边界清晰。
* @param left 执行该处理所需的 left 输入。
* @param right 执行该处理所需的 right 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
@Override
public int compare(VehicleSnapshot left, VehicleSnapshot right) {
return left.getVehicleId().compareTo(right.getVehicleId());
@@ -75,6 +98,13 @@ public final class LegacyDispatchCenter {
return new CycleResult(cycleNumber, processed, cycleEvents);
}
/**
* 执行“process unissued queue”所表示的处理流程。
*
* <p>该方法属于 {@code LegacyDispatchCenter},用于保持当前模块的职责边界清晰。
* @param vehicle 执行该处理所需的 vehicle 输入。
* @param queue 执行该处理所需的 queue 输入。
*/
private void processUnissuedQueue(
VehicleSnapshot vehicle,
DispatchQueueEntry queue
@@ -117,6 +147,13 @@ public final class LegacyDispatchCenter {
+ queue.getVehicleId());
}
/**
* 执行“process issued queue”所表示的处理流程。
*
* <p>该方法属于 {@code LegacyDispatchCenter},用于保持当前模块的职责边界清晰。
* @param vehicle 执行该处理所需的 vehicle 输入。
* @param queue 执行该处理所需的 queue 输入。
*/
private void processIssuedQueue(
VehicleSnapshot vehicle,
DispatchQueueEntry queue
@@ -143,6 +180,12 @@ public final class LegacyDispatchCenter {
}
}
/**
* 执行“complete”所表示的处理流程。
*
* <p>该方法属于 {@code LegacyDispatchCenter},用于保持当前模块的职责边界清晰。
* @param queue 执行该处理所需的 queue 输入。
*/
private void complete(DispatchQueueEntry queue) {
if (state.completeQueue(queue.getQueueId())) {
state.addEvent(

View File

@@ -8,10 +8,24 @@ import java.util.List;
import java.util.Optional;
public interface QueueAdmission {
/**
* 执行“create pending queue”所表示的处理流程。
*
* <p>该方法属于 {@code QueueAdmission},用于保持当前模块的职责边界清晰。
* @param state 执行该处理所需的 state 输入。
* @param frozenVehicles 执行该处理所需的 frozen vehicles 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
Optional<DispatchQueueEntry> createPendingQueue(
InMemoryWcsState state,
List<VehicleSnapshot> frozenVehicles
);
/**
* 返回当前对象保存的“invocation count”信息。
*
* <p>该方法属于 {@code QueueAdmission},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
int getInvocationCount();
}

View File

@@ -15,6 +15,13 @@ public final class QueueAdmissionService implements QueueAdmission {
private final GridMap map;
private int invocationCount;
/**
* 创建 {@code QueueAdmissionService} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code QueueAdmissionService},用于保持当前模块的职责边界清晰。
* @param assignmentService 执行该处理所需的 assignment service 输入。
* @param map 执行该处理所需的 map 输入。
*/
public QueueAdmissionService(
VehicleAssignmentService assignmentService,
GridMap map
@@ -26,6 +33,14 @@ public final class QueueAdmissionService implements QueueAdmission {
this.map = map;
}
/**
* 执行“create pending queue”所表示的处理流程。
*
* <p>该方法属于 {@code QueueAdmissionService},用于保持当前模块的职责边界清晰。
* @param state 执行该处理所需的 state 输入。
* @param frozenVehicles 执行该处理所需的 frozen vehicles 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
@Override
public Optional<DispatchQueueEntry> createPendingQueue(
InMemoryWcsState state,
@@ -69,6 +84,12 @@ public final class QueueAdmissionService implements QueueAdmission {
return Optional.of(queue);
}
/**
* 返回当前对象保存的“invocation count”信息。
*
* <p>该方法属于 {@code QueueAdmissionService},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
@Override
public int getInvocationCount() {
return invocationCount;

View File

@@ -10,6 +10,14 @@ public final class VehicleAssignmentDecision {
private final VehicleSnapshot vehicle;
private final String reason;
/**
* 创建 {@code VehicleAssignmentDecision} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code VehicleAssignmentDecision},用于保持当前模块的职责边界清晰。
* @param code 执行该处理所需的 code 输入。
* @param vehicle 执行该处理所需的 vehicle 输入。
* @param reason 执行该处理所需的 reason 输入。
*/
private VehicleAssignmentDecision(
DecisionCode code,
VehicleSnapshot vehicle,
@@ -20,6 +28,14 @@ public final class VehicleAssignmentDecision {
this.reason = reason;
}
/**
* 执行“assigned”所表示的处理流程。
*
* <p>该方法属于 {@code VehicleAssignmentDecision},用于保持当前模块的职责边界清晰。
* @param vehicle 执行该处理所需的 vehicle 输入。
* @param reason 执行该处理所需的 reason 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public static VehicleAssignmentDecision assigned(
VehicleSnapshot vehicle,
String reason
@@ -27,6 +43,14 @@ public final class VehicleAssignmentDecision {
return new VehicleAssignmentDecision(DecisionCode.ASSIGNED, vehicle, reason);
}
/**
* 执行“rejected”所表示的处理流程。
*
* <p>该方法属于 {@code VehicleAssignmentDecision},用于保持当前模块的职责边界清晰。
* @param code 执行该处理所需的 code 输入。
* @param reason 执行该处理所需的 reason 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public static VehicleAssignmentDecision rejected(
DecisionCode code,
String reason
@@ -37,14 +61,32 @@ public final class VehicleAssignmentDecision {
return new VehicleAssignmentDecision(code, null, reason);
}
/**
* 返回当前对象保存的“code”信息。
*
* <p>该方法属于 {@code VehicleAssignmentDecision},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public DecisionCode getCode() {
return code;
}
/**
* 返回当前对象保存的“vehicle”信息。
*
* <p>该方法属于 {@code VehicleAssignmentDecision},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Optional<VehicleSnapshot> getVehicle() {
return Optional.ofNullable(vehicle);
}
/**
* 返回当前对象保存的“reason”信息。
*
* <p>该方法属于 {@code VehicleAssignmentDecision},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getReason() {
return reason;
}

View File

@@ -13,6 +13,16 @@ import java.util.Map;
public final class VehicleAssignmentService {
/**
* 按中心调度规则从当前车队重新选择最适合服务任务源点的车辆。
*
* <p>只接受在线、自动模式、空闲、允许下发且电量大于 30% 的车辆;候选依次比较同层优先、楼层距离、
* y/x 坐标距离和车辆编号。历史 {@code agv_id} 不参与此选择,结果中的原因字符串保留评分依据便于对照。
* @param task 执行该处理所需的 task 输入。
* @param vehicles 执行该处理所需的 vehicles 输入。
* @param sites 执行该处理所需的 sites 输入。
* @return 选中的车辆及比较依据,或因端点无效/无可用车产生的拒绝结果。
*/
public VehicleAssignmentDecision select(
DispatchTask task,
List<VehicleSnapshot> vehicles,
@@ -74,6 +84,11 @@ public final class VehicleAssignmentService {
);
}
/**
* 判断快照车辆是否满足中心调度的派车前置条件。
* @param vehicle 执行该处理所需的 vehicle 输入。
* @return 车辆在线、空闲、自动且可下发并具备安全电量时返回 {@code true}。
*/
private boolean isEligible(VehicleSnapshot vehicle) {
return vehicle != null
&& vehicle.isConnected()
@@ -85,6 +100,14 @@ public final class VehicleAssignmentService {
private static final class Candidate {
private static final Comparator<Candidate> ORDER = new Comparator<Candidate>() {
/**
* 执行“compare”所表示的处理流程。
*
* <p>该方法属于 {@code 匿名类型},用于保持当前模块的职责边界清晰。
* @param left 执行该处理所需的 left 输入。
* @param right 执行该处理所需的 right 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
@Override
public int compare(Candidate left, Candidate right) {
int result = Integer.compare(
@@ -116,6 +139,14 @@ public final class VehicleAssignmentService {
private final int yDistance;
private final int xDistance;
/**
* 创建 {@code Candidate} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code Candidate},用于保持当前模块的职责边界清晰。
* @param vehicle 执行该处理所需的 vehicle 输入。
* @param current 执行该处理所需的 current 输入。
* @param source 执行该处理所需的 source 输入。
*/
private Candidate(VehicleSnapshot vehicle, Site current, Site source) {
this.vehicle = vehicle;
this.sameFloorPenalty = vehicle.getFloor() == source.getFloor() ? 0 : 1;

View File

@@ -21,6 +21,18 @@ public final class DispatchQueueEntry {
private int executionStatus;
private List<String> path;
/**
* 创建 {@code DispatchQueueEntry} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。
* @param queueId 执行该处理所需的 queue id 输入。
* @param taskId 执行该处理所需的 task id 输入。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param queueType 执行该处理所需的 queue type 输入。
* @param startSite 执行该处理所需的 start site 输入。
* @param endSite 执行该处理所需的 end site 输入。
* @param priority 执行该处理所需的 priority 输入。
*/
private DispatchQueueEntry(
String queueId,
String taskId,
@@ -42,6 +54,14 @@ public final class DispatchQueueEntry {
this.path = Collections.emptyList();
}
/**
* 执行“business”所表示的处理流程。
*
* <p>该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。
* @param task 执行该处理所需的 task 输入。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public static DispatchQueueEntry business(DispatchTask task, String vehicleId) {
if (task == null) {
throw new IllegalArgumentException("task must not be null");
@@ -60,6 +80,16 @@ public final class DispatchQueueEntry {
);
}
/**
* 执行“avoidance”所表示的处理流程。
*
* <p>该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。
* @param queueId 执行该处理所需的 queue id 输入。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param startSite 执行该处理所需的 start site 输入。
* @param endSite 执行该处理所需的 end site 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public static DispatchQueueEntry avoidance(
String queueId,
String vehicleId,
@@ -87,6 +117,12 @@ public final class DispatchQueueEntry {
);
}
/**
* 执行“mark issued”所表示的处理流程。
*
* <p>该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。
* @param issuedPath 执行该处理所需的 issued path 输入。
*/
public void markIssued(List<String> issuedPath) {
if (issued != 0) {
throw new IllegalStateException("queue has already been issued");
@@ -99,6 +135,11 @@ public final class DispatchQueueEntry {
this.executionStatus = 3;
}
/**
* 执行“mark completed”所表示的处理流程。
*
* <p>该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。
*/
public void markCompleted() {
if (issued == 0) {
throw new IllegalStateException("unissued queue cannot complete");
@@ -106,46 +147,112 @@ public final class DispatchQueueEntry {
this.executionStatus = 4;
}
/**
* 返回当前对象保存的“queue id”信息。
*
* <p>该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getQueueId() {
return queueId;
}
/**
* 返回当前对象保存的“task id”信息。
*
* <p>该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getTaskId() {
return taskId;
}
/**
* 返回当前对象保存的“vehicle id”信息。
*
* <p>该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getVehicleId() {
return vehicleId;
}
/**
* 返回当前对象保存的“queue type”信息。
*
* <p>该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public QueueType getQueueType() {
return queueType;
}
/**
* 返回当前对象保存的“start site”信息。
*
* <p>该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getStartSite() {
return startSite;
}
/**
* 返回当前对象保存的“end site”信息。
*
* <p>该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getEndSite() {
return endSite;
}
/**
* 返回当前对象保存的“priority”信息。
*
* <p>该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getPriority() {
return priority;
}
/**
* 返回当前对象保存的“issued”信息。
*
* <p>该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getIssued() {
return issued;
}
/**
* 返回当前对象保存的“execution status”信息。
*
* <p>该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getExecutionStatus() {
return executionStatus;
}
/**
* 判断当前上下文是否满足“is issued”条件。
*
* <p>该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isIssued() {
return issued == 1;
}
/**
* 返回当前对象保存的“path”信息。
*
* <p>该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<String> getPath() {
return path;
}

View File

@@ -14,6 +14,17 @@ public final class DispatchTask {
private final int floor;
private final int priority;
/**
* 创建 {@code DispatchTask} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code DispatchTask},用于保持当前模块的职责边界清晰。
* @param taskId 执行该处理所需的 task id 输入。
* @param type 执行该处理所需的 type 输入。
* @param sourceSite 执行该处理所需的 source site 输入。
* @param targetSite 执行该处理所需的 target site 输入。
* @param floor 执行该处理所需的 floor 输入。
* @param priority 执行该处理所需的 priority 输入。
*/
public DispatchTask(
String taskId,
TaskType type,
@@ -36,30 +47,74 @@ public final class DispatchTask {
this.priority = priority;
}
/**
* 返回当前对象保存的“task id”信息。
*
* <p>该方法属于 {@code DispatchTask},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getTaskId() {
return taskId;
}
/**
* 返回当前对象保存的“type”信息。
*
* <p>该方法属于 {@code DispatchTask},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public TaskType getType() {
return type;
}
/**
* 返回当前对象保存的“source site”信息。
*
* <p>该方法属于 {@code DispatchTask},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getSourceSite() {
return sourceSite;
}
/**
* 返回当前对象保存的“target site”信息。
*
* <p>该方法属于 {@code DispatchTask},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getTargetSite() {
return targetSite;
}
/**
* 返回当前对象保存的“floor”信息。
*
* <p>该方法属于 {@code DispatchTask},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getFloor() {
return floor;
}
/**
* 返回当前对象保存的“priority”信息。
*
* <p>该方法属于 {@code DispatchTask},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getPriority() {
return priority;
}
/**
* 执行“require text”所表示的处理流程。
*
* <p>该方法属于 {@code DispatchTask},用于保持当前模块的职责边界清晰。
* @param value 执行该处理所需的 value 输入。
* @param name 执行该处理所需的 name 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private static String requireText(String value, String name) {
if (value == null || value.trim().isEmpty()) {
throw new IllegalArgumentException(name + " must not be blank");

View File

@@ -9,6 +9,16 @@ public final class Site {
private final int y;
private final String channel;
/**
* 创建 {@code Site} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code Site},用于保持当前模块的职责边界清晰。
* @param id 执行该处理所需的 id 输入。
* @param floor 执行该处理所需的 floor 输入。
* @param x 执行该处理所需的 x 输入。
* @param y 执行该处理所需的 y 输入。
* @param channel 执行该处理所需的 channel 输入。
*/
public Site(String id, int floor, int x, int y, String channel) {
this.id = requireText(id, "site id");
if (floor <= 0) {
@@ -20,26 +30,64 @@ public final class Site {
this.channel = requireText(channel, "channel");
}
/**
* 返回当前对象保存的“id”信息。
*
* <p>该方法属于 {@code Site},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getId() {
return id;
}
/**
* 返回当前对象保存的“floor”信息。
*
* <p>该方法属于 {@code Site},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getFloor() {
return floor;
}
/**
* 返回当前对象保存的“x”信息。
*
* <p>该方法属于 {@code Site},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getX() {
return x;
}
/**
* 返回当前对象保存的“y”信息。
*
* <p>该方法属于 {@code Site},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getY() {
return y;
}
/**
* 返回当前对象保存的“channel”信息。
*
* <p>该方法属于 {@code Site},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getChannel() {
return channel;
}
/**
* 执行“require text”所表示的处理流程。
*
* <p>该方法属于 {@code Site},用于保持当前模块的职责边界清晰。
* @param value 执行该处理所需的 value 输入。
* @param name 执行该处理所需的 name 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private static String requireText(String value, String name) {
if (value == null || value.trim().isEmpty()) {
throw new IllegalArgumentException(name + " must not be blank");
@@ -47,6 +95,13 @@ public final class Site {
return value;
}
/**
* 比较当前对象与给定对象是否具有相同业务值。
*
* <p>该方法属于 {@code Site},用于保持当前模块的职责边界清晰。
* @param other 执行该处理所需的 other 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
@Override
public boolean equals(Object other) {
if (this == other) {
@@ -59,6 +114,12 @@ public final class Site {
return id.equals(site.id);
}
/**
* 判断当前上下文是否满足“hash code”条件。
*
* <p>该方法属于 {@code Site},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
@Override
public int hashCode() {
return Objects.hash(id);

View File

@@ -11,6 +11,20 @@ public final class VehicleSnapshot {
private final boolean allowSend;
private final boolean cargo;
/**
* 创建 {@code VehicleSnapshot} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code VehicleSnapshot},用于保持当前模块的职责边界清晰。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param floor 执行该处理所需的 floor 输入。
* @param currentSite 执行该处理所需的 current site 输入。
* @param workMode 执行该处理所需的 work mode 输入。
* @param status 执行该处理所需的 status 输入。
* @param battery 执行该处理所需的 battery 输入。
* @param connected 执行该处理所需的 connected 输入。
* @param allowSend 执行该处理所需的 allow send 输入。
* @param cargo 执行该处理所需的 cargo 输入。
*/
public VehicleSnapshot(
String vehicleId,
int floor,
@@ -39,42 +53,104 @@ public final class VehicleSnapshot {
this.cargo = cargo;
}
/**
* 返回当前对象保存的“vehicle id”信息。
*
* <p>该方法属于 {@code VehicleSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getVehicleId() {
return vehicleId;
}
/**
* 返回当前对象保存的“floor”信息。
*
* <p>该方法属于 {@code VehicleSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getFloor() {
return floor;
}
/**
* 返回当前对象保存的“current site”信息。
*
* <p>该方法属于 {@code VehicleSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getCurrentSite() {
return currentSite;
}
/**
* 返回当前对象保存的“work mode”信息。
*
* <p>该方法属于 {@code VehicleSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getWorkMode() {
return workMode;
}
/**
* 返回当前对象保存的“status”信息。
*
* <p>该方法属于 {@code VehicleSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getStatus() {
return status;
}
/**
* 返回当前对象保存的“battery”信息。
*
* <p>该方法属于 {@code VehicleSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getBattery() {
return battery;
}
/**
* 判断当前上下文是否满足“is connected”条件。
*
* <p>该方法属于 {@code VehicleSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isConnected() {
return connected;
}
/**
* 判断当前上下文是否满足“is allow send”条件。
*
* <p>该方法属于 {@code VehicleSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isAllowSend() {
return allowSend;
}
/**
* 判断当前上下文是否满足“is cargo”条件。
*
* <p>该方法属于 {@code VehicleSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isCargo() {
return cargo;
}
/**
* 执行“at”所表示的处理流程。
*
* <p>该方法属于 {@code VehicleSnapshot},用于保持当前模块的职责边界清晰。
* @param siteId 执行该处理所需的 site id 输入。
* @param newFloor 执行该处理所需的 new floor 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public VehicleSnapshot at(String siteId, int newFloor) {
return new VehicleSnapshot(
vehicleId,
@@ -89,6 +165,14 @@ public final class VehicleSnapshot {
);
}
/**
* 执行“require text”所表示的处理流程。
*
* <p>该方法属于 {@code VehicleSnapshot},用于保持当前模块的职责边界清晰。
* @param value 执行该处理所需的 value 输入。
* @param name 执行该处理所需的 name 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private static String requireText(String value, String name) {
if (value == null || value.trim().isEmpty()) {
throw new IllegalArgumentException(name + " must not be blank");

View File

@@ -27,6 +27,12 @@ public final class InMemoryWcsState {
private final List<String> events = new ArrayList<String>();
private int cycleNumber;
/**
* 执行“add vehicle”所表示的处理流程。
*
* <p>该方法属于 {@code InMemoryWcsState},用于保持当前模块的职责边界清晰。
* @param vehicle 执行该处理所需的 vehicle 输入。
*/
public void addVehicle(VehicleSnapshot vehicle) {
if (vehicle == null) {
throw new IllegalArgumentException("vehicle must not be null");
@@ -39,6 +45,12 @@ public final class InMemoryWcsState {
vehicles.put(vehicle.getVehicleId(), vehicle);
}
/**
* 执行“update vehicle”所表示的处理流程。
*
* <p>该方法属于 {@code InMemoryWcsState},用于保持当前模块的职责边界清晰。
* @param vehicle 执行该处理所需的 vehicle 输入。
*/
public void updateVehicle(VehicleSnapshot vehicle) {
if (vehicle == null || !vehicles.containsKey(vehicle.getVehicleId())) {
throw new IllegalArgumentException("cannot update unknown vehicle");
@@ -46,6 +58,12 @@ public final class InMemoryWcsState {
vehicles.put(vehicle.getVehicleId(), vehicle);
}
/**
* 执行“add task”所表示的处理流程。
*
* <p>该方法属于 {@code InMemoryWcsState},用于保持当前模块的职责边界清晰。
* @param task 执行该处理所需的 task 输入。
*/
public void addTask(DispatchTask task) {
if (task == null) {
throw new IllegalArgumentException("task must not be null");
@@ -56,6 +74,13 @@ public final class InMemoryWcsState {
pendingTasks.put(task.getTaskId(), task);
}
/**
* 执行“admit task”所表示的处理流程。
*
* <p>该方法属于 {@code InMemoryWcsState},用于保持当前模块的职责边界清晰。
* @param task 执行该处理所需的 task 输入。
* @param queue 执行该处理所需的 queue 输入。
*/
public void admitTask(DispatchTask task, DispatchQueueEntry queue) {
if (task == null || !pendingTasks.containsKey(task.getTaskId())) {
throw new IllegalArgumentException("task is not pending: " + task);
@@ -64,6 +89,12 @@ public final class InMemoryWcsState {
pendingTasks.remove(task.getTaskId());
}
/**
* 执行“add queue”所表示的处理流程。
*
* <p>该方法属于 {@code InMemoryWcsState},用于保持当前模块的职责边界清晰。
* @param queue 执行该处理所需的 queue 输入。
*/
public void addQueue(DispatchQueueEntry queue) {
if (queue == null) {
throw new IllegalArgumentException("queue must not be null");
@@ -79,6 +110,13 @@ public final class InMemoryWcsState {
activeQueues.put(queue.getQueueId(), queue);
}
/**
* 执行“complete queue”所表示的处理流程。
*
* <p>该方法属于 {@code InMemoryWcsState},用于保持当前模块的职责边界清晰。
* @param queueId 执行该处理所需的 queue id 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean completeQueue(String queueId) {
DispatchQueueEntry queue = activeQueues.remove(queueId);
if (queue == null) {
@@ -89,16 +127,36 @@ public final class InMemoryWcsState {
return true;
}
/**
* 返回当前对象保存的“vehicles”信息。
*
* <p>该方法属于 {@code InMemoryWcsState},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<VehicleSnapshot> getVehicles() {
return Collections.unmodifiableList(
new ArrayList<VehicleSnapshot>(vehicles.values())
);
}
/**
* 返回当前对象保存的“pending tasks”信息。
*
* <p>该方法属于 {@code InMemoryWcsState},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<DispatchTask> getPendingTasks() {
List<DispatchTask> result =
new ArrayList<DispatchTask>(pendingTasks.values());
Collections.sort(result, new Comparator<DispatchTask>() {
/**
* 执行“compare”所表示的处理流程。
*
* <p>该方法属于 {@code 匿名类型},用于保持当前模块的职责边界清晰。
* @param left 执行该处理所需的 left 输入。
* @param right 执行该处理所需的 right 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
@Override
public int compare(DispatchTask left, DispatchTask right) {
int priority = Integer.compare(right.getPriority(), left.getPriority());
@@ -111,16 +169,35 @@ public final class InMemoryWcsState {
return Collections.unmodifiableList(result);
}
/**
* 返回当前对象保存的“active queues”信息。
*
* <p>该方法属于 {@code InMemoryWcsState},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<DispatchQueueEntry> getActiveQueues() {
return Collections.unmodifiableList(
new ArrayList<DispatchQueueEntry>(activeQueues.values())
);
}
/**
* 返回当前对象保存的“history”信息。
*
* <p>该方法属于 {@code InMemoryWcsState},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<DispatchQueueEntry> getHistory() {
return Collections.unmodifiableList(history);
}
/**
* 执行“find queue by vehicle”所表示的处理流程。
*
* <p>该方法属于 {@code InMemoryWcsState},用于保持当前模块的职责边界清晰。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Optional<DispatchQueueEntry> findQueueByVehicle(String vehicleId) {
for (DispatchQueueEntry queue : activeQueues.values()) {
if (queue.getVehicleId().equals(vehicleId)) {
@@ -130,6 +207,12 @@ public final class InMemoryWcsState {
return Optional.empty();
}
/**
* 执行“add event”所表示的处理流程。
*
* <p>该方法属于 {@code InMemoryWcsState},用于保持当前模块的职责边界清晰。
* @param event 执行该处理所需的 event 输入。
*/
public void addEvent(String event) {
if (event == null || event.trim().isEmpty()) {
throw new IllegalArgumentException("event must not be blank");
@@ -137,15 +220,33 @@ public final class InMemoryWcsState {
events.add(event);
}
/**
* 返回当前对象保存的“events”信息。
*
* <p>该方法属于 {@code InMemoryWcsState},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<String> getEvents() {
return Collections.unmodifiableList(events);
}
/**
* 执行“next cycle”所表示的处理流程。
*
* <p>该方法属于 {@code InMemoryWcsState},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int nextCycle() {
cycleNumber++;
return cycleNumber;
}
/**
* 返回当前对象保存的“cycle number”信息。
*
* <p>该方法属于 {@code InMemoryWcsState},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getCycleNumber() {
return cycleNumber;
}

View File

@@ -10,6 +10,14 @@ public final class SimulatedProtocolAdapter {
private final List<String> attemptedQueueIds = new ArrayList<String>();
private String nextFailure;
/**
* 执行“send”所表示的处理流程。
*
* <p>该方法属于 {@code SimulatedProtocolAdapter},用于保持当前模块的职责边界清晰。
* @param queue 执行该处理所需的 queue 输入。
* @param path 执行该处理所需的 path 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public ProtocolResult send(DispatchQueueEntry queue, List<String> path) {
if (queue == null || path == null || path.isEmpty()) {
throw new IllegalArgumentException("queue and non-empty path are required");
@@ -23,6 +31,12 @@ public final class SimulatedProtocolAdapter {
return ProtocolResult.success();
}
/**
* 执行“fail next send”所表示的处理流程。
*
* <p>该方法属于 {@code SimulatedProtocolAdapter},用于保持当前模块的职责边界清晰。
* @param reason 执行该处理所需的 reason 输入。
*/
public void failNextSend(String reason) {
if (reason == null || reason.trim().isEmpty()) {
throw new IllegalArgumentException("failure reason must not be blank");
@@ -30,6 +44,12 @@ public final class SimulatedProtocolAdapter {
nextFailure = reason;
}
/**
* 返回当前对象保存的“attempted queue ids”信息。
*
* <p>该方法属于 {@code SimulatedProtocolAdapter},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<String> getAttemptedQueueIds() {
return Collections.unmodifiableList(attemptedQueueIds);
}
@@ -38,23 +58,55 @@ public final class SimulatedProtocolAdapter {
private final boolean success;
private final String message;
/**
* 创建 {@code ProtocolResult} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code ProtocolResult},用于保持当前模块的职责边界清晰。
* @param success 执行该处理所需的 success 输入。
* @param message 执行该处理所需的 message 输入。
*/
private ProtocolResult(boolean success, String message) {
this.success = success;
this.message = message;
}
/**
* 执行“success”所表示的处理流程。
*
* <p>该方法属于 {@code ProtocolResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public static ProtocolResult success() {
return new ProtocolResult(true, "accepted");
}
/**
* 执行“failure”所表示的处理流程。
*
* <p>该方法属于 {@code ProtocolResult},用于保持当前模块的职责边界清晰。
* @param message 执行该处理所需的 message 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public static ProtocolResult failure(String message) {
return new ProtocolResult(false, message);
}
/**
* 判断当前上下文是否满足“is success”条件。
*
* <p>该方法属于 {@code ProtocolResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isSuccess() {
return success;
}
/**
* 返回当前对象保存的“message”信息。
*
* <p>该方法属于 {@code ProtocolResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getMessage() {
return message;
}

View File

@@ -19,6 +19,12 @@ public final class GridMap {
private final Map<String, String> cacheSitesByChannel =
new LinkedHashMap<String, String>();
/**
* 执行“add site”所表示的处理流程。
*
* <p>该方法属于 {@code GridMap},用于保持当前模块的职责边界清晰。
* @param site 执行该处理所需的 site 输入。
*/
public void addSite(Site site) {
if (site == null) {
throw new IllegalArgumentException("site must not be null");
@@ -30,6 +36,13 @@ public final class GridMap {
neighbors.put(site.getId(), new LinkedHashSet<String>());
}
/**
* 执行“connect”所表示的处理流程。
*
* <p>该方法属于 {@code GridMap},用于保持当前模块的职责边界清晰。
* @param left 执行该处理所需的 left 输入。
* @param right 执行该处理所需的 right 输入。
*/
public void connect(String left, String right) {
requireSite(left);
requireSite(right);
@@ -37,11 +50,24 @@ public final class GridMap {
neighbors.get(right).add(left);
}
/**
* 执行“block”所表示的处理流程。
*
* <p>该方法属于 {@code GridMap},用于保持当前模块的职责边界清晰。
* @param siteId 执行该处理所需的 site id 输入。
*/
public void block(String siteId) {
requireSite(siteId);
blockedSites.add(siteId);
}
/**
* 更新当前对象的“cache site”状态。
*
* <p>该方法属于 {@code GridMap},用于保持当前模块的职责边界清晰。
* @param channel 执行该处理所需的 channel 输入。
* @param siteId 执行该处理所需的 site id 输入。
*/
public void setCacheSite(String channel, String siteId) {
if (channel == null || channel.trim().isEmpty()) {
throw new IllegalArgumentException("channel must not be blank");
@@ -50,14 +76,34 @@ public final class GridMap {
cacheSitesByChannel.put(channel, siteId);
}
/**
* 返回当前对象保存的“site”信息。
*
* <p>该方法属于 {@code GridMap},用于保持当前模块的职责边界清晰。
* @param siteId 执行该处理所需的 site id 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Site getSite(String siteId) {
return sites.get(siteId);
}
/**
* 返回当前对象保存的“sites”信息。
*
* <p>该方法属于 {@code GridMap},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Map<String, Site> getSites() {
return Collections.unmodifiableMap(sites);
}
/**
* 返回当前对象保存的“neighbors”信息。
*
* <p>该方法属于 {@code GridMap},用于保持当前模块的职责边界清晰。
* @param siteId 执行该处理所需的 site id 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<String> getNeighbors(String siteId) {
requireSite(siteId);
List<String> result = new ArrayList<String>(neighbors.get(siteId));
@@ -65,14 +111,33 @@ public final class GridMap {
return result;
}
/**
* 返回当前对象保存的“blocked sites”信息。
*
* <p>该方法属于 {@code GridMap},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Set<String> getBlockedSites() {
return Collections.unmodifiableSet(blockedSites);
}
/**
* 返回当前对象保存的“cache site”信息。
*
* <p>该方法属于 {@code GridMap},用于保持当前模块的职责边界清晰。
* @param channel 执行该处理所需的 channel 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getCacheSite(String channel) {
return cacheSitesByChannel.get(channel);
}
/**
* 执行“require site”所表示的处理流程。
*
* <p>该方法属于 {@code GridMap},用于保持当前模块的职责边界清晰。
* @param siteId 执行该处理所需的 site id 输入。
*/
private void requireSite(String siteId) {
if (!sites.containsKey(siteId)) {
throw new IllegalArgumentException("unknown site: " + siteId);

View File

@@ -13,6 +13,17 @@ import java.util.Set;
public final class GridPathPlanner {
/**
* 在完整网格上用广度优先搜索重新规划两站点间的最短可达路径。
*
* <p>静态禁行点与本轮动态阻塞点共同生效,但车辆当前站点允许作为起点;目标不可走或无法抵达时返回空,
* 由上层关闭 {@code NO_ROUTE} 或保持等待,而不是借用历史 {@code path_info}。
* @param map 执行该处理所需的 map 输入。
* @param start 执行该处理所需的 start 输入。
* @param end 执行该处理所需的 end 输入。
* @param dynamicBlocked 执行该处理所需的 dynamic blocked 输入。
* @return 包含起终点的最短路径;无路时为空列表。
*/
public List<String> shortestPath(
GridMap map,
String start,
@@ -53,6 +64,13 @@ public final class GridPathPlanner {
return Collections.emptyList();
}
/**
* 将 BFS 前驱链反向还原为车辆可顺序执行的起点到终点路径。
*
* @param parent 每个已搜索站点的前驱关系。
* @param end 已找到的目标站点。
* @return 包含起点和终点的不可变最短路径。
*/
private List<String> buildPath(Map<String, String> parent, String end) {
List<String> reversed = new ArrayList<String>();
String current = end;

View File

@@ -14,6 +14,13 @@ public final class TrafficController {
private final GridMap map;
private final GridPathPlanner planner;
/**
* 创建 {@code TrafficController} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code TrafficController},用于保持当前模块的职责边界清晰。
* @param map 执行该处理所需的 map 输入。
* @param planner 执行该处理所需的 planner 输入。
*/
public TrafficController(GridMap map, GridPathPlanner planner) {
if (map == null || planner == null) {
throw new IllegalArgumentException("map and planner are required");
@@ -22,6 +29,16 @@ public final class TrafficController {
this.planner = planner;
}
/**
* 执行“plan”所表示的处理流程。
*
* <p>该方法属于 {@code TrafficController},用于保持当前模块的职责边界清晰。
* @param vehicle 执行该处理所需的 vehicle 输入。
* @param queue 执行该处理所需的 queue 输入。
* @param vehicles 执行该处理所需的 vehicles 输入。
* @param queues 执行该处理所需的 queues 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public TrafficDecision plan(
VehicleSnapshot vehicle,
DispatchQueueEntry queue,
@@ -84,6 +101,16 @@ public final class TrafficController {
return TrafficDecision.path(path);
}
/**
* 执行“build blocked sites”所表示的处理流程。
*
* <p>该方法属于 {@code TrafficController},用于保持当前模块的职责边界清晰。
* @param vehicle 执行该处理所需的 vehicle 输入。
* @param vehicles 执行该处理所需的 vehicles 输入。
* @param queues 执行该处理所需的 queues 输入。
* @param currentQueue 执行该处理所需的 current queue 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private Set<String> buildBlockedSites(
VehicleSnapshot vehicle,
Collection<VehicleSnapshot> vehicles,
@@ -117,6 +144,15 @@ public final class TrafficController {
return blocked;
}
/**
* 执行“find channel blocker”所表示的处理流程。
*
* <p>该方法属于 {@code TrafficController},用于保持当前模块的职责边界清晰。
* @param vehicle 执行该处理所需的 vehicle 输入。
* @param target 执行该处理所需的 target 输入。
* @param vehicles 执行该处理所需的 vehicles 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private VehicleSnapshot findChannelBlocker(
VehicleSnapshot vehicle,
Site target,
@@ -140,6 +176,14 @@ public final class TrafficController {
return null;
}
/**
* 判断当前上下文是否满足“has active queue”条件。
*
* <p>该方法属于 {@code TrafficController},用于保持当前模块的职责边界清晰。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param queues 执行该处理所需的 queues 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private boolean hasActiveQueue(
String vehicleId,
Collection<DispatchQueueEntry> queues
@@ -153,6 +197,14 @@ public final class TrafficController {
return false;
}
/**
* 执行“find vehicle”所表示的处理流程。
*
* <p>该方法属于 {@code TrafficController},用于保持当前模块的职责边界清晰。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param vehicles 执行该处理所需的 vehicles 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private VehicleSnapshot findVehicle(
String vehicleId,
Collection<VehicleSnapshot> vehicles
@@ -165,6 +217,15 @@ public final class TrafficController {
return null;
}
/**
* 执行“require inputs”所表示的处理流程。
*
* <p>该方法属于 {@code TrafficController},用于保持当前模块的职责边界清晰。
* @param vehicle 执行该处理所需的 vehicle 输入。
* @param queue 执行该处理所需的 queue 输入。
* @param vehicles 执行该处理所需的 vehicles 输入。
* @param queues 执行该处理所需的 queues 输入。
*/
private void requireInputs(
VehicleSnapshot vehicle,
DispatchQueueEntry queue,

View File

@@ -14,6 +14,15 @@ public final class TrafficDecision {
private final DispatchQueueEntry avoidanceQueue;
private final String reason;
/**
* 创建 {@code TrafficDecision} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code TrafficDecision},用于保持当前模块的职责边界清晰。
* @param code 执行该处理所需的 code 输入。
* @param path 执行该处理所需的 path 输入。
* @param avoidanceQueue 执行该处理所需的 avoidance queue 输入。
* @param reason 执行该处理所需的 reason 输入。
*/
private TrafficDecision(
DecisionCode code,
List<String> path,
@@ -26,6 +35,13 @@ public final class TrafficDecision {
this.reason = reason;
}
/**
* 执行“path”所表示的处理流程。
*
* <p>该方法属于 {@code TrafficDecision},用于保持当前模块的职责边界清晰。
* @param path 执行该处理所需的 path 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public static TrafficDecision path(List<String> path) {
return new TrafficDecision(
DecisionCode.PATH_READY,
@@ -35,10 +51,26 @@ public final class TrafficDecision {
);
}
/**
* 执行“hold”所表示的处理流程。
*
* <p>该方法属于 {@code TrafficDecision},用于保持当前模块的职责边界清晰。
* @param code 执行该处理所需的 code 输入。
* @param reason 执行该处理所需的 reason 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public static TrafficDecision hold(DecisionCode code, String reason) {
return new TrafficDecision(code, Collections.<String>emptyList(), null, reason);
}
/**
* 执行“avoidance”所表示的处理流程。
*
* <p>该方法属于 {@code TrafficDecision},用于保持当前模块的职责边界清晰。
* @param avoidanceQueue 执行该处理所需的 avoidance queue 输入。
* @param reason 执行该处理所需的 reason 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public static TrafficDecision avoidance(
DispatchQueueEntry avoidanceQueue,
String reason
@@ -51,18 +83,42 @@ public final class TrafficDecision {
);
}
/**
* 返回当前对象保存的“code”信息。
*
* <p>该方法属于 {@code TrafficDecision},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public DecisionCode getCode() {
return code;
}
/**
* 返回当前对象保存的“path”信息。
*
* <p>该方法属于 {@code TrafficDecision},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<String> getPath() {
return path;
}
/**
* 返回当前对象保存的“avoidance queue”信息。
*
* <p>该方法属于 {@code TrafficDecision},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Optional<DispatchQueueEntry> getAvoidanceQueue() {
return Optional.ofNullable(avoidanceQueue);
}
/**
* 返回当前对象保存的“reason”信息。
*
* <p>该方法属于 {@code TrafficDecision},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getReason() {
return reason;
}

View File

@@ -35,6 +35,14 @@ public final class ShadowTrafficCoordinator {
private final Map<String, TrafficVehicleSnapshot> previousSnapshots =
new LinkedHashMap<String, TrafficVehicleSnapshot>();
/**
* 创建 {@code ShadowTrafficCoordinator} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code ShadowTrafficCoordinator},用于保持当前模块的职责边界清晰。
* @param map 执行该处理所需的 map 输入。
* @param authoritativeLedger 执行该处理所需的 authoritative ledger 输入。
* @param policy 执行该处理所需的 policy 输入。
*/
public ShadowTrafficCoordinator(EffectiveTrafficMap map, ResourceLedger authoritativeLedger,
RollingDispatchPolicy policy) {
this.map = map;
@@ -42,6 +50,15 @@ public final class ShadowTrafficCoordinator {
this.policy = policy;
}
/**
* 对一个冻结的影子交通快照运行可重放的资源裁决,并生成带输入哈希的决策事件。
*
* <p>只接收 SHADOW 模式且版本匹配的地图;过期或异常车辆快照会被隔离,候选车必须存在于本轮快照。
* 哈希覆盖地图容量、资源持有者和候选移动,使相同业务输入可复核为相同调度决策。
* @param snapshot 执行该处理所需的 snapshot 输入。
* @param candidates 执行该处理所需的 candidates 输入。
* @return 包含裁决、输入快照和可重放哈希的决策事件。
*/
public DecisionEvent run(TrafficSnapshot snapshot, List<ShadowCandidate> candidates) {
if (snapshot.getControlMode() != ControlMode.SHADOW) {
throw new IllegalStateException("coordinator accepts SHADOW snapshots only");
@@ -75,6 +92,14 @@ public final class ShadowTrafficCoordinator {
new DecisionReplayInput(map, authoritativeLedger, snapshot, candidates));
}
/**
* 将本轮地图、资源占用和候选移动按稳定顺序序列化后计算 SHA-256,用作决策重放的输入指纹。
* @param map 执行该处理所需的 map 输入。
* @param ledger 执行该处理所需的 ledger 输入。
* @param snapshot 执行该处理所需的 snapshot 输入。
* @param candidates 执行该处理所需的 candidates 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public static String computeInputHash(EffectiveTrafficMap map, ResourceLedger ledger,
TrafficSnapshot snapshot, List<ShadowCandidate> candidates) {
StringBuilder canonical = new StringBuilder()

View File

@@ -1,6 +1,12 @@
package com.ft546.wcs.shadow.application;
public final class ShadowWriteForbiddenException extends IllegalStateException {
/**
* 创建 {@code ShadowWriteForbiddenException} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code ShadowWriteForbiddenException},用于保持当前模块的职责边界清晰。
* @param operation 执行该处理所需的 operation 输入。
*/
public ShadowWriteForbiddenException(String operation) {
super("SHADOW forbids authoritative write: " + operation);
}

View File

@@ -1,14 +1,32 @@
package com.ft546.wcs.shadow.application;
public final class ShadowWritePort {
/**
* 执行“send plc command”所表示的处理流程。
*
* <p>该方法属于 {@code ShadowWritePort},用于保持当前模块的职责边界清晰。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
*/
public void sendPlcCommand(String vehicleId) {
throw new ShadowWriteForbiddenException("PLC " + vehicleId);
}
/**
* 执行“update business state”所表示的处理流程。
*
* <p>该方法属于 {@code ShadowWritePort},用于保持当前模块的职责边界清晰。
* @param taskId 执行该处理所需的 task id 输入。
*/
public void updateBusinessState(String taskId) {
throw new ShadowWriteForbiddenException("BUSINESS " + taskId);
}
/**
* 执行“write reservation”所表示的处理流程。
*
* <p>该方法属于 {@code ShadowWritePort},用于保持当前模块的职责边界清晰。
* @param segmentId 执行该处理所需的 segment id 输入。
*/
public void writeReservation(String segmentId) {
throw new ShadowWriteForbiddenException("RESERVATION " + segmentId);
}

View File

@@ -11,6 +11,16 @@ import java.util.List;
import java.util.Set;
public final class RollingDispatchPolicy {
/**
* 在冻结的交通快照上为本轮所有候选移动排序并裁决 GRANT、HOLD 或 YIELD。
*
* <p>已承诺移动优先,然后按紧急程度、业务优先级、等待年龄、清障成本和稳定标识排序。策略在台账副本上
* 逐个试占资源;检测到等待环即 HOLD,存在安全让车点时返回 YIELD,保证决策可重放且不改动权威资源。
* @param input 执行该处理所需的 input 输入。
* @param authoritative 执行该处理所需的 authoritative 输入。
* @param map 执行该处理所需的 map 输入。
* @return 与候选一一对应的交通裁决及可解释原因。
*/
public List<ShadowDecision> decide(List<ShadowCandidate> input, ResourceLedger authoritative,
EffectiveTrafficMap map) {
List<ShadowCandidate> candidates = new ArrayList<ShadowCandidate>(input);
@@ -59,6 +69,18 @@ public final class RollingDispatchPolicy {
return Collections.unmodifiableList(decisions);
}
/**
* 执行“decision”所表示的处理流程。
*
* <p>该方法属于 {@code RollingDispatchPolicy},用于保持当前模块的职责边界清晰。
* @param candidate 执行该处理所需的 candidate 输入。
* @param type 执行该处理所需的 type 输入。
* @param reason 执行该处理所需的 reason 输入。
* @param resources 执行该处理所需的 resources 输入。
* @param blockers 执行该处理所需的 blockers 输入。
* @param yieldSite 执行该处理所需的 yield site 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private ShadowDecision decision(ShadowCandidate candidate, DecisionType type, String reason,
Set<ResourceKey> resources, Set<String> blockers, String yieldSite) {
return new ShadowDecision(candidate.getTaskId(), candidate.getVehicleId(), type, reason,

View File

@@ -18,6 +18,20 @@ public final class ShadowCandidate {
private final List<ResourceKey> resources;
private final String safeYieldSite;
/**
* 创建 {@code ShadowCandidate} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code ShadowCandidate},用于保持当前模块的职责边界清晰。
* @param taskId 执行该处理所需的 task id 输入。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param committed 执行该处理所需的 committed 输入。
* @param emergency 执行该处理所需的 emergency 输入。
* @param businessPriority 执行该处理所需的 business priority 输入。
* @param waitAge 执行该处理所需的 wait age 输入。
* @param clearanceCost 执行该处理所需的 clearance cost 输入。
* @param resources 执行该处理所需的 resources 输入。
* @param safeYieldSite 执行该处理所需的 safe yield site 输入。
*/
private ShadowCandidate(String taskId, String vehicleId, boolean committed, boolean emergency,
int businessPriority, long waitAge, int clearanceCost,
Collection<ResourceKey> resources, String safeYieldSite) {
@@ -32,6 +46,20 @@ public final class ShadowCandidate {
this.safeYieldSite = safeYieldSite;
}
/**
* 执行“waiting”所表示的处理流程。
*
* <p>该方法属于 {@code ShadowCandidate},用于保持当前模块的职责边界清晰。
* @param taskId 执行该处理所需的 task id 输入。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param emergency 执行该处理所需的 emergency 输入。
* @param businessPriority 执行该处理所需的 business priority 输入。
* @param waitAge 执行该处理所需的 wait age 输入。
* @param clearanceCost 执行该处理所需的 clearance cost 输入。
* @param resources 执行该处理所需的 resources 输入。
* @param safeYieldSite 执行该处理所需的 safe yield site 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public static ShadowCandidate waiting(String taskId, String vehicleId, boolean emergency,
int businessPriority, long waitAge, int clearanceCost,
Collection<ResourceKey> resources, String safeYieldSite) {
@@ -39,18 +67,81 @@ public final class ShadowCandidate {
waitAge, clearanceCost, resources, safeYieldSite);
}
/**
* 执行“committed”所表示的处理流程。
*
* <p>该方法属于 {@code ShadowCandidate},用于保持当前模块的职责边界清晰。
* @param taskId 执行该处理所需的 task id 输入。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param resources 执行该处理所需的 resources 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public static ShadowCandidate committed(String taskId, String vehicleId,
Collection<ResourceKey> resources) {
return new ShadowCandidate(taskId, vehicleId, true, false, 0, 0, 0, resources, null);
}
/**
* 返回当前对象保存的“task id”信息。
*
* <p>该方法属于 {@code ShadowCandidate},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getTaskId() { return taskId; }
/**
* 返回当前对象保存的“vehicle id”信息。
*
* <p>该方法属于 {@code ShadowCandidate},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getVehicleId() { return vehicleId; }
/**
* 判断当前上下文是否满足“is committed”条件。
*
* <p>该方法属于 {@code ShadowCandidate},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isCommitted() { return committed; }
/**
* 判断当前上下文是否满足“is emergency”条件。
*
* <p>该方法属于 {@code ShadowCandidate},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isEmergency() { return emergency; }
/**
* 返回当前对象保存的“business priority”信息。
*
* <p>该方法属于 {@code ShadowCandidate},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getBusinessPriority() { return businessPriority; }
/**
* 返回当前对象保存的“wait age”信息。
*
* <p>该方法属于 {@code ShadowCandidate},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getWaitAge() { return waitAge; }
/**
* 返回当前对象保存的“clearance cost”信息。
*
* <p>该方法属于 {@code ShadowCandidate},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getClearanceCost() { return clearanceCost; }
/**
* 返回当前对象保存的“resources”信息。
*
* <p>该方法属于 {@code ShadowCandidate},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<ResourceKey> getResources() { return resources; }
/**
* 返回当前对象保存的“safe yield site”信息。
*
* <p>该方法属于 {@code ShadowCandidate},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getSafeYieldSite() { return safeYieldSite; }
}

View File

@@ -16,6 +16,18 @@ public final class ShadowDecision {
private final Set<String> blockingVehicles;
private final String yieldSite;
/**
* 创建 {@code ShadowDecision} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code ShadowDecision},用于保持当前模块的职责边界清晰。
* @param taskId 执行该处理所需的 task id 输入。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param type 执行该处理所需的 type 输入。
* @param reasonCode 执行该处理所需的 reason code 输入。
* @param conflictingResources 执行该处理所需的 conflicting resources 输入。
* @param blockingVehicles 执行该处理所需的 blocking vehicles 输入。
* @param yieldSite 执行该处理所需的 yield site 输入。
*/
public ShadowDecision(String taskId, String vehicleId, DecisionType type, String reasonCode,
Set<ResourceKey> conflictingResources, Set<String> blockingVehicles,
String yieldSite) {
@@ -30,14 +42,63 @@ public final class ShadowDecision {
this.yieldSite = yieldSite;
}
/**
* 返回当前对象保存的“task id”信息。
*
* <p>该方法属于 {@code ShadowDecision},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getTaskId() { return taskId; }
/**
* 返回当前对象保存的“vehicle id”信息。
*
* <p>该方法属于 {@code ShadowDecision},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getVehicleId() { return vehicleId; }
/**
* 返回当前对象保存的“type”信息。
*
* <p>该方法属于 {@code ShadowDecision},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public DecisionType getType() { return type; }
/**
* 返回当前对象保存的“reason code”信息。
*
* <p>该方法属于 {@code ShadowDecision},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getReasonCode() { return reasonCode; }
/**
* 返回当前对象保存的“conflicting resources”信息。
*
* <p>该方法属于 {@code ShadowDecision},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Set<ResourceKey> getConflictingResources() { return conflictingResources; }
/**
* 返回当前对象保存的“blocking vehicles”信息。
*
* <p>该方法属于 {@code ShadowDecision},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Set<String> getBlockingVehicles() { return blockingVehicles; }
/**
* 返回当前对象保存的“yield site”信息。
*
* <p>该方法属于 {@code ShadowDecision},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getYieldSite() { return yieldSite; }
/**
* 比较当前对象与给定对象是否具有相同业务值。
*
* <p>该方法属于 {@code ShadowDecision},用于保持当前模块的职责边界清晰。
* @param other 执行该处理所需的 other 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
@Override
public boolean equals(Object other) {
if (!(other instanceof ShadowDecision)) return false;
@@ -51,6 +112,12 @@ public final class ShadowDecision {
&& Objects.equals(yieldSite, that.yieldSite);
}
/**
* 判断当前上下文是否满足“hash code”条件。
*
* <p>该方法属于 {@code ShadowDecision},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
@Override
public int hashCode() {
return Objects.hash(taskId, vehicleId, type, reasonCode,

View File

@@ -10,17 +10,39 @@ import java.util.Set;
public final class WaitForGraph {
private final Map<String, Set<String>> edges = new LinkedHashMap<String, Set<String>>();
/**
* 执行“would create cycle”所表示的处理流程。
*
* <p>该方法属于 {@code WaitForGraph},用于保持当前模块的职责边界清晰。
* @param waiter 执行该处理所需的 waiter 输入。
* @param holders 执行该处理所需的 holders 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean wouldCreateCycle(String waiter, Collection<String> holders) {
WaitForGraph copy = copy();
copy.put(waiter, holders);
return !copy.isAcyclic();
}
/**
* 执行“add wait”所表示的处理流程。
*
* <p>该方法属于 {@code WaitForGraph},用于保持当前模块的职责边界清晰。
* @param waiter 执行该处理所需的 waiter 输入。
* @param holders 执行该处理所需的 holders 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean addWait(String waiter, Collection<String> holders) {
put(waiter, holders);
return !isAcyclic();
}
/**
* 判断当前上下文是否满足“is acyclic”条件。
*
* <p>该方法属于 {@code WaitForGraph},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isAcyclic() {
Set<String> visiting = new LinkedHashSet<String>();
Set<String> visited = new LinkedHashSet<String>();
@@ -30,6 +52,15 @@ public final class WaitForGraph {
return true;
}
/**
* 判断当前上下文是否满足“has cycle”条件。
*
* <p>该方法属于 {@code WaitForGraph},用于保持当前模块的职责边界清晰。
* @param node 执行该处理所需的 node 输入。
* @param visiting 执行该处理所需的 visiting 输入。
* @param visited 执行该处理所需的 visited 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private boolean hasCycle(String node, Set<String> visiting, Set<String> visited) {
if (visiting.contains(node)) return true;
if (visited.contains(node)) return false;
@@ -42,11 +73,24 @@ public final class WaitForGraph {
return false;
}
/**
* 执行“put”所表示的处理流程。
*
* <p>该方法属于 {@code WaitForGraph},用于保持当前模块的职责边界清晰。
* @param waiter 执行该处理所需的 waiter 输入。
* @param holders 执行该处理所需的 holders 输入。
*/
private void put(String waiter, Collection<String> holders) {
if (!edges.containsKey(waiter)) edges.put(waiter, new LinkedHashSet<String>());
edges.get(waiter).addAll(holders);
}
/**
* 执行“copy”所表示的处理流程。
*
* <p>该方法属于 {@code WaitForGraph},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private WaitForGraph copy() {
WaitForGraph copy = new WaitForGraph();
for (Map.Entry<String, Set<String>> entry : edges.entrySet()) {

View File

@@ -15,6 +15,20 @@ public final class ExecutionFeedback {
private final boolean connected;
private final boolean commitAckKnown;
/**
* 创建 {@code ExecutionFeedback} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code ExecutionFeedback},用于保持当前模块的职责边界清晰。
* @param plcBootId 执行该处理所需的 plc boot id 输入。
* @param plannerEpoch 执行该处理所需的 planner epoch 输入。
* @param planVersion 执行该处理所需的 plan version 输入。
* @param segmentSeq 执行该处理所需的 segment seq 输入。
* @param snapshotSeq 执行该处理所需的 snapshot seq 输入。
* @param currentSite 执行该处理所需的 current site 输入。
* @param remainingPath 执行该处理所需的 remaining path 输入。
* @param connected 执行该处理所需的 connected 输入。
* @param commitAckKnown 执行该处理所需的 commit ack known 输入。
*/
public ExecutionFeedback(String plcBootId, long plannerEpoch, long planVersion, long segmentSeq,
long snapshotSeq, String currentSite, List<String> remainingPath,
boolean connected, boolean commitAckKnown) {
@@ -29,13 +43,67 @@ public final class ExecutionFeedback {
this.commitAckKnown = commitAckKnown;
}
/**
* 返回当前对象保存的“plc boot id”信息。
*
* <p>该方法属于 {@code ExecutionFeedback},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getPlcBootId() { return plcBootId; }
/**
* 返回当前对象保存的“planner epoch”信息。
*
* <p>该方法属于 {@code ExecutionFeedback},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getPlannerEpoch() { return plannerEpoch; }
/**
* 返回当前对象保存的“plan version”信息。
*
* <p>该方法属于 {@code ExecutionFeedback},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getPlanVersion() { return planVersion; }
/**
* 返回当前对象保存的“segment seq”信息。
*
* <p>该方法属于 {@code ExecutionFeedback},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getSegmentSeq() { return segmentSeq; }
/**
* 返回当前对象保存的“snapshot seq”信息。
*
* <p>该方法属于 {@code ExecutionFeedback},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getSnapshotSeq() { return snapshotSeq; }
/**
* 返回当前对象保存的“current site”信息。
*
* <p>该方法属于 {@code ExecutionFeedback},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getCurrentSite() { return currentSite; }
/**
* 返回当前对象保存的“remaining path”信息。
*
* <p>该方法属于 {@code ExecutionFeedback},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<String> getRemainingPath() { return remainingPath; }
/**
* 判断当前上下文是否满足“is connected”条件。
*
* <p>该方法属于 {@code ExecutionFeedback},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isConnected() { return connected; }
/**
* 判断当前上下文是否满足“is commit ack known”条件。
*
* <p>该方法属于 {@code ExecutionFeedback},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isCommitAckKnown() { return commitAckKnown; }
}

View File

@@ -10,6 +10,14 @@ import java.util.List;
import java.util.Set;
public final class FeedbackReconciler {
/**
* 执行“reconcile”所表示的处理流程。
*
* <p>该方法属于 {@code FeedbackReconciler},用于保持当前模块的职责边界清晰。
* @param segment 执行该处理所需的 segment 输入。
* @param feedback 执行该处理所需的 feedback 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public FeedbackResult reconcile(TrafficSegment segment, ExecutionFeedback feedback) {
if (!feedback.isConnected()) return quarantine(segment, "COMMUNICATION_LOST");
if (!feedback.isCommitAckKnown()) return quarantine(segment, "COMMIT_ACK_UNKNOWN");
@@ -44,11 +52,26 @@ public final class FeedbackReconciler {
segment.withLastSnapshotSeq(feedback.getSnapshotSeq()));
}
/**
* 执行“quarantine”所表示的处理流程。
*
* <p>该方法属于 {@code FeedbackReconciler},用于保持当前模块的职责边界清晰。
* @param segment 执行该处理所需的 segment 输入。
* @param reason 执行该处理所需的 reason 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private FeedbackResult quarantine(TrafficSegment segment, String reason) {
return new FeedbackResult(true, reason, Collections.<ResourceKey>emptySet(),
allResources(segment.getPath()), segment.transition(SegmentEvent.QUARANTINE));
}
/**
* 执行“all resources”所表示的处理流程。
*
* <p>该方法属于 {@code FeedbackReconciler},用于保持当前模块的职责边界清晰。
* @param path 执行该处理所需的 path 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private Set<ResourceKey> allResources(List<String> path) {
Set<ResourceKey> resources = new LinkedHashSet<ResourceKey>();
for (int i = 0; i < path.size(); i++) {

View File

@@ -14,6 +14,16 @@ public final class FeedbackResult {
private final Set<ResourceKey> retainedResources;
private final TrafficSegment updatedSegment;
/**
* 创建 {@code FeedbackResult} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code FeedbackResult},用于保持当前模块的职责边界清晰。
* @param quarantined 执行该处理所需的 quarantined 输入。
* @param reasonCode 执行该处理所需的 reason code 输入。
* @param releasedResources 执行该处理所需的 released resources 输入。
* @param retainedResources 执行该处理所需的 retained resources 输入。
* @param updatedSegment 执行该处理所需的 updated segment 输入。
*/
FeedbackResult(boolean quarantined, String reasonCode, Set<ResourceKey> releasedResources,
Set<ResourceKey> retainedResources, TrafficSegment updatedSegment) {
this.quarantined = quarantined;
@@ -25,9 +35,39 @@ public final class FeedbackResult {
this.updatedSegment = updatedSegment;
}
/**
* 判断当前上下文是否满足“is quarantined”条件。
*
* <p>该方法属于 {@code FeedbackResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isQuarantined() { return quarantined; }
/**
* 返回当前对象保存的“reason code”信息。
*
* <p>该方法属于 {@code FeedbackResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getReasonCode() { return reasonCode; }
/**
* 返回当前对象保存的“released resources”信息。
*
* <p>该方法属于 {@code FeedbackResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Set<ResourceKey> getReleasedResources() { return releasedResources; }
/**
* 返回当前对象保存的“retained resources”信息。
*
* <p>该方法属于 {@code FeedbackResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Set<ResourceKey> getRetainedResources() { return retainedResources; }
/**
* 返回当前对象保存的“updated segment”信息。
*
* <p>该方法属于 {@code FeedbackResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public TrafficSegment getUpdatedSegment() { return updatedSegment; }
}

View File

@@ -13,6 +13,19 @@ public final class HistoricalMapCell {
private final String warehouse;
private final String spaceArea;
/**
* 创建 {@code HistoricalMapCell} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code HistoricalMapCell},用于保持当前模块的职责边界清晰。
* @param siteId 执行该处理所需的 site id 输入。
* @param x 执行该处理所需的 x 输入。
* @param y 执行该处理所需的 y 输入。
* @param z 执行该处理所需的 z 输入。
* @param value 执行该处理所需的 value 输入。
* @param axy 执行该处理所需的 axy 输入。
* @param warehouse 执行该处理所需的 warehouse 输入。
* @param spaceArea 执行该处理所需的 space area 输入。
*/
@JsonCreator
public HistoricalMapCell(@JsonProperty("site_id") String siteId,
@JsonProperty("x") int x,
@@ -32,12 +45,60 @@ public final class HistoricalMapCell {
this.spaceArea = spaceArea == null ? "" : spaceArea;
}
/**
* 返回当前对象保存的“site id”信息。
*
* <p>该方法属于 {@code HistoricalMapCell},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getSiteId() { return siteId; }
/**
* 返回当前对象保存的“x”信息。
*
* <p>该方法属于 {@code HistoricalMapCell},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getX() { return x; }
/**
* 返回当前对象保存的“y”信息。
*
* <p>该方法属于 {@code HistoricalMapCell},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getY() { return y; }
/**
* 返回当前对象保存的“z”信息。
*
* <p>该方法属于 {@code HistoricalMapCell},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getZ() { return z; }
/**
* 返回当前对象保存的“value”信息。
*
* <p>该方法属于 {@code HistoricalMapCell},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getValue() { return value; }
/**
* 返回当前对象保存的“axy”信息。
*
* <p>该方法属于 {@code HistoricalMapCell},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getAxy() { return axy; }
/**
* 返回当前对象保存的“warehouse”信息。
*
* <p>该方法属于 {@code HistoricalMapCell},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getWarehouse() { return warehouse; }
/**
* 返回当前对象保存的“space area”信息。
*
* <p>该方法属于 {@code HistoricalMapCell},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getSpaceArea() { return spaceArea; }
}

View File

@@ -7,6 +7,16 @@ public final class HistoricalMapSite {
private final int z;
private final String axy;
/**
* 创建 {@code HistoricalMapSite} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code HistoricalMapSite},用于保持当前模块的职责边界清晰。
* @param siteId 执行该处理所需的 site id 输入。
* @param x 执行该处理所需的 x 输入。
* @param y 执行该处理所需的 y 输入。
* @param z 执行该处理所需的 z 输入。
* @param axy 执行该处理所需的 axy 输入。
*/
public HistoricalMapSite(String siteId, int x, int y, int z, String axy) {
if (siteId == null || siteId.trim().isEmpty()) {
throw new IllegalArgumentException("site id must not be blank");
@@ -18,9 +28,39 @@ public final class HistoricalMapSite {
this.axy = axy == null ? "" : axy;
}
/**
* 返回当前对象保存的“site id”信息。
*
* <p>该方法属于 {@code HistoricalMapSite},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getSiteId() { return siteId; }
/**
* 返回当前对象保存的“x”信息。
*
* <p>该方法属于 {@code HistoricalMapSite},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getX() { return x; }
/**
* 返回当前对象保存的“y”信息。
*
* <p>该方法属于 {@code HistoricalMapSite},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getY() { return y; }
/**
* 返回当前对象保存的“z”信息。
*
* <p>该方法属于 {@code HistoricalMapSite},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getZ() { return z; }
/**
* 返回当前对象保存的“axy”信息。
*
* <p>该方法属于 {@code HistoricalMapSite},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getAxy() { return axy; }
}

View File

@@ -17,6 +17,17 @@ public final class HistoricalPath {
private final Set<ResourceKey> resources;
private final List<String> issues;
/**
* 创建 {@code HistoricalPath} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code HistoricalPath},用于保持当前模块的职责边界清晰。
* @param record 执行该处理所需的 record 输入。
* @param createdAt 执行该处理所需的 created at 输入。
* @param finishedAt 执行该处理所需的 finished at 输入。
* @param nodes 执行该处理所需的 nodes 输入。
* @param resources 执行该处理所需的 resources 输入。
* @param issues 执行该处理所需的 issues 输入。
*/
HistoricalPath(HistoricalQueueRecord record, LocalDateTime createdAt, LocalDateTime finishedAt,
List<String> nodes, Set<ResourceKey> resources, List<String> issues) {
this.record = record;
@@ -27,12 +38,54 @@ public final class HistoricalPath {
this.issues = Collections.unmodifiableList(new ArrayList<String>(issues));
}
/**
* 返回当前对象保存的“record”信息。
*
* <p>该方法属于 {@code HistoricalPath},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public HistoricalQueueRecord getRecord() { return record; }
/**
* 返回当前对象保存的“created at”信息。
*
* <p>该方法属于 {@code HistoricalPath},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public LocalDateTime getCreatedAt() { return createdAt; }
/**
* 返回当前对象保存的“finished at”信息。
*
* <p>该方法属于 {@code HistoricalPath},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public LocalDateTime getFinishedAt() { return finishedAt; }
/**
* 返回当前对象保存的“nodes”信息。
*
* <p>该方法属于 {@code HistoricalPath},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<String> getNodes() { return nodes; }
/**
* 返回当前对象保存的“resources”信息。
*
* <p>该方法属于 {@code HistoricalPath},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Set<ResourceKey> getResources() { return resources; }
/**
* 返回当前对象保存的“issues”信息。
*
* <p>该方法属于 {@code HistoricalPath},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<String> getIssues() { return issues; }
/**
* 判断当前上下文是否满足“is replayable”条件。
*
* <p>该方法属于 {@code HistoricalPath},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isReplayable() {
return createdAt != null && finishedAt != null && !nodes.isEmpty() && issues.isEmpty();
}

View File

@@ -27,6 +27,28 @@ public final class HistoricalQueueDataset {
private final int missingIntervalRows;
private final int reversedIntervalRows;
/**
* 创建 {@code HistoricalQueueDataset} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。
* @param records 执行该处理所需的 records 输入。
* @param mapSiteDetails 执行该处理所需的 map site details 输入。
* @param fullMapCells 执行该处理所需的 full map cells 输入。
* @param fullMapRows 执行该处理所需的 full map rows 输入。
* @param fullMapSha256 执行该处理所需的 full map sha256 输入。
* @param manifestSampleRows 执行该处理所需的 manifest sample rows 输入。
* @param fullScanTotalRows 执行该处理所需的 full scan total rows 输入。
* @param database 执行该处理所需的 database 输入。
* @param sourceTable 执行该处理所需的 source table 输入。
* @param extractedAt 执行该处理所需的 extracted at 输入。
* @param minCreateDate 执行该处理所需的 min create date 输入。
* @param maxCreateDate 执行该处理所需的 max create date 输入。
* @param minFinishDate 执行该处理所需的 min finish date 输入。
* @param maxFinishDate 执行该处理所需的 max finish date 输入。
* @param missingPathRows 执行该处理所需的 missing path rows 输入。
* @param missingIntervalRows 执行该处理所需的 missing interval rows 输入。
* @param reversedIntervalRows 执行该处理所需的 reversed interval rows 输入。
*/
public HistoricalQueueDataset(List<HistoricalQueueRecord> records,
Map<String, HistoricalMapSite> mapSiteDetails,
List<HistoricalMapCell> fullMapCells,
@@ -58,25 +80,133 @@ public final class HistoricalQueueDataset {
this.reversedIntervalRows = reversedIntervalRows;
}
/**
* 返回当前对象保存的“records”信息。
*
* <p>该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<HistoricalQueueRecord> getRecords() { return records; }
/**
* 返回当前对象保存的“map sites”信息。
*
* <p>该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Set<String> getMapSites() {
return Collections.unmodifiableSet(
new LinkedHashSet<String>(mapSiteDetails.keySet()));
}
/**
* 返回当前对象保存的“map site details”信息。
*
* <p>该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Map<String, HistoricalMapSite> getMapSiteDetails() { return mapSiteDetails; }
/**
* 返回当前对象保存的“full map cells”信息。
*
* <p>该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<HistoricalMapCell> getFullMapCells() { return fullMapCells; }
/**
* 返回当前对象保存的“full map rows”信息。
*
* <p>该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getFullMapRows() { return fullMapRows; }
/**
* 返回当前对象保存的“full map sha256”信息。
*
* <p>该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getFullMapSha256() { return fullMapSha256; }
/**
* 返回当前对象保存的“manifest sample rows”信息。
*
* <p>该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getManifestSampleRows() { return manifestSampleRows; }
/**
* 返回当前对象保存的“full scan total rows”信息。
*
* <p>该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getFullScanTotalRows() { return fullScanTotalRows; }
/**
* 返回当前对象保存的“database”信息。
*
* <p>该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getDatabase() { return database; }
/**
* 返回当前对象保存的“source table”信息。
*
* <p>该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getSourceTable() { return sourceTable; }
/**
* 返回当前对象保存的“extracted at”信息。
*
* <p>该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getExtractedAt() { return extractedAt; }
/**
* 返回当前对象保存的“min create date”信息。
*
* <p>该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getMinCreateDate() { return minCreateDate; }
/**
* 返回当前对象保存的“max create date”信息。
*
* <p>该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getMaxCreateDate() { return maxCreateDate; }
/**
* 返回当前对象保存的“min finish date”信息。
*
* <p>该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getMinFinishDate() { return minFinishDate; }
/**
* 返回当前对象保存的“max finish date”信息。
*
* <p>该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getMaxFinishDate() { return maxFinishDate; }
/**
* 返回当前对象保存的“missing path rows”信息。
*
* <p>该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getMissingPathRows() { return missingPathRows; }
/**
* 返回当前对象保存的“missing interval rows”信息。
*
* <p>该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getMissingIntervalRows() { return missingIntervalRows; }
/**
* 返回当前对象保存的“reversed interval rows”信息。
*
* <p>该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getReversedIntervalRows() { return reversedIntervalRows; }
}

View File

@@ -24,6 +24,14 @@ import java.util.Set;
public final class HistoricalQueueLoader {
private static final ObjectMapper MAPPER = new ObjectMapper();
/**
* 执行“load”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalQueueLoader},用于保持当前模块的职责边界清晰。
* @param loader 执行该处理所需的 loader 输入。
* @param basePath 执行该处理所需的 base path 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public HistoricalQueueDataset load(ClassLoader loader, String basePath) {
try {
byte[] manifestBytes = read(loader, basePath + "/manifest.json");
@@ -90,6 +98,12 @@ public final class HistoricalQueueLoader {
}
}
/**
* 执行“validate passable cells”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalQueueLoader},用于保持当前模块的职责边界清晰。
* @param cells 执行该处理所需的 cells 输入。
*/
private static void validatePassableCells(List<HistoricalMapCell> cells) {
Set<String> siteIds = new LinkedHashSet<String>();
Set<String> coordinates = new LinkedHashSet<String>();
@@ -108,6 +122,13 @@ public final class HistoricalQueueLoader {
}
}
/**
* 执行“load”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalQueueLoader},用于保持当前模块的职责边界清晰。
* @param basePath 执行该处理所需的 base path 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public HistoricalQueueDataset load(Path basePath) {
if (basePath == null || basePath.getParent() == null || basePath.getParent().getParent() == null) {
throw new IllegalArgumentException("invalid history snapshot path");
@@ -125,6 +146,13 @@ public final class HistoricalQueueLoader {
}
}
/**
* 执行“verify sha256”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalQueueLoader},用于保持当前模块的职责边界清晰。
* @param expected 执行该处理所需的 expected 输入。
* @param bytes 执行该处理所需的 bytes 输入。
*/
public static void verifySha256(String expected, byte[] bytes) {
CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder()
.onMalformedInput(CodingErrorAction.REPORT)
@@ -145,6 +173,13 @@ public final class HistoricalQueueLoader {
}
}
/**
* 执行“sha256”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalQueueLoader},用于保持当前模块的职责边界清晰。
* @param bytes 执行该处理所需的 bytes 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private static String sha256(byte[] bytes) {
try {
byte[] digest = MessageDigest.getInstance("SHA-256").digest(bytes);
@@ -156,6 +191,15 @@ public final class HistoricalQueueLoader {
}
}
/**
* 执行“read”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalQueueLoader},用于保持当前模块的职责边界清晰。
* @param loader 执行该处理所需的 loader 输入。
* @param name 执行该处理所需的 name 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
* @throws IOException 当调用条件不满足或处理无法继续时抛出。
*/
private static byte[] read(ClassLoader loader, String name) throws IOException {
InputStream input = loader.getResourceAsStream(name);
if (input == null) throw new IllegalArgumentException("missing classpath resource " + name);

View File

@@ -15,6 +15,14 @@ public final class HistoricalQueueNormalizer {
private static final DateTimeFormatter TIME = DateTimeFormatter
.ofPattern("uuuu-MM-dd HH:mm:ss").withResolverStyle(ResolverStyle.STRICT);
/**
* 执行“normalize”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalQueueNormalizer},用于保持当前模块的职责边界清晰。
* @param record 执行该处理所需的 record 输入。
* @param mapSites 执行该处理所需的 map sites 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public HistoricalPath normalize(HistoricalQueueRecord record, Set<String> mapSites) {
List<String> issues = new ArrayList<String>();
LocalDateTime created = parse(record.getCreateDate(), "INVALID_CREATE_DATE", issues);
@@ -44,6 +52,15 @@ public final class HistoricalQueueNormalizer {
return new HistoricalPath(record, created, finished, nodes, resources, issues);
}
/**
* 执行“parse”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalQueueNormalizer},用于保持当前模块的职责边界清晰。
* @param value 执行该处理所需的 value 输入。
* @param issue 执行该处理所需的 issue 输入。
* @param issues 执行该处理所需的 issues 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private LocalDateTime parse(String value, String issue, List<String> issues) {
if (value == null || value.trim().isEmpty()) {
issues.add(issue);

View File

@@ -21,8 +21,28 @@ public final class HistoricalQueueRecord {
@JsonProperty("finish_date") private String finishDate;
@JsonProperty("agv_id") private String agvId;
/**
* 创建 {@code HistoricalQueueRecord} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。
*/
public HistoricalQueueRecord() { }
/**
* 创建 {@code HistoricalQueueRecord} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。
* @param guid 执行该处理所需的 guid 输入。
* @param taskNo 执行该处理所需的 task no 输入。
* @param taskType 执行该处理所需的 task type 输入。
* @param priority 执行该处理所需的 priority 输入。
* @param startSite 执行该处理所需的 start site 输入。
* @param endSite 执行该处理所需的 end site 输入。
* @param pathInfo 执行该处理所需的 path info 输入。
* @param createDate 执行该处理所需的 create date 输入。
* @param finishDate 执行该处理所需的 finish date 输入。
* @param agvId 执行该处理所需的 agv id 输入。
*/
public HistoricalQueueRecord(String guid, String taskNo, String taskType, Integer priority,
String startSite, String endSite, String pathInfo,
String createDate, String finishDate, String agvId) {
@@ -38,19 +58,109 @@ public final class HistoricalQueueRecord {
this.agvId = agvId;
}
/**
* 返回当前对象保存的“guid”信息。
*
* <p>该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getGuid() { return guid; }
/**
* 返回当前对象保存的“task no”信息。
*
* <p>该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getTaskNo() { return taskNo; }
/**
* 返回当前对象保存的“task type”信息。
*
* <p>该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getTaskType() { return taskType; }
/**
* 返回当前对象保存的“priority”信息。
*
* <p>该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Integer getPriority() { return priority; }
/**
* 返回当前对象保存的“cargo”信息。
*
* <p>该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getCargo() { return cargo; }
/**
* 返回当前对象保存的“issued”信息。
*
* <p>该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getIssued() { return issued; }
/**
* 返回当前对象保存的“execution status”信息。
*
* <p>该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getExecutionStatus() { return executionStatus; }
/**
* 返回当前对象保存的“start site”信息。
*
* <p>该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getStartSite() { return startSite; }
/**
* 返回当前对象保存的“end site”信息。
*
* <p>该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getEndSite() { return endSite; }
/**
* 返回当前对象保存的“floor”信息。
*
* <p>该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getFloor() { return floor; }
/**
* 返回当前对象保存的“path info”信息。
*
* <p>该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getPathInfo() { return pathInfo; }
/**
* 返回当前对象保存的“create date”信息。
*
* <p>该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getCreateDate() { return createDate; }
/**
* 返回当前对象保存的“start date”信息。
*
* <p>该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getStartDate() { return startDate; }
/**
* 返回当前对象保存的“finish date”信息。
*
* <p>该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getFinishDate() { return finishDate; }
/**
* 返回当前对象保存的“agv id”信息。
*
* <p>该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getAgvId() { return agvId; }
}

View File

@@ -10,6 +10,14 @@ import java.util.List;
import java.util.Set;
public final class HistoricalReplayAnalyzer {
/**
* 执行“overlaps”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalReplayAnalyzer},用于保持当前模块的职责边界清晰。
* @param left 执行该处理所需的 left 输入。
* @param right 执行该处理所需的 right 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean overlaps(HistoricalPath left, HistoricalPath right) {
if (left.getCreatedAt() == null || left.getFinishedAt() == null
|| right.getCreatedAt() == null || right.getFinishedAt() == null) return false;
@@ -17,6 +25,13 @@ public final class HistoricalReplayAnalyzer {
&& right.getCreatedAt().isBefore(left.getFinishedAt());
}
/**
* 执行“analyze”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalReplayAnalyzer},用于保持当前模块的职责边界清晰。
* @param input 执行该处理所需的 input 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<HistoricalReplayResult> analyze(List<HistoricalPath> input) {
List<HistoricalPath> ordered = new ArrayList<HistoricalPath>(input);
Collections.sort(ordered, stableOrder());
@@ -60,6 +75,12 @@ public final class HistoricalReplayAnalyzer {
return Collections.unmodifiableList(results);
}
/**
* 执行“stable order”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalReplayAnalyzer},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private Comparator<HistoricalPath> stableOrder() {
return Comparator
.comparing((HistoricalPath p) -> p.getRecord().getPriority() == null
@@ -71,6 +92,14 @@ public final class HistoricalReplayAnalyzer {
.thenComparing(p -> text(p.getRecord().getGuid()));
}
/**
* 执行“shared nodes”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalReplayAnalyzer},用于保持当前模块的职责边界清晰。
* @param left 执行该处理所需的 left 输入。
* @param right 执行该处理所需的 right 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private List<String> sharedNodes(HistoricalPath left, HistoricalPath right) {
Set<String> values = new LinkedHashSet<String>();
Set<String> rightNodes = new LinkedHashSet<String>(right.getNodes());
@@ -78,6 +107,14 @@ public final class HistoricalReplayAnalyzer {
return new ArrayList<String>(values);
}
/**
* 执行“opposite edges”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalReplayAnalyzer},用于保持当前模块的职责边界清晰。
* @param left 执行该处理所需的 left 输入。
* @param right 执行该处理所需的 right 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private List<String> oppositeEdges(HistoricalPath left, HistoricalPath right) {
Set<String> rightDirections = new LinkedHashSet<String>();
for (int i = 1; i < right.getNodes().size(); i++) {
@@ -94,6 +131,18 @@ public final class HistoricalReplayAnalyzer {
return new ArrayList<String>(result);
}
/**
* 执行“result”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalReplayAnalyzer},用于保持当前模块的职责边界清晰。
* @param path 执行该处理所需的 path 输入。
* @param category 执行该处理所需的 category 输入。
* @param decision 执行该处理所需的 decision 输入。
* @param related 执行该处理所需的 related 输入。
* @param resources 执行该处理所需的 resources 输入。
* @param reason 执行该处理所需的 reason 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private HistoricalReplayResult result(HistoricalPath path, HistoricalReplayCategory category,
String decision, HistoricalPath related,
List<String> resources, String reason) {
@@ -102,9 +151,24 @@ public final class HistoricalReplayAnalyzer {
related == null ? null : related.getRecord().getTaskNo(), resources, reason);
}
/**
* 执行“same”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalReplayAnalyzer},用于保持当前模块的职责边界清晰。
* @param left 执行该处理所需的 left 输入。
* @param right 执行该处理所需的 right 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private boolean same(String left, String right) {
return left != null && left.equals(right);
}
/**
* 执行“text”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalReplayAnalyzer},用于保持当前模块的职责边界清晰。
* @param value 执行该处理所需的 value 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private String text(String value) { return value == null ? "" : value; }
}

View File

@@ -7,8 +7,20 @@ import java.util.ArrayList;
import java.util.List;
public final class HistoricalReplayApplication {
/**
* 创建 {@code HistoricalReplayApplication} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code HistoricalReplayApplication},用于保持当前模块的职责边界清晰。
*/
private HistoricalReplayApplication() { }
/**
* 执行“main”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalReplayApplication},用于保持当前模块的职责边界清晰。
* @param args 执行该处理所需的 args 输入。
* @throws Exception 当调用条件不满足或处理无法继续时抛出。
*/
public static void main(String[] args) throws Exception {
if (args.length != 1) {
throw new IllegalArgumentException("usage: HistoricalReplayApplication <outputDir>");

View File

@@ -19,6 +19,16 @@ import java.util.TreeSet;
public final class HistoricalReplayReportWriter {
private static final ObjectMapper JSON = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
/**
* 执行“write”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalReplayReportWriter},用于保持当前模块的职责边界清晰。
* @param outputDir 执行该处理所需的 output dir 输入。
* @param dataset 执行该处理所需的 dataset 输入。
* @param paths 执行该处理所需的 paths 输入。
* @param results 执行该处理所需的 results 输入。
* @throws IOException 当调用条件不满足或处理无法继续时抛出。
*/
public void write(Path outputDir, HistoricalQueueDataset dataset,
List<HistoricalPath> paths, List<HistoricalReplayResult> results) throws IOException {
Files.createDirectories(outputDir);
@@ -73,6 +83,13 @@ public final class HistoricalReplayReportWriter {
writeManifest(outputDir);
}
/**
* 执行“replay rows”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalReplayReportWriter},用于保持当前模块的职责边界清晰。
* @param results 执行该处理所需的 results 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private List<List<String>> replayRows(List<HistoricalReplayResult> results) {
List<List<String>> rows = new ArrayList<List<String>>();
rows.add(Arrays.asList("创建时间", "完成时间", "车辆", "任务号", "起点", "终点",
@@ -91,6 +108,13 @@ public final class HistoricalReplayReportWriter {
return rows;
}
/**
* 判断当前上下文是否满足“issue rows”条件。
*
* <p>该方法属于 {@code HistoricalReplayReportWriter},用于保持当前模块的职责边界清晰。
* @param paths 执行该处理所需的 paths 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private List<List<String>> issueRows(List<HistoricalPath> paths) {
List<List<String>> rows = new ArrayList<List<String>>();
rows.add(Arrays.asList("GUID", "车辆", "任务号", "问题类型", "原始路径", "是否影响回放", "处理方式"));
@@ -104,6 +128,14 @@ public final class HistoricalReplayReportWriter {
return rows;
}
/**
* 执行“write csv”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalReplayReportWriter},用于保持当前模块的职责边界清晰。
* @param file 执行该处理所需的 file 输入。
* @param rows 执行该处理所需的 rows 输入。
* @throws IOException 当调用条件不满足或处理无法继续时抛出。
*/
private void writeCsv(Path file, List<List<String>> rows) throws IOException {
StringBuilder csv = new StringBuilder("\uFEFF");
for (List<String> row : rows) {
@@ -116,6 +148,13 @@ public final class HistoricalReplayReportWriter {
Files.write(file, csv.toString().getBytes(StandardCharsets.UTF_8));
}
/**
* 执行“write manifest”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalReplayReportWriter},用于保持当前模块的职责边界清晰。
* @param outputDir 执行该处理所需的 output dir 输入。
* @throws IOException 当调用条件不满足或处理无法继续时抛出。
*/
private void writeManifest(Path outputDir) throws IOException {
List<String> names = Arrays.asList("data-quality-issues.csv", "replay-results.csv", "summary.json");
StringBuilder manifest = new StringBuilder();
@@ -125,6 +164,13 @@ public final class HistoricalReplayReportWriter {
Files.write(outputDir.resolve("manifest.sha256"), manifest.toString().getBytes(StandardCharsets.UTF_8));
}
/**
* 执行“sha256”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalReplayReportWriter},用于保持当前模块的职责边界清晰。
* @param bytes 执行该处理所需的 bytes 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private String sha256(byte[] bytes) {
try {
byte[] hash = MessageDigest.getInstance("SHA-256").digest(bytes);
@@ -136,5 +182,12 @@ public final class HistoricalReplayReportWriter {
}
}
/**
* 执行“value”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalReplayReportWriter},用于保持当前模块的职责边界清晰。
* @param value 执行该处理所需的 value 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private String value(String value) { return value == null ? "" : value; }
}

View File

@@ -14,6 +14,18 @@ public final class HistoricalReplayResult {
private final List<String> sharedResources;
private final String reason;
/**
* 创建 {@code HistoricalReplayResult} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code HistoricalReplayResult},用于保持当前模块的职责边界清晰。
* @param path 执行该处理所需的 path 输入。
* @param category 执行该处理所需的 category 输入。
* @param decision 执行该处理所需的 decision 输入。
* @param relatedAgvId 执行该处理所需的 related agv id 输入。
* @param relatedTaskNo 执行该处理所需的 related task no 输入。
* @param sharedResources 执行该处理所需的 shared resources 输入。
* @param reason 执行该处理所需的 reason 输入。
*/
HistoricalReplayResult(HistoricalPath path, HistoricalReplayCategory category, String decision,
String relatedAgvId, String relatedTaskNo,
List<String> sharedResources, String reason) {
@@ -26,14 +38,63 @@ public final class HistoricalReplayResult {
this.reason = reason;
}
/**
* 返回当前对象保存的“path”信息。
*
* <p>该方法属于 {@code HistoricalReplayResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public HistoricalPath getPath() { return path; }
/**
* 返回当前对象保存的“category”信息。
*
* <p>该方法属于 {@code HistoricalReplayResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public HistoricalReplayCategory getCategory() { return category; }
/**
* 返回当前对象保存的“decision”信息。
*
* <p>该方法属于 {@code HistoricalReplayResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getDecision() { return decision; }
/**
* 返回当前对象保存的“related agv id”信息。
*
* <p>该方法属于 {@code HistoricalReplayResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getRelatedAgvId() { return relatedAgvId; }
/**
* 返回当前对象保存的“related task no”信息。
*
* <p>该方法属于 {@code HistoricalReplayResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getRelatedTaskNo() { return relatedTaskNo; }
/**
* 返回当前对象保存的“shared resources”信息。
*
* <p>该方法属于 {@code HistoricalReplayResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<String> getSharedResources() { return sharedResources; }
/**
* 返回当前对象保存的“reason”信息。
*
* <p>该方法属于 {@code HistoricalReplayResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getReason() { return reason; }
/**
* 比较当前对象与给定对象是否具有相同业务值。
*
* <p>该方法属于 {@code HistoricalReplayResult},用于保持当前模块的职责边界清晰。
* @param other 执行该处理所需的 other 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
@Override
public boolean equals(Object other) {
if (!(other instanceof HistoricalReplayResult)) return false;
@@ -47,6 +108,12 @@ public final class HistoricalReplayResult {
&& Objects.equals(reason, that.reason);
}
/**
* 判断当前上下文是否满足“hash code”条件。
*
* <p>该方法属于 {@code HistoricalReplayResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
@Override
public int hashCode() {
return Objects.hash(path.getRecord().getGuid(), category, decision,

View File

@@ -11,24 +11,108 @@ public final class ClearanceMove {
private int index;
private int protocolAttempts;
/**
* 创建 {@code ClearanceMove} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param ownerTaskId 执行该处理所需的 owner task id 输入。
* @param route 执行该处理所需的 route 输入。
*/
ClearanceMove(String vehicleId, String ownerTaskId, List<String> route) {
this.vehicleId = vehicleId;
this.ownerTaskId = ownerTaskId;
this.route = Collections.unmodifiableList(new ArrayList<String>(route));
}
/**
* 返回当前对象保存的“vehicle id”信息。
*
* <p>该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getVehicleId() { return vehicleId; }
/**
* 返回当前对象保存的“owner task id”信息。
*
* <p>该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getOwnerTaskId() { return ownerTaskId; }
/**
* 返回当前对象保存的“source site”信息。
*
* <p>该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getSourceSite() { return route.get(0); }
/**
* 返回当前对象保存的“target site”信息。
*
* <p>该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getTargetSite() { return route.get(route.size() - 1); }
/**
* 返回当前对象保存的“route”信息。
*
* <p>该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<String> getRoute() { return route; }
/**
* 返回当前对象保存的“index”信息。
*
* <p>该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getIndex() { return index; }
/**
* 返回当前对象保存的“protocol attempts”信息。
*
* <p>该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getProtocolAttempts() { return protocolAttempts; }
/**
* 判断当前上下文是否满足“is complete”条件。
*
* <p>该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isComplete() { return index >= route.size() - 1; }
/**
* 执行“current site”所表示的处理流程。
*
* <p>该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
String currentSite() { return route.get(index); }
/**
* 执行“next site”所表示的处理流程。
*
* <p>该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
String nextSite() { return route.get(index + 1); }
/**
* 执行“moved”所表示的处理流程。
*
* <p>该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。
*/
void moved() { index++; }
/**
* 执行“attempted protocol”所表示的处理流程。
*
* <p>该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。
*/
void attemptedProtocol() { protocolAttempts++; }
/**
* 执行“clearance task id”所表示的处理流程。
*
* <p>该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
String clearanceTaskId() { return "CLEARANCE:" + ownerTaskId + ":" + vehicleId; }
}

View File

@@ -13,6 +13,20 @@ import java.util.Optional;
import java.util.Set;
public final class ClearanceMovePlanner {
/**
* 为挡住主任务前进方向的空闲车规划临时让路路线,而不改变主任务本身的服务路径。
*
* <p>候选目的地必须避开主任务剩余路线、其他车辆位置和已预约节点;在可达候选中先选路径最短,
* 再优先选分支或死端位置,最后以站点编号稳定排序。找不到安全位置时返回空,让调用方继续 HOLD。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param currentSite 执行该处理所需的 current site 输入。
* @param ownerTaskId 执行该处理所需的 owner task id 输入。
* @param ownerRemainingRoute 执行该处理所需的 owner remaining route 输入。
* @param occupiedSites 执行该处理所需的 occupied sites 输入。
* @param reservedResources 执行该处理所需的 reserved resources 输入。
* @param map 执行该处理所需的 map 输入。
* @return 可安全执行的清障动作;不存在让路位置时为空。
*/
public Optional<ClearanceMove> plan(String vehicleId, String currentSite,
String ownerTaskId, List<String> ownerRemainingRoute,
Set<String> occupiedSites,
@@ -58,6 +72,14 @@ public final class ClearanceMovePlanner {
private final List<String> route;
private final boolean branch;
/**
* 创建 {@code Candidate} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code Candidate},用于保持当前模块的职责边界清晰。
* @param target 执行该处理所需的 target 输入。
* @param route 执行该处理所需的 route 输入。
* @param branch 执行该处理所需的 branch 输入。
*/
private Candidate(String target, List<String> route, boolean branch) {
this.target = target;
this.route = route;

View File

@@ -16,6 +16,17 @@ public final class CorridorReservationManager {
new LinkedHashMap<String, Set<String>>();
private final Map<String, Rank> ranks = new LinkedHashMap<String, Rank>();
/**
* 为一条待执行路线预留走廊方向,防止相向车辆同时进入同一条物理边。
*
* <p>边以无向规范键识别、以方向区分。已存在反向持有者时拒绝并返回当前最应优先通过的任务;
* 同向任务可以共享预约。预约成功后保存任务到边的反向索引,供移动、HOLD、完成和重派及时释放。
* @param taskId 执行该处理所需的 task id 输入。
* @param route 执行该处理所需的 route 输入。
* @param effectivePriority 执行该处理所需的 effective priority 输入。
* @param arrivalMillis 执行该处理所需的 arrival millis 输入。
* @return 是否取得走廊以及冲突时的优先持有者和业务原因。
*/
public ReservationDecision reserve(String taskId, List<String> route,
int effectivePriority, long arrivalMillis) {
if (taskId == null || taskId.trim().isEmpty() || route == null || route.isEmpty()) {
@@ -43,6 +54,12 @@ public final class CorridorReservationManager {
return ReservationDecision.granted();
}
/**
* 在车辆通过一条边后立即释放该段走廊,允许后续同向或反向任务重新竞争资源。
* @param taskId 执行该处理所需的 task id 输入。
* @param from 执行该处理所需的 from 输入。
* @param to 执行该处理所需的 to 输入。
*/
public void releasePassedEdge(String taskId, String from, String to) {
String edgeId = request(from, to).edgeId;
EdgeReservation reservation = edges.get(edgeId);
@@ -60,6 +77,10 @@ public final class CorridorReservationManager {
}
}
/**
* 在任务完成、故障暂停或连续 HOLD 重派时,释放该任务尚未通过的全部走廊及其排序信息。
* @param taskId 执行该处理所需的 task id 输入。
*/
public void releaseTask(String taskId) {
Set<String> reserved = taskEdges.remove(taskId);
if (reserved != null) {
@@ -73,11 +94,22 @@ public final class CorridorReservationManager {
ranks.remove(taskId);
}
/**
* 查询某物理边当前代表性持有者,用于解释走廊方向冲突的归属。
* @param left 执行该处理所需的 left 输入。
* @param right 执行该处理所需的 right 输入。
* @return 按调度顺序优先的持有任务;没有预约时返回 {@code null}。
*/
public String ownerFor(String left, String right) {
EdgeReservation reservation = edges.get(request(left, right).edgeId);
return reservation == null ? null : bestOwner(reservation.holders);
}
/**
* 按有效优先级、到达时间和任务编号稳定排序,选出应代表同向预约的任务。
* @param holders 执行该处理所需的 holders 输入。
* @return 可用于冲突诊断和让行决策的任务编号。
*/
private String bestOwner(Set<String> holders) {
List<Rank> candidates = new ArrayList<Rank>();
for (String holder : holders) {
@@ -91,6 +123,12 @@ public final class CorridorReservationManager {
return candidates.get(0).taskId;
}
/**
* 将有向移动转换为“无向边键 + 方向号”,使 A→B 与 B→A 被识别为同一物理走廊的相反通行权。
* @param from 执行该处理所需的 from 输入。
* @param to 执行该处理所需的 to 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private EdgeRequest request(String from, String to) {
if (from == null || to == null || from.equals(to)) {
throw new IllegalArgumentException("corridor edge endpoints must differ");
@@ -105,22 +143,62 @@ public final class CorridorReservationManager {
private final String ownerTaskId;
private final String reason;
/**
* 创建 {@code ReservationDecision} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code ReservationDecision},用于保持当前模块的职责边界清晰。
* @param granted 执行该处理所需的 granted 输入。
* @param ownerTaskId 执行该处理所需的 owner task id 输入。
* @param reason 执行该处理所需的 reason 输入。
*/
private ReservationDecision(boolean granted, String ownerTaskId, String reason) {
this.granted = granted;
this.ownerTaskId = ownerTaskId;
this.reason = reason;
}
/**
* 执行“granted”所表示的处理流程。
*
* <p>该方法属于 {@code ReservationDecision},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private static ReservationDecision granted() {
return new ReservationDecision(true, null, "GRANTED");
}
/**
* 执行“denied”所表示的处理流程。
*
* <p>该方法属于 {@code ReservationDecision},用于保持当前模块的职责边界清晰。
* @param ownerTaskId 执行该处理所需的 owner task id 输入。
* @param reason 执行该处理所需的 reason 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private static ReservationDecision denied(String ownerTaskId, String reason) {
return new ReservationDecision(false, ownerTaskId, reason);
}
/**
* 判断当前上下文是否满足“is granted”条件。
*
* <p>该方法属于 {@code ReservationDecision},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isGranted() { return granted; }
/**
* 返回当前对象保存的“owner task id”信息。
*
* <p>该方法属于 {@code ReservationDecision},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getOwnerTaskId() { return ownerTaskId; }
/**
* 返回当前对象保存的“reason”信息。
*
* <p>该方法属于 {@code ReservationDecision},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getReason() { return reason; }
}
@@ -128,6 +206,12 @@ public final class CorridorReservationManager {
private final int direction;
private final Set<String> holders = new LinkedHashSet<String>();
/**
* 创建 {@code EdgeReservation} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code EdgeReservation},用于保持当前模块的职责边界清晰。
* @param direction 执行该处理所需的 direction 输入。
*/
private EdgeReservation(int direction) { this.direction = direction; }
}
@@ -135,6 +219,13 @@ public final class CorridorReservationManager {
private final String edgeId;
private final int direction;
/**
* 创建 {@code EdgeRequest} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code EdgeRequest},用于保持当前模块的职责边界清晰。
* @param edgeId 执行该处理所需的 edge id 输入。
* @param direction 执行该处理所需的 direction 输入。
*/
private EdgeRequest(String edgeId, int direction) {
this.edgeId = edgeId;
this.direction = direction;
@@ -146,6 +237,14 @@ public final class CorridorReservationManager {
private final int priority;
private final long arrivalMillis;
/**
* 创建 {@code Rank} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code Rank},用于保持当前模块的职责边界清晰。
* @param taskId 执行该处理所需的 task id 输入。
* @param priority 执行该处理所需的 priority 输入。
* @param arrivalMillis 执行该处理所需的 arrival millis 输入。
*/
private Rank(String taskId, int priority, long arrivalMillis) {
this.taskId = taskId;
this.priority = priority;

View File

@@ -16,18 +16,44 @@ public final class DeterministicFaultPlan {
private final String vehicleId;
private final VehicleEventType type;
/**
* 创建 {@code VehicleEvent} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code VehicleEvent},用于保持当前模块的职责边界清晰。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param type 执行该处理所需的 type 输入。
*/
private VehicleEvent(String vehicleId, VehicleEventType type) {
this.vehicleId = vehicleId;
this.type = type;
}
/**
* 返回当前对象保存的“vehicle id”信息。
*
* <p>该方法属于 {@code VehicleEvent},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getVehicleId() { return vehicleId; }
/**
* 返回当前对象保存的“type”信息。
*
* <p>该方法属于 {@code VehicleEvent},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public VehicleEventType getType() { return type; }
}
private final Map<String, Map<Integer, SimulatedPlcGateway.PlcReason>> plcFailures;
private final Map<Long, List<VehicleEvent>> vehicleEvents;
/**
* 创建 {@code DeterministicFaultPlan} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code DeterministicFaultPlan},用于保持当前模块的职责边界清晰。
* @param plcFailures 执行该处理所需的 plc failures 输入。
* @param vehicleEvents 执行该处理所需的 vehicle events 输入。
*/
private DeterministicFaultPlan(
Map<String, Map<Integer, SimulatedPlcGateway.PlcReason>> plcFailures,
Map<Long, List<VehicleEvent>> vehicleEvents) {
@@ -35,15 +61,42 @@ public final class DeterministicFaultPlan {
this.vehicleEvents = vehicleEvents;
}
/**
* 执行“builder”所表示的处理流程。
*
* <p>该方法属于 {@code DeterministicFaultPlan},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public static Builder builder() { return new Builder(); }
/**
* 执行“none”所表示的处理流程。
*
* <p>该方法属于 {@code DeterministicFaultPlan},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public static DeterministicFaultPlan none() { return builder().build(); }
/**
* 执行“plc reason”所表示的处理流程。
*
* <p>该方法属于 {@code DeterministicFaultPlan},用于保持当前模块的职责边界清晰。
* @param taskId 执行该处理所需的 task id 输入。
* @param attempt 执行该处理所需的 attempt 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
SimulatedPlcGateway.PlcReason plcReason(String taskId, int attempt) {
Map<Integer, SimulatedPlcGateway.PlcReason> byAttempt = plcFailures.get(taskId);
return byAttempt == null ? null : byAttempt.get(attempt);
}
/**
* 执行“events at”所表示的处理流程。
*
* <p>该方法属于 {@code DeterministicFaultPlan},用于保持当前模块的职责边界清晰。
* @param eventNumber 执行该处理所需的 event number 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<VehicleEvent> eventsAt(long eventNumber) {
List<VehicleEvent> events = vehicleEvents.get(eventNumber);
return events == null ? Collections.emptyList() : events;
@@ -55,6 +108,15 @@ public final class DeterministicFaultPlan {
private final Map<Long, List<VehicleEvent>> vehicleEvents =
new LinkedHashMap<Long, List<VehicleEvent>>();
/**
* 执行“plc failure”所表示的处理流程。
*
* <p>该方法属于 {@code Builder},用于保持当前模块的职责边界清晰。
* @param taskId 执行该处理所需的 task id 输入。
* @param attempt 执行该处理所需的 attempt 输入。
* @param reason 执行该处理所需的 reason 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Builder plcFailure(String taskId, int attempt,
SimulatedPlcGateway.PlcReason reason) {
if (taskId == null || attempt <= 0 || reason == null
@@ -71,6 +133,15 @@ public final class DeterministicFaultPlan {
return this;
}
/**
* 执行“vehicle event”所表示的处理流程。
*
* <p>该方法属于 {@code Builder},用于保持当前模块的职责边界清晰。
* @param eventNumber 执行该处理所需的 event number 输入。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param type 执行该处理所需的 type 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Builder vehicleEvent(long eventNumber, String vehicleId, VehicleEventType type) {
if (eventNumber < 0 || vehicleId == null || vehicleId.trim().isEmpty() || type == null) {
throw new IllegalArgumentException("valid vehicle event is required");
@@ -84,6 +155,12 @@ public final class DeterministicFaultPlan {
return this;
}
/**
* 执行“build”所表示的处理流程。
*
* <p>该方法属于 {@code Builder},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public DeterministicFaultPlan build() {
Map<String, Map<Integer, SimulatedPlcGateway.PlcReason>> plc =
new LinkedHashMap<String, Map<Integer, SimulatedPlcGateway.PlcReason>>();

View File

@@ -7,8 +7,20 @@ import java.nio.file.Path;
import java.nio.file.Paths;
public final class HistoricalDispatchSimulationApplication {
/**
* 创建 {@code HistoricalDispatchSimulationApplication} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationApplication},用于保持当前模块的职责边界清晰。
*/
private HistoricalDispatchSimulationApplication() { }
/**
* 执行“main”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationApplication},用于保持当前模块的职责边界清晰。
* @param args 执行该处理所需的 args 输入。
* @throws Exception 当调用条件不满足或处理无法继续时抛出。
*/
public static void main(String[] args) throws Exception {
if (args.length < 1 || args.length > 2) {
throw new IllegalArgumentException(

View File

@@ -26,6 +26,16 @@ public final class HistoricalDispatchSimulationReportWriter {
private static final ObjectMapper MAPPER = new ObjectMapper()
.enable(SerializationFeature.INDENT_OUTPUT);
/**
* 输出可审计的历史任务仿真报告,包括摘要、逐任务结果、逐 tick 事件、不变量和校验清单。
*
* <p>报告显式声明 {@code path_info} 未用于规划,区分历史耗时和按加速倍率还原的仿真耗时,
* 并给出完成/等待/失败、重选车/重规划、HOLD/重试、归档与 WMS 幂等性证据。
* @param outputDir 执行该处理所需的 output dir 输入。
* @param dataset 执行该处理所需的 dataset 输入。
* @param result 执行该处理所需的 result 输入。
* @throws IOException 当调用条件不满足或处理无法继续时抛出。
*/
public void write(Path outputDir, HistoricalQueueDataset dataset,
HistoricalDispatchSimulationResult result) throws IOException {
if (outputDir == null || dataset == null || result == null) {
@@ -41,6 +51,12 @@ public final class HistoricalDispatchSimulationReportWriter {
"task-results.csv", "tick-events.csv"));
}
/**
* 汇总用户关心的调度结果、性能分位数、安全不变量及历史与仿真的耗时差异。
* @param dataset 执行该处理所需的 dataset 输入。
* @param result 执行该处理所需的 result 输入。
* @return 可序列化为 {@code summary.json} 的业务指标字典。
*/
private Map<String, Object> summary(HistoricalQueueDataset dataset,
HistoricalDispatchSimulationResult result) {
Map<String, Object> value = new LinkedHashMap<String, Object>();
@@ -88,6 +104,11 @@ public final class HistoricalDispatchSimulationReportWriter {
return value;
}
/**
* 计算等待、完成或历史耗时样本的平均值、P95 和 P99,空样本保持空统计值。
* @param samples 执行该处理所需的 samples 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private Map<String, Object> timeStats(List<Long> samples) {
SimulationMetrics metrics = new SimulationMetrics();
Map<String, Object> stats = new LinkedHashMap<String, Object>();
@@ -98,6 +119,13 @@ public final class HistoricalDispatchSimulationReportWriter {
return stats;
}
/**
* 执行“waiting samples”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationReportWriter},用于保持当前模块的职责边界清晰。
* @param result 执行该处理所需的 result 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private List<Long> waitingSamples(HistoricalDispatchSimulationResult result) {
List<Long> values = new ArrayList<Long>();
for (SimulationTaskResult task : result.getTaskResults()) {
@@ -106,6 +134,13 @@ public final class HistoricalDispatchSimulationReportWriter {
return values;
}
/**
* 执行“completion samples”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationReportWriter},用于保持当前模块的职责边界清晰。
* @param result 执行该处理所需的 result 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private List<Long> completionSamples(HistoricalDispatchSimulationResult result) {
List<Long> values = new ArrayList<Long>();
for (SimulationTaskResult task : result.getTaskResults()) {
@@ -114,6 +149,13 @@ public final class HistoricalDispatchSimulationReportWriter {
return values;
}
/**
* 执行“historical samples”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationReportWriter},用于保持当前模块的职责边界清晰。
* @param result 执行该处理所需的 result 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private List<Long> historicalSamples(HistoricalDispatchSimulationResult result) {
List<Long> values = new ArrayList<Long>();
for (SimulationTaskResult task : result.getTaskResults()) {
@@ -123,6 +165,11 @@ public final class HistoricalDispatchSimulationReportWriter {
return values;
}
/**
* 将完成耗时按加速倍率还原后与历史 {@code finish_date-create_date} 比较,形成差异样本。
* @param result 执行该处理所需的 result 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private List<Long> durationDifferenceSamples(HistoricalDispatchSimulationResult result) {
List<Long> values = new ArrayList<Long>();
for (SimulationTaskResult task : result.getTaskResults()) {
@@ -135,6 +182,12 @@ public final class HistoricalDispatchSimulationReportWriter {
return values;
}
/**
* 跨任务汇总 HOLD 或 PLC 重试原因,说明等待和重试分别由何种业务条件造成。
* @param result 执行该处理所需的 result 输入。
* @param hold 执行该处理所需的 hold 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private Map<String, Integer> aggregateReasons(HistoricalDispatchSimulationResult result,
boolean hold) {
Map<String, Integer> values = new LinkedHashMap<String, Integer>();
@@ -148,6 +201,13 @@ public final class HistoricalDispatchSimulationReportWriter {
return values;
}
/**
* 执行“failure reasons”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationReportWriter},用于保持当前模块的职责边界清晰。
* @param result 执行该处理所需的 result 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private Map<String, Integer> failureReasons(HistoricalDispatchSimulationResult result) {
Map<String, Integer> values = new LinkedHashMap<String, Integer>();
for (SimulationTaskResult task : result.getTaskResults()) {
@@ -158,6 +218,11 @@ public final class HistoricalDispatchSimulationReportWriter {
return values;
}
/**
* 导出资源双占、对向冲突、重复归档、重复 WMS 业务效果和死锁等安全断言统计。
* @param result 执行该处理所需的 result 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private Map<String, Object> invariantSummary(HistoricalDispatchSimulationResult result) {
SimulationInvariantSummary source = result.getInvariants();
Map<String, Object> values = new LinkedHashMap<String, Object>();
@@ -171,6 +236,12 @@ public final class HistoricalDispatchSimulationReportWriter {
return values;
}
/**
* 写出逐历史任务的业务字段、中心重选车辆/路径、状态、等待重试及历史耗时对照。
* @param path 执行该处理所需的 path 输入。
* @param result 执行该处理所需的 result 输入。
* @throws IOException 当调用条件不满足或处理无法继续时抛出。
*/
private void writeTaskCsv(Path path, HistoricalDispatchSimulationResult result)
throws IOException {
StringBuilder csv = new StringBuilder("\ufeff");
@@ -211,6 +282,12 @@ public final class HistoricalDispatchSimulationReportWriter {
Files.write(path, csv.toString().getBytes(StandardCharsets.UTF_8));
}
/**
* 写出逐 tick 的 ASSIGN、MOVE、HOLD、清障、PLC 重试和完成事件,支持还原调度过程。
* @param path 执行该处理所需的 path 输入。
* @param result 执行该处理所需的 result 输入。
* @throws IOException 当调用条件不满足或处理无法继续时抛出。
*/
private void writeEventCsv(Path path, HistoricalDispatchSimulationResult result)
throws IOException {
StringBuilder csv = new StringBuilder("\ufeff");
@@ -224,6 +301,13 @@ public final class HistoricalDispatchSimulationReportWriter {
Files.write(path, csv.toString().getBytes(StandardCharsets.UTF_8));
}
/**
* 执行“row”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationReportWriter},用于保持当前模块的职责边界清晰。
* @param target 执行该处理所需的 target 输入。
* @param values 执行该处理所需的 values 输入。
*/
private void row(StringBuilder target, Object... values) {
for (int i = 0; i < values.length; i++) {
if (i > 0) target.append(',');
@@ -232,6 +316,11 @@ public final class HistoricalDispatchSimulationReportWriter {
target.append("\r\n");
}
/**
* 按 RFC 风格转义 CSV 字段,防止路径、原因或历史字段中的逗号和引号破坏报表列。
* @param value 执行该处理所需的 value 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private String csv(Object value) {
if (value == null) return "";
String text = String.valueOf(value);
@@ -241,6 +330,11 @@ public final class HistoricalDispatchSimulationReportWriter {
return text;
}
/**
* 解析历史创建与完成时间作为对照指标;解析失败时返回空,绝不用于驱动本次任务完成。
* @param task 执行该处理所需的 task 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private Long historicalDuration(SimulationTaskResult task) {
try {
LocalDateTime created = LocalDateTime.parse(task.getRecord().getCreateDate(), TIME);
@@ -251,6 +345,12 @@ public final class HistoricalDispatchSimulationReportWriter {
}
}
/**
* 以稳定文件名排序写出 SHA-256 清单,保证报告内容可复核且交付文件未被静默修改。
* @param outputDir 执行该处理所需的 output dir 输入。
* @param names 执行该处理所需的 names 输入。
* @throws IOException 当调用条件不满足或处理无法继续时抛出。
*/
private void writeManifest(Path outputDir, List<String> names) throws IOException {
List<String> ordered = new ArrayList<String>(names);
Collections.sort(ordered);
@@ -263,6 +363,13 @@ public final class HistoricalDispatchSimulationReportWriter {
manifest.toString().getBytes(StandardCharsets.UTF_8));
}
/**
* 执行“sha256”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationReportWriter},用于保持当前模块的职责边界清晰。
* @param bytes 执行该处理所需的 bytes 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private String sha256(byte[] bytes) {
try {
byte[] digest = MessageDigest.getInstance("SHA-256").digest(bytes);
@@ -274,11 +381,25 @@ public final class HistoricalDispatchSimulationReportWriter {
}
}
/**
* 执行“trim trailing commas”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationReportWriter},用于保持当前模块的职责边界清晰。
* @param value 执行该处理所需的 value 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private String trimTrailingCommas(String value) {
int end = value.length();
while (end > 0 && value.charAt(end - 1) == ',') end--;
return value.substring(0, end);
}
/**
* 执行“text”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationReportWriter},用于保持当前模块的职责边界清晰。
* @param value 执行该处理所需的 value 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private String text(String value) { return value == null ? "" : value; }
}

View File

@@ -17,6 +17,19 @@ public final class HistoricalDispatchSimulationResult {
private final long tickCount;
private final int acceleration;
/**
* 创建 {@code HistoricalDispatchSimulationResult} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。
* @param taskResults 执行该处理所需的 task results 输入。
* @param events 执行该处理所需的 events 输入。
* @param invariants 执行该处理所需的 invariants 输入。
* @param archiveCount 执行该处理所需的 archive count 输入。
* @param wmsDeliveryAttempts 执行该处理所需的 wms delivery attempts 输入。
* @param wmsBusinessEffects 执行该处理所需的 wms business effects 输入。
* @param tickCount 执行该处理所需的 tick count 输入。
* @param acceleration 执行该处理所需的 acceleration 输入。
*/
HistoricalDispatchSimulationResult(List<SimulationTaskResult> taskResults,
List<SimulationTickEvent> events,
SimulationInvariantSummary invariants,
@@ -33,19 +46,91 @@ public final class HistoricalDispatchSimulationResult {
this.acceleration = acceleration;
}
/**
* 返回当前对象保存的“task results”信息。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<SimulationTaskResult> getTaskResults() { return taskResults; }
/**
* 返回当前对象保存的“events”信息。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<SimulationTickEvent> getEvents() { return events; }
/**
* 返回当前对象保存的“invariants”信息。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public SimulationInvariantSummary getInvariants() { return invariants; }
/**
* 返回当前对象保存的“archive count”信息。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getArchiveCount() { return archiveCount; }
/**
* 返回当前对象保存的“wms delivery attempts”信息。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getWmsDeliveryAttempts() { return wmsDeliveryAttempts; }
/**
* 返回当前对象保存的“wms business effects”信息。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getWmsBusinessEffects() { return wmsBusinessEffects; }
/**
* 返回当前对象保存的“tick count”信息。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getTickCount() { return tickCount; }
/**
* 返回当前对象保存的“acceleration”信息。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getAcceleration() { return acceleration; }
/**
* 返回当前对象保存的“completed count”信息。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getCompletedCount() { return count(SimulationTaskStatus.COMPLETED); }
/**
* 返回当前对象保存的“waiting count”信息。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getWaitingCount() { return count(SimulationTaskStatus.WAITING); }
/**
* 返回当前对象保存的“failed count”信息。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getFailedCount() { return count(SimulationTaskStatus.FAILED); }
/**
* 返回当前对象保存的“reassignment count”信息。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getReassignmentCount() {
int count = 0;
for (SimulationTaskResult result : taskResults) {
@@ -56,6 +141,12 @@ public final class HistoricalDispatchSimulationResult {
return count;
}
/**
* 返回当前对象保存的“replanned count”信息。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getReplannedCount() {
int count = 0;
for (SimulationTaskResult result : taskResults) {
@@ -68,12 +159,24 @@ public final class HistoricalDispatchSimulationResult {
return count;
}
/**
* 返回当前对象保存的“retry count”信息。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getRetryCount() {
int count = 0;
for (SimulationTaskResult result : taskResults) count += result.getRetryCount();
return count;
}
/**
* 执行“completed by vehicle”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Map<String, Integer> completedByVehicle() {
Map<String, Integer> counts = new LinkedHashMap<String, Integer>();
for (SimulationTaskResult result : taskResults) {
@@ -84,6 +187,12 @@ public final class HistoricalDispatchSimulationResult {
return Collections.unmodifiableMap(counts);
}
/**
* 判断当前上下文是否满足“canonical view”条件。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String canonicalView() {
List<SimulationTaskResult> ordered = new ArrayList<SimulationTaskResult>(taskResults);
Collections.sort(ordered, Comparator.comparing(SimulationTaskResult::getSimulationTaskId));
@@ -100,6 +209,13 @@ public final class HistoricalDispatchSimulationResult {
return value.toString();
}
/**
* 执行“count”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。
* @param status 执行该处理所需的 status 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private int count(SimulationTaskStatus status) {
int count = 0;
for (SimulationTaskResult result : taskResults) {
@@ -108,6 +224,13 @@ public final class HistoricalDispatchSimulationResult {
return count;
}
/**
* 执行“immutable”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。
* @param values 执行该处理所需的 values 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private static <T> List<T> immutable(List<T> values) {
return Collections.unmodifiableList(new ArrayList<T>(values));
}

View File

@@ -32,6 +32,19 @@ public final class HistoricalDispatchSimulator {
private static final long STEP_MILLIS = 1_000L;
private static final int HOLD_REDISPATCH_THRESHOLD = 10;
/**
* 按中心调度的完整业务链路回放历史任务,而不是复用历史车辆或 {@code path_info}。
*
* <p>先将 {@code create_date} 按配置倍率映射成仿真到达时间,再建立等待队列、车辆运行态、
* 资源台账、PLC、归档和 WMS 接收器。每个 tick 固定依次处理车辆故障、就绪任务选车与路径预约、
* 清障移动、活动任务逐边移动以及资源容量校验,因而同一输入总能得到可复现的调度结果。
* 历史任务号、类型、起终点和优先级作为业务输入;历史完成状态和完成时间不会推进任务。
* 无物理进展时由 watchdog 判死锁,超过 tick 上限时明确失败,避免把未运行的任务误报为完成。
* @param input 执行该处理所需的 input 输入。
* @param config 执行该处理所需的 config 输入。
* @param faults 执行该处理所需的 faults 输入。
* @return 包含任务终态、重选车辆和路径、HOLD/重试原因、资源不变量及归档/WMS统计的仿真结果。
*/
public HistoricalDispatchSimulationResult simulate(
HistoricalSimulationInput input, SimulationConfig config,
DeterministicFaultPlan faults) {
@@ -129,6 +142,13 @@ public final class HistoricalDispatchSimulator {
tick, config.getAcceleration());
}
/**
* 将输入快照转换为可变的车辆运行时状态,供本次调度独立地选车、移动和处理故障。
*
* <p>这一步只以初始车位和健康状态为起点;任务历史 {@code agv_id} 不参与强制绑定。
* @param input 执行该处理所需的 input 输入。
* @return 以车辆编号索引的运行时车队。
*/
private Map<String, SimulatedVehicleRuntime> createRuntimes(HistoricalSimulationInput input) {
Map<String, SimulatedVehicleRuntime> runtimes =
new LinkedHashMap<String, SimulatedVehicleRuntime>();
@@ -138,6 +158,14 @@ public final class HistoricalDispatchSimulator {
return runtimes;
}
/**
* 对初始车位执行容量检查,确保仿真从没有节点双占的交通状态开始。
*
* <p>若初始快照本身超过节点容量,只记录不变量违规;后续报告据此暴露输入数据问题。
* @param vehicles 执行该处理所需的 vehicles 输入。
* @param ledger 执行该处理所需的 ledger 输入。
* @param invariants 执行该处理所需的 invariants 输入。
*/
private void occupyInitialNodes(Map<String, SimulatedVehicleRuntime> vehicles,
ResourceLedger ledger,
SimulationInvariantSummary invariants) {
@@ -151,6 +179,23 @@ public final class HistoricalDispatchSimulator {
}
}
/**
* 在每个 tick 先施加断线、重启、低电量和车辆故障等确定性事件,并收回失效车辆正在承担的工作。
*
* <p>车辆失去可分配资格后,清障动作被暂停;正在执行的任务释放走廊预约、回到原到达时间的队列,
* 同时记录 HOLD 原因。这样恢复后的调度会重新选车和规划,而不会让故障车辆继续占用任务。
* @param tick 执行该处理所需的 tick 输入。
* @param now 执行该处理所需的 now 输入。
* @param faults 执行该处理所需的 faults 输入。
* @param vehicles 执行该处理所需的 vehicles 输入。
* @param active 执行该处理所需的 active 输入。
* @param clearanceMoves 执行该处理所需的 clearance moves 输入。
* @param queue 执行该处理所需的 queue 输入。
* @param executions 执行该处理所需的 executions 输入。
* @param reservations 执行该处理所需的 reservations 输入。
* @param events 执行该处理所需的 events 输入。
* @return 本 tick 是否发生车辆业务状态变化。
*/
private boolean applyVehicleEvents(long tick, long now, DeterministicFaultPlan faults,
Map<String, SimulatedVehicleRuntime> vehicles,
Map<String, ActiveTask> active,
@@ -198,6 +243,28 @@ public final class HistoricalDispatchSimulator {
return changed;
}
/**
* 为已到达的历史任务执行中心调度:重新规划服务路径、筛选可用车队、自动选车并申请走廊方向预约。
*
* <p>源到目标无路时直接关闭为 {@code NO_ROUTE};若车队中仍存在可能到达源点的车辆,任务继续等待。
* 选中的车先走接近路径再走服务路径,预约被相反方向任务占用时记录 HOLD 而不出队;只有预约成功才
* 创建活动任务并写入 ASSIGN 事件。因此历史 {@code agv_id} 与 {@code path_info} 仅用于报告对照。
* @param tick 执行该处理所需的 tick 输入。
* @param now 执行该处理所需的 now 输入。
* @param input 执行该处理所需的 input 输入。
* @param queue 执行该处理所需的 queue 输入。
* @param vehicles 执行该处理所需的 vehicles 输入。
* @param active 执行该处理所需的 active 输入。
* @param clearanceMoves 执行该处理所需的 clearance moves 输入。
* @param executions 执行该处理所需的 executions 输入。
* @param terminal 执行该处理所需的 terminal 输入。
* @param planner 执行该处理所需的 planner 输入。
* @param assignment 执行该处理所需的 assignment 输入。
* @param plc 执行该处理所需的 plc 输入。
* @param reservations 执行该处理所需的 reservations 输入。
* @param events 执行该处理所需的 events 输入。
* @return 本 tick 是否至少有一个任务被分配或因永久不可达关闭。
*/
private boolean assignReadyTasks(long tick, long now, HistoricalSimulationInput input,
SimulationTaskQueue queue,
Map<String, SimulatedVehicleRuntime> vehicles,
@@ -284,6 +351,16 @@ public final class HistoricalDispatchSimulator {
return progress;
}
/**
* 判断车队是否还有任意车辆能抵达任务源点,用于区分暂时等车和永久无路两种情况。
*
* <p>该检查不要求车辆当前健康可分配,因为断线或低电量车辆恢复后仍可能服务该任务。
* @param task 执行该处理所需的 task 输入。
* @param vehicles 执行该处理所需的 vehicles 输入。
* @param input 执行该处理所需的 input 输入。
* @param planner 执行该处理所需的 planner 输入。
* @return 存在通往源点的车队路径时返回 {@code true}。
*/
private boolean fleetCanReach(HistoricalSimulationTask task,
Map<String, SimulatedVehicleRuntime> vehicles,
HistoricalSimulationInput input,
@@ -295,6 +372,35 @@ public final class HistoricalDispatchSimulator {
return false;
}
/**
* 推进全部已分配任务的下一条边,并在移动前依次执行方向冲突、清障、交通决策、资源台账和 PLC 确认。
*
* <p>同 tick 的同向或对向边会产生 {@code OPPOSITE_EDGE_WINDOW} HOLD;目标被空闲车占用时先规划清障。
* ShadowTrafficCoordinator 是调度决策层,ResourceLedger 是最终资源权威,两者任一拒绝都不会移动。
* PLC 非 ACK 时释放本次边和目标节点、记录重试;达到次数上限则释放预约并回队重派。收到 ACK 后才移动车辆,
* 并逐段释放已离开的节点、边和走廊预约,到达终点后归档并触发幂等 WMS 回调。
* @param tick 执行该处理所需的 tick 输入。
* @param now 执行该处理所需的 now 输入。
* @param input 执行该处理所需的 input 输入。
* @param config 执行该处理所需的 config 输入。
* @param queue 执行该处理所需的 queue 输入。
* @param vehicles 执行该处理所需的 vehicles 输入。
* @param active 执行该处理所需的 active 输入。
* @param executions 执行该处理所需的 executions 输入。
* @param terminal 执行该处理所需的 terminal 输入。
* @param planner 执行该处理所需的 planner 输入。
* @param ledger 执行该处理所需的 ledger 输入。
* @param plc 执行该处理所需的 plc 输入。
* @param archive 执行该处理所需的 archive 输入。
* @param wms 执行该处理所需的 wms 输入。
* @param invariants 执行该处理所需的 invariants 输入。
* @param reservations 执行该处理所需的 reservations 输入。
* @param clearanceMoves 执行该处理所需的 clearance moves 输入。
* @param clearancePlanner 执行该处理所需的 clearance planner 输入。
* @param events 执行该处理所需的 events 输入。
* @param traversedEdges 执行该处理所需的 traversed edges 输入。
* @return 本 tick 是否有业务任务完成分配、移动或关闭。
*/
private boolean advanceActiveTasks(long tick, long now,
HistoricalSimulationInput input,
SimulationConfig config,
@@ -429,6 +535,24 @@ public final class HistoricalDispatchSimulator {
return progress;
}
/**
* 逐段执行为主任务让路的清障移动,并施加与正常任务相同的方向、交通、资源和 PLC 约束。
*
* <p>清障车不是特权车辆:对向窗口、决策拒绝、资源拒绝或 PLC 非 ACK 都只会记录
* {@code CLEARANCE_HOLD}/{@code CLEARANCE_PLC_RETRY},不会穿透已有占用。只有 ACK 后才更新车位并
* 释放已走过的资源;路线完成时删除清障动作,让主任务在后续 tick 重新裁决。
* @param tick 执行该处理所需的 tick 输入。
* @param now 执行该处理所需的 now 输入。
* @param input 执行该处理所需的 input 输入。
* @param config 执行该处理所需的 config 输入。
* @param vehicles 执行该处理所需的 vehicles 输入。
* @param clearanceMoves 执行该处理所需的 clearance moves 输入。
* @param ledger 执行该处理所需的 ledger 输入。
* @param plc 执行该处理所需的 plc 输入。
* @param events 执行该处理所需的 events 输入。
* @param traversedEdges 执行该处理所需的 traversed edges 输入。
* @return 清障移动和清障完成标记,供主循环的进展看门狗判断物理进展。
*/
private ClearanceProgress advanceClearanceMoves(long tick, long now,
HistoricalSimulationInput input,
SimulationConfig config,
@@ -519,6 +643,24 @@ public final class HistoricalDispatchSimulator {
return new ClearanceProgress(moved, completed);
}
/**
* 为阻塞主任务目标节点的空闲车挑选一条安全的临时让路路线。
*
* <p>仅处理健康、未执行任务、也未参与其他清障的车辆;规划器避开主任务剩余路径、已占节点和已预约资源。
* 规划成功立即登记清障动作并记录 {@code CLEARANCE_PLANNED},主任务本 tick 仍 HOLD,等待实际让路完成。
* @param tick 执行该处理所需的 tick 输入。
* @param now 执行该处理所需的 now 输入。
* @param owner 执行该处理所需的 owner 输入。
* @param vehicles 执行该处理所需的 vehicles 输入。
* @param active 执行该处理所需的 active 输入。
* @param clearanceMoves 执行该处理所需的 clearance moves 输入。
* @param clearancePlanner 执行该处理所需的 clearance planner 输入。
* @param ledger 执行该处理所需的 ledger 输入。
* @param input 执行该处理所需的 input 输入。
* @param blockingVehicleIds 执行该处理所需的 blocking vehicle ids 输入。
* @param events 执行该处理所需的 events 输入。
* @return 至少有一辆阻塞车获得清障路线时返回 {@code true}。
*/
private boolean planClearanceForIdleBlockers(
long tick, long now, ActiveTask owner,
Map<String, SimulatedVehicleRuntime> vehicles,
@@ -562,6 +704,15 @@ public final class HistoricalDispatchSimulator {
return false;
}
/**
* 找出占据指定目标节点且当前空闲的车辆,作为清障候选而非直接判定资源冲突。
* @param siteId 执行该处理所需的 site id 输入。
* @param movingVehicleId 执行该处理所需的 moving vehicle id 输入。
* @param vehicles 执行该处理所需的 vehicles 输入。
* @param active 执行该处理所需的 active 输入。
* @param clearanceMoves 执行该处理所需的 clearance moves 输入。
* @return 可由清障流程处理的阻塞车辆编号集合。
*/
private Set<String> idleVehiclesAt(String siteId, String movingVehicleId,
Map<String, SimulatedVehicleRuntime> vehicles,
Map<String, ActiveTask> active,
@@ -580,12 +731,35 @@ public final class HistoricalDispatchSimulator {
return blockers;
}
/**
* 按等待时长计算活动任务的有效优先级,使重复 HOLD 的低优先级任务不会永久饥饿。
*
* <p>数值越小优先级越高;每经过一个老化区间减一,最低为零,与等待队列的排序规则保持一致。
* @param execution 执行该处理所需的 execution 输入。
* @param now 执行该处理所需的 now 输入。
* @param config 执行该处理所需的 config 输入。
* @return 用于本 tick 交通裁决的有效优先级。
*/
private int queuePriority(Execution execution, long now, SimulationConfig config) {
long waited = Math.max(0L, now - execution.arrivalMillis);
return (int) Math.max(0L, (long) execution.task.getPriority()
- waited / config.getAgingIntervalMillis());
}
/**
* 记录一次不可移动原因,并在连续 HOLD 达阈值时撤销当前分配、释放走廊并回队重新调度。
*
* <p>重派保留原始到达时间和历史业务字段,但允许中心重新选择车辆和路径,避免单车长期占住任务。
* @param tick 执行该处理所需的 tick 输入。
* @param now 执行该处理所需的 now 输入。
* @param current 执行该处理所需的 current 输入。
* @param vehicle 执行该处理所需的 vehicle 输入。
* @param active 执行该处理所需的 active 输入。
* @param queue 执行该处理所需的 queue 输入。
* @param reason 执行该处理所需的 reason 输入。
* @param reservations 执行该处理所需的 reservations 输入。
* @param events 执行该处理所需的 events 输入。
*/
private void recordHold(long tick, long now, ActiveTask current,
SimulatedVehicleRuntime vehicle,
Map<String, ActiveTask> active,
@@ -606,6 +780,24 @@ public final class HistoricalDispatchSimulator {
}
}
/**
* 将已抵达终点的任务关闭为完成,并完成走廊释放、队列归档及幂等 WMS 完成回调。
*
* <p>同一任务故意向 WMS 投递两次,用于验证传输可能重复而业务效果只能生效一次;归档或业务效果重复
* 都会写入不变量统计。历史 {@code finish_date} 不参与此判定,完成时间只取本次仿真的 ACK 移动结果。
* @param tick 执行该处理所需的 tick 输入。
* @param now 执行该处理所需的 now 输入。
* @param activeTask 执行该处理所需的 active task 输入。
* @param vehicle 执行该处理所需的 vehicle 输入。
* @param active 执行该处理所需的 active 输入。
* @param terminal 执行该处理所需的 terminal 输入。
* @param plc 执行该处理所需的 plc 输入。
* @param archive 执行该处理所需的 archive 输入。
* @param wms 执行该处理所需的 wms 输入。
* @param invariants 执行该处理所需的 invariants 输入。
* @param reservations 执行该处理所需的 reservations 输入。
* @param events 执行该处理所需的 events 输入。
*/
private void complete(long tick, long now, ActiveTask activeTask,
SimulatedVehicleRuntime vehicle,
Map<String, ActiveTask> active,
@@ -631,6 +823,18 @@ public final class HistoricalDispatchSimulator {
"ARCHIVED_WMS_ACK", vehicle.getCurrentSite(), vehicle.getCurrentSite()));
}
/**
* 在异常收敛或报告截点将尚未关闭的排队、活动任务快照为等待状态。
*
* <p>该方法只生成可诊断的终态结果,不能把任务标为完成,也不会修改车辆位置或资源所有权。
* @param queue 执行该处理所需的 queue 输入。
* @param active 执行该处理所需的 active 输入。
* @param executions 执行该处理所需的 executions 输入。
* @param terminal 执行该处理所需的 terminal 输入。
* @param plc 执行该处理所需的 plc 输入。
* @param reason 执行该处理所需的 reason 输入。
* @param now 执行该处理所需的 now 输入。
*/
private void snapshotWaiting(SimulationTaskQueue queue,
Map<String, ActiveTask> active,
Map<String, Execution> executions,
@@ -652,6 +856,18 @@ public final class HistoricalDispatchSimulator {
}
}
/**
* 汇总一个任务在本次仿真中的调度轨迹和终态,用于历史对比及最终统计。
*
* <p>结果包含实际被中心选中的车辆、重新规划的服务路径、等待/HOLD 与 PLC 重试原因;完成时间仅在
* {@code COMPLETED} 时写入,以便与历史 {@code finish_date} 的耗时独立比较。
* @param execution 执行该处理所需的 execution 输入。
* @param status 执行该处理所需的 status 输入。
* @param reason 执行该处理所需的 reason 输入。
* @param plc 执行该处理所需的 plc 输入。
* @param now 执行该处理所需的 now 输入。
* @return 面向报告和断言的不可变任务结果。
*/
private SimulationTaskResult result(Execution execution, SimulationTaskStatus status,
String reason, SimulatedPlcGateway plc, long now) {
return new SimulationTaskResult(execution.task.getSimulationTaskId(),
@@ -664,6 +880,13 @@ public final class HistoricalDispatchSimulator {
execution.retryCount, execution.holdReasons, execution.retryReasons);
}
/**
* 校验资源台账没有超过节点或边的配置容量,并把双占问题记入仿真不变量。
*
* <p>台账是资源保护的权威记录;该校验不修改占用,只确保报告能揭示资源双占或容量越界。
* @param ledger 执行该处理所需的 ledger 输入。
* @param invariants 执行该处理所需的 invariants 输入。
*/
private void verifyLedger(ResourceLedger ledger, SimulationInvariantSummary invariants) {
for (Map.Entry<ResourceKey, Set<String>> entry : ledger.snapshotHolders().entrySet()) {
Integer capacity = ledger.getCapacities().get(entry.getKey());
@@ -676,20 +899,49 @@ public final class HistoricalDispatchSimulator {
}
}
/**
* 为任务累计一次 HOLD 及其业务原因,供老化重派和报告统计使用。
* @param execution 执行该处理所需的 execution 输入。
* @param reason 执行该处理所需的 reason 输入。
*/
private static void hold(Execution execution, String reason) {
execution.holdCount++;
increment(execution.holdReasons, reason);
}
/**
* 为 PLC 非 ACK 累计一次重试及协议原因,不移动任务进度。
* @param execution 执行该处理所需的 execution 输入。
* @param reason 执行该处理所需的 reason 输入。
*/
private static void retry(Execution execution, String reason) {
execution.retryCount++;
increment(execution.retryReasons, reason);
}
/**
* 执行“increment”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalDispatchSimulator},用于保持当前模块的职责边界清晰。
* @param values 执行该处理所需的 values 输入。
* @param key 执行该处理所需的 key 输入。
*/
private static void increment(Map<String, Integer> values, String key) {
values.put(key, values.containsKey(key) ? values.get(key) + 1 : 1);
}
/**
* 创建按 tick 记录的调度审计事件,供分析车辆选择、路径移动、HOLD 和重试链路。
* @param tick 执行该处理所需的 tick 输入。
* @param now 执行该处理所需的 now 输入。
* @param type 执行该处理所需的 type 输入。
* @param taskId 执行该处理所需的 task id 输入。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param reason 执行该处理所需的 reason 输入。
* @param from 执行该处理所需的 from 输入。
* @param to 执行该处理所需的 to 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private SimulationTickEvent event(long tick, long now, String type,
String taskId, String vehicleId, String reason,
String from, String to) {
@@ -710,6 +962,13 @@ public final class HistoricalDispatchSimulator {
private final Map<String, Integer> retryReasons =
new LinkedHashMap<String, Integer>();
/**
* 创建 {@code Execution} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code Execution},用于保持当前模块的职责边界清晰。
* @param task 执行该处理所需的 task 输入。
* @param arrivalMillis 执行该处理所需的 arrival millis 输入。
*/
private Execution(HistoricalSimulationTask task, long arrivalMillis) {
this.task = task;
this.arrivalMillis = arrivalMillis;
@@ -722,6 +981,13 @@ public final class HistoricalDispatchSimulator {
private int index;
private int holdStreak;
/**
* 创建 {@code ActiveTask} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code ActiveTask},用于保持当前模块的职责边界清晰。
* @param execution 执行该处理所需的 execution 输入。
* @param route 执行该处理所需的 route 输入。
*/
private ActiveTask(Execution execution, List<String> route) {
this.execution = execution;
this.route = Collections.unmodifiableList(new ArrayList<String>(route));
@@ -732,6 +998,13 @@ public final class HistoricalDispatchSimulator {
private final boolean moved;
private final boolean completed;
/**
* 创建 {@code ClearanceProgress} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code ClearanceProgress},用于保持当前模块的职责边界清晰。
* @param moved 执行该处理所需的 moved 输入。
* @param completed 执行该处理所需的 completed 输入。
*/
private ClearanceProgress(boolean moved, boolean completed) {
this.moved = moved;
this.completed = completed;

View File

@@ -17,6 +17,14 @@ import java.util.Map;
import java.util.Set;
public final class HistoricalGridMapCompiler {
/**
* 从完整历史地图编译可通行网格和交通资源图,而不是只截取历史 {@code path_info} 经过的节点。
*
* <p>仅值为 1 或 2 的单元可通行;站点编号与三维坐标必须唯一。编译器只连接相邻的右侧和上侧单元,
* 由无向连接形成完整路网,并计算连通分量供任务端点预检。重复、空站点或空地图会作为无效地图拒绝。
* @param cells 执行该处理所需的 cells 输入。
* @return 同时供路径规划和交通裁决使用的网格、资源图及连通性索引。
*/
public CompiledHistoricalMap compile(List<HistoricalMapCell> cells) {
if (cells == null || cells.isEmpty()) {
throw new IllegalArgumentException("full map cells are required");
@@ -61,6 +69,13 @@ public final class HistoricalGridMapCompiler {
return new CompiledHistoricalMap(gridMap, trafficMap, sites, components(gridMap));
}
/**
* 当相邻坐标确有可通行单元时,同时建立路径规划连接和资源裁决边定义。
* @param map 执行该处理所需的 map 输入。
* @param trafficEdges 执行该处理所需的 traffic edges 输入。
* @param left 执行该处理所需的 left 输入。
* @param right 执行该处理所需的 right 输入。
*/
private void connectIfPresent(GridMap map,
Set<TrafficMapCompiler.EdgeDefinition> trafficEdges,
HistoricalMapCell left, HistoricalMapCell right) {
@@ -70,6 +85,11 @@ public final class HistoricalGridMapCompiler {
left.getSiteId(), right.getSiteId()));
}
/**
* 使用广度优先遍历为可通行站点编号连通分量,提前识别跨断开地图的无路任务。
* @param map 执行该处理所需的 map 输入。
* @return 站点到连通分量编号的稳定映射。
*/
private Map<String, Integer> components(GridMap map) {
Map<String, Integer> result = new LinkedHashMap<String, Integer>();
List<String> ids = new ArrayList<String>(map.getSites().keySet());
@@ -94,6 +114,13 @@ public final class HistoricalGridMapCompiler {
return result;
}
/**
* 生成三维坐标唯一键,用于发现地图单元重叠并定位相邻格。
* @param x 执行该处理所需的 x 输入。
* @param y 执行该处理所需的 y 输入。
* @param z 执行该处理所需的 z 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private static String coordinate(int x, int y, int z) {
return x + "," + y + "," + z;
}
@@ -104,6 +131,15 @@ public final class HistoricalGridMapCompiler {
private final Map<String, HistoricalMapCell> passableSites;
private final Map<String, Integer> componentIds;
/**
* 创建 {@code CompiledHistoricalMap} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code CompiledHistoricalMap},用于保持当前模块的职责边界清晰。
* @param gridMap 执行该处理所需的 grid map 输入。
* @param trafficMap 执行该处理所需的 traffic map 输入。
* @param passableSites 执行该处理所需的 passable sites 输入。
* @param componentIds 执行该处理所需的 component ids 输入。
*/
private CompiledHistoricalMap(GridMap gridMap, EffectiveTrafficMap trafficMap,
Map<String, HistoricalMapCell> passableSites,
Map<String, Integer> componentIds) {
@@ -115,10 +151,35 @@ public final class HistoricalGridMapCompiler {
new LinkedHashMap<String, Integer>(componentIds));
}
/**
* 返回当前对象保存的“grid map”信息。
*
* <p>该方法属于 {@code CompiledHistoricalMap},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public GridMap getGridMap() { return gridMap; }
/**
* 返回当前对象保存的“traffic map”信息。
*
* <p>该方法属于 {@code CompiledHistoricalMap},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public EffectiveTrafficMap getTrafficMap() { return trafficMap; }
/**
* 返回当前对象保存的“passable sites”信息。
*
* <p>该方法属于 {@code CompiledHistoricalMap},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Map<String, HistoricalMapCell> getPassableSites() { return passableSites; }
/**
* 返回当前对象保存的“component id”信息。
*
* <p>该方法属于 {@code CompiledHistoricalMap},用于保持当前模块的职责边界清晰。
* @param siteId 执行该处理所需的 site id 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getComponentId(String siteId) {
Integer component = componentIds.get(siteId);
if (component == null) throw new IllegalArgumentException("unknown passable site " + siteId);

View File

@@ -7,6 +7,14 @@ public final class HistoricalSimulationFailure {
private final HistoricalQueueRecord record;
private final String reason;
/**
* 创建 {@code HistoricalSimulationFailure} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code HistoricalSimulationFailure},用于保持当前模块的职责边界清晰。
* @param simulationTaskId 执行该处理所需的 simulation task id 输入。
* @param record 执行该处理所需的 record 输入。
* @param reason 执行该处理所需的 reason 输入。
*/
HistoricalSimulationFailure(String simulationTaskId, HistoricalQueueRecord record,
String reason) {
this.simulationTaskId = simulationTaskId;
@@ -14,7 +22,25 @@ public final class HistoricalSimulationFailure {
this.reason = reason;
}
/**
* 返回当前对象保存的“simulation task id”信息。
*
* <p>该方法属于 {@code HistoricalSimulationFailure},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getSimulationTaskId() { return simulationTaskId; }
/**
* 返回当前对象保存的“record”信息。
*
* <p>该方法属于 {@code HistoricalSimulationFailure},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public HistoricalQueueRecord getRecord() { return record; }
/**
* 返回当前对象保存的“reason”信息。
*
* <p>该方法属于 {@code HistoricalSimulationFailure},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getReason() { return reason; }
}

View File

@@ -15,6 +15,16 @@ public final class HistoricalSimulationInput {
private final EffectiveTrafficMap trafficMap;
private final List<VehicleSnapshot> initialVehicles;
/**
* 创建 {@code HistoricalSimulationInput} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code HistoricalSimulationInput},用于保持当前模块的职责边界清晰。
* @param tasks 执行该处理所需的 tasks 输入。
* @param failedInputs 执行该处理所需的 failed inputs 输入。
* @param gridMap 执行该处理所需的 grid map 输入。
* @param trafficMap 执行该处理所需的 traffic map 输入。
* @param initialVehicles 执行该处理所需的 initial vehicles 输入。
*/
HistoricalSimulationInput(List<HistoricalSimulationTask> tasks,
List<HistoricalSimulationFailure> failedInputs,
GridMap gridMap, EffectiveTrafficMap trafficMap,
@@ -26,12 +36,48 @@ public final class HistoricalSimulationInput {
this.initialVehicles = immutable(initialVehicles);
}
/**
* 返回当前对象保存的“tasks”信息。
*
* <p>该方法属于 {@code HistoricalSimulationInput},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<HistoricalSimulationTask> getTasks() { return tasks; }
/**
* 返回当前对象保存的“failed inputs”信息。
*
* <p>该方法属于 {@code HistoricalSimulationInput},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<HistoricalSimulationFailure> getFailedInputs() { return failedInputs; }
/**
* 返回当前对象保存的“grid map”信息。
*
* <p>该方法属于 {@code HistoricalSimulationInput},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public GridMap getGridMap() { return gridMap; }
/**
* 返回当前对象保存的“traffic map”信息。
*
* <p>该方法属于 {@code HistoricalSimulationInput},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public EffectiveTrafficMap getTrafficMap() { return trafficMap; }
/**
* 返回当前对象保存的“initial vehicles”信息。
*
* <p>该方法属于 {@code HistoricalSimulationInput},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<VehicleSnapshot> getInitialVehicles() { return initialVehicles; }
/**
* 执行“all simulation ids”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalSimulationInput},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<String> allSimulationIds() {
List<String> ids = new ArrayList<String>();
for (HistoricalSimulationTask task : tasks) ids.add(task.getSimulationTaskId());
@@ -41,6 +87,13 @@ public final class HistoricalSimulationInput {
return Collections.unmodifiableList(ids);
}
/**
* 执行“immutable”所表示的处理流程。
*
* <p>该方法属于 {@code HistoricalSimulationInput},用于保持当前模块的职责边界清晰。
* @param source 执行该处理所需的 source 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private static <T> List<T> immutable(List<T> source) {
return Collections.unmodifiableList(new ArrayList<T>(source));
}

View File

@@ -13,6 +13,15 @@ import java.util.Comparator;
import java.util.List;
public final class HistoricalSimulationInputFactory {
/**
* 将历史队列和完整地图转换为中心调度可直接执行的仿真输入。
*
* <p>历史记录先规范化并按 {@code create_date/task_no/guid} 稳定排序;再由完整地图解析物理端点和连通性。
* 任务号、类型、起终点、优先级保留为业务输入,历史路径只保留作对照;非法任务类型形成
* {@code INVALID_TASK_TYPE} 失败输入,不会被当作已经完成。最后初始化三层车队起点,供调度中心重新选车。
* @param dataset 执行该处理所需的 dataset 输入。
* @return 包含可调度任务、输入失败、完整交通图和初始车队的仿真输入。
*/
public HistoricalSimulationInput create(HistoricalQueueDataset dataset) {
if (dataset == null) throw new IllegalArgumentException("dataset is required");
HistoricalQueueNormalizer normalizer = new HistoricalQueueNormalizer();
@@ -58,6 +67,11 @@ public final class HistoricalSimulationInputFactory {
compiled.getTrafficMap(), vehicles);
}
/**
* 为一至三层建立固定的初始模拟车队,并验证每层出车点在完整地图上真实存在。
* @param compiled 执行该处理所需的 compiled 输入。
* @return 可供中心调度重新选择的三台初始车辆快照。
*/
private List<VehicleSnapshot> initialVehicles(
HistoricalGridMapCompiler.CompiledHistoricalMap compiled) {
List<VehicleSnapshot> vehicles = new ArrayList<VehicleSnapshot>();
@@ -74,6 +88,11 @@ public final class HistoricalSimulationInputFactory {
return vehicles;
}
/**
* 将历史任务类型编码映射为调度中心识别的入库、出库或移位业务类型。
* @param value 执行该处理所需的 value 输入。
* @return 已识别的业务类型;未知编码返回 {@code null} 以生成输入失败。
*/
private DispatchTask.TaskType taskType(String value) {
if ("1".equals(value)) return DispatchTask.TaskType.INBOUND;
if ("2".equals(value)) return DispatchTask.TaskType.OUTBOUND;
@@ -81,9 +100,20 @@ public final class HistoricalSimulationInputFactory {
return null;
}
/**
* 用历史任务号、GUID 和稳定序号构造仿真唯一标识,避免重复业务号覆盖不同历史记录。
* @param record 执行该处理所需的 record 输入。
* @param stableSequence 执行该处理所需的 stable sequence 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private String simulationId(HistoricalQueueRecord record, int stableSequence) {
return text(record.getTaskNo()) + "@" + text(record.getGuid()) + "#" + stableSequence;
}
/**
* 将可空历史字段规范成可参与排序和拼接的空文本,保证输入排序和 ID 构造稳定。
* @param value 执行该处理所需的 value 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private static String text(String value) { return value == null ? "" : value; }
}

View File

@@ -20,6 +20,21 @@ public final class HistoricalSimulationTask {
private final List<String> historicalNodes;
private final int arrivalSequence;
/**
* 创建 {@code HistoricalSimulationTask} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code HistoricalSimulationTask},用于保持当前模块的职责边界清晰。
* @param simulationTaskId 执行该处理所需的 simulation task id 输入。
* @param record 执行该处理所需的 record 输入。
* @param taskType 执行该处理所需的 task type 输入。
* @param priority 执行该处理所需的 priority 输入。
* @param createdAt 执行该处理所需的 created at 输入。
* @param historicalFinishedAt 执行该处理所需的 historical finished at 输入。
* @param physicalSource 执行该处理所需的 physical source 输入。
* @param physicalTarget 执行该处理所需的 physical target 输入。
* @param historicalNodes 执行该处理所需的 historical nodes 输入。
* @param arrivalSequence 执行该处理所需的 arrival sequence 输入。
*/
HistoricalSimulationTask(String simulationTaskId, HistoricalQueueRecord record,
DispatchTask.TaskType taskType, int priority,
LocalDateTime createdAt, LocalDateTime historicalFinishedAt,
@@ -38,14 +53,74 @@ public final class HistoricalSimulationTask {
this.arrivalSequence = arrivalSequence;
}
/**
* 返回当前对象保存的“simulation task id”信息。
*
* <p>该方法属于 {@code HistoricalSimulationTask},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getSimulationTaskId() { return simulationTaskId; }
/**
* 返回当前对象保存的“record”信息。
*
* <p>该方法属于 {@code HistoricalSimulationTask},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public HistoricalQueueRecord getRecord() { return record; }
/**
* 返回当前对象保存的“task type”信息。
*
* <p>该方法属于 {@code HistoricalSimulationTask},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public DispatchTask.TaskType getTaskType() { return taskType; }
/**
* 返回当前对象保存的“priority”信息。
*
* <p>该方法属于 {@code HistoricalSimulationTask},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getPriority() { return priority; }
/**
* 返回当前对象保存的“created at”信息。
*
* <p>该方法属于 {@code HistoricalSimulationTask},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public LocalDateTime getCreatedAt() { return createdAt; }
/**
* 返回当前对象保存的“historical finished at”信息。
*
* <p>该方法属于 {@code HistoricalSimulationTask},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public LocalDateTime getHistoricalFinishedAt() { return historicalFinishedAt; }
/**
* 返回当前对象保存的“physical source”信息。
*
* <p>该方法属于 {@code HistoricalSimulationTask},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getPhysicalSource() { return physicalSource; }
/**
* 返回当前对象保存的“physical target”信息。
*
* <p>该方法属于 {@code HistoricalSimulationTask},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getPhysicalTarget() { return physicalTarget; }
/**
* 返回当前对象保存的“historical nodes”信息。
*
* <p>该方法属于 {@code HistoricalSimulationTask},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<String> getHistoricalNodes() { return historicalNodes; }
/**
* 返回当前对象保存的“arrival sequence”信息。
*
* <p>该方法属于 {@code HistoricalSimulationTask},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getArrivalSequence() { return arrivalSequence; }
}

View File

@@ -8,6 +8,13 @@ public final class IdempotentWmsCompletionReceiver {
private final Set<String> completedTaskIds = new LinkedHashSet<String>();
private int deliveryAttempts;
/**
* 接收一次 WMS 完成回调,记录投递次数但只允许每个任务产生一次完成业务效果。
*
* <p>模拟器会刻意重复投递以验证幂等性,因此“收到两次”是可预期传输行为,不等于重复归档或重复完成。
* @param taskId 执行该处理所需的 task id 输入。
* @return 首次产生业务效果时返回 {@code true};重复回调返回 {@code false}。
*/
public boolean receive(String taskId) {
if (taskId == null || taskId.trim().isEmpty()) {
throw new IllegalArgumentException("task id is required");
@@ -16,8 +23,26 @@ public final class IdempotentWmsCompletionReceiver {
return completedTaskIds.add(taskId);
}
/**
* 返回当前对象保存的“delivery attempts”信息。
*
* <p>该方法属于 {@code IdempotentWmsCompletionReceiver},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getDeliveryAttempts() { return deliveryAttempts; }
/**
* 返回当前对象保存的“business effects”信息。
*
* <p>该方法属于 {@code IdempotentWmsCompletionReceiver},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getBusinessEffects() { return completedTaskIds.size(); }
/**
* 返回当前对象保存的“completed task ids”信息。
*
* <p>该方法属于 {@code IdempotentWmsCompletionReceiver},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Set<String> getCompletedTaskIds() {
return Collections.unmodifiableSet(completedTaskIds);
}

View File

@@ -6,6 +6,15 @@ import com.ft546.wcs.shadow.history.HistoricalQueueRecord;
import java.util.Map;
public final class PhysicalEndpointResolver {
/**
* 将历史记录中的逻辑起终点解析成完整地图中的实际可通行站点。
*
* <p>源点所在 z 坐标决定物理楼层;历史 {@code floor} 只作为一致性诊断。终点写为 {@code tsj} 时按该
* 物理楼层映射到 {@code 07050<floor>}。未知源点或目标点直接关闭输入,避免调度器对不存在的地图节点规划。
* @param record 执行该处理所需的 record 输入。
* @param passableSites 执行该处理所需的 passable sites 输入。
* @return 物理起终点、解析楼层以及历史楼层字段的一致性标记。
*/
public ResolvedEndpoints resolve(HistoricalQueueRecord record,
Map<String, HistoricalMapCell> passableSites) {
if (record == null || passableSites == null) {
@@ -40,6 +49,15 @@ public final class PhysicalEndpointResolver {
private final int floor;
private final boolean declaredFloorConsistent;
/**
* 创建 {@code ResolvedEndpoints} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code ResolvedEndpoints},用于保持当前模块的职责边界清晰。
* @param source 执行该处理所需的 source 输入。
* @param target 执行该处理所需的 target 输入。
* @param floor 执行该处理所需的 floor 输入。
* @param declaredFloorConsistent 执行该处理所需的 declared floor consistent 输入。
*/
private ResolvedEndpoints(String source, String target, int floor,
boolean declaredFloorConsistent) {
this.source = source;
@@ -48,9 +66,33 @@ public final class PhysicalEndpointResolver {
this.declaredFloorConsistent = declaredFloorConsistent;
}
/**
* 返回当前对象保存的“source”信息。
*
* <p>该方法属于 {@code ResolvedEndpoints},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getSource() { return source; }
/**
* 返回当前对象保存的“target”信息。
*
* <p>该方法属于 {@code ResolvedEndpoints},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getTarget() { return target; }
/**
* 返回当前对象保存的“floor”信息。
*
* <p>该方法属于 {@code ResolvedEndpoints},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getFloor() { return floor; }
/**
* 判断当前上下文是否满足“is declared floor consistent”条件。
*
* <p>该方法属于 {@code ResolvedEndpoints},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isDeclaredFloorConsistent() { return declaredFloorConsistent; }
}
}

View File

@@ -18,6 +18,18 @@ public final class SimulatedPlcGateway {
private final long bootId;
private final PlcReason reason;
/**
* 创建 {@code PlcResponse} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code PlcResponse},用于保持当前模块的职责边界清晰。
* @param taskId 执行该处理所需的 task id 输入。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param from 执行该处理所需的 from 输入。
* @param to 执行该处理所需的 to 输入。
* @param attempt 执行该处理所需的 attempt 输入。
* @param bootId 执行该处理所需的 boot id 输入。
* @param reason 执行该处理所需的 reason 输入。
*/
private PlcResponse(String taskId, String vehicleId, String from, String to,
int attempt, long bootId, PlcReason reason) {
this.taskId = taskId;
@@ -29,23 +41,79 @@ public final class SimulatedPlcGateway {
this.reason = reason;
}
/**
* 返回当前对象保存的“task id”信息。
*
* <p>该方法属于 {@code PlcResponse},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getTaskId() { return taskId; }
/**
* 返回当前对象保存的“vehicle id”信息。
*
* <p>该方法属于 {@code PlcResponse},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getVehicleId() { return vehicleId; }
/**
* 返回当前对象保存的“from”信息。
*
* <p>该方法属于 {@code PlcResponse},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getFrom() { return from; }
/**
* 返回当前对象保存的“to”信息。
*
* <p>该方法属于 {@code PlcResponse},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getTo() { return to; }
/**
* 返回当前对象保存的“attempt”信息。
*
* <p>该方法属于 {@code PlcResponse},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getAttempt() { return attempt; }
/**
* 返回当前对象保存的“boot id”信息。
*
* <p>该方法属于 {@code PlcResponse},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getBootId() { return bootId; }
/**
* 返回当前对象保存的“reason”信息。
*
* <p>该方法属于 {@code PlcResponse},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public PlcReason getReason() { return reason; }
}
private final DeterministicFaultPlan faults;
private final Map<String, Integer> attempts = new LinkedHashMap<String, Integer>();
/**
* 创建 PLC 协议模拟器,并绑定确定性故障计划以便重复测试发送、超时和丢 ACK 场景。
* @param faults 执行该处理所需的 faults 输入。
*/
public SimulatedPlcGateway(DeterministicFaultPlan faults) {
if (faults == null) throw new IllegalArgumentException("fault plan is required");
this.faults = faults;
}
/**
* 模拟向 PLC 下发一条车辆移动命令,并按任务累计发送次数返回计划中的协议结果。
*
* <p>默认结果是 ACK;响应携带当前车辆 bootId,使重启后的旧确认不会被错误用于推进当前位置。
* @param taskId 执行该处理所需的 task id 输入。
* @param vehicle 执行该处理所需的 vehicle 输入。
* @param from 执行该处理所需的 from 输入。
* @param to 执行该处理所需的 to 输入。
* @return 含尝试次数、车辆启动代次和 ACK/失败原因的模拟 PLC 响应。
*/
public PlcResponse send(String taskId, SimulatedVehicleRuntime vehicle,
String from, String to) {
int attempt = attempts.containsKey(taskId) ? attempts.get(taskId) + 1 : 1;
@@ -56,6 +124,12 @@ public final class SimulatedPlcGateway {
attempt, vehicle.getBootId(), reason);
}
/**
* 校验 PLC 响应是否仍属于当前车辆实例,拒绝重启前滞留的 ACK。
* @param response 执行该处理所需的 response 输入。
* @param vehicle 执行该处理所需的 vehicle 输入。
* @return 原失败响应,或将过期 ACK 改写为 {@code STALE_BOOT_ID} 后的响应。
*/
public PlcResponse accept(PlcResponse response, SimulatedVehicleRuntime vehicle) {
if (response.getReason() != PlcReason.ACK) return response;
if (response.getBootId() != vehicle.getBootId()) {
@@ -66,11 +140,22 @@ public final class SimulatedPlcGateway {
return response;
}
/**
* 查询任务累计发送 PLC 指令的次数,用于重试上限判断和结果报告。
* @param taskId 执行该处理所需的 task id 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int attemptsFor(String taskId) {
Integer value = attempts.get(taskId);
return value == null ? 0 : value;
}
/**
* 返回当前对象保存的“attempts”信息。
*
* <p>该方法属于 {@code SimulatedPlcGateway},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Map<String, Integer> getAttempts() {
return Collections.unmodifiableMap(attempts);
}

View File

@@ -12,6 +12,14 @@ public final class SimulatedVehicleRuntime {
private boolean synchronizedAfterBoot = true;
private long bootId = 1L;
/**
* 创建 {@code SimulatedVehicleRuntime} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code SimulatedVehicleRuntime},用于保持当前模块的职责边界清晰。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param currentSite 执行该处理所需的 current site 输入。
* @param floor 执行该处理所需的 floor 输入。
*/
public SimulatedVehicleRuntime(String vehicleId, String currentSite, int floor) {
if (vehicleId == null || vehicleId.trim().isEmpty()
|| currentSite == null || currentSite.trim().isEmpty() || floor <= 0) {
@@ -22,6 +30,11 @@ public final class SimulatedVehicleRuntime {
this.floor = floor;
}
/**
* 由调度快照恢复车辆可变运行态,作为本次仿真的独立车队初值。
* @param snapshot 执行该处理所需的 snapshot 输入。
* @return 可响应故障、PLC ACK 和逐节点移动的车辆运行时对象。
*/
public static SimulatedVehicleRuntime from(VehicleSnapshot snapshot) {
SimulatedVehicleRuntime runtime = new SimulatedVehicleRuntime(
snapshot.getVehicleId(), snapshot.getCurrentSite(), snapshot.getFloor());
@@ -30,22 +43,38 @@ public final class SimulatedVehicleRuntime {
return runtime;
}
/**
* 判断车辆是否可被中心调度分配:必须在线、无故障、重启后已同步且电量高于 30%。
* @return 满足全部派车前提时返回 {@code true}。
*/
public boolean isAssignmentEligible() {
return connected && !faulted && synchronizedAfterBoot && battery > 30;
}
/** 将车辆切换为断线状态,使调度器暂停其任务并等待重连。 */
public void disconnect() { connected = false; }
/** 将车辆标记为已重连;是否可派车仍取决于故障、同步和电量。 */
public void connect() { connected = true; }
/** 标记车辆故障,使其退出新的任务分配和清障候选。 */
public void fail() { faulted = true; }
/** 清除车辆故障标记;其余派车前提由当前运行态继续约束。 */
public void recover() { faulted = false; }
/**
* 模拟车辆重启并提升 bootId,强制等待同步以隔离重启前的 PLC 确认。
*/
public void restart() {
bootId++;
synchronizedAfterBoot = false;
}
/** 重启后的状态同步完成后,恢复车辆满足派车条件的可能性。 */
public void synchronizeAfterRestart() { synchronizedAfterBoot = true; }
/**
* 更新模拟电量;低至 30% 或以下时中心调度不再选择该车。
* @param battery 执行该处理所需的 battery 输入。
*/
public void setBattery(int battery) {
if (battery < 0 || battery > 100) {
throw new IllegalArgumentException("battery must be between 0 and 100");
@@ -53,6 +82,11 @@ public final class SimulatedVehicleRuntime {
this.battery = battery;
}
/**
* 在 PLC ACK 后提交车辆的真实仿真位置,表示该节点已实际到达而非仅完成路径规划。
* @param site 执行该处理所需的 site 输入。
* @param newFloor 执行该处理所需的 new floor 输入。
*/
public void moveTo(String site, int newFloor) {
if (site == null || site.trim().isEmpty() || newFloor <= 0) {
throw new IllegalArgumentException("valid destination is required");
@@ -61,18 +95,70 @@ public final class SimulatedVehicleRuntime {
floor = newFloor;
}
/**
* 生成当前运行态的只读快照,供选车服务在不直接修改车辆的前提下比较候选车。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public VehicleSnapshot snapshot() {
return new VehicleSnapshot(vehicleId, floor, currentSite, 5,
faulted ? 0 : 1, battery, connected,
connected && !faulted && synchronizedAfterBoot, false);
}
/**
* 返回当前对象保存的“vehicle id”信息。
*
* <p>该方法属于 {@code SimulatedVehicleRuntime},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getVehicleId() { return vehicleId; }
/**
* 返回当前对象保存的“current site”信息。
*
* <p>该方法属于 {@code SimulatedVehicleRuntime},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getCurrentSite() { return currentSite; }
/**
* 返回当前对象保存的“floor”信息。
*
* <p>该方法属于 {@code SimulatedVehicleRuntime},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getFloor() { return floor; }
/**
* 返回当前对象保存的“battery”信息。
*
* <p>该方法属于 {@code SimulatedVehicleRuntime},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getBattery() { return battery; }
/**
* 返回当前对象保存的“boot id”信息。
*
* <p>该方法属于 {@code SimulatedVehicleRuntime},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getBootId() { return bootId; }
/**
* 判断当前上下文是否满足“is connected”条件。
*
* <p>该方法属于 {@code SimulatedVehicleRuntime},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isConnected() { return connected; }
/**
* 判断当前上下文是否满足“is faulted”条件。
*
* <p>该方法属于 {@code SimulatedVehicleRuntime},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isFaulted() { return faulted; }
/**
* 判断当前上下文是否满足“is synchronized after boot”条件。
*
* <p>该方法属于 {@code SimulatedVehicleRuntime},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isSynchronizedAfterBoot() { return synchronizedAfterBoot; }
}

View File

@@ -10,27 +10,74 @@ public final class SimulationArchive {
private final String vehicleId;
private final long completedAtMillis;
/**
* 创建 {@code ArchiveRecord} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code ArchiveRecord},用于保持当前模块的职责边界清晰。
* @param taskId 执行该处理所需的 task id 输入。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param completedAtMillis 执行该处理所需的 completed at millis 输入。
*/
private ArchiveRecord(String taskId, String vehicleId, long completedAtMillis) {
this.taskId = taskId;
this.vehicleId = vehicleId;
this.completedAtMillis = completedAtMillis;
}
/**
* 返回当前对象保存的“task id”信息。
*
* <p>该方法属于 {@code ArchiveRecord},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getTaskId() { return taskId; }
/**
* 返回当前对象保存的“vehicle id”信息。
*
* <p>该方法属于 {@code ArchiveRecord},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getVehicleId() { return vehicleId; }
/**
* 返回当前对象保存的“completed at millis”信息。
*
* <p>该方法属于 {@code ArchiveRecord},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getCompletedAtMillis() { return completedAtMillis; }
}
private final Map<String, ArchiveRecord> records =
new LinkedHashMap<String, ArchiveRecord>();
/**
* 将已实际完成的任务写入队列归档;同一任务只能归档一次。
*
* <p>返回值让调用方将重复归档尝试记入不变量,而不是覆盖原来的完成车辆和完成时刻。
* @param taskId 执行该处理所需的 task id 输入。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param completedAtMillis 执行该处理所需的 completed at millis 输入。
* @return 首次归档返回 {@code true};任务已存在时返回 {@code false}。
*/
public boolean complete(String taskId, String vehicleId, long completedAtMillis) {
if (records.containsKey(taskId)) return false;
records.put(taskId, new ArchiveRecord(taskId, vehicleId, completedAtMillis));
return true;
}
/**
* 执行“size”所表示的处理流程。
*
* <p>该方法属于 {@code SimulationArchive},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int size() { return records.size(); }
/**
* 返回当前对象保存的“records”信息。
*
* <p>该方法属于 {@code SimulationArchive},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Map<String, ArchiveRecord> getRecords() {
return Collections.unmodifiableMap(records);
}

View File

@@ -13,6 +13,13 @@ public final class SimulationClock {
private final int acceleration;
private final Map<LocalDateTime, Long> arrivals;
/**
* 将历史 {@code create_date} 序列映射为加速后的仿真时钟,保留任务先后关系但压缩等待间隔。
*
* <p>仅允许 10 倍或 100 倍;最早任务映射到零时刻,后续任务相对最早时间的间隔按倍率缩短。
* @param sourceArrivals 执行该处理所需的 source arrivals 输入。
* @param acceleration 执行该处理所需的 acceleration 输入。
*/
public SimulationClock(List<LocalDateTime> sourceArrivals, int acceleration) {
if (acceleration != 10 && acceleration != 100) {
throw new IllegalArgumentException("acceleration must be 10 or 100");
@@ -35,15 +42,31 @@ public final class SimulationClock {
this.arrivals = Collections.unmodifiableMap(converted);
}
/**
* 查询一条已接纳历史到达时间对应的仿真时刻,控制任务何时进入调度队列。
* @param sourceArrival 执行该处理所需的 source arrival 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long toSimulationMillis(LocalDateTime sourceArrival) {
Long value = arrivals.get(sourceArrival);
if (value == null) throw new IllegalArgumentException("unknown source arrival");
return value;
}
/**
* 将加速后的耗时还原为历史时间尺度,供历史完成耗时与仿真耗时比较。
* @param simulationDurationMillis 执行该处理所需的 simulation duration millis 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long sourceDurationMillis(long simulationDurationMillis) {
return Math.multiplyExact(simulationDurationMillis, acceleration);
}
/**
* 返回当前对象保存的“acceleration”信息。
*
* <p>该方法属于 {@code SimulationClock},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getAcceleration() { return acceleration; }
}

View File

@@ -7,6 +7,16 @@ public final class SimulationConfig {
private final int noProgressLimit;
private final int tickLimit;
/**
* 创建 {@code SimulationConfig} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code SimulationConfig},用于保持当前模块的职责边界清晰。
* @param acceleration 执行该处理所需的 acceleration 输入。
* @param agingIntervalMillis 执行该处理所需的 aging interval millis 输入。
* @param retryLimit 执行该处理所需的 retry limit 输入。
* @param noProgressLimit 执行该处理所需的 no progress limit 输入。
* @param tickLimit 执行该处理所需的 tick limit 输入。
*/
public SimulationConfig(int acceleration, long agingIntervalMillis, int retryLimit,
int noProgressLimit, int tickLimit) {
if (acceleration != 10 && acceleration != 100) {
@@ -23,13 +33,49 @@ public final class SimulationConfig {
this.tickLimit = tickLimit;
}
/**
* 执行“defaults”所表示的处理流程。
*
* <p>该方法属于 {@code SimulationConfig},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public static SimulationConfig defaults() {
return new SimulationConfig(100, 30_000L, 3, 500, 20_000);
}
/**
* 返回当前对象保存的“acceleration”信息。
*
* <p>该方法属于 {@code SimulationConfig},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getAcceleration() { return acceleration; }
/**
* 返回当前对象保存的“aging interval millis”信息。
*
* <p>该方法属于 {@code SimulationConfig},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getAgingIntervalMillis() { return agingIntervalMillis; }
/**
* 返回当前对象保存的“retry limit”信息。
*
* <p>该方法属于 {@code SimulationConfig},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getRetryLimit() { return retryLimit; }
/**
* 返回当前对象保存的“no progress limit”信息。
*
* <p>该方法属于 {@code SimulationConfig},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getNoProgressLimit() { return noProgressLimit; }
/**
* 返回当前对象保存的“tick limit”信息。
*
* <p>该方法属于 {@code SimulationConfig},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getTickLimit() { return tickLimit; }
}

View File

@@ -8,20 +8,92 @@ public final class SimulationInvariantSummary {
private int duplicateWmsBusinessEffects;
private int deadlocks;
/**
* 执行“capacity violation”所表示的处理流程。
*
* <p>该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。
*/
void capacityViolation() { capacityViolations++; }
/**
* 执行“node double occupancy violation”所表示的处理流程。
*
* <p>该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。
*/
void nodeDoubleOccupancyViolation() { nodeDoubleOccupancyViolations++; }
/**
* 执行“opposite edge violation”所表示的处理流程。
*
* <p>该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。
*/
void oppositeEdgeViolation() { oppositeEdgeViolations++; }
/**
* 执行“duplicate archive attempt”所表示的处理流程。
*
* <p>该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。
*/
void duplicateArchiveAttempt() { duplicateArchiveAttempts++; }
/**
* 执行“duplicate wms business effect”所表示的处理流程。
*
* <p>该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。
*/
void duplicateWmsBusinessEffect() { duplicateWmsBusinessEffects++; }
/**
* 执行“deadlock”所表示的处理流程。
*
* <p>该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。
*/
void deadlock() { deadlocks++; }
/**
* 返回当前对象保存的“capacity violations”信息。
*
* <p>该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getCapacityViolations() { return capacityViolations; }
/**
* 返回当前对象保存的“node double occupancy violations”信息。
*
* <p>该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getNodeDoubleOccupancyViolations() { return nodeDoubleOccupancyViolations; }
/**
* 返回当前对象保存的“opposite edge violations”信息。
*
* <p>该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getOppositeEdgeViolations() { return oppositeEdgeViolations; }
/**
* 返回当前对象保存的“duplicate archive attempts”信息。
*
* <p>该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getDuplicateArchiveAttempts() { return duplicateArchiveAttempts; }
/**
* 返回当前对象保存的“duplicate wms business effects”信息。
*
* <p>该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getDuplicateWmsBusinessEffects() { return duplicateWmsBusinessEffects; }
/**
* 返回当前对象保存的“deadlocks”信息。
*
* <p>该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getDeadlocks() { return deadlocks; }
/**
* 执行“total safety violations”所表示的处理流程。
*
* <p>该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int totalSafetyViolations() {
return capacityViolations + nodeDoubleOccupancyViolations
+ oppositeEdgeViolations + duplicateArchiveAttempts

View File

@@ -5,6 +5,12 @@ import java.util.Collections;
import java.util.List;
public final class SimulationMetrics {
/**
* 计算一组等待或完成耗时样本的算术平均值;没有样本时返回 {@code null}。
*
* @param samples 非空的毫秒耗时样本。
* @return 算术平均值,或空样本对应的 {@code null}。
*/
public Double average(List<Long> samples) {
validate(samples);
if (samples.isEmpty()) return null;
@@ -13,6 +19,13 @@ public final class SimulationMetrics {
return total / samples.size();
}
/**
* 按升序样本计算指定分位数,用于报告 P95/P99 的长尾等待和完成时间。
*
* @param samples 非空的毫秒耗时样本。
* @param percentile 位于 {@code (0, 1]} 的目标分位数。
* @return 对应分位点的样本值,或空样本对应的 {@code null}。
*/
public Long percentile(List<Long> samples, double percentile) {
validate(samples);
if (percentile <= 0.0 || percentile > 1.0) {
@@ -25,6 +38,12 @@ public final class SimulationMetrics {
return ordered.get(index);
}
/**
* 执行“validate”所表示的处理流程。
*
* <p>该方法属于 {@code SimulationMetrics},用于保持当前模块的职责边界清晰。
* @param samples 执行该处理所需的 samples 输入。
*/
private void validate(List<Long> samples) {
if (samples == null || samples.contains(null)) {
throw new IllegalArgumentException("non-null samples are required");

View File

@@ -5,6 +5,11 @@ public final class SimulationProgressWatchdog {
private int lastTerminalCount;
private int unchangedEvents;
/**
* 创建无物理进展看门狗,防止资源互等或逻辑错误让仿真无限运行。
* @param unchangedLimit 执行该处理所需的 unchanged limit 输入。
* @param initialTerminalCount 执行该处理所需的 initial terminal count 输入。
*/
public SimulationProgressWatchdog(int unchangedLimit, int initialTerminalCount) {
if (unchangedLimit <= 0 || initialTerminalCount < 0) {
throw new IllegalArgumentException("valid progress limits are required");
@@ -13,10 +18,24 @@ public final class SimulationProgressWatchdog {
this.lastTerminalCount = initialTerminalCount;
}
/**
* 以任务终态变化作为最小进展信号执行死锁判断,供简单场景调用。
* @param terminalCount 执行该处理所需的 terminal count 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean observe(int terminalCount) {
return observe(terminalCount, false, false);
}
/**
* 观察本 tick 是否出现任务关闭、车辆移动或清障完成;连续无物理进展达到阈值即报告死锁。
*
* <p>终态数量必须单调,防止异常路径把已关闭任务重新当成未完成任务。
* @param terminalCount 执行该处理所需的 terminal count 输入。
* @param vehicleMoved 执行该处理所需的 vehicle moved 输入。
* @param clearanceCompleted 执行该处理所需的 clearance completed 输入。
* @return 达到无进展阈值时返回 {@code true},调用方应终止仿真并报告死锁。
*/
public boolean observe(int terminalCount, boolean vehicleMoved,
boolean clearanceCompleted) {
if (terminalCount < lastTerminalCount) {

View File

@@ -12,6 +12,10 @@ public final class SimulationTaskQueue {
private final Map<String, Entry> entries = new LinkedHashMap<String, Entry>();
private final Map<String, Long> originalArrivals = new LinkedHashMap<String, Long>();
/**
* 创建按历史到达时间、业务优先级和老化规则排序的调度等待队列。
* @param agingIntervalMillis 执行该处理所需的 aging interval millis 输入。
*/
public SimulationTaskQueue(long agingIntervalMillis) {
if (agingIntervalMillis <= 0) {
throw new IllegalArgumentException("aging interval must be positive");
@@ -19,6 +23,11 @@ public final class SimulationTaskQueue {
this.agingIntervalMillis = agingIntervalMillis;
}
/**
* 接纳一条历史任务到仿真队列,并保存不可变的首次到达时间作为后续重排和防饥饿基准。
* @param task 执行该处理所需的 task 输入。
* @param arrivalMillis 执行该处理所需的 arrival millis 输入。
*/
public void add(HistoricalSimulationTask task, long arrivalMillis) {
if (task == null || arrivalMillis < 0) {
throw new IllegalArgumentException("task and non-negative arrival are required");
@@ -31,17 +40,34 @@ public final class SimulationTaskQueue {
entries.put(id, new Entry(task, arrivalMillis));
}
/**
* 将因故障、PLC 重试耗尽或连续 HOLD 被撤销的任务重新入队,保留其原始到达时间和等待资历。
* @param task 执行该处理所需的 task 输入。
*/
public void requeue(HistoricalSimulationTask task) {
Long arrival = originalArrivals.get(task.getSimulationTaskId());
if (arrival == null) throw new IllegalArgumentException("task was never admitted");
entries.put(task.getSimulationTaskId(), new Entry(task, arrival));
}
/**
* 从等待队列取走已分配或已关闭的任务,之后由活动任务或终态结果负责其生命周期。
* @param simulationTaskId 执行该处理所需的 simulation task id 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public HistoricalSimulationTask remove(String simulationTaskId) {
Entry entry = entries.remove(simulationTaskId);
return entry == null ? null : entry.task;
}
/**
* 返回当前仿真时刻已经到达的任务,并按有效优先级、到达时间和历史标识稳定排序。
*
* <p>有效优先级会随等待时间改善,故先进入系统的低优先级任务最终能越过长期占用的高优先级任务,
* 从而实现饥饿保护。
* @param nowMillis 执行该处理所需的 now millis 输入。
* @return 本 tick 可由中心调度尝试选车的稳定有序任务列表。
*/
public List<HistoricalSimulationTask> readyAt(final long nowMillis) {
List<Entry> ready = new ArrayList<Entry>();
for (Entry entry : entries.values()) {
@@ -58,33 +84,75 @@ public final class SimulationTaskQueue {
return Collections.unmodifiableList(result);
}
/**
* 判断当前上下文是否满足“is empty”条件。
*
* <p>该方法属于 {@code SimulationTaskQueue},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isEmpty() { return entries.isEmpty(); }
/**
* 执行“size”所表示的处理流程。
*
* <p>该方法属于 {@code SimulationTaskQueue},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int size() { return entries.size(); }
/**
* 查询任务首次进入系统的仿真时刻,用于排序、HOLD 重派和等待时间指标。
* @param simulationTaskId 执行该处理所需的 simulation task id 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long arrivalMillis(String simulationTaskId) {
Long value = originalArrivals.get(simulationTaskId);
if (value == null) throw new IllegalArgumentException("task was never admitted");
return value;
}
/**
* 以任务首次到达时间计算当前有效优先级,保证活动任务和等待队列采用同一老化规则。
* @param task 执行该处理所需的 task 输入。
* @param nowMillis 执行该处理所需的 now millis 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int effectivePriorityFor(HistoricalSimulationTask task, long nowMillis) {
Long arrival = originalArrivals.get(task.getSimulationTaskId());
if (arrival == null) throw new IllegalArgumentException("task was never admitted");
return effectivePriority(new Entry(task, arrival), nowMillis);
}
/**
* 每过一个老化区间将数值优先级降低一级,最低为零;数值越小表示越先被调度。
* @param entry 执行该处理所需的 entry 输入。
* @param nowMillis 执行该处理所需的 now millis 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private int effectivePriority(Entry entry, long nowMillis) {
long waited = Math.max(0L, nowMillis - entry.arrivalMillis);
long improvement = waited / agingIntervalMillis;
return (int) Math.max(0L, (long) entry.task.getPriority() - improvement);
}
/**
* 将可空历史业务字段转成稳定排序用的空文本。
*
* @param value 可能为空的历史字段。
* @return 非空文本,空值映射为空字符串。
*/
private static String text(String value) { return value == null ? "" : value; }
private static final class Entry {
private final HistoricalSimulationTask task;
private final long arrivalMillis;
/**
* 创建 {@code Entry} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code Entry},用于保持当前模块的职责边界清晰。
* @param task 执行该处理所需的 task 输入。
* @param arrivalMillis 执行该处理所需的 arrival millis 输入。
*/
private Entry(HistoricalSimulationTask task, long arrivalMillis) {
this.task = task;
this.arrivalMillis = arrivalMillis;

View File

@@ -25,6 +25,26 @@ public final class SimulationTaskResult {
private final Map<String, Integer> holdReasons;
private final Map<String, Integer> retryReasons;
/**
* 创建 {@code SimulationTaskResult} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。
* @param simulationTaskId 执行该处理所需的 simulation task id 输入。
* @param record 执行该处理所需的 record 输入。
* @param status 执行该处理所需的 status 输入。
* @param reason 执行该处理所需的 reason 输入。
* @param simulatedVehicleId 执行该处理所需的 simulated vehicle id 输入。
* @param plannedPath 执行该处理所需的 planned path 输入。
* @param assignedVehicles 执行该处理所需的 assigned vehicles 输入。
* @param arrivalMillis 执行该处理所需的 arrival millis 输入。
* @param firstAssignedMillis 执行该处理所需的 first assigned millis 输入。
* @param completedMillis 执行该处理所需的 completed millis 输入。
* @param holdCount 执行该处理所需的 hold count 输入。
* @param protocolAttempts 执行该处理所需的 protocol attempts 输入。
* @param retryCount 执行该处理所需的 retry count 输入。
* @param holdReasons 执行该处理所需的 hold reasons 输入。
* @param retryReasons 执行该处理所需的 retry reasons 输入。
*/
SimulationTaskResult(String simulationTaskId, HistoricalQueueRecord record,
SimulationTaskStatus status, String reason,
String simulatedVehicleId, List<String> plannedPath,
@@ -50,32 +70,148 @@ public final class SimulationTaskResult {
this.retryReasons = immutableMap(retryReasons);
}
/**
* 返回当前对象保存的“simulation task id”信息。
*
* <p>该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getSimulationTaskId() { return simulationTaskId; }
/**
* 返回当前对象保存的“record”信息。
*
* <p>该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public HistoricalQueueRecord getRecord() { return record; }
/**
* 返回当前对象保存的“status”信息。
*
* <p>该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public SimulationTaskStatus getStatus() { return status; }
/**
* 返回当前对象保存的“reason”信息。
*
* <p>该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getReason() { return reason; }
/**
* 返回当前对象保存的“simulated vehicle id”信息。
*
* <p>该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getSimulatedVehicleId() { return simulatedVehicleId; }
/**
* 返回当前对象保存的“planned path”信息。
*
* <p>该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<String> getPlannedPath() { return plannedPath; }
/**
* 返回当前对象保存的“assigned vehicles”信息。
*
* <p>该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<String> getAssignedVehicles() { return assignedVehicles; }
/**
* 返回当前对象保存的“arrival millis”信息。
*
* <p>该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getArrivalMillis() { return arrivalMillis; }
/**
* 返回当前对象保存的“first assigned millis”信息。
*
* <p>该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Long getFirstAssignedMillis() { return firstAssignedMillis; }
/**
* 返回当前对象保存的“completed millis”信息。
*
* <p>该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Long getCompletedMillis() { return completedMillis; }
/**
* 返回当前对象保存的“hold count”信息。
*
* <p>该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getHoldCount() { return holdCount; }
/**
* 返回当前对象保存的“protocol attempts”信息。
*
* <p>该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getProtocolAttempts() { return protocolAttempts; }
/**
* 返回当前对象保存的“retry count”信息。
*
* <p>该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int getRetryCount() { return retryCount; }
/**
* 返回当前对象保存的“hold reasons”信息。
*
* <p>该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Map<String, Integer> getHoldReasons() { return holdReasons; }
/**
* 返回当前对象保存的“retry reasons”信息。
*
* <p>该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Map<String, Integer> getRetryReasons() { return retryReasons; }
/**
* 返回当前对象保存的“waiting millis”信息。
*
* <p>该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Long getWaitingMillis() {
return firstAssignedMillis == null ? null : firstAssignedMillis - arrivalMillis;
}
/**
* 返回当前对象保存的“completion millis”信息。
*
* <p>该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Long getCompletionMillis() {
return completedMillis == null ? null : completedMillis - arrivalMillis;
}
/**
* 执行“immutable”所表示的处理流程。
*
* <p>该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。
* @param values 执行该处理所需的 values 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private static <T> List<T> immutable(List<T> values) {
return Collections.unmodifiableList(new ArrayList<T>(values));
}
/**
* 执行“immutable map”所表示的处理流程。
*
* <p>该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。
* @param values 执行该处理所需的 values 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private static Map<String, Integer> immutableMap(Map<String, Integer> values) {
return Collections.unmodifiableMap(new LinkedHashMap<String, Integer>(values));
}

View File

@@ -10,6 +10,19 @@ public final class SimulationTickEvent {
private final String fromSite;
private final String toSite;
/**
* 创建 {@code SimulationTickEvent} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code SimulationTickEvent},用于保持当前模块的职责边界清晰。
* @param tick 执行该处理所需的 tick 输入。
* @param simulationMillis 执行该处理所需的 simulation millis 输入。
* @param type 执行该处理所需的 type 输入。
* @param taskId 执行该处理所需的 task id 输入。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param reason 执行该处理所需的 reason 输入。
* @param fromSite 执行该处理所需的 from site 输入。
* @param toSite 执行该处理所需的 to site 输入。
*/
public SimulationTickEvent(long tick, long simulationMillis, String type,
String taskId, String vehicleId, String reason,
String fromSite, String toSite) {
@@ -23,12 +36,60 @@ public final class SimulationTickEvent {
this.toSite = toSite;
}
/**
* 返回当前对象保存的“tick”信息。
*
* <p>该方法属于 {@code SimulationTickEvent},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getTick() { return tick; }
/**
* 返回当前对象保存的“simulation millis”信息。
*
* <p>该方法属于 {@code SimulationTickEvent},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getSimulationMillis() { return simulationMillis; }
/**
* 返回当前对象保存的“type”信息。
*
* <p>该方法属于 {@code SimulationTickEvent},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getType() { return type; }
/**
* 返回当前对象保存的“task id”信息。
*
* <p>该方法属于 {@code SimulationTickEvent},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getTaskId() { return taskId; }
/**
* 返回当前对象保存的“vehicle id”信息。
*
* <p>该方法属于 {@code SimulationTickEvent},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getVehicleId() { return vehicleId; }
/**
* 返回当前对象保存的“reason”信息。
*
* <p>该方法属于 {@code SimulationTickEvent},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getReason() { return reason; }
/**
* 返回当前对象保存的“from site”信息。
*
* <p>该方法属于 {@code SimulationTickEvent},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getFromSite() { return fromSite; }
/**
* 返回当前对象保存的“to site”信息。
*
* <p>该方法属于 {@code SimulationTickEvent},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getToSite() { return toSite; }
}

View File

@@ -19,6 +19,20 @@ public final class EffectiveTrafficMap {
private final Set<String> safeWaitSites;
private final Set<String> safeYieldSites;
/**
* 创建 {@code EffectiveTrafficMap} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code EffectiveTrafficMap},用于保持当前模块的职责边界清晰。
* @param mapCode 执行该处理所需的 map code 输入。
* @param versionId 执行该处理所需的 version id 输入。
* @param zoneCode 执行该处理所需的 zone code 输入。
* @param checksum 执行该处理所需的 checksum 输入。
* @param nodes 执行该处理所需的 nodes 输入。
* @param edges 执行该处理所需的 edges 输入。
* @param capacities 执行该处理所需的 capacities 输入。
* @param safeWaitSites 执行该处理所需的 safe wait sites 输入。
* @param safeYieldSites 执行该处理所需的 safe yield sites 输入。
*/
EffectiveTrafficMap(String mapCode, long versionId, String zoneCode, String checksum,
Set<String> nodes, Set<ResourceKey> edges, Map<ResourceKey, Integer> capacities,
Set<String> safeWaitSites, Set<String> safeYieldSites) {
@@ -33,13 +47,67 @@ public final class EffectiveTrafficMap {
this.safeYieldSites = Collections.unmodifiableSet(new LinkedHashSet<String>(safeYieldSites));
}
/**
* 返回当前对象保存的“map code”信息。
*
* <p>该方法属于 {@code EffectiveTrafficMap},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getMapCode() { return mapCode; }
/**
* 返回当前对象保存的“version id”信息。
*
* <p>该方法属于 {@code EffectiveTrafficMap},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getVersionId() { return versionId; }
/**
* 返回当前对象保存的“zone code”信息。
*
* <p>该方法属于 {@code EffectiveTrafficMap},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getZoneCode() { return zoneCode; }
/**
* 返回当前对象保存的“checksum”信息。
*
* <p>该方法属于 {@code EffectiveTrafficMap},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getChecksum() { return checksum; }
/**
* 返回当前对象保存的“nodes”信息。
*
* <p>该方法属于 {@code EffectiveTrafficMap},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Set<String> getNodes() { return nodes; }
/**
* 返回当前对象保存的“edges”信息。
*
* <p>该方法属于 {@code EffectiveTrafficMap},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Set<ResourceKey> getEdges() { return edges; }
/**
* 返回当前对象保存的“capacities”信息。
*
* <p>该方法属于 {@code EffectiveTrafficMap},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Map<ResourceKey, Integer> getCapacities() { return capacities; }
/**
* 返回当前对象保存的“safe wait sites”信息。
*
* <p>该方法属于 {@code EffectiveTrafficMap},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Set<String> getSafeWaitSites() { return safeWaitSites; }
/**
* 返回当前对象保存的“safe yield sites”信息。
*
* <p>该方法属于 {@code EffectiveTrafficMap},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Set<String> getSafeYieldSites() { return safeYieldSites; }
}

View File

@@ -9,6 +9,13 @@ import java.util.Map;
import java.util.Set;
public final class TrafficMapCompiler {
/**
* 执行“compile”所表示的处理流程。
*
* <p>该方法属于 {@code TrafficMapCompiler},用于保持当前模块的职责边界清晰。
* @param definition 执行该处理所需的 definition 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public EffectiveTrafficMap compile(MapDefinition definition) {
if (definition == null) {
throw new IllegalArgumentException("map definition is required");
@@ -70,6 +77,13 @@ public final class TrafficMapCompiler {
private final String first;
private final String second;
/**
* 创建 {@code EdgeDefinition} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code EdgeDefinition},用于保持当前模块的职责边界清晰。
* @param first 执行该处理所需的 first 输入。
* @param second 执行该处理所需的 second 输入。
*/
public EdgeDefinition(String first, String second) {
this.first = first;
this.second = second;
@@ -89,6 +103,22 @@ public final class TrafficMapCompiler {
private final Set<String> safeWaitSites;
private final Set<String> safeYieldSites;
/**
* 创建 {@code MapDefinition} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code MapDefinition},用于保持当前模块的职责边界清晰。
* @param mapCode 执行该处理所需的 map code 输入。
* @param versionId 执行该处理所需的 version id 输入。
* @param zoneCode 执行该处理所需的 zone code 输入。
* @param confirmed 执行该处理所需的 confirmed 输入。
* @param baseChecksum 执行该处理所需的 base checksum 输入。
* @param configuredChecksum 执行该处理所需的 configured checksum 输入。
* @param nodes 执行该处理所需的 nodes 输入。
* @param edges 执行该处理所需的 edges 输入。
* @param explicitCapacities 执行该处理所需的 explicit capacities 输入。
* @param safeWaitSites 执行该处理所需的 safe wait sites 输入。
* @param safeYieldSites 执行该处理所需的 safe yield sites 输入。
*/
public MapDefinition(String mapCode, long versionId, String zoneCode, boolean confirmed,
String baseChecksum, String configuredChecksum, Set<String> nodes,
Set<EdgeDefinition> edges, Map<ResourceKey, Integer> explicitCapacities,
@@ -110,11 +140,25 @@ public final class TrafficMapCompiler {
this.safeYieldSites = immutable(safeYieldSites);
}
/**
* 执行“with safe wait sites”所表示的处理流程。
*
* <p>该方法属于 {@code MapDefinition},用于保持当前模块的职责边界清晰。
* @param sites 执行该处理所需的 sites 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public MapDefinition withSafeWaitSites(Set<String> sites) {
return new MapDefinition(mapCode, versionId, zoneCode, confirmed, baseChecksum,
configuredChecksum, nodes, edges, explicitCapacities, sites, safeYieldSites);
}
/**
* 执行“with additional edge”所表示的处理流程。
*
* <p>该方法属于 {@code MapDefinition},用于保持当前模块的职责边界清晰。
* @param edge 执行该处理所需的 edge 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public MapDefinition withAdditionalEdge(EdgeDefinition edge) {
Set<EdgeDefinition> changed = new LinkedHashSet<EdgeDefinition>(edges);
changed.add(edge);
@@ -122,6 +166,14 @@ public final class TrafficMapCompiler {
configuredChecksum, nodes, changed, explicitCapacities, safeWaitSites, safeYieldSites);
}
/**
* 执行“with capacity”所表示的处理流程。
*
* <p>该方法属于 {@code MapDefinition},用于保持当前模块的职责边界清晰。
* @param key 执行该处理所需的 key 输入。
* @param capacity 执行该处理所需的 capacity 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public MapDefinition withCapacity(ResourceKey key, int capacity) {
Map<ResourceKey, Integer> changed = new LinkedHashMap<ResourceKey, Integer>(explicitCapacities);
changed.put(key, capacity);
@@ -129,11 +181,25 @@ public final class TrafficMapCompiler {
configuredChecksum, nodes, edges, changed, safeWaitSites, safeYieldSites);
}
/**
* 执行“with version id”所表示的处理流程。
*
* <p>该方法属于 {@code MapDefinition},用于保持当前模块的职责边界清晰。
* @param changedVersionId 执行该处理所需的 changed version id 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public MapDefinition withVersionId(long changedVersionId) {
return new MapDefinition(mapCode, changedVersionId, zoneCode, confirmed, baseChecksum,
configuredChecksum, nodes, edges, explicitCapacities, safeWaitSites, safeYieldSites);
}
/**
* 执行“immutable”所表示的处理流程。
*
* <p>该方法属于 {@code MapDefinition},用于保持当前模块的职责边界清晰。
* @param source 执行该处理所需的 source 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private static <T> Set<T> immutable(Set<T> source) {
return Collections.unmodifiableSet(new LinkedHashSet<T>(source));
}

View File

@@ -16,11 +16,36 @@ public final class DecisionEvent {
private final List<ShadowDecision> decisions;
private final DecisionReplayInput replayInput;
/**
* 创建 {@code DecisionEvent} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code DecisionEvent},用于保持当前模块的职责边界清晰。
* @param decisionId 执行该处理所需的 decision id 输入。
* @param tickSeq 执行该处理所需的 tick seq 输入。
* @param mapCode 执行该处理所需的 map code 输入。
* @param mapVersion 执行该处理所需的 map version 输入。
* @param policyVersion 执行该处理所需的 policy version 输入。
* @param inputHash 执行该处理所需的 input hash 输入。
* @param decisions 执行该处理所需的 decisions 输入。
*/
public DecisionEvent(String decisionId, long tickSeq, String mapCode, long mapVersion,
String policyVersion, String inputHash, List<ShadowDecision> decisions) {
this(decisionId, tickSeq, mapCode, mapVersion, policyVersion, inputHash, decisions, null);
}
/**
* 创建 {@code DecisionEvent} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code DecisionEvent},用于保持当前模块的职责边界清晰。
* @param decisionId 执行该处理所需的 decision id 输入。
* @param tickSeq 执行该处理所需的 tick seq 输入。
* @param mapCode 执行该处理所需的 map code 输入。
* @param mapVersion 执行该处理所需的 map version 输入。
* @param policyVersion 执行该处理所需的 policy version 输入。
* @param inputHash 执行该处理所需的 input hash 输入。
* @param decisions 执行该处理所需的 decisions 输入。
* @param replayInput 执行该处理所需的 replay input 输入。
*/
public DecisionEvent(String decisionId, long tickSeq, String mapCode, long mapVersion,
String policyVersion, String inputHash, List<ShadowDecision> decisions,
DecisionReplayInput replayInput) {
@@ -34,20 +59,82 @@ public final class DecisionEvent {
this.replayInput = replayInput;
}
/**
* 返回当前对象保存的“decision id”信息。
*
* <p>该方法属于 {@code DecisionEvent},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getDecisionId() { return decisionId; }
/**
* 返回当前对象保存的“tick seq”信息。
*
* <p>该方法属于 {@code DecisionEvent},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getTickSeq() { return tickSeq; }
/**
* 返回当前对象保存的“map code”信息。
*
* <p>该方法属于 {@code DecisionEvent},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getMapCode() { return mapCode; }
/**
* 返回当前对象保存的“map version”信息。
*
* <p>该方法属于 {@code DecisionEvent},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getMapVersion() { return mapVersion; }
/**
* 返回当前对象保存的“policy version”信息。
*
* <p>该方法属于 {@code DecisionEvent},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getPolicyVersion() { return policyVersion; }
/**
* 返回当前对象保存的“input hash”信息。
*
* <p>该方法属于 {@code DecisionEvent},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getInputHash() { return inputHash; }
/**
* 返回当前对象保存的“decisions”信息。
*
* <p>该方法属于 {@code DecisionEvent},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<ShadowDecision> getDecisions() { return decisions; }
/**
* 返回当前对象保存的“replay input”信息。
*
* <p>该方法属于 {@code DecisionEvent},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public DecisionReplayInput getReplayInput() { return replayInput; }
/**
* 执行“with input hash”所表示的处理流程。
*
* <p>该方法属于 {@code DecisionEvent},用于保持当前模块的职责边界清晰。
* @param changedHash 执行该处理所需的 changed hash 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public DecisionEvent withInputHash(String changedHash) {
return new DecisionEvent(decisionId, tickSeq, mapCode, mapVersion, policyVersion,
changedHash, decisions, replayInput);
}
/**
* 执行“with decisions”所表示的处理流程。
*
* <p>该方法属于 {@code DecisionEvent},用于保持当前模块的职责边界清晰。
* @param changedDecisions 执行该处理所需的 changed decisions 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public DecisionEvent withDecisions(List<ShadowDecision> changedDecisions) {
return new DecisionEvent(decisionId, tickSeq, mapCode, mapVersion, policyVersion,
inputHash, changedDecisions, replayInput);

View File

@@ -15,6 +15,15 @@ public final class DecisionReplayInput {
private final TrafficSnapshot snapshot;
private final List<ShadowCandidate> candidates;
/**
* 创建 {@code DecisionReplayInput} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code DecisionReplayInput},用于保持当前模块的职责边界清晰。
* @param map 执行该处理所需的 map 输入。
* @param ledger 执行该处理所需的 ledger 输入。
* @param snapshot 执行该处理所需的 snapshot 输入。
* @param candidates 执行该处理所需的 candidates 输入。
*/
public DecisionReplayInput(EffectiveTrafficMap map, ResourceLedger ledger,
TrafficSnapshot snapshot, List<ShadowCandidate> candidates) {
this.map = map;
@@ -23,9 +32,39 @@ public final class DecisionReplayInput {
this.candidates = Collections.unmodifiableList(new ArrayList<ShadowCandidate>(candidates));
}
/**
* 返回当前对象保存的“map”信息。
*
* <p>该方法属于 {@code DecisionReplayInput},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public EffectiveTrafficMap getMap() { return map; }
/**
* 执行“fresh ledger”所表示的处理流程。
*
* <p>该方法属于 {@code DecisionReplayInput},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public ResourceLedger freshLedger() { return ledger.copy(); }
/**
* 返回当前对象保存的“snapshot”信息。
*
* <p>该方法属于 {@code DecisionReplayInput},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public TrafficSnapshot getSnapshot() { return snapshot; }
/**
* 返回当前对象保存的“candidates”信息。
*
* <p>该方法属于 {@code DecisionReplayInput},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<ShadowCandidate> getCandidates() { return candidates; }
/**
* 执行“stored ledger”所表示的处理流程。
*
* <p>该方法属于 {@code DecisionReplayInput},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
ResourceLedger storedLedger() { return ledger; }
}

View File

@@ -27,6 +27,14 @@ import java.util.Set;
public final class DecisionReplayService {
private final ObjectMapper mapper = new ObjectMapper();
/**
* 执行“read”所表示的处理流程。
*
* <p>该方法属于 {@code DecisionReplayService},用于保持当前模块的职责边界清晰。
* @param input 执行该处理所需的 input 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
* @throws IOException 当调用条件不满足或处理无法继续时抛出。
*/
public DecisionEvent read(InputStream input) throws IOException {
if (input == null) throw new IllegalArgumentException("decision event input is required");
JsonNode root = mapper.readTree(input);
@@ -115,6 +123,13 @@ public final class DecisionReplayService {
root.path("inputHash").asText(), decisions, replayInput);
}
/**
* 执行“replay”所表示的处理流程。
*
* <p>该方法属于 {@code DecisionReplayService},用于保持当前模块的职责边界清晰。
* @param event 执行该处理所需的 event 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<ShadowDecision> replay(DecisionEvent event) {
if (event.getReplayInput() == null) {
throw new IllegalStateException("event has no replay input");
@@ -134,6 +149,14 @@ public final class DecisionReplayService {
return recomputed;
}
/**
* 执行“require text”所表示的处理流程。
*
* <p>该方法属于 {@code DecisionReplayService},用于保持当前模块的职责边界清晰。
* @param node 执行该处理所需的 node 输入。
* @param field 执行该处理所需的 field 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private static String requireText(JsonNode node, String field) {
JsonNode value = node.get(field);
if (value == null || !value.isTextual() || value.asText().trim().isEmpty()) {
@@ -142,6 +165,14 @@ public final class DecisionReplayService {
return value.asText();
}
/**
* 执行“require positive”所表示的处理流程。
*
* <p>该方法属于 {@code DecisionReplayService},用于保持当前模块的职责边界清晰。
* @param node 执行该处理所需的 node 输入。
* @param field 执行该处理所需的 field 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private static long requirePositive(JsonNode node, String field) {
JsonNode value = node.get(field);
if (value == null || !value.canConvertToLong() || value.asLong() <= 0) {
@@ -150,16 +181,37 @@ public final class DecisionReplayService {
return value.asLong();
}
/**
* 执行“require array”所表示的处理流程。
*
* <p>该方法属于 {@code DecisionReplayService},用于保持当前模块的职责边界清晰。
* @param node 执行该处理所需的 node 输入。
* @param field 执行该处理所需的 field 输入。
*/
private static void requireArray(JsonNode node, String field) {
if (!node.path(field).isArray()) throw new IllegalArgumentException(field + " must be an array");
}
/**
* 执行“strings”所表示的处理流程。
*
* <p>该方法属于 {@code DecisionReplayService},用于保持当前模块的职责边界清晰。
* @param array 执行该处理所需的 array 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private static Set<String> strings(JsonNode array) {
Set<String> result = new LinkedHashSet<String>();
for (JsonNode value : array) result.add(value.asText());
return result;
}
/**
* 执行“resource keys”所表示的处理流程。
*
* <p>该方法属于 {@code DecisionReplayService},用于保持当前模块的职责边界清晰。
* @param array 执行该处理所需的 array 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private static Set<ResourceKey> resourceKeys(JsonNode array) {
Set<ResourceKey> result = new LinkedHashSet<ResourceKey>();
for (JsonNode value : array) result.add(ResourceKey.fromValue(value.asText()));

View File

@@ -5,24 +5,59 @@ import java.util.Objects;
public final class ResourceKey implements Comparable<ResourceKey> {
private final String value;
/**
* 创建 {@code ResourceKey} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code ResourceKey},用于保持当前模块的职责边界清晰。
* @param value 执行该处理所需的 value 输入。
*/
private ResourceKey(String value) {
this.value = value;
}
/**
* 执行“node”所表示的处理流程。
*
* <p>该方法属于 {@code ResourceKey},用于保持当前模块的职责边界清晰。
* @param siteId 执行该处理所需的 site id 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public static ResourceKey node(String siteId) {
return new ResourceKey("NODE:" + required(siteId));
}
/**
* 执行“edge”所表示的处理流程。
*
* <p>该方法属于 {@code ResourceKey},用于保持当前模块的职责边界清晰。
* @param first 执行该处理所需的 first 输入。
* @param second 执行该处理所需的 second 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public static ResourceKey edge(String first, String second) {
String a = required(first);
String b = required(second);
return new ResourceKey(a.compareTo(b) <= 0 ? "EDGE:" + a + ":" + b : "EDGE:" + b + ":" + a);
}
/**
* 执行“conflict”所表示的处理流程。
*
* <p>该方法属于 {@code ResourceKey},用于保持当前模块的职责边界清晰。
* @param code 执行该处理所需的 code 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public static ResourceKey conflict(String code) {
return new ResourceKey("CONFLICT:" + required(code));
}
/**
* 执行“from value”所表示的处理流程。
*
* <p>该方法属于 {@code ResourceKey},用于保持当前模块的职责边界清晰。
* @param value 执行该处理所需的 value 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public static ResourceKey fromValue(String value) {
String normalized = required(value);
if (!normalized.startsWith("NODE:")
@@ -33,10 +68,23 @@ public final class ResourceKey implements Comparable<ResourceKey> {
return new ResourceKey(normalized);
}
/**
* 执行“value”所表示的处理流程。
*
* <p>该方法属于 {@code ResourceKey},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String value() {
return value;
}
/**
* 执行“required”所表示的处理流程。
*
* <p>该方法属于 {@code ResourceKey},用于保持当前模块的职责边界清晰。
* @param value 执行该处理所需的 value 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private static String required(String value) {
if (value == null || value.trim().isEmpty()) {
throw new IllegalArgumentException("resource component is required");
@@ -44,21 +92,47 @@ public final class ResourceKey implements Comparable<ResourceKey> {
return value.trim();
}
/**
* 执行“compare to”所表示的处理流程。
*
* <p>该方法属于 {@code ResourceKey},用于保持当前模块的职责边界清晰。
* @param other 执行该处理所需的 other 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
@Override
public int compareTo(ResourceKey other) {
return value.compareTo(other.value);
}
/**
* 比较当前对象与给定对象是否具有相同业务值。
*
* <p>该方法属于 {@code ResourceKey},用于保持当前模块的职责边界清晰。
* @param other 执行该处理所需的 other 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
@Override
public boolean equals(Object other) {
return other instanceof ResourceKey && value.equals(((ResourceKey) other).value);
}
/**
* 判断当前上下文是否满足“hash code”条件。
*
* <p>该方法属于 {@code ResourceKey},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
@Override
public int hashCode() {
return Objects.hash(value);
}
/**
* 生成便于诊断和日志输出的文本表示。
*
* <p>该方法属于 {@code ResourceKey},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
@Override
public String toString() {
return value;

View File

@@ -12,10 +12,25 @@ public final class ResourceLedger {
private final Map<ResourceKey, LinkedHashSet<String>> holders =
new LinkedHashMap<ResourceKey, LinkedHashSet<String>>();
/**
* 创建 {@code ResourceLedger} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code ResourceLedger},用于保持当前模块的职责边界清晰。
* @param capacities 执行该处理所需的 capacities 输入。
*/
public ResourceLedger(Map<ResourceKey, Integer> capacities) {
this.capacities = Collections.unmodifiableMap(new LinkedHashMap<ResourceKey, Integer>(capacities));
}
/**
* 作为交通资源的权威台账,原子地检查并占用车辆下一步所需的起点节点、边和目标节点。
*
* <p>未知资源直接拒绝;已满资源返回冲突资源和占用车辆。只有全部资源可用时才写入占用,避免出现
* 部分成功造成的资源泄漏或双占。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param requested 执行该处理所需的 requested 输入。
* @return 授权结果,或不可达资源/冲突车辆信息。
*/
public ProtectionResult evaluate(String vehicleId, Collection<ResourceKey> requested) {
LinkedHashSet<ResourceKey> conflicts = new LinkedHashSet<ResourceKey>();
LinkedHashSet<String> blockers = new LinkedHashSet<String>();
@@ -49,6 +64,11 @@ public final class ResourceLedger {
Collections.<ResourceKey>emptySet(), Collections.<String>emptySet());
}
/**
* 释放车辆不再需要的节点或边,通常在 PLC ACK 后离开旧节点、或 PLC 失败后撤销本次预占时调用。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param resources 执行该处理所需的 resources 输入。
*/
public void release(String vehicleId, Collection<ResourceKey> resources) {
for (ResourceKey key : resources) {
Set<String> current = holders.get(key);
@@ -58,16 +78,34 @@ public final class ResourceLedger {
}
}
/**
* 执行“holders for”所表示的处理流程。
*
* <p>该方法属于 {@code ResourceLedger},用于保持当前模块的职责边界清晰。
* @param key 执行该处理所需的 key 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Set<String> holdersFor(ResourceKey key) {
Set<String> current = holders.get(key);
return current == null ? Collections.<String>emptySet()
: Collections.unmodifiableSet(new LinkedHashSet<String>(current));
}
/**
* 执行“protected count”所表示的处理流程。
*
* <p>该方法属于 {@code ResourceLedger},用于保持当前模块的职责边界清晰。
* @param key 执行该处理所需的 key 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public int protectedCount(ResourceKey key) {
return holdersFor(key).size();
}
/**
* 复制当前资源占用以供本轮策略试算,保证候选排序不会直接改写权威台账。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public ResourceLedger copy() {
ResourceLedger copy = new ResourceLedger(capacities);
for (Map.Entry<ResourceKey, LinkedHashSet<String>> entry : holders.entrySet()) {
@@ -76,10 +114,20 @@ public final class ResourceLedger {
return copy;
}
/**
* 返回当前对象保存的“capacities”信息。
*
* <p>该方法属于 {@code ResourceLedger},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Map<ResourceKey, Integer> getCapacities() {
return capacities;
}
/**
* 导出资源持有者快照,供不变量检查和报告确认没有节点、边资源双占。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Map<ResourceKey, Set<String>> snapshotHolders() {
Map<ResourceKey, Set<String>> snapshot = new LinkedHashMap<ResourceKey, Set<String>>();
for (Map.Entry<ResourceKey, LinkedHashSet<String>> entry : holders.entrySet()) {
@@ -89,6 +137,13 @@ public final class ResourceLedger {
return Collections.unmodifiableMap(snapshot);
}
/**
* 执行“capacity”所表示的处理流程。
*
* <p>该方法属于 {@code ResourceLedger},用于保持当前模块的职责边界清晰。
* @param key 执行该处理所需的 key 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
private int capacity(ResourceKey key) {
Integer capacity = capacities.get(key);
if (capacity == null) {
@@ -103,6 +158,15 @@ public final class ResourceLedger {
private final Set<ResourceKey> conflictingResources;
private final Set<String> blockingVehicles;
/**
* 创建 {@code ProtectionResult} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code ProtectionResult},用于保持当前模块的职责边界清晰。
* @param granted 执行该处理所需的 granted 输入。
* @param unknownResource 执行该处理所需的 unknown resource 输入。
* @param conflictingResources 执行该处理所需的 conflicting resources 输入。
* @param blockingVehicles 执行该处理所需的 blocking vehicles 输入。
*/
private ProtectionResult(boolean granted, boolean unknownResource,
Set<ResourceKey> conflictingResources,
Set<String> blockingVehicles) {
@@ -114,9 +178,33 @@ public final class ResourceLedger {
new LinkedHashSet<String>(blockingVehicles));
}
/**
* 判断当前上下文是否满足“is granted”条件。
*
* <p>该方法属于 {@code ProtectionResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isGranted() { return granted; }
/**
* 判断当前上下文是否满足“is unknown resource”条件。
*
* <p>该方法属于 {@code ProtectionResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isUnknownResource() { return unknownResource; }
/**
* 返回当前对象保存的“conflicting resources”信息。
*
* <p>该方法属于 {@code ProtectionResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Set<ResourceKey> getConflictingResources() { return conflictingResources; }
/**
* 返回当前对象保存的“blocking vehicles”信息。
*
* <p>该方法属于 {@code ProtectionResult},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Set<String> getBlockingVehicles() { return blockingVehicles; }
}
}

View File

@@ -16,6 +16,21 @@ public final class TrafficSegment {
private final ReservationState reservationState;
private final long lastSnapshotSeq;
/**
* 创建 {@code TrafficSegment} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。
* @param segmentId 执行该处理所需的 segment id 输入。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param plcBootId 执行该处理所需的 plc boot id 输入。
* @param plannerEpoch 执行该处理所需的 planner epoch 输入。
* @param planVersion 执行该处理所需的 plan version 输入。
* @param segmentSeq 执行该处理所需的 segment seq 输入。
* @param path 执行该处理所需的 path 输入。
* @param state 执行该处理所需的 state 输入。
* @param reservationState 执行该处理所需的 reservation state 输入。
* @param lastSnapshotSeq 执行该处理所需的 last snapshot seq 输入。
*/
private TrafficSegment(String segmentId, String vehicleId, String plcBootId, long plannerEpoch,
long planVersion, long segmentSeq, List<String> path, SegmentState state,
ReservationState reservationState, long lastSnapshotSeq) {
@@ -31,6 +46,19 @@ public final class TrafficSegment {
this.lastSnapshotSeq = lastSnapshotSeq;
}
/**
* 执行“planned”所表示的处理流程。
*
* <p>该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。
* @param segmentId 执行该处理所需的 segment id 输入。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param plcBootId 执行该处理所需的 plc boot id 输入。
* @param plannerEpoch 执行该处理所需的 planner epoch 输入。
* @param planVersion 执行该处理所需的 plan version 输入。
* @param segmentSeq 执行该处理所需的 segment seq 输入。
* @param path 执行该处理所需的 path 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public static TrafficSegment planned(String segmentId, String vehicleId, String plcBootId,
long plannerEpoch, long planVersion, long segmentSeq,
List<String> path) {
@@ -41,6 +69,13 @@ public final class TrafficSegment {
segmentSeq, path, SegmentState.SOFT_PLANNED, ReservationState.SOFT, -1L);
}
/**
* 执行“transition”所表示的处理流程。
*
* <p>该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。
* @param event 执行该处理所需的 event 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public TrafficSegment transition(SegmentEvent event) {
SegmentState next;
ReservationState reservation = reservationState;
@@ -77,25 +112,98 @@ public final class TrafficSegment {
segmentSeq, path, next, reservation, lastSnapshotSeq);
}
/**
* 执行“with last snapshot seq”所表示的处理流程。
*
* <p>该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。
* @param snapshotSeq 执行该处理所需的 snapshot seq 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public TrafficSegment withLastSnapshotSeq(long snapshotSeq) {
return new TrafficSegment(segmentId, vehicleId, plcBootId, plannerEpoch, planVersion,
segmentSeq, path, state, reservationState, snapshotSeq);
}
/**
* 执行“require”所表示的处理流程。
*
* <p>该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。
* @param required 执行该处理所需的 required 输入。
*/
private void require(SegmentState required) {
if (state != required) {
throw new IllegalStateException(state + " cannot accept transition requiring " + required);
}
}
/**
* 返回当前对象保存的“segment id”信息。
*
* <p>该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getSegmentId() { return segmentId; }
/**
* 返回当前对象保存的“vehicle id”信息。
*
* <p>该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getVehicleId() { return vehicleId; }
/**
* 返回当前对象保存的“plc boot id”信息。
*
* <p>该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getPlcBootId() { return plcBootId; }
/**
* 返回当前对象保存的“planner epoch”信息。
*
* <p>该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getPlannerEpoch() { return plannerEpoch; }
/**
* 返回当前对象保存的“plan version”信息。
*
* <p>该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getPlanVersion() { return planVersion; }
/**
* 返回当前对象保存的“segment seq”信息。
*
* <p>该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getSegmentSeq() { return segmentSeq; }
/**
* 返回当前对象保存的“path”信息。
*
* <p>该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<String> getPath() { return path; }
/**
* 返回当前对象保存的“state”信息。
*
* <p>该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public SegmentState getState() { return state; }
/**
* 返回当前对象保存的“reservation state”信息。
*
* <p>该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public ReservationState getReservationState() { return reservationState; }
/**
* 返回当前对象保存的“last snapshot seq”信息。
*
* <p>该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getLastSnapshotSeq() { return lastSnapshotSeq; }
}

View File

@@ -6,10 +6,25 @@ import java.time.Instant;
public final class SnapshotFreshnessPolicy {
private final Duration maximumAge;
/**
* 创建 {@code SnapshotFreshnessPolicy} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code SnapshotFreshnessPolicy},用于保持当前模块的职责边界清晰。
* @param maximumAge 执行该处理所需的 maximum age 输入。
*/
public SnapshotFreshnessPolicy(Duration maximumAge) {
this.maximumAge = maximumAge;
}
/**
* 执行“validate”所表示的处理流程。
*
* <p>该方法属于 {@code SnapshotFreshnessPolicy},用于保持当前模块的职责边界清晰。
* @param previous 执行该处理所需的 previous 输入。
* @param current 执行该处理所需的 current 输入。
* @param decisionTime 执行该处理所需的 decision time 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public SnapshotHealth validate(TrafficVehicleSnapshot previous,
TrafficVehicleSnapshot current, Instant decisionTime) {
if (!current.isConnected()) return SnapshotHealth.unhealthy("COMMUNICATION_LOST");
@@ -32,14 +47,46 @@ public final class SnapshotFreshnessPolicy {
private final boolean healthy;
private final String reasonCode;
/**
* 创建 {@code SnapshotHealth} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code SnapshotHealth},用于保持当前模块的职责边界清晰。
* @param healthy 执行该处理所需的 healthy 输入。
* @param reasonCode 执行该处理所需的 reason code 输入。
*/
private SnapshotHealth(boolean healthy, String reasonCode) {
this.healthy = healthy;
this.reasonCode = reasonCode;
}
/**
* 执行“healthy”所表示的处理流程。
*
* <p>该方法属于 {@code SnapshotHealth},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
static SnapshotHealth healthy() { return new SnapshotHealth(true, "OK"); }
/**
* 执行“unhealthy”所表示的处理流程。
*
* <p>该方法属于 {@code SnapshotHealth},用于保持当前模块的职责边界清晰。
* @param reason 执行该处理所需的 reason 输入。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
static SnapshotHealth unhealthy(String reason) { return new SnapshotHealth(false, reason); }
/**
* 判断当前上下文是否满足“is healthy”条件。
*
* <p>该方法属于 {@code SnapshotHealth},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isHealthy() { return healthy; }
/**
* 返回当前对象保存的“reason code”信息。
*
* <p>该方法属于 {@code SnapshotHealth},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getReasonCode() { return reasonCode; }
}
}

View File

@@ -14,11 +14,34 @@ public final class TrafficSnapshot {
private final ControlMode controlMode;
private final List<TrafficVehicleSnapshot> vehicles;
/**
* 创建 {@code TrafficSnapshot} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code TrafficSnapshot},用于保持当前模块的职责边界清晰。
* @param tickSeq 执行该处理所需的 tick seq 输入。
* @param decisionTime 执行该处理所需的 decision time 输入。
* @param mapCode 执行该处理所需的 map code 输入。
* @param mapVersion 执行该处理所需的 map version 输入。
* @param policyVersion 执行该处理所需的 policy version 输入。
* @param vehicles 执行该处理所需的 vehicles 输入。
*/
public TrafficSnapshot(long tickSeq, Instant decisionTime, String mapCode, long mapVersion,
String policyVersion, List<TrafficVehicleSnapshot> vehicles) {
this(tickSeq, decisionTime, mapCode, mapVersion, policyVersion, ControlMode.SHADOW, vehicles);
}
/**
* 创建 {@code TrafficSnapshot} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code TrafficSnapshot},用于保持当前模块的职责边界清晰。
* @param tickSeq 执行该处理所需的 tick seq 输入。
* @param decisionTime 执行该处理所需的 decision time 输入。
* @param mapCode 执行该处理所需的 map code 输入。
* @param mapVersion 执行该处理所需的 map version 输入。
* @param policyVersion 执行该处理所需的 policy version 输入。
* @param controlMode 执行该处理所需的 control mode 输入。
* @param vehicles 执行该处理所需的 vehicles 输入。
*/
public TrafficSnapshot(long tickSeq, Instant decisionTime, String mapCode, long mapVersion,
String policyVersion, ControlMode controlMode,
List<TrafficVehicleSnapshot> vehicles) {
@@ -31,11 +54,53 @@ public final class TrafficSnapshot {
this.vehicles = Collections.unmodifiableList(new ArrayList<TrafficVehicleSnapshot>(vehicles));
}
/**
* 返回当前对象保存的“tick seq”信息。
*
* <p>该方法属于 {@code TrafficSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getTickSeq() { return tickSeq; }
/**
* 返回当前对象保存的“decision time”信息。
*
* <p>该方法属于 {@code TrafficSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Instant getDecisionTime() { return decisionTime; }
/**
* 返回当前对象保存的“map code”信息。
*
* <p>该方法属于 {@code TrafficSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getMapCode() { return mapCode; }
/**
* 返回当前对象保存的“map version”信息。
*
* <p>该方法属于 {@code TrafficSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getMapVersion() { return mapVersion; }
/**
* 返回当前对象保存的“policy version”信息。
*
* <p>该方法属于 {@code TrafficSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getPolicyVersion() { return policyVersion; }
/**
* 返回当前对象保存的“control mode”信息。
*
* <p>该方法属于 {@code TrafficSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public ControlMode getControlMode() { return controlMode; }
/**
* 返回当前对象保存的“vehicles”信息。
*
* <p>该方法属于 {@code TrafficSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<TrafficVehicleSnapshot> getVehicles() { return vehicles; }
}

View File

@@ -18,6 +18,22 @@ public final class TrafficVehicleSnapshot {
private final boolean faulted;
private final boolean manual;
/**
* 创建 {@code TrafficVehicleSnapshot} 实例并初始化其内部状态。
*
* <p>该方法属于 {@code TrafficVehicleSnapshot},用于保持当前模块的职责边界清晰。
* @param vehicleId 执行该处理所需的 vehicle id 输入。
* @param plcBootId 执行该处理所需的 plc boot id 输入。
* @param heartbeatSeq 执行该处理所需的 heartbeat seq 输入。
* @param snapshotSeq 执行该处理所需的 snapshot seq 输入。
* @param receivedAt 执行该处理所需的 received at 输入。
* @param currentSite 执行该处理所需的 current site 输入。
* @param nextSite 执行该处理所需的 next site 输入。
* @param remainingPath 执行该处理所需的 remaining path 输入。
* @param connected 执行该处理所需的 connected 输入。
* @param faulted 执行该处理所需的 faulted 输入。
* @param manual 执行该处理所需的 manual 输入。
*/
public TrafficVehicleSnapshot(String vehicleId, String plcBootId, long heartbeatSeq,
long snapshotSeq, Instant receivedAt, String currentSite,
String nextSite, List<String> remainingPath, boolean connected,
@@ -35,15 +51,81 @@ public final class TrafficVehicleSnapshot {
this.manual = manual;
}
/**
* 返回当前对象保存的“vehicle id”信息。
*
* <p>该方法属于 {@code TrafficVehicleSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getVehicleId() { return vehicleId; }
/**
* 返回当前对象保存的“plc boot id”信息。
*
* <p>该方法属于 {@code TrafficVehicleSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getPlcBootId() { return plcBootId; }
/**
* 返回当前对象保存的“heartbeat seq”信息。
*
* <p>该方法属于 {@code TrafficVehicleSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getHeartbeatSeq() { return heartbeatSeq; }
/**
* 返回当前对象保存的“snapshot seq”信息。
*
* <p>该方法属于 {@code TrafficVehicleSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public long getSnapshotSeq() { return snapshotSeq; }
/**
* 返回当前对象保存的“received at”信息。
*
* <p>该方法属于 {@code TrafficVehicleSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public Instant getReceivedAt() { return receivedAt; }
/**
* 返回当前对象保存的“current site”信息。
*
* <p>该方法属于 {@code TrafficVehicleSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getCurrentSite() { return currentSite; }
/**
* 返回当前对象保存的“next site”信息。
*
* <p>该方法属于 {@code TrafficVehicleSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public String getNextSite() { return nextSite; }
/**
* 返回当前对象保存的“remaining path”信息。
*
* <p>该方法属于 {@code TrafficVehicleSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public List<String> getRemainingPath() { return remainingPath; }
/**
* 判断当前上下文是否满足“is connected”条件。
*
* <p>该方法属于 {@code TrafficVehicleSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isConnected() { return connected; }
/**
* 判断当前上下文是否满足“is faulted”条件。
*
* <p>该方法属于 {@code TrafficVehicleSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isFaulted() { return faulted; }
/**
* 判断当前上下文是否满足“is manual”条件。
*
* <p>该方法属于 {@code TrafficVehicleSnapshot},用于保持当前模块的职责边界清晰。
* @return 本次处理产生的结果;调用方据此继续后续流程。
*/
public boolean isManual() { return manual; }
}