An error occurred while loading the file. Please try again.
-
Grand Francois authored
#45 Nub.getReferencedValuesIterator() : modif pour prendre en compte la désignation des valeurs ("xxx" pour un paramètre, "xxx." pour un résultat)
c1e22dc7
import { Debug } from "./base";
import { Dichotomie } from "./dichotomie";
import { ComputeNode } from "./compute-node";
import { Result } from "./util/result";
import { ParamValues } from "./param/param-values";
import { ParamValueMode } from "./param/param-value-mode";
import { ParamDefinition } from ".";
import { IReferencedNub } from "./value_ref/object_ref";
/**
* Classe abstraite de Noeud de calcul : classe de base pour tous les calculs
*/
export abstract class Nub extends ComputeNode implements IReferencedNub {
private _dichoStartIntervalMaxSteps: number = 100;
/**
* résultat de Calc()/CalcSerie()
*/
protected _result: Result;
/*
* paramétrage de la dichotomie
*/
/**
* étapes de recherche de l'intervalle de départ
*/
set dichoStartIntervalMaxSteps(n: number) {
this._dichoStartIntervalMaxSteps = n;
}
/**
* Formule utilisée pour le calcul analytique (solution directe ou méthode de résolution spécifique)
*/
public abstract Equation(sVarCalc: string): Result;
/**
* Calcul d'une équation quelque soit l'inconnue à calculer
* @param sVarCalc nom de la variable à calculer
* @param rInit valeur initiale de la variable à calculer dans le cas de la dichotomie
* @param rPrec précision de calcul
*/
public Calc(sVarCalc: string, rInit?: number, rPrec: number = 0.001): Result {
const computedVar = this.getParameter(sVarCalc);
if (rInit === undefined) {
rInit = computedVar.v;
}
if (computedVar.isAnalytical()) {
this._result = this.Equation(sVarCalc);
this._result.name = sVarCalc;
return this._result;
}
const resSolve: Result = this.Solve(sVarCalc, rInit, rPrec);
if (!resSolve.ok) {
this._result = resSolve;
this._result.name = sVarCalc;
return this._result;
}
const sAnalyticalPrm: string = this.getFirstAnalyticalParameter().symbol;
computedVar.setValue(resSolve.vCalc);
const res: Result = this.Equation(sAnalyticalPrm);
res.vCalc = resSolve.vCalc;
this._result = res;
this._result.name = sVarCalc;
return res;
}
/**
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
* effectue une série de calculs sur un paramètre
* @param rPrec précision de calcul
* @param rInit solution approximative du paramètre
* @param sDonnee éventuel symbole du paramètre à calculer
*/
public CalcSerie(rPrec: number = 0.001, rInit?: number, sDonnee?: string): Result {
let variatedParam: ParamDefinition;
let computedParam: ParamDefinition;
let prmValue: ParamValues; // instance de ParamValues utilisée pour le paramètre varié (qui peut être un paramètre référencé (importé))
for (const p of this.parameterIterator) {
switch (p.valueMode) {
case ParamValueMode.SINGLE:
break;
case ParamValueMode.LISTE:
case ParamValueMode.MINMAX:
if (variatedParam == undefined) {
variatedParam = p;
prmValue = p.paramValues;
}
else
throw new Error(`CalcSerie() : il y plusieurs paramètres à varier (au moins ${variatedParam.symbol} et ${p.symbol})`);
break;
case ParamValueMode.CALCUL:
if (sDonnee == undefined) {
if (computedParam == undefined)
computedParam = p;
else
throw new Error(`CalcSerie() : il y plusieurs paramètres à calculer (au moins ${computedParam.symbol} et ${p.symbol})`);
}
break;
case ParamValueMode.LINK:
if (p.referencedParamValues !== undefined)
switch (p.referencedParamValues.valueMode) {
case ParamValueMode.SINGLE:
break;
case ParamValueMode.LISTE:
case ParamValueMode.MINMAX:
if (variatedParam == undefined) {
variatedParam = p;
prmValue = p.referencedParamValues;
}
else
throw new Error(`CalcSerie() : il y plusieurs paramètres à varier (au moins ${variatedParam.symbol} et ${p.symbol})`);
break;
case ParamValueMode.CALCUL:
if (sDonnee == undefined) {
if (computedParam == undefined)
computedParam = p;
else
throw new Error(`CalcSerie() : il y plusieurs paramètres à calculer (au moins ${computedParam.symbol} et ${p.symbol})`);
}
break;
default:
throw new Error(`CalcSerie() : valeur référencée de ParamValueMode ${ParamValueMode[p.referencedParamValues.valueMode]} non prise en charge`);
}
break;
default:
throw new Error(`CalcSerie() : valeur de ParamValueMode ${ParamValueMode[p.valueMode]} non prise en charge`);
}
}
if (sDonnee)
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
var computedSymbol: string = sDonnee;
else {
if (computedParam == undefined)
throw new Error(`CalcSerie() : aucun paramètre à calculer`);
computedSymbol = computedParam.symbol;
}
if (rInit === undefined)
rInit = computedParam.v;
if (variatedParam == undefined)
this._result = this.Calc(computedSymbol, rInit, rPrec); // résultat dans this._result
else {
const res = new Result();
prmValue.initIterator();
while (prmValue.hasNext) {
prmValue.next;
this.Calc(computedSymbol, rInit, rPrec); // résultat dans this._result
if (this._result.ok) {
res.addResultElement(this._result.resultElement);
res.addLog(this._result.log);
rInit = this._result.resultElement.vCalc;
}
res.globalLog.addLog(this._result.globalLog);
}
this._result = res;
}
this._result.name = computedSymbol;
return this._result;
}
/**
* Résoud l'équation par une méthode numérique
* @param sVarCalc nom de la variable à calculer
* @param rInit valeur initiale de la variable à calculer dans le cas de la dichotomie
* @param rPrec précision de calcul
*/
private Solve(sVarCalc: string, rInit: number, rPrec: number): Result {
const dicho: Dichotomie = new Dichotomie(this, sVarCalc, this.DBG);
dicho.startIntervalMaxSteps = this._dichoStartIntervalMaxSteps;
const target = this.getFirstAnalyticalParameter();
return dicho.Dichotomie(target.v, rPrec, rInit);
}
public get result(): Result {
return this._result;
}
// interface IReferencedNub
public getReferencedParamValues(desc: string): ParamValues {
return this.getParameter(desc).paramValues;
}
public getReferencedResult(desc?: string): Result {
if (desc === undefined || (this._result !== undefined && this._result.name === desc))
return this._result;
return this.CalcSerie(0.001, 0.1, desc); // 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
}
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): IterableIterator<number> {
const tmp = desc.split(".");
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
if (tmp.length > 1 && tmp[1] === "")
if (this._result !== undefined && this._result.name === tmp[0])
return this._result.valuesIterator;
const p = this.getParameter(desc);
switch (p.paramValues.valueMode) {
case ParamValueMode.SINGLE:
case ParamValueMode.MINMAX:
case ParamValueMode.LISTE:
return p.paramValues.valuesIterator;
case ParamValueMode.CALCUL:
return this.getReferencedResult(desc).valuesIterator;
case ParamValueMode.LINK:
throw new Error(`Nub.getReferencedValuesIterator() : mode de valeur ${ParamValueMode[p.paramValues.valueMode]} invalide pour le paramètre référencé par ${desc}`);
}
}
/**
* @returns liste des paramètres liables à un paramètre
* @param p paramètre qui sert de clé de recherche des paramètres liables
*/
// public getLinkableParameters(param: ParamDefinition): any[] {
// const res: any[] = [];
// for (const p of this._prms)
// if (p.uid !== param.uid)
// switch (p.valueMode) {
// case ParamValueMode.SINGLE:
// case ParamValueMode.MINMAX:
// case ParamValueMode.LISTE:
// switch (param.symbol) {
// case "Z1":
// case "Z2":
// if (p.symbol === "Z1" || p.symbol === "Z2")
// res.push({ "param": p, "nub": this });
// break;
// default:
// if (p.symbol === param.symbol)
// res.push({ "param": p, "nub": this });
// }
// }
// return res;
// }
private addPrefix(str: string, prefix: string) {
return prefix === undefined ? str : `${prefix}${str}`;
}
/**
* 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":NamedIterableValues, "nub":Nub}, nub=Nub d'origine de la "value"
*/
public getLinkableValues(src: any, prefix?: string): any[] {
const res: any[] = [];
const isStr = typeof (src) === "string";
const name = isStr ? src : src.name;
const hasUid = isStr ? false : "uid" in src;
// paramètres
for (const p of this._prms) {
const cond = hasUid ? p.uid !== src.uid : true; // pour éviter d'ajouter le paramètre d'entrée dans le tableau résultat
if (cond)
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
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 });
}
}
}
// résultat
if (this._result !== undefined) {
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 });
}
return res;
}
}