diff --git a/spec/section_param/section_param.spec.ts b/spec/section_param/section_param.spec.ts index 929be985264d82860e45ab76d1d943473055c91f..04517e86da77d416cfd2d0f452f5ef812b1e71b2 100644 --- a/spec/section_param/section_param.spec.ts +++ b/spec/section_param/section_param.spec.ts @@ -36,8 +36,6 @@ function testVarier(nub: SectionParametree, p: ParamDefinition) { expect(nub.result).toBeDefined(); expect(nub.result.resultElements.length).toBe(9); - // console.log(Object.keys(nub.result.resultElements[0].extraResults)); - // console.log(nub.result.resultElements); // tslint:disable-next-line:prefer-for-of for (let i = 0; i < nub.result.resultElements.length; i++) { expect(Object.keys(nub.result.resultElements[i].extraResults).length).toBe(17); @@ -51,7 +49,7 @@ describe("Section paramétrée rectangulaire, paramètres fixés : ", () => { const nub = createSection(precDist); nub.CalcSerie(); expect(nub.result).toBeDefined(); - expect(Object.keys(nub.result.resultElements[0].extraResults).length).toBe(17); + expect(Object.keys(nub.result.resultElement.extraResults).length).toBe(17); }); }); diff --git a/src/nub.ts b/src/nub.ts index 1112d635681d9ae297f95389b6fbf1aaccc2fa95..a5f56bce6de9e668edc259e688511a58ab62dace 100644 --- a/src/nub.ts +++ b/src/nub.ts @@ -9,6 +9,7 @@ import { ParamValues } from "./param/param-values"; import { Props } from "./props"; import { IObservable, Observable, Observer } from "./util/observer"; import { Result } from "./util/result"; +import { ResultElement } from "./util/resultelement"; /** * Classe abstraite de Noeud de calcul dans une session : @@ -20,6 +21,16 @@ export abstract class Nub extends ComputeNode implements IObservable { return this._result; } + /** + * Local setter to set results of Equation() / Solve() / … as current + * ResultElement, instead of overwriting the whole Result object + * (used by CalcSerie with varying parameters) + */ + protected set currentResult(r: Result) { + this._result.resultElement = r.resultElement; + this._result.resultElement.log = r.log; + } + /** Returns Props object (observable set of key-values) associated to this Nub */ public get properties(): Props { // completes props with calcType if not already set @@ -260,18 +271,23 @@ export abstract class Nub extends ComputeNode implements IObservable { computedVar = this.calculatedParam; } + // if Calc() is called outside of CalcSerie(), _result might not be initialized + if (! this._result) { + this.initNewResultElement(); + } + if (rInit === undefined) { rInit = computedVar.v; } if (computedVar.isAnalytical()) { - this._result = this.Equation(sVarCalc); + this.currentResult = this.Equation(sVarCalc); this._result.name = sVarCalc; return this._result; } const resSolve: Result = this.Solve(sVarCalc, rInit); if (!resSolve.ok) { - this._result = resSolve; + this.currentResult = resSolve; this._result.name = sVarCalc; return this._result; } @@ -279,12 +295,12 @@ export abstract class Nub extends ComputeNode implements IObservable { computedVar.v = resSolve.vCalc; const res: Result = this.Equation(sAnalyticalPrm); res.vCalc = resSolve.vCalc; - this._result = res; + this.currentResult = res; this._result.name = sVarCalc; this.notifyResultUpdated(); - return res; + return this._result; } /** @@ -347,7 +363,9 @@ export abstract class Nub extends ComputeNode implements IObservable { } if (variated.length === 0) { // no parameter is varying - this._result = this.doCalc(computedSymbol, rInit); + // prepare a new slot to store results + this.initNewResultElement(); + this.doCalc(computedSymbol, rInit); // résultat dans this.currentResult (resultElement le plus récent) this.progress = 100; } else { // at least one parameter is varying @@ -366,7 +384,7 @@ export abstract class Nub extends ComputeNode implements IObservable { const remainingProgress = 100 - this.progress; progressStep = remainingProgress / size; - const res = new Result(undefined, this); + // const res = new Result(undefined, this); // (re)init all iterators for (const v of variated) { @@ -377,6 +395,9 @@ export abstract class Nub extends ComputeNode implements IObservable { } } + // reinit Result + this._result = new Result(undefined, this); + // iterate over longest series (in fact any series would do) while (variated[longest].values.hasNext) { // get next value for all variating parameters @@ -384,18 +405,18 @@ export abstract class Nub extends ComputeNode implements IObservable { const currentIteratorValue = v.values.next(); v.param.v = currentIteratorValue.value; } + // prepare a new slot to store results + this.initNewResultElement(); // calculate - this.doCalc(computedSymbol, rInit); // résultat dans this._result - if (this._result.ok) { - res.addResultElement(this._result.resultElement); - res.addLog(this._result.log); + this.doCalc(computedSymbol, rInit); // résultat dans this.currentResult (resultElement le plus récent) + if (this._result.resultElement.ok) { rInit = this._result.resultElement.vCalc; } - res.globalLog.addLog(this._result.globalLog); + this._result.globalLog.addLog(this._result.globalLog); // update progress this.progress += progressStep; } - this._result = res; + // this._result = res; // round progress to 100% this.progress = 100; } @@ -1106,6 +1127,23 @@ export abstract class Nub extends ComputeNode implements IObservable { throw new Error(`Nub of class ${this.constructor.name} has no parent`); } + /** + * Adds a new empty resultElement to the current Result object, so that + * computation result is stored into it, via set currentResult(); does + * the same for all children + */ + public initNewResultElement() { + if (! this._result) { + this._result = new Result(undefined, this); + } + // push empty result element for further affectation va set currentResult() + this._result.addResultElement(new ResultElement()); + // do the same for children + for (const c of this._children) { + c.initNewResultElement(); + } + } + // interface IObservable /** diff --git a/src/pab/pab.ts b/src/pab/pab.ts index d3181b66d08688ac0a84528fe10fa54285a900e7..70dd95cb6b888b91ef9da6d0a69d422d3a048b2b 100644 --- a/src/pab/pab.ts +++ b/src/pab/pab.ts @@ -236,6 +236,16 @@ export class Pab extends Nub { return ret; } + /** + * Adds a new empty resultElement to the current Result object, so that + * computation result is stored into it, via set currentResult(); does + * the same for all children and downWall + */ + public initNewResultElement() { + super.initNewResultElement(); + this.downWall.initNewResultElement(); + } + /** * paramétrage de la calculabilité des paramètres */ diff --git a/src/remous.ts b/src/remous.ts index b54b3a336235123b27117e9b64c543b29612e740..2b470dc3c9b299975b904dc4edb2386130a9f94d 100644 --- a/src/remous.ts +++ b/src/remous.ts @@ -468,7 +468,8 @@ export class CourbeRemous extends SectionNub { } } - this._result = res; + this.initNewResultElement(); + this.currentResult = res; return res; } diff --git a/src/section/section_parametree.ts b/src/section/section_parametree.ts index b88b68ae04ecbf68a3145cf18a9c325ba95195cb..9c4ff94e9cd38766b87df491d602d5cb1ecf4f3f 100644 --- a/src/section/section_parametree.ts +++ b/src/section/section_parametree.ts @@ -79,60 +79,63 @@ export class SectionParametree extends SectionNub { // par les appels successifs car c'est en même temps un paramètre et une variable temporaire) const Y = this.getParameter("Y").v; - this._result = new Result(undefined, this); + /* this._result = new Result(undefined, this); const re = new ResultElement(); - this._result.addResultElement(re); + this._result.addResultElement(re); */ + if (! this._result) { + this.initNewResultElement(); + } // charge spécifique - this.addExtraResultFromVar("Hs", Y, re); + this.addExtraResultFromVar("Hs", Y); // charge critique - this.addExtraResultFromVar("Hsc", Y, re); + this.addExtraResultFromVar("Hsc", Y); // largeur au miroir - this.addExtraResultFromVar("B", Y, re); + this.addExtraResultFromVar("B", Y); // périmètre hydraulique - this.addExtraResultFromVar("P", Y, re); + this.addExtraResultFromVar("P", Y); // surface hydraulique - this.addExtraResultFromVar("S", Y, re); + this.addExtraResultFromVar("S", Y); // rayon hydraulique - this.addExtraResultFromVar("R", Y, re); + this.addExtraResultFromVar("R", Y); // vitesse moyenne - this.addExtraResultFromVar("V", Y, re); + this.addExtraResultFromVar("V", Y); // nombre de Froude - this.addExtraResultFromVar("Fr", Y, re); + this.addExtraResultFromVar("Fr", Y); // tirant d'eau critique - this.addExtraResultFromVar("Yc", Y, re); + this.addExtraResultFromVar("Yc", Y); // tirant d'eau normal - this.addExtraResultFromVar("Yn", Y, re); + this.addExtraResultFromVar("Yn", Y); // tirant d'eau fluvial - this.addExtraResultFromVar("Yf", Y, re); + this.addExtraResultFromVar("Yf", Y); // tirant d'eau torrentiel - this.addExtraResultFromVar("Yt", Y, re); + this.addExtraResultFromVar("Yt", Y); // tirant d'eau conjugué - this.addExtraResultFromVar("Yco", Y, re); + this.addExtraResultFromVar("Yco", Y); // perte de charge - this.addExtraResultFromVar("J", Y, re); + this.addExtraResultFromVar("J", Y); // Variation linéaire de l'énergie spécifique - this.addExtraResultFromVar("I-J", Y, re); + this.addExtraResultFromVar("I-J", Y); // impulsion hydraulique - this.addExtraResultFromVar("Imp", Y, re); + this.addExtraResultFromVar("Imp", Y); // contrainte de cisaillement - this.addExtraResultFromVar("Tau0", Y, re); + this.addExtraResultFromVar("Tau0", Y); return this._result; } @@ -231,12 +234,12 @@ export class SectionParametree extends SectionNub { * Calculates varCalc from Y, and sets the result as an * extraResult of the given ResultElement */ - private addExtraResultFromVar(varCalc: string, Y: number, re: ResultElement) { + private addExtraResultFromVar(varCalc: string, Y: number) { const r: Result = this.section.CalcSection(varCalc, Y); if (r.ok) { - re.addExtraResult(varCalc, r.vCalc); + this._result.resultElement.addExtraResult(varCalc, r.vCalc); } else { - re.log.addLog(r.log); + this._result.resultElement.log.addLog(r.log); } } } diff --git a/src/section/section_type.ts b/src/section/section_type.ts index 0167c75131b3b31282c4b8df54905d0788d2bf9b..dc901277000ceea64f699e81c76eb74bc45ee558 100644 --- a/src/section/section_type.ts +++ b/src/section/section_type.ts @@ -241,7 +241,7 @@ export abstract class acSection extends Nub { * (used by triggerChainCalculation) */ public CalcSerie(rInit?: number, sDonnee?: any): Result { - this._result = this.parent.CalcSerie(rInit, sDonnee); + this.currentResult = this.parent.CalcSerie(rInit, sDonnee); return this._result; } diff --git a/src/structure/parallel_structure.ts b/src/structure/parallel_structure.ts index 02b492ac426cb152a131877de9f9a8285005ee37..f0223961d586e562fcf26c0e57a32eb7a3f232c8 100644 --- a/src/structure/parallel_structure.ts +++ b/src/structure/parallel_structure.ts @@ -108,14 +108,17 @@ export class ParallelStructure extends Nub { * @param rInit Valeur initiale */ public Calc(sVarCalc: string | any, rInit?: number): Result { - let res: Result; + // if Calc() is called outside of CalcSerie(), _result might not be initialized + if (! this._result) { + this.initNewResultElement(); + } switch (sVarCalc) { case "Z1": case "Z2": case "Q": - res = super.Calc(sVarCalc, rInit); - if (res.ok) { - this.getParameter(sVarCalc).v = res.vCalc; + this.currentResult = super.Calc(sVarCalc, rInit); + if (this._result.ok) { + this.getParameter(sVarCalc).v = this._result.resultElement.vCalc; } break; default: @@ -124,24 +127,24 @@ export class ParallelStructure extends Nub { } // Pour les caractéristiques des ouvrages const structureIndex = this.getIndexForChild(sVarCalc.uid); - res = this.CalcStructPrm(structureIndex, sVarCalc.symbol); - if (res.ok) { + this.currentResult = this.CalcStructPrm(structureIndex, sVarCalc.symbol); + if (this._result.ok) { // Suppression des extraResults : ils sont complétés plus bas pour chaque ouvrage - res.resultElement.extraResults = {}; - this._children[structureIndex].getParameter(sVarCalc.symbol).v = res.vCalc; + this._result.resultElement.extraResults = {}; + this._children[structureIndex].getParameter(sVarCalc.symbol).v = this._result.resultElement.vCalc; } } - if (res.ok) { + if (this._result.ok) { // Recalcul du débit total pour récupérer les résultats des ouvrages dans les résultats complémentaires const resQtot: Result = this.CalcQ(); for (const extraResKey in resQtot.extraResults) { if (resQtot.extraResults.hasOwnProperty(extraResKey)) { - res.resultElement.addExtraResult(extraResKey, resQtot.extraResults[extraResKey]); + this._result.resultElement.addExtraResult(extraResKey, resQtot.extraResults[extraResKey]); } } } - this._result = res; - return res; + + return this._result; } /** diff --git a/src/structure/structure_vanlev.ts b/src/structure/structure_vanlev.ts index 0447d0ba8ae03e2e045d3faa115e9293e0b47633..8e730e96341d3c50da14802bcc66435becc79ca2 100644 --- a/src/structure/structure_vanlev.ts +++ b/src/structure/structure_vanlev.ts @@ -44,6 +44,35 @@ export class StructureVanLevParams extends RectangularStructureParams { } } +function CalcVanneLevante( + s: StructureVanLevVillemonte | StructureVanLevLarinier, + sVarCalc: string, rInit: number +): Result { + + if (sVarCalc !== "Z1") { + throw new Error("CalcVanneLevante sVarCalc should be Z1"); + } + // Calculation of ZDV + s.prms.Z1.v = s.prms.Z2.v + s.prms.DH.v; + const r1: Result = s.superCalc("ZDV", rInit); + s.prms.ZDV.v = r1.vCalc; + // Check if calculated ZDV is between minZDV and maxZDV + let m: Message; + if (r1.vCalc < s.prms.minZDV.v) { + m = new Message(MessageCode.WARNING_VANLEV_ZDV_INF_MIN); + s.prms.ZDV.v = s.prms.minZDV.v; + } else if (r1.vCalc > s.prms.maxZDV.v) { + m = new Message(MessageCode.WARNING_VANLEV_ZDV_SUP_MAX); + s.prms.ZDV.v = s.prms.maxZDV.v; + } + const r2: Result = s.superCalc("Z1", rInit); + r2.extraResults.ZDV = s.prms.ZDV.v; + if (m !== undefined) { + r2.resultElement.addMessage(m); + } + return r2; +} + // tslint:disable-next-line:max-classes-per-file export class StructureVanLevVillemonte extends StructureWeirVillemonte { diff --git a/src/util/result.ts b/src/util/result.ts index aeff109304d67eac6063f03dda210abbf0ef3630..f41e7b07ea4f09e6b20977f0f16c87149c3cfc4c 100644 --- a/src/util/result.ts +++ b/src/util/result.ts @@ -76,14 +76,23 @@ export class Result extends JalhydObject implements INamedIterableValues { } /** - * Retourne le résultat du premier ResultElement + * Retourne le ResultElement le plus récent */ get resultElement(): ResultElement { if (this._resultElements.length === 0) { throw new Error("appel à la méthode de Result.result() invalide, il n'y a pas au moins un 'ResultElement'"); } + return this._resultElements[ this._resultElements.length - 1 ]; + } - return this._resultElements[0]; + /** + * Affecte le ResultElement le plus récent + */ + set resultElement(r: ResultElement) { + if (this._resultElements.length === 0) { + throw new Error("appel à la méthode de Result.result() invalide, il n'y a pas au moins un 'ResultElement'"); + } + this._resultElements[ this._resultElements.length - 1 ] = r; } get resultElements(): ResultElement[] { diff --git a/src/util/resultelement.ts b/src/util/resultelement.ts index ebe984b8cffc7a436adca170972a5f5257b5272f..201542bfc74e031a22156e0ec3c5b3d8eab4fa53 100644 --- a/src/util/resultelement.ts +++ b/src/util/resultelement.ts @@ -6,15 +6,17 @@ import { Message, MessageCode, MessageSeverity } from "./message"; * Représente une valeur unique */ export class ResultElement { + /** - * Valeur calculée + * Messages (erreurs, infos, ...) + * public for easy setting by Nub */ - private _vCalc: number; + public log: cLog; /** - * Messages (erreurs, infos, ...) + * Valeur calculée */ - private _log: cLog; + private _vCalc: number; /** * résultats complémentaires @@ -22,7 +24,7 @@ export class ResultElement { private _extraResults: { [key: string]: any }; constructor(v?: number | Message) { - this._log = new cLog(); + this.log = new cLog(); if (typeof v === "number") { this._vCalc = v; } else if (v instanceof Message) { @@ -37,22 +39,18 @@ export class ResultElement { this._vCalc = r; } - public get log() { - return this._log; - } - get code(): MessageCode { if (this.messageCount !== 1) { throw new Error("appel à Result.code invalide, il n'y pas exactement un message de log"); } - return this._log.messages[0].code; + return this.log.messages[0].code; } get extraVar() { if (this.messageCount !== 1) { throw new Error("appel à Result.extraVar invalide, il n'y pas exactement un message de log"); } - return this._log.messages[0].extraVar; + return this.log.messages[0].extraVar; } private get hasExtraResults(): boolean { @@ -64,11 +62,11 @@ export class ResultElement { } private get messageCount(): number { - return this._log.messages.length; + return this.log.messages.length; } public get hasErrorMessages(): boolean { - for (const m of this._log.messages) { + for (const m of this.log.messages) { if (m.code !== MessageCode.ERROR_OK && m.getSeverity() === MessageSeverity.ERROR) { return true; } @@ -84,14 +82,14 @@ export class ResultElement { * ajoute un message au journal */ public addMessage(m: Message) { - this._log.add(m); + this.log.add(m); } /** * insert un message en début de liste */ public insertMessage(m: Message) { - this._log.insert(m); + this.log.insert(m); } /** @@ -129,7 +127,7 @@ export class ResultElement { } } // Add Logs - this._log.addLog(resultElementToAdd.log); + this.log.addLog(resultElementToAdd.log); } /**