session.ts 36.7 KB
Newer Older
1
import { isNumeric } from "./base";
2
import { CalculatorType, SectionType } from "./compute-node";
3
import { config } from "./config";
4
import { LCMaterial } from "./lc-material";
5
import { LinkedValue } from "./linked-value";
Dorchies David's avatar
lint    
Dorchies David committed
6
import { Nub } from "./nub";
Mathias Chouet's avatar
Mathias Chouet committed
7
import { ParamDefinition } from "./param/param-definition";
Mathias Chouet's avatar
Mathias Chouet committed
8
import { Props } from "./props";
9
import { SessionSettings } from "./session_settings";
10

Dorchies David's avatar
lint    
Dorchies David committed
11
// Calculettes
12
13
14
15
import { Grille, GrilleProfile, GrilleType } from "./devalaison/grille";
import { GrilleParams } from "./devalaison/grille_params";
import { Jet } from "./devalaison/jet";
import { JetParams } from "./devalaison/jet_params";
16
17
import { ConcentrationBlocs } from "./macrorugo/concentration_blocs";
import { ConcentrationBlocsParams } from "./macrorugo/concentration_blocs_params";
18
import { MacroRugo } from "./macrorugo/macrorugo";
Dorchies David's avatar
Dorchies David committed
19
20
import { MacrorugoCompound } from "./macrorugo/macrorugo_compound";
import { MacrorugoCompoundParams } from "./macrorugo/macrorugo_compound_params";
21
import { MacrorugoParams } from "./macrorugo/macrorugo_params";
22
import { MRCInclination } from "./macrorugo/mrc-inclination";
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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";
Mathias Chouet's avatar
Mathias Chouet committed
49
import { CloisonAval } from "./pab/cloison_aval";
50
import { CloisonsAvalParams } from "./pab/cloison_aval_params";
51
52
import { Cloisons } from "./pab/cloisons";
import { CloisonsParams } from "./pab/cloisons_params";
53
import { Pab } from "./pab/pab";
54
import { PabChute } from "./pab/pab_chute";
55
import { PabChuteParams } from "./pab/pab_chute_params";
56
import { PabDimension } from "./pab/pab_dimension";
57
import { PabDimensionParams } from "./pab/pab_dimensions_params";
58
import { PabNombre } from "./pab/pab_nombre";
59
60
import { PabNombreParams } from "./pab/pab_nombre_params";
import { PabParams } from "./pab/pab_params";
61
import { PabPuissance } from "./pab/pab_puissance";
62
import { PabPuissanceParams } from "./pab/pab_puissance_params";
63
64
65
66
67
68
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";
69
70
import { Dever } from "./structure/dever";
import { DeverParams } from "./structure/dever_params";
71
import { CreateStructure } from "./structure/factory_structure";
72
73
import { ParallelStructure } from "./structure/parallel_structure";
import { ParallelStructureParams } from "./structure/parallel_structure_params";
74
import { LoiDebit, StructureType } from "./structure/structure_props";
75
76
import { Par, ParType } from "./par/par";
import { ParParams } from "./par/par_params";
matcho's avatar
matcho committed
77
78
import { ParSimulation } from "./par/par_simulation";
import { ParSimulationParams } from "./par/par_simulation_params";
79
80
81
82
import { FishSpecies } from "./verification/fish_species";
import { Espece } from "./verification/espece";
import { EspeceParams } from "./verification/espece_params";
import { Verificateur } from "./verification/verificateur";
83
import { DivingJetSupport } from "./verification/diving-jet-support";
84
85
import { PreBarrage } from "./prebarrage/pre_barrage";
import { PreBarrageParams } from "./prebarrage/pre_barrage_params";
86
87
88
import { PbCloison } from "./prebarrage/pb_cloison";
import { PbBassin } from "./prebarrage/pb_bassin";
import { PbBassinParams } from "./prebarrage/pb_bassin_params";
89

90
export class Session {
Dorchies David's avatar
lint    
Dorchies David committed
91

92
93
94
95
96
97
98
99
100
101
102
    /** 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,
103
        nodeType: SectionType,
104
105
        calcType: CalculatorType,
        structureType: StructureType,
106
        inclinedApron: MRCInclination,
107
        parType: ParType,
108
109
        species: FishSpecies,
        divingJetSupported: DivingJetSupport
110
111
    };

112
    public static getInstance(): Session {
113
114
        if (Session._instance === undefined) {
            Session._instance = new Session();
Dorchies David's avatar
lint    
Dorchies David committed
115
        }
116
        return Session._instance;
Dorchies David's avatar
lint    
Dorchies David committed
117
    }
118

119
120
121
122
123
124
125
    /**
     * 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])) {
126
127
128
                if (Object.keys(Session.enumFromProperty).includes(k)) {
                    const enumClass = Session.enumFromProperty[k];
                    res[k] = enumClass[res[k]];
129
130
131
132
133
134
                }
            }
        }
        return res;
    }

135
136
    /** instance pour le pattern singleton */
    private static _instance: Session;
137

138
139
140
    /** free documentation text, in Markdown format, to save into session file (optional) */
    public documentation = "";

141
142
    /** Nubs de la session */
    private _nubs: Nub[] = [];
143

144
    /**
145
     * crée un Nub et l'ajoute à la session
146
     * @param props propriétés du Nub (computeType, nodeType...)
147
     */
148
149
    public createSessionNub(p: Props, dbg: boolean = false): Nub {
        const res = this.createNub(p, undefined, dbg);
150
        this._nubs.push(res);
151
152
153
        return res;
    }

Mathias Chouet's avatar
Mathias Chouet committed
154
155
156
157
    /**
     * Adds an existing Nub to the session
     */
    public registerNub(n: Nub) {
158
159
160
        if (this.uidAlreadyUsed(n.uid)) {
            n.setUid(Nub.nextUID);
        }
Mathias Chouet's avatar
Mathias Chouet committed
161
162
163
        this._nubs.push(n);
    }

164
165
166
167
168
169
170
171
172
    /**
     * Adds many existing Nubs to the session
     */
    public registerNubs(nubs: Nub[]) {
        for (const n of nubs) {
            this.registerNub(n);
        }
    }

Mathias Chouet's avatar
Mathias Chouet committed
173
174
175
176
177
178
179
    /**
     * Removes all Nubs from the Session
     */
    public clear() {
        this._nubs = [];
    }

180
181
182
183
184
185
186
    /**
     * Returns number of Nubs in the session
     */
    public getNumberOfNubs() {
        return this._nubs.length;
    }

187
188
189
190
191
    /** Accessor for Nubs list */
    public getAllNubs() {
        return this._nubs;
    }

Mathias Chouet's avatar
Mathias Chouet committed
192
    /**
193
194
     * Removes a Nub from the session; does not consider Structure nubs inside Calculator nubs
     * @param sn the Nub to remove from the session
Mathias Chouet's avatar
Mathias Chouet committed
195
196
     */
    public deleteNub(sn: Nub) {
Dorchies David's avatar
lint    
Dorchies David committed
197
        let i = 0;
198
        for (const n of this._nubs) {
Dorchies David's avatar
lint    
Dorchies David committed
199
            if (n.uid === sn.uid) {
200
                this._nubs.splice(i, 1);
Dorchies David's avatar
lint    
Dorchies David committed
201
202
203
204
                return;
            }
            i++;
        }
Mathias Chouet's avatar
Mathias Chouet committed
205
        throw new Error(`Session.deleteNub() : le Nub (uid ${sn.uid}) à supprimer n'a pas été trouvé`);
Dorchies David's avatar
lint    
Dorchies David committed
206
207
    }

208
209
210
211
    /**
     * 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
212
     * @param settings app preferences to store in the session file (decimals, precision…)
213
     */
214
    public serialise(options?: { [key: string]: {} }, settings?: { [key: string]: {} }): string {
215
        const sess: any[] = [];
216
217
218
219
220
221
222
223
224
        // session-wide settings
        let sessionSettings = {
            precision: SessionSettings.precision,
            maxIterations: SessionSettings.maxIterations
        };
        if (settings) {
            sessionSettings = {...sessionSettings, ...settings};
        }
        // nubs in session
225
        let ids: string[];
226
        let idsWithChildren: string[];
227
228
        if (options) {
            ids = Object.keys(options);
229
230
231
232
233
234
235
236
237
            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);
                    }
                }
            }
238
        }
239
        for (const n of this._nubs) {
240
            if (ids === undefined || ids.length === 0) {
241
                sess.push(n.objectRepresentation(undefined, ids));
242
            } else if (ids.includes(n.uid)) {
243
                sess.push(n.objectRepresentation(options[n.uid], idsWithChildren));
244
245
            }
        }
Mathias Chouet's avatar
Mathias Chouet committed
246
247
248
        return JSON.stringify({
            header: {
                source: "jalhyd",
249
                format_version: config.serialisation.fileFormatVersion,
Mathias Chouet's avatar
Mathias Chouet committed
250
251
                created: (new Date()).toISOString()
            },
252
            settings: sessionSettings,
253
            documentation: this.documentation,
Mathias Chouet's avatar
Mathias Chouet committed
254
255
            session: sess
        });
256
257
258
259
260
    }

    /**
     * Loads (a part of) a session from a JSON representation
     * @param serialised JSON data
261
     * @param uids unserialise only the Nubs havin the given UIDs
262
     */
263
    public unserialise(serialised: string, uids?: string[]): { nubs: any[], hasErrors: boolean, settings: any } {
264
        // return value
265
        const ret: { nubs: any[], hasErrors: boolean, settings: any } = {
266
            nubs: [],
267
268
            hasErrors: false,
            settings: {}
269
        };
270
271
        // unserialise to object
        const data = JSON.parse(serialised);
272
273
        // settings
        if (data.settings) {
274
            ret.settings = data.settings;
275
276
277
278
279
280
281
282
            if (data.settings.precision !== undefined) {
                SessionSettings.precision = data.settings.precision;
            }
            if (data.settings.maxIterations !== undefined) {
                SessionSettings.maxIterations = data.settings.maxIterations;
            }
        }
        // nubs
283
284
        if (data.session && Array.isArray(data.session)) {
            data.session.forEach((e: any) => {
Dorchies David's avatar
Dorchies David committed
285
                if (!uids || uids.length === 0 || uids.includes(e.uid)) {
286
                    const nubPointer = this.createNubFromObjectRepresentation(e);
287
288
289
290
291
                    ret.nubs.push(nubPointer);
                    // forward errors
                    if (nubPointer.hasErrors) {
                        ret.hasErrors = true;
                    }
292
293
294
                }
            });
        }
295
296
297
        // concatenate doc
        if (data.documentation !== undefined && data.documentation !== "") {
            this.documentation += `\n\n` + data.documentation;
298
        }
299
300

        // second pass for links
301
302
303
304
305
        const flRes = this.fixLinks(serialised, uids);
        // forward errors
        if (flRes.hasErrors) {
            ret.hasErrors = true;
        }
306
307
308
309
310
311
        // second pass for Solveurs
        const fsRes = this.fixSolveurs(serialised, uids);
        // forward errors
        if (fsRes.hasErrors) {
            ret.hasErrors = true;
        }
312

313
        return ret;
314
315
316
    }

    /**
317
     * Creates a Nub from a JSON representation and adds it to the current session; returns
318
319
     * a pointer to the Nub and its JSON metadata
     * @param serialised JSON representation of a single Nub
Mathias Chouet's avatar
Mathias Chouet committed
320
     * @param register if false, new Nub will just be returned and won't be registered into the session
321
     */
Mathias Chouet's avatar
Mathias Chouet committed
322
323
    public unserialiseSingleNub(serialised: string, register: boolean = true): { nub: Nub, meta: any } {
        return this.createNubFromObjectRepresentation(JSON.parse(serialised), register);
324
325
326
327
328
    }

    /**
     * Returns the Nub identified by uid if any
     */
329
    public findNubByUid(uid: string): Nub {
330
331
332
333
334
335
        let foundNub: Nub;
        outerLoop:
        for (const n of this._nubs) {
            if (n.uid === uid) {
                foundNub = n;
            }
336
337
338
339
340
341
            for (const s of n.getChildren()) {
                if (s.uid === uid) {
                    foundNub = s;
                    break outerLoop;
                }
            }
342
343
        }
        return foundNub;
Dorchies David's avatar
lint    
Dorchies David committed
344
345
    }

346
    /**
347
     * Crée un Nub à partir d'une description (Props)
348
349
350
351
352
353
     * @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éé
354
     * @param dbg activer débogage
355
     */
Mathias Chouet's avatar
Mathias Chouet committed
356
    public createNub(params: Props, parentNub?: Nub, dbg: boolean = false): Nub {
357
358
        const calcType: CalculatorType = params.getPropValue("calcType");

Mathias Chouet's avatar
Mathias Chouet committed
359
        let nub: Nub;
Mathias Chouet's avatar
tslint    
Mathias Chouet committed
360
        let prms: any;
Mathias Chouet's avatar
Mathias Chouet committed
361

362
        switch (calcType) {
Dorchies David's avatar
Dorchies David committed
363
364
365
366
367
368
369
370
371
372
            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;
373

Dorchies David's avatar
Dorchies David committed
374
375
376
377
378
379
380
381
            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
382
383
                    5.33, // paramètre N du matériau
                    0 // Ks Perte de charge singulière
Dorchies David's avatar
Dorchies David committed
384
385
386
                );
                nub = new LechaptCalmon(prms, dbg);
                break;
387

Dorchies David's avatar
Dorchies David committed
388
389
390
            case CalculatorType.SectionParametree:
                nub = new SectionParametree(undefined, dbg);
                break;
391

Dorchies David's avatar
Dorchies David committed
392
393
394
            case CalculatorType.RegimeUniforme:
                nub = new RegimeUniforme(undefined, dbg);
                break;
395

Dorchies David's avatar
Dorchies David committed
396
397
            case CalculatorType.CourbeRemous:
                prms = new CourbeRemousParams(
398
399
400
401
402
403
                    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
Dorchies David's avatar
Dorchies David committed
404
405
406
                );
                nub = new CourbeRemous(undefined, prms, MethodeResolution.EulerExplicite, dbg);
                break;
407

Dorchies David's avatar
Dorchies David committed
408
409
410
411
412
413
414
415
416
            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;
417

Dorchies David's avatar
Dorchies David committed
418
419
420
421
422
423
424
425
426
            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;
427

Dorchies David's avatar
Dorchies David committed
428
429
            case CalculatorType.Structure:
                const loiDebit: LoiDebit = params.getPropValue("loiDebit");
430
                nub = CreateStructure(loiDebit, (parentNub as ParallelStructure), dbg);
Dorchies David's avatar
Dorchies David committed
431
                break;
432

Dorchies David's avatar
Dorchies David committed
433
434
435
436
437
438
439
440
            case CalculatorType.ParallelStructure:
                prms = new ParallelStructureParams(
                    0.5, // Q
                    102, // Z1
                    101.5 // Z2
                );
                nub = new ParallelStructure(prms, dbg);
                break;
441

Dorchies David's avatar
Dorchies David committed
442
443
444
445
446
447
448
449
450
            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;
451

Dorchies David's avatar
Dorchies David committed
452
453
454
455
456
457
458
459
460
461
462
463
            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;
464

Dorchies David's avatar
Dorchies David committed
465
466
467
468
469
470
471
472
473
474
            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
Dorchies David's avatar
Dorchies David committed
475
                        0.13,   // C
476
477
                        0.4,    // D
                        0.4,    // k
478
                        1     // Cd0
Dorchies David's avatar
Dorchies David committed
479
480
481
                    ), dbg
                );
                break;
Dorchies David's avatar
Dorchies David committed
482

Dorchies David's avatar
Dorchies David committed
483
484
485
486
487
488
489
490
491
            case CalculatorType.PabChute:
                nub = new PabChute(
                    new PabChuteParams(
                        2,      // Z1
                        0.5,    // Z2
                        1.5     // DH
                    ), dbg
                );
                break;
492

Dorchies David's avatar
Dorchies David committed
493
494
495
496
497
498
499
500
501
            case CalculatorType.PabNombre:
                nub = new PabNombre(
                    new PabNombreParams(
                        6,     // DHT
                        10,    // N
                        0.6    // DH
                    ), dbg
                );
                break;
502

Dorchies David's avatar
Dorchies David committed
503
            case CalculatorType.Section:
504
                const nodeType: SectionType = params.getPropValue("nodeType");
Dorchies David's avatar
Dorchies David committed
505
506
                nub = this.createSection(nodeType, dbg);
                break;
Mathias Chouet's avatar
Mathias Chouet committed
507

508
509
510
511
512
513
            case CalculatorType.Pab:
                nub = new Pab(
                    new PabParams(
                        1.5,    // Q
                        102,    // Z1
                        99      // Z2
514
                    ), undefined, dbg
515
516
517
                );
                break;

Mathias Chouet's avatar
Mathias Chouet committed
518
            case CalculatorType.CloisonAval: {
519
                    prms = new CloisonsAvalParams(
Dorchies David's avatar
Dorchies David committed
520
521
                        0.5, // Q
                        102, // Z1
522
523
                        101.5, // Z2
                        0 // ZRAM
Dorchies David's avatar
Dorchies David committed
524
525
526
527
528
                    );
                    nub = new CloisonAval(prms, dbg);
                    break;
                }

Dorchies David's avatar
Dorchies David committed
529
530
531
532
            case CalculatorType.MacroRugoCompound:
                nub = new MacrorugoCompound(
                    new MacrorugoCompoundParams(
                        13.1,   // Z1
533
534
                        12.5,   // ZRL
                        12.5,   // ZRR
535
                        4,      // B
Dorchies David's avatar
Dorchies David committed
536
537
538
                        3,      // DH
                        0.05,   // If
                        0.01,   // Ks
Dorchies David's avatar
Dorchies David committed
539
                        0.13,   // C
540
541
                        0.4,    // D
                        0.4,    // k
542
                        1     // Cd0
543
                    ), dbg
Dorchies David's avatar
Dorchies David committed
544
545
                );
                break;
546

Mathias Chouet's avatar
Mathias Chouet committed
547
            case CalculatorType.Jet:
548
549
550
551
                nub = new Jet(
                    new JetParams(
                        5,      // V0
                        0.03,   // S
552
553
554
                        30,     // ZJ
                        29.2,   // ZW
                        28.5,   // ZF
555
                        3       // D
556
                    ), dbg
557
558
                );
                break;
559

Mathias Chouet's avatar
Mathias Chouet committed
560
            case CalculatorType.Grille:
Mathias Chouet's avatar
Mathias Chouet committed
561
562
563
564
565
566
567
568
569
570
571
572
                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
573
574
                        2,          // a
                        1.5,        // c
Mathias Chouet's avatar
Mathias Chouet committed
575
                        0.5,        // O
576
                        0.5,        // Ob
577
578
                        0.1,        // OEntH
                        4           // cIncl
579
                    ), dbg
Mathias Chouet's avatar
Mathias Chouet committed
580
581
582
                );
                break;

Mathias Chouet's avatar
Mathias Chouet committed
583
584
585
586
587
588
589
            case CalculatorType.Pente:
                nub = new Pente(
                    new PenteParams(
                        101,        // Z1
                        99.5,       // Z2
                        10,         // L
                        0.15        // I
590
                    ), dbg
Mathias Chouet's avatar
Mathias Chouet committed
591
592
593
                );
                break;

Mathias Chouet's avatar
Mathias Chouet committed
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
            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;

609
610
611
612
613
614
            case CalculatorType.Solveur:
                nub = new Solveur(
                    new SolveurParams(undefined)
                );
                break;

Mathias Chouet's avatar
Mathias Chouet committed
615
616
617
618
619
620
621
622
623
624
625
626
            case CalculatorType.YAXB:
                nub = new YAXB(
                    new YAXBParams(
                        10,     // Y
                        2,      // A
                        3,      // X
                        4       // B
                    ),
                    dbg
                );
                break;

Mathias Chouet's avatar
Mathias Chouet committed
627
628
629
630
631
632
633
634
635
636
            case CalculatorType.Trigo:
                nub = new Trigo(
                    new TrigoParams(
                        0.985,  // Y
                        10      // X
                    ),
                    dbg
                );
                break;

Mathias Chouet's avatar
Mathias Chouet committed
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
            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;

657
658
659
            case CalculatorType.ConcentrationBlocs:
                nub = new ConcentrationBlocs(
                    new ConcentrationBlocsParams(
Mathias Chouet's avatar
Mathias Chouet committed
660
661
662
663
                        0.128, // Concentration de blocs
                        5,     // Nombre de motifs
                        4.9,   // Largeur de la passe
                        0.35   // Diamètre des plots
664
                    ), dbg
665
666
667
                );
                break;

668
669
670
671
672
673
            case CalculatorType.Par:
                nub = new Par(
                    new ParParams(
                        0.25,   // Q
                        10,     // Z1
                        9,      // Z2
Mathias Chouet's avatar
Mathias Chouet committed
674
                        0.64,   // ha
675
676
677
678
679
680
                        0.2,    // S
                        0.4,    // P
                        0.6,    // L
                        0.1,    // a
                        1,      // N
                        1       // M
681
                    ), dbg
682
683
684
                );
                break;

matcho's avatar
matcho committed
685
686
687
688
689
690
691
692
693
            case CalculatorType.ParSimulation:
                nub = new ParSimulation(
                    new ParSimulationParams(
                        0.25,       // Q
                        10,         // Z1
                        9,          // Z2
                        0.2,        // S
                        0.4,        // P
                        undefined,  // Nb
694
                        9.242,       // ZR1
matcho's avatar
matcho committed
695
                        undefined,  // ZD1
696
                        8.222,       // ZR2
matcho's avatar
matcho committed
697
698
699
700
701
                        undefined,  // ZD2
                        0.6,        // L
                        0.1,        // a
                        1,          // N
                        1           // M
702
703
704
705
706
707
708
709
710
711
712
                    ), dbg
                );
                break;

            case CalculatorType.PreBarrage:
                nub = new PreBarrage(
                    new PreBarrageParams(
                        1,      // Q
                        101,    // Z1
                        100     // Z2
                    ), dbg
matcho's avatar
matcho committed
713
714
715
                );
                break;

716
717
718
719
            case CalculatorType.Espece:
                nub = new Espece(
                    // default params are those for SPECIES_1 (Salmons and trouts)
                    new EspeceParams(
720
721
722
723
724
725
726
                        0.35,   // DHMaxS
                        0.35,   // DHMaxP
                        0.3,    // BMin
                        1,      // PMinS
                        1,      // PMinP
                        2.5,    // LMinS
                        2.5,    // LMinP
727
728
                        0.3,    // HMin
                        0.4,    // YMin
729
                        2.5,    // VeMax
730
                        0.2,    // YMinSB
Mathias Chouet's avatar
Mathias Chouet committed
731
                        0.3,    // YMinPB
732
733
                        150,    // PVMaxPrec
                        200     // PVMaxLim
734
735
736
737
738
                    )
                );
                break;

            case CalculatorType.Verificateur:
739
                nub = new Verificateur();
Mathias Chouet's avatar
Mathias Chouet committed
740
741
                break;

742
743
744
745
746
747
748
749
750
            case CalculatorType.PbBassin:
                nub = new PbBassin(new PbBassinParams(
                    10,  // S
                    100  // ZF
                ), dbg);
                break;

            case CalculatorType.PbCloison:
                nub = new PbCloison(undefined, undefined);
751
752
                break;

Dorchies David's avatar
Dorchies David committed
753
754
755
756
            default:
                throw new Error(
                    `Session.createNub() : type de module '${CalculatorType[calcType]}' non pris en charge`
                );
757
        }
Mathias Chouet's avatar
Mathias Chouet committed
758
759

        // propagate properties
760
761
762
763
764
765
766
767
768
769
        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's avatar
Mathias Chouet committed
770
771

        return nub;
772
773
    }

774
    /**
775
776
     * Returns true if given uid is already used by a Nub in this session,
     * or a Structure nub inside one of them
777
     */
778
    public uidAlreadyUsed(uid: string, nubs: Nub[] = this._nubs): boolean {
779
        let alreadyUsed = false;
780
        for (const n of nubs) {
781
782
            if (n.uid === uid) {
                alreadyUsed = true;
783
                break;
784
            }
785
786
            if (! alreadyUsed) {
                alreadyUsed = this.uidAlreadyUsed(uid, n.getChildren());
787
            }
788
789
790
791
        }
        return alreadyUsed;
    }

792
    /**
793
794
     * Returns all Nubs depending on the given one (parameter or result),
     * without following links (1st level only)
795
     * @param uid UID of the Nub that underwent a change
796
797
798
799
     * @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
800
801
802
     * @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
803
     */
804
805
806
807
    public getDependingNubs(
        uid: string,
        symbol?: string,
        includeValuesLinks: boolean = false,
808
        includeOtherDependencies: boolean = false
809
    ): Nub[] {
810
811
        const dependingNubs: Nub[] = [];
        for (const n of this._nubs) {
812
813
            if (
                n.uid !== uid
814
                && n.resultDependsOnNub(uid, [], symbol, includeValuesLinks, includeOtherDependencies)
815
            ) {
816
817
818
819
820
821
                dependingNubs.push(n);
            }
        }
        return dependingNubs;
    }

822
823
824
825
826
827
828
829
830
831
832
833
834
835
    /**
     * 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;
    }

Mathias Chouet's avatar
Mathias Chouet committed
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
    /**
     * 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;
    }

864
    /**
865
     * Returns a list of nub/symbol couples, that can be linked to the given
Mathias Chouet's avatar
Mathias Chouet committed
866
     * parameter, among all current nubs
867
868
869
870
871
872
873
874
     * @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);
        }
Mathias Chouet's avatar
Mathias Chouet committed
875
876
877
        /* console.log("LINKABLE VALUES", res.map((lv) => {
            return `${lv.nub.uid}(${lv.nub.constructor.name})/${lv.symbol}`;
        })); */
878
879
880
        return res;
    }

881
882
    /**
     * Crée un Nub de type Section
883
     * @param nt SectionType
884
885
     * @param dbg activer débogage
     */
886
    public createSection(nt: SectionType, dbg: boolean = false): acSection {
887
        switch (nt) {
888
            case SectionType.SectionTrapeze: {
Dorchies David's avatar
Dorchies David committed
889
890
891
892
893
894
895
896
                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
                );
897

Dorchies David's avatar
Dorchies David committed
898
899
                return new cSnTrapez(prms, dbg);
            }
900

901
            case SectionType.SectionRectangle: {
Dorchies David's avatar
Dorchies David committed
902
903
904
905
906
907
908
909
910
                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);
            }
911

912
            case SectionType.SectionCercle: {
Dorchies David's avatar
Dorchies David committed
913
914
915
916
917
918
919
920
921
                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);
            }
922

923
            case SectionType.SectionPuissance: {
Dorchies David's avatar
Dorchies David committed
924
925
926
927
928
929
930
931
932
933
                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);
            }
934
935

            default:
936
                throw new Error(`type de section ${SectionType[nt]} non pris en charge`);
937
938
        }
    }
Mathias Chouet's avatar
Mathias Chouet committed
939
940
941
942
943

    /**
     * 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
Mathias Chouet's avatar
Mathias Chouet committed
944
     * @param register if false, new Nub will just be returned and won't be registered into the session
Mathias Chouet's avatar
Mathias Chouet committed
945
     */
Mathias Chouet's avatar
Mathias Chouet committed
946
947
948
    private createNubFromObjectRepresentation(obj: any, register: boolean = true)
        : { nub: Nub, meta: any, hasErrors: boolean } {

949
950
951
952
953
954
        // return value;
        const nubPointer: { nub: Nub, meta: any, hasErrors: boolean } = {
            nub: undefined,
            meta: undefined,
            hasErrors: false
        };
955
956
        // decode properties
        const props = Session.invertEnumKeysAndValuesInProperties(obj.props, true);
Mathias Chouet's avatar
Mathias Chouet committed
957
        // create the Nub
Mathias Chouet's avatar
Mathias Chouet committed
958
959
        let newNub;
        if (register) {
960
            newNub = this.createSessionNub(new Props(props));
Mathias Chouet's avatar
Mathias Chouet committed
961
        } else {
962
            newNub = this.createNub(new Props(props));
Mathias Chouet's avatar
Mathias Chouet committed
963
        }
Mathias Chouet's avatar
Mathias Chouet committed
964
        // try to keep the original ID
Dorchies David's avatar
Dorchies David committed
965
        if (!this.uidAlreadyUsed(obj.uid)) {
Mathias Chouet's avatar
Mathias Chouet committed
966
967
            newNub.setUid(obj.uid);
        }
968
        const res = newNub.loadObjectRepresentation(obj);
Mathias Chouet's avatar
Mathias Chouet committed
969
        nubPointer.nub = newNub;
970
971
972
973
        // forward errors
        if (res.hasErrors) {
            nubPointer.hasErrors = true;
        }
Mathias Chouet's avatar
Mathias Chouet committed
974
975
976
977
978
979
980
981
982
983
        // 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
     */
984
985
986
987
988
    private fixLinks(serialised: string, uids?: string[]): { hasErrors: boolean } {
        // return value
        const res = {
            hasErrors: false
        };
Mathias Chouet's avatar
Mathias Chouet committed
989
990
        const data = JSON.parse(serialised);
        if (data.session && Array.isArray(data.session)) {
991
            // find each corresponding Nub in the session
Mathias Chouet's avatar
Mathias Chouet committed
992
            data.session.forEach((e: any) => {
Dorchies David's avatar
Dorchies David committed
993
                if (!uids || uids.length === 0 || uids.includes(e.uid)) {
Mathias Chouet's avatar
Mathias Chouet committed
994
995
                    const nub = this.findNubByUid(e.uid);
                    // find linked parameters
996
997
998
999
1000
                    const ret = nub.fixLinks(e);
                    // forwardErrors
                    if (ret.hasErrors) {
                        res.hasErrors = true;
                    }
Mathias Chouet's avatar
Mathias Chouet committed
1001
1002
1003
                }
            });
        }
1004
        return res;
Mathias Chouet's avatar
Mathias Chouet committed
1005
    }
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033

    /**
     * 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) {
                            res.hasErrors = true;
                        }
                    }
                }
            });
        }
        return res;
    }
Dorchies David's avatar
lint    
Dorchies David committed
1034
}