Newer
Older
AUBRY JEAN-PASCAL
committed
/* eslint-disable @typescript-eslint/member-ordering */
francois.grand
committed
import { Injectable } from "@angular/core";
francois.grand
committed
import { decode } from "he";
import {
CalculatorType,
LinkedValue,
Observable,
ParamDefinition,
Session,
Nub,
ParallelStructure,
Pab,
Props,
Cloisons,
SPP,
PreBarrage,
PbBassin,
PbBassinParams,
LoiDebit,
PbCloison,
CreateStructure,
Structure,
SectionNub,
SectionParametree,
acSection,
round,
RegimeUniforme,
CourbeRemous
import { ApplicationSetupService } from "./app-setup.service";
import { HttpService } from "./http.service";
import { I18nService } from "./internationalisation.service";
import { NotificationsService } from "./notifications.service";
import { FormulaireDefinition } from "../formulaire/definition/form-definition";
import { FormulaireElement } from "../formulaire/elements/formulaire-element";
import { InputField } from "../formulaire/elements/input-field";
François Grand
committed
import { SelectField } from "../formulaire/elements/select/select-field";
import { FormulaireSectionParametree } from "../formulaire/definition/form-section-parametree";
import { FormulaireCourbeRemous } from "../formulaire/definition/form-courbe-remous";
import { FormulaireParallelStructure } from "../formulaire/definition/form-parallel-structures";
import { NgParameter } from "../formulaire/elements/ngparam";
import { FieldsetContainer } from "../formulaire/elements/fieldset-container";
import { FormulairePab } from "../formulaire/definition/form-pab";
import { FormulaireMacrorugoCompound } from "../formulaire/definition/form-macrorugo-compound";
import { FormulaireGrille } from "../formulaire/definition/form-grille";
import { FormulaireSolveur } from "../formulaire/definition/form-solveur";
import { AppComponent } from "../app.component";
import { FormulaireSPP } from "../formulaire/definition/form-spp";
import { FormulaireFixedVar } from "../formulaire/definition/form-fixedvar";
import { FormulaireSection } from "../formulaire/definition/form-section";
import { FormulairePAR } from "../formulaire/definition/form-par";
import { FormulaireVerificateur } from "../formulaire/definition/form-verificateur";
import { FormulaireEspece } from "../formulaire/definition/form-espece";
import { FormulairePrebarrage } from "../formulaire/definition/form-prebarrage";
François Grand
committed
import { ServiceFactory } from "./service-factory";
import { FormulairePressureLoss } from "app/formulaire/definition/form-pressureloss";
import { getNubResultUnit } from "jalhyd";
AUBRY JEAN-PASCAL
committed
import { FormulaireMacrorugoRemous } from "app/formulaire/definition/form-macrorugo-remous";
// import { FormulaireMacrorugo } from "app/formulaire/definition/form-macrorugo";
export class FormulaireService extends Observable {
private _formulaires: FormulaireDefinition[];
private _currentFormId: string = null;
private _selectedLoadedNubs: any[] = [];
public static getConfigPathPrefix(ct: CalculatorType): string {
const ctName = CalculatorType[ct].toLowerCase();
return "app/calculators/" + ctName + "/";
}
private i18nService: I18nService,
private appSetupService: ApplicationSetupService,
mathias.chouet
committed
private httpService: HttpService,
private intlService: I18nService,
private notificationsService: NotificationsService
this.clearFormulaires();
public get formulaires(): FormulaireDefinition[] {
return this._formulaires;
}
public getTitlebyIdOnSelectedLoadedNubs(uid: string) {
return this._selectedLoadedNubs.find(selectedNub => selectedNub.uid === uid)
}
/** Removes all formulaires from the list */
public clearFormulaires() {
this._formulaires = [];
}
/**
* Retourne le titre complet du type de module de calcul, dans la langue en cours
*/
public getLocalisedTitleFromCalculatorType(type: CalculatorType) {
const sCalculator: string = CalculatorType[type].toUpperCase();
return this.intlService.localizeText(`INFO_${sCalculator}_TITRE`);
}
/**
* Retourne la description du type de module de calcul, dans la langue en cours
*/
public getLocalisedDescriptionFromCalculatorType(type: CalculatorType) {
const sCalculator: string = CalculatorType[type].toUpperCase();
return this.intlService.localizeText(`INFO_${sCalculator}_DESCRIPTION`);
/**
* Retourne le titre cour du type de module de calcul, dans la langue en cours
* (pour les titres d'onglets par défaut)
*/
mathias.chouet
committed
public getLocalisedShortTitleFromCalculatorType(type: any) {
if (typeof type !== "string") { // retrocompatibility for old file format
type = CalculatorType[type];
}
const sCalculator: string = type.toUpperCase();
return this.intlService.localizeText(`INFO_${sCalculator}_TITRE_COURT`);
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/**
* Forces update of all form strings in given Formulaire, with current language
*/
public updateFormulaireLocalisation(f: FormulaireDefinition) {
const requiredLang = this.intlService.currentLanguage;
f.updateLocalisation(requiredLang);
}
/**
* Tente de trouver une traduction pour textKey dans les fichiers de langues
* spécifiques du module de calcul en cours, dans la langue en cours, puis
* dans la langue par défaut; si aucune traduction n'est trouvée, demande au
* service i18n de rechercher dans les fichiers de langues globaux
* @param textKey la clé du texte à traduire
*/
public localizeText(textKey: string, ct: CalculatorType): string {
const calcType = /* this.currentForm?.currentNub?.calcType || */ ct;
if (calcType !== undefined) {
// throw new Error("FormulaireService.localizeText(): cannot find CalculatorType for current form's Nub");
let langCache = this.i18nService.languageCache;
if (langCache && langCache[calcType]) {
langCache = langCache[calcType]; // …for target Nub type
}
// try current language
if (
langCache
&& langCache[this.intlService.currentLanguage]
&& langCache[this.intlService.currentLanguage][textKey] !== undefined
) {
return langCache[this.intlService.currentLanguage][textKey];
}
}
// fallback to global (not calculator type specific) translation system
return this.i18nService.localizeText(textKey);
}
/**
* Returns variable name from symbol
* @param calcType
* @param symbol
*/
public expandVariableName(calcType: CalculatorType, symbol: string): string {
let s = "";
let langCache = this.i18nService.languageCache;
if (langCache && langCache[calcType]) {
langCache = langCache[calcType]; // …for target Nub type
}
if (langCache && langCache[this.intlService.currentLanguage]) {
langCache = langCache[this.intlService.currentLanguage]; // … for current language
}
if (langCache && langCache[symbol] !== undefined) {
s = this.localizeText(symbol, calcType);
// is symbol of the form ouvrages[i]… ?
const re = /([A-Z,a-z]+)\[(\d+)\]\.(.+)/;
const match = re.exec(symbol);
if (match) {
// Les libellés correspondants sont INFO OUVRAGE et INFO_LIB_OUVRAGE_XXX
s = this.intlService.localizeText(`INFO_${match[1].toUpperCase()}`)
+ " n°" + (+match[2] + 1) + ": "
+ this.expandVariableName(calcType, `${match[1].toUpperCase()}_${match[3].toUpperCase()}`);
} else {
s = this.intlService.localizeText("INFO_LIB_" + symbol.toLocaleUpperCase());
}
}
return s;
}
/**
* Returns variable name and unit from symbol
* @param calcType
* @param symbol
* @param forceUnit if given, will be used as unit
public expandVariableNameAndUnit(calcType: CalculatorType, symbol: string, forceUnit?: string): string {
let s = this.expandVariableName(calcType, symbol);
let langCache = this.i18nService.languageCache; // language cache…
if (langCache && langCache[calcType]) {
langCache = langCache[calcType]; // …for target Nub type
}
if (langCache && langCache[this.intlService.currentLanguage]) {
langCache = langCache[this.intlService.currentLanguage]; // … for current language
}
mathias.chouet
committed
// remove device number before looking for unit (hacky)
let symbolBase = symbol.toLocaleUpperCase();
const idx = symbolBase.indexOf("].");
if (idx !== -1) {
symbolBase = symbolBase.substring(idx + 2);
}
let unit: string;
// unit of a parameter is supposed to be read from JaLHyd ParadDefinition and passed
// through "forceUnit"; keys like "UNIT_*" in the config file are for extra results
if (forceUnit) {
unit = forceUnit;
} else {
unit = getNubResultUnit(calcType, symbol);
if (unit === undefined) {
// last chance: if unit cannot be read in model, use translation files
const unitKey = "UNIT_" + symbolBase;
if (langCache && langCache[unitKey] !== undefined) {
unit = this.localizeText(unitKey, calcType);
}
}
}
if (unit) {
s = s + " (" + unit + ")";
}
return s;
}
/**
* From https://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex
*/
private escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
}
/**
* Checks if the given calculator name (tab title) is already used by any existing
* form; if so, adds a number after it
*/
private suffixNameIfNeeded(name: string) {
let found = false;
let maxNumber = 0;
// extract base name
let baseName = name;
const re1 = new RegExp("^.+( \\d+)$");
const matches1 = re1.exec(name);
if (matches1) {
baseName = baseName.replace(matches1[1], "");
}
// browse session calculators
const re2 = new RegExp("^" + this.escapeRegExp(baseName) + "( (\\d+))?$");
for (const f of this.formulaires) {
const matches2 = re2.exec(f.calculatorName);
if (matches2) {
found = true;
if (matches2[2] !== undefined) {
const nb = Number(matches2[2]);
maxNumber = Math.max(maxNumber, nb);
}
}
}
// suffix if needed
if (found) {
name = baseName + " " + (maxNumber + 1);
}
return name;
}
public loadConfig(ct: CalculatorType): Promise<any> {
const f: string = FormulaireService.getConfigPathPrefix(ct) + "config.json";
return this.httpService.httpGetRequestPromise(f);
private newFormulaire(ct: CalculatorType): FormulaireDefinition {
francois.grand
committed
let f: FormulaireDefinition;
switch (ct) {
case CalculatorType.SectionParametree:
francois.grand
committed
f = new FormulaireSectionParametree();
francois.grand
committed
break;
francois.grand
committed
case CalculatorType.RegimeUniforme:
francois.grand
committed
break;
case CalculatorType.CourbeRemous:
francois.grand
committed
f = new FormulaireCourbeRemous();
francois.grand
committed
break;
case CalculatorType.ParallelStructure:
case CalculatorType.Cloisons:
f = new FormulaireParallelStructure();
case CalculatorType.Pab:
f = new FormulairePab();
break;
case CalculatorType.MacroRugoCompound:
f = new FormulaireMacrorugoCompound();
break;
case CalculatorType.Grille:
f = new FormulaireGrille();
break;
case CalculatorType.Par:
case CalculatorType.ParSimulation:
f = new FormulairePAR();
break;
case CalculatorType.Solveur:
f = new FormulaireSolveur();
break;
case CalculatorType.SPP:
f = new FormulaireSPP();
break;
case CalculatorType.Verificateur:
f = new FormulaireVerificateur();
break;
case CalculatorType.Espece:
f = new FormulaireEspece();
break;
case CalculatorType.PreBarrage:
f = new FormulairePrebarrage();
break;
case CalculatorType.PressureLoss:
f = new FormulairePressureLoss();
break;
AUBRY JEAN-PASCAL
committed
case CalculatorType.MacrorugoRemous:
f = new FormulaireMacrorugoRemous();
francois.grand
committed
default:
francois.grand
committed
}
f.defaultProperties["calcType"] = ct;
return f;
}
/**
* crée un formulaire d'un type donné
* @param ct type de formulaire
* @param nub nub existant à associer au formulaire (chargement de session / duplication de module)
* @param calculatorName nom du module, à afficher dans l'interface
public async createFormulaire(ct: CalculatorType, nub?: Nub, calculatorName?: string): Promise<FormulaireDefinition> {
// Crée un formulaire du bon type
const f: FormulaireDefinition = this.newFormulaire(ct);
// Charge la configuration dépendamment du type
const s: any = await this.loadConfig(ct);
// Associe le Nub fourni (chargement de session / duplication de module), sinon en crée un nouveau
if (nub) {
f.currentNub = nub;
} else {
const confProps = f.parseConfigToProps();
confProps.setPropValue("calcType", ct);
f.initNub(confProps);
// Restaure le nom du module, sinon affecte le nom par défaut
let tempName: string;
if (calculatorName) {
tempName = calculatorName;
} else {
tempName = decode(this.getLocalisedShortTitleFromCalculatorType(ct));
}
// Suffixe le nom du module si nécessaire
f.calculatorName = this.suffixNameIfNeeded(tempName);
f.parseConfig();
// add fieldsets for existing Structures if needed
// (when loading session only)
if (f.currentNub instanceof ParallelStructure) {
for (const struct of f.currentNub.structures) {
for (const e of f.allFormElements) {
if (e instanceof FieldsetContainer) { // @TODO manage many containers one day ?
e.addFromTemplate(undefined, struct);
// add fieldsets for existing YAXN if needed
// (when loading session only)
if (f.currentNub instanceof SPP) {
for (const c of f.currentNub.getChildren()) {
for (const e of f.allFormElements) {
if (e instanceof FieldsetContainer) { // @TODO manage many containers one day ?
e.addFromTemplate(undefined, c);
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
// when creating a new Pab, add one wall with one device, plus the downwall
// (when loading session, those items are already present)
if (
f instanceof FormulairePab
&& f.currentNub instanceof Pab
&& f.currentNub.children.length === 0
&& f.currentNub.downWall === undefined
) {
// 1. one wall
const newWall = Session.getInstance().createNub(
new Props({
calcType: CalculatorType.Cloisons
})
) as Cloisons;
// add new default device for new wall
const newDevice = Session.getInstance().createNub(
new Props({
calcType: CalculatorType.Structure,
loiDebit: newWall.getDefaultLoiDebit()
})
);
newWall.addChild(newDevice);
f.pabNub.addChild(newWall);
// 2. downwall
const newDownWall = Session.getInstance().createNub(
new Props({
calcType: CalculatorType.CloisonAval
})
) as CloisonAval;
// add new default device for new downwall
const newDownwallDevice = Session.getInstance().createNub(
new Props({
calcType: CalculatorType.Structure,
loiDebit: newDownWall.getDefaultLoiDebit()
})
);
newDownWall.addChild(newDownwallDevice);
f.pabNub.downWall = newDownWall;
}
// when creating a new PreBarrage, add one basin and two walls with one
// device each (when loading session, those items are already present)
if (
f instanceof FormulairePrebarrage
&& f.currentNub instanceof PreBarrage
&& f.currentNub.children.length === 0
) {
François Grand
committed
const emptyFields: boolean = ServiceFactory.applicationSetupService.enableEmptyFieldsOnFormInit;
François Grand
committed
f.currentNub.addChild(new PbBassin(new PbBassinParams(13.80, 95, emptyFields)));
François Grand
committed
f.currentNub.addChild(new PbCloison(undefined, f.currentNub.children[0] as PbBassin, undefined, emptyFields));
const s1: Structure = CreateStructure(LoiDebit.WeirCunge80, undefined, undefined, emptyFields);
// s1.prms.ZDV.singleValue = 95.30;
// s1.getParameter("L").singleValue = 0.4;
// s1.getParameter("CdGR").singleValue = 1.04;
f.currentNub.children[1].addChild(s1);
// 2nd wall
François Grand
committed
f.currentNub.addChild(new PbCloison(f.currentNub.children[0] as PbBassin, undefined, undefined, emptyFields));
const s2: Structure = CreateStructure(LoiDebit.WeirCunge80, undefined, undefined, emptyFields);
// s2.prms.ZDV.singleValue = 95.30;
// s2.getParameter("L").singleValue = 0.4;
// s2.getParameter("CdGR").singleValue = 1.04;
f.currentNub.children[2].addChild(s2);
}
this.notifyObservers({
"action": "createForm",
mathias.chouet
committed
/**
* Trick to notify param-link components that parent form name changed
* @TODO find a way to make param-link components directly observe FormDefinition
*/
public propagateFormNameChange(f: FormulaireDefinition, name: string) {
this.notifyObservers({
"action": "formNameChanged",
"form": f,
"value": name
});
}
public getFormulaireFromId(uid: string): FormulaireDefinition {
for (const f of this._formulaires) {
if (f.uid === uid) {
public getInputField(formId: string, elemId: string): InputField {
const s = this.getFormulaireElementById(formId, elemId);
if (!(s instanceof InputField)) {
throw new Error("Form element with id '" + elemId + "' is not an input");
}
public getSelectField(formId: string, elemId: string): SelectField {
const s = this.getFormulaireElementById(formId, elemId);
throw new Error("Form element with id '" + elemId + "' is not a select");
private getFormulaireElementById(formId: string, elemId: string): FormulaireElement {
const s = f.getFormulaireNodeById(elemId);
francois.grand
committed
return s as FormulaireElement;
francois.grand
committed
public getParamdefParentForm(prm: ParamDefinition): FormulaireDefinition {
for (const f of this._formulaires) {
for (const p of f.allFormElements) {
if (p instanceof NgParameter) {
if (p.paramDefinition.uid === prm.uid) {
francois.grand
committed
return f;
francois.grand
committed
}
/**
* retrouve un formulaire à partir d'un uid de Nub
*/
public getFormulaireFromNubId(uid: string) {
for (const f of this._formulaires) {
if (f.hasNubId(uid)) {
return f;
}
}
}
/**
* Supprime le formulaire ciblé, et demande à JaLHyd d'effacer son Nub de la Session
* @param uid formulaire à supprimer
*/
public requestCloseForm(uid: string) {
const form = this.getFormulaireFromId(uid);
const nub = form.currentNub;
if (form) {
this._formulaires = this._formulaires.filter(f => f.uid !== uid);
this.notifyObservers({
"form": form
// reset the result panels of all forms depending on this one
// @TODO UI should detect model change instead of doing this manually
mathias.chouet
committed
this.resetAllDependingFormsResults(form, [], undefined, true, false);
if (nub) {
// reset model results (important, also resets dependent Nubs results in chain)
form.currentNub.resetResult();
Session.getInstance().deleteNub(nub);
}
}
public get currentFormId() {
return this._currentFormId;
}
public setCurrentForm(formId: string) {
const form = this.getFormulaireFromId(formId);
this._currentFormId = null;
this.notifyObservers({
"action": "invalidFormId",
"formId": formId
});
this._currentFormId = formId;
this.notifyObservers({
"action": "currentFormChanged",
"formId": formId
francois.grand
committed
public get currentForm(): FormulaireDefinition {
francois.grand
committed
return this.getFormulaireFromId(this._currentFormId);
}
public get currentFormHasResults(): boolean {
const form = this.currentForm;
francois.grand
committed
return form.hasResults;
francois.grand
committed
return false;
}
francois.grand
committed
private readSingleFile(file: File): Promise<any> {
return new Promise<any>((resolve, reject) => {
fr.onload = () => {
resolve(fr.result);
};
fr.onerror = () => {
fr.abort();
reject(new Error(`Erreur de lecture du fichier ${file.name}`));
};
fr.readAsText(file);
});
}
francois.grand
committed
/**
* charge une session en tenant compte des modules de calcul sélectionnés
francois.grand
committed
* @param f fichier session
* @param formInfos infos sur les modules de calcul @see DialogLoadSessionComponent.calculators
francois.grand
committed
*/
public async loadSession(i: Blob | string, formInfos: any[] = []): Promise<{ hasErrors: boolean, loaded: string[] }> {
François Grand
committed
// disable "empty fields" flag temporarly
const emptyFields = ServiceFactory.applicationSetupService.enableEmptyFieldsOnFormInit;
ServiceFactory.applicationSetupService.enableEmptyFieldsOnFormInit = false;
this._selectedLoadedNubs = formInfos;
François Grand
committed
let s;
if (i instanceof Blob) {
s = await this.readSingleFile(i as File);
} else {
s = i;
}
const uids: string[] = [];
formInfos.forEach((fi) => {
if (fi.selected) {
uids.push(fi.uid);
const res = Session.getInstance().unserialise(s, uids);
const newNubs = res.nubs;
// for each new Nub, create the related form, set its title
for (let i = 0; i < newNubs.length; i++) {
const nn = newNubs[i];
let title;
if (nn.meta && nn.meta.title) {
title = nn.meta.title;
}
await this.createFormulaire(nn.nub.calcType, nn.nub, title); // await guarantees loading order
}
François Grand
committed
// restore "empty fields" flag
ServiceFactory.applicationSetupService.enableEmptyFieldsOnFormInit = emptyFields;
// apply settings
if (res.settings) {
// model based settings
if (res.settings.precision !== undefined) {
this.appSetupService.computePrecision = res.settings.precision;
}
if (res.settings.maxIterations !== undefined) {
this.appSetupService.maxIterations = res.settings.maxIterations;
}
// GUI settings
if (res.settings.displayPrecision !== undefined) {
this.appSetupService.displayPrecision = res.settings.displayPrecision;
}
}
// forward errors
return {
hasErrors: res.hasErrors,
loaded: newNubs.map(n => n.nub.uid)
// forward errors to caller to avoid "Uncaught (in promise)"
getSelectedLoadedNubs() {
return this._selectedLoadedNubs;
}
/**
* Sends an UTF-8 text file for download
*/
public downloadTextFile(session: string, filename: string = "file_1") {
const mt = "text/plain;charset=utf-8";
const blob = new Blob([session], { type: "text/plain;charset=utf-8" });
AppComponent.download(blob, filename, "text/plain");
francois.grand
committed
}
francois.grand
committed
/**
* obtient des infos (nom, uid des modules de calcul, dépendances) d'un fichier session
francois.grand
committed
* @param f fichier session
*/
public async calculatorInfosFromSessionFile(f: File): Promise<{ nubs: any[], formatVersion: string }> {
const s = await this.readSingleFile(f);
const res: {
nubs: any[];
formatVersion: string;
} = {
nubs: [],
formatVersion: ""
};
const data = JSON.parse(s);
// liste des noms de modules de calcul
if (data.session && Array.isArray(data.session)) {
data.session.forEach((e: any) => {
const nubInfo = {
uid: e.uid,
title: e.meta && e.meta.title ? e.meta.title : undefined,
requires: [],
children: [],
type: e.props.calcType
};
// list linked params dependencies for each Nub
if (e.parameters) {
e.parameters.forEach((p) => {
if (p.targetNub && !nubInfo.requires.includes(p.targetNub)) {
nubInfo.requires.push(p.targetNub);
}
});
}
// list children nubs for each Nub
if (e.children) {
e.children.forEach((p) => {
nubInfo.children.push(p.uid);
});
}
res.nubs.push(nubInfo);
});
}
// version du format de fichier
if (data.header && data.header.format_version) {
res.formatVersion = data.header.format_version;
}
return res;
francois.grand
committed
}
francois.grand
committed
public saveForm(f: FormulaireDefinition) {
this.notifyObservers({
"action": "saveForm",
"form": f
});
}
* Demande à la Session JalHYd la liste des paramètres/résultats pouvant être liés au
* paramètre fourni
* @param p the parameter on which we look for available links
* @param update force calculation instead of using cached linkable values
public getLinkableValues(p: NgParameter, update = false): LinkedValue[] {
let linkableValues: LinkedValue[] = [];
if (p) {
if (!(this.currentForm.currentNub instanceof Pab)) {
/**
* link caching is only for PAB otherwise link buttons of parallel
* structures are not created/deleted when new structure is
* created/deleted.
*/
update = true;
}
if (update || p.linkableValues === undefined) {
linkableValues = Session.getInstance().getLinkableValues(p.paramDefinition);
// join form names to ease usage
for (let i = 0; i < linkableValues.length; i++) {
const lv = linkableValues[i];
for (const f of this._formulaires) {
if (f.currentNub) {
if (f.currentNub.uid === lv.nub.uid) {
lv.meta["formTitle"] = f.calculatorName;
} else {
// child structures ?
for (const s of f.currentNub.getChildren()) {
if (s.uid === lv.nub.uid) {
lv.meta["formTitle"] = f.calculatorName;
}
francois.grand
committed
}
linkableValues = this.filterLinkableValues(linkableValues);
} else {
linkableValues = p.linkableValues;
francois.grand
committed
}
francois.grand
committed
}
francois.grand
committed
/**
* filtre les valeurs liables à un paramètre :
* - supprime les valeurs non affichées dans leur parent (ce n'est pas le cas par ex
* pour Q, Z1, Z2 dans les ouvrages enfants des ouvrages //)
francois.grand
committed
* @param values valeurs liables (modifié par la méthode)
*/
public filterLinkableValues(values: any[]): any[] {
for (let i = values.length - 1; i >= 0; i--) {
const v = values[i].value;
if (v instanceof ParamDefinition) {
// pour chaque paramètre...
const prm: ParamDefinition = v;
const parentForm: FormulaireDefinition = this.getParamdefParentForm(prm);
// ... on cherche s'il est affiché dans son parent
if (parentForm !== undefined) {
for (const fe of parentForm.allFormElements) {
if (fe instanceof NgParameter) {
francois.grand
committed
if (fe.paramDefinition.uid === prm.uid) {
found = true;
break;
}
francois.grand
committed
values.splice(i, 1);
francois.grand
committed
}
}
return values;
}
/**
* Resets the results of all forms depending on the given form "f"
* @param f
mathias.chouet
committed
* @param symbol symbol of the parameter whose value change triggered this method
* @param forceResetAllDependencies if true, even non-calculated non-modified parameters
* links will be considered as dependencies @see jalhyd#98
mathias.chouet
committed
public resetAllDependingFormsResults(
f: FormulaireDefinition,
visited: string[] = [],
symbol?: string,
forceResetAllDependencies: boolean = false,
notify: boolean = true
) {
const dependingNubs = Session.getInstance().getDependingNubs(f.currentNub.uid, symbol, forceResetAllDependencies, true);
if (!visited.includes(dn.uid)) {
const form = this.getFormulaireFromNubId(dn.uid);
mathias.chouet
committed
if (form) {
const hadResults = form.hasResults;
// form might not have a result, but still have another form depending on it !
// console.debug(`FormulaireService.resetAllDependingFormsResults(form->${dn.uid})`);
mathias.chouet
committed
form.resetResults(visited);
if (hadResults) {
if (notify) {
this.notificationsService.notify(
this.intlService.localizeText("INFO_SNACKBAR_RESULTS_INVALIDATED") + " " + form.calculatorName,
1500
mathias.chouet
committed
);
}
mathias.chouet
committed
}
/**
* Génère un formulaire SectionParametree à partir du module courant
* s'il est du type régime uniforme ou courbe de remous
*/
François Grand
committed
public async generateParametricSectionForm(Y?: number): Promise<FormulaireDefinition> {
if (this.currentForm.currentNub instanceof SectionNub) {
const sn: SectionNub = this.currentForm.currentNub;
if (sn instanceof RegimeUniforme || sn instanceof CourbeRemous) {
AUBRY JEAN-PASCAL
committed
// change _If visibility to copy section
sn.section.prms.If.visible = true;
// copy section
const serialisedSection = sn.section.serialise();
AUBRY JEAN-PASCAL
committed
// Reinitialize _If visibility
sn.section.prms.If.visible = false;
François Grand
committed
const sectionCopy: acSection = Session.getInstance().unserialiseSingleNub(serialisedSection, false).nub as acSection;
if (Y !== undefined) {
sectionCopy.prms.Y.singleValue = Y;
}
const secParam = new SectionParametree(sectionCopy);
François Grand
committed
if (sn instanceof RegimeUniforme) {
// copy value of calculated param
const cp: ParamDefinition = sn.calculatedParam;
const scp: ParamDefinition = secParam.section.getParameter(cp.symbol);
if (cp.hasMultipleValues) {
scp.setValues(sn.result.getCalculatedValues().map(v => round(v, this.appSetupService.displayPrecision)));
} else {
scp.singleValue = sn.result.vCalc;
}
}
Session.getInstance().registerNub(secParam);
return await this.createFormulaire(CalculatorType.SectionParametree, secParam);
}
}
return Promise.reject("cannot create parametric section from current form");
}