diff --git a/boilerplate/ts/src/boilerplate.ts b/boilerplate/ts/src/boilerplate.ts index 4c8587c6e14765e139c229a9c02d5b82934252b0..5421d43e8cad7b288b749d5847993efa810fda65 100644 --- a/boilerplate/ts/src/boilerplate.ts +++ b/boilerplate/ts/src/boilerplate.ts @@ -7,20 +7,15 @@ import { formattedValue, LoiDebit, Props, - Session + Session, + Cloisons, + PabChute, + PabNombre, + PabPuissance, + PabDimension, + RectangularStructure } from "jalhyd"; -/** - * Not all classes are exported through index.d.ts, prefer importing - * classes using full path - */ -import { Cloisons } from "jalhyd/build/pab/cloisons"; -import { PabChute } from "jalhyd/build/pab/pab_chute"; -import { PabDimension } from "jalhyd/build/pab/pab_dimension"; -import { PabNombre } from "jalhyd/build/pab/pab_nombre"; -import { PabPuissance } from "jalhyd/build/pab/pab_puissance"; -import { RectangularStructure } from "jalhyd/build/structure/rectangular_structure"; - // ---- example of modules setup and calculation : fish ladder ---- const pabChute = Session.getInstance().createSessionNub( diff --git a/package-lock.json b/package-lock.json index 81da99e6e87b129e1a01de03ad740f4ac6ecb94a..3726cb5715387e4d42ea6cae09b51acc3512d829 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "LGPL-3.0-or-later", "dependencies": { "@types/base-64": "^1.0.0", + "@types/lodash": "^4.14.191", "base-64": "^1.0.0" }, "devDependencies": { @@ -284,6 +285,11 @@ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", "dev": true }, + "node_modules/@types/lodash": { + "version": "4.14.191", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz", + "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==" + }, "node_modules/@types/node": { "version": "18.0.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.3.tgz", @@ -2777,6 +2783,11 @@ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", "dev": true }, + "@types/lodash": { + "version": "4.14.191", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz", + "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==" + }, "@types/node": { "version": "18.0.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.3.tgz", diff --git a/package.json b/package.json index 01d22ed74231dc3a8f8113a703c00815a64fb564..0b8cfecc6d68330f4db0e94ed0f798ee2a22bf0a 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "module": "build/index.js", "dependencies": { "@types/base-64": "^1.0.0", + "@types/lodash": "^4.14.191", "base-64": "^1.0.0" }, "devDependencies": { diff --git a/spec/fuzzing.spec.ts b/spec/fuzzing.spec.ts index 8dead94243e8e6dd27123927ab82803368df6172..87adb5ba9c87276bfdd1eee41db7a3291d6d60fd 100644 --- a/spec/fuzzing.spec.ts +++ b/spec/fuzzing.spec.ts @@ -1,5 +1,5 @@ import { CalculatorType } from "../src/compute-node"; -import { Grille, ParamDomainValue, Session, SPP, YAXN, YAXNParams, Par, ParSimulation, ParSimulationParams } from "../src/index"; +import { Grille, ParamDomainValue, Session, SPP, YAXN, YAXNParams, Par, ParSimulation, ParSimulationParams, PressureLoss, PL_LechaptCalmonParams, PL_LechaptCalmon } from "../src/index"; import { MacrorugoCompound } from "../src/macrorugo/macrorugo_compound"; import { Trigo, TrigoOperation } from "../src/math/trigo"; import { Nub } from "../src/nub"; @@ -7,7 +7,7 @@ import { SectionNub } from "../src/open-channel/section/section_nub"; import { CloisonAval } from "../src/pab/cloison_aval"; import { Pab } from "../src/pab/pab"; import { ParamDefinition } from "../src/param/param-definition"; -import { PressureLossType } from "../src/pipe_flow/pressureloss_law"; +import { PressureLossLaw, PressureLossType } from "../src/pipe_flow/pressureloss_law"; import { Props } from "../src/props"; import { CreateStructure } from "../src/structure/factory_structure"; import { ParallelStructure } from "../src/structure/parallel_structure"; @@ -46,7 +46,8 @@ const nubsNotTested: CalculatorType[] = [ CalculatorType.Espece, CalculatorType.PbBassin, CalculatorType.PbCloison, - CalculatorType.PreBarrage // TODO: Add special treatments for creating fuzzy PreBarrage + CalculatorType.PreBarrage, // TODO: Add special treatments for creating fuzzy PreBarrage + CalculatorType.LechaptCalmon ]; const nubsWithStructures: CalculatorType[] = [ @@ -61,6 +62,10 @@ const nubsWithSection: CalculatorType[] = [ CalculatorType.CourbeRemous ]; +const nubsWithPressureLossLaw: CalculatorType[] = [ + CalculatorType.PressureLoss +] + const calTypes = Object.keys(CalculatorType) .filter((key: any) => @@ -127,6 +132,26 @@ function setRandomSection(sn: SectionNub) { sn.setSection(newSect); } +function setRandomPressureLossLaw(pl: PressureLoss) { + const pressureLossLaws = [CalculatorType.LechaptCalmon]; + const i = Math.floor(Math.random() * pressureLossLaws.length); + let pll: PressureLossLaw; + switch (pressureLossLaws[i]) { + case CalculatorType.LechaptCalmon: + const lcp = new PL_LechaptCalmonParams(1.863, 2, 5.33); // peu importe les valeurs, elles sont randomisées + randomizeParameter(lcp.L); + randomizeParameter(lcp.M); + randomizeParameter(lcp.N); + const lc = new PL_LechaptCalmon(lcp); + pll = lc; + break; + + default: + throw new Error("invalid pressure loss law"); + } + pl.setLaw(pll); +} + function setRandomTrigoOperation(sn: Trigo) { const op = Math.floor(Math.random() * 6); sn.operation = op; @@ -169,7 +194,7 @@ function setPab(pab: Pab, nClMax = 30, nStMax = 3) { } function setMacrorugoCompound(n: MacrorugoCompound) { - n.properties.setPropValue("inclinedApron", Math.floor(Math.random() * 2)); + n.setPropValue("inclinedApron", Math.floor(Math.random() * 2)); } function setGrille(g: Grille) { @@ -189,8 +214,11 @@ function CreateTestNub(iCalType: number): Nub { if (nubsWithSection.includes(iCalType)) { setRandomSection(n as SectionNub); } + if (nubsWithPressureLossLaw.includes(iCalType)) { + setRandomPressureLossLaw(n as PressureLoss); + } if (iCalType === CalculatorType.CourbeRemous) { - n.properties.setPropValue( + n.setPropValue( "methodeResolution", Math.floor(Math.random() * 3) // Euler, RK4, Trapèzes ); diff --git a/spec/macrorugo/macrorugo_compound.spec.ts b/spec/macrorugo/macrorugo_compound.spec.ts index b71376acb302d436b25cd76f991c9b58bdf1ff3e..be2e09c8f6dd3b811316aea450de0453f1ee7f86 100644 --- a/spec/macrorugo/macrorugo_compound.spec.ts +++ b/spec/macrorugo/macrorugo_compound.spec.ts @@ -73,7 +73,7 @@ describe("MacroRugoCompound: ", () => { const mrc = Session.getInstance().createNub( new Props({ calcType: CalculatorType.MacroRugoCompound }) ) as MacrorugoCompound; - mrc.properties.setPropValue("inclinedApron", MRCInclination.INCLINED); + mrc.setPropValue("inclinedApron", MRCInclination.INCLINED); mrc.prms.BR.singleValue = BR; const mr = getMacroRugoRef(); const res = mrc.CalcSerie(); @@ -97,7 +97,7 @@ describe("MacroRugoCompound: ", () => { const mrc = Session.getInstance().createNub( new Props({ calcType: CalculatorType.MacroRugoCompound }) ) as MacrorugoCompound; - mrc.properties.setPropValue("inclinedApron", MRCInclination.INCLINED); + mrc.setPropValue("inclinedApron", MRCInclination.INCLINED); // width = 4m mrc.prms.BR.singleValue = 5; // delta Z = 2m diff --git a/spec/macrorugo/macrorugo_compound_jalhyd174.spec.ts b/spec/macrorugo/macrorugo_compound_jalhyd174.spec.ts index ffdc327280fc09bc9f45bfb5b127ae7bc3cdce16..f7178f010cb0db619f578fca8eb18af13920cba8 100644 --- a/spec/macrorugo/macrorugo_compound_jalhyd174.spec.ts +++ b/spec/macrorugo/macrorugo_compound_jalhyd174.spec.ts @@ -62,7 +62,7 @@ describe("MacroRugoCompound: ", () => { nub = Session.getInstance().createNub( new Props({ calcType: CalculatorType.MacroRugoCompound }) ) as MacrorugoCompound; - nub.properties.setPropValue("inclinedApron", MRCInclination.INCLINED); + nub.setPropValue("inclinedApron", MRCInclination.INCLINED); nub.prms.C.singleValue = 0.09; // easy sqrt nub.prms.PBD.singleValue = 0.6; // ax = 2 nub.prms.BR.singleValue = 3; @@ -82,7 +82,7 @@ describe("MacroRugoCompound: ", () => { nub = Session.getInstance().createNub( new Props({ calcType: CalculatorType.MacroRugoCompound }) ) as MacrorugoCompound; - nub.properties.setPropValue("inclinedApron", MRCInclination.INCLINED); + nub.setPropValue("inclinedApron", MRCInclination.INCLINED); nub.prms.C.singleValue = 0.09; nub.prms.PBD.singleValue = 0.6; nub.prms.BR.singleValue = 1.95; @@ -104,7 +104,7 @@ describe("MacroRugoCompound: ", () => { nub = Session.getInstance().createNub( new Props({ calcType: CalculatorType.MacroRugoCompound }) ) as MacrorugoCompound; - nub.properties.setPropValue("inclinedApron", MRCInclination.INCLINED); + nub.setPropValue("inclinedApron", MRCInclination.INCLINED); nub.prms.C.singleValue = 0.09; nub.prms.PBD.singleValue = 0.6; nub.prms.BR.singleValue = 5.8; diff --git a/spec/macrorugo/macrorugo_compound_jalhyd284.spec.ts b/spec/macrorugo/macrorugo_compound_jalhyd284.spec.ts index 1c6fe7ef7b09779df031972bb911abda0c58da9e..9c170171a7be7a2f1c466038d80af321ac4a98a2 100644 --- a/spec/macrorugo/macrorugo_compound_jalhyd284.spec.ts +++ b/spec/macrorugo/macrorugo_compound_jalhyd284.spec.ts @@ -11,7 +11,7 @@ describe("MacroRugoCompound: ", () => { nub = Session.getInstance().createNub( new Props({ calcType: CalculatorType.MacroRugoCompound }) ) as MacrorugoCompound; - nub.properties.setPropValue("inclinedApron", MRCInclination.INCLINED); + nub.setPropValue("inclinedApron", MRCInclination.INCLINED); }); describe("jalhyd #284 warnings about block concentration − ", () => { diff --git a/spec/pipe_flow/lechaptcalmon.spec.ts b/spec/pipe_flow/lechaptcalmon.spec.ts index a7fa7bc264f73527a6aa74e812556c0c870e74a0..7625d080670cc32636422e63de9f3ab8f83e3d19 100644 --- a/spec/pipe_flow/lechaptcalmon.spec.ts +++ b/spec/pipe_flow/lechaptcalmon.spec.ts @@ -1,28 +1,56 @@ +import { PressureLoss, PressureLossParams } from "../../src/internal_modules"; +import { LCMaterial } from "../../src/lc-material"; import { ParamCalculability } from "../../src/param/param-definition"; import { PL_LechaptCalmon } from "../../src/pipe_flow/pl_lechaptcalmon"; import { PL_LechaptCalmonParams } from "../../src/pipe_flow/pl_lechaptcalmon_params"; import { SessionSettings } from "../../src/session_settings"; import { MessageCode } from "../../src/util/message"; -function getLechapt(): PL_LechaptCalmon { - const l = new PL_LechaptCalmon( +function getLechapt(): PressureLoss { + const plParams = new PressureLossParams( + 0.3, // débit + 0.5, // diamètre + 0.1, /// perte de charge + 20, // longueur du toyo + 1 // Kloc + ); + const lc = new PL_LechaptCalmon( new PL_LechaptCalmonParams( - 0.3, // débit - 0.5, // diamètre - 0.1, /// perte de charge - 20, // longueur du toyo - 1, // Ks 1.863, // paramètre L du matériau 2, // paramètre M du matériau 5.33 // paramètre N du matériau ) ); - l.calculatedParam = l.prms.J; - l.prms.J.singleValue = l.CalcSerie().vCalc; - return l; + const pl: PressureLoss = new PressureLoss(plParams, lc); + + pl.calculatedParam = pl.prms.J; + pl.prms.J.singleValue = pl.CalcSerie().vCalc; + return pl; } -let lechapt: PL_LechaptCalmon = getLechapt(); +function getLechaptWith(Q: number, D: number, Lg: number, Kloc: number, mat: LCMaterial): PressureLoss { + const plParams = new PressureLossParams( + Q, // débit + D, // diamètre + 0, /// perte de charge + Lg, // longueur du toyo + Kloc, // coef de perte de charge singulière + ); + const lc = new PL_LechaptCalmon( + new PL_LechaptCalmonParams( + 1.863, // paramètre L du matériau + 2, // paramètre M du matériau + 5.33 // paramètre N du matériau + ) + ); + lc.material = mat; + const pl: PressureLoss = new PressureLoss(plParams, lc); + pl.calculatedParam = pl.prms.J; + pl.prms.J.singleValue = pl.CalcSerie().vCalc; + return pl; +} + +let lechapt: PressureLoss = getLechapt(); describe("Class LechaptCalmon : ", () => { beforeAll(() => { @@ -35,16 +63,17 @@ describe("Class LechaptCalmon : ", () => { if ([ParamCalculability.EQUATION, ParamCalculability.DICHO].includes(p.calculability) && p.visible) { it(`Calc(${p.symbol}) should return ${p.currentValue}`, () => { lechapt.calculatedParam = lechapt.getParameter(p.symbol); - const ref: number = p.currentValue; + lechapt.CalcSerie(); + const ref: number = lechapt.result.vCalc; const V: number = lechapt.result.values.V; - const Jl: number = lechapt.result.values.Jl; - const Kl: number = lechapt.result.values.Kl; + const Jlin: number = lechapt.child.result.values.Jlin; + const Klin: number = lechapt.result.values.Klin; const fD: number = lechapt.result.values.fD; lechapt.calculatedParam.singleValue = lechapt.calculatedParam.singleValue / 2; expect(lechapt.CalcSerie().vCalc).toBeCloseTo(ref, 2); expect(lechapt.result.values.V).toBeCloseTo(V, 3); - expect(lechapt.result.values.Jl).toBeCloseTo(Jl, 3); - expect(lechapt.result.values.Kl).toBeCloseTo(Kl, 3); + expect(lechapt.child.result.values.Jlin).toBeCloseTo(Jlin, 3); + expect(lechapt.result.values.Klin).toBeCloseTo(Klin, 3); expect(lechapt.result.values.fD).toBeCloseTo(fD, 3); }); } @@ -53,7 +82,7 @@ describe("Class LechaptCalmon : ", () => { describe("warning on speed value -", () => { it("case 1: there should not be any warning", () => { - const res = lechapt.CalcSerie(); + const res = lechapt.result; expect(res.log.messages.length).toBe(0); }); @@ -65,3 +94,77 @@ describe("Class LechaptCalmon : ", () => { }); }); }); + +describe("article original", () => { + it("", () => { + const oldMaxIter = SessionSettings.maxIterations; + const oldPrec = SessionSettings.precision; + + try { + SessionSettings.maxIterations = 100; + SessionSettings.precision = 1e-7; + + const plParams = new PressureLossParams( + 0.0085, // débit + 0.175, // diamètre + 0, /// perte de charge + 1000, // longueur du toyo + 0, // Kloc + ); + + // L,M,N : cf. pl_lechaptcalmon.ts + const lechaptPrms = new PL_LechaptCalmonParams( + 1.863, // paramètre L du matériau + 2, // paramètre M du matériau + 5.33, // paramètre N du matériau + ); + + const lechapt = new PL_LechaptCalmon(lechaptPrms); + lechapt.material = LCMaterial.HydraulicallySmoothPipe005D02; + + const pl: PressureLoss = new PressureLoss(plParams, lechapt); + + const res = pl.CalcSerie(); + expect(res.vCalc).toBeCloseTo(0.784, 3); + } + finally { + SessionSettings.maxIterations = oldMaxIter; + SessionSettings.precision = oldPrec; + } + }); +}); + +describe("specific values -", () => { + it("test 1", () => { + const pl: PressureLoss = getLechaptWith(3, 1.2, 100, 0, LCMaterial.HydraulicallySmoothPipe025D1); + let r = pl.result; + let cr = pl.child.result; + expect(r.vCalc).toBeCloseTo(0.295085, 6); // J + expect(r.values.V).toBeCloseTo(2.652582, 6); + expect(cr.values.Jlin).toBeCloseTo(0.295085, 6); + expect(r.values.Klin).toBeCloseTo(0.822826, 6); + expect(r.values.fD).toBeCloseTo(0.009874, 6); + + const lc: PL_LechaptCalmon = pl.child as PL_LechaptCalmon; + lc.material = LCMaterial.UnlinedCastIronCoarseConcrete; + pl.CalcSerie(); + r = pl.result; + cr = pl.child.result; + expect(r.vCalc).toBeCloseTo(0.634482, 6); // J + expect(r.values.V).toBeCloseTo(2.652582, 6); + expect(cr.values.Jlin).toBeCloseTo(0.634482, 6); + expect(r.values.Klin).toBeCloseTo(1.769215, 6); + expect(r.values.fD).toBeCloseTo(0.021231, 6); + }); + + it("test 2", () => { + const pl: PressureLoss = getLechaptWith(0.05, 0.5, 100, 1, LCMaterial.RolledSteelSmoothConcrete); + const r = pl.result; + const cr = pl.child.result; + expect(r.vCalc).toBeCloseTo(0.015625, 6); // J + expect(r.values.V).toBeCloseTo(0.254648, 6); + expect(cr.values.Jlin).toBeCloseTo(0.012320, 6); + expect(r.values.Klin).toBeCloseTo(3.727563, 6); + expect(r.values.fD).toBeCloseTo(0.023638, 6); + }); +}); diff --git a/spec/session/serialisation.spec.ts b/spec/session/serialisation.spec.ts index e77d7c12838a5b7b036b4d9e1ffd6eca038b81e8..c857a40ddda74516239124dc77be013061c9f4af 100644 --- a/spec/session/serialisation.spec.ts +++ b/spec/session/serialisation.spec.ts @@ -522,7 +522,7 @@ describe("PreBarrage - ", () => { expect(c1.bassinAmont).toBeUndefined(); expect(c1.bassinAval).toBeUndefined(); expect(c1.structures.length).toBe(1); - expect(c1.structures[0].properties.getPropValue("loiDebit")).toBe(LoiDebit.WeirSubmergedLarinier); + expect(c1.structures[0].getPropValue("loiDebit")).toBe(LoiDebit.WeirSubmergedLarinier); const s1 = c1.structures[0].prms as RectangularStructureParams; expect(s1.ZDV.singleValue).toBe(101.11); expect(s1.L.singleValue).toBe(0.211); @@ -532,7 +532,7 @@ describe("PreBarrage - ", () => { expect(c2.bassinAmont).toBeUndefined(); expect(c2.bassinAval.uid).toBe("M3AxbT"); expect(c2.structures.length).toBe(1); - expect(c2.structures[0].properties.getPropValue("loiDebit")).toBe(LoiDebit.TriangularWeirBroad); + expect(c2.structures[0].getPropValue("loiDebit")).toBe(LoiDebit.TriangularWeirBroad); const s2 = c2.structures[0].prms as TriangularStructureParams; expect(s2.ZDV.singleValue).toBe(101.22); expect(s2.CdT.singleValue).toBe(1.3622); @@ -542,7 +542,7 @@ describe("PreBarrage - ", () => { expect(c3.bassinAmont).toBeUndefined(); expect(c3.bassinAval.uid).toBe("d2kxcD"); expect(c3.structures.length).toBe(1); - expect(c3.structures[0].properties.getPropValue("loiDebit")).toBe(LoiDebit.OrificeFree); + expect(c3.structures[0].getPropValue("loiDebit")).toBe(LoiDebit.OrificeFree); const s3 = c3.structures[0].prms as StructureOrificeFreeParams; expect(s3.S.singleValue).toBe(0.133); expect(s3.CdO.singleValue).toBe(0.733); @@ -552,7 +552,7 @@ describe("PreBarrage - ", () => { expect(c4.bassinAmont.uid).toBe("M3AxbT"); expect(c4.bassinAval.uid).toBe("d2kxcD"); expect(c4.structures.length).toBe(1); - expect(c4.structures[0].properties.getPropValue("loiDebit")).toBe(LoiDebit.RectangularOrificeSubmerged); + expect(c4.structures[0].getPropValue("loiDebit")).toBe(LoiDebit.RectangularOrificeSubmerged); const s4 = c4.structures[0].prms as RectangularStructureParams; expect(s4.ZDV.singleValue).toBe(101.44); expect(s4.L.singleValue).toBe(0.244); @@ -563,7 +563,7 @@ describe("PreBarrage - ", () => { expect(c5.bassinAmont.uid).toBe("d2kxcD"); expect(c5.bassinAval).toBeUndefined(); expect(c5.structures.length).toBe(1); - expect(c5.structures[0].properties.getPropValue("loiDebit")).toBe(LoiDebit.GateCunge80); + expect(c5.structures[0].getPropValue("loiDebit")).toBe(LoiDebit.GateCunge80); const s5 = c5.structures[0].prms as RectangularStructureParams; expect(s5.ZDV.singleValue).toBe(101.55); expect(s5.L.singleValue).toBe(0.255); diff --git a/spec/structure/functions.ts b/spec/structure/functions.ts index 0d771331ad79f8d6cab3541309e084f09b399a42..e5c5d2a517bd05ee8ba273c044842611c25d30c9 100644 --- a/spec/structure/functions.ts +++ b/spec/structure/functions.ts @@ -158,8 +158,7 @@ export function testParallelStructures(o: { ps: ParallelStructure, ld: number[] beforeEach(() => { originalCalculatedValue = o.ps.calculatedParam.currentValue; if ( // #136 Multiple solutions for GateCem88v ZDV - !(o.ps.calculatedParam.parentNub.properties - .getPropValue("loiDebit") === LoiDebit.GateCem88v + !(o.ps.calculatedParam.parentNub.getPropValue("loiDebit") === LoiDebit.GateCem88v && o.ps.calculatedParam.symbol === "ZDV") ) { // altering value to force looking for the solution diff --git a/src/devalaison/grille.ts b/src/devalaison/grille.ts index adf140b643dc5b117425afac7fbe7b2acf0b6598..e03b505d276c82cf6feb726db5472f39385ba616 100644 --- a/src/devalaison/grille.ts +++ b/src/devalaison/grille.ts @@ -67,19 +67,19 @@ export class Grille extends Nub implements Observer { } public get gridType(): GrilleType { - return this.properties.getPropValue("gridType"); + return this.getPropValue("gridType"); } public get gridProfile(): GrilleProfile { - return this.properties.getPropValue("gridProfile"); + return this.getPropValue("gridProfile"); } public set type(type: GrilleType) { - this.properties.setPropValue("gridType", type); + this.setPropValue("gridType", type); } public set profile(profile: GrilleProfile) { - this.properties.setPropValue("gridProfile", profile); + this.setPropValue("gridProfile", profile); } /** Coefficient de forme des barreaux a */ diff --git a/src/index.ts b/src/index.ts index 5b315a80c2b33fc880947344d0928c377cc30bbc..d6c10fa84e35bae89351d186fe3e8fd2004111a6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -45,6 +45,7 @@ export * from "./structure/structure"; export * from "./structure/structure_params"; export * from "./structure/factory_structure"; export * from "./structure/structure_props"; +export * from "./structure/rectangular_structure"; export * from "./linked-value"; export * from "./jalhyd_object"; export * from "./date_revision"; @@ -61,6 +62,7 @@ export * from "./pab/pab_puissance"; export * from "./pab/pab_puissance_params"; export * from "./pab/cloison_aval"; export * from "./pipe_flow/pl_lechaptcalmon"; +export * from "./pipe_flow/pl_lechaptcalmon_params"; export * from "./pipe_flow/pressureloss"; export * from "./pipe_flow/pressureloss_law"; export * from "./lc-material"; diff --git a/src/internal_modules.ts b/src/internal_modules.ts index 58b3a9bde01cce55a423aadcf09fbc9e1ae664db..427ef5383fe8ca738753ba3bda70f7d15b3dbaa9 100644 --- a/src/internal_modules.ts +++ b/src/internal_modules.ts @@ -10,7 +10,6 @@ export * from "./compute-node"; export * from "./dichotomie"; export * from "./nub"; export * from "./child_nub"; -export * from "./props"; export * from "./session_settings"; export * from "./config"; export * from "./param/param-domain"; @@ -166,5 +165,5 @@ export * from "./verification/espece_params"; export * from "./verification/fish_species"; export * from "./verification/verificateur"; export * from "./verification/verificateur_params"; - +export * from "./props"; export * from "./session"; diff --git a/src/macrorugo/macrorugo.ts b/src/macrorugo/macrorugo.ts index 196fbe4187b60ff8fbc6c7c51e8ba63f7f8ebcf7..db2cd017f3a232dcb056c4d2e430443870552730 100644 --- a/src/macrorugo/macrorugo.ts +++ b/src/macrorugo/macrorugo.ts @@ -101,7 +101,7 @@ export class MacroRugo extends FishPass { this.parent === undefined || ( this.parent instanceof MacrorugoCompound - && this.parent.properties.getPropValue("inclinedApron") === MRCInclination.NOT_INCLINED + && this.parent.getPropValue("inclinedApron") === MRCInclination.NOT_INCLINED ) ) { const ax: number = this.prms.PBD.v / Math.sqrt(this.prms.C.v); diff --git a/src/macrorugo/macrorugo_compound.ts b/src/macrorugo/macrorugo_compound.ts index 7be71618f58b71da83beb687c51ee6a1959a4603..7744680b562b074a761868af23e028458c7b00b2 100644 --- a/src/macrorugo/macrorugo_compound.ts +++ b/src/macrorugo/macrorugo_compound.ts @@ -30,15 +30,15 @@ export class MacrorugoCompound extends MacroRugo implements Observer { } public get inclinedApron(): MRCInclination { - return this.properties.getPropValue("inclinedApron"); + return this.getPropValue("inclinedApron"); } public set inclinedApron(i: MRCInclination) { - this.properties.setPropValue("inclinedApron", i); + this.setPropValue("inclinedApron", i); } public CalcSerie(rInit?: number): Result { - if (this.properties.getPropValue("inclinedApron") === MRCInclination.INCLINED) { + if (this.getPropValue("inclinedApron") === MRCInclination.INCLINED) { // important to regenerate it here, at every iteration of CalcSerie() this.generateInclinedFishway(); } @@ -94,7 +94,7 @@ export class MacrorugoCompound extends MacroRugo implements Observer { this.currentResultElement = this.Equation(sVarCalc); // lateral inclination for inclined aprons - if (this.properties.getPropValue("inclinedApron") === MRCInclination.INCLINED) { + if (this.getPropValue("inclinedApron") === MRCInclination.INCLINED) { // extraResult : inclination this.result.resultElement.values.LIncl = (this.prms.ZRL.v - this.prms.ZRR.v) / this.prms.BR.v; // La largeur de la rampe inclinée est-elle adéquate par rapport à la largeur de motif ax ? diff --git a/src/math/spp.ts b/src/math/spp.ts index 598fa5b3bea70a4d6e0847ec8221e459c8ee5244..de128ce77aec989b39b711574e9bb2bf8454be36 100644 --- a/src/math/spp.ts +++ b/src/math/spp.ts @@ -31,11 +31,11 @@ export class SPP extends Nub { } public get operation(): SPPOperation { - return this.properties.getPropValue("sppOperation"); + return this.getPropValue("sppOperation"); } public set operation(o: SPPOperation) { - this.properties.setPropValue("sppOperation", o); + this.setPropValue("sppOperation", o); } /** diff --git a/src/math/trigo.ts b/src/math/trigo.ts index 4050e21c213332a009d2d2b8c8034c10400b939d..286169998997726711b76af3ba71777267f52ea6 100644 --- a/src/math/trigo.ts +++ b/src/math/trigo.ts @@ -30,7 +30,7 @@ export class Trigo extends Nub implements Observer { this.setCalculatorType(CalculatorType.Trigo); this._defaultCalculatedParam = prms.Y; this.resetDefaultCalculatedParam(); - this.properties.addObserver(this); + this._props.addObserver(this); this.operation = TrigoOperation.COS; this.unit = TrigoUnit.DEG; } @@ -41,19 +41,19 @@ export class Trigo extends Nub implements Observer { } public get operation(): TrigoOperation { - return this.properties.getPropValue("trigoOperation"); + return this.getPropValue("trigoOperation"); } public set operation(o: TrigoOperation) { - this.properties.setPropValue("trigoOperation", o); + this.setPropValue("trigoOperation", o); } public get unit(): TrigoUnit { - return this.properties.getPropValue("trigoUnit"); + return this.getPropValue("trigoUnit"); } public set unit(u: TrigoUnit) { - this.properties.setPropValue("trigoUnit", u); + this.setPropValue("trigoUnit", u); } public Equation(sVarCalc: string): Result { diff --git a/src/nub.ts b/src/nub.ts index fe913bdaf00358a14d90de0b123639342a4d31ba..e40d9c23efb7f1d431568cf3ff608f3948c9ded7 100644 --- a/src/nub.ts +++ b/src/nub.ts @@ -1,4 +1,4 @@ -import { CalculatorType, ComputeNode } from "./internal_modules"; +import { CalculatorType, ComputeNode, IProperties } from "./internal_modules"; import { Dichotomie } from "./internal_modules"; import { acSection, MacrorugoCompound, Pab, ParamDefinition, ParamsEquation, @@ -12,7 +12,7 @@ import { ParamsEquationArrayIterator } from "./internal_modules"; import { Props } from "./internal_modules"; import { SessionSettings } from "./internal_modules"; import { Message, MessageCode } from "./internal_modules"; -import { IObservable, Observable, Observer } from "./internal_modules"; +import { Observable, Observer } from "./internal_modules"; import { Result } from "./internal_modules"; import { ResultElement } from "./internal_modules"; import { VariatedDetails } from "./internal_modules"; @@ -21,7 +21,7 @@ import { VariatedDetails } from "./internal_modules"; * Classe abstraite de Noeud de calcul dans une session : * classe de base pour tous les calculs */ -export abstract class Nub extends ComputeNode implements IObservable { +export abstract class Nub extends ComputeNode implements IProperties { /** * Find longest series, BUT: if any varying parameter is a calculation result, @@ -103,17 +103,6 @@ export abstract class Nub extends ComputeNode implements IObservable { return this._result; } - private _calcType: CalculatorType; - - /** - * set Nub calculator type. - * give children the opportunity to react to assignment - * @see Structure - */ - protected setCalculatorType(ct: CalculatorType) { - this._calcType = ct; - } - /** * Local setter to set result element of Equation() / Solve() / … as current * ResultElement, instead of overwriting the whole Result object @@ -126,13 +115,6 @@ export abstract class Nub extends ComputeNode implements IObservable { this._result.resultElement = r.resultElement; } - /** Returns Props object (observable set of key-values) associated to this Nub */ - public get properties(): Props { - // completes props with calcType if not already set - this._props.setPropValue("calcType", this.calcType); - return this._props; - } - public set properties(props: Props) { this.setProperties(props); } @@ -204,7 +186,16 @@ export abstract class Nub extends ComputeNode implements IObservable { } public get calcType(): CalculatorType { - return this._calcType; + return this.getPropValue("calcType"); + } + + /** + * set Nub calculator type. + * give children the opportunity to react to assignment + * @see Structure + */ + protected setCalculatorType(ct: CalculatorType) { + this.setPropValue("calcType", ct); } public get calculatedParam(): ParamDefinition { @@ -275,7 +266,7 @@ export abstract class Nub extends ComputeNode implements IObservable { } // move code out of setter to ease inheritance - public setProperties(props: Props, resetProps: boolean = false) { + public setProperties(props: IProperties, resetProps: boolean = false) { // copy observers const observers = this._props.getObservers(); // empty props @@ -288,18 +279,18 @@ export abstract class Nub extends ComputeNode implements IObservable { } // set new props values let error: Error; - for (const p of Object.keys(props.props)) { + for (const p of props.keys) { // try properties one by one so that if an error is thrown, // remaining properties are still copied let oldValue: any; try { // keep old value to restore it in case of an error, or else it breaks fixTargets() - oldValue = this._props.getPropValue(p); // should always be undefined but who knows - this._props.setPropValue(p, props.getPropValue(p)); + oldValue = this.getPropValue(p); // should always be undefined but who knows + this.setPropValue(p, props.getPropValue(p)); } catch (e) { error = e; // no one will notice ^^ - this._props.setPropValue(p, oldValue); + this.setPropValue(p, oldValue); } } // throw caught error if any @@ -745,10 +736,6 @@ export abstract class Nub extends ComputeNode implements IObservable { return this._children; } - public getParent(): Nub { - return this.parent; - } - /** * @returns iterator on all child nubs (may include extra nubs, see Pab nub) */ @@ -794,7 +781,7 @@ export abstract class Nub extends ComputeNode implements IObservable { !this.isParentOrChildOf(src.nubUid) && ( // check grand-parent for PreBarrage special case @TODO find a generic way // to perform both tests (synthesise .nubUid and .originNub.uid) - !(this._calcType === CalculatorType.PreBarrage) + !(this.calcType === CalculatorType.PreBarrage) || !this.isParentOrChildOf(src.originNub.uid) ) ) { @@ -893,7 +880,7 @@ export abstract class Nub extends ComputeNode implements IObservable { && src.symbol === "QA" ) ) - && this._calcType !== CalculatorType.PreBarrage + && this.calcType !== CalculatorType.PreBarrage ) { for (const cn of this.getChildren()) { res = res.concat(cn.getLinkableValues(src)); @@ -913,8 +900,7 @@ export abstract class Nub extends ComputeNode implements IObservable { if (this.uid === uid) { return true; } - const parent = this.getParent(); - if (parent && parent.uid === uid) { + if (this._parent && this._parent.uid === uid) { return true; } for (const c of this.getChildren()) { @@ -934,9 +920,8 @@ export abstract class Nub extends ComputeNode implements IObservable { if (this.uid === uid) { return true; } - const parent = this.getParent(); - if (parent) { - for (const c of parent.getChildren()) { + if (this._parent) { + for (const c of this._parent.getChildren()) { if (c.uid === uid) { return true; } @@ -1047,9 +1032,8 @@ export abstract class Nub extends ComputeNode implements IObservable { */ public dependsOnNubResult(nub: Nub, followLinksChain: boolean = true): boolean { let thisFamily: Nub[] = [this]; - const tp = this.getParent(); - if (tp) { - thisFamily = thisFamily.concat(tp); + if (this._parent) { + thisFamily = thisFamily.concat(this._parent); } thisFamily = thisFamily.concat(this.getChildren()); @@ -1085,9 +1069,8 @@ export abstract class Nub extends ComputeNode implements IObservable { */ public dependsOnParameter(src: ParamDefinition) { let thisFamily: Nub[] = [this]; - const tp = this.getParent(); - if (tp) { - thisFamily = thisFamily.concat(tp); + if (this._parent) { + thisFamily = thisFamily.concat(this._parent); } thisFamily = thisFamily.concat(this.getChildren()); @@ -1151,9 +1134,8 @@ export abstract class Nub extends ComputeNode implements IObservable { } } // does any of our parent's parameters depend on the target Nub ? - const parent = this.getParent(); - if (parent) { - if (parent.resultDependsOnNub(uid, visited, symbol, includeValuesLinks, includeOtherDependencies)) { + if (this._parent) { + if (this._parent.resultDependsOnNub(uid, visited, symbol, includeValuesLinks, includeOtherDependencies)) { return true; } } @@ -1266,7 +1248,7 @@ export abstract class Nub extends ComputeNode implements IObservable { public objectRepresentation(extra?: object, nubUidsInSession?: string[]): object { let ret: any = { uid: this.uid, - props: Session.invertEnumKeysAndValuesInProperties(this.properties.props), + props: this.invertedPropertiesEnumAndValues(), }; if (extra) { @@ -1330,7 +1312,7 @@ export abstract class Nub extends ComputeNode implements IObservable { if (obj.children && Array.isArray(obj.children)) { for (const s of obj.children) { // decode properties - const props = Session.invertEnumKeysAndValuesInProperties(s.props, true); + const props = Props.invertEnumKeysAndValuesInProperties(s.props, true); // create the Nub const subNub = Session.getInstance().createNub(new Props(props), this); // try to keep the original ID @@ -1845,4 +1827,40 @@ export abstract class Nub extends ComputeNode implements IObservable { // } // return []; // } + + public invertedPropertiesEnumAndValues(forceNumbers: boolean = false) { + return this._props.invertEnumKeysAndValues(forceNumbers); + } + + public addPropertiesObserver(o: Observer) { + this._props.addObserver(o); + } + + protected childHasProperty(key: string, nth?: number): boolean { + if (this._children.length > 0) { + const n = nth ?? 0; + if (n < this._children.length) { + return this._children[n].hasProperty(key); + } + } + return false; + } + + // interface IProperties + + public hasProperty(key: string): boolean { + return true; + } + + public get keys(): string[] { + return this._props.keys; + } + + public getPropValue(key: string): any { + return this._props.getPropValue(key); + } + + public setPropValue(key: string, val: any, sender?: any): boolean { + return this._props.setPropValue(key, val, sender); + } } diff --git a/src/open-channel/bief.ts b/src/open-channel/bief.ts index c449b55c2a5829459f4f052254091298ad3ab686..9448017779fb6416ef373a581fc361ba0fb36c4d 100644 --- a/src/open-channel/bief.ts +++ b/src/open-channel/bief.ts @@ -40,7 +40,7 @@ export class Bief extends SectionNub implements Observer { } public set regime(regime: BiefRegime) { - this.properties.setPropValue("regime", regime); + this.setPropValue("regime", regime); } public Calc(sVarCalc?: string, rInit?: number): Result { @@ -74,13 +74,13 @@ export class Bief extends SectionNub implements Observer { if ( this.calculatedParam === this.prms.Z1 - && this.properties.getPropValue("regime") === BiefRegime.Torrentiel + && this.getPropValue("regime") === BiefRegime.Torrentiel ) { throw new Error("Bief.Equation() : cannot calculate Z1 in Torrential regime"); } if ( this.calculatedParam === this.prms.Z2 - && this.properties.getPropValue("regime") === BiefRegime.Fluvial + && this.getPropValue("regime") === BiefRegime.Fluvial ) { throw new Error("Bief.Equation() : cannot calculate Z2 in Fluvial regime"); } diff --git a/src/open-channel/remous.ts b/src/open-channel/remous.ts index 0c043b268252ee5ae5f23b9971a18b77b36c3314..7c20f500f0309008480d50467846ba04980f0b17 100644 --- a/src/open-channel/remous.ts +++ b/src/open-channel/remous.ts @@ -46,11 +46,11 @@ export class CourbeRemous extends SectionNub { } public get methodeResolution(): MethodeResolution { - return this.properties.getPropValue("methodeResolution"); + return this.getPropValue("methodeResolution"); } public set methodeResolution(m: MethodeResolution) { - this.properties.setPropValue("methodeResolution", m); + this.setPropValue("methodeResolution", m); } public setSection(s: acSection) { @@ -528,7 +528,7 @@ export class CourbeRemous extends SectionNub { * @param sDonnee éventuel symbole / paire symbole-uid du paramètre à calculer */ public CalcSerie(rInit?: number): Result { - const varCalc = this.properties.getPropValue("varCalc"); + const varCalc = this.getPropValue("varCalc"); const res = this.calculRemous(varCalc); return res; } @@ -834,7 +834,7 @@ export class CourbeRemous extends SectionNub { // let funcCalcY = 'Calc_Y_' + Resolution; // return this[funcCalcY](Y); let res: Result; - const methodeResolution: MethodeResolution = this.properties.getPropValue("methodeResolution"); + const methodeResolution: MethodeResolution = this.getPropValue("methodeResolution"); switch (methodeResolution) { case MethodeResolution.Trapezes: res = this.Calc_Y_Trapez(Y); diff --git a/src/open-channel/section/section_circulaire.ts b/src/open-channel/section/section_circulaire.ts index c96857fc761b332d7cb262699f8e1ac37674c97b..a04d2353ecc52bfa9a070ffc4d1a899e29ec4d86 100644 --- a/src/open-channel/section/section_circulaire.ts +++ b/src/open-channel/section/section_circulaire.ts @@ -18,7 +18,7 @@ export class cSnCirc extends acSection { constructor(prms: ParamsSectionCirc, dbg: boolean = false) { super(prms, dbg); - this._nodeType = SectionType.SectionCercle; + this.nodeType = SectionType.SectionCercle; // commenté car si D est la variable à déterminer, il peut valoir n'importe // quoi... if (prms.YB.v > D) { prms.YB.v = D; } // On place la berge au sommet du cercle diff --git a/src/open-channel/section/section_nub.ts b/src/open-channel/section/section_nub.ts index bc4dffc5be5ffdfebdd5e4ea9364aa04854bb8e8..f33df5aacd1a94d32a4bfd7baedbca0a04d62d49 100644 --- a/src/open-channel/section/section_nub.ts +++ b/src/open-channel/section/section_nub.ts @@ -27,18 +27,6 @@ export abstract class SectionNub extends Nub { this._sectionVars = {}; } - /** Returns Props object (observable set of key-values) associated to this Nub */ - public get properties(): Props { - // completes props with calcType if not already set - this._props.setPropValue("calcType", this.calcType); - return this._props; - } - - // setter is not inherited from Nub if getter is redefined :/ - public set properties(props: Props) { - super.setProperties(props); - } - public getParameter(name: string): ParamDefinition { if (typeof name !== "string") { // dirty hack because calculated param descriptor for section params is an object { uid: , symbol: } @@ -104,10 +92,27 @@ export abstract class SectionNub extends Nub { this._children[0] = undefined; } this.replaceChild(0, s); + this._props.removeProp("nodeType"); // because this property belongs to child section and is set as long as section is not defined /** * Y linkability managed in child classes through 'visible' flag * @see Bief,CourbeRemous */ } } + + // interface IProperties + + public getPropValue(key: string): any { + if (this.childHasProperty(key)) { + return this.section.getPropValue(key); + } + return this._props.getPropValue(key); + } + + public setPropValue(key: string, val: any, sender?: any): boolean { + if (this.childHasProperty(key)) { + return this.section.setPropValue(key, val, sender); + } + return this._props.setPropValue(key, val, sender); + } } diff --git a/src/open-channel/section/section_puissance.ts b/src/open-channel/section/section_puissance.ts index c54eda30758ed032abe09832b00448e09ae3f168..3e73cc2d0af0722d722f9e4b5a877e3b25f3682f 100644 --- a/src/open-channel/section/section_puissance.ts +++ b/src/open-channel/section/section_puissance.ts @@ -13,7 +13,7 @@ export class cSnPuiss extends acSection { constructor(prms: ParamsSectionPuiss, dbg: boolean = false) { super(prms, dbg); - this._nodeType = SectionType.SectionPuissance; + this.nodeType = SectionType.SectionPuissance; } protected setParametersCalculability() { diff --git a/src/open-channel/section/section_rectang.ts b/src/open-channel/section/section_rectang.ts index f801ad556fad44e97f2995f578cb0315b13d8731..83d89747d4019e78ea60cd1a68a4f62d2b9cb6bc 100644 --- a/src/open-channel/section/section_rectang.ts +++ b/src/open-channel/section/section_rectang.ts @@ -10,7 +10,7 @@ import { acSection } from "../../internal_modules"; export class cSnRectang extends acSection { constructor(prms: ParamsSectionRectang, dbg: boolean = false) { super(prms, dbg); - this._nodeType = SectionType.SectionRectangle; + this.nodeType = SectionType.SectionRectangle; } get prms(): ParamsSectionRectang { diff --git a/src/open-channel/section/section_trapez.ts b/src/open-channel/section/section_trapez.ts index 578842f06e6862de5f099683acc95ecdc31443d6..8dfd4fb4d8b5359a92e818c00bc73c70380f468e 100644 --- a/src/open-channel/section/section_trapez.ts +++ b/src/open-channel/section/section_trapez.ts @@ -15,7 +15,7 @@ export class cSnTrapez extends acSection { } constructor(prms: ParamsSectionTrapez, dbg: boolean = false) { super(prms, dbg); - this._nodeType = SectionType.SectionTrapeze; + this.nodeType = SectionType.SectionTrapeze; } protected setParametersCalculability() { diff --git a/src/open-channel/section/section_type.ts b/src/open-channel/section/section_type.ts index 8c7b1983d2d4a45df395f35e1d514f8a4c719783..ae0e8c6e523446807c58a50103a55845809e03ec 100644 --- a/src/open-channel/section/section_type.ts +++ b/src/open-channel/section/section_type.ts @@ -52,8 +52,6 @@ export abstract class acSection extends Nub { protected bSnFermee: boolean = false; protected arCalcGeo: { [key: string]: number } = {}; /// Données ne dépendant pas de la cote de l'eau - protected _nodeType: SectionType; - private _hautCritique: Result; // Tirant d'eau critique /** @@ -99,22 +97,11 @@ export abstract class acSection extends Nub { } public get nodeType() { - return this._nodeType; - } - - /** Returns Props object (observable set of key-values) associated to this Nub */ - public get properties(): Props { - // completes props with calcType and nodeType if not already set - this._props.setPropValue("calcType", this.calcType); - if (this._props.getPropValue("nodeType") === undefined) { - this._props.setPropValue("nodeType", this.nodeType); - } - return this._props; + return this._props.getPropValue("nodeType"); } - // setter is not inherited from Nub if getter is redefined :/ - public set properties(props: Props) { - super.setProperties(props); + protected set nodeType(nt: SectionType) { + this._props.setPropValue("nodeType", nt); } /** @@ -828,4 +815,10 @@ export abstract class acSection extends Nub { const v = 1000 * (this.prms.Q.v * rV.vCalc + ParamsSection.G * rSYG.vCalc); return new Result(v); } + + // interface IProperties + + public hasProperty(key: string): boolean { + return key === "nodeType"; + } } diff --git a/src/pab/cloison_aval.ts b/src/pab/cloison_aval.ts index 16d4cced82cc63e25064dd839d428f1dcee7fcdb..39c48c4a489c53a0cbe52efaee8a5eedabe10b02 100644 --- a/src/pab/cloison_aval.ts +++ b/src/pab/cloison_aval.ts @@ -22,7 +22,7 @@ export class CloisonAval extends ParallelStructure { public get indexVanneLevante(): number { for (let i = 0; i < this.structures.length; i++) { if (loiAdmissiblesCloisonAval.VanneLevante.includes( - this.structures[i].properties.getPropValue("loiDebit")) + this.structures[i].getPropValue("loiDebit")) ) { return i; } @@ -119,7 +119,7 @@ export class CloisonAval extends ParallelStructure { public checkVanneLevante() { let n: number = 0; for (const st of this.structures) { - if (loiAdmissiblesCloisonAval.VanneLevante.includes(st.properties.getPropValue("loiDebit"))) { + if (loiAdmissiblesCloisonAval.VanneLevante.includes(st.getPropValue("loiDebit"))) { n += 1; } } diff --git a/src/pab/cloisons.ts b/src/pab/cloisons.ts index f113d453571277d5e6aa5596d37890a56303845b..88a036fd7e75064ad62a683cfab6af5c448c7c5d 100644 --- a/src/pab/cloisons.ts +++ b/src/pab/cloisons.ts @@ -88,7 +88,7 @@ export class Cloisons extends ParallelStructure { s.result.resultElement.addExtraResult("ZDV", this.prms.Z1.v - s.prms.h1.v); } // calcul de la pelle - if (s.properties.getPropValue("loiDebit") !== LoiDebit.OrificeSubmerged) { + if (s.getPropValue("loiDebit") !== LoiDebit.OrificeSubmerged) { const pelle = s.prms.ZDV.v - this.prms.ZRAM.v; s.result.resultElement.values.P = pelle; if (pelle < -1E-7) { // si c'est enfoncé d'un dixième de micron ça va diff --git a/src/pab/pab.ts b/src/pab/pab.ts index da52306f500de759a6852683bd0d44b370d3905c..f197cd5425da7a0c41eb3b898d00760de0a54db7 100644 --- a/src/pab/pab.ts +++ b/src/pab/pab.ts @@ -292,7 +292,7 @@ export class Pab extends FishPass { // load downwall if any if (obj.downWall) { // decode properties - const props = Session.invertEnumKeysAndValuesInProperties(obj.downWall.props, true); + const props = Props.invertEnumKeysAndValuesInProperties(obj.downWall.props, true); // create the Nub const dw = Session.getInstance().createNub(new Props(props), this) as CloisonAval; // try to keep the original ID diff --git a/src/par/par.ts b/src/par/par.ts index 509575092e1b23454bc4a88e3547b81d298c203c..9821ec1414e947ca80d76932421eb28322a98277 100644 --- a/src/par/par.ts +++ b/src/par/par.ts @@ -61,11 +61,11 @@ export class Par extends FishPass implements Observer { } public get parType(): ParType { - return this.properties.getPropValue("parType"); + return this.getPropValue("parType"); } public set parType(e: ParType) { - this.properties.setPropValue("parType", e); + this.setPropValue("parType", e); } public Calc(sVarCalc: string, rInit?: number): Result { diff --git a/src/par/par_simulation.ts b/src/par/par_simulation.ts index 39fb57b6fff5bd16946113e8bce79c58ffdd3d16..773107687ca74f729bef2541c08cdd4deb5ec2bd 100644 --- a/src/par/par_simulation.ts +++ b/src/par/par_simulation.ts @@ -28,11 +28,11 @@ export class ParSimulation extends Par implements Observer { } public get parType(): ParType { - return this.properties.getPropValue("parType"); + return this.getPropValue("parType"); } public set parType(e: ParType) { - this.properties.setPropValue("parType", e); + this.setPropValue("parType", e); } public Calc(sVarCalc: string, rInit?: number): Result { diff --git a/src/param/param-definition.ts b/src/param/param-definition.ts index 18907050c89a3433d5d80df9c62528529c604462..e34e7a31ecb7a17ef62496c07c1f29db297fb90e 100644 --- a/src/param/param-definition.ts +++ b/src/param/param-definition.ts @@ -1061,7 +1061,7 @@ export class ParamDefinition implements INamedIterableValues, IObservable { // direct, parent or children reference ? if ( (ref.nub.uid === uid) - || (ref.nub.getParent() && ref.nub.getParent().uid === uid) + || (ref.nub.parent && ref.nub.parent.uid === uid) || (ref.nub.getChildren().map((c) => c.uid).includes(uid)) ) { linked = ( diff --git a/src/pipe_flow/pl_lechaptcalmon.ts b/src/pipe_flow/pl_lechaptcalmon.ts index cc7d9a13ac81c1d8cf28251050f740f818dd574d..bd649cfa01d8baaf7b9d108c343ee8aa11c3d93a 100644 --- a/src/pipe_flow/pl_lechaptcalmon.ts +++ b/src/pipe_flow/pl_lechaptcalmon.ts @@ -1,4 +1,4 @@ -import { CalculatorType } from "../internal_modules"; +import { CalculatorType, PressureLossParams } from "../internal_modules"; import { LCMaterial } from "../internal_modules"; import { ParamCalculability } from "../internal_modules"; import { Message, MessageCode } from "../internal_modules"; @@ -72,10 +72,9 @@ export class PL_LechaptCalmon extends PressureLossLaw implements Observer { constructor(prms: PL_LechaptCalmonParams, dbg: boolean = false) { super(prms, dbg); this.setCalculatorType(CalculatorType.LechaptCalmon); - this._pressureLossType = PressureLossType.LechaptCalmon; + this.pressureLossType = PressureLossType.LechaptCalmon; this._props.addObserver(this); this.material = LCMaterial.PVCPolyethylene; - this.calculatedParam = prms.J; this._intlType = "LechaptCalmon"; } @@ -84,18 +83,35 @@ export class PL_LechaptCalmon extends PressureLossLaw implements Observer { } public get material(): LCMaterial { - return this.properties.getPropValue("material"); + return this.getPropValue("material"); } public set material(m: LCMaterial) { - this.properties.setPropValue("material", m); + this.setPropValue("material", m); } - protected calc_Jlin(r: Result) { + public Equation(sVarCalc: string): Result { + if (sVarCalc !== undefined && sVarCalc !== "Jlin") { + throw new Error("PL_LechaptCalmon.Equation() : invalid variable name " + sVarCalc); + } + const r: Result = this._result; + + // récupération des paramètres Q,D et Lg dans le parent + const parentPrms = this.parent.prms as PressureLossParams; + const Q = parentPrms.Q.v; + const D = parentPrms.D.v; + const Lg = parentPrms.Lg.v; + + // Calcul de la perte de charge linéaire spécifique à chaque module de perte de charge. + r.values.Jlin = this.prms.L.v * Math.pow(Q, this.prms.M.v) / Math.pow(D, this.prms.N.v) * (Lg / 1000); + + return r; + } + + public finalChecks(r: Result) { if (r.values.V < 0.4 || r.values.V > 2) { r.resultElement.log.add(new Message(MessageCode.WARNING_LECHAPT_CALMON_SPEED_OUTSIDE_04_2)); } - r.values.Jl = this.prms.L.v * Math.pow(this.prms.Q.v, this.prms.M.v) / Math.pow(this.prms.D.v, this.prms.N.v) * (this.prms.Lg.v / 1000); } /** @@ -105,14 +121,6 @@ export class PL_LechaptCalmon extends PressureLossLaw implements Observer { return this._prms as PL_LechaptCalmonParams; } - public Calc(sVarCalc: string, rInit?: number): Result { - const r = super.Calc(sVarCalc, rInit); - const V2 = Math.pow(r.values.V, 2); - r.values.Kl = 19.62 * r.values.Jl / V2; - r.values.fD = this.prms.J.V / this.prms.Lg.V / V2 * 19.62 * this.prms.D.V; - return r; - } - // interface Observer public update(sender: any, data: any) { @@ -125,7 +133,6 @@ export class PL_LechaptCalmon extends PressureLossLaw implements Observer { * paramétrage de la calculabilité des paramètres */ protected setParametersCalculability() { - super.setParametersCalculability(); this.prms.L.calculability = ParamCalculability.FIXED; this.prms.M.calculability = ParamCalculability.FIXED; this.prms.N.calculability = ParamCalculability.FIXED; @@ -133,10 +140,10 @@ export class PL_LechaptCalmon extends PressureLossLaw implements Observer { protected exposeResults() { this._resultsFamilies = { - Kl: undefined, + Klin: undefined, fD: undefined, V: undefined, - Jl: undefined + Jlin: undefined }; } @@ -145,10 +152,20 @@ export class PL_LechaptCalmon extends PressureLossLaw implements Observer { * according to this._materials presets */ private applyMaterialPreset() { - const m = this.properties.getPropValue("material"); + const m = this.getPropValue("material"); const values = PL_LechaptCalmon._materials[m]; this.prms.L.singleValue = values.L; this.prms.M.singleValue = values.M; this.prms.N.singleValue = values.N; } + + // interface IProperties + + public hasProperty(key: string): boolean { + if (super.hasProperty(key)) { + return true; + } + + return key === "material"; + } } diff --git a/src/pipe_flow/pl_lechaptcalmon_params.ts b/src/pipe_flow/pl_lechaptcalmon_params.ts index b23fba86ddb98287786102fdb83366f607b0394f..040984826f438337effe11d403dcb9286bbdda0f 100644 --- a/src/pipe_flow/pl_lechaptcalmon_params.ts +++ b/src/pipe_flow/pl_lechaptcalmon_params.ts @@ -16,8 +16,8 @@ export class PL_LechaptCalmonParams extends PressureLossLawParams { /** Paramètre de rugosité N */ private _N: ParamDefinition; - constructor(rQ: number, rD: number, rJ: number, rLg: number, rKloc: number, rL: number, rM: number, rN: number, nullParams: boolean = false) { - super(rQ, rD, rJ, rLg, rKloc, nullParams); + constructor(rL: number, rM: number, rN: number, nullParams: boolean = false) { + super(); this._L = new ParamDefinition(this, "L", new ParamDomain(ParamDomainValue.INTERVAL, 0.8, 2), undefined, rL, undefined, false, nullParams); this._M = new ParamDefinition(this, "M", new ParamDomain(ParamDomainValue.INTERVAL, 1.5, 2.5), undefined, rM, diff --git a/src/pipe_flow/pressureloss.ts b/src/pipe_flow/pressureloss.ts index 53580105c5bb91de481ce4d63f5a9d7865689219..0f5b095c5d25400d15830a38704f9559e452aa99 100644 --- a/src/pipe_flow/pressureloss.ts +++ b/src/pipe_flow/pressureloss.ts @@ -1,63 +1,133 @@ -import { Nub } from "../internal_modules"; +import { Nub, ParamCalculability } from "../internal_modules"; import { Observer } from "../internal_modules"; import { Result } from "../internal_modules"; import { CalculatorType } from "../internal_modules"; import { PressureLossParams } from "../internal_modules"; import { PressureLossLaw } from "../internal_modules"; -import { PressureLossLawParams } from "../internal_modules"; export class PressureLoss extends Nub { - constructor(law: PressureLossLaw, dbg: boolean = false) { - super(new PressureLossParams(), dbg); + /** + * { symbol => string } map that defines units for extra results + */ + private static _resultsUnits = { + Q: "m³/s", + D: "m", + J: "m/m", + Lg: "m" + }; + + constructor(prms: PressureLossParams, law: PressureLossLaw, dbg: boolean = false) { + super(prms, dbg); this.setCalculatorType(CalculatorType.PressureLoss); - this.addChild(law); + this.calculatedParam = prms.J; + this.setLaw(law); } /** * paramètres castés au bon type */ - get prms(): PressureLossLawParams { - return this.child.prms as PressureLossLawParams; + get prms(): PressureLossParams { + return this._prms as PressureLossParams; } - private get child(): PressureLossLaw { + public get child(): PressureLossLaw { return this._children[0] as PressureLossLaw; } + /** + * Set/replaces the current section + */ + public setLaw(pll: PressureLossLaw) { + if (pll) { + // prevent index out of bounds at first time + if (this._children.length === 0) { + this._children[0] = undefined; + } + this.replaceChild(0, pll); + this._props.removeProp("pressureLossType"); // because this property belongs to child pressure loss law and is set as long as law is not defined + /** + * Y linkability managed in child classes through 'visible' flag + * @see Bief,CourbeRemous + */ + } + } /** * paramétrage de la calculabilité des paramètres */ protected setParametersCalculability() { - } - - public CalcSerie(rInit?: number, resetDepending: boolean = true): Result { - return this.child.CalcSerie(rInit, resetDepending); + this.prms.Q.calculability = ParamCalculability.DICHO; + this.prms.D.calculability = ParamCalculability.DICHO; + this.prms.J.calculability = ParamCalculability.EQUATION; + this.prms.Lg.calculability = ParamCalculability.DICHO; + this.prms.Kloc.calculability = ParamCalculability.DICHO; } public Calc(sVarCalc: string, rInit?: number): Result { - return this.child.Calc(sVarCalc, rInit); + const r: Result = super.Calc(sVarCalc, rInit); + + const V2 = Math.pow(r.values.V, 2); + const Jlin = this.child.result.values.Jlin; + r.values.Klin = 19.62 * Jlin / V2; + r.values.fD = this.prms.J.V / this.prms.Lg.V / V2 * 19.62 * this.prms.D.V; + + this.child.finalChecks(r); + + return r; } public Equation(sVarCalc: string): Result { - return this.child.Equation(sVarCalc); + if (sVarCalc !== "J") { + throw new Error("PressureLoss.Equation() : invalid variable name " + sVarCalc); + } + + if (this._result === undefined) { + this.initNewResultElement(); + } + + const r: Result = this._result; + + // vitesse + r.values.V = this.prms.Q.v / (Math.PI * Math.pow(this.prms.D.v / 2, 2)); + + // perte de charge linéaire propre à chaque module + const rc: Result = this.child.Equation("Jlin"); + if (!rc.ok) { + r.addLog(rc.log); + return r; + } + + // perte de charge totale (J) + r.vCalc = rc.values.Jlin + this.prms.Kloc.v / 19.62 * Math.pow(r.values.V, 2); + + return r; } public get result(): Result { - return this.child.result; + return this._result; // redéfini (à l'identique) car on a redéfini le setter (et un setter seul fait que le getter n'est pas hérité) } public set result(r: Result) { throw new Error("PressureLoss.set result() called!"); } - // interface IObservable + public static override resultsUnits() { + return PressureLoss._resultsUnits; + } + + // interface IProperties - public addObserver(o: Observer) { - this.child.addObserver(o); + public getPropValue(key: string): any { + if (this.childHasProperty(key)) { + return this.child.getPropValue(key); + } + return this._props.getPropValue(key); } - public removeObserver(o: Observer) { - this.child.removeObserver(o); + public setPropValue(key: string, val: any, sender?: any): boolean { + if (this.childHasProperty(key)) { + return this.child.setPropValue(key, val, sender); + } + return this._props.setPropValue(key, val, sender); } } diff --git a/src/pipe_flow/pressureloss_law.ts b/src/pipe_flow/pressureloss_law.ts index 63cfd77d220a66b80bc75af03fde57f2ebd67d8f..ccd36b34388b06ed7032c60831b289432073ea68 100644 --- a/src/pipe_flow/pressureloss_law.ts +++ b/src/pipe_flow/pressureloss_law.ts @@ -1,6 +1,5 @@ -import { Nub, ParamCalculability, PressureLossLawParams } from "../internal_modules"; +import { CalculatorType, Nub, PressureLossLawParams } from "../internal_modules"; import { Result } from "../internal_modules"; -import { Message, MessageCode } from "../internal_modules"; /** * Lois de perte de charge @@ -13,11 +12,19 @@ export enum PressureLossType { * generic pressure loss law (analogous to acSection with respect to SectionParametree nub) */ export abstract class PressureLossLaw extends Nub { - - protected _pressureLossType: PressureLossType; + /** + * correspondance entre les lois de perte de charge et les types de calculette + */ + public static readonly calcTypeFromPressureLossLaw: any = { + [PressureLossType.LechaptCalmon]: CalculatorType.LechaptCalmon, + }; public get pressureLossType(): PressureLossType { - return this._pressureLossType; + return this.getPropValue("pressureLossType"); + } + + public set pressureLossType(plt: PressureLossType) { + this.setPropValue("pressureLossType", plt); } /** @@ -28,37 +35,14 @@ export abstract class PressureLossLaw extends Nub { } /** - * Calcul de la perte de charge linéaire spécifique à chaque module de perte de charge. - * Le paramètre Result est in-out cad qu'il est modifié avec la charge linéaire. - */ - protected abstract calc_Jlin(r: Result): any; - - /** - * paramétrage de la calculabilité des paramètres + * vérifications post-calcul */ - protected setParametersCalculability() { - this.prms.Q.calculability = ParamCalculability.DICHO; - this.prms.D.calculability = ParamCalculability.DICHO; - this.prms.J.calculability = ParamCalculability.EQUATION; - this.prms.Lg.calculability = ParamCalculability.DICHO; - this.prms.Kloc.calculability = ParamCalculability.DICHO; + public finalChecks(r: Result) { } - public Equation(sVarCalc: string): Result { - if (sVarCalc !== "J") { - throw new Error("PressureLossLaw.Equation() : invalid variable name " + sVarCalc); - } - - const r: Result = new Result(0, this); - - // la vitesse est générique - r.values.V = this.prms.Q.v / (Math.PI * Math.pow(this.prms.D.v / 2, 2)); - - // perte de charge linéaire propré à chaque module - this.calc_Jlin(r); - - r.vCalc = r.values.Jl + this.prms.Kloc.v / 19.62 * Math.pow(r.values.V, 2); // perte de charge totale + // interface IProperties - return r; + public hasProperty(key: string): boolean { + return key === "pressureLossType"; } } diff --git a/src/pipe_flow/pressureloss_law_params.ts b/src/pipe_flow/pressureloss_law_params.ts index 1aab2e8a52adec4a2ba442c9bcc98c57f1f1011c..154da09bd38a1f44213b43c8aee1878fa8925e50 100644 --- a/src/pipe_flow/pressureloss_law_params.ts +++ b/src/pipe_flow/pressureloss_law_params.ts @@ -1,58 +1,7 @@ -import { ParamDefinition, ParamFamily } from "../internal_modules"; -import { ParamsEquation } from "../internal_modules"; -import { ParamDomain, ParamDomainValue } from "../internal_modules"; +import { ParamDefinition, ParamDomain, ParamDomainValue, ParamsEquation } from "../internal_modules"; /** * generic pressure loss law parameters */ export class PressureLossLawParams extends ParamsEquation { - /** Débit */ - private _Q: ParamDefinition; - - /** Diamètre */ - private _D: ParamDefinition; - - /** Perte de charge */ - private _J: ParamDefinition; - - /** Longueur de la conduite */ - private _Lg: ParamDefinition; - - /** Perte de charge singulière Kloc */ - private _Kloc: ParamDefinition; - - constructor(rQ: number, rD: number, rJ: number, rLg: number, rKloc: number, nullParams: boolean = false) { - super(); - this._Q = new ParamDefinition(this, "Q", ParamDomainValue.POS, "m³/s", rQ, ParamFamily.FLOWS, undefined, nullParams); - this._D = new ParamDefinition(this, "D", new ParamDomain(ParamDomainValue.INTERVAL, 0, 20), "m", rD, ParamFamily.DIAMETERS, undefined, nullParams); - this._J = new ParamDefinition(this, "J", ParamDomainValue.POS_NULL, "m", rJ, undefined, undefined, nullParams); - this._Lg = new ParamDefinition(this, "Lg", ParamDomainValue.POS, "m", rLg, ParamFamily.LENGTHS, undefined, nullParams); - this._Kloc = new ParamDefinition(this, "Kloc", ParamDomainValue.POS_NULL, undefined, rKloc, undefined, undefined, nullParams); - - this.addParamDefinition(this._Q); - this.addParamDefinition(this._D); - this.addParamDefinition(this._J); - this.addParamDefinition(this._Lg); - this.addParamDefinition(this._Kloc); - } - - get Q() { - return this._Q; - } - - get D() { - return this._D; - } - - get J() { - return this._J; - } - - get Lg() { - return this._Lg; - } - - get Kloc() { - return this._Kloc; - } } diff --git a/src/pipe_flow/pressureloss_params.ts b/src/pipe_flow/pressureloss_params.ts index b12f1bc23855b3143abdd0d4d6941bf89c8acdf6..53ff48faaca7c28a946b1d7f48ab694ea202ef79 100644 --- a/src/pipe_flow/pressureloss_params.ts +++ b/src/pipe_flow/pressureloss_params.ts @@ -1,4 +1,55 @@ +import { ParamDefinition, ParamFamily } from "../internal_modules"; +import { ParamDomain, ParamDomainValue } from "../internal_modules"; import { ParamsEquation } from "../internal_modules"; -// dummy parameters class for code consistency, analogous to SectionParams -export class PressureLossParams extends ParamsEquation { } +export class PressureLossParams extends ParamsEquation { + /** Débit */ + private _Q: ParamDefinition; + + /** Diamètre */ + private _D: ParamDefinition; + + /** Perte de charge */ + private _J: ParamDefinition; + + /** Longueur de la conduite */ + private _Lg: ParamDefinition; + + /** Coefficient de perte de charge singulière Kloc */ + private _Kloc: ParamDefinition; + + constructor(rQ: number, rD: number, rJ: number, rLg: number, rKloc: number, nullParams: boolean = false) { + super(); + this._Q = new ParamDefinition(this, "Q", ParamDomainValue.POS, "m³/s", rQ, ParamFamily.FLOWS, undefined, nullParams); + this._D = new ParamDefinition(this, "D", new ParamDomain(ParamDomainValue.INTERVAL, 0, 20), "m", rD, ParamFamily.DIAMETERS, undefined, nullParams); + this._J = new ParamDefinition(this, "J", ParamDomainValue.POS_NULL, "m", rJ, undefined, undefined, nullParams); + this._Lg = new ParamDefinition(this, "Lg", ParamDomainValue.POS, "m", rLg, ParamFamily.LENGTHS, undefined, nullParams); + this._Kloc = new ParamDefinition(this, "Kloc", ParamDomainValue.POS_NULL, undefined, rKloc, undefined, undefined, nullParams); + + this.addParamDefinition(this._Q); + this.addParamDefinition(this._D); + this.addParamDefinition(this._J); + this.addParamDefinition(this._Lg); + this.addParamDefinition(this._Kloc); + } + + get Q() { + return this._Q; + } + + get D() { + return this._D; + } + + get J() { + return this._J; + } + + get Lg() { + return this._Lg; + } + + get Kloc() { + return this._Kloc; + } +} diff --git a/src/prebarrage/pb_cloison.ts b/src/prebarrage/pb_cloison.ts index 6a5f18c26ac2194c114fe128f420b6bedd0c5f15..11db86a6f574575cf997d5c8be0e67f52d418f63 100644 --- a/src/prebarrage/pb_cloison.ts +++ b/src/prebarrage/pb_cloison.ts @@ -15,8 +15,8 @@ export class PbCloison extends ParallelStructure { this.prms.Q.visible = false; this.prms.Z1.visible = false; this.prms.Z2.visible = false; - this.properties.setPropValue("upstreamBasin", bassinAmont === undefined ? "" : bassinAmont.uid); - this.properties.setPropValue("downstreamBasin", bassinAval === undefined ? "" : bassinAval.uid); + this.setPropValue("upstreamBasin", bassinAmont === undefined ? "" : bassinAmont.uid); + this.setPropValue("downstreamBasin", bassinAval === undefined ? "" : bassinAval.uid); this.setCalculatorType(CalculatorType.PbCloison); this._intlType = "Cloison"; } @@ -45,7 +45,7 @@ export class PbCloison extends ParallelStructure { if (b !== undefined) { uid = b.uid; } - this.properties.setPropValue("upstreamBasin", uid); + this.setPropValue("upstreamBasin", uid); this.parent.updatePointers(); } @@ -68,7 +68,7 @@ export class PbCloison extends ParallelStructure { if (b !== undefined) { uid = b.uid; } - this.properties.setPropValue("downstreamBasin", uid); + this.setPropValue("downstreamBasin", uid); this.parent.updatePointers(); } diff --git a/src/prebarrage/pre_barrage.ts b/src/prebarrage/pre_barrage.ts index 12305ba2ad9b8f231e1eb7b1c799bd7ee331768e..08122a1b53cd5c8fb221620acfe2fce9e5ec317c 100644 --- a/src/prebarrage/pre_barrage.ts +++ b/src/prebarrage/pre_barrage.ts @@ -650,10 +650,10 @@ export class PreBarrage extends Nub { if (c instanceof PbCloison) { for (const k of Object.keys(ret.changedUids)) { // find basins having the changed UID - if (c.properties.props.upstreamBasin === k) { + if (c.getPropValue("upstreamBasin") === k) { c.bassinAmont = this.findChild(ret.changedUids[k]) as PbBassin; } - if (c.properties.props.downstreamBasin === k) { + if (c.getPropValue("downstreamBasin") === k) { c.bassinAval = this.findChild(ret.changedUids[k]) as PbBassin; } } diff --git a/src/props.ts b/src/props.ts index 868e28dfe4c6bec48a7fdffab4fe7cce576023a4..01743005bfdd85440e6dbe2fc701d1a321e2f236 100644 --- a/src/props.ts +++ b/src/props.ts @@ -1,70 +1,147 @@ -import { IObservable, Observable, Observer } from "./internal_modules"; +import { cloneDeep } from "lodash"; + +import { BiefRegime, CalculatorType, DivingJetSupport, FishSpecies, GrilleProfile, GrilleType, IObservable, LCMaterial, LoiDebit, MRCInclination, MethodeResolution, Observable, Observer, ParType, PressureLossType, SPPOperation, SectionType, StructureType, TrigoOperation, TrigoUnit, isNumeric } from "./internal_modules"; /** - * special property names + * get enum numerical value from enum class name and value as a string + * @param enumClass enum class name + * @param enumValueName enum value as a string + * @returns enum numerical value */ +export function enumValueFromString(enumClass: string, enumValueName: string): any { + // !! property names must be unique throughout JaLHyd !! + const enumValues = Props.enumFromProperty[enumClass]; + if (enumValues) { + return enumValues[enumValueName]; + } + throw new Error("unknown enum class ${enumClass}"); +} /** * represents a boolean: true if provided value at parameter creation must be ignore (@see nghyd/enableEmptyFieldsOnFormInit) */ export const Prop_NullParameters: string = "nullparams"; +/** + * Interface permettant de propager de manière transparente des opérations sur des propriétés en encapsulant celles ci + * (implémentée par Props et les classes possédant directement ou indirectement un membre de type Props, par ex Nub) + */ +export interface IProperties extends IObservable { + /** + * get property value + * @param key property name + */ + getPropValue(key: string): any; + + /** + * set property value + * @param key property name + * @param val property value to set + * @param sender object from which modification originates + */ + setPropValue(key: string, val: any, sender?: any): boolean; + + /** + * determine if this object directly or indirectly has a given property + * @param key property name + */ + hasProperty(key: string): boolean; + + /** + * list of properties keys + */ + readonly keys: string[]; +} + /** * gestion d'un ensemble de propriétés (clé/valeur) qui prévient quand * l'une d'entre-elles change */ -export class Props implements IObservable { +export class Props implements IProperties { + + /** correspondance entre les noms de propriétés et les enum associés */ + public static readonly enumFromProperty: any = { + calcType: CalculatorType, + divingJetSupported: DivingJetSupport, + gridProfile: GrilleProfile, + gridType: GrilleType, + inclinedApron: MRCInclination, + loiDebit: LoiDebit, + material: LCMaterial, + methodeResolution: MethodeResolution, + nodeType: SectionType, + parType: ParType, + pressureLossType: PressureLossType, + regime: BiefRegime, + species: FishSpecies, + sppOperation: SPPOperation, + structureType: StructureType, + trigoOperation: TrigoOperation, + trigoUnit: TrigoUnit + }; + // implémentation de IObservable par délégation private _observable: Observable; - constructor(private _props: any = {}) { + // object literal representing properties keys and values + private _map: any = {}; + + constructor(prps?: any | IProperties) { this._observable = new Observable(); + + if (prps !== undefined) { + if (Props.implementsIProperties(prps)) { + this.copyIProperties(prps); + } + else + this._map = cloneDeep(prps); + } + } + + /** + * @returns true if an object implements the IProperties interface + */ + public static implementsIProperties(o: any): boolean { + return "getPropValue" in o && "setPropValue" in o && "hasProperty" in o && "keys" in o; + } + + /** + * set properties map from an IProperties + */ + private copyIProperties(p: IProperties) { + this._map = {}; + for (const k of p.keys) { + this._map[k] = p.getPropValue(k); + } + } + + public get keys(): string[] { + return Object.keys(this._map); } public getPropValue(key: string): any { - return this._props[key]; + return this._map[key]; } public setPropValue(key: string, val: any, sender?: any): boolean { if (key === undefined) { throw new Error("setPropValue : undefined key!"); } - const oldValue = this._props[key]; + const oldValue = this._map[key]; const changed = oldValue !== val; if (changed) { - this._props[key] = val; + this._map[key] = val; this.notifyPropChange(key, val, sender); } return changed; } - /** - * fixe la valeur de toutes les propriétés - * @param props nouvelles valeurs - * @param sender objet modificateur - */ - public setProps(props: {}, sender?: any) { - let p; - if (props instanceof Props) { - p = props._props; - } else { - p = props; - } - const changed = this.compareObjects(this._props, p); - if (changed) { - this._props = {}; - for (const k in p) { - if (p.hasOwnProperty(k)) { - this._props[k] = p[k]; - } - } - - this.notifyPropsChange(sender); - } + public removeProp(key: string) { + delete this._map[key]; } - public get props() { - return this._props; + public hasProperty(key: string): boolean { + return true; } public getObservers(): Observer[] { @@ -75,31 +152,24 @@ export class Props implements IObservable { * Remove all properties, does not notify of any change */ public reset() { - this._props = {}; + this._map = {}; } /** * Clones properties into a new Props object */ public clone(): Props { - const res = new Props(); - // copy values - for (const k in this._props) { - if (this._props.hasOwnProperty(k)) { - res._props[k] = this._props[k]; - } - } - return res; + return new Props(this); } public toString(): string { let res = "["; - for (const k in this._props) { - if (this._props.hasOwnProperty(k)) { + for (const k in this._map) { + if (this._map.hasOwnProperty(k)) { if (res !== "[") { res += ", "; } - res += `${k}:${this._props[k]}`; + res += `${k}:${this._map[k]}`; } } res += "]"; @@ -129,16 +199,6 @@ export class Props implements IObservable { this._observable.notifyObservers(data, sender); } - /** - * notification de changement de la valeur de toutes les propriétés - * @param sender objet ayant changé les valeurs - */ - private notifyPropsChange(sender: any) { - this.notifyObservers({ - action: "propertiesChange", - }, sender); - } - /** * notification de changement de la valeur d'une propriété * @param prop nom de la propriété modifiée @@ -154,32 +214,22 @@ export class Props implements IObservable { } /** - * compare 2 objets (clés et valeurs) - * @return true s'il existe une différence + * Returns a copy of given map, inverting enum keys and values */ - private compareObjects(o1: { [key: string]: any }, o2: { [key: string]: any }) { - const oldKeys: string[] = Object.keys(o1).sort(); - const newKeys: string[] = Object.keys(o2).sort(); - - // nombre de clés - const changed = oldKeys.length !== newKeys.length; - if (changed) { - return true; - } - // nom des clés - for (const i in oldKeys) { - if (oldKeys[i] !== newKeys[i]) { - return true; - } - } - // valeurs - for (const i in o1) { - if (o1[i] !== o2[i]) { - return true; + public static invertEnumKeysAndValuesInProperties(stringProps: any, forceNumbers: boolean = false) { + const res = JSON.parse(JSON.stringify(stringProps)); // clone + for (const k in res) { + if (!forceNumbers || !isNumeric(res[k])) { + if (Object.keys(Props.enumFromProperty).includes(k)) { + const enumClass = Props.enumFromProperty[k]; + res[k] = enumClass[res[k]]; + } } } - - return false; + return res; } + public invertEnumKeysAndValues(forceNumbers: boolean = false) { + return Props.invertEnumKeysAndValuesInProperties(this._map, forceNumbers); + } } diff --git a/src/session.ts b/src/session.ts index d1fb86c0b3e0e74f7e06ca2fb6ee56929df537fa..f9f6ef3b7879a1b9b657f8e66affb92e4cac5095 100644 --- a/src/session.ts +++ b/src/session.ts @@ -1,7 +1,5 @@ -import { isNumeric } from "./internal_modules"; -import { CalculatorType, SectionType } from "./internal_modules"; +import { CalculatorType, IProperties, PressureLossParams, SectionType } from "./internal_modules"; import { config } from "./internal_modules"; -import { LCMaterial } from "./internal_modules"; import { LinkedValue } from "./internal_modules"; import { Nub } from "./internal_modules"; import { ParamDefinition } from "./internal_modules"; @@ -9,7 +7,7 @@ import { Props, Prop_NullParameters } from "./internal_modules"; import { SessionSettings } from "./internal_modules"; // Calculettes -import { Grille, GrilleProfile, GrilleType } from "./internal_modules"; +import { Grille } from "./internal_modules"; import { GrilleParams } from "./internal_modules"; import { Jet } from "./internal_modules"; import { JetParams } from "./internal_modules"; @@ -19,17 +17,16 @@ import { MacroRugo } from "./internal_modules"; import { MacrorugoCompound } from "./internal_modules"; import { MacrorugoCompoundParams } from "./internal_modules"; import { MacrorugoParams } from "./internal_modules"; -import { MRCInclination } from "./internal_modules"; -import { SPP, SPPOperation } from "./internal_modules"; +import { SPP } from "./internal_modules"; import { SPPParams } from "./internal_modules"; -import { Trigo, TrigoOperation, TrigoUnit } from "./internal_modules"; +import { Trigo } from "./internal_modules"; import { TrigoParams } from "./internal_modules"; import { YAXB } from "./internal_modules"; import { YAXBParams } from "./internal_modules"; import { YAXN } from "./internal_modules"; import { YAXNParams } from "./internal_modules"; import { Bief } from "./internal_modules"; -import { BiefParams, BiefRegime } from "./internal_modules"; +import { BiefParams } from "./internal_modules"; import { MethodeResolution } from "./internal_modules"; import { Pente } from "./internal_modules"; import { PenteParams } from "./internal_modules"; @@ -71,16 +68,14 @@ import { DeverParams } from "./internal_modules"; import { CreateStructure } from "./internal_modules"; import { ParallelStructure } from "./internal_modules"; import { ParallelStructureParams } from "./internal_modules"; -import { LoiDebit, StructureType } from "./internal_modules"; -import { Par, ParType } from "./internal_modules"; +import { LoiDebit } from "./internal_modules"; +import { Par } from "./internal_modules"; import { ParParams } from "./internal_modules"; import { ParSimulation } from "./internal_modules"; import { ParSimulationParams } from "./internal_modules"; -import { FishSpecies } from "./internal_modules"; import { Espece } from "./internal_modules"; import { EspeceParams } from "./internal_modules"; import { Verificateur } from "./internal_modules"; -import { DivingJetSupport } from "./internal_modules"; import { PreBarrage } from "./internal_modules"; import { PreBarrageParams } from "./internal_modules"; import { PbCloison } from "./internal_modules"; @@ -92,27 +87,6 @@ import { PressureLossLaw, PressureLossType } from "./internal_modules"; export class Session { - /** correspondance entre les noms des propriétés et les enum associés */ - public static enumFromProperty: any = { - loiDebit: LoiDebit, - methodeResolution: MethodeResolution, - material: LCMaterial, - gridProfile: GrilleProfile, - gridType: GrilleType, - regime: BiefRegime, - trigoOperation: TrigoOperation, - trigoUnit: TrigoUnit, - sppOperation: SPPOperation, - nodeType: SectionType, - calcType: CalculatorType, - structureType: StructureType, - inclinedApron: MRCInclination, - parType: ParType, - species: FishSpecies, - divingJetSupported: DivingJetSupport, - pressureLossType: PressureLossType - }; - public static getInstance(): Session { if (Session._instance === undefined) { Session._instance = new Session(); @@ -120,22 +94,6 @@ export class Session { return Session._instance; } - /** - * Returns a copy of given map, inverting enum keys and values - */ - public static invertEnumKeysAndValuesInProperties(stringProps: any, forceNumbers: boolean = false) { - const res = JSON.parse(JSON.stringify(stringProps)); // clone - for (const k in res) { - if (!forceNumbers || !isNumeric(res[k])) { - if (Object.keys(Session.enumFromProperty).includes(k)) { - const enumClass = Session.enumFromProperty[k]; - res[k] = enumClass[res[k]]; - } - } - } - return res; - } - /** instance pour le pattern singleton */ private static _instance: Session; @@ -364,20 +322,56 @@ export class Session { return foundNub; } + private static parameterIndex(obj: any, symbol: string): number { + let i; + const prms = obj["parameters"]; + for (i in prms) { + if (prms[i]["symbol"] === symbol) { + return +i; + } + } + return -1; + } + /** * Calcule le type de calculette compatible et modifie les propriétés en conséquence. * Permet de charger des fichiers session avec une version antérieure. * Par ex : Lechapt-Calmon -> PressureLoss */ - private compatibleCalculatorType(props: Props): CalculatorType { - const ct: CalculatorType = props.getPropValue("calcType"); - switch (ct) { + private compatibleCalculator(obj: any): any { + switch (obj["props"]["calcType"]) { case CalculatorType.LechaptCalmon: - props.setPropValue("pressureLossType", PressureLossType.LechaptCalmon); - return CalculatorType.PressureLoss; + // create parent PressureLoss nub + const plProps = new Props(); + plProps.setPropValue("calcType", CalculatorType.PressureLoss); + const pl = this.createNub(plProps); + + // JSON representation + let res: any = pl.objectRepresentation(); + + // set Lechapt-Calmon as child + res["children"] = [obj]; + + // move PressureLoss parameters from Lechapt-Calmon + const movedParams = ["Q", "D", "J", "Lg", "Kloc"]; + for (const p of movedParams) { + // if child has parameter + const cp = Session.parameterIndex(obj, p); + if (cp !== -1) { + const pp = Session.parameterIndex(res, p); + if (pp === -1) { + res["parameters"].push(obj["parameters"][cp]); + } else { + res["parameters"][pp] = obj["parameters"][cp]; + } + // delete obj["parameters"][pp]; + obj["parameters"].splice(cp, 1); + } + } + return res; default: - return ct; + return obj; } } @@ -391,15 +385,14 @@ export class Session { * définies dans le constructeur du Nub créé * @param dbg activer débogage */ - public createNub(params: Props, parentNub?: Nub, dbg: boolean = false): Nub { - const calcType = this.compatibleCalculatorType(params); - + public createNub(params: IProperties, parentNub?: Nub, dbg: boolean = false): Nub { // true if provided values to parameter creation must be ignored const nullParams: boolean = params.getPropValue(Prop_NullParameters) === undefined ? false : params.getPropValue(Prop_NullParameters); let nub: Nub; let prms: any; + const calcType: CalculatorType = params.getPropValue("calcType"); switch (calcType) { case CalculatorType.ConduiteDistributrice: prms = new ConduiteDistribParams( @@ -415,11 +408,6 @@ export class Session { case CalculatorType.LechaptCalmon: prms = new PL_LechaptCalmonParams( - 3, // débit - 1.2, // diamètre - 0.6, /// perte de charge - 100, // longueur du toyo - 0, // Ks Perte de charge singulière 1.863, // paramètre L du matériau 2, // paramètre M du matériau 5.33, // paramètre N du matériau @@ -821,9 +809,17 @@ export class Session { break; case CalculatorType.PressureLoss: + const plParams = new PressureLossParams( + 3, // débit + 1.2, // diamètre + 0.6, /// perte de charge + 100, // longueur du toyo + 0, // Kloc Perte de charge singulière + nullParams + ); const lossType: PressureLossType = params.getPropValue("pressureLossType") ?? PressureLossType.LechaptCalmon; - const pl = this.createPressureLossLaw(lossType, dbg, nullParams); - nub = new PressureLoss(pl, dbg); + nub = new PressureLoss(plParams, undefined, dbg); + nub.setPropValue("pressureLossType", lossType); break; default: @@ -834,7 +830,7 @@ export class Session { // propagate properties try { - nub.properties = params; + nub.setProperties(params); } catch (e) { // loading Solveur properties when unserialising a session might fail because target // Nub / param do not exist yet; silent fail in this case, and Solveur.fixTargets() @@ -1020,27 +1016,21 @@ export class Session { /** * Crée un Nub de type perte de charge */ - private createPressureLossLaw(plt: PressureLossType, dbg: boolean = false, nullParams: boolean = false): PressureLossLaw { - switch (plt) { - case PressureLossType.LechaptCalmon: - const prms = new PL_LechaptCalmonParams( - 3, // débit - 1.2, // diamètre - 0.6, /// perte de charge - 100, // longueur du toyo - 0, // Ks Perte de charge singulière - 1.863, // paramètre L du matériau - 2, // paramètre M du matériau - 5.33, // paramètre N du matériau - nullParams - - ); - return new PL_LechaptCalmon(prms, dbg); - - default: - throw new Error(`type de perte de charge ${PressureLossType[plt]} non pris en charge`); - } - } + // private createPressureLossLaw(plt: PressureLossType, dbg: boolean = false, nullParams: boolean = false): PressureLossLaw { + // switch (plt) { + // case PressureLossType.LechaptCalmon: + // const prms = new PL_LechaptCalmonParams( + // 1.863, // paramètre L du matériau + // 2, // paramètre M du matériau + // 5.33, // paramètre N du matériau + // nullParams + // ); + // return new PL_LechaptCalmon(prms, dbg); + + // default: + // throw new Error(`type de perte de charge ${PressureLossType[plt]} non pris en charge`); + // } + // } /** * Creates a Nub from an object representation and adds it to the current session; returns @@ -1057,8 +1047,10 @@ export class Session { meta: undefined, hasErrors: false }; + // get upward compatible calculator + obj = this.compatibleCalculator(obj); // decode properties - const props = Session.invertEnumKeysAndValuesInProperties(obj.props, true); + const props = Props.invertEnumKeysAndValuesInProperties(obj.props, true); // create the Nub let newNub; if (register) { diff --git a/src/solveur/solveur.ts b/src/solveur/solveur.ts index e40c9af1478a75e28bb8f504ad8c27ebd0b5f3e8..7ed087eacda325d4b6efd1fee2714605bc3e512f 100644 --- a/src/solveur/solveur.ts +++ b/src/solveur/solveur.ts @@ -77,7 +77,7 @@ export class Solveur extends Nub implements Observer { if (n !== undefined) { uid = n.uid; } - this.properties.setPropValue("nubToCalculate", uid); + this.setPropValue("nubToCalculate", uid); } public get targettedResult(): string { @@ -126,7 +126,7 @@ export class Solveur extends Nub implements Observer { if (p !== undefined) { sp = p.nubUid + "/" + p.symbol; } - this.properties.setPropValue("searchedParameter", sp); + this.setPropValue("searchedParameter", sp); } /** @@ -255,8 +255,8 @@ export class Solveur extends Nub implements Observer { }; try { // do not use setters, to allow setting directly the string UIDs - this.properties.setPropValue("nubToCalculate", obj.props.nubToCalculate); - this.properties.setPropValue("searchedParameter", obj.props.searchedParameter); + this.setPropValue("nubToCalculate", obj.props.nubToCalculate); + this.setPropValue("searchedParameter", obj.props.searchedParameter); } catch (e) { ret.hasErrors = true; } diff --git a/src/structure/factory_structure.ts b/src/structure/factory_structure.ts index 849ca3ee347a7c8dd318c9b821ed8f89605d7445..31927f6063b25e5b24a2f494c2209286ddef30bf 100755 --- a/src/structure/factory_structure.ts +++ b/src/structure/factory_structure.ts @@ -224,7 +224,7 @@ export function CreateStructure(loiDebit: LoiDebit, parentNub?: ParallelStructur if (parentNub) { ret.setParent(parentNub); // Set Structure Type - ret.properties.setPropValue("structureType", StructureProperties.findCompatibleStructure(loiDebit, parentNub)); + ret.setPropValue("structureType", StructureProperties.findCompatibleStructure(loiDebit, parentNub)); } return ret; diff --git a/src/structure/structure.ts b/src/structure/structure.ts index 78312bee20c9217c15f8cd2352104bf928e0ebba..0363d5133eabb71e30e54a71ff16896f9cdb262c 100644 --- a/src/structure/structure.ts +++ b/src/structure/structure.ts @@ -96,23 +96,6 @@ export abstract class Structure extends ChildNub { this._intlType = "Ouvrage"; } - /** Returns Props object (observable set of key-values) associated to this Nub */ - public get properties(): Props { - return this._props; - } - - // overriden to set property once and for all (it's a constant) - protected setCalculatorType(ct: CalculatorType): void { - super.setCalculatorType(ct); - // completes props with calcType - this._props.setPropValue("calcType", this.calcType); - } - - // setter is not inherited from Nub if getter is redefined :/ - public set properties(props: Props) { - super.setProperties(props); - } - public get isZDVcalculable(): boolean { return this._isZDVcalculable; } diff --git a/src/units.ts b/src/units.ts index b1538784ef270bc180e2a2317f893762d01baf65..f072fe21f2024c04a270368b36d2cf3d5fba5f86 100644 --- a/src/units.ts +++ b/src/units.ts @@ -1,5 +1,6 @@ import { CalculatorType } from "./compute-node"; import { Cloisons, ConcentrationBlocs, Dever, Grille, Jet, MacroRugo, PabNombre, Par, RegimeUniforme } from "./index"; +import { PressureLoss } from "./internal_modules"; /** * correspondance type de calculette - classe de Nub @@ -13,7 +14,8 @@ const nubClasses = new Map<CalculatorType, any>([ [CalculatorType.Cloisons, Cloisons], [CalculatorType.PabNombre, PabNombre], [CalculatorType.Par, Par], - [CalculatorType.Dever, Dever] + [CalculatorType.Dever, Dever], + [CalculatorType.PressureLoss, PressureLoss] ]); /** @@ -29,5 +31,5 @@ export function getNubResultUnit(nubType: CalculatorType, symbol: string) { const units = f(); return units[symbol]; } - return {}; + return undefined; } diff --git a/src/util/enum.ts b/src/util/enum.ts index fc4a9cb0fe8f692f1f95cdf0cf5d67c9b90ef06f..d3c7dcbec424152a4ba22b4056f8950b9aa48892 100644 --- a/src/util/enum.ts +++ b/src/util/enum.ts @@ -47,19 +47,3 @@ export class EnumEx { return Object.keys(e).map((k) => e[k]); } } - - -/** - * get enum numerical value from enum class name and value as a string - * @param enumClass enum class name - * @param enumValueName enum value as a string - * @returns enum numerical value - */ -export function enumValueFromString(enumClass: string, enumValueName: string): any { - // !! property names must be unique throughout JaLHyd !! - const enumValues = Session.enumFromProperty[enumClass]; - if (enumValues) { - return enumValues[enumValueName]; - } - throw new Error("unknown enum class ${enumClass}"); -} diff --git a/src/verification/espece.ts b/src/verification/espece.ts index dcc026235524bdb02f3642b440e20569ee45616e..25d43cad7f07cc1fc8500759f83b5993409ff9b4 100644 --- a/src/verification/espece.ts +++ b/src/verification/espece.ts @@ -340,7 +340,7 @@ export class Espece extends Nub implements Observer { /** Changing the fish species will load adequate predefined values */ public set species(s: FishSpecies) { - this.properties.setPropValue("species", s); + this.setPropValue("species", s); } public set passToCheck(p: FishPass) { @@ -349,11 +349,11 @@ export class Espece extends Nub implements Observer { } public get divingJetSupported(): DivingJetSupport { - return this.properties.getPropValue("divingJetSupported"); + return this.getPropValue("divingJetSupported"); } public set divingJetSupported(i: DivingJetSupport) { - this.properties.setPropValue("divingJetSupported", i); + this.setPropValue("divingJetSupported", i); } /** @@ -898,7 +898,7 @@ export class Espece extends Nub implements Observer { for (const device of wall.structures) { let zdv = device.prms.ZDV.singleValue; // if device is a regulated weir, get calculated ZDV at current iteration from parent downWall - if (loiAdmissiblesCloisonAval.VanneLevante.includes(device.properties.getPropValue("loiDebit"))) { + if (loiAdmissiblesCloisonAval.VanneLevante.includes(device.getPropValue("loiDebit"))) { zdv = device.parent.result.resultElements[this.indexToCheck].values.ZDV; } // do not use device.prms.h1.v, that contains only the latest calculated value if pass is variyng diff --git a/src/verification/verificateur.ts b/src/verification/verificateur.ts index 2d0621630af097bfa1aa020f9a5225346e9aacc8..c459b78b5eb628c410a65c9e178d6a4125505036 100644 --- a/src/verification/verificateur.ts +++ b/src/verification/verificateur.ts @@ -45,7 +45,7 @@ export class Verificateur extends Nub { } public set speciesList(l: string[]) { - this.properties.setPropValue("speciesList", l); + this.setPropValue("speciesList", l); // (re)create Espece instances this.initSpecies(); } @@ -67,7 +67,7 @@ export class Verificateur extends Nub { if (n !== undefined) { uid = n.uid; } - this.properties.setPropValue("nubToVerify", uid); + this.setPropValue("nubToVerify", uid); } /**