From 72fc44f37633b63da4ec3e4247321293adb0e22c Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Mon, 25 Mar 2019 15:38:48 +0100 Subject: [PATCH] Better representation of parameter to calculate, when it is a child nub parameter (Structure) --- spec/structure/functions.ts | 20 ++++-- spec/structure/parallel_structure.spec.ts | 17 +++-- src/nub.ts | 25 ++++++-- src/structure/parallel_structure.ts | 76 +++++------------------ src/structure/structure.ts | 6 +- 5 files changed, 70 insertions(+), 74 deletions(-) diff --git a/spec/structure/functions.ts b/spec/structure/functions.ts index 0ea2b260..298ab9c7 100644 --- a/spec/structure/functions.ts +++ b/spec/structure/functions.ts @@ -118,7 +118,10 @@ export function testParallelStructures(oPS: ParallelStructure, iStTypes: number[ // Le calcul de l'ouverture sur les seuils doit renvoyer une exception (cas impossible) it(`Calc(${prm.symbol}) should return exception`, () => { expect( - () => { oPS.Calc(i + "." + prm.symbol); } + () => { oPS.Calc({ + uid: oPS.structures[i].uid, + symbol: prm.symbol + }); } ).toThrow(new Error("Structure:Calc : Calcul de W impossible sur un seuil")); }); } else if ( @@ -129,7 +132,10 @@ export function testParallelStructures(oPS: ParallelStructure, iStTypes: number[ // Les lois CEM88D et CUNGE80 ne font pas intervenir ZDV dans le calcul d'un orifice noyé it(`Calc(${prm.symbol}) should return an error`, () => { expect( - oPS.Calc(i + "." + prm.symbol).code + oPS.Calc({ + uid: oPS.structures[i].uid, + symbol: prm.symbol + }).code ).toBe(MessageCode.ERROR_STRUCTURE_ZDV_PAS_CALCULABLE); }); } else if ( @@ -138,12 +144,18 @@ export function testParallelStructures(oPS: ParallelStructure, iStTypes: number[ ) { // Le calcul de l'angle de l'équation triangulaire n'est pas assez précis it(`Calc(${prm.symbol}) should return ${ref}`, () => { - checkResult(oPS.Calc(i + "." + prm.symbol), ref, 1); + checkResult(oPS.Calc({ + uid: oPS.structures[i].uid, + symbol: prm.symbol + }), ref, 1); }); } else { // Cas normal : On teste la valeur calculée it(`Calc(${prm.symbol}) should return ${ref}`, () => { - checkResult(oPS.Calc(i + "." + prm.symbol), ref); + checkResult(oPS.Calc({ + uid: oPS.structures[i].uid, + symbol: prm.symbol + }), ref); }); } prm.v = ref; // Go back to initial value for following tests diff --git a/spec/structure/parallel_structure.spec.ts b/spec/structure/parallel_structure.spec.ts index e13a7b16..78c0be76 100644 --- a/spec/structure/parallel_structure.spec.ts +++ b/spec/structure/parallel_structure.spec.ts @@ -39,11 +39,20 @@ describe("Class ParallelStructure: ", () => { itParallelStructure("Q", 30, 15); itParallelStructure("Z1", 30, 15); itParallelStructure("Z2", 15, 15); - itParallelStructure("0.ZDV", 0, 15); - itParallelStructure("1.ZDV", 0, 15); + itParallelStructure({ + uid: pstruct.structures[0].uid, + symbol: "ZDV" + }, 0, 15); + itParallelStructure({ + uid: pstruct.structures[1].uid, + symbol: "ZDV" + }, 0, 15); it("shoud return an error Q too high", () => { pstruct.prms.Q.v = 14; - const res: Result = pstruct.Calc("1.ZDV"); + const res: Result = pstruct.Calc({ + uid: pstruct.structures[1].uid, + symbol: "ZDV" + }); expect(res.code).toBe(MessageCode.ERROR_STRUCTURE_Q_TROP_ELEVE); }); }); @@ -55,7 +64,7 @@ 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: string, rVcalc: number, Q?: number) { +function itParallelStructure(sVarCalc: any, rVcalc: number, Q?: number) { it(`${sVarCalc} should be ${rVcalc}`, () => { checkResult(pstruct.Calc(sVarCalc), rVcalc); }); diff --git a/src/nub.ts b/src/nub.ts index efef15d7..c6f9b612 100644 --- a/src/nub.ts +++ b/src/nub.ts @@ -1,4 +1,4 @@ -import { ParamDefinition, Session } from "."; +import { ParamDefinition, Session, Structure } from "."; import { ComputeNode } from "./compute-node"; import { Dichotomie } from "./dichotomie"; import { INamedIterableValues, IterableValues } from "./param/param-value-iterator"; @@ -91,9 +91,9 @@ export abstract class Nub extends ComputeNode { /** * effectue une série de calculs sur un paramètre * @param rInit solution approximative du paramètre - * @param sDonnee éventuel symbole du paramètre à calculer + * @param sDonnee éventuel symbole / paire symbole-uid du paramètre à calculer */ - public CalcSerie(rInit?: number, sDonnee?: string): Result { + public CalcSerie(rInit?: number, sDonnee?: any): Result { let computedParam: ParamDefinition; // instance de ParamValues utilisée pour le paramètre varié (qui peut être un paramètre référencé (importé)) let variatedValues: IterableValues; @@ -149,7 +149,7 @@ export abstract class Nub extends ComputeNode { } } - let computedSymbol: string; + let computedSymbol: any; if (sDonnee) { computedSymbol = sDonnee; } else { @@ -182,7 +182,9 @@ export abstract class Nub extends ComputeNode { this._result = res; } - this._result.name = computedSymbol; + const realSymbol = (typeof computedSymbol === "string") ? computedSymbol : computedSymbol.symbol; + this._result.name = realSymbol; + return this._result; } @@ -234,7 +236,18 @@ export abstract class Nub extends ComputeNode { ) { // if it is safe to link p's value to src if (p.isLinkableTo(src)) { - res.push(new LinkedValue(this, p, p.symbol)); + // if p is a CALC param of a Structure, other than "Q", expose its parent + // (structures always have Q as CALC param and cannot have another) + if ( + (this instanceof Structure) + && (p.valueMode === ParamValueMode.CALCUL) + && p.symbol !== "Q" + ) { + // trick to expose p a a result of the parent Nub + res.push(new LinkedValue(this.parent, p, p.symbol)); + } else { + res.push(new LinkedValue(this, p, p.symbol)); + } } } } diff --git a/src/structure/parallel_structure.ts b/src/structure/parallel_structure.ts index 984fce3b..9638dace 100644 --- a/src/structure/parallel_structure.ts +++ b/src/structure/parallel_structure.ts @@ -1,27 +1,15 @@ import { Nub } from "../nub"; import { ParamCalculability } from "../param/param-definition"; -import { Result } from "../util/result"; -import { ParallelStructureParams } from "./parallel_structure_params"; -import { Structure } from "./structure"; - -import { ParamDefinition } from "../param/param-definition"; import { IParamDefinitionIterator, ParamsEquation, ParamsEquationArrayIterator } from "../param/params-equation"; - import { Props } from "../props"; import { Session } from "../session"; -import { LinkedValue } from "../value_ref/object_ref"; +import { Result } from "../util/result"; +import { ParallelStructureParams } from "./parallel_structure_params"; +import { Structure } from "./structure"; import { loiAdmissiblesOuvrages, LoiDebit } from "./structure_props"; export { ParallelStructureParams }; -/** - * Interface pour mémoriser le n° d'ouvrage et le paramètre à calculer - */ -interface IStructureVarCalc { - index: number; - prm: string; -} - /** * Calcul de une ou plusieurs structures hydrauliques en parallèles * reliées par les cotes amont et aval et dont le débit est égal à la @@ -125,12 +113,13 @@ export class ParallelStructure extends Nub { /** * Returns the current index of the given structure if any, * or else returns -1 - * @param structure Structure to look for + * @param structure Structure or Structure UID to look for */ - public getIndexForStructure(structure: Structure): number { + public getIndexForStructure(structure: Structure | string): number { let index: number = -1; + const uid = (structure instanceof Structure) ? structure.uid : structure; for (let i = 0; i < this._structures.length; i++) { - if (this._structures[i].uid === structure.uid) { + if (this._structures[i].uid === uid) { index = i; } } @@ -239,10 +228,11 @@ export class ParallelStructure extends Nub { /** * Calcul du débit total, de la cote amont ou aval ou d'un paramètre d'une structure * @param sVarCalc Nom du paramètre à calculer : - * "Q", "Z1", "Z2" ou "n.X" avec "n" l'index de l'ouvrage et "X" son paramètre + * "Q", "Z1", "Z2" + * ou { uid: "abcdef", symbol: "X" } avec "abcdef" l'index de l'ouvrage et "X" son paramètre * @param rInit Valeur initiale */ - public Calc(sVarCalc: string, rInit?: number): Result { + public Calc(sVarCalc: string | any, rInit?: number): Result { let res: Result; switch (sVarCalc) { case "Z1": @@ -255,12 +245,13 @@ export class ParallelStructure extends Nub { break; default: // Pour les caractéristiques des ouvrages - const sVC = this.getStructureVarCalc(sVarCalc); - res = this.CalcStructPrm(sVC, rInit); + // const sVC = this.getStructureVarCalc(sVarCalc); + const structureIndex = this.getIndexForStructure(sVarCalc.uid); + res = this.CalcStructPrm(structureIndex, sVarCalc.symbol); // Suppression des extraResults : ils sont complétés plus bas pour chaque ouvrage res.resultElement.extraResults = {}; if (res.ok) { - this._structures[sVC.index].getParameter(sVC.prm).setValue(res.vCalc); + this._structures[structureIndex].getParameter(sVarCalc.symbol).setValue(res.vCalc); } } if (res.ok) { @@ -378,50 +369,17 @@ export class ParallelStructure extends Nub { } } - /** - * Renvoie le n° de structure et le paramètre à calculer - * @param sVarCalc Nom du paramètre à calculer : "n.X" avec "n" l'index de l'ouvrage et "X" son paramètre - */ - protected getStructureVarCalc(sVarCalc: string): IStructureVarCalc { - let sIndex: string; - let sPrm: string; - if (sVarCalc.indexOf(".") === -1) { - throw new Error(`getStructureVarCalc() : erreur d'analyse de ${sVarCalc}, (pas de la forme n.X)`); - } - [sIndex, sPrm] = sVarCalc.split("."); - const i = parseInt(sIndex, 10); - if (isNaN(i)) { - throw new Error(`getStructureVarCalc() : erreur d'analyse de ${sVarCalc} (${sIndex} n'est pas un nombre)`); - } - return { index: i, prm: sPrm }; - } - /** * Calcul du paramètre d'un des ouvrages en parallèle * @param sVC Index de l'ouvrage et paramètre à calculer * @param rInit Valeur initiale */ - protected CalcStructPrm(sVC: IStructureVarCalc, rInit?: number): Result { + protected CalcStructPrm(index: number, symbol: string, rInit?: number): Result { // Le débit restant sur la structure en calcul est : - this._structures[sVC.index].prms.Q.setValue(this.prms.Q.v - this.CalcQ(sVC.index).vCalc); + this._structures[index].prms.Q.setValue(this.prms.Q.v - this.CalcQ(index).vCalc); // Calcul du paramètre de la structure en calcul - return this._structures[sVC.index].Calc(sVC.prm, rInit); - } - - /** - * Renvoie le n° de structure et le paramètre à calculer - * @param sVarCalc Nom du paramètre à calculer : "ouvrage[n].X" avec "n" l'index de l'ouvrage et "X" son paramètre - */ - private getStructureVarCalc2(sVarCalc: string): IStructureVarCalc { - const re = /([A-Z,a-z]+)\[(\d+)\]\.(.+)/; - const match = re.exec(sVarCalc); - if (match === null || match[1] !== "ouvrage") { - throw new Error( - `getStructureVarCalc2() : erreur d'analyse de ${sVarCalc}, (pas de la forme ouvrage[n].X)` - ); - } - return { index: +match[2], prm: match[3] }; + return this._structures[index].Calc(symbol, rInit); } } diff --git a/src/structure/structure.ts b/src/structure/structure.ts index e7062aa4..f19bca59 100644 --- a/src/structure/structure.ts +++ b/src/structure/structure.ts @@ -1,8 +1,8 @@ import { Nub } from "../nub"; import { ParamCalculability, ParamDefinition, ParamFamily } from "../param/param-definition"; +import { ParamValueMode } from "../param/param-value-mode"; import { Message, MessageCode } from "../util/message"; import { Result } from "../util/result"; -import { LinkedValue } from "../value_ref/object_ref"; import { ParallelStructure } from "./parallel_structure"; import { StructureParams } from "./structure_params"; @@ -71,6 +71,10 @@ export abstract class Structure extends Nub { constructor(prms: StructureParams, dbg: boolean = false) { super(prms, dbg); this._isZDVcalculable = true; + // Q is always the only calculated variable; setting another parameter + // of a Structure to CALC mode makes it the calculated variable of the + // *parent* ParallelStructures + this.prms.Q.valueMode = ParamValueMode.CALCUL; } get isZDVcalculable(): boolean { -- GitLab