Skip to content
Snippets Groups Projects
Commit 7ad47435 authored by mathias.chouet's avatar mathias.chouet
Browse files

Ajout module Passe à Bassins

Small CSS fix for mat-select label font-size
removed unused code
excluded PabCloisons from modules list
parent 0d0b57bb
No related branches found
No related tags found
1 merge request!45Resolve "Ajout du module de calcul d'une passe à bassins"
Showing
with 467 additions and 76 deletions
[
{
"id": "fs_param_hydro",
"type": "fieldset",
"calcType": "Pab",
"option": "cal",
"fields": [
{
"type": "input",
"id": "Q",
"symbol": "Q",
"unit": "m³/s"
},
{
"type": "input",
"id": "Z1",
"unit": "m"
},
{
"type": "input",
"id": "Z2",
"unit": "m"
}
]
},
{
"id": "fs_bassin",
"type": "fieldset_template",
"calcType": "PabCloisons",
"option": "fix",
"fields": [
{
"id": "select_modele_cloisons",
"type": "select",
"select": []
},
{
"type": "input",
"id": "QA",
"unit": "m³/s"
}
]
},
{
"id": "bassin_container",
"type": "template_container",
"templates": [
"fs_bassin"
]
},
{
"id": "fs_param_calc",
"type": "fieldset",
"calcType": "ParallelStructure",
"option": "fix",
"fields": [
{
"type": "input",
"id": "Pr"
}
]
},
{
"type": "options",
"modeleCloisonsSelectId": "select_modele_cloisons",
"idCal": "Q"
}
]
\ No newline at end of file
{
"fs_param_hydro": "Hydraulic parameters",
"Q": "Flow",
"Z1": "Upstream elevation",
"Z2": "Downstream elevation",
"fs_bassin": "Basin",
"bassin_container": "Basins",
"select_modele_cloisons": "Cross walls model"
}
\ No newline at end of file
{
"fs_param_hydro": "Paramètres hydrauliques",
"Q": "Débit",
"Z1": "Cote amont",
"Z2": "Cote aval",
"fs_bassin": "Bassin",
"bassin_container": "Bassins",
"select_modele_cloisons": "Modèle de cloisons"
}
\ No newline at end of file
......@@ -8,6 +8,7 @@ import { ServiceFactory } from "../../services/service-factory";
import { I18nService } from "../../services/internationalisation/internationalisation.service";
import { FormulaireParallelStructure } from "../../formulaire/definition/concrete/form-parallel-structures";
import { FieldsetContainer } from "../../formulaire/fieldset-container";
import { FormulairePab } from "../../formulaire/definition/concrete/form-pab";
@Component({
......@@ -78,6 +79,7 @@ export class CalculatorListComponent implements OnInit {
if ( // those 2 sub-Nub types cannot be built outside a parent
t !== CalculatorType.Structure
&& t !== CalculatorType.Section
&& t !== CalculatorType.PabCloisons
) {
unusedTheme.calculators.push({
type: t,
......@@ -108,6 +110,15 @@ export class CalculatorListComponent implements OnInit {
}
}
}
// on ajoute un ouvrage après l'ouverture du module de calcul "passe à bassins"
if (f instanceof FormulairePab) {
for (const e of f.allFormElements) {
if (e instanceof FieldsetContainer) {
e.addFromTemplate(0);
break;
}
}
}
});
}
......
......@@ -2,7 +2,7 @@ import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material";
import { Inject, Component } from "@angular/core";
import { I18nService } from "../../services/internationalisation/internationalisation.service";
import { FormGroup, FormBuilder, Validators } from "@angular/forms";
import { FormBuilder } from "@angular/forms";
@Component({
selector: "dialog-generate-pab",
......@@ -11,13 +11,13 @@ import { FormGroup, FormBuilder, Validators } from "@angular/forms";
})
export class DialogGeneratePABComponent {
public debit: number;
public debit = 1.5;
public coteAmont: number;
public coteAmont = 102;
public coteAval: number;
public coteAval = 99;
public nbBassins: number;
public nbBassins = 6;
constructor(
public dialogRef: MatDialogRef<DialogGeneratePABComponent>,
......
......@@ -2,7 +2,7 @@ import { Component, OnInit, DoCheck, OnDestroy, ViewChild, ViewChildren,
QueryList, AfterViewChecked, ElementRef } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router";
import { Observer, Session, ParamValueMode, CalculatorType } from "jalhyd";
import { Observer, Session, Cloisons, Pab, PabCloisons, ParamValueMode, CalculatorType } from "jalhyd";
import { FormulaireService } from "../../services/formulaire/formulaire.service";
import { I18nService } from "../../services/internationalisation/internationalisation.service";
......@@ -432,6 +432,9 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit,
);
}
/**
* Génère une passe à bassins à partir du modèle de cloisons en cours
*/
public generatePAB() {
// création du dialogue de génération d'une passe à bassin
const dialogRef = this.generatePABDialog.open(
......@@ -441,8 +444,26 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit,
dialogRef.afterClosed().subscribe(result => {
if (result) {
if (result.generate) {
console.log("ON GÉNÈRE !!", result);
// this.doEmptySession();
this.formulaireService.createFormulaire(CalculatorType.Pab).then((f: FormulaireDefinition) => {
const pab = (f.currentNub as Pab);
const params = pab.prms;
// paramètres hydrauliques
params.Q.singleValue = result.debit;
params.Z1.singleValue = result.coteAmont;
params.Z2.singleValue = result.coteAval;
// création des bassins
for (let i = 0; i < result.nbBassins; i++) {
const modeleCloisons = new PabCloisons((this._formulaire.currentNub as Cloisons));
pab.addChild(modeleCloisons);
for (const e of f.allFormElements) {
if (e instanceof FieldsetContainer) {
// @TODO how to pass Nub here ? (parameter exists but is never used)
e.addFromTemplate(0, undefined, modeleCloisons);
break;
}
}
}
});
}
}
});
......
......@@ -10,15 +10,15 @@ mat-form-field {
}
}
}
}
::ng-deep .mat-form-field-label {
font-size: 1.1em;
line-height: 1.4em;
margin-top: -2px;
&.mat-form-field-empty {
font-size: 1em;
}
::ng-deep .mat-form-field-label {
font-size: 1.1em;
line-height: 1.4em;
margin-top: -2px;
&.mat-form-field-empty {
font-size: 1em;
}
}
}
......@@ -13,7 +13,7 @@
"title": "Passe à poisson sur le Lez, entre Bollène et Suze",
"credits": "Hervé Capra / Irstea"
},
"calculators": [ 5, 6, 12, 13, 10, 9 ]
"calculators": [ 15, 5, 6, 12, 13, 10, 9 ]
},
{
"name": "PASSE_NATURELLE",
......
import { FormulaireDefinition } from "../form-definition";
import { CalculatorResults } from "../../../results/calculator-results";
import { FormDefParamToCalculate } from "../form-def-paramcalc";
import { FormResult } from "../form-result";
import { FormCompute } from "../form-compute";
import { FormResultFixedVar } from "../form-result-fixedvar";
......@@ -9,23 +8,16 @@ import { ServiceFactory } from "../../../services/service-factory";
export class FormulaireBase extends FormulaireDefinition {
protected _formParamCalc: FormDefParamToCalculate;
protected _formCompute: FormCompute;
protected _formResult: FormResult;
constructor() {
super();
this._formParamCalc = new FormDefParamToCalculate(this);
this._formResult = new FormResultFixedVar(this, false);
this._formCompute = new FormComputeFixedVar(this, (this._formResult as FormResultFixedVar));
}
protected completeParse(json: {}) {
this._formParamCalc.parseOptions(json);
}
/**
* Resets the form results, the results panel on screen, the model
* results, and does the same for all depending modules
......
import { Structure, Nub, ParallelStructure, StructureProperties, Props, Session, PabCloisons, Pab } from "jalhyd";
import { FormComputeParallelStructures } from "../form-compute-parallel-structures";
import { FormResultFixedVar } from "../form-result-fixedvar";
import { FieldsetContainer } from "../../fieldset-container";
import { FieldSet } from "../../fieldset";
import { SelectField } from "../../select-field";
import { NgParameter } from "../../ngparam";
import { FieldsetTemplate } from "../../fieldset-template";
import { FormulaireNode } from "../../formulaire-node";
import { FormulaireBase } from "./form-base";
/**
* Formulaire pour les passes à bassins, inspiré du formulaire
* pour les structures en parallèle
*/
export class FormulairePab extends FormulaireBase {
/** id du select configurant le modèle de cloisons */
private __modeleCloisonsSelectId: string;
constructor() {
super();
this._formResult = new FormResultFixedVar(this, false);
// remove obsolete observer set by super()
this.removeObserver(this._formCompute);
this._formCompute = new FormComputeParallelStructures(this, (this._formResult as FormResultFixedVar));
}
private createPabCloisons(templ: FieldsetTemplate): Nub {
// !!! attention !!!
// Il doit y avoir cohérence dans le fichier de conf entre les valeurs defaultXXX et les valeurs possibles pour les select
// cad valeur par défaut du 1er select (type d'ouvrage), du 2ème (loi de débit).
// A terme, il faudrait analyser le fichier de conf (dépendances d'existence) pour déterminer automatiquement ces valeurs
const params = {};
params["calcType"] = templ.calcTypeFromConfig;
params["nodeType"] = templ.defaultNodeTypeFromConfig;
return this.createBassin(new Props(params));
}
/**
* ajoute un Nub Structure
* @param st structure à ajouter
* @param after position après laquelle insérer la structure, à la fin sinon
*/
private addPabCloisons(st: Structure, after?: number) {
this.parallelStructureNub.addChild(st, after);
}
private get parallelStructureNub(): ParallelStructure {
return this.currentNub as ParallelStructure;
}
/**
* Asks JaLHyd to create a PabCloisons Nub as a child of the current Calculator Module
* and return it; does not store it in the Session (for PabCloisons, not for Calculator Modules)
* @param p properties for the new Nub
*/
protected createBassin(p: Props): PabCloisons {
return Session.getInstance().createNub(p, this.currentNub as Pab) as PabCloisons;
}
/**
* Replaces the current Nub in the current calculator module, with a new one built with properties "params"
* @param params properties to build the new Nub (calcType, loiDebit...)
*/
protected replaceNub(sn: Structure, params: Props): Nub {
const parent = (this.currentNub as PabCloisons);
const newBassin = this.createBassin(params);
parent.replaceChildInplace(sn, newBassin);
return newBassin;
}
/**
* Deleted the given child Nub in the current calculator module
* @param params properties to build the new Nub (calcType, loiDebit...)
*/
protected deleteNub(sn: Structure) {
const parent = (this.currentNub as PabCloisons);
parent.deleteChild(parent.getIndexForChild(sn));
}
public createFieldset(parent: FormulaireNode, json: {}, data?: {}, nub?: Nub): FieldSet {
console.log("++++++++++ CREATE FIELDSET +++++++++++", parent.constructor.name, json, data, nub ? nub.constructor.name : "zizi");
if (json["calcType"] === "PabCloisons") {
console.log("youpidou");
// indice après lequel insérer le nouveau FieldSet
const after = data["after"];
const res: FieldSet = new FieldSet(parent);
let n: Nub;
if (nub) { // use existing Nub (build interface based on model)
n = nub;
} else {
n = this.createPabCloisons(data["template"]);
this.addPabCloisons(n as Structure, after);
}
res.setNub(n, false);
if (after !== undefined) {
parent.kids.splice(after + 1, 0, res);
} else {
parent.kids.push(res);
}
this.resetResults();
return res;
} else {
return super.createFieldset(parent, json, data);
}
}
protected parseOptions(json: {}) {
super.parseOptions(json);
// id du select configurant le type d'ouvrage
this.__modeleCloisonsSelectId = this.getOption(json, "ouvrageSelectId");
}
public afterParseFieldset(fs: FieldSet) {
// si le FieldSet contient le select de type d'ouvrage
if (this.__modeleCloisonsSelectId) {
const sel = fs.getFormulaireNodeById(this.__modeleCloisonsSelectId);
if (sel) {
// on abonne le formulaire aux propriétés du FieldSet
fs.properties.addObserver(this);
}
}
}
public moveFieldsetUp(fs: FieldSet) {
if (fs.nub instanceof Structure) {
// déplacement du nub
fs.nub.parent.moveChildUp(fs.nub);
// déplacement du fieldset
this.fieldsetContainer.moveFieldsetUp(fs);
this.resetResults();
} else {
super.moveFieldsetUp(fs);
}
}
public moveFieldsetDown(fs: FieldSet) {
if (fs.nub instanceof Structure) {
// déplacement du nub
fs.nub.parent.moveChildDown(fs.nub);
// déplacement du fieldset
this.fieldsetContainer.moveFieldsetDown(fs);
this.resetResults();
} else { super.moveFieldsetDown(fs); }
}
public removeFieldset(fs: FieldSet) {
if (fs.nub instanceof Structure) {
// suppression du sous-nub dans le Nub parent
this.deleteNub(fs.nub);
// suppression du fieldset
this.fieldsetContainer.removeFieldset(fs);
this.resetResults();
} else { super.removeFieldset(fs); }
}
protected completeParse(json: {}) {
this.subscribeFieldsetContainer();
}
private get fieldsetContainer(): FieldsetContainer {
const n = this.getFormulaireNodeById("bassin_container");
if (n === undefined || !(n instanceof FieldsetContainer)) {
throw new Error("l'élément 'bassin_container' n'est pas du type FieldsetContainer");
}
return n as FieldsetContainer;
}
/**
* abonnement en tant qu'observateur du FieldsetContainer
*/
private subscribeFieldsetContainer() {
this.fieldsetContainer.addObserver(this);
}
/**
* abonnement en tant qu'observateur des NgParameter des FieldSet contenus dans le FieldsetContainer
*/
private subscribeBasinFields(fs: FieldSet) {
for (const n of fs.allFormElements) {
if (n instanceof NgParameter || n instanceof SelectField) {
n.addObserver(this);
}
}
}
// interface Observer
public update(sender: any, data: any) {
super.update(sender, data);
if (sender instanceof FieldsetContainer) {
switch (data.action) {
case "newFieldset":
console.log(">>>>>>>>> yeah new fieldset !", data);
this.reset();
this.subscribeBasinFields(data["fieldset"]);
}
} else if (sender instanceof FieldSet && data.action === "propertyChange") {
console.log(">>>>>>>>> PAB property change !", data);
switch (sender.id) {
case "fs_bassin":
// @TODO set modelCloisons
/* const props = sender.properties;
// ensure loiDebit is set
props.setPropValue("loiDebit", data.value);
this.adjustProperties(props, data["name"], data["value"]);
// replace Structure Nub
const newNub = this.replaceNub((sender.nub as Structure), props);
sender.setNub(newNub);
// treat the fieldset as new to re-subscribe to Nub properties change events
this.afterParseFieldset(sender);
this.reset(); */
break;
}
}
}
}
import { Structure, Nub, ParallelStructure, LoiDebit, StructureProperties, Props, Session, StructureType } from "jalhyd";
import { Structure, Nub, ParallelStructure, StructureProperties, Props, Session } from "jalhyd";
import { FormDefParallelStructures } from "../form-def-parallel-structures";
import { FormComputeParallelStructures } from "../form-compute-parallel-structures";
import { FormResultFixedVar } from "../form-result-fixedvar";
import { FieldsetContainer } from "../../fieldset-container";
......@@ -13,8 +12,6 @@ import { FormulaireBase } from "./form-base";
export class FormulaireParallelStructure extends FormulaireBase {
private _formParallelStruct: FormDefParallelStructures;
/**
* id du select configurant le type d'ouvrage
*/
......@@ -23,11 +20,10 @@ export class FormulaireParallelStructure extends FormulaireBase {
constructor() {
super();
this._formResult = new FormResultFixedVar(this, false);
this._formParallelStruct = new FormDefParallelStructures();
// remove obsolete observer set by super()
this.removeObserver(this._formCompute);
this._formCompute = new FormComputeParallelStructures(this, this._formParallelStruct, (this._formResult as FormResultFixedVar));
this._formCompute = new FormComputeParallelStructures(this, (this._formResult as FormResultFixedVar));
}
private createStructNub(templ: FieldsetTemplate): Nub {
......@@ -171,7 +167,6 @@ export class FormulaireParallelStructure extends FormulaireBase {
}
protected completeParse(json: {}) {
this._formParamCalc.parseOptions(json);
this.subscribeFieldsetContainer();
}
......
......@@ -23,7 +23,6 @@ export class FormulaireRegimeUniforme extends FormulaireBase implements Observer
}
protected completeParse(json: {}) {
this._formParamCalc.parseOptions(json);
super.completeParse(json);
}
......
import { ComputeNode, ParamDefinition, PabCloisons, Pab } from "jalhyd";
import { FormComputeFixedVar } from "./form-compute-fixedvar";
import { FormResultFixedVar } from "./form-result-fixedvar";
import { FormulaireDefinition } from "./form-definition";
import { NgParameter } from "../ngparam";
import { FormulaireNode } from "../formulaire-node";
import { FieldSet } from "../fieldset";
import { FieldsetContainer } from "../fieldset-container";
export class FormComputePab extends FormComputeFixedVar {
constructor(formBase: FormulaireDefinition, formResult: FormResultFixedVar) {
super(formBase, formResult);
}
/**
* @return dans le cas d'un paramètre de bassin, le FieldSet parent d'un paramètre,
* le FieldsetContainer parent du FieldSet
* ainsi que l'indice du FieldSet parent dans le FieldsetContainer
*/
private structureParents(p: NgParameter): [FieldsetContainer, FieldSet, number] {
const parent1: FormulaireNode = p.parent;
if (parent1 !== undefined) {
if (parent1 instanceof FieldSet) {
const parent2 = parent1.parent;
if (parent2 instanceof FieldsetContainer) {
const fsIndex = parent1.indexAsKid();
return [parent2, parent1, fsIndex];
}
}
}
return [undefined, undefined, -1];
}
/**
* construit un identifiant de type { uid: "abcdef", symbol: "X" }
* avec "abcdef" l'index du bassin et "X" son paramètre
*/
protected getParameterRefid(p: ParamDefinition): any {
const nub = p.parentComputeNode;
if (nub instanceof PabCloisons) {
return {
uid: nub.uid,
symbol: p.symbol
};
} else {
return super.getParameterRefid(p);
}
}
protected setParameterValue(node: ComputeNode, p: NgParameter, val: number) {
const [fsc, fs, i] = this.structureParents(p);
if (i === -1) {
super.setParameterValue(node, p, val);
} else {
const n: Pab = node as Pab;
const prm = n.children[i].getParameter(p.symbol);
prm.v = val;
}
}
}
......@@ -7,14 +7,11 @@ import { NgParameter } from "../ngparam";
import { FormulaireNode } from "../formulaire-node";
import { FieldSet } from "../fieldset";
import { FieldsetContainer } from "../fieldset-container";
import { FormDefParallelStructures } from "./form-def-parallel-structures";
export class FormComputeParallelStructures extends FormComputeFixedVar {
private _formParallelStruct: FormDefParallelStructures;
constructor(formBase: FormulaireDefinition, formParallelStruct: FormDefParallelStructures, formResult: FormResultFixedVar) {
constructor(formBase: FormulaireDefinition, formResult: FormResultFixedVar) {
super(formBase, formResult);
this._formParallelStruct = formParallelStruct;
}
/**
......
import { FormulaireDefinition } from "./form-definition";
/**
* gestion des formulaires avec "paramètre fixé" et "paramètre à varier"
*/
export class FormDefFixedVar {
protected _formBase: FormulaireDefinition;
constructor(base: FormulaireDefinition) {
this._formBase = base;
}
}
/**
* gestion des formulaires "ouvrages parallèles"
*/
export class FormDefParallelStructures {
}
import { FormulaireDefinition } from "./form-definition";
import { FormDefFixedVar } from "./form-def-fixedvar";
/**
* gestion des formulaires avec "paramètre à calculer" (conduite distributrice, Lechapt-Calmon, régime uniforme, passes à bassin)
*/
export class FormDefParamToCalculate extends FormDefFixedVar {
constructor(base: FormulaireDefinition) {
super(base);
}
public parseOptions(json: {}) {
}
}
......@@ -3,7 +3,7 @@ import { Injectable } from "@angular/core";
import { decode } from "he";
import { saveAs } from "file-saver";
import { CalculatorType, LinkedValue, Observable, ParamDefinition, Session, Nub, ParallelStructure } from "jalhyd";
import { CalculatorType, LinkedValue, Observable, ParamDefinition, Session, Nub, ParallelStructure, Pab } from "jalhyd";
import { HttpService } from "../../services/http/http.service";
import { I18nService } from "../../services/internationalisation/internationalisation.service";
......@@ -22,6 +22,7 @@ import { NgParameter } from "../../formulaire/ngparam";
import { FieldsetContainer } from "../..//formulaire/fieldset-container";
import { ApplicationSetupService } from "../app-setup/app-setup.service";
import { NotificationsService } from "../notifications/notifications.service";
import { FormulairePab } from "../../formulaire/definition/concrete/form-pab";
@Injectable()
export class FormulaireService extends Observable {
......@@ -60,6 +61,7 @@ export class FormulaireService extends Observable {
this.calculatorPaths[CalculatorType.Dever] = "dever";
this.calculatorPaths[CalculatorType.Cloisons] = "cloisons";
this.calculatorPaths[CalculatorType.MacroRugo] = "macrorugo";
this.calculatorPaths[CalculatorType.Pab] = "pab";
}
private get _intlService(): I18nService {
......@@ -213,6 +215,10 @@ export class FormulaireService extends Observable {
f = new FormulaireParallelStructure();
break;
case CalculatorType.Pab:
f = new FormulairePab();
break;
default:
f = new FormulaireBase();
}
......@@ -256,16 +262,30 @@ export class FormulaireService extends Observable {
f.parseConfig();
// add fieldsets for existing structures if needed
// add fieldsets for existing Structures if needed
// (when loading session only)
if (f.currentNub instanceof ParallelStructure) {
for (s of f.currentNub.structures) {
for (const struct of f.currentNub.structures) {
for (const e of f.allFormElements) {
if (e instanceof FieldsetContainer) { // @TODO manage many containers one day ?
e.addFromTemplate(0, undefined, struct);
}
}
}
}
// add fieldsets for existing PabCloisons if needed
// (when loading session only)
if (f.currentNub instanceof Pab) {
for (const child of f.currentNub.children) {
for (const e of f.allFormElements) {
if (e instanceof FieldsetContainer) { // @TODO manage many containers one day ?
e.addFromTemplate(0, undefined, s);
e.addFromTemplate(0, undefined, child);
}
}
}
}
return f;
}).then(fi => {
......
......@@ -132,6 +132,8 @@
"INFO_LIB_PR": "Display accuracy",
"INFO_LIB_Q": "Discharge",
"INFO_LIB_SELECT_LOIDEBIT1": "Stage-discharge law",
"INFO_LIB_QA": "Attraction flow",
"INFO_LIB_SELECT_LOIDEBIT": "Stage-discharge law",
"INFO_LIB_SELECT_LOIDEBIT1_KIVI": "Kindsvater-Carter and Villemonte",
"INFO_LIB_SELECT_LOIDEBIT2": "Stage-discharge law",
"INFO_LIB_SELECT_LOIDEBIT3": "Stage-discharge law",
......@@ -176,6 +178,8 @@
"INFO_OPTION_YES": "Yes",
"INFO_OPTION_GENERATE": "Generate",
"INFO_OUVRAGE": "Structure",
"INFO_PAB_TITRE": "Fish ladder",
"INFO_PAB_TITRE_COURT": "Fish ladder",
"INFO_PABCHUTE_TITRE": "Fish ladder: fall",
"INFO_PABCHUTE_TITRE_COURT": "FL: fall",
"INFO_PABDIMENSIONS_TITRE": "Fish ladder: dimensions",
......
......@@ -132,6 +132,8 @@
"INFO_LIB_PR": "Précision de calcul",
"INFO_LIB_Q": "Débit",
"INFO_LIB_SELECT_LOIDEBIT1": "Loi de débit",
"INFO_LIB_QA": "Débit d'attrait",
"INFO_LIB_SELECT_LOIDEBIT": "Loi de débit",
"INFO_LIB_SELECT_LOIDEBIT1_KIVI": "Kindsvater-Carter et Villemonte",
"INFO_LIB_SELECT_LOIDEBIT2": "Loi de débit",
"INFO_LIB_SELECT_LOIDEBIT3": "Loi de débit",
......@@ -177,6 +179,8 @@
"INFO_OPTION_GENERATE": "Générer",
"INFO_OUVRAGE": "Ouvrage",
"INFO_PABCHUTE_TITRE": "Passe à bassins&nbsp;: chute",
"INFO_PAB_TITRE": "Passe à bassins",
"INFO_PAB_TITRE_COURT": "PAB",
"INFO_PABCHUTE_TITRE_COURT": "PAB&nbsp;: chute",
"INFO_PABDIMENSIONS_TITRE": "Passe à bassins&nbsp;: dimensions",
"INFO_PABDIMENSIONS_TITRE_COURT": "PAB&nbsp;: dimensions",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment