session.ts 19.81 KiB
import { CalculatorType, ComputeNodeType } from "./compute-node";
import { LinkedValue } from "./linked-value";
import { Nub } from "./nub";
import { Props } from "./props";
// Calculettes
import { ConduiteDistrib, ConduiteDistribParams } from "./cond_distri";
import { LechaptCalmon, LechaptCalmonParams } from "./lechaptcalmon";
import { MacroRugo, MacrorugoParams } from "./macrorugo/macrorugo";
import { PabChute, PabChuteParams } from "./pab/pab_chute";
import { PabDimension, PabDimensionParams } from "./pab/pab_dimension";
import { PabNombre, PabNombreParams } from "./pab/pab_nombre";
import { PabPuissance, PabPuissanceParams } from "./pab/pab_puissance";
import { RegimeUniforme } from "./regime_uniforme";
import { CourbeRemous, CourbeRemousParams, MethodeResolution } from "./remous";
import { SectionParametree } from "./section/section_parametree";
// Classes relatives aux sections
import { cSnCirc, ParamsSectionCirc } from "./section/section_circulaire";
import { cSnPuiss, ParamsSectionPuiss } from "./section/section_puissance";
import { cSnRectang, ParamsSectionRectang } from "./section/section_rectang";
import { cSnTrapez, ParamsSectionTrapez } from "./section/section_trapez";
import { acSection } from "./section/section_type";
// Classes relatives aux structures
import { Pab, PabParams } from "./pab/pab";
import { PabCloisons } from "./pab/pab_cloisons";
import { ParamDefinition } from "./param/param-definition";
import { Cloisons } from "./structure/cloisons";
import { CloisonsParams } from "./structure/cloisons_params";
import { Dever, DeverParams } from "./structure/dever";
import { CreateStructure } from "./structure/factory_structure";
import { ParallelStructure, ParallelStructureParams } from "./structure/parallel_structure";
import { LoiDebit } from "./structure/structure_props";
export class Session {
    public static getInstance() {
        if (Session._instance === undefined) {
            Session._instance = new Session();
        return Session._instance;
    /** instance pour le pattern singleton */
    private static _instance: Session;
    private defaultPrecision: number = 0.001;
    /** Nubs de la session */
    private _nubs: Nub[];
    constructor() {
        this._nubs = [];
    /**
     * crée un Nub et l'ajoute à la session
     * @param props propriétés du Nub (computeType, nodeType...)
    public createSessionNub(p: Props, dbg: boolean = false): Nub {
        const res = this.createNub(p, undefined, dbg);
        this._nubs.push(res);
        return res;
    /**
     * Adds an existing Nub to the session
    public registerNub(n: Nub) {
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
this._nubs.push(n); } /** * Removes all Nubs from the Session */ public clear() { this._nubs = []; } /** * Returns number of Nubs in the session */ public getNumberOfNubs() { return this._nubs.length; } /** * Removes a Nub from the session; does not consider Structure nubs inside Calculator nubs * @param sn the Nub to remove from the session */ public deleteNub(sn: Nub) { let i = 0; for (const n of this._nubs) { if (n.uid === sn.uid) { this._nubs.splice(i, 1); return; } i++; } 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 */ public serialise(options?: { [key: string]: {} }): string { const sess: any[] = []; let ids: string[] = []; if (options) { ids = Object.keys(options); } for (const n of this._nubs) { if (ids.length === 0) { sess.push(n.objectRepresentation()); } else if (ids.includes(n.uid)) { sess.push(n.objectRepresentation(options[n.uid])); } } return JSON.stringify({ header: { source: "jalhyd", format_version: "1.0", // don't forget to update this number when modifying session file structure, created: (new Date()).toISOString() }, session: sess }); } /** * Loads (a part of) a session from a JSON representation * @param serialised JSON data */ public unserialise(serialised: string, uids?: string[]) { const newNubs: any[] = []; // unserialise to object const data = JSON.parse(serialised); if (data.session && Array.isArray(data.session)) {
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
// for each Nub representation, create the corresponding Nub in the session data.session.forEach((e: any) => { if (! uids || uids.length === 0 || uids.includes(e.uid)) { const nubPointer = this.createNubFromObjectRepresentation(e); newNubs.push(nubPointer); } }); } // second pass for links this.fixLinks(serialised, uids); // second pass for PABs this.fixPAB(serialised, uids); return newNubs; } /** * Creates a Nub from a JSON representation and adds it tot he current session; returns * a pointer to the Nub and its JSON metadata * @param serialised JSON representation of a single Nub */ public unserialiseSingleNub(serialised: string): { nub: Nub, meta: any } { return this.createNubFromObjectRepresentation(JSON.parse(serialised)); } /** * 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 paramètres supplémentaires spécifiques * - calcType: type de Nub * - nodeType: sous type de Nub * @param dbg activer débogage */ public createNub(params: Props, parentNub?: Nub, dbg: boolean = false): Nub { const calcType: CalculatorType = params.getPropValue("calcType"); const nodeType: ComputeNodeType = params.getPropValue("nodeType"); let nub: Nub; let prms: any; switch (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
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
); 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 ); 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( 0.15, // Yamont = tirant amont 0.4, // Yaval = tirant 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: {
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
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.05, // C 0.5, // D 0.8, // k 1.5 // Cd0 ), dbg ); break; } case CalculatorType.PabChute: { nub = new PabChute( new PabChuteParams( 2, // Z1 0.5, // Z2 1.5 // DH
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
), dbg ); break; } case CalculatorType.PabNombre: { nub = new PabNombre( new PabNombreParams( 6, // DHT 10, // N 0.6 // DH ), dbg ); break; } case CalculatorType.Section: { nub = this.createSection(nodeType, dbg); break; } case CalculatorType.Pab: nub = new Pab( new PabParams( 1.5, // Q 102, // Z1 99 // Z2 ), undefined, dbg ); break; case CalculatorType.PabCloisons: const modeleCloisons: string = params.getPropValue("modeleCloisons"); if (modeleCloisons) { const cloisons = (Session.getInstance().findNubByUid(modeleCloisons) as Cloisons); // si le module Cloisons ciblé n'existe pas, Session.fixPAB() est censé s'en occuper nub = new PabCloisons(cloisons); } else { nub = new PabCloisons(undefined); // don't forget to init with a Cloisons model afterwards ! } break; default: { throw new Error( // tslint:disable-next-line:max-line-length `Session.createNub() : calculatrice '${CalculatorType[calcType]}' / noeud de calcul '${ComputeNodeType[nodeType]}' non pris en charge` ); } } // propagate properties nub.properties = params; return nub; } /** * 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;
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
} for (const s of n.getChildren()) { if (s.uid === uid) { alreadyUsed = true; break outerLoop; } } } return alreadyUsed; } /** * Returns all Nubs depending on the given one (parameter or result), * without following links (1st level only) */ public getDependingNubs(uid: string) { const dependingNubs: Nub[] = []; for (const n of this._nubs) { if (n.uid !== uid && n.resultDependsOnNub(uid)) { dependingNubs.push(n); } } return dependingNubs; } /** * Returns a list of nub/symbol couples, that can be linked to the given * parameter, amoung all current nubs * @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}`; })); */ return res; } /** * Returns all Nubs of type Cloisons, to be used as models in PAB */ public getCloisonsNubs() { const cloisonsNubs: Nub[] = []; for (const n of this._nubs) { if (n instanceof Cloisons) { cloisonsNubs.push(n); } } return cloisonsNubs; } /** * Crée un Nub de type Section * @param nt ComputeNodeType * @param dbg activer débogage */ public createSection(nt: ComputeNodeType, dbg: boolean = false): acSection { switch (nt) { case ComputeNodeType.None: // pour les paramètres communs, n'importe quelle section convient case ComputeNodeType.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
491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
0.001, // If=pente du fond 1, // YB= hauteur de berge ); return new cSnTrapez(prms, dbg); } case ComputeNodeType.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 ComputeNodeType.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 ComputeNodeType.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); } default: throw new Error(`type de section ${ComputeNodeType[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 */ private createNubFromObjectRepresentation(obj: any): { nub: Nub, meta: any } { const nubPointer: any = {}; // create the Nub const newNub = this.createSessionNub(new Props(obj.props)); // try to keep the original ID if (! this.uidAlreadyUsed(obj.uid)) { newNub.setUid(obj.uid); } newNub.loadObjectRepresentation(obj); nubPointer.nub = newNub; // add metadata (used by GUI, for ex.) if (obj.meta) { nubPointer.meta = obj.meta; } return nubPointer; }
561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
/** * Asks all loaded Nubs to relink any parameter that has a wrong target */ private fixLinks(serialised: string, uids?: string[]) { 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); // find linked parameters nub.fixLinks(e); } }); } } /** * Asks all loaded PAB Nubs to reinit any PabCloisons from their model */ private fixPAB(serialised: string, uids?: string[]) { const data = JSON.parse(serialised); if (data.session && Array.isArray(data.session)) { // find each PAB in the session data.session.forEach((e: any) => { if ( (! uids || uids.length === 0 || uids.includes(e.uid)) && (e.props.calcType === CalculatorType.Pab) ) { const nub = (this.findNubByUid(e.uid) as Pab); // find linked parameters nub.fixPAB(e); } }); } } }