diff --git a/src/main/java/org/gridsuite/network/map/dto/definition/extension/BusbarSectionFinderTraverser.java b/src/main/java/org/gridsuite/network/map/dto/definition/extension/BusbarSectionFinderTraverser.java index 2faa6c7d..0391051a 100644 --- a/src/main/java/org/gridsuite/network/map/dto/definition/extension/BusbarSectionFinderTraverser.java +++ b/src/main/java/org/gridsuite/network/map/dto/definition/extension/BusbarSectionFinderTraverser.java @@ -8,40 +8,82 @@ import com.powsybl.iidm.network.IdentifiableType; import com.powsybl.iidm.network.Switch; +import com.powsybl.iidm.network.SwitchKind; import com.powsybl.iidm.network.Terminal; import com.powsybl.math.graph.TraverseResult; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; /** * @author Slimane Amar */ public class BusbarSectionFinderTraverser implements Terminal.TopologyTraverser { - private final boolean onlyConnectedBbs; - - private String firstTraversedBbsId; - - public BusbarSectionFinderTraverser(boolean onlyConnectedBbs) { - this.onlyConnectedBbs = onlyConnectedBbs; - } + private final List busbarCandidates = new ArrayList<>(); + private final Set visitedTerminals = new HashSet<>(); + private static final int MAX_VISITED = 50; @Override public TraverseResult traverse(Terminal terminal, boolean connected) { - if (terminal.getConnectable().getType() == IdentifiableType.BUSBAR_SECTION) { - firstTraversedBbsId = terminal.getConnectable().getId(); + String terminalId = terminal.getConnectable().getId(); + if (visitedTerminals.contains(terminalId)) { + return TraverseResult.TERMINATE_PATH; + } + visitedTerminals.add(terminalId); + if (visitedTerminals.size() > MAX_VISITED) { return TraverseResult.TERMINATE_TRAVERSER; } + + // If a busbar section is found, add it as a candidate + if (terminal.getConnectable().getType() == IdentifiableType.BUSBAR_SECTION) { + busbarCandidates.add(new BusbarCandidate(terminalId, connected)); + // CONTINUE to explore other paths to other busbars + return TraverseResult.CONTINUE; + } return TraverseResult.CONTINUE; } @Override public TraverseResult traverse(Switch aSwitch) { - if (onlyConnectedBbs && aSwitch.isOpen()) { - return TraverseResult.TERMINATE_PATH; + if (visitedTerminals.size() > MAX_VISITED) { + return TraverseResult.TERMINATE_TRAVERSER; + } + + // KEY: Open disconnectors end this path but not the overall traversal + // They block access to this busbar but not to the others + if (aSwitch.isOpen() && aSwitch.getKind() == SwitchKind.DISCONNECTOR) { + return TraverseResult.TERMINATE_PATH; // Ends this path, not the whole traversal } return TraverseResult.CONTINUE; } - public String getFirstTraversedBbsId() { - return firstTraversedBbsId; + public String getBusbarWithClosedDisconnector() { + // Search for a connected busbar (disconnector closed) + for (BusbarCandidate candidate : busbarCandidates) { + if (candidate.isConnected()) { + return candidate.getId(); + } + } + + // If none is connected, return the first one found (fallback) + if (!busbarCandidates.isEmpty()) { + return busbarCandidates.getFirst().getId(); + } + return null; + } + + @Getter + private static class BusbarCandidate { + private final String id; + private final boolean connected; + + public BusbarCandidate(String id, boolean connected) { + this.id = id; + this.connected = connected; + } } } diff --git a/src/main/java/org/gridsuite/network/map/dto/utils/ElementUtils.java b/src/main/java/org/gridsuite/network/map/dto/utils/ElementUtils.java index acb483b2..8e788687 100644 --- a/src/main/java/org/gridsuite/network/map/dto/utils/ElementUtils.java +++ b/src/main/java/org/gridsuite/network/map/dto/utils/ElementUtils.java @@ -47,9 +47,10 @@ public static String getBusOrBusbarSection(Terminal terminal) { return terminal.getBusBreakerView().getConnectableBus().getId(); } } else { - final BusbarSectionFinderTraverser connectedBusbarSectionFinder = new BusbarSectionFinderTraverser(terminal.isConnected()); - terminal.traverse(connectedBusbarSectionFinder, TraversalType.BREADTH_FIRST); - return connectedBusbarSectionFinder.getFirstTraversedBbsId(); + // NODE_BREAKER: explore all paths and choose the busbar with the closed disconnector + BusbarSectionFinderTraverser finder = new BusbarSectionFinderTraverser(); + terminal.traverse(finder, TraversalType.BREADTH_FIRST); + return finder.getBusbarWithClosedDisconnector(); } }