From bccba9cd57d55cfef8bf77e1ab902cff45d472f6 Mon Sep 17 00:00:00 2001
From: "francois.grand" <francois.grand@irstea.fr>
Date: Thu, 28 Sep 2017 10:02:17 +0200
Subject: [PATCH] =?UTF-8?q?impl=C3=A9mentation=20de=20la=20d=C3=A9pendance?=
 =?UTF-8?q?=20d'existence=20sur=20param=C3=A8tre=20"=C3=A0=20varier"?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../generic/calculator.component.ts           |  10 +-
 src/app/calculators/generic/formulaire.ts     | 138 +++++++++++++++---
 src/app/calculators/generic/ngparam.ts        |  17 ++-
 .../section-param/section-param.config.json   | 104 +++++++++++++
 .../section-param/section-param.fr.json       |  21 ++-
 5 files changed, 260 insertions(+), 30 deletions(-)

diff --git a/src/app/calculators/generic/calculator.component.ts b/src/app/calculators/generic/calculator.component.ts
index 024fabbdb..a0ec553c1 100644
--- a/src/app/calculators/generic/calculator.component.ts
+++ b/src/app/calculators/generic/calculator.component.ts
@@ -117,14 +117,6 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, Observer {
         return undefined;
     }
 
-    private logObject(obj: {}, m?: string) {
-        // évite le message "Value below was evaluated just now" dans le debugger de Chrome
-        if (m == undefined)
-            console.log(JSON.stringify(obj));
-        else
-            console.log(m + " " + JSON.stringify(obj));
-    }
-
     /*
     private getHtmlElementFromId_helper(elm: HTMLElement, id: string): HTMLElement {
         if (elm.hasAttribute('id'))
@@ -253,6 +245,8 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, Observer {
 
         // this.appRef.tick();
         //        this.changeDetectorRef.detectChanges();  // provoque une détection des changements dans les contrôles
+
+        this.applyDependencies();
     }
 
     protected getParameterValue(symbol: string): number {
diff --git a/src/app/calculators/generic/formulaire.ts b/src/app/calculators/generic/formulaire.ts
index a18610654..d2a7c7657 100644
--- a/src/app/calculators/generic/formulaire.ts
+++ b/src/app/calculators/generic/formulaire.ts
@@ -85,14 +85,11 @@ export class FormulaireDefinition {
      * remet tous les paramètres à FIX sauf "me" et ceux (celui) à l'état "except"
      */
     public resetOther(me: NgParameter, except: ParamRadioConfig) {
-        // console.log("reset me=" + me.symbol + " sauf=" + ParamRadioConfig[except])
         for (let fs of this._fieldSets) {
             for (let p of fs.fields) {
                 if (p instanceof NgParameter)
-                    if (p != me && p.radioState != except && p.radioConfig != ParamRadioConfig.FIX) {
-                        // console.log("reset " + p.symbol + " st " + ParamRadioConfig[p.radioState] + " -> FIX");
+                    if (p != me && p.radioState != except && p.radioConfig != ParamRadioConfig.FIX)
                         p.radioState = ParamRadioConfig.FIX;
-                    }
             }
         }
     }
@@ -102,7 +99,6 @@ export class FormulaireDefinition {
      */
     public setDefault() {
         let defaultParamCal = this.getParamFromSymbol(this._defaultCalculatedParam);
-        // console.log("setdefault " + defaultParamCal.symbol + " -> CAL")
         defaultParamCal.radioState = ParamRadioConfig.CAL;
     }
 
@@ -164,8 +160,8 @@ export class FormulaireDefinition {
             let d = json[di];
             let masterField: FormulaireElement = this.getFormulaireElementById(d["refid"]);
             if (masterField != undefined) {
-                let dep = new ValueDependency(masterField, slave);
-                dep.masterValue = d["refvalue"];
+                let masterValue = d["refvalue"];
+                let dep = new ValueDependency(masterField, slave, masterValue);
                 dep.slaveValue = d["value"];
                 this._dependencies.push(dep);
             }
@@ -177,8 +173,29 @@ export class FormulaireDefinition {
             let d = json[di];
             let masterField: FormulaireElement = this.getFormulaireElementById(d["refid"]);
             if (masterField != undefined) {
-                let dep = new ExistenceDependency(masterField, slave);
-                dep.masterValue = d["refvalue"];
+                let rv = d["refvalue"];
+                if (rv != undefined)
+                    var mc: DependencyCondition = new ValueDependencyCondition(rv);
+                else {
+                    let cond = d["cond"];
+                    if (cond != undefined) {
+                        switch (cond) {
+                            case "isvar":
+                                var mc = new DependencyCondition(DependencyConditionType.IsVariable);
+                                break;
+
+                            case "isdisp":
+                                var mc = new DependencyCondition(DependencyConditionType.IsDisplayed);
+                                break;
+
+                            default:
+                                throw "Formulaire.parse_existence_dependencies() : type de condition '" + cond + "' non pris en charge";
+                        }
+                    }
+                    else
+                        throw "Formulaire.parse_existence_dependencies() : infos de dépendance manquantes/non prises en charge";
+                }
+                let dep = new ExistenceDependency(masterField, slave, mc);
                 this._dependencies.push(dep);
             }
         }
@@ -300,12 +317,17 @@ export class FormulaireDefinition {
                 }
             }
         }
+
+        // logObject(this._dependencies, "dependences");
     }
 
     private getDependencyFromMasterValue(v: any): Dependency {
         for (let d of this._dependencies)
-            if (d.masterValue === v)
-                return d;
+            if (d.masterCondition.type == DependencyConditionType.HasValue) {
+                let mv = (<ValueDependencyCondition>d.masterCondition).value;
+                if (mv === v)
+                    return d;
+            }
         return undefined;
     }
 
@@ -313,13 +335,24 @@ export class FormulaireDefinition {
         return Number(s) != NaN;
     }
 
+    private prepareExistenceDependencies() {
+        // si des FormulaireElement sont présents dans des ExistenceDependency, on met leur membre isDisplayed à false
+
+        for (let d of this.dependencies)
+            if (d instanceof ExistenceDependency) {
+                let slave: FormulaireElement = this.getFormulaireElementById(d.slaveElement.id);
+                slave.isDisplayed = false;
+            }
+    }
+
     public applyDependencies() {
+        this.prepareExistenceDependencies();
+
         for (let d of this.dependencies) {
-            let master = this.getFieldById(d.masterElement.id);
+            let master: FormulaireElement = this.getFormulaireElementById(d.masterElement.id);
             if (d instanceof ExistenceDependency) {
-                let slave = this.getFormulaireElementById(d.slaveElement.id);
-                let ed = <ExistenceDependency>d;
-                slave.isDisplayed = master.getValue() == ed.masterValue;
+                let slave: FormulaireElement = this.getFormulaireElementById(d.slaveElement.id);
+                slave.isDisplayed = slave.isDisplayed || master.verifiesDependency(d);
             }
             else if (d instanceof ValueDependency) {
                 let vd = <ValueDependency>d;
@@ -330,7 +363,7 @@ export class FormulaireDefinition {
                     this.setHtmlElementValue(slave, vd.slaveValue);
                 }
                 */
-                if (master.getValue() == vd.masterValue) {
+                if (master.verifiesDependency(d)) {
                     let slave = this.getFieldById(d.slaveElement.id);
                     if (this.isNumber(vd.slaveValue))
                         slave.setValue(+vd.slaveValue);
@@ -384,6 +417,15 @@ export abstract class FormulaireElement {
         return this._id;
     }
 
+    protected abstract verifyDependency(d: Dependency): boolean;
+
+    public verifiesDependency(d: Dependency): boolean {
+        if (d.masterCondition.type == DependencyConditionType.IsDisplayed)
+            return this.isDisplayed;
+
+        return this.verifyDependency(d);
+    }
+
     public abstract updateLocalisation(loc: StringMap): void;
 
     public toString() {
@@ -447,6 +489,10 @@ export class FieldSet extends FormulaireElement {
         return undefined;
     }
 
+    protected verifyDependency(d: Dependency): boolean {
+        throw "FieldSet.verifyDependency() : type de condition '" + DependencyConditionType[d.masterCondition.type] + "' non pris en charge";
+    }
+
     public updateLocalisation(loc: StringMap) {
         this.label = loc[this.id];
     }
@@ -500,6 +546,17 @@ export class SelectField extends Field {
             }
     }
 
+    protected verifyDependency(d: Dependency): boolean {
+        switch (d.masterCondition.type) {
+            case DependencyConditionType.HasValue:
+                let mc: ValueDependencyCondition = <ValueDependencyCondition>d.masterCondition;
+                return this.selectedEntry.value === mc.value;
+
+            default:
+                throw "SelectField.verifyDependency() : type de condition '" + DependencyConditionType[d.masterCondition.type] + "' non pris en charge";
+        }
+    }
+
     public updateLocalisation(loc: StringMap) {
         this.label = loc[this.id];
         for (let e of this._entries) {
@@ -508,7 +565,7 @@ export class SelectField extends Field {
     }
 }
 
-export class InputField extends Field {
+export abstract class InputField extends Field {
     private _value: any;
 
     constructor(type: ComputeNodeType, id: string) {
@@ -528,15 +585,48 @@ export class InputField extends Field {
     }
 }
 
+export enum DependencyConditionType {
+    HasValue, IsVariable, IsDisplayed
+}
+
+export class DependencyCondition {
+    constructor(private _type: DependencyConditionType) {
+    }
+
+    public get type() {
+        return this._type;
+    }
+
+    public toString(): string {
+        return "cond=" + DependencyConditionType[this._type];
+    }
+}
+
+export class ValueDependencyCondition extends DependencyCondition {
+    constructor(private _value: any) {
+        super(DependencyConditionType.HasValue);
+    }
+
+    public get value(): any {
+        return this._value;
+    }
+
+    public toString(): string {
+        return super.toString() + " " + this._value;
+    }
+}
+
 export abstract class Dependency {
     private _master: FormulaireElement;
-    public masterValue: any;
 
     private _slave: FormulaireElement;
 
-    constructor(m: FormulaireElement, s: FormulaireElement) {
+    private _masterCondition: DependencyCondition;
+
+    constructor(m: FormulaireElement, s: FormulaireElement, mc: DependencyCondition) {
         this._master = m;
         this._slave = s;
+        this._masterCondition = mc;
     }
 
     public get masterElement(): FormulaireElement {
@@ -547,14 +637,22 @@ export abstract class Dependency {
         return this._slave;
     }
 
+    public get masterCondition(): DependencyCondition {
+        return this._masterCondition;
+    }
+
     public toString(): string {
-        return "master=" + this._master.toString() + "\n  master val:" + this.masterValue + "\n  slave=" + this._slave.toString();
+        return "master=" + this._master.toString() + "\n  " + this._masterCondition.toString() + "\n  slave=" + this._slave.toString();
     }
 }
 
 export class ValueDependency extends Dependency {
     public slaveValue: any;
 
+    constructor(m: FormulaireElement, s: FormulaireElement, masterValue: any) {
+        super(m, s, new ValueDependencyCondition(masterValue));
+    }
+
     public toString() {
         return "valdep\n  " + super.toString() + "\n  slave val " + this.slaveValue;
     }
diff --git a/src/app/calculators/generic/ngparam.ts b/src/app/calculators/generic/ngparam.ts
index 4fda34057..f477e9ec5 100644
--- a/src/app/calculators/generic/ngparam.ts
+++ b/src/app/calculators/generic/ngparam.ts
@@ -1,6 +1,6 @@
 import { ComputeNodeType, ParamDefinition, ParamDomainValue, ErrorMessage } from 'jalhyd';
 
-import { InputField } from './formulaire';
+import { InputField, Dependency, DependencyConditionType, ValueDependencyCondition } from './formulaire';
 import { StringMap } from '../../stringmap';
 
 export enum ParamRadioConfig {
@@ -94,6 +94,21 @@ export class NgParameter extends InputField {
         throw "invalid parameter radio configuration " + s;
     }
 
+    protected verifyDependency(d: Dependency): boolean {
+        switch (d.masterCondition.type) {
+            case DependencyConditionType.HasValue:
+                {
+                    let mc: ValueDependencyCondition = <ValueDependencyCondition>d.masterCondition;
+                    return this.getValue() === mc.value;
+                }
+
+            case DependencyConditionType.IsVariable:
+                return this.radioState == ParamRadioConfig.VAR;
+
+            default:
+                throw "NgParameter.verifyDependency() : type de condition '" + DependencyConditionType[d.masterCondition.type] + "' non pris en charge";
+        }
+    }
 
     public updateLocalisation(loc: StringMap) {
         this.label = loc[this.id];
diff --git a/src/app/calculators/section-param/section-param.config.json b/src/app/calculators/section-param/section-param.config.json
index 962648469..081004b8c 100644
--- a/src/app/calculators/section-param/section-param.config.json
+++ b/src/app/calculators/section-param/section-param.config.json
@@ -164,6 +164,110 @@
             }
         ]
     },
+    {
+        "id": "fs_computed_var",
+        "dep_exist": [
+            {
+                "refid": "LargeurFond",
+                "cond": "isvar"
+            },
+            {
+                "refid": "Fruit",
+                "cond": "isvar"
+            },
+            {
+                "refid": "D",
+                "cond": "isvar"
+            },
+            {
+                "refid": "k",
+                "cond": "isvar"
+            },
+            {
+                "refid": "LargeurBerge",
+                "cond": "isvar"
+            },
+            {
+                "refid": "Ks",
+                "cond": "isvar"
+            },
+            {
+                "refid": "If",
+                "cond": "isvar"
+            },
+            {
+                "refid": "YB",
+                "cond": "isvar"
+            },
+            {
+                "refid": "Q",
+                "cond": "isvar"
+            },
+            {
+                "refid": "Y",
+                "cond": "isvar"
+            }
+        ],
+        "fields": [
+            {
+                "id": "select_target",
+                "type": "select",
+                "select": [
+                    {
+                        "id": "select_target_hs"
+                    },
+                    {
+                        "id": "select_target_hsc"
+                    },
+                    {
+                        "id": "select_target_b"
+                    },
+                    {
+                        "id": "select_target_p"
+                    },
+                    {
+                        "id": "select_target_s"
+                    },
+                    {
+                        "id": "select_target_r"
+                    },
+                    {
+                        "id": "select_target_v"
+                    },
+                    {
+                        "id": "select_target_fr"
+                    },
+                    {
+                        "id": "select_target_yc"
+                    },
+                    {
+                        "id": "select_target_yn"
+                    },
+                    {
+                        "id": "select_target_yf"
+                    },
+                    {
+                        "id": "select_target_yt"
+                    },
+                    {
+                        "id": "select_target_yco"
+                    },
+                    {
+                        "id": "select_target_j"
+                    },
+                    {
+                        "id": "select_target_i_j"
+                    },
+                    {
+                        "id": "select_target_imp"
+                    },
+                    {
+                        "id": "select_target_tau0"
+                    }
+                ]
+            }
+        ]
+    },
     {
         "id": "options",
         "nodeType": "SectionParametree"
diff --git a/src/app/calculators/section-param/section-param.fr.json b/src/app/calculators/section-param/section-param.fr.json
index 51a2fd90c..c8130d2eb 100644
--- a/src/app/calculators/section-param/section-param.fr.json
+++ b/src/app/calculators/section-param/section-param.fr.json
@@ -22,5 +22,24 @@
     "Q": "Débit",
     "Y": "Tirant d'eau",
     "fs_param_calc": "Paramètres de calcul",
-    "Pr": "Précision de calcul"
+    "Pr": "Précision de calcul",
+    "fs_computed_var": "Donnée à calculer",
+    "select_target": "Choix de la donnée à calculer",
+    "select_target_hs": "La charge spécifique (m)",
+    "select_target_hsc": "La charge critique (m)",
+    "select_target_b": "La largeur au miroir (m)",
+    "select_target_p": "Le périmètre mouillé (m)",
+    "select_target_s": "La surface mouillée (m2)",
+    "select_target_r": "Le rayon hydraulique (m)",
+    "select_target_v": "La vitesse moyenne (m/s)",
+    "select_target_fr": "Le Froude",
+    "select_target_yc": "Le tirant d'eau critique (m)",
+    "select_target_yn": "Le tirant d'eau normal (m)",
+    "select_target_yf": "Le tirant d'eau fluvial (m)",
+    "select_target_yt": "Le tirant d'eau torrentiel (m)",
+    "select_target_yco": "Le tirant d'eau conjugué (m)",
+    "select_target_j": "La perte de charge (m)",
+    "select_target_i_j": "Variation linéaire de l'énergie spécifique (m/m)",
+    "select_target_imp": "Impulsion (m/m)",
+    "select_target_tau0": "La force tractrice (N)"
 }
\ No newline at end of file
-- 
GitLab