diff --git a/pom.xml b/pom.xml
index f87ea9ad..18d3852a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -258,4 +258,4 @@
test
-
+
\ No newline at end of file
diff --git a/src/main/java/org/gridsuite/securityanalysis/server/dto/LimitViolationDTO.java b/src/main/java/org/gridsuite/securityanalysis/server/dto/LimitViolationDTO.java
index 46919404..dd620113 100644
--- a/src/main/java/org/gridsuite/securityanalysis/server/dto/LimitViolationDTO.java
+++ b/src/main/java/org/gridsuite/securityanalysis/server/dto/LimitViolationDTO.java
@@ -26,6 +26,7 @@ public class LimitViolationDTO {
private double limitReduction;
private double value;
private Double loading;
+ private String locationId;
public static LimitViolationDTO toDto(AbstractLimitViolationEntity limitViolation) {
return LimitViolationDTO.builder()
@@ -37,11 +38,13 @@ public static LimitViolationDTO toDto(AbstractLimitViolationEntity limitViolatio
.limitReduction(limitViolation.getLimitReduction())
.value(limitViolation.getValue())
.loading(limitViolation.getLoading())
+ .locationId(limitViolation.getLocationId())
.build();
}
public List toCsvRow(Map translations) {
List csvRow = new ArrayList<>();
+ csvRow.add(this.getLocationId());
csvRow.add(this.getLimitType() != null ? CsvExportUtils.translate(this.getLimitType().name(), translations) : "");
csvRow.add(CsvExportUtils.replaceNullWithEmptyString(CsvExportUtils.translate(this.getLimitName(), translations)));
csvRow.add(Double.toString(this.getLimit()));
diff --git a/src/main/java/org/gridsuite/securityanalysis/server/dto/PreContingencyLimitViolationResultDTO.java b/src/main/java/org/gridsuite/securityanalysis/server/dto/PreContingencyLimitViolationResultDTO.java
index 6555757c..ae227b7b 100644
--- a/src/main/java/org/gridsuite/securityanalysis/server/dto/PreContingencyLimitViolationResultDTO.java
+++ b/src/main/java/org/gridsuite/securityanalysis/server/dto/PreContingencyLimitViolationResultDTO.java
@@ -11,6 +11,7 @@
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
+import lombok.experimental.FieldNameConstants;
import org.gridsuite.securityanalysis.server.entities.PreContingencyLimitViolationEntity;
import java.util.List;
@@ -21,6 +22,7 @@
@AllArgsConstructor
@NoArgsConstructor
@Builder
+@FieldNameConstants
public class PreContingencyLimitViolationResultDTO {
private String subjectId;
@@ -31,7 +33,6 @@ public static PreContingencyLimitViolationResultDTO toDto(PreContingencyLimitVio
String subjectId = preContingencyLimitViolation.getSubjectLimitViolation() != null
? preContingencyLimitViolation.getSubjectLimitViolation().getSubjectId()
: null;
-
return PreContingencyLimitViolationResultDTO.builder()
.subjectId(subjectId)
.status(preContingencyLimitViolation.getResult().getPreContingencyStatus())
@@ -40,7 +41,7 @@ public static PreContingencyLimitViolationResultDTO toDto(PreContingencyLimitVio
}
public List toCsvRow(Map translations) {
- List csvRow = List.of(this.getSubjectId());
+ List csvRow = List.of();
if (this.getLimitViolation() != null) {
return Stream.concat(csvRow.stream(), this.getLimitViolation().toCsvRow(translations).stream()).toList();
diff --git a/src/main/java/org/gridsuite/securityanalysis/server/dto/SubjectLimitViolationDTO.java b/src/main/java/org/gridsuite/securityanalysis/server/dto/SubjectLimitViolationDTO.java
index 67e6cad0..117df8e3 100644
--- a/src/main/java/org/gridsuite/securityanalysis/server/dto/SubjectLimitViolationDTO.java
+++ b/src/main/java/org/gridsuite/securityanalysis/server/dto/SubjectLimitViolationDTO.java
@@ -21,14 +21,12 @@
@Builder
public class SubjectLimitViolationDTO {
private String subjectId;
-
private LimitViolationDTO limitViolation;
public static SubjectLimitViolationDTO toDto(ContingencyLimitViolationEntity limitViolation) {
String subjectId = limitViolation.getSubjectLimitViolation() != null
? limitViolation.getSubjectLimitViolation().getSubjectId()
: null;
-
return SubjectLimitViolationDTO.builder()
.subjectId(subjectId)
.limitViolation(LimitViolationDTO.toDto(limitViolation))
diff --git a/src/main/java/org/gridsuite/securityanalysis/server/dto/SubjectLimitViolationResultDTO.java b/src/main/java/org/gridsuite/securityanalysis/server/dto/SubjectLimitViolationResultDTO.java
index a71338af..e2978043 100644
--- a/src/main/java/org/gridsuite/securityanalysis/server/dto/SubjectLimitViolationResultDTO.java
+++ b/src/main/java/org/gridsuite/securityanalysis/server/dto/SubjectLimitViolationResultDTO.java
@@ -27,7 +27,6 @@
@NoArgsConstructor
public class SubjectLimitViolationResultDTO {
private String subjectId;
-
private List contingencies;
public static SubjectLimitViolationResultDTO toDto(SubjectLimitViolationEntity subjectLimitViolation) {
diff --git a/src/main/java/org/gridsuite/securityanalysis/server/entities/AbstractLimitViolationEntity.java b/src/main/java/org/gridsuite/securityanalysis/server/entities/AbstractLimitViolationEntity.java
index 52b0625e..2bc0dc7c 100644
--- a/src/main/java/org/gridsuite/securityanalysis/server/entities/AbstractLimitViolationEntity.java
+++ b/src/main/java/org/gridsuite/securityanalysis/server/entities/AbstractLimitViolationEntity.java
@@ -58,6 +58,9 @@ public abstract class AbstractLimitViolationEntity {
@Column(name = "loading")
private Double loading;
+ @Column
+ private String locationId;
+
public static Double computeLoading(LimitViolation limitViolation) {
return LimitViolationType.CURRENT.equals(limitViolation.getLimitType())
? 100 * limitViolation.getValue() / limitViolation.getLimit()
diff --git a/src/main/java/org/gridsuite/securityanalysis/server/entities/ContingencyEntity.java b/src/main/java/org/gridsuite/securityanalysis/server/entities/ContingencyEntity.java
index 0f883dca..21e7a562 100644
--- a/src/main/java/org/gridsuite/securityanalysis/server/entities/ContingencyEntity.java
+++ b/src/main/java/org/gridsuite/securityanalysis/server/entities/ContingencyEntity.java
@@ -6,6 +6,7 @@
*/
package org.gridsuite.securityanalysis.server.entities;
+import com.powsybl.iidm.network.Network;
import com.powsybl.security.results.PostContingencyResult;
import jakarta.persistence.*;
import lombok.Getter;
@@ -41,7 +42,6 @@ public ContingencyEntity(String contingencyId, String status, List
}
}
- public static ContingencyEntity toEntity(PostContingencyResult postContingencyResult, Map subjectLimitViolationsBySubjectId) {
+ public static ContingencyEntity toEntity(Network network, PostContingencyResult postContingencyResult, Map subjectLimitViolationsBySubjectId) {
List contingencyElements = postContingencyResult.getContingency().getElements().stream().map(contingencyElement -> ContingencyElementEmbeddable.toEntity(contingencyElement)).collect(Collectors.toList());
List contingencyLimitViolations = postContingencyResult.getLimitViolationsResult().getLimitViolations().stream()
- .map(limitViolation -> ContingencyLimitViolationEntity.toEntity(limitViolation, subjectLimitViolationsBySubjectId.get(limitViolation.getSubjectId())))
+ .map(limitViolation -> ContingencyLimitViolationEntity.toEntity(network, limitViolation, subjectLimitViolationsBySubjectId.get(limitViolation.getSubjectId())))
.collect(Collectors.toList());
return new ContingencyEntity(postContingencyResult.getContingency().getId(), postContingencyResult.getStatus().name(), contingencyElements, contingencyLimitViolations);
}
diff --git a/src/main/java/org/gridsuite/securityanalysis/server/entities/ContingencyLimitViolationEntity.java b/src/main/java/org/gridsuite/securityanalysis/server/entities/ContingencyLimitViolationEntity.java
index 3db04004..00d9d73b 100644
--- a/src/main/java/org/gridsuite/securityanalysis/server/entities/ContingencyLimitViolationEntity.java
+++ b/src/main/java/org/gridsuite/securityanalysis/server/entities/ContingencyLimitViolationEntity.java
@@ -6,7 +6,9 @@
*/
package org.gridsuite.securityanalysis.server.entities;
+import com.powsybl.iidm.network.Network;
import com.powsybl.security.LimitViolation;
+import com.powsybl.ws.commons.computation.utils.ComputationResultUtils;
import jakarta.persistence.*;
import lombok.*;
import lombok.experimental.FieldNameConstants;
@@ -30,7 +32,7 @@ public class ContingencyLimitViolationEntity extends AbstractLimitViolationEntit
@Setter
private ContingencyEntity contingency;
- public static ContingencyLimitViolationEntity toEntity(LimitViolation limitViolation, SubjectLimitViolationEntity subjectLimitViolation) {
+ public static ContingencyLimitViolationEntity toEntity(Network network, LimitViolation limitViolation, SubjectLimitViolationEntity subjectLimitViolation) {
ContingencyLimitViolationEntity contingencyLimitViolationEntity = ContingencyLimitViolationEntity.builder()
.limit(limitViolation.getLimit())
.limitName(limitViolation.getLimitName())
@@ -40,6 +42,7 @@ public static ContingencyLimitViolationEntity toEntity(LimitViolation limitViola
.value(limitViolation.getValue())
.side(limitViolation.getSide())
.loading(computeLoading(limitViolation))
+ .locationId(ComputationResultUtils.getViolationLocationId(limitViolation, network))
.subjectLimitViolation(subjectLimitViolation)
.build();
diff --git a/src/main/java/org/gridsuite/securityanalysis/server/entities/PreContingencyLimitViolationEntity.java b/src/main/java/org/gridsuite/securityanalysis/server/entities/PreContingencyLimitViolationEntity.java
index 9a7ab5a1..b3c4daf6 100644
--- a/src/main/java/org/gridsuite/securityanalysis/server/entities/PreContingencyLimitViolationEntity.java
+++ b/src/main/java/org/gridsuite/securityanalysis/server/entities/PreContingencyLimitViolationEntity.java
@@ -6,12 +6,11 @@
*/
package org.gridsuite.securityanalysis.server.entities;
+import com.powsybl.iidm.network.Network;
import com.powsybl.security.LimitViolation;
import com.powsybl.security.results.PreContingencyResult;
-import jakarta.persistence.Entity;
-import jakarta.persistence.FetchType;
-import jakarta.persistence.ManyToOne;
-import jakarta.persistence.Table;
+import com.powsybl.ws.commons.computation.utils.ComputationResultUtils;
+import jakarta.persistence.*;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
@@ -35,16 +34,15 @@
@FieldNameConstants
@Table(name = "pre_contingency_limit_violation")
public class PreContingencyLimitViolationEntity extends AbstractLimitViolationEntity {
-
@ManyToOne(fetch = FetchType.LAZY)
@Setter
SecurityAnalysisResultEntity result;
- public static List toEntityList(PreContingencyResult preContingencyResult, Map subjectLimitViolationsBySubjectId) {
- return preContingencyResult.getLimitViolationsResult().getLimitViolations().stream().map(limitViolation -> toEntity(limitViolation, subjectLimitViolationsBySubjectId.get(limitViolation.getSubjectId()))).collect(Collectors.toList());
+ public static List toEntityList(Network network, PreContingencyResult preContingencyResult, Map subjectLimitViolationsBySubjectId) {
+ return preContingencyResult.getLimitViolationsResult().getLimitViolations().stream().map(limitViolation -> toEntity(network, limitViolation, subjectLimitViolationsBySubjectId.get(limitViolation.getSubjectId()))).collect(Collectors.toList());
}
- public static PreContingencyLimitViolationEntity toEntity(LimitViolation limitViolation, SubjectLimitViolationEntity subjectLimitViolation) {
+ public static PreContingencyLimitViolationEntity toEntity(Network network, LimitViolation limitViolation, SubjectLimitViolationEntity subjectLimitViolation) {
return PreContingencyLimitViolationEntity.builder()
.subjectLimitViolation(subjectLimitViolation)
.limit(limitViolation.getLimit())
@@ -55,6 +53,7 @@ public static PreContingencyLimitViolationEntity toEntity(LimitViolation limitVi
.value(limitViolation.getValue())
.side(limitViolation.getSide())
.loading(computeLoading(limitViolation))
+ .locationId(ComputationResultUtils.getViolationLocationId(limitViolation, network))
.build();
}
}
diff --git a/src/main/java/org/gridsuite/securityanalysis/server/entities/SecurityAnalysisResultEntity.java b/src/main/java/org/gridsuite/securityanalysis/server/entities/SecurityAnalysisResultEntity.java
index afd34e19..6d192143 100644
--- a/src/main/java/org/gridsuite/securityanalysis/server/entities/SecurityAnalysisResultEntity.java
+++ b/src/main/java/org/gridsuite/securityanalysis/server/entities/SecurityAnalysisResultEntity.java
@@ -6,6 +6,7 @@
*/
package org.gridsuite.securityanalysis.server.entities;
+import com.powsybl.iidm.network.Network;
import com.powsybl.security.SecurityAnalysisResult;
import jakarta.persistence.*;
import lombok.*;
@@ -52,7 +53,7 @@ public SecurityAnalysisResultEntity(UUID id) {
this.id = id;
}
- public static SecurityAnalysisResultEntity toEntity(UUID resultUuid, SecurityAnalysisResult securityAnalysisResult, SecurityAnalysisStatus securityAnalysisStatus) {
+ public static SecurityAnalysisResultEntity toEntity(Network network, UUID resultUuid, SecurityAnalysisResult securityAnalysisResult, SecurityAnalysisStatus securityAnalysisStatus) {
Map subjectLimitViolationsBySubjectId = getUniqueSubjectLimitViolationsFromResult(securityAnalysisResult)
.stream().collect(Collectors.toMap(
SubjectLimitViolationEntity::getSubjectId,
@@ -60,9 +61,9 @@ public static SecurityAnalysisResultEntity toEntity(UUID resultUuid, SecurityAna
);
List contingencies = securityAnalysisResult.getPostContingencyResults().stream()
- .map(postContingencyResult -> ContingencyEntity.toEntity(postContingencyResult, subjectLimitViolationsBySubjectId)).collect(Collectors.toList());
+ .map(postContingencyResult -> ContingencyEntity.toEntity(network, postContingencyResult, subjectLimitViolationsBySubjectId)).collect(Collectors.toList());
- List preContingencyLimitViolations = PreContingencyLimitViolationEntity.toEntityList(securityAnalysisResult.getPreContingencyResult(), subjectLimitViolationsBySubjectId);
+ List preContingencyLimitViolations = PreContingencyLimitViolationEntity.toEntityList(network, securityAnalysisResult.getPreContingencyResult(), subjectLimitViolationsBySubjectId);
List subjectLimitViolations = Stream.concat(
contingencies.stream().flatMap(c -> c.getContingencyLimitViolations().stream()),
diff --git a/src/main/java/org/gridsuite/securityanalysis/server/service/SecurityAnalysisResultService.java b/src/main/java/org/gridsuite/securityanalysis/server/service/SecurityAnalysisResultService.java
index 1e59f723..57a0049b 100644
--- a/src/main/java/org/gridsuite/securityanalysis/server/service/SecurityAnalysisResultService.java
+++ b/src/main/java/org/gridsuite/securityanalysis/server/service/SecurityAnalysisResultService.java
@@ -9,6 +9,7 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.ThreeSides;
import com.powsybl.security.LimitViolationType;
import com.powsybl.security.SecurityAnalysisResult;
@@ -56,6 +57,7 @@ public class SecurityAnalysisResultService extends AbstractComputationResultServ
private static final List ALLOWED_NMK_CONTINGENCIES_RESULT_SORT_PROPERTIES = List.of(
ContingencyEntity.Fields.contingencyId,
ContingencyEntity.Fields.status,
+ ContingencyEntity.Fields.contingencyLimitViolations + SpecificationUtils.FIELD_SEPARATOR + AbstractLimitViolationEntity.Fields.locationId,
ContingencyEntity.Fields.contingencyLimitViolations + SpecificationUtils.FIELD_SEPARATOR + AbstractLimitViolationEntity.Fields.limitType,
ContingencyEntity.Fields.contingencyLimitViolations + SpecificationUtils.FIELD_SEPARATOR + AbstractLimitViolationEntity.Fields.limitName,
ContingencyEntity.Fields.contingencyLimitViolations + SpecificationUtils.FIELD_SEPARATOR + AbstractLimitViolationEntity.Fields.limit,
@@ -68,6 +70,7 @@ public class SecurityAnalysisResultService extends AbstractComputationResultServ
private static final List ALLOWED_NMK_SUBJECT_LIMIT_VIOLATIONS_RESULT_SORT_PROPERTIES = List.of(
SubjectLimitViolationEntity.Fields.subjectId,
+ SubjectLimitViolationEntity.Fields.contingencyLimitViolations + SpecificationUtils.FIELD_SEPARATOR + AbstractLimitViolationEntity.Fields.locationId,
SubjectLimitViolationEntity.Fields.contingencyLimitViolations + SpecificationUtils.FIELD_SEPARATOR + AbstractLimitViolationEntity.Fields.limitType,
SubjectLimitViolationEntity.Fields.contingencyLimitViolations + SpecificationUtils.FIELD_SEPARATOR + AbstractLimitViolationEntity.Fields.limitName,
SubjectLimitViolationEntity.Fields.contingencyLimitViolations + SpecificationUtils.FIELD_SEPARATOR + AbstractLimitViolationEntity.Fields.limit,
@@ -87,8 +90,9 @@ public class SecurityAnalysisResultService extends AbstractComputationResultServ
AbstractLimitViolationEntity.Fields.value,
AbstractLimitViolationEntity.Fields.loading,
AbstractLimitViolationEntity.Fields.acceptableDuration,
- AbstractLimitViolationEntity.Fields.side
- );
+ AbstractLimitViolationEntity.Fields.side,
+ AbstractLimitViolationEntity.Fields.locationId
+ );
public SecurityAnalysisResultService(SecurityAnalysisResultRepository securityAnalysisResultRepository,
ContingencyRepository contingencyRepository,
@@ -228,11 +232,11 @@ public void assertResultExists(UUID resultUuid) {
}
@Transactional
- public void insert(UUID resultUuid, SecurityAnalysisResult result, SecurityAnalysisStatus status) {
+ public void insert(Network network, UUID resultUuid, SecurityAnalysisResult result, SecurityAnalysisStatus status) {
Objects.requireNonNull(resultUuid);
Objects.requireNonNull(result);
- SecurityAnalysisResultEntity securityAnalysisResult = SecurityAnalysisResultEntity.toEntity(resultUuid, result, status);
+ SecurityAnalysisResultEntity securityAnalysisResult = SecurityAnalysisResultEntity.toEntity(network, resultUuid, result, status);
securityAnalysisResultRepository.save(securityAnalysisResult);
}
@@ -522,6 +526,8 @@ private static Comparator getCommonComparator(S
Comparator.comparing(AbstractLimitViolationEntity::getSide, Comparator.nullsLast(Comparator.naturalOrder()));
case AbstractLimitViolationEntity.Fields.loading ->
Comparator.comparing(AbstractLimitViolationEntity::getLoading, Comparator.nullsLast(Comparator.naturalOrder()));
+ case AbstractLimitViolationEntity.Fields.locationId ->
+ Comparator.comparing(AbstractLimitViolationEntity::getLocationId, Comparator.nullsLast(Comparator.naturalOrder()));
default -> throw new IllegalArgumentException("Sorting on the column '" + field + "' is not supported"); // not supposed to happen
};
}
diff --git a/src/main/java/org/gridsuite/securityanalysis/server/service/SecurityAnalysisWorkerService.java b/src/main/java/org/gridsuite/securityanalysis/server/service/SecurityAnalysisWorkerService.java
index 96d1b6af..464793cf 100644
--- a/src/main/java/org/gridsuite/securityanalysis/server/service/SecurityAnalysisWorkerService.java
+++ b/src/main/java/org/gridsuite/securityanalysis/server/service/SecurityAnalysisWorkerService.java
@@ -194,7 +194,7 @@ protected void postRun(SecurityAnalysisRunContext runContext, AtomicReference resultContext, SecurityAnalysisResult result) {
- resultService.insert(
+ resultService.insert(network,
resultContext.getResultUuid(),
result,
result.getPreContingencyResult().getStatus() == LoadFlowResult.ComponentResult.Status.CONVERGED
diff --git a/src/main/resources/db/changelog/changesets/changelog_20250207T161145Z.xml b/src/main/resources/db/changelog/changesets/changelog_20250207T161145Z.xml
new file mode 100644
index 00000000..d727bbd9
--- /dev/null
+++ b/src/main/resources/db/changelog/changesets/changelog_20250207T161145Z.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml
index 3d8814b5..7279e0d3 100644
--- a/src/main/resources/db/changelog/db.changelog-master.yaml
+++ b/src/main/resources/db/changelog/db.changelog-master.yaml
@@ -39,4 +39,6 @@ databaseChangeLog:
- include:
file: changesets/changelog_20241212T111835Z.xml
relativeToChangelogFile: true
-
+ - include:
+ file: changesets/changelog_20250207T161145Z.xml
+ relativeToChangelogFile: true
diff --git a/src/test/java/org/gridsuite/securityanalysis/server/FindContingenciesTest.java b/src/test/java/org/gridsuite/securityanalysis/server/FindContingenciesTest.java
index 5ac54bd0..3f39125e 100644
--- a/src/test/java/org/gridsuite/securityanalysis/server/FindContingenciesTest.java
+++ b/src/test/java/org/gridsuite/securityanalysis/server/FindContingenciesTest.java
@@ -6,7 +6,10 @@
*/
package org.gridsuite.securityanalysis.server;
+import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.ThreeSides;
+import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory;
+import com.powsybl.network.store.iidm.impl.NetworkFactoryImpl;
import com.powsybl.security.LimitViolationType;
import org.gridsuite.securityanalysis.server.dto.ContingencyResultDTO;
import org.gridsuite.securityanalysis.server.dto.ResourceFilterDTO;
@@ -61,7 +64,9 @@ class FindContingenciesTest {
@BeforeAll
void setUp() {
- resultEntity = SecurityAnalysisResultEntity.toEntity(UUID.randomUUID(), RESULT, SecurityAnalysisStatus.CONVERGED);
+ // network store service mocking
+ Network network = EurostagTutorialExample1Factory.create(new NetworkFactoryImpl());
+ resultEntity = SecurityAnalysisResultEntity.toEntity(network, UUID.randomUUID(), RESULT, SecurityAnalysisStatus.CONVERGED);
securityAnalysisResultRepository.save(resultEntity);
}
diff --git a/src/test/java/org/gridsuite/securityanalysis/server/FindPreContingencyLimitViolationTest.java b/src/test/java/org/gridsuite/securityanalysis/server/FindPreContingencyLimitViolationTest.java
index 8d957d0c..e1140812 100644
--- a/src/test/java/org/gridsuite/securityanalysis/server/FindPreContingencyLimitViolationTest.java
+++ b/src/test/java/org/gridsuite/securityanalysis/server/FindPreContingencyLimitViolationTest.java
@@ -6,14 +6,12 @@
*/
package org.gridsuite.securityanalysis.server;
+import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.ThreeSides;
-import org.gridsuite.securityanalysis.server.dto.PreContingencyLimitViolationResultDTO;
-import org.gridsuite.securityanalysis.server.dto.ResourceFilterDTO;
-import org.gridsuite.securityanalysis.server.dto.SecurityAnalysisStatus;
-import org.gridsuite.securityanalysis.server.dto.SubjectLimitViolationResultDTO;
-import org.gridsuite.securityanalysis.server.entities.AbstractLimitViolationEntity;
-import org.gridsuite.securityanalysis.server.entities.SecurityAnalysisResultEntity;
-import org.gridsuite.securityanalysis.server.entities.SubjectLimitViolationEntity;
+import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory;
+import com.powsybl.network.store.iidm.impl.NetworkFactoryImpl;
+import org.gridsuite.securityanalysis.server.dto.*;
+import org.gridsuite.securityanalysis.server.entities.*;
import org.gridsuite.securityanalysis.server.repositories.SecurityAnalysisResultRepository;
import org.gridsuite.securityanalysis.server.repositories.specifications.SpecificationUtils;
import org.gridsuite.securityanalysis.server.service.SecurityAnalysisResultService;
@@ -36,7 +34,6 @@
import static com.vladmihalcea.sql.SQLStatementCountValidator.reset;
import static org.assertj.core.api.Assertions.assertThat;
import static org.gridsuite.securityanalysis.server.SecurityAnalysisProviderMock.*;
-
/**
* @author Anis Touri
*/
@@ -53,7 +50,9 @@ class FindPreContingencyLimitViolationTest {
@BeforeAll
void setUp() {
- resultEntity = SecurityAnalysisResultEntity.toEntity(UUID.randomUUID(), PRECONTINGENCY_RESULT, SecurityAnalysisStatus.CONVERGED);
+ // network store service mocking
+ Network network = EurostagTutorialExample1Factory.create(new NetworkFactoryImpl());
+ resultEntity = SecurityAnalysisResultEntity.toEntity(network, UUID.randomUUID(), PRECONTINGENCY_RESULT, SecurityAnalysisStatus.CONVERGED);
securityAnalysisResultRepository.save(resultEntity);
}
@@ -79,6 +78,13 @@ void findFilteredPrecontingencyLimitViolationResultsTest(List
.containsExactlyElementsOf(
expectedResult.stream().map(PreContingencyLimitViolationResultDTO::getSubjectId).toList()
);
+
+ // assert location ids
+ assertThat(preContingencyLimitViolation).extracting(PreContingencyLimitViolationResultDTO.Fields.limitViolation + SpecificationUtils.FIELD_SEPARATOR + AbstractLimitViolationEntity.Fields.locationId)
+ .containsExactlyElementsOf(
+ expectedResult.stream().map(preContingencyLimitViolationResultDTO -> preContingencyLimitViolationResultDTO.getLimitViolation().getLocationId()).toList()
+ );
+
assertSelectCount(expectedSelectCount);
}
@@ -95,7 +101,7 @@ private static Stream provideParentFilter() {
RESULT_PRECONTINGENCY.stream().sorted(Comparator.comparing(PreContingencyLimitViolationResultDTO::getSubjectId)).filter(c -> c.getSubjectId().contains("3")).toList(), 2),
Arguments.of(List.of(new ResourceFilterDTO(ResourceFilterDTO.DataType.TEXT, ResourceFilterDTO.Type.STARTS_WITH, "l", AbstractLimitViolationEntity.Fields.subjectLimitViolation + SpecificationUtils.FIELD_SEPARATOR + SubjectLimitViolationEntity.Fields.subjectId)), Sort.by(Sort.Direction.ASC, AbstractLimitViolationEntity.Fields.subjectLimitViolation + SpecificationUtils.FIELD_SEPARATOR + SubjectLimitViolationEntity.Fields.subjectId),
RESULT_PRECONTINGENCY.stream().sorted(Comparator.comparing(PreContingencyLimitViolationResultDTO::getSubjectId)).filter(c -> c.getSubjectId().startsWith("l")).toList(), 2),
- Arguments.of(List.of(new ResourceFilterDTO(ResourceFilterDTO.DataType.TEXT, ResourceFilterDTO.Type.STARTS_WITH, "3", AbstractLimitViolationEntity.Fields.subjectLimitViolation + SpecificationUtils.FIELD_SEPARATOR + SubjectLimitViolationEntity.Fields.subjectId)), Sort.by(Sort.Direction.ASC, AbstractLimitViolationEntity.Fields.subjectLimitViolation + SpecificationUtils.FIELD_SEPARATOR + SubjectLimitViolationEntity.Fields.subjectId),
+ Arguments.of(List.of(new ResourceFilterDTO(ResourceFilterDTO.DataType.TEXT, ResourceFilterDTO.Type.STARTS_WITH, "3", AbstractLimitViolationEntity.Fields.locationId)), Sort.by(Sort.Direction.ASC, AbstractLimitViolationEntity.Fields.locationId),
RESULT_PRECONTINGENCY.stream().sorted(Comparator.comparing(PreContingencyLimitViolationResultDTO::getSubjectId)).filter(c -> c.getSubjectId().startsWith("3")).toList(), 2)
);
}
diff --git a/src/test/java/org/gridsuite/securityanalysis/server/FindSubjectLimitViolationsTest.java b/src/test/java/org/gridsuite/securityanalysis/server/FindSubjectLimitViolationsTest.java
index 8c07fba8..ae9f903b 100644
--- a/src/test/java/org/gridsuite/securityanalysis/server/FindSubjectLimitViolationsTest.java
+++ b/src/test/java/org/gridsuite/securityanalysis/server/FindSubjectLimitViolationsTest.java
@@ -6,7 +6,10 @@
*/
package org.gridsuite.securityanalysis.server;
+import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.ThreeSides;
+import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory;
+import com.powsybl.network.store.iidm.impl.NetworkFactoryImpl;
import com.powsybl.security.LimitViolationType;
import org.gridsuite.securityanalysis.server.dto.ContingencyLimitViolationDTO;
import org.gridsuite.securityanalysis.server.dto.ResourceFilterDTO;
@@ -58,7 +61,9 @@ class FindSubjectLimitViolationsTest {
@BeforeAll
void setUp() {
- resultEntity = SecurityAnalysisResultEntity.toEntity(UUID.randomUUID(), RESULT, SecurityAnalysisStatus.CONVERGED);
+ // network store service mocking
+ Network network = EurostagTutorialExample1Factory.create(new NetworkFactoryImpl());
+ resultEntity = SecurityAnalysisResultEntity.toEntity(network, UUID.randomUUID(), RESULT, SecurityAnalysisStatus.CONVERGED);
securityAnalysisResultRepository.save(resultEntity);
}
@@ -81,6 +86,9 @@ void findFilteredSubjectLimitViolationResultsTest(List filter
// assert subject ids to check parent filters
assertThat(subjectLimitViolationPage.getContent()).extracting("subjectId").containsExactlyElementsOf(expectedResult.stream().map(SubjectLimitViolationResultDTO::getSubjectId).toList());
+ assertThat(subjectLimitViolationPage.getContent().stream()
+ .map(SubjectLimitViolationResultDTO::toDto).map(lm -> lm.getContingencies().stream().map(c -> c.getLimitViolation().getLocationId()).toList()))
+ .containsExactlyElementsOf(expectedResult.stream().map(slm -> slm.getContingencies().stream().map(FindSubjectLimitViolationsTest::getContingencyLimitViolationDTOLocationId).toList()).toList());
// assert limit violation contingency ids to check nested filters
assertThat(subjectLimitViolationPage.getContent().stream()
.map(SubjectLimitViolationResultDTO::toDto)
@@ -223,4 +231,8 @@ private static Stream provideForbiddenFilter() {
private static String getContingencyLimitViolationDTOContingencyId(ContingencyLimitViolationDTO contingencyLimitViolationDTO) {
return contingencyLimitViolationDTO.getContingency().getContingencyId();
}
+
+ private static String getContingencyLimitViolationDTOLocationId(ContingencyLimitViolationDTO contingencyLimitViolationDTO) {
+ return contingencyLimitViolationDTO.getLimitViolation().getLocationId();
+ }
}
diff --git a/src/test/java/org/gridsuite/securityanalysis/server/SecurityAnalysisControllerTest.java b/src/test/java/org/gridsuite/securityanalysis/server/SecurityAnalysisControllerTest.java
index cf2b7d77..c8c71deb 100644
--- a/src/test/java/org/gridsuite/securityanalysis/server/SecurityAnalysisControllerTest.java
+++ b/src/test/java/org/gridsuite/securityanalysis/server/SecurityAnalysisControllerTest.java
@@ -428,6 +428,8 @@ private void assertFiltredResultN() throws Exception {
String resultAsString = mvcResult.getResponse().getContentAsString();
List preContingencyResult = mapper.readValue(resultAsString, new TypeReference<>() { });
assertEquals(1, preContingencyResult.size());
+ assertEquals("vl1 (VLGEN_0, VLLOAD_0)", preContingencyResult.get(0).getLimitViolation().getLocationId());
+
}
private void checkNResultEnumFilters(UUID resultUuid) throws Exception {
@@ -437,7 +439,7 @@ private void checkNResultEnumFilters(UUID resultUuid) throws Exception {
content().contentType(MediaType.APPLICATION_JSON)).andReturn();
List nResults = mapper.readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() { });
-
+ verifynResultsLocationId(nResults);
List expectedLimitTypes = nResults.stream().map(result -> result.getLimitViolation().getLimitType()).distinct().toList();
mvcResult = mockMvc.perform(get("/" + VERSION + "/results/{resultUuid}/n-limit-types", resultUuid))
.andExpectAll(
@@ -457,6 +459,10 @@ private void checkNResultEnumFilters(UUID resultUuid) throws Exception {
Assertions.assertThat(sides).hasSameElementsAs(expectedSides);
}
+ private void verifynResultsLocationId(List nResults) {
+ Assertions.assertThat(nResults.stream().map(preContingencyLimitViolationResultDTO -> preContingencyLimitViolationResultDTO.getLimitViolation().getLocationId()).toList()).hasSameElementsAs(List.of("l3", "vl1 (VLGEN_0, VLLOAD_0)", "l6"));
+ }
+
private void checkNmKResultEnumFilters(UUID resultUuid) throws Exception {
// getting 100 elements here because we want to fetch all test datas to check fetched filters belongs to fetched results
MvcResult mvcResult = mockMvc.perform(get("/" + VERSION + "/results/" + RESULT_UUID + "/nmk-contingencies-result/paged?size=100"))
@@ -467,7 +473,7 @@ private void checkNmKResultEnumFilters(UUID resultUuid) throws Exception {
JsonNode resultsJsonNode = mapper.readTree(mvcResult.getResponse().getContentAsString());
ObjectReader resultsObjectReader = mapper.readerFor(new TypeReference>() { });
List nmkResult = resultsObjectReader.readValue(resultsJsonNode.get("content"));
-
+ verifyNmkContingrnciesResultLocationIds(nmkResult);
List expectedLimitTypes = nmkResult.stream().map(ContingencyResultDTO::getSubjectLimitViolations).flatMap(subjectLimitViolationDTOS -> subjectLimitViolationDTOS.stream().map(slm -> slm.getLimitViolation().getLimitType())).distinct().toList();
mvcResult = mockMvc.perform(get("/" + VERSION + "/results/{resultUuid}/nmk-limit-types", resultUuid))
.andExpectAll(
@@ -496,6 +502,17 @@ private void checkNmKResultEnumFilters(UUID resultUuid) throws Exception {
Assertions.assertThat(status).hasSameElementsAs(expectedStatus);
}
+ private void verifyNmkContingrnciesResultLocationIds(List nmkResult) {
+ List locationIds = nmkResult.stream()
+ .flatMap(result -> result.getSubjectLimitViolations().stream())
+ .map(subjectLimitViolationDTO -> subjectLimitViolationDTO.getLimitViolation().getLocationId())
+ .distinct()
+ .toList();
+
+ Assertions.assertThat(locationIds).hasSameElementsAs(List.of("l3", "vl1 (VLGEN_0, VLLOAD_0)", "l6", "vl7"));
+
+ }
+
@Test
void runWithTwoLists() throws Exception {
MvcResult mvcResult;
@@ -797,12 +814,11 @@ private void checkAllZippedCsvResults() throws Exception {
.headers(List.of("Ouvrage", "Type de contrainte", "Nom du seuil", "Valeur du seuil (A ou kV)", "Valeur calculée (A ou kV)", "Charge (%)", "Surcharge", "Côté"))
.enumValueTranslations(ENUM_TRANSLATIONS_FR)
.build());
- assertRequestsCount(2, 0, 0, 0);
SQLStatementCountValidator.reset();
checkZippedCsvResult("nmk-contingencies-result", "/results/nmk-contingencies-result-en.csv",
CsvTranslationDTO.builder()
- .headers(List.of("Contingency ID", "Status", "Constraint", "Violation type", "Limit name", "Limit value (A or kV)", "Calculated value (A or kV)", "Load (%)", "Overload", "Side"))
+ .headers(List.of("Contingency ID", "Status", "Constraint", "Bus", "Violation type", "Limit name", "Limit value (A or kV)", "Calculated value (A or kV)", "Load (%)", "Overload", "Side"))
.enumValueTranslations(ENUM_TRANSLATIONS_EN)
.build());
/*
@@ -817,7 +833,7 @@ private void checkAllZippedCsvResults() throws Exception {
SQLStatementCountValidator.reset();
checkZippedCsvResult("nmk-contingencies-result", "/results/nmk-contingencies-result-fr.csv",
CsvTranslationDTO.builder()
- .headers(List.of("Id aléa", "Statut", "Contrainte", "Type de contrainte", "Nom du seuil", "Valeur du seuil (A ou kV)", "Charge (%)", "Surcharge", "Côté"))
+ .headers(List.of("Id aléa", "Statut", "Contrainte", "Noeud électrique", "Type de contrainte", "Nom du seuil", "Valeur du seuil (A ou kV)", "Charge (%)", "Surcharge", "Côté"))
.enumValueTranslations(ENUM_TRANSLATIONS_FR)
.build());
assertRequestsCount(4, 0, 0, 0);
@@ -825,7 +841,7 @@ private void checkAllZippedCsvResults() throws Exception {
SQLStatementCountValidator.reset();
checkZippedCsvResult("nmk-constraints-result", "/results/nmk-constraints-result-en.csv",
CsvTranslationDTO.builder()
- .headers(List.of("Constraint", "Contingency ID", "Status", "Violation type", "Limit name", "Limit value (A or kV)", "Calculated value (A or kV)", "Load (%)", "Overload", "Side"))
+ .headers(List.of("Constraint", "Contingency ID", "Status", "Bus", "Violation type", "Limit name", "Limit value (A or kV)", "Calculated value (A or kV)", "Load (%)", "Overload", "Side"))
.enumValueTranslations(ENUM_TRANSLATIONS_EN)
.build());
/*
@@ -840,7 +856,7 @@ private void checkAllZippedCsvResults() throws Exception {
SQLStatementCountValidator.reset();
checkZippedCsvResult("nmk-constraints-result", "/results/nmk-constraints-result-fr.csv",
CsvTranslationDTO.builder()
- .headers(List.of("Contrainte", "ID aléa", "Statut", "Type de contrainte", "Nom du seuil", "Valeur du seuil (A ou kV)", "Valeur calculée (A ou kV)", "Charge (%)", "Surcharge", "Côté"))
+ .headers(List.of("Contrainte", "ID aléa", "Statut", "Noeud électrique", "Type de contrainte", "Nom du seuil", "Valeur du seuil (A ou kV)", "Valeur calculée (A ou kV)", "Charge (%)", "Surcharge", "Côté"))
.enumValueTranslations(ENUM_TRANSLATIONS_FR)
.build());
assertRequestsCount(4, 0, 0, 0);
diff --git a/src/test/java/org/gridsuite/securityanalysis/server/SecurityAnalysisProviderMock.java b/src/test/java/org/gridsuite/securityanalysis/server/SecurityAnalysisProviderMock.java
index 7cb374f7..293d368f 100644
--- a/src/test/java/org/gridsuite/securityanalysis/server/SecurityAnalysisProviderMock.java
+++ b/src/test/java/org/gridsuite/securityanalysis/server/SecurityAnalysisProviderMock.java
@@ -9,9 +9,12 @@
import com.powsybl.contingency.*;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.TwoSides;
+import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory;
import com.powsybl.loadflow.LoadFlowResult;
+import com.powsybl.network.store.iidm.impl.NetworkFactoryImpl;
import com.powsybl.security.*;
import com.powsybl.security.results.PostContingencyResult;
+import com.powsybl.ws.commons.computation.utils.ComputationResultUtils;
import org.gridsuite.securityanalysis.server.dto.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -77,10 +80,10 @@ public class SecurityAnalysisProviderMock implements SecurityAnalysisProvider {
//MAX VALUE for acceptable duration here is important to check this value is actually set to null when exporting it
static final LimitViolation LIMIT_VIOLATION_1 = new LimitViolation("l3", LimitViolationType.CURRENT, "l3_name", Integer.MAX_VALUE, 10, 1, 11, TwoSides.ONE);
- static final LimitViolation LIMIT_VIOLATION_2 = new LimitViolation("vl1", LimitViolationType.HIGH_VOLTAGE, "permanent", 0, 400, 1, 410);
+ static final LimitViolation LIMIT_VIOLATION_2 = new LimitViolation("vl1", null, LimitViolationType.HIGH_VOLTAGE, "permanent", 0, 400, 1, 410, null, new BusBreakerViolationLocation(List.of("NGEN", "NLOAD")));
static final LimitViolation LIMIT_VIOLATION_3 = new LimitViolation("l6", LimitViolationType.CURRENT, "l6_name", 20 * 60, 10, 1, 11, TwoSides.ONE);
static final LimitViolation LIMIT_VIOLATION_4 = new LimitViolation("vl7", LimitViolationType.HIGH_VOLTAGE, "vl7_name", 0, 400, 2, 410);
- static final LimitViolation LIMIT_VIOLATION_5 = new LimitViolation("vl5", LimitViolationType.LOW_VOLTAGE, "vl5_name", 0, 350, 3, 416, TwoSides.TWO);
+ static final LimitViolation LIMIT_VIOLATION_5 = new LimitViolation("vl5", null, LimitViolationType.LOW_VOLTAGE, "vl5_name", 0, 400, 1, 410, null, new BusBreakerViolationLocation(List.of("NLOAD")));
static final LimitViolation LIMIT_VIOLATION_6 = new LimitViolation("l7", LimitViolationType.CURRENT, "l7_name", 20 * 60, 10.51242140448186, 1.00001290229799f, 11.024281313654868, TwoSides.ONE);
static final List RESULT_LIMIT_VIOLATIONS = List.of(LIMIT_VIOLATION_1, LIMIT_VIOLATION_2);
static final List FAILED_LIMIT_VIOLATIONS = List.of(LIMIT_VIOLATION_3, LIMIT_VIOLATION_4);
@@ -236,7 +239,8 @@ private static SubjectLimitViolationDTO toSubjectLimitViolationDTO(LimitViolatio
limitViolation.getLimit(),
limitViolation.getLimitReduction(),
limitViolation.getValue(),
- computedLoading
+ computedLoading,
+ ComputationResultUtils.getViolationLocationId(limitViolation, getNetwork())
)
);
}
@@ -262,7 +266,8 @@ private static PreContingencyLimitViolationResultDTO toPreContingencyResultDTO(L
limitViolation.getLimit(),
limitViolation.getLimitReduction(),
limitViolation.getValue(),
- computedLoading
+ computedLoading,
+ ComputationResultUtils.getViolationLocationId(limitViolation, getNetwork())
));
}
@@ -298,8 +303,13 @@ private static ContingencyLimitViolationDTO toContingencyLimitViolationDTO(Conti
limitViolation.getLimit(),
limitViolation.getLimitReduction(),
limitViolation.getValue(),
- computedLoading
+ computedLoading,
+ ComputationResultUtils.getViolationLocationId(limitViolation, getNetwork())
)
);
}
+
+ private static Network getNetwork() {
+ return EurostagTutorialExample1Factory.create(new NetworkFactoryImpl());
+ }
}
diff --git a/src/test/java/org/gridsuite/securityanalysis/server/service/SecurityAnalysisResultServiceTest.java b/src/test/java/org/gridsuite/securityanalysis/server/service/SecurityAnalysisResultServiceTest.java
index e970a378..c2ea216b 100644
--- a/src/test/java/org/gridsuite/securityanalysis/server/service/SecurityAnalysisResultServiceTest.java
+++ b/src/test/java/org/gridsuite/securityanalysis/server/service/SecurityAnalysisResultServiceTest.java
@@ -6,6 +6,9 @@
*/
package org.gridsuite.securityanalysis.server.service;
+import com.powsybl.iidm.network.Network;
+import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory;
+import com.powsybl.network.store.iidm.impl.NetworkFactoryImpl;
import com.vladmihalcea.sql.SQLStatementCountValidator;
import org.gridsuite.securityanalysis.server.dto.SecurityAnalysisStatus;
import org.junit.jupiter.api.Test;
@@ -14,7 +17,7 @@
import java.util.UUID;
-import static org.gridsuite.securityanalysis.server.SecurityAnalysisProviderMock.RESULT;
+import static org.gridsuite.securityanalysis.server.SecurityAnalysisProviderMock.*;
import static org.gridsuite.securityanalysis.server.util.DatabaseQueryUtils.assertRequestsCount;
/**
@@ -22,14 +25,14 @@
*/
@SpringBootTest
class SecurityAnalysisResultServiceTest {
-
@Autowired
private SecurityAnalysisResultService securityAnalysisResultService;
@Test
void deleteResultPerfTest() {
+ Network network = EurostagTutorialExample1Factory.create(new NetworkFactoryImpl());
UUID resultUuid = UUID.randomUUID();
- securityAnalysisResultService.insert(resultUuid, RESULT, SecurityAnalysisStatus.CONVERGED);
+ securityAnalysisResultService.insert(network, resultUuid, RESULT, SecurityAnalysisStatus.CONVERGED);
SQLStatementCountValidator.reset();
securityAnalysisResultService.delete(resultUuid);
diff --git a/src/test/resources/results/n-result-en.csv b/src/test/resources/results/n-result-en.csv
index aa4c4436..31785e07 100644
--- a/src/test/resources/results/n-result-en.csv
+++ b/src/test/resources/results/n-result-en.csv
@@ -1,4 +1,4 @@
Equipment,Violation type,Limit name,Limit value (A or kV),Calculated value (A or kV),Load (%),Overload,Side
l3,Current,l3_name,10.0,11.0,110.0,,Side 1
l6,Current,l6_name,10.0,11.0,110.0,1200,Side 1
-vl1,High voltage,IST,400.0,410.0,,0,
+"vl1 (VLGEN_0, VLLOAD_0)",High voltage,IST,400.0,410.0,,0,
diff --git a/src/test/resources/results/n-result-fr.csv b/src/test/resources/results/n-result-fr.csv
index 30dd4ca0..e2fd45e0 100644
--- a/src/test/resources/results/n-result-fr.csv
+++ b/src/test/resources/results/n-result-fr.csv
@@ -1,4 +1,4 @@
Ouvrage,Type de contrainte,Nom du seuil,Valeur du seuil (A ou kV),Valeur calculée (A ou kV),Charge (%),Surcharge,Côté
l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
l6,Intensité,l6_name,10.0,11.0,110.0,1200,Côté 1
-vl1,Tension haute,IST,400.0,410.0,,0,
+"vl1 (VLGEN_0, VLLOAD_0)",Tension haute,IST,400.0,410.0,,0,
diff --git a/src/test/resources/results/nmk-constraints-result-en.csv b/src/test/resources/results/nmk-constraints-result-en.csv
index b83a95c7..838864c2 100644
--- a/src/test/resources/results/nmk-constraints-result-en.csv
+++ b/src/test/resources/results/nmk-constraints-result-en.csv
@@ -1,27 +1,27 @@
-Constraint,Contingency ID,Status,Violation type,Limit name,Limit value (A or kV),Calculated value (A or kV),Load (%),Overload,Side
-l3,l1,Converged,Current,l3_name,10.0,11.0,110.0,,Side 1
-l3,l2,Converged,Current,l3_name,10.0,11.0,110.0,,Side 1
-l3,l3,Converged,Current,l3_name,10.0,11.0,110.0,,Side 1
-l3,l4,Converged,Current,l3_name,10.0,11.0,110.0,,Side 1
-l3,l6,Converged,Current,l3_name,10.0,11.0,110.0,,Side 1
-l3,l7,Converged,Current,l3_name,10.0,11.0,110.0,,Side 1
-l3,l8,Converged,Current,l3_name,10.0,11.0,110.0,,Side 1
-l3,l9,Converged,Current,l3_name,10.0,11.0,110.0,,Side 1
-l3,la,Converged,Current,l3_name,10.0,11.0,110.0,,Side 1
-l3,lb,Converged,Current,l3_name,10.0,11.0,110.0,,Side 1
-vl1,l1,Converged,High voltage,IST,400.0,410.0,,0,
-vl1,l2,Converged,High voltage,IST,400.0,410.0,,0,
-vl1,l3,Converged,High voltage,IST,400.0,410.0,,0,
-vl1,l4,Converged,High voltage,IST,400.0,410.0,,0,
-vl1,l6,Converged,High voltage,IST,400.0,410.0,,0,
-vl1,l7,Converged,High voltage,IST,400.0,410.0,,0,
-vl1,l8,Converged,High voltage,IST,400.0,410.0,,0,
-vl1,l9,Converged,High voltage,IST,400.0,410.0,,0,
-vl1,la,Converged,High voltage,IST,400.0,410.0,,0,
-vl1,lb,Converged,High voltage,IST,400.0,410.0,,0,
-l6,f1,Failed,Current,l6_name,10.0,11.0,110.0,1200,Side 1
-l6,f2,Failed,Current,l6_name,10.0,11.0,110.0,1200,Side 1
-l6,f3,Failed,Current,l6_name,10.0,11.0,110.0,1200,Side 1
-vl7,f1,Failed,High voltage,vl7_name,400.0,410.0,,0,
-vl7,f2,Failed,High voltage,vl7_name,400.0,410.0,,0,
-vl7,f3,Failed,High voltage,vl7_name,400.0,410.0,,0,
+Constraint,Contingency ID,Status,Bus,Violation type,Limit name,Limit value (A or kV),Calculated value (A or kV),Load (%),Overload,Side
+l3,l1,Converged,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
+l3,l2,Converged,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
+l3,l3,Converged,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
+l3,l4,Converged,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
+l3,l6,Converged,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
+l3,l7,Converged,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
+l3,l8,Converged,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
+l3,l9,Converged,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
+l3,la,Converged,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
+l3,lb,Converged,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
+vl1,l1,Converged,"vl1 (VLGEN_0, VLLOAD_0)",High voltage,IST,400.0,410.0,,0,
+vl1,l2,Converged,"vl1 (VLGEN_0, VLLOAD_0)",High voltage,IST,400.0,410.0,,0,
+vl1,l3,Converged,"vl1 (VLGEN_0, VLLOAD_0)",High voltage,IST,400.0,410.0,,0,
+vl1,l4,Converged,"vl1 (VLGEN_0, VLLOAD_0)",High voltage,IST,400.0,410.0,,0,
+vl1,l6,Converged,"vl1 (VLGEN_0, VLLOAD_0)",High voltage,IST,400.0,410.0,,0,
+vl1,l7,Converged,"vl1 (VLGEN_0, VLLOAD_0)",High voltage,IST,400.0,410.0,,0,
+vl1,l8,Converged,"vl1 (VLGEN_0, VLLOAD_0)",High voltage,IST,400.0,410.0,,0,
+vl1,l9,Converged,"vl1 (VLGEN_0, VLLOAD_0)",High voltage,IST,400.0,410.0,,0,
+vl1,la,Converged,"vl1 (VLGEN_0, VLLOAD_0)",High voltage,IST,400.0,410.0,,0,
+vl1,lb,Converged,"vl1 (VLGEN_0, VLLOAD_0)",High voltage,IST,400.0,410.0,,0,
+l6,f1,Failed,l6,Current,l6_name,10.0,11.0,110.0,1200,Side 1
+l6,f2,Failed,l6,Current,l6_name,10.0,11.0,110.0,1200,Side 1
+l6,f3,Failed,l6,Current,l6_name,10.0,11.0,110.0,1200,Side 1
+vl7,f1,Failed,vl7,High voltage,vl7_name,400.0,410.0,,0,
+vl7,f2,Failed,vl7,High voltage,vl7_name,400.0,410.0,,0,
+vl7,f3,Failed,vl7,High voltage,vl7_name,400.0,410.0,,0,
diff --git a/src/test/resources/results/nmk-constraints-result-fr.csv b/src/test/resources/results/nmk-constraints-result-fr.csv
index 4e8dbba1..7dce92d8 100644
--- a/src/test/resources/results/nmk-constraints-result-fr.csv
+++ b/src/test/resources/results/nmk-constraints-result-fr.csv
@@ -1,27 +1,27 @@
-Contrainte,ID aléa,Statut,Type de contrainte,Nom du seuil,Valeur du seuil (A ou kV),Valeur calculée (A ou kV),Charge (%),Surcharge,Côté
-l3,l1,Convergence,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
-l3,l2,Convergence,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
-l3,l3,Convergence,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
-l3,l4,Convergence,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
-l3,l6,Convergence,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
-l3,l7,Convergence,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
-l3,l8,Convergence,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
-l3,l9,Convergence,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
-l3,la,Convergence,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
-l3,lb,Convergence,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
-vl1,l1,Convergence,Tension haute,IST,400.0,410.0,,0,
-vl1,l2,Convergence,Tension haute,IST,400.0,410.0,,0,
-vl1,l3,Convergence,Tension haute,IST,400.0,410.0,,0,
-vl1,l4,Convergence,Tension haute,IST,400.0,410.0,,0,
-vl1,l6,Convergence,Tension haute,IST,400.0,410.0,,0,
-vl1,l7,Convergence,Tension haute,IST,400.0,410.0,,0,
-vl1,l8,Convergence,Tension haute,IST,400.0,410.0,,0,
-vl1,l9,Convergence,Tension haute,IST,400.0,410.0,,0,
-vl1,la,Convergence,Tension haute,IST,400.0,410.0,,0,
-vl1,lb,Convergence,Tension haute,IST,400.0,410.0,,0,
-l6,f1,Echec,Intensité,l6_name,10.0,11.0,110.0,1200,Côté 1
-l6,f2,Echec,Intensité,l6_name,10.0,11.0,110.0,1200,Côté 1
-l6,f3,Echec,Intensité,l6_name,10.0,11.0,110.0,1200,Côté 1
-vl7,f1,Echec,Tension haute,vl7_name,400.0,410.0,,0,
-vl7,f2,Echec,Tension haute,vl7_name,400.0,410.0,,0,
-vl7,f3,Echec,Tension haute,vl7_name,400.0,410.0,,0,
+Contrainte,ID aléa,Statut,Noeud électrique,Type de contrainte,Nom du seuil,Valeur du seuil (A ou kV),Valeur calculée (A ou kV),Charge (%),Surcharge,Côté
+l3,l1,Convergence,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
+l3,l2,Convergence,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
+l3,l3,Convergence,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
+l3,l4,Convergence,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
+l3,l6,Convergence,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
+l3,l7,Convergence,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
+l3,l8,Convergence,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
+l3,l9,Convergence,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
+l3,la,Convergence,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
+l3,lb,Convergence,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
+vl1,l1,Convergence,"vl1 (VLGEN_0, VLLOAD_0)",Tension haute,IST,400.0,410.0,,0,
+vl1,l2,Convergence,"vl1 (VLGEN_0, VLLOAD_0)",Tension haute,IST,400.0,410.0,,0,
+vl1,l3,Convergence,"vl1 (VLGEN_0, VLLOAD_0)",Tension haute,IST,400.0,410.0,,0,
+vl1,l4,Convergence,"vl1 (VLGEN_0, VLLOAD_0)",Tension haute,IST,400.0,410.0,,0,
+vl1,l6,Convergence,"vl1 (VLGEN_0, VLLOAD_0)",Tension haute,IST,400.0,410.0,,0,
+vl1,l7,Convergence,"vl1 (VLGEN_0, VLLOAD_0)",Tension haute,IST,400.0,410.0,,0,
+vl1,l8,Convergence,"vl1 (VLGEN_0, VLLOAD_0)",Tension haute,IST,400.0,410.0,,0,
+vl1,l9,Convergence,"vl1 (VLGEN_0, VLLOAD_0)",Tension haute,IST,400.0,410.0,,0,
+vl1,la,Convergence,"vl1 (VLGEN_0, VLLOAD_0)",Tension haute,IST,400.0,410.0,,0,
+vl1,lb,Convergence,"vl1 (VLGEN_0, VLLOAD_0)",Tension haute,IST,400.0,410.0,,0,
+l6,f1,Echec,l6,Intensité,l6_name,10.0,11.0,110.0,1200,Côté 1
+l6,f2,Echec,l6,Intensité,l6_name,10.0,11.0,110.0,1200,Côté 1
+l6,f3,Echec,l6,Intensité,l6_name,10.0,11.0,110.0,1200,Côté 1
+vl7,f1,Echec,vl7,Tension haute,vl7_name,400.0,410.0,,0,
+vl7,f2,Echec,vl7,Tension haute,vl7_name,400.0,410.0,,0,
+vl7,f3,Echec,vl7,Tension haute,vl7_name,400.0,410.0,,0,
diff --git a/src/test/resources/results/nmk-contingencies-result-en.csv b/src/test/resources/results/nmk-contingencies-result-en.csv
index 01b78dc7..2ee6d435 100644
--- a/src/test/resources/results/nmk-contingencies-result-en.csv
+++ b/src/test/resources/results/nmk-contingencies-result-en.csv
@@ -1,27 +1,27 @@
-Contingency ID,Status,Constraint,Violation type,Limit name,Limit value (A or kV),Calculated value (A or kV),Load (%),Overload,Side
-l1,Converged,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
-l1,Converged,vl1,High voltage,IST,400.0,410.0,,0,
-l2,Converged,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
-l2,Converged,vl1,High voltage,IST,400.0,410.0,,0,
-l3,Converged,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
-l3,Converged,vl1,High voltage,IST,400.0,410.0,,0,
-l4,Converged,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
-l4,Converged,vl1,High voltage,IST,400.0,410.0,,0,
-l6,Converged,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
-l6,Converged,vl1,High voltage,IST,400.0,410.0,,0,
-l7,Converged,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
-l7,Converged,vl1,High voltage,IST,400.0,410.0,,0,
-l8,Converged,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
-l8,Converged,vl1,High voltage,IST,400.0,410.0,,0,
-l9,Converged,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
-l9,Converged,vl1,High voltage,IST,400.0,410.0,,0,
-la,Converged,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
-la,Converged,vl1,High voltage,IST,400.0,410.0,,0,
-lb,Converged,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
-lb,Converged,vl1,High voltage,IST,400.0,410.0,,0,
-f1,Failed,l6,Current,l6_name,10.0,11.0,110.0,1200,Side 1
-f1,Failed,vl7,High voltage,vl7_name,400.0,410.0,,0,
-f2,Failed,l6,Current,l6_name,10.0,11.0,110.0,1200,Side 1
-f2,Failed,vl7,High voltage,vl7_name,400.0,410.0,,0,
-f3,Failed,l6,Current,l6_name,10.0,11.0,110.0,1200,Side 1
-f3,Failed,vl7,High voltage,vl7_name,400.0,410.0,,0,
+Contingency ID,Status,Constraint,Bus,Violation type,Limit name,Limit value (A or kV),Calculated value (A or kV),Load (%),Overload,Side
+l1,Converged,l3,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
+l1,Converged,vl1,"vl1 (VLGEN_0, VLLOAD_0)",High voltage,IST,400.0,410.0,,0,
+l2,Converged,l3,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
+l2,Converged,vl1,"vl1 (VLGEN_0, VLLOAD_0)",High voltage,IST,400.0,410.0,,0,
+l3,Converged,l3,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
+l3,Converged,vl1,"vl1 (VLGEN_0, VLLOAD_0)",High voltage,IST,400.0,410.0,,0,
+l4,Converged,l3,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
+l4,Converged,vl1,"vl1 (VLGEN_0, VLLOAD_0)",High voltage,IST,400.0,410.0,,0,
+l6,Converged,l3,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
+l6,Converged,vl1,"vl1 (VLGEN_0, VLLOAD_0)",High voltage,IST,400.0,410.0,,0,
+l7,Converged,l3,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
+l7,Converged,vl1,"vl1 (VLGEN_0, VLLOAD_0)",High voltage,IST,400.0,410.0,,0,
+l8,Converged,l3,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
+l8,Converged,vl1,"vl1 (VLGEN_0, VLLOAD_0)",High voltage,IST,400.0,410.0,,0,
+l9,Converged,l3,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
+l9,Converged,vl1,"vl1 (VLGEN_0, VLLOAD_0)",High voltage,IST,400.0,410.0,,0,
+la,Converged,l3,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
+la,Converged,vl1,"vl1 (VLGEN_0, VLLOAD_0)",High voltage,IST,400.0,410.0,,0,
+lb,Converged,l3,l3,Current,l3_name,10.0,11.0,110.0,,Side 1
+lb,Converged,vl1,"vl1 (VLGEN_0, VLLOAD_0)",High voltage,IST,400.0,410.0,,0,
+f1,Failed,l6,l6,Current,l6_name,10.0,11.0,110.0,1200,Side 1
+f1,Failed,vl7,vl7,High voltage,vl7_name,400.0,410.0,,0,
+f2,Failed,l6,l6,Current,l6_name,10.0,11.0,110.0,1200,Side 1
+f2,Failed,vl7,vl7,High voltage,vl7_name,400.0,410.0,,0,
+f3,Failed,l6,l6,Current,l6_name,10.0,11.0,110.0,1200,Side 1
+f3,Failed,vl7,vl7,High voltage,vl7_name,400.0,410.0,,0,
diff --git a/src/test/resources/results/nmk-contingencies-result-fr.csv b/src/test/resources/results/nmk-contingencies-result-fr.csv
index 2e3577c6..a82e93c6 100644
--- a/src/test/resources/results/nmk-contingencies-result-fr.csv
+++ b/src/test/resources/results/nmk-contingencies-result-fr.csv
@@ -1,27 +1,27 @@
-Id aléa,Statut,Contrainte,Type de contrainte,Nom du seuil,Valeur du seuil (A ou kV),Charge (%),Surcharge,Côté
-l1,Convergence,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
-l1,Convergence,vl1,Tension haute,IST,400.0,410.0,,0,
-l2,Convergence,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
-l2,Convergence,vl1,Tension haute,IST,400.0,410.0,,0,
-l3,Convergence,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
-l3,Convergence,vl1,Tension haute,IST,400.0,410.0,,0,
-l4,Convergence,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
-l4,Convergence,vl1,Tension haute,IST,400.0,410.0,,0,
-l6,Convergence,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
-l6,Convergence,vl1,Tension haute,IST,400.0,410.0,,0,
-l7,Convergence,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
-l7,Convergence,vl1,Tension haute,IST,400.0,410.0,,0,
-l8,Convergence,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
-l8,Convergence,vl1,Tension haute,IST,400.0,410.0,,0,
-l9,Convergence,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
-l9,Convergence,vl1,Tension haute,IST,400.0,410.0,,0,
-la,Convergence,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
-la,Convergence,vl1,Tension haute,IST,400.0,410.0,,0,
-lb,Convergence,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
-lb,Convergence,vl1,Tension haute,IST,400.0,410.0,,0,
-f1,Echec,l6,Intensité,l6_name,10.0,11.0,110.0,1200,Côté 1
-f1,Echec,vl7,Tension haute,vl7_name,400.0,410.0,,0,
-f2,Echec,l6,Intensité,l6_name,10.0,11.0,110.0,1200,Côté 1
-f2,Echec,vl7,Tension haute,vl7_name,400.0,410.0,,0,
-f3,Echec,l6,Intensité,l6_name,10.0,11.0,110.0,1200,Côté 1
-f3,Echec,vl7,Tension haute,vl7_name,400.0,410.0,,0,
+Id aléa,Statut,Contrainte,Noeud électrique,Type de contrainte,Nom du seuil,Valeur du seuil (A ou kV),Charge (%),Surcharge,Côté
+l1,Convergence,l3,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
+l1,Convergence,vl1,"vl1 (VLGEN_0, VLLOAD_0)",Tension haute,IST,400.0,410.0,,0,
+l2,Convergence,l3,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
+l2,Convergence,vl1,"vl1 (VLGEN_0, VLLOAD_0)",Tension haute,IST,400.0,410.0,,0,
+l3,Convergence,l3,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
+l3,Convergence,vl1,"vl1 (VLGEN_0, VLLOAD_0)",Tension haute,IST,400.0,410.0,,0,
+l4,Convergence,l3,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
+l4,Convergence,vl1,"vl1 (VLGEN_0, VLLOAD_0)",Tension haute,IST,400.0,410.0,,0,
+l6,Convergence,l3,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
+l6,Convergence,vl1,"vl1 (VLGEN_0, VLLOAD_0)",Tension haute,IST,400.0,410.0,,0,
+l7,Convergence,l3,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
+l7,Convergence,vl1,"vl1 (VLGEN_0, VLLOAD_0)",Tension haute,IST,400.0,410.0,,0,
+l8,Convergence,l3,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
+l8,Convergence,vl1,"vl1 (VLGEN_0, VLLOAD_0)",Tension haute,IST,400.0,410.0,,0,
+l9,Convergence,l3,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
+l9,Convergence,vl1,"vl1 (VLGEN_0, VLLOAD_0)",Tension haute,IST,400.0,410.0,,0,
+la,Convergence,l3,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
+la,Convergence,vl1,"vl1 (VLGEN_0, VLLOAD_0)",Tension haute,IST,400.0,410.0,,0,
+lb,Convergence,l3,l3,Intensité,l3_name,10.0,11.0,110.0,,Côté 1
+lb,Convergence,vl1,"vl1 (VLGEN_0, VLLOAD_0)",Tension haute,IST,400.0,410.0,,0,
+f1,Echec,l6,l6,Intensité,l6_name,10.0,11.0,110.0,1200,Côté 1
+f1,Echec,vl7,vl7,Tension haute,vl7_name,400.0,410.0,,0,
+f2,Echec,l6,l6,Intensité,l6_name,10.0,11.0,110.0,1200,Côté 1
+f2,Echec,vl7,vl7,Tension haute,vl7_name,400.0,410.0,,0,
+f3,Echec,l6,l6,Intensité,l6_name,10.0,11.0,110.0,1200,Côté 1
+f3,Echec,vl7,vl7,Tension haute,vl7_name,400.0,410.0,,0,