Newer
Older
import { isNumeric } from "./base";
import { CalculatorType, SectionType } from "./compute-node";
import { config } from "./config";
import { LCMaterial } from "./lc-material";
import { LinkedValue } from "./linked-value";
import { ParamDefinition } from "./param/param-definition";
import { SessionSettings } from "./session_settings";
import { Grille, GrilleProfile, GrilleType } from "./devalaison/grille";
import { GrilleParams } from "./devalaison/grille_params";
import { Jet } from "./devalaison/jet";
import { JetParams } from "./devalaison/jet_params";
import { ConcentrationBlocs } from "./macrorugo/concentration_blocs";
import { ConcentrationBlocsParams } from "./macrorugo/concentration_blocs_params";
import { MacroRugo } from "./macrorugo/macrorugo";
import { MacrorugoCompound } from "./macrorugo/macrorugo_compound";
import { MacrorugoCompoundParams } from "./macrorugo/macrorugo_compound_params";
import { MacrorugoParams } from "./macrorugo/macrorugo_params";
import { MRCInclination } from "./macrorugo/mrc-inclination";
import { SPP, SPPOperation } from "./math/spp";
import { SPPParams } from "./math/spp_params";
import { Trigo, TrigoOperation, TrigoUnit } from "./math/trigo";
import { TrigoParams } from "./math/trigo_params";
import { YAXB } from "./math/yaxb";
import { YAXBParams } from "./math/yaxb_params";
import { YAXN } from "./math/yaxn";
import { YAXNParams } from "./math/yaxn_params";
import { Bief } from "./open-channel/bief";
import { BiefParams, BiefRegime } from "./open-channel/bief_params";
import { MethodeResolution } from "./open-channel/methode-resolution";
import { Pente } from "./open-channel/pente";
import { PenteParams } from "./open-channel/pente_params";
import { RegimeUniforme } from "./open-channel/regime_uniforme";
import { CourbeRemous } from "./open-channel/remous";
import { CourbeRemousParams } from "./open-channel/remous_params";
import { cSnCirc } from "./open-channel/section/section_circulaire";
import { ParamsSectionCirc } from "./open-channel/section/section_circulaire_params";
import { SectionParametree } from "./open-channel/section/section_parametree";
import { cSnPuiss } from "./open-channel/section/section_puissance";
import { ParamsSectionPuiss } from "./open-channel/section/section_puissance_params";
import { cSnRectang } from "./open-channel/section/section_rectang";
import { ParamsSectionRectang } from "./open-channel/section/section_rectang_params";
import { cSnTrapez } from "./open-channel/section/section_trapez";
import { ParamsSectionTrapez } from "./open-channel/section/section_trapez_params";
import { acSection } from "./open-channel/section/section_type";
import { CloisonsAvalParams } from "./pab/cloison_aval_params";
David Dorchies
committed
import { Cloisons } from "./pab/cloisons";
import { CloisonsParams } from "./pab/cloisons_params";
import { Pab } from "./pab/pab";
import { PabChute } from "./pab/pab_chute";
import { PabChuteParams } from "./pab/pab_chute_params";
import { PabDimension } from "./pab/pab_dimension";
import { PabDimensionParams } from "./pab/pab_dimensions_params";
import { PabNombre } from "./pab/pab_nombre";
import { PabNombreParams } from "./pab/pab_nombre_params";
import { PabParams } from "./pab/pab_params";
import { PabPuissance } from "./pab/pab_puissance";
import { PabPuissanceParams } from "./pab/pab_puissance_params";
import { ConduiteDistrib } from "./pipe_flow/cond_distri";
import { ConduiteDistribParams } from "./pipe_flow/cond_distri_params";
import { LechaptCalmon } from "./pipe_flow/lechaptcalmon";
import { LechaptCalmonParams } from "./pipe_flow/lechaptcalmon_params";
import { Solveur } from "./solveur/solveur";
import { SolveurParams } from "./solveur/solveur_params";
import { Dever } from "./structure/dever";
import { DeverParams } from "./structure/dever_params";
francois.grand
committed
import { CreateStructure } from "./structure/factory_structure";
import { ParallelStructure } from "./structure/parallel_structure";
import { ParallelStructureParams } from "./structure/parallel_structure_params";
import { LoiDebit, StructureType } from "./structure/structure_props";
import { Par, ParType } from "./par/par";
import { ParParams } from "./par/par_params";
import { ParSimulation } from "./par/par_simulation";
import { ParSimulationParams } from "./par/par_simulation_params";
import { FishSpecies } from "./verification/fish_species";
import { Espece } from "./verification/espece";
import { EspeceParams } from "./verification/espece_params";
import { Verificateur } from "./verification/verificateur";
David Dorchies
committed
/** correspondance entre les noms des propriétés et les enum associés */
public static enumFromProperty: any = {
loiDebit: LoiDebit,
methodeResolution: MethodeResolution,
material: LCMaterial,
gridProfile: GrilleProfile,
gridType: GrilleType,
regime: BiefRegime,
trigoOperation: TrigoOperation,
trigoUnit: TrigoUnit,
sppOperation: SPPOperation,
calcType: CalculatorType,
structureType: StructureType,
public static getInstance(): Session {
if (Session._instance === undefined) {
Session._instance = new Session();
/**
* Returns a copy of given map, inverting enum keys and values
*/
public static invertEnumKeysAndValuesInProperties(stringProps: any, forceNumbers: boolean = false) {
const res = JSON.parse(JSON.stringify(stringProps)); // clone
for (const k in res) {
if (!forceNumbers || !isNumeric(res[k])) {
if (Object.keys(Session.enumFromProperty).includes(k)) {
const enumClass = Session.enumFromProperty[k];
res[k] = enumClass[res[k]];
}
}
}
return res;
}
/** instance pour le pattern singleton */
private static _instance: Session;
/** free documentation text, in Markdown format, to save into session file (optional) */
public documentation = "";
/** Nubs de la session */
private _nubs: Nub[] = [];
francois.grand
committed
/**
* @param props propriétés du Nub (computeType, nodeType...)
francois.grand
committed
*/
public createSessionNub(p: Props, dbg: boolean = false): Nub {
const res = this.createNub(p, undefined, dbg);
francois.grand
committed
return res;
}
/**
* Adds an existing Nub to the session
*/
public registerNub(n: Nub) {
if (this.uidAlreadyUsed(n.uid)) {
n.setUid(Nub.nextUID);
}
/**
* Adds many existing Nubs to the session
*/
public registerNubs(nubs: Nub[]) {
for (const n of nubs) {
this.registerNub(n);
}
}
/**
* Removes all Nubs from the Session
*/
public clear() {
this._nubs = [];
}
/**
* Returns number of Nubs in the session
*/
public getNumberOfNubs() {
return this._nubs.length;
}
/** Accessor for Nubs list */
public getAllNubs() {
return this._nubs;
}
mathias.chouet
committed
* Removes a Nub from the session; does not consider Structure nubs inside Calculator nubs
* @param sn the Nub to remove from the session
throw new Error(`Session.deleteNub() : le Nub (uid ${sn.uid}) à supprimer n'a pas été trouvé`);
/**
* Returns a JSON representation of (a part of) the current session
* @param options an object having Nub uids as keys, with extra data object as values;
* if empty or undefined, all Nubs are serialised
* @param settings app preferences to store in the session file (decimals, precision…)
public serialise(options?: { [key: string]: {} }, settings?: { [key: string]: {} }): string {
const sess: any[] = [];
// session-wide settings
let sessionSettings = {
precision: SessionSettings.precision,
maxIterations: SessionSettings.maxIterations
};
if (settings) {
sessionSettings = {...sessionSettings, ...settings};
}
// nubs in session
let idsWithChildren: string[];
if (options) {
ids = Object.keys(options);
idsWithChildren = [...ids];
// add ids of children
for (const n of this._nubs) {
if (ids.includes(n.uid)) {
for (const c of n.getChildren()) {
idsWithChildren.push(c.uid);
}
}
}
for (const n of this._nubs) {
if (ids === undefined || ids.length === 0) {
sess.push(n.objectRepresentation(undefined, ids));
} else if (ids.includes(n.uid)) {
sess.push(n.objectRepresentation(options[n.uid], idsWithChildren));
return JSON.stringify({
header: {
source: "jalhyd",
format_version: config.serialisation.fileFormatVersion,
documentation: this.documentation,
}
/**
* Loads (a part of) a session from a JSON representation
* @param serialised JSON data
* @param uids unserialise only the Nubs havin the given UIDs
public unserialise(serialised: string, uids?: string[]): { nubs: any[], hasErrors: boolean, settings: any } {
const ret: { nubs: any[], hasErrors: boolean, settings: any } = {
hasErrors: false,
settings: {}
// unserialise to object
const data = JSON.parse(serialised);
// settings
if (data.settings) {
ret.settings = data.settings;
if (data.settings.precision !== undefined) {
SessionSettings.precision = data.settings.precision;
}
if (data.settings.maxIterations !== undefined) {
SessionSettings.maxIterations = data.settings.maxIterations;
}
}
// nubs
if (data.session && Array.isArray(data.session)) {
data.session.forEach((e: any) => {
if (!uids || uids.length === 0 || uids.includes(e.uid)) {
const nubPointer = this.createNubFromObjectRepresentation(e);
ret.nubs.push(nubPointer);
// forward errors
if (nubPointer.hasErrors) {
ret.hasErrors = true;
}
}
});
}
// concatenate doc
if (data.documentation !== undefined && data.documentation !== "") {
this.documentation += `\n\n` + data.documentation;
mathias.chouet
committed
// second pass for links
const flRes = this.fixLinks(serialised, uids);
// forward errors
if (flRes.hasErrors) {
ret.hasErrors = true;
}
// second pass for Solveurs
const fsRes = this.fixSolveurs(serialised, uids);
// forward errors
if (fsRes.hasErrors) {
ret.hasErrors = true;
}
mathias.chouet
committed
}
/**
mathias.chouet
committed
* Creates a Nub from a JSON representation and adds it to the current session; returns
* a pointer to the Nub and its JSON metadata
* @param serialised JSON representation of a single Nub
* @param register if false, new Nub will just be returned and won't be registered into the session
public unserialiseSingleNub(serialised: string, register: boolean = true): { nub: Nub, meta: any } {
return this.createNubFromObjectRepresentation(JSON.parse(serialised), register);
}
/**
* Returns the Nub identified by uid if any
*/
public findNubByUid(uid: string): Nub {
let foundNub: Nub;
outerLoop:
for (const n of this._nubs) {
if (n.uid === uid) {
foundNub = n;
}
for (const s of n.getChildren()) {
if (s.uid === uid) {
foundNub = s;
break outerLoop;
}
}
}
return foundNub;
* Crée un Nub à partir d'une description (Props)
* @param params propriétés à partir desquelles on détermine la classe du Nub à créer
* - calcType: type de Nub
* - nodeType: pour un Nub contenant une section
* - loiDebit: pour un Nub de type Structure (calcType doit être CalculatorType.Structure)
* Si d'autres propriétés sont fournies, elle écraseront les éventuelles propriétés par défaut
* définies dans le constructeur du Nub créé
public createNub(params: Props, parentNub?: Nub, dbg: boolean = false): Nub {
francois.grand
committed
const calcType: CalculatorType = params.getPropValue("calcType");
case CalculatorType.ConduiteDistributrice:
prms = new ConduiteDistribParams(
3, // débit Q
1.2, // diamètre D
0.6, // perte de charge J
100, // Longueur de la conduite Lg
1e-6, // Viscosité dynamique Nu
);
nub = new ConduiteDistrib(prms, dbg);
break;
case CalculatorType.LechaptCalmon:
prms = new LechaptCalmonParams(
3, // débit
1.2, // diamètre
0.6, /// perte de charge
100, // longueur du toyo
1.863, // paramètre L du matériau
2, // paramètre M du matériau
5.33, // paramètre N du matériau
0 // Ks Perte de charge singulière
);
nub = new LechaptCalmon(prms, dbg);
break;
case CalculatorType.SectionParametree:
nub = new SectionParametree(undefined, dbg);
break;
case CalculatorType.RegimeUniforme:
nub = new RegimeUniforme(undefined, dbg);
break;
case CalculatorType.CourbeRemous:
prms = new CourbeRemousParams(
100.25, // Z1 = cote de l'eau amont
100.4, // Z2 = cote de l'eau aval
100.1, // ZF1 = cote de fond amont
100, // ZF2 = cote de fond aval
100, // Long = Longueur du bief
5, // Dx = Pas d'espace
);
nub = new CourbeRemous(undefined, prms, MethodeResolution.EulerExplicite, dbg);
break;
case CalculatorType.PabDimensions:
prms = new PabDimensionParams(
2, // Longueur L
1, // Largeur W
0.5, // Tirant d'eau Y
2 // Volume V
);
nub = new PabDimension(prms, dbg);
break;
case CalculatorType.PabPuissance:
prms = new PabPuissanceParams(
0.3, // Chute entre bassins DH (m)
0.1, // Débit Q (m3/s)
0.5, // Volume V (m3)
588.6 // Puissance dissipée PV (W/m3)
);
nub = new PabPuissance(prms, dbg);
break;
case CalculatorType.Structure:
const loiDebit: LoiDebit = params.getPropValue("loiDebit");
nub = CreateStructure(loiDebit, (parentNub as ParallelStructure));
break;
case CalculatorType.ParallelStructure:
prms = new ParallelStructureParams(
0.5, // Q
102, // Z1
101.5 // Z2
);
nub = new ParallelStructure(prms, dbg);
break;
case CalculatorType.Dever:
const deverPrms = new DeverParams(
0.5, // Q
102, // Z1
10, // BR : largeur du cours d'eau
99 // ZR : cote du lit du cours d'eau
);
nub = new Dever(deverPrms, dbg);
break;
case CalculatorType.Cloisons:
nub = new Cloisons(
new CloisonsParams(
1.5, // Débit total (m3/s)
102, // Cote de l'eau amont (m)
10, // Longueur des bassins (m)
1, // Largeur des bassins (m)
1, // Profondeur moyenne (m)
0.5 // Hauteur de chute (m)
), dbg
);
break;
case CalculatorType.MacroRugo:
nub = new MacroRugo(
new MacrorugoParams(
12.5, // ZF1
6, // L
1, // B
0.05, // If
1.57, // Q
0.6, // h
0.01, // Ks
0.4, // D
0.4, // k
case CalculatorType.PabChute:
nub = new PabChute(
new PabChuteParams(
2, // Z1
0.5, // Z2
1.5 // DH
), dbg
);
break;
case CalculatorType.PabNombre:
nub = new PabNombre(
new PabNombreParams(
6, // DHT
10, // N
0.6 // DH
), dbg
);
break;
const nodeType: SectionType = params.getPropValue("nodeType");
nub = this.createSection(nodeType, dbg);
break;
case CalculatorType.Pab:
nub = new Pab(
new PabParams(
1.5, // Q
102, // Z1
99 // Z2
prms = new CloisonsAvalParams(
);
nub = new CloisonAval(prms, dbg);
break;
}
case CalculatorType.MacroRugoCompound:
nub = new MacrorugoCompound(
new MacrorugoCompoundParams(
13.1, // Z1
0.4, // D
0.4, // k
David Dorchies
committed
nub = new Jet(
new JetParams(
5, // V0
0.03, // S
30, // ZJ
29.2, // ZW
28.5, // ZF
David Dorchies
committed
3 // D
)
);
break;
nub = new Grille(
new GrilleParams(
10, // QMax
100, // CRad
101.5, // CEau
101.5, // CSomGrille
2, // B
72, // Beta
90, // Alpha
20, // b
20, // p
20, // e
2, // a
1.5, // c
0.1, // OEntH
4 // cIncl
case CalculatorType.Pente:
nub = new Pente(
new PenteParams(
101, // Z1
99.5, // Z2
10, // L
0.15 // I
)
);
break;
case CalculatorType.Bief:
nub = new Bief(
undefined,
new BiefParams(
100.25, // Z1 = cote de l'eau amont
100.4, // Z2 = cote de l'eau aval
100.1, // ZF1 = cote de fond amont
100, // ZF2 = cote de fond aval
100, // Long = Longueur du bief
5, // Dx = Pas d'espace
),
dbg
);
break;
case CalculatorType.Solveur:
nub = new Solveur(
new SolveurParams(undefined)
);
break;
case CalculatorType.YAXB:
nub = new YAXB(
new YAXBParams(
10, // Y
2, // A
3, // X
4 // B
),
dbg
);
break;
case CalculatorType.Trigo:
nub = new Trigo(
new TrigoParams(
0.985, // Y
10 // X
),
dbg
);
break;
case CalculatorType.SPP:
nub = new SPP(
new SPPParams(
1 // Y
),
dbg
);
break;
case CalculatorType.YAXN:
nub = new YAXN(
new YAXNParams(
1, // A
1, // X
1 // B
),
dbg
);
break;
case CalculatorType.ConcentrationBlocs:
nub = new ConcentrationBlocs(
new ConcentrationBlocsParams(
0.128, // Concentration de blocs
5, // Nombre de motifs
4.9, // Largeur de la passe
0.35 // Diamètre des plots
case CalculatorType.Par:
nub = new Par(
new ParParams(
0.25, // Q
10, // Z1
9, // Z2
0.2, // S
0.4, // P
0.6, // L
0.1, // a
1, // N
1 // M
)
);
break;
case CalculatorType.ParSimulation:
nub = new ParSimulation(
new ParSimulationParams(
0.25, // Q
10, // Z1
9, // Z2
0.2, // S
0.4, // P
undefined, // Nb
undefined, // ZD2
0.6, // L
0.1, // a
1, // N
1 // M
)
);
break;
case CalculatorType.Espece:
nub = new Espece(
// default params are those for SPECIES_1 (Salmons and trouts)
new EspeceParams(
0.35, // DHMaxS
0.35, // DHMaxP
0.3, // BMin
1, // PMinS
1, // PMinP
2.5, // LMinS
2.5, // LMinP
2.5, // VeMax
)
);
break;
case CalculatorType.Verificateur:
nub = new Verificateur();
default:
throw new Error(
`Session.createNub() : type de module '${CalculatorType[calcType]}' non pris en charge`
);
try {
nub.properties = params;
} catch (e) {
// loading Solveur properties when unserialising a session might fail because target
// Nub / param do not exist yet; silent fail in this case, and Solveur.fixTargets()
// might fix it later
if (! (nub instanceof Solveur)) {
throw e;
}
}
mathias.chouet
committed
* Returns true if given uid is already used by a Nub in this session,
* or a Structure nub inside one of them
*/
public uidAlreadyUsed(uid: string): boolean {
let alreadyUsed = false;
outerLoop:
for (const n of this._nubs) {
if (n.uid === uid) {
alreadyUsed = true;
break outerLoop;
}
for (const s of n.getChildren()) {
if (s.uid === uid) {
alreadyUsed = true;
break outerLoop;
mathias.chouet
committed
}
}
}
return alreadyUsed;
}
/**
* Returns all Nubs depending on the given one (parameter or result),
* without following links (1st level only)
* @param uid UID of the Nub that underwent a change
* @param symbol symbol of the parameter whose value change triggered this method; if specified,
* Nubs targetting this symbol will be considered dependent
* @param includeValuesLinks if true, even Nubs targetting non-calculated non-modified parameters
* will be considered dependent @see jalhyd#98
* @param includeOtherDependencies if true, will be considered dependent
* - Solveur Nubs having given Nub either as X or as Ytarget's parent Nub
* - Verificateur Nubs having given Nub either as selected Custom Species or Pass to check
*/
public getDependingNubs(
uid: string,
symbol?: string,
includeValuesLinks: boolean = false,
includeOtherDependencies: boolean = false
): Nub[] {
const dependingNubs: Nub[] = [];
for (const n of this._nubs) {
if (
n.uid !== uid
&& n.resultDependsOnNub(uid, [], symbol, includeValuesLinks, includeOtherDependencies)
dependingNubs.push(n);
}
}
return dependingNubs;
}
/**
* Returns all Nubs depending on the result of at least one other Nub.
* Used by Solveur to find available "target" nubs to calculate.
*/
public getDownstreamNubs(): Nub[] {
const downstreamNubs: Nub[] = [];
for (const n of this._nubs) {
if (n.getRequiredNubs().length > 0) {
downstreamNubs.push(n);
}
}
return downstreamNubs;
}
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
/**
* Returns all Nubs that do not depend on the result of any other Nub
* (includes single Nubs).
*/
public getUpstreamNubs(): Nub[] {
const upstreamNubs: Nub[] = [];
for (const n of this._nubs) {
if (n.getRequiredNubs().length === 0) {
upstreamNubs.push(n);
}
}
return upstreamNubs;
}
/**
* Returns all upstream Nubs that have at least one declared extra result.
* Used by Solveur to find available "target" nubs to calculate.
*/
public getUpstreamNubsHavingExtraResults() {
const unher: Nub[] = [];
for (const n of this.getUpstreamNubs()) {
if (n.resultsFamilies && Object.keys(n.resultsFamilies).length > 0) {
unher.push(n);
}
}
return unher;
}
* Returns a list of nub/symbol couples, that can be linked to the given
* @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);
}
/* console.log("LINKABLE VALUES", res.map((lv) => {
return `${lv.nub.uid}(${lv.nub.constructor.name})/${lv.symbol}`;
})); */
public createSection(nt: SectionType, dbg: boolean = false): acSection {
case SectionType.SectionTrapeze: {
const prms = new ParamsSectionTrapez(2.5, // largeur de fond
0.56, // fruit
0.8, // tirant d'eau
40, // Ks=Strickler
1.2, // Q=Débit
0.001, // If=pente du fond
1, // YB= hauteur de berge
);
case SectionType.SectionRectangle: {
const prms = new ParamsSectionRectang(0.8, // tirant d'eau
2.5, // largeur de fond
40, // Ks=Strickler
1.2, // Q=Débit
0.001, // If=pente du fond
1 // YB=hauteur de berge
);
return new cSnRectang(prms, dbg);
}
case SectionType.SectionCercle: {
const prms = new ParamsSectionCirc(2, // diamètre
0.8, // tirant d'eau
40, // Ks=Strickler
1.2, // Q=Débit
0.001, // If=pente du fond
1, // YB= hauteur de berge
);
return new cSnCirc(prms, dbg);
}
case SectionType.SectionPuissance: {
const prms = new ParamsSectionPuiss(0.5, // coefficient
0.8, // tirant d'eau
4, // largeur de berge
40, // Ks=Strickler
1.2, // Q=Débit
0.001, // If=pente du fond
1, // YB= hauteur de berge
);
return new cSnPuiss(prms, dbg);
}
throw new Error(`type de section ${SectionType[nt]} non pris en charge`);
/**
* 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
* @param register if false, new Nub will just be returned and won't be registered into the session
private createNubFromObjectRepresentation(obj: any, register: boolean = true)
: { nub: Nub, meta: any, hasErrors: boolean } {
// return value;
const nubPointer: { nub: Nub, meta: any, hasErrors: boolean } = {
nub: undefined,
meta: undefined,
hasErrors: false
};
// decode properties
const props = Session.invertEnumKeysAndValuesInProperties(obj.props, true);
newNub = this.createSessionNub(new Props(props));
newNub = this.createNub(new Props(props));
const res = newNub.loadObjectRepresentation(obj);
// forward errors
if (res.hasErrors) {
nubPointer.hasErrors = true;
}
// add metadata (used by GUI, for ex.)
if (obj.meta) {
nubPointer.meta = obj.meta;
}
return nubPointer;
}
/**
* Asks all loaded Nubs to relink any parameter that has a wrong target
*/
private fixLinks(serialised: string, uids?: string[]): { hasErrors: boolean } {
// return value
const res = {
hasErrors: false
};
const data = JSON.parse(serialised);
if (data.session && Array.isArray(data.session)) {
// find each corresponding Nub in the session
if (!uids || uids.length === 0 || uids.includes(e.uid)) {
const nub = this.findNubByUid(e.uid);
// find linked parameters
const ret = nub.fixLinks(e);
// forwardErrors
if (ret.hasErrors) {
res.hasErrors = true;
}
/**
* Asks every loaded Solveur to reconnect to its nubToCalculate / searchedParameter
*/
private fixSolveurs(serialised: string, uids?: string[]): { hasErrors: boolean } {
// return value
const res = {
hasErrors: false
};
const data = JSON.parse(serialised);
if (data.session && Array.isArray(data.session)) {
// find each corresponding Nub in the session
data.session.forEach((e: any) => {
if (!uids || uids.length === 0 || uids.includes(e.uid)) {
const nub = this.findNubByUid(e.uid);
if (nub instanceof Solveur) {
// find targetted nubToCalculate / searchedParam
const ret = nub.fixTargets(e);
// forwardErrors
if (ret.hasErrors) {