feat(wcs): add deterministic route planning
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
package com.ruoyi.wcs.domain.traffic;
|
||||
|
||||
import com.ruoyi.wcs.domain.shared.DomainRuleViolation;
|
||||
import com.ruoyi.wcs.domain.topology.EffectiveTopology;
|
||||
import com.ruoyi.wcs.domain.topology.ResourceDefinition;
|
||||
import com.ruoyi.wcs.domain.topology.TopologyCompiler;
|
||||
import com.ruoyi.wcs.domain.topology.TopologyDefinition;
|
||||
import com.ruoyi.wcs.domain.topology.TopologyEdge;
|
||||
import com.ruoyi.wcs.domain.topology.TopologyNode;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
class AStarRoutePlannerTest {
|
||||
private final RoutePlanner planner = new AStarRoutePlanner();
|
||||
|
||||
@Test
|
||||
void avoidsBlockedEdgeAndUsesStableNodeIdTieBreak() {
|
||||
RoutePlan route = planner.plan(grid(), "A", "D",
|
||||
Collections.singleton("EDGE:B:D"));
|
||||
|
||||
assertEquals(Arrays.asList("A", "C", "D"), route.getNodeIds());
|
||||
assertEquals(Arrays.asList("NODE:A", "EDGE:A:C", "NODE:C",
|
||||
"EDGE:C:D", "NODE:D"), route.getResourceKeys());
|
||||
assertEquals(2, route.getDistanceCost());
|
||||
assertEquals(1, route.getTurnCount());
|
||||
assertEquals(7L, route.getTopologyVersion());
|
||||
}
|
||||
|
||||
@Test
|
||||
void breaksEqualRouteCostsByNodeId() {
|
||||
RoutePlan route = planner.plan(grid(), "A", "D",
|
||||
Collections.<String>emptySet());
|
||||
|
||||
assertEquals(Arrays.asList("A", "B", "D"), route.getNodeIds());
|
||||
}
|
||||
|
||||
@Test
|
||||
void avoidsBlockedNodeAndNeverTreatsBlockedStartAsAnObstacle() {
|
||||
RoutePlan route = planner.plan(grid(), "A", "D",
|
||||
new HashSet<String>(Arrays.asList("NODE:A", "NODE:B")));
|
||||
|
||||
assertEquals(Arrays.asList("A", "C", "D"), route.getNodeIds());
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsUnknownDestination() {
|
||||
assertThrows(DomainRuleViolation.class, () -> planner.plan(
|
||||
grid(), "A", "UNKNOWN", Collections.<String>emptySet()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsUnreachableDestination() {
|
||||
assertThrows(DomainRuleViolation.class, () -> planner.plan(grid(), "A", "D",
|
||||
new HashSet<String>(Arrays.asList("NODE:B", "NODE:C"))));
|
||||
}
|
||||
|
||||
private static EffectiveTopology grid() {
|
||||
TopologyDefinition definition = new TopologyDefinition("FT546", 7L, true,
|
||||
Arrays.asList(
|
||||
node("A", 0, 0), node("B", 1, 0),
|
||||
node("C", 0, 1), node("D", 1, 1)),
|
||||
Arrays.asList(
|
||||
edge("A", "B"), edge("B", "D"),
|
||||
edge("A", "C"), edge("C", "D")),
|
||||
Collections.<ResourceDefinition>emptyList(),
|
||||
Collections.<String>emptyList(), Collections.<String>emptyList());
|
||||
return new TopologyCompiler().compile(definition);
|
||||
}
|
||||
|
||||
private static TopologyNode node(String id, int x, int y) {
|
||||
return new TopologyNode(id, "F1", x, y, 1, false, false);
|
||||
}
|
||||
|
||||
private static TopologyEdge edge(String source, String target) {
|
||||
return new TopologyEdge(source, target, 1, 1);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user