From 0084a0c54e89395ec68aeb23f3072273670eacd9 Mon Sep 17 00:00:00 2001 From: Mathias Chouet <mathias.chouet@irstea.fr> Date: Tue, 19 May 2020 14:48:58 +0200 Subject: [PATCH 1/4] Update jalhyd_branch --- jalhyd_branch | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/jalhyd_branch b/jalhyd_branch index 989a06763..1e054d20c 100644 --- a/jalhyd_branch +++ b/jalhyd_branch @@ -1,2 +1 @@ -214-regime-uniforme-conduite-circulaire-provoquer-une-erreur-fatale-si-la-conduite-est-en-charge - +223-calage-d-une-par-remplacer-la-cote-de-deversement-par-la-charge -- GitLab From 39b5c1dba8f53c0736c9ca1f8b99b0504294f17d Mon Sep 17 00:00:00 2001 From: Mathias Chouet <mathias.chouet@irstea.fr> Date: Tue, 19 May 2020 17:06:14 +0200 Subject: [PATCH 2/4] Par: replace ZD1 with ha (see jalhyd#223) --- src/app/calculators/par/config.json | 2 +- src/app/calculators/par/en.json | 4 ++-- src/app/calculators/par/fr.json | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app/calculators/par/config.json b/src/app/calculators/par/config.json index 21944de32..7834b616e 100644 --- a/src/app/calculators/par/config.json +++ b/src/app/calculators/par/config.json @@ -21,7 +21,7 @@ "property": "parType", "default": "PLANE" }, - "ZD1", + "ha", "S", { "id": "P", diff --git a/src/app/calculators/par/en.json b/src/app/calculators/par/en.json index 6274ab345..dea01abe1 100644 --- a/src/app/calculators/par/en.json +++ b/src/app/calculators/par/en.json @@ -7,7 +7,7 @@ "fs_geometry": "Pass geometry", - "ZD1": "Upstream spilling elevation", + "ha": "Upstream head", "S": "Slope", "P": "Space between baffles", "L": "Total width of baffle / pattern (superactive)", @@ -16,7 +16,7 @@ "M": "Number of longitudinal strips", "h": "Water level in the pass", - "ha": "Upstream head", + "ZD1": "Upstream spilling elevation", "qStar": "Dimensionless flow", "V": "Flow velocity", "Nb": "Number of baffles", diff --git a/src/app/calculators/par/fr.json b/src/app/calculators/par/fr.json index 027b8097a..120e429b1 100644 --- a/src/app/calculators/par/fr.json +++ b/src/app/calculators/par/fr.json @@ -7,7 +7,7 @@ "fs_geometry": "Géométrie de la passe", - "ZD1": "Cote de déversement à l'amont", + "ha": "Charge amont", "S": "Pente", "P": "Espacement entre les ralentisseurs", "L": "Largeur totale du ralentisseur / du motif (suractifs)", @@ -16,7 +16,7 @@ "M": "Nombre de bandes longitudinales", "h": "Hauteur d'eau dans la passe", - "ha": "Charge amont", + "ZD1": "Cote de déversement à l'amont", "qStar": "Débit adimensionnel", "V": "Vitesse débitante", "Nb": "Nombre de ralentisseurs", -- GitLab From 8820bc7d590c486c10f4c20a5bc0697a74cb29c6 Mon Sep 17 00:00:00 2001 From: Mathias Chouet <mathias.chouet@irstea.fr> Date: Wed, 20 May 2020 14:34:39 +0200 Subject: [PATCH 3/4] Generate PAR Sim from PAR: popup for variating values --- src/app/app.module.ts | 3 + src/app/calculators/par/config.json | 5 +- ...log-generate-par-simulation.component.html | 28 +++++ ...log-generate-par-simulation.component.scss | 11 ++ ...ialog-generate-par-simulation.component.ts | 109 ++++++++++++++++ .../calculator.component.ts | 119 +++++++++++++----- .../formulaire/definition/form-definition.ts | 2 +- src/locale/messages.en.json | 3 + src/locale/messages.fr.json | 3 + 9 files changed, 249 insertions(+), 34 deletions(-) create mode 100644 src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.html create mode 100644 src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.scss create mode 100644 src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 8509d10d6..15ede0e09 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -100,6 +100,7 @@ import { DialogEditPabComponent } from "./components/dialog-edit-pab/dialog-edit import { DialogEditParamComputedComponent } from "./components/dialog-edit-param-computed/dialog-edit-param-computed.component"; import { DialogEditParamValuesComponent } from "./components/dialog-edit-param-values/dialog-edit-param-values.component"; import { DialogGeneratePABComponent } from "./components/dialog-generate-pab/dialog-generate-pab.component"; +import { DialogGeneratePARSimulationComponent } from "./components/dialog-generate-par-simulation/dialog-generate-par-simulation.component"; import { DialogLoadSessionComponent } from "./components/dialog-load-session/dialog-load-session.component"; import { DialogLogEntriesDetailsComponent } from "./components/dialog-log-entries-details/dialog-log-entries-details.component"; import { DialogSaveSessionComponent } from "./components/dialog-save-session/dialog-save-session.component"; @@ -189,6 +190,7 @@ const appRoutes: Routes = [ DialogEditParamComputedComponent, DialogEditParamValuesComponent, DialogGeneratePABComponent, + DialogGeneratePARSimulationComponent, DialogLoadSessionComponent, DialogLogEntriesDetailsComponent, DialogSaveSessionComponent, @@ -240,6 +242,7 @@ const appRoutes: Routes = [ DialogEditParamComputedComponent, DialogEditParamValuesComponent, DialogGeneratePABComponent, + DialogGeneratePARSimulationComponent, DialogSaveSessionComponent, DialogLoadSessionComponent, DialogLogEntriesDetailsComponent diff --git a/src/app/calculators/par/config.json b/src/app/calculators/par/config.json index 7834b616e..3d592b2bd 100644 --- a/src/app/calculators/par/config.json +++ b/src/app/calculators/par/config.json @@ -4,7 +4,10 @@ "type": "fieldset", "fields": [ "Q", - "Z1", + { + "id": "Z1", + "allowEmpty": true + }, { "id": "Z2", "allowEmpty": true diff --git a/src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.html b/src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.html new file mode 100644 index 000000000..3f42734c8 --- /dev/null +++ b/src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.html @@ -0,0 +1,28 @@ +<h1 mat-dialog-title [innerHTML]="uitextGeneratePARSimulation"></h1> + +<form id="form-generate-par-simulation"> + + <div mat-dialog-content> + <div id="generate-par-sim-desc"> + {{ uitextDescription }} + </div> + <mat-form-field> + <mat-select id="select-combination" [placeholder]="label" [(value)]="selectedValue"> + <mat-option *ngFor="let e of entries" [value]="e" [title]="entryLabel(e)"> + {{ entryLabel(e) }} + </mat-option> + </mat-select> + </mat-form-field> + </div> + + <div mat-dialog-actions [attr.align]="'end'"> + <button mat-raised-button color="primary" [mat-dialog-close]="false" cdkFocusInitial> + {{ uitextCancel }} + </button> + <button mat-raised-button type="submit" color="warn" (click)="generatePARSimulation()" id="do-generate" + [disabled]=""> + {{ uitextGenerate }} + </button> + </div> + +</form> diff --git a/src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.scss b/src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.scss new file mode 100644 index 000000000..6fc610865 --- /dev/null +++ b/src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.scss @@ -0,0 +1,11 @@ +#form-generate-par-simulation { + max-width: 500px; +} + +mat-form-field { + width: 100%; +} + +#generate-par-sim-desc { + margin-bottom: 1em; +} diff --git a/src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.ts b/src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.ts new file mode 100644 index 000000000..dcb956902 --- /dev/null +++ b/src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.ts @@ -0,0 +1,109 @@ +import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog"; +import { Inject, Component } from "@angular/core"; + +import { I18nService } from "../../services/internationalisation.service"; +import { MultiDimensionResults } from "../../results/multidimension-results"; + +import { fv, longestVarNgParam } from "../../util"; + +@Component({ + selector: "dialog-generate-par-simulation", + templateUrl: "dialog-generate-par-simulation.component.html", + styleUrls: ["dialog-generate-par-simulation.component.scss"] +}) +export class DialogGeneratePARSimulationComponent { + + public selectedValue: number; + + /** résultats de la ParCalage */ + private _results: MultiDimensionResults; + + /** size of the longest variable value */ + private size = 0; + + /** inferred extended values list for each variating parameter */ + private varValues = []; + + constructor( + public dialogRef: MatDialogRef<DialogGeneratePARSimulationComponent>, + private intlService: I18nService, + @Inject(MAT_DIALOG_DATA) public data: any + ) { + this._results = data.results; + this.selectedValue = 0; + + if (this._results) { + // pre-extract variable parameters values + this.varValues = []; + // find longest list + const lvp = longestVarNgParam(this._results.variatedParameters); + this.size = lvp.size; + // get extended values lists for each variable parameter + for (const v of this._results.variatedParameters) { + const vv = []; + const iter = v.getExtendedValuesIterator(this.size); + while (iter.hasNext) { + const nv = iter.next(); + vv.push(fv(nv.value)); + } + this.varValues.push(vv); + } + } + } + + public generatePARSimulation() { + this.dialogRef.close({ + generate: true, + selected: this.selectedValue, + size: this.size + }); + } + + public get uitextDescription() { + return this.intlService.localizeText("INFO_DIALOG_PARSIM_DESC"); + } + + public get uitextGeneratePARSimulation() { + return this.intlService.localizeText("INFO_CALCULATOR_RESULTS_GENERATE_PAR_SIMULATION"); + } + + public get uitextGenerate() { + return this.intlService.localizeText("INFO_OPTION_GENERATE"); + } + + public get uitextCancel() { + return this.intlService.localizeText("INFO_OPTION_CANCEL"); + } + + public get entries(): number[] { + const ret: number[] = []; + for (let i = 0; i < this.size; i++) { + ret.push(i); + } + return ret; + } + + protected entryLabel(index: number): string { + const kv = []; + for (let i = 0; i < this.varValues.length; i++) { + const vv = this.varValues[i]; + const vp = this._results.variatedParameters[i]; + let symbol = vp.symbol; + // is vp a parameter of a child Nub ? + if ( + vp.paramDefinition.parentNub + && vp.paramDefinition.parentNub !== vp.paramDefinition.originNub + ) { + const pos = vp.paramDefinition.parentNub.findPositionInParent() + 1; + symbol = this.intlService.localizeText("INFO_LIB_RADIER_N_COURT") + pos + "_" + symbol; + } + kv.push(`${symbol} = ${vv[index]}`); + } + return kv.join(", "); + } + + public get label() { + return this.intlService.localizeText("INFO_PARAMFIELD_BOUNDARY_CONDITIONS"); + } + +} diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts index 6e9adab42..53894e408 100644 --- a/src/app/components/generic-calculator/calculator.component.ts +++ b/src/app/components/generic-calculator/calculator.component.ts @@ -40,7 +40,10 @@ import { PabTableComponent } from "../pab-table/pab-table.component"; import { MatDialog } from "@angular/material/dialog"; import { DialogConfirmCloseCalcComponent } from "../dialog-confirm-close-calc/dialog-confirm-close-calc.component"; import { DialogGeneratePABComponent } from "../dialog-generate-pab/dialog-generate-pab.component"; +import { DialogGeneratePARSimulationComponent } from "../dialog-generate-par-simulation/dialog-generate-par-simulation.component"; import { PabTable } from "../../formulaire/elements/pab-table"; +import { MultiDimensionResults } from "../../results/multidimension-results"; +import { NgParameter } from "../../formulaire/elements/ngparam"; import { HotkeysService, Hotkey } from "angular2-hotkeys"; @@ -124,6 +127,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe private router: Router, private confirmCloseCalcDialog: MatDialog, private generatePABDialog: MatDialog, + private generatePARSimulationDialog: MatDialog, private _elementRef: ElementRef, private hotkeysService: HotkeysService, private appSetupService: ApplicationSetupService, @@ -849,58 +853,109 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe return ( this.hasResults && ! parCalage.result.hasErrorMessages() - && this.allParamsAreFixed([ "Z1", "Q" ]) // only Z1 and Q may vary + && parCalage.prms.Z1.isDefined + && parCalage.prms.Z2.isDefined ); } public get uitextGenerateParSimulationTitle(): string { - if (! this.allParamsAreFixed([ "Z1", "Q" ])) { - return this.intlService.localizeText("INFO_ONLY_Z1_Q_MAY_VARY"); - } const parCalage = (this._formulaire.currentNub as Par); if (! this.hasResults || parCalage.result.hasErrorMessages()) { return this.intlService.localizeText("INFO_CALCULATE_FIRST"); } + if ( + parCalage.prms.Z1.isDefined + || parCalage.prms.Z2.isDefined + ) { + return this.intlService.localizeText("INFO_Z1_Z2_MUST_BE_DEFINED"); + } return ""; } /** - * Génère une simulation de passe à ralentisseurs à partir du calage en cours + * Génère une simulation de passe à ralentisseurs à partir du calage en cours; si + * au moins un paramètre varie, propose de choisir parmi les combinaisons de valeurs */ public generatePARSimulation() { const parCalage = (this._formulaire.currentNub as Par); const pcal = parCalage.prms; - // copy base params + let pres: { [key: string]: number } = parCalage.result.values; + + const varParams: NgParameter[] = this._formulaire.getVariatedParameters(); + if (varParams.length > 0) { + // open popup to choose combination of varying parameters + const mdParResults = new MultiDimensionResults(); + mdParResults.variatedParameters = varParams; + const dialogRef = this.generatePARSimulationDialog.open( + DialogGeneratePARSimulationComponent, + { + data: { + results: mdParResults + }, + disableClose: false + } + ); + dialogRef.afterClosed().subscribe(result => { + if (result && result.generate) { + const i = result.selected; + const s = result.size; // longest variating series, ie. number of iterations + pres = parCalage.result.resultElements[i].values; + // generate set of fixed values from chosen iteration i + this.doGenerateParSimWithValues({ + Q: pcal.Q.isCalculated ? pres.Q : (pcal.Q.hasMultipleValues ? pcal.Q.getInferredValuesList(s)[i] : pcal.Q.V), + Z1: pcal.Z1.hasMultipleValues ? pcal.Z1.getInferredValuesList(s)[i] : pcal.Z1.V, + Z2: pcal.Z2.hasMultipleValues ? pcal.Z2.getInferredValuesList(s)[i] : pcal.Z2.V, + S: pcal.S.hasMultipleValues ? pcal.S.getInferredValuesList(s)[i] : pcal.S.V, + P: pcal.P.hasMultipleValues ? pcal.P.getInferredValuesList(s)[i] : pcal.P.V, + L: pcal.L.isCalculated ? pres.L : (pcal.L.hasMultipleValues ? pcal.L.getInferredValuesList(s)[i] : pcal.L.V), + N: pcal.N.hasMultipleValues ? pcal.N.getInferredValuesList(s)[i] : pcal.N.V, + M: pcal.M.hasMultipleValues ? pcal.M.getInferredValuesList(s)[i] : pcal.M.V, + Nb: pres.Nb, + ZR1: pres.ZR1, + ZD1: pres.ZD1, + ZR2: pres.ZR2, + ZD2: pres.ZD2, + a: pres.a + }); + } + }); + } else { + // no parameter is varyng, generate directly + this.doGenerateParSimWithValues({ + Q: pcal.Q.V, + Z1: pcal.Z1.singleValue, + Z2: pcal.Z2.singleValue, + S: pcal.S.singleValue, + P: pcal.P.singleValue, + L: pcal.L.V, + N: pcal.Q.singleValue, + M: pcal.Q.singleValue, + Nb: pres.Nb, + ZR1: pres.ZR1, + ZD1: pres.ZD1, + ZR2: pres.ZR2, + ZD2: pres.ZD2, + a: pres.a + }); + } + } + + /** + * Creates a new Formulaire with a ParSimulation Nub, using given + * values as parameters + */ + protected doGenerateParSimWithValues(v: any) { + const parCalage = (this._formulaire.currentNub as Par); const psim = new ParSimulationParams( - undefined, // Q - undefined, // Z1 - pcal.Z2.singleValue, pcal.S.singleValue, pcal.P.singleValue, - undefined, // Nb - undefined, // ZR1 - pcal.ZD1.singleValue, - undefined, // ZR2 - undefined, // ZD2 - pcal.L.singleValue, pcal.a.singleValue, pcal.N.singleValue, pcal.M.singleValue + round(v.Q, 3), round(v.Z1, 3), round(v.Z2, 3), + round(v.S, 3), round(v.P, 3), round(v.Nb, 3), + round(v.ZR1, 3), round(v.ZD1, 3), round(v.ZR2, 3), + round(v.ZD2, 3), round(v.L, 3), round(v.a, 3), + round(v.N, 3), round(v.M, 3) ); const parSimulation = new ParSimulation(psim); - Session.getInstance().registerNub(parSimulation); - - // copy other params parSimulation.parType = parCalage.parType; - // Z1 and Q, that might be variating - psim.Z1.copyValuesFrom(pcal.Z1); - psim.Q.copyValuesFrom(pcal.Q); - // P, Nb, ZR1 - if (pcal.P.singleValue === undefined) { - psim.P.singleValue = round(parCalage.result.values.P, 3); - } - psim.Nb.singleValue = parCalage.result.values.Nb; - psim.ZR1.singleValue = round(parCalage.result.values.ZR1, 3); - // ZR2, ZD2 - if (pcal.Z2.singleValue !== undefined) { - psim.ZD2.singleValue = round(parCalage.result.values.ZD2, 3); - psim.ZR2.singleValue = round(parCalage.result.values.ZR2, 3); - } + Session.getInstance().registerNub(parSimulation); this.formulaireService.createFormulaire(CalculatorType.ParSimulation, parSimulation) .then((f: FormulaireDefinition) => { diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts index 4c55719f1..3cb94b538 100644 --- a/src/app/formulaire/definition/form-definition.ts +++ b/src/app/formulaire/definition/form-definition.ts @@ -516,7 +516,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs return ngparam; } - protected getVariatedParameters(): NgParameter[] { + public getVariatedParameters(): NgParameter[] { let res: NgParameter[] = []; // find variated local parameters res = this.getDisplayedParamListFromState(ParamRadioConfig.VAR); diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json index 31b17ed80..6b1e26841 100644 --- a/src/locale/messages.en.json +++ b/src/locale/messages.en.json @@ -173,6 +173,7 @@ "INFO_CHILD_TYPE_MACRORUGO_PLUR": "aprons", "INFO_CHILD_TYPE_PUISSANCE": "power", "INFO_CHILD_TYPE_PUISSANCE_PLUR": "powers", + "INFO_DIALOG_PARSIM_DESC": "Choose a combination of values to generate the simulation", "INFO_FIELDSET_ADD": "Add", "INFO_FIELDSET_COPY": "Copy", "INFO_FIELDSET_REMOVE": "Remove", @@ -333,7 +334,9 @@ "INFO_MACRORUGOCOMPOUND_TITRE": "Compound rock-ramp fishpasses", "INFO_MACRORUGOCOMPOUND_TITRE_COURT": "Compound RR", "INFO_MACRORUGOCOMPOUND_LINCL": "Lateral inclination (m/m): ", + "INFO_ONLY_Q_MAY_VARY": "Only flow may vary", "INFO_ONLY_Z1_Q_MAY_VARY": "Only upstream elevation and flow may vary", + "INFO_Z1_Z2_MUST_BE_DEFINED": "Upstream and downstream elevations must be defined", "INFO_PENTE_TITRE": "Slope", "INFO_PENTE_TITRE_COURT": "Slope", "INFO_MENU_EMPTY_SESSION_TITLE": "New session", diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json index c0c908e86..74c306b9e 100644 --- a/src/locale/messages.fr.json +++ b/src/locale/messages.fr.json @@ -173,6 +173,7 @@ "INFO_CHILD_TYPE_MACRORUGO_PLUR": "radiers", "INFO_CHILD_TYPE_PUISSANCE": "puissance", "INFO_CHILD_TYPE_PUISSANCE_PLUR": "puissances", + "INFO_DIALOG_PARSIM_DESC": "Choisir une combinaison de valeurs pour générer la simulation", "INFO_FIELDSET_ADD": "Ajouter", "INFO_FIELDSET_COPY": "Copier", "INFO_FIELDSET_REMOVE": "Supprimer", @@ -333,7 +334,9 @@ "INFO_MACRORUGOCOMPOUND_TITRE": "Passe à macro-rugosités complexe", "INFO_MACRORUGOCOMPOUND_TITRE_COURT": "M-Rugo complexe", "INFO_MACRORUGOCOMPOUND_LINCL": "Dévers latéral (m/m) :", + "INFO_ONLY_Q_MAY_VARY": "Seul le débit peut varier", "INFO_ONLY_Z1_Q_MAY_VARY": "Seuls la cote amont et le débit peuvent varier", + "INFO_Z1_Z2_MUST_BE_DEFINED": "Les cotes amont et aval doivent être définies", "INFO_PENTE_TITRE": "Pente", "INFO_PENTE_TITRE_COURT": "Pente", "INFO_MENU_EMPTY_SESSION_TITLE": "Nouvelle session", -- GitLab From dfe516479326f3f8623ae6e15cb7957e4c41a6eb Mon Sep 17 00:00:00 2001 From: Mathias Chouet <mathias.chouet@irstea.fr> Date: Wed, 20 May 2020 15:55:53 +0200 Subject: [PATCH 4/4] Fix missing translation --- e2e/check-translations.e2e-spec.ts | 6 +++++- .../components/generic-calculator/calculator.component.ts | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/e2e/check-translations.e2e-spec.ts b/e2e/check-translations.e2e-spec.ts index b16c9a56d..ddcd763d3 100644 --- a/e2e/check-translations.e2e-spec.ts +++ b/e2e/check-translations.e2e-spec.ts @@ -77,7 +77,11 @@ describe("ngHyd − check translation of all calculators", () => { } // check absence of "*** message not found" in whole DOM - expect(await browser.getPageSource()).not.toContain("*** message not found"); + const ps = await browser.getPageSource(); + expect(ps).not.toContain("*** message not found"); + /* const pos = ps.indexOf("*** message not found"); + const bout = ps.substring(pos - 50, pos + 50); + console.log("------------ BOUT ---------------", bout); */ // empty session await navBar.clickMenuButton(); diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts index 53894e408..a72bd526e 100644 --- a/src/app/components/generic-calculator/calculator.component.ts +++ b/src/app/components/generic-calculator/calculator.component.ts @@ -814,7 +814,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe public get uitextGenerateRuSpTitle(): string { if (! this.generateRuSpEnabled) { - return this.intlService.localizeText("INFO_CALCULER_D_ABORD"); + return this.intlService.localizeText("INFO_CALCULATE_FIRST"); } else { return ""; } -- GitLab