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)&nbsp;:",
+    "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