diff --git a/spec/value_ref/value_ref_variable_extraresult.spec.ts b/spec/value_ref/value_ref_variable_extraresult.spec.ts index 4181371846363a2fe1f32b669a41db192231bb10..384e8270717a4407e7fa1dac6ceea45c26f3a3fd 100644 --- a/spec/value_ref/value_ref_variable_extraresult.spec.ts +++ b/spec/value_ref/value_ref_variable_extraresult.spec.ts @@ -1,5 +1,5 @@ // tslint:disable-next-line:max-line-length -import { CourbeRemous, CourbeRemousParams, cSnRectang, MethodeResolution, ParamsSectionRectang, Result } from "../../src"; +import { CourbeRemous, CourbeRemousParams, cSnRectang, MethodeResolution, ParamsSectionRectang, Result, ParamDefinition, ParamDomain, ParamDomainValue } from "../../src"; /** * IMPORTANT ! @@ -47,10 +47,11 @@ describe("référence d'un paramètre à un résultat complémentaire multivalu 0.9962500000000004, 0.9970000000000003, 0.9977500000000002, 0.9985000000000002, 0.9992500000000001, 1]; - const vs = rem.getLinkableValues("flu"); + const fakeParamDef = new ParamDefinition(undefined, "flu", ParamDomainValue.ANY); + const vs = rem.getLinkableValues(fakeParamDef); expect(Object.keys(vs).length).toEqual(1); - const vs2 = vs[0].value; + const vs2 = vs[0].element; expect(vs2.name).toEqual("flu"); let i = 0; diff --git a/src/compute-node.ts b/src/compute-node.ts index ee8892db68a2b8ffaec6a560634b187eb1a26ccb..28fa7eccbd0bd61a0ec0008ace18fb8c75d26b55 100644 --- a/src/compute-node.ts +++ b/src/compute-node.ts @@ -36,8 +36,17 @@ export enum ComputeNodeType { * noeud de calcul */ export abstract class ComputeNode extends JalhydObject implements IDebug { + /** + * Set of ParamDefinition, used as input of this node + */ protected _prms: ParamsEquation; + /** + * { symbol => ParamFamily } map for ExtraResults; defines a priori which + * future extra result can be linked to other Nub's parameters + */ + protected _extraResultsFamilies: any; + private _debug: Debug; constructor(prms: ParamsEquation, dbg: boolean = false) { @@ -55,13 +64,17 @@ export abstract class ComputeNode extends JalhydObject implements IDebug { this._prms.Pr.calculability = ParamCalculability.FREE; this.setParametersCalculability(); this._prms.DefineCalculability(); + this.setExtraResultsFamilies(); } public get prms(): ParamsEquation { return this._prms; } - /** Retrieves a parameter from its symbol (unique in a given Nub) */ + /** + * Retrieves a parameter from its symbol (unique in a given Nub) + * @WARNING also retrieves **extra results** and returns them as ParamDefinition ! + */ public getParameter(name: string): ParamDefinition { for (const p of this.parameterIterator) { if (p.symbol === name) { @@ -93,6 +106,17 @@ export abstract class ComputeNode extends JalhydObject implements IDebug { return this._debug.DBG; } + /** + * Define ParamFamily (@see ParamDefinition) for extra results + */ + protected setExtraResultsFamilies() { + this._extraResultsFamilies = {}; + } + + public get extraResultsFamilies() { + return this._extraResultsFamilies; + } + protected abstract setParametersCalculability(): void; } diff --git a/src/cond_distri.ts b/src/cond_distri.ts index 6ad742b7fd67e9680f2b87baca753fa39e131dc2..1b97c1bd95c9caa878d5899abd7b0ff0edd82068 100644 --- a/src/cond_distri.ts +++ b/src/cond_distri.ts @@ -1,5 +1,5 @@ import { Nub } from "./nub"; -import { ParamCalculability, ParamDefinition } from "./param/param-definition"; +import { ParamCalculability, ParamDefinition, ParamFamily } from "./param/param-definition"; import { ParamDomainValue } from "./param/param-domain"; import { ParamsEquation } from "./param/params-equation"; import { Result } from "./util/result"; @@ -27,10 +27,10 @@ export class ConduiteDistribParams extends ParamsEquation { constructor(rQ: number, rD: number, rJ: number, rLg: number, rNu: number) { super(); - this.Q = new ParamDefinition(this, "Q", ParamDomainValue.POS, rQ); - this.D = new ParamDefinition(this, "D", ParamDomainValue.POS, rD); + this.Q = new ParamDefinition(this, "Q", ParamDomainValue.POS, rQ, ParamFamily.FLOWS); + this.D = new ParamDefinition(this, "D", ParamDomainValue.POS, rD, ParamFamily.DIAMETERS); this.J = new ParamDefinition(this, "J", ParamDomainValue.POS, rJ); - this.Lg = new ParamDefinition(this, "Lg", ParamDomainValue.POS, rLg); + this.Lg = new ParamDefinition(this, "Lg", ParamDomainValue.POS, rLg, ParamFamily.LENGTHS); this.Nu = new ParamDefinition(this, "Nu", ParamDomainValue.POS, rNu); this.addParamDefinition(this.Q); diff --git a/src/dichotomie.ts b/src/dichotomie.ts index 00ba788d772a92c2cb3b83774c032ead3d7f5353..b17acfe1bfd897b7f52ea572e4c3ff058034a1df 100644 --- a/src/dichotomie.ts +++ b/src/dichotomie.ts @@ -273,7 +273,7 @@ export class Dichotomie extends Debug { private getStartInterval(rTarget: number, rInit: number): any { this.debug("intervalle de départ"); - const prmDom: ParamDomain = this._paramX.getDomain(); + const prmDom: ParamDomain = this._paramX.domain; const step = 0.001; // const step = this.nub.prms.Pr.v; diff --git a/src/index.ts b/src/index.ts index 28bdee68b1a1d5c67df4234f8924f3c7ee880d1a..67bf8be63d14f736f14cafe00f5b81fe70bdb152 100644 --- a/src/index.ts +++ b/src/index.ts @@ -30,5 +30,6 @@ export * from "./structure/structure"; export * from "./structure/structure_params"; export * from "./structure/factory_structure"; export * from "./structure/structure_props"; +export * from "./value_ref/object_ref"; export * from "./jalhyd_object"; export * from "./date_revision"; diff --git a/src/jalhyd_object.ts b/src/jalhyd_object.ts index 398456e3b199a576d0f2f23cb1c3aa773dc2f515..0911cb24a6c2b5a2a997440feb173948bbfa86cd 100644 --- a/src/jalhyd_object.ts +++ b/src/jalhyd_object.ts @@ -1,3 +1,5 @@ +import { ParamFamily } from "./param/param-definition"; + export interface IJalhydObject { readonly uid: string; } @@ -6,6 +8,10 @@ export interface INamedObject extends IJalhydObject { readonly name: string; } +export interface IObjectWithFamily extends IJalhydObject { + readonly family: ParamFamily; +} + export abstract class JalhydObject implements IJalhydObject { public get uid(): string { diff --git a/src/lechaptcalmon.ts b/src/lechaptcalmon.ts index e003c54b6c2484ffde65134146e05234b73a24ad..a00363fce1eda374cd487a1f7de8ac0761d9b1d9 100644 --- a/src/lechaptcalmon.ts +++ b/src/lechaptcalmon.ts @@ -1,5 +1,5 @@ import { Nub } from "./nub"; -import { ParamCalculability, ParamDefinition } from "./param/param-definition"; +import { ParamCalculability, ParamDefinition, ParamFamily } from "./param/param-definition"; import { ParamDomainValue } from "./param/param-domain"; import { ParamsEquation } from "./param/params-equation"; import { Result } from "./util/result"; @@ -31,10 +31,10 @@ export class LechaptCalmonParams extends ParamsEquation { constructor(rQ: number, rD: number, rJ: number, rLg: number, rL: number, rM: number, rN: number) { super(); - this._Q = new ParamDefinition(this, "Q", ParamDomainValue.POS, rQ); - this._D = new ParamDefinition(this, "D", ParamDomainValue.POS, rD); + this._Q = new ParamDefinition(this, "Q", ParamDomainValue.POS, rQ, ParamFamily.FLOWS); + this._D = new ParamDefinition(this, "D", ParamDomainValue.POS, rD, ParamFamily.DIAMETERS); this._J = new ParamDefinition(this, "J", ParamDomainValue.POS, rJ); - this._Lg = new ParamDefinition(this, "Lg", ParamDomainValue.POS, rLg); + this._Lg = new ParamDefinition(this, "Lg", ParamDomainValue.POS, rLg, ParamFamily.LENGTHS); this._L = new ParamDefinition(this, "L", ParamDomainValue.POS, rL); this._M = new ParamDefinition(this, "M", ParamDomainValue.POS, rM); this._N = new ParamDefinition(this, "N", ParamDomainValue.POS, rN); diff --git a/src/macrorugo/macrorugo.ts b/src/macrorugo/macrorugo.ts index 3d26de1cfa7d065f2fcd6f944a97203e7bc800cb..97fa19e024cd59836f0c66d86e58606b26b08b95 100644 --- a/src/macrorugo/macrorugo.ts +++ b/src/macrorugo/macrorugo.ts @@ -1,5 +1,5 @@ import { Nub } from "../nub"; -import { ParamCalculability } from "../param/param-definition"; +import { ParamCalculability, ParamFamily } from "../param/param-definition"; import { ParamValueMode } from "../param/param-value-mode"; import { Result } from "../util/result"; import { MacrorugoParams } from "./macrorugo_params"; @@ -140,6 +140,13 @@ export class MacroRugo extends Nub { this.prms.Cd0.calculability = ParamCalculability.FREE; } + protected setExtraResultsFamilies() { + this._extraResultsFamilies = { + ZF2: ParamFamily.ELEVATIONS, + Q_GuideTech: ParamFamily.FLOWS + }; + } + /** * Equation from Cassan, L., Laurens, P., 2016. Design of emergent and submerged rock-ramp fish passes. * Knowledge & Management of Aquatic Ecosystems 45. diff --git a/src/macrorugo/macrorugo_params.ts b/src/macrorugo/macrorugo_params.ts index 4fbfc30dcbd30a9f09d8e86484890c15d482531d..016cee473a5d0a324c933a6a01db4d7db9b220db 100644 --- a/src/macrorugo/macrorugo_params.ts +++ b/src/macrorugo/macrorugo_params.ts @@ -1,4 +1,4 @@ -import { ParamDefinition } from "../param/param-definition"; +import { ParamDefinition, ParamFamily } from "../param/param-definition"; import { ParamDomainValue } from "../param/param-domain"; import { ParamsEquation } from "../param/params-equation"; @@ -56,22 +56,22 @@ export class MacrorugoParams extends ParamsEquation { rY: number, rRF: number, rCB: number, rPBD: number, rPBH: number, rCd0: number) { super(); - this._ZF1 = new ParamDefinition(this, "ZF1", ParamDomainValue.POS, rZF1); + this._ZF1 = new ParamDefinition(this, "ZF1", ParamDomainValue.POS, rZF1, ParamFamily.ELEVATIONS); this.addParamDefinition(this._ZF1); - this._L = new ParamDefinition(this, "L", ParamDomainValue.POS, rL); + this._L = new ParamDefinition(this, "L", ParamDomainValue.POS, rL, ParamFamily.LENGTHS); this.addParamDefinition(this._L); - this._B = new ParamDefinition(this, "B", ParamDomainValue.POS, rB); + this._B = new ParamDefinition(this, "B", ParamDomainValue.POS, rB, ParamFamily.WIDTHS); this.addParamDefinition(this._B); - this._If = new ParamDefinition(this, "If", ParamDomainValue.POS, rIf); + this._If = new ParamDefinition(this, "If", ParamDomainValue.POS, rIf, ParamFamily.SLOPES); this.addParamDefinition(this._If); - this._Q = new ParamDefinition(this, "Q", ParamDomainValue.POS, rQ); + this._Q = new ParamDefinition(this, "Q", ParamDomainValue.POS, rQ, ParamFamily.FLOWS); this.addParamDefinition(this._Q); - this._Y = new ParamDefinition(this, "Y", ParamDomainValue.POS, rY); + this._Y = new ParamDefinition(this, "Y", ParamDomainValue.POS, rY, ParamFamily.HEIGHTS); this.addParamDefinition(this._Y); this._Ks = new ParamDefinition(this, "Ks", ParamDomainValue.POS_NULL, rRF); @@ -80,10 +80,10 @@ export class MacrorugoParams extends ParamsEquation { this._C = new ParamDefinition(this, "C", ParamDomainValue.POS, rCB); this.addParamDefinition(this._C); - this._PBD = new ParamDefinition(this, "PBD", ParamDomainValue.POS, rPBD); + this._PBD = new ParamDefinition(this, "PBD", ParamDomainValue.POS, rPBD, ParamFamily.DIAMETERS); this.addParamDefinition(this._PBD); - this._PBH = new ParamDefinition(this, "PBH", ParamDomainValue.POS, rPBH); + this._PBH = new ParamDefinition(this, "PBH", ParamDomainValue.POS, rPBH, ParamFamily.HEIGHTS); this.addParamDefinition(this._PBH); this._Cd0 = new ParamDefinition(this, "Cd0", ParamDomainValue.POS, rCd0); diff --git a/src/nub.ts b/src/nub.ts index cb4ba15fe6ed65dbaffd8c9bdf32f26bd95ad7ad..4fc141821d7e013ec1b78bcc30831d7eb82f9a6f 100644 --- a/src/nub.ts +++ b/src/nub.ts @@ -1,18 +1,17 @@ import { ParamDefinition, Session } from "."; import { ComputeNode } from "./compute-node"; import { Dichotomie } from "./dichotomie"; -import { INamedIterableValues, INumberIterator, IterableValues } from "./param/param-value-iterator"; +import { INamedIterableValues, IterableValues } from "./param/param-value-iterator"; import { ParamValueMode } from "./param/param-value-mode"; -import { ParamValues } from "./param/param-values"; import { Props } from "./props"; import { Result } from "./util/result"; -import { IReferencedNub } from "./value_ref/object_ref"; +import { LinkedValue } from "./value_ref/object_ref"; /** * Classe abstraite de Noeud de calcul dans une session : * classe de base pour tous les calculs */ -export abstract class Nub extends ComputeNode implements IReferencedNub { +export abstract class Nub extends ComputeNode { /** paramétrage de la dichotomie */ public dichoStartIntervalMaxSteps: number = 100; @@ -77,6 +76,18 @@ export abstract class Nub extends ComputeNode implements IReferencedNub { return res; } + /** + * Returns the parameter set to CALC mode, if any + */ + public getComputedParam(): ParamDefinition { + for (const p of this._prms) { + if (p.valueMode === ParamValueMode.CALCUL) { + return p; + } + } + return undefined; + } + /** * effectue une série de calculs sur un paramètre * @param rInit solution approximative du paramètre @@ -99,6 +110,7 @@ export abstract class Nub extends ComputeNode implements IReferencedNub { } } + // checks which values are variating, if any switch (p.valueMode) { case ParamValueMode.SINGLE: break; @@ -110,14 +122,23 @@ export abstract class Nub extends ComputeNode implements IReferencedNub { case ParamValueMode.CALCUL: // Le paramètre lié est un résultat de calcul - if (p.isReferenceDefined && p.referencedResult.nbResultElements > 1) { + // @TODO check this (check ultimate target param value mode ?) + // @TODO WTF comment un mode CALCUL peut-il avoir une référence ?? + if ( + p.isReferenceDefined() + && p.referencedValue.isResult() + && (p.referencedValue.element as Result).nbResultElements > 1 + ) { variatedValues = this.setVariatedValues(p, variatedValues); } break; case ParamValueMode.LINK: - const ro = p.referencedObject; - if (ro !== undefined && ro.hasMultipleValues) { + if ( + p.isReferenceDefined() + && p.referencedValue.isResult() + && (p.referencedValue.element as Result).nbResultElements > 1 + ) { variatedValues = this.setVariatedValues(p, variatedValues); } break; @@ -181,123 +202,96 @@ export abstract class Nub extends ComputeNode implements IReferencedNub { return p.v; } - // interface IReferencedNub - - public getReferencedParamValues(desc: string): ParamValues { - const prm = this.getParameter(desc); - if (prm !== undefined) { - return prm.paramValues; - } - return undefined; - } - - public getReferencedResult(desc?: string): Result { - if (desc === undefined || (this._result !== undefined && this._result.name === desc)) { - return this._result; - } - - // il y a des valeurs par défaut pour la précision et la valeur initiale, - // mais il faudra prévoir un mécanisme pour les transmettre - return this.CalcSerie(0.1, desc); - } - - public getReferencedExtraResult(desc: string): any { - const tmp: string[] = desc.split("."); - const r: Result = this.getReferencedResult(tmp[0]); - return r.getExtraResult(tmp[1]); - } - - public getReferencedValuesIterator(desc: string): INumberIterator { - const ro = this.getReferencedObject(desc); - return ro.valuesIterator; - } - - public getReferencedObject(desc: string): INamedIterableValues { - const tmp = desc.split("."); - - if (tmp.length === 1) { - // paramètre (ex "Q") - return this.getParameter(desc); - } + /** + * Liste des valeurs (paramètre, résultat, résultat complémentaire) liables à un paramètre + * @param src paramètre auquel lier d'autres valeurs + * @param excludeResult true si on veut exclure des valeurs retournées le résultat/résultat complémentaire + * correspondant à la clé de recherche + */ + public getLinkableValues(src: ParamDefinition): LinkedValue[] { + const res: LinkedValue[] = []; + const symbol = src.symbol; + + // if parameter comes from the same Nub, no linking is possible at all; + // different Structures in the same parent are different Nubs so they + // can get linked to each other + if (src.nubUid !== this.uid) { + + // 1. parameters + for (const p of this._prms) { + // if symbol and Nub type are identical, or if family is identical + if ( + (p.symbol === symbol && this.calcType === src.nubCalcType) + || (p.family !== undefined && (p.family === src.family)) + ) { + // a calculated parameter cannot be a link target; instead, its future result + // will be targeted (@see machanism in LinkedValue) + if (p.valueMode === ParamValueMode.CALCUL) { + // beware of circular dependencies ! + if (! this.resultDependsOnNub(src.nubUid)) { + res.push(new LinkedValue(this, p, p.symbol)); + } + } else { + // beware of circular dependencies ! + if (p.valueMode !== ParamValueMode.LINK || ! p.dependsOnParameter(src)) { + res.push(new LinkedValue(this, p, p.symbol)); + } + } + } + } - if (tmp[1] === "") { - // résultat (ex "Q.") - if (this._result !== undefined) { - return this._result; + // 2. extra results + if (this._extraResultsFamilies) { + // beware of circular dependencies ! + if (! this.resultDependsOnNub(src.nubUid)) { + const erk = Object.keys(this._extraResultsFamilies); + for (const erSymbol of erk) { + const erFamily = this._extraResultsFamilies[erSymbol]; + // if family is identical + if (erFamily === src.family) { + res.push(new LinkedValue(this, undefined, erSymbol)); + } + } + } } } - // les autres objets référençables n'implémentant pas IJalhydObject... - return undefined; + return res; } /** - * liste des valeurs (paramètre, résultat, résultat complémentaire) liables à un paramètre - * @param src objet qui sert de clé de recherche des paramètres liables, de type INamedObject | string - * @param excludeResult true si on veut exclure des valeurs retournées le résultat/résultat complémentaire - * correspondant à la clé de recherche - * @returns tableau d'objets de la forme { "name":string, "value":INamedIterableValues, "nub":Nub}, - * nub=Nub d'origine de la "value" - * - * l'étiquette "name" (cf. INubReference.defineReference) est de la forme <n | ouvrage[n] | N1>[.[N2]] - * n : indice de de l'ouvrage dans le cas des ouvrages parallèles - * N1 : un nom de paramètre/résultat (dans le cas d'un résultat, il est suivi d'un point) - * N2 : nom de résultat complémentaire (optionnel) - * ex : - * Q, Z1 (paramètres) - * J. (résultat) - * .Yf (résultat complémentaire du résultat courant) - * Q.Yf (résultat complémentaire du résultat nommé "Q") - * 0.Q : paramètre Q du 1er ouvrage (ouvrages parallèles) - * ouvrage[1].Q_Mode : résultat complémentaire du 2ème ouvrage (ouvrages parallèles) + * Returns true if the computation of the current Nub requires, directly + * or not, anything (parameter or result) from the given Nub UID "uid" + * (to prevent circular linking) + * @param uid */ - public getLinkableValues(src: any, prefix?: string, excludeResult: boolean = false): any[] { - const res: any[] = []; - - const isStr = typeof (src) === "string"; - const name = isStr ? src : src.name; - const hasUid = isStr ? false : "uid" in src; - - // paramètres + public resultDependsOnNub(uid: string): boolean { + // does any of our parameters depend on the target Nub ? for (const p of this._prms) { - // pour éviter d'ajouter le paramètre d'entrée dans le tableau résultat - const cond = hasUid ? p.uid !== src.uid : true; - if (cond) { - switch (p.valueMode) { - case ParamValueMode.SINGLE: - case ParamValueMode.MINMAX: - case ParamValueMode.LISTE: - switch (name) { - case "Z1": - case "Z2": - if (p.symbol === "Z1" || p.symbol === "Z2") { - res.push({ name: this.addPrefix(p.symbol, prefix), value: p, nub: this }); - } - break; - - default: - if (p.symbol === name) { - res.push({ name: this.addPrefix(p.symbol, prefix), value: p, nub: this }); - } - } + if (p.valueMode === ParamValueMode.LINK) { + if (p.dependsOnNub(uid)) { + return true; } } } + return false; + } - // résultat - if (this._result !== undefined && !excludeResult) { - if (this._result.name === name) { - res.push({ name: this.addPrefix(`${name}.`, prefix), value: this._result, nub: this }); - } - - // résultats complémentaires - const erIter = this._result.getIterableExtraResults(name); - if (erIter !== undefined) { - res.push({ name: this.addPrefix(`${this._result.name}.${name}`, prefix), value: erIter, nub: this }); + /** + * Returns true if the computation of the current Nub has multiple values + * (whether it is already computed or not), by detecting if any parameter, + * linked or not, is variated + */ + public resultHasMultipleValues(): boolean { + for (const p of this._prms) { + if (p.valueMode === ParamValueMode.MINMAX || p.valueMode === ParamValueMode.LISTE) { + return true; + } else if (p.valueMode === ParamValueMode.LINK) { + // indirect recursivity + return p.referencedValue.hasMultipleValues(); } } - - return res; + return false; } /** @@ -413,10 +407,9 @@ export abstract class Nub extends ComputeNode implements IReferencedNub { return dicho.Dichotomie(target.v, rPrec, rInit); } - private addPrefix(str: string, prefix: string) { - return prefix === undefined ? str : `${prefix}${str}`; - } - + /** + * Sets the variated values and warns if there were already some + */ private setVariatedValues(newValues: INamedIterableValues, oldValues: IterableValues) { if (oldValues === undefined) { return newValues; diff --git a/src/pab/pab_dimension.ts b/src/pab/pab_dimension.ts index 40631cceebeb70cd92899d58d055d556b6eb9862..355f806a57e944256353b2e02c78f16f924c6eb2 100644 --- a/src/pab/pab_dimension.ts +++ b/src/pab/pab_dimension.ts @@ -1,5 +1,5 @@ import { Nub } from "../nub"; -import { ParamCalculability, ParamDefinition } from "../param/param-definition"; +import { ParamCalculability, ParamDefinition, ParamFamily } from "../param/param-definition"; import { ParamDomainValue } from "../param/param-domain"; import { ParamsEquation } from "../param/params-equation"; import { Result } from "../util/result"; @@ -21,10 +21,10 @@ export class PabDimensionParams extends ParamsEquation { constructor(rL: number, rW: number, rY: number, rV?: number) { super(); - this._L = new ParamDefinition(this, "L", ParamDomainValue.POS, rL); - this._W = new ParamDefinition(this, "W", ParamDomainValue.POS, rW); - this._Y = new ParamDefinition(this, "Y", ParamDomainValue.POS, rY); - this._V = new ParamDefinition(this, "V", ParamDomainValue.POS, rV); + this._L = new ParamDefinition(this, "L", ParamDomainValue.POS, rL, ParamFamily.LENGTHS); + this._W = new ParamDefinition(this, "W", ParamDomainValue.POS, rW, ParamFamily.WIDTHS); + this._Y = new ParamDefinition(this, "Y", ParamDomainValue.POS, rY, ParamFamily.HEIGHTS); + this._V = new ParamDefinition(this, "V", ParamDomainValue.POS, rV, ParamFamily.VOLUMES); this.addParamDefinition(this._L); this.addParamDefinition(this._W); diff --git a/src/pab/pab_puissance.ts b/src/pab/pab_puissance.ts index 5a397b63625f88c3085f3ab69fe5c03fafd914bc..e02dbc953cf1558d961cd98c99f9719cad3363bb 100644 --- a/src/pab/pab_puissance.ts +++ b/src/pab/pab_puissance.ts @@ -1,5 +1,5 @@ import { Nub } from "../nub"; -import { ParamCalculability, ParamDefinition } from "../param/param-definition"; +import { ParamCalculability, ParamDefinition, ParamFamily } from "../param/param-definition"; import { ParamDomainValue } from "../param/param-domain"; import { ParamsEquation } from "../param/params-equation"; import { Result } from "../util/result"; @@ -21,9 +21,9 @@ export class PabPuissanceParams extends ParamsEquation { constructor(rDH: number, rQ: number, rV: number, rPV?: number) { super(); - this._DH = new ParamDefinition(this, "DH", ParamDomainValue.POS, rDH); - this._Q = new ParamDefinition(this, "Q", ParamDomainValue.POS, rQ); - this._V = new ParamDefinition(this, "V", ParamDomainValue.POS, rV); + this._DH = new ParamDefinition(this, "DH", ParamDomainValue.POS, rDH, ParamFamily.HEIGHTS); + this._Q = new ParamDefinition(this, "Q", ParamDomainValue.POS, rQ, ParamFamily.FLOWS); + this._V = new ParamDefinition(this, "V", ParamDomainValue.POS, rV, ParamFamily.VOLUMES); this._PV = new ParamDefinition(this, "PV", ParamDomainValue.POS, rPV); this.addParamDefinition(this._DH); diff --git a/src/param/param-definition.ts b/src/param/param-definition.ts index ea4fdb8ea49b394988d97f31bfca518263921d6b..5c86b0dbbf906fd2bf7ae90ab5f29d6b26ba67ae 100644 --- a/src/param/param-definition.ts +++ b/src/param/param-definition.ts @@ -1,10 +1,9 @@ +import { CalculatorType } from "../compute-node"; +import { Nub } from "../nub"; import { Interval } from "../util/interval"; import { Message, MessageCode } from "../util/message"; - -import { IJalhydObject, JalhydObject } from "../jalhyd_object"; import { IObservable, Observable, Observer } from "../util/observer"; -import { Result } from "../util/result"; -import { INubReference, IReferencedNub } from "../value_ref/object_ref"; +import { LinkedValue } from "../value_ref/object_ref"; import { ParamDomain, ParamDomainValue } from "./param-domain"; import { INamedIterableValues, INumberIterator } from "./param-value-iterator"; import { ParamValueMode } from "./param-value-mode"; @@ -26,9 +25,25 @@ export enum ParamCalculability { } /** - * Paramètre avec symbole, domaine de définition, calculabilité + * Parameter family: defines linkability with other parameters/results + */ +export enum ParamFamily { + LENGTHS, // longueur + WIDTHS, // largeur + SLOPES, // pente + HEIGHTS, // profondeur, tirant d'eau, chute + ELEVATIONS, // cote + VOLUMES, + FLOWS, // débit + DIAMETERS, + // SPEEDS // vitesses, seulement des résultats +} + +/** + * Paramètre avec symbole, famille, domaine de définition, calculabilité, + * pointant éventuellement vers un autre paramètre / résultat */ -export class ParamDefinition implements INubReference, INamedIterableValues, IObservable { +export class ParamDefinition implements INamedIterableValues, IObservable { /** le paramètre doit-il être exposé (par ex: affiché par l'interface graphique) ? */ public visible: boolean = true; @@ -36,7 +51,8 @@ export class ParamDefinition implements INubReference, INamedIterableValues, IOb /** symbole */ private _symbol: string; - private _parent: ParamsEquation | JalhydObject; + /** related parameters groups; indirectly gives access to the Nub using this parameter */ + private _parent: ParamsEquation; /** domaine de définition */ private _domain: ParamDomain; @@ -47,17 +63,24 @@ export class ParamDefinition implements INubReference, INamedIterableValues, IOb /** valeur(s) prise(s) */ private _paramValues: ParamValues; + /** parameters family, for linking */ + private _family: ParamFamily; + + /** pointer to another Parameter / Result, in case of LINK mode */ + private _referencedValue: LinkedValue; + /** implémentation par délégation de IObservable */ private _observable: Observable; - constructor(parent: ParamsEquation | JalhydObject, symb: string, d: ParamDomain | ParamDomainValue, - val?: number, visible: boolean = true) { + constructor(parent: ParamsEquation, symb: string, d: ParamDomain | ParamDomainValue, + val?: number, family?: ParamFamily, visible: boolean = true) { this._parent = parent; this._symbol = symb; this._observable = new Observable(); this._paramValues = new ParamValues(); this._paramValues.setSingleValue(val); this._calc = ParamCalculability.FREE; + this._family = family; this.visible = visible; if (d instanceof ParamDomain) { @@ -72,7 +95,7 @@ export class ParamDefinition implements INubReference, INamedIterableValues, IOb /** * set parent a-posteriori; used by nghyd when populating forms */ - set parent(parent: ParamsEquation | JalhydObject) { + set parent(parent: ParamsEquation) { this._parent = parent; } @@ -82,23 +105,44 @@ export class ParamDefinition implements INubReference, INamedIterableValues, IOb * ex: 123_Q */ get uid(): string { + return this.nubUid + "_" + this._symbol; + } + + /** + * Identifiant unique du Nub parent + */ + get nubUid(): string { let parentUid: string = null; - if (this._parent instanceof JalhydObject) { - parentUid = String(this._parent.uid); - } else if (this._parent instanceof ParamsEquation) { + if (this._parent) { // uid du ComputeNode utilisant le ParamsEquation parentUid = String(this._parent.nubUid); } else { - throw new Error("ParamDefinition.uid : parameter has no parent !"); + throw new Error("ParamDefinition.nubUid : parameter has no parent !"); + } + return parentUid; + } + + /** + * Type de modult du Nub parent + */ + get nubCalcType(): CalculatorType { + let parentCalcType: CalculatorType; + if (this._parent) { + // uid du ComputeNode utilisant le ParamsEquation + if (this._parent.parent instanceof Nub) { + parentCalcType = this._parent.parent.calcType; + } + } else { + throw new Error("ParamDefinition.nubCalcType : parameter has no parent !"); } - return parentUid + "_" + this._symbol; + return parentCalcType; } get symbol(): string { return this._symbol; } - public getDomain(): ParamDomain { + public get domain(): ParamDomain { return this._domain; } @@ -106,16 +150,27 @@ export class ParamDefinition implements INubReference, INamedIterableValues, IOb return this._domain.interval; } + /** + * Current values set associated to this parameter; might + * be a targetted set of values, if parameter is in LINK mode + */ public get paramValues(): ParamValues { - if (this.isReferenceDefined) { - return this.referencedParamValues; + if (this._referencedValue) { + return this._referencedValue.getParamValues(); } return this._paramValues; } + public get referencedValue() { + return this._referencedValue; + } + + public get family() { + return this._family; + } + get calculability(): ParamCalculability { if (this._calc === undefined) { - // throw "value of parameter '" + this._symbol + "' calculability is not defined"; const e = new Message(MessageCode.ERROR_PARAMDEF_CALC_UNDEFINED); e.extraVar.symbol = this.symbol; throw e; @@ -128,34 +183,17 @@ export class ParamDefinition implements INubReference, INamedIterableValues, IOb this._calc = c; } - /** returns value or referenced value */ + /** + * Proxy to getValue() + */ get v(): number { - if (this.isReferenceDefined) { - const ro = this.referencedObject; - - if (ro instanceof ParamDefinition) { - switch (this.referencedParamValues.valueMode) { - case ParamValueMode.CALCUL: - const r = this.referencedResult; - if (r.nbResultElements === 1) { - return r.resultElement.vCalc; - } - throw new Error(`il n'y a pas exactement un ResultElement dans le Result "${r.name}"`); - - default: - return this.referencedParamValues.currentValue; - } - } else if (ro instanceof Result) { - return ro.currentValue; - } - - return this.referencedExtraResult; - } - return this.getValue(); } - /** set value, with calculability control */ + /** + * set value, with calculability control + * @TODO move calculability control to setValue() ? + */ set v(val: number) { if (this.calculability === ParamCalculability.NONE) { const e = new Message(MessageCode.ERROR_PARAMDEF_VALUE_FIXED); @@ -168,33 +206,55 @@ export class ParamDefinition implements INubReference, INamedIterableValues, IOb /** * gestion de la valeur */ - public get isDefined(): boolean { - return this._paramValues.isDefined; + return this.paramValues.isDefined; } public getValue(): number { - if (!this._paramValues.isDefined) { - const e = new Message(MessageCode.ERROR_PARAMDEF_VALUE_UNDEFINED); - e.extraVar.symbol = this.symbol; - throw e; + if (this.isReferenceDefined()) { + // transparent proxy to linked value + try { + /* console.log("---> get value reference proxy for", this.symbol, this.nubCalcType, + this.referencedValue.symbol, + this.referencedValue.element ? this.referencedValue.element.constructor.name : "walou"); */ + return this.referencedValue.getValue(); + } catch (e) { + // target value is not yet defined (generally because target is an extra result) + return undefined; + } + } else { + // current value from own values set + if (! this._paramValues.isDefined) { + const e = new Message(MessageCode.ERROR_PARAMDEF_VALUE_UNDEFINED); + e.extraVar.symbol = this.symbol; + throw e; + } + return this._paramValues.currentValue; } - - return this._paramValues.currentValue; } + // for INumberiterator interface public get currentValue(): number { return this.getValue(); } + /** + * Sets the current value of the parameter's own values set; + * should never be called when in LINK mode + * @param val + * @param sender + */ public setValue(val: number, sender?: any) { + if (this.valueMode === ParamValueMode.LINK) { + console.error("!! trying to set current value in LINK mode"); + } this.checkValue(val); this._paramValues.currentValue = val; this.notifyValueModified(sender); } public get uncheckedValue(): number { - return this._paramValues.uncheckedValue; + return this.paramValues.uncheckedValue; } public checkValue(v: number) { @@ -252,15 +312,15 @@ export class ParamDefinition implements INubReference, INamedIterableValues, IOb } public checkMin(min: number): boolean { - return this.isMinMaxDomainValid(min) && (min < this._paramValues.max); + return this.isMinMaxDomainValid(min) && (min < this.paramValues.max); } public checkMax(max: number): boolean { - return this.isMinMaxDomainValid(max) && (this._paramValues.min < max); + return this.isMinMaxDomainValid(max) && (this.paramValues.min < max); } public checkStep(step: number): boolean { - return this.isMinMaxValid && this._paramValues.stepRefValue.intervalHasValue(step); + return this.isMinMaxValid && this.paramValues.stepRefValue.intervalHasValue(step); } get isValueValid(): boolean { @@ -274,24 +334,24 @@ export class ParamDefinition implements INubReference, INamedIterableValues, IOb } get isMinMaxValid(): boolean { - return this.checkMinMax(this._paramValues.min, this._paramValues.max); + return this.checkMinMax(this.paramValues.min, this.paramValues.max); } public get isRangeValid(): boolean { - switch (this._paramValues.valueMode) { + switch (this.valueMode) { case ParamValueMode.LISTE: return this.isListValid; case ParamValueMode.MINMAX: - return this.checkStep(this._paramValues.step); + return this.checkStep(this.paramValues.step); } // tslint:disable-next-line:max-line-length - throw new Error(`"ParamDefinition.isRangeValid() : valeur ${ParamValueMode[this._paramValues.valueMode]} de ParamValueMode non prise en compte`); + throw new Error(`"ParamDefinition.isRangeValid() : valeur ${ParamValueMode[this.valueMode]} de ParamValueMode non prise en compte`); } public get isValid() { - switch (this._paramValues.valueMode) { + switch (this.valueMode) { case ParamValueMode.SINGLE: return this.isValueValid; @@ -303,10 +363,9 @@ export class ParamDefinition implements INubReference, INamedIterableValues, IOb return true; case ParamValueMode.LINK: - if (!this.isReferenceDefined) { + if (! this._referencedValue) { return false; } - try { for (const v of this.valuesIterator) { this.checkValue(v); @@ -319,7 +378,7 @@ export class ParamDefinition implements INubReference, INamedIterableValues, IOb throw new Error( // tslint:disable-next-line:max-line-length - `ParamDefinition.isValid() : valeur de ParamValueMode '${ParamValueMode[this._paramValues.valueMode]}' non prise en charge` + `ParamDefinition.isValid() : valeur de ParamValueMode '${ParamValueMode[this.valueMode]}' non prise en charge` ); } @@ -331,6 +390,73 @@ export class ParamDefinition implements INubReference, INamedIterableValues, IOb this._paramValues.valueMode = m; } + /** + * If parameter mode is LINK, returns the value mode of the ultimately + * targetted parameter, else returns its own value mode; if targetted + * value is a result, returns undefined + */ + /* public get finalValueMode(): ParamValueMode { + if (this.valueMode === ParamValueMode.LINK && this.isReferenceDefined()) { + if (this._referencedValue.isParameter()) { + return (this._referencedValue.value as ParamDefinition).finalValueMode; + } else { + return undefined; + } + } else { + return this.valueMode; + } + } */ + + /** + * Sets the current parameter to LINK mode, pointing to the given + * symbol (might be a Parameter (computed or not) or an ExtraResult) + * of the given Nub + * + * Prefer @see defineReferenceFromLinkedValue() whenever possible + * + * @param nub + * @param symbol + */ + public defineReference(nub: Nub, symbol: string) { + // clear current reference + this.undefineReference(); + // find what the symbol points to + if (nub) { + // 1. extra result ? + // - start here to avoid extra results being presented as + // parameters by the iterator internally used by nub.getParameter() + // - extra results with no family are not linkable + if (Object.keys(nub.extraResultsFamilies).includes(symbol)) { + this._referencedValue = new LinkedValue(nub, undefined, symbol); + } else { + // 2. is it a parameter (possibly in CALC mode) ? + const p = nub.getParameter(symbol); + if (p) { + this._referencedValue = new LinkedValue(nub, p, symbol); + } + } + } + if (this._referencedValue) { + // set value mode + this.valueMode = ParamValueMode.LINK; + } else { + throw new Error(`defineReference - could not find target for ${nub.uid}.${symbol}`); + } + } + + public defineReferenceFromLinkedValue(target: LinkedValue) { + this._referencedValue = target; + this.valueMode = ParamValueMode.LINK; + } + + public undefineReference() { + this._referencedValue = undefined; + } + + public isReferenceDefined(): boolean { + return (this._referencedValue !== undefined); + } + /** * Returns an object representation of the Parameter's current state */ @@ -357,78 +483,90 @@ export class ParamDefinition implements INubReference, INamedIterableValues, IOb break; case ParamValueMode.LINK: - paramRep.targetNub = (this.referencedNub as any).uid; - paramRep.targetParam = this.referenceDefinition; + paramRep.targetNub = this._referencedValue.nub.uid; + paramRep.targetParam = this._referencedValue.symbol; break; } return paramRep; } - // interface INubReference - - public defineReference(target: IReferencedNub, desc: string) { - const oldDef = this._paramValues.referenceDefinition; - const oldTarget = this._paramValues.referencedNub; - try { - this._paramValues.defineReference(target, desc); - this.checkReferenceCircularity(this, []); - } catch (e) { - this._paramValues.defineReference(oldTarget, oldDef); - throw e; + /** + * Returns true if the current parameter is linked, directly or not, + * to the given parameter "p" (to prevent circular linking) + * @param p + */ + public dependsOnParameter(p: ParamDefinition): boolean { + let linked = false; + if (this.valueMode === ParamValueMode.LINK && this.isReferenceDefined()) { + const ref = this._referencedValue; + // direct reference ? + if (ref.nub.uid === p.nubUid && ref.symbol === p.symbol) { + linked = true; + } else { // indirect reference ? + if (ref.isParameter()) { + // recursive call to linked parameter + linked = (ref.element as ParamDefinition).dependsOnParameter(p); + } else if (ref.isResult() || ref.isExtraResult()) { + // must not be linked to a result of the candidate parameter's Nub + linked = (ref.nub.uid === p.nubUid); + } + } } + return linked; } - public undefineReference() { - this._paramValues.undefineReference(); - } - - get referenceDefinition(): string { - return this._paramValues.referenceDefinition; - } - - get referencedNub(): IReferencedNub { - return this._paramValues.referencedNub; - } - - get isReferenceDefined(): boolean { - return this._paramValues.isReferenceDefined; - } - - get referencedParamValues(): ParamValues { - return this._paramValues.referencedParamValues; - } - - get referencedResult(): Result { - return this._paramValues.referencedResult; - } - - get referencedExtraResult(): any { - return this._paramValues.referencedExtraResult; + /** + * Returns true if the current parameter is linked, directly or not, + * to the Nub having UID "uid" (to prevent circular linking) + * @param uid + */ + public dependsOnNub(uid: string): boolean { + let linked = false; + if (this.valueMode === ParamValueMode.LINK && this.isReferenceDefined()) { + const ref = this._referencedValue; + // direct reference ? + if (ref.nub.uid === uid) { + linked = true; + } else { // indirect reference ? + if (ref.isParameter()) { + // recursive call to linked parameter + linked = (ref.element as ParamDefinition).dependsOnNub(uid); + } + } + } + return linked; } - get referencedValuesIterator(): INumberIterator { - return this._paramValues.referencedValuesIterator; - } + // interface INamedIterableValues - get referencedObject(): INamedIterableValues { - return this._paramValues.referencedObject; + get name(): string { + return this._symbol; } - // interface INamedIterableValues - + /** + * Transparent proxy to own values iterator or targetted values iterator (in LINK mode) + */ public get valuesIterator(): INumberIterator { - if (this.isReferenceDefined) { - return this.referencedValuesIterator; + if (this._referencedValue) { + return this._referencedValue.getParamValues().valuesIterator; } return this._paramValues.valuesIterator; } + /** + * Returns true if there are more than 1 value associated to this parameter; + * might be its own values (MINMAX / LISTE mode), or targetted values (LINK mode) + */ public get hasMultipleValues(): boolean { - return this._paramValues.hasMultipleValues; - } - - public get name(): string { - return this._symbol; + if (this._referencedValue) { + return this._referencedValue.hasMultipleValues(); + } else { + if (this.valueMode === ParamValueMode.CALCUL) { + return (this._parent.parent as Nub).resultHasMultipleValues(); + } else { + return this._paramValues.hasMultipleValues; + } + } } public initValuesIterator(reverse: boolean = false): INumberIterator { @@ -479,7 +617,7 @@ export class ParamDefinition implements INubReference, INamedIterableValues, IOb public clone(): ParamDefinition { const res = new ParamDefinition(this._parent, this._symbol, - this.getDomain().clone(), this.uncheckedValue, this.visible); + this.domain.clone(), this.uncheckedValue, this._family, this.visible); res._calc = this._calc; return res; } @@ -500,15 +638,13 @@ export class ParamDefinition implements INubReference, INamedIterableValues, IOb if (v === undefined) { return false; } - - if (this._paramValues.valueMode === ParamValueMode.MINMAX) { + if (this.valueMode === ParamValueMode.MINMAX) { try { this.checkValue(v); } catch (e) { return false; } } - return true; } @@ -517,11 +653,11 @@ export class ParamDefinition implements INubReference, INamedIterableValues, IOb } private get isListValid(): boolean { - if (this._paramValues.valueList === undefined) { + if (this.paramValues.valueList === undefined) { return false; } - for (const v of this._paramValues.valueList) { + for (const v of this.paramValues.valueList) { try { this.checkValue(v); } catch (e) { @@ -531,27 +667,4 @@ export class ParamDefinition implements INubReference, INamedIterableValues, IOb return true; } - /** - * vérifie l'absence de référence circulaire - * @param seenUids liste des uids déjà vérifiés - * @param o objet à tester (son uid est il déjà dans la liste ?) - */ - private checkReferenceCircularity(o: any, seenUids: string[]) { - if ("uid" in o) { - if (seenUids.indexOf(o.uid) !== -1) { - throw new Error(`références circulaires détectées (uids : ${seenUids})`); - } - - seenUids.push(o.uid); - - if ("referencedObject" in o) { - const curr = o as INubReference; - const next = curr.referencedObject; - if (next !== undefined) { - this.checkReferenceCircularity(next as IJalhydObject, seenUids); - } - } - } - } - } diff --git a/src/param/param-value-iterator.ts b/src/param/param-value-iterator.ts index 9b233c5291ad625575f9d9ac8da9ab5c723dd533..7e245be877d29eca174038bafdf7f57fc65be815 100644 --- a/src/param/param-value-iterator.ts +++ b/src/param/param-value-iterator.ts @@ -1,4 +1,4 @@ -import { INamedObject } from "../jalhyd_object"; +import { INamedObject, IObjectWithFamily } from "../jalhyd_object"; import { ArrayReverseIterator } from "../util/iterator"; import { ParamValueMode } from "./param-value-mode"; import { ParamValues } from "./param-values"; @@ -47,7 +47,7 @@ export interface IterableValues extends INumberIterator { /** * objets pouvant avoir un nom et un itérateur sur une série de valeurs numériques */ -export interface INamedIterableValues extends INamedObject, IterableValues { +export interface INamedIterableValues extends INamedObject, IObjectWithFamily, IterableValues { } /** diff --git a/src/param/param-values.ts b/src/param/param-values.ts index 733d86553f085e48f9c22fefe9e28787e07431c0..e1c97a0e6b94c2956f5c7e5424e834843629f4c3 100644 --- a/src/param/param-values.ts +++ b/src/param/param-values.ts @@ -1,14 +1,13 @@ -import { Interval, Result } from ".."; -import { INubReference, IReferencedNub, NubReference } from "../value_ref/object_ref"; -import { INamedIterableValues, INumberIterator, IterableValues, ParamValueIterator } from "./param-value-iterator"; +import { Interval } from ".."; +import { INumberIterator, IterableValues, ParamValueIterator } from "./param-value-iterator"; import { ParamValueMode } from "./param-value-mode"; -export class ParamValues implements INubReference, IterableValues { - - /** - * implémentation par délégation de INubReference - */ - public _nubRef: NubReference; +/** + * Represents the value(s) taken by a Parameter, along with and depending on + * the value mode; linked values are not managed here, only the LINK value + * mode is defined here + */ +export class ParamValues implements IterableValues { /** * mode de génération des valeurs : min/max, liste, ... @@ -50,10 +49,6 @@ export class ParamValues implements INubReference, IterableValues { */ private _iterator: INumberIterator; - constructor() { - this._nubRef = new NubReference(); - } - public setValues(o: number | any, max?: number, step?: number) { if (typeof (o) === "number") { if (max === undefined) { @@ -126,9 +121,6 @@ export class ParamValues implements INubReference, IterableValues { * valeur courante */ public get currentValue(): number { - if (this.isReferenceDefined) { - return this._nubRef.referencedObject.currentValue; - } return this._currentValue; } @@ -140,9 +132,6 @@ export class ParamValues implements INubReference, IterableValues { * valeur dans le mode SINGLE */ public get singleValue(): number { - if (this.isReferenceDefined) { - return this._nubRef.referencedParamValues.singleValue; - } return this._singleValue; } @@ -165,9 +154,6 @@ export class ParamValues implements INubReference, IterableValues { case ParamValueMode.MINMAX: return this._minValue; - case ParamValueMode.LINK: - return this._nubRef.referencedParamValues.min; - default: this.checkValueMode(ParamValueMode.MINMAX); // pour générer une erreur return undefined; // pour le compilo @@ -184,9 +170,6 @@ export class ParamValues implements INubReference, IterableValues { case ParamValueMode.MINMAX: return this._maxValue; - case ParamValueMode.LINK: - return this._nubRef.referencedParamValues.max; - default: this.checkValueMode(ParamValueMode.MINMAX); return undefined; // pour le compilo @@ -208,9 +191,6 @@ export class ParamValues implements INubReference, IterableValues { case ParamValueMode.MINMAX: return this._stepValue; - case ParamValueMode.LINK: - return this._nubRef.referencedParamValues.step; - default: this.checkValueMode(ParamValueMode.MINMAX); // pour générer une erreur return undefined; // pour le compilo @@ -240,52 +220,6 @@ export class ParamValues implements INubReference, IterableValues { return new ParamValueIterator(this, reverse); } - // interface INubReference - - public defineReference(target: IReferencedNub, desc: string) { - this.valueMode = ParamValueMode.LINK; - this._nubRef.defineReference(target, desc); - } - - public undefineReference() { - this._nubRef.undefineReference(); - } - - public get referencedNub(): IReferencedNub { - return this._nubRef.referencedNub; - } - - public get referenceDefinition(): string { - return this._nubRef.referenceDefinition; - } - - public get isReferenceDefined(): boolean { - return this._valueMode === ParamValueMode.LINK && this._nubRef.isReferenceDefined; - } - - public get referencedParamValues(): ParamValues { - return this._nubRef.referencedParamValues; - } - - public get referencedResult(): Result { - return this._nubRef.referencedResult; - } - - public get referencedExtraResult(): any { - return this._nubRef.referencedExtraResult; - } - - public get referencedValuesIterator(): any { - return this._nubRef.referencedValuesIterator; - } - - public get referencedObject(): INamedIterableValues { - if (this.isReferenceDefined) { - return this._nubRef.referencedObject; - } - return undefined; - } - // interface IterableValues public get valuesIterator(): INumberIterator { @@ -293,28 +227,19 @@ export class ParamValues implements INubReference, IterableValues { } public get hasMultipleValues(): boolean { - let it; - if (this.isReferenceDefined) { - it = this.referencedValuesIterator; - } else { - // dans certains cas (mode LINK mais aucune valeur liable compatible), on ne peut avoir d'itérateur - if (this._valueMode !== ParamValueMode.LINK) { - it = this.getValuesIterator(); + const it = this.getValuesIterator(); + if (it) { + let n = 0; + for (const v of it) { + n++; + if (n > 1) { + break; + } } - } - - if (it === undefined) { + return n > 1; + } else { return false; } - - let n = 0; - for (const v of it) { - n++; - if (n > 1) { - break; - } - } - return n > 1; } public initValuesIterator(reverse: boolean = false): INumberIterator { @@ -324,10 +249,6 @@ export class ParamValues implements INubReference, IterableValues { this._iterator = this.getValuesIterator(reverse); break; - case ParamValueMode.LINK: - this._iterator = this.referencedObject.initValuesIterator(reverse); - break; - default: throw new Error(`ParamValues : mode de valeurs ${ParamValueMode[this._valueMode]} incorrect`); } @@ -348,13 +269,9 @@ export class ParamValues implements INubReference, IterableValues { */ public next(): IteratorResult<number> { let res; - if (this.isReferenceDefined) { - res = this.referencedObject.next(); - } else { - res = this._iterator.next(); - if (!res.done) { - this._currentValue = res.value; - } + res = this._iterator.next(); + if (!res.done) { + this._currentValue = res.value; } return res; } diff --git a/src/param/params-equation.ts b/src/param/params-equation.ts index d25392d64a84906b97cf766d44d0a3841de33119..ce3218aeca676abbfc62df551dea5fce7d98ff0d 100644 --- a/src/param/params-equation.ts +++ b/src/param/params-equation.ts @@ -1,7 +1,6 @@ -import { MapIterator } from "../util/iterator"; - import { ComputeNode } from "../compute-node"; -import { ParamCalculability, ParamDefinition } from "./param-definition"; +import { MapIterator } from "../util/iterator"; +import { ParamDefinition } from "./param-definition"; import { ParamDomainValue } from "./param-domain"; export interface IParamDefinitionIterator extends IterableIterator<ParamDefinition> { @@ -89,7 +88,10 @@ export abstract class ParamsEquation implements Iterable<ParamDefinition> { /** précision de calcul par défaut */ private static DEFAULT_COMPUTE_PREC = 0.0001; - /** pointeur vers la calculette qui utilise ces paramètres */ + /** + * Pointeur vers la calculette qui utilise ces paramètres; défini dans le constructeur + * du Nub en général, au moment où il reçoit les ParamsEquation + */ public parent: ComputeNode; protected _paramMap: { [key: string]: ParamDefinition } = {}; diff --git a/src/remous.ts b/src/remous.ts index 2432df05d7b411f5f1ede8c87865d2a273fd2f22..ffe33c4c55f8a2c62d9529c111f2031231ba56a6 100644 --- a/src/remous.ts +++ b/src/remous.ts @@ -2,7 +2,7 @@ import { ParamValues } from "."; import { round, XOR } from "./base"; import { Dichotomie } from "./dichotomie"; import { Nub } from "./nub"; -import { ParamCalculability, ParamDefinition } from "./param/param-definition"; +import { ParamCalculability, ParamDefinition, ParamFamily } from "./param/param-definition"; import { ParamDomainValue } from "./param/param-domain"; import { ParamsEquation } from "./param/params-equation"; import { acSection, ParamsSection } from "./section/section_type"; @@ -51,16 +51,22 @@ export class CourbeRemousParams extends ParamsEquation { constructor(s: acSection, rYamont: number, rYAval: number, rLong: number, rDx: number) { super(); this._section = s; - this._Yamont = new ParamDefinition(this, "Yamont", ParamDomainValue.POS, rYamont); - this._Yaval = new ParamDefinition(this, "Yaval", ParamDomainValue.POS, rYAval); - this._Long = new ParamDefinition(this, "Long", ParamDomainValue.POS, rLong); + this._Yamont = new ParamDefinition(this, "Yamont", ParamDomainValue.POS, rYamont, ParamFamily.HEIGHTS); + this._Yaval = new ParamDefinition(this, "Yaval", ParamDomainValue.POS, rYAval, ParamFamily.HEIGHTS); + this._Long = new ParamDefinition(this, "Long", ParamDomainValue.POS, rLong, ParamFamily.LENGTHS); this._Dx = new ParamDefinition(this, "Dx", ParamDomainValue.POS, rDx); this.addParamDefinition(this._Yamont); this.addParamDefinition(this._Yaval); this.addParamDefinition(this._Long); this.addParamDefinition(this._Dx); - this.addParamDefinitions(this._section.prms); + // merge parameters from "section" but change their parent ParamsEquation, so that the + // grand-parent Nub is Remous and not acSection (for linking) + for (const p of this._section.prms) { + p.parent = this; + this.addParamDefinition(p); + } + this.DefineCalculability(); // Pour ne pas remettre en undefined les prms de _section } @@ -507,6 +513,15 @@ export class CourbeRemous extends Nub { throw new Error("CourbeRemous.Equation() : parameter " + sVarCalc + " not allowed"); } + protected setExtraResultsFamilies() { + this._extraResultsFamilies = { + B: ParamFamily.WIDTHS, + Yf: ParamFamily.HEIGHTS, + Yt: ParamFamily.HEIGHTS, + Yco: ParamFamily.HEIGHTS + }; + } + private get Sn(): acSection { return this.prms.Sn; } diff --git a/src/section/section_circulaire.ts b/src/section/section_circulaire.ts index 0a0d9c90a8dc3c6d718f19192fd4cb6c9e379bee..0efae0855dd9f3e6eb62f09ea962cb7a8c415f5d 100644 --- a/src/section/section_circulaire.ts +++ b/src/section/section_circulaire.ts @@ -1,4 +1,4 @@ -import { ParamCalculability, ParamDefinition } from "../param/param-definition"; +import { ParamCalculability, ParamDefinition, ParamFamily } from "../param/param-definition"; import { ParamDomainValue } from "../param/param-domain"; import { Message, MessageCode } from "../util/message"; import { Result } from "../util/result"; @@ -9,7 +9,7 @@ export class ParamsSectionCirc extends ParamsSection { constructor(rD: number, rY: number, rKs: number, rQ: number, rIf: number, rYB: number) { super(rY, undefined, rKs, rQ, rIf, rYB); - this._D = new ParamDefinition(this, "D", ParamDomainValue.POS, rD); + this._D = new ParamDefinition(this, "D", ParamDomainValue.POS, rD, ParamFamily.DIAMETERS); this.addParamDefinition(this._D); // hide params diff --git a/src/section/section_parametree.ts b/src/section/section_parametree.ts index e19f134731f1c703b63933b91336a3fafd5a46f5..63f4c3d95a499dbadd9054291b34944492b29448 100644 --- a/src/section/section_parametree.ts +++ b/src/section/section_parametree.ts @@ -1,14 +1,19 @@ import { Nub } from "../nub"; -import { ParamCalculability, ParamDefinition } from "../param/param-definition"; +import { ParamCalculability, ParamDefinition, ParamFamily } from "../param/param-definition"; import { ParamDomain, ParamDomainValue } from "../param/param-domain"; import { ParamValueMode } from "../param/param-value-mode"; +import { ParamsEquation } from "../param/params-equation"; import { Result } from "../util/result"; import { ResultElement } from "../util/resultelement"; import { acSection } from "./section_type"; +// dummy ParamsEquation for code consistency +export class SectionParams extends ParamsEquation {} + /** * Nub sur les sections paramétrées */ +// tslint:disable-next-line:max-classes-per-file export class SectionParametree extends Nub { public get section(): acSection { @@ -153,6 +158,17 @@ export class SectionParametree extends Nub { // tslint:disable-next-line:no-empty protected setParametersCalculability(): void {} + protected setExtraResultsFamilies() { + this._extraResultsFamilies = { + B: ParamFamily.WIDTHS, + Yc: ParamFamily.HEIGHTS, + Yn: ParamFamily.HEIGHTS, + Yf: ParamFamily.HEIGHTS, + Yt: ParamFamily.HEIGHTS, + Yco: ParamFamily.HEIGHTS + }; + } + private initSectionVars() { this._sectionVars = {}; this.initSectionVar("Hs"); @@ -208,7 +224,8 @@ export class SectionParametree extends Nub { throw new Error(`SectionParametree.createSectionVar() : symbole ${symbol} non pris en charge`); } - const res = new ParamDefinition(this, symbol, dom); + const pe = new SectionParams(this); + const res = new ParamDefinition(pe, symbol, dom); res.calculability = ParamCalculability.EQUATION; return res; } diff --git a/src/section/section_trapez.ts b/src/section/section_trapez.ts index 7e5e085ab2612d89f59e2d73243853624f87adb2..789c93ea3a2a4b5217a0740ed6f92fdf892a540f 100644 --- a/src/section/section_trapez.ts +++ b/src/section/section_trapez.ts @@ -1,4 +1,4 @@ -import { ParamCalculability, ParamDefinition } from "../param/param-definition"; +import { ParamCalculability, ParamDefinition, ParamFamily } from "../param/param-definition"; import { ParamDomainValue } from "../param/param-domain"; import { Result } from "../util/result"; import { acSection, ParamsSection } from "./section_type"; @@ -11,7 +11,8 @@ export class ParamsSectionTrapez extends ParamsSection { rQ: number, rIf: number, rYB: number) { super(rY, undefined, rKs, rQ, rIf, rYB); - this._LargeurFond = new ParamDefinition(this, "LargeurFond", ParamDomainValue.POS_NULL, rLargeurFond); + this._LargeurFond = new ParamDefinition(this, "LargeurFond", ParamDomainValue.POS_NULL, + rLargeurFond, ParamFamily.WIDTHS); this._Fruit = new ParamDefinition(this, "Fruit", ParamDomainValue.POS_NULL, rFruit); this.addParamDefinition(this._LargeurFond); diff --git a/src/section/section_type.ts b/src/section/section_type.ts index ca74eaee7f429a8cf8433df5dfc18c9a48566e2e..9941393ee9447c90b80dc6072a0805b916277e28 100644 --- a/src/section/section_type.ts +++ b/src/section/section_type.ts @@ -1,5 +1,5 @@ import { ComputeNode } from "../compute-node"; -import { ParamCalculability, ParamDefinition } from "../param/param-definition"; +import { ParamCalculability, ParamDefinition, ParamFamily } from "../param/param-definition"; import { ParamDomainValue } from "../param/param-domain"; import { ParamsEquation } from "../param/params-equation"; import { Message, MessageCode } from "../util/message"; @@ -22,9 +22,9 @@ export abstract class cParamsCanal extends ParamsEquation { constructor(rKs: number, rQ: number, rIf: number, rYB: number) { super(); this._Ks = new ParamDefinition(this, "Ks", ParamDomainValue.POS, rKs); - this._Q = new ParamDefinition(this, "Q", ParamDomainValue.POS_NULL, rQ); - this._If = new ParamDefinition(this, "If", ParamDomainValue.ANY, rIf); - this._YB = new ParamDefinition(this, "YB", ParamDomainValue.POS, rYB); + this._Q = new ParamDefinition(this, "Q", ParamDomainValue.POS_NULL, rQ, ParamFamily.FLOWS); + this._If = new ParamDefinition(this, "If", ParamDomainValue.ANY, rIf, ParamFamily.SLOPES); + this._YB = new ParamDefinition(this, "YB", ParamDomainValue.POS, rYB, ParamFamily.HEIGHTS); this.addParamDefinition(this._Ks); this.addParamDefinition(this._Q); @@ -82,9 +82,9 @@ export abstract class ParamsSection extends cParamsCanal { rIf: number, rYB: number) { super(rKs, rQ, rIf, rYB); - this._Y = new ParamDefinition(this, "Y", ParamDomainValue.POS_NULL, rY); + this._Y = new ParamDefinition(this, "Y", ParamDomainValue.POS_NULL, rY, ParamFamily.HEIGHTS); this._LargeurBerge = new ParamDefinition( - this, "LargeurBerge", ParamDomainValue.POS_NULL, rLargeurBerge); + this, "LargeurBerge", ParamDomainValue.POS_NULL, rLargeurBerge, ParamFamily.WIDTHS); this.addParamDefinition(this._Y); this.addParamDefinition(this._LargeurBerge); diff --git a/src/session.ts b/src/session.ts index b17ff9439ffc3e87e6fa4291b7e88b75091df14f..621e1526e7aaa3f1fb1b94f6867dfe17ff67d27d 100644 --- a/src/session.ts +++ b/src/session.ts @@ -23,9 +23,11 @@ import { cSnTrapez, ParamsSectionTrapez } from "./section/section_trapez"; import { acSection } from "./section/section_type"; // Classes relatives aux structures +import { ParamDefinition } from "./param/param-definition"; import { CreateStructure } from "./structure/factory_structure"; import { Structure } from "./structure/structure"; import { LoiDebit, StructureType } from "./structure/structure_props"; +import { LinkedValue } from "./value_ref/object_ref"; export class Session { @@ -368,7 +370,21 @@ export class Session { } /** - * Creates a Nub from an object representation and adds it tot he current session; returns + * Returns a list of nub/symbol couples, that can be linked to the given + * parameter, amoung all current nubs + * @param p + */ + public getLinkableValues(p: ParamDefinition): LinkedValue[] { + let res: LinkedValue[] = []; + for (const n of this._nubs) { + const linkableValues = n.getLinkableValues(p); + res = res.concat(linkableValues); + } + return res; + } + + /** + * Creates a Nub from an object representation and adds it to the current session; returns * a pointer to the Nub and its JSON metadata * @param obj object representation of a single Nub */ diff --git a/src/structure/cloisons_params.ts b/src/structure/cloisons_params.ts index 5d3e378e0b836db59f28be6db0e325b7c42495f2..0d1e4aa66eba95a4171c3bfb82952a03e220f0ce 100644 --- a/src/structure/cloisons_params.ts +++ b/src/structure/cloisons_params.ts @@ -1,4 +1,4 @@ -import { ParamDefinition } from "../param/param-definition"; +import { ParamDefinition, ParamFamily } from "../param/param-definition"; import { ParamDomainValue } from "../param/param-domain"; import { ParallelStructureParams } from "./parallel_structure_params"; @@ -29,13 +29,13 @@ export class CloisonsParams extends ParallelStructureParams { */ constructor(rQ: number, rZ1: number, rLB: number, rBB: number, rPB: number, rDH: number) { super(rQ, rZ1, rZ1 - rDH); - this.LB = new ParamDefinition(this, "LB", ParamDomainValue.POS, rLB); + this.LB = new ParamDefinition(this, "LB", ParamDomainValue.POS, rLB, ParamFamily.LENGTHS); this.addParamDefinition(this.LB); - this.BB = new ParamDefinition(this, "BB", ParamDomainValue.POS, rBB); + this.BB = new ParamDefinition(this, "BB", ParamDomainValue.POS, rBB, ParamFamily.WIDTHS); this.addParamDefinition(this.BB); - this.PB = new ParamDefinition(this, "PB", ParamDomainValue.POS, rPB); + this.PB = new ParamDefinition(this, "PB", ParamDomainValue.POS, rPB, ParamFamily.HEIGHTS); this.addParamDefinition(this.PB); - this.DH = new ParamDefinition(this, "DH", ParamDomainValue.POS, rDH); + this.DH = new ParamDefinition(this, "DH", ParamDomainValue.POS, rDH, ParamFamily.HEIGHTS); this.addParamDefinition(this.DH); // hide Z2 this.Z2.visible = false; diff --git a/src/structure/dever.ts b/src/structure/dever.ts index 43199715635c19554344297e1a95467bbb3ccd7a..4af0244f17285ba418d5c9b052d8595158d625e4 100644 --- a/src/structure/dever.ts +++ b/src/structure/dever.ts @@ -1,4 +1,4 @@ -import { ParamCalculability } from "../param/param-definition"; +import { ParamCalculability, ParamFamily } from "../param/param-definition"; import { Result } from "../util/result"; import { DeverParams } from "./dever_params"; import { ParallelStructure } from "./parallel_structure"; @@ -95,6 +95,12 @@ export class Dever extends ParallelStructure { this.prms.Z2.calculability = ParamCalculability.NONE; } + protected setExtraResultsFamilies() { + this._extraResultsFamilies = { + CvQT: ParamFamily.FLOWS + }; + } + /** * Calcul de la somme des aires des ouvrages. * @note N.B. : doit être appelé après calcul si le calcul porte sur Z1 ou diff --git a/src/structure/dever_params.ts b/src/structure/dever_params.ts index a8a8a15e02b3c7aa27385c524ffb55eff70e929d..87b3509de30e7ce2a325b3e879d63fa48c478bd0 100644 --- a/src/structure/dever_params.ts +++ b/src/structure/dever_params.ts @@ -1,4 +1,4 @@ -import { ParamDefinition } from "../param/param-definition"; +import { ParamDefinition, ParamFamily } from "../param/param-definition"; import { ParamDomainValue } from "../param/param-domain"; import { ParallelStructureParams } from "./parallel_structure_params"; @@ -21,9 +21,9 @@ export class DeverParams extends ParallelStructureParams { */ constructor(rQ: number, rZ1: number, rBR: number, rZR: number) { super(rQ, rZ1, - Infinity); - this.BR = new ParamDefinition(this, "BR", ParamDomainValue.ANY, rBR); + this.BR = new ParamDefinition(this, "BR", ParamDomainValue.ANY, rBR, ParamFamily.WIDTHS); this.addParamDefinition(this.BR); - this.ZR = new ParamDefinition(this, "ZR", ParamDomainValue.ANY, rZR); + this.ZR = new ParamDefinition(this, "ZR", ParamDomainValue.ANY, rZR, ParamFamily.ELEVATIONS); this.addParamDefinition(this.ZR); // hide fields this.Z2.visible = false; diff --git a/src/structure/parallel_structure.ts b/src/structure/parallel_structure.ts index bfbc4067101ed83661cad2872117a416d7ea27a8..9ef6b309d665ac44ea99e27f7971860b8302c7d5 100644 --- a/src/structure/parallel_structure.ts +++ b/src/structure/parallel_structure.ts @@ -5,12 +5,11 @@ import { ParallelStructureParams } from "./parallel_structure_params"; import { Structure } from "./structure"; import { ParamDefinition } from "../param/param-definition"; -import { INamedIterableValues } from "../param/param-value-iterator"; -import { ParamValues } from "../param/param-values"; import { IParamDefinitionIterator, ParamsEquation, ParamsEquationArrayIterator } from "../param/params-equation"; import { Props } from "../props"; import { Session } from "../session"; +import { LinkedValue } from "../value_ref/object_ref"; import { loiAdmissiblesOuvrages, LoiDebit } from "./structure_props"; export { ParallelStructureParams }; @@ -142,8 +141,15 @@ export class ParallelStructure extends Nub { * @return true si la structure donnée est dans la liste */ public hasStructure(structure: Nub): boolean { + return this.hasStructureUid(structure.uid); + } + + /** + * @return true si la structure donnée est dans la liste + */ + public hasStructureUid(structureUid: string): boolean { for (const s of this._structures) { - if (s.uid === structure.uid) { + if (s.uid === structureUid) { return true; } } @@ -270,70 +276,46 @@ export class ParallelStructure extends Nub { return res; } - // interface IReferencedNub - public getReferencedObject(desc: string): INamedIterableValues { - try { - // analyse n.X - const i: IStructureVarCalc = this.getStructureVarCalc(desc); - return this._structures[i.index].getParameter(i.prm); - } catch (e) { - // desc n'est pas de la forme n.X - try { - // analyse ouvrage[n].X - const i: IStructureVarCalc = this.getStructureVarCalc2(desc); - const res = this._structures[i.index].result; - if (res === undefined) { - return undefined; // pas de résultat calculé - } - return res.getExtraResult(i.prm); - } catch (e) { - // desc n'est pas de la forme ouvrage[n].X - } - } - // pas de la forme n.X ou ouvrage[n].X ou erreur sur n ou X - return super.getReferencedObject(desc); - } - - public getReferencedParamValues(desc: string): ParamValues { - try { - const ro = this.getReferencedObject(desc); - if (ro instanceof ParamDefinition) { - return ro.paramValues; - } - return undefined; - } catch (e) { - // pas de la forme n.X ou ouvrage[n].X ou erreur sur n ou X - const param = this.getParameter(desc); - if (param === undefined) { - return undefined; - } - return param.paramValues; - } - } - - public getReferencedExtraResult(desc: string): any { - return this._result.getExtraResult(desc); - } - /** * liste des valeurs (paramètre, résultat, résultat complémentaire) liables à un paramètre - * @param src objet qui sert de clé de recherche des paramètres liables, de type INamedObject | string - * @returns tableau d'objets de la forme : - * { "name":string, "value":INamedIterableValues, "nub":Nub}, nub=Nub d'origine de la "value" + * @param src paramètre auquel lier d'autres valeurs */ - public getLinkableValues(src: any): any[] { - // paramètres liables de ce Nub - let res = super.getLinkableValues(src); - let i = 0; + public getLinkableValues(src: ParamDefinition): LinkedValue[] { + let res: LinkedValue[] = []; + // linabkle parameters of this Nub, unless src comes from a child Structure + if (! this.hasStructureUid(src.nubUid)) { + res = super.getLinkableValues(src); + } + // paramètres liables des Nub structures enfants for (const s of this._structures) { - // paramètres liables des Nub structures enfants - const childStructureLinkableParams = s.getLinkableValues(src, undefined, true); + const childStructureLinkableParams = s.getLinkableValues(src); res = res.concat(childStructureLinkableParams); - i++; } return res; } + /** + * Returns true if the computation of the current Nub requires, directly + * or not, anything (parameter or result) from the given Nub UID "uid"; + * includes checking child Structures if any + * (to prevent circular linking) + * @param uid + */ + public resultDependsOnNub(uid: string): boolean { + let depends = super.resultDependsOnNub(uid); + // does any of our child structures parameters depend on the target Nub ? + if (! depends) { + structuresloop: + for (const s of this.structures) { + if (s.resultDependsOnNub(uid)) { + depends = true; + break structuresloop; + } + } + } + return depends; + } + /** * Returns an object representation of the Nub's current state; compared to generic * Nub::objectRepresentation(), represents the parallel structures in a specific way diff --git a/src/structure/parallel_structure_params.ts b/src/structure/parallel_structure_params.ts index 6bcfd33e7e65936a92a0089eb9b6ea461690e0d5..b4d05f6bdb1a8cf8a4f167d8264ba9caac56986a 100644 --- a/src/structure/parallel_structure_params.ts +++ b/src/structure/parallel_structure_params.ts @@ -1,4 +1,4 @@ -import { ParamDefinition } from "../param/param-definition"; +import { ParamDefinition, ParamFamily } from "../param/param-definition"; import { ParamDomainValue } from "../param/param-domain"; import { ParamsEquation } from "../param/params-equation"; @@ -23,11 +23,11 @@ export class ParallelStructureParams extends ParamsEquation { */ constructor(rQ: number, rZ1: number, rZ2: number) { super(); - this.Q = new ParamDefinition(this, "Q", ParamDomainValue.ANY, rQ); + this.Q = new ParamDefinition(this, "Q", ParamDomainValue.ANY, rQ, ParamFamily.FLOWS); this.addParamDefinition(this.Q); - this.Z1 = new ParamDefinition(this, "Z1", ParamDomainValue.ANY, rZ1); + this.Z1 = new ParamDefinition(this, "Z1", ParamDomainValue.ANY, rZ1, ParamFamily.ELEVATIONS); this.addParamDefinition(this.Z1); - this.Z2 = new ParamDefinition(this, "Z2", ParamDomainValue.ANY, rZ2); + this.Z2 = new ParamDefinition(this, "Z2", ParamDomainValue.ANY, rZ2, ParamFamily.ELEVATIONS); this.addParamDefinition(this.Z2); } } diff --git a/src/structure/rectangular_structure_params.ts b/src/structure/rectangular_structure_params.ts index 1ffab8094b4975e9faaeb271ba4a98fcbebb5390..b7de51e6ba2042b920b05a2f7f13062d9e09864a 100644 --- a/src/structure/rectangular_structure_params.ts +++ b/src/structure/rectangular_structure_params.ts @@ -1,4 +1,4 @@ -import { ParamDefinition } from "../param/param-definition"; +import { ParamDefinition, ParamFamily } from "../param/param-definition"; import { ParamDomainValue } from "../param/param-domain"; import { StructureParams } from "./structure_params"; @@ -25,7 +25,7 @@ export class RectangularStructureParams extends StructureParams { */ constructor(rQ: number, rZDV: number, rZ1: number, rZ2: number, rL: number, rCd: number, rW: number = Infinity) { super(rQ, rZDV, rZ1, rZ2, rW); - this.L = new ParamDefinition(this, "L", ParamDomainValue.POS, rL); + this.L = new ParamDefinition(this, "L", ParamDomainValue.POS, rL, ParamFamily.WIDTHS); this.addParamDefinition(this.L); this.Cd = new ParamDefinition(this, "Cd", ParamDomainValue.POS, rCd); this.addParamDefinition(this.Cd); diff --git a/src/structure/structure.ts b/src/structure/structure.ts index 7a59fdbe58fc365565f1d150bdbfaa8829e57f41..c525d94890fb118a080d76d1dc7ae63d60e427a7 100644 --- a/src/structure/structure.ts +++ b/src/structure/structure.ts @@ -1,7 +1,8 @@ import { Nub } from "../nub"; -import { ParamCalculability } from "../param/param-definition"; +import { ParamCalculability, ParamDefinition, ParamFamily } from "../param/param-definition"; 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"; @@ -90,6 +91,15 @@ export abstract class Structure extends Nub { return this.parent.getIndexForStructure(this); } + public getLinkableValues(src: ParamDefinition): LinkedValue[] { + const res: LinkedValue[] = []; + // OK unless the source parameter belongs to this Structure's parent + if (this.parent.uid !== src.nubUid) { + return super.getLinkableValues(src); + } + return res; + } + /** * Calcul de l'aire d'écoulement sur le seuil ou dans l'orifice */ @@ -256,4 +266,10 @@ export abstract class Structure extends Nub { } } + protected setExtraResultsFamilies() { + this._extraResultsFamilies = { + Q: ParamFamily.FLOWS + }; + } + } diff --git a/src/structure/structure_kivi_params.ts b/src/structure/structure_kivi_params.ts index a690bd61ab73d6c8cc405d000d1f3daa59edabf9..9ab1cd4cff20b60d6ee5a8ce3dceb39ac656a92d 100644 --- a/src/structure/structure_kivi_params.ts +++ b/src/structure/structure_kivi_params.ts @@ -1,4 +1,4 @@ -import { ParamDefinition } from "../param/param-definition"; +import { ParamDefinition, ParamFamily } from "../param/param-definition"; import { ParamDomainValue } from "../param/param-domain"; import { StructureParams } from "./structure_params"; @@ -30,13 +30,13 @@ export class StructureKiviParams extends StructureParams { rZRAM: number ) { super(rQ, rZDV, rZ1, rZ2, Infinity); - this.L = new ParamDefinition(this, "L", ParamDomainValue.POS_NULL, rL); + this.L = new ParamDefinition(this, "L", ParamDomainValue.POS_NULL, rL, ParamFamily.WIDTHS); this.addParamDefinition(this.L); this.alpha = new ParamDefinition(this, "alpha", ParamDomainValue.POS, rAlpha); this.addParamDefinition(this.alpha); this.beta = new ParamDefinition(this, "beta", ParamDomainValue.POS_NULL, rBeta); this.addParamDefinition(this.beta); - this.ZRAM = new ParamDefinition(this, "ZRAM", ParamDomainValue.ANY, rZRAM); + this.ZRAM = new ParamDefinition(this, "ZRAM", ParamDomainValue.ANY, rZRAM, ParamFamily.ELEVATIONS); this.addParamDefinition(this.ZRAM); } } diff --git a/src/structure/structure_orifice_submerged_params.ts b/src/structure/structure_orifice_submerged_params.ts index 2c4ca25838a77d9533c808d1702bb9bbd260d2e2..68b0fc8ce2eef16034c0bcdc38eb38daaebd6a02 100644 --- a/src/structure/structure_orifice_submerged_params.ts +++ b/src/structure/structure_orifice_submerged_params.ts @@ -1,4 +1,4 @@ -import { ParamDefinition } from "../param/param-definition"; +import { ParamDefinition, ParamFamily } from "../param/param-definition"; import { ParamDomainValue } from "../param/param-domain"; import { StructureParams } from "../structure/structure_params"; diff --git a/src/structure/structure_params.ts b/src/structure/structure_params.ts index 3f3018c4c00d8f44a28cdda2e60f2c46ce505cf1..c70a06b90d616907c957a9cabbab1f41b0636565 100644 --- a/src/structure/structure_params.ts +++ b/src/structure/structure_params.ts @@ -1,5 +1,5 @@ import { Nub } from "../nub"; -import { ParamDefinition } from "../param/param-definition"; +import { ParamDefinition, ParamFamily } from "../param/param-definition"; import { ParamDomainValue } from "../param/param-domain"; import { ParamsEquation } from "../param/params-equation"; @@ -40,21 +40,21 @@ export class StructureParams extends ParamsEquation { */ constructor(rQ: number, rZDV: number, rZ1: number, rZ2: number, rW: number = Infinity) { super(); - this.Q = new ParamDefinition(this, "Q", ParamDomainValue.ANY, rQ, false); // hidden by default + this.Q = new ParamDefinition(this, "Q", ParamDomainValue.ANY, rQ, ParamFamily.FLOWS, false); this.addParamDefinition(this.Q); - this.ZDV = new ParamDefinition(this, "ZDV", ParamDomainValue.ANY, rZDV); + this.ZDV = new ParamDefinition(this, "ZDV", ParamDomainValue.ANY, rZDV, ParamFamily.ELEVATIONS); this.addParamDefinition(this.ZDV); - this.Z1 = new ParamDefinition(this, "Z1", ParamDomainValue.ANY, rZ1, false); // hidden by default + this.Z1 = new ParamDefinition(this, "Z1", ParamDomainValue.ANY, rZ1, ParamFamily.ELEVATIONS, false); this.addParamDefinition(this.Z1); - this.Z2 = new ParamDefinition(this, "Z2", ParamDomainValue.ANY, rZ2, false); // hidden by default + this.Z2 = new ParamDefinition(this, "Z2", ParamDomainValue.ANY, rZ2, ParamFamily.ELEVATIONS, false); this.addParamDefinition(this.Z2); this.h1 = new ParamDefinition(this, "h1", ParamDomainValue.POS_NULL, - Math.max(0, this.Z1.v - this.ZDV.v), false); // hidden by default + Math.max(0, this.Z1.v - this.ZDV.v), ParamFamily.HEIGHTS, false); this.addParamDefinition(this.h1); this.h2 = new ParamDefinition(this, "h2", ParamDomainValue.POS_NULL, - Math.max(0, this.Z2.v - this.ZDV.v), false); // hidden by default + Math.max(0, this.Z2.v - this.ZDV.v), ParamFamily.HEIGHTS, false); this.addParamDefinition(this.h2); - this.W = new ParamDefinition(this, "W", ParamDomainValue.POS_NULL, rW, false); // hidden by default + this.W = new ParamDefinition(this, "W", ParamDomainValue.POS_NULL, rW, ParamFamily.WIDTHS, false); this.addParamDefinition(this.W); // hide params this.Pr.visible = false; diff --git a/src/structure/structure_triangular_trunc_weir_free_params.ts b/src/structure/structure_triangular_trunc_weir_free_params.ts index 6226c35e0601a77c434efa529b8286df76ff1b9a..694f2b9db203e606ce38e9fa2bb292c6bda7f091 100644 --- a/src/structure/structure_triangular_trunc_weir_free_params.ts +++ b/src/structure/structure_triangular_trunc_weir_free_params.ts @@ -1,4 +1,4 @@ -import { ParamDefinition } from "../param/param-definition"; +import { ParamDefinition, ParamFamily } from "../param/param-definition"; import { ParamDomainValue } from "../param/param-domain"; import { StructureParams } from "./structure_params"; @@ -33,7 +33,7 @@ export class TriangularTruncStructureParams extends StructureParams { super(rQ, rZDV, rZ1, - Infinity, rW); this.BT = new ParamDefinition(this, "BT", ParamDomainValue.POS, rBT); this.addParamDefinition(this.BT); - this.ZT = new ParamDefinition(this, "ZT", ParamDomainValue.POS, rZT); + this.ZT = new ParamDefinition(this, "ZT", ParamDomainValue.POS, rZT, ParamFamily.ELEVATIONS); this.addParamDefinition(this.ZT); this.Cd = new ParamDefinition(this, "Cd", ParamDomainValue.POS, rCd); this.addParamDefinition(this.Cd); diff --git a/src/structure/structure_triangular_weir_free_params.ts b/src/structure/structure_triangular_weir_free_params.ts index 7c4253ec2624e3d5a9ca3cc17a29a5b39af04ec3..89745252bc6052ecae255546f5b00a2f6767f178 100644 --- a/src/structure/structure_triangular_weir_free_params.ts +++ b/src/structure/structure_triangular_weir_free_params.ts @@ -1,4 +1,4 @@ -import { ParamDefinition } from "../param/param-definition"; +import { ParamDefinition, ParamFamily } from "../param/param-definition"; import { ParamDomainValue } from "../param/param-domain"; import { StructureParams } from "./structure_params"; diff --git a/src/util/message.ts b/src/util/message.ts index 966f4cb6abe30932eb5d8237735310c17e5c55b9..cd5b6e391250a41ce7262a6cfe7b65f44dfc7648 100644 --- a/src/util/message.ts +++ b/src/util/message.ts @@ -63,6 +63,11 @@ export enum MessageCode { */ ERROR_PARAMDEF_VALUE_UNDEFINED, + /** + * la valeur de la cible d'un ParamDefinition est non définie + */ + ERROR_PARAMDEF_LINKED_VALUE_UNDEFINED, + /** * la valeur d'un ParamDefinition ne peut pas être changée */ diff --git a/src/util/result.ts b/src/util/result.ts index 55a9e877c1a963c3f5a9388b752fa63251032a57..356b1c8ccaf0005099a9814ecf69e7f714e13aff 100644 --- a/src/util/result.ts +++ b/src/util/result.ts @@ -1,6 +1,11 @@ import { JalhydObject } from "../jalhyd_object"; -// tslint:disable-next-line:max-line-length -import { INamedIterableValues, INumberIterator, NumberArrayIterator, NumberArrayReverseIterator } from "../param/param-value-iterator"; +import { ParamFamily } from "../param/param-definition"; +import { + INamedIterableValues, + INumberIterator, + NumberArrayIterator, + NumberArrayReverseIterator +} from "../param/param-value-iterator"; import { cLog } from "./log"; import { Message, MessageCode, MessageSeverity } from "./message"; import { ResultElement } from "./resultelement"; @@ -11,6 +16,13 @@ import { ResultElement } from "./resultelement"; */ // tslint:disable-next-line:max-classes-per-file export class Result extends JalhydObject implements INamedIterableValues { + + /** nom de la variable/paramètre calculé */ + public name: string; + + /** "parameters" family, for linked parameters */ + public family: ParamFamily; + /** * Messages (erreurs, infos, ...) */ @@ -18,11 +30,6 @@ export class Result extends JalhydObject implements INamedIterableValues { private _resultElements: ResultElement[]; - /** - * nom de la variable/paramètre calculé - */ - private _name: string; - /** * itérateur sur les valeurs des ResultElements */ @@ -43,14 +50,6 @@ export class Result extends JalhydObject implements INamedIterableValues { } } - public get name(): string { - return this._name; - } - - public set name(n: string) { - this._name = n; - } - /** * retourne le journal de la calculette */ @@ -201,10 +200,6 @@ export class Result extends JalhydObject implements INamedIterableValues { } } - // protected get messageCount(): number { - // return this._globalLog.messages.length; - // } - /** * ajoute un message au journal */ @@ -345,6 +340,9 @@ export class Result extends JalhydObject implements INamedIterableValues { */ // tslint:disable-next-line:max-classes-per-file export class ExtraResults extends JalhydObject implements INamedIterableValues { + + public family: ParamFamily; + private _name: string; private _values: number[]; diff --git a/src/value_ref/object_ref.ts b/src/value_ref/object_ref.ts index baba13fb94b3c03a90d5dfe3f6243898b5939658..3db161ae793733f22b87c737f869f5c26fd00c13 100644 --- a/src/value_ref/object_ref.ts +++ b/src/value_ref/object_ref.ts @@ -1,196 +1,128 @@ -import { INamedIterableValues, INumberIterator } from "../param/param-value-iterator"; +import { Nub } from "../nub"; +import { ParamDefinition } from "../param/param-definition"; +import { INamedIterableValues } from "../param/param-value-iterator"; +import { ParamValueMode } from "../param/param-value-mode"; import { ParamValues } from "../param/param-values"; -import { Result } from "../util/result"; +import { Message, MessageCode } from "../util/message"; -/* - * gestion de la valeur d'un paramètre par référence à une autre valeur (paramètre, résultat, résultat complémentaire) - * - * la référence (cf. INubReference.defineReference) (cf. INubReference.defineReference) - * est de la forme <n | ouvrage[n] | N1>[.[N2]] - * n : indice de de l'ouvrage dans le cas des ouvrages parallèles - * N1 : un nom de paramètre/résultat (dans le cas d'un résultat, il est suivi d'un point) - * N2 : nom de résultat complémentaire (optionnel) - * ex : - * Q, Z1 (paramètres) - * J. (résultat) - * .Yf (résultat complémentaire du résultat courant) - * Q.Yf (résultat complémentaire du résultat nommé "Q") - * 0.Q : paramètre Q du 1er ouvrage (ouvrages parallèles) - * ouvrage[1].Q_Mode : résultat complémentaire du 2ème ouvrage (ouvrages parallèles) - */ +export class LinkedValue { + /** linked value metadata (ex: calculator title for GUI) */ + public meta: any; -/** - * Nub dont certaines valeurs sont référençables pour réutilisation - * (d'une calculette sur une autre par ex) - */ -export interface IReferencedNub { + /** target Nub */ + private _nub: Nub; - /** - * getter des valeurs - * @param desc : description sous forme symbolique - */ - getReferencedParamValues(desc: string): ParamValues; - - /** - * getter du résultat - * @param desc : description sous forme symbolique - */ - getReferencedResult(desc?: string): Result; - - /** - * getter du résultat complémentaire - * @param desc : description sous forme symbolique - */ - getReferencedExtraResult(desc: string): any; - - /** - * itérateur sur les valeurs - */ - getReferencedValuesIterator(desc: string): INumberIterator; - - /** - * objet (paramètre/résultat/résultat complémentaire) référencé - */ - getReferencedObject(desc: string): INamedIterableValues; -} - -/** - * référence vers un Nub contenant une valeur vers laquelle on crée un lien - */ -export interface INubReference { - - /** - * description symbolique de la référence - */ - readonly referenceDefinition: string; - - /** - * true si la référence a été définie - */ - readonly isReferenceDefined: boolean; - - /** - * instance de ParamValues référencée - */ - readonly referencedParamValues: ParamValues; - - /** - * instance de Result référencée - */ - readonly referencedResult: Result; + /** target value : ParamDefinition (possibly in CALC mode) | undefined (ExtraResults) */ + private _element: INamedIterableValues; - /** - * instance de résultat complémentaire référencée - */ - readonly referencedExtraResult: any; + /** parameter / result symbol (ex: "Q") */ + private _symbol: string; - /** - * itérateur sur les valeurs référencées - */ - readonly referencedValuesIterator: INumberIterator; - - /** - * objet (paramètre/résultat/résultat complémentaire) référencé - */ - readonly referencedObject: INamedIterableValues; + constructor(nub: Nub, element: INamedIterableValues, symbol: string, meta: any = {}) { + this._nub = nub; + this._element = element; + this._symbol = symbol; + this.meta = meta; + } - /** - * définition de la valeur référencée dans le Nub - * @param target Nub contenant la valeur qu'on va référencer - * @param desc : description de la valeur pointée sous forme symbolique. Exemples : Q, <n° d'ouvrage>.Z1 - */ - defineReference(target: IReferencedNub, desc: string): void; + public get nub() { return this._nub; } + public get element() { return this._element; } + public get symbol() { return this._symbol; } /** - * supprime la référence + * Returns true if targetted value is a ParamDefinition (in CALC mode or not), + * and not an extra result */ - undefineReference(): void; -} - -/** - * implémentation par défaut de INubReference - */ -export class NubReference implements INubReference { - private _referencedNub: IReferencedNub; - - private _refDefinition: string; - - public defineReference(target: IReferencedNub, desc: string) { - this._referencedNub = target; - this._refDefinition = desc; + public isParameter(): boolean { + return (this.element instanceof ParamDefinition); } /** - * supprime la référence + * Returns true if targetted value is a ParamDefinition in CALC mode + * (might not have any value yet) */ - public undefineReference() { - this._referencedNub = undefined; - this._refDefinition = undefined; + public isResult(): boolean { + return ( + this.isParameter() + && (this.element as ParamDefinition).valueMode === ParamValueMode.CALCUL + ); } /** - * description symbolique de la référence + * Returns true if targetted value is an extra result + * (might not have any value yet) */ - public get referenceDefinition(): string { - return this._refDefinition; - } - - public get isReferenceDefined(): boolean { - return this._referencedNub !== undefined && this._refDefinition !== undefined; + public isExtraResult(): boolean { + return ( + this.nub !== undefined + && this.symbol !== undefined + && ! this.isParameter() + ); } /** - * Nub référencé - */ - public get referencedNub(): IReferencedNub { - return this._referencedNub; + * Returns true if v and the current objects have the same : + * - Nub UID + * - symbol + * - value type (Parameter / Result) + * (ignores metadata) + * @param v + */ + public equals(v: LinkedValue): boolean { + return ( + v + && (v.nub.uid === this.nub.uid) + && (v.symbol === this.symbol) + && ( + (v.element === undefined && this.element === undefined) + || ( + v.element !== undefined + && this.element !== undefined + && v.element.constructor.name === this.element.constructor.name + ) + ) + ); } /** - * instance de ParamValues référencée + * Returs the ParamValues for the linked Parameter if any, or a + * pseudo ParamValues object if the targetted element is a Result + * or ExtraResults */ - public get referencedParamValues(): ParamValues { - if (!this.isReferenceDefined) { - return undefined; + public getParamValues(): ParamValues { + if (this.isParameter()) { + return (this.element as ParamDefinition).paramValues; + } else { + // @TODO implement + throw new Error("not implemented - get pseudo ParamValues for ExtraResults"); } - const rpv = this._referencedNub.getReferencedParamValues(this._refDefinition); - if (rpv) { - rpv._nubRef = this; - } - return rpv; } /** - * instance de Result référencée + * Returns the current value of this.paramValues; throws an error if + * this.paramValues is not defined */ - public get referencedResult(): Result { - if (!this.isReferenceDefined) { - return undefined; + public getValue() { + if (! this.getParamValues().isDefined) { + const e = new Message(MessageCode.ERROR_PARAMDEF_LINKED_VALUE_UNDEFINED); + e.extraVar.symbol = this.symbol; + throw e; } - return this._referencedNub.getReferencedResult(this._refDefinition); + return this.getParamValues().currentValue; } /** - * instance de résultat complémentaire référencée + * Returns true if + * - a parameter is targetted and it has multiple values + * - a result / extra result is targetted and it has more than 1 value */ - public get referencedExtraResult(): any { - if (!this.isReferenceDefined) { - return undefined; + public hasMultipleValues(): boolean { + if (this.isParameter()) { + return (this.element as ParamDefinition).hasMultipleValues; + } else if (this.isResult() || this.isExtraResult()) { + // guess if parent Nub has any variating parameter (linked or not) + return this.nub.resultHasMultipleValues(); } - return this._referencedNub.getReferencedExtraResult(this._refDefinition); - } - - /** - * itérateur sur les valeurs référencées - */ - public get referencedValuesIterator(): INumberIterator { - return this._referencedNub.getReferencedValuesIterator(this._refDefinition); - } - - /** - * objet (paramètre/résultat/résultat complémentaire) référencé - */ - public get referencedObject(): INamedIterableValues { - return this._referencedNub.getReferencedObject(this._refDefinition); + return false; } }