diff --git a/spec/structure/parallel_structure.spec.ts b/spec/structure/parallel_structure.spec.ts index a473e54cfed2ff39ac5cba2a01c7b619ffe90a7e..8a01b1d2014e232fa97f1147a6ae49803962326f 100644 --- a/spec/structure/parallel_structure.spec.ts +++ b/spec/structure/parallel_structure.spec.ts @@ -18,35 +18,36 @@ import { checkResult } from "../test_func"; import { testParallelStructures } from "./functions"; import { structTest } from "./structure_test"; -const pstruct: ParallelStructure = new ParallelStructure( - new ParallelStructureParams(30, 30, 15), // Q = 30, Z1 = 30, Z2 = 15 - false // debug -); - -/* - * Tests avec deux structures test identiques - */ +function createEnv() { + const pstruct = new ParallelStructure( + new ParallelStructureParams(30, 30, 15), // Q = 30, Z1 = 30, Z2 = 15 + false // debug + ); + /* + * Tests avec deux structures test identiques + */ + pstruct.addChild(structTest); + pstruct.addChild(structTest); + return pstruct; +} -pstruct.addChild(structTest); -pstruct.addChild(structTest); +let pstruct: ParallelStructure; describe("Class ParallelStructure: ", () => { describe("Calc()", () => { + beforeEach(() => { + pstruct = createEnv(); + }); it("should return 1 result", () => { - const res: Result = pstruct.Calc("Q"); - expect(pstruct.Calc("Q").nbResultElements).toEqual(1); + const p1 = createEnv(); + const res: Result = p1.Calc("Q"); + expect(p1.Calc("Q").nbResultElements).toEqual(1); }); - itParallelStructure("Q", 30, 15); - itParallelStructure("Z1", 30, 15); - itParallelStructure("Z2", 15, 15); - itParallelStructure({ - uid: pstruct.structures[0].uid, - symbol: "ZDV" - }, 0, 15); - itParallelStructure({ - uid: pstruct.structures[1].uid, - symbol: "ZDV" - }, 0, 15); + itParallelStructure(null, "Q", 30, 15); + itParallelStructure(null, "Z1", 30, 15); + itParallelStructure(null, "Z2", 15, 15); + itParallelStructure(0, "ZDV", 0, 15); + itParallelStructure(1, "ZDV", 0, 15); it("shoud return an error Q too high", () => { pstruct.prms.Q.v = 14; const res: Result = pstruct.Calc({ @@ -57,6 +58,16 @@ describe("Class ParallelStructure: ", () => { }); }); }); +function getVarCalc(pstructLoc: ParallelStructure, structIndex: number, sVarCalc: string) : any { + if (structIndex !== null) { + return { + uid: pstructLoc.structures[structIndex].uid, + symbol: sVarCalc + }; + } else { + return sVarCalc; + } +} /** * Test sur ParallelStructure @@ -64,25 +75,30 @@ describe("Class ParallelStructure: ", () => { * @param rVcalc Valeur de référence à retrouver * @param Q Débit de chacune des structures (pour structures identiques uniquement) */ -function itParallelStructure(sVarCalc: any, rVcalc: number, Q?: number) { +function itParallelStructure(structIndex: number, sVarCalc: string, rVcalc: number, Q?: number) { it(`${sVarCalc} should be ${rVcalc}`, () => { - checkResult(pstruct.Calc(sVarCalc), rVcalc); + const VC1: any = getVarCalc(pstruct, structIndex, sVarCalc); + checkResult(pstruct.Calc(VC1), rVcalc); }); if (Q !== undefined) { - for (let i = 0; i < pstruct.structures.length; i++) { - it(`ExtraResult[ouvrage[${i}].Q] should be ${Q}`, () => { + const pstructLocal = createEnv(); + for (let i = 0; i < pstructLocal.structures.length; i++) { + it(`Calc(${JSON.stringify(sVarCalc)}) ExtraResult[ouvrage[${i}].Q] should be ${Q}`, () => { + const VC2: any = getVarCalc(pstruct, structIndex, sVarCalc); expect( - pstruct.Calc(sVarCalc).resultElement.extraResults[`ouvrage[${i}].Q`] + pstruct.Calc(VC2).resultElement.extraResults[`ouvrage[${i}].Q`] ).toBeCloseTo(Q, Math.max(0, precDigits - 1)); }); - it(`ExtraResult[ouvrage[${i}].Q_Mode] should be 0`, () => { + it(`Calc(${JSON.stringify(sVarCalc)}) ExtraResult[ouvrage[${i}].Q_Mode] should be 0`, () => { + const VC3 = getVarCalc(pstruct, structIndex, sVarCalc); expect( - pstruct.Calc(sVarCalc).resultElement.extraResults[`ouvrage[${i}].Q_ENUM_StructureFlowMode`] + pstruct.Calc(VC3).resultElement.extraResults[`ouvrage[${i}].Q_ENUM_StructureFlowMode`] ).toEqual(0); }); - it(`ExtraResult[ouvrage[${i}].Q_Regime] should be 0`, () => { + it(`Calc(${JSON.stringify(sVarCalc)}) ExtraResult[ouvrage[${i}].Q_Regime] should be 0`, () => { + const VC4 = getVarCalc(pstruct, structIndex, sVarCalc); expect( - pstruct.Calc(sVarCalc).resultElement.extraResults[`ouvrage[${i}].Q_ENUM_StructureFlowRegime`] + pstruct.Calc(VC4).resultElement.extraResults[`ouvrage[${i}].Q_ENUM_StructureFlowRegime`] ).toEqual(0); }); } diff --git a/spec/value_ref/value_ref.spec.ts b/spec/value_ref/value_ref.spec.ts index c07d15df38100e24403282aca46a88343773331c..c101298864c894401e8b4b5257bdcbbba19af3a5 100644 --- a/spec/value_ref/value_ref.spec.ts +++ b/spec/value_ref/value_ref.spec.ts @@ -6,7 +6,7 @@ */ // import { describe, expect, it } from "../mock_jasmine"; -import { Result, Session } from "../../src/index"; +import { Result, Session, ParamValueMode } from "../../src/index"; import { NubTest, NubTestParams } from "../nubtest"; import { precDigits } from "../test_config"; @@ -42,15 +42,16 @@ describe("référence d'un paramètre à un autre : ", () => { createEnv(); - prm2.A.v = 0; // valeur esclave, doit être masquée par la valeur maître (cad prm1.A, normalement 1) + // valeur esclave, doit être masquée par la valeur maître (cad prm1.A, normalement 1) + prm2.A.singleValue = 0; prm2.A.defineReference(nub1, "A"); - expect(prm1.A.v).toEqual(1); - expect(prm1.B.v).toEqual(2); - expect(prm1.C.v).toEqual(3); - expect(prm2.A.v).toEqual(1); - expect(prm2.B.v).toEqual(2); - expect(prm2.C.v).toEqual(3); + expect(prm1.A.singleValue).toEqual(1); + expect(prm1.B.singleValue).toEqual(2); + expect(prm1.C.singleValue).toEqual(3); + expect(prm2.A.singleValue).toEqual(1); + expect(prm2.B.singleValue).toEqual(2); + expect(prm2.C.singleValue).toEqual(3); }); it("test 2", () => { @@ -60,15 +61,16 @@ describe("référence d'un paramètre à un autre : ", () => { createEnv(); - prm2.B.v = 0; // valeur esclave, doit être masquée par la valeur maître (cad prm1.B, normalement 2) + // valeur esclave, doit être masquée par la valeur maître (cad prm1.B, normalement 2) + prm2.B.singleValue = 0; prm2.B.defineReference(nub1, "B"); - expect(prm1.A.v).toEqual(1); - expect(prm1.B.v).toEqual(2); - expect(prm1.C.v).toEqual(3); - expect(prm2.A.v).toEqual(1); - expect(prm2.B.v).toEqual(2); - expect(prm2.C.v).toEqual(3); + expect(prm1.A.singleValue).toEqual(1); + expect(prm1.B.singleValue).toEqual(2); + expect(prm1.C.singleValue).toEqual(3); + expect(prm2.A.singleValue).toEqual(1); + expect(prm2.B.singleValue).toEqual(2); + expect(prm2.C.singleValue).toEqual(3); }); it("test 3", () => { @@ -78,18 +80,19 @@ describe("référence d'un paramètre à un autre : ", () => { createEnv(); - prm2.C.v = 0; // valeur esclave, doit être masquée par la valeur maître (cad prm1.C, normalement 3) + // valeur esclave, doit être masquée par la valeur maître (cad prm1.C, normalement 3) + prm2.C.singleValue = 0; prm2.C.defineReference(nub1, "C"); // as C is a calculated param nub2.triggerChainCalculation(); - expect(prm1.A.v).toEqual(1); - expect(prm1.B.v).toEqual(2); - expect(prm1.C.v).toEqual(3); - expect(prm2.A.v).toEqual(1); - expect(prm2.B.v).toEqual(2); - expect(prm2.C.v).toEqual(3); + expect(prm1.A.singleValue).toEqual(1); + expect(prm1.B.singleValue).toEqual(2); + expect(prm1.C.singleValue).toEqual(3); + expect(prm2.A.singleValue).toEqual(1); + expect(prm2.B.singleValue).toEqual(2); + expect(prm2.C.singleValue).toEqual(3); }); it("test 4", () => { @@ -99,7 +102,8 @@ describe("référence d'un paramètre à un autre : ", () => { createEnv(); - prm2.A.v = 0; // valeur esclave, doit être masquée par la valeur maître (cad prm1.A, normalement 1) + // valeur esclave, doit être masquée par la valeur maître (cad prm1.A, normalement 1) + prm2.A.singleValue = 0; prm2.A.defineReference(nub1, "A"); expect(nub1.Calc("A").vCalc).toBeCloseTo(1, precDigits); @@ -118,18 +122,18 @@ describe("référence d'un paramètre à un autre : ", () => { createEnv(); - prm1.B.v = 3; // valeur maître - prm2.B.v = 0; // valeur esclave (doit être masquée par la valeur maître) + prm1.B.singleValue = 3; // valeur maître + prm2.B.singleValue = 0; // valeur esclave (doit être masquée par la valeur maître) prm2.B.defineReference(nub1, "B"); - expect(nub1.Calc("A").vCalc).toBeCloseTo(0, precDigits); - expect(nub1.Calc("B").vCalc).toBeCloseTo(3, precDigits); - expect(nub1.Calc("C").vCalc).toBeCloseTo(3, precDigits); + expect(nub1.CalcSerie(undefined, "A").vCalc).toBeCloseTo(0, precDigits); + expect(nub1.CalcSerie(undefined, "B").vCalc).toBeCloseTo(2, precDigits); + expect(nub1.CalcSerie(undefined, "C").vCalc).toBeCloseTo(4, precDigits); + + expect(nub2.CalcSerie(undefined, "A").vCalc).toBeCloseTo(0, precDigits); + expect(nub2.CalcSerie(undefined, "B").vCalc).toBeCloseTo(2, precDigits); + expect(nub2.CalcSerie(undefined, "C").vCalc).toBeCloseTo(4, precDigits); - expect(nub2.Calc("A").vCalc).toBeCloseTo(0, precDigits); - // tslint:disable-next-line:max-line-length - // expect(nub2.Calc("B").vCalc).toBeCloseTo(3, precDigits); // échoue car l'écriture du paramètre esclave (pendant la dichotomie) n'affecte pas la valeur maître; la relecture du paramètre esclave ne reflète pas la valeur écrite - expect(nub2.Calc("C").vCalc).toBeCloseTo(3, precDigits); }); it("test 6", () => { @@ -139,7 +143,8 @@ describe("référence d'un paramètre à un autre : ", () => { createEnv(); - prm2.C.v = 0; // valeur esclave, doit être masquée par la valeur maître (cad prm1.C, normalement 3) + // valeur esclave, doit être masquée par la valeur maître (cad prm1.C, normalement 3) + prm2.C.singleValue = 0; prm2.C.defineReference(nub1, "C"); expect(nub1.Calc("A").vCalc).toBeCloseTo(1, precDigits); @@ -160,15 +165,16 @@ describe("référence d'un paramètre à un autre : ", () => { createEnv(); - prm1.B.v = 5; + prm1.B.singleValue = 5; nub1.calculatedParam = prm1.C; - prm2.A.v = 0; // valeur esclave (doit être masquée par la valeur maître, cad prm1.C, normalement 3) + // valeur esclave (doit être masquée par la valeur maître, cad prm1.C, normalement 3) + prm2.A.singleValue = 0; prm2.A.defineReference(nub1, "C"); // as C is a calculated param nub2.triggerChainCalculation(); - expect(prm2.A.v).toBeCloseTo(6, precDigits); + expect(prm2.A.singleValue).toBeCloseTo(6, precDigits); }); it("test 2", () => { @@ -178,16 +184,14 @@ describe("référence d'un paramètre à un autre : ", () => { createEnv(); - prm1.C.v = 0; // valeur bidon, doit être 3 après calcul + prm1.C.singleValue = 0; // valeur bidon, doit être 3 après calcul nub1.calculatedParam = prm1.C; - prm2.C.v = 0; // valeur bidon, doit être 5 après calcul - prm2.A.v = 0; // valeur esclave bidon, doit être masquée par la valeur maître (cad prm1.C, normalement 3) + prm2.C.singleValue = 0; // valeur bidon, doit être 5 après calcul + // valeur esclave bidon, doit être masquée par la valeur maître (cad prm1.C, normalement 3) + prm2.A.singleValue = 0; prm2.A.defineReference(nub1, "C"); - // as C is a calculated param - nub2.triggerChainCalculation(); - - expect(nub2.Calc("C").vCalc).toBeCloseTo(5, precDigits); + expect(nub2.CalcSerie(undefined, "C").vCalc).toBeCloseTo(5, precDigits); }); it("test 3", () => { @@ -204,7 +208,7 @@ describe("référence d'un paramètre à un autre : ", () => { prm1.A.setValues(min, max, step); // valeur esclave bidon, doit être masquée par la valeur maître (cad prm1.A, normalement [1,2,3,4,5]) - prm2.A.v = 0; + prm2.A.singleValue = 0; prm2.A.defineReference(nub1, "A"); let n = 0; @@ -228,9 +232,9 @@ describe("référence d'un paramètre à un autre : ", () => { prm1.A.setValues(input); // valeur esclave bidon, doit être masquée par la valeur maître (cad prm1.A, normalement [2,3,4,5,6]) - prm2.A.v = 0; + prm2.A.singleValue = 0; prm2.A.defineReference(nub1, "A"); - prm2.Pr.v = 0.001; + prm2.Pr.singleValue = 0.001; const r: Result = nub2.CalcSerie(0.1, "C"); diff --git a/spec/value_ref/value_ref_indirect.spec.ts b/spec/value_ref/value_ref_indirect.spec.ts index 9e59d8766dd39005dfd4c3552296be7ae27eb6b2..aca3ba20d54efab48f4e95bc6fe2a572a1bf8212 100644 --- a/spec/value_ref/value_ref_indirect.spec.ts +++ b/spec/value_ref/value_ref_indirect.spec.ts @@ -29,14 +29,14 @@ let prm4: DeverParams; function createEnv() { // Nub 1 : Régime Uniforme const paramSect = new ParamsSectionCirc(2, 0.6613, 40, 1.2, 0.001, 1); - paramSect.Pr.v = 0.01; + paramSect.Pr.singleValue = 0.01; const sect = new cSnCirc(paramSect); nub1 = new RegimeUniforme(sect); prm1 = nub1.section.prms as ParamsSectionCirc; // Nub 2 : Section Paramétrée const prmsS = new ParamsSectionTrapez(1, 0.5, 1, 0.01, 1, 0.01, 2); - prmsS.Pr.v = 0.01; + prmsS.Pr.singleValue = 0.01; nub2 = new SectionParametree(new cSnTrapez(prmsS)); prm2 = nub2.section.prms as ParamsSectionTrapez; // = prmsS @@ -46,7 +46,7 @@ function createEnv() { // Nub 4 : Déversoirs Dénoyés prm4 = new DeverParams(0.5, 102, 10, 99); - prm4.Pr.v = 0.01; + prm4.Pr.singleValue = 0.01; nub4 = new Dever(prm4); nub4.addChild( CreateStructure( @@ -72,7 +72,7 @@ describe("référence indirecte d'un paramètre à un autre : ", () => { createEnv(); - prm3.Y.v = 0.1; // valeur esclave, doit être masquée par la valeur maître (cad prm1.Y) + prm3.Y.singleValue = 0.1; // valeur esclave, doit être masquée par la valeur maître (cad prm1.Y) prm3.Y.defineReference(nub2.section, "Y"); prm2.Y.defineReference(nub1.section, "Y"); @@ -88,7 +88,7 @@ describe("référence indirecte d'un paramètre à un autre : ", () => { createEnv(); - prm3.Y.v = 0.1; // valeur esclave, doit être masquée par la valeur maître (cad prm1.Y) + prm3.Y.singleValue = 0.1; // valeur esclave, doit être masquée par la valeur maître (cad prm1.Y) prm3.Y.defineReference(nub2.section, "Y"); prm2.Y.defineReference(nub1.section, "Y"); prm1.Y.setValues(2, 5, 1); @@ -105,12 +105,11 @@ describe("référence indirecte d'un paramètre à un autre : ", () => { createEnv(); - prm3.Y.v = 0.1; // valeur esclave, doit être masquée par la valeur maître (cad prm1.Y) + prm3.Y.singleValue = 0.1; // valeur esclave, doit être masquée par la valeur maître (cad prm1.Y) prm3.Y.defineReference(nub2.section, "Y"); prm2.Y.defineReference(nub1.section, "Y"); - prm1.LargeurBerge.v = 3.5; // Section Circ ! - prm1.Ks.v = 42; + prm1.Ks.singleValue = 42; nub1.calculatedParam = prm1.Y; nub3.CalcSerie(); @@ -125,12 +124,12 @@ describe("référence indirecte d'un paramètre à un autre : ", () => { createEnv(); - prm3.Y.v = 0.1; // valeur esclave, doit être masquée par la valeur maître (cad prm1.Y) + prm3.Y.singleValue = 0.1; // valeur esclave, doit être masquée par la valeur maître (cad prm1.Y) prm3.Y.defineReference(nub2.section, "Y"); prm2.Y.defineReference(nub1.section, "Y"); prm1.D.setValues(2.5, 7, 0.5); - prm1.Ks.v = 42; + prm1.Ks.singleValue = 42; nub1.calculatedParam = prm1.Y; nub3.CalcSerie(); @@ -154,7 +153,7 @@ describe("référence indirecte d'un paramètre à un autre : ", () => { createEnv(); - prm1.Q.v = 0.1; // valeur esclave, doit être masquée par la valeur maître (cad prm4.Q) + prm1.Q.singleValue = 0.1; // valeur esclave, doit être masquée par la valeur maître (cad prm4.Q) prm1.Q.defineReference(nub2.section, "Q"); nub1.calculatedParam = prm1.Ks; prm2.Q.defineReference(nub4, "CvQT"); @@ -173,7 +172,7 @@ describe("référence indirecte d'un paramètre à un autre : ", () => { createEnv(); - prm1.Q.v = 0.1; // valeur esclave, doit être masquée par la valeur maître (cad prm4.Q) + prm1.Q.singleValue = 0.1; // valeur esclave, doit être masquée par la valeur maître (cad prm4.Q) prm1.Q.defineReference(nub2.section, "Q"); nub1.calculatedParam = prm1.Ks; prm2.Q.defineReference(nub4, "CvQT"); diff --git a/spec/value_ref/value_ref_section.spec.ts b/spec/value_ref/value_ref_section.spec.ts index 50c1d19e6419ec62779b975ed7799bed2bc2b25c..4dec46b616240f2baf4b5511b19816800cba6f2a 100644 --- a/spec/value_ref/value_ref_section.spec.ts +++ b/spec/value_ref/value_ref_section.spec.ts @@ -51,12 +51,12 @@ describe("référence d'un paramètre à un autre : ", () => { createEnv(); - prm2.Q.v = 0; // valeur esclave, doit être masquée par la valeur maître (cad prm1.CvQT) + prm2.Q.singleValue = 0; // valeur esclave, doit être masquée par la valeur maître (cad prm1.CvQT) prm2.Q.defineReference(nub1, "CvQT"); - nub2.CalcSerie(); + nub2.CalcSerie(); // triggers chain calculation - expect(prm2.Q.v).toBeCloseTo(10.106); + expect(prm2.Q.singleValue).toBeCloseTo(10.106); }); }); }); diff --git a/src/dichotomie.ts b/src/dichotomie.ts index b17acfe1bfd897b7f52ea572e4c3ff058034a1df..21f744078216404a30bf51b7db6b541e18936b13 100644 --- a/src/dichotomie.ts +++ b/src/dichotomie.ts @@ -159,7 +159,7 @@ export class Dichotomie extends Debug { } private set vX(vCalc: number) { - this._paramX.setValue(vCalc); + this._paramX.v = vCalc; } /** diff --git a/src/linked-value.ts b/src/linked-value.ts index 9de169224e6fc016b6e4a57478df2163e78100d0..b817cdecded268cd9e929a940317b0faf333c5c1 100644 --- a/src/linked-value.ts +++ b/src/linked-value.ts @@ -3,7 +3,6 @@ import { ParamDefinition } from "./param/param-definition"; import { INamedIterableValues } from "./param/param-value-iterator"; import { ParamValueMode } from "./param/param-value-mode"; import { ParamValues } from "./param/param-values"; -import { Message, MessageCode } from "./util/message"; export class LinkedValue { /** linked value metadata (ex: calculator title for GUI) */ @@ -134,10 +133,6 @@ export class LinkedValue { if (targetParam.hasMultipleValues) { const multipleRes = this.nub.result.getCalculatedValues(); this._paramValues.setValues(multipleRes); - if (this._paramValues.currentValue === undefined) { - // or else isDefined() will return false - this._paramValues.currentValue = multipleRes[0]; - } } else { const singleRes = this.nub.result.vCalc; this._paramValues.setValues(singleRes); @@ -146,9 +141,6 @@ export class LinkedValue { // return local cache ret = this._paramValues; } else { - // else simple parameter proxy (see below) - // @TODO why ? risk of getting obsolete values ! - // ret = targetParam.paramValues; throw new Error("LinkedValue.getParamValues() - result not available"); } @@ -169,10 +161,6 @@ export class LinkedValue { if (this.nub.resultHasMultipleValues()) { const multipleExtraRes = this.nub.result.getExtraResults(this.symbol); this._paramValues.setValues(multipleExtraRes); - if (this._paramValues.currentValue === undefined) { - // or else isDefined() will return false - this._paramValues.currentValue = multipleExtraRes[0]; - } } else { const singleExtraRes = this.nub.result.getExtraResult(this.symbol); this._paramValues.setValues(singleExtraRes); @@ -192,33 +180,12 @@ export class LinkedValue { } /** - * Returns the current value of this.paramValues; triggers a chain computation - * if required to obtain ParamValues; throws an error if this.paramValues is - * ultimately not defined + * Returns the single value of this.paramValues; triggers a chain computation + * if required to obtain ParamValues */ public getValue(triggerChainComputation: boolean = false) { const pv = this.getParamValues(triggerChainComputation); - if (! pv.isDefined) { - const e = new Message(MessageCode.ERROR_PARAMDEF_LINKED_VALUE_UNDEFINED); - e.extraVar.symbol = this.symbol; - throw e; - } - return pv.currentValue; - } - - /** - * Returns the current multiple values list of this.paramValues; triggers a - * chain computation if required to obtain ParamValues; throws an error if - * this.paramValues is ultimately not defined - */ - public getValues(triggerChainComputation: boolean = false): number[] { - const pv = this.getParamValues(triggerChainComputation); - if (! pv.isDefined) { - const e = new Message(MessageCode.ERROR_PARAMDEF_LINKED_VALUE_UNDEFINED); - e.extraVar.symbol = this.symbol; - throw e; - } - return pv.valueList; + return pv.singleValue; } /** @@ -236,6 +203,17 @@ export class LinkedValue { return false; } + /** + * Returns true if target value is available + */ + public isDefined() { + if (this.isExtraResult()) { + return (this.nub.result !== undefined); + } else { + return (this.element as ParamDefinition).isDefined; + } + } + /** * When invalidating a Nub's result, parameters pointing to this result should * invalidate their proxy paramValues too @@ -243,4 +221,17 @@ export class LinkedValue { public invalidateParamValues() { this._paramValues = undefined; } + + /** + * Calles before calculation: asks target parameter to copy its + * single value to its current value so that .v is up to date + */ + public setCurrentValueFromSingleValue() { + if (this.isParameter()) { + const targetParam = (this.element as ParamDefinition); + if (targetParam.valueMode === ParamValueMode.SINGLE) { + targetParam.paramValues.currentValue = targetParam.paramValues.singleValue; + } + } + } } diff --git a/src/nub.ts b/src/nub.ts index f18235deb176287136d9b1d624e95f23e19eda29..4cbca8c0aeb50b5dd41c82e1c1db0936625e5052 100644 --- a/src/nub.ts +++ b/src/nub.ts @@ -256,7 +256,7 @@ export abstract class Nub extends ComputeNode implements IObservable { return this._result; } const sAnalyticalPrm: string = this.getFirstAnalyticalParameter().symbol; - computedVar.setValue(resSolve.vCalc); + computedVar.v = resSolve.vCalc; const res: Result = this.Equation(sAnalyticalPrm); res.vCalc = resSolve.vCalc; this._result = res; @@ -298,8 +298,10 @@ export abstract class Nub extends ComputeNode implements IObservable { this.progress = 0; this.triggerChainCalculation(); + this.copySingleValuesToCurrentValues(); + + // check which values are variating, if any for (const p of this.parameterIterator) { - // checks which values are variating, if any switch (p.valueMode) { case ParamValueMode.SINGLE: case ParamValueMode.CALCUL: @@ -360,7 +362,8 @@ export abstract class Nub extends ComputeNode implements IObservable { variatedValues.initValuesIterator(false); while (variatedValues.hasNext) { - variatedValues.next(); + const currentIteratorValue = variatedValues.next(); + variatedParam.v = currentIteratorValue.value; // copy to local sandbox value this.Calc(computedSymbol, rInit); // résultat dans this._result if (this._result.ok) { @@ -1019,6 +1022,31 @@ export abstract class Nub extends ComputeNode implements IObservable { this._observable.notifyObservers(data, sender); } + /** + * For all SINGLE, LINK and CALC parameters, copies singleValue to + * currentValue (.v) before calculation + */ + protected copySingleValuesToCurrentValues() { + for (const p of this.parameterIterator) { + switch (p.valueMode) { + case ParamValueMode.SINGLE: + case ParamValueMode.CALCUL: + p.v = p.singleValue; + break; + case ParamValueMode.LINK: + if (p.referencedValue) { + p.v = p.referencedValue.getValue(); + } else { + throw Error("Nub.CalcSerie() : linked value not defined"); + } + break; + default: + // variable mode, let iterator do the job + p.v = undefined; + } + } + } + /** * To call Nub.calc(…) from indirect child */ diff --git a/src/param/param-definition.ts b/src/param/param-definition.ts index 13b100c3b7c605837b1a4c51322a232d588f32c7..fc9b44f5ea2c5b780f66f7046d0e5a3c5f90e3a6 100644 --- a/src/param/param-definition.ts +++ b/src/param/param-definition.ts @@ -50,6 +50,9 @@ export class ParamDefinition implements INamedIterableValues, IObservable { /** le paramètre doit-il être exposé (par ex: affiché par l'interface graphique) ? */ public visible: boolean = true; + /** sandbox value used during calculation */ + public v: number; + /** mode de génération des valeurs : min/max, liste, ... */ private _valueMode: ParamValueMode; @@ -84,7 +87,11 @@ export class ParamDefinition implements INamedIterableValues, IObservable { this._symbol = symb; this._observable = new Observable(); this._paramValues = new ParamValues(); + + // set single value and copy it to currentValue this._paramValues.singleValue = val; + this.v = val; + this._calc = ParamCalculability.FREE; this._family = family; this.visible = visible; @@ -370,74 +377,84 @@ export class ParamDefinition implements INamedIterableValues, IObservable { } /** - * Proxy to getValue(); never triggers chain computation + * Returns true if current value (not singleValue !) is defined */ - get v(): number { - return this.getValue(); + public get hasCurrentValue(): boolean { + return (this.v !== undefined); } /** - * set value, with calculability control - * @TODO move calculability control to setValue() ? + * Returns true if held value (not currentValue !) is defined, + * depending on the value mode */ - set v(val: number) { - if (this.calculability === ParamCalculability.NONE) { - const e = new Message(MessageCode.ERROR_PARAMDEF_VALUE_FIXED); - e.extraVar.symbol = this.symbol; - throw e; - } - this.setValue(val); - } - public get isDefined(): boolean { - try { - return this.paramValues.isDefined; - } catch (e) { - // unavailable targetted result (pending calculation) - return false; + let defined = false; + switch (this.valueMode) { + case ParamValueMode.SINGLE: + defined = (this.singleValue !== undefined); + break; + case ParamValueMode.MINMAX: + defined = ( + this.paramValues.min !== undefined + && this.paramValues.max !== undefined + && this.paramValues.step !== undefined + ); + break; + case ParamValueMode.LISTE: + defined = (this.valueList.length > 0 && this.valueList[0] !== undefined); + break; + case ParamValueMode.CALCUL: + if (this.parentNub && this.parentNub.result && this.parentNub.result.nbResultElements > 0) { + const res = this.parentNub.result; + defined = (res.vCalc !== undefined); + } + break; + case ParamValueMode.LINK: + defined = this.referencedValue.isDefined(); } + return defined; } // -- values getters / setters; in LINK mode, reads / writes from / to the target values public get singleValue(): number { - this.checkValueMode(ParamValueMode.SINGLE); + this.checkValueMode([ParamValueMode.SINGLE, ParamValueMode.CALCUL, ParamValueMode.LINK]); return this.paramValues.singleValue; } public set singleValue(v: number) { - this.checkValueMode(ParamValueMode.SINGLE); + this.checkValueMode([ParamValueMode.SINGLE, ParamValueMode.CALCUL, ParamValueMode.LINK]); this.paramValues.singleValue = v; this.notifyValueModified(this); } public get min() { - this.checkValueMode(ParamValueMode.MINMAX); + this.checkValueMode([ParamValueMode.MINMAX, ParamValueMode.LINK]); return this.paramValues.min; } public set min(v: number) { - this.checkValueMode(ParamValueMode.MINMAX); + this.checkValueMode([ParamValueMode.MINMAX]); this.paramValues.min = v; } public get max() { - this.checkValueMode(ParamValueMode.MINMAX); + this.checkValueMode([ParamValueMode.MINMAX, ParamValueMode.LINK]); return this.paramValues.max; } public set max(v: number) { - this.checkValueMode(ParamValueMode.MINMAX); + this.checkValueMode([ParamValueMode.MINMAX]); this.paramValues.max = v; } public get step() { - this.checkValueMode(ParamValueMode.MINMAX); + this.checkValueMode([ParamValueMode.MINMAX, ParamValueMode.LINK]); return this.paramValues.step; } public set step(v: number) { - this.checkValueMode(ParamValueMode.MINMAX); + this.checkValueMode([ParamValueMode.MINMAX]); this.paramValues.step = v; } @@ -445,17 +462,17 @@ export class ParamDefinition implements INamedIterableValues, IObservable { * Generates a reference step value, given the current (local) values for min / max */ public get stepRefValue(): Interval { - this.checkValueMode(ParamValueMode.MINMAX); + this.checkValueMode([ParamValueMode.MINMAX]); return new Interval(1e-9, this._paramValues.max - this._paramValues.min); } public get valueList() { - this.checkValueMode(ParamValueMode.LISTE); + this.checkValueMode([ParamValueMode.LISTE, ParamValueMode.LINK]); return this.paramValues.valueList; } public set valueList(l: number[]) { - this.checkValueMode(ParamValueMode.LISTE); + this.checkValueMode([ParamValueMode.LISTE]); this.paramValues.valueList = l; } @@ -463,23 +480,22 @@ export class ParamDefinition implements INamedIterableValues, IObservable { return this.paramValues.valuesIterator.count(); } - /** - * Get current value (not singleValue !) - * Might throw an error if parameter is in LINK mode, and target - * value is a result that is not yet computed - */ - public getValue(): number { - if (! this.paramValues.isDefined) { - const e = new Message(MessageCode.ERROR_PARAMDEF_VALUE_UNDEFINED); - e.extraVar.symbol = this.symbol; - throw e; - } + // for INumberiterator interface + public get currentValue(): number { + // magically follows links return this.paramValues.currentValue; } - // for INumberiterator interface - public get currentValue(): number { - return this.getValue(); + public set currentValue(v: number) { + // magically follows links + this.paramValues.currentValue = v; + } + + /** + * Get single value + */ + public getValue(): number { + return this.paramValues.singleValue; } /** @@ -507,7 +523,7 @@ export class ParamDefinition implements INamedIterableValues, IObservable { */ public setValue(val: number, sender?: any) { this.checkValueAgainstDomain(val); - this.paramValues.currentValue = val; + this.paramValues.singleValue = val; // this.notifyValueModified(sender); // @TODO why ? currentValue is only used temporarily for calculation } @@ -590,11 +606,11 @@ export class ParamDefinition implements INamedIterableValues, IObservable { } /** - * Return true if current value is valid regarding the domain constraints + * Return true if single value is valid regarding the domain constraints */ get isValueValid(): boolean { try { - const v = this.getValue(); + const v = this.paramValues.singleValue; this.checkValueAgainstDomain(v); return true; } catch (e) { @@ -760,7 +776,7 @@ export class ParamDefinition implements INamedIterableValues, IObservable { // adjust parameter representation depending on value mode switch (this._valueMode) { case ParamValueMode.SINGLE: - paramRep.value = this.getValue(); + paramRep.value = this.singleValue; break; case ParamValueMode.MINMAX: @@ -1100,9 +1116,11 @@ export class ParamDefinition implements INamedIterableValues, IObservable { * In LINK mode, the tested valueMode is the mode of the ultimately targetted * set of values (may never be LINK) */ - private checkValueMode(expected: ParamValueMode) { - if (this.paramValues.valueMode !== expected) { - throw new Error(`ParamValues : mode de valeurs ${ParamValueMode[expected]} incorrect`); + private checkValueMode(expected: ParamValueMode[]) { + if (! expected.includes(this.valueMode)) { + throw new Error( + `ParamDefinition : mode de valeurs ${ParamValueMode[this.valueMode]} incorrect` + ); } } diff --git a/src/param/param-values.ts b/src/param/param-values.ts index badb8433f819f721766be6945e081e18fbbf2842..e367f6173174cf6ee1fe1afbac0da1a33ba9a434 100644 --- a/src/param/param-values.ts +++ b/src/param/param-values.ts @@ -42,7 +42,6 @@ export class ParamValues implements IterableValues { public set singleValue(v: number) { this._singleValue = v; - this.currentValue = v; } public count() { @@ -54,18 +53,15 @@ export class ParamValues implements IterableValues { if (max === undefined) { this.valueMode = ParamValueMode.SINGLE; this.singleValue = o; - this.currentValue = o; } else { this.valueMode = ParamValueMode.MINMAX; this.min = o; this.max = max; this.step = step; - this.currentValue = undefined; } } else if (Array.isArray(o)) { this.valueMode = ParamValueMode.LISTE; this.valueList = o; - this.currentValue = undefined; } else { throw new Error(`ParamValues.setValues() : appel invalide`); } @@ -107,10 +103,6 @@ export class ParamValues implements IterableValues { } } - public get isDefined() { - return this.currentValue !== undefined; - } - // -- iterator-related methods /** diff --git a/src/section/section_circulaire.ts b/src/section/section_circulaire.ts index 4ff68af501fbcdcc70f02a0985eb0d4d341e4d1e..af68e902e0e87710bff49ebcfb450b4a9790135b 100644 --- a/src/section/section_circulaire.ts +++ b/src/section/section_circulaire.ts @@ -92,7 +92,7 @@ export class cSnCirc extends acSection { } this.debug("circ.Calc_B() : PAS débordement"); - if (this.prms.D.isDefined && this.prms.Y.isDefined) { + if (this.prms.D.hasCurrentValue && this.prms.Y.hasCurrentValue) { const rAlpha: Result = this.calcFromY("Alpha"); if (!rAlpha.ok) { return rAlpha; @@ -104,8 +104,8 @@ export class cSnCirc extends acSection { } const e: Message = new Message(MessageCode.ERROR_PARAMDEF_VALUE_UNDEFINED); - e.extraVar.diameterValue = this.prms.D.isDefined ? String(this.prms.D.v) : "undefined"; - e.extraVar.yValue = this.prms.Y.isDefined ? String(this.prms.Y.v) : "undefined"; + e.extraVar.diameterValue = this.prms.D.hasCurrentValue ? String(this.prms.D.v) : "undefined"; + e.extraVar.yValue = this.prms.Y.hasCurrentValue ? String(this.prms.Y.v) : "undefined"; throw e; } diff --git a/src/structure/cloisons.ts b/src/structure/cloisons.ts index 5dd0b51964c721398197427a7969dd2e84f07f6e..70c53d652a19b553392cebc59db21dac23327a25 100644 --- a/src/structure/cloisons.ts +++ b/src/structure/cloisons.ts @@ -5,7 +5,7 @@ import { ParamCalculability } from "../param/param-definition"; import { Result } from "../util/result"; import { CloisonsParams } from "./cloisons_params"; import { ParallelStructure } from "./parallel_structure"; -import { StructureKivi, StructureKiviParams } from "./structure_kivi"; +import { StructureKiviParams } from "./structure_kivi"; import { loiAdmissiblesCloisons, LoiDebit } from "./structure_props"; export { CloisonsParams }; @@ -54,7 +54,7 @@ export class Cloisons extends ParallelStructure { case "BB": r = this.nubCalc(sVC, rInit); if (r.ok) { - this.getParameter(sVC).setValue(r.vCalc); + this.getParameter(sVC).v = r.vCalc; } break; default: diff --git a/src/structure/dever.ts b/src/structure/dever.ts index fedcf19599084101a75386072526d3feee0eaba2..368510fea9558dc5a089ccfd74e5ef47e65806c4 100644 --- a/src/structure/dever.ts +++ b/src/structure/dever.ts @@ -67,7 +67,7 @@ export class Dever extends ParallelStructure { case "ZR": res = this.nubCalc(sVarCalc, rInit); if (res.ok) { - this.getParameter(sVarCalc).setValue(res.vCalc); + this.getParameter(sVarCalc).v = res.vCalc; } break; default: diff --git a/src/structure/factory_structure.ts b/src/structure/factory_structure.ts index f1f0b7c069d03772125befd1885995c09e1be794..1379b405f308414b607978ff940bef0966d7775d 100644 --- a/src/structure/factory_structure.ts +++ b/src/structure/factory_structure.ts @@ -39,7 +39,7 @@ export function CreateStructure(loiDebit: LoiDebit, parentNub?: ParallelStructur case LoiDebit.Cunge80: case LoiDebit.RectangularOrificeFree: case LoiDebit.RectangularOrificeSubmerged: - rectStructPrms.W.v = 0.5; + rectStructPrms.W.singleValue = 0.5; rectStructPrms.Cd.v = oCd.VanneR; // Cd pour une vanne rectangulaire } diff --git a/src/structure/parallel_structure.ts b/src/structure/parallel_structure.ts index 7b589783e9e8a691e86169891de7852f0fc1e564..2f4f8e32a49a17ff2db8ed51f02d1c95173c2730 100644 --- a/src/structure/parallel_structure.ts +++ b/src/structure/parallel_structure.ts @@ -105,7 +105,7 @@ export class ParallelStructure extends Nub { case "Q": res = super.Calc(sVarCalc, rInit); if (res.ok) { - this.getParameter(sVarCalc).setValue(res.vCalc); + this.getParameter(sVarCalc).v = res.vCalc; } break; default: @@ -118,7 +118,7 @@ export class ParallelStructure extends Nub { // Suppression des extraResults : ils sont complétés plus bas pour chaque ouvrage res.resultElement.extraResults = {}; if (res.ok) { - this._children[structureIndex].getParameter(sVarCalc.symbol).setValue(res.vCalc); + this._children[structureIndex].getParameter(sVarCalc.symbol).v = res.vCalc; } } if (res.ok) { @@ -179,7 +179,7 @@ export class ParallelStructure extends Nub { */ protected CalcStructPrm(index: number, symbol: string, rInit?: number): Result { // Le débit restant sur la structure en calcul est : - this.structures[index].prms.Q.setValue(this.prms.Q.v - this.CalcQ(index).vCalc); + this.structures[index].prms.Q.v = this.prms.Q.v - this.CalcQ(index).vCalc; // Calcul du paramètre de la structure en calcul return this.structures[index].Calc(symbol, rInit); diff --git a/src/structure/structure_cem88d.ts b/src/structure/structure_cem88d.ts index 8c08a710694713d4cc809de003996e08f22f269d..7d960877c7196de70d66a60fcdee71b7c14a10c6 100644 --- a/src/structure/structure_cem88d.ts +++ b/src/structure/structure_cem88d.ts @@ -6,8 +6,6 @@ import { LoiDebit } from "./structure_props"; export { RectangularStructureParams }; - - /** * Equation CEM88D : déversoir / orifice (pelle importante) Cemagref 1988 */