11
11
import java .util .*;
12
12
13
13
/**
14
- * @author Slimane Amar <slimane.amar at rte-france.com>
14
+ * @author Ghazwa Rehili <ghazwa.rehili at rte-france.com>
15
15
*/
16
16
// TODO : to remove when this class is available in network-store
17
17
public final class BusbarSectionFinderTraverser {
18
18
19
- /**
20
- * Private constructor to prevent instantiation of this utility class.
21
- */
22
19
private BusbarSectionFinderTraverser () {
23
20
throw new UnsupportedOperationException ();
24
21
}
25
22
26
- /**
27
- * Finds the best busbar section connected to the given terminal.
28
- * Uses a breadth-first search algorithm to explore all possible paths.
29
- *
30
- * @param terminal the starting terminal
31
- * @return the best busbar result according to selection criteria, or null if none found
32
- */
33
- public static BusbarSectionResult findBestBusbar (Terminal terminal ) {
23
+ private record NodePath (int node , List <SwitchInfo > pathSwitches , SwitchInfo lastSwitch ) { }
24
+
25
+ public record SwitchInfo (String id , SwitchKind kind , boolean isOpen ) { }
26
+
27
+ public record BusbarSectionResult (String busbarSectionId , int depth , SwitchInfo lastSwitch ) { }
28
+
29
+ public static String findBusbarSectionId (Terminal terminal ) {
30
+ BusbarSectionResult result = getBusbarSectionResult (terminal );
31
+ return result != null ? result .busbarSectionId () : null ;
32
+ }
33
+
34
+ public static BusbarSectionResult getBusbarSectionResult (Terminal terminal ) {
34
35
VoltageLevel .NodeBreakerView view = terminal .getVoltageLevel ().getNodeBreakerView ();
35
36
int startNode = terminal .getNodeBreakerView ().getNode ();
36
37
List <BusbarSectionResult > allResults = searchAllBusbars (view , startNode );
@@ -40,46 +41,22 @@ public static BusbarSectionResult findBestBusbar(Terminal terminal) {
40
41
return selectBestBusbar (allResults );
41
42
}
42
43
43
- /**
44
- * Selects the best busbar from a list of candidates using a priority-based approach:
45
- * Priority 1: Busbar with closed last switch (minimum depth, then minimum switches before last)
46
- * Priority 2: Busbar with open last switch (minimum depth, then minimum switches before last)
47
- * Priority 3: Busbar without switch (direct connection, minimum depth)
48
- *
49
- * @param results list of all found busbar results
50
- * @return the best busbar according to selection criteria
51
- */
52
44
private static BusbarSectionResult selectBestBusbar (List <BusbarSectionResult > results ) {
53
- // Priority 1: Search for busbar with closed last switch
45
+ List <BusbarSectionResult > withoutSwitch = results .stream ().filter (r -> r .lastSwitch () == null ).toList ();
46
+ if (!withoutSwitch .isEmpty ()) {
47
+ return withoutSwitch .stream ().min (Comparator .comparingInt (BusbarSectionResult ::depth )).orElse (null );
48
+ }
54
49
List <BusbarSectionResult > withClosedSwitch = results .stream ().filter (r -> r .lastSwitch () != null && !r .lastSwitch ().isOpen ()).toList ();
55
50
if (!withClosedSwitch .isEmpty ()) {
56
- return withClosedSwitch .stream ().min (Comparator .comparingInt (BusbarSectionResult ::depth ). thenComparingInt ( BusbarSectionResult :: switchesBeforeLast ) ).orElse (null );
51
+ return withClosedSwitch .stream ().min (Comparator .comparingInt (BusbarSectionResult ::depth )).orElse (null );
57
52
}
58
-
59
- // Priority 2: Search for busbar with open last switch
60
53
List <BusbarSectionResult > withOpenSwitch = results .stream ().filter (r -> r .lastSwitch () != null && r .lastSwitch ().isOpen ()).toList ();
61
54
if (!withOpenSwitch .isEmpty ()) {
62
- return withOpenSwitch .stream ().min (Comparator .comparingInt (BusbarSectionResult ::depth ). thenComparingInt ( BusbarSectionResult :: switchesBeforeLast ) ).orElse (null );
55
+ return withOpenSwitch .stream ().min (Comparator .comparingInt (BusbarSectionResult ::depth )).orElse (null );
63
56
}
64
-
65
- // Priority 3: Busbars without switch direct connection
66
- List <BusbarSectionResult > withoutSwitch = results .stream ().filter (r -> r .lastSwitch () == null ).toList ();
67
- if (!withoutSwitch .isEmpty ()) {
68
- return withoutSwitch .stream ().min (Comparator .comparingInt (BusbarSectionResult ::depth )).orElse (null );
69
- }
70
-
71
- // Fallback: select first busbar
72
57
return results .getFirst ();
73
58
}
74
59
75
- /**
76
- * Searches all accessible busbars from a starting node using breadth-first search.
77
- * Explores the node-breaker topology through switches.
78
- *
79
- * @param view the node-breaker view of the voltage level
80
- * @param startNode the starting node index
81
- * @return list of all busbar results found
82
- */
83
60
private static List <BusbarSectionResult > searchAllBusbars (VoltageLevel .NodeBreakerView view , int startNode ) {
84
61
List <BusbarSectionResult > results = new ArrayList <>();
85
62
Set <Integer > visited = new HashSet <>();
@@ -111,13 +88,11 @@ private static Optional<BusbarSectionResult> tryCreateBusbarResult(VoltageLevel.
111
88
return Optional .empty ();
112
89
}
113
90
Terminal term = nodeTerminal .get ();
114
- // Check if current node is a busbar section
115
91
if (term .getConnectable ().getType () == IdentifiableType .BUSBAR_SECTION ) {
116
92
String busbarSectionId = term .getConnectable ().getId ();
117
93
int depth = currentNodePath .pathSwitches ().size ();
118
94
SwitchInfo lastSwitch = currentNodePath .lastSwitch ();
119
- int switchesBeforeLast = lastSwitch != null ? (depth - 1 ) : 0 ;
120
- return Optional .of (new BusbarSectionResult (busbarSectionId , depth , switchesBeforeLast , lastSwitch ));
95
+ return Optional .of (new BusbarSectionResult (busbarSectionId , depth , lastSwitch ));
121
96
}
122
97
return Optional .empty ();
123
98
}
@@ -128,7 +103,7 @@ private static void exploreAdjacentNodes(VoltageLevel.NodeBreakerView view, Node
128
103
int node2 = view .getNode2 (sw .getId ());
129
104
Optional <Integer > nextNode = getNextNodeIfAdjacent (currentNodePath .node (), node1 , node2 );
130
105
if (nextNode .isPresent () && !visited .contains (nextNode .get ())) {
131
- NodePath newPath = createNodePath (currentNodePath , sw , node1 , node2 , nextNode .get ());
106
+ NodePath newPath = createNodePath (currentNodePath , sw , nextNode .get ());
132
107
queue .offer (newPath );
133
108
}
134
109
});
@@ -144,36 +119,10 @@ private static Optional<Integer> getNextNodeIfAdjacent(int currentNode, int node
144
119
return Optional .empty ();
145
120
}
146
121
147
- private static NodePath createNodePath (NodePath currentNodePath , Switch sw , int node1 , int node2 , int nextNode ) {
122
+ private static NodePath createNodePath (NodePath currentNodePath , Switch sw , int nextNode ) {
148
123
List <SwitchInfo > newPathSwitches = new ArrayList <>(currentNodePath .pathSwitches ());
149
- SwitchInfo switchInfo = new SwitchInfo (sw .getId (), sw .getKind (), sw .isOpen (), node1 , node2 );
124
+ SwitchInfo switchInfo = new SwitchInfo (sw .getId (), sw .getKind (), sw .isOpen ());
150
125
newPathSwitches .add (switchInfo );
151
126
return new NodePath (nextNode , newPathSwitches , switchInfo );
152
127
}
153
-
154
- /**
155
- * Internal record to track the path during graph traversal.
156
- */
157
- private record NodePath (int node , List <SwitchInfo > pathSwitches , SwitchInfo lastSwitch ) { }
158
-
159
- /**
160
- * Record containing information about a switch in the topology.
161
- */
162
- public record SwitchInfo (String id , SwitchKind kind , boolean isOpen , int node1 , int node2 ) { }
163
-
164
- /**
165
- * Record containing the result of a busbar search with selection metadata.
166
- */
167
- public record BusbarSectionResult (String busbarSectionId , int depth , int switchesBeforeLast , SwitchInfo lastSwitch ) { }
168
-
169
- /**
170
- * Convenience method to get only the busbar ID.
171
- *
172
- * @param terminal the starting terminal
173
- * @return the busbar ID or null if none found
174
- */
175
- public static String findBusbarSectionId (Terminal terminal ) {
176
- BusbarSectionResult result = findBestBusbar (terminal );
177
- return result != null ? result .busbarSectionId () : null ;
178
- }
179
128
}
0 commit comments