diff --git a/.vscode/launch.json b/.vscode/launch.json index be37e2d1bdf7fef954f0e29a3c64ca397f7415a1..b627ca869d60e1b451d619ebfe96d0d68513cff5 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,6 +4,7 @@ // Pour plus d'informations, visitez : https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { "name": "Launch Program", "type": "node", @@ -14,7 +15,7 @@ "${workspaceRoot}/build/**/*.js" ], "cwd": "${workspaceRoot}", - // "preLaunchTask": "buildspec" + "preLaunchTask": "buildspec" } ] } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 8379e3ff2087b7446cabec75434a16916aae6722..0f4734d17fd2ea08611521470cb5f04c24acd7f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "jalhyd", - "version": "1.0.2", + "version": "1.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/spec/mock_jasmine.ts b/spec/mock_jasmine.ts index 2baf17136e0af0f3d14d27c2a7a5d47d49aa5395..e3a0c3fa63e86f26d9002005bafe80c062d401c8 100644 --- a/spec/mock_jasmine.ts +++ b/spec/mock_jasmine.ts @@ -161,8 +161,7 @@ class Expect { if (exception.message !== expected.message) { console.error(`Function throws '${exception.message}' but '${expected.message}' was expected`); } - } - else if (exception.message) { + } else if (exception.message) { console.error(`Function throws '${exception.message}' but no message was expected`); } } diff --git a/spec/nubtest.ts b/spec/nubtest.ts index 5d8c6bedcf7da95be4270fea7f9768ed8ba7ff9a..710e3526b5b170efe7c10bc27bbe3c7ebe54f61f 100644 --- a/spec/nubtest.ts +++ b/spec/nubtest.ts @@ -1,7 +1,7 @@ -import { Result } from "../src/util/result"; +import { ParamCalculability, ParamDefinition, ParamDomainValue } from "../src"; import { Nub } from "../src/nub"; import { ParamsEquation } from "../src/param/params-equation"; -import { ParamDefinition, ParamDomainValue, ParamCalculability } from "../src"; +import { Result } from "../src/util/result"; export class NubTestParams extends ParamsEquation { private _A: ParamDefinition; @@ -32,11 +32,17 @@ export class NubTestParams extends ParamsEquation { } } +// tslint:disable-next-line:max-classes-per-file export class NubTest extends Nub { constructor(prms: NubTestParams, dbg: boolean = false) { super(prms, dbg); } + public Equation(): Result { + // C = A+B + return new Result(this.prms.A.v + this.prms.B.v); + } + protected setParametersCalculability() { this.getParameter("A").calculability = ParamCalculability.DICHO; this.getParameter("B").calculability = ParamCalculability.DICHO; @@ -47,10 +53,6 @@ export class NubTest extends Nub { return this._prms as NubTestParams; } - Equation(): Result { - // C = A+B - return new Result(this.prms.A.v + this.prms.B.v); - } } export let nub = new NubTest(new NubTestParams()); diff --git a/spec/value_ref/value_ref.spec.ts b/spec/value_ref/value_ref.spec.ts index 82ed531ea7af2861f4a8d7cb79e7880a30f29053..b442a245774cff8b8651132d141c950efacb9f25 100644 --- a/spec/value_ref/value_ref.spec.ts +++ b/spec/value_ref/value_ref.spec.ts @@ -6,10 +6,10 @@ */ // import { describe, expect, it, xdescribe, xit } from "../mock_jasmine"; +import { Result } from "../../src"; +import { ParamValueMode } from "../../src/param/param-value-mode"; import { NubTest, NubTestParams } from "../nubtest"; import { precDigits } from "../test_config"; -import { ParamValueMode } from "../../src/param/param-value-mode"; -import { Result } from "../../src"; let nub1: NubTest; let nub2: NubTest; @@ -181,7 +181,7 @@ describe("référence d'un paramètre à un autre : ", () => { it('test 3', () => { // cas de figure : // nub2.A est lié à nub1.A (valeur variée) - // lecture de nub2.A + // lecture de nub2.A createEnv(); diff --git a/spec/value_ref/value_ref_variable.spec.ts b/spec/value_ref/value_ref_variable.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..21fc66aad4cbbbef32bf9c65011dad53ee6530b6 --- /dev/null +++ b/spec/value_ref/value_ref_variable.spec.ts @@ -0,0 +1,54 @@ +import { ParamValueMode } from "../../src"; +import { ConduiteDistrib, ConduiteDistribParams } from "../../src/cond_distri"; +import { Result } from "../../src/util/result"; + +/** + * 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 paramètre varié : ", () => { + it("ConduiteDistri Q varie sur nub1, nub2.Q => nub1.Q, calcul et comparaison de J pour les deux", () => { + // 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; + const res1: Result = nub1.CalcSerie(0.001, 0.6, "J"); + + prm2.Q.defineReference(nub1, "Q"); + const res2 = nub2.CalcSerie(0.001, 0.6, "J"); + + for (let i = 0; i < res1.resultElements.length; i++) { + expect(res1.resultElements[i].vCalc).toEqual(res2.resultElements[i].vCalc); + } + + }); +}); diff --git a/spec/value_ref/value_ref_variable_result.spec.ts b/spec/value_ref/value_ref_variable_result.spec.ts index 9eff1a2bbaccef2f7902459bf49b06a320188cff..7b74fa2a3ce293e70667173918b8bdec9d8966e2 100644 --- a/spec/value_ref/value_ref_variable_result.spec.ts +++ b/spec/value_ref/value_ref_variable_result.spec.ts @@ -1,6 +1,6 @@ -import { ConduiteDistrib } from "../../src/cond_distri"; -import { ConduiteDistribParams } from "../../src/cond_distri"; import { ParamValueMode } from "../../src"; +import { ConduiteDistrib, ConduiteDistribParams } from "../../src/cond_distri"; +import { Result } from "../../src/util/result"; /** * IMPORTANT ! @@ -29,8 +29,28 @@ function createEnv() { prm2 = nub2.parameters as ConduiteDistribParams; } -describe("référence d'un paramètre à un résultat multivalué : ", () => { - it("test 1", () => { +describe("référence d'un paramètre à un résultat : ", () => { + it("ConduiteDistri Q fixe => Calc(J) => Importe(J) => Calc(Q)", () => { + // cas de figure : + // nub2.Q est lié au résultat J de nub1 + // lecture de nub2.Q + + createEnv(); + + prm1.Q.v = 2; + prm1.J.paramValues.valueMode = ParamValueMode.CALCUL; + const res1: Result = nub1.CalcSerie(0.001, 0.6, "J"); + + expect(res1.resultElements.length).toEqual(1); // nombre de valeurs du Result + + prm2.J.defineReference(nub1, "J."); + const res2 = nub2.CalcSerie(0.001, 0.6, "Q"); + expect(res2.resultElements.length).toEqual(1); // nombre de valeurs du Result + + expect(res2.vCalc).toBeCloseTo(prm1.Q.v, 3); + }); + + it("ConduiteDistri Q varie => Calc(J) => Importe(J) => Calc(Q)", () => { // cas de figure : // nub2.Q est lié au résultat J de nub1 // lecture de nub2.Q @@ -41,28 +61,20 @@ describe("référence d'un paramètre à un résultat multivalué : ", () => { prm1.Q.paramValues.min = 1.5; prm1.Q.paramValues.max = 6; prm1.Q.paramValues.step = 0.5; - prm2.Q.defineReference(nub1, "J."); + prm1.J.paramValues.valueMode = ParamValueMode.CALCUL; + const res1: Result = nub1.CalcSerie(0.001, 0.6, "J"); - const expectedJ: number[] = [0.024202971271651448, 0.04004160474685753, 0.059170330781816, 0.08140876712328136, 0.10661739314398751, 0.1346833675705545, 0.16551253143900968, 0.19902447617522237, 0.23514929908544743, 0.273825361776767]; + prm2.J.defineReference(nub1, "J."); + const res2 = nub2.CalcSerie(0.001, 0.6, "Q"); - 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++]); + expect(res1.resultElements.length).toEqual(10); // nombre de valeurs du Result + expect(res2.resultElements.length).toEqual(10); - i = 0; - for (const v of res.valuesIterator) - expect(v).toEqual(expectedJ[i++]); - expect(i).toEqual(expectedJ.length); - - // 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++]); - expect(i).toEqual(expectedJ.length); + let QREF = prm1.Q.paramValues.min; + for (const re of res2.resultElements) { + // console.log(re.vCalc); + expect(re.vCalc).toBeCloseTo(QREF, 0.001); + QREF += prm1.Q.paramValues.step; + } }); }); diff --git a/src/nub.ts b/src/nub.ts index 68ae8e3cadee30d7f285008c7a2d449965956e98..99e2c66a4b7016ba2870259cca89a9b92d5f34ab 100644 --- a/src/nub.ts +++ b/src/nub.ts @@ -1,24 +1,25 @@ +import { ParamDefinition } from "."; import { Debug } from "./base"; -import { Dichotomie } from "./dichotomie"; import { ComputeNode } from "./compute-node"; -import { Result } from "./util/result"; -import { ParamValues } from "./param/param-values"; +import { Dichotomie } from "./dichotomie"; +import { NamedIterableValues, NumberIterator, IterableValues } from "./param/param-value-iterator"; import { ParamValueMode } from "./param/param-value-mode"; -import { ParamDefinition } from "."; +import { ParamValues } from "./param/param-values"; +import { Result } from "./util/result"; import { IReferencedNub } from "./value_ref/object_ref"; -import { NamedIterableValues, NumberIterator } from "./param/param-value-iterator"; /** * Classe abstraite de Noeud de calcul : classe de base pour tous les calculs */ export abstract class Nub extends ComputeNode implements IReferencedNub { - private _dichoStartIntervalMaxSteps: number = 100; /** * résultat de Calc()/CalcSerie() */ protected _result: Result; + private _dichoStartIntervalMaxSteps: number = 100; + /* * paramétrage de la dichotomie */ @@ -75,87 +76,72 @@ export abstract class Nub extends ComputeNode implements IReferencedNub { * @param sDonnee éventuel symbole du paramètre à calculer */ public CalcSerie(rPrec: number = 0.001, rInit?: number, sDonnee?: string): Result { - let variatedParam: ParamDefinition; let computedParam: ParamDefinition; - let prmValue: ParamValues; // instance de ParamValues utilisée pour le paramètre varié (qui peut être un paramètre référencé (importé)) + // instance de ParamValues utilisée pour le paramètre varié (qui peut être un paramètre référencé (importé)) + let variatedValues: IterableValues; for (const p of this.parameterIterator) { + if (p.valueMode === ParamValueMode.CALCUL) { + if (sDonnee === undefined) { + if (computedParam === undefined) { + computedParam = p; + } else { + // tslint:disable-next-line:max-line-length + throw new Error(`CalcSerie() : il y plusieurs paramètres à calculer (au moins ${computedParam.symbol} et ${p.symbol})`); + } + } + } + switch (p.valueMode) { case ParamValueMode.SINGLE: break; case ParamValueMode.LISTE: case ParamValueMode.MINMAX: - if (variatedParam == undefined) { - variatedParam = p; - prmValue = p.paramValues; - } - else - throw new Error(`CalcSerie() : il y plusieurs paramètres à varier (au moins ${variatedParam.symbol} et ${p.symbol})`); + variatedValues = this.setVariatedValues(p, variatedValues); break; case ParamValueMode.CALCUL: - if (sDonnee == undefined) { - if (computedParam == undefined) - computedParam = p; - else - throw new Error(`CalcSerie() : il y plusieurs paramètres à calculer (au moins ${computedParam.symbol} et ${p.symbol})`); + // Le paramètre lié est un résultat de calcul + if (p.isReferenceDefined && p.referencedResult.nbResultElements > 1) { + variatedValues = this.setVariatedValues(p, variatedValues); } break; case ParamValueMode.LINK: - if (p.referencedParamValues !== undefined) - switch (p.referencedParamValues.valueMode) { - case ParamValueMode.SINGLE: - break; - - case ParamValueMode.LISTE: - case ParamValueMode.MINMAX: - if (variatedParam == undefined) { - variatedParam = p; - prmValue = p.referencedParamValues; - } - else - throw new Error(`CalcSerie() : il y plusieurs paramètres à varier (au moins ${variatedParam.symbol} et ${p.symbol})`); - break; - - case ParamValueMode.CALCUL: - if (sDonnee == undefined) { - if (computedParam == undefined) - computedParam = p; - else - throw new Error(`CalcSerie() : il y plusieurs paramètres à calculer (au moins ${computedParam.symbol} et ${p.symbol})`); - } - break; - - default: - throw new Error(`CalcSerie() : valeur référencée de ParamValueMode ${ParamValueMode[p.referencedParamValues.valueMode]} non prise en charge`); - } + const ro = p.referencedObject; + if (ro !== undefined && ro.hasMultipleValues) + variatedValues = this.setVariatedValues(p, variatedValues); break; default: + // tslint:disable-next-line:max-line-length throw new Error(`CalcSerie() : valeur de ParamValueMode ${ParamValueMode[p.valueMode]} non prise en charge`); } } - if (sDonnee) - var computedSymbol: string = sDonnee; - else { - if (computedParam == undefined) + let computedSymbol: string; + if (sDonnee) { + computedSymbol = sDonnee; + } else { + if (computedParam === undefined) { throw new Error(`CalcSerie() : aucun paramètre à calculer`); + } computedSymbol = computedParam.symbol; } - if (rInit === undefined) + if (rInit === undefined) { rInit = computedParam.v; + } - if (variatedParam == undefined) + if (variatedValues === undefined) { this._result = this.Calc(computedSymbol, rInit, rPrec); // résultat dans this._result - else { + } else { const res = new Result(); - prmValue.initIterator(); - while (prmValue.hasNext) { - prmValue.next; + variatedValues.initValuesIterator(false); + while (variatedValues.hasNext) { + // tslint:disable-next-line:no-unused-expression + variatedValues.next(); this.Calc(computedSymbol, rInit, rPrec); // résultat dans this._result if (this._result.ok) { res.addResultElement(this._result.resultElement); @@ -171,19 +157,6 @@ export abstract class Nub extends ComputeNode implements IReferencedNub { return this._result; } - /** - * Résoud l'équation par une méthode numérique - * @param sVarCalc nom de la variable à calculer - * @param rInit valeur initiale de la variable à calculer dans le cas de la dichotomie - * @param rPrec précision de calcul - */ - private Solve(sVarCalc: string, rInit: number, rPrec: number): Result { - const dicho: Dichotomie = new Dichotomie(this, sVarCalc, this.DBG); - dicho.startIntervalMaxSteps = this._dichoStartIntervalMaxSteps; - const target = this.getFirstAnalyticalParameter(); - return dicho.Dichotomie(target.v, rPrec, rInit); - } - public get result(): Result { return this._result; } @@ -192,16 +165,20 @@ export abstract class Nub extends ComputeNode implements IReferencedNub { public getReferencedParamValues(desc: string): ParamValues { const prm = this.getParameter(desc); - if (prm !== undefined) + if (prm !== undefined) { return prm.paramValues; + } return undefined; } public getReferencedResult(desc?: string): Result { - if (desc === undefined || (this._result !== undefined && this._result.name === desc)) + if (desc === undefined || (this._result !== undefined && this._result.name === desc)) { return this._result; + } - 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 + // 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 + return this.CalcSerie(0.001, 0.1, desc); } public getReferencedExtraResult(desc: string): any { @@ -218,26 +195,41 @@ export abstract class Nub extends ComputeNode implements IReferencedNub { public getReferencedObject(desc: string): NamedIterableValues { const tmp = desc.split("."); - if (tmp.length == 1) // paramètre (ex "Q") + if (tmp.length === 1) { + // paramètre (ex "Q") return this.getParameter(desc); + } - if (tmp[1] === "") // résultat (ex "Q.") - if (this._result !== undefined) + if (tmp[1] === "") { + // résultat (ex "Q.") + if (this._result !== undefined) { return this._result; + } + } // les autres objets référençables n'implémentant pas IJalhydObject... return undefined; } - private addPrefix(str: string, prefix: string) { - return prefix === undefined ? str : `${prefix}${str}`; - } - /** * liste des valeurs (paramètre, résultat, résultat complémentaire) liables à un paramètre * @param src objet qui sert de clé de recherche des paramètres liables, de type INamedObject | string - * @param excludeResult true si on veut exclure des valeurs retournées le résultat/résultat complémentaire correspondant à la clé de recherche - * @returns tableau d'objets de la forme { "name":string, "value":NamedIterableValues, "nub":Nub}, nub=Nub d'origine de la "value" + * @param excludeResult true si on veut exclure des valeurs retournées le résultat/résultat complémentaire + * correspondant à la clé de recherche + * @returns tableau d'objets de la forme { "name":string, "value":NamedIterableValues, "nub":Nub}, + * nub=Nub d'origine de la "value" + * + * l'étiquette "name" (cf. INubReference.defineReference) est de la forme <n | ouvrage[n] | N1>[.[N2]] + * n : indice de de l'ouvrage dans le cas des ouvrages parallèles + * N1 : un nom de paramètre/résultat (dans le cas d'un résultat, il est suivi d'un point) + * N2 : nom de résultat complémentaire (optionnel) + * ex : + * Q, Z1 (paramètres) + * J. (résultat) + * .Yf (résultat complémentaire du résultat courant) + * Q.Yf (résultat complémentaire du résultat nommé "Q") + * 0.Q : paramètre Q du 1er ouvrage (ouvrages parallèles) + * ouvrage[1].Q_Mode : résultat complémentaire du 2ème ouvrage (ouvrages parallèles) */ public getLinkableValues(src: any, prefix?: string, excludeResult: boolean = false): any[] { const res: any[] = []; @@ -249,8 +241,9 @@ export abstract class Nub extends ComputeNode implements IReferencedNub { // paramètres for (const p of this._prms) { - const cond = hasUid ? p.uid !== src.uid : true; // pour éviter d'ajouter le paramètre d'entrée dans le tableau résultat - if (cond) + // pour éviter d'ajouter le paramètre d'entrée dans le tableau résultat + const cond = hasUid ? p.uid !== src.uid : true; + if (cond) { switch (p.valueMode) { case ParamValueMode.SINGLE: case ParamValueMode.MINMAX: @@ -258,29 +251,60 @@ export abstract class Nub extends ComputeNode implements IReferencedNub { switch (name) { case "Z1": case "Z2": - if (p.symbol === "Z1" || p.symbol === "Z2") - res.push({ "name": this.addPrefix(p.symbol, prefix), "value": p, "nub": this }); + if (p.symbol === "Z1" || p.symbol === "Z2") { + res.push({ name: this.addPrefix(p.symbol, prefix), value: p, nub: this }); + } break; default: - if (p.symbol === name) - res.push({ "name": this.addPrefix(p.symbol, prefix), "value": p, "nub": this }); + if (p.symbol === name) { + res.push({ name: this.addPrefix(p.symbol, prefix), value: p, nub: this }); + } } } + } } // résultat if (this._result !== undefined && !excludeResult) { - if (this._result.name === name) - res.push({ "name": this.addPrefix(`${name}.`, prefix), "value": this._result, "nub": this }); + if (this._result.name === name) { + res.push({ name: this.addPrefix(`${name}.`, prefix), value: this._result, nub: this }); + } // résultats complémentaires - const erIter = this._result.getIterableExtraResults(name) - if (erIter !== undefined) - res.push({ "name": this.addPrefix(`${this._result.name}.${name}`, prefix), "value": erIter, "nub": this }); + const erIter = this._result.getIterableExtraResults(name); + if (erIter !== undefined) { + res.push({ name: this.addPrefix(`${this._result.name}.${name}`, prefix), value: erIter, nub: this }); + } } return res; } + + /** + * Résoud l'équation par une méthode numérique + * @param sVarCalc nom de la variable à calculer + * @param rInit valeur initiale de la variable à calculer dans le cas de la dichotomie + * @param rPrec précision de calcul + */ + private Solve(sVarCalc: string, rInit: number, rPrec: number): Result { + const dicho: Dichotomie = new Dichotomie(this, sVarCalc, this.DBG); + dicho.startIntervalMaxSteps = this._dichoStartIntervalMaxSteps; + const target = this.getFirstAnalyticalParameter(); + return dicho.Dichotomie(target.v, rPrec, rInit); + } + + private addPrefix(str: string, prefix: string) { + return prefix === undefined ? str : `${prefix}${str}`; + } + + private setVariatedValues(newValues: NamedIterableValues, oldValues: IterableValues) { + if (oldValues === undefined) { + return newValues; + } else { + // tslint:disable-next-line:max-line-length + throw new Error(`CalcSerie() : Paramètres à varier redondant : ${newValues.name}`); + } + } } diff --git a/src/param/param-base.ts b/src/param/param-base.ts index 2d8ff743bbbde4813228a2cc495dd75fc4df46d8..b4b6024457e97110d34af5e379531ce4ab80565f 100644 --- a/src/param/param-base.ts +++ b/src/param/param-base.ts @@ -1,14 +1,14 @@ import { Interval } from "../util/interval"; import { Message, MessageCode } from "../util/message"; -import { JalhydObject, IJalhydObject } from "../jalhyd_object" -import { ParamDomain, ParamDomainValue } from "./param-domain"; -import { ParamValues } from "./param-values"; -import { ParamValueMode } from "./param-value-mode"; -import { IReferencedNub, INubReference } from "../value_ref/object_ref"; +import { IJalhydObject, JalhydObject } from "../jalhyd_object"; +import { IObservable, Observable, Observer } from "../util/observer"; import { Result } from "../util/result"; +import { INubReference, IReferencedNub } from "../value_ref/object_ref"; +import { ParamDomain, ParamDomainValue } from "./param-domain"; import { NamedIterableValues, NumberIterator } from "./param-value-iterator"; -import { IObservable, Observable, Observer } from "../util/observer"; +import { ParamValueMode } from "./param-value-mode"; +import { ParamValues } from "./param-values"; /** * paramètre avec symbole et domaine de définition @@ -39,7 +39,7 @@ export class BaseParam extends JalhydObject implements INubReference, NamedItera super(); this._symbol = symb; - this._observable = new Observable() + this._observable = new Observable(); this._paramValues = new ParamValues(); this._paramValues.setSingleValue(val); @@ -66,8 +66,9 @@ export class BaseParam extends JalhydObject implements INubReference, NamedItera } public get paramValues(): ParamValues { - if (this.isReferenceDefined) + if (this.isReferenceDefined) { return this.referencedParamValues; + } return this._paramValues; } @@ -89,15 +90,8 @@ export class BaseParam extends JalhydObject implements INubReference, NamedItera return this._paramValues.currentValue; } - /** - * notification envoyée après la modification de la valeur du paramètre - */ - private notifyValueModified(sender: any) { - this.notifyObservers( - { - "action": "baseparamAfterValue", - }, sender - ); + public get currentValue(): number { + return this.getValue(); } public setValue(val: number, sender?: any) { @@ -164,24 +158,6 @@ export class BaseParam extends JalhydObject implements INubReference, NamedItera } } - /** - * vérifie si un min/max est valide par rapport au domaine de définition - */ - private isMinMaxDomainValid(v: number): boolean { - if (v == undefined) - return false; - - if (this._paramValues.valueMode == ParamValueMode.MINMAX) - try { - this.checkValue(v); - } - catch (e) { - return false; - } - - return true; - } - public checkMin(min: number): boolean { return this.isMinMaxDomainValid(min) && (min < this._paramValues.max); } @@ -190,41 +166,22 @@ export class BaseParam extends JalhydObject implements INubReference, NamedItera return this.isMinMaxDomainValid(max) && (this._paramValues.min < max); } - private checkMinMax(min: number, max: number): boolean { - return this.isMinMaxDomainValid(min) && this.isMinMaxDomainValid(max) && (min < max); - } - - public get isMinMaxValid(): boolean { - return this.checkMinMax(this._paramValues.min, this._paramValues.max); - } - public checkStep(step: number): boolean { return this.isMinMaxValid && this._paramValues.stepRefValue.intervalHasValue(step); } - public get isValueValid(): boolean { + get isValueValid(): boolean { try { const v = this.getValue(); this.checkValue(v); return true; - } - catch (e) { + } catch (e) { return false; } } - private get isListValid(): boolean { - if (this._paramValues.valueList == undefined) - return false; - - for (let v of this._paramValues.valueList) - try { - this.checkValue(v); - } - catch (e) { - return false; - } - return true; + get isMinMaxValid(): boolean { + return this.checkMinMax(this._paramValues.min, this._paramValues.max); } public get isRangeValid(): boolean { @@ -236,6 +193,7 @@ export class BaseParam extends JalhydObject implements INubReference, NamedItera return this.checkStep(this._paramValues.step); } + // tslint:disable-next-line:max-line-length throw new Error(`"BaseParam.isRangeValid() : valeur ${ParamValueMode[this._paramValues.valueMode]} de ParamValueMode non prise en compte`); } @@ -252,20 +210,24 @@ export class BaseParam extends JalhydObject implements INubReference, NamedItera return true; case ParamValueMode.LINK: - if (!this.isReferenceDefined) + if (!this.isReferenceDefined) { return false; + } try { - for (const v of this.valuesIterator) + for (const v of this.valuesIterator) { this.checkValue(v); - return true - } - catch (e) { + } + return true; + } catch (e) { return false; } } - throw new Error(`"BaseParam.isValid() : valeur de ParamValueMode '${ParamValueMode[this._paramValues.valueMode]}' non prise en charge`); + throw new Error( + // tslint:disable-next-line:max-line-length + `BaseParam.isValid() : valeur de ParamValueMode '${ParamValueMode[this._paramValues.valueMode]}' non prise en charge` + ); } public get valueMode() { @@ -278,36 +240,13 @@ export class BaseParam extends JalhydObject implements INubReference, NamedItera // interface INubReference - /** - * vérifie l'absence de référence circulaire - * @param seenUids liste des uids déjà vérifiés - * @param o objet à tester (son uid est il déjà dans la liste ?) - */ - private checkReferenceCircularity(o: any, seenUids: number[]) { - if ("uid" in o) { - // if (o.uid in seenUids) - if (seenUids.indexOf(o.uid) !== -1) - throw new Error(`références circulaires détectées (uids : ${seenUids})`); - - seenUids.push(o.uid); - - if ("referencedObject" in o) { - const curr = o as INubReference; - const next = curr.referencedObject; - if (next !== undefined) - this.checkReferenceCircularity(next as IJalhydObject, seenUids); - } - } - } - public defineReference(target: IReferencedNub, desc: string) { const oldDef = this._paramValues.referenceDefinition; const oldTarget = this._paramValues.referencedNub; try { this._paramValues.defineReference(target, desc); this.checkReferenceCircularity(this, []); - } - catch (e) { + } catch (e) { this._paramValues.defineReference(oldTarget, oldDef); throw e; } @@ -317,43 +256,44 @@ export class BaseParam extends JalhydObject implements INubReference, NamedItera this._paramValues.undefineReference(); } - public get referenceDefinition(): string { + get referenceDefinition(): string { return this._paramValues.referenceDefinition; } - public get referencedNub(): IReferencedNub { + get referencedNub(): IReferencedNub { return this._paramValues.referencedNub; } - public get isReferenceDefined(): boolean { + get isReferenceDefined(): boolean { return this._paramValues.isReferenceDefined; } - public get referencedParamValues(): ParamValues { + get referencedParamValues(): ParamValues { return this._paramValues.referencedParamValues; } - public get referencedResult(): Result { + get referencedResult(): Result { return this._paramValues.referencedResult; } - public get referencedExtraResult(): any { + get referencedExtraResult(): any { return this._paramValues.referencedExtraResult; } - public get referencedValuesIterator(): NumberIterator { + get referencedValuesIterator(): NumberIterator { return this._paramValues.referencedValuesIterator; } - public get referencedObject(): NamedIterableValues { + get referencedObject(): NamedIterableValues { return this._paramValues.referencedObject; } // interface NamedIterableValues public get valuesIterator(): NumberIterator { - if (this.isReferenceDefined) + if (this.isReferenceDefined) { return this.referencedValuesIterator; + } return this._paramValues.valuesIterator; } @@ -365,6 +305,22 @@ export class BaseParam extends JalhydObject implements INubReference, NamedItera return this._symbol; } + public initValuesIterator(reverse: boolean = false): NumberIterator { + return this._paramValues.initValuesIterator(reverse); + } + + public get hasNext(): boolean { + return this._paramValues.hasNext; + } + + public next(): IteratorResult<number> { + return this._paramValues.next(); + } + + public [Symbol.iterator](): IterableIterator<number> { + return this._paramValues; + } + // interface IObservable /** @@ -384,7 +340,81 @@ export class BaseParam extends JalhydObject implements INubReference, NamedItera /** * notifie un événement aux observateurs */ - notifyObservers(data: any, sender?: any) { + public notifyObservers(data: any, sender?: any) { this._observable.notifyObservers(data, sender); } + + /** + * notification envoyée après la modification de la valeur du paramètre + */ + private notifyValueModified(sender: any) { + this.notifyObservers( + { + action: "baseparamAfterValue", + }, sender + ); + } + + /** + * vérifie si un min/max est valide par rapport au domaine de définition + */ + private isMinMaxDomainValid(v: number): boolean { + if (v === undefined) { + return false; + } + + if (this._paramValues.valueMode === ParamValueMode.MINMAX) { + try { + this.checkValue(v); + } catch (e) { + return false; + } + } + + return true; + } + + private checkMinMax(min: number, max: number): boolean { + return this.isMinMaxDomainValid(min) && this.isMinMaxDomainValid(max) && (min < max); + } + + private get isListValid(): boolean { + if (this._paramValues.valueList === undefined) { + return false; + } + + for (const v of this._paramValues.valueList) { + try { + this.checkValue(v); + } catch (e) { + return false; + } + } + return true; + } + + /** + * vérifie l'absence de référence circulaire + * @param seenUids liste des uids déjà vérifiés + * @param o objet à tester (son uid est il déjà dans la liste ?) + */ + private checkReferenceCircularity(o: any, seenUids: number[]) { + if ("uid" in o) { + // if (o.uid in seenUids) + if (seenUids.indexOf(o.uid) !== -1) { + throw new Error(`références circulaires détectées (uids : ${seenUids})`); + } + + seenUids.push(o.uid); + + if ("referencedObject" in o) { + const curr = o as INubReference; + const next = curr.referencedObject; + if (next !== undefined) { + this.checkReferenceCircularity(next as IJalhydObject, seenUids); + } + } + } + } + } diff --git a/src/param/param-definition.ts b/src/param/param-definition.ts index 3cfde12f879738e1fbab0aa38e8a6b2167ff893f..43997761ffc4edf10e310ad740f1379b5ce47b0a 100644 --- a/src/param/param-definition.ts +++ b/src/param/param-definition.ts @@ -1,9 +1,8 @@ import { Message, MessageCode } from "../util/message"; - +import { Result } from "../util/result"; import { BaseParam } from "./param-base"; import { ParamDomain, ParamDomainValue } from "./param-domain"; import { ParamValueMode } from "./param-value-mode"; -import { Result } from "../util/result"; /** * calculabilité du paramètre @@ -53,16 +52,17 @@ export class ParamDefinition extends BaseParam { switch (this.referencedParamValues.valueMode) { case ParamValueMode.CALCUL: const r = this.referencedResult; - if (r.nbResultElements == 1) + if (r.nbResultElements === 1) { return r.resultElement.vCalc; + } throw new Error(`il n'y a pas exactement un ResultElement dans le Result "${r.name}"`); default: return this.referencedParamValues.currentValue; } + } else if (ro instanceof Result) { + return ro.currentValue; } - else if (ro instanceof Result) - return ro.vCalc; return this.referencedExtraResult; } diff --git a/src/param/param-value-iterator.ts b/src/param/param-value-iterator.ts index c5f05fcbf12acf15c3e56c4129a5823c4fe7578d..459cf1585089410f03ee865cc1c28835278ceafd 100644 --- a/src/param/param-value-iterator.ts +++ b/src/param/param-value-iterator.ts @@ -1,6 +1,7 @@ -import { ParamValues } from "./param-values"; -import { ParamValueMode } from "./param-value-mode"; import { INamedObject } from "../jalhyd_object"; +import { ParamValueMode } from "./param-value-mode"; +import { ParamValues } from "./param-values"; +import { ArrayReverseIterator } from "../util/iterator"; /** * itérateur sur des nombres @@ -15,14 +16,20 @@ export interface NumberIterator extends IterableIterator<number> { * prochaine valeur */ next(): IteratorResult<number>; + + /** + * valeur courante cad résultat du précédent appel à next(). + * contrairement à next(), on peut l'appeler plusieurs fois sans modifier l'état de l'itérateur + */ + readonly currentValue: number; } /** - * interface implémentée par les objets pouvant renvoyer un itérateur sur une série de valeurs numériques + * interface implémentée par les objets pouvant posséder/renvoyer un itérateur sur une série de valeurs numériques */ -export interface IterableValues { +export interface IterableValues extends NumberIterator { /** - * itérateur sur les valeurs + * crée un nouvel itérateur sur les valeurs */ readonly valuesIterator: NumberIterator; @@ -30,6 +37,11 @@ export interface IterableValues { * true si la série de valeurs a plus d'une valeur */ readonly hasMultipleValues: boolean; + + /** + * initialise un itérateur interne sur les valeurs implicitement utilisé par hasNext() et next() + */ + initValuesIterator(reverse: boolean): NumberIterator; } /** @@ -52,6 +64,11 @@ export class ParamValueIterator implements NumberIterator { */ private _reverse: boolean; + /** + * valeur courante + */ + private _current: number; + private _index: number; /** @@ -65,7 +82,7 @@ export class ParamValueIterator implements NumberIterator { constructor(prm: ParamValues, reverse: boolean = false) { prm.check(); this._param = prm; - this.reset(reverse) + this.reset(reverse); } public reset(reverse: boolean) { @@ -79,10 +96,11 @@ export class ParamValueIterator implements NumberIterator { case ParamValueMode.MINMAX: this._config = 1; - if (reverse) + if (reverse) { this._index = this._param.max; - else + } else { this._index = this._param.min; + } break; case ParamValueMode.LISTE: @@ -99,7 +117,7 @@ export class ParamValueIterator implements NumberIterator { switch (this._config) { // valeur fixée case 0: - return this._index == 0; + return this._index === 0; // min/max case 1: @@ -120,29 +138,31 @@ export class ParamValueIterator implements NumberIterator { // valeur fixée case 0: if (this.hasNext) { + this._current = this._param.singleValue; this._index++; return { done: false, - value: this._param.singleValue + value: this._current }; - } - else + } else { return { done: true, value: undefined }; + } // min/max case 1: - const res = this._index; + this._current = this._index; if (this.hasNext) { - if (this._reverse) + if (this._reverse) { this._index -= this._param.step; - else + } else { this._index += this._param.step; + } return { done: false, - value: res + value: this._current }; } else { return { @@ -155,10 +175,10 @@ export class ParamValueIterator implements NumberIterator { case 2: const i = this._index; if (this.hasNext) { - const res = this._param.valueList[this._index++]; + this._current = this._param.valueList[this._index++]; return { done: false, - value: res + value: this._current }; } else { return { @@ -172,11 +192,89 @@ export class ParamValueIterator implements NumberIterator { } } - // public get current(): number { - // if (this._config == 1) - // return this._index; - // throw new Error(`appel ParamValueIterator.current() invalide`) - // } + public get currentValue(): number { + return this._current; + } + + // interface IterableIterator + + public [Symbol.iterator](): IterableIterator<number> { + return this; + } +} + +/** + * itérateur sur les valeurs prises par un tableau + */ +export class NumberArrayIterator implements NumberIterator { + private _it: IterableIterator<number>; + + private _index: number; + + /** + * valeur courante + */ + private _current: number; + + constructor(private _arr: number[]) { + this._it = this._arr[Symbol.iterator](); // crée un itérateur à partir d'un tableau + this._index = 0; + } + + public get hasNext(): boolean { + return this._index < this._arr.length; + } + + public next(): IteratorResult<number> { + this._index++; + const res = this._it.next(); + if (!res.done) + this._current = res.value; + return res; + } + + public get currentValue(): number { + return this._current; + } + + // interface IterableIterator + + public [Symbol.iterator](): IterableIterator<number> { + return this; + } +} + +/** + * itérateur sur les valeurs prises par un tableau (parcourues depuis la fin) + */ +export class NumberArrayReverseIterator extends ArrayReverseIterator<number> implements NumberIterator { + private _count: number; + + /** + * valeur courante + */ + private _current: number; + + constructor(arr: number[]) { + super(arr); + this._count = 0; + } + + public get hasNext(): boolean { + return this._count < super._arr.length; + } + + public next(): IteratorResult<number> { + this._count++; + const res = super.next(); + if (!res.done) + this._current = res.value; + return res; + } + + public get currentValue(): number { + return this._current; + } // interface IterableIterator diff --git a/src/param/param-values.ts b/src/param/param-values.ts index f30e70d5b2b9ae6e0dcfdb62f57e96ff3459fe00..dea1db9d04ea3f282f7fae570d5ca27489234532 100644 --- a/src/param/param-values.ts +++ b/src/param/param-values.ts @@ -1,9 +1,9 @@ -import { Pair } from "../util/pair" -import { DefinedNumber } from "../util/definedvalue"; -import { IReferencedNub, INubReference, NubReference } from "../value_ref/object_ref"; import { Result } from ".."; +import { DefinedNumber } from "../util/definedvalue"; +import { Pair } from "../util/pair"; +import { INubReference, IReferencedNub, NubReference } from "../value_ref/object_ref"; +import { IterableValues, NamedIterableValues, NumberIterator, ParamValueIterator } from "./param-value-iterator"; import { ParamValueMode } from "./param-value-mode"; -import { ParamValueIterator, IterableValues, NamedIterableValues, NumberIterator } from "./param-value-iterator"; export class ParamValues implements INubReference, IterableValues { /** @@ -59,7 +59,7 @@ export class ParamValues implements INubReference, IterableValues { public setValues(o: number | any, max?: number, step?: number) { if (typeof (o) === "number") { - if (max == undefined) { + if (max === undefined) { this._valueMode = ParamValueMode.SINGLE; this._singleValue.value = o as number; this._currentValue.value = o as number; @@ -70,14 +70,13 @@ export class ParamValues implements INubReference, IterableValues { this._stepValue = step; this._currentValue.undefine(); } - } - else if (Array.isArray(o)) { + } else if (Array.isArray(o)) { this._valueMode = ParamValueMode.LISTE; this._valueList = o; this._currentValue.undefine(); - } - else + } else { throw new Error(`ParamValues.setValues() : appel invalide`); + } } public get valueMode() { @@ -88,32 +87,33 @@ export class ParamValues implements INubReference, IterableValues { this._valueMode = m; } - private checkValueMode(expected: ParamValueMode) { - if (this._valueMode != expected) - throw new Error(`ParamValues : mode de valeurs ${ParamValueMode[expected]} incorrect`); - } - public check() { switch (this._valueMode) { case ParamValueMode.SINGLE: - if (!this._singleValue.isDefined) + if (!this._singleValue.isDefined) { throw new Error(`ParamValues : valeur fixe non définie`); + } break; case ParamValueMode.MINMAX: - if (this._minValue == undefined) + if (this._minValue === undefined) { throw new Error(`ParamValues : valeur min non définie`); - if (this._maxValue == undefined) + } + if (this._maxValue === undefined) { throw new Error(`ParamValues : valeur max non définie`); - if (this._stepValue == undefined) + } + if (this._stepValue === undefined) { throw new Error(`ParamValues : valeur du pas non définie`); - if (this._minValue > this._maxValue) + } + if (this._minValue > this._maxValue) { throw new Error(`ParamValues : min > max`); + } break; case ParamValueMode.LISTE: - if (this._valueList == undefined) + if (this._valueList === undefined) { throw new Error(`ParamValues : liste de valeurs non définie`); + } break; case ParamValueMode.LINK: @@ -129,8 +129,9 @@ export class ParamValues implements INubReference, IterableValues { * valeur courante */ public get currentValue(): number { - if (this.isReferenceDefined) - return this._nubRef.referencedParamValues.currentValue; + if (this.isReferenceDefined) { + return this._nubRef.referencedObject.currentValue; + } return this._currentValue.value; } @@ -142,8 +143,9 @@ export class ParamValues implements INubReference, IterableValues { * valeur dans le mode SINGLE */ public get singleValue(): number { - if (this.isReferenceDefined) + if (this.isReferenceDefined) { return this._nubRef.referencedParamValues.singleValue; + } return this._singleValue.value; } @@ -161,6 +163,12 @@ export class ParamValues implements INubReference, IterableValues { return this._currentValue.isDefined; } + private checkValueMode(expected: ParamValueMode) { + if (this._valueMode !== expected) { + throw new Error(`ParamValues : mode de valeurs ${ParamValueMode[expected]} incorrect`); + } + } + public get min() { switch (this._valueMode) { case ParamValueMode.MINMAX: @@ -241,42 +249,6 @@ export class ParamValues implements INubReference, IterableValues { return new ParamValueIterator(this, reverse); } - /** - * - * @param reverse prépare un itérateur pour parcourir les valeurs - */ - public initIterator(reverse: boolean = false) { - switch (this._valueMode) { - case ParamValueMode.LISTE: - case ParamValueMode.MINMAX: - this._iterator = this.getValuesIterator(reverse); - break; - - case ParamValueMode.LINK: - this._iterator = this._nubRef.referencedParamValues.getValuesIterator(reverse); - break; - - default: - throw new Error(`ParamValues : mode de valeurs ${ParamValueMode[this._valueMode]} incorrect`); - } - } - - /** - * @return true si il reste des valeurs à parcourir par l'itérateur courant - */ - public get hasNext(): boolean { - return this._iterator.hasNext; - } - - /** - * fixe la valeur courante à la prochaine valeur à parcourir par l'itérateur courant - * @return prochaine valeur à parcourir par l'itérateur courant - */ - public get next(): number { - this._currentValue.value = this._iterator.next().value; - return this._currentValue.value; - } - // interface INubReference public defineReference(target: IReferencedNub, desc: string) { @@ -317,8 +289,9 @@ export class ParamValues implements INubReference, IterableValues { } public get referencedObject(): NamedIterableValues { - if (this.isReferenceDefined) + if (this.isReferenceDefined) { return this._nubRef.referencedObject; + } return undefined; } @@ -329,23 +302,71 @@ export class ParamValues implements INubReference, IterableValues { } public get hasMultipleValues(): boolean { - if (this.isReferenceDefined) - var it = this.referencedValuesIterator; - else { + let it; + if (this.isReferenceDefined) { + it = this.referencedValuesIterator; + } else { // dans certains cas (mode LINK mais aucune valeur liable compatible), on ne peut avoir d'itérateur - if (this._valueMode !== ParamValueMode.LINK) + if (this._valueMode !== ParamValueMode.LINK) { it = this.getValuesIterator(); + } } - if (it === undefined) + if (it === undefined) { return false; + } let n = 0; for (const v of it) { n++; - if (n > 1) + if (n > 1) { break; + } } return n > 1; } + + public initValuesIterator(reverse: boolean = false): NumberIterator { + switch (this._valueMode) { + case ParamValueMode.LISTE: + case ParamValueMode.MINMAX: + this._iterator = this.getValuesIterator(reverse); + break; + + case ParamValueMode.LINK: + this._iterator = this.referencedObject.initValuesIterator(reverse); + break; + + default: + throw new Error(`ParamValues : mode de valeurs ${ParamValueMode[this._valueMode]} incorrect`); + } + + return this._iterator; + } + + /** + * @return true si il reste des valeurs à parcourir par l'itérateur courant + */ + public get hasNext(): boolean { + return this._iterator.hasNext; + } + + /** + * fixe la valeur courante à la prochaine valeur à parcourir par l'itérateur courant + * @return prochaine valeur à parcourir par l'itérateur courant + */ + public next(): IteratorResult<number> { + if (this.isReferenceDefined) + var res = this.referencedObject.next(); + else { + res = this._iterator.next(); + if (!res.done) + this._currentValue.value = res.value; + } + return res; + } + + public [Symbol.iterator](): IterableIterator<number> { + return this; + } } diff --git a/src/remous.ts b/src/remous.ts index ac0ee931a6983c133609d9ecef2170307fcd39fa..f23ac606f0f6244be9fd523c3fef1e8e42141ecc 100644 --- a/src/remous.ts +++ b/src/remous.ts @@ -543,7 +543,7 @@ export class CourbeRemous extends Nub { `Condition limite aval (${this.prms.Yaval.v}) >= ` + `Hauteur critique (${this.Sn.HautCritique}) : calcul de la partie fluviale à partir de l'aval`); this.Dx = this.prms.Dx.v; - xValues.initIterator(true); + xValues.initValuesIterator(true); res = this.calcul(this.prms.Yaval.v, xValues); res.insertMessage(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL)); } else { @@ -578,7 +578,7 @@ export class CourbeRemous extends Nub { ") <= Hauteur critique (" + this.Sn.HautCritique + ") : calcul de la partie torrentielle à partir de l'amont"); this.Dx = -this.prms.Dx.v; - xValues.initIterator(false); + xValues.initValuesIterator(false); res = this.calcul(this.prms.Yamont.v, xValues); res.insertMessage(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL)); } else { @@ -802,11 +802,11 @@ export class CourbeRemous extends Nub { const res = new ResultElement(); let lastY = YCL; - trY[round(varParam.next, this.prmSect.iPrec.v)] = lastY; + trY[round(varParam.next().value, this.prmSect.iPrec.v)] = lastY; // Boucle de calcul de la courbe de remous while (varParam.hasNext) { - const x = varParam.next; + const x = varParam.next().value; // this.debug("lastY " + lastY); const rY: Result = this.Calc_Y(lastY); // this.debug("calcul : x " + x + " y " + rY.vCalc); diff --git a/src/session_nub.ts b/src/session_nub.ts index 4a80ed6d6c84bcdb0d56487f0e3e798a1ba16bda..4313fab85a35e73b884dbf09cc58fb83453c7101 100644 --- a/src/session_nub.ts +++ b/src/session_nub.ts @@ -222,7 +222,18 @@ export class SessionNub { /** * liste des valeurs(paramètre, résultat, résultat complémentaire) liables à un paramètre * @param src objet qui sert de clé de recherche des paramètres liables, de type INamedObject | string - * @returns tableau d'objets de la forme { "value":NamedIterableValues, "nub":Nub}, nub=Nub d'origine de la "value" + * @returns tableau d'objets de la forme { "value":NamedIterableValues, "nub":Nub}, + * nub=Nub d'origine de la "value" + * + * l'étiquette "name" est de la forme <n|N1>[.[N2]] + * n : indice de de l'ouvrage dans le cas des ouvrages parallèles + * N1 : un nom de paramètre/résultat (dans le cas d'un résultat, il est suivi d'un point) + * N2 : nom de résultat complémentaire (optionnel) + * ex : + * Q, Z1 (paramètres) + * J. (résultat) + * .Yf (résultat complémentaire du résultat courant) + * Q.Yf (résultat complémentaire du résultat nommé "Q") */ public getLinkableValues(src: any, excludeResult: boolean = false): any[] { return this._nub.getLinkableValues(src, undefined, excludeResult); diff --git a/src/structure/parallel_structure.ts b/src/structure/parallel_structure.ts index 60299bc80d0f0b9872c038f3185b0d8a52820dfd..1ecbc67a0febad528dab4f8d83385f012a91d838 100644 --- a/src/structure/parallel_structure.ts +++ b/src/structure/parallel_structure.ts @@ -225,12 +225,16 @@ export class ParallelStructure extends Nub { const i: IStructureVarCalc = this.getStructureVarCalc(desc); return this.structures[i.index].getParameter(i.prm); } catch (e) { + // desc n'est pas de la forme n.X try { // analyse ouvrage[n].X const i: IStructureVarCalc = this.getStructureVarCalc2(desc); - return this.structures[i.index].result.getExtraResult(i.prm); + const res = this.structures[i.index].result; + if (res === undefined) + return undefined; // pas de résultat calculé + return res.getExtraResult(i.prm); } catch (e) { - // ??? + // desc n'est pas de la forme ouvrage[n].X } } // pas de la forme n.X ou ouvrage[n].X ou erreur sur n ou X diff --git a/src/util/iterator.ts b/src/util/iterator.ts index 190813773fb9fe94a8acd78edd9221ddf80a50a9..b33d36b9461241e2f116d8c4e016d123557642a8 100644 --- a/src/util/iterator.ts +++ b/src/util/iterator.ts @@ -10,7 +10,7 @@ export class ArrayReverseIterator<T> implements IterableIterator<T> { private _index: number; - constructor(private _arr: any[]) { + constructor(protected _arr: any[]) { this._index = this._arr === undefined ? 0 : this._arr.length - 1; } diff --git a/src/util/result.ts b/src/util/result.ts index 6c4ac03d06b95d66e157aa39a5b004242b653ba0..0998f141445eb78331682947b42ad45d284278e4 100644 --- a/src/util/result.ts +++ b/src/util/result.ts @@ -1,8 +1,8 @@ +import { JalhydObject } from "../jalhyd_object"; +import { NamedIterableValues, NumberIterator, NumberArrayReverseIterator, NumberArrayIterator } from "../param/param-value-iterator"; import { cLog } from "./log"; import { Message, MessageCode, MessageSeverity } from "./message"; import { ResultElement } from "./resultelement"; -import { JalhydObject } from "../jalhyd_object"; -import { NamedIterableValues, NumberIterator } from "../param/param-value-iterator"; /** * Résultat global d'un calcul @@ -22,6 +22,11 @@ export class Result extends JalhydObject implements NamedIterableValues { */ private _name: string; + /** + * itérateur sur les valeurs des ResultElements + */ + private _iterator: NumberIterator; + constructor(v?: number | Message | ResultElement, d?: any) { super(); this._globalLog = new cLog(); @@ -296,6 +301,38 @@ export class Result extends JalhydObject implements NamedIterableValues { return undefined; } + + public initValuesIterator(reverse: boolean = false): NumberIterator { + const vals: number[] = []; + for (const r of this._resultElements) { + vals.push(r.vCalc); + } + + if (reverse) + this._iterator = new NumberArrayReverseIterator(vals); + else + this._iterator = new NumberArrayIterator(vals); + + return this._iterator; + } + + public get hasNext(): boolean { + return this._iterator.hasNext; + } + + public next(): IteratorResult<number> { + return this._iterator.next(); + } + + public get currentValue(): number { + if (this._iterator === undefined) + return this.vCalc; + return this._iterator.currentValue; + } + + public [Symbol.iterator](): IterableIterator<number> { + return this; + } } /** @@ -306,6 +343,11 @@ export class ExtraResults extends JalhydObject implements NamedIterableValues { private _values: number[]; + /** + * itérateur courant + */ + private _iterator: NumberIterator; + constructor(n: string) { super(); this._name = n; @@ -329,4 +371,29 @@ export class ExtraResults extends JalhydObject implements NamedIterableValues { public get name(): string { return this._name; } + + public initValuesIterator(reverse: boolean = false): NumberIterator { + if (reverse) + this._iterator = new NumberArrayReverseIterator(this._values); + else + this._iterator = new NumberArrayIterator(this._values); + + return this._iterator; + } + + public get hasNext(): boolean { + return this._iterator.hasNext; + } + + public next(): IteratorResult<number> { + return this._iterator.next(); + } + + public get currentValue(): number { + return this._iterator.currentValue; + } + + public [Symbol.iterator](): IterableIterator<number> { + return this; + } } diff --git a/src/value_ref/object_ref.ts b/src/value_ref/object_ref.ts index b321604faacda0da1060ddf9d13a545697286afa..7670eaaaaca224f4f3b985c6ac42bacecd42cc7d 100644 --- a/src/value_ref/object_ref.ts +++ b/src/value_ref/object_ref.ts @@ -1,13 +1,30 @@ -import { ParamValues } from "../param/param-values"; -import { Result } from ".."; -import { IJalhydObject } from "../jalhyd_object"; +import { Nub } from "../nub"; import { NamedIterableValues, NumberIterator } from "../param/param-value-iterator"; +import { ParamValues } from "../param/param-values"; +import { Result } from "../util/result"; + +/* + * gestion de la valeur d'un paramètre par référence à une autre valeur (paramètre, résultat, résultat complémentaire) + * + * la référence (cf. INubReference.defineReference) (cf. INubReference.defineReference) est de la forme <n | ouvrage[n] | N1>[.[N2]] + * n : indice de de l'ouvrage dans le cas des ouvrages parallèles + * N1 : un nom de paramètre/résultat (dans le cas d'un résultat, il est suivi d'un point) + * N2 : nom de résultat complémentaire (optionnel) + * ex : + * Q, Z1 (paramètres) + * J. (résultat) + * .Yf (résultat complémentaire du résultat courant) + * Q.Yf (résultat complémentaire du résultat nommé "Q") + * 0.Q : paramètre Q du 1er ouvrage (ouvrages parallèles) + * ouvrage[1].Q_Mode : résultat complémentaire du 2ème ouvrage (ouvrages parallèles) + */ /** * Nub dont certaines valeurs sont référençables pour réutilisation * (d'une calculette sur une autre par ex) */ export interface IReferencedNub { + /** * getter des valeurs * @param desc : description sous forme symbolique @@ -132,8 +149,9 @@ export class NubReference implements INubReference { * instance de ParamValues référencée */ public get referencedParamValues(): ParamValues { - if (!this.isReferenceDefined) + if (!this.isReferenceDefined) { return undefined; + } return this._referencedNub.getReferencedParamValues(this._refDefinition); } @@ -141,8 +159,9 @@ export class NubReference implements INubReference { * instance de Result référencée */ public get referencedResult(): Result { - if (!this.isReferenceDefined) + if (!this.isReferenceDefined) { return undefined; + } return this._referencedNub.getReferencedResult(this._refDefinition); } @@ -150,8 +169,9 @@ export class NubReference implements INubReference { * instance de résultat complémentaire référencée */ public get referencedExtraResult(): any { - if (!this.isReferenceDefined) + if (!this.isReferenceDefined) { return undefined; + } return this._referencedNub.getReferencedExtraResult(this._refDefinition); }