Newer
Older
francois.grand
committed
import { Injectable } from "@angular/core";
import { Response } from "@angular/http";
import { Observable as rxObservable } from "rxjs/Observable";
import "rxjs/add/operator/toPromise";
francois.grand
committed
import { decode } from "he";
import { saveAs } from "file-saver";
francois.grand
committed
import { CalculatorType, EnumEx, Observable, ParamDefinition, ParamValueMode } from "jalhyd";
francois.grand
committed
import { ServiceFactory } from "../service-factory";
francois.grand
committed
import { HttpService } from "../../services/http/http.service";
import { InternationalisationService } from "../../services/internationalisation/internationalisation.service";
francois.grand
committed
import { FormulaireDefinition } from "../../formulaire/definition/form-definition";
francois.grand
committed
import { FormulaireElement } from "../../formulaire/formulaire-element";
import { InputField } from "../../formulaire/input-field";
francois.grand
committed
import { SelectField } from "../../formulaire/select-field";
import { CheckField } from "../../formulaire/check-field";
import { StringMap } from "../../stringmap";
francois.grand
committed
import { FormulaireConduiteDistributrice } from "../../formulaire/definition/concrete/form-cond-distri";
import { FormulaireLechaptCalmon } from "../../formulaire/definition/concrete/form-lechapt-calmon";
import { FormulaireSectionParametree } from "../../formulaire/definition/concrete/form-section-parametree";
import { FormulaireCourbeRemous } from "../../formulaire/definition/concrete/form-courbe-remous";
import { FormulaireRegimeUniforme } from "../../formulaire/definition/concrete/form-regime-uniforme";
import { FormulairePasseBassinDimensions } from "../../formulaire/definition/concrete/form-passe-bassin-dim";
import { FormulairePasseBassinPuissance } from "../../formulaire/definition/concrete/form-passe-bassin-puissance";
import { FormulaireParallelStructure } from "../../formulaire/definition/concrete/form-parallel-structures";
import { FormulaireDever } from "../../formulaire/definition/concrete/form-dever";
francois.grand
committed
import { NgParameter } from "../../formulaire/ngparam";
export class FormulaireService extends Observable {
private _formulaires: FormulaireDefinition[];
private _currentFormId = -1;
francois.grand
committed
constructor() {
francois.grand
committed
private get _intlService(): InternationalisationService {
return ServiceFactory.instance.internationalisationService;
}
private get _httpService(): HttpService {
return ServiceFactory.instance.httpService;
}
public get formulaires(): FormulaireDefinition[] {
return this._formulaires;
}
private loadLocalisation(calc: CalculatorType): Promise<any> {
francois.grand
committed
let f: string = this.getConfigPathPrefix(calc) + this._intlService.currentLanguage.tag + ".json"
let resp: rxObservable<Response> = this._httpService.httpGetRequestResponse(undefined, undefined, undefined, f);
let prom = resp.map(res => res.text()).toPromise();
return prom.then((res) => {
let j = JSON.parse(res);
return j as StringMap;
})
}
/**
* met à jour la langue du formulaire
* @param formId id unique du formulaire
* @param localisation ensemble id-message traduit
*/
private updateFormulaireLocalisation(formId: number, localisation: StringMap) {
for (let f of this._formulaires)
f.updateLocalisation(localisation);
break;
}
/**
* met à jour l'aide du formulaire
* @param formId id unique du formulaire
*/
private updateFormulaireHelp(formId: number) {
for (let f of this._formulaires)
f.updateHelp();
break;
}
}
/**
* charge la localisation et met à jour la langue du formulaire
*/
private loadUpdateFormulaireLocalisation(f: FormulaireDefinition): Promise<any> {
return this.loadLocalisation(f.calculatorType)
.then(localisation => {
this.updateFormulaireLocalisation(f.uid, localisation);
this.updateFormulaireHelp(f.uid);
});
}
public updateLocalisation() {
for (const c of EnumEx.getValues(CalculatorType)) {
const prom: Promise<StringMap> = this.loadLocalisation(c);
prom.then(loc => {
for (const f of this._formulaires) {
if (f.calculatorType === c) {
this.updateFormulaireLocalisation(f.uid, loc);
public getLocalisedTitleFromCalculatorType(type: CalculatorType) {
const sCalculator: string = CalculatorType[type].toUpperCase();
return this._intlService.localizeText(`INFO_${sCalculator}_TITRE`);
}
public loadConfig(ct: CalculatorType): Promise<any> {
let f: string = this.getConfigPathPrefix(ct) + "config.json"
return this._httpService.httpGetRequest2(undefined, undefined, undefined, f);
private newFormulaire(ct: CalculatorType, jsonState?: {}): FormulaireDefinition {
francois.grand
committed
let f: FormulaireDefinition;
switch (ct) {
case CalculatorType.ConduiteDistributrice:
francois.grand
committed
f = new FormulaireConduiteDistributrice();
francois.grand
committed
break;
case CalculatorType.LechaptCalmon:
francois.grand
committed
f = new FormulaireLechaptCalmon();
francois.grand
committed
break;
case CalculatorType.SectionParametree:
francois.grand
committed
f = new FormulaireSectionParametree();
francois.grand
committed
break;
case CalculatorType.RegimeUniforme:
francois.grand
committed
f = new FormulaireRegimeUniforme();
francois.grand
committed
break;
case CalculatorType.CourbeRemous:
francois.grand
committed
f = new FormulaireCourbeRemous();
francois.grand
committed
break;
case CalculatorType.PabDimensions:
francois.grand
committed
f = new FormulairePasseBassinDimensions();
francois.grand
committed
break;
case CalculatorType.PabPuissance:
francois.grand
committed
f = new FormulairePasseBassinPuissance();
francois.grand
committed
break;
case CalculatorType.ParallelStructure:
francois.grand
committed
f = new FormulaireParallelStructure();
break;
f = new FormulaireDever();
francois.grand
committed
default:
throw new Error(`FormulaireService.createFormulaire() : type de calculette ${ct} non pris en charge`)
}
f.defaultProperties["calcType"] = ct;
return f;
}
/**
* crée un formulaire d'un type donné
* @param ct type de formulaire
*/
public createFormulaire(ct: CalculatorType, jsonState?: {}): Promise<FormulaireDefinition> {
const f: FormulaireDefinition = this.newFormulaire(ct);
let prom: Promise<any> = this.loadConfig(ct);
return prom.then(s => {
f.preparseConfig(JSON.parse(s));
return f;
}).then(f => {
if (jsonState === undefined) {
f.calculatorName = decode(this.getLocalisedTitleFromCalculatorType(ct) + " (" + f.uid + ")");
f.initSessionNub();
}
else {
f.deserialiseJSON(jsonState);
const props = jsonState["props"];
f.initSessionNub(props);
}
return f;
}).then(f => {
f.parseConfig(undefined);
return f;
}).then(f => {
this.loadUpdateFormulaireLocalisation(f);
return f;
}).then(f => {
f.applyDependencies();
return f;
}).then(f => {
this.notifyObservers(
{
"form": f
});
public getFormulaireFromId(uid: number): FormulaireDefinition {
for (let f of this._formulaires)
francois.grand
committed
return undefined;
public getInputField(formId: number, elemId: string): InputField {
let s = this.getFormulaireElementById(formId, elemId);
if (!(s instanceof InputField))
throw "Form element with id '" + elemId + "' is not an input";
return <InputField>s;
}
public getCheckField(formId: number, elemId: string): CheckField {
let s = this.getFormulaireElementById(formId, elemId);
if (!(s instanceof CheckField))
throw "Form element with id '" + elemId + "' is not a checkbox";
return <CheckField>s;
public getSelectField(formId: number, elemId: string): SelectField {
let s = this.getFormulaireElementById(formId, elemId);
if (!(s instanceof SelectField))
throw "Form element with id '" + elemId + "' is not a select";
return <SelectField>s;
private getFormulaireElementById(formId: number, elemId: string): FormulaireElement {
for (let f of this._formulaires)
francois.grand
committed
let 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)
return f;
return undefined;
}
public getConfigPathPrefix(ct: CalculatorType): string {
throw "FormulaireService.getConfigPathPrefix() : invalid undefined CalculatorType"
switch (ct) {
case CalculatorType.ConduiteDistributrice:
return "app/calculators/cond_distri/cond_distri.";
case CalculatorType.LechaptCalmon:
return "app/calculators/lechapt-calmon/lechapt-calmon.";
case CalculatorType.SectionParametree:
return "app/calculators/section-param/section-param.";
case CalculatorType.RegimeUniforme:
return "app/calculators/regime-uniforme/regime-uniforme.";
francois.grand
committed
case CalculatorType.CourbeRemous:
return "app/calculators/remous/remous.";
case CalculatorType.PabDimensions:
return "app/calculators/pab-dimensions/pab-dimensions.";
case CalculatorType.PabPuissance:
return "app/calculators/pab-puissance/pab-puissance.";
case CalculatorType.Structure:
return "app/calculators/ouvrages/ouvrages.";
case CalculatorType.ParallelStructure:
return "app/calculators/parallel-structures/parallel-structures.";
case CalculatorType.Dever:
return "app/calculators/dever/dever.";
throw new Error("FormulaireService.getConfigPathPrefix() : valeur de CalculatorType " + ct + " non implémentée")
public requestCloseForm(uid: number) {
const form = this.getFormulaireFromId(uid);
this._formulaires = this._formulaires.filter(f => f.uid !== uid);
this.notifyObservers({
"form": form
});
}
}
public get currentFormId() {
return this._currentFormId;
}
public setCurrentForm(formId: number) {
const form = this.getFormulaireFromId(formId);
this._currentFormId = -1;
this.notifyObservers({
"action": "invalidFormId",
"formId": formId
});
this._currentFormId = formId;
this.notifyObservers({
"action": "currentFormChanged",
"formId": formId
francois.grand
committed
private get currentForm(): FormulaireDefinition {
return this.getFormulaireFromId(this._currentFormId);
}
public get currentFormHasResults(): boolean {
const form = this.currentForm;
francois.grand
committed
return form.hasResults;
return false;
}
francois.grand
committed
private readSingleFile(file: File): Promise<any> {
return new Promise<any>((resolve, reject) => {
var fr = new FileReader();
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 calculettes sélectionnées
* @param f fichier session
* @param formInfos infos sur les calculettes @see LoadCalculatorComponent._calculators
*/
public loadSession(f: File, formInfos: any[]) {
this.readSingleFile(f).then(s => {
const session = JSON.parse(s);
for (const k in session)
switch (k) {
case "session":
francois.grand
committed
this.deserialiseSession(session[k], formInfos);
break;
default:
throw new Error(`session file : invalid key '${k}'`);
}
}).catch(err => {
throw err;
});
public saveSession(session: {}, filename?: string) {
francois.grand
committed
const blob = new Blob([JSON.stringify(session)], { type: "text/plain;charset=utf-8" });
saveAs(blob, filename);
francois.grand
committed
}
francois.grand
committed
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
/**
* obtient des infos (nom, uid des calculettes) d'un fichier session
* @param f fichier session
*/
public calculatorInfosFromSessionFile(f: File): Promise<any[]> {
return this.readSingleFile(f).then(s => {
const res: any[] = [];
const session = JSON.parse(s);
// liste des noms de calculettes
for (const k in session)
switch (k) {
case "session":
const sess = session[k];
const elems = sess["elements"];
for (const e of elems)
for (const k in e)
if (k === "form") {
const form = e[k];
res.push({ "uid": form["uid"], "title": form["id"] });
}
break;
default:
throw new Error(`session file : invalid key '${k}'`);
}
return res;
});
}
francois.grand
committed
public saveForm(f: FormulaireDefinition) {
this.notifyObservers({
"action": "saveForm",
"form": f
});
}
private deserialiseForm(elements: {}) {
const props = elements["props"];
const ct: CalculatorType = props["calcType"];
this.createFormulaire(ct, elements);
}
francois.grand
committed
private deserialiseSessionElement(element: {}, formInfos: any[]) {
const keys = Object.keys(element);
if (keys.length !== 1)
throw new Error(`session file : invalid session object '${element}'`);
switch (keys[0]) {
case "form":
francois.grand
committed
const form = element[keys[0]];
for (const i of formInfos)
francois.grand
committed
this.deserialiseForm(form);
break;
default:
throw new Error(`session file : invalid key '${keys[0]}' in session object`);
}
}
francois.grand
committed
private deserialiseSession(elements: {}, formInfos: any[]) {
for (const ks in elements)
switch (ks) {
case "elements":
for (const e of elements[ks])
francois.grand
committed
this.deserialiseSessionElement(e, formInfos);
break;
default:
throw new Error(`session file : invalid key '${ks}' in session object`);
}
}
francois.grand
committed
/**
francois.grand
committed
* @returns liste des valeurs liables à un paramètre sous la forme d'un tableau d'objets
francois.grand
committed
* {"param":<paramètre lié>, "nub":<Nub d'origine du paramètre lié>, "formTitle":<nom de la calculette liée au nub>}
francois.grand
committed
* @param p paramètre qui sert de clé de recherche des paramètres liables
francois.grand
committed
*/
francois.grand
committed
public getLinkableValues(p: NgParameter): any[] {
francois.grand
committed
let res: any[] = [];
if (p !== undefined)
for (const f of this._formulaires) {
francois.grand
committed
// nub associé au formulaire
francois.grand
committed
const sn = f.currentSessionNub;
francois.grand
committed
francois.grand
committed
try {
// on vérifie que le paramètre en entrée appartient au nub
const np = sn.nub.getParameter(p.symbol);
francois.grand
committed
// si oui, on demande à exclure des valeurs retournées le résultat du même nom que le paramètre
const ps = sn.getLinkableValues(p.paramDefinition, p.paramDefinition.uid === np.uid);
for (const np of ps) {
np["formTitle"] = f.calculatorName;
res.push(np);
}
francois.grand
committed
}
francois.grand
committed
catch (e) {
// p.symbol n'existe pas dans le nub testé
}
francois.grand
committed
}
return res;
}
francois.grand
committed
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
/**
* 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 //)
* @param values valeurs liables (modifié par la méthode)
*/
public filterLinkableValues(values: any[]): any[] {
// suppression des paramètres non affichés
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
let found: boolean = false;
if (parentForm !== undefined)
for (const fe of parentForm.allFormElements)
if (fe instanceof NgParameter)
if (fe.paramDefinition.uid === prm.uid) {
found = true;
break;
}
if (!found)
values.splice(i, 1);
}
}
return values;
}