diff --git a/src/app/app.module.ts b/src/app/app.module.ts index e386fe63e09506f9dd154af9f19d59bfe41fadcb..b73ea0bc2a71f3a2b52fc5faaae303a074e55306 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -40,6 +40,8 @@ import { LogComponent } from './components/log/log.component'; import { CalculatorListComponent } from './components/calculator-list/calculator-list.component'; import { ApplicationSetupComponent } from './components/app-setup/app-setup.component'; import { BaseParamInputComponent } from './components/base-param-input/base-param-input.component'; +import { SingleResultComponent } from './components/single-result/single-result.component'; +import { LogEntryComponent } from './components/log-entry/log-entry.component'; const appRoutes: Routes = [ { path: 'list', component: CalculatorListComponent }, @@ -72,7 +74,7 @@ const appRoutes: Routes = [ ParamFieldLineComponent, NgParamMinComponent, NgParamMaxComponent, NgParamStepComponent, ParamValuesComponent, ValueListComponent, SelectFieldLineComponent, CheckFieldLineComponent, - LogComponent, + LogComponent, LogEntryComponent, CalculatorListComponent, ApplicationSetupComponent, BaseParamInputComponent, @@ -80,7 +82,8 @@ const appRoutes: Routes = [ // AlertDialog, CalculatorResultsComponent, FixedVarResultsComponent, SectionResultsComponent, RemousResultsComponent, ResultsGraphComponent, GraphTypeSelectComponent, - CalcCanvasComponent, SectionCanvasComponent + CalcCanvasComponent, SectionCanvasComponent, + SingleResultComponent ], // entryComponents: [AlertDialog], providers: [ // services diff --git a/src/app/components/app-setup/app-setup.component.html b/src/app/components/app-setup/app-setup.component.html index 0612fc7fe082e2c8537c7c0f2a0ff03b480369c5..433caf89aeb3a2bc564e2a6c3974f70550aa84a0 100644 --- a/src/app/components/app-setup/app-setup.component.html +++ b/src/app/components/app-setup/app-setup.component.html @@ -20,6 +20,13 @@ </div> </div> + <!-- nombre d'itérations max Newton --> + <div class="row"> + <div class="col-4 mx-auto"> + <base-param-input #newtonMaxIter title="{{uitextNewtonMaxIteration}}"></base-param-input> + </div> + </div> + <!-- langue --> <div class="row"> diff --git a/src/app/components/app-setup/app-setup.component.ts b/src/app/components/app-setup/app-setup.component.ts index d1a048b3559dd301dc3727aa6be0e029b5d49cc3..0c267b4ec1fda6eb5f53c561d05c12c58d2d1b93 100644 --- a/src/app/components/app-setup/app-setup.component.ts +++ b/src/app/components/app-setup/app-setup.component.ts @@ -23,12 +23,20 @@ export class ApplicationSetupComponent extends BaseComponent implements Observer */ private _computePrec: NgBaseParam; + /** + * nombre d'iterations max Newton + */ + private _newtonMaxIter: NgBaseParam; + @ViewChild("displayAccurary") private _displayAccuraryComponent: BaseParamInputComponent; @ViewChild("computeAccuracy") private _computeAccuraryComponent: BaseParamInputComponent; + @ViewChild("newtonMaxIter") + private _newtonMaxIterComponent: BaseParamInputComponent; + constructor( private appSetupService: ApplicationSetupService, private intlService: InternationalisationService @@ -56,6 +64,10 @@ export class ApplicationSetupComponent extends BaseComponent implements Observer return this.intlService.localizeText("INFO_SETUP_PRECISION_CALCUL"); } + private get uitextNewtonMaxIteration(): string { + return this.intlService.localizeText("INFO_SETUP_NEWTON_MAX_ITER"); + } + private init() { // modèle du composant BaseParamInputComponent de précision d'affichage this._displayPrec = new NgBaseParam("dp", ParamDomainValue.POS, this.appSetupService.displayPrecision); @@ -66,6 +78,11 @@ export class ApplicationSetupComponent extends BaseComponent implements Observer this._computePrec = new NgBaseParam("cp", ParamDomainValue.POS, this.appSetupService.computePrecision); this._computePrec.addObserver(this); this._computeAccuraryComponent.model = this._computePrec; + + // modèle du composant BaseParamInputComponent du max d'itérations pour Newton + this._newtonMaxIter = new NgBaseParam("nmi", ParamDomainValue.POS, this.appSetupService.newtonMaxIter); + this._newtonMaxIter.addObserver(this); + this._newtonMaxIterComponent.model = this._newtonMaxIter; } /** @@ -87,6 +104,10 @@ export class ApplicationSetupComponent extends BaseComponent implements Observer case "cp": this.appSetupService.computePrecision = +data; break; + + case "nmi": + this.appSetupService.newtonMaxIter = +data; + break; } } } diff --git a/src/app/components/calculator-list/calculator-list.component.ts b/src/app/components/calculator-list/calculator-list.component.ts index 39993acec5b5111059a4ffac072ff28b0a39a109..9ce84d292495902ff634fef4cbfbdd05d42ad049 100644 --- a/src/app/components/calculator-list/calculator-list.component.ts +++ b/src/app/components/calculator-list/calculator-list.component.ts @@ -1,10 +1,11 @@ import { Component, OnInit } from "@angular/core"; import { Router } from '@angular/router'; +import { EnumEx } from "jalhyd"; + import { CalculatorType, FormulaireDefinition } from "../../formulaire/formulaire-definition"; import { FormulaireService } from "../../services/formulaire/formulaire.service"; import { InternationalisationService } from '../../services/internationalisation/internationalisation.service'; -import { EnumEx } from "../../util"; class ListElement { private _label: string; diff --git a/src/app/components/calculator-results/calculator-results.component.ts b/src/app/components/calculator-results/calculator-results.component.ts index 1baea27e8a9a901d8862114b2fa5edb8c9ce8123..15546ce01f67fa861ac53c7b4fc83196f06ed376 100644 --- a/src/app/components/calculator-results/calculator-results.component.ts +++ b/src/app/components/calculator-results/calculator-results.component.ts @@ -61,14 +61,14 @@ export class CalculatorResultsComponent implements AfterViewChecked { } private getFixedVarResultsStyleDisplay() { - return this._formulaire != undefined && this._formulaire.hasFixVarResults() ? "block" : "none"; + return this._formulaire != undefined && this._formulaire.hasFixVarResults ? "block" : "none"; } private getSectionResultsStyleDisplay() { - return this._formulaire != undefined && this._formulaire.hasSectionResults() ? "block" : "none"; + return this._formulaire != undefined && this._formulaire.hasSectionResults ? "block" : "none"; } private getRemousResultsStyleDisplay() { - return this._formulaire != undefined && this._formulaire.hasRemousResults() ? "block" : "none"; + return this._formulaire != undefined && this._formulaire.hasRemousResults ? "block" : "none"; } } diff --git a/src/app/components/fixedvar-results/fixedvar-results.component.html b/src/app/components/fixedvar-results/fixedvar-results.component.html index f3ddd2076cd24f2b97897e85f6a1cc896de15b42..05555d9311b47416db8fa15a9d858ed63ec7ff02 100644 --- a/src/app/components/fixedvar-results/fixedvar-results.component.html +++ b/src/app/components/fixedvar-results/fixedvar-results.component.html @@ -16,9 +16,11 @@ <th class="result_center">{{uitextParamFixes}}</th> <th class="result_center">{{uitextValeurs}}</th> </tr> - <tr *ngFor="let r of _fixedResults; let i=index"> + <tr *ngFor="let r of fixedResults; let i=index"> <td class="result_right {{getFixedResultClass(i)}}">{{r.label}}</td> - <td class="result_center {{getFixedResultClass(i)}}">{{r.value}}</td> + <td class="result_center {{getFixedResultClass(i)}}"> + <single-result [result]=r.value> </single-result> + </td> </tr> </table> </div> @@ -30,9 +32,13 @@ <th class="result_center">{{_results.variableParamHeader}}</th> <th class="result_center">{{_results.variableResultHeader}}</th> </tr> - <tr *ngFor="let r of _varResults; let i=index"> - <td class="result_center">{{r.param}}</td> - <td class="result_center">{{r.result}}</td> + <tr *ngFor="let r of varResults; let i=index"> + <td class="result_center"> + <single-result [result]=r.param></single-result> + </td> + <td class="result_center"> + <single-result [result]=r.result></single-result> + </td> </tr> </table> </div> diff --git a/src/app/components/fixedvar-results/fixedvar-results.component.ts b/src/app/components/fixedvar-results/fixedvar-results.component.ts index 27b225369857614cc456b08f8cd98921776383e6..f55c8cd547955ef16eb057eb9c14d2efdee51e7d 100644 --- a/src/app/components/fixedvar-results/fixedvar-results.component.ts +++ b/src/app/components/fixedvar-results/fixedvar-results.component.ts @@ -1,7 +1,6 @@ import { Component, ViewChild, DoCheck } from "@angular/core"; import { InternationalisationService } from "../../services/internationalisation/internationalisation.service"; -import { ApplicationSetupService } from '../../services/app-setup/app-setup.service'; import { LogComponent } from '../../components/log/log.component'; import { FixedVarResults } from "../../results/fixed-var-results"; import { ResultsGraphComponent } from "../results-graph/results-graph.component"; @@ -35,16 +34,6 @@ export class FixedVarResultsComponent implements DoCheck { */ private _results: FixedVarResults; - /** - * résultats fixed mis en forme - */ - private _fixedResults: Object[]; - - /** - * résultats fixed mis en forme - */ - private _varResults: Object[]; - /** * true si le graphe des résultats doit être remis à jour */ @@ -60,8 +49,7 @@ export class FixedVarResultsComponent implements DoCheck { private resultsGraphComponent: ResultsGraphComponent; constructor( - private intlService: InternationalisationService, - private appSetupService: ApplicationSetupService + private intlService: InternationalisationService ) { } public set results(r: FixedVarResults) { @@ -70,8 +58,6 @@ export class FixedVarResultsComponent implements DoCheck { } public updateView() { - this._fixedResults = []; - this._varResults = []; this.logComponent.log = undefined; this.generateResults(); this._updateResultsGraph = true; @@ -89,17 +75,6 @@ export class FixedVarResultsComponent implements DoCheck { private generateResults() { if (this._results != undefined) { - const nDigits = this.appSetupService.displayDigits; - const prec = this.appSetupService.displayPrecision; - - for (let r of this._results.fixedResults) { - let v = r["value"]; - this._fixedResults.push({ "label": r["label"], "value": v.toFixed(nDigits) }); - } - - for (let r of this._results.varResults) - this._varResults.push({ "param": r["param"].toFixed(nDigits), "result": r["result"].toFixed(nDigits) }); - this.logComponent.log = this._results.log; } } @@ -108,14 +83,14 @@ export class FixedVarResultsComponent implements DoCheck { * affichage de la table des résultats fixés */ private get showFixedResults(): boolean { - return this._results != undefined && this._results.hasFixedResults(); + return this._results != undefined && this._results.hasFixedResults; } /** * affichage de la table des résultats variés */ private get showVarResults(): boolean { - return this._results != undefined && this._results.hasVarResults(); + return this._results != undefined && this._results.hasVarResults; } private get uitextParamFixes() { @@ -131,4 +106,12 @@ export class FixedVarResultsComponent implements DoCheck { return "font-weight-bold"; return "result_id_" + String(i & 1); } + + private get fixedResults() { + return this._results.fixedResults; + } + + private get varResults() { + return this._results.varResults; + } } diff --git a/src/app/components/log-entry/log-entry.component.html b/src/app/components/log-entry/log-entry.component.html new file mode 100644 index 0000000000000000000000000000000000000000..b603829536bc89da7a1d9c8a52de720ade88136d --- /dev/null +++ b/src/app/components/log-entry/log-entry.component.html @@ -0,0 +1,11 @@ +<div class="row entry"> + <div class="col-1" style="text-align: center;"> + <i *ngIf="levelInfo" class="fa fa-check" style="color:green"></i> + <i *ngIf="levelWarning" class="fa fa-exclamation" style="color:orange"></i> + <i *ngIf="levelError" class="fa fa-exclamation-triangle" style="color:red"></i> + </div> + <div class="col-11"> + <!-- on utilise [innerHTML] pour que les codes HTML comme soient interprétés correctement --> + <span [innerHTML]="text"></span> + </div> +</div> \ No newline at end of file diff --git a/src/app/components/log-entry/log-entry.component.ts b/src/app/components/log-entry/log-entry.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..effa2e57a5ffffa5562787dc43b8e5a393a61399 --- /dev/null +++ b/src/app/components/log-entry/log-entry.component.ts @@ -0,0 +1,62 @@ +import { Component, Input, OnChanges } from "@angular/core"; + +import { Message, MessageSeverity } from 'jalhyd'; + +import { InternationalisationService } from "../../services/internationalisation/internationalisation.service"; +import { ApplicationSetupService } from '../../services/app-setup/app-setup.service'; + +@Component({ + selector: "log-entry", + templateUrl: "./log-entry.component.html", + styles: [` + .entry { + margin-left: 1em; + margin-right: 1em; + margin-top: 0.5em; + margin-bottom: 0.5em; + } + `] + +}) +export class LogEntryComponent implements OnChanges { + @Input("message") + private _message: Message; + + /** + * message mis en forme + */ + private _text: string; + + constructor( + private intlService: InternationalisationService, + private appSetupService: ApplicationSetupService + ) { } + + /** + * appelé quand les @Input changent + */ + ngOnChanges() { + this.updateText(); + } + + private updateText() { + const nDigits = this.appSetupService.displayDigits; + this._text = this.intlService.localizeMessage(this._message, nDigits); + } + + private get text(): string { + return this._text; + } + + private get levelInfo(): boolean { + return this._message.getSeverity() == MessageSeverity.INFO; + } + + private get levelWarning(): boolean { + return this._message.getSeverity() == MessageSeverity.WARNING; + } + + private get levelError(): boolean { + return this._message.getSeverity() == MessageSeverity.ERROR; + } +} diff --git a/src/app/components/log/log.component.html b/src/app/components/log/log.component.html index 90fd45727409a32db29d8773e1cdb925cc3a8f8f..37ecc7a8eb42e8fcccfdf195bfd4cfbd0a3605c3 100644 --- a/src/app/components/log/log.component.html +++ b/src/app/components/log/log.component.html @@ -1,11 +1,13 @@ <div class="row" *ngIf="hasEntries"> <div class="col-12"> <div class="hyd_log"> + <!-- titre --> <div class="titre">{{uitextTitreJournal}}</div> - <ul *ngFor="let r of _logEntries"> - <!-- on utilise [innerHTML] pour que les codes HTML comme soient interprétés correctement --> - <li [innerHTML]="r"></li> - </ul> + + <!-- entrées du journal --> + <ng-template ngFor let-m [ngForOf]="messages"> + <log-entry [message]=m></log-entry> + </ng-template> </div> </div> </div> \ No newline at end of file diff --git a/src/app/components/log/log.component.ts b/src/app/components/log/log.component.ts index 43fb0471793cdd40bc18d489052224696d2b2ea7..93d567509a15cf1230395e10b361dda9e2c8f1ed 100644 --- a/src/app/components/log/log.component.ts +++ b/src/app/components/log/log.component.ts @@ -1,11 +1,8 @@ import { Component } from "@angular/core"; -import { Message, cLog } from 'jalhyd'; +import { cLog, Message } from 'jalhyd'; -import { NgParameter } from "../../formulaire/ngparam"; import { InternationalisationService } from "../../services/internationalisation/internationalisation.service"; -import { ApplicationSetupService } from '../../services/app-setup/app-setup.service'; - @Component({ selector: "log", @@ -37,14 +34,8 @@ export class LogComponent { */ private _log: cLog; - /** - * entrées du journal mises en forme - */ - private _logEntries: string[]; - constructor( private intlService: InternationalisationService, - private appSetupService: ApplicationSetupService ) { } private get uitextTitreJournal() { @@ -52,20 +43,14 @@ export class LogComponent { } private get hasEntries(): boolean { - return this._logEntries != undefined && this._logEntries.length != 0; + return this._log != undefined && this._log.messages.length != 0; } - private generateEntries() { - this._logEntries = []; - if (this._log != undefined) { - const nDigits = this.appSetupService.displayDigits; - for (let m of this._log.messages) - this._logEntries.push(this.intlService.localizeMessage(m, nDigits)); - } + private get messages(): Message[] { + return this._log.messages; } public set log(log: cLog) { this._log = log; - this.generateEntries(); } } diff --git a/src/app/components/remous-results/remous-results.component.html b/src/app/components/remous-results/remous-results.component.html index 621cca20c22b2cc08a322247c7b1964dff1ab453..a2eecd6ce48e05577319392fd258f9023363bac9 100644 --- a/src/app/components/remous-results/remous-results.component.html +++ b/src/app/components/remous-results/remous-results.component.html @@ -31,12 +31,24 @@ <th>{{extraParamLabel}}</th> </tr> </thead> - <tr *ngFor="let r of series; let i=index" [class]="getResultClass(i)"> + <tr *ngFor="let r of values; let i=index" [class]="getResultClass(i)"> <td>{{r.abs}}</td> - <td>{{r.flu}}</td> - <td>{{r.extraFlu}}</td> - <td>{{r.tor}}</td> - <td>{{r.extraTor}}</td> + <!-- <td>{{r.flu}}</td> --> + <td> + <single-result [result]=r.flu></single-result> + </td> + <!-- <td>{{r.extraFlu}}</td> --> + <td> + <single-result [result]=r.extraFlu></single-result> + </td> + <!-- <td>{{r.tor}}</td> --> + <td> + <single-result [result]=r.tor></single-result> + </td> + <!-- <td>{{r.extraTor}}</td> --> + <td> + <single-result [result]=r.extraTor></single-result> + </td> </tr> </table> </div> \ No newline at end of file diff --git a/src/app/components/remous-results/remous-results.component.ts b/src/app/components/remous-results/remous-results.component.ts index 9bc71e6545cd2cebb3f23bb0612521d8c70b3c2c..c72b5b10c3e68b38eb40b531a3fac592f290871c 100644 --- a/src/app/components/remous-results/remous-results.component.ts +++ b/src/app/components/remous-results/remous-results.component.ts @@ -1,14 +1,14 @@ -import { Component, ViewChild } from '@angular/core'; +import { Component, ViewChild } from "@angular/core"; -import { Message } from 'jalhyd'; +import { Result, ArrayReverseIterator, ResultElement } from "jalhyd"; -import { InternationalisationService } from '../../services/internationalisation/internationalisation.service'; -import { LogComponent } from '../../components/log/log.component'; +import { InternationalisationService } from "../../services/internationalisation/internationalisation.service"; +import { LogComponent } from "../../components/log/log.component"; import { RemousResults } from "../../results/remous-results"; @Component({ - selector: 'remous-results', - templateUrl: './remous-results.component.html', + selector: "remous-results", + templateUrl: "./remous-results.component.html", styles: [` .result_label { text-align: right; @@ -36,17 +36,22 @@ export class RemousResultsComponent { /* * config du graphe principal */ - private graph1_type = 'line'; + private graph1_type = "line"; private graph1_data = {}; private graph1_options = {}; /* * config du graphe secondaire (paramètre supplémentaire sauf Hs, Hsc, Yf, Yt, Yco) */ - private graph2_type = 'line'; + private graph2_type = "line"; private graph2_data = {}; private graph2_options = {}; + /** + * liste de valeurs pour le tableau + */ + private _values: Object[]; + /** * composant journal */ @@ -115,20 +120,13 @@ export class RemousResultsComponent { this.graph2_data = {}; this.graph2_options = {}; this.logComponent.log = undefined; + this._values = []; if (this._results != undefined) { this.logComponent.log = this._results.log; this.generateGraph(); } } - private searchObjectInArray(array: any[], key: string, value: any) { - for (let o of array) - if (o[key] == value) - return o; - - return undefined; - } - private connectRessaut(lineFlu: LineData, lineTor: LineData) { if (lineFlu != undefined && lineTor != undefined) { let tX = lineFlu.tx.slice(0); // copie @@ -142,13 +140,11 @@ export class RemousResultsComponent { }); let minXflu; // abscisse de début de la courbe fluviale - for (let x of tX) { - let r = this.searchObjectInArray(this._results.series, "abs", x); - if (r != undefined && r["flu"] != "") { - minXflu = x; + for (let r of this._results.series) + if (r.getExtraResult("flu") != undefined) { + minXflu = r.vCalc; break; } - } if (minXflu != undefined && minXflu != tX[0]) { // la courbe fluviale ne démarre pas au début, on ajoute un point de raccord avec la ligne torrentielle @@ -160,15 +156,12 @@ export class RemousResultsComponent { } let maxXtor; // abscisse de fin de la courbe torrentielle - tX.reverse(); - for (let x of tX) { - let r = this.searchObjectInArray(this._results.series, "abs", x); - if (r != undefined && r["tor"] != "") { - maxXtor = x; + const it = new ArrayReverseIterator<Result>(this._results.series); + for (let r of it) + if (r.getExtraResult("tor") != undefined) { + maxXtor = r.vCalc; break; } - } - tX.reverse(); if (maxXtor != undefined && maxXtor != tX[tX.length - 1]) { // la courbe torrentielle ne finit pas à la fin des abscisses, on ajoute un point de raccord avec la ligne fluviale @@ -190,10 +183,10 @@ export class RemousResultsComponent { // abscisses let labs: number[] = []; - if (this._results.series.length > 0) { + if (this._results.hasSeriesData) { var xmax = -1e8; for (let r of this._results.series) { - let x = +r["abs"]; + let x = r.vCalc; labs.push(x); xmax = Math.max(x, xmax); } @@ -213,16 +206,16 @@ export class RemousResultsComponent { gr1.drawLine(0, 0, 3, "#753F00", this.uitextFond, "#753F00"); // ligne de berge - if (this._results.hautBerge != undefined) - gr1.drawLine(this._results.hautBerge, this._results.hautBerge, 4, "#C58F50", this.uitextBerge); + if (this._results.hautBerge != undefined && this._results.hautBerge.ok) + gr1.drawLine(this._results.hautBerge.vCalc, this._results.hautBerge.vCalc, 4, "#C58F50", this.uitextBerge); // hauteur normale - if (this._results.hautNormale != undefined) - gr1.drawLine(this._results.hautNormale, this._results.hautNormale, 5, "#A4C537", this.uitextTirantNormal); + if (this._results.hautNormale != undefined && this._results.hautNormale.ok) + gr1.drawLine(this._results.hautNormale.vCalc, this._results.hautNormale.vCalc, 5, "#A4C537", this.uitextTirantNormal); // hauteur critique - if (this._results.hautCritique != undefined) - gr1.drawLine(this._results.hautCritique, this._results.hautCritique, 6, "#FF0000", this.uitextTirantCritique); + if (this._results.hautCritique != undefined && this._results.hautCritique.ok) + gr1.drawLine(this._results.hautCritique.vCalc, this._results.hautCritique.vCalc, 6, "#FF0000", this.uitextTirantCritique); // lignes d'eau torrentielle et fluviale @@ -238,20 +231,34 @@ export class RemousResultsComponent { } for (let r of this._results.series) { - let x: number = +r["abs"]; - let yFlu: string = r["flu"]; - let yTor: string = r["tor"]; - - let yExtra: string = r["extraFlu"]; - if (yExtra == "") - yExtra = r["extraTor"]; - - if (yFlu != "") - lineFlu.mapPoint(x, +yFlu); - if (yTor != "") - lineTor.mapPoint(x, +yTor); - if (yExtra != "") - lineExtra.mapPoint(x, +yExtra); + const x = r.vCalc; + + const yExtra = r.getExtraResult("extra"); + if (yExtra != undefined) + lineExtra.mapPoint(x, yExtra); + + const yFlu = r.getExtraResult("flu"); + let extraFlu; + if (yFlu != undefined) { + lineFlu.mapPoint(x, yFlu); + extraFlu = yExtra; + } + + const yTor = r.getExtraResult("tor"); + let extraTor; + if (yTor != undefined) { + lineTor.mapPoint(x, yTor); + extraTor = yExtra; + } + + this._values.push( + { + "abs": x, + "flu": new ResultElement(yFlu), + "extraFlu": new ResultElement(extraFlu), + "tor": new ResultElement(yTor), + "extraTor": new ResultElement(extraTor) + }); } if (this._results.hasExtra) { @@ -313,6 +320,10 @@ export class RemousResultsComponent { } } + private get values() { + return this._values; + } + private getResultClass(i: number) { return "result_id_" + String(i & 1); } diff --git a/src/app/components/results-graph/results-graph.component.ts b/src/app/components/results-graph/results-graph.component.ts index 861ea67986221e41e08c9b36d1198e0578072b02..507ce7824a90b1d5d27bc4de5d4cbf74bba2f275 100644 --- a/src/app/components/results-graph/results-graph.component.ts +++ b/src/app/components/results-graph/results-graph.component.ts @@ -94,7 +94,7 @@ export class ResultsGraphComponent { let dat = []; for (let i in this._results.varResults) { let r = this._results.varResults[i]; - labs.push(r["param"]); + labs.push(r["param"].vCalc); dat.push(this._results.varGraph[i]); } @@ -125,7 +125,7 @@ export class ResultsGraphComponent { let dat = []; for (let i in this._results.varResults) { let r = this._results.varResults[i]; - dat.push({ x: r["param"], y: this._results.varGraph[i] }); + dat.push({ x: r["param"].vCalc, y: this._results.varGraph[i] }); } this.graph_options.title.text = this._results.graphTitle; diff --git a/src/app/components/section-canvas/section-canvas.component.ts b/src/app/components/section-canvas/section-canvas.component.ts index 1876d7453104931ce2b1ea494a244636d978d509..fcac05278683d9789d1e87f277b82c15da8e3f36 100644 --- a/src/app/components/section-canvas/section-canvas.component.ts +++ b/src/app/components/section-canvas/section-canvas.component.ts @@ -1,6 +1,9 @@ import { Component, ViewChild } from '@angular/core'; -import { acSection, cSnTrapez, ParamsSectionTrapez, cSnRectang, ParamsSectionRectang, cSnCirc, ParamsSectionCirc, cSnPuiss, ParamsSectionPuiss } from 'jalhyd'; +import { + acSection, cSnTrapez, ParamsSectionTrapez, cSnRectang, ParamsSectionRectang, cSnCirc, + ParamsSectionCirc, cSnPuiss, ParamsSectionPuiss, Result +} from 'jalhyd'; import { CalcCanvasComponent } from '../canvas/canvas.component'; @@ -173,35 +176,46 @@ export class SectionCanvasComponent { let D: number = prms.D.v; let r: number = D / 2; - // largeur au miroir - let B: number = sect.Calc("B", yb); + try { + // largeur au miroir + let B: Result = sect.Calc("B", yb); + if (!B.ok) + throw B; - // largeur totale de la section - let maxWidth: number = yb < r ? B : D; + // largeur totale de la section + let maxWidth: number = yb < r ? B.vCalc : D; - // hauteur totale de la section - let maxHeight: number = this.getMaxLevel(); - maxHeight *= 1.1; + // hauteur totale de la section + let maxHeight: number = this.getMaxLevel(); + maxHeight *= 1.1; - this.computeScale(maxWidth, maxHeight); + this.computeScale(maxWidth, maxHeight); - // dessin de la section + // dessin de la section - this._calcCanvas.setStrokeColor(0, 0, 0); - this._calcCanvas.setLineWidth(5); + this._calcCanvas.setStrokeColor(0, 0, 0); + this._calcCanvas.setLineWidth(5); - let wx: number = maxWidth / 2; - let alpha: number = sect.Calc("Alpha", yb); - let s: number = Math.PI / 2 - alpha; - let e: number = Math.PI / 2 + alpha; - this.drawSectionEllipse(wx, r, r, r, 0, s, e); + let wx: number = maxWidth / 2; + let alpha: Result = sect.Calc("Alpha", yb); + if (!alpha.ok) + throw alpha; - // pointillés du haut + let s: number = Math.PI / 2 - alpha.vCalc; + let e: number = Math.PI / 2 + alpha.vCalc; + this.drawSectionEllipse(wx, r, r, r, 0, s, e); - let w: number = yb > r ? (D - B) / 2 : 0; - this.drawTopDashLines(w, maxWidth - w, yb, maxHeight); + // pointillés du haut - return maxWidth; + let w: number = yb > r ? (D - B.vCalc) / 2 : 0; + this.drawTopDashLines(w, maxWidth - w, yb, maxHeight); + + return maxWidth; + } + catch (e) { + let r: Result = e as Result; + this.drawText("error : " + r.log.toString(), 0, 0); + } } private drawSectionPara() { @@ -261,7 +275,7 @@ export class SectionCanvasComponent { this._calcCanvas.drawEllipse(this.Xm2pix(x), this.Ym2pix(y), rX * this._scaleX, rY * this._scaleY, rot, start, end); } - private drawText(s: string, x: number, y: number, align: string) { + private drawText(s: string, x: number, y: number, align: string = undefined) { this._calcCanvas.fillText(s, this.Xm2pix(x), this.Ym2pix(y), align); } diff --git a/src/app/components/section-results/section-results.component.html b/src/app/components/section-results/section-results.component.html index 674f8026d070535ca080f6a2768a39ed5e033077..c9143041f40990f44d6d3e28e8670cedbe7a5927 100644 --- a/src/app/components/section-results/section-results.component.html +++ b/src/app/components/section-results/section-results.component.html @@ -6,12 +6,14 @@ </div> <!-- tableau de valeurs --> -<div class="row"> +<div *ngIf="hasResults" class="row"> <div class="col mx-auto"> <table style="width: 100%"> - <tr *ngFor="let r of _results; let i=index" [class]="getResultClass(i)"> + <tr *ngFor="let r of sectionResults; let i=index" [class]="getResultClass(i)"> <td class="result_label">{{r.label}}</td> - <td class="result_value">{{r.value}}</td> + <td class="result_value"> + <single-result [result]=r.value></single-result> + </td> </tr> </table> </div> diff --git a/src/app/components/section-results/section-results.component.ts b/src/app/components/section-results/section-results.component.ts index 61e28aa7e801f4f4d83fea95d43ae2bc68e89794..528e3ef84f8c009fa76e60e055cbce42ba8bb30c 100644 --- a/src/app/components/section-results/section-results.component.ts +++ b/src/app/components/section-results/section-results.component.ts @@ -1,6 +1,6 @@ import { Component, ViewChild } from '@angular/core'; -import { acSection } from 'jalhyd'; +import { acSection, Result } from 'jalhyd'; import { SectionCanvasComponent } from '../section-canvas/section-canvas.component'; import { SectionResults } from '../../results/section-results'; @@ -36,11 +36,6 @@ export class SectionResultsComponent { */ private _sectionResults: SectionResults; - /** - * résultats mis en forme - */ - private _results: Object[]; - constructor(private appSetupService: ApplicationSetupService) { } private static labelColors: { [key: string]: any; } = { @@ -62,7 +57,6 @@ export class SectionResultsComponent { } public updateView() { - this._results = []; this._sectionCanvas.reset(); if (this._sectionResults != undefined) this.formatResults(); @@ -73,19 +67,25 @@ export class SectionResultsComponent { const nDigits = this.appSetupService.displayDigits; for (let r of this._sectionResults.results) { - const v = r["value"]; + const v: Result = r["value"]; const l = r["label"]; - this._results.push({ "label": l, "value": v.toFixed(nDigits) }); - const drawLabel = r["drawLabel"]; - if (drawLabel != undefined) - this._sectionCanvas.addLevel(v, drawLabel + " = " + v.toFixed(nDigits), SectionResultsComponent.labelColors[drawLabel]); + if (drawLabel != undefined && v.vCalc != undefined) + this._sectionCanvas.addLevel(v.vCalc, drawLabel + " = " + v.vCalc.toFixed(nDigits), SectionResultsComponent.labelColors[drawLabel]); } this._sectionCanvas.section = this._sectionResults.section; } } + private get hasResults(): boolean { + return this._sectionResults != undefined; + } + + private get sectionResults() { + return this._sectionResults.results; + } + private getResultClass(i: number) { return "result_id_" + String(i & 1); } diff --git a/src/app/components/single-result/single-result.component.html b/src/app/components/single-result/single-result.component.html new file mode 100644 index 0000000000000000000000000000000000000000..f0611067b17cefd03d6e279a3668bae59a64b1a8 --- /dev/null +++ b/src/app/components/single-result/single-result.component.html @@ -0,0 +1,16 @@ +<!-- template pour le popup --> +<ng-template #popTemplate> + <div [innerHtml]="htmlTooltip"></div> +</ng-template> + +<div class="row" [mdbTooltip]="popTemplate" [isDisabled]="tooltipDisabled"> + <div class="col-12"> + <!-- icône en cas d'erreur --> + <i *ngIf="hasError" class="fa fa-exclamation-triangle" style="color:red" aria-hidden="true"></i> + + <!-- valeur --> + <span *ngIf="!hasError"> + {{value}} + </span> + </div> +</div> \ No newline at end of file diff --git a/src/app/components/single-result/single-result.component.ts b/src/app/components/single-result/single-result.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..8a5994b2f51d0e66c6456e00d2cc4d1662a9423a --- /dev/null +++ b/src/app/components/single-result/single-result.component.ts @@ -0,0 +1,87 @@ +import { Component, Input } from "@angular/core"; + +import { ResultElement } from 'jalhyd'; + +import { ApplicationSetupService } from "../../services/app-setup/app-setup.service"; +import { InternationalisationService } from "../../services/internationalisation/internationalisation.service"; +import { OnChanges } from "@angular/core/src/metadata/lifecycle_hooks"; + +@Component({ + selector: "single-result", + templateUrl: "./single-result.component.html" +}) +export class SingleResultComponent implements OnChanges { + @Input("result") + private _result: ResultElement; + + /** + * valeur à afficher + */ + private _value: string; + + /** + * true si la valeur est en erreur + */ + private _hasError: boolean; + + /** + * code HTML du tooltip + */ + private _htmlTooltip: string; + + /** + * true si pas de texte à afficher dans le tooltip + */ + private _emptyTooltip: boolean = false; + + constructor( + private appSetupService: ApplicationSetupService, + private intlService: InternationalisationService + ) { } + + /** + * appelé quand les @Input changent + */ + ngOnChanges() { + this.updateTooltip(); + } + + private updateTooltip() { + // valeur à afficher + + const nDigits = this.appSetupService.displayDigits; + const r: ResultElement = this._result; + this._hasError = r == undefined || r.vCalc == undefined; + this._value = this._hasError ? " " : this._value = r.vCalc.toFixed(nDigits); + + // texte du tooltip + + let res = ""; + + if (this._result != undefined) + for (let m of this._result.log.messages) { + if (res.length > 0) + res += "<br/>"; + res += this.intlService.localizeMessage(m); + } + + this._htmlTooltip = res; + this._emptyTooltip = this._htmlTooltip.length == 0; + } + + private get value(): string { + return this._value; + } + + private get hasError() { + return this._hasError && !this._emptyTooltip; + } + + private get htmlTooltip(): string { + return this._htmlTooltip; + } + + private get tooltipDisabled(): boolean { + return this._emptyTooltip; + } +} diff --git a/src/app/formulaire/formulaire-definition.ts b/src/app/formulaire/formulaire-definition.ts index 4f1ebfc4cb532c2d0871a76449cf17d4f33c6658..287bee8e2bb13be1718f76020c811261d468795e 100644 --- a/src/app/formulaire/formulaire-definition.ts +++ b/src/app/formulaire/formulaire-definition.ts @@ -1,5 +1,5 @@ -import { ComputeNodeType, ParamsEquation, Nub, acSection, RegimeUniforme, MethodeResolution, CourbeRemousParams, CourbeRemous, ParamDomainValue } from "jalhyd"; -import { ParamsSectionRectang, cSnRectang, ParamsSectionCirc, cSnCirc, ParamsSectionPuiss, cSnPuiss, Result } from "jalhyd"; +import { ComputeNodeType, ParamsEquation, Nub, acSection, RegimeUniforme, MethodeResolution, CourbeRemousParams, CourbeRemous, ParamDomainValue, Result, ResultElement } from "jalhyd"; +import { ParamsSectionRectang, cSnRectang, ParamsSectionCirc, cSnCirc, ParamsSectionPuiss, cSnPuiss } from "jalhyd"; import { ConduiteDistrib, ConduiteDistribParams, LechaptCalmon, LechaptCalmonParams, ParamsSectionTrapez, cSnTrapez } from "jalhyd"; import { PabDimension, PabDimensionParams, PabPuissance, PabPuissanceParams } from "jalhyd"; @@ -698,17 +698,17 @@ export class FormulaireDefinition extends Observable { private addFixedResults(displaySymbol: boolean) { for (let p of this.getInputParameters()) if (p.radioState == ParamRadioConfig.FIX && p.symbol !== "Pr") - this._fixVarResults.addFixedResult(p, p.getValue(), displaySymbol); + this._fixVarResults.addFixedResultElement(p, p.getValue(), displaySymbol); } - private addSectionFixedResult(val: number, label: string, drawLabel: string = undefined) { + private addSectionFixedResult(val: ResultElement, label: string, drawLabel: string = undefined) { this._sectionResults.addResult(val, label, drawLabel); } private addSectionFixedResults(displaySymbol: boolean) { for (let p of this.getDisplayedInputParameters()) if (p.radioState == ParamRadioConfig.FIX && this.isMySectionType(p.computeNodeType, false) && p.symbol !== "Pr") - this._fixVarResults.addFixedResult(p, p.getValue(), displaySymbol); + this._fixVarResults.addFixedResultElement(p, p.getValue(), displaySymbol); } private getSectionVariatedParameter(): NgParameter { @@ -750,7 +750,7 @@ export class FormulaireDefinition extends Observable { sect.Reset(true); let res = sect.Calc(compSymbol, Y); - this._fixVarResults.addVarResult(val, res); + this._fixVarResults.addVarResultElement(val, res.result); } this._fixVarResults.graphTitle = computedParam.symbol + " = f( " + varParam.symbol + " )"; @@ -778,79 +778,71 @@ export class FormulaireDefinition extends Observable { // charge spécifique let Hs = sect.Calc("Hs", Y); - this.addSectionFixedResult(Hs, this.intlService.localizeText("INFO_GRANDEUR_HS"), "Hs"); + this.addSectionFixedResult(Hs.result, this.intlService.localizeText("INFO_GRANDEUR_HS"), "Hs"); // charge critique let Hsc = sect.Calc("Hsc", Y); - this.addSectionFixedResult(Hsc, this.intlService.localizeText("INFO_GRANDEUR_HSC"), "Hsc"); + this.addSectionFixedResult(Hsc.result, this.intlService.localizeText("INFO_GRANDEUR_HSC"), "Hsc"); // largeur au miroir let B = sect.Calc("B", Y); - this.addSectionFixedResult(B, this.intlService.localizeText("INFO_GRANDEUR_B")); + this.addSectionFixedResult(B.result, this.intlService.localizeText("INFO_GRANDEUR_B")); // périmètre hydraulique let P = sect.Calc("P", Y); - this.addSectionFixedResult(P, this.intlService.localizeText("INFO_GRANDEUR_P")); + this.addSectionFixedResult(P.result, this.intlService.localizeText("INFO_GRANDEUR_P")); // surface hydraulique let S = sect.Calc("S", Y); - this.addSectionFixedResult(S, this.intlService.localizeText("INFO_GRANDEUR_S")); + this.addSectionFixedResult(S.result, this.intlService.localizeText("INFO_GRANDEUR_S")); // rayon hydraulique let R = sect.Calc("R", Y); - this.addSectionFixedResult(R, this.intlService.localizeText("INFO_GRANDEUR_R")); + this.addSectionFixedResult(R.result, this.intlService.localizeText("INFO_GRANDEUR_R")); // vitesse moyenne let V = sect.Calc("V", Y); - this.addSectionFixedResult(V, this.intlService.localizeText("INFO_GRANDEUR_V")); + this.addSectionFixedResult(V.result, this.intlService.localizeText("INFO_GRANDEUR_V")); // nombre de Froude let Fr = sect.Calc("Fr", Y); - this.addSectionFixedResult(Fr, this.intlService.localizeText("INFO_GRANDEUR_FR"), ); + this.addSectionFixedResult(Fr.result, this.intlService.localizeText("INFO_GRANDEUR_FR"), ); // tirant d'eau critique let Yc = sect.Calc("Yc", Y); - this.addSectionFixedResult(Yc, this.intlService.localizeText("INFO_GRANDEUR_YC"), "Yc"); + this.addSectionFixedResult(Yc.result, this.intlService.localizeText("INFO_GRANDEUR_YC"), "Yc"); // tirant d'eau normal let Yn = sect.Calc("Yn", Y); - this.addSectionFixedResult(Yn, this.intlService.localizeText("INFO_GRANDEUR_YN"), "Yn"); + this.addSectionFixedResult(Yn.result, this.intlService.localizeText("INFO_GRANDEUR_YN"), "Yn"); // tirant d'eau fluvial let Yf = sect.Calc("Yf", Y); - this.addSectionFixedResult(Yf, this.intlService.localizeText("INFO_GRANDEUR_YF"), "Yf"); + this.addSectionFixedResult(Yf.result, this.intlService.localizeText("INFO_GRANDEUR_YF"), "Yf"); // tirant d'eau torrentiel let Yt = sect.Calc("Yt", Y); - this.addSectionFixedResult(Yt, this.intlService.localizeText("INFO_GRANDEUR_YT"), "Yt"); + this.addSectionFixedResult(Yt.result, this.intlService.localizeText("INFO_GRANDEUR_YT"), "Yt"); // tirant d'eau conjugué let Yco = sect.Calc("Yco", Y); - this.addSectionFixedResult(Yco, this.intlService.localizeText("INFO_GRANDEUR_YCO"), "Yco"); + this.addSectionFixedResult(Yco.result, this.intlService.localizeText("INFO_GRANDEUR_YCO"), "Yco"); // perte de charge let J = sect.Calc("J", Y); - this.addSectionFixedResult(J, this.intlService.localizeText("INFO_GRANDEUR_J")); + this.addSectionFixedResult(J.result, this.intlService.localizeText("INFO_GRANDEUR_J")); // Variation linéaire de l'énergie spécifique let IJ = sect.Calc("I-J", Y); - this.addSectionFixedResult(IJ, this.intlService.localizeText("INFO_GRANDEUR_I-J")); + this.addSectionFixedResult(IJ.result, this.intlService.localizeText("INFO_GRANDEUR_I-J")); // impulsion hydraulique let Imp = sect.Calc("Imp", Y); - this.addSectionFixedResult(Imp, this.intlService.localizeText("INFO_GRANDEUR_IMP")); + this.addSectionFixedResult(Imp.result, this.intlService.localizeText("INFO_GRANDEUR_IMP")); // contrainte de cisaillement let Tau0 = sect.Calc("Tau0", Y); - this.addSectionFixedResult(Tau0, this.intlService.localizeText("INFO_GRANDEUR_TAU0")); - } - - private addRemousResult(x: string, f: number, t: number, e: number) { - const nDigits = this.appSetupService.displayDigits; - let flu = f == undefined ? "" : f.toFixed(nDigits); - let tor = t == undefined ? "" : t.toFixed(nDigits); - let extra = e == undefined ? "" : e.toFixed(nDigits); - this._remousResults.addResult(x, flu, tor, extra); + this.addSectionFixedResult(Tau0.result, this.intlService.localizeText("INFO_GRANDEUR_TAU0")); } private doComputeRemous() { @@ -866,8 +858,8 @@ export class FormulaireDefinition extends Observable { let Long: number = this.getNodeParameterValue(ComputeNodeType.CourbeRemous, "Long"); // longueur du bief let If: number = this.getNodeParameterValue(ComputeNodeType.CourbeRemous, "If"); // pente du fond let YB: number = this.getNodeParameterValue(ComputeNodeType.CourbeRemous, "YB"); // hauteur de berge - let Yn: number = sect.Calc("Yn"); // hauteur normale - let Yc: number = sect.Calc("Yc"); // hauteur critique + let Yn: Result = sect.Calc("Yn"); // hauteur normale + let Yc: Result = sect.Calc("Yc"); // hauteur critique this._remousResults.penteFond = If; @@ -894,13 +886,13 @@ export class FormulaireDefinition extends Observable { let prmCR: CourbeRemousParams = new CourbeRemousParams(sect, Yamont, Yaval, Long, Dx, methRes); let cr = new CourbeRemous(prmCR); - let res = cr.calculRemous(extraSymbol == "none" ? undefined : extraSymbol); + let res: Result = cr.calculRemous(extraSymbol == "none" ? undefined : extraSymbol); // affichage du graphe - this._remousResults.hauteurBerge = YB; - this._remousResults.hauteurNormale = Yn; - this._remousResults.hauteurCritique = Yc; + this._remousResults.hauteurBerge = new ResultElement(YB); + this._remousResults.hauteurNormale = Yn.result; + this._remousResults.hauteurCritique = Yc.result; if (extraSymbol != "none") { this._remousResults.extraParamLabel = dsf.selectedEntry.label; this._remousResults.extraGraph = ["Hs", "Hsc", "Yf", "Yt", "Yco"].indexOf(extraSymbol) == -1; @@ -908,21 +900,9 @@ export class FormulaireDefinition extends Observable { else this._remousResults.extraGraph = false; - // journal - - this._remousResults.log = cr.log; - // résultats numériques - let kFlu = Object.keys(res.flu); - let kTor = Object.keys(res.tor); - for (let i = 0; i < res.trX.length; i++) { - let x: string = res.trX[i]; - let f = res.flu[x]; - let t = res.tor[x]; - let e = res.tRes[x]; - this.addRemousResult(x, f, t, e); - } + this._remousResults.addResult(res); } private getVariatedParameter(): NgParameter { @@ -1017,6 +997,7 @@ export class FormulaireDefinition extends Observable { let Fruit = this.getNodeParameterValue(nt, "Fruit"); // Fruit des berges let prms = new ParamsSectionTrapez(LargeurFond, Fruit, Y, Ks, Q, If, Prec, YB); let cn = new cSnTrapez(prms); + cn.newtonMaxIter = this.appSetupService.newtonMaxIter; return [cn, prms]; } @@ -1027,6 +1008,7 @@ export class FormulaireDefinition extends Observable { let LargeurFond = this.getNodeParameterValue(nt, "LargeurBerge"); // Largeur au fond let prms = new ParamsSectionRectang(Y, LargeurFond, Ks, Q, If, Prec, YB); let cn = new cSnRectang(prms); + cn.newtonMaxIter = this.appSetupService.newtonMaxIter; return [cn, prms]; } @@ -1037,6 +1019,7 @@ export class FormulaireDefinition extends Observable { let D = this.getNodeParameterValue(nt, "D"); // Largeur au fond let prms = new ParamsSectionCirc(D, Y, Ks, Q, If, Prec, YB); let cn = new cSnCirc(prms); + cn.newtonMaxIter = this.appSetupService.newtonMaxIter; return [cn, prms]; } @@ -1048,6 +1031,7 @@ export class FormulaireDefinition extends Observable { let LargeurBerge = this.getNodeParameterValue(nt, "LargeurBerge"); // Largeur au niveau des berges let prms = new ParamsSectionPuiss(k, Y, LargeurBerge, Ks, Q, If, Prec, YB); let cn = new cSnPuiss(prms); + cn.newtonMaxIter = this.appSetupService.newtonMaxIter; return [cn, prms]; } @@ -1110,7 +1094,7 @@ export class FormulaireDefinition extends Observable { let res: Result = this.runNubCalc(nub, computedParam, computePrec); if (res.ok) { this.addFixedResults(!rg); - this._fixVarResults.addFixedResult(computedParam, res.vCalc, !rg); + this._fixVarResults.addFixedResultElement(computedParam, res.result, !rg); } else { this._fixVarResults.addLogMessages(res.log); @@ -1136,7 +1120,7 @@ export class FormulaireDefinition extends Observable { let res: Result = this.runNubCalc(nub, computedParam, computePrec); if (res.ok) { - this._fixVarResults.addVarResult(val, res.vCalc); + this._fixVarResults.addVarResultElement(val, res.result); } else { this._fixVarResults.addLogMessages(res.log); @@ -1152,7 +1136,7 @@ export class FormulaireDefinition extends Observable { let res: Result = this.runNubCalc(nub, computedParam, computePrec); if (res.ok) { - this._fixVarResults.addVarResult(val, res.vCalc); + this._fixVarResults.addVarResultElement(val, res.result); } else { this._fixVarResults.addLogMessages(res.log); @@ -1197,20 +1181,20 @@ export class FormulaireDefinition extends Observable { return this.getFormulaireElementById(id).isDisplayed; } - public hasFixVarResults(): boolean { - return this._fixVarResults.hasResults(); + public get hasFixVarResults(): boolean { + return this._fixVarResults.hasResults; } - public hasSectionResults(): boolean { - return this._sectionResults.hasResults(); + public get hasSectionResults(): boolean { + return this._sectionResults.hasResults; } - public hasRemousResults(): boolean { - return this._remousResults.hasResults(); + public get hasRemousResults(): boolean { + return this._remousResults.hasResults; } public get hasResults(): boolean { - return this.hasFixVarResults() || this.hasSectionResults() || this.hasRemousResults(); + return this.hasFixVarResults || this.hasSectionResults || this.hasRemousResults; } public updateLocalisation(localisation: StringMap) { diff --git a/src/app/results/calculator-results.ts b/src/app/results/calculator-results.ts index b91a4c642daacc2d90ef48da6537a06c56cdae08..10c87330b006d869f25477c91f68ad4c98452d61 100644 --- a/src/app/results/calculator-results.ts +++ b/src/app/results/calculator-results.ts @@ -24,5 +24,5 @@ export abstract class CalculatorResults { /** * indique si il existe des résultats à afficher */ - public abstract hasResults(): boolean; + public abstract get hasResults(): boolean; } \ No newline at end of file diff --git a/src/app/results/fixed-var-results.ts b/src/app/results/fixed-var-results.ts index 97d16be54d613650eb983d9ccb41279b5a629303..0c2dabda746e8df2a8b8b6c260ed02723575f892 100644 --- a/src/app/results/fixed-var-results.ts +++ b/src/app/results/fixed-var-results.ts @@ -1,4 +1,4 @@ -import { cLog } from "jalhyd"; +import { cLog, Result, ResultElement } from "jalhyd"; import { NgParameter } from "../formulaire/ngparam"; import { CalculatorResults } from "./calculator-results"; @@ -105,14 +105,22 @@ export class FixedVarResults extends CalculatorResults { this._log = new cLog(); } - public addFixedResult(p: NgParameter, v: number, displaySymbol: boolean) { - this._fixedResults.push({ "label": this.paramLabel(p, displaySymbol), "value": v }); + public addFixedResultElement(p: NgParameter, v: ResultElement | number, displaySymbol: boolean) { + if (v instanceof ResultElement) + this._fixedResults.push({ "label": this.paramLabel(p, displaySymbol), "value": v }); + else if (typeof v === "number") + this._fixedResults.push({ "label": this.paramLabel(p, displaySymbol), "value": new ResultElement(v) }); + else + throw "appel FixedVarResults.addFixedResultElement() invalide : v = " + String(v); } - public addVarResult(paramVal: number, resVal: number) { + public addVarResultElement(paramVal: number, resVal: ResultElement) { this._isFixed = false; - this._varResults.push({ "param": paramVal, "result": resVal }); - this._varGraph.push(resVal); + this._varResults.push({ "param": new ResultElement(paramVal), "result": resVal }); + if (resVal.ok) + this._varGraph.push(resVal.vCalc); + else + this._varGraph.push(0); } public addLogMessages(l: cLog) { @@ -148,15 +156,15 @@ export class FixedVarResults extends CalculatorResults { this._graphTitle = t; } - public hasFixedResults(): boolean { + public get hasFixedResults(): boolean { return this._fixedResults.length > 0; } - public hasVarResults(): boolean { + public get hasVarResults(): boolean { return this._varResults.length > 0; } - public hasResults(): boolean { - return this.hasFixedResults() || this.hasVarResults(); + public get hasResults(): boolean { + return this.hasFixedResults || this.hasVarResults; } } diff --git a/src/app/results/remous-results.ts b/src/app/results/remous-results.ts index 758ea621bbc7ed18c1a57b4f5de9fb8acd917b94..4c277be280c20b6481b18eafaeb63db53471cd23 100644 --- a/src/app/results/remous-results.ts +++ b/src/app/results/remous-results.ts @@ -1,11 +1,12 @@ +import { cLog, Result, ResultElement } from "jalhyd"; + import { CalculatorResults } from "./calculator-results"; -import { cLog } from "jalhyd"; export class RemousResults extends CalculatorResults { /** * hauteur de berge */ - private _hautBerge: number; + private _hautBerge: ResultElement; /** * pente du fond @@ -15,20 +16,30 @@ export class RemousResults extends CalculatorResults { /** * hauteur normale */ - private _hautNormale: number; + private _hautNormale: ResultElement; /** * hauteur critique */ - private _hautCritique: number; + private _hautCritique: ResultElement; /** * résultats numériques */ - private _series: Object[] = []; + private _series: ResultElement[] = []; + + /** + * présence de données pour la courbe fluviale + */ + private _hasFlu: boolean; + + /** + * présence de données pour la courbe torrentielle + */ + private _hasTor: boolean; /** - * présence d'un paramètre supplémentaire + * présence de données pour le paramètre supplémentaire */ private _hasExtra: boolean; @@ -60,6 +71,8 @@ export class RemousResults extends CalculatorResults { this._hautNormale = undefined; this._hautCritique = undefined; this._extraParamLabel = undefined; + this._hasFlu = false; + this._hasTor = false; this._hasExtra = false; this._extraGraph = false; } @@ -76,12 +89,31 @@ export class RemousResults extends CalculatorResults { return this._series; } - public addResult(x: string, flu: string, tor: string, extra: string) { - let extraFlu = (flu == "" ? "" : extra); - let extraTor = (tor == "" ? "" : extra); - if (extraFlu != "" || extraTor != "") - this._hasExtra = true; - this._series.push({ "abs": x, "flu": flu, "extraFlu": extraFlu, "tor": tor, "extraTor": extraTor }); + public addResult(res: Result) { + if (res.ok) { + const trX = res.getExtraResult("trX"); + const flu = res.getExtraResult("flu"); + const tor = res.getExtraResult("tor"); + const extra = res.getExtraResult("tRes"); + for (let x of trX) { + let r = new ResultElement(x); + if (flu[x] != undefined) { + r.addExtraResult("flu", flu[x]); + this._hasFlu = true; + } + if (tor[x] != undefined) { + r.addExtraResult("tor", tor[x]); + this._hasTor = true; + } + if (extra[x] != undefined) { + r.addExtraResult("extra", extra[x]); + this._hasExtra = true; + } + this._series.push(r); + } + } + + this._log.addLog(res.globalLog); } public get extraParamLabel() { @@ -92,15 +124,11 @@ export class RemousResults extends CalculatorResults { this._extraParamLabel = l; } - // public addLogEntry(m: Message, nDigits: number) { - // this.logComponent.addLogEntry(m, nDigits); - // } - public get hautBerge() { return this._hautBerge; } - public set hauteurBerge(v: number) { + public set hauteurBerge(v: ResultElement) { this._hautBerge = v; } @@ -116,7 +144,7 @@ export class RemousResults extends CalculatorResults { return this._hautNormale; } - public set hauteurNormale(v: number) { + public set hauteurNormale(v: ResultElement) { this._hautNormale = v; } @@ -124,7 +152,7 @@ export class RemousResults extends CalculatorResults { return this._hautCritique; } - public set hauteurCritique(v: number) { + public set hauteurCritique(v: ResultElement) { this._hautCritique = v; } @@ -140,12 +168,12 @@ export class RemousResults extends CalculatorResults { this._extraGraph = b; } - public hasResults(): boolean { + public get hasResults(): boolean { return this._hautBerge != undefined || this._penteFond != undefined || this._hautNormale != undefined || this._hautCritique != undefined || - this._series.length > 0; + this.hasSeriesData; } /** @@ -159,21 +187,13 @@ export class RemousResults extends CalculatorResults { * @return true si il existe au moins une données dans la série fluviale */ public get hasFluData(): boolean { - for (let r of this._series) - if (r["flu"] != undefined) - return true; - - return false; + return this._hasFlu; } /** * @return true si il existe au moins une données dans la série torrentielle */ public get hasTorData(): boolean { - for (let r of this._series) - if (r["tor"] != undefined) - return true; - - return false; + return this._hasTor; } -} \ No newline at end of file +} diff --git a/src/app/results/section-results.ts b/src/app/results/section-results.ts index 12abf4b36c134145f1006f86ea5b9f84e88db10f..680b5b40cc6803df2d923c6e113b96c27542668a 100644 --- a/src/app/results/section-results.ts +++ b/src/app/results/section-results.ts @@ -1,4 +1,4 @@ -import { acSection } from "jalhyd"; +import { acSection, Result, ResultElement } from "jalhyd"; import { CalculatorResults } from "./calculator-results"; import { NgParameter } from "../formulaire/ngparam"; @@ -18,13 +18,7 @@ export class SectionResults extends CalculatorResults { this._results = []; } - // public addResult(v: number, l: string, fixedPrec: number, drawLabel: string) { - // this._results.push({ "label": l, "value": v.toFixed(fixedPrec) }); - // if (drawLabel != undefined) { - // this._sectionCanvas.addLevel(v, drawLabel + " = " + v.toFixed(fixedPrec), SectionResultsComponent.labelColors[drawLabel]); - // } - // } - public addResult(v: number, l: string, drawLabel: string) { + public addResult(v: ResultElement, l: string, drawLabel: string) { this._results.push({ "label": l, "value": v, @@ -32,10 +26,6 @@ export class SectionResults extends CalculatorResults { }); } - // public addFixedResult(p: NgParameter, v: number, fixedPrec: number, displaySymbol: boolean) { - // this._fixedResults.push({ "label": this.paramLabel(p, displaySymbol), "value": v.toFixed(fixedPrec) }); - // } - public get results() { return this._results; } @@ -48,7 +38,7 @@ export class SectionResults extends CalculatorResults { this._section = s; } - public hasResults(): boolean { + public get hasResults(): boolean { return this._section != undefined && this._results.length > 0; } -} \ No newline at end of file +} diff --git a/src/app/services/app-setup/app-setup.service.ts b/src/app/services/app-setup/app-setup.service.ts index 24585c12f86c5eed427228808ac2b67e557064e7..16a9ef5dec88202e522f0147d92c1e0a3442209f 100644 --- a/src/app/services/app-setup/app-setup.service.ts +++ b/src/app/services/app-setup/app-setup.service.ts @@ -3,6 +3,8 @@ export class ApplicationSetupService { private _computePrecision: number; + private _newtonMaxIter: number; + constructor() { this.defaults(); } @@ -10,6 +12,7 @@ export class ApplicationSetupService { public defaults() { this._displayPrecision = 0.001; this._computePrecision = 0.0001; + this._newtonMaxIter = 50; } public get displayPrecision() { @@ -31,4 +34,12 @@ export class ApplicationSetupService { public set computePrecision(p: number) { this._computePrecision = p; } + + public get newtonMaxIter() { + return this._newtonMaxIter; + } + + public set newtonMaxIter(p: number) { + this._newtonMaxIter = p; + } } diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index 623e46f7298937927fa015a0b51dd40bbaa6ef2b..5c313c89931a990fb48be6395c9543a0caf2cd6c 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -3,6 +3,8 @@ import { Response } from "@angular/http"; import { Observable as rxObservable } from "rxjs/Observable"; import "rxjs/add/operator/toPromise"; +import { EnumEx } from "jalhyd"; + import { ParamService } from "../param/param.service"; import { HttpService } from "../../services/http/http.service"; import { InternationalisationService } from "../../services/internationalisation/internationalisation.service"; @@ -13,7 +15,6 @@ import { InputField } from "../../formulaire/input-field"; import { SelectField } from "../../formulaire/select-field"; import { CheckField } from "../../formulaire/check-field"; import { StringMap } from "../../stringmap"; -import { EnumEx } from "../../util"; import { Observable } from "../observer"; @Injectable() diff --git a/src/app/util.ts b/src/app/util.ts index 297bda30c95628265de4e338e22e363a23853612..d312650ee1fe5a79090b880b1dd7f3052a1b53c2 100644 --- a/src/app/util.ts +++ b/src/app/util.ts @@ -5,34 +5,3 @@ export function logObject(obj: {}, m?: string) { else console.log(m + " " + JSON.stringify(obj)); } - -/** - * classe d'itérateurs pour les enums - * cf. https://stackoverflow.com/questions/21293063/how-to-programmatically-enumerate-an-enum-type-in-typescript-0-9-5#21294925 - */ -export class EnumEx { - /** - * retourne les noms et les valeurs d'un enum - */ - static getNamesAndValues<T extends number>(e: any) { - return EnumEx.getNames(e).map(n => ({ name: n, value: e[n] as T })); - } - - /** - * retourne les noms d'un enum - */ - static getNames(e: any) { - return EnumEx.getObjValues(e).filter(v => typeof v === "string") as string[]; - } - - /** - * retourne les valeurs d'un enum - */ - static getValues<T extends number>(e: any) { - return EnumEx.getObjValues(e).filter(v => typeof v === "number") as T[]; - } - - private static getObjValues(e: any): (number | string)[] { - return Object.keys(e).map(k => e[k]); - } -} \ No newline at end of file diff --git a/src/locale/error_messages.en.json b/src/locale/error_messages.en.json index 85aeb9c69a37ebe6a2ac10ab2322027f173d0a3d..90b1704b7e51798c7f5b25b516a97e04587db46f 100644 --- a/src/locale/error_messages.en.json +++ b/src/locale/error_messages.en.json @@ -5,6 +5,7 @@ "ERROR_DICHO_NULL_STEP": "Dichotomy (initial interval search): invalid null step", "ERROR_DICHO_INVALID_STEP_GROWTH": "Dichotomy (initial interval search): invalid null step growth", "ERROR_DICHO_FUNCTION_VARIATION": "unable to determinate function direction of variation", + "ERROR_NEWTON_DERIVEE_NULLE": "Null function derivative in Newton computation", "ERROR_PARAMDOMAIN_INTERVAL_BOUNDS": "invalid %minValue%/%maxValue% min/max boundaries for 'interval' parameter definition domain", "ERROR_PARAMDEF_CALC_UNDEFINED": "calculability of '%symbol%' parameter is undefined", "ERROR_PARAMDEF_VALUE_UNDEFINED": "value of '%symbol%' parameter is undefined", @@ -17,14 +18,14 @@ "ERROR_INTERVAL_UNDEF": "Interval: invalid 'undefined' value", "ERROR_INTERVAL_OUTSIDE": "Interval: value %value% is outside of %interval", "ERROR_LANG_UNSUPPORTED": "internationalisation: unsupported '%locale%' locale", - "ERROR_REMOUS_ARRET_CRITIQUE": "Calculation stopped: critical elevation reached at abscissa %x%", - "ERROR_REMOUS_CALCUL_FLUVIAL": "Downstream boundary condition >= Critical elevation: calculation of subcritical part from downstream", - "ERROR_REMOUS_CALCUL_TORRENTIEL": "Uptream boundary condition <= Critical elevation: calculation of supercritical part from upstream", - "ERROR_REMOUS_RESSAUT_DEHORS": "Hydraulic jump detected %sens% abscissa %x% m", - "ERROR_REMOUS_LARGEUR_BERGE": "Width at embankment level = %B% m", - "ERROR_REMOUS_H_CRITIQUE": "Width at embankment level = %Yc% m", - "ERROR_REMOUS_H_NORMALE": "Normal water level = %Yn% m", - "ERROR_REMOUS_RESSAUT_HYDRO": "Hydraulic jump detected between abscissa %xmin% and %xmax% m", + "WARNING_REMOUS_ARRET_CRITIQUE": "Calculation stopped: critical elevation reached at abscissa %x%", + "INFO_REMOUS_CALCUL_FLUVIAL": "Downstream boundary condition >= Critical elevation: calculation of subcritical part from downstream", + "INFO_REMOUS_CALCUL_TORRENTIEL": "Uptream boundary condition <= Critical elevation: calculation of supercritical part from upstream", + "INFO_REMOUS_RESSAUT_DEHORS": "Hydraulic jump detected %sens% abscissa %x% m", + "INFO_REMOUS_LARGEUR_BERGE": "Width at embankment level = %B% m", + "INFO_REMOUS_H_CRITIQUE": "Width at embankment level = %Yc% m", + "INFO_REMOUS_H_NORMALE": "Normal water level = %Yn% m", + "INFO_REMOUS_RESSAUT_HYDRO": "Hydraulic jump detected between abscissa %xmin% and %xmax% m", "ERROR_REMOUS_PENTE_FORTE": "The water line slope is too steep at abscissa %x% m (the discretisation step should be reduced)", "ERROR_REMOUS_PAS_CALCUL_DEPUIS_AVAL": "Downstream boundary condition < Critical elevation: no possible calculation from downstream", "ERROR_REMOUS_PAS_CALCUL_DEPUIS_AMONT": "Upstream boundary condition < Critical elevation: no possible calculation from upstream", @@ -71,6 +72,7 @@ "INFO_SETUP_TITLE": "Application setup", "INFO_SETUP_PRECISION_AFFICHAGE": "Display accuracy", "INFO_SETUP_PRECISION_CALCUL": "Computation accuracy", + "INFO_SETUP_NEWTON_MAX_ITER": "Newton iteration limit", "INFO_MENU_NOUVELLE_CALC": "New calculator", "INFO_CLOSE_DIALOGUE_TITRE": "Please confirm", "INFO_CLOSE_DIALOGUE_TEXT": "Warning ! Parameters and results will be lost. Really close?", diff --git a/src/locale/error_messages.fr.json b/src/locale/error_messages.fr.json index 13475608d9c7d04f65944390ea8a0007baa30404..0bbc5c5cab8c715ad9de510707ee27c4bc0961de 100644 --- a/src/locale/error_messages.fr.json +++ b/src/locale/error_messages.fr.json @@ -5,6 +5,7 @@ "ERROR_DICHO_NULL_STEP": "Dichotomie : le pas pour la recherche de l'intervalle de départ ne devrait pas être nul", "ERROR_DICHO_INVALID_STEP_GROWTH": "Dichotomie : l'augmentation du pas pour la recherche de l'intervalle de départ est incorrecte (=0)", "ERROR_DICHO_FUNCTION_VARIATION": "Dichotomie : impossible de determiner le sens de variation de la fonction", + "ERROR_NEWTON_DERIVEE_NULLE": "Dérivée nulle dans un calcul par la méthode de Newton", "ERROR_PARAMDOMAIN_INTERVAL_BOUNDS": "Les bornes (%minValue%/%maxValue%) de l'intervalle sont incorrectes", "ERROR_PARAMDEF_CALC_UNDEFINED": "La calculabilité du paramètre %symbol% n'est pas définie", "ERROR_PARAMDEF_VALUE_UNDEFINED": "La valeur du paramètre %symbol% n'est pas définie", @@ -17,14 +18,14 @@ "ERROR_INTERVAL_UNDEF": "Interval : valeur 'undefined' incorrecte", "ERROR_INTERVAL_OUTSIDE": "Interval : la valeur %value% est hors de l'intervalle %interval", "ERROR_LANG_UNSUPPORTED": "Internationalisation : locale '%locale%' non prise en charge", - "ERROR_REMOUS_ARRET_CRITIQUE": "Arrêt du calcul : hauteur critique atteinte à l'abscisse %x%", - "ERROR_REMOUS_CALCUL_FLUVIAL": "Condition limite aval >= Hauteur critique : calcul de la partie fluviale à partir de l'aval", - "ERROR_REMOUS_CALCUL_TORRENTIEL": "Condition limite amont <= Hauteur critique : calcul de la partie torrentielle à partir de l'amont", - "ERROR_REMOUS_RESSAUT_DEHORS": "Ressaut hydraulique détecté à l'%sens% de l'abscisse %x% m", - "ERROR_REMOUS_LARGEUR_BERGE": "Largeur au niveau des berges = %B% m", - "ERROR_REMOUS_H_CRITIQUE": "Tirant d'eau critique = %Yc% m", - "ERROR_REMOUS_H_NORMALE": "Tirant d'eau normal = %Yn% m", - "ERROR_REMOUS_RESSAUT_HYDRO": "Ressaut hydraulique détecté entre les abscisses %xmin% et %xmax% m", + "WARNING_REMOUS_ARRET_CRITIQUE": "Arrêt du calcul : hauteur critique atteinte à l'abscisse %x%", + "INFO_REMOUS_CALCUL_FLUVIAL": "Condition limite aval >= Hauteur critique : calcul de la partie fluviale à partir de l'aval", + "INFO_REMOUS_CALCUL_TORRENTIEL": "Condition limite amont <= Hauteur critique : calcul de la partie torrentielle à partir de l'amont", + "INFO_REMOUS_RESSAUT_DEHORS": "Ressaut hydraulique détecté à l'%sens% de l'abscisse %x% m", + "INFO_REMOUS_LARGEUR_BERGE": "Largeur au niveau des berges = %B% m", + "INFO_REMOUS_H_CRITIQUE": "Tirant d'eau critique = %Yc% m", + "INFO_REMOUS_H_NORMALE": "Tirant d'eau normal = %Yn% m", + "INFO_REMOUS_RESSAUT_HYDRO": "Ressaut hydraulique détecté entre les abscisses %xmin% et %xmax% m", "ERROR_REMOUS_PENTE_FORTE": "La pente de la ligne d'eau est trop forte à l'abscisse %x% m (il faudrait réduire le pas de discrétisation)", "ERROR_REMOUS_PAS_CALCUL_DEPUIS_AVAL": "Condition limite aval < Hauteur critique : pas de calcul possible depuis l'aval", "ERROR_REMOUS_PAS_CALCUL_DEPUIS_AMONT": "Condition limite amont > Hauteur critique : pas de calcul possible depuis l'amont", @@ -77,6 +78,7 @@ "INFO_SETUP_TITLE": "Paramètres de l'application", "INFO_SETUP_PRECISION_AFFICHAGE": "Précision d'affichage", "INFO_SETUP_PRECISION_CALCUL": "Précision de calcul", + "INFO_SETUP_NEWTON_MAX_ITER": "Newton : nombre d'itérations maximum", "INFO_MENU_NOUVELLE_CALC": "Nouvelle calculette", "INFO_CLOSE_DIALOGUE_TITRE": "Confirmer la fermeture", "INFO_CLOSE_DIALOGUE_TEXT": "Attention ! Les paramètres et résultats de la calculette seront perdus. Vraiment fermer ?", diff --git a/tsconfig.json b/tsconfig.json index 2efa5347ee856b98e099a3e9dd2592943a379ab9..efcc640cfdbc209ea2dc56a41820d56dbd55fdda 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,7 +7,7 @@ "moduleResolution": "node", "emitDecoratorMetadata": true, "experimentalDecorators": true, - "target": "es5", + "target": "es6", "typeRoots": [ "node_modules/@types" ],