feat(javaTest): expose full-map route evidence
This commit is contained in:
@@ -2,6 +2,7 @@ package com.ft546.wcs.shadow.history.visualizer;
|
|||||||
|
|
||||||
import com.ft546.wcs.demo.model.Site;
|
import com.ft546.wcs.demo.model.Site;
|
||||||
import com.ft546.wcs.demo.model.VehicleSnapshot;
|
import com.ft546.wcs.demo.model.VehicleSnapshot;
|
||||||
|
import com.ft546.wcs.demo.traffic.GridMap;
|
||||||
import com.ft546.wcs.shadow.history.HistoricalQueueDataset;
|
import com.ft546.wcs.shadow.history.HistoricalQueueDataset;
|
||||||
import com.ft546.wcs.shadow.history.HistoricalQueueRecord;
|
import com.ft546.wcs.shadow.history.HistoricalQueueRecord;
|
||||||
import com.ft546.wcs.shadow.history.simulation.HistoricalDispatchSimulationResult;
|
import com.ft546.wcs.shadow.history.simulation.HistoricalDispatchSimulationResult;
|
||||||
@@ -41,6 +42,8 @@ public final class SimulationVisualizationMapper {
|
|||||||
DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
|
DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
private final HistoricalQueueDataset dataset;
|
private final HistoricalQueueDataset dataset;
|
||||||
|
private final RouteTopologyEvidenceMapper routeTopology =
|
||||||
|
new RouteTopologyEvidenceMapper();
|
||||||
|
|
||||||
public SimulationVisualizationMapper(HistoricalQueueDataset dataset) {
|
public SimulationVisualizationMapper(HistoricalQueueDataset dataset) {
|
||||||
if (dataset == null) throw new IllegalArgumentException("dataset is required");
|
if (dataset == null) throw new IllegalArgumentException("dataset is required");
|
||||||
@@ -71,6 +74,8 @@ public final class SimulationVisualizationMapper {
|
|||||||
}
|
}
|
||||||
payload.put("floors", new ArrayList<Integer>(floors));
|
payload.put("floors", new ArrayList<Integer>(floors));
|
||||||
payload.put("sites", sites);
|
payload.put("sites", sites);
|
||||||
|
// 页面底图必须使用当前 Java 地图的真实邻接边,不能在浏览器中按坐标猜路。
|
||||||
|
payload.put("edges", routeTopology.fullMapEdges(input.getGridMap()));
|
||||||
|
|
||||||
List<VehicleSnapshot> orderedVehicles =
|
List<VehicleSnapshot> orderedVehicles =
|
||||||
new ArrayList<VehicleSnapshot>(input.getInitialVehicles());
|
new ArrayList<VehicleSnapshot>(input.getInitialVehicles());
|
||||||
@@ -96,7 +101,7 @@ public final class SimulationVisualizationMapper {
|
|||||||
List<Map<String, Object>> tasks = new ArrayList<Map<String, Object>>();
|
List<Map<String, Object>> tasks = new ArrayList<Map<String, Object>>();
|
||||||
for (SimulationTaskResult task : orderedTasks) {
|
for (SimulationTaskResult task : orderedTasks) {
|
||||||
tasks.add(task(task, definitions.get(task.getSimulationTaskId()),
|
tasks.add(task(task, definitions.get(task.getSimulationTaskId()),
|
||||||
result.getAcceleration()));
|
result.getAcceleration(), input.getGridMap()));
|
||||||
}
|
}
|
||||||
List<Map<String, Object>> events = new ArrayList<Map<String, Object>>();
|
List<Map<String, Object>> events = new ArrayList<Map<String, Object>>();
|
||||||
for (SimulationTickEvent event : result.getEvents()) events.add(event(event));
|
for (SimulationTickEvent event : result.getEvents()) events.add(event(event));
|
||||||
@@ -145,7 +150,8 @@ public final class SimulationVisualizationMapper {
|
|||||||
|
|
||||||
private Map<String, Object> task(SimulationTaskResult task,
|
private Map<String, Object> task(SimulationTaskResult task,
|
||||||
HistoricalSimulationTask definition,
|
HistoricalSimulationTask definition,
|
||||||
int acceleration) {
|
int acceleration,
|
||||||
|
GridMap gridMap) {
|
||||||
HistoricalQueueRecord record = task.getRecord();
|
HistoricalQueueRecord record = task.getRecord();
|
||||||
List<String> historicalPath = historicalPath(record.getPathInfo());
|
List<String> historicalPath = historicalPath(record.getPathInfo());
|
||||||
Long historicalDuration = historicalDuration(task);
|
Long historicalDuration = historicalDuration(task);
|
||||||
@@ -170,6 +176,9 @@ public final class SimulationVisualizationMapper {
|
|||||||
value.put("simulatedVehicleId", task.getSimulatedVehicleId());
|
value.put("simulatedVehicleId", task.getSimulatedVehicleId());
|
||||||
value.put("historicalPath", historicalPath);
|
value.put("historicalPath", historicalPath);
|
||||||
value.put("plannedPath", task.getPlannedPath());
|
value.put("plannedPath", task.getPlannedPath());
|
||||||
|
// 边差证据解释新旧路线在哪里重合或分叉,但不参与调度中心的规划结果。
|
||||||
|
value.put("pathComparison", routeTopology.compare(
|
||||||
|
gridMap, historicalPath, task.getPlannedPath()));
|
||||||
value.put("assignedVehicles", task.getAssignedVehicles());
|
value.put("assignedVehicles", task.getAssignedVehicles());
|
||||||
value.put("status", task.getStatus().name());
|
value.put("status", task.getStatus().name());
|
||||||
value.put("reason", task.getReason());
|
value.put("reason", task.getReason());
|
||||||
|
|||||||
@@ -71,9 +71,13 @@ class HistoricalDispatchVisualizerServerTest {
|
|||||||
assertEquals(Boolean.FALSE, map(health.body).get("simulationBusy"));
|
assertEquals(Boolean.FALSE, map(health.body).get("simulationBusy"));
|
||||||
assertEquals(200, bootstrap.status);
|
assertEquals(200, bootstrap.status);
|
||||||
assertEquals("OFFLINE_IN_MEMORY_SIMULATION", map(bootstrap.body).get("mode"));
|
assertEquals("OFFLINE_IN_MEMORY_SIMULATION", map(bootstrap.body).get("mode"));
|
||||||
|
assertFalse(list(map(bootstrap.body).get("edges")).isEmpty());
|
||||||
assertEquals(200, simulation.status);
|
assertEquals(200, simulation.status);
|
||||||
assertEquals(1, map(map(simulation.body).get("summary")).get("completedCount"));
|
assertEquals(1, map(map(simulation.body).get("summary")).get("completedCount"));
|
||||||
assertFalse(list(map(simulation.body).get("events")).isEmpty());
|
assertFalse(list(map(simulation.body).get("events")).isEmpty());
|
||||||
|
Map<String, Object> taskEvidence = map(
|
||||||
|
list(map(simulation.body).get("tasks")).get(0));
|
||||||
|
assertTrue(taskEvidence.containsKey("pathComparison"));
|
||||||
assertTrue(simulation.body.contains("plannedPath"));
|
assertTrue(simulation.body.contains("plannedPath"));
|
||||||
assertTrue(simulation.body.contains("MOVE"));
|
assertTrue(simulation.body.contains("MOVE"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,10 @@ import org.junit.jupiter.api.Test;
|
|||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
@@ -45,6 +47,7 @@ class SimulationVisualizationMapperTest {
|
|||||||
void bootstrapReturnsSortedSearchableSitesAndInitialVehicles() {
|
void bootstrapReturnsSortedSearchableSitesAndInitialVehicles() {
|
||||||
Map<String, Object> payload = mapper().bootstrap(input);
|
Map<String, Object> payload = mapper().bootstrap(input);
|
||||||
List<Map<String, Object>> sites = listOfMaps(payload.get("sites"));
|
List<Map<String, Object>> sites = listOfMaps(payload.get("sites"));
|
||||||
|
List<Map<String, Object>> edges = listOfMaps(payload.get("edges"));
|
||||||
List<Map<String, Object>> vehicles = listOfMaps(payload.get("vehicles"));
|
List<Map<String, Object>> vehicles = listOfMaps(payload.get("vehicles"));
|
||||||
|
|
||||||
assertEquals("OFFLINE_IN_MEMORY_SIMULATION", payload.get("mode"));
|
assertEquals("OFFLINE_IN_MEMORY_SIMULATION", payload.get("mode"));
|
||||||
@@ -56,6 +59,21 @@ class SimulationVisualizationMapperTest {
|
|||||||
assertTrue(sites.get(0).containsKey("x"));
|
assertTrue(sites.get(0).containsKey("x"));
|
||||||
assertTrue(sites.get(0).containsKey("y"));
|
assertTrue(sites.get(0).containsKey("y"));
|
||||||
assertTrue(sites.get(0).containsKey("floor"));
|
assertTrue(sites.get(0).containsKey("floor"));
|
||||||
|
|
||||||
|
int neighborReferences = input.getGridMap().getSites().keySet().stream()
|
||||||
|
.mapToInt(siteId -> input.getGridMap().getNeighbors(siteId).size())
|
||||||
|
.sum();
|
||||||
|
assertEquals(neighborReferences / 2, edges.size());
|
||||||
|
Set<String> edgeKeys = new HashSet<String>();
|
||||||
|
for (Map<String, Object> edge : edges) {
|
||||||
|
String from = String.valueOf(edge.get("fromSite"));
|
||||||
|
String to = String.valueOf(edge.get("toSite"));
|
||||||
|
assertTrue(input.getGridMap().getSites().containsKey(from));
|
||||||
|
assertTrue(input.getGridMap().getSites().containsKey(to));
|
||||||
|
assertTrue(from.compareTo(to) < 0);
|
||||||
|
assertTrue(input.getGridMap().getNeighbors(from).contains(to));
|
||||||
|
assertTrue(edgeKeys.add(from + "|" + to));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -74,6 +92,15 @@ class SimulationVisualizationMapperTest {
|
|||||||
assertEquals(sampleTask.getPhysicalTarget(), tasks.get(0).get("physicalEndSite"));
|
assertEquals(sampleTask.getPhysicalTarget(), tasks.get(0).get("physicalEndSite"));
|
||||||
assertEquals(Boolean.TRUE, tasks.get(0).get("vehicleChanged"));
|
assertEquals(Boolean.TRUE, tasks.get(0).get("vehicleChanged"));
|
||||||
assertEquals(Boolean.TRUE, tasks.get(0).get("pathChanged"));
|
assertEquals(Boolean.TRUE, tasks.get(0).get("pathChanged"));
|
||||||
|
Map<String, Object> comparison = map(tasks.get(0).get("pathComparison"));
|
||||||
|
assertEquals(0, comparison.get("sharedEdgeCount"));
|
||||||
|
assertEquals(sourceTask.getPlannedPath().size() - 1,
|
||||||
|
comparison.get("plannedOnlyEdgeCount"));
|
||||||
|
assertEquals(0, comparison.get("historicalOnlyEdgeCount"));
|
||||||
|
List<Map<String, Object>> invalidHistorical =
|
||||||
|
listOfMaps(comparison.get("invalidHistoricalSegments"));
|
||||||
|
assertEquals(1, invalidHistorical.size());
|
||||||
|
assertEquals("UNKNOWN_SITE", invalidHistorical.get(0).get("reason"));
|
||||||
assertTrue(events.stream().anyMatch(event -> "ASSIGN".equals(event.get("eventType"))));
|
assertTrue(events.stream().anyMatch(event -> "ASSIGN".equals(event.get("eventType"))));
|
||||||
assertTrue(events.stream().anyMatch(event -> "MOVE".equals(event.get("eventType"))));
|
assertTrue(events.stream().anyMatch(event -> "MOVE".equals(event.get("eventType"))));
|
||||||
assertTrue(events.stream().anyMatch(event -> "PLC_RETRY".equals(event.get("eventType"))));
|
assertTrue(events.stream().anyMatch(event -> "PLC_RETRY".equals(event.get("eventType"))));
|
||||||
|
|||||||
Reference in New Issue
Block a user