From c6b23ef251172e6855189c29343ab75cb16579e4 Mon Sep 17 00:00:00 2001
From: "francois.grand" <francois.grand@irstea.fr>
Date: Wed, 13 Jun 2018 10:50:58 +0200
Subject: [PATCH] =?UTF-8?q?=20#45=20ajout=20d'un=20test=20unitaire=20de=20?=
 =?UTF-8?q?r=C3=A9f=C3=A9rence=20=C3=A0=20un=20r=C3=A9sultat=20de=20calul?=
 =?UTF-8?q?=20multivalu=C3=A9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../value_ref_variable_result.spec.ts         | 66 +++++++++++++++++++
 src/nub.ts                                    | 21 +++++-
 src/param/param-base.ts                       | 15 ++++-
 src/param/param-value-iterator.ts             |  7 ++
 src/param/param-values.ts                     | 16 ++++-
 src/util/result.ts                            | 12 +++-
 src/value_ref/object_ref.ts                   | 17 +++++
 7 files changed, 148 insertions(+), 6 deletions(-)
 create mode 100644 spec/value_ref/value_ref_variable_result.spec.ts

diff --git a/spec/value_ref/value_ref_variable_result.spec.ts b/spec/value_ref/value_ref_variable_result.spec.ts
new file mode 100644
index 00000000..14f325ef
--- /dev/null
+++ b/spec/value_ref/value_ref_variable_result.spec.ts
@@ -0,0 +1,66 @@
+import { ConduiteDistrib } from "../../src/cond_distri";
+import { ConduiteDistribParams } from "../../src/cond_distri";
+import { ParamValueMode } from "../../src";
+
+/**
+ * IMPORTANT !
+ * Décommenter temporairement la ligne suivante (import { } from "./mock_jasmine")
+ * Pour exécuter ce code dans le débugger.
+ * Faire de même avec le fichier test_func.ts
+ */
+// import { describe, expect, it, xdescribe, xit } from "../mock_jasmine";
+
+let nub1: ConduiteDistrib;
+let nub2: ConduiteDistrib;
+let prm1: ConduiteDistribParams;
+let prm2: ConduiteDistribParams;
+
+/**
+ * crée l'environnement de test.
+ * répété à chaque test car il manque un mock de beforeEach
+ */
+function createEnv() {
+    // Nub maître
+    nub1 = new ConduiteDistrib(new ConduiteDistribParams(3, 1.2, 0.6, 100, 0.000001));
+    prm1 = nub1.parameters as ConduiteDistribParams;
+
+    // Nub esclave
+    nub2 = new ConduiteDistrib(new ConduiteDistribParams(3, 1.2, 0.6, 100, 0.000001));
+    prm2 = nub2.parameters as ConduiteDistribParams;
+}
+
+describe("référence d'un paramètre à un résultat multivalué : ", () => {
+    it("test 1", () => {
+        // cas de figure :
+        // nub2.Q est lié au résultat J de nub1
+        // lecture de nub2.Q
+
+        createEnv();
+
+        prm1.Q.paramValues.valueMode = ParamValueMode.MINMAX;
+        prm1.Q.paramValues.min = 1.5;
+        prm1.Q.paramValues.max = 6;
+        prm1.Q.paramValues.step = 0.5;
+        prm2.Q.defineReference(nub1, "J");
+
+        const expectedJ: number[] = [0.024202971271651448, 0.04004160474685753, 0.059170330781816, 0.08140876712328136, 0.10661739314398751, 0.1346833675705545, 0.16551253143900968, 0.19902447617522237, 0.23514929908544743, 0.273825361776767];
+
+        const res = nub1.CalcSerie(0.001, 0.6, "J");
+        let i = 0;
+        for (const re of res.resultElements)
+            // console.log(re.vCalc);
+            expect(re.vCalc).toEqual(expectedJ[i++]);
+
+        i = 0;
+        for (const v of res.valuesIterator)
+            expect(v).toEqual(expectedJ[i++]);
+
+        // i = 0;
+        // for (const v of prm1.J.valuesIterator)
+        //     expect(v).toEqual(expectedJ[i++]); // échoue car le valueMode de J (SINGLE) n'est pas modifié par CalcSerie()
+
+        i = 0;
+        for (const v of prm2.Q.valuesIterator)
+            expect(v).toEqual(expectedJ[i++]);
+    });
+});
diff --git a/src/nub.ts b/src/nub.ts
index 2f8db7a9..367114fa 100644
--- a/src/nub.ts
+++ b/src/nub.ts
@@ -158,7 +158,7 @@ export abstract class Nub extends ComputeNode implements IReferencedObject {
         if (desc === undefined || (this._result !== undefined && this._result.name === desc))
             return this._result;
 
-        return this.CalcSerie(0.001, 0.1, desc);
+        return this.CalcSerie(0.001, 0.1, desc); // il y a des valeurs par défaut pour la précision et la valeur initiale, mais il faudra prévoir un mécanisme pour les transmettre
     }
 
     public getReferencedExtraResult(desc: string): any {
@@ -166,4 +166,23 @@ export abstract class Nub extends ComputeNode implements IReferencedObject {
         const r: Result = this.getReferencedResult(tmp[0]);
         return r.getExtraResult(tmp[1]);
     }
+
+    public getReferencedValuesIterator(desc: string): IterableIterator<number> {
+        if (this._result !== undefined && this._result.name === desc)
+            return this._result.valuesIterator;
+
+        const p = this.getParameter(desc);
+        switch (p.paramValues.valueMode) {
+            case ParamValueMode.SINGLE:
+            case ParamValueMode.MINMAX:
+            case ParamValueMode.LISTE:
+                return p.paramValues.valuesIterator;
+
+            case ParamValueMode.CALCUL:
+                return this.getReferencedResult(desc).valuesIterator;
+
+            case ParamValueMode.LINK:
+                throw new Error(`Nub.getReferencedValuesIterator() : mode de valeur ${ParamValueMode[p.paramValues.valueMode]} invalide pour le paramètre référencé par ${desc}`);
+        }
+    }
 }
diff --git a/src/param/param-base.ts b/src/param/param-base.ts
index 8da7d270..9778896b 100644
--- a/src/param/param-base.ts
+++ b/src/param/param-base.ts
@@ -8,12 +8,13 @@ import { ParamValues } from "./param-values";
 import { ParamValueMode } from "./param-value-mode";
 import { IReferencedObject, IObjectReference } from "../value_ref/object_ref";
 import { Result } from "..";
+import { IterableValues } from "./param-value-iterator";
 
 /**
  * paramètre avec symbole et domaine de définition
  */
 // tslint:disable-next-line:max-classes-per-file
-export class BaseParam extends JalhydObject implements IObjectReference {
+export class BaseParam extends JalhydObject implements IObjectReference, IterableValues {
     /**
      * symbole
      */
@@ -173,4 +174,16 @@ export class BaseParam extends JalhydObject implements IObjectReference {
     public get referencedExtraResult(): any {
         return this._paramValues.referencedExtraResult;
     }
+
+    public get referencedValuesIterator(): IterableIterator<number> {
+        return this._paramValues.referencedValuesIterator;
+    }
+
+    // interface IterableValues
+
+    public get valuesIterator(): IterableIterator<number> {
+        if (this.isReferenceDefined)
+            return this.referencedValuesIterator;
+        return this._paramValues.valuesIterator;
+    }
 }
diff --git a/src/param/param-value-iterator.ts b/src/param/param-value-iterator.ts
index 0d123d96..b23c73f8 100644
--- a/src/param/param-value-iterator.ts
+++ b/src/param/param-value-iterator.ts
@@ -1,6 +1,13 @@
 import { ParamValues } from "./param-values";
 import { ParamValueMode } from "./param-value-mode";
 
+/**
+ * interface implémentée par les objets pouvant renvoyer un itérateur sur une série de valeurs numériques
+ */
+export interface IterableValues {
+    readonly valuesIterator: IterableIterator<number>;
+}
+
 /**
  * itérateur sur les (ou la) valeurs prises par le paramètre
  */
diff --git a/src/param/param-values.ts b/src/param/param-values.ts
index 9f72b116..d4e5373c 100644
--- a/src/param/param-values.ts
+++ b/src/param/param-values.ts
@@ -3,9 +3,9 @@ import { DefinedNumber } from "../util/definedvalue";
 import { IReferencedObject, IObjectReference, ObjectReference } from "../value_ref/object_ref";
 import { Result } from "..";
 import { ParamValueMode } from "./param-value-mode";
-import { ParamValueIterator } from "./param-value-iterator";
+import { ParamValueIterator, IterableValues } from "./param-value-iterator";
 
-export class ParamValues implements IObjectReference {
+export class ParamValues implements IObjectReference, IterableValues {
     /**
      * mode de génération des valeurs : min/max, liste, ...
      */
@@ -243,7 +243,7 @@ export class ParamValues implements IObjectReference {
     }
 
     /**
-     * crée un iterateur
+     * crée un ParamValueIterator
      * @param reverse true si on veut itérer max->min ou depuis la fin de la liste
      */
     public getValuesIterator(reverse: boolean = false): ParamValueIterator {
@@ -312,4 +312,14 @@ export class ParamValues implements IObjectReference {
     public get referencedExtraResult(): any {
         return this._valueRef.referencedExtraResult;
     }
+
+    public get referencedValuesIterator(): any {
+        return this._valueRef.referencedValuesIterator;
+    }
+
+    // interface IterableValues
+
+    public get valuesIterator(): IterableIterator<number> {
+        return this.getValuesIterator();
+    }
 }
diff --git a/src/util/result.ts b/src/util/result.ts
index 091786ad..729c60e4 100644
--- a/src/util/result.ts
+++ b/src/util/result.ts
@@ -1,13 +1,14 @@
 import { cLog } from "./log";
 import { Message, MessageCode, MessageSeverity } from "./message";
 import { ResultElement } from "./resultelement";
+import { IterableValues } from "../param/param-value-iterator";
 
 /**
  * Résultat global d'un calcul
  * Peut comporter un ou plusieurs Result.
  */
 // tslint:disable-next-line:max-classes-per-file
-export class Result {
+export class Result implements IterableValues {
     /**
      * Messages (erreurs, infos, ...)
      */
@@ -260,4 +261,13 @@ export class Result {
 
         return false;
     }
+
+    //  interface IterableValues
+
+    public get valuesIterator(): IterableIterator<number> {
+        const tmp: number[] = [];
+        for (const re of this.resultElements)
+            tmp.push(re.vCalc);
+        return tmp[Symbol.iterator]();
+    }
 }
diff --git a/src/value_ref/object_ref.ts b/src/value_ref/object_ref.ts
index 19f79e7e..4b49b007 100644
--- a/src/value_ref/object_ref.ts
+++ b/src/value_ref/object_ref.ts
@@ -23,6 +23,11 @@ export interface IReferencedObject {
      * @param desc : description sous forme symbolique
      */
     getReferencedExtraResult(desc: string): any;
+
+    /**
+     * itérateur sur les valeurs
+     */
+    getReferencedValuesIterator(desc: string): IterableIterator<number>;
 }
 
 /**
@@ -60,6 +65,11 @@ export interface IObjectReference {
      * instance de résultat complémentaire référencée
      */
     readonly referencedExtraResult: any;
+
+    /**
+     * itérateur sur les valeurs référencées
+     */
+    readonly referencedValuesIterator: IterableIterator<number>;
 }
 
 /**
@@ -119,4 +129,11 @@ export class ObjectReference implements IObjectReference {
             return undefined;
         return this._referencedObject.getReferencedExtraResult(this._refDefinition);
     }
+
+    /**
+     * itérateur sur les valeurs référencées
+     */
+    public get referencedValuesIterator(): IterableIterator<number> {
+        return this._referencedObject.getReferencedValuesIterator(this._refDefinition);
+    }
 }
-- 
GitLab