diff --git a/src/base.ts b/src/base.ts index f74f97a4a38d112ac8224622d167b277c5de2fd1..95f88b73cec1aa1c9a65082e35b2e22592df4ff9 100644 --- a/src/base.ts +++ b/src/base.ts @@ -1,16 +1,3 @@ -/** - * Série de valeurs à calculer définie par le nom de la variable à sérier et le vecteur de valeur - */ -export class Serie { - public name: string; - public values: number[]; - - constructor(name: string, values: number[]) { - this.name = name; - this.values = values; - } -} - /** * Gestion des messages de debogage dans la console * @note Etendre cette classe pour toutes les classes à debugguer diff --git a/src/compute-node.ts b/src/compute-node.ts index 92c5ec74cf29d8361221c163561d20416a704589..acc5e5b432f2a038355e24a2a00ba525bf24c1d6 100644 --- a/src/compute-node.ts +++ b/src/compute-node.ts @@ -1,6 +1,7 @@ import { Debug } from "./base"; import { ParamsEquation } from "./param/params-equation"; import { ParamDefinition } from "./param/param-definition"; +import { ParamValueMode } from "./param/param-values"; /** * type de calculette @@ -51,5 +52,16 @@ export abstract class ComputeNode extends Debug { return this._prms.getFirstAnalyticalParameter(); } + public initParametersValueMode(computedParam: ParamDefinition, variatedParam?: ParamDefinition, variatedMode?: ParamValueMode) { + for (const k in this._prms.map) { + if (k == computedParam.symbol) + this._prms.map[k].paramValues.valueMode = ParamValueMode.CALCUL; + else if (variatedParam && k == variatedParam.symbol) + this._prms.map[k].paramValues.valueMode = variatedMode; + else + this._prms.map[k].paramValues.valueMode = ParamValueMode.SINGLE; + } + } + protected abstract setParametersCalculability(): void; } diff --git a/src/nub.ts b/src/nub.ts index 0b3cf86cdd623d8a899530fefb128423709d4700..6ed251bdaa9a0f77a2468aeefcfe08fcf9e1c39b 100644 --- a/src/nub.ts +++ b/src/nub.ts @@ -1,7 +1,9 @@ -import { Debug, Serie } from "./base"; +import { Debug } from "./base"; import { Dichotomie } from "./dichotomie"; import { ComputeNode } from "./compute-node"; import { Result } from "./util/result"; +import { ParamValues, ParamValueMode } from "./param/param-values"; +import { ParamDefinition } from "."; /** * Classe abstraite de Noeud de calcul : classe de base pour tous les calculs @@ -58,13 +60,56 @@ export abstract class Nub extends ComputeNode { return res; } - public CalcSerie(svarCalc: string, serie: Serie): Result[] { - /** @todo faire une boucle pour appeler this.Calc avec chaque valeur de serie.values - * - */ - // let results = [new (Result)]; - const results = [new Result(0)]; - return results; + public CalcSerie(rPrec: number = 0.001, rInit?: number): Result { + const res = new Result(); + this._result = res; + + let variatedParam: ParamDefinition; + let computedParam: ParamDefinition; + for (const k in this._prms.map) { + const p: ParamDefinition = this._prms.map[k]; + + switch (p.valueMode) { + case ParamValueMode.LISTE: + case ParamValueMode.MINMAX: + if (variatedParam == undefined) + variatedParam = p; + else + throw new Error(`CalcSerie() : il y plusieurs paramètres à varier (au moins ${variatedParam.symbol} et ${p.symbol})`); + break; + + case ParamValueMode.CALCUL: + if (computedParam == undefined) + computedParam = p; + else + throw new Error(`CalcSerie() : il y plusieurs paramètres à calculer (au moins ${computedParam.symbol} et ${p.symbol})`); + break; + } + } + + if (computedParam == undefined) + throw new Error(`CalcSerie() : aucun paramètre à calculer`); + + if (rInit === undefined) + rInit = this._prms.map[computedParam.symbol].v; + + if (variatedParam == undefined) + this.Calc(computedParam.symbol, rInit, rPrec); // résultat dans this._result + else { + const res = new Result(); + variatedParam.paramValues.initIterator(); + while (variatedParam.paramValues.hasNext) { + variatedParam.paramValues.next; + this.Calc(computedParam.symbol, rInit, rPrec); // résultat dans this._result + res.addResultElement(this._result.resultElement); + res.addLog(this._result.log); + if (this._result.ok) + rInit = this._result.resultElement.vCalc; + } + this._result = res; + } + + return this._result; } /** diff --git a/src/param/param-values.ts b/src/param/param-values.ts index 266cb51a15ae48ee2491a55ae89b8991cf409825..f05578e86ade4afac04083ec3f9ee5d63402e098 100644 --- a/src/param/param-values.ts +++ b/src/param/param-values.ts @@ -82,11 +82,32 @@ export class ParamValueIterator implements IterableIterator<number> { } } + public get hasNext(): boolean { + switch (this._config) { + // valeur fixée + case 0: + return this._index == 0; + + // min/max + case 1: + const end = this._reverse ? this._index < this._param.min : this._index > this._param.max; + return !end; + + // liste + case 2: + const i = this._index; + return this._index >= this._param.valueList.length; + + default: + throw new Error(`ParamValueIterator.hasNext() : erreur interne`); + } + } + public next(): IteratorResult<number> { switch (this._config) { // valeur fixée case 0: - if (this._index == 0) + if (this.hasNext) return { done: false, value: this._param.singleValue @@ -100,8 +121,7 @@ export class ParamValueIterator implements IterableIterator<number> { // min/max case 1: const res = this._index; - const end = this._reverse ? this._index < this._param.min : this._index > this._param.max; - if (!end) { + if (this.hasNext) { if (this._reverse) this._index -= this._param.step; else @@ -120,7 +140,7 @@ export class ParamValueIterator implements IterableIterator<number> { // liste case 2: const i = this._index; - if (this._index < this._param.valueList.length) { + if (this.hasNext) { const res = this._param.valueList[this._index++]; return { done: false, @@ -182,6 +202,11 @@ export class ParamValues { */ private _valueList: number[]; + /** + * itérateur courant + */ + private _iterator: ParamValueIterator; + constructor() { this._singleValue = new DefinedNumber(); this.valueMode = ParamValueMode.CALCUL; @@ -280,10 +305,47 @@ export class ParamValues { this.valueMode = ParamValueMode.LISTE; } + /** + * crée un iterateur + * @param reverse true si on veut itérer max->min ou depuis la fin de la liste + */ public getValuesIterator(reverse: boolean = false): ParamValueIterator { return new ParamValueIterator(this, reverse); } + /** + * + * @param reverse prépare un itérateur pour parcourir les valeurs + */ + public initIterator(reverse: boolean = false) { + switch (this._valueMode) { + case ParamValueMode.LISTE: + case ParamValueMode.MINMAX: + break; + + default: + throw new Error(`ParamValues : mode de valeurs ${ParamValueMode[this._valueMode]} incorrect`); + } + + this._iterator = this.getValuesIterator(reverse); + } + + /** + * @return true si il reste des valeurs à parcourir par l'itérateur courant + */ + public get hasNext(): boolean { + return this._iterator.hasNext; + } + + /** + * fixe la valeur courante à la prochaine valeur à parcourir par l'itérateur courant + * @return prochaine valeur à parcourir par l'itérateur courant + */ + public get next(): number { + this._singleValue.value = this._iterator.next().value; + return this._singleValue.value; + } + /** * copie des membres */ diff --git a/src/remous.ts b/src/remous.ts index 45070fadac9e71a1cbec3912a644aa88c6b962da..3e02d648b599003609f2de6d1cdec9dd54496e1d 100644 --- a/src/remous.ts +++ b/src/remous.ts @@ -9,7 +9,7 @@ import { cLog } from "./util/log"; import { Message, MessageCode } from "./util/message"; import { Result } from "./util/result"; import { ResultElement } from "./util/resultelement"; -import { ParamValueIterator, ParamValues } from "."; +import { ParamValueIterator, ParamValues, BaseParam } from "."; export enum MethodeResolution { Trapezes, EulerExplicite, RungeKutta4 @@ -563,7 +563,8 @@ export class CourbeRemous extends Nub { `Condition limite aval (${this.prms.Yaval.v}) >= ` + `Hauteur critique (${this.Sn.HautCritique}) : calcul de la partie fluviale à partir de l'aval`); this.Dx = this.prms.Dx.v; - res = this.calcul(this.prms.Yaval.v, xValues.getValuesIterator(true)); + xValues.initIterator(true); + res = this.calcul(this.prms.Yaval.v, xValues); res.insertMessage(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL)); } else { this.debug( @@ -597,7 +598,8 @@ export class CourbeRemous extends Nub { ") <= Hauteur critique (" + this.Sn.HautCritique + ") : calcul de la partie torrentielle à partir de l'amont"); this.Dx = -this.prms.Dx.v; - res = this.calcul(this.prms.Yamont.v, xValues.getValuesIterator(false)); + xValues.initIterator(false); + res = this.calcul(this.prms.Yamont.v, xValues); res.insertMessage(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL)); } else { // this._log.add(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AMONT)); @@ -815,15 +817,16 @@ export class CourbeRemous extends Nub { * Calcul d'une courbe de remous en fluvial ou torrentiel * @param YCL Condition limite amont (torrentiel) ou aval (fluvial) */ - private calcul(YCL: number, valueIterator: ParamValueIterator): ResultElement { + private calcul(YCL: number, varParam: ParamValues): ResultElement { const trY: { [key: number]: number; } = {}; const res = new ResultElement(); let lastY = YCL; - trY[round(valueIterator.next().value, this.prmSect.iPrec.v)] = lastY; + trY[round(varParam.next, this.prmSect.iPrec.v)] = lastY; // Boucle de calcul de la courbe de remous - for (const x of valueIterator) { + while (varParam.hasNext) { + const x = varParam.next; // this.debug("lastY " + lastY); const rY: Result = this.Calc_Y(lastY); // this.debug("calcul : x " + x + " y " + rY.vCalc);