From 3b21daa7b398eab81f6afb75dbed16865a9e6add Mon Sep 17 00:00:00 2001 From: alejandravv <48628943+alejandravv@users.noreply.github.com> Date: Wed, 29 Jan 2020 13:13:18 +0100 Subject: [PATCH 1/8] Working on issue #96: Adding weights to the SI computation (#102) * Start working on issue #96: - add checkbox for "weighted average " - add modal draft to input weight * Intermediate step: adaptation of the database, addition of weights attribute, change source code on corresponding functions. * - Save new SI funcion with weights - Fetch with weights - Updates in enter/edit weights form * Add weights to assesSI functionality Transform editSI (to use weights) Save button check total sum of weighted SI * Correct weighted average formula Improve enter/edit weights form Try to paint Quality Model with weights * Improve Quality Model view with weights * Paint correctly Quality Model * Test Correction * Test correction * Make QualityModel representation SI---Factors consistent with Factors---Metrics Add Rationale field on CurrentTable view of SI Add info field to setStrategicIndicatorValue(...) function * Add rationale field to Current i Historic Table view * Improvements of enter/edit weights form: - Selected Factors names - Only numbers - Cancel button functionality * edit SI with weights not work at all * Working on edit SI funcionality and some test corrections * Corrected edit SI funcionality * Added contextual help to product configuration views * Added contextual help to strategic indicators configuration views * Sort SI's list in the strategic indicator configuration view * Change SI & Factor Rationale * Some tests correction * Correct some code smells and tests * Correct contextual help on Product view * Add contextual help to project's part on Product view * Correct some tests * Finish tests correction & Update documentation --- build.gradle | 4 +- docs/asciidoc/index.adoc | 2 +- docs/asciidoc/index.html | 184 ++++++++++----- libs/qrapids-qma-elastic-0.18.jar | Bin 0 -> 44680 bytes sonar-project.properties | 2 +- .../qrapids/app/domain/adapters/AssesSI.java | 20 ++ .../qrapids/app/domain/adapters/Forecast.java | 2 + .../adapters/QMA/QMAStrategicIndicators.java | 6 +- ...egicIndicatorQualityFactorsController.java | 31 +++ .../StrategicIndicatorsController.java | 147 ++++++++++-- ...dicatorQualityFactorNotFoundException.java | 4 + .../StrategicIndicatorQualityFactors.java | 70 ++++++ .../domain/models/Strategic_Indicator.java | 51 ++++- ...egicIndicatorQualityFactorsRepository.java | 16 ++ .../StrategicIndicatorRepository.java | 1 + .../app/presentation/rest/dto/DTOSI.java | 12 +- .../dto/DTOStrategicIndicatorEvaluation.java | 11 +- .../rest/services/StrategicIndicators.java | 34 +-- src/main/resources/static/css/products.css | 2 +- .../resources/static/css/stylesDashboard.css | 11 + .../resources/static/js/app/app.services.js | 4 +- src/main/resources/static/js/configSI.js | 214 +++++++++++++++++- .../resources/static/js/loadQualityModel.js | 24 +- src/main/resources/static/js/product.js | 54 ++--- .../CurrentTable.html | 2 +- .../HistoricTable.html | 2 +- .../resources/templates/Fragments/Modals.html | 34 +++ .../resources/templates/Product/Products.html | 5 +- .../QualityFactors/CurrentTable.html | 2 +- .../QualityFactors/HistoricTable.html | 2 +- .../StrategicIndicatorsConfig.html | 10 +- .../StrategicIndicators/CurrentTable.html | 9 + .../StrategicIndicators/HistoricTable.html | 7 + .../StrategicIndicatorsControllerTest.java | 141 ++++++++---- ...IndicatorQualityFactorsRepositoryTest.java | 84 +++++++ .../StrategicIndicatorRepositoryTest.java | 62 +++-- .../rest/services/ProductsTest.java | 12 +- .../services/StrategicIndicatorsTest.java | 80 +++++-- .../app/testHelpers/DomainObjectsBuilder.java | 85 ++++++- yiu/gradle.xml | 20 ++ yiu/jarRepositories.xml | 25 ++ yiu/misc.xml | 8 + yiu/vcs.xml | 6 + yiu/workspace.xml | 148 ++++++++++++ 44 files changed, 1366 insertions(+), 284 deletions(-) create mode 100644 libs/qrapids-qma-elastic-0.18.jar create mode 100644 src/main/java/com/upc/gessi/qrapids/app/domain/controllers/StrategicIndicatorQualityFactorsController.java create mode 100644 src/main/java/com/upc/gessi/qrapids/app/domain/exceptions/StrategicIndicatorQualityFactorNotFoundException.java create mode 100644 src/main/java/com/upc/gessi/qrapids/app/domain/models/StrategicIndicatorQualityFactors.java create mode 100644 src/main/java/com/upc/gessi/qrapids/app/domain/repositories/StrategicIndicator/StrategicIndicatorQualityFactorsRepository.java create mode 100644 src/test/java/com/upc/gessi/qrapids/app/domain/repositories/StrategicIndicator/StrategicIndicatorQualityFactorsRepositoryTest.java create mode 100644 yiu/gradle.xml create mode 100644 yiu/jarRepositories.xml create mode 100644 yiu/misc.xml create mode 100644 yiu/vcs.xml create mode 100644 yiu/workspace.xml diff --git a/build.gradle b/build.gradle index cbd40923..07e034ef 100644 --- a/build.gradle +++ b/build.gradle @@ -26,7 +26,7 @@ apply plugin: 'jacoco' apply plugin: 'org.asciidoctor.convert' group = 'com.upc.gessi.qrapids' -version = '1.1.1' +version = '1.2' sourceCompatibility = 1.8 war { @@ -78,7 +78,7 @@ dependencies { compile('org.elasticsearch.client:transport:5.6.3') compile('org.elasticsearch:elasticsearch:5.6.3') compile('org.elasticsearch.client:elasticsearch-rest-high-level-client:5.6.3') - compile files('libs/qrapids-qma-elastic-0.16.jar') + compile files('libs/qrapids-qma-elastic-0.18.jar') //API QR Generator compile files('libs/qrapids-qr_generator-0.2.jar') diff --git a/docs/asciidoc/index.adoc b/docs/asciidoc/index.adoc index d434e4c0..5b59b30d 100644 --- a/docs/asciidoc/index.adoc +++ b/docs/asciidoc/index.adoc @@ -1,5 +1,5 @@ = Q-Rapids Dashboard API REST Documentation -v1.1.1, {docdate} +v1.2, {docdate} :toc: left :sectnums: diff --git a/docs/asciidoc/index.html b/docs/asciidoc/index.html index 98d19659..69e0855e 100644 --- a/docs/asciidoc/index.html +++ b/docs/asciidoc/index.html @@ -5,7 +5,7 @@ - + Q-Rapids Dashboard API REST Documentation + + +
+
+
+ + + + + +
+
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/src/test/java/com/upc/gessi/qrapids/app/domain/controllers/StrategicIndicatorsControllerTest.java b/src/test/java/com/upc/gessi/qrapids/app/domain/controllers/StrategicIndicatorsControllerTest.java index 3280864f..cbcadaae 100644 --- a/src/test/java/com/upc/gessi/qrapids/app/domain/controllers/StrategicIndicatorsControllerTest.java +++ b/src/test/java/com/upc/gessi/qrapids/app/domain/controllers/StrategicIndicatorsControllerTest.java @@ -525,7 +525,7 @@ public void trainForecastModelsSingleProject() throws IOException { } @Test - public void assessStrategicIndicators() throws IOException, CategoriesException, ProjectNotFoundException { + public void assessStrategicIndicators() throws IOException, CategoriesException, ArithmeticException, ProjectNotFoundException { Project project = domainObjectsBuilder.buildProject(); when(projectsController.findProjectByExternalId(project.getExternalId())).thenReturn(project); @@ -590,10 +590,20 @@ public void assessStrategicIndicators() throws IOException, CategoriesException, factorValuesList.add(factor2Value); factorValuesList.add(factor3Value); + List factorWeightsList = new ArrayList<>(); + factorWeightsList.add(0.33333334f); + factorWeightsList.add(0.33333334f); + factorWeightsList.add(0.33333334f); + + List factorWeightedValuesList = new ArrayList<>(); + int factorsNumber = factorValuesList.size(); Float factorsValuesSum = 0f; + int i = 0; for (Float factorValue : factorValuesList) { factorsValuesSum += factorValue; + factorWeightedValuesList.add(factorValue * factorWeightsList.get(i)); + i++; } Float factorsAverageValue = factorsValuesSum / factorsNumber; @@ -603,16 +613,12 @@ public void assessStrategicIndicators() throws IOException, CategoriesException, when(qmaStrategicIndicators.setStrategicIndicatorValue(eq(project.getExternalId()), eq(strategicIndicator.getExternalId()), eq(strategicIndicatorName), eq(strategicIndicatorDescription), eq(factorsAverageValue.floatValue()), anyString(),ArgumentMatchers.any(LocalDate.class), isNull(), anyList(), eq(0L))).thenReturn(true); - List factorWeightsList = new ArrayList<>(); - factorWeightsList.add(1f); - factorWeightsList.add(1f); - factorWeightsList.add(1f); List factorCategoryNamesList = new ArrayList<>(); factorCategoryNamesList.add("Good"); factorCategoryNamesList.add("Good"); factorCategoryNamesList.add("Neutral"); - when(qmaRelations.setStrategicIndicatorFactorRelation(eq(project.getExternalId()), eq(strategicIndicator.getQuality_factors()), eq(strategicIndicator.getExternalId()), ArgumentMatchers.any(LocalDate.class), eq(factorWeightsList), eq(factorValuesList), eq(factorCategoryNamesList), eq(factorsAverageValue.toString()))).thenReturn(true); + when(qmaRelations.setStrategicIndicatorFactorRelation(eq(project.getExternalId()), eq(strategicIndicator.getQuality_factors()), eq(strategicIndicator.getExternalId()), ArgumentMatchers.any(LocalDate.class), eq(factorWeightsList), eq(factorWeightedValuesList), eq(factorCategoryNamesList), eq(factorsAverageValue.toString()))).thenReturn(true); // When boolean correct = strategicIndicatorsController.assessStrategicIndicators(project.getExternalId(), null); @@ -638,7 +644,7 @@ public void assessStrategicIndicators() throws IOException, CategoriesException, verify(qmaStrategicIndicators, times(1)).prepareSIIndex(eq(project.getExternalId())); verifyNoMoreInteractions(qmaStrategicIndicators); - verify(qmaRelations, times(1)).setStrategicIndicatorFactorRelation(eq(project.getExternalId()), eq(strategicIndicator.getQuality_factors()), eq(strategicIndicator.getExternalId()), ArgumentMatchers.any(LocalDate.class), eq(factorWeightsList), eq(factorValuesList), eq(factorCategoryNamesList), eq(factorsAverageValue.toString())); + verify(qmaRelations, times(1)).setStrategicIndicatorFactorRelation(eq(project.getExternalId()), eq(strategicIndicator.getQuality_factors()), eq(strategicIndicator.getExternalId()), ArgumentMatchers.any(LocalDate.class), eq(factorWeightsList), eq(factorWeightedValuesList), eq(factorCategoryNamesList), eq(factorsAverageValue.toString())); verifyNoMoreInteractions(qmaRelations); } @@ -811,10 +817,20 @@ public void assessStrategicIndicator () throws IOException, ProjectNotFoundExcep factorValuesList.add(factor2Value); factorValuesList.add(factor3Value); + List factorWeightsList = new ArrayList<>(); + factorWeightsList.add(0.33333334f); + factorWeightsList.add(0.33333334f); + factorWeightsList.add(0.33333334f); + + List factorWeightedValuesList = new ArrayList<>(); + int factorsNumber = factorValuesList.size(); Float factorsValuesSum = 0f; + int i = 0; for (Float factorValue : factorValuesList) { factorsValuesSum += factorValue; + factorWeightedValuesList.add(factorValue*factorWeightsList.get(i)); + i++; } Float factorsAverageValue = factorsValuesSum / factorsNumber; @@ -824,16 +840,12 @@ public void assessStrategicIndicator () throws IOException, ProjectNotFoundExcep when(qmaStrategicIndicators.setStrategicIndicatorValue(eq(project.getExternalId()), eq(strategicIndicator.getExternalId()), eq(strategicIndicatorName), eq(strategicIndicatorDescription), eq(factorsAverageValue.floatValue()), anyString(), ArgumentMatchers.any(LocalDate.class), isNull(), anyList(), eq(0L))).thenReturn(true); - List factorWeightsList = new ArrayList<>(); - factorWeightsList.add(1f); - factorWeightsList.add(1f); - factorWeightsList.add(1f); List factorCategoryNamesList = new ArrayList<>(); factorCategoryNamesList.add("Good"); factorCategoryNamesList.add("Good"); factorCategoryNamesList.add("Neutral"); - when(qmaRelations.setStrategicIndicatorFactorRelation(eq(project.getExternalId()), eq(strategicIndicator.getQuality_factors()), eq(strategicIndicator.getExternalId()), ArgumentMatchers.any(LocalDate.class), eq(factorWeightsList), eq(factorValuesList), eq(factorCategoryNamesList), eq(factorsAverageValue.toString()))).thenReturn(true); + when(qmaRelations.setStrategicIndicatorFactorRelation(eq(project.getExternalId()), eq(strategicIndicator.getQuality_factors()), eq(strategicIndicator.getExternalId()), ArgumentMatchers.any(LocalDate.class), eq(factorWeightsList), eq(factorWeightedValuesList), eq(factorCategoryNamesList), eq(factorsAverageValue.toString()))).thenReturn(true); // When boolean correct = strategicIndicatorsController.assessStrategicIndicator(strategicIndicator.getName(), project.getExternalId()); @@ -855,7 +867,7 @@ public void assessStrategicIndicator () throws IOException, ProjectNotFoundExcep verify(qmaStrategicIndicators, times(1)).setStrategicIndicatorValue(eq(project.getExternalId()), eq(strategicIndicator.getExternalId()), eq(strategicIndicatorName), eq(strategicIndicatorDescription), eq(factorsAverageValue.floatValue()), anyString(), ArgumentMatchers.any(LocalDate.class), isNull(), anyList(), eq(0L)); verifyNoMoreInteractions(qmaStrategicIndicators); - verify(qmaRelations, times(1)).setStrategicIndicatorFactorRelation(eq(project.getExternalId()), eq(strategicIndicator.getQuality_factors()), eq(strategicIndicator.getExternalId()), ArgumentMatchers.any(LocalDate.class), eq(factorWeightsList), eq(factorValuesList), eq(factorCategoryNamesList), eq(factorsAverageValue.toString())); + verify(qmaRelations, times(1)).setStrategicIndicatorFactorRelation(eq(project.getExternalId()), eq(strategicIndicator.getQuality_factors()), eq(strategicIndicator.getExternalId()), ArgumentMatchers.any(LocalDate.class), eq(factorWeightsList), eq(factorWeightedValuesList), eq(factorCategoryNamesList), eq(factorsAverageValue.toString())); verifyNoMoreInteractions(qmaRelations); } diff --git a/src/test/java/com/upc/gessi/qrapids/app/presentation/rest/services/StrategicIndicatorsTest.java b/src/test/java/com/upc/gessi/qrapids/app/presentation/rest/services/StrategicIndicatorsTest.java index 13aa5588..14ecb5b9 100644 --- a/src/test/java/com/upc/gessi/qrapids/app/presentation/rest/services/StrategicIndicatorsTest.java +++ b/src/test/java/com/upc/gessi/qrapids/app/presentation/rest/services/StrategicIndicatorsTest.java @@ -2551,12 +2551,14 @@ public void getQualityModel() throws Exception { .andExpect(jsonPath("$[0].color", is(dtoRelationsSI.getColor()))) .andExpect(jsonPath("$[0].factors", hasSize(1))) .andExpect(jsonPath("$[0].factors[0].id", is(dtoRelationsFactor.getId()))) - .andExpect(jsonPath("$[0].factors[0].value", is(dtoRelationsFactor.getValue()))) + .andExpect(jsonPath("$[0].factors[0].weightedValue", is(dtoRelationsFactor.getWeightedValue()))) .andExpect(jsonPath("$[0].factors[0].weight", is(dtoRelationsFactor.getWeight()))) + .andExpect(jsonPath("$[0].factors[0].assessmentValue", is(dtoRelationsFactor.getAssessmentValue()))) .andExpect(jsonPath("$[0].factors[0].metrics", hasSize(1))) .andExpect(jsonPath("$[0].factors[0].metrics[0].id", is(dtoRelationsMetric.getId()))) - .andExpect(jsonPath("$[0].factors[0].metrics[0].value", is(dtoRelationsMetric.getValue()))) - .andExpect(jsonPath("$[0].factors[0].metrics[0].weight", is(dtoRelationsMetric.getWeight()))); + .andExpect(jsonPath("$[0].factors[0].metrics[0].weightedValue", is(dtoRelationsMetric.getWeightedValue()))) + .andExpect(jsonPath("$[0].factors[0].metrics[0].weight", is(dtoRelationsMetric.getWeight()))) + .andExpect(jsonPath("$[0].factors[0].metrics[0].assessmentValue", is(dtoRelationsMetric.getAssessmentValue()))); // Verify mock interactions verify(strategicIndicatorsDomainController, times(1)).getQualityModel(projectExternalId, null); @@ -2592,13 +2594,15 @@ public void getQualityModelForDate() throws Exception { .andExpect(jsonPath("$[0].factors", hasSize(1))) .andExpect(jsonPath("$[0].factors[0].id", is(dtoRelationsFactor.getId()))) .andExpect(jsonPath("$[0].factors[0].name", is(dtoRelationsFactor.getName()))) - .andExpect(jsonPath("$[0].factors[0].value", is(dtoRelationsFactor.getValue()))) + .andExpect(jsonPath("$[0].factors[0].weightedValue", is(dtoRelationsFactor.getWeightedValue()))) .andExpect(jsonPath("$[0].factors[0].weight", is(dtoRelationsFactor.getWeight()))) + .andExpect(jsonPath("$[0].factors[0].assessmentValue", is(dtoRelationsFactor.getAssessmentValue()))) .andExpect(jsonPath("$[0].factors[0].metrics", hasSize(1))) .andExpect(jsonPath("$[0].factors[0].metrics[0].id", is(dtoRelationsMetric.getId()))) .andExpect(jsonPath("$[0].factors[0].metrics[0].name", is(dtoRelationsMetric.getName()))) - .andExpect(jsonPath("$[0].factors[0].metrics[0].value", is(dtoRelationsMetric.getValue()))) + .andExpect(jsonPath("$[0].factors[0].metrics[0].weightedValue", is(dtoRelationsMetric.getWeightedValue()))) .andExpect(jsonPath("$[0].factors[0].metrics[0].weight", is(dtoRelationsMetric.getWeight()))) + .andExpect(jsonPath("$[0].factors[0].metrics[0].assessmentValue", is(dtoRelationsMetric.getAssessmentValue()))) .andDo(document("si/quality-model", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()), @@ -2626,20 +2630,24 @@ public void getQualityModelForDate() throws Exception { .description("Quality factor identifier"), fieldWithPath("[].factors[].name") .description("Quality factor name"), - fieldWithPath("[].factors[].value") - .description("Quality factor value"), + fieldWithPath("[].factors[].weightedValue") + .description("Quality factor weighted value"), fieldWithPath("[].factors[].weight") .description("Quality factor weight in the strategic indicator assessment"), + fieldWithPath("[].factors[].assessmentValue") + .description("Quality factor assessment value"), fieldWithPath("[].factors[].metrics") .description("List with all the metrics composing the quality factor"), fieldWithPath("[].factors[].metrics[].id") .description("Metric identifier"), fieldWithPath("[].factors[].metrics[].name") .description("Metric name"), - fieldWithPath("[].factors[].metrics[].value") - .description("Metric value"), + fieldWithPath("[].factors[].metrics[].weightedValue") + .description("Metric weighted value"), fieldWithPath("[].factors[].metrics[].weight") - .description("Metric weight in the computation of the quality factor")) + .description("Metric weight in the computation of the quality factor"), + fieldWithPath("[].factors[].metrics[].assessmentValue") + .description("Metric assessment value")) )); // Verify mock interactions diff --git a/src/test/java/com/upc/gessi/qrapids/app/testHelpers/DomainObjectsBuilder.java b/src/test/java/com/upc/gessi/qrapids/app/testHelpers/DomainObjectsBuilder.java index f4e389c4..745d051a 100644 --- a/src/test/java/com/upc/gessi/qrapids/app/testHelpers/DomainObjectsBuilder.java +++ b/src/test/java/com/upc/gessi/qrapids/app/testHelpers/DomainObjectsBuilder.java @@ -563,7 +563,7 @@ public List buildDTORelationsSI () { String metricValue = "0.8"; String metricWeight = "1"; DTORelationsMetric dtoRelationsMetric = new DTORelationsMetric(metricId); - dtoRelationsMetric.setValue(metricValue); + dtoRelationsMetric.setWeightedValue(metricValue); dtoRelationsMetric.setWeight(metricWeight); List dtoRelationsMetricList = new ArrayList<>(); dtoRelationsMetricList.add(dtoRelationsMetric); @@ -572,7 +572,7 @@ public List buildDTORelationsSI () { String factorValue = "0.8"; String factorWeight = "1"; DTORelationsFactor dtoRelationsFactor = new DTORelationsFactor(factorId); - dtoRelationsFactor.setValue(factorValue); + dtoRelationsFactor.setWeightedValue(factorValue); dtoRelationsFactor.setWeight(factorWeight); dtoRelationsFactor.setMetrics(dtoRelationsMetricList); List dtoRelationsFactorList = new ArrayList<>(); From 9fe13be9573d1df22701e91ae6ca46281f7aa30b Mon Sep 17 00:00:00 2001 From: AlexV Date: Fri, 20 Mar 2020 13:29:40 +0100 Subject: [PATCH 8/8] Correct categories representation on DSI and Factors views --- .../resources/static/js/parseDataDetailedSICurrent.js | 11 +++-------- src/main/resources/static/js/parseDataQFCurrent.js | 3 +-- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/main/resources/static/js/parseDataDetailedSICurrent.js b/src/main/resources/static/js/parseDataDetailedSICurrent.js index a7c50fdc..0bdc39ab 100644 --- a/src/main/resources/static/js/parseDataDetailedSICurrent.js +++ b/src/main/resources/static/js/parseDataDetailedSICurrent.js @@ -90,21 +90,16 @@ function getData() { function getCategories() { var serverUrl = sessionStorage.getItem("serverUrl"); - var url = "/api/strategicIndicators/categories"; + var url = "/api/qualityFactors/categories"; if (serverUrl) { url = serverUrl + url; } $.getJSON(url).then (function(cat) { - categories.push({ - name: cat[0].name, // high category - color: cat[0].color, - upperThreshold: 1, - }); - for (var i = 1; i < cat.length; i++) { + for (var i = 0; i < cat.length; i++) { categories.push({ name: cat[i].name, color: cat[i].color, - upperThreshold: categories[i-1].upperThreshold - 1/cat.length, + upperThreshold: cat[i].upperThreshold, }); } console.log(categories); diff --git a/src/main/resources/static/js/parseDataQFCurrent.js b/src/main/resources/static/js/parseDataQFCurrent.js index 5a47eda0..e8b086e8 100644 --- a/src/main/resources/static/js/parseDataQFCurrent.js +++ b/src/main/resources/static/js/parseDataQFCurrent.js @@ -57,13 +57,12 @@ function getData() { function getCategories() { var serverUrl = sessionStorage.getItem("serverUrl"); - var url = "/api/qualityFactors/categories"; + var url = "/api/metrics/categories"; if (serverUrl) { url = serverUrl + url; } $.getJSON(url).then (function(cat) { for (var i = 0; i < cat.length; i++) { - //categories = cat; categories.push({ name: cat[i].name, color: cat[i].color,