From c2970c6f7b6fe9431c5fa3c03d9d758dfb5ffa4f Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Tue, 26 Mar 2019 15:41:19 +0100 Subject: [PATCH] =?UTF-8?q?Fix=20#174,=20#177=20-=20modules=20li=C3=A9s=20?= =?UTF-8?q?par=20leurs=20r=C3=A9sultats:=20calcul=20en=20cha=C3=AEne=20de?= =?UTF-8?q?=20l'aval=20vers=20l'amont?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- e2e/clone-calc.e2e-spec.ts | 3 -- .../base-param-input.component.ts | 2 +- .../fixedvar-results.component.ts | 1 + .../param-values/param-values.component.ts | 2 +- .../definition/concrete/form-courbe-remous.ts | 3 ++ .../concrete/form-lechapt-calmon.ts | 3 ++ .../concrete/form-parallel-structures.ts | 3 ++ .../concrete/form-regime-uniforme.ts | 3 ++ .../concrete/form-section-parametree.ts | 3 ++ .../definition/form-compute-courbe-remous.ts | 20 ++++++-- .../definition/form-compute-fixedvar.ts | 18 ++++--- .../form-compute-section-parametree.ts | 19 +++++--- src/app/formulaire/definition/form-compute.ts | 48 ++++++++++++++++--- .../form-def-parallel-structures.ts | 4 -- .../formulaire/definition/form-definition.ts | 31 +++++++++++- src/app/formulaire/fieldset.ts | 3 -- src/app/formulaire/ngparam.ts | 16 +++++-- 17 files changed, 140 insertions(+), 42 deletions(-) diff --git a/e2e/clone-calc.e2e-spec.ts b/e2e/clone-calc.e2e-spec.ts index 459b3d767..dab35d149 100644 --- a/e2e/clone-calc.e2e-spec.ts +++ b/e2e/clone-calc.e2e-spec.ts @@ -2,7 +2,6 @@ import { AppPage } from "./app.po"; import { ListPage } from "./list.po"; import { CalculatorPage } from "./calculator.po"; import { Navbar } from "./navbar.po"; -import { SideNav } from "./sidenav.po"; import { browser } from "protractor"; /** @@ -13,14 +12,12 @@ describe("ngHyd − clone a calculator", () => { let listPage: ListPage; let calcPage: CalculatorPage; let navbar: Navbar; - let sidenav: SideNav; beforeEach(() => { startPage = new AppPage(); listPage = new ListPage(); calcPage = new CalculatorPage(); navbar = new Navbar(); - sidenav = new SideNav(); }); it("when cloning a calculator, the clone should have the same values for all parameters", async () => { diff --git a/src/app/components/base-param-input/base-param-input.component.ts b/src/app/components/base-param-input/base-param-input.component.ts index e04b0a460..001a186d7 100644 --- a/src/app/components/base-param-input/base-param-input.component.ts +++ b/src/app/components/base-param-input/base-param-input.component.ts @@ -75,7 +75,7 @@ export class NgBaseParam extends Observable { valid = true; } catch (e) { if (e instanceof Message) { - // @TODO ici au début le service de localisation n'a pas encore chargé ses messages… + // ici au début le service de localisation n'a pas encore chargé ses messages… msg = ServiceFactory.instance.i18nService.localizeMessage(e); } else { msg = "invalid value"; diff --git a/src/app/components/fixedvar-results/fixedvar-results.component.ts b/src/app/components/fixedvar-results/fixedvar-results.component.ts index d6dca7a41..3392fb698 100644 --- a/src/app/components/fixedvar-results/fixedvar-results.component.ts +++ b/src/app/components/fixedvar-results/fixedvar-results.component.ts @@ -98,6 +98,7 @@ export class FixedVarResultsComponent implements DoCheck { this.resultsGraphComponent.results = undefined; } + // set _doUpdate flag so that results are rebuilt on the next Angular display cycle this._doUpdate = false; if (this._fixedResults !== undefined) { this._doUpdate = this._fixedResults.hasResults || this._fixedResults.hasLog; diff --git a/src/app/components/param-values/param-values.component.ts b/src/app/components/param-values/param-values.component.ts index 07a32d455..95c9e3c71 100644 --- a/src/app/components/param-values/param-values.component.ts +++ b/src/app/components/param-values/param-values.component.ts @@ -63,7 +63,7 @@ export class ParamValuesComponent implements AfterViewInit, Observer { this.openDialog(); }); } - // subscribe to parameter values change (through dialog actions) @TODO draft + // subscribe to parameter values change (through dialog actions) this.param.addObserver(this); } diff --git a/src/app/formulaire/definition/concrete/form-courbe-remous.ts b/src/app/formulaire/definition/concrete/form-courbe-remous.ts index 4e96da330..99be68efb 100644 --- a/src/app/formulaire/definition/concrete/form-courbe-remous.ts +++ b/src/app/formulaire/definition/concrete/form-courbe-remous.ts @@ -49,6 +49,9 @@ export class FormulaireCourbeRemous extends FormulaireBase { // interface Observer update(sender: IObservable, data: any) { + + super.update(sender, data); + if (sender instanceof FieldSet && data.action === "propertyChange") { switch (sender.id) { case "fs_section": diff --git a/src/app/formulaire/definition/concrete/form-lechapt-calmon.ts b/src/app/formulaire/definition/concrete/form-lechapt-calmon.ts index c84864baa..db2991206 100644 --- a/src/app/formulaire/definition/concrete/form-lechapt-calmon.ts +++ b/src/app/formulaire/definition/concrete/form-lechapt-calmon.ts @@ -26,6 +26,9 @@ export class FormulaireLechaptCalmon extends FormulaireBase implements Observer // interface Observer public update(sender: any, data: any) { + + super.update(sender, data); + // en cas de changement de valeur du select de matériau, effacement des résultats et MAJ des champs L,M,N if (sender instanceof SelectField) { if (data.action === "select") { diff --git a/src/app/formulaire/definition/concrete/form-parallel-structures.ts b/src/app/formulaire/definition/concrete/form-parallel-structures.ts index d71119c87..ec840a970 100644 --- a/src/app/formulaire/definition/concrete/form-parallel-structures.ts +++ b/src/app/formulaire/definition/concrete/form-parallel-structures.ts @@ -338,6 +338,9 @@ export class FormulaireParallelStructure extends FormulaireBase { // interface Observer public update(sender: any, data: any) { + + super.update(sender, data); + if (sender instanceof FieldsetContainer) { switch (data.action) { case "newFieldset": diff --git a/src/app/formulaire/definition/concrete/form-regime-uniforme.ts b/src/app/formulaire/definition/concrete/form-regime-uniforme.ts index 35a08225c..503bdaba7 100644 --- a/src/app/formulaire/definition/concrete/form-regime-uniforme.ts +++ b/src/app/formulaire/definition/concrete/form-regime-uniforme.ts @@ -33,6 +33,9 @@ export class FormulaireRegimeUniforme extends FormulaireBase implements Observer // interface Observer update(sender: IObservable, data: any) { + + super.update(sender, data); + // changement de propriété du FieldSet contenant le select de choix du type de section if (sender instanceof FieldSet && sender.id === "fs_section" && data.action === "propertyChange") { this.replaceCurrentNub(sender.properties); diff --git a/src/app/formulaire/definition/concrete/form-section-parametree.ts b/src/app/formulaire/definition/concrete/form-section-parametree.ts index 9c48c038b..1a3ef62b1 100644 --- a/src/app/formulaire/definition/concrete/form-section-parametree.ts +++ b/src/app/formulaire/definition/concrete/form-section-parametree.ts @@ -31,6 +31,9 @@ export class FormulaireSectionParametree extends FormulaireBase { // interface Observer update(sender: IObservable, data: any) { + + super.update(sender, data); + // changement de propriété du FieldSet contenant le select de choix du type de section if (sender instanceof FieldSet && data.action === "propertyChange") { switch (sender.id) { diff --git a/src/app/formulaire/definition/form-compute-courbe-remous.ts b/src/app/formulaire/definition/form-compute-courbe-remous.ts index dc3a6a2e2..b69986e83 100644 --- a/src/app/formulaire/definition/form-compute-courbe-remous.ts +++ b/src/app/formulaire/definition/form-compute-courbe-remous.ts @@ -7,6 +7,11 @@ import { FormCompute } from "./form-compute"; import { FormResultRemous } from "./form-result-remous"; export class FormComputeCourbeRemous extends FormCompute { + + private resultYn: Result; + + private resultYc: Result; + constructor(formBase: FormulaireDefinition, private _formSection: FormDefSection, formResult: FormResultRemous) { super(formBase, formResult); } @@ -21,8 +26,15 @@ export class FormComputeCourbeRemous extends FormCompute { const prmCR: CourbeRemousParams = cr.prms as CourbeRemousParams; const sect: acSection = prmCR.Sn; - const Yn: Result = sect.Calc("Yn"); // hauteur normale - const Yc: Result = sect.Calc("Yc"); // hauteur critique + this.resultYn = sect.Calc("Yn"); // hauteur normale + this.resultYc = sect.Calc("Yc"); // hauteur critique + + this.reaffectResultComponents(); + } + + protected reaffectResultComponents() { + const cr: CourbeRemous = this._formBase.currentNub as CourbeRemous; + const prmCR: CourbeRemousParams = cr.prms as CourbeRemousParams; this.remousResults.parameters = prmCR; @@ -33,8 +45,8 @@ export class FormComputeCourbeRemous extends FormCompute { this.remousResults.result = cr.calculRemous(this.remousResults.extraParamSymbol); // données du graphe - this.remousResults.hauteurNormale = Yn.resultElement; - this.remousResults.hauteurCritique = Yc.resultElement; + this.remousResults.hauteurNormale = this.resultYn.resultElement; + this.remousResults.hauteurCritique = this.resultYc.resultElement; if (this.remousResults.extraParamSymbol) { this.remousResults.extraGraph = ["Hs", "Hsc", "Yf", "Yt", "Yco"].indexOf(this.remousResults.extraParamSymbol) === -1; } else { diff --git a/src/app/formulaire/definition/form-compute-fixedvar.ts b/src/app/formulaire/definition/form-compute-fixedvar.ts index 151b875bf..616899160 100644 --- a/src/app/formulaire/definition/form-compute-fixedvar.ts +++ b/src/app/formulaire/definition/form-compute-fixedvar.ts @@ -1,4 +1,4 @@ -import { Nub, Result, ComputeNode, ParamValueMode } from "jalhyd"; +import { Nub, Result, ComputeNode } from "jalhyd"; import { FormCompute } from "./form-compute"; import { NgParameter, ParamRadioConfig } from "../ngparam"; @@ -45,22 +45,28 @@ export class FormComputeFixedVar extends FormCompute { protected compute() { const nub: Nub = this._formBase.currentNub; const computedParam: NgParameter = this.getComputedParameter(); + + const res: Result = this.runNubCalc(nub, computedParam); + + this.reaffectResultComponents(); + } + + protected reaffectResultComponents() { + const nub: Nub = this._formBase.currentNub; + const computedParam: NgParameter = this.getComputedParameter(); this.formResult.addFixedParameters(); const varParam: NgParameter = this.getVariatedParameter(); if (varParam === undefined) { // pas de paramètre à varier - const res: Result = this.runNubCalc(nub, computedParam); - this.formResult.fixedResults.result = res; + this.formResult.fixedResults.result = nub.result; this.formResult.fixedResults.calculatedParameter = computedParam; } else { // il y a un paramètre à varier - const res: Result = this.runNubCalc(nub, computedParam); - this.formResult.varResults.variatedParameter = varParam; this.formResult.varResults.calculatedParameter = computedParam; - this.formResult.varResults.result = res; + this.formResult.varResults.result = nub.result; this.formResult.varResults.update(false); } } diff --git a/src/app/formulaire/definition/form-compute-section-parametree.ts b/src/app/formulaire/definition/form-compute-section-parametree.ts index fc41974d9..068dce9d2 100644 --- a/src/app/formulaire/definition/form-compute-section-parametree.ts +++ b/src/app/formulaire/definition/form-compute-section-parametree.ts @@ -12,6 +12,8 @@ import { FormulaireNode } from "../formulaire-node"; export class FormComputeSectionParametree extends FormCompute { + private tmpResult: Result; + constructor(formBase: FormulaireDefinition, private _formSection: FormDefSection, formResult: FormResult) { super(formBase, formResult); } @@ -62,20 +64,25 @@ export class FormComputeSectionParametree extends FormCompute { const sectNub: SectionParametree = this._formBase.currentNub as SectionParametree; - const sect: acSection = sectNub.section; - this._sectionResults.section = sect; - - const tmpResult: Result = sectNub.CalcSerie( + this.tmpResult = sectNub.CalcSerie( undefined, // valeur initiale, non utilisée dans ce cas undefined // variable à calculer, non utilisée ); + this.reaffectResultComponents(); + } + + protected reaffectResultComponents() { + const sectNub: SectionParametree = this._formBase.currentNub as SectionParametree; + const sect: acSection = sectNub.section; + this._sectionResults.section = sect; + // résultats de section (avec le graphique de section) - this._sectionResults.result = tmpResult; + this._sectionResults.result = this.tmpResult; // résultats complémentaires des paramètres fixés this._formSectionResult.addSectionFixedParameters(false); - this._formSectionResult.fixedResults.result = tmpResult; + this._formSectionResult.fixedResults.result = this.tmpResult; } /** diff --git a/src/app/formulaire/definition/form-compute.ts b/src/app/formulaire/definition/form-compute.ts index 4e8494753..d1e848b28 100644 --- a/src/app/formulaire/definition/form-compute.ts +++ b/src/app/formulaire/definition/form-compute.ts @@ -1,11 +1,14 @@ -import { Nub, Result, ParamDomainValue } from "jalhyd"; +import { Nub, Result, ParamDomainValue, Observer } from "jalhyd"; import { FormResult } from "./form-result"; import { FormulaireDefinition } from "./form-definition"; import { NgParameter } from "../ngparam"; -export abstract class FormCompute { +export abstract class FormCompute implements Observer { + constructor(protected _formBase: FormulaireDefinition, protected _formResult: FormResult) { + // indirectly subscribe to Nub result updates + this._formBase.addObserver(this); } protected abstract compute(); @@ -23,14 +26,25 @@ export abstract class FormCompute { } /** - * lance le calcul d'un paramètre en déterminant une valeur initiale + * Copies current Nub result into result components for display on page. + * Should be called every time the Nub result changes + */ + protected abstract reaffectResultComponents(); + + /** + * Lance le calcul d'un paramètre en déterminant une valeur initiale. + * Si nécessaire déclenche un calcul en chaîne des modules en amont. */ protected runNubCalc(nub: Nub, computedParam: NgParameter): Result { let init: number; + // require chain computation; redundant with Nub.CalcSerie but required + // to get initial value here... + const computedParamValue = computedParam.getValue(true); + switch (computedParam.domain.domain) { case ParamDomainValue.ANY: if (computedParam && computedParam.isDefined) { - init = computedParam.getValue(); + init = computedParamValue; } if (init === undefined) { init = 0; @@ -39,7 +53,7 @@ export abstract class FormCompute { case ParamDomainValue.POS_NULL: if (computedParam && computedParam.isDefined) { - init = Math.max(computedParam.getValue(), 0); + init = Math.max(computedParamValue, 0); } if (init === undefined) { init = 0; @@ -52,7 +66,7 @@ export abstract class FormCompute { case ParamDomainValue.NOT_NULL: if (computedParam && computedParam.isDefined) { - init = computedParam.getValue(); + init = computedParamValue; } if (init === undefined || init === 0) { init = 1e-8; @@ -61,7 +75,7 @@ export abstract class FormCompute { case ParamDomainValue.POS: if (computedParam && computedParam.isDefined) { - init = Math.max(computedParam.getValue(), 1e-8); + init = Math.max(computedParamValue, 1e-8); } if (init === undefined) { init = 1e-8; @@ -72,6 +86,9 @@ export abstract class FormCompute { return nub.CalcSerie(init, this.getParameterRefid(computedParam)); } + /** + * Triggers computation of the Nub, updates form results + */ public doCompute() { this._formResult.resetResults(); @@ -81,4 +98,21 @@ export abstract class FormCompute { "action": "resultsUpdated", }, this._formBase); } + + // interface Observer + + public update(sender: any, data: any): void { + if (sender instanceof Nub) { + switch (data.action) { + case "nubResultUpdated": + // forward Nub results update notification to FormCompute objects + this.reaffectResultComponents(); + /* console.log("_____forwarding 2"); + this._formBase.notifyObservers({ + "action": "resultsUpdated", + }, this._formBase); */ + break; + } + } + } } diff --git a/src/app/formulaire/definition/form-def-parallel-structures.ts b/src/app/formulaire/definition/form-def-parallel-structures.ts index a4856994d..5206d9cc0 100644 --- a/src/app/formulaire/definition/form-def-parallel-structures.ts +++ b/src/app/formulaire/definition/form-def-parallel-structures.ts @@ -1,7 +1,3 @@ -import { CalculatorType, StructureType, LoiDebit } from "jalhyd"; - -import { FieldSet } from "../fieldset"; - /** * gestion des formulaires "ouvrages parallèles" */ diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts index 4d14b15b7..daa57be19 100644 --- a/src/app/formulaire/definition/form-definition.ts +++ b/src/app/formulaire/definition/form-definition.ts @@ -1,4 +1,4 @@ -import { CalculatorType, ComputeNodeType, Nub, Props, Observer, Session, ParallelStructure } from "jalhyd"; +import { CalculatorType, ComputeNodeType, Nub, Props, Observer, Session } from "jalhyd"; import { FormulaireElement } from "../formulaire-element"; import { NgParameter, ParamRadioConfig } from "../ngparam"; @@ -94,7 +94,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs } public initNub(props?: Props) { - this._currentNub = this.createNub(props ? props : new Props(this.defaultProperties)); + this.currentNub = this.createNub(props ? props : new Props(this.defaultProperties)); } public get currentNub(): Nub { @@ -108,7 +108,15 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs `Nub ${n.properties["calcType"]} incompatible avec le formulaire ${this._calculatorName} (${this._props["calcType"]})` ); } + // unsubscribe from old Nub + if (this._currentNub) { + this._currentNub.removeObserver(this); + } + // replace Nub this._currentNub = n; + // subscribe to new Nub (for result updates) + console.log("SET CURRENT NUB -- (re)subscribe to Nub", this._currentNub.uid); + this._currentNub.addObserver(this); } /** @@ -351,6 +359,16 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs }, this); } + /** + * Forwards Nub's result updated notification. + * Used by FormCompute to update results display + */ + protected notifyNubResultUpdated(sender) { + this.notifyObservers({ + action: "nubResultUpdated" + }, sender); + } + /** * réinitialisation du formulaire suite à un changement d'une valeur, d'une option, ... : * effacement des résultats, application des dépendances, ... @@ -469,5 +487,14 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs // interface Observer public update(sender: any, data: any) { + console.log("--- FormDefinition received update", sender.constructor.name, data); + if (sender instanceof Nub) { + switch (data.action) { + case "resultUpdated": + // forward Nub results update notification to FormCompute objects + this.notifyNubResultUpdated(sender); + break; + } + } } } diff --git a/src/app/formulaire/fieldset.ts b/src/app/formulaire/fieldset.ts index ffa32a38d..ff2789eb3 100644 --- a/src/app/formulaire/fieldset.ts +++ b/src/app/formulaire/fieldset.ts @@ -133,9 +133,6 @@ export class FieldSet extends FormulaireElement implements Observer { if (res) { res.parseConfig(json, { "radioConfig": default_radio_config }); - // set parent Nub on Parameter to ensure UID availability - // should always be done @TODO check - // res.paramDefinition.parent = this._nub; } return res; diff --git a/src/app/formulaire/ngparam.ts b/src/app/formulaire/ngparam.ts index 809b9d1f7..10ed51962 100644 --- a/src/app/formulaire/ngparam.ts +++ b/src/app/formulaire/ngparam.ts @@ -51,7 +51,6 @@ export class NgParameter extends InputField implements Observer { /** * Returns a text preview of the current value(s), depending on the value mode - * @TODO use display precision to limit decimals */ public static preview(p: ParamDefinition): string { let valuePreview: string; @@ -107,7 +106,12 @@ export class NgParameter extends InputField implements Observer { return v.toFixed(nDigits); }).slice(0, 5).join("; ") + "…"; } else { - valuePreview = String(p.referencedValue.nub.result.vCalc.toFixed(nDigits)); + const vCalc = p.referencedValue.nub.result.vCalc; + if (vCalc) { + valuePreview = String(vCalc.toFixed(nDigits)); + } else { + throw new Error("NgParameter.preview() : No vCalc for computed target Nub !"); + } } } else { valuePreview = i18n.localizeText("INFO_PARAMFIELD_IN_CALCULATION"); @@ -120,7 +124,6 @@ export class NgParameter extends InputField implements Observer { // was the result already computed ? try { const remoteValues = p.referencedValue.getParamValues(); - // @TODO is the computed value fresh or stale ? if (p.referencedValue.hasMultipleValues()) { // like LIST mode valuePreview = i18n.localizeText("INFO_PARAMFIELD_PARAMVARIER_VALUES"); @@ -269,8 +272,11 @@ export class NgParameter extends InputField implements Observer { throw new Error("invalid parameter radio configuration " + s); } - public getValue() { - return this._paramDef.v; + /** + * Asks the ParamDefinition for its current value + */ + public getValue(triggerChainComputation: boolean = false) { + return this._paramDef.getValue(triggerChainComputation); } /** -- GitLab