docs(javaTest): publish complete center dispatch evidence

This commit is contained in:
zgw
2026-07-31 15:03:15 +08:00
parent 35d8fb6ec4
commit 3a6e0102c7
11 changed files with 4845 additions and 12 deletions

View File

@@ -49,6 +49,12 @@ public final class HistoricalDispatchSimulationReportWriter {
value.put("database", dataset.getDatabase());
value.put("sourceTable", dataset.getSourceTable());
value.put("sourceRowCount", dataset.getFullScanTotalRows());
value.put("fullMapRows", dataset.getFullMapRows());
value.put("passableMapRows", dataset.getFullMapCells().stream()
.filter(cell -> cell.getValue() == 1 || cell.getValue() == 2).count());
value.put("fullMapSha256", dataset.getFullMapSha256());
value.put("plannerVersion", "GridPathPlanner-BFS/full-grid-v1");
value.put("pathInfoUsedForPlanning", false);
value.put("inputCount", result.getTaskResults().size());
value.put("acceleration", result.getAcceleration());
value.put("completedCount", result.getCompletedCount());
@@ -69,9 +75,13 @@ public final class HistoricalDispatchSimulationReportWriter {
value.put("archiveCount", result.getArchiveCount());
value.put("wmsDeliveryAttempts", result.getWmsDeliveryAttempts());
value.put("wmsBusinessEffects", result.getWmsBusinessEffects());
value.put("wmsDuplicateDeliveryAttempts", Math.max(0,
result.getWmsDeliveryAttempts() - result.getCompletedCount()));
value.put("wmsDuplicateBusinessEffects",
result.getInvariants().getDuplicateWmsBusinessEffects());
value.put("archiveComplete", result.getArchiveCount() == result.getCompletedCount());
value.put("wmsIdempotent", result.getWmsBusinessEffects() == result.getCompletedCount()
&& result.getWmsDeliveryAttempts() == result.getCompletedCount() * 2);
&& result.getInvariants().getDuplicateWmsBusinessEffects() == 0);
value.put("invariants", invariantSummary(result));
return value;
}
@@ -163,7 +173,8 @@ public final class HistoricalDispatchSimulationReportWriter {
throws IOException {
StringBuilder csv = new StringBuilder("\ufeff");
row(csv, "simulation_task_id", "task_no", "guid", "task_type", "priority",
"original_start_site", "original_end_site", "historical_agv", "simulated_agv",
"business_start_site", "business_end_site", "physical_start_site",
"physical_end_site", "historical_agv", "simulated_agv",
"historical_path", "planned_path", "assigned_vehicles", "status", "reason",
"arrival_ms", "first_assigned_ms", "completed_ms", "waiting_ms",
"historical_duration_ms", "simulation_duration_ms", "scaled_source_duration_ms",
@@ -176,10 +187,15 @@ public final class HistoricalDispatchSimulationReportWriter {
Long difference = historical == null || scaled == null ? null : scaled - historical;
String historicalPath = trimTrailingCommas(text(task.getRecord().getPathInfo()));
String plannedPath = String.join(",", task.getPlannedPath());
String physicalStart = task.getPlannedPath().isEmpty()
? "" : task.getPlannedPath().get(0);
String physicalEnd = task.getPlannedPath().isEmpty()
? "" : task.getPlannedPath().get(task.getPlannedPath().size() - 1);
row(csv, task.getSimulationTaskId(), task.getRecord().getTaskNo(),
task.getRecord().getGuid(), task.getRecord().getTaskType(),
task.getRecord().getPriority(), task.getRecord().getStartSite(),
task.getRecord().getEndSite(), task.getRecord().getAgvId(),
task.getRecord().getEndSite(), physicalStart, physicalEnd,
task.getRecord().getAgvId(),
task.getSimulatedVehicleId(), historicalPath, plannedPath,
String.join("|", task.getAssignedVehicles()), task.getStatus(), task.getReason(),
task.getArrivalMillis(), task.getFirstAssignedMillis(), task.getCompletedMillis(),

View File

@@ -24,6 +24,7 @@ public final class SimulationInvariantSummary {
public int totalSafetyViolations() {
return capacityViolations + nodeDoubleOccupancyViolations
+ oppositeEdgeViolations + duplicateWmsBusinessEffects;
+ oppositeEdgeViolations + duplicateArchiveAttempts
+ duplicateWmsBusinessEffects;
}
}

View File

@@ -40,10 +40,21 @@ class HistoricalDispatchSimulationReportWriterTest {
JsonNode summary = new ObjectMapper().readTree(output.resolve("summary.json").toFile());
assertEquals("REAL_HISTORY_DRIVEN_DISPATCH_SIMULATION", summary.path("mode").asText());
assertEquals(240, summary.path("inputCount").asInt());
assertEquals(240, summary.path("completedCount").asInt()
+ summary.path("waitingCount").asInt() + summary.path("failedCount").asInt());
assertEquals(240, summary.path("completedCount").asInt());
assertEquals(0, summary.path("waitingCount").asInt());
assertEquals(0, summary.path("failedCount").asInt());
assertEquals(2552, summary.path("fullMapRows").asInt());
assertEquals(1175, summary.path("passableMapRows").asInt());
assertEquals(64, summary.path("fullMapSha256").asText().length());
assertEquals("GridPathPlanner-BFS/full-grid-v1",
summary.path("plannerVersion").asText());
assertTrue(summary.has("pathInfoUsedForPlanning"));
assertEquals(false, summary.path("pathInfoUsedForPlanning").asBoolean(true));
assertEquals(result.getArchiveCount(), summary.path("archiveCount").asInt());
assertEquals(result.getWmsBusinessEffects(), summary.path("wmsBusinessEffects").asInt());
assertEquals(240, summary.path("wmsDuplicateDeliveryAttempts").asInt());
assertEquals(0, summary.path("wmsDuplicateBusinessEffects").asInt());
assertTrue(summary.path("wmsIdempotent").asBoolean());
assertTrue(summary.has("waitingTime"));
assertTrue(summary.has("completionTime"));
assertTrue(summary.has("historicalDuration"));
@@ -54,6 +65,7 @@ class HistoricalDispatchSimulationReportWriterTest {
StandardCharsets.UTF_8);
assertTrue(taskCsv.startsWith("\ufeffsimulation_task_id,task_no,guid"));
assertTrue(taskCsv.contains("historical_agv,simulated_agv"));
assertTrue(taskCsv.contains("business_start_site,business_end_site,physical_start_site,physical_end_site"));
assertTrue(taskCsv.contains("historical_path,planned_path"));
assertTrue(taskCsv.contains("historical_duration_ms,simulation_duration_ms"));
assertTrue(taskCsv.contains("hold_reasons,retry_reasons"));

View File

@@ -0,0 +1,16 @@
package com.ft546.wcs.shadow.history.simulation;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class SimulationInvariantSummaryTest {
@Test
void countsDuplicateArchiveAttemptsAsSafetyViolations() {
SimulationInvariantSummary summary = new SimulationInvariantSummary();
summary.duplicateArchiveAttempt();
assertEquals(1, summary.totalSafetyViolations());
}
}