diff --git a/README.md b/README.md index dbf6b670110ea65931e06dfa69fc1e18b2d12279..b990318dfbe4862995b1e5793b9d078457be62d1 100644 --- a/README.md +++ b/README.md @@ -36,3 +36,144 @@ and then : ### To flag suspicious language usage `npm run lint` + + +# Procédure d'ajout d'une calculette # + +##JaLHyd + + +* Créer la classe de paramétrage + + * exemple : + + export class TotoParams extends ParamsEquation { + [key: string]: any; // pour pouvoir faire this['methode](); + + /** Longueur L */ + private _L: ParamDefinition; + + /** Largeur W */ + private _W: ParamDefinition; + + /** Tugudu A */ + private _A: ParamDefinition; + + constructor(rL: number, rW: number, rA:number=undefined) { + super(); + this._L = new ParamDefinition(ComputeNodeType.LechaptCalmon, 'L', ParamDomainValue.POS, rL); + this._W = new ParamDefinition(ComputeNodeType.LechaptCalmon, 'W', ParamDomainValue.POS, rW); + this._A = new ParamDefinition(ComputeNodeType.LechaptCalmon, 'A', ParamDomainValue.POS, rA); + + this.addParamDefinition(this._L); + this.addParamDefinition(this._W); + this.addParamDefinition(this._A); + } + + get L() { + return this._L; + } + + get W() { + return this._W; + } + + get A() { + return this._A; + } + } + + +* Créer la classe de calcul + + * exemple : + + export class Toto extends Nub { + constructor(prms: TotoParams, dbg: boolean = false) { + super(prms, dbg); + } + + /** + * paramètres castés au bon type + */ + get prms(): TotoParams { + return <TotoParams>this._prms; + } + + /** + * paramétrage de la calculabilité des paramètres + */ + protected setParametersCalculability() { + this.prms.L.calculability = ParamCalculability.DICHO; + this.prms.W.calculability = ParamCalculability.DICHO; + this.prms.A.calculability = ParamCalculability.EQUATION; + } + + Equation(sVarCalc: string): Result { + let v: number; + + switch (sVarCalc) { + case "A": + v = this.prms.L.v / this.prms.W.v; + break; + + default: + throw "Toto.Equation() : invalid variable name " + sVarCalc; + } + + return new Result(v); + } + } + + +* Créer les tests unitaires correspondants + + +* Ajouter une valeur à l'enum _ComputeNodeType_ pour identifier le type de noeud de calcul (par ex _MaCalculette_). + + +* Compléter la méthode _ComputeNodeParameters.getComputeNodeParameters()_. + + Si plusieurs valeurs de _ComputeNodeType_ font référence à la même calculette, n'ajouter les _case_ que pour les valeurs "concrètes". Par exemple, pour les sections paramétrées, il n'y a pas de _case_ pour la valeur _SectionParametree_ qui est générique. + + +##ngHyd + + +* Créer les fichier de configuration de la calculette + - dans _src/app/calculators_ : créer un répertoire (par ex _ma-calculette_) + + - dans _src/app/calculators/ma-calculette_ : + + Créer _ma-calculette.config.json_ sur le modèle des autres. + Les ids utilisés doivent correspondre au symbole fourni à classe _ParamDefinition_ (2ème paramètre du constructeur) + + Ne pas oublier de spécifier : + - le type de noeud de la calculette (dans l'objet comportant _"id":"options"_) avec le champ _"nodeType": "MaCalculette"_ + - éventuellement le type de noeud de fieldset particuliers (objets comportant _"id":"fs_XXX"_) avec le champ _"nodeType": "MaCalculetteBleue"_ + + - dans _src/app/calculators/ma-calculette_ : + + Créer les fichiers d'internationalisation (_ma-calculette.<langue>.json_). Il doivent reprendre tous les ids utilisés dans le fichier de configuration et fournir leur traduction. + +* Ajouter une valeur à l'enum _CalculatorType_ pour identifier la calculette. + + On ne reprend pas directement l'enum _ComputeNodeType_ car celui ci sert à distinguer les variantes au sein d'une même calculette (par exemple les différentes sections paramétrées). + +* Composant CalculatorListComponent : ajouter une ligne au constructeur pour créer une nouvelle entrée dans la liste des calculettes disponibles. + +* Classe _FormulaireService_, méthode _getConfigPathPrefix()_ : compléter le _switch_ pour fournir le préfixe des fichiers de configuration/internationalisation. + +* Classe ParamService : compléter le constructeur. + +* S'il existe plusieurs valeurs de _ComputeNodeType_ pour la même calculette, compléter les méthodes + - _FormulaireDefinition.getComputeNodeTypeFromSection()_. + - _ParamService.hasParameter()_ + +* _src/locale/error_messages.<langue>.json_ : + Ajouter un champ pour le titre de la calculette. Par exemple : + _"INFO_MACALC_TITRE": "Ma calculette"_ + Compléter la méthode _GenericCalculatorComponent .uitextTitre()_ avec cette valeur et la valeur de l'enum _CalculatorType_ correspondante. + +* Classe FormulaireDefinition : compléter la méthode _doCompute()_. + En particulier, adapter les méthodes _getNubAndParameters()_ ou _getSectionNubAndParameters()_ (récupération des valeurs saisies dans l'interface). \ No newline at end of file diff --git a/src/app/calculators/generic/calculator.component.ts b/src/app/calculators/generic/calculator.component.ts index c308fc8e1ee21451e565cc2b82c335a256ca13a1..bf01f8b7ea4fcc6305f5132b28c05333dfb3dd75 100644 --- a/src/app/calculators/generic/calculator.component.ts +++ b/src/app/calculators/generic/calculator.component.ts @@ -68,6 +68,9 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, OnDestroy, O case CalculatorType.CourbeRemous: return this.intlService.localizeText("INFO_REMOUS_TITRE") + case CalculatorType.PabDimensions: + return this.intlService.localizeText("INFO_PABDIM_TITRE") + default: return "Invalid calculator type " + this._formulaire.calculatorType; } diff --git a/src/app/calculators/pab-dimensions/pab-dimensions.config.json b/src/app/calculators/pab-dimensions/pab-dimensions.config.json new file mode 100644 index 0000000000000000000000000000000000000000..6449d508f61fb6db66599db2f791300f75af13ce --- /dev/null +++ b/src/app/calculators/pab-dimensions/pab-dimensions.config.json @@ -0,0 +1,37 @@ +[ + { + "id": "fs_dimensions", + "option": "cal", + "fields": [ + { + "type": "input", + "id": "L", + "unit": "m", + "value": 2 + }, + { + "type": "input", + "id": "W", + "unit": "m", + "value": 1 + }, + { + "type": "input", + "id": "Y", + "unit": "m", + "value": 0.5 + }, + { + "type": "input", + "id": "V", + "unit": "m³", + "value": 1 + } + ] + }, + { + "id": "options", + "idCal": "V", + "nodeType": "PabDimensions" + } +] \ No newline at end of file diff --git a/src/app/calculators/pab-dimensions/pab-dimensions.en.json b/src/app/calculators/pab-dimensions/pab-dimensions.en.json new file mode 100644 index 0000000000000000000000000000000000000000..df5b11b452d5814c96e3d5dcfd82bb520ec62e39 --- /dev/null +++ b/src/app/calculators/pab-dimensions/pab-dimensions.en.json @@ -0,0 +1,7 @@ +{ + "fs_dimensions": "Basin dimensions", + "L": "Length", + "W": "Width", + "Y": "Draft", + "V": "Volume" +} \ No newline at end of file diff --git a/src/app/calculators/pab-dimensions/pab-dimensions.fr.json b/src/app/calculators/pab-dimensions/pab-dimensions.fr.json new file mode 100644 index 0000000000000000000000000000000000000000..3fea96a6aae55f0e9de06b9a7cbc00f92cfdb6e2 --- /dev/null +++ b/src/app/calculators/pab-dimensions/pab-dimensions.fr.json @@ -0,0 +1,7 @@ +{ + "fs_dimensions": "Dimensions du bassin", + "L": "Longueur", + "W": "Largeur", + "Y": "Tirant d'eau", + "V": "Volume" +} \ No newline at end of file diff --git a/src/app/components/calculator-list/calculator-list.component.ts b/src/app/components/calculator-list/calculator-list.component.ts index e7b41b35f243ab373e3418482051d5c46cf70d7e..a0042bcb7f4baea83638bbbbbb58ea85032042ef 100644 --- a/src/app/components/calculator-list/calculator-list.component.ts +++ b/src/app/components/calculator-list/calculator-list.component.ts @@ -25,6 +25,7 @@ export class CalculatorListComponent { this._items.push(new ListElement("Regime uniforme", CalculatorType.RegimeUniforme)); this._items.push(new ListElement("Sections paramétrées", CalculatorType.SectionParametree)); this._items.push(new ListElement("Courbes remous", CalculatorType.CourbeRemous)); + this._items.push(new ListElement("Dimensions d'une passe à bassin", CalculatorType.PabDimensions)); } private create(t: CalculatorType) { 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 ba9d29ccaff164390da9bbdacd763dc4be5c97f5..3af87680608be80edc4c47a22afbf7d3dc590cea 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 @@ -6,19 +6,23 @@ <div class="btn-group" role="group"> <!-- radio "fixé" --> - <label class="{{radioFixClass}} h-50 px-3 py-2" [(ngModel)]="radioModel" mdbRadio="Left" name="radio_param_{{symbol}}" value="fix" + <!-- px-3 : padding left/right 3 --> + <!-- py-3 : padding top/bottom 3 --> + <!-- h-50 : hauteur relative de l'élément par rapport au parent à 50%--> + <!-- cf. https://getbootstrap.com/docs/4.0/utilities/spacing --> + <label class="{{radioFixClass}} h-75 px-3 py-3" [(ngModel)]="radioModel" mdbRadio="Left" name="radio_param_{{symbol}}" value="fix" (click)="onRadioClick(symbol, 'fix')" [checked]=radioFixCheck [disabled]=isDisabled id="radio_fix"> {{uitextParamFixe}} </label> <!-- radio "varier" --> - <label class="{{radioVarClass}} h-50 px-3 py-2" [(ngModel)]="radioModel" mdbRadio="Middle" name="radio_param_{{symbol}}" + <label class="{{radioVarClass}} h-75 px-3 py-3" [(ngModel)]="radioModel" mdbRadio="Middle" name="radio_param_{{symbol}}" value="var" (click)="onRadioClick(symbol, 'var')" [checked]=radioVarCheck [disabled]=isDisabled id="radio_var"> {{uitextParamVarier}} </label> <!-- radio "calculer" --> - <label class="{{radioCalClass}} h-50 px-3 py-2" [(ngModel)]="radioModel" mdbRadio="Right" name="radio_param_{{symbol}}" value="cal" + <label class="{{radioCalClass}} h-75 px-3 py-3" [(ngModel)]="radioModel" mdbRadio="Right" name="radio_param_{{symbol}}" value="cal" (click)="onRadioClick(symbol, 'cal')" [checked]=radioCalCheck [disabled]=isDisabled id="radio_cal"> {{uitextParamCalculer}} </label> @@ -26,28 +30,28 @@ </div> <div *ngIf="isRadioVarChecked" class="row"> - <div class="col-6 col-sm-8 text-xs-left text-sm-right"> + <div class="col-12 col-sm-4 col-md-3"> {{uitextValeurMini}} </div> - <div class="col-6 col-sm-4 pr-5"> + <div class="col-12 col-sm-4 col-md-3 pr-5"> <input type="text" class="input-alternate" name="inputmin" placeholder="min" [(ngModel)]="_param.minValue" /> </div> </div> <div *ngIf="isRadioVarChecked" class="row"> - <div class="col-6 col-sm-8 text-xs-left text-sm-right"> + <div class="col-12 col-sm-4 col-md-3"> {{uitextValeurMaxi}} </div> - <div class="col-6 col-sm-4 pr-5"> + <div class="col-12 col-sm-4 col-md-3 pr-5"> <input type="text" class="input-alternate" name="inputmax" placeholder="max" [(ngModel)]="_param.maxValue" /> </div> </div> <div *ngIf="isRadioVarChecked" class="row"> - <div class="col-6 col-sm-8 text-xs-left text-sm-right"> + <div class="col-12 col-sm-4 col-md-3"> {{uitextPasVariation}} </div> - <div class="col-6 col-sm-4 pr-5"> + <div class="col-12 col-sm-4 col-md-3 pr-5"> <input type="text" class="input-alternate" name="inputstep" placeholder="step" [(ngModel)]="_param.stepValue" /> </div> </div> \ No newline at end of file diff --git a/src/app/components/param-input/param-input.component.html b/src/app/components/param-input/param-input.component.html index 2e1af91be2ee365ae2d2697b4adf14c634696f9a..472ce2a3e32cb47e355c6d1b9b37d7e934b74ed2 100644 --- a/src/app/components/param-input/param-input.component.html +++ b/src/app/components/param-input/param-input.component.html @@ -1,5 +1,6 @@ <div class="md-form form-sm"> - <input mdbActive type="text" id="form1" class="form-control" [ngModel]="_uiValue.uncheckedValueString" (ngModelChange)="setValue($event)"> + <input mdbActive type="text" id="form1" class="form-control" [disabled]="isDisabled" [ngModel]="_uiValue.uncheckedValueString" + (ngModelChange)="setValue($event)"> <label for="form1">{{_title}}</label> <small class="text-danger">{{_message}}</small> </div> \ No newline at end of file diff --git a/src/app/components/param-input/param-input.component.ts b/src/app/components/param-input/param-input.component.ts index a2eeb9810478b13ee5dd309f32ef89824dff8413..1b16d3a64e69f48d0e9d940741c5bfedb46c6fe6 100644 --- a/src/app/components/param-input/param-input.component.ts +++ b/src/app/components/param-input/param-input.component.ts @@ -81,6 +81,10 @@ export class ParamInputComponent implements ControlValueAccessor, DoCheck { return this.intlService.localizeText("INFO_SAISIEPARAM_TITRE"); } + private get isDisabled(): boolean { + return this._inputDisabled; + } + /** * fonction appelée lorsque l'utilisateur fait une saisie * @param event valeur du contrôle diff --git a/src/app/formulaire/formulaire-definition.ts b/src/app/formulaire/formulaire-definition.ts index 82771cde8dd5a788e7a4823fd796cc74587af03e..862ce7d7fbbe0f8e41f1213b1849076cfbede3ae 100644 --- a/src/app/formulaire/formulaire-definition.ts +++ b/src/app/formulaire/formulaire-definition.ts @@ -1,7 +1,7 @@ import { ComputeNodeType, ParamsEquation, Nub, acSection, RegimeUniforme, MethodeResolution, CourbeRemousParams, CourbeRemous } from "jalhyd"; import { ParamsSectionRectang, cSnRectang, ParamsSectionCirc, cSnCirc, ParamsSectionPuiss, cSnPuiss, Result } from "jalhyd"; import { ConduiteDistrib, ConduiteDistribParams, LechaptCalmon, LechaptCalmonParams, ParamsSectionTrapez, cSnTrapez } from "jalhyd"; - +import { PabDimension, PabDimensionParams } from "jalhyd"; import { ParamService } from "../services/param/param.service"; import { InternationalisationService } from "../services/internationalisation/internationalisation.service"; @@ -21,10 +21,12 @@ import { ExistenceDependency } from "./existence-dependency"; import { FixedVarResults } from "../results/fixed-var-results"; import { SectionResults } from "../results/section-results"; import { RemousResults } from "../results/remous-results"; +import { StringMap } from "../stringmap"; export enum CalculatorType { - ConduiteDistributrice, LechaptCalmon, SectionParametree, RegimeUniforme, CourbeRemous + ConduiteDistributrice, LechaptCalmon, SectionParametree, RegimeUniforme, CourbeRemous, + PabDimensions, // passe à bassin rectangulaire } @@ -143,6 +145,17 @@ export class FormulaireDefinition { return undefined; } + private hasParameter(symbol: string): boolean { + for (let fs of this._fieldSets) { + for (let p of fs.fields) { + if (p instanceof NgParameter) + if (p.symbol === symbol) + return true; + } + } + return false; + } + public getParamFromSymbol(symbol: string): NgParameter { for (let fs of this._fieldSets) { for (let p of fs.fields) { @@ -310,6 +323,23 @@ export class FormulaireDefinition { sourceParam.radioState = newState; + // on vérifie qu'il y a au moins un paramètre "à calculer" et sinon, on prend le 1er qui est à "fixé" + if (this.getParamFromState(ParamRadioConfig.CAL) == undefined) { + let newCal: NgParameter = undefined; + + for (let fs of this._fieldSets) { + for (let p of fs.fields) { + if (p instanceof NgParameter) + if (p.radioState == ParamRadioConfig.FIX && p != sourceParam) { + newCal = p; + break; + } + } + } + + newCal.radioState = ParamRadioConfig.CAL; + } + this.resetResults(); this.applyDependencies(); } @@ -917,6 +947,17 @@ export class FormulaireDefinition { return [nub, prms]; } + case CalculatorType.PabDimensions: + { + let L: number = this.getParameterValue("L"); // longueur L + let W: number = this.getParameterValue("W"); // largeur W + let Y: number = this.getParameterValue("Y"); // tirant d'eau Y + let V: number = this.getParameterValue("V"); // volume V + let prms = new PabDimensionParams(L, W, Y, V); + let nub = new PabDimension(prms); // pour initialiser la calculabilité des paramètres + return [nub, prms]; + } + default: throw "FormulaireService.getNubAndParameters() : valeur de CalculatorType " + this.calculatorType + " non implémentée" } @@ -1006,8 +1047,8 @@ export class FormulaireDefinition { prms = np[1]; } - let computePrec: number = this.getParameterValue("Pr"); // précision de calcul - let nDigits: number = -Math.log10(computePrec); + if (this.hasParameter("Pr")) + var computePrec: number = this.getParameterValue("Pr"); // précision de calcul let computedParam: NgParameter = this.getComputedParameter(); @@ -1015,7 +1056,10 @@ export class FormulaireDefinition { if (varParam == undefined) { // pas de paramètre à varier - let res: Result = nub.Calc(computedParam.symbol, 0, computePrec); + if (computePrec == undefined) + var res: Result = nub.Calc(computedParam.symbol, 0); + else + res = nub.Calc(computedParam.symbol, 0, computePrec); if (res.ok) { this.addFixedResults(!rg); this._fixVarResults.addFixedResult(computedParam, res.vCalc, !rg); @@ -1089,4 +1133,17 @@ export class FormulaireDefinition { public hasRemousResults(): boolean { return this._remousResults.hasResults(); } + + public updateLocalisation(localisation: StringMap) { + for (let loc_id in localisation) { + for (let fs of this._fieldSets) { + if (fs.id == loc_id) + fs.updateLocalisation(localisation); + + for (let p of fs.fields) + if (p.id === loc_id) + p.updateLocalisation(localisation); + } + } + } } diff --git a/src/app/formulaire/formulaire-element.ts b/src/app/formulaire/formulaire-element.ts index 69df8ebbb221b0f8c80367ffd2295111348a0fd0..bc1ee5f95a0723463cc520f1a60b6a1c47c30c44 100644 --- a/src/app/formulaire/formulaire-element.ts +++ b/src/app/formulaire/formulaire-element.ts @@ -10,7 +10,7 @@ export abstract class FormulaireElement { private _id: string; private _formId: number; public isDisplayed: boolean; - public label: string; + private _label: string; constructor(nodeType: ComputeNodeType, id: string, formId: number) { this._nodeType = nodeType; @@ -31,6 +31,10 @@ export abstract class FormulaireElement { return this._formId; } + get label(): string { + return this._label; + } + protected abstract verifyDependency(d: Dependency): boolean; public verifiesDependency(d: Dependency): boolean { @@ -41,7 +45,7 @@ export abstract class FormulaireElement { } public updateLocalisation(loc: StringMap) { - this.label = loc[this.id]; + this._label = loc[this.id]; } public toString() { diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index 1b833bc14e79d4960f03fa567103a79d792b4e15..59b3183e0e46b592b170b8b281d912209697a524 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -50,11 +50,11 @@ export class FormulaireService extends Observable { * @param localisation ensemble id-message traduit */ private updateFormulaireLocalisation(formId: number, localisation: StringMap) { - for (let loc_id in localisation) { - let fe = this.getFormulaireElementById(formId, loc_id); - if (fe != undefined) - fe.updateLocalisation(localisation); - } + for (let f of this._formulaires) + if (f.uid == formId) { + f.updateLocalisation(localisation); + break; + } } /** @@ -172,6 +172,9 @@ export class FormulaireService extends Observable { case CalculatorType.CourbeRemous: return "app/calculators/remous/remous."; + case CalculatorType.PabDimensions: + return "app/calculators/pab-dimensions/pab-dimensions."; + default: throw "FormulaireService.getConfigPathPrefix() : valeur de CalculatorType " + ct + " non implémentée" } diff --git a/src/app/services/param/param.service.ts b/src/app/services/param/param.service.ts index 2eeac9c2975909eb5abc5f5fb48c8513ddc03063..a2e3aa375b0bb38babf97137a3870d157e7dbd68 100644 --- a/src/app/services/param/param.service.ts +++ b/src/app/services/param/param.service.ts @@ -23,6 +23,7 @@ export class ParamService { this.addParameters(ComputeNodeType.CourbeRemousPuissance); this.addParameters(ComputeNodeType.CourbeRemousRectangle); this.addParameters(ComputeNodeType.CourbeRemousTrapeze); + this.addParameters(ComputeNodeType.PabDimensions); // précision de calcul diff --git a/src/locale/error_messages.en.json b/src/locale/error_messages.en.json index 0db0563450bd6592c69bfb05c88e083ad69d402c..e02bec72ccc24ffbcfa1b13f8a32817b3c96154c 100644 --- a/src/locale/error_messages.en.json +++ b/src/locale/error_messages.en.json @@ -68,5 +68,6 @@ "INFO_REMOUSRESULTS_FOND": "Bottom", "INFO_REMOUSRESULTS_BERGE": "Embankment", "INFO_REMOUSRESULTS_TIRANTNORMAL": "Normal water level", - "INFO_REMOUSRESULTS_TIRANTCRITIQUE": "Critical water level" + "INFO_REMOUSRESULTS_TIRANTCRITIQUE": "Critical water level", + "INFO_PABDIM_TITRE": "Passe à bassin : dimensions" } \ No newline at end of file diff --git a/src/locale/error_messages.fr.json b/src/locale/error_messages.fr.json index 8a77498a05c2b24f1f66739b3b1affa406d2520e..309ebcc53adccac93688e65c60f500708eb10908 100644 --- a/src/locale/error_messages.fr.json +++ b/src/locale/error_messages.fr.json @@ -74,5 +74,6 @@ "INFO_REMOUSRESULTS_FOND": "Fond", "INFO_REMOUSRESULTS_BERGE": "Berge", "INFO_REMOUSRESULTS_TIRANTNORMAL": "Tirant d'eau normal", - "INFO_REMOUSRESULTS_TIRANTCRITIQUE": "Tirant d'eau critique" + "INFO_REMOUSRESULTS_TIRANTCRITIQUE": "Tirant d'eau critique", + "INFO_PABDIM_TITRE": "Passe à bassin : dimensions" } \ No newline at end of file