diff --git a/src/app/app.module.ts b/src/app/app.module.ts index a6f375b494be9832db1f7c25fb32ef0575dfb14f..d9b61bed6e1086d8213e51c8fdd84c28d175303f 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -74,6 +74,8 @@ import { ResultsChartComponent } from "./components/results-chart/results-chart. import { PabResultsComponent } from "./components/pab-results/pab-results.component"; import { VerificateurResultsComponent } from "./components/verificateur-results/verificateur-results.component"; import { PabResultsTableComponent } from "./components/pab-results/pab-results-table.component"; +import { PbResultsComponent } from "./components/pb-results/pb-results.component"; +import { PbResultsTableComponent } from "./components/pb-results/pb-results-table.component"; import { ChartTypeSelectComponent } from "./components/results-chart/chart-type.component"; import { CalculatorListComponent } from "./components/calculator-list/calculator-list.component"; import { ApplicationSetupComponent } from "./components/app-setup/app-setup.component"; @@ -224,6 +226,8 @@ const appRoutes: Routes = [ PabResultsComponent, PabResultsTableComponent, PabTableComponent, + PbResultsComponent, + PbResultsTableComponent, PbSchemaComponent, VariableResultsSelectorComponent, MacrorugoCompoundResultsComponent, diff --git a/src/app/calculators/prebarrage/fr.json b/src/app/calculators/prebarrage/fr.json index 287b7935274a233f039fdeda648f01deb7262e12..7b3f06d22fed9d55444f5741c2338c9896482d8c 100644 --- a/src/app/calculators/prebarrage/fr.json +++ b/src/app/calculators/prebarrage/fr.json @@ -3,5 +3,18 @@ "Q": "Débit", "Z1": "Cote de l'eau amont", - "Z2": "Cote de l'eau aval" + "Z2": "Cote de l'eau aval", + + "Z": "Cote de l'eau", + "S": "Surface", + "ZF": "Cote de fond", + "PV": "Puissance dissipée", + "YMOY": "Profondeur moyenne", + + "UNIT_Q": "m³/s", + "UNIT_S": "m²", + "UNIT_Z": "m", + "UNIT_ZF": "m", + "UNIT_YMOY": "m", + "UNIT_PV": "W/m³" } diff --git a/src/app/components/calculator-results/calculator-results.component.html b/src/app/components/calculator-results/calculator-results.component.html index 319b3eab39c1483dc3b8c646ce2e2c7e040d63be..4befd3308c7879d86644375226764181d321f72f 100644 --- a/src/app/components/calculator-results/calculator-results.component.html +++ b/src/app/components/calculator-results/calculator-results.component.html @@ -2,6 +2,7 @@ <section-results [hidden]="! isSP"></section-results> <remous-results [hidden]="! isRemous"></remous-results> <pab-results [hidden]="! isPAB"></pab-results> + <pb-results [hidden]="! isPB"></pb-results> <verificateur-results [hidden]="! isVerificateur"></verificateur-results> <macrorugo-compound-results [hidden]="! isMRC"></macrorugo-compound-results> <jet-results [hidden]="! isJet"></jet-results> diff --git a/src/app/components/calculator-results/calculator-results.component.ts b/src/app/components/calculator-results/calculator-results.component.ts index 900cf877a848c0e0385faf2cacf504334afc7e6a..c8c6b712f80a02f8470c9636b2dc53e87d9c312f 100644 --- a/src/app/components/calculator-results/calculator-results.component.ts +++ b/src/app/components/calculator-results/calculator-results.component.ts @@ -11,6 +11,7 @@ import { GenericCalculatorComponent } from "../generic-calculator/calculator.com import { VerificateurResultsComponent } from "../verificateur-results/verificateur-results.component"; import { CalculatorType } from "jalhyd"; +import { PbResultsComponent } from "../pb-results/pb-results.component"; @Component({ selector: "calc-results", @@ -50,6 +51,12 @@ export class CalculatorResultsComponent implements AfterViewChecked { @ViewChild(VerificateurResultsComponent, { static: true }) private verificateurResultsComponent: VerificateurResultsComponent; + /* + * composant d'affichage des résultats des prébarrages + */ + @ViewChild(PbResultsComponent, { static: true }) + private pbResultsComponent: PbResultsComponent; + /** * composant d'affichage des résultats des passes à macrorugosités complexes */ @@ -77,31 +84,38 @@ export class CalculatorResultsComponent implements AfterViewChecked { this._formulaire = f; if (this._formulaire === undefined) { this.fixedVarResultsComponent.results = undefined; + this.sectionResultsComponent.results = undefined; + this.pbResultsComponent.results = undefined; this.jetResultsComponent.results = undefined; this.mrcResultsComponent.results = undefined; this.pabResultsComponent.results = undefined; this.remousResultsComponent.results = undefined; - this.sectionResultsComponent.results = undefined; this.verificateurResultsComponent.results = undefined; } else { - if (this.showGenericResults) { this.fixedVarResultsComponent.results = f.results; } - if (this.isJet) { this.jetResultsComponent.results = f.results; } - if (this.isMRC) { this.mrcResultsComponent.results = f.results; } - if (this.isPAB) { this.pabResultsComponent.results = f.results; } - if (this.isRemous) { this.remousResultsComponent.results = f.results; } - if (this.isSP) { this.sectionResultsComponent.results = f.results; } - if (this.isVerificateur) { this.verificateurResultsComponent.results = f.results; } + this.sectionResultsComponent.results = f.results; + this.remousResultsComponent.results = f.results; + this.pabResultsComponent.results = f.results; + this.pbResultsComponent.results = f.results; + this.mrcResultsComponent.results = f.results; + // FixedVar and Jet are mutually incompatible (the 2nd extend the 1st) + if (this.isJet) { + this.jetResultsComponent.results = f.results; + this.fixedVarResultsComponent.results = undefined; + } else { + this.fixedVarResultsComponent.results = f.results; + this.jetResultsComponent.results = undefined; + } } } public updateView() { - if (this.showGenericResults) { this.fixedVarResultsComponent.updateView(); } - if (this.isJet) { this.jetResultsComponent.updateView(); } - if (this.isMRC) { this.mrcResultsComponent.updateView(); } - if (this.isPAB) { this.pabResultsComponent.updateView(); } - if (this.isRemous) { this.remousResultsComponent.updateView(); } - if (this.isSP) { this.sectionResultsComponent.updateView(); } - if (this.isVerificateur) { this.verificateurResultsComponent.updateView(); } + this.fixedVarResultsComponent.updateView(); + this.sectionResultsComponent.updateView(); + this.remousResultsComponent.updateView(); + this.pabResultsComponent.updateView(); + this.pbResultsComponent.updateView(); + this.mrcResultsComponent.updateView(); + this.jetResultsComponent.updateView(); } public ngAfterViewChecked() { diff --git a/src/app/components/fixedvar-results/fixed-results.component.html b/src/app/components/fixedvar-results/fixed-results.component.html index d9bca96253f0a62db118c20b9cf88b8dd74cd0e9..849bf9d4ecce8f749b0ac8d2d8a84ffc5c8f1be5 100644 --- a/src/app/components/fixedvar-results/fixed-results.component.html +++ b/src/app/components/fixedvar-results/fixed-results.component.html @@ -5,7 +5,6 @@ <mat-icon color="primary">file_download</mat-icon> </button> </div> - <!-- table des résultats fixés --> <div class="fixed-results-inner-container" #tableContainer> <table mat-table [dataSource]="dataSet" [trackBy]="tbIndex"> diff --git a/src/app/components/fixedvar-results/fixed-results.component.ts b/src/app/components/fixedvar-results/fixed-results.component.ts index 32660b36862b5b0c3650fc5b133a0be1535743fd..004c46c9cd7eb69fb9f9a9025fb14080cc9d838e 100644 --- a/src/app/components/fixedvar-results/fixed-results.component.ts +++ b/src/app/components/fixedvar-results/fixed-results.component.ts @@ -36,6 +36,7 @@ export class FixedResultsComponent extends ResultsComponentDirective { } public set results(r: FixedResults) { + console.log("->->->->-> je suis FRC et j'ai reçu des résultats", r === undefined ? "keud" : r.result); this._fixedResults = r; } diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts index 9c26baa5d1741d5eea9dc47bf4bd8ee4e973fcee..6c2119744534d4e97d5b5515137daab44e50fe3d 100644 --- a/src/app/components/generic-calculator/calculator.component.ts +++ b/src/app/components/generic-calculator/calculator.component.ts @@ -590,9 +590,11 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe /** réception d'un événement de clic sur un nœud du schéma de PréBarrage */ public onPBNodeSelected(event: any) { - this.showPBInputData = true; // @TODO pas forcément ! (résultats de l'élément cliqué) - // show proper form (actually subform elements) depending on what was clicked + // show proper form (actually subform elements) or proper results, + // depending on what was clicked (this._formulaire as FormulairePrebarrage).nodeSelected(event.node); + // refresh results component + this.resultsComponent.updateView(); } public openHelp() { diff --git a/src/app/components/pb-results/pb-results-table.component.html b/src/app/components/pb-results/pb-results-table.component.html new file mode 100644 index 0000000000000000000000000000000000000000..75f0451ffc692eaf760d382fc2f1f57d05be633a --- /dev/null +++ b/src/app/components/pb-results/pb-results-table.component.html @@ -0,0 +1,30 @@ +<div class="pb-results-table-container" #pbResultsTable fxLayout="row wrap" fxLayoutAlign="center center"> + <div fxFlex="1 1 100%"> + <div class="pb-results-table-buttons"> + <button mat-icon-button (click)="exportAsSpreadsheet()" [title]="uitextExportAsSpreadsheet"> + <mat-icon color="primary">file_download</mat-icon> + </button> + <button mat-icon-button *ngIf="! isFullscreen" (click)="setFullscreen(pbResultsTable)" [title]="uitextEnterFSTitle"> + <mat-icon color="primary" class="scaled12">fullscreen</mat-icon> + </button> + <button mat-icon-button *ngIf="isFullscreen" (click)="exitFullscreen()" [title]="uitextExitFSTitle"> + <mat-icon color="primary" class="scaled12">fullscreen_exit</mat-icon> + </button> + </div> + + <div class="pb-results-table-scrollable-container" [ngClass]="{'full-height': isFullscreen}"> + <!-- scrollable --> + <div class="pb-results-table-inner-container" #tableContainer> + <table mat-table [dataSource]="dataSet"> + <ng-container *ngFor="let h of headers; let i = index" [matColumnDef]="h"> + <th mat-header-cell *matHeaderCellDef [innerHTML]="h"></th> + <td mat-cell *matCellDef="let element" [innerHTML]="element[i]"></td> + </ng-container> + + <tr mat-header-row *matHeaderRowDef="headers"></tr> + <tr mat-row *matRowDef="let row; columns: headers;"></tr> + </table> + </div> + </div> + </div> +</div> diff --git a/src/app/components/pb-results/pb-results-table.component.scss b/src/app/components/pb-results/pb-results-table.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..9e49c5ca0d3a6dc21ed1e49e943311bff2a49307 --- /dev/null +++ b/src/app/components/pb-results/pb-results-table.component.scss @@ -0,0 +1,52 @@ +/** @see additional styles in src/styles.css */ + +:host { + display: block; + margin-bottom: 1.5em; +} + +.pb-results-table-container { + background-color: white; +} + +.pb-results-table-buttons { + padding-right: 4px; + padding-top: 4px; + text-align: right; + background-color: white; + + button { + margin-left: 3px; + width: auto; + + mat-icon { + &.scaled12 { + transform: scale(1.2) + } + } + } +} + +.pb-results-table-scrollable-container { + overflow-x: scroll; + border: solid #ccc 1px; + + &.full-height { + height: calc(100vh - 40px); // rend le mode plein-écran scrollable verticalement, sinon ça dépasse + } +} + +table.mat-table { + + .mat-header-row { + height: 40px; + } + + .mat-row { + height: 32px; + + &:nth-child(odd) { + background-color: #f4f4f4; + } + } +} diff --git a/src/app/components/pb-results/pb-results-table.component.ts b/src/app/components/pb-results/pb-results-table.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..b1ab9838b5fec90c1c89405d38f302397c347412 --- /dev/null +++ b/src/app/components/pb-results/pb-results-table.component.ts @@ -0,0 +1,143 @@ +import { Component, ViewChild, ElementRef } from "@angular/core"; + +import { PreBarrage, PbBassin } from "jalhyd"; + +import { I18nService } from "../../services/internationalisation.service"; +import { ResultsComponentDirective } from "../fixedvar-results/results.component"; +import { AppComponent } from "../../app.component"; +import { fv } from "../../util"; +import { PrebarrageResults } from "../../results/prebarrage-results"; + +@Component({ + selector: "pb-results-table", + templateUrl: "./pb-results-table.component.html", + styleUrls: [ + "./pb-results-table.component.scss" + ] +}) +export class PbResultsTableComponent extends ResultsComponentDirective { + + /** résultats non mis en forme */ + private _pbResults: PrebarrageResults; + + /** entêtes des colonnes */ + private _headers: string[]; + + /** résultats mis en forme */ + private _dataSet: any[]; + + @ViewChild("tableContainer") + table: ElementRef; + + constructor( + protected intlService: I18nService + ) { + super(); + } + + /* private getJetTypes(re: Result, vi: number): string { + // jet type for each device + const devices = re.sourceNub.getChildren(); + const jetTypes: string[] = devices.map((device) => { + const jt = device.result.resultElements[vi].getValue("ENUM_StructureJetType"); + let jetType = this.intlService.localizeText("INFO_ENUM_STRUCTUREJETTYPE_" + jt); + if (devices.length > 1) { + // evil HTML injection in table cell (simpler) + jetType = this.intlService.localizeText("INFO_LIB_FS_OUVRAGE") + " n°" + + (device.findPositionInParent() + 1) + ": " + jetType; + } + return jetType; + }); + return `<div class="inner-cell-line">` + jetTypes.join(`, </div><div class="inner-cell-line">`) + `</div>`; + } */ + + public set results(r: PrebarrageResults) { + this._pbResults = r; + console.log("Set results dans PBRTC !", r); + + this._dataSet = []; + if ( + this._pbResults + && this._pbResults.bassinsResults + && this._pbResults.bassinsResults.length > 0 + && ! this._pbResults.hasOnlyErrors() + ) { + const pr = this._pbResults; + const pb = pr.result.sourceNub as PreBarrage; + // when a parameter is variating, index of the variating parameter + // values to build the data from + const vi = pr.variableIndex; + + // refresh headers here if language changed + this._headers = pr.headers; + + // upstream line + if (pr.result.resultElements[vi].vCalc) { // le calcul peut avoir échoué + this._dataSet.push([ + this.intlService.localizeText("INFO_LIB_AMONT"), + "", "", + fv(pb.prms.Z1.V), + "", "", + fv(pb.prms.Q.V) + ]); + } + + // basins 1 - n + for (let i = 0; i < pr.bassinsResults.length; i++) { + if ( + Object.keys(pr.bassinsResults[i].resultElements[vi].values).length > 0 // no vCalc in this case + ) { + const rb = pr.bassinsResults[i].resultElements[vi].values; + const basin = pr.bassinsResults[i].sourceNub as PbBassin; + this._dataSet.push([ + i + 1, // n° cloison + fv(basin.prms.S.V), + fv(basin.prms.ZF.V), + fv(rb.Z), + fv(rb.PV), + fv(rb.YMOY), + fv(rb.Q) + ]); + } + } + + // downstream line + if (pr.result.resultElements[vi].vCalc) { // le calcul peut avoir échoué + this._dataSet.push([ + this.intlService.localizeText("INFO_LIB_AVAL"), + "", "", + fv(pb.prms.Z2.V), + "", "", + fv(pb.prms.Q.V) + ]); + } + } + } + + public get headers() { + return this._headers; + } + + /** + * Returns a combination of parameters and results for mat-table + */ + public get dataSet() { + return this._dataSet; + } + + public exportAsSpreadsheet() { + AppComponent.exportAsSpreadsheet(this.table.nativeElement); + } + + public get uitextExportAsSpreadsheet() { + return this.intlService.localizeText("INFO_RESULTS_EXPORT_AS_SPREADSHEET"); + } + + public get uitextEnterFSTitle() { + return this.intlService.localizeText("INFO_CHART_BUTTON_TITLE_ENTER_FS"); + } + + public get uitextExitFSTitle() { + return this.intlService.localizeText("INFO_CHART_BUTTON_TITLE_EXIT_FS"); + } +} diff --git a/src/app/components/pb-results/pb-results.component.html b/src/app/components/pb-results/pb-results.component.html new file mode 100644 index 0000000000000000000000000000000000000000..db8aa6d9152b0e1d58fb4be0db0e0f0c3edd7e9c --- /dev/null +++ b/src/app/components/pb-results/pb-results.component.html @@ -0,0 +1,23 @@ +<div class="container"> + + <log #generalLog [logTitle]="uitextGeneralLogTitle">log général</log> + + <variable-results-selector [results]="pbResults" (indexChange)="variableIndexChanged()"> + </variable-results-selector> + + <log #iterationLog></log> + + <!-- tableau de résultats des bassins --> + <pb-results-table *ngIf="showBasinsResults" [results]="pbResults"></pb-results-table> + + <!-- <quicknav *ngIf="hasDisplayableResults" [items]="[ 'input', 'results', 'charts' ]" + [currentItem]="'charts'" [align]="'left'"></quicknav> --> + + <!-- <div id="pb-graphs-container" class="container" fxLayout="row wrap" fxLayoutAlign="space-around start"> + <pb-profile-chart *ngIf="hasDisplayableResults" fxFlex.gt-xs="1 0 400px" fxFlex.lt-sm="1 0 300px"> + </pb-profile-chart> + <results-chart *ngIf="hasDisplayableResults" fxFlex.gt-xs="1 0 400px" fxFlex.lt-sm="1 0 300px"> + </results-chart> + </div> --> + +</div> diff --git a/src/app/components/pb-results/pb-results.component.scss b/src/app/components/pb-results/pb-results.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..446313ba6da367fde3da7c3b760e39086f71a804 --- /dev/null +++ b/src/app/components/pb-results/pb-results.component.scss @@ -0,0 +1,4 @@ +results-chart { + margin-left: 1em; + margin-right: 1em; +} diff --git a/src/app/components/pb-results/pb-results.component.ts b/src/app/components/pb-results/pb-results.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..5a031da132bb4735afc5ab0ab5762d075021e84e --- /dev/null +++ b/src/app/components/pb-results/pb-results.component.ts @@ -0,0 +1,324 @@ +import { Component, ViewChild, DoCheck } from "@angular/core"; + +import { Result, cLog, Message, MessageCode, MessageSeverity } from "jalhyd"; + +import { LogComponent } from "../log/log.component"; +import { CalculatorResults } from "../../results/calculator-results"; +import { PbResultsTableComponent } from "./pb-results-table.component"; +import { PrebarrageResults } from "../../results/prebarrage-results"; +import { VariableResultsSelectorComponent } from "../variable-results-selector/variable-results-selector.component"; +import { I18nService } from "../../services/internationalisation.service"; +import { PabProfileChartComponent } from "../pab-profile-chart/pab-profile-chart.component"; +import { FixedResults } from "../../results/fixed-results"; + +@Component({ + selector: "pb-results", + templateUrl: "./pb-results.component.html", + styleUrls: [ + "./pb-results.component.scss" + ] +}) +export class PbResultsComponent implements DoCheck { + + /** résultats des bassins, non mis en forme */ + private _pbResults: PrebarrageResults; + + /** true si les résultats doiventt être remis à jour */ + private _doUpdate = false; + + @ViewChild(PbResultsTableComponent) + private pbResultsTableComponent: PbResultsTableComponent; + + @ViewChild(VariableResultsSelectorComponent) + private variableResultsSelectorComponent: VariableResultsSelectorComponent; + + @ViewChild("generalLog") + private generalLogComponent: LogComponent; + + @ViewChild("iterationLog") + private iterationLogComponent: LogComponent; + + /* @ViewChild(PabProfileChartComponent) + private profileChartComponent: PabProfileChartComponent; */ + + constructor( + private i18nService: I18nService, + ) { } + + public set results(rs: CalculatorResults[]) { + this._pbResults = undefined; + for (const r of rs) { + if (r instanceof PrebarrageResults) { + this._pbResults = r as PrebarrageResults; + } + } + this.updateView(); + } + + public get pbResults() { + return this._pbResults; + } + + public get hasResults(): boolean { + return this._pbResults && this._pbResults.hasResults; + } + + public get showBasinsResults(): boolean { + let ret = this._pbResults && this._pbResults.hasResults; + if ( + this._pbResults + && this._pbResults.variatedParameters + && this._pbResults.variatedParameters.length > 0 + ) { + ret = ret + && this._pbResults.variableIndex !== undefined + && this._pbResults.result.resultElements[this._pbResults.variableIndex] !== undefined + && this._pbResults.result.resultElements[this._pbResults.variableIndex].ok; + } + return ret; + } + + /** + * update results table and chart when the variable index changed (event sent by + * PabVariableResultsSelectorComponent); variable index is already set in + * pabResults at this time + */ + public variableIndexChanged() { + this.updateView(); + } + + public updateView() { + if (this.iterationLogComponent) { + this.iterationLogComponent.log = undefined; + } + if (this.generalLogComponent) { + this.generalLogComponent.log = undefined; + } + if (this.pbResultsTableComponent) { + this.pbResultsTableComponent.results = undefined; + } + if (this.variableResultsSelectorComponent) { + this.variableResultsSelectorComponent.results = undefined; + } + /* if (this.profileChartComponent) { + this.profileChartComponent.results = undefined; + } */ + // set _doUpdate flag so that results are rebuilt on the next Angular display cycle + this._doUpdate = false; + if (this._pbResults !== undefined) { + this._doUpdate = this._doUpdate || this._pbResults.hasResults || this._pbResults.hasLog; + } + } + + public ngDoCheck() { + if (this._doUpdate) { + this._doUpdate = !this.updateResults(); + } + } + + /* private mergeGlobalLog(result: Result, log: cLog) { + if (result) { + if (result.hasGlobalLog()) { + log.addLog(result.globalLog); + } + // if no parameter is varying, 1st element log is considered "global" + if (this.pbResults.variatedParameters.length === 0) { + if (result.hasResultElements() && result.resultElement.hasLog()) { + log.addLog(result.log); + } + } + } + } */ + + /** + * Returns the number of errors, warnings, infos among children logs + */ + /* private logStats(): any { + const ret = { + info: 0, + warning: 0, + error: 0 + }; + if (this._pbResults.result && this._pbResults.result.hasLog()) { + for (const re of this._pbResults.result.resultElements) { + if (re.hasLog()) { + for (const m of re.log.messages) { + const s = m.getSeverity(); + switch (s) { + case MessageSeverity.INFO: + ret.info ++; + break; + case MessageSeverity.WARNING: + ret.warning ++; + break; + case MessageSeverity.ERROR: + ret.error ++; + break; + } + } + } + } + } + for (const cr of this._pbResults.cloisonsResults) { + if (cr && cr.hasLog()) { + for (const re of cr.resultElements) { + if (re.hasLog()) { + for (const m of re.log.messages) { + const s = m.getSeverity(); + switch (s) { + case MessageSeverity.INFO: + ret.info ++; + break; + case MessageSeverity.WARNING: + ret.warning ++; + break; + case MessageSeverity.ERROR: + ret.error ++; + break; + } + } + } + } + } + } + if (this._pbResults.cloisonAvalResults && this._pbResults.cloisonAvalResults.hasLog()) { + for (const re of this._pbResults.cloisonAvalResults.resultElements) { + if (re.hasLog()) { + for (const m of re.log.messages) { + const s = m.getSeverity(); + switch (s) { + case MessageSeverity.INFO: + ret.info ++; + break; + case MessageSeverity.WARNING: + ret.warning ++; + break; + case MessageSeverity.ERROR: + ret.error ++; + break; + } + } + } + } + } + return ret; + } */ + + /* + * 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._pbResults && this.pbResults.variatedParameters.length > 0) { + this.mergeGlobalLog(this._pbResults.result, l); + // un problème avec la PAB en général / les cloisons, à une étape quelconque ? + if ( + (this.pbResults.hasLog) + && l.messages.length === 0 // existing global messages make generic message below useless + ) { + const logStats = this.logStats(); + const m = new Message(MessageCode.WARNING_PROBLEMS_ENCOUNTERED); + m.extraVar.info = "" + logStats.info; // to avoid displaying fixed number of digits + m.extraVar.warning = "" + logStats.warning; + m.extraVar.error = "" + logStats.error; + l.add(m); + // 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._pbResults) { + if (this.pbResults.variatedParameters.length > 0) { + // A. si un paramètre varie + const vi = this._pbResults.variableIndex; + // log de la PAB pour l'itération en cours + if ( + this._pbResults.result + && this._pbResults.result.hasResultElements() + && this._pbResults.result.resultElements[vi] + && this._pbResults.result.resultElements[vi].hasLog() + ) { + l.addLog(this._pbResults.result.resultElements[vi].log); + } + // logs des enfants pour l'itération en cours + for (const cr of this._pbResults.cloisonsResults) { + if (cr && cr.hasResultElements() && cr.resultElements[vi].hasLog()) { + l.addLog(cr.resultElements[vi].log); + } + } + if (this._pbResults.cloisonAvalResults && this._pbResults.cloisonAvalResults.resultElements[vi].hasLog()) { + l.addLog(this._pbResults.cloisonAvalResults.resultElements[vi].log); + } + } else { + // B. si aucun paramètre ne varie + this.mergeGlobalLog(this._pbResults.result, l); // faut bien mettre le log global quelque part + // logs des enfants + for (const cr of this._pbResults.cloisonsResults) { + if (cr && cr.hasResultElements() && cr.resultElement.hasLog()) { + l.addLog(cr.resultElement.log); + } + } + if (this._pbResults.cloisonAvalResults && this._pbResults.cloisonAvalResults.resultElement.hasLog()) { + l.addLog(this._pbResults.cloisonAvalResults.resultElement.log); + } + } + } + return l; + } */ + + /** + * met à jour l'affichage des résultats + * @returns true si les résultats ont pu être mis à jour + */ + private updateResults() { + console.log("------------ update results -----------"); + let pabUpdated: boolean; + let profileChartUpdated: boolean; + let selectorUpdated: boolean; + + // results or not, there might be a log + const logUpdated = (this.iterationLogComponent !== undefined || this.generalLogComponent !== undefined); // gne ? + if (logUpdated) { + // order of logs is important ! + /* this.iterationLogComponent.log = this.iterationLog; + this.generalLogComponent.log = this.globalLog; */ + } + + if (this.hasResults) { + pabUpdated = this.pbResultsTableComponent !== undefined; + if (pabUpdated) { + this.pbResultsTableComponent.results = this._pbResults; + } + selectorUpdated = this.variableResultsSelectorComponent !== undefined; + if (selectorUpdated) { + this.variableResultsSelectorComponent.results = this._pbResults; + } + /* profileChartUpdated = this.profileChartComponent !== undefined; + if (profileChartUpdated) { + this.profileChartComponent.results = this._pbResults; + this.profileChartComponent.updateView(); + } */ + } else { + pabUpdated = true; + profileChartUpdated = true; + selectorUpdated = true; + } + + return pabUpdated && logUpdated && profileChartUpdated && selectorUpdated; + } + + public get uitextGeneralLogTitle(): string { + return this.i18nService.localizeText("INFO_TITREJOURNAL_GLOBAL"); + } + +} diff --git a/src/app/formulaire/definition/form-prebarrage.ts b/src/app/formulaire/definition/form-prebarrage.ts index 0199451c3313a44108094330023812fc48138f4c..8cd69289368fb5ea5936366e9b2fa2d35f51b3fe 100644 --- a/src/app/formulaire/definition/form-prebarrage.ts +++ b/src/app/formulaire/definition/form-prebarrage.ts @@ -1,4 +1,4 @@ -import { CalculatorType, PbBassin, PbCloison, IObservable } from "jalhyd"; +import { CalculatorType, PbBassin, PbCloison, IObservable, PreBarrage } from "jalhyd"; import { FormulaireFixedVar } from "./form-fixedvar"; import { PbSchema } from "../elements/pb-schema"; @@ -6,6 +6,9 @@ import { FormulaireDefinition } from "./form-definition"; import { ServiceFactory } from "../../services/service-factory"; import { FormulairePbCloison } from "./form-pb-cloison"; import { FieldsetContainer } from "../elements/fieldset-container"; +import { CalculatorResults } from "../../results/calculator-results"; +import { PrebarrageResults } from "../../results/prebarrage-results"; +import { NgParameter } from "../elements/ngparam"; /** * Formulaire pour les PréBarrage @@ -24,6 +27,34 @@ export class FormulairePrebarrage extends FormulaireFixedVar { /** configuration for re-creating wall form every time needed */ private wallFormConfig: string; + protected _selectedItem: PbBassin | PbCloison; + + protected _pbResults: PrebarrageResults; + + constructor() { + super(); + this._pbResults = new PrebarrageResults(); + } + + /* public get pbNub(): PreBarrage { + return this.currentNub as PreBarrage; + } */ + + public get pbResults(): PrebarrageResults { + return this._pbResults; + } + + public get results(): CalculatorResults[] { + // ensure help links are propagated + this._pbResults.helpLinks = this.helpLinks; + console.log("RENVOI", [ this.fixedResults, this._pbResults ]); + return [ this.fixedResults, this._pbResults ]; + } + + public get hasResults(): boolean { + return this._pbResults.hasResults; + } + public parseConfig(json?: {}) { if (json !== undefined) { this._jsonConfig = json; @@ -82,7 +113,15 @@ export class FormulairePrebarrage extends FormulaireFixedVar { this.kids.push(sch); } + /** + * Déclenché par CalculatorComponent lorsque le schéma de prébarrage + * envoie un événement "nodeSelected" (on a cliqué sur un nœud) + */ public nodeSelected(node: PbBassin | PbCloison) { + // store for results formatting + this._selectedItem = node; + this.reaffectResultComponents(); + // show only the relevant form if (node === undefined) { this.showFormElements(this.riverForm); @@ -156,4 +195,58 @@ export class FormulairePrebarrage extends FormulaireFixedVar { } } } + + protected compute() { + this.runNubCalc(this.currentNub); + this.refreshFieldsets(); // important: before reaffectResultComponents() or it will break results components localization + // reset variable index to avoid trying to access an index > 0 when nothing varies + const pabr = this.pbResults; + pabr.variableIndex = 0; + + this.reaffectResultComponents(); + } + + protected reaffectResultComponents() { + const pb: PreBarrage = (this.currentNub as PreBarrage); + const computedParam: NgParameter = this.getComputedParameter(); + const varParams: NgParameter[] = this.getVariatedParameters(); + + // pour le sélecteur d'itérations + if (varParams) { + this.pbResults.variatedParameters = varParams; + } + + // résultats selon l'objet sélectionné sur le schéma + if (this._selectedItem !== undefined && this._selectedItem instanceof PbCloison) { + // cacher les résultats de bassins + this.pbResults.reset(); + + // afficher les résultats de cloison + console.log("RRC => cloison !", this._selectedItem.uid, this._selectedItem.result); + this.fixedResults.result = this._selectedItem.result; + if (computedParam !== undefined) { + this.fixedResults.calculatedParameter = computedParam; + } + } else { + // cacher les résultats de la cloison + this.fixedResults.reset(); + this.addFixedParameters(); + + // afficher les résultats des bassins + this.pbResults.reset(); + // résultat général du Nub (amont, aval, débit) + this.pbResults.result = pb.result; + this.pbResults.calculatedParameter = computedParam; + // résultat de chaque bassin + for (const b of pb.bassins) { + this.pbResults.bassinsResults.push(b.result); + } + } + } + + public resetResults() { + super.resetResults(); + this._fixedResults.reset(); + this._pbResults.reset(); + } } diff --git a/src/app/results/prebarrage-results.ts b/src/app/results/prebarrage-results.ts new file mode 100644 index 0000000000000000000000000000000000000000..cea9887149c7d410214b25139956cf52ca50137c --- /dev/null +++ b/src/app/results/prebarrage-results.ts @@ -0,0 +1,111 @@ +import { Result } from "jalhyd"; + +import { ServiceFactory } from "../services/service-factory"; +import { MultiDimensionResults } from "./multidimension-results"; + +export class PrebarrageResults extends MultiDimensionResults { + + /** résultats des bassins, dans l'ordre */ + public bassinsResults: Result[]; + + /** symboles des colonnes de résultat */ + protected _columns: string[]; + + public constructor() { + super(); + this.reset(); + // standard headers + this._columns = [ + "BASSIN", + "S", + "ZF", + "Z", + "PV", + "YMOY", + "Q" + ]; + } + + /** headers symbols */ + public get columns() { + return this._columns; + } + + /** translated headers texts */ + public get headers() { + return this._columns.map((h) => { + // calculator type for translation + const sn = this.result.sourceNub; + let ct = sn.calcType; + if (sn.parent) { + ct = sn.parent.calcType; + } + let label = ServiceFactory.instance.formulaireService.expandVariableNameAndUnit(ct , h); + label += this.getHelpLink(h); + return label; + }); + } + + public reset() { + super.reset(); + this.bassinsResults = []; + this.result = undefined; + } + + /** + * Returns true if at least one log message is present in the PAB result or any + * of the children results + */ + public get hasLog(): boolean { + if (this.bassinsResults) { + for (const cr of this.bassinsResults) { + if (cr && cr.hasLog()) { + return true; + } + } + } + return (this.result && this.result.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; + // log principal + err = (err || this.result.hasErrorMessages()); + // logs des bassins + for (const c of this.bassinsResults) { + err = (err || c.hasErrorMessages()); + } + + return err; + } + + /** retourne true si le calcul à l'itération i a échoué */ + public iterationHasError(i: number): boolean { + let err = this.result.resultElements[i].hasErrorMessages(); + // logs des bassins + for (const c of this.bassinsResults) { + err = (err || c.resultElements[i].hasErrorMessages()); + } + + 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 bassins + for (const c of this.bassinsResults) { + err = (err && c.hasOnlyErrors); + } + + return err; + } +} diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json index b74de92216edbe039110a8cf6bcda3bbe0d68598..c2c32a603cd3fa8c70c33c32e5fe85c8479cb760 100644 --- a/src/locale/messages.en.json +++ b/src/locale/messages.en.json @@ -258,6 +258,7 @@ "INFO_LIB_AMONT": "Upstream", "INFO_LIB_AVAL": "Downstream", "INFO_LIB_B": "Surface width", + "INFO_LIB_BASSIN": "Basin", "INFO_LIB_BB": "Pool width", "INFO_LIB_BETA": "Beta coefficient", "INFO_LIB_BT": "Half opening of the triangle", diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json index 3047fac2a4e9020cec9cffd67c97fc1912a412e5..1dd7eb5cd2876055c49dcc88610c95c1d05c86c6 100644 --- a/src/locale/messages.fr.json +++ b/src/locale/messages.fr.json @@ -258,6 +258,7 @@ "INFO_LIB_AMONT": "Amont", "INFO_LIB_AVAL": "Aval", "INFO_LIB_B": "Largeur au miroir", + "INFO_LIB_BASSIN": "Bassin", "INFO_LIB_BB": "Largeur du bassin", "INFO_LIB_BETA": "Coefficient béta", "INFO_LIB_BT": "Demi-ouverture du triangle",