From 3311350600b4d8eb51c937b823f370cb21cba915 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Tue, 9 Jul 2019 11:39:34 +0200 Subject: [PATCH] Work on #236 for PAB --- src/app/components/log/log.component.ts | 12 +- .../pab-results-table.component.ts | 2 +- .../pab-results/pab-results.component.html | 6 +- .../pab-results/pab-results.component.ts | 123 +++++++++++++++--- src/app/results/pab-results.ts | 50 +++++-- src/locale/messages.en.json | 7 +- src/locale/messages.fr.json | 7 +- 7 files changed, 166 insertions(+), 41 deletions(-) diff --git a/src/app/components/log/log.component.ts b/src/app/components/log/log.component.ts index 6ab788350..c84de0364 100644 --- a/src/app/components/log/log.component.ts +++ b/src/app/components/log/log.component.ts @@ -1,4 +1,4 @@ -import { Component } from "@angular/core"; +import { Component, Input } from "@angular/core"; import { cLog, Message } from "jalhyd"; @@ -17,12 +17,20 @@ export class LogComponent { */ private _log: cLog; + // title to display above the log + @Input() + public logTitle: string; + constructor( private intlService: I18nService, ) { } private get uitextTitreJournal() { - return this.intlService.localizeText("INFO_TITREJOURNAL"); + if (this.logTitle) { + return this.logTitle; + } else { + return this.intlService.localizeText("INFO_TITREJOURNAL"); + } } public get hasEntries(): boolean { diff --git a/src/app/components/pab-results/pab-results-table.component.ts b/src/app/components/pab-results/pab-results-table.component.ts index ed15acd8b..b5b202e67 100644 --- a/src/app/components/pab-results/pab-results-table.component.ts +++ b/src/app/components/pab-results/pab-results-table.component.ts @@ -44,7 +44,7 @@ export class PabResultsTableComponent extends ResultsComponent { this._pabResults && this._pabResults.cloisonsResults && this._pabResults.cloisonsResults.length > 0 - && ! this._pabResults.hasError() + && ! this._pabResults.hasOnlyErrors() ) { const pr = this._pabResults; const nDigits = this.appSetupService.displayDigits; diff --git a/src/app/components/pab-results/pab-results.component.html b/src/app/components/pab-results/pab-results.component.html index 083ed5a54..6f8a67cb0 100644 --- a/src/app/components/pab-results/pab-results.component.html +++ b/src/app/components/pab-results/pab-results.component.html @@ -1,8 +1,11 @@ <div class="container"> + + <log #generalLog [logTitle]="uitextGeneralLogTitle">log général</log> + <pab-variable-results-selector [results]="pabResults" (indexChange)="variableIndexChanged()"> </pab-variable-results-selector> - <log></log> + <log #iterationLog></log> <div> <!-- tableau de résultats --> @@ -10,4 +13,5 @@ </div> <results-graph *ngIf="hasResults"></results-graph> + </div> diff --git a/src/app/components/pab-results/pab-results.component.ts b/src/app/components/pab-results/pab-results.component.ts index 975c769d9..a0c5e16ab 100644 --- a/src/app/components/pab-results/pab-results.component.ts +++ b/src/app/components/pab-results/pab-results.component.ts @@ -1,6 +1,6 @@ import { Component, ViewChild, DoCheck } from "@angular/core"; -import { Result, cLog } from "jalhyd"; +import { Result, cLog, MessageSeverity, Message, MessageCode } from "jalhyd"; import { LogComponent } from "../../components/log/log.component"; import { CalculatorResults } from "../../results/calculator-results"; @@ -12,6 +12,7 @@ import { PabVariableResultsSelectorComponent } from "./pab-variable-results-sele import { PlottableData } from "../../results/plottable-data"; import { PlottablePabResults } from "../../results/plottable-pab-results"; import { ResultsGraphComponent } from "../results-graph/results-graph.component"; +import { I18nService } from "../../services/internationalisation/internationalisation.service"; @Component({ selector: "pab-results", @@ -37,14 +38,18 @@ export class PabResultsComponent implements DoCheck { @ViewChild(PabVariableResultsSelectorComponent) private pabVariableResultsSelectorComponent: PabVariableResultsSelectorComponent; - @ViewChild(LogComponent) - private logComponent: LogComponent; + @ViewChild("generalLog") + private generalLogComponent: LogComponent; + + @ViewChild("iterationLog") + private iterationLogComponent: LogComponent; @ViewChild(ResultsGraphComponent) private resultsGraphComponent: ResultsGraphComponent; constructor( private appSetupService: ApplicationSetupService, + private i18nService: I18nService, ) { this._plottableResults = new PlottablePabResults(); } @@ -67,7 +72,8 @@ export class PabResultsComponent implements DoCheck { } public updateView() { - this.logComponent.log = undefined; + this.iterationLogComponent.log = undefined; + this.generalLogComponent.log = undefined; if (this.pabResultsTableComponent) { this.pabResultsTableComponent.results = undefined; } @@ -90,31 +96,100 @@ export class PabResultsComponent implements DoCheck { } } - private mergeLog(result: Result, log: cLog) { - if (result && result.hasLog) { + private mergeGlobalLog(result: Result, log: cLog) { + if (result) { if (result.hasGlobalLog) { log.addLog(result.globalLog); - } else { - // add every ResultElement log - for (const re of result.resultElements) { - log.addLog(re.log); + } + // if no parameter is varying, 1st element log is considered "global" + if (this.pabResults.variatedParameters.length === 0) { + if (result.hasResultElements && result.resultElement.hasLog) { + log.addLog(result.log); } } } } - private get mergedGlobalLogs(): cLog { - const res = new cLog(); + /** + * Retourne true si au moins une des cloisons a un message de log dans + * un de ses ResultElement + */ + private childrenHaveLogs(): boolean { + for (const cr of this._pabResults.cloisonsResults) { + if (cr && cr.hasLog) { + return true; + } + } + if (this._pabResults.cloisonAvalResults && this._pabResults.cloisonAvalResults.hasLog) { + return true; + } + return false; + } + + /* + * Retourne les logs à afficher dans le composant de log global, au dessus + * du sélecteur d'itération : messages globaux et / ou résumé des messages + * spécifiques à chaque ResultElement + */ + private get globalLog(): cLog { + const l = new cLog(); + if (this._pabResults && this.pabResults.variatedParameters.length > 0) { + this.mergeGlobalLog(this._pabResults.result, l); + // un problème avec la PAB en général / les cloisons, à une étape quelconque ? + if ( + (this.pabResults.hasLog || this.childrenHaveLogs()) + && l.messages.length === 0 // existing global messages make generic message below useless + ) { + l.add(new Message(MessageCode.WARNING_PROBLEMS_ENCOUNTERED)); + } + } // sinon pas de log global (aucun paramètre ne varie) + return l; + } + + /** + * Retourne les logs à afficher dans le composant de log global, au dessus + * du sélecteur d'itération : messages globaux et / ou résumé des messages + * spécifiques à chaque ResultElement + */ + private get iterationLog(): cLog { + const l = new cLog(); if (this._pabResults) { - this.mergeLog(this._pabResults.result, res); - // log des cloisons - for (const c of this._pabResults.cloisonsResults) { - this.mergeLog(c, res); + if (this.pabResults.variatedParameters.length > 0) { + // A. si un paramètre varie + const vi = this._pabResults.variableIndex; + // log de la PAB pour l'itération en cours + if ( + this._pabResults.result + && this._pabResults.result.hasResultElements + && this._pabResults.result.resultElements[vi] + && this._pabResults.result.resultElements[vi].hasLog + ) { + l.addLog(this._pabResults.result.resultElements[vi].log); + } + // logs des enfants pour l'itération en cours + for (const cr of this._pabResults.cloisonsResults) { + if (cr && cr.hasResultElements && cr.resultElements[vi].hasLog) { + l.addLog(cr.resultElements[vi].log); + } + } + if (this._pabResults.cloisonAvalResults && this._pabResults.cloisonAvalResults.resultElements[vi].hasLog) { + l.addLog(this._pabResults.cloisonAvalResults.resultElements[vi].log); + } + } else { + // B. si aucun paramètre ne varie + this.mergeGlobalLog(this._pabResults.result, l); // faut bien mettre le log global quelque part + // logs des enfants + for (const cr of this._pabResults.cloisonsResults) { + if (cr && cr.hasResultElements && cr.resultElement.hasLog) { + l.addLog(cr.resultElement.log); + } + } + if (this._pabResults.cloisonAvalResults && this._pabResults.cloisonAvalResults.resultElement.hasLog) { + l.addLog(this._pabResults.cloisonAvalResults.resultElement.log); + } } - // log de la cloison aval - this.mergeLog(this._pabResults.cloisonAvalResults, res); } - return res; + return l; } /** @@ -126,9 +201,11 @@ export class PabResultsComponent implements DoCheck { let graphUpdated: boolean; // results or not, there might be a log - const logUpdated = this.logComponent !== undefined; + const logUpdated = (this.iterationLogComponent !== undefined || this.generalLogComponent !== undefined); // gne ? if (logUpdated) { - this.logComponent.log = this.mergedGlobalLogs; + // order of logs is important ! + this.iterationLogComponent.log = this.iterationLog; + this.generalLogComponent.log = this.globalLog; } if (this.hasResults) { @@ -167,6 +244,10 @@ export class PabResultsComponent implements DoCheck { return this._pabResults && this._pabResults.hasResults; } + public get uitextGeneralLogTitle(): string { + return this.i18nService.localizeText("INFO_TITREJOURNAL_GLOBAL"); + } + /** builds a set of PlottableData from PabResults, to feed the graph */ protected get plottableResults(): PlottableData { this._plottableResults.setPabResults(this.pabResults); diff --git a/src/app/results/pab-results.ts b/src/app/results/pab-results.ts index a14311da3..480902606 100644 --- a/src/app/results/pab-results.ts +++ b/src/app/results/pab-results.ts @@ -44,20 +44,6 @@ export class PabResults extends CalculatedParamResults { ]; } - public get hasLog(): boolean { - if (this.cloisonsResults) { - for (const cr of this.cloisonsResults) { - if (cr && cr.hasLog) { - return true; - } - } - } - return ( - (this.result && this.result.hasLog) - || (this.cloisonAvalResults && this.cloisonAvalResults.hasLog) - ); - } - /** headers symbols */ public get columns() { return this._columns; @@ -83,6 +69,27 @@ export class PabResults extends CalculatedParamResults { this.Z2 = []; } + // returns true if at least one log message is present in the PAB result or any + // of the children result + public get hasLog(): boolean { + if (this.cloisonsResults) { + for (const cr of this.cloisonsResults) { + if (cr && cr.hasLog) { + return true; + } + } + } + return ( + (this.result && this.result.hasLog) + || (this.cloisonAvalResults && this.cloisonAvalResults.hasLog) + ); + } + + // do not test result.ok else log messages will prevent partial results from being displayed + public get hasResults(): boolean { + return this.result !== undefined && ! this.result.hasOnlyErrors; + } + /** retourne true si au moins un calcul a échoué (le log a un code négatif) */ public hasError(): boolean { let err = false; @@ -97,4 +104,19 @@ export class PabResults extends CalculatedParamResults { return err; } + + /** retourne true si tous les calculs ont échoué */ + public hasOnlyErrors(): boolean { + let err = true; + // log principal + err = (err && this.result.hasOnlyErrors); + // logs des cloisons + for (const c of this.cloisonsResults) { + err = (err && c.hasOnlyErrors); + } + // log de la cloison aval + err = (err && this.cloisonAvalResults.hasOnlyErrors); + + return err; + } } diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json index 8073f20da..877e04d65 100644 --- a/src/locale/messages.en.json +++ b/src/locale/messages.en.json @@ -42,6 +42,7 @@ "ERROR_SECTION_NON_CONVERGENCE_NEWTON_HTOR": "Non convergence of the calculation of the corresponding height (Newton's method) for the calculation of the supercritical depth", "ERROR_SECTION_PENTE_NEG_NULLE_HNORMALE_INF": "The slope is negative or zero, the normal depth is infinite", "ERROR_STRUCTURE_Q_TROP_ELEVE": "The flow passing through the other devices is too high: the requested parameter is not calculable.", + "ERROR_Z1_LOWER_THAN_Z2": "Upstream elevation is lower than downstream elevation", "INFO_CALCULATOR_CALC_NAME": "Calculator name", "INFO_CALCULATOR_CALCULER": "Compute", "INFO_CALCULATOR_PARAMFIXES": "Fixed parameters", @@ -290,6 +291,7 @@ "INFO_PARAMFIELD_VARIATED": "Variated", "INFO_PARAMMODE_LIST": "Values list", "INFO_PARAMMODE_MINMAX": "Min/max", + "WARNING_PROBLEMS_ENCOUNTERED": "Problems occurred during calculation", "INFO_REGIMEUNIFORME_TITRE_COURT": "Uniform flow", "INFO_REGIMEUNIFORME_TITRE": "Uniform flow calculation", "INFO_REMOUS_CALCUL_FLUVIAL": "Downstream boundary condition >= Critical elevation: calculation of subcritical part from downstream", @@ -334,9 +336,12 @@ "INFO_THEME_PASSE_NATURELLE_DESCRIPTION": "Tools for sizing a natural fish pass also called macroroughness pass or rock-ramp fish pass", "INFO_THEME_PASSE_NATURELLE_TITRE": "Natural pass", "INFO_TITREJOURNAL": "Calculation log", + "INFO_TITREJOURNAL_GLOBAL": "Calculation log synthesis", "INFO_WELCOME_CONTENT": "<p>The Cassiopée software was developed by <a href=\"https://www.afbiodiversite.fr\" target=\"_blank\">AFB</a> (French Agency for Biodiversity) and <a href=\"http://g-eau.fr/index.php/en/\" target=\"_blank\">UMR G-EAU</a> (Joint Research Unit \"Water Management, Actors, Territories\").</p><p>It includes tools for designing fish passes, and hydraulic calculation tools useful for environmental and agricultural engineering.</p><p>For more information, consult <a href=\"assets/docs-fr/mentions_legales.html\" target=\"_blank\">legal notice</a> and <a href=\"assets/docs-fr/index.html\" target=\"_blank\">documentation</a>.</p>", "INFO_WELCOME_SUBTITLE": "Hydraulic calculators", "WARNING_REMOUS_ARRET_CRITIQUE": "Calculation stopped: critical elevation reached at abscissa %x%", "WARNING_STRUCTUREKIVI_HP_TROP_ELEVE": "h/p must not be greater than 2.5. h/p is forced to 2.5", - "WARNING_STRUCTUREKIVI_PELLE_TROP_FAIBLE": "Threshold height should be greater than 0.1 m. Beta coefficient is forced to 0" + "WARNING_STRUCTUREKIVI_PELLE_TROP_FAIBLE": "Threshold height should be greater than 0.1 m. Beta coefficient is forced to 0", + "WARNING_VANLEV_ZDV_INF_MIN": "Regulated weir: minimum sill elevation reached", + "WARNING_VANLEV_ZDV_SUP_MAX": "Regulated weir: maximum sill elevation reached" } diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json index 2a210aadd..ce4263946 100644 --- a/src/locale/messages.fr.json +++ b/src/locale/messages.fr.json @@ -42,6 +42,7 @@ "ERROR_SECTION_NON_CONVERGENCE_NEWTON_HTOR": "Non convergence du calcul de la hauteur correspondante (Méthode de Newton) pour le calcul de la hauteur torrentielle", "ERROR_SECTION_PENTE_NEG_NULLE_HNORMALE_INF": "La pente est négative ou nulle, la hauteur normale est infinie", "ERROR_STRUCTURE_Q_TROP_ELEVE": "Le débit passant par les autres ouvrages est trop élevé: le paramètre demandé n'est pas calculable.", + "ERROR_Z1_LOWER_THAN_Z2": "La cote amont est plus basse que la cote aval", "INFO_CALCULATOR_CALC_NAME": "Nom du module de calcul", "INFO_CALCULATOR_CALCULER": "Calculer", "INFO_CALCULATOR_PARAMFIXES": "Paramètres fixés", @@ -290,6 +291,7 @@ "INFO_PARAMFIELD_VARIATED": "Varié", "INFO_PARAMMODE_LIST": "Liste de valeurs", "INFO_PARAMMODE_MINMAX": "Min/max", + "WARNING_PROBLEMS_ENCOUNTERED": "Des problèmes sont survenus durant le calcul", "INFO_REGIMEUNIFORME_TITRE_COURT": "R. uniforme", "INFO_REGIMEUNIFORME_TITRE": "Régime uniforme", "INFO_REMOUS_CALCUL_FLUVIAL": "Condition limite aval >= Hauteur critique : calcul de la partie fluviale à partir de l'aval", @@ -334,9 +336,12 @@ "INFO_THEME_PASSE_NATURELLE_DESCRIPTION": "Outils de dimensionnement d'une passe à poissons de type passe naturelle ou encore appelée passe à macro-rugosités", "INFO_THEME_PASSE_NATURELLE_TITRE": "Passe naturelle", "INFO_TITREJOURNAL": "Journal de calcul", + "INFO_TITREJOURNAL_GLOBAL": "Synthèse du journal de calcul", "INFO_WELCOME_CONTENT": "<p>Le logiciel Cassiopée a été développé par l'<a href=\"https://www.afbiodiversite.fr\" target=\"_blank\">AFB</a> (Agence Française pour la Biodiversité) et <a href=\"http://g-eau.fr\" target=\"_blank\">L'UMR G-EAU</a> (UMR Gestion de l'Eau, Acteurs, Usages).</p><p>Il regroupe des outils d'aide à la conception de passes à poissons et des outils de calcul hydraulique utiles pour l'ingénierie en environnement et agriculture.</p><p>Pour plus d'informations, consulter les <a href=\"assets/docs-fr/mentions_legales.html\" target=\"_blank\">mentions légales</a> et la <a href=\"assets/docs-fr/index.html\" target=\"_blank\">documentation</a>.</p>", "INFO_WELCOME_SUBTITLE": "Modules de calcul d'hydraulique", "WARNING_REMOUS_ARRET_CRITIQUE": "Arrêt du calcul : hauteur critique atteinte à l'abscisse %x%", "WARNING_STRUCTUREKIVI_HP_TROP_ELEVE": "h/p ne doit pas être supérieur à 2,5. h/p est forcé à 2,5", - "WARNING_STRUCTUREKIVI_PELLE_TROP_FAIBLE": "La pelle du seuil doit mesurer au moins 0,1 m. Le coefficient béta est forcé à 0" + "WARNING_STRUCTUREKIVI_PELLE_TROP_FAIBLE": "La pelle du seuil doit mesurer au moins 0,1 m. Le coefficient béta est forcé à 0", + "WARNING_VANLEV_ZDV_INF_MIN": "Seuil régulé : cote minimale de seuil atteinte", + "WARNING_VANLEV_ZDV_SUP_MAX": "Seuil régulé : cote maximale de seuil atteinte" } -- GitLab