diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000000000000000000000000000000000000..560298a3045c52d0ab3ab4eaeeec40ee183c8432 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,24 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "chrome", + "request": "launch", + "name": "Launch Chrome (local webserver)", + "url": "http://localhost:4200", + "webRoot": "${workspaceFolder}", + "runtimeExecutable": "/usr/bin/chromium-browser" + }, + { + "name": "Launch Firefox (local webserver)", + "type": "firefox", + "request": "launch", + "reAttach": true, + "url": "http://localhost:4200", + "webRoot": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/jalhyd_branch b/jalhyd_branch index 1f7391f92b6a3792204e07e99f71f643cc35e7e1..d918178ee85dc2bcfd1fc54e443dc6f25955d946 100644 --- a/jalhyd_branch +++ b/jalhyd_branch @@ -1 +1 @@ -master +45-importation-d-un-parametre-resultat-ou-resultat-complementaire-d-une-autre-calculette diff --git a/src/app/app.component.ts b/src/app/app.component.ts index f71d031e10b2674c67c337d6f66c4b34bd5de60c..8f495b5da0dbe4234713a14f92f25418f2569097 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -368,7 +368,9 @@ export class AppComponent implements OnInit, OnDestroy, Observer { */ @HostListener('window:beforeunload', ['$event']) confirmExit($event) { - // affecter une valeur différente de null provoque l'affichage d'un dialogue de confirmation, mais le texte n'est pas affiché - $event.returnValue = 'Your data will be lost !'; + if (environment.production) { + // affecter une valeur différente de null provoque l'affichage d'un dialogue de confirmation, mais le texte n'est pas affiché + $event.returnValue = 'Your data will be lost !'; + } } } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index e084fe592034151af1d011caaf7dd1d531a7abc8..d5fb120410be0b16bc83e3198dcc029abee4aa4d 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -53,6 +53,7 @@ import { LoadCalculatorComponent } from './components/load-calculator/load-calcu import { LoadCalcDialogAnchorDirective } from './components/load-calculator/load-calculator-anchor.directive'; import { SaveCalculatorComponent } from './components/save-calculator/save-calculator.component'; import { SaveCalcDialogAnchorDirective } from './components/save-calculator/save-calculator-anchor.directive'; +import { ParamLinkComponent } from './components/param-link/param-link.component'; const appRoutes: Routes = [ { path: 'list', component: CalculatorListComponent }, @@ -100,7 +101,8 @@ const appRoutes: Routes = [ FixedResultsComponent, VarResultsComponent, HelpComponent, LoadCalculatorComponent, LoadCalcDialogAnchorDirective, - SaveCalculatorComponent, SaveCalcDialogAnchorDirective + SaveCalculatorComponent, SaveCalcDialogAnchorDirective, + ParamLinkComponent ], // entryComponents: [AlertDialog], entryComponents: [LoadCalculatorComponent, SaveCalculatorComponent], diff --git a/src/app/components/field-set/field-set.component.ts b/src/app/components/field-set/field-set.component.ts index 1c14aafc4185fa19cc05fc904844a2b2a092313d..cbf78ed49f4f3602b7382efd91d71ac4ca0b0ce1 100644 --- a/src/app/components/field-set/field-set.component.ts +++ b/src/app/components/field-set/field-set.component.ts @@ -261,6 +261,13 @@ export class FieldSetComponent implements DoCheck { this._paramComponents.forEach(fsc => fsc.updateParameterFromUI()); } + /** + * met à jour les paramètres liés + */ + public updateLinkedParameters() { + this._paramComponents.forEach(fsc => fsc.updateLinkedParameter()); + } + /** * clic sur le bouton ajouter */ diff --git a/src/app/components/fieldset-container/fieldset-container.component.ts b/src/app/components/fieldset-container/fieldset-container.component.ts index 240f408b9337099a717173d56df4b9632e1e30ca..947302dee60faf8f7c06174212a4a6641545725d 100644 --- a/src/app/components/fieldset-container/fieldset-container.component.ts +++ b/src/app/components/fieldset-container/fieldset-container.component.ts @@ -161,6 +161,13 @@ export class FieldsetContainerComponent implements DoCheck, AfterViewInit { this._fieldsetComponents.forEach(fsc => fsc.updateParametersFromUI()); } + /** + * met à jour les paramètres liés + */ + public updateLinkedParameters() { + this._fieldsetComponents.forEach(fsc => fsc.updateLinkedParameters()); + } + /** * réception d'un événement de demande d'ajout d'un FieldSet */ diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts index b7b8a07fc9487b2738c8179cf7ee0d1090eaf1bc..2b0a443f97c077b33886bf5f2c44ed3f769c912a 100644 --- a/src/app/components/generic-calculator/calculator.component.ts +++ b/src/app/components/generic-calculator/calculator.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, DoCheck, OnDestroy, ViewChild, ViewChildren, QueryList } from "@angular/core"; +import { Component, OnInit, DoCheck, OnDestroy, ViewChild, ViewChildren, QueryList, AfterViewChecked } from "@angular/core"; import { ActivatedRoute } from '@angular/router'; import { Observer } from "jalhyd"; @@ -39,7 +39,7 @@ import { ServiceFactory } from "../../services/service-factory"; ` ] }) -export class GenericCalculatorComponent extends BaseComponent implements OnInit, DoCheck, OnDestroy, Observer { +export class GenericCalculatorComponent extends BaseComponent implements OnInit, DoCheck, AfterViewChecked, OnDestroy, Observer { /** * liste des FieldSetComponent */ @@ -89,6 +89,14 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, */ private isCalculateDisabled: boolean = true; + /** + * flag (+info) indiquant un événement onRadio à traiter + * nécessaire avec l'introduction du mode de valeur LINK des paramètres car quand on modifie le mode à LINK, les possibles + * paramètres liables ne sont pas encore connus + */ + private _pendingRadioClick: boolean = false; + private _pendingRadioClickInfo: any; + // services private intlService: InternationalisationService; @@ -105,7 +113,7 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, private get formElements(): FormulaireElement[] { if (this._formulaire == undefined) return []; - return this._formulaire.formElements; + return this._formulaire.kids as FormulaireElement[]; } /** @@ -193,7 +201,17 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, * gestion des événements clic sur les radios */ private onRadioClick(info: any) { - this._formulaire.onRadioClick(info); + this.updateLinkedParameters(); + this._pendingRadioClick = true; + this._pendingRadioClickInfo = info; + } + + public ngAfterViewChecked() { + if (this._pendingRadioClick) { + this._pendingRadioClick = false; + this._formulaire.onRadioClick(this._pendingRadioClickInfo); + this._pendingRadioClickInfo = undefined; + } } private onCloseForm() { @@ -219,6 +237,14 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, this._fieldsetContainerComponents.forEach(fscc => fscc.updateParametersFromUI()); } + /** + * met à jour les paramètres liés + */ + private updateLinkedParameters() { + this._fieldsetComponents.forEach(fsc => fsc.updateLinkedParameters()); + this._fieldsetContainerComponents.forEach(fscc => fscc.updateLinkedParameters()); + } + private doCompute() { this.updateParametersFromUI(); this._formulaire.doCompute(); diff --git a/src/app/components/ngparam-input/ngparam-input.component.ts b/src/app/components/ngparam-input/ngparam-input.component.ts index abce24cdfbdc44650ae0a0e7f389f8115023d526..bba17a97f99d03cb6696d95801689d46af2f3386 100644 --- a/src/app/components/ngparam-input/ngparam-input.component.ts +++ b/src/app/components/ngparam-input/ngparam-input.component.ts @@ -115,6 +115,20 @@ export class NgParamInputComponent extends GenericInputComponent implements Obse this._tmp = data["value"]; this.updateAndValidateUI(); } + break; + + // changement de valueMode du paramètre ou de valeur à laquelle il est lié + case "valueModeChange": + case "valueLinkChange": + if (this._tmp !== data["value"]) { + this._tmp = data["value"]; + this.updateAndValidateUI(); + } + break; } } + + public ngOnDestroy() { + this._paramDef.removeObserver(this); + } } diff --git a/src/app/components/param-field-line/param-field-line.component.html b/src/app/components/param-field-line/param-field-line.component.html index b504852524f154d58adcfce7ab77d1030ab30036..d3ae40fd9df0a92537e7443cd6347772c46d8dcd 100644 --- a/src/app/components/param-field-line/param-field-line.component.html +++ b/src/app/components/param-field-line/param-field-line.component.html @@ -27,7 +27,17 @@ value="cal" (click)="onRadioClick('cal')" [checked]=radioCalCheck [disabled]=isDisabled id="radio_cal"> {{uitextParamCalculer}} </label> + + <!-- radio "lié" --> + <label *ngIf="hasRadioLink()" class="{{radioLinkClass}} h-75 px-3 py-3" [(ngModel)]="radioModel" mdbRadio="Right" name="radio_param_{{symbol}}" + value="link" (click)="onRadioClick('link')" [checked]=radioLinkCheck [disabled]=isDisabled id="radio_link"> + {{uitextParamLie}} + </label> </div> </div> -<param-values *ngIf="isRadioVarChecked" [param]="_param" (onValid)=onParamValuesValid($event)></param-values> \ No newline at end of file +<!-- composant pour gérer le cas "paramètre à varier" (min-max/liste de valeurs) --> +<param-values *ngIf="isRadioVarChecked" [param]="_param" (onValid)=onParamValuesValid($event)></param-values> + +<!-- composant pour gérer le cas "paramètre lié" --> +<param-link *ngIf="isRadioLinkChecked" [param]="_param" (onValid)=onParamValuesValid($event)></param-link> \ No newline at end of file diff --git a/src/app/components/param-field-line/param-field-line.component.ts b/src/app/components/param-field-line/param-field-line.component.ts index d43df61f3c4f4a7bd72b86cee476ccf4f992d039..c957e6b1a8a9a766c3ce67f64b083c8b478eccaf 100644 --- a/src/app/components/param-field-line/param-field-line.component.ts +++ b/src/app/components/param-field-line/param-field-line.component.ts @@ -4,7 +4,9 @@ import { InternationalisationService } from "../../services/internationalisation import { NgParameter, ParamRadioConfig } from "../../formulaire/ngparam"; import { NgParamInputComponent } from "../ngparam-input/ngparam-input.component"; import { ServiceFactory } from "../../services/service-factory"; -import { ParamValueMode } from "jalhyd"; +import { ParamValueMode, CalculatorType, ParallelStructure } from "jalhyd"; +import { FormulaireService } from "../../services/formulaire/formulaire.service"; +import { ParamLinkComponent } from "../param-link/param-link.component"; @Component({ selector: "param-field-line", @@ -33,6 +35,9 @@ export class ParamFieldLineComponent implements OnChanges { @ViewChild(NgParamInputComponent) private _ngParamInputComponent: NgParamInputComponent; + @ViewChild(ParamLinkComponent) + private _paramLinkComponent: ParamLinkComponent; + @Output() private onValid: EventEmitter<void>; @@ -51,8 +56,11 @@ export class ParamFieldLineComponent implements OnChanges { private intlService: InternationalisationService; + private _formService: FormulaireService; + constructor() { this.intlService = ServiceFactory.instance.internationalisationService; + this._formService = ServiceFactory.instance.formulaireService; this.onValid = new EventEmitter(); this.inputChange = new EventEmitter(); } @@ -78,6 +86,10 @@ export class ParamFieldLineComponent implements OnChanges { return this.intlService.localizeText("INFO_PARAMFIELD_PARAMCALCULER"); } + private get uitextParamLie() { + return this.intlService.localizeText("INFO_PARAMFIELD_PARAMLIE"); + } + /** * Parameter symbol (Q, Ks, B, ...) input attribute */ @@ -91,7 +103,7 @@ export class ParamFieldLineComponent implements OnChanges { private hasRadioFix(): boolean { switch (this._param.radioConfig) { case ParamRadioConfig.FIX: - return false; + return this.hasRadioLink(); default: return true; @@ -125,6 +137,26 @@ export class ParamFieldLineComponent implements OnChanges { } } + /** + * calcule la présence du radio "paramètre lié" (importé d'une autre calculette) + */ + private hasRadioLink(): boolean { + if (this._formService.formulaires.length > 0) { + // au moins 2 calculettes ouvertes + if (this._formService.formulaires.length > 1) + return this._formService.filterLinkableValues(this._formService.getLinkableValues(this._param)).length > 0; + + // ou une seule calculette "ouvrages parallèles" + if (this._formService.formulaires[0].calculatorType == CalculatorType.ParallelStructure) { + const ps: ParallelStructure = this._formService.formulaires[0].currentSessionNub.nub as ParallelStructure; + if (ps.structures.length > 1) + return this._formService.filterLinkableValues(this._formService.getLinkableValues(this._param)).length > 0; + } + + } + return false; + } + /** * calcule l'état du radio "paramètre fixé" */ @@ -148,6 +180,15 @@ export class ParamFieldLineComponent implements OnChanges { return undefined; } + /** + * calcule l'état du radio "paramètre lié" + */ + private get radioLinkCheck(): string { + if (this._param.radioState == ParamRadioConfig.LINK) + return "checked"; + return undefined; + } + /** * retourne l'état du radio "paramètre fixé" sous forme booléenne */ @@ -162,6 +203,13 @@ export class ParamFieldLineComponent implements OnChanges { return this._param.radioState == ParamRadioConfig.VAR; } + /** + * retourne l'état du radio "paramètre lié" sous forme booléenne + */ + private get isRadioLinkChecked(): boolean { + return this._param.radioState == ParamRadioConfig.LINK; + } + /* * gestion des événements clic sur les radios : * envoi d'un message au composant parent @@ -173,9 +221,12 @@ export class ParamFieldLineComponent implements OnChanges { private onRadioClick(option: string) { const oldValue = this._param.valueMode; + switch (option) { case "fix": + const oldValueMode = this._param.valueMode; this._param.valueMode = ParamValueMode.SINGLE; + this._param.setValue(this, this._param.paramDefinition.paramValues.singleValue); break; case "var": @@ -185,6 +236,10 @@ export class ParamFieldLineComponent implements OnChanges { case "cal": this._param.valueMode = ParamValueMode.CALCUL; break; + + case "link": + this._param.valueMode = ParamValueMode.LINK; + break; } this.onRadio.emit({ @@ -240,6 +295,15 @@ export class ParamFieldLineComponent implements OnChanges { return ""; } + /** + * classe du radio "lié" + */ + private get radioLinkClass(): string { + if (this.on) + return this.radioLinkCheck == undefined ? this.offClass : this.onClass; + return ""; + } + /** * validité des saisies du composant */ @@ -302,4 +366,12 @@ export class ParamFieldLineComponent implements OnChanges { public updateParameterFromUI() { this._ngParamInputComponent.updateModelFromUI(); } + + /** + * met à jour les paramètres liés + */ + public updateLinkedParameter() { + if (this._paramLinkComponent !== undefined) + this._paramLinkComponent.updateParamList(); + } } diff --git a/src/app/components/param-link/param-link.component.html b/src/app/components/param-link/param-link.component.html new file mode 100644 index 0000000000000000000000000000000000000000..1fc1166766aeb759588caf42bd7188988076d4c3 --- /dev/null +++ b/src/app/components/param-link/param-link.component.html @@ -0,0 +1,13 @@ +<div class="row"> + <div class="btn-group col-6 col-sm-3" dropdown (click)="onSelectLinkableParam($event)"> + <button dropdownToggle class="btn btn-primary dropdown-toggle waves-light my-1" type="button" mdbRippleRadius> + {{currentLinkedParamLabel}} + </button> + <div class="dropdown-menu"> + <a class="dropdown-item" *ngFor="let e of _linkableParams" [value]=e>{{selectItemLabel(e)}}</a> + </div> + </div> + <div class="col-6 text-danger"> + {{_message}} + </div> +</div> \ No newline at end of file diff --git a/src/app/components/param-link/param-link.component.ts b/src/app/components/param-link/param-link.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..d7b5bc013a4ff9ac4a0a134bb0160055693a1d48 --- /dev/null +++ b/src/app/components/param-link/param-link.component.ts @@ -0,0 +1,200 @@ +import { Component, Input, Output, EventEmitter, OnChanges, OnDestroy } from "@angular/core"; + +import { NgParameter } from "../../formulaire/ngparam"; +import { ServiceFactory } from "../../services/service-factory"; +import { ParamValueMode, Observer, ParamDefinition } from "jalhyd"; +import { FormulaireService } from "../../services/formulaire/formulaire.service"; +import { FormulaireDefinition } from "../../formulaire/definition/form-definition"; + +@Component({ + selector: "param-link", + templateUrl: "./param-link.component.html" +}) +export class ParamLinkComponent implements OnChanges, Observer, OnDestroy { + // paramètre géré (qui sera lié à une valeur, cad qui importe cette valeur) + @Input("param") + private _param: NgParameter; + + @Output() + private onValid: EventEmitter<boolean>; + + /** + * indice actuel du paramètre sélectionné dans la lsite + */ + private _currentIndex = -1; + + /** + * message affiché à côté du select des paramètres + */ + private _message: string; + + /** + * liste des paramètres liables sous la forme + * {"name":<étiquette>, "value":<valeur liable>, "nub":<Nub d'origine du paramètre>, "formTitle":<nom de la calculette liée au nub>} + * + * l'étiquette "name" est de la forme <n|N1>[.[N2]] + * n : indice de de l'ouvrage dans le cas des ouvrages parallèles + * N1 : un nom de paramètre/résultat (dans le cas d'un résultat, il est suivi d'un point) + * N2 : nom de résultat complémentaire (optionnel) + * ex : + * Q, Z1 (paramètres) + * J. (résultat) + * .Yf (résultat complémentaire du résultat courant) + * Q.Yf (résultat complémentaire du résultat nommé "Q") + */ + private _linkableParams: any[]; + + private _formService: FormulaireService; + + constructor() { + this.onValid = new EventEmitter(); + this._formService = ServiceFactory.instance.formulaireService; + this._formService.addObserver(this); + } + + /** + * envoi d'un événement de validité + */ + private emitValidity() { + // this.onValid.emit(this._validList); + } + + /** + * réception d'un événement du menu des paramètres liables + */ + private onSelectLinkableParam(event: any) { + const next = event.target.value; + + let i = 0; + for (const e of this._linkableParams) + if (this._linkableParams[i].value.uid == next.value.uid) { + this.linkTo(i); + break; + } + else + i++; + } + + /** + * valeur courante affichée dans le select des paramètres liables + */ + private get currentLinkedParamLabel(): string { + if (this._linkableParams !== undefined) { + if (this._currentIndex === -1 || this._currentIndex >= this._linkableParams.length) + return undefined; + + return this.selectItemLabel(this._linkableParams[this._currentIndex]); + } + + return undefined; + } + + // // le paramètre est il déjà lié à une valeur ? si oui laquelle ? + // if(this._currentIndex === -1 && this._param.valueMode == ParamValueMode.LINK && this._linkableParams !== undefined) { + // let i = 0; + // for (const e of this._linkableParams) + // if (e.param.uid === this._param.paramDefinition.re) { + // this._currentIndex = i; + // break; + // } + // else + // i++; + // } + + /** + * attribut "label" d'une entrée du select des paramètres + */ + private selectItemLabel(i: any) { + const s = i.name; // nom associé au paramètre/à la valeur + const c = i.formTitle; // nom de la calculette + + const re5 = /(\d+)\.(.+)\.$/; // forme <nombre>.xxx. (résultat d'ouvrage) + const match5 = re5.exec(s); + if (match5 !== null) { + const n = +match5[1] + 1 + return `${match5[2]} (résultat de ${c}, ouvrage n°${n})`; + } + + const re1 = /([^\.]+)\.$/; // forme xxx. (résultat) + const match1 = re1.exec(s); + if (match1 !== null) + return `${match1[1]} (résultat de ${c})`; + + const re4 = /(\d+)\.(.+)/; // forme <nombre>.xxx (ouvrage) + const match4 = re4.exec(s); + if (match4 !== null) { + const n = +match4[1] + 1 + return `${match4[2]} (${c}, ouvrage n°${n})`; + } + + const re2 = /([^\.]+)\.(.+)/; // forme xxx.yyy (résultat complémentaire) + const match2 = re2.exec(s); + if (match2 !== null) + return `${match2[2]} (${c}, résultat complémentaire de ${match2[1]})`; + + const re3 = /^\.(.+)/; // forme .xxx (résultat complémentaire) + const match3 = re3.exec(s); + if (match3 !== null) + return `${match3[1]} (${c}, résultat complémentaire)`; + + return `${s} (${c})`; // forme simple (paramètre) + } + + /** + * lie le paramètre géré à un des paramètres liables de la liste + * @param index indice dans la liste + */ + private linkTo(index: number) { + if (this._currentIndex !== index) { + this._currentIndex = index; + const lp = this._linkableParams[index]; + + this._param.linkToParameter(lp.nub, lp.name); + } + } + + public updateParamList() { + // liste des paramètres liables + + if (this._param.valueMode === ParamValueMode.LINK) + this._linkableParams = this._formService.filterLinkableValues(this._formService.getLinkableValues(this._param)); + else + this._linkableParams = []; + + // initialisation de l'indice courant + + if (this._linkableParams.length > 0) { + if (this._currentIndex === -1) + this.linkTo(0); + this._message = undefined; + } + else { + this._currentIndex = -1; + this._message = "Aucun paramètre compatible trouvé"; + } + } + + public ngOnChanges() { + if (this._param !== undefined) + this._param.removeObserver(this); + this._param.addObserver(this); + + this.updateParamList(); + } + + public ngOnDestroy() { + this._param.removeObserver(this); + } + + // interface Observer + + public update(sender: any, data: any) { + if (sender instanceof FormulaireService) { + switch (data["action"]) { + case "createForm": + this.updateParamList(); + break; + } + } + } +} diff --git a/src/app/components/param-values/param-values.component.html b/src/app/components/param-values/param-values.component.html index d231d60368df700bfdf4e0473e6b24cc22c8f818..0335d8bddfbd2a6ee34e288de944edd1d8b307c5 100644 --- a/src/app/components/param-values/param-values.component.html +++ b/src/app/components/param-values/param-values.component.html @@ -8,13 +8,13 @@ </div> </div> - <div *ngIf="!isList" class="col-12 col-sm-3"> + <div *ngIf="isMinMax" class="col-12 col-sm-3"> <ngparam-min [title]="uitextValeurMini" (onChange)="onMinChanged($event)"></ngparam-min> </div> - <div *ngIf="!isList" class="col-12 col-sm-3"> + <div *ngIf="isMinMax" class="col-12 col-sm-3"> <ngparam-max [title]="uitextValeurMaxi" (onChange)="onMaxChanged($event)"></ngparam-max> </div> - <div *ngIf="!isList" class="col-12 col-sm-3"> + <div *ngIf="isMinMax" class="col-12 col-sm-3"> <ngparam-step [title]="uitextPasVariation" [param]=_param (onChange)="onStepChanged($event)"></ngparam-step> </div> diff --git a/src/app/components/param-values/param-values.component.ts b/src/app/components/param-values/param-values.component.ts index 91200b4644d6621f42c394c380a805950d2a171c..36761b432690baecbecafc7447b664ab7e593491 100644 --- a/src/app/components/param-values/param-values.component.ts +++ b/src/app/components/param-values/param-values.component.ts @@ -281,6 +281,13 @@ export class ParamValuesComponent extends BaseComponent implements AfterViewChec return this._param.valueMode == ParamValueMode.LISTE; } + /** + * true si mode "lié" + */ + private get isLink(): boolean { + return this._param.valueMode == ParamValueMode.LINK; + } + /** * true si mode "min/max/pas" */ diff --git a/src/app/components/remous-results/remous-results.component.ts b/src/app/components/remous-results/remous-results.component.ts index 07bbca115f0eb052f226c231adda47df5729d129..a986c11d1f9f34b312d801ad697fffbefa089b49 100644 --- a/src/app/components/remous-results/remous-results.component.ts +++ b/src/app/components/remous-results/remous-results.component.ts @@ -1,12 +1,11 @@ import { Component, ViewChild } from "@angular/core"; -import { ArrayReverseIterator, ResultElement, ParamValueIterator } from "jalhyd"; +import { ArrayReverseIterator, ResultElement, NumberIterator } from "jalhyd"; import { InternationalisationService } from "../../services/internationalisation/internationalisation.service"; import { LogComponent } from "../../components/log/log.component"; import { RemousResults } from "../../results/remous-results"; import { CalculatorResults } from "../../results/calculator-results"; -import { VarResults } from "../../results/var-results"; import { VarResultsComponent } from "../fixedvar-results/var-results.component"; @Component({ @@ -17,12 +16,12 @@ import { VarResultsComponent } from "../fixedvar-results/var-results.component"; text-align: right; padding-top:10px; padding-bottom:10px; - padding-right:10px; + padding-right:10px; } .result_value { text-align: center; - padding-left:30px; - padding-right:30px; + padding-left:30px; + padding-right:30px; } .result_id_0 { background-color: #f0f0f0; @@ -58,7 +57,7 @@ export class RemousResultsComponent { /** * true si les résultats doivent être mis à jour */ - private _doUpdate: boolean = false; + private _doUpdate = false; /** * composant des résultats variables @@ -76,54 +75,56 @@ export class RemousResultsComponent { } private get uitextLigneFluviale() { - return this.intlService.localizeText("INFO_REMOUSRESULTS_LIGNEFLUVIALE") + return this.intlService.getExtraResLabel("FLU"); } private get uitextLigneTorrentielle() { - return this.intlService.localizeText("INFO_REMOUSRESULTS_LIGNETORRENTIELLE") + return this.intlService.getExtraResLabel("TOR"); } private get uitextAbscisse() { - return this.intlService.localizeText("INFO_REMOUSRESULTS_ABSCISSE") + return this.intlService.localizeText("INFO_REMOUSRESULTS_ABSCISSE"); } private get uitextTirant() { - return this.intlService.localizeText("INFO_REMOUSRESULTS_TIRANT") + return this.intlService.localizeText("INFO_REMOUSRESULTS_TIRANT"); } private get uitextFond() { - return this.intlService.localizeText("INFO_REMOUSRESULTS_FOND") + return this.intlService.localizeText("INFO_REMOUSRESULTS_FOND"); } private get uitextBerge() { - return this.intlService.localizeText("INFO_REMOUSRESULTS_BERGE") + return this.intlService.localizeText("INFO_REMOUSRESULTS_BERGE"); } private get uitextTirantNormal() { - return this.intlService.localizeText("INFO_REMOUSRESULTS_TIRANTNORMAL") + return this.intlService.localizeText("INFO_REMOUSRESULTS_TIRANTNORMAL"); } private get uitextTirantCritique() { - return this.intlService.localizeText("INFO_REMOUSRESULTS_TIRANTCRITIQUE") + return this.intlService.localizeText("INFO_REMOUSRESULTS_TIRANTCRITIQUE"); } private get extraGraph(): boolean { - return this._remousResults == undefined ? false : this._remousResults.extraGraph; + return this._remousResults === undefined ? false : this._remousResults.extraGraph; } private get extraParamLabel(): string { - return this._remousResults == undefined ? undefined : this._remousResults.extraParamLabel; + return this._remousResults === undefined ? undefined : + this.intlService.getExtraResLabel(this._remousResults.extraParamSymbol); } public set results(rs: CalculatorResults[]) { this._remousResults = undefined; - if (rs != undefined) + if (rs !== undefined) { for (const r of rs) { if (r instanceof RemousResults) { this._remousResults = r; break; } } + } this.updateView(); } @@ -132,26 +133,30 @@ export class RemousResultsComponent { this.graph1_options = {}; this.graph2_data = {}; this.graph2_options = {}; - if (this.varResultsComponent != undefined) + if (this.varResultsComponent !== undefined) { this.varResultsComponent.results = undefined; - if (this.logComponent != undefined) + } + if (this.logComponent !== undefined) { this.logComponent.log = undefined; + } this._tableHeaders = []; - if (this._remousResults != undefined) + if (this._remousResults !== undefined) { this._doUpdate = this._remousResults.hasResults; + } } - /** + /** * appelé pour gérer les changements non détectés par Angular */ public ngDoCheck() { - if (this._doUpdate) + if (this._doUpdate) { this._doUpdate = !this.updateResults(); + } } private updateResults() { - if (this.logComponent != undefined && this._remousResults != undefined) { + if (this.logComponent !== undefined && this._remousResults !== undefined) { this.logComponent.log = this._remousResults.log; this.generateGraph(); return true; @@ -159,62 +164,66 @@ export class RemousResultsComponent { return false; } - private get abscisseIterator(): ParamValueIterator { + private get abscisseIterator(): NumberIterator { return this._remousResults.varResults.variatedParameter.paramDefinition.paramValues.getValuesIterator(); } private connectRessaut(lineFlu: LineData, lineTor: LineData) { - if (lineFlu != undefined && lineTor != undefined) { - let tX = lineFlu.tx.slice(0); // copie + if (lineFlu !== undefined && lineTor !== undefined) { + const tX = lineFlu.tx.slice(0); // copie tX.sort((a, b) => { - if (a > b) + if (a > b) { return 1; - if (a < b) + } + if (a < b) { return -1; + } return 0; }); let minXflu; // abscisse de début de la courbe fluviale let itX = this.abscisseIterator; - for (let re of this._remousResults.result.resultElements) { - if (!itX.hasNext) - throw new Error("RemousResultsComponent.connectRessaut() : erreur interne (itérateur sur x)") + for (const re of this._remousResults.result.resultElements) { + if (!itX.hasNext) { + throw new Error("RemousResultsComponent.connectRessaut() : erreur interne (itérateur sur x)"); + } const x = itX.next().value; - if (re.getExtraResult("flu") != undefined) { + if (re.getExtraResult("flu") !== undefined) { minXflu = x; break; } } - if (minXflu != undefined && minXflu != tX[0]) { + if (minXflu !== undefined && minXflu !== tX[0]) { // la courbe fluviale ne démarre pas au début, on ajoute un point de raccord avec la ligne torrentielle - let i = tX.indexOf(minXflu); - let xflu = tX[i - 1]; - let yflu = lineTor.getYat(xflu); + const i = tX.indexOf(minXflu); + const xflu = tX[i - 1]; + const yflu = lineTor.getYat(xflu); lineFlu.setPoint(xflu, yflu); } let maxXtor; // abscisse de fin de la courbe torrentielle const itRE = new ArrayReverseIterator<ResultElement>(this._remousResults.result.resultElements); itX = this.abscisseIterator; - for (let r of itRE) { - if (!itX.hasNext) - throw new Error("RemousResultsComponent.connectRessaut() : erreur interne (itérateur sur x)") + for (const r of itRE) { + if (!itX.hasNext) { + throw new Error("RemousResultsComponent.connectRessaut() : erreur interne (itérateur sur x)"); + } const x = itX.next(); - if (r.getExtraResult("tor") != undefined) { + if (r.getExtraResult("tor") !== undefined) { maxXtor = x; break; } } - if (maxXtor != undefined && maxXtor != tX[tX.length - 1]) { + if (maxXtor !== undefined && maxXtor !== tX[tX.length - 1]) { // la courbe torrentielle ne finit pas à la fin des abscisses, on ajoute un point de raccord avec la ligne fluviale - let i = tX.indexOf(maxXtor); - let xflu = tX[i + 1]; - let yflu = lineFlu.getYat(xflu); + const i = tX.indexOf(maxXtor); + const xflu = tX[i + 1]; + const yflu = lineFlu.getYat(xflu); lineTor.setPoint(xflu, yflu); } } @@ -225,86 +234,109 @@ export class RemousResultsComponent { // le dernier dataset de la liste datasets est dessiné en 1er this._remousResults.update(); - if (this.varResultsComponent) + if (this.varResultsComponent) { this.varResultsComponent.results = this._remousResults.varResults; + } const penteFond: number = this._remousResults.penteFond; // abscisses let labs: number[] = []; + let xmax: number; if (this._remousResults.result.ok) { - var xmax = -1e8; - const itX = this.abscisseIterator; - while (itX.hasNext) { - const x = itX.next().value; + xmax = -1e8; + const itX2 = this.abscisseIterator; + while (itX2.hasNext) { + const x = itX2.next().value; labs.push(x); xmax = Math.max(x, xmax); } - } - else { + } else { labs = [0, 1]; xmax = 1; } // init graphiques - let gr1 = new GraphData(labs, penteFond, xmax); - if (this._remousResults.extraGraph) - var gr2 = new GraphData(labs, 0, xmax); + const gr1 = new GraphData(labs, penteFond, xmax); + let gr2: GraphData; + if (this._remousResults.extraGraph) { + gr2 = new GraphData(labs, 0, xmax); + } // ligne de fond gr1.drawLine(0, 0, 3, "#753F00", this.uitextFond, "#753F00"); // ligne de berge - if (this._remousResults.hautBerge) + if (this._remousResults.hautBerge) { gr1.drawLine(this._remousResults.hautBerge, this._remousResults.hautBerge, 4, "#C58F50", this.uitextBerge); + } // hauteur normale - if (this._remousResults.hautNormale != undefined && this._remousResults.hautNormale.ok) - gr1.drawLine(this._remousResults.hautNormale.vCalc, this._remousResults.hautNormale.vCalc, 5, "#A4C537", this.uitextTirantNormal); + if (this._remousResults.hautNormale !== undefined && this._remousResults.hautNormale.ok) { + gr1.drawLine(this._remousResults.hautNormale.vCalc, this._remousResults.hautNormale.vCalc, + 5, "#A4C537", this.uitextTirantNormal + ); + } // hauteur critique - if (this._remousResults.hautCritique != undefined && this._remousResults.hautCritique.ok) - gr1.drawLine(this._remousResults.hautCritique.vCalc, this._remousResults.hautCritique.vCalc, 6, "#FF0000", this.uitextTirantCritique); + if (this._remousResults.hautCritique !== undefined && this._remousResults.hautCritique.ok) { + gr1.drawLine(this._remousResults.hautCritique.vCalc, this._remousResults.hautCritique.vCalc, + 6, "#FF0000", this.uitextTirantCritique + ); + } // lignes d'eau torrentielle et fluviale - if (this._remousResults.hasFluData) - var lineFlu = gr1.newLine(0); - if (this._remousResults.hasTorData) - var lineTor = gr1.newLine(1); + let lineFlu: LineData; + if (this._remousResults.hasFluData) { + lineFlu = gr1.newLine(0); + } + let lineTor: LineData; + if (this._remousResults.hasTorData) { + lineTor = gr1.newLine(1); + } + let lineExtra: LineData; if (this._remousResults.hasExtra) { - if (this._remousResults.extraGraph) - var lineExtra = gr2.newLine(2); - else + if (this._remousResults.extraGraph) { + lineExtra = gr2.newLine(2); + } else { lineExtra = gr1.newLine(2); + } } const itX = this.abscisseIterator; - for (let re of this._remousResults.result.resultElements) { + for (const re of this._remousResults.result.resultElements) { if (!itX.hasNext) - throw new Error("RemousResultsComponent.generateGraph() : erreur interne (itérateur sur x)") + throw new Error("RemousResultsComponent.generateGraph() : erreur interne (itérateur sur x)"); const x = itX.next().value; - const yExtra = re.getExtraResult("tRes"); - if (yExtra != undefined) + const yExtra = re.getExtraResult(this._remousResults.extraParamSymbol); + if (yExtra !== undefined) lineExtra.mapPoint(x, yExtra); const yFlu = re.getExtraResult("flu"); - if (yFlu != undefined) + if (yFlu !== undefined) lineFlu.mapPoint(x, yFlu); const yTor = re.getExtraResult("tor"); - if (yTor != undefined) + if (yTor !== undefined) lineTor.mapPoint(x, yTor); } if (this._remousResults.hasExtra) { - if (this._remousResults.extraGraph) - lineExtra.data = { label: this._remousResults.extraParamLabel, tension: 0, spanGaps: true, borderColor: "#0093BD", pointRadius: 4 }; - else - lineExtra.data = { label: this._remousResults.extraParamLabel, tension: 0, fill: false, spanGaps: true, borderColor: "#C17AF0", pointRadius: 4 }; + if (this._remousResults.extraGraph) { + lineExtra.data = { + label: this.extraParamLabel, + tension: 0, spanGaps: true, borderColor: "#0093BD", pointRadius: 4 + }; + } else { + lineExtra.data = { + label: this.extraParamLabel, + tension: 0, fill: false, spanGaps: true, borderColor: "#C17AF0", pointRadius: 4 + }; + } } // raccordement ligne fluviale -> torrentielle pour dessiner le ressaut @@ -313,9 +345,9 @@ export class RemousResultsComponent { // ajout des données au graphique - if (lineTor != undefined) + if (lineTor !== undefined) lineTor.data = { label: this.uitextLigneTorrentielle, tension: 0, borderColor: "#77A3CD", pointBackgroundColor: "#77A3CD", pointRadius: 4, backgroundColor: "#D1D0D4" }; - if (lineFlu != undefined) + if (lineFlu !== undefined) lineFlu.data = { label: this.uitextLigneFluviale, tension: 0, borderColor: "#0093BD", pointBackgroundColor: "#0093BD", pointRadius: 4, backgroundColor: "#D1D0D4" }; this.graph1_data = gr1.data; @@ -368,7 +400,7 @@ export class RemousResultsComponent { } private get hasResults(): boolean { - return this._remousResults != undefined && this._remousResults.hasResults; + return this._remousResults !== undefined && this._remousResults.hasResults; } private get hasData(): boolean { @@ -414,12 +446,12 @@ class LineData { } public getYat(x: number) { - let i = this._tx.indexOf(x); + const i = this._tx.indexOf(x); return this._ty[i]; } public setPoint(x: number, y: number) { - let i = this._tx.indexOf(x); + const i = this._tx.indexOf(x); this._ty[i] = y; } @@ -436,7 +468,7 @@ class LineData { } public hasYs(): boolean { - for (let y of this._ty) + for (const y of this._ty) if (y != null) return true; return false; @@ -481,7 +513,7 @@ class GraphData { * @param z profondeur de la lign */ public newLine(z: number): LineData { - let res = new LineData(this); + const res = new LineData(this); res.z = z; this._lines.push(res); return res; @@ -515,19 +547,19 @@ class GraphData { * @param fillColor couleur de remplissage sous la ligne */ public drawLine(y0: number, ymax: number, prof: number, color: string, lbl: string, fillColor: string = undefined) { - let l = this.newLine(prof); + const l = this.newLine(prof); l.mapPoint(0, y0); l.mapPoint(this._longBief, ymax); // l.data = { label: lbl, data: l, fill: fillColor != undefined, tension: 0, borderColor: color, backgroundColor: fillColor, pointRadius: 0 }; l.data = { - label: lbl, fill: fillColor != undefined, tension: 0, spanGaps: true, + label: lbl, fill: fillColor !== undefined, tension: 0, spanGaps: true, borderColor: color, backgroundColor: fillColor, pointRadius: 0 }; } public get data() { - let ds = []; + const ds = []; this._lines.sort((a, b) => { if (a.z > b.z) return -1; @@ -536,7 +568,7 @@ class GraphData { return 0; }); - for (let l of this._lines) + for (const l of this._lines) ds.push(l.data); return { diff --git a/src/app/components/result-element/vertical-result-element.component.ts b/src/app/components/result-element/vertical-result-element.component.ts index 53fff99656de4a8e04de9b02562dac6bf7d28a7a..ae8f7c09c0ef8511914c5550006cd8aba0e224f0 100644 --- a/src/app/components/result-element/vertical-result-element.component.ts +++ b/src/app/components/result-element/vertical-result-element.component.ts @@ -54,7 +54,7 @@ export class VerticalResultElementComponent extends ResultElementBaseComponent { const lblClass = (i % 2) == 0 ? "label1" : "label2"; const valueClass = (i % 2) == 0 ? "value1" : "value2"; this.vcRef.createEmbeddedView(this.trTemplate, { - extraRes: { "label": this.intlService.translateLabel(k), "value": this.intlService.formatResult(k, er) }, + extraRes: { "label": this.intlService.getExtraResLabel(k), "value": this.intlService.formatResult(k, er) }, classes: { "label_class": lblClass, "value_class": valueClass } }); i++; diff --git a/src/app/components/section-results/section-results.component.ts b/src/app/components/section-results/section-results.component.ts index 0656b917ad31ae06cce6956c66e4734f40a2d57f..f296b115b73fdb4931c4eb04cf92b2de36632b14 100644 --- a/src/app/components/section-results/section-results.component.ts +++ b/src/app/components/section-results/section-results.component.ts @@ -16,12 +16,12 @@ import { InternationalisationService } from '../../services/internationalisation text-align: right; padding-top:10px; padding-bottom:10px; - padding-right:10px; + padding-right:10px; } .result_value { text-align: center; - padding-left:30px; - padding-right:30px; + padding-left:30px; + padding-right:30px; } .result_id_0 { background-color: #f0f0f0; @@ -82,7 +82,7 @@ export class SectionResultsComponent implements DoCheck { this._doUpdate = this._results.hasResults; } - /** + /** * appelé pour gérer les changements non détectés par Angular */ public ngDoCheck() { @@ -105,8 +105,7 @@ export class SectionResultsComponent implements DoCheck { // traduction des symboles des variables calculées for (const k in this._results.result.extraResults) { - const k2 = "INFO_GRANDEUR_" + k.toUpperCase(); - const lbl = this.intlService.localizeText(k2); + const lbl = k.toUpperCase(); const er = this._results.result.getExtraResult(k); this._resultElement.addExtraResult(lbl, er); diff --git a/src/app/formulaire/check-field.ts b/src/app/formulaire/check-field.ts index 95f1afcdb45ee0a00720fe2e42c60ac6a5339a28..f508e699a1714362f7f21720c1431a943adcf734 100644 --- a/src/app/formulaire/check-field.ts +++ b/src/app/formulaire/check-field.ts @@ -1,7 +1,4 @@ import { Field } from "./field"; -import { Dependency } from "./dependency/dependency"; -import { DependencyConditionType } from "./dependency/dependency-condition"; -import { FormulaireDefinition } from "./definition/form-definition"; import { FormulaireNode } from "./formulaire-node"; export class CheckField extends Field { diff --git a/src/app/formulaire/definition/concrete/form-courbe-remous.ts b/src/app/formulaire/definition/concrete/form-courbe-remous.ts index c4653bbace083e3b72966a065e931accb31f74b2..f67df0d0bad7a6af51e35c75cd330a1dddfeb63d 100644 --- a/src/app/formulaire/definition/concrete/form-courbe-remous.ts +++ b/src/app/formulaire/definition/concrete/form-courbe-remous.ts @@ -6,7 +6,6 @@ import { FormComputeCourbeRemous } from "../form-compute-courbe-remous"; import { FormulaireDefinition } from "../form-definition"; import { CalculatorResults } from "../../../results/calculator-results"; import { FieldSet } from "../../fieldset"; -import { SelectField } from "../../select-field"; export class FormulaireCourbeRemous extends FormulaireDefinition { private _formSection: FormDefSection; diff --git a/src/app/formulaire/definition/concrete/form-regime-uniforme.ts b/src/app/formulaire/definition/concrete/form-regime-uniforme.ts index db3fd0e698109c5bdfe1fb55a1ef8e936ad96818..611391ed1fd4c7e89fcebafbd018d20fa3053c12 100644 --- a/src/app/formulaire/definition/concrete/form-regime-uniforme.ts +++ b/src/app/formulaire/definition/concrete/form-regime-uniforme.ts @@ -76,7 +76,6 @@ export class FormulaireRegimeUniforme extends FormulaireDefinition implements Ob public reset() { super.reset(); - this._formParamCalc.parseOptions(this.jsonConfig); } // interface Observer diff --git a/src/app/formulaire/definition/form-compute-courbe-remous.ts b/src/app/formulaire/definition/form-compute-courbe-remous.ts index 664a17cf419b94ecf9266cbc6cec2abbe4eeb76e..69f3a832a3ce2f1c39faeb372d16b568dbe0e307 100644 --- a/src/app/formulaire/definition/form-compute-courbe-remous.ts +++ b/src/app/formulaire/definition/form-compute-courbe-remous.ts @@ -22,31 +22,30 @@ export class FormComputeCourbeRemous extends FormCompute { const prmCR: CourbeRemousParams = cr.parameters as CourbeRemousParams; const sect: acSection = prmCR.Sn; - let Yn: Result = sect.Calc("Yn"); // hauteur normale - let Yc: Result = sect.Calc("Yc"); // hauteur critique + const Yn: Result = sect.Calc("Yn"); // hauteur normale + const Yc: Result = sect.Calc("Yc"); // hauteur critique this.remousResults.parameters = prmCR; // méthode de résolution - let msf: SelectField = <SelectField>this._formBase.getFormulaireNodeById("select_resolution"); - let methRes: MethodeResolution = msf.getValue().value; + const msf: SelectField = <SelectField>this._formBase.getFormulaireNodeById("select_resolution"); + const methRes: MethodeResolution = msf.getValue().value; // variable supplémentaire à calculer - const extraSymbol: string = this._formBase.getSelectedValue("select_target"); + this.remousResults.extraParamSymbol = this._formBase.getSelectedValue("select_target"); // calcul - this.remousResults.result = cr.calculRemous(extraSymbol); + this.remousResults.result = cr.calculRemous(this.remousResults.extraParamSymbol); // données du graphe this.remousResults.hauteurNormale = Yn.resultElement; this.remousResults.hauteurCritique = Yc.resultElement; - if (extraSymbol) { - this.remousResults.extraParamLabel = this._formBase.getSelectedLabel("select_target"); - this.remousResults.extraGraph = ["Hs", "Hsc", "Yf", "Yt", "Yco"].indexOf(extraSymbol) == -1; + if (this.remousResults.extraParamSymbol) { + this.remousResults.extraGraph = ["Hs", "Hsc", "Yf", "Yt", "Yco"].indexOf(this.remousResults.extraParamSymbol) === -1; } else this.remousResults.extraGraph = false; diff --git a/src/app/formulaire/definition/form-compute-fixedvar.ts b/src/app/formulaire/definition/form-compute-fixedvar.ts index 1955e9350f40905ef743ed1e3a3be5eac17474e3..9285a6704e1367ad8523b7738120f08ae4924fee 100644 --- a/src/app/formulaire/definition/form-compute-fixedvar.ts +++ b/src/app/formulaire/definition/form-compute-fixedvar.ts @@ -15,7 +15,16 @@ export class FormComputeFixedVar extends FormCompute { } private getVariatedParameter(): NgParameter { - return this._formBase.getDisplayedParamFromState(ParamRadioConfig.VAR); + let res = this._formBase.getDisplayedParamFromState(ParamRadioConfig.VAR); + if (res !== undefined) + return res; + + const pms = this._formBase.getDisplayedParamListFromState(ParamRadioConfig.LINK); + for (const p of pms) + if (p.paramDefinition.hasMultipleValues) + return p; + + return undefined; } private getComputedParameter(): NgParameter { diff --git a/src/app/formulaire/definition/form-def-fixedvar.ts b/src/app/formulaire/definition/form-def-fixedvar.ts index 3c00d56577f7229e2720125787701b420d62e6fc..9016a8a3081104112b212f1231f9c5af7f892f47 100644 --- a/src/app/formulaire/definition/form-def-fixedvar.ts +++ b/src/app/formulaire/definition/form-def-fixedvar.ts @@ -19,33 +19,103 @@ export class FormDefFixedVar { /** * remet les radios de tous les paramètres à FIX sauf "me" et ceux (celui) à l'état "except" */ - protected resetOtherRadio(me: NgParameter, except: ParamRadioConfig) { + protected resetOtherRadio(me: NgParameter, except: ParamRadioConfig = undefined) { for (const p of this._formBase.allFormElements) { if (p instanceof NgParameter) - if (p != me && p.radioState != except && p.radioConfig != ParamRadioConfig.FIX) + if (p != me && p.radioState != except && p.radioState != ParamRadioConfig.LINK && p.radioConfig != ParamRadioConfig.FIX) p.valueMode = ParamValueMode.SINGLE; } } + /** + * gère un changement de mode pour un paramètre + * règles : + * - 1 seul paramètre CAL à la fois + * - 1 seul paramètre multivalué (VAR) à la fois (directement ou par liaison) + * - plusieurs paramètres FIX à la fois possible + * - plusieurs paramètres LINK à la fois possible si les 2 1ères règles sont respectées + * + * analyse : + * ancien état nouvel état action(s) + * FIX VAR action1 + * FIX CAL action2 + * FIX LINK si paramètre lié FIX : aucune + * si paramètre lié VAR : action1 + * si paramètre lié CAL : si valeur unique : aucune + * si valeur multiple : action1 + * si paramètre lié LINK : recommencer ce cas avec le paramètre lié + * + * VAR FIX aucune + * VAR CAL action2 + * VAR LINK si paramètre lié FIX : aucune + * si paramètre lié VAR : aucune + * si paramètre lié CAL : si valeur unique : aucune + * si valeur multiple : aucune + * si paramètre lié LINK : recommencer ce cas avec le paramètre lié + * + * CAL FIX action5 + * CAL VAR action3 + action5 + * CAL LINK si paramètre lié FIX : aucune + * si paramètre lié VAR : action3 + action4|action5 + * si paramètre lié CAL : action3 + action4|action5 + * si paramètre lié LINK : recommencer ce cas avec le paramètre lié + * + * action1 : reset (à FIX) de tous les autres paramètres que celui modifié sauf celui à CAL + * action2 : reset (à FIX) de tous les autres paramètres que celui modifié sauf celui/ceux à VAR + * action3 : reset (à FIX) de tous les autres paramètres que celui modifié + * action4 : mettre le paramètre désigné par la conf comme "par défault" à CAL + * action5 : mettre le 1er paramètre de la calculette à CAL + */ protected processRadioStateChange(sourceParam: NgParameter, oldState: ParamValueMode) { switch (oldState) { - case ParamValueMode.SINGLE: - switch (sourceParam.valueMode) { // nouvel état - case ParamValueMode.MINMAX: + case ParamValueMode.SINGLE: // ancien état + switch (sourceParam.valueMode) { + case ParamValueMode.MINMAX: // nouvel état case ParamValueMode.LISTE: this.resetOtherRadio(sourceParam, ParamRadioConfig.CAL); break; - case ParamValueMode.CALCUL: + case ParamValueMode.CALCUL: // nouvel état this.resetOtherRadio(sourceParam, ParamRadioConfig.VAR); break; + + case ParamValueMode.LINK: // nouvel état + if (sourceParam.paramDefinition.hasMultipleValues) + this.resetOtherRadio(sourceParam, ParamRadioConfig.CAL); + else { + const refParamValues = sourceParam.paramDefinition.referencedParamValues; + if (refParamValues !== undefined) // cad si on référence un paramètre et non un Result par ex + if (refParamValues.valueMode == ParamValueMode.LINK) + throw new Error(`références de paramètre en chaîne non pris en charge`); // cas à traiter + } + break; } break; - case ParamValueMode.LISTE: + case ParamValueMode.LISTE: // ancien état case ParamValueMode.MINMAX: - switch (sourceParam.valueMode) { // nouvel état - case ParamValueMode.CALCUL: + switch (sourceParam.valueMode) { + case ParamValueMode.CALCUL: // nouvel état + this.resetOtherRadio(sourceParam, ParamRadioConfig.VAR); + break; + + case ParamValueMode.LINK: // nouvel état + // mode du paramètre référencé + const refParamValues = sourceParam.paramDefinition.referencedParamValues; + if (refParamValues.valueMode === ParamValueMode.LINK) + throw new Error(`références de paramètre en chaîne non pris en charge`) + break; + } + break; + + case ParamValueMode.LINK: // ancien état + switch (sourceParam.valueMode) { + case ParamValueMode.MINMAX: // nouvel état + case ParamValueMode.LISTE: + this.resetOtherRadio(sourceParam, ParamRadioConfig.CAL); + break; + + case ParamValueMode.CALCUL: // nouvel état this.resetOtherRadio(sourceParam, ParamRadioConfig.VAR); break; } @@ -81,6 +151,13 @@ export class FormDefFixedVar { } } + private logParams() { + console.log("----"); + for (const fe of this._formBase.allFormElements) + if (fe instanceof NgParameter) + console.log(`${fe.paramDefinition.symbol} : ${ParamValueMode[fe.paramDefinition.valueMode]}`); + } + /** * gestion des événements clic sur les radios */ @@ -88,6 +165,8 @@ export class FormDefFixedVar { const param: NgParameter = info.param; // paramètre source de l'événement radio const old: ParamValueMode = info.oldValueMode; // ancien état (radio) + //this.logParams(); this.resetRadiosAndResults(param, old); + //this.logParams(); } } diff --git a/src/app/formulaire/definition/form-def-paramcalc.ts b/src/app/formulaire/definition/form-def-paramcalc.ts index 67bcd3939c70cfb13c729c0afacc1a8e26628337..de7d95b77ac5efcba949cb26594d2e4f8b36cd52 100644 --- a/src/app/formulaire/definition/form-def-paramcalc.ts +++ b/src/app/formulaire/definition/form-def-paramcalc.ts @@ -38,28 +38,56 @@ export class FormDefParamToCalculate extends FormDefFixedVar { } /** - * met le paramètre par défaut à CAL + * met le paramètre par défaut à CAL sauf si c'est "except" + * @param except paramètre à ne pas remettre à CAL */ - private setDefault(): NgParameter { + private setDefault(except: NgParameter = undefined): NgParameter { const defaultParamCal: NgParameter = this._formBase.getParamFromSymbol(this._defaultCalculatedParam); - defaultParamCal.valueMode = ParamValueMode.CALCUL; + if (except === undefined || defaultParamCal.uid !== except.uid) + defaultParamCal.valueMode = ParamValueMode.CALCUL; return defaultParamCal; } + /** + * @see FormDefFixedVar.processRadioStateChange pour l'analyse + */ protected processRadioStateChange(sourceParam: NgParameter, oldState: ParamValueMode) { super.processRadioStateChange(sourceParam, oldState); switch (oldState) { - case ParamValueMode.CALCUL: - switch (sourceParam.valueMode) { // nouvel état - case ParamValueMode.SINGLE: - this.setDefault(); + case ParamValueMode.CALCUL: // ancien état + switch (sourceParam.valueMode) { + case ParamValueMode.SINGLE: // nouvel état + this.setDefault(sourceParam); break; - case ParamValueMode.MINMAX: + case ParamValueMode.MINMAX: // nouvel état case ParamValueMode.LISTE: - super.resetOtherRadio(sourceParam, ParamRadioConfig.CAL); - this.setDefault(); + super.resetOtherRadio(sourceParam); + this.setDefault(sourceParam); + break; + + case ParamValueMode.LINK: // nouvel état + if (sourceParam.paramDefinition.hasMultipleValues) { + super.resetOtherRadio(sourceParam); + this.setDefault(); + } + else { + // mode du paramètre référencé + const refParamValues = sourceParam.paramDefinition.referencedParamValues; + if (refParamValues !== undefined) + switch (refParamValues.valueMode) { + case ParamValueMode.MINMAX: + case ParamValueMode.LISTE: + case ParamValueMode.CALCUL: + super.resetOtherRadio(sourceParam); + this.setDefault(); + break; + + case ParamValueMode.LINK: + throw new Error(`références de paramètre en chaîne non pris en charge`); // cas à traiter + } + } break; } } diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts index c9d0506967eeb3b97296704e826bfa8125904d6b..85656392cacfc0b289727e5f80d452017d648624 100644 --- a/src/app/formulaire/definition/form-definition.ts +++ b/src/app/formulaire/definition/form-definition.ts @@ -14,7 +14,6 @@ import { DeepFieldsetIterator } from "../form-iterator/deep-fieldset-iterator"; import { DeepFormulaireElementIterator } from "../form-iterator/deep-element-iterator"; import { TopFormulaireElementIterator } from "../form-iterator/top-element-iterator"; import { CalculatorResults } from "../../results/calculator-results"; -import { FieldsetTemplate } from "../fieldset-template"; /** * classe de base pour tous les formulaires @@ -183,7 +182,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs private parse_template_container(json: {}, templates: any[]) { const fsc: FieldsetContainer = new FieldsetContainer(this); fsc.parseConfig(json, templates); - this.formElements.push(fsc); + this.kids.push(fsc); } public parseDependencies(json: {}) { @@ -383,13 +382,9 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs return select.getValue().label; } - public get formElements(): FormulaireElement[] { - return this.kids as FormulaireElement[]; - } - public applyDependencies() { for (const fe of this.topFormElements) - fe.applyDependencies(this); + fe.applyDependencies(); } public abstract resetResults(); diff --git a/src/app/formulaire/definition/form-result-fixedvar.ts b/src/app/formulaire/definition/form-result-fixedvar.ts index 0dacc750a71041b2f37d20c05d72a2d652fa99da..695bc2059247e2fe753f826ab9bb94ce8cc56f53 100644 --- a/src/app/formulaire/definition/form-result-fixedvar.ts +++ b/src/app/formulaire/definition/form-result-fixedvar.ts @@ -1,4 +1,4 @@ -import { ResultElement, cLog } from "jalhyd"; +import { ResultElement, cLog, ParamValueMode } from "jalhyd"; import { FixedResults } from "../../results/fixed-results"; import { GraphType, VarResults } from "../../results/var-results"; @@ -40,6 +40,10 @@ export class FormResultFixedVar extends FormResult { for (const p of this._formBase.getDisplayedParamListFromState(ParamRadioConfig.FIX)) if (p.symbol !== "Pr") this._fixedResults.addFixedParameter(p); + + for (const p of this._formBase.getDisplayedParamListFromState(ParamRadioConfig.LINK)) + if (!p.paramDefinition.hasMultipleValues) + this._fixedResults.addFixedParameter(p); } public set graphType(t: GraphType) { diff --git a/src/app/formulaire/fieldset-container.ts b/src/app/formulaire/fieldset-container.ts index 1f384a140395d38231d64f8a7bb3e4a439e4a615..6d8c093b0a53a066dbfec7c21b72e0d77797618b 100644 --- a/src/app/formulaire/fieldset-container.ts +++ b/src/app/formulaire/fieldset-container.ts @@ -1,12 +1,8 @@ -import { Structure } from "jalhyd"; - import { FormulaireElement } from "./formulaire-element"; import { FieldSet } from "./fieldset"; import { FieldsetTemplate } from "./fieldset-template"; -import { Dependency } from "./dependency/dependency"; import { StringMap } from "../stringmap"; import { FormulaireNode } from "./formulaire-node"; -import { FormulaireParallelStructure } from "./definition/concrete/form-parallel-structures"; export class FieldsetContainer extends FormulaireElement { private _templates: FieldsetTemplate[]; diff --git a/src/app/formulaire/fieldset.ts b/src/app/formulaire/fieldset.ts index af553da83b6dd95dc4862dada03a2ecbeffe0d84..9cff04ec9478d00608ac1256ec229da70f013eea 100644 --- a/src/app/formulaire/fieldset.ts +++ b/src/app/formulaire/fieldset.ts @@ -1,8 +1,6 @@ import { CalculatorType, ComputeNodeType, ParamDefinition, LoiDebit, StructureType, Props, SessionNub, Observer } from "jalhyd"; import { FormulaireElement } from "./formulaire-element"; -import { Dependency } from "./dependency/dependency"; -import { DependencyConditionType } from "./dependency/dependency-condition"; import { Field } from "./field"; import { CheckField } from "./check-field"; import { SelectField } from "./select-field"; @@ -11,7 +9,6 @@ import { ServiceFactory } from "../services/service-factory"; import { ParamService } from "../services/param/param.service"; import { FormulaireDefinition } from "./definition/form-definition"; import { StringMap } from "../stringmap"; -import { FieldsetContainer } from "./fieldset-container"; import { FormulaireNode } from "./formulaire-node"; export class FieldSet extends FormulaireElement implements Observer { @@ -40,16 +37,6 @@ export class FieldSet extends FormulaireElement implements Observer { this._props = new Props(); } - /** - * formulaire parent - */ - private get parentForm(): FormulaireDefinition { - let res = this.parent; - while (!(res instanceof FormulaireDefinition)) - res = res.parent; - return res as FormulaireDefinition; - - } public get sessionNub(): SessionNub { return this._sessionNub; } @@ -242,7 +229,7 @@ export class FieldSet extends FormulaireElement implements Observer { // fin MAJ selects - this.applyDependencies(this.parentForm); + this.applyDependencies(); } public parseConfig(json: {}, data?: {}) { @@ -250,12 +237,13 @@ export class FieldSet extends FormulaireElement implements Observer { this._confId = json["id"]; + const parentForm = this.parentForm as FormulaireDefinition; const ct: string = json["calcType"]; - const calc_type: CalculatorType = ct == undefined ? this.parentForm.calculatorType : CalculatorType[ct]; + const calc_type: CalculatorType = ct == undefined ? parentForm.calculatorType : CalculatorType[ct]; this.setPropValue("calcType", calc_type); const dnt: string = json["defaultNodeType"]; - const node_type: ComputeNodeType = dnt == undefined ? this.parentForm.nodeType : ComputeNodeType[dnt]; + const node_type: ComputeNodeType = dnt == undefined ? parentForm.nodeType : ComputeNodeType[dnt]; this.setPropValue("nodeType", node_type); const st: string = json["defaultStructType"]; diff --git a/src/app/formulaire/formulaire-element.ts b/src/app/formulaire/formulaire-element.ts index 94311583903421552d7d5ae7bc7e46ede318aff6..5fe3851bdcbccf643c69c5f1e3c6b3de7399c824 100644 --- a/src/app/formulaire/formulaire-element.ts +++ b/src/app/formulaire/formulaire-element.ts @@ -2,10 +2,8 @@ import { FormulaireNode } from "./formulaire-node" import { StringMap } from "../stringmap"; import { Dependency } from "./dependency/dependency"; import { DependencyCondition, DependencyConditionType } from "./dependency/dependency-condition"; -import { ValueDependency } from "./dependency/value-dependency"; import { ValueDependencyCondition } from "./dependency/value-dependency-condition"; import { ExistenceDependency } from "./dependency/existence-dependency"; -import { FormulaireDefinition } from "./definition/form-definition"; import { DeepFormulaireElementIterator } from "./form-iterator/deep-element-iterator"; /** @@ -59,6 +57,17 @@ export abstract class FormulaireElement extends FormulaireNode { return super.kids as FormulaireElement[]; } + /** + * formulaire parent + */ + public get parentForm(): FormulaireNode { + let res = this.parent; + //while (!(res instanceof FormulaireDefinition)) + while (!("calculatorName" in res)) // pour éviter de faire référence au type FormulaireDefinition, supprimer l'import correspondant et casser les dépendances circulaires d'import + res = res.parent; + return res; + } + /** * analyse les dépendances d'existence * @param json configuration de la dépendance @@ -127,7 +136,7 @@ export abstract class FormulaireElement extends FormulaireNode { } } - public applyDependencies(parentForm: FormulaireDefinition) { + public applyDependencies() { this.prepareExistenceDependencies(); for (let d of this._dependencies) { @@ -135,7 +144,7 @@ export abstract class FormulaireElement extends FormulaireNode { } for (const k of this.getKids()) - k.applyDependencies(parentForm); + k.applyDependencies(); } public printDependencies() { diff --git a/src/app/formulaire/input-field.ts b/src/app/formulaire/input-field.ts index 3aa574a33ebe77ae308d1000a94521e29b3f1563..933e2c626a48567c335c6807cb7abb916af457a8 100644 --- a/src/app/formulaire/input-field.ts +++ b/src/app/formulaire/input-field.ts @@ -1,6 +1,4 @@ import { Field } from "./field" -import { FormulaireDefinition } from "./definition/form-definition"; - export abstract class InputField extends Field { private _value: any; diff --git a/src/app/formulaire/ngparam.ts b/src/app/formulaire/ngparam.ts index 552594bc42c3db2db734a7d87c08b1c3fa49f523..71b4e6b68e6e83f159c6f1d533759eba5062309b 100644 --- a/src/app/formulaire/ngparam.ts +++ b/src/app/formulaire/ngparam.ts @@ -1,10 +1,9 @@ -import { ParamDefinition, Pair, ParamDomain, ParamValues, ParamValueMode, ParamValueIterator } from "jalhyd"; +import { ParamDefinition, Pair, ParamDomain, ParamValueMode, NumberIterator, Nub, Observer, asObservable } from "jalhyd"; import { InputField } from "./input-field"; import { Dependency } from "./dependency/dependency"; import { DependencyConditionType } from "./dependency/dependency-condition"; import { ValueDependencyCondition } from "./dependency/value-dependency-condition"; -import { FormulaireDefinition } from "./definition/form-definition"; import { ServiceFactory } from "../services/service-factory"; import { ApplicationSetupService } from "../services/app-setup/app-setup.service"; import { StringMap } from "../stringmap"; @@ -24,13 +23,18 @@ export enum ParamRadioConfig { /** * boutons radio "paramètre fixé", "paramètre à varier" et "paramètre à calculer" */ - CAL + CAL, + + /** + * boutons radio "paramètre fixé", "paramètre à varier" et "paramètre à calculer", "paramètre lié" + */ + LINK }; /** * classe englobante de ParamDefinition (champs supplémentaires pour l'affichage, radio boutons, ...) */ -export class NgParameter extends InputField { +export class NgParameter extends InputField implements Observer { public unit: string; public radioConfig: ParamRadioConfig; @@ -70,7 +74,7 @@ export class NgParameter extends InputField { } public get radioState() { - switch (this._paramDef.paramValues.valueMode) { + switch (this._paramDef.valueMode) { case ParamValueMode.SINGLE: return ParamRadioConfig.FIX; @@ -80,6 +84,9 @@ export class NgParameter extends InputField { case ParamValueMode.CALCUL: return ParamRadioConfig.CAL; + + case ParamValueMode.LINK: + return ParamRadioConfig.LINK; } } @@ -100,14 +107,50 @@ export class NgParameter extends InputField { * fixe la valeur du paramètre. * une notification préalable est envoyée pour laisser l'occasion aux objets liés de préciser le contexte * dans lequel cette valeur existe - * @param sender - * @param val + * @param sender + * @param val */ public setValue(sender: any, val: number) { - this._paramDef.v = val; + this._paramDef.setValue(val, sender); this.notifyValueModified(sender); } + /** + * supprime un lien avec un paramètre + */ + private unlinkParameter() { + let o = asObservable(this._paramDef.referencedObject); + if (this.valueMode === ParamValueMode.LINK) { + this._paramDef.undefineReference(); + if (o !== undefined) + o.removeObserver(this); + } + } + + /** + * crée le lien avec un paramètre + */ + public linkToParameter(n: Nub, ref: string) { + const changed: boolean = this._paramDef.valueMode !== ParamValueMode.LINK || this._paramDef.referencedNub !== n || this._paramDef.referenceDefinition !== ref; + if (changed) { + let o = asObservable(this._paramDef.referencedObject); + if (o !== undefined) + o.removeObserver(this); + + this.valueMode = ParamValueMode.LINK; + this._paramDef.defineReference(n, ref); + + o = asObservable(this._paramDef.referencedObject); + if (o !== undefined) + o.addObserver(this); // pour être prévenu des changements de valeur de l'object référencé + + this.notifyObservers({ + "action": "valueLinkChange", + "value": this.getValue() + }); + } + } + get isDefined(): boolean { return this._paramDef.isDefined; } @@ -128,42 +171,26 @@ export class NgParameter extends InputField { public set valueMode(m: ParamValueMode) { // undefined si on clique en dehors du select après l'avoir ouvert (cad sans avoir fait de sélection) // et au même niveau, cad à côté du bouton et non à côté du menu déroulant - if (m != undefined) - this._paramValues.valueMode = m; - } - - /** - * vérifie si un min/max est valide par rapport au domaine de définition - */ - private isMinMaxDomainValid(v: number): boolean { - if (v == undefined) - return false; - - if (this._paramValues.valueMode == ParamValueMode.MINMAX) - try { - this.checkValue(v); - } - catch (e) { - return false; - } - - return true; - } - - private checkMinMax(min: number, max: number): boolean { - return this.isMinMaxDomainValid(min) && this.isMinMaxDomainValid(max) && (min < max); + if (m !== undefined && this._paramDef.valueMode !== m) { + this.unlinkParameter(); + this._paramDef.valueMode = m; + this.notifyObservers({ + "action": "valueModeChange", + "value": this._paramDef.getValue() + }); + } } public checkMin(min: number): boolean { - return this.isMinMaxDomainValid(min) && (min < this._paramValues.max); + return this._paramDef.checkMin(min); } public checkMax(max: number): boolean { - return this.isMinMaxDomainValid(max) && (this._paramValues.min < max); + return this._paramDef.checkMax(max); } public get isMinMaxValid(): boolean { - return this.checkMinMax(this._paramValues.min, this._paramValues.max); + return this._paramDef.isMinMaxValid; } public get minValue() { @@ -183,7 +210,7 @@ export class NgParameter extends InputField { } public checkStep(step: number): boolean { - return this.isMinMaxValid && this._paramValues.stepRefValue.intervalHasValue(step); + return this._paramDef.checkStep(step); } public get stepRefValue(): Pair { @@ -206,59 +233,11 @@ export class NgParameter extends InputField { this._paramValues.valueList = l; } - private get isListValid(): boolean { - if (this._paramValues.valueList == undefined) - return false; - - for (let v of this._paramValues.valueList) - try { - this.checkValue(v); - } - catch (e) { - return false; - } - return true; - } - - private get isRangeValid(): boolean { - switch (this._paramValues.valueMode) { - case ParamValueMode.LISTE: - return this.isListValid; - - case ParamValueMode.MINMAX: - return this.checkStep(this._paramValues.step); - } - - throw new Error(`"NgParameter.isRangeValid() : valeur ${ParamValueMode[this._paramValues.valueMode]} de ParamValueMode non prise en compte`); - } - - private get isValueValid(): boolean { - try { - const v = this._paramDef.getValue(); - this._paramDef.checkValue(v); - return true; - } - catch (e) { - return false; - } - } - public get isValid() { - switch (this.radioState) { - case ParamRadioConfig.FIX: - return this.isValueValid; - - case ParamRadioConfig.VAR: - return this.isRangeValid; - - case ParamRadioConfig.CAL: - return true; - - case undefined: - return false; - } + if (this.radioState === undefined) + return false; - throw new Error(`"NgParameter.isValid() : valeur de ParamRadioConfig '${this.radioState}' (radioState) non prise en compte`); + return this._paramDef.isValid; } private static getRadioConfig(s: string) { @@ -309,16 +288,8 @@ export class NgParameter extends InputField { } } - public get valuesIterator(): ParamValueIterator { - return this._paramValues.getValuesIterator(); - } - - public updateLocalisation(loc: StringMap) { - super.updateLocalisation(loc); - if (this.label == undefined) { - const key: string = `INFO_GRANDEUR_${this.symbol.toUpperCase()}`; - super.updateLocalisation(loc, key); - } + public get valuesIterator(): NumberIterator { + return this._paramDef.valuesIterator; } private paramValuesJSON(): any { @@ -394,4 +365,14 @@ export class NgParameter extends InputField { } } } + + // interface Observer + + public update(sender: any, data: any) { + switch (data["action"]) { + case "baseparamAfterValue": // changement de valeur envoyé par l'objet référencé + this.notifyValueModified(sender); + break; + } + } } diff --git a/src/app/results/remous-results.ts b/src/app/results/remous-results.ts index 99cbddeb6fb468cab402617cd2bf0ad979b2bfa8..ec7d5ef9c09c35f803dc8e60f04bf48f4c992187 100644 --- a/src/app/results/remous-results.ts +++ b/src/app/results/remous-results.ts @@ -57,7 +57,7 @@ export class RemousResults extends CalculatorResults { /** * titre de la colonne du paramètre supplémentaire */ - private _extraParamLabel: string; + private _extraParamSymbol: string; /** * journal de calcul @@ -76,7 +76,7 @@ export class RemousResults extends CalculatorResults { this._penteFond = undefined; this._hautNormale = undefined; this._hautCritique = undefined; - this._extraParamLabel = undefined; + this._extraParamSymbol = undefined; this._hasFlu = false; this._hasTor = false; this._hasExtra = false; @@ -127,7 +127,7 @@ export class RemousResults extends CalculatorResults { this._hasFlu = true; if (!this._hasTor && re.getExtraResult("tor")) this._hasTor = true; - if (!this._hasExtra && re.getExtraResult("tRes")) + if (!this._hasExtra && re.getExtraResult(this.extraParamSymbol)) this._hasExtra = true; } @@ -143,13 +143,17 @@ export class RemousResults extends CalculatorResults { if (this._hasTor) keys.push("tor"); if (this._hasExtra) - keys.push("tRes"); + keys.push(this.extraParamSymbol); this._varResults.extraResultKeys = keys; this._varResults.update(true); } - public set extraParamLabel(l: string) { - this._extraParamLabel = l; + public get extraParamSymbol(): string { + return this._extraParamSymbol; + } + + public set extraParamSymbol(l: string) { + this._extraParamSymbol = l; } public get hautBerge() { diff --git a/src/app/results/var-results.ts b/src/app/results/var-results.ts index 72cec056145ed3fd1bb79984b56419704c422dfd..4a39c1c9a7f8812d3f70408d155963d64bd6fe08 100644 --- a/src/app/results/var-results.ts +++ b/src/app/results/var-results.ts @@ -136,6 +136,6 @@ export class VarResults extends CalculatedParamResults { const intlService = ServiceFactory.instance.internationalisationService; for (const k of this._extraResultKeys) - this._extraResultHeaders.push(intlService.translateLabel(k)); + this._extraResultHeaders.push(intlService.getExtraResLabel(k)); } } diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index c51afc628ef2d2cffca040d64eca6d3e7ef6db65..c8bb1e5d2d016cb8956139710763697896b289fc 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -5,7 +5,7 @@ import "rxjs/add/operator/toPromise"; import { decode } from "he"; import { saveAs } from "file-saver"; -import { CalculatorType, EnumEx, Observable } from "jalhyd"; +import { CalculatorType, EnumEx, Observable, ParamDefinition, ParamValueMode } from "jalhyd"; import { ServiceFactory } from "../service-factory"; import { HttpService } from "../../services/http/http.service"; @@ -25,6 +25,7 @@ import { FormulairePasseBassinDimensions } from "../../formulaire/definition/con 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"; +import { NgParameter } from "../../formulaire/ngparam"; @Injectable() export class FormulaireService extends Observable { @@ -248,6 +249,15 @@ export class FormulaireService extends Observable { return undefined; } + 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 { if (ct == undefined) throw "FormulaireService.getConfigPathPrefix() : invalid undefined CalculatorType" @@ -452,4 +462,70 @@ export class FormulaireService extends Observable { throw new Error(`session file : invalid key '${ks}' in session object`); } } + + /** + * @returns liste des valeurs liables à un paramètre sous la forme d'un tableau d'objets + * {"param":<paramètre lié>, "nub":<Nub d'origine du paramètre lié>, "formTitle":<nom de la calculette liée au nub>} + * @param p paramètre qui sert de clé de recherche des paramètres liables + */ + public getLinkableValues(p: NgParameter): any[] { + let res: any[] = []; + + if (p !== undefined) + for (const f of this._formulaires) { + // nub associé au formulaire + const sn = f.currentSessionNub; + + try { + // on vérifie que le paramètre en entrée appartient au nub + const np = sn.nub.getParameter(p.symbol); + + // 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); + } + } + catch (e) { + // p.symbol n'existe pas dans le nub testé + } + } + + return res; + } + + /** + * 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; + } } diff --git a/src/app/services/internationalisation/internationalisation.service.ts b/src/app/services/internationalisation/internationalisation.service.ts index 00397c93119559fa0db87f5cb47b6c6a52cf117c..95b6dcbad37360c531d705f00eacdecfd213cc12 100644 --- a/src/app/services/internationalisation/internationalisation.service.ts +++ b/src/app/services/internationalisation/internationalisation.service.ts @@ -163,10 +163,10 @@ export class InternationalisationService extends Observable { */ public localizeText(code: string) { if (this._Messages === undefined) { - return "<messages not loaded>"; + return "*** messages not loaded: ${code} ***"; } if (this._Messages[code] === undefined) { - return `<message not exists: ${code}>`; + return `*** message not exists: ${code} ***`; } return this._Messages[code]; } @@ -182,7 +182,7 @@ export class InternationalisationService extends Observable { /** * Traduit un libellé qui peut être un code */ - public translateLabel(s: string) { + public getExtraResLabel(s: string) { const key = "INFO_EXTRARES_LIB_"; const match = this.parseLabel(s); if (match) { diff --git a/src/app/services/param/param.service.ts b/src/app/services/param/param.service.ts index 0b5dea30679d99ce1f1f9732326d8f9885426e36..bdf292efe32cbcac376bc1be16fc9dc2e644a8c4 100644 --- a/src/app/services/param/param.service.ts +++ b/src/app/services/param/param.service.ts @@ -84,7 +84,7 @@ export class ParamService { break; default: - throw new Error(`ComputeNodeParameters.getParameter() : symbole ${symbol} non pris en charge`); + throw new Error(`ParamService.createParameter() : symbole ${symbol} non pris en charge`); } } diff --git a/src/locale/error_messages.en.json b/src/locale/error_messages.en.json index f010427d9b99184f4cb50a6616c3fb84cfa07578..985191346b4255111ce457b26b637751507cef37 100644 --- a/src/locale/error_messages.en.json +++ b/src/locale/error_messages.en.json @@ -33,6 +33,7 @@ "INFO_PARAMFIELD_PARAMFIXE": "Fixed", "INFO_PARAMFIELD_PARAMVARIER": "Vary", "INFO_PARAMFIELD_PARAMCALCULER": "Calculate", + "INFO_PARAMFIELD_PARAMLIE": "Link", "INFO_PARAMFIELD_VALEURMINI": "From minimum value", "INFO_PARAMFIELD_VALEURMAXI": "to maximum value", "INFO_PARAMFIELD_PASVARIATION": "with a variation step of:", diff --git a/src/locale/error_messages.fr.json b/src/locale/error_messages.fr.json index 270d66e42b75aa88a66a5195b4ee6f6c357b490f..e0e56d74ca3f00cc48186a806455143a8990714a 100644 --- a/src/locale/error_messages.fr.json +++ b/src/locale/error_messages.fr.json @@ -39,6 +39,7 @@ "INFO_PARAMFIELD_PARAMFIXE": "fixé", "INFO_PARAMFIELD_PARAMVARIER": "varier", "INFO_PARAMFIELD_PARAMCALCULER": "calculer", + "INFO_PARAMFIELD_PARAMLIE": "lié", "INFO_PARAMFIELD_VALEURMINI": "De la valeur minimum", "INFO_PARAMFIELD_VALEURMAXI": "à la valeur maximum", "INFO_PARAMFIELD_PASVARIATION": "avec un pas de :", @@ -49,24 +50,7 @@ "INFO_LECHAPTCALMON_TITRE": "Lechapt-Calmon", "INFO_REGIMEUNIFORME_TITRE": "Régime uniforme", "INFO_SECTIONPARAMETREE_TITRE": "Section paramétrée", - "INFO_GRANDEUR_Q": "Débit (m³/s)", - "INFO_GRANDEUR_HS": "La charge spécifique (m)", - "INFO_GRANDEUR_HSC": "La charge critique (m)", - "INFO_GRANDEUR_B": "La largeur au miroir (m)", - "INFO_GRANDEUR_P": "Le périmètre mouillé (m)", - "INFO_GRANDEUR_S": "La surface mouillée (m²)", - "INFO_GRANDEUR_R": "Le rayon hydraulique (m)", - "INFO_GRANDEUR_V": "La vitesse moyenne (m/s)", - "INFO_GRANDEUR_FR": "Le Froude", - "INFO_GRANDEUR_YC": "Le tirant d'eau critique (m)", - "INFO_GRANDEUR_YN": "Le tirant d'eau normal (m)", - "INFO_GRANDEUR_YF": "Le tirant d'eau fluvial (m)", - "INFO_GRANDEUR_YT": "Le tirant d'eau torrentiel (m)", - "INFO_GRANDEUR_YCO": "Le tirant d'eau conjugué (m)", - "INFO_GRANDEUR_J": "La perte de charge (m)", - "INFO_GRANDEUR_I-J": "Variation linéaire de l'énergie spécifique (m/m)", - "INFO_GRANDEUR_IMP": "Impulsion (N)", - "INFO_GRANDEUR_TAU0": "La force tractrice (Pa)", + "INFO_COURBEREMOUS_TITRE": "Courbes de remous", "INFO_REMOUSRESULTS_TITREJOURNAL": "Journal de calcul", "INFO_REMOUSRESULTS_ABSCISSE": "Abscisse (m)", @@ -95,10 +79,27 @@ "INFO_EXTRARES_LIB_OUVRAGE_Q": "Débit (m³/s)", "INFO_EXTRARES_LIB_OUVRAGE_Q_MODE": "Type d'écoulement", "INFO_EXTRARES_LIB_OUVRAGE_Q_REGIME": "Régime", - "INFO_EXTRARES_LIB_V": "V: Vitesse (m/s)", "INFO_EXTRARES_LIB_EC": "EC: Énergie cinétique (m)", "INFO_EXTRARES_LIB_CV": "Cv: Coefficient de vitesse d'approche", "INFO_EXTRARES_LIB_CVQT": "CV.QT: Débit corrigé (m³/s)", + "INFO_EXTRARES_LIB_Q": "Débit (m³/s)", + "INFO_EXTRARES_LIB_HS": "Charge spécifique (m)", + "INFO_EXTRARES_LIB_HSC": "Charge critique (m)", + "INFO_EXTRARES_LIB_B": "Largeur au miroir (m)", + "INFO_EXTRARES_LIB_P": "Périmètre mouillé (m)", + "INFO_EXTRARES_LIB_S": "Surface mouillée (m²)", + "INFO_EXTRARES_LIB_R": "Rayon hydraulique (m)", + "INFO_EXTRARES_LIB_V": "Vitesse moyenne (m/s)", + "INFO_EXTRARES_LIB_FR": "Froude", + "INFO_EXTRARES_LIB_YC": "Tirant d'eau critique (m)", + "INFO_EXTRARES_LIB_YN": "Tirant d'eau normal (m)", + "INFO_EXTRARES_LIB_YF": "Tirant d'eau fluvial (m)", + "INFO_EXTRARES_LIB_YT": "Tirant d'eau torrentiel (m)", + "INFO_EXTRARES_LIB_YCO": "Tirant d'eau conjugué (m)", + "INFO_EXTRARES_LIB_J": "Perte de charge (m)", + "INFO_EXTRARES_LIB_I-J": "Variation linéaire de l'énergie spécifique (m/m)", + "INFO_EXTRARES_LIB_IMP": "Impulsion (N)", + "INFO_EXTRARES_LIB_TAU0": "Force tractrice (Pa)", "INFO_EXTRARES_ENUM_OUVRAGE_Q_MODE_0": "Surface libre", "INFO_EXTRARES_ENUM_OUVRAGE_Q_MODE_1": "En charge",