From 4051e3f446b8f3ddee4b898356c041e3bf0d602d Mon Sep 17 00:00:00 2001 From: zgw <13623675548@163.com> Date: Tue, 4 Aug 2026 10:24:25 +0800 Subject: [PATCH] docs(javaTest): document every Java method --- ...08-04-javaTest-method-commentation-plan.md | 129 +++++++++ .../com/ft546/wcs/demo/DemoApplication.java | 51 ++++ .../ft546/wcs/demo/center/CycleResult.java | 26 ++ .../wcs/demo/center/LegacyDispatchCenter.java | 43 +++ .../ft546/wcs/demo/center/QueueAdmission.java | 14 + .../demo/center/QueueAdmissionService.java | 21 ++ .../center/VehicleAssignmentDecision.java | 42 +++ .../demo/center/VehicleAssignmentService.java | 31 ++ .../wcs/demo/model/DispatchQueueEntry.java | 107 +++++++ .../ft546/wcs/demo/model/DispatchTask.java | 55 ++++ .../java/com/ft546/wcs/demo/model/Site.java | 61 ++++ .../ft546/wcs/demo/model/VehicleSnapshot.java | 84 ++++++ .../wcs/demo/repository/InMemoryWcsState.java | 101 +++++++ .../simulation/SimulatedProtocolAdapter.java | 52 ++++ .../com/ft546/wcs/demo/traffic/GridMap.java | 65 +++++ .../wcs/demo/traffic/GridPathPlanner.java | 18 ++ .../wcs/demo/traffic/TrafficController.java | 61 ++++ .../wcs/demo/traffic/TrafficDecision.java | 56 ++++ .../application/ShadowTrafficCoordinator.java | 25 ++ .../ShadowWriteForbiddenException.java | 6 + .../shadow/application/ShadowWritePort.java | 18 ++ .../decision/RollingDispatchPolicy.java | 22 ++ .../wcs/shadow/decision/ShadowCandidate.java | 91 ++++++ .../wcs/shadow/decision/ShadowDecision.java | 67 +++++ .../wcs/shadow/decision/WaitForGraph.java | 44 +++ .../shadow/feedback/ExecutionFeedback.java | 68 +++++ .../shadow/feedback/FeedbackReconciler.java | 23 ++ .../wcs/shadow/feedback/FeedbackResult.java | 40 +++ .../wcs/shadow/history/HistoricalMapCell.java | 61 ++++ .../wcs/shadow/history/HistoricalMapSite.java | 40 +++ .../wcs/shadow/history/HistoricalPath.java | 53 ++++ .../history/HistoricalQueueDataset.java | 130 +++++++++ .../shadow/history/HistoricalQueueLoader.java | 44 +++ .../history/HistoricalQueueNormalizer.java | 17 ++ .../shadow/history/HistoricalQueueRecord.java | 110 +++++++ .../history/HistoricalReplayAnalyzer.java | 64 ++++ .../history/HistoricalReplayApplication.java | 12 + .../history/HistoricalReplayReportWriter.java | 53 ++++ .../history/HistoricalReplayResult.java | 67 +++++ .../history/simulation/ClearanceMove.java | 84 ++++++ .../simulation/ClearanceMovePlanner.java | 22 ++ .../CorridorReservationManager.java | 99 +++++++ .../simulation/DeterministicFaultPlan.java | 77 +++++ ...storicalDispatchSimulationApplication.java | 12 + ...toricalDispatchSimulationReportWriter.java | 121 ++++++++ .../HistoricalDispatchSimulationResult.java | 123 ++++++++ .../HistoricalDispatchSimulator.java | 273 ++++++++++++++++++ .../simulation/HistoricalGridMapCompiler.java | 61 ++++ .../HistoricalSimulationFailure.java | 26 ++ .../simulation/HistoricalSimulationInput.java | 53 ++++ .../HistoricalSimulationInputFactory.java | 30 ++ .../simulation/HistoricalSimulationTask.java | 75 +++++ .../IdempotentWmsCompletionReceiver.java | 25 ++ .../simulation/PhysicalEndpointResolver.java | 42 +++ .../simulation/SimulatedPlcGateway.java | 85 ++++++ .../simulation/SimulatedVehicleRuntime.java | 86 ++++++ .../history/simulation/SimulationArchive.java | 47 +++ .../history/simulation/SimulationClock.java | 23 ++ .../history/simulation/SimulationConfig.java | 46 +++ .../SimulationInvariantSummary.java | 72 +++++ .../history/simulation/SimulationMetrics.java | 19 ++ .../SimulationProgressWatchdog.java | 19 ++ .../simulation/SimulationTaskQueue.java | 68 +++++ .../simulation/SimulationTaskResult.java | 136 +++++++++ .../simulation/SimulationTickEvent.java | 61 ++++ .../wcs/shadow/map/EffectiveTrafficMap.java | 68 +++++ .../wcs/shadow/map/TrafficMapCompiler.java | 66 +++++ .../wcs/shadow/replay/DecisionEvent.java | 87 ++++++ .../shadow/replay/DecisionReplayInput.java | 39 +++ .../shadow/replay/DecisionReplayService.java | 52 ++++ .../wcs/shadow/resource/ResourceKey.java | 74 +++++ .../wcs/shadow/resource/ResourceLedger.java | 88 ++++++ .../wcs/shadow/segment/TrafficSegment.java | 108 +++++++ .../snapshot/SnapshotFreshnessPolicy.java | 47 +++ .../wcs/shadow/snapshot/TrafficSnapshot.java | 65 +++++ .../snapshot/TrafficVehicleSnapshot.java | 82 ++++++ .../com/ft546/wcs/demo/DemoScenarioTest.java | 6 + .../wcs/demo/LegacyDispatchCenterTest.java | 88 ++++++ .../ft546/wcs/demo/QueueLifecycleTest.java | 15 + .../ft546/wcs/demo/TrafficControllerTest.java | 58 ++++ .../demo/VehicleAssignmentServiceTest.java | 61 ++++ .../wcs/shadow/FeedbackReconcilerTest.java | 43 +++ .../HistoricalQueueDatabaseReplayTest.java | 21 ++ .../wcs/shadow/HistoricalQueueLoaderTest.java | 25 ++ .../shadow/HistoricalQueueNormalizerTest.java | 22 ++ .../shadow/HistoricalReplayAnalyzerTest.java | 39 +++ .../wcs/shadow/MapAndResourceLedgerTest.java | 29 ++ .../wcs/shadow/RollingDispatchPolicyTest.java | 48 +++ .../wcs/shadow/SegmentAndSnapshotTest.java | 30 ++ .../shadow/ShadowCoordinatorReplayTest.java | 43 +++ .../shadow/ShadowInvariantPropertyTest.java | 32 ++ .../wcs/shadow/ShadowSimulationDataTest.java | 186 ++++++++++++ .../simulation/ClearanceMovePlannerTest.java | 5 + .../CorridorReservationManagerTest.java | 10 + .../HistoricalDispatchFaultMatrixTest.java | 10 + ...toricalDispatchSimulationRealDataTest.java | 22 ++ ...calDispatchSimulationReportWriterTest.java | 6 + .../HistoricalDispatchSimulatorTest.java | 67 +++++ .../HistoricalGridMapCompilerTest.java | 16 + .../HistoricalSimulationInputFactoryTest.java | 33 +++ .../PhysicalEndpointResolverTest.java | 11 + .../simulation/SimulationAdaptersTest.java | 15 + .../simulation/SimulationClockTest.java | 15 + .../SimulationInvariantSummaryTest.java | 5 + .../simulation/SimulationMetricsTest.java | 10 + .../SimulationProgressWatchdogTest.java | 15 + .../simulation/SimulationTaskQueueTest.java | 19 ++ 107 files changed, 5638 insertions(+) create mode 100644 docs/superpowers/plans/2026-08-04-javaTest-method-commentation-plan.md diff --git a/docs/superpowers/plans/2026-08-04-javaTest-method-commentation-plan.md b/docs/superpowers/plans/2026-08-04-javaTest-method-commentation-plan.md new file mode 100644 index 0000000..347a39f --- /dev/null +++ b/docs/superpowers/plans/2026-08-04-javaTest-method-commentation-plan.md @@ -0,0 +1,129 @@ +# JavaTest Method Commentation Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Add Chinese documentation to every Java constructor and method under `javaTest`, with detailed explanations for the WCS dispatch simulation's core control flow. + +**Architecture:** Use a temporary Java compiler-API scanner to find every `MethodTree` reliably, including nested types and multi-line declarations. Use the same scanner after editing to prove that each method has an immediately preceding Javadoc block. Add concise comments to simple value objects and tests, then enrich scheduler, map, resource, simulation, report, and fault-handling methods manually where behavior cannot be inferred from a name alone. + +**Tech Stack:** Java 8 source, JDK compiler tree API, Maven, JUnit 5. + +## Global Constraints + +- Modify only Java comments under `javaTest/src/main/java` and `javaTest/src/test/java`; no executable Java behavior may change. +- Cover every constructor and method, including getters, helpers, nested types, and JUnit test methods. +- Use Chinese Javadoc. Add `@param`, `@return`, or `@throws` where the signature's contract needs explanation. +- Keep line comments restricted to complex algorithmic blocks. +- Do not modify `ruoyi-*` modules, test resources, Maven configuration, or generated evidence. +- Final verification requires a complete method-Javadoc scan, `git diff --check`, and `cd javaTest && mvn clean test`. + +--- + +### Task 1: Establish method coverage inventory + +**Files:** +- Read: `javaTest/src/main/java/**/*.java` +- Read: `javaTest/src/test/java/**/*.java` +- Create temporarily outside the repository: compiler-API scanner source and compiled class. + +**Interfaces:** +- Consumes: Java source roots. +- Produces: a deterministic list of methods lacking a Javadoc block directly before the declaration. + +- [x] **Step 1: Run a baseline scan** + +Compile and run a temporary Java program that uses `JavacTask.parse()` and `TreePathScanner.visitMethod()` to print `::` when the declaration's preceding non-whitespace source text does not end in `*/`. + +Expected: every current Java method is reported because the baseline contains no Javadocs. + +- [x] **Step 2: Preserve the scanner command for final verification** + +Use the same temporary scanner source and source roots without modifying any repository file. The final run must emit no missing methods. + +### Task 2: Cover non-simulation production support code + +**Files:** +- Modify: `javaTest/src/main/java/com/ft546/wcs/demo/**/*.java` +- Modify: `javaTest/src/main/java/com/ft546/wcs/shadow/{decision,map,replay,resource,snapshot}/**/*.java` + +**Interfaces:** +- Consumes: method names, signatures, and class responsibilities. +- Produces: a Javadoc block for every method in the listed packages. + +- [x] **Step 1: Add type and method Javadocs** + +Document domain values, queue admission, vehicle assignment, path and traffic helpers, decision models, replay adapters, resource ledgers, and snapshots. For setters and lifecycle methods, state which state changes. For predicates, state the condition evaluated. For value-object accessors, state the exposed field meaning. + +- [x] **Step 2: Add algorithm block comments** + +Explain only non-obvious loops and ordering rules, such as candidate scoring, resource capacity evaluation, canonical edge keys, and snapshot version checks. + +- [x] **Step 3: Run the coverage scan for the listed roots** + +Expected: no method from these packages appears in the scanner output. + +### Task 3: Cover history ingestion and complete dispatch simulation + +**Files:** +- Modify: `javaTest/src/main/java/com/ft546/wcs/shadow/history/**/*.java` +- Modify: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/**/*.java` + +**Interfaces:** +- Consumes: historical queue/map records and the in-memory simulation workflow. +- Produces: method-level explanations of data normalization, full-grid compilation, endpoint resolution, scheduling, path planning, arbitration, clearance, PLC acknowledgement, movement, release, archive, WMS callback, fault recovery, reporting, and metrics. + +- [x] **Step 1: Add comments to history loading and data objects** + +Explain manifest/hash validation, historical-field boundaries, normalized path quality issues, and immutable result/data object accessors. + +- [x] **Step 2: Add detailed comments to simulation orchestration** + +For `HistoricalDispatchSimulator` and related managers, describe the tick order, eligible vehicle selection, independent path planning, corridor ownership, HOLD/redispatch conditions, clearance move lifecycle, resource release timing, watchdog rules, terminalization, and invariants. + +- [x] **Step 3: Add detailed comments to report and adapter code** + +Explain duration scaling, historical-vs-simulated comparison fields, CSV escaping, deterministic manifest construction, and the distinction between WMS deliveries and idempotent business effects. + +- [x] **Step 4: Run the coverage scan for main sources** + +Expected: no production Java method appears in the scanner output. + +### Task 4: Cover test code and fixtures + +**Files:** +- Modify: `javaTest/src/test/java/**/*.java` + +**Interfaces:** +- Consumes: existing JUnit scenarios and fixture helpers. +- Produces: a Javadoc block for every test, lifecycle helper, and fixture/data builder explaining scenario setup and assertion intent. + +- [x] **Step 1: Document unit and integration tests** + +Describe the expected business property for every test. Document parameter sources, fixture constructors, synthetic maps, deterministic fault plans, and test data builders so a reader can understand why the scenario exists. + +- [x] **Step 2: Run the coverage scan for test sources** + +Expected: no test method or fixture helper appears in the scanner output. + +### Task 5: Verify comment-only delivery + +**Files:** +- Verify: all Java files under `javaTest/src/main/java` and `javaTest/src/test/java`. + +- [x] **Step 1: Run the full source coverage scan** + +Expected: zero missing Javadocs across all constructors and methods. + +- [x] **Step 2: Inspect the diff for accidental behavior changes** + +Run `git diff --check` and inspect changed Java lines. Expected: only comments and unavoidable line-ending metadata warnings; no executable statements, imports, signatures, or literals change. + +- [x] **Step 3: Run full verification** + +Run `cd javaTest && mvn clean test`. + +Expected: the existing complete suite passes without test failures, errors, or skips. + +- [x] **Step 4: Commit the documentation change** + +Run `git add javaTest/src/main/java javaTest/src/test/java docs/superpowers/plans/2026-08-04-javaTest-method-commentation-plan.md` followed by `git commit -m "docs(javaTest): document every Java method"`. diff --git a/javaTest/src/main/java/com/ft546/wcs/demo/DemoApplication.java b/javaTest/src/main/java/com/ft546/wcs/demo/DemoApplication.java index 8f5fe6c..cbf21db 100644 --- a/javaTest/src/main/java/com/ft546/wcs/demo/DemoApplication.java +++ b/javaTest/src/main/java/com/ft546/wcs/demo/DemoApplication.java @@ -34,13 +34,30 @@ import java.util.LinkedHashSet; public final class DemoApplication { + /** + * 创建 {@code DemoApplication} 实例并初始化其内部状态。 + * + *

该方法属于 {@code DemoApplication},用于保持当前模块的职责边界清晰。 + */ private DemoApplication() { } + /** + * 执行“main”所表示的处理流程。 + * + *

该方法属于 {@code DemoApplication},用于保持当前模块的职责边界清晰。 + * @param args 执行该处理所需的 args 输入。 + */ public static void main(String[] args) { runScenario(System.out); } + /** + * 执行“run scenario”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@code DemoApplication},用于保持当前模块的职责边界清晰。 + * @param out 执行该处理所需的 out 输入。 + */ private static void printOfflineShadowSummary(PrintStream out) { LinkedHashSet nodes = new LinkedHashSet(Arrays.asList("A", "B", "C")); LinkedHashSet edges = diff --git a/javaTest/src/main/java/com/ft546/wcs/demo/center/CycleResult.java b/javaTest/src/main/java/com/ft546/wcs/demo/center/CycleResult.java index d2c0a73..964c3b6 100644 --- a/javaTest/src/main/java/com/ft546/wcs/demo/center/CycleResult.java +++ b/javaTest/src/main/java/com/ft546/wcs/demo/center/CycleResult.java @@ -9,6 +9,14 @@ public final class CycleResult { private final List processedVehicleIds; private final List events; + /** + * 创建 {@code CycleResult} 实例并初始化其内部状态。 + * + *

该方法属于 {@code CycleResult},用于保持当前模块的职责边界清晰。 + * @param cycleNumber 执行该处理所需的 cycle number 输入。 + * @param processedVehicleIds 执行该处理所需的 processed vehicle ids 输入。 + * @param events 执行该处理所需的 events 输入。 + */ public CycleResult( int cycleNumber, List processedVehicleIds, @@ -21,14 +29,32 @@ public final class CycleResult { this.events = Collections.unmodifiableList(new ArrayList(events)); } + /** + * 返回当前对象保存的“cycle number”信息。 + * + *

该方法属于 {@code CycleResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getCycleNumber() { return cycleNumber; } + /** + * 返回当前对象保存的“processed vehicle ids”信息。 + * + *

该方法属于 {@code CycleResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getProcessedVehicleIds() { return processedVehicleIds; } + /** + * 返回当前对象保存的“events”信息。 + * + *

该方法属于 {@code CycleResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getEvents() { return events; } diff --git a/javaTest/src/main/java/com/ft546/wcs/demo/center/LegacyDispatchCenter.java b/javaTest/src/main/java/com/ft546/wcs/demo/center/LegacyDispatchCenter.java index 2c61013..253d605 100644 --- a/javaTest/src/main/java/com/ft546/wcs/demo/center/LegacyDispatchCenter.java +++ b/javaTest/src/main/java/com/ft546/wcs/demo/center/LegacyDispatchCenter.java @@ -20,6 +20,15 @@ public final class LegacyDispatchCenter { private final TrafficController traffic; private final SimulatedProtocolAdapter protocol; + /** + * 创建 {@code LegacyDispatchCenter} 实例并初始化其内部状态。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@code LegacyDispatchCenter},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public CycleResult runCycle() { int eventStart = state.getEvents().size(); int cycleNumber = state.nextCycle(); @@ -45,6 +60,14 @@ public final class LegacyDispatchCenter { List vehicles = new ArrayList(state.getVehicles()); Collections.sort(vehicles, new Comparator() { + /** + * 执行“compare”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@code LegacyDispatchCenter},用于保持当前模块的职责边界清晰。 + * @param vehicle 执行该处理所需的 vehicle 输入。 + * @param queue 执行该处理所需的 queue 输入。 + */ private void processIssuedQueue( VehicleSnapshot vehicle, DispatchQueueEntry queue @@ -143,6 +180,12 @@ public final class LegacyDispatchCenter { } } + /** + * 执行“complete”所表示的处理流程。 + * + *

该方法属于 {@code LegacyDispatchCenter},用于保持当前模块的职责边界清晰。 + * @param queue 执行该处理所需的 queue 输入。 + */ private void complete(DispatchQueueEntry queue) { if (state.completeQueue(queue.getQueueId())) { state.addEvent( diff --git a/javaTest/src/main/java/com/ft546/wcs/demo/center/QueueAdmission.java b/javaTest/src/main/java/com/ft546/wcs/demo/center/QueueAdmission.java index 18ee7eb..a04076b 100644 --- a/javaTest/src/main/java/com/ft546/wcs/demo/center/QueueAdmission.java +++ b/javaTest/src/main/java/com/ft546/wcs/demo/center/QueueAdmission.java @@ -8,10 +8,24 @@ import java.util.List; import java.util.Optional; public interface QueueAdmission { + /** + * 执行“create pending queue”所表示的处理流程。 + * + *

该方法属于 {@code QueueAdmission},用于保持当前模块的职责边界清晰。 + * @param state 执行该处理所需的 state 输入。 + * @param frozenVehicles 执行该处理所需的 frozen vehicles 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ Optional createPendingQueue( InMemoryWcsState state, List frozenVehicles ); + /** + * 返回当前对象保存的“invocation count”信息。 + * + *

该方法属于 {@code QueueAdmission},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ int getInvocationCount(); } diff --git a/javaTest/src/main/java/com/ft546/wcs/demo/center/QueueAdmissionService.java b/javaTest/src/main/java/com/ft546/wcs/demo/center/QueueAdmissionService.java index e9bda67..1b4b48f 100644 --- a/javaTest/src/main/java/com/ft546/wcs/demo/center/QueueAdmissionService.java +++ b/javaTest/src/main/java/com/ft546/wcs/demo/center/QueueAdmissionService.java @@ -15,6 +15,13 @@ public final class QueueAdmissionService implements QueueAdmission { private final GridMap map; private int invocationCount; + /** + * 创建 {@code QueueAdmissionService} 实例并初始化其内部状态。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@code QueueAdmissionService},用于保持当前模块的职责边界清晰。 + * @param state 执行该处理所需的 state 输入。 + * @param frozenVehicles 执行该处理所需的 frozen vehicles 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ @Override public Optional createPendingQueue( InMemoryWcsState state, @@ -69,6 +84,12 @@ public final class QueueAdmissionService implements QueueAdmission { return Optional.of(queue); } + /** + * 返回当前对象保存的“invocation count”信息。 + * + *

该方法属于 {@code QueueAdmissionService},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ @Override public int getInvocationCount() { return invocationCount; diff --git a/javaTest/src/main/java/com/ft546/wcs/demo/center/VehicleAssignmentDecision.java b/javaTest/src/main/java/com/ft546/wcs/demo/center/VehicleAssignmentDecision.java index 924e14b..cc295e8 100644 --- a/javaTest/src/main/java/com/ft546/wcs/demo/center/VehicleAssignmentDecision.java +++ b/javaTest/src/main/java/com/ft546/wcs/demo/center/VehicleAssignmentDecision.java @@ -10,6 +10,14 @@ public final class VehicleAssignmentDecision { private final VehicleSnapshot vehicle; private final String reason; + /** + * 创建 {@code VehicleAssignmentDecision} 实例并初始化其内部状态。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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”信息。 + * + *

该方法属于 {@code VehicleAssignmentDecision},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public DecisionCode getCode() { return code; } + /** + * 返回当前对象保存的“vehicle”信息。 + * + *

该方法属于 {@code VehicleAssignmentDecision},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Optional getVehicle() { return Optional.ofNullable(vehicle); } + /** + * 返回当前对象保存的“reason”信息。 + * + *

该方法属于 {@code VehicleAssignmentDecision},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getReason() { return reason; } diff --git a/javaTest/src/main/java/com/ft546/wcs/demo/center/VehicleAssignmentService.java b/javaTest/src/main/java/com/ft546/wcs/demo/center/VehicleAssignmentService.java index d44e8ca..676e042 100644 --- a/javaTest/src/main/java/com/ft546/wcs/demo/center/VehicleAssignmentService.java +++ b/javaTest/src/main/java/com/ft546/wcs/demo/center/VehicleAssignmentService.java @@ -13,6 +13,16 @@ import java.util.Map; public final class VehicleAssignmentService { + /** + * 按中心调度规则从当前车队重新选择最适合服务任务源点的车辆。 + * + *

只接受在线、自动模式、空闲、允许下发且电量大于 30% 的车辆;候选依次比较同层优先、楼层距离、 + * y/x 坐标距离和车辆编号。历史 {@code agv_id} 不参与此选择,结果中的原因字符串保留评分依据便于对照。 + * @param task 执行该处理所需的 task 输入。 + * @param vehicles 执行该处理所需的 vehicles 输入。 + * @param sites 执行该处理所需的 sites 输入。 + * @return 选中的车辆及比较依据,或因端点无效/无可用车产生的拒绝结果。 + */ public VehicleAssignmentDecision select( DispatchTask task, List 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 ORDER = new Comparator() { + /** + * 执行“compare”所表示的处理流程。 + * + *

该方法属于 {@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} 实例并初始化其内部状态。 + * + *

该方法属于 {@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; diff --git a/javaTest/src/main/java/com/ft546/wcs/demo/model/DispatchQueueEntry.java b/javaTest/src/main/java/com/ft546/wcs/demo/model/DispatchQueueEntry.java index 28e994e..f257669 100644 --- a/javaTest/src/main/java/com/ft546/wcs/demo/model/DispatchQueueEntry.java +++ b/javaTest/src/main/java/com/ft546/wcs/demo/model/DispatchQueueEntry.java @@ -21,6 +21,18 @@ public final class DispatchQueueEntry { private int executionStatus; private List path; + /** + * 创建 {@code DispatchQueueEntry} 实例并初始化其内部状态。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。 + * @param issuedPath 执行该处理所需的 issued path 输入。 + */ public void markIssued(List 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”所表示的处理流程。 + * + *

该方法属于 {@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”信息。 + * + *

该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getQueueId() { return queueId; } + /** + * 返回当前对象保存的“task id”信息。 + * + *

该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getTaskId() { return taskId; } + /** + * 返回当前对象保存的“vehicle id”信息。 + * + *

该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getVehicleId() { return vehicleId; } + /** + * 返回当前对象保存的“queue type”信息。 + * + *

该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public QueueType getQueueType() { return queueType; } + /** + * 返回当前对象保存的“start site”信息。 + * + *

该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getStartSite() { return startSite; } + /** + * 返回当前对象保存的“end site”信息。 + * + *

该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getEndSite() { return endSite; } + /** + * 返回当前对象保存的“priority”信息。 + * + *

该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getPriority() { return priority; } + /** + * 返回当前对象保存的“issued”信息。 + * + *

该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getIssued() { return issued; } + /** + * 返回当前对象保存的“execution status”信息。 + * + *

该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getExecutionStatus() { return executionStatus; } + /** + * 判断当前上下文是否满足“is issued”条件。 + * + *

该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isIssued() { return issued == 1; } + /** + * 返回当前对象保存的“path”信息。 + * + *

该方法属于 {@code DispatchQueueEntry},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getPath() { return path; } diff --git a/javaTest/src/main/java/com/ft546/wcs/demo/model/DispatchTask.java b/javaTest/src/main/java/com/ft546/wcs/demo/model/DispatchTask.java index 961a874..e1f73ac 100644 --- a/javaTest/src/main/java/com/ft546/wcs/demo/model/DispatchTask.java +++ b/javaTest/src/main/java/com/ft546/wcs/demo/model/DispatchTask.java @@ -14,6 +14,17 @@ public final class DispatchTask { private final int floor; private final int priority; + /** + * 创建 {@code DispatchTask} 实例并初始化其内部状态。 + * + *

该方法属于 {@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”信息。 + * + *

该方法属于 {@code DispatchTask},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getTaskId() { return taskId; } + /** + * 返回当前对象保存的“type”信息。 + * + *

该方法属于 {@code DispatchTask},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public TaskType getType() { return type; } + /** + * 返回当前对象保存的“source site”信息。 + * + *

该方法属于 {@code DispatchTask},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getSourceSite() { return sourceSite; } + /** + * 返回当前对象保存的“target site”信息。 + * + *

该方法属于 {@code DispatchTask},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getTargetSite() { return targetSite; } + /** + * 返回当前对象保存的“floor”信息。 + * + *

该方法属于 {@code DispatchTask},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getFloor() { return floor; } + /** + * 返回当前对象保存的“priority”信息。 + * + *

该方法属于 {@code DispatchTask},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getPriority() { return priority; } + /** + * 执行“require text”所表示的处理流程。 + * + *

该方法属于 {@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"); diff --git a/javaTest/src/main/java/com/ft546/wcs/demo/model/Site.java b/javaTest/src/main/java/com/ft546/wcs/demo/model/Site.java index ac6e060..2076ca6 100644 --- a/javaTest/src/main/java/com/ft546/wcs/demo/model/Site.java +++ b/javaTest/src/main/java/com/ft546/wcs/demo/model/Site.java @@ -9,6 +9,16 @@ public final class Site { private final int y; private final String channel; + /** + * 创建 {@code Site} 实例并初始化其内部状态。 + * + *

该方法属于 {@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”信息。 + * + *

该方法属于 {@code Site},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getId() { return id; } + /** + * 返回当前对象保存的“floor”信息。 + * + *

该方法属于 {@code Site},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getFloor() { return floor; } + /** + * 返回当前对象保存的“x”信息。 + * + *

该方法属于 {@code Site},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getX() { return x; } + /** + * 返回当前对象保存的“y”信息。 + * + *

该方法属于 {@code Site},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getY() { return y; } + /** + * 返回当前对象保存的“channel”信息。 + * + *

该方法属于 {@code Site},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getChannel() { return channel; } + /** + * 执行“require text”所表示的处理流程。 + * + *

该方法属于 {@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; } + /** + * 比较当前对象与给定对象是否具有相同业务值。 + * + *

该方法属于 {@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”条件。 + * + *

该方法属于 {@code Site},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ @Override public int hashCode() { return Objects.hash(id); diff --git a/javaTest/src/main/java/com/ft546/wcs/demo/model/VehicleSnapshot.java b/javaTest/src/main/java/com/ft546/wcs/demo/model/VehicleSnapshot.java index af7960c..5649abc 100644 --- a/javaTest/src/main/java/com/ft546/wcs/demo/model/VehicleSnapshot.java +++ b/javaTest/src/main/java/com/ft546/wcs/demo/model/VehicleSnapshot.java @@ -11,6 +11,20 @@ public final class VehicleSnapshot { private final boolean allowSend; private final boolean cargo; + /** + * 创建 {@code VehicleSnapshot} 实例并初始化其内部状态。 + * + *

该方法属于 {@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”信息。 + * + *

该方法属于 {@code VehicleSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getVehicleId() { return vehicleId; } + /** + * 返回当前对象保存的“floor”信息。 + * + *

该方法属于 {@code VehicleSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getFloor() { return floor; } + /** + * 返回当前对象保存的“current site”信息。 + * + *

该方法属于 {@code VehicleSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getCurrentSite() { return currentSite; } + /** + * 返回当前对象保存的“work mode”信息。 + * + *

该方法属于 {@code VehicleSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getWorkMode() { return workMode; } + /** + * 返回当前对象保存的“status”信息。 + * + *

该方法属于 {@code VehicleSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getStatus() { return status; } + /** + * 返回当前对象保存的“battery”信息。 + * + *

该方法属于 {@code VehicleSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getBattery() { return battery; } + /** + * 判断当前上下文是否满足“is connected”条件。 + * + *

该方法属于 {@code VehicleSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isConnected() { return connected; } + /** + * 判断当前上下文是否满足“is allow send”条件。 + * + *

该方法属于 {@code VehicleSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isAllowSend() { return allowSend; } + /** + * 判断当前上下文是否满足“is cargo”条件。 + * + *

该方法属于 {@code VehicleSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isCargo() { return cargo; } + /** + * 执行“at”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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"); diff --git a/javaTest/src/main/java/com/ft546/wcs/demo/repository/InMemoryWcsState.java b/javaTest/src/main/java/com/ft546/wcs/demo/repository/InMemoryWcsState.java index 2a1284f..b009e2c 100644 --- a/javaTest/src/main/java/com/ft546/wcs/demo/repository/InMemoryWcsState.java +++ b/javaTest/src/main/java/com/ft546/wcs/demo/repository/InMemoryWcsState.java @@ -27,6 +27,12 @@ public final class InMemoryWcsState { private final List events = new ArrayList(); private int cycleNumber; + /** + * 执行“add vehicle”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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”信息。 + * + *

该方法属于 {@code InMemoryWcsState},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getVehicles() { return Collections.unmodifiableList( new ArrayList(vehicles.values()) ); } + /** + * 返回当前对象保存的“pending tasks”信息。 + * + *

该方法属于 {@code InMemoryWcsState},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getPendingTasks() { List result = new ArrayList(pendingTasks.values()); Collections.sort(result, new Comparator() { + /** + * 执行“compare”所表示的处理流程。 + * + *

该方法属于 {@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”信息。 + * + *

该方法属于 {@code InMemoryWcsState},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getActiveQueues() { return Collections.unmodifiableList( new ArrayList(activeQueues.values()) ); } + /** + * 返回当前对象保存的“history”信息。 + * + *

该方法属于 {@code InMemoryWcsState},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getHistory() { return Collections.unmodifiableList(history); } + /** + * 执行“find queue by vehicle”所表示的处理流程。 + * + *

该方法属于 {@code InMemoryWcsState},用于保持当前模块的职责边界清晰。 + * @param vehicleId 执行该处理所需的 vehicle id 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Optional 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”所表示的处理流程。 + * + *

该方法属于 {@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”信息。 + * + *

该方法属于 {@code InMemoryWcsState},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getEvents() { return Collections.unmodifiableList(events); } + /** + * 执行“next cycle”所表示的处理流程。 + * + *

该方法属于 {@code InMemoryWcsState},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int nextCycle() { cycleNumber++; return cycleNumber; } + /** + * 返回当前对象保存的“cycle number”信息。 + * + *

该方法属于 {@code InMemoryWcsState},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getCycleNumber() { return cycleNumber; } diff --git a/javaTest/src/main/java/com/ft546/wcs/demo/simulation/SimulatedProtocolAdapter.java b/javaTest/src/main/java/com/ft546/wcs/demo/simulation/SimulatedProtocolAdapter.java index 46822ab..494a559 100644 --- a/javaTest/src/main/java/com/ft546/wcs/demo/simulation/SimulatedProtocolAdapter.java +++ b/javaTest/src/main/java/com/ft546/wcs/demo/simulation/SimulatedProtocolAdapter.java @@ -10,6 +10,14 @@ public final class SimulatedProtocolAdapter { private final List attemptedQueueIds = new ArrayList(); private String nextFailure; + /** + * 执行“send”所表示的处理流程。 + * + *

该方法属于 {@code SimulatedProtocolAdapter},用于保持当前模块的职责边界清晰。 + * @param queue 执行该处理所需的 queue 输入。 + * @param path 执行该处理所需的 path 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public ProtocolResult send(DispatchQueueEntry queue, List 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”所表示的处理流程。 + * + *

该方法属于 {@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”信息。 + * + *

该方法属于 {@code SimulatedProtocolAdapter},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getAttemptedQueueIds() { return Collections.unmodifiableList(attemptedQueueIds); } @@ -38,23 +58,55 @@ public final class SimulatedProtocolAdapter { private final boolean success; private final String message; + /** + * 创建 {@code ProtocolResult} 实例并初始化其内部状态。 + * + *

该方法属于 {@code ProtocolResult},用于保持当前模块的职责边界清晰。 + * @param success 执行该处理所需的 success 输入。 + * @param message 执行该处理所需的 message 输入。 + */ private ProtocolResult(boolean success, String message) { this.success = success; this.message = message; } + /** + * 执行“success”所表示的处理流程。 + * + *

该方法属于 {@code ProtocolResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public static ProtocolResult success() { return new ProtocolResult(true, "accepted"); } + /** + * 执行“failure”所表示的处理流程。 + * + *

该方法属于 {@code ProtocolResult},用于保持当前模块的职责边界清晰。 + * @param message 执行该处理所需的 message 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public static ProtocolResult failure(String message) { return new ProtocolResult(false, message); } + /** + * 判断当前上下文是否满足“is success”条件。 + * + *

该方法属于 {@code ProtocolResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isSuccess() { return success; } + /** + * 返回当前对象保存的“message”信息。 + * + *

该方法属于 {@code ProtocolResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getMessage() { return message; } diff --git a/javaTest/src/main/java/com/ft546/wcs/demo/traffic/GridMap.java b/javaTest/src/main/java/com/ft546/wcs/demo/traffic/GridMap.java index 6f3e97f..d867627 100644 --- a/javaTest/src/main/java/com/ft546/wcs/demo/traffic/GridMap.java +++ b/javaTest/src/main/java/com/ft546/wcs/demo/traffic/GridMap.java @@ -19,6 +19,12 @@ public final class GridMap { private final Map cacheSitesByChannel = new LinkedHashMap(); + /** + * 执行“add site”所表示的处理流程。 + * + *

该方法属于 {@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()); } + /** + * 执行“connect”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@code GridMap},用于保持当前模块的职责边界清晰。 + * @param siteId 执行该处理所需的 site id 输入。 + */ public void block(String siteId) { requireSite(siteId); blockedSites.add(siteId); } + /** + * 更新当前对象的“cache site”状态。 + * + *

该方法属于 {@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”信息。 + * + *

该方法属于 {@code GridMap},用于保持当前模块的职责边界清晰。 + * @param siteId 执行该处理所需的 site id 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Site getSite(String siteId) { return sites.get(siteId); } + /** + * 返回当前对象保存的“sites”信息。 + * + *

该方法属于 {@code GridMap},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Map getSites() { return Collections.unmodifiableMap(sites); } + /** + * 返回当前对象保存的“neighbors”信息。 + * + *

该方法属于 {@code GridMap},用于保持当前模块的职责边界清晰。 + * @param siteId 执行该处理所需的 site id 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getNeighbors(String siteId) { requireSite(siteId); List result = new ArrayList(neighbors.get(siteId)); @@ -65,14 +111,33 @@ public final class GridMap { return result; } + /** + * 返回当前对象保存的“blocked sites”信息。 + * + *

该方法属于 {@code GridMap},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Set getBlockedSites() { return Collections.unmodifiableSet(blockedSites); } + /** + * 返回当前对象保存的“cache site”信息。 + * + *

该方法属于 {@code GridMap},用于保持当前模块的职责边界清晰。 + * @param channel 执行该处理所需的 channel 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getCacheSite(String channel) { return cacheSitesByChannel.get(channel); } + /** + * 执行“require site”所表示的处理流程。 + * + *

该方法属于 {@code GridMap},用于保持当前模块的职责边界清晰。 + * @param siteId 执行该处理所需的 site id 输入。 + */ private void requireSite(String siteId) { if (!sites.containsKey(siteId)) { throw new IllegalArgumentException("unknown site: " + siteId); diff --git a/javaTest/src/main/java/com/ft546/wcs/demo/traffic/GridPathPlanner.java b/javaTest/src/main/java/com/ft546/wcs/demo/traffic/GridPathPlanner.java index 00fd2e7..baa5a21 100644 --- a/javaTest/src/main/java/com/ft546/wcs/demo/traffic/GridPathPlanner.java +++ b/javaTest/src/main/java/com/ft546/wcs/demo/traffic/GridPathPlanner.java @@ -13,6 +13,17 @@ import java.util.Set; public final class GridPathPlanner { + /** + * 在完整网格上用广度优先搜索重新规划两站点间的最短可达路径。 + * + *

静态禁行点与本轮动态阻塞点共同生效,但车辆当前站点允许作为起点;目标不可走或无法抵达时返回空, + * 由上层关闭 {@code NO_ROUTE} 或保持等待,而不是借用历史 {@code path_info}。 + * @param map 执行该处理所需的 map 输入。 + * @param start 执行该处理所需的 start 输入。 + * @param end 执行该处理所需的 end 输入。 + * @param dynamicBlocked 执行该处理所需的 dynamic blocked 输入。 + * @return 包含起终点的最短路径;无路时为空列表。 + */ public List shortestPath( GridMap map, String start, @@ -53,6 +64,13 @@ public final class GridPathPlanner { return Collections.emptyList(); } + /** + * 将 BFS 前驱链反向还原为车辆可顺序执行的起点到终点路径。 + * + * @param parent 每个已搜索站点的前驱关系。 + * @param end 已找到的目标站点。 + * @return 包含起点和终点的不可变最短路径。 + */ private List buildPath(Map parent, String end) { List reversed = new ArrayList(); String current = end; diff --git a/javaTest/src/main/java/com/ft546/wcs/demo/traffic/TrafficController.java b/javaTest/src/main/java/com/ft546/wcs/demo/traffic/TrafficController.java index 2d3d016..7bd8184 100644 --- a/javaTest/src/main/java/com/ft546/wcs/demo/traffic/TrafficController.java +++ b/javaTest/src/main/java/com/ft546/wcs/demo/traffic/TrafficController.java @@ -14,6 +14,13 @@ public final class TrafficController { private final GridMap map; private final GridPathPlanner planner; + /** + * 创建 {@code TrafficController} 实例并初始化其内部状态。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@code TrafficController},用于保持当前模块的职责边界清晰。 + * @param vehicle 执行该处理所需的 vehicle 输入。 + * @param vehicles 执行该处理所需的 vehicles 输入。 + * @param queues 执行该处理所需的 queues 输入。 + * @param currentQueue 执行该处理所需的 current queue 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private Set buildBlockedSites( VehicleSnapshot vehicle, Collection vehicles, @@ -117,6 +144,15 @@ public final class TrafficController { return blocked; } + /** + * 执行“find channel blocker”所表示的处理流程。 + * + *

该方法属于 {@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”条件。 + * + *

该方法属于 {@code TrafficController},用于保持当前模块的职责边界清晰。 + * @param vehicleId 执行该处理所需的 vehicle id 输入。 + * @param queues 执行该处理所需的 queues 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private boolean hasActiveQueue( String vehicleId, Collection queues @@ -153,6 +197,14 @@ public final class TrafficController { return false; } + /** + * 执行“find vehicle”所表示的处理流程。 + * + *

该方法属于 {@code TrafficController},用于保持当前模块的职责边界清晰。 + * @param vehicleId 执行该处理所需的 vehicle id 输入。 + * @param vehicles 执行该处理所需的 vehicles 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private VehicleSnapshot findVehicle( String vehicleId, Collection vehicles @@ -165,6 +217,15 @@ public final class TrafficController { return null; } + /** + * 执行“require inputs”所表示的处理流程。 + * + *

该方法属于 {@code TrafficController},用于保持当前模块的职责边界清晰。 + * @param vehicle 执行该处理所需的 vehicle 输入。 + * @param queue 执行该处理所需的 queue 输入。 + * @param vehicles 执行该处理所需的 vehicles 输入。 + * @param queues 执行该处理所需的 queues 输入。 + */ private void requireInputs( VehicleSnapshot vehicle, DispatchQueueEntry queue, diff --git a/javaTest/src/main/java/com/ft546/wcs/demo/traffic/TrafficDecision.java b/javaTest/src/main/java/com/ft546/wcs/demo/traffic/TrafficDecision.java index bf1e594..290df4e 100644 --- a/javaTest/src/main/java/com/ft546/wcs/demo/traffic/TrafficDecision.java +++ b/javaTest/src/main/java/com/ft546/wcs/demo/traffic/TrafficDecision.java @@ -14,6 +14,15 @@ public final class TrafficDecision { private final DispatchQueueEntry avoidanceQueue; private final String reason; + /** + * 创建 {@code TrafficDecision} 实例并初始化其内部状态。 + * + *

该方法属于 {@code TrafficDecision},用于保持当前模块的职责边界清晰。 + * @param code 执行该处理所需的 code 输入。 + * @param path 执行该处理所需的 path 输入。 + * @param avoidanceQueue 执行该处理所需的 avoidance queue 输入。 + * @param reason 执行该处理所需的 reason 输入。 + */ private TrafficDecision( DecisionCode code, List path, @@ -26,6 +35,13 @@ public final class TrafficDecision { this.reason = reason; } + /** + * 执行“path”所表示的处理流程。 + * + *

该方法属于 {@code TrafficDecision},用于保持当前模块的职责边界清晰。 + * @param path 执行该处理所需的 path 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public static TrafficDecision path(List path) { return new TrafficDecision( DecisionCode.PATH_READY, @@ -35,10 +51,26 @@ public final class TrafficDecision { ); } + /** + * 执行“hold”所表示的处理流程。 + * + *

该方法属于 {@code TrafficDecision},用于保持当前模块的职责边界清晰。 + * @param code 执行该处理所需的 code 输入。 + * @param reason 执行该处理所需的 reason 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public static TrafficDecision hold(DecisionCode code, String reason) { return new TrafficDecision(code, Collections.emptyList(), null, reason); } + /** + * 执行“avoidance”所表示的处理流程。 + * + *

该方法属于 {@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”信息。 + * + *

该方法属于 {@code TrafficDecision},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public DecisionCode getCode() { return code; } + /** + * 返回当前对象保存的“path”信息。 + * + *

该方法属于 {@code TrafficDecision},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getPath() { return path; } + /** + * 返回当前对象保存的“avoidance queue”信息。 + * + *

该方法属于 {@code TrafficDecision},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Optional getAvoidanceQueue() { return Optional.ofNullable(avoidanceQueue); } + /** + * 返回当前对象保存的“reason”信息。 + * + *

该方法属于 {@code TrafficDecision},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getReason() { return reason; } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/application/ShadowTrafficCoordinator.java b/javaTest/src/main/java/com/ft546/wcs/shadow/application/ShadowTrafficCoordinator.java index 942ef5b..cad2031 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/application/ShadowTrafficCoordinator.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/application/ShadowTrafficCoordinator.java @@ -35,6 +35,14 @@ public final class ShadowTrafficCoordinator { private final Map previousSnapshots = new LinkedHashMap(); + /** + * 创建 {@code ShadowTrafficCoordinator} 实例并初始化其内部状态。 + * + *

该方法属于 {@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; } + /** + * 对一个冻结的影子交通快照运行可重放的资源裁决,并生成带输入哈希的决策事件。 + * + *

只接收 SHADOW 模式且版本匹配的地图;过期或异常车辆快照会被隔离,候选车必须存在于本轮快照。 + * 哈希覆盖地图容量、资源持有者和候选移动,使相同业务输入可复核为相同调度决策。 + * @param snapshot 执行该处理所需的 snapshot 输入。 + * @param candidates 执行该处理所需的 candidates 输入。 + * @return 包含裁决、输入快照和可重放哈希的决策事件。 + */ public DecisionEvent run(TrafficSnapshot snapshot, List 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 candidates) { StringBuilder canonical = new StringBuilder() diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/application/ShadowWriteForbiddenException.java b/javaTest/src/main/java/com/ft546/wcs/shadow/application/ShadowWriteForbiddenException.java index 1f8389b..eeb764d 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/application/ShadowWriteForbiddenException.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/application/ShadowWriteForbiddenException.java @@ -1,6 +1,12 @@ package com.ft546.wcs.shadow.application; public final class ShadowWriteForbiddenException extends IllegalStateException { + /** + * 创建 {@code ShadowWriteForbiddenException} 实例并初始化其内部状态。 + * + *

该方法属于 {@code ShadowWriteForbiddenException},用于保持当前模块的职责边界清晰。 + * @param operation 执行该处理所需的 operation 输入。 + */ public ShadowWriteForbiddenException(String operation) { super("SHADOW forbids authoritative write: " + operation); } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/application/ShadowWritePort.java b/javaTest/src/main/java/com/ft546/wcs/shadow/application/ShadowWritePort.java index b26c19c..271e6f2 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/application/ShadowWritePort.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/application/ShadowWritePort.java @@ -1,14 +1,32 @@ package com.ft546.wcs.shadow.application; public final class ShadowWritePort { + /** + * 执行“send plc command”所表示的处理流程。 + * + *

该方法属于 {@code ShadowWritePort},用于保持当前模块的职责边界清晰。 + * @param vehicleId 执行该处理所需的 vehicle id 输入。 + */ public void sendPlcCommand(String vehicleId) { throw new ShadowWriteForbiddenException("PLC " + vehicleId); } + /** + * 执行“update business state”所表示的处理流程。 + * + *

该方法属于 {@code ShadowWritePort},用于保持当前模块的职责边界清晰。 + * @param taskId 执行该处理所需的 task id 输入。 + */ public void updateBusinessState(String taskId) { throw new ShadowWriteForbiddenException("BUSINESS " + taskId); } + /** + * 执行“write reservation”所表示的处理流程。 + * + *

该方法属于 {@code ShadowWritePort},用于保持当前模块的职责边界清晰。 + * @param segmentId 执行该处理所需的 segment id 输入。 + */ public void writeReservation(String segmentId) { throw new ShadowWriteForbiddenException("RESERVATION " + segmentId); } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/decision/RollingDispatchPolicy.java b/javaTest/src/main/java/com/ft546/wcs/shadow/decision/RollingDispatchPolicy.java index 183cc4d..edbcc17 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/decision/RollingDispatchPolicy.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/decision/RollingDispatchPolicy.java @@ -11,6 +11,16 @@ import java.util.List; import java.util.Set; public final class RollingDispatchPolicy { + /** + * 在冻结的交通快照上为本轮所有候选移动排序并裁决 GRANT、HOLD 或 YIELD。 + * + *

已承诺移动优先,然后按紧急程度、业务优先级、等待年龄、清障成本和稳定标识排序。策略在台账副本上 + * 逐个试占资源;检测到等待环即 HOLD,存在安全让车点时返回 YIELD,保证决策可重放且不改动权威资源。 + * @param input 执行该处理所需的 input 输入。 + * @param authoritative 执行该处理所需的 authoritative 输入。 + * @param map 执行该处理所需的 map 输入。 + * @return 与候选一一对应的交通裁决及可解释原因。 + */ public List decide(List input, ResourceLedger authoritative, EffectiveTrafficMap map) { List candidates = new ArrayList(input); @@ -59,6 +69,18 @@ public final class RollingDispatchPolicy { return Collections.unmodifiableList(decisions); } + /** + * 执行“decision”所表示的处理流程。 + * + *

该方法属于 {@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 resources, Set blockers, String yieldSite) { return new ShadowDecision(candidate.getTaskId(), candidate.getVehicleId(), type, reason, diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/decision/ShadowCandidate.java b/javaTest/src/main/java/com/ft546/wcs/shadow/decision/ShadowCandidate.java index c295be8..7ffd412 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/decision/ShadowCandidate.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/decision/ShadowCandidate.java @@ -18,6 +18,20 @@ public final class ShadowCandidate { private final List resources; private final String safeYieldSite; + /** + * 创建 {@code ShadowCandidate} 实例并初始化其内部状态。 + * + *

该方法属于 {@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 resources, String safeYieldSite) { @@ -32,6 +46,20 @@ public final class ShadowCandidate { this.safeYieldSite = safeYieldSite; } + /** + * 执行“waiting”所表示的处理流程。 + * + *

该方法属于 {@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 resources, String safeYieldSite) { @@ -39,18 +67,81 @@ public final class ShadowCandidate { waitAge, clearanceCost, resources, safeYieldSite); } + /** + * 执行“committed”所表示的处理流程。 + * + *

该方法属于 {@code ShadowCandidate},用于保持当前模块的职责边界清晰。 + * @param taskId 执行该处理所需的 task id 输入。 + * @param vehicleId 执行该处理所需的 vehicle id 输入。 + * @param resources 执行该处理所需的 resources 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public static ShadowCandidate committed(String taskId, String vehicleId, Collection resources) { return new ShadowCandidate(taskId, vehicleId, true, false, 0, 0, 0, resources, null); } + /** + * 返回当前对象保存的“task id”信息。 + * + *

该方法属于 {@code ShadowCandidate},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getTaskId() { return taskId; } + /** + * 返回当前对象保存的“vehicle id”信息。 + * + *

该方法属于 {@code ShadowCandidate},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getVehicleId() { return vehicleId; } + /** + * 判断当前上下文是否满足“is committed”条件。 + * + *

该方法属于 {@code ShadowCandidate},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isCommitted() { return committed; } + /** + * 判断当前上下文是否满足“is emergency”条件。 + * + *

该方法属于 {@code ShadowCandidate},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isEmergency() { return emergency; } + /** + * 返回当前对象保存的“business priority”信息。 + * + *

该方法属于 {@code ShadowCandidate},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getBusinessPriority() { return businessPriority; } + /** + * 返回当前对象保存的“wait age”信息。 + * + *

该方法属于 {@code ShadowCandidate},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getWaitAge() { return waitAge; } + /** + * 返回当前对象保存的“clearance cost”信息。 + * + *

该方法属于 {@code ShadowCandidate},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getClearanceCost() { return clearanceCost; } + /** + * 返回当前对象保存的“resources”信息。 + * + *

该方法属于 {@code ShadowCandidate},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getResources() { return resources; } + /** + * 返回当前对象保存的“safe yield site”信息。 + * + *

该方法属于 {@code ShadowCandidate},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getSafeYieldSite() { return safeYieldSite; } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/decision/ShadowDecision.java b/javaTest/src/main/java/com/ft546/wcs/shadow/decision/ShadowDecision.java index 83be58f..5f84701 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/decision/ShadowDecision.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/decision/ShadowDecision.java @@ -16,6 +16,18 @@ public final class ShadowDecision { private final Set blockingVehicles; private final String yieldSite; + /** + * 创建 {@code ShadowDecision} 实例并初始化其内部状态。 + * + *

该方法属于 {@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 conflictingResources, Set blockingVehicles, String yieldSite) { @@ -30,14 +42,63 @@ public final class ShadowDecision { this.yieldSite = yieldSite; } + /** + * 返回当前对象保存的“task id”信息。 + * + *

该方法属于 {@code ShadowDecision},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getTaskId() { return taskId; } + /** + * 返回当前对象保存的“vehicle id”信息。 + * + *

该方法属于 {@code ShadowDecision},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getVehicleId() { return vehicleId; } + /** + * 返回当前对象保存的“type”信息。 + * + *

该方法属于 {@code ShadowDecision},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public DecisionType getType() { return type; } + /** + * 返回当前对象保存的“reason code”信息。 + * + *

该方法属于 {@code ShadowDecision},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getReasonCode() { return reasonCode; } + /** + * 返回当前对象保存的“conflicting resources”信息。 + * + *

该方法属于 {@code ShadowDecision},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Set getConflictingResources() { return conflictingResources; } + /** + * 返回当前对象保存的“blocking vehicles”信息。 + * + *

该方法属于 {@code ShadowDecision},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Set getBlockingVehicles() { return blockingVehicles; } + /** + * 返回当前对象保存的“yield site”信息。 + * + *

该方法属于 {@code ShadowDecision},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getYieldSite() { return yieldSite; } + /** + * 比较当前对象与给定对象是否具有相同业务值。 + * + *

该方法属于 {@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”条件。 + * + *

该方法属于 {@code ShadowDecision},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ @Override public int hashCode() { return Objects.hash(taskId, vehicleId, type, reasonCode, diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/decision/WaitForGraph.java b/javaTest/src/main/java/com/ft546/wcs/shadow/decision/WaitForGraph.java index 0950ba2..981e684 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/decision/WaitForGraph.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/decision/WaitForGraph.java @@ -10,17 +10,39 @@ import java.util.Set; public final class WaitForGraph { private final Map> edges = new LinkedHashMap>(); + /** + * 执行“would create cycle”所表示的处理流程。 + * + *

该方法属于 {@code WaitForGraph},用于保持当前模块的职责边界清晰。 + * @param waiter 执行该处理所需的 waiter 输入。 + * @param holders 执行该处理所需的 holders 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean wouldCreateCycle(String waiter, Collection holders) { WaitForGraph copy = copy(); copy.put(waiter, holders); return !copy.isAcyclic(); } + /** + * 执行“add wait”所表示的处理流程。 + * + *

该方法属于 {@code WaitForGraph},用于保持当前模块的职责边界清晰。 + * @param waiter 执行该处理所需的 waiter 输入。 + * @param holders 执行该处理所需的 holders 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean addWait(String waiter, Collection holders) { put(waiter, holders); return !isAcyclic(); } + /** + * 判断当前上下文是否满足“is acyclic”条件。 + * + *

该方法属于 {@code WaitForGraph},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isAcyclic() { Set visiting = new LinkedHashSet(); Set visited = new LinkedHashSet(); @@ -30,6 +52,15 @@ public final class WaitForGraph { return true; } + /** + * 判断当前上下文是否满足“has cycle”条件。 + * + *

该方法属于 {@code WaitForGraph},用于保持当前模块的职责边界清晰。 + * @param node 执行该处理所需的 node 输入。 + * @param visiting 执行该处理所需的 visiting 输入。 + * @param visited 执行该处理所需的 visited 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private boolean hasCycle(String node, Set visiting, Set visited) { if (visiting.contains(node)) return true; if (visited.contains(node)) return false; @@ -42,11 +73,24 @@ public final class WaitForGraph { return false; } + /** + * 执行“put”所表示的处理流程。 + * + *

该方法属于 {@code WaitForGraph},用于保持当前模块的职责边界清晰。 + * @param waiter 执行该处理所需的 waiter 输入。 + * @param holders 执行该处理所需的 holders 输入。 + */ private void put(String waiter, Collection holders) { if (!edges.containsKey(waiter)) edges.put(waiter, new LinkedHashSet()); edges.get(waiter).addAll(holders); } + /** + * 执行“copy”所表示的处理流程。 + * + *

该方法属于 {@code WaitForGraph},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private WaitForGraph copy() { WaitForGraph copy = new WaitForGraph(); for (Map.Entry> entry : edges.entrySet()) { diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/feedback/ExecutionFeedback.java b/javaTest/src/main/java/com/ft546/wcs/shadow/feedback/ExecutionFeedback.java index 48da417..0ecc9eb 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/feedback/ExecutionFeedback.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/feedback/ExecutionFeedback.java @@ -15,6 +15,20 @@ public final class ExecutionFeedback { private final boolean connected; private final boolean commitAckKnown; + /** + * 创建 {@code ExecutionFeedback} 实例并初始化其内部状态。 + * + *

该方法属于 {@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 remainingPath, boolean connected, boolean commitAckKnown) { @@ -29,13 +43,67 @@ public final class ExecutionFeedback { this.commitAckKnown = commitAckKnown; } + /** + * 返回当前对象保存的“plc boot id”信息。 + * + *

该方法属于 {@code ExecutionFeedback},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getPlcBootId() { return plcBootId; } + /** + * 返回当前对象保存的“planner epoch”信息。 + * + *

该方法属于 {@code ExecutionFeedback},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getPlannerEpoch() { return plannerEpoch; } + /** + * 返回当前对象保存的“plan version”信息。 + * + *

该方法属于 {@code ExecutionFeedback},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getPlanVersion() { return planVersion; } + /** + * 返回当前对象保存的“segment seq”信息。 + * + *

该方法属于 {@code ExecutionFeedback},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getSegmentSeq() { return segmentSeq; } + /** + * 返回当前对象保存的“snapshot seq”信息。 + * + *

该方法属于 {@code ExecutionFeedback},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getSnapshotSeq() { return snapshotSeq; } + /** + * 返回当前对象保存的“current site”信息。 + * + *

该方法属于 {@code ExecutionFeedback},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getCurrentSite() { return currentSite; } + /** + * 返回当前对象保存的“remaining path”信息。 + * + *

该方法属于 {@code ExecutionFeedback},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getRemainingPath() { return remainingPath; } + /** + * 判断当前上下文是否满足“is connected”条件。 + * + *

该方法属于 {@code ExecutionFeedback},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isConnected() { return connected; } + /** + * 判断当前上下文是否满足“is commit ack known”条件。 + * + *

该方法属于 {@code ExecutionFeedback},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isCommitAckKnown() { return commitAckKnown; } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/feedback/FeedbackReconciler.java b/javaTest/src/main/java/com/ft546/wcs/shadow/feedback/FeedbackReconciler.java index 500aa67..cec96f0 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/feedback/FeedbackReconciler.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/feedback/FeedbackReconciler.java @@ -10,6 +10,14 @@ import java.util.List; import java.util.Set; public final class FeedbackReconciler { + /** + * 执行“reconcile”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@code FeedbackReconciler},用于保持当前模块的职责边界清晰。 + * @param segment 执行该处理所需的 segment 输入。 + * @param reason 执行该处理所需的 reason 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private FeedbackResult quarantine(TrafficSegment segment, String reason) { return new FeedbackResult(true, reason, Collections.emptySet(), allResources(segment.getPath()), segment.transition(SegmentEvent.QUARANTINE)); } + /** + * 执行“all resources”所表示的处理流程。 + * + *

该方法属于 {@code FeedbackReconciler},用于保持当前模块的职责边界清晰。 + * @param path 执行该处理所需的 path 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private Set allResources(List path) { Set resources = new LinkedHashSet(); for (int i = 0; i < path.size(); i++) { diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/feedback/FeedbackResult.java b/javaTest/src/main/java/com/ft546/wcs/shadow/feedback/FeedbackResult.java index 7ce9b95..9070271 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/feedback/FeedbackResult.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/feedback/FeedbackResult.java @@ -14,6 +14,16 @@ public final class FeedbackResult { private final Set retainedResources; private final TrafficSegment updatedSegment; + /** + * 创建 {@code FeedbackResult} 实例并初始化其内部状态。 + * + *

该方法属于 {@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 releasedResources, Set retainedResources, TrafficSegment updatedSegment) { this.quarantined = quarantined; @@ -25,9 +35,39 @@ public final class FeedbackResult { this.updatedSegment = updatedSegment; } + /** + * 判断当前上下文是否满足“is quarantined”条件。 + * + *

该方法属于 {@code FeedbackResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isQuarantined() { return quarantined; } + /** + * 返回当前对象保存的“reason code”信息。 + * + *

该方法属于 {@code FeedbackResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getReasonCode() { return reasonCode; } + /** + * 返回当前对象保存的“released resources”信息。 + * + *

该方法属于 {@code FeedbackResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Set getReleasedResources() { return releasedResources; } + /** + * 返回当前对象保存的“retained resources”信息。 + * + *

该方法属于 {@code FeedbackResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Set getRetainedResources() { return retainedResources; } + /** + * 返回当前对象保存的“updated segment”信息。 + * + *

该方法属于 {@code FeedbackResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public TrafficSegment getUpdatedSegment() { return updatedSegment; } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalMapCell.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalMapCell.java index 4cd569c..063c4c8 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalMapCell.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalMapCell.java @@ -13,6 +13,19 @@ public final class HistoricalMapCell { private final String warehouse; private final String spaceArea; + /** + * 创建 {@code HistoricalMapCell} 实例并初始化其内部状态。 + * + *

该方法属于 {@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”信息。 + * + *

该方法属于 {@code HistoricalMapCell},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getSiteId() { return siteId; } + /** + * 返回当前对象保存的“x”信息。 + * + *

该方法属于 {@code HistoricalMapCell},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getX() { return x; } + /** + * 返回当前对象保存的“y”信息。 + * + *

该方法属于 {@code HistoricalMapCell},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getY() { return y; } + /** + * 返回当前对象保存的“z”信息。 + * + *

该方法属于 {@code HistoricalMapCell},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getZ() { return z; } + /** + * 返回当前对象保存的“value”信息。 + * + *

该方法属于 {@code HistoricalMapCell},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getValue() { return value; } + /** + * 返回当前对象保存的“axy”信息。 + * + *

该方法属于 {@code HistoricalMapCell},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getAxy() { return axy; } + /** + * 返回当前对象保存的“warehouse”信息。 + * + *

该方法属于 {@code HistoricalMapCell},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getWarehouse() { return warehouse; } + /** + * 返回当前对象保存的“space area”信息。 + * + *

该方法属于 {@code HistoricalMapCell},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getSpaceArea() { return spaceArea; } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalMapSite.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalMapSite.java index 6494295..1ca2519 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalMapSite.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalMapSite.java @@ -7,6 +7,16 @@ public final class HistoricalMapSite { private final int z; private final String axy; + /** + * 创建 {@code HistoricalMapSite} 实例并初始化其内部状态。 + * + *

该方法属于 {@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”信息。 + * + *

该方法属于 {@code HistoricalMapSite},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getSiteId() { return siteId; } + /** + * 返回当前对象保存的“x”信息。 + * + *

该方法属于 {@code HistoricalMapSite},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getX() { return x; } + /** + * 返回当前对象保存的“y”信息。 + * + *

该方法属于 {@code HistoricalMapSite},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getY() { return y; } + /** + * 返回当前对象保存的“z”信息。 + * + *

该方法属于 {@code HistoricalMapSite},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getZ() { return z; } + /** + * 返回当前对象保存的“axy”信息。 + * + *

该方法属于 {@code HistoricalMapSite},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getAxy() { return axy; } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalPath.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalPath.java index a54f954..9726d60 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalPath.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalPath.java @@ -17,6 +17,17 @@ public final class HistoricalPath { private final Set resources; private final List issues; + /** + * 创建 {@code HistoricalPath} 实例并初始化其内部状态。 + * + *

该方法属于 {@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 nodes, Set resources, List issues) { this.record = record; @@ -27,12 +38,54 @@ public final class HistoricalPath { this.issues = Collections.unmodifiableList(new ArrayList(issues)); } + /** + * 返回当前对象保存的“record”信息。 + * + *

该方法属于 {@code HistoricalPath},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public HistoricalQueueRecord getRecord() { return record; } + /** + * 返回当前对象保存的“created at”信息。 + * + *

该方法属于 {@code HistoricalPath},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public LocalDateTime getCreatedAt() { return createdAt; } + /** + * 返回当前对象保存的“finished at”信息。 + * + *

该方法属于 {@code HistoricalPath},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public LocalDateTime getFinishedAt() { return finishedAt; } + /** + * 返回当前对象保存的“nodes”信息。 + * + *

该方法属于 {@code HistoricalPath},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getNodes() { return nodes; } + /** + * 返回当前对象保存的“resources”信息。 + * + *

该方法属于 {@code HistoricalPath},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Set getResources() { return resources; } + /** + * 返回当前对象保存的“issues”信息。 + * + *

该方法属于 {@code HistoricalPath},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getIssues() { return issues; } + /** + * 判断当前上下文是否满足“is replayable”条件。 + * + *

该方法属于 {@code HistoricalPath},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isReplayable() { return createdAt != null && finishedAt != null && !nodes.isEmpty() && issues.isEmpty(); } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalQueueDataset.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalQueueDataset.java index 83849e0..24dae90 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalQueueDataset.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalQueueDataset.java @@ -27,6 +27,28 @@ public final class HistoricalQueueDataset { private final int missingIntervalRows; private final int reversedIntervalRows; + /** + * 创建 {@code HistoricalQueueDataset} 实例并初始化其内部状态。 + * + *

该方法属于 {@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 records, Map mapSiteDetails, List fullMapCells, @@ -58,25 +80,133 @@ public final class HistoricalQueueDataset { this.reversedIntervalRows = reversedIntervalRows; } + /** + * 返回当前对象保存的“records”信息。 + * + *

该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getRecords() { return records; } + /** + * 返回当前对象保存的“map sites”信息。 + * + *

该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Set getMapSites() { return Collections.unmodifiableSet( new LinkedHashSet(mapSiteDetails.keySet())); } + /** + * 返回当前对象保存的“map site details”信息。 + * + *

该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Map getMapSiteDetails() { return mapSiteDetails; } + /** + * 返回当前对象保存的“full map cells”信息。 + * + *

该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getFullMapCells() { return fullMapCells; } + /** + * 返回当前对象保存的“full map rows”信息。 + * + *

该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getFullMapRows() { return fullMapRows; } + /** + * 返回当前对象保存的“full map sha256”信息。 + * + *

该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getFullMapSha256() { return fullMapSha256; } + /** + * 返回当前对象保存的“manifest sample rows”信息。 + * + *

该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getManifestSampleRows() { return manifestSampleRows; } + /** + * 返回当前对象保存的“full scan total rows”信息。 + * + *

该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getFullScanTotalRows() { return fullScanTotalRows; } + /** + * 返回当前对象保存的“database”信息。 + * + *

该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getDatabase() { return database; } + /** + * 返回当前对象保存的“source table”信息。 + * + *

该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getSourceTable() { return sourceTable; } + /** + * 返回当前对象保存的“extracted at”信息。 + * + *

该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getExtractedAt() { return extractedAt; } + /** + * 返回当前对象保存的“min create date”信息。 + * + *

该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getMinCreateDate() { return minCreateDate; } + /** + * 返回当前对象保存的“max create date”信息。 + * + *

该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getMaxCreateDate() { return maxCreateDate; } + /** + * 返回当前对象保存的“min finish date”信息。 + * + *

该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getMinFinishDate() { return minFinishDate; } + /** + * 返回当前对象保存的“max finish date”信息。 + * + *

该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getMaxFinishDate() { return maxFinishDate; } + /** + * 返回当前对象保存的“missing path rows”信息。 + * + *

该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getMissingPathRows() { return missingPathRows; } + /** + * 返回当前对象保存的“missing interval rows”信息。 + * + *

该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getMissingIntervalRows() { return missingIntervalRows; } + /** + * 返回当前对象保存的“reversed interval rows”信息。 + * + *

该方法属于 {@code HistoricalQueueDataset},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getReversedIntervalRows() { return reversedIntervalRows; } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalQueueLoader.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalQueueLoader.java index 82d4c21..a3762b6 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalQueueLoader.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalQueueLoader.java @@ -24,6 +24,14 @@ import java.util.Set; public final class HistoricalQueueLoader { private static final ObjectMapper MAPPER = new ObjectMapper(); + /** + * 执行“load”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalQueueLoader},用于保持当前模块的职责边界清晰。 + * @param cells 执行该处理所需的 cells 输入。 + */ private static void validatePassableCells(List cells) { Set siteIds = new LinkedHashSet(); Set coordinates = new LinkedHashSet(); @@ -108,6 +122,13 @@ public final class HistoricalQueueLoader { } } + /** + * 执行“load”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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); diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalQueueNormalizer.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalQueueNormalizer.java index 7836063..412b9ed 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalQueueNormalizer.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalQueueNormalizer.java @@ -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”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalQueueNormalizer},用于保持当前模块的职责边界清晰。 + * @param record 执行该处理所需的 record 输入。 + * @param mapSites 执行该处理所需的 map sites 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public HistoricalPath normalize(HistoricalQueueRecord record, Set mapSites) { List issues = new ArrayList(); 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”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalQueueNormalizer},用于保持当前模块的职责边界清晰。 + * @param value 执行该处理所需的 value 输入。 + * @param issue 执行该处理所需的 issue 输入。 + * @param issues 执行该处理所需的 issues 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private LocalDateTime parse(String value, String issue, List issues) { if (value == null || value.trim().isEmpty()) { issues.add(issue); diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalQueueRecord.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalQueueRecord.java index f7a8670..e8e62d3 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalQueueRecord.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalQueueRecord.java @@ -21,8 +21,28 @@ public final class HistoricalQueueRecord { @JsonProperty("finish_date") private String finishDate; @JsonProperty("agv_id") private String agvId; + /** + * 创建 {@code HistoricalQueueRecord} 实例并初始化其内部状态。 + * + *

该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。 + */ public HistoricalQueueRecord() { } + /** + * 创建 {@code HistoricalQueueRecord} 实例并初始化其内部状态。 + * + *

该方法属于 {@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”信息。 + * + *

该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getGuid() { return guid; } + /** + * 返回当前对象保存的“task no”信息。 + * + *

该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getTaskNo() { return taskNo; } + /** + * 返回当前对象保存的“task type”信息。 + * + *

该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getTaskType() { return taskType; } + /** + * 返回当前对象保存的“priority”信息。 + * + *

该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Integer getPriority() { return priority; } + /** + * 返回当前对象保存的“cargo”信息。 + * + *

该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getCargo() { return cargo; } + /** + * 返回当前对象保存的“issued”信息。 + * + *

该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getIssued() { return issued; } + /** + * 返回当前对象保存的“execution status”信息。 + * + *

该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getExecutionStatus() { return executionStatus; } + /** + * 返回当前对象保存的“start site”信息。 + * + *

该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getStartSite() { return startSite; } + /** + * 返回当前对象保存的“end site”信息。 + * + *

该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getEndSite() { return endSite; } + /** + * 返回当前对象保存的“floor”信息。 + * + *

该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getFloor() { return floor; } + /** + * 返回当前对象保存的“path info”信息。 + * + *

该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getPathInfo() { return pathInfo; } + /** + * 返回当前对象保存的“create date”信息。 + * + *

该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getCreateDate() { return createDate; } + /** + * 返回当前对象保存的“start date”信息。 + * + *

该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getStartDate() { return startDate; } + /** + * 返回当前对象保存的“finish date”信息。 + * + *

该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getFinishDate() { return finishDate; } + /** + * 返回当前对象保存的“agv id”信息。 + * + *

该方法属于 {@code HistoricalQueueRecord},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getAgvId() { return agvId; } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalReplayAnalyzer.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalReplayAnalyzer.java index c1d5dd5..1bd3c67 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalReplayAnalyzer.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalReplayAnalyzer.java @@ -10,6 +10,14 @@ import java.util.List; import java.util.Set; public final class HistoricalReplayAnalyzer { + /** + * 执行“overlaps”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalReplayAnalyzer},用于保持当前模块的职责边界清晰。 + * @param input 执行该处理所需的 input 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List analyze(List input) { List ordered = new ArrayList(input); Collections.sort(ordered, stableOrder()); @@ -60,6 +75,12 @@ public final class HistoricalReplayAnalyzer { return Collections.unmodifiableList(results); } + /** + * 执行“stable order”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalReplayAnalyzer},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private Comparator 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”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalReplayAnalyzer},用于保持当前模块的职责边界清晰。 + * @param left 执行该处理所需的 left 输入。 + * @param right 执行该处理所需的 right 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private List sharedNodes(HistoricalPath left, HistoricalPath right) { Set values = new LinkedHashSet(); Set rightNodes = new LinkedHashSet(right.getNodes()); @@ -78,6 +107,14 @@ public final class HistoricalReplayAnalyzer { return new ArrayList(values); } + /** + * 执行“opposite edges”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalReplayAnalyzer},用于保持当前模块的职责边界清晰。 + * @param left 执行该处理所需的 left 输入。 + * @param right 执行该处理所需的 right 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private List oppositeEdges(HistoricalPath left, HistoricalPath right) { Set rightDirections = new LinkedHashSet(); for (int i = 1; i < right.getNodes().size(); i++) { @@ -94,6 +131,18 @@ public final class HistoricalReplayAnalyzer { return new ArrayList(result); } + /** + * 执行“result”所表示的处理流程。 + * + *

该方法属于 {@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 resources, String reason) { @@ -102,9 +151,24 @@ public final class HistoricalReplayAnalyzer { related == null ? null : related.getRecord().getTaskNo(), resources, reason); } + /** + * 执行“same”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalReplayAnalyzer},用于保持当前模块的职责边界清晰。 + * @param left 执行该处理所需的 left 输入。 + * @param right 执行该处理所需的 right 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private boolean same(String left, String right) { return left != null && left.equals(right); } + /** + * 执行“text”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalReplayAnalyzer},用于保持当前模块的职责边界清晰。 + * @param value 执行该处理所需的 value 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private String text(String value) { return value == null ? "" : value; } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalReplayApplication.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalReplayApplication.java index 489d48d..3804bc9 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalReplayApplication.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalReplayApplication.java @@ -7,8 +7,20 @@ import java.util.ArrayList; import java.util.List; public final class HistoricalReplayApplication { + /** + * 创建 {@code HistoricalReplayApplication} 实例并初始化其内部状态。 + * + *

该方法属于 {@code HistoricalReplayApplication},用于保持当前模块的职责边界清晰。 + */ private HistoricalReplayApplication() { } + /** + * 执行“main”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalReplayApplication},用于保持当前模块的职责边界清晰。 + * @param args 执行该处理所需的 args 输入。 + * @throws Exception 当调用条件不满足或处理无法继续时抛出。 + */ public static void main(String[] args) throws Exception { if (args.length != 1) { throw new IllegalArgumentException("usage: HistoricalReplayApplication "); diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalReplayReportWriter.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalReplayReportWriter.java index d24388f..33fc9cd 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalReplayReportWriter.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalReplayReportWriter.java @@ -19,6 +19,16 @@ import java.util.TreeSet; public final class HistoricalReplayReportWriter { private static final ObjectMapper JSON = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT); + /** + * 执行“write”所表示的处理流程。 + * + *

该方法属于 {@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 paths, List results) throws IOException { Files.createDirectories(outputDir); @@ -73,6 +83,13 @@ public final class HistoricalReplayReportWriter { writeManifest(outputDir); } + /** + * 执行“replay rows”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalReplayReportWriter},用于保持当前模块的职责边界清晰。 + * @param results 执行该处理所需的 results 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private List> replayRows(List results) { List> rows = new ArrayList>(); rows.add(Arrays.asList("创建时间", "完成时间", "车辆", "任务号", "起点", "终点", @@ -91,6 +108,13 @@ public final class HistoricalReplayReportWriter { return rows; } + /** + * 判断当前上下文是否满足“issue rows”条件。 + * + *

该方法属于 {@code HistoricalReplayReportWriter},用于保持当前模块的职责边界清晰。 + * @param paths 执行该处理所需的 paths 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private List> issueRows(List paths) { List> rows = new ArrayList>(); rows.add(Arrays.asList("GUID", "车辆", "任务号", "问题类型", "原始路径", "是否影响回放", "处理方式")); @@ -104,6 +128,14 @@ public final class HistoricalReplayReportWriter { return rows; } + /** + * 执行“write csv”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalReplayReportWriter},用于保持当前模块的职责边界清晰。 + * @param file 执行该处理所需的 file 输入。 + * @param rows 执行该处理所需的 rows 输入。 + * @throws IOException 当调用条件不满足或处理无法继续时抛出。 + */ private void writeCsv(Path file, List> rows) throws IOException { StringBuilder csv = new StringBuilder("\uFEFF"); for (List row : rows) { @@ -116,6 +148,13 @@ public final class HistoricalReplayReportWriter { Files.write(file, csv.toString().getBytes(StandardCharsets.UTF_8)); } + /** + * 执行“write manifest”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalReplayReportWriter},用于保持当前模块的职责边界清晰。 + * @param outputDir 执行该处理所需的 output dir 输入。 + * @throws IOException 当调用条件不满足或处理无法继续时抛出。 + */ private void writeManifest(Path outputDir) throws IOException { List 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”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalReplayReportWriter},用于保持当前模块的职责边界清晰。 + * @param value 执行该处理所需的 value 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private String value(String value) { return value == null ? "" : value; } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalReplayResult.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalReplayResult.java index 5ad5aaf..4410ae7 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalReplayResult.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalReplayResult.java @@ -14,6 +14,18 @@ public final class HistoricalReplayResult { private final List sharedResources; private final String reason; + /** + * 创建 {@code HistoricalReplayResult} 实例并初始化其内部状态。 + * + *

该方法属于 {@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 sharedResources, String reason) { @@ -26,14 +38,63 @@ public final class HistoricalReplayResult { this.reason = reason; } + /** + * 返回当前对象保存的“path”信息。 + * + *

该方法属于 {@code HistoricalReplayResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public HistoricalPath getPath() { return path; } + /** + * 返回当前对象保存的“category”信息。 + * + *

该方法属于 {@code HistoricalReplayResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public HistoricalReplayCategory getCategory() { return category; } + /** + * 返回当前对象保存的“decision”信息。 + * + *

该方法属于 {@code HistoricalReplayResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getDecision() { return decision; } + /** + * 返回当前对象保存的“related agv id”信息。 + * + *

该方法属于 {@code HistoricalReplayResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getRelatedAgvId() { return relatedAgvId; } + /** + * 返回当前对象保存的“related task no”信息。 + * + *

该方法属于 {@code HistoricalReplayResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getRelatedTaskNo() { return relatedTaskNo; } + /** + * 返回当前对象保存的“shared resources”信息。 + * + *

该方法属于 {@code HistoricalReplayResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getSharedResources() { return sharedResources; } + /** + * 返回当前对象保存的“reason”信息。 + * + *

该方法属于 {@code HistoricalReplayResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getReason() { return reason; } + /** + * 比较当前对象与给定对象是否具有相同业务值。 + * + *

该方法属于 {@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”条件。 + * + *

该方法属于 {@code HistoricalReplayResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ @Override public int hashCode() { return Objects.hash(path.getRecord().getGuid(), category, decision, diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/ClearanceMove.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/ClearanceMove.java index b90a285..4e9fdda 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/ClearanceMove.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/ClearanceMove.java @@ -11,24 +11,108 @@ public final class ClearanceMove { private int index; private int protocolAttempts; + /** + * 创建 {@code ClearanceMove} 实例并初始化其内部状态。 + * + *

该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。 + * @param vehicleId 执行该处理所需的 vehicle id 输入。 + * @param ownerTaskId 执行该处理所需的 owner task id 输入。 + * @param route 执行该处理所需的 route 输入。 + */ ClearanceMove(String vehicleId, String ownerTaskId, List route) { this.vehicleId = vehicleId; this.ownerTaskId = ownerTaskId; this.route = Collections.unmodifiableList(new ArrayList(route)); } + /** + * 返回当前对象保存的“vehicle id”信息。 + * + *

该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getVehicleId() { return vehicleId; } + /** + * 返回当前对象保存的“owner task id”信息。 + * + *

该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getOwnerTaskId() { return ownerTaskId; } + /** + * 返回当前对象保存的“source site”信息。 + * + *

该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getSourceSite() { return route.get(0); } + /** + * 返回当前对象保存的“target site”信息。 + * + *

该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getTargetSite() { return route.get(route.size() - 1); } + /** + * 返回当前对象保存的“route”信息。 + * + *

该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getRoute() { return route; } + /** + * 返回当前对象保存的“index”信息。 + * + *

该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getIndex() { return index; } + /** + * 返回当前对象保存的“protocol attempts”信息。 + * + *

该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getProtocolAttempts() { return protocolAttempts; } + /** + * 判断当前上下文是否满足“is complete”条件。 + * + *

该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isComplete() { return index >= route.size() - 1; } + /** + * 执行“current site”所表示的处理流程。 + * + *

该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ String currentSite() { return route.get(index); } + /** + * 执行“next site”所表示的处理流程。 + * + *

该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ String nextSite() { return route.get(index + 1); } + /** + * 执行“moved”所表示的处理流程。 + * + *

该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。 + */ void moved() { index++; } + /** + * 执行“attempted protocol”所表示的处理流程。 + * + *

该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。 + */ void attemptedProtocol() { protocolAttempts++; } + /** + * 执行“clearance task id”所表示的处理流程。 + * + *

该方法属于 {@code ClearanceMove},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ String clearanceTaskId() { return "CLEARANCE:" + ownerTaskId + ":" + vehicleId; } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/ClearanceMovePlanner.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/ClearanceMovePlanner.java index c116e59..e6bbeec 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/ClearanceMovePlanner.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/ClearanceMovePlanner.java @@ -13,6 +13,20 @@ import java.util.Optional; import java.util.Set; public final class ClearanceMovePlanner { + /** + * 为挡住主任务前进方向的空闲车规划临时让路路线,而不改变主任务本身的服务路径。 + * + *

候选目的地必须避开主任务剩余路线、其他车辆位置和已预约节点;在可达候选中先选路径最短, + * 再优先选分支或死端位置,最后以站点编号稳定排序。找不到安全位置时返回空,让调用方继续 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 plan(String vehicleId, String currentSite, String ownerTaskId, List ownerRemainingRoute, Set occupiedSites, @@ -58,6 +72,14 @@ public final class ClearanceMovePlanner { private final List route; private final boolean branch; + /** + * 创建 {@code Candidate} 实例并初始化其内部状态。 + * + *

该方法属于 {@code Candidate},用于保持当前模块的职责边界清晰。 + * @param target 执行该处理所需的 target 输入。 + * @param route 执行该处理所需的 route 输入。 + * @param branch 执行该处理所需的 branch 输入。 + */ private Candidate(String target, List route, boolean branch) { this.target = target; this.route = route; diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/CorridorReservationManager.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/CorridorReservationManager.java index bfa439c..62e3db2 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/CorridorReservationManager.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/CorridorReservationManager.java @@ -16,6 +16,17 @@ public final class CorridorReservationManager { new LinkedHashMap>(); private final Map ranks = new LinkedHashMap(); + /** + * 为一条待执行路线预留走廊方向,防止相向车辆同时进入同一条物理边。 + * + *

边以无向规范键识别、以方向区分。已存在反向持有者时拒绝并返回当前最应优先通过的任务; + * 同向任务可以共享预约。预约成功后保存任务到边的反向索引,供移动、HOLD、完成和重派及时释放。 + * @param taskId 执行该处理所需的 task id 输入。 + * @param route 执行该处理所需的 route 输入。 + * @param effectivePriority 执行该处理所需的 effective priority 输入。 + * @param arrivalMillis 执行该处理所需的 arrival millis 输入。 + * @return 是否取得走廊以及冲突时的优先持有者和业务原因。 + */ public ReservationDecision reserve(String taskId, List 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 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 holders) { List candidates = new ArrayList(); 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} 实例并初始化其内部状态。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@code ReservationDecision},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private static ReservationDecision granted() { return new ReservationDecision(true, null, "GRANTED"); } + /** + * 执行“denied”所表示的处理流程。 + * + *

该方法属于 {@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”条件。 + * + *

该方法属于 {@code ReservationDecision},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isGranted() { return granted; } + /** + * 返回当前对象保存的“owner task id”信息。 + * + *

该方法属于 {@code ReservationDecision},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getOwnerTaskId() { return ownerTaskId; } + /** + * 返回当前对象保存的“reason”信息。 + * + *

该方法属于 {@code ReservationDecision},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getReason() { return reason; } } @@ -128,6 +206,12 @@ public final class CorridorReservationManager { private final int direction; private final Set holders = new LinkedHashSet(); + /** + * 创建 {@code EdgeReservation} 实例并初始化其内部状态。 + * + *

该方法属于 {@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} 实例并初始化其内部状态。 + * + *

该方法属于 {@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} 实例并初始化其内部状态。 + * + *

该方法属于 {@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; diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/DeterministicFaultPlan.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/DeterministicFaultPlan.java index cd5e042..77907f7 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/DeterministicFaultPlan.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/DeterministicFaultPlan.java @@ -16,18 +16,44 @@ public final class DeterministicFaultPlan { private final String vehicleId; private final VehicleEventType type; + /** + * 创建 {@code VehicleEvent} 实例并初始化其内部状态。 + * + *

该方法属于 {@code VehicleEvent},用于保持当前模块的职责边界清晰。 + * @param vehicleId 执行该处理所需的 vehicle id 输入。 + * @param type 执行该处理所需的 type 输入。 + */ private VehicleEvent(String vehicleId, VehicleEventType type) { this.vehicleId = vehicleId; this.type = type; } + /** + * 返回当前对象保存的“vehicle id”信息。 + * + *

该方法属于 {@code VehicleEvent},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getVehicleId() { return vehicleId; } + /** + * 返回当前对象保存的“type”信息。 + * + *

该方法属于 {@code VehicleEvent},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public VehicleEventType getType() { return type; } } private final Map> plcFailures; private final Map> vehicleEvents; + /** + * 创建 {@code DeterministicFaultPlan} 实例并初始化其内部状态。 + * + *

该方法属于 {@code DeterministicFaultPlan},用于保持当前模块的职责边界清晰。 + * @param plcFailures 执行该处理所需的 plc failures 输入。 + * @param vehicleEvents 执行该处理所需的 vehicle events 输入。 + */ private DeterministicFaultPlan( Map> plcFailures, Map> vehicleEvents) { @@ -35,15 +61,42 @@ public final class DeterministicFaultPlan { this.vehicleEvents = vehicleEvents; } + /** + * 执行“builder”所表示的处理流程。 + * + *

该方法属于 {@code DeterministicFaultPlan},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public static Builder builder() { return new Builder(); } + /** + * 执行“none”所表示的处理流程。 + * + *

该方法属于 {@code DeterministicFaultPlan},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public static DeterministicFaultPlan none() { return builder().build(); } + /** + * 执行“plc reason”所表示的处理流程。 + * + *

该方法属于 {@code DeterministicFaultPlan},用于保持当前模块的职责边界清晰。 + * @param taskId 执行该处理所需的 task id 输入。 + * @param attempt 执行该处理所需的 attempt 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ SimulatedPlcGateway.PlcReason plcReason(String taskId, int attempt) { Map byAttempt = plcFailures.get(taskId); return byAttempt == null ? null : byAttempt.get(attempt); } + /** + * 执行“events at”所表示的处理流程。 + * + *

该方法属于 {@code DeterministicFaultPlan},用于保持当前模块的职责边界清晰。 + * @param eventNumber 执行该处理所需的 event number 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List eventsAt(long eventNumber) { List events = vehicleEvents.get(eventNumber); return events == null ? Collections.emptyList() : events; @@ -55,6 +108,15 @@ public final class DeterministicFaultPlan { private final Map> vehicleEvents = new LinkedHashMap>(); + /** + * 执行“plc failure”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@code Builder},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public DeterministicFaultPlan build() { Map> plc = new LinkedHashMap>(); diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationApplication.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationApplication.java index 2fe8fa7..0c79bae 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationApplication.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationApplication.java @@ -7,8 +7,20 @@ import java.nio.file.Path; import java.nio.file.Paths; public final class HistoricalDispatchSimulationApplication { + /** + * 创建 {@code HistoricalDispatchSimulationApplication} 实例并初始化其内部状态。 + * + *

该方法属于 {@code HistoricalDispatchSimulationApplication},用于保持当前模块的职责边界清晰。 + */ private HistoricalDispatchSimulationApplication() { } + /** + * 执行“main”所表示的处理流程。 + * + *

该方法属于 {@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( diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationReportWriter.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationReportWriter.java index 248e7e6..56baeb4 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationReportWriter.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationReportWriter.java @@ -26,6 +26,16 @@ public final class HistoricalDispatchSimulationReportWriter { private static final ObjectMapper MAPPER = new ObjectMapper() .enable(SerializationFeature.INDENT_OUTPUT); + /** + * 输出可审计的历史任务仿真报告,包括摘要、逐任务结果、逐 tick 事件、不变量和校验清单。 + * + *

报告显式声明 {@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 summary(HistoricalQueueDataset dataset, HistoricalDispatchSimulationResult result) { Map value = new LinkedHashMap(); @@ -88,6 +104,11 @@ public final class HistoricalDispatchSimulationReportWriter { return value; } + /** + * 计算等待、完成或历史耗时样本的平均值、P95 和 P99,空样本保持空统计值。 + * @param samples 执行该处理所需的 samples 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private Map timeStats(List samples) { SimulationMetrics metrics = new SimulationMetrics(); Map stats = new LinkedHashMap(); @@ -98,6 +119,13 @@ public final class HistoricalDispatchSimulationReportWriter { return stats; } + /** + * 执行“waiting samples”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalDispatchSimulationReportWriter},用于保持当前模块的职责边界清晰。 + * @param result 执行该处理所需的 result 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private List waitingSamples(HistoricalDispatchSimulationResult result) { List values = new ArrayList(); for (SimulationTaskResult task : result.getTaskResults()) { @@ -106,6 +134,13 @@ public final class HistoricalDispatchSimulationReportWriter { return values; } + /** + * 执行“completion samples”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalDispatchSimulationReportWriter},用于保持当前模块的职责边界清晰。 + * @param result 执行该处理所需的 result 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private List completionSamples(HistoricalDispatchSimulationResult result) { List values = new ArrayList(); for (SimulationTaskResult task : result.getTaskResults()) { @@ -114,6 +149,13 @@ public final class HistoricalDispatchSimulationReportWriter { return values; } + /** + * 执行“historical samples”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalDispatchSimulationReportWriter},用于保持当前模块的职责边界清晰。 + * @param result 执行该处理所需的 result 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private List historicalSamples(HistoricalDispatchSimulationResult result) { List values = new ArrayList(); 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 durationDifferenceSamples(HistoricalDispatchSimulationResult result) { List values = new ArrayList(); 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 aggregateReasons(HistoricalDispatchSimulationResult result, boolean hold) { Map values = new LinkedHashMap(); @@ -148,6 +201,13 @@ public final class HistoricalDispatchSimulationReportWriter { return values; } + /** + * 执行“failure reasons”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalDispatchSimulationReportWriter},用于保持当前模块的职责边界清晰。 + * @param result 执行该处理所需的 result 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private Map failureReasons(HistoricalDispatchSimulationResult result) { Map values = new LinkedHashMap(); for (SimulationTaskResult task : result.getTaskResults()) { @@ -158,6 +218,11 @@ public final class HistoricalDispatchSimulationReportWriter { return values; } + /** + * 导出资源双占、对向冲突、重复归档、重复 WMS 业务效果和死锁等安全断言统计。 + * @param result 执行该处理所需的 result 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private Map invariantSummary(HistoricalDispatchSimulationResult result) { SimulationInvariantSummary source = result.getInvariants(); Map values = new LinkedHashMap(); @@ -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”所表示的处理流程。 + * + *

该方法属于 {@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 names) throws IOException { List ordered = new ArrayList(names); Collections.sort(ordered); @@ -263,6 +363,13 @@ public final class HistoricalDispatchSimulationReportWriter { manifest.toString().getBytes(StandardCharsets.UTF_8)); } + /** + * 执行“sha256”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalDispatchSimulationReportWriter},用于保持当前模块的职责边界清晰。 + * @param value 执行该处理所需的 value 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private String text(String value) { return value == null ? "" : value; } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationResult.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationResult.java index bd32a47..6c7e5cf 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationResult.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationResult.java @@ -17,6 +17,19 @@ public final class HistoricalDispatchSimulationResult { private final long tickCount; private final int acceleration; + /** + * 创建 {@code HistoricalDispatchSimulationResult} 实例并初始化其内部状态。 + * + *

该方法属于 {@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 taskResults, List events, SimulationInvariantSummary invariants, @@ -33,19 +46,91 @@ public final class HistoricalDispatchSimulationResult { this.acceleration = acceleration; } + /** + * 返回当前对象保存的“task results”信息。 + * + *

该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getTaskResults() { return taskResults; } + /** + * 返回当前对象保存的“events”信息。 + * + *

该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getEvents() { return events; } + /** + * 返回当前对象保存的“invariants”信息。 + * + *

该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public SimulationInvariantSummary getInvariants() { return invariants; } + /** + * 返回当前对象保存的“archive count”信息。 + * + *

该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getArchiveCount() { return archiveCount; } + /** + * 返回当前对象保存的“wms delivery attempts”信息。 + * + *

该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getWmsDeliveryAttempts() { return wmsDeliveryAttempts; } + /** + * 返回当前对象保存的“wms business effects”信息。 + * + *

该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getWmsBusinessEffects() { return wmsBusinessEffects; } + /** + * 返回当前对象保存的“tick count”信息。 + * + *

该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getTickCount() { return tickCount; } + /** + * 返回当前对象保存的“acceleration”信息。 + * + *

该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getAcceleration() { return acceleration; } + /** + * 返回当前对象保存的“completed count”信息。 + * + *

该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getCompletedCount() { return count(SimulationTaskStatus.COMPLETED); } + /** + * 返回当前对象保存的“waiting count”信息。 + * + *

该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getWaitingCount() { return count(SimulationTaskStatus.WAITING); } + /** + * 返回当前对象保存的“failed count”信息。 + * + *

该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getFailedCount() { return count(SimulationTaskStatus.FAILED); } + /** + * 返回当前对象保存的“reassignment count”信息。 + * + *

该方法属于 {@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”信息。 + * + *

该方法属于 {@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”信息。 + * + *

该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getRetryCount() { int count = 0; for (SimulationTaskResult result : taskResults) count += result.getRetryCount(); return count; } + /** + * 执行“completed by vehicle”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Map completedByVehicle() { Map counts = new LinkedHashMap(); for (SimulationTaskResult result : taskResults) { @@ -84,6 +187,12 @@ public final class HistoricalDispatchSimulationResult { return Collections.unmodifiableMap(counts); } + /** + * 判断当前上下文是否满足“canonical view”条件。 + * + *

该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String canonicalView() { List ordered = new ArrayList(taskResults); Collections.sort(ordered, Comparator.comparing(SimulationTaskResult::getSimulationTaskId)); @@ -100,6 +209,13 @@ public final class HistoricalDispatchSimulationResult { return value.toString(); } + /** + * 执行“count”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalDispatchSimulationResult},用于保持当前模块的职责边界清晰。 + * @param values 执行该处理所需的 values 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private static List immutable(List values) { return Collections.unmodifiableList(new ArrayList(values)); } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulator.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulator.java index 5ce1205..d926491 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulator.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulator.java @@ -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}。 + * + *

先将 {@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()); } + /** + * 将输入快照转换为可变的车辆运行时状态,供本次调度独立地选车、移动和处理故障。 + * + *

这一步只以初始车位和健康状态为起点;任务历史 {@code agv_id} 不参与强制绑定。 + * @param input 执行该处理所需的 input 输入。 + * @return 以车辆编号索引的运行时车队。 + */ private Map createRuntimes(HistoricalSimulationInput input) { Map runtimes = new LinkedHashMap(); @@ -138,6 +158,14 @@ public final class HistoricalDispatchSimulator { return runtimes; } + /** + * 对初始车位执行容量检查,确保仿真从没有节点双占的交通状态开始。 + * + *

若初始快照本身超过节点容量,只记录不变量违规;后续报告据此暴露输入数据问题。 + * @param vehicles 执行该处理所需的 vehicles 输入。 + * @param ledger 执行该处理所需的 ledger 输入。 + * @param invariants 执行该处理所需的 invariants 输入。 + */ private void occupyInitialNodes(Map vehicles, ResourceLedger ledger, SimulationInvariantSummary invariants) { @@ -151,6 +179,23 @@ public final class HistoricalDispatchSimulator { } } + /** + * 在每个 tick 先施加断线、重启、低电量和车辆故障等确定性事件,并收回失效车辆正在承担的工作。 + * + *

车辆失去可分配资格后,清障动作被暂停;正在执行的任务释放走廊预约、回到原到达时间的队列, + * 同时记录 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 vehicles, Map active, @@ -198,6 +243,28 @@ public final class HistoricalDispatchSimulator { return changed; } + /** + * 为已到达的历史任务执行中心调度:重新规划服务路径、筛选可用车队、自动选车并申请走廊方向预约。 + * + *

源到目标无路时直接关闭为 {@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 vehicles, @@ -284,6 +351,16 @@ public final class HistoricalDispatchSimulator { return progress; } + /** + * 判断车队是否还有任意车辆能抵达任务源点,用于区分暂时等车和永久无路两种情况。 + * + *

该检查不要求车辆当前健康可分配,因为断线或低电量车辆恢复后仍可能服务该任务。 + * @param task 执行该处理所需的 task 输入。 + * @param vehicles 执行该处理所需的 vehicles 输入。 + * @param input 执行该处理所需的 input 输入。 + * @param planner 执行该处理所需的 planner 输入。 + * @return 存在通往源点的车队路径时返回 {@code true}。 + */ private boolean fleetCanReach(HistoricalSimulationTask task, Map vehicles, HistoricalSimulationInput input, @@ -295,6 +372,35 @@ public final class HistoricalDispatchSimulator { return false; } + /** + * 推进全部已分配任务的下一条边,并在移动前依次执行方向冲突、清障、交通决策、资源台账和 PLC 确认。 + * + *

同 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 约束。 + * + *

清障车不是特权车辆:对向窗口、决策拒绝、资源拒绝或 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); } + /** + * 为阻塞主任务目标节点的空闲车挑选一条安全的临时让路路线。 + * + *

仅处理健康、未执行任务、也未参与其他清障的车辆;规划器避开主任务剩余路径、已占节点和已预约资源。 + * 规划成功立即登记清障动作并记录 {@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 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 idleVehiclesAt(String siteId, String movingVehicleId, Map vehicles, Map active, @@ -580,12 +731,35 @@ public final class HistoricalDispatchSimulator { return blockers; } + /** + * 按等待时长计算活动任务的有效优先级,使重复 HOLD 的低优先级任务不会永久饥饿。 + * + *

数值越小优先级越高;每经过一个老化区间减一,最低为零,与等待队列的排序规则保持一致。 + * @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 达阈值时撤销当前分配、释放走廊并回队重新调度。 + * + *

重派保留原始到达时间和历史业务字段,但允许中心重新选择车辆和路径,避免单车长期占住任务。 + * @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 active, @@ -606,6 +780,24 @@ public final class HistoricalDispatchSimulator { } } + /** + * 将已抵达终点的任务关闭为完成,并完成走廊释放、队列归档及幂等 WMS 完成回调。 + * + *

同一任务故意向 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 active, @@ -631,6 +823,18 @@ public final class HistoricalDispatchSimulator { "ARCHIVED_WMS_ACK", vehicle.getCurrentSite(), vehicle.getCurrentSite())); } + /** + * 在异常收敛或报告截点将尚未关闭的排队、活动任务快照为等待状态。 + * + *

该方法只生成可诊断的终态结果,不能把任务标为完成,也不会修改车辆位置或资源所有权。 + * @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 active, Map executions, @@ -652,6 +856,18 @@ public final class HistoricalDispatchSimulator { } } + /** + * 汇总一个任务在本次仿真中的调度轨迹和终态,用于历史对比及最终统计。 + * + *

结果包含实际被中心选中的车辆、重新规划的服务路径、等待/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); } + /** + * 校验资源台账没有超过节点或边的配置容量,并把双占问题记入仿真不变量。 + * + *

台账是资源保护的权威记录;该校验不修改占用,只确保报告能揭示资源双占或容量越界。 + * @param ledger 执行该处理所需的 ledger 输入。 + * @param invariants 执行该处理所需的 invariants 输入。 + */ private void verifyLedger(ResourceLedger ledger, SimulationInvariantSummary invariants) { for (Map.Entry> 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”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalDispatchSimulator},用于保持当前模块的职责边界清晰。 + * @param values 执行该处理所需的 values 输入。 + * @param key 执行该处理所需的 key 输入。 + */ private static void increment(Map 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 retryReasons = new LinkedHashMap(); + /** + * 创建 {@code Execution} 实例并初始化其内部状态。 + * + *

该方法属于 {@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} 实例并初始化其内部状态。 + * + *

该方法属于 {@code ActiveTask},用于保持当前模块的职责边界清晰。 + * @param execution 执行该处理所需的 execution 输入。 + * @param route 执行该处理所需的 route 输入。 + */ private ActiveTask(Execution execution, List route) { this.execution = execution; this.route = Collections.unmodifiableList(new ArrayList(route)); @@ -732,6 +998,13 @@ public final class HistoricalDispatchSimulator { private final boolean moved; private final boolean completed; + /** + * 创建 {@code ClearanceProgress} 实例并初始化其内部状态。 + * + *

该方法属于 {@code ClearanceProgress},用于保持当前模块的职责边界清晰。 + * @param moved 执行该处理所需的 moved 输入。 + * @param completed 执行该处理所需的 completed 输入。 + */ private ClearanceProgress(boolean moved, boolean completed) { this.moved = moved; this.completed = completed; diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalGridMapCompiler.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalGridMapCompiler.java index ba7a4ab..332fdfe 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalGridMapCompiler.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalGridMapCompiler.java @@ -17,6 +17,14 @@ import java.util.Map; import java.util.Set; public final class HistoricalGridMapCompiler { + /** + * 从完整历史地图编译可通行网格和交通资源图,而不是只截取历史 {@code path_info} 经过的节点。 + * + *

仅值为 1 或 2 的单元可通行;站点编号与三维坐标必须唯一。编译器只连接相邻的右侧和上侧单元, + * 由无向连接形成完整路网,并计算连通分量供任务端点预检。重复、空站点或空地图会作为无效地图拒绝。 + * @param cells 执行该处理所需的 cells 输入。 + * @return 同时供路径规划和交通裁决使用的网格、资源图及连通性索引。 + */ public CompiledHistoricalMap compile(List 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 trafficEdges, HistoricalMapCell left, HistoricalMapCell right) { @@ -70,6 +85,11 @@ public final class HistoricalGridMapCompiler { left.getSiteId(), right.getSiteId())); } + /** + * 使用广度优先遍历为可通行站点编号连通分量,提前识别跨断开地图的无路任务。 + * @param map 执行该处理所需的 map 输入。 + * @return 站点到连通分量编号的稳定映射。 + */ private Map components(GridMap map) { Map result = new LinkedHashMap(); List ids = new ArrayList(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 passableSites; private final Map componentIds; + /** + * 创建 {@code CompiledHistoricalMap} 实例并初始化其内部状态。 + * + *

该方法属于 {@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 passableSites, Map componentIds) { @@ -115,10 +151,35 @@ public final class HistoricalGridMapCompiler { new LinkedHashMap(componentIds)); } + /** + * 返回当前对象保存的“grid map”信息。 + * + *

该方法属于 {@code CompiledHistoricalMap},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public GridMap getGridMap() { return gridMap; } + /** + * 返回当前对象保存的“traffic map”信息。 + * + *

该方法属于 {@code CompiledHistoricalMap},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public EffectiveTrafficMap getTrafficMap() { return trafficMap; } + /** + * 返回当前对象保存的“passable sites”信息。 + * + *

该方法属于 {@code CompiledHistoricalMap},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Map getPassableSites() { return passableSites; } + /** + * 返回当前对象保存的“component id”信息。 + * + *

该方法属于 {@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); diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationFailure.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationFailure.java index 5e84a10..e572c82 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationFailure.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationFailure.java @@ -7,6 +7,14 @@ public final class HistoricalSimulationFailure { private final HistoricalQueueRecord record; private final String reason; + /** + * 创建 {@code HistoricalSimulationFailure} 实例并初始化其内部状态。 + * + *

该方法属于 {@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”信息。 + * + *

该方法属于 {@code HistoricalSimulationFailure},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getSimulationTaskId() { return simulationTaskId; } + /** + * 返回当前对象保存的“record”信息。 + * + *

该方法属于 {@code HistoricalSimulationFailure},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public HistoricalQueueRecord getRecord() { return record; } + /** + * 返回当前对象保存的“reason”信息。 + * + *

该方法属于 {@code HistoricalSimulationFailure},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getReason() { return reason; } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationInput.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationInput.java index 5aed57d..df0430f 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationInput.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationInput.java @@ -15,6 +15,16 @@ public final class HistoricalSimulationInput { private final EffectiveTrafficMap trafficMap; private final List initialVehicles; + /** + * 创建 {@code HistoricalSimulationInput} 实例并初始化其内部状态。 + * + *

该方法属于 {@code HistoricalSimulationInput},用于保持当前模块的职责边界清晰。 + * @param tasks 执行该处理所需的 tasks 输入。 + * @param failedInputs 执行该处理所需的 failed inputs 输入。 + * @param gridMap 执行该处理所需的 grid map 输入。 + * @param trafficMap 执行该处理所需的 traffic map 输入。 + * @param initialVehicles 执行该处理所需的 initial vehicles 输入。 + */ HistoricalSimulationInput(List tasks, List failedInputs, GridMap gridMap, EffectiveTrafficMap trafficMap, @@ -26,12 +36,48 @@ public final class HistoricalSimulationInput { this.initialVehicles = immutable(initialVehicles); } + /** + * 返回当前对象保存的“tasks”信息。 + * + *

该方法属于 {@code HistoricalSimulationInput},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getTasks() { return tasks; } + /** + * 返回当前对象保存的“failed inputs”信息。 + * + *

该方法属于 {@code HistoricalSimulationInput},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getFailedInputs() { return failedInputs; } + /** + * 返回当前对象保存的“grid map”信息。 + * + *

该方法属于 {@code HistoricalSimulationInput},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public GridMap getGridMap() { return gridMap; } + /** + * 返回当前对象保存的“traffic map”信息。 + * + *

该方法属于 {@code HistoricalSimulationInput},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public EffectiveTrafficMap getTrafficMap() { return trafficMap; } + /** + * 返回当前对象保存的“initial vehicles”信息。 + * + *

该方法属于 {@code HistoricalSimulationInput},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getInitialVehicles() { return initialVehicles; } + /** + * 执行“all simulation ids”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalSimulationInput},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List allSimulationIds() { List ids = new ArrayList(); for (HistoricalSimulationTask task : tasks) ids.add(task.getSimulationTaskId()); @@ -41,6 +87,13 @@ public final class HistoricalSimulationInput { return Collections.unmodifiableList(ids); } + /** + * 执行“immutable”所表示的处理流程。 + * + *

该方法属于 {@code HistoricalSimulationInput},用于保持当前模块的职责边界清晰。 + * @param source 执行该处理所需的 source 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private static List immutable(List source) { return Collections.unmodifiableList(new ArrayList(source)); } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationInputFactory.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationInputFactory.java index fb9ba1b..cbfc9f2 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationInputFactory.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationInputFactory.java @@ -13,6 +13,15 @@ import java.util.Comparator; import java.util.List; public final class HistoricalSimulationInputFactory { + /** + * 将历史队列和完整地图转换为中心调度可直接执行的仿真输入。 + * + *

历史记录先规范化并按 {@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 initialVehicles( HistoricalGridMapCompiler.CompiledHistoricalMap compiled) { List vehicles = new ArrayList(); @@ -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; } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationTask.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationTask.java index 21dcd4c..33f676c 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationTask.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationTask.java @@ -20,6 +20,21 @@ public final class HistoricalSimulationTask { private final List historicalNodes; private final int arrivalSequence; + /** + * 创建 {@code HistoricalSimulationTask} 实例并初始化其内部状态。 + * + *

该方法属于 {@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”信息。 + * + *

该方法属于 {@code HistoricalSimulationTask},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getSimulationTaskId() { return simulationTaskId; } + /** + * 返回当前对象保存的“record”信息。 + * + *

该方法属于 {@code HistoricalSimulationTask},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public HistoricalQueueRecord getRecord() { return record; } + /** + * 返回当前对象保存的“task type”信息。 + * + *

该方法属于 {@code HistoricalSimulationTask},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public DispatchTask.TaskType getTaskType() { return taskType; } + /** + * 返回当前对象保存的“priority”信息。 + * + *

该方法属于 {@code HistoricalSimulationTask},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getPriority() { return priority; } + /** + * 返回当前对象保存的“created at”信息。 + * + *

该方法属于 {@code HistoricalSimulationTask},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public LocalDateTime getCreatedAt() { return createdAt; } + /** + * 返回当前对象保存的“historical finished at”信息。 + * + *

该方法属于 {@code HistoricalSimulationTask},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public LocalDateTime getHistoricalFinishedAt() { return historicalFinishedAt; } + /** + * 返回当前对象保存的“physical source”信息。 + * + *

该方法属于 {@code HistoricalSimulationTask},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getPhysicalSource() { return physicalSource; } + /** + * 返回当前对象保存的“physical target”信息。 + * + *

该方法属于 {@code HistoricalSimulationTask},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getPhysicalTarget() { return physicalTarget; } + /** + * 返回当前对象保存的“historical nodes”信息。 + * + *

该方法属于 {@code HistoricalSimulationTask},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getHistoricalNodes() { return historicalNodes; } + /** + * 返回当前对象保存的“arrival sequence”信息。 + * + *

该方法属于 {@code HistoricalSimulationTask},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getArrivalSequence() { return arrivalSequence; } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/IdempotentWmsCompletionReceiver.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/IdempotentWmsCompletionReceiver.java index 8442291..552d430 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/IdempotentWmsCompletionReceiver.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/IdempotentWmsCompletionReceiver.java @@ -8,6 +8,13 @@ public final class IdempotentWmsCompletionReceiver { private final Set completedTaskIds = new LinkedHashSet(); private int deliveryAttempts; + /** + * 接收一次 WMS 完成回调,记录投递次数但只允许每个任务产生一次完成业务效果。 + * + *

模拟器会刻意重复投递以验证幂等性,因此“收到两次”是可预期传输行为,不等于重复归档或重复完成。 + * @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”信息。 + * + *

该方法属于 {@code IdempotentWmsCompletionReceiver},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getDeliveryAttempts() { return deliveryAttempts; } + /** + * 返回当前对象保存的“business effects”信息。 + * + *

该方法属于 {@code IdempotentWmsCompletionReceiver},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getBusinessEffects() { return completedTaskIds.size(); } + /** + * 返回当前对象保存的“completed task ids”信息。 + * + *

该方法属于 {@code IdempotentWmsCompletionReceiver},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Set getCompletedTaskIds() { return Collections.unmodifiableSet(completedTaskIds); } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/PhysicalEndpointResolver.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/PhysicalEndpointResolver.java index c1818a9..53506c8 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/PhysicalEndpointResolver.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/PhysicalEndpointResolver.java @@ -6,6 +6,15 @@ import com.ft546.wcs.shadow.history.HistoricalQueueRecord; import java.util.Map; public final class PhysicalEndpointResolver { + /** + * 将历史记录中的逻辑起终点解析成完整地图中的实际可通行站点。 + * + *

源点所在 z 坐标决定物理楼层;历史 {@code floor} 只作为一致性诊断。终点写为 {@code tsj} 时按该 + * 物理楼层映射到 {@code 07050}。未知源点或目标点直接关闭输入,避免调度器对不存在的地图节点规划。 + * @param record 执行该处理所需的 record 输入。 + * @param passableSites 执行该处理所需的 passable sites 输入。 + * @return 物理起终点、解析楼层以及历史楼层字段的一致性标记。 + */ public ResolvedEndpoints resolve(HistoricalQueueRecord record, Map passableSites) { if (record == null || passableSites == null) { @@ -40,6 +49,15 @@ public final class PhysicalEndpointResolver { private final int floor; private final boolean declaredFloorConsistent; + /** + * 创建 {@code ResolvedEndpoints} 实例并初始化其内部状态。 + * + *

该方法属于 {@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”信息。 + * + *

该方法属于 {@code ResolvedEndpoints},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getSource() { return source; } + /** + * 返回当前对象保存的“target”信息。 + * + *

该方法属于 {@code ResolvedEndpoints},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getTarget() { return target; } + /** + * 返回当前对象保存的“floor”信息。 + * + *

该方法属于 {@code ResolvedEndpoints},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getFloor() { return floor; } + /** + * 判断当前上下文是否满足“is declared floor consistent”条件。 + * + *

该方法属于 {@code ResolvedEndpoints},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isDeclaredFloorConsistent() { return declaredFloorConsistent; } } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulatedPlcGateway.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulatedPlcGateway.java index 77cf8f4..6c515c8 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulatedPlcGateway.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulatedPlcGateway.java @@ -18,6 +18,18 @@ public final class SimulatedPlcGateway { private final long bootId; private final PlcReason reason; + /** + * 创建 {@code PlcResponse} 实例并初始化其内部状态。 + * + *

该方法属于 {@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”信息。 + * + *

该方法属于 {@code PlcResponse},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getTaskId() { return taskId; } + /** + * 返回当前对象保存的“vehicle id”信息。 + * + *

该方法属于 {@code PlcResponse},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getVehicleId() { return vehicleId; } + /** + * 返回当前对象保存的“from”信息。 + * + *

该方法属于 {@code PlcResponse},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getFrom() { return from; } + /** + * 返回当前对象保存的“to”信息。 + * + *

该方法属于 {@code PlcResponse},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getTo() { return to; } + /** + * 返回当前对象保存的“attempt”信息。 + * + *

该方法属于 {@code PlcResponse},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getAttempt() { return attempt; } + /** + * 返回当前对象保存的“boot id”信息。 + * + *

该方法属于 {@code PlcResponse},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getBootId() { return bootId; } + /** + * 返回当前对象保存的“reason”信息。 + * + *

该方法属于 {@code PlcResponse},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public PlcReason getReason() { return reason; } } private final DeterministicFaultPlan faults; private final Map attempts = new LinkedHashMap(); + /** + * 创建 PLC 协议模拟器,并绑定确定性故障计划以便重复测试发送、超时和丢 ACK 场景。 + * @param faults 执行该处理所需的 faults 输入。 + */ public SimulatedPlcGateway(DeterministicFaultPlan faults) { if (faults == null) throw new IllegalArgumentException("fault plan is required"); this.faults = faults; } + /** + * 模拟向 PLC 下发一条车辆移动命令,并按任务累计发送次数返回计划中的协议结果。 + * + *

默认结果是 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”信息。 + * + *

该方法属于 {@code SimulatedPlcGateway},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Map getAttempts() { return Collections.unmodifiableMap(attempts); } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulatedVehicleRuntime.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulatedVehicleRuntime.java index c735e4e..1747370 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulatedVehicleRuntime.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulatedVehicleRuntime.java @@ -12,6 +12,14 @@ public final class SimulatedVehicleRuntime { private boolean synchronizedAfterBoot = true; private long bootId = 1L; + /** + * 创建 {@code SimulatedVehicleRuntime} 实例并初始化其内部状态。 + * + *

该方法属于 {@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”信息。 + * + *

该方法属于 {@code SimulatedVehicleRuntime},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getVehicleId() { return vehicleId; } + /** + * 返回当前对象保存的“current site”信息。 + * + *

该方法属于 {@code SimulatedVehicleRuntime},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getCurrentSite() { return currentSite; } + /** + * 返回当前对象保存的“floor”信息。 + * + *

该方法属于 {@code SimulatedVehicleRuntime},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getFloor() { return floor; } + /** + * 返回当前对象保存的“battery”信息。 + * + *

该方法属于 {@code SimulatedVehicleRuntime},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getBattery() { return battery; } + /** + * 返回当前对象保存的“boot id”信息。 + * + *

该方法属于 {@code SimulatedVehicleRuntime},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getBootId() { return bootId; } + /** + * 判断当前上下文是否满足“is connected”条件。 + * + *

该方法属于 {@code SimulatedVehicleRuntime},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isConnected() { return connected; } + /** + * 判断当前上下文是否满足“is faulted”条件。 + * + *

该方法属于 {@code SimulatedVehicleRuntime},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isFaulted() { return faulted; } + /** + * 判断当前上下文是否满足“is synchronized after boot”条件。 + * + *

该方法属于 {@code SimulatedVehicleRuntime},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isSynchronizedAfterBoot() { return synchronizedAfterBoot; } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationArchive.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationArchive.java index fb9637a..9d9026f 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationArchive.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationArchive.java @@ -10,27 +10,74 @@ public final class SimulationArchive { private final String vehicleId; private final long completedAtMillis; + /** + * 创建 {@code ArchiveRecord} 实例并初始化其内部状态。 + * + *

该方法属于 {@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”信息。 + * + *

该方法属于 {@code ArchiveRecord},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getTaskId() { return taskId; } + /** + * 返回当前对象保存的“vehicle id”信息。 + * + *

该方法属于 {@code ArchiveRecord},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getVehicleId() { return vehicleId; } + /** + * 返回当前对象保存的“completed at millis”信息。 + * + *

该方法属于 {@code ArchiveRecord},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getCompletedAtMillis() { return completedAtMillis; } } private final Map records = new LinkedHashMap(); + /** + * 将已实际完成的任务写入队列归档;同一任务只能归档一次。 + * + *

返回值让调用方将重复归档尝试记入不变量,而不是覆盖原来的完成车辆和完成时刻。 + * @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”所表示的处理流程。 + * + *

该方法属于 {@code SimulationArchive},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int size() { return records.size(); } + /** + * 返回当前对象保存的“records”信息。 + * + *

该方法属于 {@code SimulationArchive},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Map getRecords() { return Collections.unmodifiableMap(records); } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationClock.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationClock.java index 7f45d64..29e445b 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationClock.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationClock.java @@ -13,6 +13,13 @@ public final class SimulationClock { private final int acceleration; private final Map arrivals; + /** + * 将历史 {@code create_date} 序列映射为加速后的仿真时钟,保留任务先后关系但压缩等待间隔。 + * + *

仅允许 10 倍或 100 倍;最早任务映射到零时刻,后续任务相对最早时间的间隔按倍率缩短。 + * @param sourceArrivals 执行该处理所需的 source arrivals 输入。 + * @param acceleration 执行该处理所需的 acceleration 输入。 + */ public SimulationClock(List 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”信息。 + * + *

该方法属于 {@code SimulationClock},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getAcceleration() { return acceleration; } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationConfig.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationConfig.java index b5b082a..2a7126f 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationConfig.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationConfig.java @@ -7,6 +7,16 @@ public final class SimulationConfig { private final int noProgressLimit; private final int tickLimit; + /** + * 创建 {@code SimulationConfig} 实例并初始化其内部状态。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@code SimulationConfig},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public static SimulationConfig defaults() { return new SimulationConfig(100, 30_000L, 3, 500, 20_000); } + /** + * 返回当前对象保存的“acceleration”信息。 + * + *

该方法属于 {@code SimulationConfig},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getAcceleration() { return acceleration; } + /** + * 返回当前对象保存的“aging interval millis”信息。 + * + *

该方法属于 {@code SimulationConfig},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getAgingIntervalMillis() { return agingIntervalMillis; } + /** + * 返回当前对象保存的“retry limit”信息。 + * + *

该方法属于 {@code SimulationConfig},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getRetryLimit() { return retryLimit; } + /** + * 返回当前对象保存的“no progress limit”信息。 + * + *

该方法属于 {@code SimulationConfig},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getNoProgressLimit() { return noProgressLimit; } + /** + * 返回当前对象保存的“tick limit”信息。 + * + *

该方法属于 {@code SimulationConfig},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getTickLimit() { return tickLimit; } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationInvariantSummary.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationInvariantSummary.java index a2f80e4..1f114bc 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationInvariantSummary.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationInvariantSummary.java @@ -8,20 +8,92 @@ public final class SimulationInvariantSummary { private int duplicateWmsBusinessEffects; private int deadlocks; + /** + * 执行“capacity violation”所表示的处理流程。 + * + *

该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。 + */ void capacityViolation() { capacityViolations++; } + /** + * 执行“node double occupancy violation”所表示的处理流程。 + * + *

该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。 + */ void nodeDoubleOccupancyViolation() { nodeDoubleOccupancyViolations++; } + /** + * 执行“opposite edge violation”所表示的处理流程。 + * + *

该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。 + */ void oppositeEdgeViolation() { oppositeEdgeViolations++; } + /** + * 执行“duplicate archive attempt”所表示的处理流程。 + * + *

该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。 + */ void duplicateArchiveAttempt() { duplicateArchiveAttempts++; } + /** + * 执行“duplicate wms business effect”所表示的处理流程。 + * + *

该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。 + */ void duplicateWmsBusinessEffect() { duplicateWmsBusinessEffects++; } + /** + * 执行“deadlock”所表示的处理流程。 + * + *

该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。 + */ void deadlock() { deadlocks++; } + /** + * 返回当前对象保存的“capacity violations”信息。 + * + *

该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getCapacityViolations() { return capacityViolations; } + /** + * 返回当前对象保存的“node double occupancy violations”信息。 + * + *

该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getNodeDoubleOccupancyViolations() { return nodeDoubleOccupancyViolations; } + /** + * 返回当前对象保存的“opposite edge violations”信息。 + * + *

该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getOppositeEdgeViolations() { return oppositeEdgeViolations; } + /** + * 返回当前对象保存的“duplicate archive attempts”信息。 + * + *

该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getDuplicateArchiveAttempts() { return duplicateArchiveAttempts; } + /** + * 返回当前对象保存的“duplicate wms business effects”信息。 + * + *

该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getDuplicateWmsBusinessEffects() { return duplicateWmsBusinessEffects; } + /** + * 返回当前对象保存的“deadlocks”信息。 + * + *

该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getDeadlocks() { return deadlocks; } + /** + * 执行“total safety violations”所表示的处理流程。 + * + *

该方法属于 {@code SimulationInvariantSummary},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int totalSafetyViolations() { return capacityViolations + nodeDoubleOccupancyViolations + oppositeEdgeViolations + duplicateArchiveAttempts diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationMetrics.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationMetrics.java index 03d3fa6..69e1a16 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationMetrics.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationMetrics.java @@ -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 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 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”所表示的处理流程。 + * + *

该方法属于 {@code SimulationMetrics},用于保持当前模块的职责边界清晰。 + * @param samples 执行该处理所需的 samples 输入。 + */ private void validate(List samples) { if (samples == null || samples.contains(null)) { throw new IllegalArgumentException("non-null samples are required"); diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationProgressWatchdog.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationProgressWatchdog.java index 7fac7bb..d03a5bc 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationProgressWatchdog.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationProgressWatchdog.java @@ -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 是否出现任务关闭、车辆移动或清障完成;连续无物理进展达到阈值即报告死锁。 + * + *

终态数量必须单调,防止异常路径把已关闭任务重新当成未完成任务。 + * @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) { diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationTaskQueue.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationTaskQueue.java index f7fdbef..ac3d8e1 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationTaskQueue.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationTaskQueue.java @@ -12,6 +12,10 @@ public final class SimulationTaskQueue { private final Map entries = new LinkedHashMap(); private final Map originalArrivals = new LinkedHashMap(); + /** + * 创建按历史到达时间、业务优先级和老化规则排序的调度等待队列。 + * @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; } + /** + * 返回当前仿真时刻已经到达的任务,并按有效优先级、到达时间和历史标识稳定排序。 + * + *

有效优先级会随等待时间改善,故先进入系统的低优先级任务最终能越过长期占用的高优先级任务, + * 从而实现饥饿保护。 + * @param nowMillis 执行该处理所需的 now millis 输入。 + * @return 本 tick 可由中心调度尝试选车的稳定有序任务列表。 + */ public List readyAt(final long nowMillis) { List ready = new ArrayList(); for (Entry entry : entries.values()) { @@ -58,33 +84,75 @@ public final class SimulationTaskQueue { return Collections.unmodifiableList(result); } + /** + * 判断当前上下文是否满足“is empty”条件。 + * + *

该方法属于 {@code SimulationTaskQueue},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isEmpty() { return entries.isEmpty(); } + /** + * 执行“size”所表示的处理流程。 + * + *

该方法属于 {@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} 实例并初始化其内部状态。 + * + *

该方法属于 {@code Entry},用于保持当前模块的职责边界清晰。 + * @param task 执行该处理所需的 task 输入。 + * @param arrivalMillis 执行该处理所需的 arrival millis 输入。 + */ private Entry(HistoricalSimulationTask task, long arrivalMillis) { this.task = task; this.arrivalMillis = arrivalMillis; diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationTaskResult.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationTaskResult.java index 3eeac0e..a3dec14 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationTaskResult.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationTaskResult.java @@ -25,6 +25,26 @@ public final class SimulationTaskResult { private final Map holdReasons; private final Map retryReasons; + /** + * 创建 {@code SimulationTaskResult} 实例并初始化其内部状态。 + * + *

该方法属于 {@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 plannedPath, @@ -50,32 +70,148 @@ public final class SimulationTaskResult { this.retryReasons = immutableMap(retryReasons); } + /** + * 返回当前对象保存的“simulation task id”信息。 + * + *

该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getSimulationTaskId() { return simulationTaskId; } + /** + * 返回当前对象保存的“record”信息。 + * + *

该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public HistoricalQueueRecord getRecord() { return record; } + /** + * 返回当前对象保存的“status”信息。 + * + *

该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public SimulationTaskStatus getStatus() { return status; } + /** + * 返回当前对象保存的“reason”信息。 + * + *

该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getReason() { return reason; } + /** + * 返回当前对象保存的“simulated vehicle id”信息。 + * + *

该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getSimulatedVehicleId() { return simulatedVehicleId; } + /** + * 返回当前对象保存的“planned path”信息。 + * + *

该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getPlannedPath() { return plannedPath; } + /** + * 返回当前对象保存的“assigned vehicles”信息。 + * + *

该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getAssignedVehicles() { return assignedVehicles; } + /** + * 返回当前对象保存的“arrival millis”信息。 + * + *

该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getArrivalMillis() { return arrivalMillis; } + /** + * 返回当前对象保存的“first assigned millis”信息。 + * + *

该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Long getFirstAssignedMillis() { return firstAssignedMillis; } + /** + * 返回当前对象保存的“completed millis”信息。 + * + *

该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Long getCompletedMillis() { return completedMillis; } + /** + * 返回当前对象保存的“hold count”信息。 + * + *

该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getHoldCount() { return holdCount; } + /** + * 返回当前对象保存的“protocol attempts”信息。 + * + *

该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getProtocolAttempts() { return protocolAttempts; } + /** + * 返回当前对象保存的“retry count”信息。 + * + *

该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public int getRetryCount() { return retryCount; } + /** + * 返回当前对象保存的“hold reasons”信息。 + * + *

该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Map getHoldReasons() { return holdReasons; } + /** + * 返回当前对象保存的“retry reasons”信息。 + * + *

该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Map getRetryReasons() { return retryReasons; } + /** + * 返回当前对象保存的“waiting millis”信息。 + * + *

该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Long getWaitingMillis() { return firstAssignedMillis == null ? null : firstAssignedMillis - arrivalMillis; } + /** + * 返回当前对象保存的“completion millis”信息。 + * + *

该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Long getCompletionMillis() { return completedMillis == null ? null : completedMillis - arrivalMillis; } + /** + * 执行“immutable”所表示的处理流程。 + * + *

该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。 + * @param values 执行该处理所需的 values 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private static List immutable(List values) { return Collections.unmodifiableList(new ArrayList(values)); } + /** + * 执行“immutable map”所表示的处理流程。 + * + *

该方法属于 {@code SimulationTaskResult},用于保持当前模块的职责边界清晰。 + * @param values 执行该处理所需的 values 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private static Map immutableMap(Map values) { return Collections.unmodifiableMap(new LinkedHashMap(values)); } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationTickEvent.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationTickEvent.java index 4c39460..8e05c8d 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationTickEvent.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationTickEvent.java @@ -10,6 +10,19 @@ public final class SimulationTickEvent { private final String fromSite; private final String toSite; + /** + * 创建 {@code SimulationTickEvent} 实例并初始化其内部状态。 + * + *

该方法属于 {@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”信息。 + * + *

该方法属于 {@code SimulationTickEvent},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getTick() { return tick; } + /** + * 返回当前对象保存的“simulation millis”信息。 + * + *

该方法属于 {@code SimulationTickEvent},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getSimulationMillis() { return simulationMillis; } + /** + * 返回当前对象保存的“type”信息。 + * + *

该方法属于 {@code SimulationTickEvent},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getType() { return type; } + /** + * 返回当前对象保存的“task id”信息。 + * + *

该方法属于 {@code SimulationTickEvent},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getTaskId() { return taskId; } + /** + * 返回当前对象保存的“vehicle id”信息。 + * + *

该方法属于 {@code SimulationTickEvent},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getVehicleId() { return vehicleId; } + /** + * 返回当前对象保存的“reason”信息。 + * + *

该方法属于 {@code SimulationTickEvent},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getReason() { return reason; } + /** + * 返回当前对象保存的“from site”信息。 + * + *

该方法属于 {@code SimulationTickEvent},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getFromSite() { return fromSite; } + /** + * 返回当前对象保存的“to site”信息。 + * + *

该方法属于 {@code SimulationTickEvent},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getToSite() { return toSite; } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/map/EffectiveTrafficMap.java b/javaTest/src/main/java/com/ft546/wcs/shadow/map/EffectiveTrafficMap.java index 9566703..2f26854 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/map/EffectiveTrafficMap.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/map/EffectiveTrafficMap.java @@ -19,6 +19,20 @@ public final class EffectiveTrafficMap { private final Set safeWaitSites; private final Set safeYieldSites; + /** + * 创建 {@code EffectiveTrafficMap} 实例并初始化其内部状态。 + * + *

该方法属于 {@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 nodes, Set edges, Map capacities, Set safeWaitSites, Set safeYieldSites) { @@ -33,13 +47,67 @@ public final class EffectiveTrafficMap { this.safeYieldSites = Collections.unmodifiableSet(new LinkedHashSet(safeYieldSites)); } + /** + * 返回当前对象保存的“map code”信息。 + * + *

该方法属于 {@code EffectiveTrafficMap},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getMapCode() { return mapCode; } + /** + * 返回当前对象保存的“version id”信息。 + * + *

该方法属于 {@code EffectiveTrafficMap},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getVersionId() { return versionId; } + /** + * 返回当前对象保存的“zone code”信息。 + * + *

该方法属于 {@code EffectiveTrafficMap},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getZoneCode() { return zoneCode; } + /** + * 返回当前对象保存的“checksum”信息。 + * + *

该方法属于 {@code EffectiveTrafficMap},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getChecksum() { return checksum; } + /** + * 返回当前对象保存的“nodes”信息。 + * + *

该方法属于 {@code EffectiveTrafficMap},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Set getNodes() { return nodes; } + /** + * 返回当前对象保存的“edges”信息。 + * + *

该方法属于 {@code EffectiveTrafficMap},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Set getEdges() { return edges; } + /** + * 返回当前对象保存的“capacities”信息。 + * + *

该方法属于 {@code EffectiveTrafficMap},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Map getCapacities() { return capacities; } + /** + * 返回当前对象保存的“safe wait sites”信息。 + * + *

该方法属于 {@code EffectiveTrafficMap},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Set getSafeWaitSites() { return safeWaitSites; } + /** + * 返回当前对象保存的“safe yield sites”信息。 + * + *

该方法属于 {@code EffectiveTrafficMap},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Set getSafeYieldSites() { return safeYieldSites; } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/map/TrafficMapCompiler.java b/javaTest/src/main/java/com/ft546/wcs/shadow/map/TrafficMapCompiler.java index a68a261..ef06c4e 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/map/TrafficMapCompiler.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/map/TrafficMapCompiler.java @@ -9,6 +9,13 @@ import java.util.Map; import java.util.Set; public final class TrafficMapCompiler { + /** + * 执行“compile”所表示的处理流程。 + * + *

该方法属于 {@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} 实例并初始化其内部状态。 + * + *

该方法属于 {@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 safeWaitSites; private final Set safeYieldSites; + /** + * 创建 {@code MapDefinition} 实例并初始化其内部状态。 + * + *

该方法属于 {@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 nodes, Set edges, Map explicitCapacities, @@ -110,11 +140,25 @@ public final class TrafficMapCompiler { this.safeYieldSites = immutable(safeYieldSites); } + /** + * 执行“with safe wait sites”所表示的处理流程。 + * + *

该方法属于 {@code MapDefinition},用于保持当前模块的职责边界清晰。 + * @param sites 执行该处理所需的 sites 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public MapDefinition withSafeWaitSites(Set sites) { return new MapDefinition(mapCode, versionId, zoneCode, confirmed, baseChecksum, configuredChecksum, nodes, edges, explicitCapacities, sites, safeYieldSites); } + /** + * 执行“with additional edge”所表示的处理流程。 + * + *

该方法属于 {@code MapDefinition},用于保持当前模块的职责边界清晰。 + * @param edge 执行该处理所需的 edge 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public MapDefinition withAdditionalEdge(EdgeDefinition edge) { Set changed = new LinkedHashSet(edges); changed.add(edge); @@ -122,6 +166,14 @@ public final class TrafficMapCompiler { configuredChecksum, nodes, changed, explicitCapacities, safeWaitSites, safeYieldSites); } + /** + * 执行“with capacity”所表示的处理流程。 + * + *

该方法属于 {@code MapDefinition},用于保持当前模块的职责边界清晰。 + * @param key 执行该处理所需的 key 输入。 + * @param capacity 执行该处理所需的 capacity 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public MapDefinition withCapacity(ResourceKey key, int capacity) { Map changed = new LinkedHashMap(explicitCapacities); changed.put(key, capacity); @@ -129,11 +181,25 @@ public final class TrafficMapCompiler { configuredChecksum, nodes, edges, changed, safeWaitSites, safeYieldSites); } + /** + * 执行“with version id”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@code MapDefinition},用于保持当前模块的职责边界清晰。 + * @param source 执行该处理所需的 source 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private static Set immutable(Set source) { return Collections.unmodifiableSet(new LinkedHashSet(source)); } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/replay/DecisionEvent.java b/javaTest/src/main/java/com/ft546/wcs/shadow/replay/DecisionEvent.java index 2bb6068..0421bcc 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/replay/DecisionEvent.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/replay/DecisionEvent.java @@ -16,11 +16,36 @@ public final class DecisionEvent { private final List decisions; private final DecisionReplayInput replayInput; + /** + * 创建 {@code DecisionEvent} 实例并初始化其内部状态。 + * + *

该方法属于 {@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 decisions) { this(decisionId, tickSeq, mapCode, mapVersion, policyVersion, inputHash, decisions, null); } + /** + * 创建 {@code DecisionEvent} 实例并初始化其内部状态。 + * + *

该方法属于 {@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 decisions, DecisionReplayInput replayInput) { @@ -34,20 +59,82 @@ public final class DecisionEvent { this.replayInput = replayInput; } + /** + * 返回当前对象保存的“decision id”信息。 + * + *

该方法属于 {@code DecisionEvent},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getDecisionId() { return decisionId; } + /** + * 返回当前对象保存的“tick seq”信息。 + * + *

该方法属于 {@code DecisionEvent},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getTickSeq() { return tickSeq; } + /** + * 返回当前对象保存的“map code”信息。 + * + *

该方法属于 {@code DecisionEvent},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getMapCode() { return mapCode; } + /** + * 返回当前对象保存的“map version”信息。 + * + *

该方法属于 {@code DecisionEvent},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getMapVersion() { return mapVersion; } + /** + * 返回当前对象保存的“policy version”信息。 + * + *

该方法属于 {@code DecisionEvent},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getPolicyVersion() { return policyVersion; } + /** + * 返回当前对象保存的“input hash”信息。 + * + *

该方法属于 {@code DecisionEvent},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getInputHash() { return inputHash; } + /** + * 返回当前对象保存的“decisions”信息。 + * + *

该方法属于 {@code DecisionEvent},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getDecisions() { return decisions; } + /** + * 返回当前对象保存的“replay input”信息。 + * + *

该方法属于 {@code DecisionEvent},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public DecisionReplayInput getReplayInput() { return replayInput; } + /** + * 执行“with input hash”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@code DecisionEvent},用于保持当前模块的职责边界清晰。 + * @param changedDecisions 执行该处理所需的 changed decisions 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public DecisionEvent withDecisions(List changedDecisions) { return new DecisionEvent(decisionId, tickSeq, mapCode, mapVersion, policyVersion, inputHash, changedDecisions, replayInput); diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/replay/DecisionReplayInput.java b/javaTest/src/main/java/com/ft546/wcs/shadow/replay/DecisionReplayInput.java index d83e7b9..4373c11 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/replay/DecisionReplayInput.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/replay/DecisionReplayInput.java @@ -15,6 +15,15 @@ public final class DecisionReplayInput { private final TrafficSnapshot snapshot; private final List candidates; + /** + * 创建 {@code DecisionReplayInput} 实例并初始化其内部状态。 + * + *

该方法属于 {@code DecisionReplayInput},用于保持当前模块的职责边界清晰。 + * @param map 执行该处理所需的 map 输入。 + * @param ledger 执行该处理所需的 ledger 输入。 + * @param snapshot 执行该处理所需的 snapshot 输入。 + * @param candidates 执行该处理所需的 candidates 输入。 + */ public DecisionReplayInput(EffectiveTrafficMap map, ResourceLedger ledger, TrafficSnapshot snapshot, List candidates) { this.map = map; @@ -23,9 +32,39 @@ public final class DecisionReplayInput { this.candidates = Collections.unmodifiableList(new ArrayList(candidates)); } + /** + * 返回当前对象保存的“map”信息。 + * + *

该方法属于 {@code DecisionReplayInput},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public EffectiveTrafficMap getMap() { return map; } + /** + * 执行“fresh ledger”所表示的处理流程。 + * + *

该方法属于 {@code DecisionReplayInput},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public ResourceLedger freshLedger() { return ledger.copy(); } + /** + * 返回当前对象保存的“snapshot”信息。 + * + *

该方法属于 {@code DecisionReplayInput},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public TrafficSnapshot getSnapshot() { return snapshot; } + /** + * 返回当前对象保存的“candidates”信息。 + * + *

该方法属于 {@code DecisionReplayInput},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getCandidates() { return candidates; } + /** + * 执行“stored ledger”所表示的处理流程。 + * + *

该方法属于 {@code DecisionReplayInput},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ ResourceLedger storedLedger() { return ledger; } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/replay/DecisionReplayService.java b/javaTest/src/main/java/com/ft546/wcs/shadow/replay/DecisionReplayService.java index 82695ff..d319363 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/replay/DecisionReplayService.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/replay/DecisionReplayService.java @@ -27,6 +27,14 @@ import java.util.Set; public final class DecisionReplayService { private final ObjectMapper mapper = new ObjectMapper(); + /** + * 执行“read”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@code DecisionReplayService},用于保持当前模块的职责边界清晰。 + * @param event 执行该处理所需的 event 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List 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”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@code DecisionReplayService},用于保持当前模块的职责边界清晰。 + * @param array 执行该处理所需的 array 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private static Set strings(JsonNode array) { Set result = new LinkedHashSet(); for (JsonNode value : array) result.add(value.asText()); return result; } + /** + * 执行“resource keys”所表示的处理流程。 + * + *

该方法属于 {@code DecisionReplayService},用于保持当前模块的职责边界清晰。 + * @param array 执行该处理所需的 array 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private static Set resourceKeys(JsonNode array) { Set result = new LinkedHashSet(); for (JsonNode value : array) result.add(ResourceKey.fromValue(value.asText())); diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/resource/ResourceKey.java b/javaTest/src/main/java/com/ft546/wcs/shadow/resource/ResourceKey.java index 3c19242..1945bcc 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/resource/ResourceKey.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/resource/ResourceKey.java @@ -5,24 +5,59 @@ import java.util.Objects; public final class ResourceKey implements Comparable { private final String value; + /** + * 创建 {@code ResourceKey} 实例并初始化其内部状态。 + * + *

该方法属于 {@code ResourceKey},用于保持当前模块的职责边界清晰。 + * @param value 执行该处理所需的 value 输入。 + */ private ResourceKey(String value) { this.value = value; } + /** + * 执行“node”所表示的处理流程。 + * + *

该方法属于 {@code ResourceKey},用于保持当前模块的职责边界清晰。 + * @param siteId 执行该处理所需的 site id 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public static ResourceKey node(String siteId) { return new ResourceKey("NODE:" + required(siteId)); } + /** + * 执行“edge”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@code ResourceKey},用于保持当前模块的职责边界清晰。 + * @param code 执行该处理所需的 code 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public static ResourceKey conflict(String code) { return new ResourceKey("CONFLICT:" + required(code)); } + /** + * 执行“from value”所表示的处理流程。 + * + *

该方法属于 {@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 { return new ResourceKey(normalized); } + /** + * 执行“value”所表示的处理流程。 + * + *

该方法属于 {@code ResourceKey},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String value() { return value; } + /** + * 执行“required”所表示的处理流程。 + * + *

该方法属于 {@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 { return value.trim(); } + /** + * 执行“compare to”所表示的处理流程。 + * + *

该方法属于 {@code ResourceKey},用于保持当前模块的职责边界清晰。 + * @param other 执行该处理所需的 other 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ @Override public int compareTo(ResourceKey other) { return value.compareTo(other.value); } + /** + * 比较当前对象与给定对象是否具有相同业务值。 + * + *

该方法属于 {@code ResourceKey},用于保持当前模块的职责边界清晰。 + * @param other 执行该处理所需的 other 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ @Override public boolean equals(Object other) { return other instanceof ResourceKey && value.equals(((ResourceKey) other).value); } + /** + * 判断当前上下文是否满足“hash code”条件。 + * + *

该方法属于 {@code ResourceKey},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ @Override public int hashCode() { return Objects.hash(value); } + /** + * 生成便于诊断和日志输出的文本表示。 + * + *

该方法属于 {@code ResourceKey},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ @Override public String toString() { return value; diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/resource/ResourceLedger.java b/javaTest/src/main/java/com/ft546/wcs/shadow/resource/ResourceLedger.java index 247db78..c58ed05 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/resource/ResourceLedger.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/resource/ResourceLedger.java @@ -12,10 +12,25 @@ public final class ResourceLedger { private final Map> holders = new LinkedHashMap>(); + /** + * 创建 {@code ResourceLedger} 实例并初始化其内部状态。 + * + *

该方法属于 {@code ResourceLedger},用于保持当前模块的职责边界清晰。 + * @param capacities 执行该处理所需的 capacities 输入。 + */ public ResourceLedger(Map capacities) { this.capacities = Collections.unmodifiableMap(new LinkedHashMap(capacities)); } + /** + * 作为交通资源的权威台账,原子地检查并占用车辆下一步所需的起点节点、边和目标节点。 + * + *

未知资源直接拒绝;已满资源返回冲突资源和占用车辆。只有全部资源可用时才写入占用,避免出现 + * 部分成功造成的资源泄漏或双占。 + * @param vehicleId 执行该处理所需的 vehicle id 输入。 + * @param requested 执行该处理所需的 requested 输入。 + * @return 授权结果,或不可达资源/冲突车辆信息。 + */ public ProtectionResult evaluate(String vehicleId, Collection requested) { LinkedHashSet conflicts = new LinkedHashSet(); LinkedHashSet blockers = new LinkedHashSet(); @@ -49,6 +64,11 @@ public final class ResourceLedger { Collections.emptySet(), Collections.emptySet()); } + /** + * 释放车辆不再需要的节点或边,通常在 PLC ACK 后离开旧节点、或 PLC 失败后撤销本次预占时调用。 + * @param vehicleId 执行该处理所需的 vehicle id 输入。 + * @param resources 执行该处理所需的 resources 输入。 + */ public void release(String vehicleId, Collection resources) { for (ResourceKey key : resources) { Set current = holders.get(key); @@ -58,16 +78,34 @@ public final class ResourceLedger { } } + /** + * 执行“holders for”所表示的处理流程。 + * + *

该方法属于 {@code ResourceLedger},用于保持当前模块的职责边界清晰。 + * @param key 执行该处理所需的 key 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Set holdersFor(ResourceKey key) { Set current = holders.get(key); return current == null ? Collections.emptySet() : Collections.unmodifiableSet(new LinkedHashSet(current)); } + /** + * 执行“protected count”所表示的处理流程。 + * + *

该方法属于 {@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> entry : holders.entrySet()) { @@ -76,10 +114,20 @@ public final class ResourceLedger { return copy; } + /** + * 返回当前对象保存的“capacities”信息。 + * + *

该方法属于 {@code ResourceLedger},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Map getCapacities() { return capacities; } + /** + * 导出资源持有者快照,供不变量检查和报告确认没有节点、边资源双占。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Map> snapshotHolders() { Map> snapshot = new LinkedHashMap>(); for (Map.Entry> entry : holders.entrySet()) { @@ -89,6 +137,13 @@ public final class ResourceLedger { return Collections.unmodifiableMap(snapshot); } + /** + * 执行“capacity”所表示的处理流程。 + * + *

该方法属于 {@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 conflictingResources; private final Set blockingVehicles; + /** + * 创建 {@code ProtectionResult} 实例并初始化其内部状态。 + * + *

该方法属于 {@code ProtectionResult},用于保持当前模块的职责边界清晰。 + * @param granted 执行该处理所需的 granted 输入。 + * @param unknownResource 执行该处理所需的 unknown resource 输入。 + * @param conflictingResources 执行该处理所需的 conflicting resources 输入。 + * @param blockingVehicles 执行该处理所需的 blocking vehicles 输入。 + */ private ProtectionResult(boolean granted, boolean unknownResource, Set conflictingResources, Set blockingVehicles) { @@ -114,9 +178,33 @@ public final class ResourceLedger { new LinkedHashSet(blockingVehicles)); } + /** + * 判断当前上下文是否满足“is granted”条件。 + * + *

该方法属于 {@code ProtectionResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isGranted() { return granted; } + /** + * 判断当前上下文是否满足“is unknown resource”条件。 + * + *

该方法属于 {@code ProtectionResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isUnknownResource() { return unknownResource; } + /** + * 返回当前对象保存的“conflicting resources”信息。 + * + *

该方法属于 {@code ProtectionResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Set getConflictingResources() { return conflictingResources; } + /** + * 返回当前对象保存的“blocking vehicles”信息。 + * + *

该方法属于 {@code ProtectionResult},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Set getBlockingVehicles() { return blockingVehicles; } } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/segment/TrafficSegment.java b/javaTest/src/main/java/com/ft546/wcs/shadow/segment/TrafficSegment.java index cadb2dd..fadf8ae 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/segment/TrafficSegment.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/segment/TrafficSegment.java @@ -16,6 +16,21 @@ public final class TrafficSegment { private final ReservationState reservationState; private final long lastSnapshotSeq; + /** + * 创建 {@code TrafficSegment} 实例并初始化其内部状态。 + * + *

该方法属于 {@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 path, SegmentState state, ReservationState reservationState, long lastSnapshotSeq) { @@ -31,6 +46,19 @@ public final class TrafficSegment { this.lastSnapshotSeq = lastSnapshotSeq; } + /** + * 执行“planned”所表示的处理流程。 + * + *

该方法属于 {@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 path) { @@ -41,6 +69,13 @@ public final class TrafficSegment { segmentSeq, path, SegmentState.SOFT_PLANNED, ReservationState.SOFT, -1L); } + /** + * 执行“transition”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@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”所表示的处理流程。 + * + *

该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。 + * @param required 执行该处理所需的 required 输入。 + */ private void require(SegmentState required) { if (state != required) { throw new IllegalStateException(state + " cannot accept transition requiring " + required); } } + /** + * 返回当前对象保存的“segment id”信息。 + * + *

该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getSegmentId() { return segmentId; } + /** + * 返回当前对象保存的“vehicle id”信息。 + * + *

该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getVehicleId() { return vehicleId; } + /** + * 返回当前对象保存的“plc boot id”信息。 + * + *

该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getPlcBootId() { return plcBootId; } + /** + * 返回当前对象保存的“planner epoch”信息。 + * + *

该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getPlannerEpoch() { return plannerEpoch; } + /** + * 返回当前对象保存的“plan version”信息。 + * + *

该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getPlanVersion() { return planVersion; } + /** + * 返回当前对象保存的“segment seq”信息。 + * + *

该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getSegmentSeq() { return segmentSeq; } + /** + * 返回当前对象保存的“path”信息。 + * + *

该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getPath() { return path; } + /** + * 返回当前对象保存的“state”信息。 + * + *

该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public SegmentState getState() { return state; } + /** + * 返回当前对象保存的“reservation state”信息。 + * + *

该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public ReservationState getReservationState() { return reservationState; } + /** + * 返回当前对象保存的“last snapshot seq”信息。 + * + *

该方法属于 {@code TrafficSegment},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getLastSnapshotSeq() { return lastSnapshotSeq; } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/snapshot/SnapshotFreshnessPolicy.java b/javaTest/src/main/java/com/ft546/wcs/shadow/snapshot/SnapshotFreshnessPolicy.java index 7f7ceac..9308a8b 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/snapshot/SnapshotFreshnessPolicy.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/snapshot/SnapshotFreshnessPolicy.java @@ -6,10 +6,25 @@ import java.time.Instant; public final class SnapshotFreshnessPolicy { private final Duration maximumAge; + /** + * 创建 {@code SnapshotFreshnessPolicy} 实例并初始化其内部状态。 + * + *

该方法属于 {@code SnapshotFreshnessPolicy},用于保持当前模块的职责边界清晰。 + * @param maximumAge 执行该处理所需的 maximum age 输入。 + */ public SnapshotFreshnessPolicy(Duration maximumAge) { this.maximumAge = maximumAge; } + /** + * 执行“validate”所表示的处理流程。 + * + *

该方法属于 {@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} 实例并初始化其内部状态。 + * + *

该方法属于 {@code SnapshotHealth},用于保持当前模块的职责边界清晰。 + * @param healthy 执行该处理所需的 healthy 输入。 + * @param reasonCode 执行该处理所需的 reason code 输入。 + */ private SnapshotHealth(boolean healthy, String reasonCode) { this.healthy = healthy; this.reasonCode = reasonCode; } + /** + * 执行“healthy”所表示的处理流程。 + * + *

该方法属于 {@code SnapshotHealth},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ static SnapshotHealth healthy() { return new SnapshotHealth(true, "OK"); } + /** + * 执行“unhealthy”所表示的处理流程。 + * + *

该方法属于 {@code SnapshotHealth},用于保持当前模块的职责边界清晰。 + * @param reason 执行该处理所需的 reason 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ static SnapshotHealth unhealthy(String reason) { return new SnapshotHealth(false, reason); } + /** + * 判断当前上下文是否满足“is healthy”条件。 + * + *

该方法属于 {@code SnapshotHealth},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isHealthy() { return healthy; } + /** + * 返回当前对象保存的“reason code”信息。 + * + *

该方法属于 {@code SnapshotHealth},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getReasonCode() { return reasonCode; } } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/snapshot/TrafficSnapshot.java b/javaTest/src/main/java/com/ft546/wcs/shadow/snapshot/TrafficSnapshot.java index e887f61..caf7ebd 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/snapshot/TrafficSnapshot.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/snapshot/TrafficSnapshot.java @@ -14,11 +14,34 @@ public final class TrafficSnapshot { private final ControlMode controlMode; private final List vehicles; + /** + * 创建 {@code TrafficSnapshot} 实例并初始化其内部状态。 + * + *

该方法属于 {@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 vehicles) { this(tickSeq, decisionTime, mapCode, mapVersion, policyVersion, ControlMode.SHADOW, vehicles); } + /** + * 创建 {@code TrafficSnapshot} 实例并初始化其内部状态。 + * + *

该方法属于 {@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 vehicles) { @@ -31,11 +54,53 @@ public final class TrafficSnapshot { this.vehicles = Collections.unmodifiableList(new ArrayList(vehicles)); } + /** + * 返回当前对象保存的“tick seq”信息。 + * + *

该方法属于 {@code TrafficSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getTickSeq() { return tickSeq; } + /** + * 返回当前对象保存的“decision time”信息。 + * + *

该方法属于 {@code TrafficSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Instant getDecisionTime() { return decisionTime; } + /** + * 返回当前对象保存的“map code”信息。 + * + *

该方法属于 {@code TrafficSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getMapCode() { return mapCode; } + /** + * 返回当前对象保存的“map version”信息。 + * + *

该方法属于 {@code TrafficSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getMapVersion() { return mapVersion; } + /** + * 返回当前对象保存的“policy version”信息。 + * + *

该方法属于 {@code TrafficSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getPolicyVersion() { return policyVersion; } + /** + * 返回当前对象保存的“control mode”信息。 + * + *

该方法属于 {@code TrafficSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public ControlMode getControlMode() { return controlMode; } + /** + * 返回当前对象保存的“vehicles”信息。 + * + *

该方法属于 {@code TrafficSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getVehicles() { return vehicles; } } diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/snapshot/TrafficVehicleSnapshot.java b/javaTest/src/main/java/com/ft546/wcs/shadow/snapshot/TrafficVehicleSnapshot.java index 0bcaa5e..bc4423b 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/snapshot/TrafficVehicleSnapshot.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/snapshot/TrafficVehicleSnapshot.java @@ -18,6 +18,22 @@ public final class TrafficVehicleSnapshot { private final boolean faulted; private final boolean manual; + /** + * 创建 {@code TrafficVehicleSnapshot} 实例并初始化其内部状态。 + * + *

该方法属于 {@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 remainingPath, boolean connected, @@ -35,15 +51,81 @@ public final class TrafficVehicleSnapshot { this.manual = manual; } + /** + * 返回当前对象保存的“vehicle id”信息。 + * + *

该方法属于 {@code TrafficVehicleSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getVehicleId() { return vehicleId; } + /** + * 返回当前对象保存的“plc boot id”信息。 + * + *

该方法属于 {@code TrafficVehicleSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getPlcBootId() { return plcBootId; } + /** + * 返回当前对象保存的“heartbeat seq”信息。 + * + *

该方法属于 {@code TrafficVehicleSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getHeartbeatSeq() { return heartbeatSeq; } + /** + * 返回当前对象保存的“snapshot seq”信息。 + * + *

该方法属于 {@code TrafficVehicleSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public long getSnapshotSeq() { return snapshotSeq; } + /** + * 返回当前对象保存的“received at”信息。 + * + *

该方法属于 {@code TrafficVehicleSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public Instant getReceivedAt() { return receivedAt; } + /** + * 返回当前对象保存的“current site”信息。 + * + *

该方法属于 {@code TrafficVehicleSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getCurrentSite() { return currentSite; } + /** + * 返回当前对象保存的“next site”信息。 + * + *

该方法属于 {@code TrafficVehicleSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public String getNextSite() { return nextSite; } + /** + * 返回当前对象保存的“remaining path”信息。 + * + *

该方法属于 {@code TrafficVehicleSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public List getRemainingPath() { return remainingPath; } + /** + * 判断当前上下文是否满足“is connected”条件。 + * + *

该方法属于 {@code TrafficVehicleSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isConnected() { return connected; } + /** + * 判断当前上下文是否满足“is faulted”条件。 + * + *

该方法属于 {@code TrafficVehicleSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isFaulted() { return faulted; } + /** + * 判断当前上下文是否满足“is manual”条件。 + * + *

该方法属于 {@code TrafficVehicleSnapshot},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ public boolean isManual() { return manual; } } diff --git a/javaTest/src/test/java/com/ft546/wcs/demo/DemoScenarioTest.java b/javaTest/src/test/java/com/ft546/wcs/demo/DemoScenarioTest.java index f3ce9e6..ca5d0a3 100644 --- a/javaTest/src/test/java/com/ft546/wcs/demo/DemoScenarioTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/demo/DemoScenarioTest.java @@ -10,6 +10,12 @@ import static org.junit.jupiter.api.Assertions.assertTrue; class DemoScenarioTest { + /** + * 验证“executable scenario shows assignment avoidance retry completion and no path hold”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code DemoScenarioTest},用于保持当前模块的职责边界清晰。 + * @throws Exception 当调用条件不满足或处理无法继续时抛出。 + */ @Test void executableScenarioShowsAssignmentAvoidanceRetryCompletionAndNoPathHold() throws Exception { diff --git a/javaTest/src/test/java/com/ft546/wcs/demo/LegacyDispatchCenterTest.java b/javaTest/src/test/java/com/ft546/wcs/demo/LegacyDispatchCenterTest.java index 9ad19dd..321e74e 100644 --- a/javaTest/src/test/java/com/ft546/wcs/demo/LegacyDispatchCenterTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/demo/LegacyDispatchCenterTest.java @@ -26,6 +26,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue; class LegacyDispatchCenterTest { + /** + * 验证“each cycle admits once and processes vehicles in stable order”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code LegacyDispatchCenterTest},用于保持当前模块的职责边界清晰。 + */ @Test void eachCycleAdmitsOnceAndProcessesVehiclesInStableOrder() { Fixture fixture = fixtureWithThreeVehicles(); @@ -38,6 +43,11 @@ class LegacyDispatchCenterTest { assertTrue(fixture.state.getActiveQueues().get(0).isIssued()); } + /** + * 验证“failed protocol send remains pending and retries next cycle”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code LegacyDispatchCenterTest},用于保持当前模块的职责边界清晰。 + */ @Test void failedProtocolSendRemainsPendingAndRetriesNextCycle() { Fixture fixture = fixtureWithOneVehicle(); @@ -57,6 +67,11 @@ class LegacyDispatchCenterTest { assertEquals(2, fixture.protocol.getAttemptedQueueIds().size()); } + /** + * 验证“vehicle at destination archives and deletes queue exactly once”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code LegacyDispatchCenterTest},用于保持当前模块的职责边界清晰。 + */ @Test void vehicleAtDestinationArchivesAndDeletesQueueExactlyOnce() { GridMap map = simpleMap(); @@ -75,6 +90,11 @@ class LegacyDispatchCenterTest { assertEquals(4, fixture.state.getHistory().get(0).getExecutionStatus()); } + /** + * 验证“channel conflict adds avoidance queue for blocking vehicle”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code LegacyDispatchCenterTest},用于保持当前模块的职责边界清晰。 + */ @Test void channelConflictAddsAvoidanceQueueForBlockingVehicle() { GridMap map = simpleMap(); @@ -96,6 +116,11 @@ class LegacyDispatchCenterTest { assertTrue(fixture.state.getEvents().toString().contains("AVOID")); } + /** + * 验证“vehicle snapshot is frozen before admission mutates live state”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code LegacyDispatchCenterTest},用于保持当前模块的职责边界清晰。 + */ @Test void vehicleSnapshotIsFrozenBeforeAdmissionMutatesLiveState() { GridMap map = simpleMap(); @@ -104,6 +129,14 @@ class LegacyDispatchCenterTest { QueueAdmission admission = new QueueAdmission() { private int invocationCount; + /** + * 验证“create pending queue”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code 匿名类型},用于保持当前模块的职责边界清晰。 + * @param liveState 执行该处理所需的 live state 输入。 + * @param frozenVehicles 执行该处理所需的 frozen vehicles 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ @Override public Optional createPendingQueue( InMemoryWcsState liveState, @@ -114,6 +147,12 @@ class LegacyDispatchCenterTest { return Optional.empty(); } + /** + * 验证“get invocation count”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code 匿名类型},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ @Override public int getInvocationCount() { return invocationCount; @@ -133,6 +172,12 @@ class LegacyDispatchCenterTest { assertEquals(1, admission.getInvocationCount()); } + /** + * 验证“fixture with three vehicles”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code LegacyDispatchCenterTest},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private Fixture fixtureWithThreeVehicles() { GridMap map = simpleMap(); InMemoryWcsState state = new InMemoryWcsState(); @@ -143,6 +188,12 @@ class LegacyDispatchCenterTest { return fixture(map, state); } + /** + * 验证“fixture with one vehicle”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code LegacyDispatchCenterTest},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private Fixture fixtureWithOneVehicle() { GridMap map = simpleMap(); InMemoryWcsState state = new InMemoryWcsState(); @@ -151,6 +202,14 @@ class LegacyDispatchCenterTest { return fixture(map, state); } + /** + * 验证“fixture”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code LegacyDispatchCenterTest},用于保持当前模块的职责边界清晰。 + * @param map 执行该处理所需的 map 输入。 + * @param state 执行该处理所需的 state 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private Fixture fixture(GridMap map, InMemoryWcsState state) { QueueAdmissionService admission = new QueueAdmissionService( new VehicleAssignmentService(), @@ -166,6 +225,12 @@ class LegacyDispatchCenterTest { return new Fixture(state, admission, protocol, center); } + /** + * 验证“simple map”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code LegacyDispatchCenterTest},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private GridMap simpleMap() { GridMap map = new GridMap(); map.addSite(new Site("A", 1, 0, 0, "START")); @@ -182,6 +247,12 @@ class LegacyDispatchCenterTest { return map; } + /** + * 验证“task”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code LegacyDispatchCenterTest},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private DispatchTask task() { return new DispatchTask( "TASK-1", @@ -193,6 +264,14 @@ class LegacyDispatchCenterTest { ); } + /** + * 验证“vehicle”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code LegacyDispatchCenterTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @param site 执行该处理所需的 site 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private VehicleSnapshot vehicle(String id, String site) { return new VehicleSnapshot(id, 1, site, 5, 1, 80, true, true, false); } @@ -203,6 +282,15 @@ class LegacyDispatchCenterTest { private final SimulatedProtocolAdapter protocol; private final LegacyDispatchCenter center; + /** + * 创建 {@code Fixture} 实例并初始化其内部状态。 + * + *

该方法属于 {@code Fixture},用于保持当前模块的职责边界清晰。 + * @param state 执行该处理所需的 state 输入。 + * @param admission 执行该处理所需的 admission 输入。 + * @param protocol 执行该处理所需的 protocol 输入。 + * @param center 执行该处理所需的 center 输入。 + */ private Fixture( InMemoryWcsState state, QueueAdmissionService admission, diff --git a/javaTest/src/test/java/com/ft546/wcs/demo/QueueLifecycleTest.java b/javaTest/src/test/java/com/ft546/wcs/demo/QueueLifecycleTest.java index 53285f0..9af112c 100644 --- a/javaTest/src/test/java/com/ft546/wcs/demo/QueueLifecycleTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/demo/QueueLifecycleTest.java @@ -15,6 +15,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue; class QueueLifecycleTest { + /** + * 验证“queue uses legacy lifecycle codes”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code QueueLifecycleTest},用于保持当前模块的职责边界清晰。 + */ @Test void queueUsesLegacyLifecycleCodes() { DispatchTask task = new DispatchTask( @@ -40,6 +45,11 @@ class QueueLifecycleTest { assertEquals(4, queue.getExecutionStatus()); } + /** + * 验证“queue copies path and rejects completion before issue”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code QueueLifecycleTest},用于保持当前模块的职责边界清晰。 + */ @Test void queueCopiesPathAndRejectsCompletionBeforeIssue() { DispatchTask task = new DispatchTask( @@ -62,6 +72,11 @@ class QueueLifecycleTest { assertThrows(UnsupportedOperationException.class, () -> queue.getPath().add("D")); } + /** + * 验证“domain inputs reject invalid values”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code QueueLifecycleTest},用于保持当前模块的职责边界清晰。 + */ @Test void domainInputsRejectInvalidValues() { assertThrows(IllegalArgumentException.class, diff --git a/javaTest/src/test/java/com/ft546/wcs/demo/TrafficControllerTest.java b/javaTest/src/test/java/com/ft546/wcs/demo/TrafficControllerTest.java index f19becc..2aefe38 100644 --- a/javaTest/src/test/java/com/ft546/wcs/demo/TrafficControllerTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/demo/TrafficControllerTest.java @@ -22,6 +22,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue; class TrafficControllerTest { + /** + * 验证“planner uses deterministic alternate route around ablocked site”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code TrafficControllerTest},用于保持当前模块的职责边界清晰。 + */ @Test void plannerUsesDeterministicAlternateRouteAroundABlockedSite() { GridMap map = diamondMap(); @@ -37,6 +42,11 @@ class TrafficControllerTest { assertEquals(Arrays.asList("A", "D", "C"), path); } + /** + * 验证“other queue remaining path and offline vehicle sites are locked”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code TrafficControllerTest},用于保持当前模块的职责边界清晰。 + */ @Test void otherQueueRemainingPathAndOfflineVehicleSitesAreLocked() { GridMap map = diamondMap(); @@ -59,6 +69,11 @@ class TrafficControllerTest { assertTrue(decision.getReason().contains("no path")); } + /** + * 验证“same channel blocker creates one priority nine avoidance queue”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code TrafficControllerTest},用于保持当前模块的职责边界清晰。 + */ @Test void sameChannelBlockerCreatesOnePriorityNineAvoidanceQueue() { GridMap map = channelMap(); @@ -83,6 +98,11 @@ class TrafficControllerTest { assertEquals(9, avoidance.getPriority()); } + /** + * 验证“existing avoidance is not duplicated and moving blocker releases the channel”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code TrafficControllerTest},用于保持当前模块的职责边界清晰。 + */ @Test void existingAvoidanceIsNotDuplicatedAndMovingBlockerReleasesTheChannel() { GridMap map = channelMap(); @@ -115,10 +135,23 @@ class TrafficControllerTest { assertEquals(Arrays.asList("A", "B", "TARGET"), released.getPath()); } + /** + * 验证“controller”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code TrafficControllerTest},用于保持当前模块的职责边界清晰。 + * @param map 执行该处理所需的 map 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private TrafficController controller(GridMap map) { return new TrafficController(map, new GridPathPlanner()); } + /** + * 验证“diamond map”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code TrafficControllerTest},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private GridMap diamondMap() { GridMap map = new GridMap(); map.addSite(new Site("A", 1, 0, 0, "START")); @@ -132,6 +165,12 @@ class TrafficControllerTest { return map; } + /** + * 验证“channel map”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code TrafficControllerTest},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private GridMap channelMap() { GridMap map = new GridMap(); map.addSite(new Site("A", 1, 0, 0, "START")); @@ -145,6 +184,16 @@ class TrafficControllerTest { return map; } + /** + * 验证“business queue”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code TrafficControllerTest},用于保持当前模块的职责边界清晰。 + * @param taskId 执行该处理所需的 task id 输入。 + * @param vehicleId 执行该处理所需的 vehicle id 输入。 + * @param source 执行该处理所需的 source 输入。 + * @param target 执行该处理所需的 target 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private DispatchQueueEntry businessQueue( String taskId, String vehicleId, @@ -162,6 +211,15 @@ class TrafficControllerTest { return DispatchQueueEntry.business(task, vehicleId); } + /** + * 验证“vehicle”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code TrafficControllerTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @param site 执行该处理所需的 site 输入。 + * @param connected 执行该处理所需的 connected 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private VehicleSnapshot vehicle(String id, String site, boolean connected) { return new VehicleSnapshot(id, 1, site, 5, 1, 80, connected, true, false); } diff --git a/javaTest/src/test/java/com/ft546/wcs/demo/VehicleAssignmentServiceTest.java b/javaTest/src/test/java/com/ft546/wcs/demo/VehicleAssignmentServiceTest.java index 96aa32c..729fd8d 100644 --- a/javaTest/src/test/java/com/ft546/wcs/demo/VehicleAssignmentServiceTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/demo/VehicleAssignmentServiceTest.java @@ -21,6 +21,11 @@ class VehicleAssignmentServiceTest { private final VehicleAssignmentService service = new VehicleAssignmentService(); private Map sites; + /** + * 验证“set up”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code VehicleAssignmentServiceTest},用于保持当前模块的职责边界清晰。 + */ @BeforeEach void setUp() { sites = new LinkedHashMap(); @@ -34,6 +39,11 @@ class VehicleAssignmentServiceTest { sites.put("X_FAR", new Site("X_FAR", 1, 0, 9, "AISLE-6")); } + /** + * 验证“same floor vehicle wins before closer cross floor vehicle”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code VehicleAssignmentServiceTest},用于保持当前模块的职责边界清晰。 + */ @Test void sameFloorVehicleWinsBeforeCloserCrossFloorVehicle() { DispatchTask task = task("SOURCE"); @@ -48,6 +58,11 @@ class VehicleAssignmentServiceTest { assertTrue(decision.getReason().contains("sameFloorPenalty=0")); } + /** + * 验证“lower vehicle id breaks an exact distance tie”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code VehicleAssignmentServiceTest},用于保持当前模块的职责边界清晰。 + */ @Test void lowerVehicleIdBreaksAnExactDistanceTie() { VehicleSnapshot vehicle2 = vehicle("2", 1, "TIE", 80, true, true, 5, 1); @@ -59,6 +74,11 @@ class VehicleAssignmentServiceTest { assertEquals("1", decision.getVehicle().get().getVehicleId()); } + /** + * 验证“only connected automatic idle allowed and charged vehicle is eligible”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code VehicleAssignmentServiceTest},用于保持当前模块的职责边界清晰。 + */ @Test void onlyConnectedAutomaticIdleAllowedAndChargedVehicleIsEligible() { VehicleSnapshot offline = vehicle("1", 1, "SAME", 80, false, true, 5, 1); @@ -77,6 +97,11 @@ class VehicleAssignmentServiceTest { assertEquals("6", decision.getVehicle().get().getVehicleId()); } + /** + * 验证“missing task site is rejected instead of using zero coordinates”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code VehicleAssignmentServiceTest},用于保持当前模块的职责边界清晰。 + */ @Test void missingTaskSiteIsRejectedInsteadOfUsingZeroCoordinates() { VehicleAssignmentDecision decision = @@ -89,6 +114,11 @@ class VehicleAssignmentServiceTest { assertTrue(decision.getReason().contains("UNKNOWN")); } + /** + * 验证“missing target site is rejected before aqueue can be created”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code VehicleAssignmentServiceTest},用于保持当前模块的职责边界清晰。 + */ @Test void missingTargetSiteIsRejectedBeforeAQueueCanBeCreated() { DispatchTask invalidTarget = new DispatchTask( @@ -111,6 +141,11 @@ class VehicleAssignmentServiceTest { assertTrue(decision.getReason().contains("UNKNOWN")); } + /** + * 验证“legacy distance uses ybefore x”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code VehicleAssignmentServiceTest},用于保持当前模块的职责边界清晰。 + */ @Test void legacyDistanceUsesYBeforeX() { VehicleSnapshot yNear = @@ -125,6 +160,11 @@ class VehicleAssignmentServiceTest { assertTrue(decision.getReason().contains("yDistance=1")); } + /** + * 验证“legacy distance uses xwhen yis tied”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code VehicleAssignmentServiceTest},用于保持当前模块的职责边界清晰。 + */ @Test void legacyDistanceUsesXWhenYIsTied() { VehicleSnapshot xNear = @@ -139,6 +179,13 @@ class VehicleAssignmentServiceTest { assertTrue(decision.getReason().contains("xDistance=1")); } + /** + * 验证“task”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code VehicleAssignmentServiceTest},用于保持当前模块的职责边界清晰。 + * @param sourceSite 执行该处理所需的 source site 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private DispatchTask task(String sourceSite) { return new DispatchTask( "TASK-1", @@ -150,6 +197,20 @@ class VehicleAssignmentServiceTest { ); } + /** + * 验证“vehicle”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code VehicleAssignmentServiceTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @param floor 执行该处理所需的 floor 输入。 + * @param site 执行该处理所需的 site 输入。 + * @param battery 执行该处理所需的 battery 输入。 + * @param connected 执行该处理所需的 connected 输入。 + * @param allowSend 执行该处理所需的 allow send 输入。 + * @param workMode 执行该处理所需的 work mode 输入。 + * @param status 执行该处理所需的 status 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private VehicleSnapshot vehicle( String id, int floor, diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/FeedbackReconcilerTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/FeedbackReconcilerTest.java index 78f19ab..6779a64 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/FeedbackReconcilerTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/FeedbackReconcilerTest.java @@ -19,6 +19,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue; class FeedbackReconcilerTest { private final FeedbackReconciler reconciler = new FeedbackReconciler(); + /** + * 验证“releases only passed node and edge and keeps destination protected”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code FeedbackReconcilerTest},用于保持当前模块的职责边界清晰。 + */ @Test void releasesOnlyPassedNodeAndEdgeAndKeepsDestinationProtected() { FeedbackResult result = reconciler.reconcile(committed(), feedback( @@ -32,6 +37,11 @@ class FeedbackReconcilerTest { assertTrue(result.getRetainedResources().contains(ResourceKey.node("C"))); } + /** + * 验证“duplicate snapshot is idempotent and eta never releases”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code FeedbackReconcilerTest},用于保持当前模块的职责边界清晰。 + */ @Test void duplicateSnapshotIsIdempotentAndEtaNeverReleases() { TrafficSegment processed = committed().withLastSnapshotSeq(10L); @@ -43,6 +53,11 @@ class FeedbackReconcilerTest { assertEquals(ReservationState.HARD, duplicate.getUpdatedSegment().getReservationState()); } + /** + * 验证“mismatch restart disconnect and ack loss fail closed”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code FeedbackReconcilerTest},用于保持当前模块的职责边界清晰。 + */ @Test void mismatchRestartDisconnectAndAckLossFailClosed() { assertQuarantined("VERSION_MISMATCH", feedback( @@ -57,6 +72,13 @@ class FeedbackReconcilerTest { "BOOT-1", 7L, 2L, 1L, 10L, "C", Arrays.asList("C", "B"), true, true)); } + /** + * 验证“assert quarantined”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code FeedbackReconcilerTest},用于保持当前模块的职责边界清晰。 + * @param reason 执行该处理所需的 reason 输入。 + * @param feedback 执行该处理所需的 feedback 输入。 + */ private void assertQuarantined(String reason, ExecutionFeedback feedback) { FeedbackResult result = reconciler.reconcile(committed(), feedback); assertTrue(result.isQuarantined()); @@ -65,6 +87,12 @@ class FeedbackReconcilerTest { assertEquals(ReservationState.UNKNOWN_HARD, result.getUpdatedSegment().getReservationState()); } + /** + * 验证“committed”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code FeedbackReconcilerTest},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private TrafficSegment committed() { return TrafficSegment.planned("SEG-1", "V1", "BOOT-1", 7L, 2L, 1L, Arrays.asList("A", "B", "C")) @@ -74,6 +102,21 @@ class FeedbackReconcilerTest { .transition(SegmentEvent.COMMITTED); } + /** + * 验证“feedback”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code FeedbackReconcilerTest},用于保持当前模块的职责边界清晰。 + * @param bootId 执行该处理所需的 boot id 输入。 + * @param epoch 执行该处理所需的 epoch 输入。 + * @param version 执行该处理所需的 version 输入。 + * @param segmentSeq 执行该处理所需的 segment seq 输入。 + * @param snapshotSeq 执行该处理所需的 snapshot seq 输入。 + * @param current 执行该处理所需的 current 输入。 + * @param remaining 执行该处理所需的 remaining 输入。 + * @param connected 执行该处理所需的 connected 输入。 + * @param ackKnown 执行该处理所需的 ack known 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private ExecutionFeedback feedback(String bootId, long epoch, long version, long segmentSeq, long snapshotSeq, String current, java.util.List remaining, boolean connected, boolean ackKnown) { diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/HistoricalQueueDatabaseReplayTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/HistoricalQueueDatabaseReplayTest.java index d3f7179..a6974cc 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/HistoricalQueueDatabaseReplayTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/HistoricalQueueDatabaseReplayTest.java @@ -25,6 +25,16 @@ class HistoricalQueueDatabaseReplayTest { private static final HistoricalQueueDataset DATA = new HistoricalQueueLoader().load( HistoricalQueueDatabaseReplayTest.class.getClassLoader(), "shadow/history"); + /** + * 验证“replays real history record”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalQueueDatabaseReplayTest},用于保持当前模块的职责边界清晰。 + * @param taskNo 执行该处理所需的 task no 输入。 + * @param agvId 执行该处理所需的 agv id 输入。 + * @param startSite 执行该处理所需的 start site 输入。 + * @param endSite 执行该处理所需的 end site 输入。 + * @param path 执行该处理所需的 path 输入。 + */ @ParameterizedTest(name = "{index} task={0} agv={1} {2}->{3}") @MethodSource("realHistoryCases") void replaysRealHistoryRecord(String taskNo, String agvId, @@ -42,6 +52,12 @@ class HistoricalQueueDatabaseReplayTest { } } + /** + * 验证“real history cases”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalQueueDatabaseReplayTest},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ static Stream realHistoryCases() { HistoricalQueueNormalizer normalizer = new HistoricalQueueNormalizer(); return DATA.getRecords().stream().map(record -> Arguments.of( @@ -49,6 +65,11 @@ class HistoricalQueueDatabaseReplayTest { normalizer.normalize(record, DATA.getMapSites()))); } + /** + * 验证“snapshot coverage and replay are deterministic”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalQueueDatabaseReplayTest},用于保持当前模块的职责边界清晰。 + */ @Test void snapshotCoverageAndReplayAreDeterministic() { assertTrue(DATA.getRecords().size() >= 200); diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/HistoricalQueueLoaderTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/HistoricalQueueLoaderTest.java index 7c8b81a..b818420 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/HistoricalQueueLoaderTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/HistoricalQueueLoaderTest.java @@ -13,6 +13,11 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; class HistoricalQueueLoaderTest { + /** + * 验证“loads and verifies the independent complete grid snapshot”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalQueueLoaderTest},用于保持当前模块的职责边界清晰。 + */ @Test void loadsAndVerifiesTheIndependentCompleteGridSnapshot() { HistoricalQueueDataset data = new HistoricalQueueLoader().load( @@ -26,6 +31,11 @@ class HistoricalQueueLoaderTest { assertEquals(64, data.getFullMapSha256().length()); } + /** + * 验证“loads versioned database snapshot and preserves original ids”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalQueueLoaderTest},用于保持当前模块的职责边界清晰。 + */ @Test void loadsVersionedDatabaseSnapshotAndPreservesOriginalIds() { HistoricalQueueDataset data = new HistoricalQueueLoader().load( @@ -49,6 +59,11 @@ class HistoricalQueueLoaderTest { assertEquals(5193, data.getMissingPathRows()); } + /** + * 验证“rejects hash mismatch”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalQueueLoaderTest},用于保持当前模块的职责边界清晰。 + */ @Test void rejectsHashMismatch() { assertThrows(IllegalArgumentException.class, () -> @@ -56,6 +71,11 @@ class HistoricalQueueLoaderTest { "wrong", "abc".getBytes(StandardCharsets.UTF_8))); } + /** + * 验证“verifies text hash independently of line ending style”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalQueueLoaderTest},用于保持当前模块的职责边界清晰。 + */ @Test void verifiesTextHashIndependentlyOfLineEndingStyle() { String canonicalSha256 = @@ -66,6 +86,11 @@ class HistoricalQueueLoaderTest { canonicalSha256, "a\r\nb\r\n".getBytes(StandardCharsets.UTF_8)); } + /** + * 验证“rejects malformed utf8 before canonical hashing”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalQueueLoaderTest},用于保持当前模块的职责边界清晰。 + */ @Test void rejectsMalformedUtf8BeforeCanonicalHashing() { String replacementCharacterSha256 = diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/HistoricalQueueNormalizerTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/HistoricalQueueNormalizerTest.java index 57e9ff8..a207224 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/HistoricalQueueNormalizerTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/HistoricalQueueNormalizerTest.java @@ -16,6 +16,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue; class HistoricalQueueNormalizerTest { private final HistoricalQueueNormalizer normalizer = new HistoricalQueueNormalizer(); + /** + * 验证“parses trailing comma and projects undirected edges”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalQueueNormalizerTest},用于保持当前模块的职责边界清晰。 + */ @Test void parsesTrailingCommaAndProjectsUndirectedEdges() { HistoricalPath path = normalizer.normalize(record("A,B,C,"), @@ -26,6 +31,11 @@ class HistoricalQueueNormalizerTest { assertTrue(path.isReplayable()); } + /** + * 验证“unknown map site is not replayable”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalQueueNormalizerTest},用于保持当前模块的职责边界清晰。 + */ @Test void unknownMapSiteIsNotReplayable() { HistoricalPath path = normalizer.normalize(record("A,UNKNOWN,"), @@ -34,6 +44,11 @@ class HistoricalQueueNormalizerTest { assertTrue(path.getIssues().contains("UNKNOWN_MAP_SITE:UNKNOWN")); } + /** + * 验证“reversed interval is not replayable”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalQueueNormalizerTest},用于保持当前模块的职责边界清晰。 + */ @Test void reversedIntervalIsNotReplayable() { HistoricalQueueRecord record = new HistoricalQueueRecord( @@ -45,6 +60,13 @@ class HistoricalQueueNormalizerTest { assertTrue(path.getIssues().contains("REVERSED_INTERVAL")); } + /** + * 验证“record”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalQueueNormalizerTest},用于保持当前模块的职责边界清晰。 + * @param path 执行该处理所需的 path 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private HistoricalQueueRecord record(String path) { return new HistoricalQueueRecord("G", "T", "1", 2, "A", "C", path, "2026-07-21 14:00:00", "2026-07-21 14:05:00", "1"); diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/HistoricalReplayAnalyzerTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/HistoricalReplayAnalyzerTest.java index 6deab6e..0bebc63 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/HistoricalReplayAnalyzerTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/HistoricalReplayAnalyzerTest.java @@ -32,6 +32,11 @@ class HistoricalReplayAnalyzerTest { private final HistoricalReplayAnalyzer analyzer = new HistoricalReplayAnalyzer(); private final Set sites = new LinkedHashSet(Arrays.asList("A", "B", "C", "D")); + /** + * 验证“touching intervals do not overlap”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalReplayAnalyzerTest},用于保持当前模块的职责边界清晰。 + */ @Test void touchingIntervalsDoNotOverlap() { HistoricalPath left = path("G1", "T1", "V1", "A,B,", "10:00:00", "10:01:00"); @@ -39,6 +44,11 @@ class HistoricalReplayAnalyzerTest { assertFalse(analyzer.overlaps(left, right)); } + /** + * 验证“detects opposite use of same undirected edge”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalReplayAnalyzerTest},用于保持当前模块的职责边界清晰。 + */ @Test void detectsOppositeUseOfSameUndirectedEdge() { List results = analyzer.analyze(Arrays.asList( @@ -48,6 +58,11 @@ class HistoricalReplayAnalyzerTest { result.getCategory() == HistoricalReplayCategory.POTENTIAL_OPPOSITE_EDGE)); } + /** + * 验证“held path still participates in later conflict detection”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalReplayAnalyzerTest},用于保持当前模块的职责边界清晰。 + */ @Test void heldPathStillParticipatesInLaterConflictDetection() { List results = analyzer.analyze(Arrays.asList( @@ -60,6 +75,11 @@ class HistoricalReplayAnalyzerTest { assertEquals("T2", results.get(2).getRelatedTaskNo()); } + /** + * 验证“identical input produces identical results”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalReplayAnalyzerTest},用于保持当前模块的职责边界清晰。 + */ @Test void identicalInputProducesIdenticalResults() { List sample = Arrays.asList( @@ -68,6 +88,13 @@ class HistoricalReplayAnalyzerTest { assertEquals(analyzer.analyze(sample), analyzer.analyze(sample)); } + /** + * 验证“writes readable evidence with original ids and boundary text”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalReplayAnalyzerTest},用于保持当前模块的职责边界清晰。 + * @param temp 执行该处理所需的 temp 输入。 + * @throws Exception 当调用条件不满足或处理无法继续时抛出。 + */ @Test void writesReadableEvidenceWithOriginalIdsAndBoundaryText(@TempDir Path temp) throws Exception { HistoricalQueueDataset dataset = new HistoricalQueueLoader().load( @@ -101,6 +128,18 @@ class HistoricalReplayAnalyzerTest { assertTrue(Files.size(temp.resolve("manifest.sha256")) > 0); } + /** + * 验证“path”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalReplayAnalyzerTest},用于保持当前模块的职责边界清晰。 + * @param guid 执行该处理所需的 guid 输入。 + * @param task 执行该处理所需的 task 输入。 + * @param agv 执行该处理所需的 agv 输入。 + * @param nodes 执行该处理所需的 nodes 输入。 + * @param start 执行该处理所需的 start 输入。 + * @param finish 执行该处理所需的 finish 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private HistoricalPath path(String guid, String task, String agv, String nodes, String start, String finish) { HistoricalQueueRecord record = new HistoricalQueueRecord(guid, task, "1", 2, diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/MapAndResourceLedgerTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/MapAndResourceLedgerTest.java index c3e6e66..2c9c2f8 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/MapAndResourceLedgerTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/MapAndResourceLedgerTest.java @@ -19,6 +19,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue; class MapAndResourceLedgerTest { + /** + * 验证“canonicalizes undirected edges and does not lock whole zone”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code MapAndResourceLedgerTest},用于保持当前模块的职责边界清晰。 + */ @Test void canonicalizesUndirectedEdgesAndDoesNotLockWholeZone() { assertEquals("EDGE:A:B", ResourceKey.edge("B", "A").value()); @@ -30,6 +35,11 @@ class MapAndResourceLedgerTest { assertTrue(ledger.evaluate("V2", Collections.singleton(ResourceKey.node("C"))).isGranted()); } + /** + * 验证“rejects unconfirmed or mismatched map”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code MapAndResourceLedgerTest},用于保持当前模块的职责边界清晰。 + */ @Test void rejectsUnconfirmedOrMismatchedMap() { TrafficMapCompiler compiler = new TrafficMapCompiler(); @@ -40,6 +50,11 @@ class MapAndResourceLedgerTest { () -> compiler.compile(definition("sha-546", "sha-546", false))); } + /** + * 验证“rejects unsafe wait sites self edges and unknown capacity resources”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code MapAndResourceLedgerTest},用于保持当前模块的职责边界清晰。 + */ @Test void rejectsUnsafeWaitSitesSelfEdgesAndUnknownCapacityResources() { TrafficMapCompiler compiler = new TrafficMapCompiler(); @@ -54,6 +69,11 @@ class MapAndResourceLedgerTest { assertThrows(IllegalArgumentException.class, () -> compiler.compile(base.withVersionId(0L))); } + /** + * 验证“enforces node edge and configured capacity”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code MapAndResourceLedgerTest},用于保持当前模块的职责边界清晰。 + */ @Test void enforcesNodeEdgeAndConfiguredCapacity() { EffectiveTrafficMap map = new TrafficMapCompiler().compile(definition("sha-546", "sha-546", true)); @@ -74,6 +94,15 @@ class MapAndResourceLedgerTest { assertFalse(ledger.evaluate("V6", Collections.singleton(ResourceKey.conflict("WIDE"))).isGranted()); } + /** + * 验证“definition”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code MapAndResourceLedgerTest},用于保持当前模块的职责边界清晰。 + * @param baseChecksum 执行该处理所需的 base checksum 输入。 + * @param configuredChecksum 执行该处理所需的 configured checksum 输入。 + * @param confirmed 执行该处理所需的 confirmed 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private TrafficMapCompiler.MapDefinition definition( String baseChecksum, String configuredChecksum, boolean confirmed) { LinkedHashSet nodes = new LinkedHashSet(Arrays.asList("A", "B", "C")); diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/RollingDispatchPolicyTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/RollingDispatchPolicyTest.java index 315acdb..83e296c 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/RollingDispatchPolicyTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/RollingDispatchPolicyTest.java @@ -23,6 +23,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue; class RollingDispatchPolicyTest { + /** + * 验证“sorts deterministically and allows non conflicting parallel grants”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code RollingDispatchPolicyTest},用于保持当前模块的职责边界清晰。 + */ @Test void sortsDeterministicallyAndAllowsNonConflictingParallelGrants() { EffectiveTrafficMap map = map(); @@ -39,6 +44,11 @@ class RollingDispatchPolicyTest { assertEquals(DecisionType.GRANT, decisions.get(1).getType()); } + /** + * 验证“holds conflicts and uses only published yield site”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code RollingDispatchPolicyTest},用于保持当前模块的职责边界清晰。 + */ @Test void holdsConflictsAndUsesOnlyPublishedYieldSite() { EffectiveTrafficMap map = map(); @@ -57,6 +67,11 @@ class RollingDispatchPolicyTest { assertEquals(Collections.singleton("BLOCKER"), decisions.get(1).getBlockingVehicles()); } + /** + * 验证“rejects wait cycle and never revokes committed segment”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code RollingDispatchPolicyTest},用于保持当前模块的职责边界清晰。 + */ @Test void rejectsWaitCycleAndNeverRevokesCommittedSegment() { EffectiveTrafficMap map = map(); @@ -76,6 +91,11 @@ class RollingDispatchPolicyTest { assertEquals("WAIT_CYCLE", decisions.get(2).getReasonCode()); } + /** + * 验证“committed segment protects resources before new candidates compete”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code RollingDispatchPolicyTest},用于保持当前模块的职责边界清晰。 + */ @Test void committedSegmentProtectsResourcesBeforeNewCandidatesCompete() { EffectiveTrafficMap map = map(); @@ -92,6 +112,11 @@ class RollingDispatchPolicyTest { assertEquals(Collections.singleton("V0"), decisions.get(1).getBlockingVehicles()); } + /** + * 验证“detects cycle before adding wait edges”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code RollingDispatchPolicyTest},用于保持当前模块的职责边界清晰。 + */ @Test void detectsCycleBeforeAddingWaitEdges() { WaitForGraph graph = new WaitForGraph(); @@ -101,6 +126,11 @@ class RollingDispatchPolicyTest { assertFalse(graph.isAcyclic()); } + /** + * 验证“unknown resource fails closed as structured hold”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code RollingDispatchPolicyTest},用于保持当前模块的职责边界清晰。 + */ @Test void unknownResourceFailsClosedAsStructuredHold() { EffectiveTrafficMap map = map(); @@ -115,12 +145,30 @@ class RollingDispatchPolicyTest { assertEquals("UNKNOWN_RESOURCE", decision.getReasonCode()); } + /** + * 验证“candidate”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code RollingDispatchPolicyTest},用于保持当前模块的职责边界清晰。 + * @param task 执行该处理所需的 task 输入。 + * @param vehicle 执行该处理所需的 vehicle 输入。 + * @param priority 执行该处理所需的 priority 输入。 + * @param age 执行该处理所需的 age 输入。 + * @param resource 执行该处理所需的 resource 输入。 + * @param yieldSite 执行该处理所需的 yield site 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private ShadowCandidate candidate(String task, String vehicle, int priority, long age, ResourceKey resource, String yieldSite) { return ShadowCandidate.waiting(task, vehicle, false, priority, age, 1, Collections.singleton(resource), yieldSite); } + /** + * 验证“map”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code RollingDispatchPolicyTest},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private EffectiveTrafficMap map() { LinkedHashSet nodes = new LinkedHashSet(Arrays.asList("A", "B", "C")); LinkedHashSet edges = diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/SegmentAndSnapshotTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/SegmentAndSnapshotTest.java index 07c6938..5ea8109 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/SegmentAndSnapshotTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/SegmentAndSnapshotTest.java @@ -23,6 +23,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue; class SegmentAndSnapshotTest { + /** + * 验证“forbids prepared to executing and keeps unknown commit protected”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code SegmentAndSnapshotTest},用于保持当前模块的职责边界清晰。 + */ @Test void forbidsPreparedToExecutingAndKeepsUnknownCommitProtected() { TrafficSegment prepared = segment() @@ -38,6 +43,11 @@ class SegmentAndSnapshotTest { assertEquals(ReservationState.UNKNOWN_HARD, uncertain.getReservationState()); } + /** + * 验证“freezes composite snapshot”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code SegmentAndSnapshotTest},用于保持当前模块的职责边界清晰。 + */ @Test void freezesCompositeSnapshot() { List vehicles = new ArrayList(); @@ -51,6 +61,11 @@ class SegmentAndSnapshotTest { () -> snapshot.getVehicles().add(vehicle("BOOT-1", 4L, Instant.now()))); } + /** + * 验证“rejects stale rollback and restart snapshots”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code SegmentAndSnapshotTest},用于保持当前模块的职责边界清晰。 + */ @Test void rejectsStaleRollbackAndRestartSnapshots() { SnapshotFreshnessPolicy policy = new SnapshotFreshnessPolicy(Duration.ofSeconds(2)); @@ -67,11 +82,26 @@ class SegmentAndSnapshotTest { assertTrue(policy.validate(previous, vehicle("BOOT-1", 6L, now), now).isHealthy()); } + /** + * 验证“segment”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code SegmentAndSnapshotTest},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private TrafficSegment segment() { return TrafficSegment.planned("SEG-1", "V1", "BOOT-1", 7L, 2L, 1L, Arrays.asList("A", "B", "C")); } + /** + * 验证“vehicle”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code SegmentAndSnapshotTest},用于保持当前模块的职责边界清晰。 + * @param bootId 执行该处理所需的 boot id 输入。 + * @param seq 执行该处理所需的 seq 输入。 + * @param receivedAt 执行该处理所需的 received at 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private TrafficVehicleSnapshot vehicle(String bootId, long seq, Instant receivedAt) { return new TrafficVehicleSnapshot( "V1", bootId, seq, seq, receivedAt, "B", "C", diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/ShadowCoordinatorReplayTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/ShadowCoordinatorReplayTest.java index ab8b51d..5447e39 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/ShadowCoordinatorReplayTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/ShadowCoordinatorReplayTest.java @@ -29,6 +29,11 @@ import static org.junit.jupiter.api.Assertions.assertThrows; class ShadowCoordinatorReplayTest { + /** + * 验证“shadow ports reject every authoritative write”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowCoordinatorReplayTest},用于保持当前模块的职责边界清晰。 + */ @Test void shadowPortsRejectEveryAuthoritativeWrite() { ShadowWritePort port = new ShadowWritePort(); @@ -38,6 +43,11 @@ class ShadowCoordinatorReplayTest { assertThrows(ShadowWriteForbiddenException.class, () -> port.writeReservation("SEG-1")); } + /** + * 验证“coordinator produces stable event without mutating authoritative ledger”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowCoordinatorReplayTest},用于保持当前模块的职责边界清晰。 + */ @Test void coordinatorProducesStableEventWithoutMutatingAuthoritativeLedger() { EffectiveTrafficMap map = map(); @@ -62,6 +72,11 @@ class ShadowCoordinatorReplayTest { assertEquals(1, ledger.protectedCount(ResourceKey.node("B"))); } + /** + * 验证“rejects non shadow stale disconnected and restarted snapshots”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowCoordinatorReplayTest},用于保持当前模块的职责边界清晰。 + */ @Test void rejectsNonShadowStaleDisconnectedAndRestartedSnapshots() { EffectiveTrafficMap map = map(); @@ -92,6 +107,12 @@ class ShadowCoordinatorReplayTest { Collections.singletonList(candidate))); } + /** + * 验证“reads and replays golden decision event”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowCoordinatorReplayTest},用于保持当前模块的职责边界清晰。 + * @throws Exception 当调用条件不满足或处理无法继续时抛出。 + */ @Test void readsAndReplaysGoldenDecisionEvent() throws Exception { InputStream input = getClass().getResourceAsStream("/shadow/golden/basic-conflict.json"); @@ -106,6 +127,12 @@ class ShadowCoordinatorReplayTest { replay.replay(event).get(0).getConflictingResources()); } + /** + * 验证“replay rejects tampered hash or recorded decision”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowCoordinatorReplayTest},用于保持当前模块的职责边界清晰。 + * @throws Exception 当调用条件不满足或处理无法继续时抛出。 + */ @Test void replayRejectsTamperedHashOrRecordedDecision() throws Exception { DecisionReplayService replay = new DecisionReplayService(); @@ -121,6 +148,12 @@ class ShadowCoordinatorReplayTest { assertThrows(IllegalStateException.class, () -> replay.replay(tamperedDecision)); } + /** + * 验证“map”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowCoordinatorReplayTest},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private EffectiveTrafficMap map() { LinkedHashSet nodes = new LinkedHashSet(Arrays.asList("A", "B", "C")); LinkedHashSet edges = @@ -133,6 +166,16 @@ class ShadowCoordinatorReplayTest { Collections.singleton("C"))); } + /** + * 验证“vehicle”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowCoordinatorReplayTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @param boot 执行该处理所需的 boot 输入。 + * @param seq 执行该处理所需的 seq 输入。 + * @param at 执行该处理所需的 at 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private TrafficVehicleSnapshot vehicle(String id, String boot, long seq, Instant at) { return new TrafficVehicleSnapshot(id, boot, seq, seq, at, "A", "B", Arrays.asList("A", "B"), true, false, false); diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/ShadowInvariantPropertyTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/ShadowInvariantPropertyTest.java index c95581c..7459556 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/ShadowInvariantPropertyTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/ShadowInvariantPropertyTest.java @@ -24,6 +24,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue; class ShadowInvariantPropertyTest { + /** + * 验证“fixed seeds preserve capacity acyclicity and determinism”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowInvariantPropertyTest},用于保持当前模块的职责边界清晰。 + */ @Test void fixedSeedsPreserveCapacityAcyclicityAndDeterminism() { for (long seed = 546001L; seed <= 546010L; seed++) { @@ -31,6 +36,12 @@ class ShadowInvariantPropertyTest { } } + /** + * 验证“verify seed”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowInvariantPropertyTest},用于保持当前模块的职责边界清晰。 + * @param seed 执行该处理所需的 seed 输入。 + */ private void verifySeed(long seed) { Random random = new Random(seed); EffectiveTrafficMap map = map(); @@ -77,6 +88,14 @@ class ShadowInvariantPropertyTest { } } + /** + * 验证“find”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowInvariantPropertyTest},用于保持当前模块的职责边界清晰。 + * @param candidates 执行该处理所需的 candidates 输入。 + * @param vehicleId 执行该处理所需的 vehicle id 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private ShadowCandidate find(List candidates, String vehicleId) { for (ShadowCandidate candidate : candidates) { if (candidate.getVehicleId().equals(vehicleId)) return candidate; @@ -84,6 +103,13 @@ class ShadowInvariantPropertyTest { throw new IllegalStateException("candidate not found " + vehicleId); } + /** + * 验证“signature”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowInvariantPropertyTest},用于保持当前模块的职责边界清晰。 + * @param decisions 执行该处理所需的 decisions 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private List signature(List decisions) { List result = new ArrayList(); for (ShadowDecision decision : decisions) { @@ -92,6 +118,12 @@ class ShadowInvariantPropertyTest { return result; } + /** + * 验证“map”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowInvariantPropertyTest},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private EffectiveTrafficMap map() { LinkedHashSet nodes = new LinkedHashSet(Arrays.asList("N0", "N1", "N2", "N3")); diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/ShadowSimulationDataTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/ShadowSimulationDataTest.java index 2d404a2..ab73d60 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/ShadowSimulationDataTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/ShadowSimulationDataTest.java @@ -38,6 +38,15 @@ import static org.junit.jupiter.api.Assertions.assertTrue; class ShadowSimulationDataTest { + /** + * 验证“executes simulation record”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @param type 执行该处理所需的 type 输入。 + * @param variant 执行该处理所需的 variant 输入。 + * @param expected 执行该处理所需的 expected 输入。 + */ @ParameterizedTest(name = "{0} {1} expected={3}") @MethodSource("simulationCases") void executesSimulationRecord(String id, String type, int variant, String expected) { @@ -58,6 +67,13 @@ class ShadowSimulationDataTest { } } + /** + * 验证“simulation cases”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + * @throws Exception 当调用条件不满足或处理无法继续时抛出。 + */ static Stream simulationCases() throws Exception { InputStream input = ShadowSimulationDataTest.class.getResourceAsStream( "/shadow/scenarios/shadow-simulation-60.json"); @@ -71,6 +87,13 @@ class ShadowSimulationDataTest { return cases.stream(); } + /** + * 验证“same node”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @param expected 执行该处理所需的 expected 输入。 + */ private void sameNode(String id, String expected) { ResourceLedger ledger = ledger(); ledger.evaluate("BLOCKER-" + id, Collections.singleton(ResourceKey.node("B"))); @@ -78,6 +101,13 @@ class ShadowSimulationDataTest { assertEquals(expected, decision.getType().name(), id); } + /** + * 验证“opposite edge”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @param expected 执行该处理所需的 expected 输入。 + */ private void oppositeEdge(String id, String expected) { ResourceLedger ledger = ledger(); ledger.evaluate("BLOCKER-" + id, Collections.singleton(ResourceKey.edge("A", "B"))); @@ -87,6 +117,13 @@ class ShadowSimulationDataTest { assertEquals(expected, decide(ledger, candidate).get(0).getType().name(), id); } + /** + * 验证“parallel”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @param expected 执行该处理所需的 expected 输入。 + */ private void parallel(String id, String expected) { List decisions = policy().decide(Arrays.asList( candidate(id + "-A", "A", null), candidate(id + "-C", "C", null)), @@ -94,6 +131,13 @@ class ShadowSimulationDataTest { assertEquals(2, count(decisions, DecisionType.valueOf(expected)), id); } + /** + * 验证“capacity two”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @param expected 执行该处理所需的 expected 输入。 + */ private void capacityTwo(String id, String expected) { ResourceLedger ledger = ledger(); ledger.evaluate("V0-" + id, Collections.singleton(ResourceKey.conflict("WIDE"))); @@ -103,6 +147,13 @@ class ShadowSimulationDataTest { assertEquals(1, count(decisions, DecisionType.HOLD), id + " " + expected); } + /** + * 验证“committed blocks”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @param expected 执行该处理所需的 expected 输入。 + */ private void committedBlocks(String id, String expected) { List decisions = policy().decide(Arrays.asList( ShadowCandidate.committed(id + "-H", "VH-" + id, @@ -112,12 +163,26 @@ class ShadowSimulationDataTest { assertEquals(DecisionType.HOLD, decisions.get(1).getType(), id + " " + expected); } + /** + * 验证“safe yield”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @param expected 执行该处理所需的 expected 输入。 + */ private void safeYield(String id, String expected) { ResourceLedger ledger = ledger(); ledger.evaluate("BLOCKER-" + id, Collections.singleton(ResourceKey.node("B"))); assertEquals(expected, decide(ledger, candidate(id, "B", "D")).get(0).getType().name(), id); } + /** + * 验证“no safe yield”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @param expected 执行该处理所需的 expected 输入。 + */ private void noSafeYield(String id, String expected) { ResourceLedger ledger = ledger(); ledger.evaluate("BLOCKER-" + id, Collections.singleton(ResourceKey.node("B"))); @@ -126,6 +191,13 @@ class ShadowSimulationDataTest { assertEquals("NO_SAFE_YIELD_SITE", decision.getReasonCode(), id); } + /** + * 验证“wait cycle”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @param expected 执行该处理所需的 expected 输入。 + */ private void waitCycle(String id, String expected) { ResourceLedger ledger = ledger(); ledger.evaluate("V2-" + id, Collections.singleton(ResourceKey.node("A"))); @@ -139,6 +211,14 @@ class ShadowSimulationDataTest { assertEquals("WAIT_CYCLE", decisions.get(1).getReasonCode(), id); } + /** + * 验证“feedback progress”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @param expected 执行该处理所需的 expected 输入。 + * @param variant 执行该处理所需的 variant 输入。 + */ private void feedbackProgress(String id, String expected, int variant) { FeedbackResult result = new FeedbackReconciler().reconcile( committedSegment(id), feedback("BOOT-1", 2L, 10L + variant, @@ -147,6 +227,14 @@ class ShadowSimulationDataTest { assertTrue(result.getReleasedResources().contains(ResourceKey.node("A")), id + " " + expected); } + /** + * 验证“feedback fail closed”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @param expected 执行该处理所需的 expected 输入。 + * @param variant 执行该处理所需的 variant 输入。 + */ private void feedbackFailClosed(String id, String expected, int variant) { ExecutionFeedback feedback; if (variant == 1) feedback = feedback("BOOT-1", 3L, 11L, "B", Arrays.asList("B", "C"), true, true); @@ -159,6 +247,14 @@ class ShadowSimulationDataTest { assertTrue(result.getReleasedResources().isEmpty(), id); } + /** + * 验证“snapshot fail closed”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @param expected 执行该处理所需的 expected 输入。 + * @param variant 执行该处理所需的 variant 输入。 + */ private void snapshotFailClosed(String id, String expected, int variant) { Instant now = Instant.parse("2026-07-30T06:00:00Z"); TrafficVehicleSnapshot previous = snapshot("BOOT-1", 10L, now.minusSeconds(1), true, false, false); @@ -172,6 +268,14 @@ class ShadowSimulationDataTest { .validate(previous, current, now).isHealthy(), id + " " + expected); } + /** + * 验证“deterministic”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @param expected 执行该处理所需的 expected 输入。 + * @param variant 执行该处理所需的 variant 输入。 + */ private void deterministic(String id, String expected, int variant) { List candidates = Arrays.asList( candidate(id + "-2", variant % 2 == 0 ? "C" : "B", null), @@ -181,27 +285,77 @@ class ShadowSimulationDataTest { assertEquals(first, second, id + " " + expected); } + /** + * 验证“decide”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @param ledger 执行该处理所需的 ledger 输入。 + * @param candidate 执行该处理所需的 candidate 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private List decide(ResourceLedger ledger, ShadowCandidate candidate) { return policy().decide(Collections.singletonList(candidate), ledger, map()); } + /** + * 验证“candidate”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @param site 执行该处理所需的 site 输入。 + * @param yieldSite 执行该处理所需的 yield site 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private ShadowCandidate candidate(String id, String site, String yieldSite) { return ShadowCandidate.waiting(id, "V-" + id, false, 1, 1, 1, Collections.singleton(ResourceKey.node(site)), yieldSite); } + /** + * 验证“conflict candidate”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private ShadowCandidate conflictCandidate(String id) { return ShadowCandidate.waiting(id, "V-" + id, false, 1, 1, 1, Collections.singleton(ResourceKey.conflict("WIDE")), null); } + /** + * 验证“count”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @param decisions 执行该处理所需的 decisions 输入。 + * @param type 执行该处理所需的 type 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private long count(List decisions, DecisionType type) { return decisions.stream().filter(decision -> decision.getType() == type).count(); } + /** + * 验证“policy”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private RollingDispatchPolicy policy() { return new RollingDispatchPolicy(); } + /** + * 验证“ledger”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private ResourceLedger ledger() { return new ResourceLedger(map().getCapacities()); } + /** + * 验证“map”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private EffectiveTrafficMap map() { LinkedHashSet nodes = new LinkedHashSet(Arrays.asList("A", "B", "C", "D")); @@ -217,6 +371,13 @@ class ShadowSimulationDataTest { capacities, Collections.singleton("B"), Collections.singleton("D"))); } + /** + * 验证“committed segment”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private TrafficSegment committedSegment(String id) { return TrafficSegment.planned("SEG-" + id, "V-" + id, "BOOT-1", 7L, 2L, 1L, Arrays.asList("A", "B", "C")) @@ -224,11 +385,36 @@ class ShadowSimulationDataTest { .transition(SegmentEvent.BEGIN_COMMIT).transition(SegmentEvent.COMMITTED); } + /** + * 验证“feedback”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @param boot 执行该处理所需的 boot 输入。 + * @param version 执行该处理所需的 version 输入。 + * @param seq 执行该处理所需的 seq 输入。 + * @param current 执行该处理所需的 current 输入。 + * @param remaining 执行该处理所需的 remaining 输入。 + * @param connected 执行该处理所需的 connected 输入。 + * @param ack 执行该处理所需的 ack 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private ExecutionFeedback feedback(String boot, long version, long seq, String current, List remaining, boolean connected, boolean ack) { return new ExecutionFeedback(boot, 7L, version, 1L, seq, current, remaining, connected, ack); } + /** + * 验证“snapshot”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ShadowSimulationDataTest},用于保持当前模块的职责边界清晰。 + * @param boot 执行该处理所需的 boot 输入。 + * @param seq 执行该处理所需的 seq 输入。 + * @param at 执行该处理所需的 at 输入。 + * @param connected 执行该处理所需的 connected 输入。 + * @param faulted 执行该处理所需的 faulted 输入。 + * @param manual 执行该处理所需的 manual 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private TrafficVehicleSnapshot snapshot(String boot, long seq, Instant at, boolean connected, boolean faulted, boolean manual) { return new TrafficVehicleSnapshot("V1", boot, seq, seq, at, "A", "B", diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/ClearanceMovePlannerTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/ClearanceMovePlannerTest.java index 7a8e026..0145276 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/ClearanceMovePlannerTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/ClearanceMovePlannerTest.java @@ -14,6 +14,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; class ClearanceMovePlannerTest { + /** + * 验证“selects areachable off route unoccupied site”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code ClearanceMovePlannerTest},用于保持当前模块的职责边界清晰。 + */ @Test void selectsAReachableOffRouteUnoccupiedSite() { GridMap map = new GridMap(); diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/CorridorReservationManagerTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/CorridorReservationManagerTest.java index 61ce292..0f11da9 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/CorridorReservationManagerTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/CorridorReservationManagerTest.java @@ -9,6 +9,11 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; class CorridorReservationManagerTest { + /** + * 验证“keeps one direction until the owner leaves the shared corridor”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code CorridorReservationManagerTest},用于保持当前模块的职责边界清晰。 + */ @Test void keepsOneDirectionUntilTheOwnerLeavesTheSharedCorridor() { CorridorReservationManager manager = new CorridorReservationManager(); @@ -30,6 +35,11 @@ class CorridorReservationManagerTest { .isGranted()); } + /** + * 验证“admits same direction while physical resources remain capacity one”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code CorridorReservationManagerTest},用于保持当前模块的职责边界清晰。 + */ @Test void admitsSameDirectionWhilePhysicalResourcesRemainCapacityOne() { CorridorReservationManager manager = new CorridorReservationManager(); diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchFaultMatrixTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchFaultMatrixTest.java index 831fc37..af9dab5 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchFaultMatrixTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchFaultMatrixTest.java @@ -16,6 +16,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; class HistoricalDispatchFaultMatrixTest { + /** + * 验证“recovers from disconnect restart low battery and vehicle fault”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalDispatchFaultMatrixTest},用于保持当前模块的职责边界清晰。 + */ @Test void recoversFromDisconnectRestartLowBatteryAndVehicleFault() { DeterministicFaultPlan faults = DeterministicFaultPlan.builder() @@ -42,6 +47,11 @@ class HistoricalDispatchFaultMatrixTest { "REDISPATCH".equals(event.getType()) || "HOLD".equals(event.getType()))); } + /** + * 验证“retries ack timeout and loss before moving”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalDispatchFaultMatrixTest},用于保持当前模块的职责边界清晰。 + */ @Test void retriesAckTimeoutAndLossBeforeMoving() { DeterministicFaultPlan faults = DeterministicFaultPlan.builder() diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationRealDataTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationRealDataTest.java index 757a756..672dad0 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationRealDataTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationRealDataTest.java @@ -20,6 +20,11 @@ class HistoricalDispatchSimulationRealDataTest { private static HistoricalDispatchSimulationResult secondRun; private static HistoricalSimulationInput simulationInput; + /** + * 验证“simulate real history twice”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalDispatchSimulationRealDataTest},用于保持当前模块的职责边界清晰。 + */ @BeforeAll static void simulateRealHistoryTwice() { HistoricalQueueDataset dataset = new HistoricalQueueLoader().load( @@ -36,10 +41,22 @@ class HistoricalDispatchSimulationRealDataTest { secondRun = simulator.simulate(input, SimulationConfig.defaults(), plan); } + /** + * 验证“real task results”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalDispatchSimulationRealDataTest},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ static Stream realTaskResults() { return result.getTaskResults().stream(); } + /** + * 验证“every history row has one auditable outcome”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalDispatchSimulationRealDataTest},用于保持当前模块的职责边界清晰。 + * @param task 执行该处理所需的 task 输入。 + */ @ParameterizedTest(name = "{index} {0}") @MethodSource("realTaskResults") void everyHistoryRowHasOneAuditableOutcome(SimulationTaskResult task) { @@ -55,6 +72,11 @@ class HistoricalDispatchSimulationRealDataTest { } } + /** + * 验证“completes the real workload deterministically without safety violations”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalDispatchSimulationRealDataTest},用于保持当前模块的职责边界清晰。 + */ @Test void completesTheRealWorkloadDeterministicallyWithoutSafetyViolations() { assertEquals(240, result.getTaskResults().size()); diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationReportWriterTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationReportWriterTest.java index 22531a2..5af3d2f 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationReportWriterTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationReportWriterTest.java @@ -19,6 +19,12 @@ import static org.junit.jupiter.api.Assertions.assertTrue; class HistoricalDispatchSimulationReportWriterTest { @TempDir Path output; + /** + * 验证“writes auditable metrics task events invariants and hashes”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalDispatchSimulationReportWriterTest},用于保持当前模块的职责边界清晰。 + * @throws Exception 当调用条件不满足或处理无法继续时抛出。 + */ @Test void writesAuditableMetricsTaskEventsInvariantsAndHashes() throws Exception { HistoricalQueueDataset dataset = new HistoricalQueueLoader().load( diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulatorTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulatorTest.java index 332e351..4f460f0 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulatorTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulatorTest.java @@ -21,6 +21,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; class HistoricalDispatchSimulatorTest { + /** + * 验证“runs multiple tasks through arbitration retry movement archive and wms”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalDispatchSimulatorTest},用于保持当前模块的职责边界清晰。 + */ @Test void runsMultipleTasksThroughArbitrationRetryMovementArchiveAndWms() { HistoricalSimulationInput input = controlledInput(); @@ -43,6 +48,11 @@ class HistoricalDispatchSimulatorTest { assertEquals(0, result.getInvariants().totalSafetyViolations()); } + /** + * 验证“holds an opposite route at the corridor entrance before it can livelock”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalDispatchSimulatorTest},用于保持当前模块的职责边界清晰。 + */ @Test void holdsAnOppositeRouteAtTheCorridorEntranceBeforeItCanLivelock() { HistoricalDispatchSimulationResult result = new HistoricalDispatchSimulator().simulate( @@ -57,6 +67,11 @@ class HistoricalDispatchSimulatorTest { assertEquals(0, result.getInvariants().totalSafetyViolations()); } + /** + * 验证“replans on the map instead of returning the historical reference path”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalDispatchSimulatorTest},用于保持当前模块的职责边界清晰。 + */ @Test void replansOnTheMapInsteadOfReturningTheHistoricalReferencePath() { HistoricalDispatchSimulationResult result = new HistoricalDispatchSimulator().simulate( @@ -68,6 +83,11 @@ class HistoricalDispatchSimulatorTest { assertEquals(1, result.getReplannedCount()); } + /** + * 验证“moves idle blockers node by node and completes both business directions”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalDispatchSimulatorTest},用于保持当前模块的职责边界清晰。 + */ @Test void movesIdleBlockersNodeByNodeAndCompletesBothBusinessDirections() { HistoricalSimulationInput input = blockedThreeVehicleCorridorInput(); @@ -97,6 +117,12 @@ class HistoricalDispatchSimulatorTest { assertEquals(0, result.getInvariants().getCapacityViolations()); } + /** + * 验证“controlled input”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalDispatchSimulatorTest},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ static HistoricalSimulationInput controlledInput() { GridMap grid = new GridMap(); for (String node : Arrays.asList("A", "B", "C", "D")) { @@ -124,6 +150,12 @@ class HistoricalDispatchSimulatorTest { return new HistoricalSimulationInput(tasks, Collections.emptyList(), grid, traffic, vehicles); } + /** + * 验证“opposite corridor input”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalDispatchSimulatorTest},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private HistoricalSimulationInput oppositeCorridorInput() { GridMap grid = new GridMap(); for (String node : Arrays.asList("A", "B", "C", "D", "E")) { @@ -154,6 +186,12 @@ class HistoricalDispatchSimulatorTest { return new HistoricalSimulationInput(tasks, Collections.emptyList(), grid, traffic, vehicles); } + /** + * 验证“alternate route input”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalDispatchSimulatorTest},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private HistoricalSimulationInput alternateRouteInput() { GridMap grid = new GridMap(); for (String node : Arrays.asList("A", "B", "C")) { @@ -180,6 +218,12 @@ class HistoricalDispatchSimulatorTest { "1", 1, "A", 5, 1, 100, true, true, false))); } + /** + * 验证“blocked three vehicle corridor input”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalDispatchSimulatorTest},用于保持当前模块的职责边界清晰。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private HistoricalSimulationInput blockedThreeVehicleCorridorInput() { GridMap grid = new GridMap(); for (String node : Arrays.asList("A", "B", "C", "D", "X", "Z")) { @@ -213,6 +257,17 @@ class HistoricalDispatchSimulatorTest { return new HistoricalSimulationInput(tasks, Collections.emptyList(), grid, traffic, vehicles); } + /** + * 验证“task”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalDispatchSimulatorTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @param source 执行该处理所需的 source 输入。 + * @param target 执行该处理所需的 target 输入。 + * @param priority 执行该处理所需的 priority 输入。 + * @param sequence 执行该处理所需的 sequence 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private static HistoricalSimulationTask task(String id, String source, String target, int priority, int sequence) { List path = "T2".equals(id) @@ -222,6 +277,18 @@ class HistoricalDispatchSimulatorTest { return customTask(id, source, target, priority, sequence, path); } + /** + * 验证“custom task”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalDispatchSimulatorTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @param source 执行该处理所需的 source 输入。 + * @param target 执行该处理所需的 target 输入。 + * @param priority 执行该处理所需的 priority 输入。 + * @param sequence 执行该处理所需的 sequence 输入。 + * @param path 执行该处理所需的 path 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private static HistoricalSimulationTask customTask( String id, String source, String target, int priority, int sequence, List path) { diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalGridMapCompilerTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalGridMapCompilerTest.java index a526fe3..443791f 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalGridMapCompilerTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalGridMapCompilerTest.java @@ -11,6 +11,11 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; class HistoricalGridMapCompilerTest { + /** + * 验证“connects only passable same floor manhattan neighbors”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalGridMapCompilerTest},用于保持当前模块的职责边界清晰。 + */ @Test void connectsOnlyPassableSameFloorManhattanNeighbors() { HistoricalGridMapCompiler.CompiledHistoricalMap compiled = @@ -31,6 +36,17 @@ class HistoricalGridMapCompilerTest { assertNotEquals(compiled.getComponentId("A"), compiled.getComponentId("UP")); } + /** + * 验证“cell”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalGridMapCompilerTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @param x 执行该处理所需的 x 输入。 + * @param y 执行该处理所需的 y 输入。 + * @param z 执行该处理所需的 z 输入。 + * @param value 执行该处理所需的 value 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private HistoricalMapCell cell(String id, int x, int y, int z, int value) { return new HistoricalMapCell(id, x, y, z, value, x + "," + y, "W", "AREA"); diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationInputFactoryTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationInputFactoryTest.java index d677518..0bab1b3 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationInputFactoryTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationInputFactoryTest.java @@ -20,6 +20,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue; class HistoricalSimulationInputFactoryTest { private static HistoricalSimulationInput input; + /** + * 验证“create input”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalSimulationInputFactoryTest},用于保持当前模块的职责边界清晰。 + */ @BeforeAll static void createInput() { HistoricalQueueDataset dataset = new HistoricalQueueLoader().load( @@ -27,6 +32,11 @@ class HistoricalSimulationInputFactoryTest { input = new HistoricalSimulationInputFactory().create(dataset); } + /** + * 验证“converts every history row to one unique schedulable or failed input”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalSimulationInputFactoryTest},用于保持当前模块的职责边界清晰。 + */ @Test void convertsEveryHistoryRowToOneUniqueSchedulableOrFailedInput() { assertEquals(240, input.getTasks().size()); @@ -35,6 +45,11 @@ class HistoricalSimulationInputFactoryTest { assertEquals(240, input.allSimulationIds().stream().distinct().count()); } + /** + * 验证“preserves business inputs while mapping physical endpoints explicitly”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalSimulationInputFactoryTest},用于保持当前模块的职责边界清晰。 + */ @Test void preservesBusinessInputsWhileMappingPhysicalEndpointsExplicitly() { HistoricalSimulationTask task = input.getTasks().stream() @@ -47,6 +62,11 @@ class HistoricalSimulationInputFactoryTest { assertFalse(task.getHistoricalNodes().isEmpty()); } + /** + * 验证“builds replannable topology and initializes the historical fleet”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalSimulationInputFactoryTest},用于保持当前模块的职责边界清晰。 + */ @Test void buildsReplannableTopologyAndInitializesTheHistoricalFleet() { assertEquals(EnumSet.allOf(DispatchTask.TaskType.class), input.getTasks().stream() @@ -57,6 +77,11 @@ class HistoricalSimulationInputFactoryTest { .map(vehicle -> vehicle.getVehicleId()).collect(Collectors.toList())); } + /** + * 验证“changing historical path does not change planning input”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalSimulationInputFactoryTest},用于保持当前模块的职责边界清晰。 + */ @Test void changingHistoricalPathDoesNotChangePlanningInput() { HistoricalQueueDataset original = new HistoricalQueueLoader().load( @@ -79,6 +104,14 @@ class HistoricalSimulationInputFactoryTest { assertEquals(originalInput.getTrafficMap().getEdges(), changedInput.getTrafficMap().getEdges()); } + /** + * 验证“copy with records”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code HistoricalSimulationInputFactoryTest},用于保持当前模块的职责边界清晰。 + * @param original 执行该处理所需的 original 输入。 + * @param records 执行该处理所需的 records 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private HistoricalQueueDataset copyWithRecords(HistoricalQueueDataset original, List records) { return new HistoricalQueueDataset(records, original.getMapSiteDetails(), diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/PhysicalEndpointResolverTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/PhysicalEndpointResolverTest.java index f2e8241..5b2a5b2 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/PhysicalEndpointResolverTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/PhysicalEndpointResolverTest.java @@ -14,6 +14,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; class PhysicalEndpointResolverTest { + /** + * 验证“uses physical source floor when the historical floor is stale”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code PhysicalEndpointResolverTest},用于保持当前模块的职责边界清晰。 + */ @Test void usesPhysicalSourceFloorWhenTheHistoricalFloorIsStale() { HistoricalQueueDataset dataset = new HistoricalQueueLoader().load( @@ -33,6 +38,12 @@ class PhysicalEndpointResolverTest { assertFalse(endpoints.isDeclaredFloorConsistent()); } + /** + * 验证“resolves tsj by the production floor rule”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code PhysicalEndpointResolverTest},用于保持当前模块的职责边界清晰。 + * @param floor 执行该处理所需的 floor 输入。 + */ @ParameterizedTest @ValueSource(ints = {1, 2, 3}) void resolvesTsjByTheProductionFloorRule(int floor) { diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationAdaptersTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationAdaptersTest.java index 09b14e4..4a3dc3f 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationAdaptersTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationAdaptersTest.java @@ -10,6 +10,11 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; class SimulationAdaptersTest { + /** + * 验证“retries deterministic send failure and rejects ack from an old boot”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code SimulationAdaptersTest},用于保持当前模块的职责边界清晰。 + */ @Test void retriesDeterministicSendFailureAndRejectsAckFromAnOldBoot() { DeterministicFaultPlan faults = DeterministicFaultPlan.builder() @@ -28,6 +33,11 @@ class SimulationAdaptersTest { assertTrue(vehicle.isAssignmentEligible()); } + /** + * 验证“excludes disconnected low battery and faulted vehicles until recovery”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code SimulationAdaptersTest},用于保持当前模块的职责边界清晰。 + */ @Test void excludesDisconnectedLowBatteryAndFaultedVehiclesUntilRecovery() { SimulatedVehicleRuntime vehicle = new SimulatedVehicleRuntime("1", "A", 1); @@ -44,6 +54,11 @@ class SimulationAdaptersTest { assertTrue(vehicle.isAssignmentEligible()); } + /** + * 验证“archives and applies wms completion exactly once across duplicate delivery”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code SimulationAdaptersTest},用于保持当前模块的职责边界清晰。 + */ @Test void archivesAndAppliesWmsCompletionExactlyOnceAcrossDuplicateDelivery() { SimulationArchive archive = new SimulationArchive(); diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationClockTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationClockTest.java index c4b1cfd..ec1a0fc 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationClockTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationClockTest.java @@ -9,6 +9,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; class SimulationClockTest { + /** + * 验证“scales every historical arrival gap without truncation”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code SimulationClockTest},用于保持当前模块的职责边界清晰。 + */ @Test void scalesEveryHistoricalArrivalGapWithoutTruncation() { LocalDateTime base = LocalDateTime.of(2026, 3, 1, 10, 0); @@ -25,6 +30,11 @@ class SimulationClockTest { assertEquals(1_000L, clock.sourceDurationMillis(10L)); } + /** + * 验证“accepts only supported acceleration factors”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code SimulationClockTest},用于保持当前模块的职责边界清晰。 + */ @Test void acceptsOnlySupportedAccelerationFactors() { LocalDateTime base = LocalDateTime.of(2026, 3, 1, 10, 0); @@ -32,6 +42,11 @@ class SimulationClockTest { () -> new SimulationClock(Arrays.asList(base), 25)); } + /** + * 验证“scales from the first arrival without accumulating rounding loss”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code SimulationClockTest},用于保持当前模块的职责边界清晰。 + */ @Test void scalesFromTheFirstArrivalWithoutAccumulatingRoundingLoss() { LocalDateTime base = LocalDateTime.of(2026, 3, 1, 10, 0); diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationInvariantSummaryTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationInvariantSummaryTest.java index d08b51a..452155c 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationInvariantSummaryTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationInvariantSummaryTest.java @@ -5,6 +5,11 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; class SimulationInvariantSummaryTest { + /** + * 验证“counts duplicate archive attempts as safety violations”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code SimulationInvariantSummaryTest},用于保持当前模块的职责边界清晰。 + */ @Test void countsDuplicateArchiveAttemptsAsSafetyViolations() { SimulationInvariantSummary summary = new SimulationInvariantSummary(); diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationMetricsTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationMetricsTest.java index c59ba89..cf31abf 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationMetricsTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationMetricsTest.java @@ -9,6 +9,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; class SimulationMetricsTest { + /** + * 验证“calculates average and nearest rank percentiles from literal samples”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code SimulationMetricsTest},用于保持当前模块的职责边界清晰。 + */ @Test void calculatesAverageAndNearestRankPercentilesFromLiteralSamples() { SimulationMetrics metrics = new SimulationMetrics(); @@ -19,6 +24,11 @@ class SimulationMetricsTest { assertEquals(3L, metrics.percentile(Arrays.asList(1L, 3L, 5L), 0.50)); } + /** + * 验证“returns null for empty samples instead of inventing zero”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code SimulationMetricsTest},用于保持当前模块的职责边界清晰。 + */ @Test void returnsNullForEmptySamplesInsteadOfInventingZero() { SimulationMetrics metrics = new SimulationMetrics(); diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationProgressWatchdogTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationProgressWatchdogTest.java index fe4a7c0..3d71984 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationProgressWatchdogTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationProgressWatchdogTest.java @@ -6,6 +6,11 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; class SimulationProgressWatchdogTest { + /** + * 验证“detects livelock when terminal count does not change despite other activity”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code SimulationProgressWatchdogTest},用于保持当前模块的职责边界清晰。 + */ @Test void detectsLivelockWhenTerminalCountDoesNotChangeDespiteOtherActivity() { SimulationProgressWatchdog watchdog = new SimulationProgressWatchdog(3, 0); @@ -15,6 +20,11 @@ class SimulationProgressWatchdogTest { assertTrue(watchdog.observe(0)); } + /** + * 验证“resets when another task reaches aterminal state”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code SimulationProgressWatchdogTest},用于保持当前模块的职责边界清晰。 + */ @Test void resetsWhenAnotherTaskReachesATerminalState() { SimulationProgressWatchdog watchdog = new SimulationProgressWatchdog(2, 0); @@ -25,6 +35,11 @@ class SimulationProgressWatchdogTest { assertTrue(watchdog.observe(1)); } + /** + * 验证“resets only for terminal movement or completed clearance progress”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code SimulationProgressWatchdogTest},用于保持当前模块的职责边界清晰。 + */ @Test void resetsOnlyForTerminalMovementOrCompletedClearanceProgress() { SimulationProgressWatchdog watchdog = new SimulationProgressWatchdog(3, 0); diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationTaskQueueTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationTaskQueueTest.java index c8d6f87..c47df75 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationTaskQueueTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationTaskQueueTest.java @@ -10,6 +10,11 @@ import java.util.Arrays; import static org.junit.jupiter.api.Assertions.assertEquals; class SimulationTaskQueueTest { + /** + * 验证“orders by priority then arrival and protects old tasks from starvation”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code SimulationTaskQueueTest},用于保持当前模块的职责边界清晰。 + */ @Test void ordersByPriorityThenArrivalAndProtectsOldTasksFromStarvation() { HistoricalSimulationTask low = task("LOW", 3, 0); @@ -22,6 +27,11 @@ class SimulationTaskQueueTest { assertEquals(Arrays.asList(low, high), queue.readyAt(90_000L)); } + /** + * 验证“requeue keeps the original arrival and accumulated age”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code SimulationTaskQueueTest},用于保持当前模块的职责边界清晰。 + */ @Test void requeueKeepsTheOriginalArrivalAndAccumulatedAge() { HistoricalSimulationTask old = task("OLD", 4, 0); @@ -35,6 +45,15 @@ class SimulationTaskQueueTest { assertEquals(old, queue.readyAt(60_000L).get(0)); } + /** + * 验证“task”场景,确保相关业务规则和断言成立。 + * + *

该方法属于 {@code SimulationTaskQueueTest},用于保持当前模块的职责边界清晰。 + * @param id 执行该处理所需的 id 输入。 + * @param priority 执行该处理所需的 priority 输入。 + * @param sequence 执行该处理所需的 sequence 输入。 + * @return 本次处理产生的结果;调用方据此继续后续流程。 + */ private HistoricalSimulationTask task(String id, int priority, int sequence) { LocalDateTime created = LocalDateTime.of(2026, 3, 1, 10, 0).plusSeconds(sequence); HistoricalQueueRecord record = new HistoricalQueueRecord(