diff --git a/.gitignore b/.gitignore
index 339da7fb56721c66af03a90404fe6c9dd5739a7a..c5b7f7ee4160b1b4bfdbb25030e4e42a73cfa781 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@
 
 # dependencies
 /node_modules
+/src/assets/mathjax
 
 # IDEs and editors
 /.idea
diff --git a/README.md b/README.md
index 529b343e4e4c66dbc3973f9ab9be1baee0581284..ac570727fdf5060fd9b44bda43ea8ffa68aba105 100644
--- a/README.md
+++ b/README.md
@@ -129,51 +129,47 @@ and then :
 * Créer les tests unitaires correspondants
 
 
-* Ajouter une valeur à l'enum _ComputeNodeType_ pour identifier le type de noeud de calcul (par ex _MaCalculette_).
+* Ajouter une valeur à l'enum _CalculatorType_ pour identifier le type de calculette (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.
+* Compléter la méthode _NubFactory.createNub()_.
 
 
 ## ngHyd
 
-* Créer les fichier de configuration de la calculette
+* Créer les fichiers 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)
+		Les ids utilisés doivent correspondre au symbole fourni à classe _BaseParam_ (1er 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"_
+		- éventuellement le type de noeud par défaut de la calculette dans les options avec le champ "_defaultNodeType_". Si ce champ est absent, sa valeur est "_ComputeNodeType.None_". Ce champ sert par ex pour les sections paramétrées à déterminer le type de section à afficher lors de la création de la calculette.
+
+		- éventuellement le type de noeud de paramètres particuliers (objets comportant _"type":"input"_) avec le champ _"nodeType": "MaCalculetteBleue"_ (par défaut, "_ComputeNodeType.None_")
 
 	- 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.
 
-* Dans le fichier *src/app/formulaire/formulaire-definition.ts* ajouter une valeur à l'enum _CalculatorType_ pour identifier la calculette.
+* créer la classe du formulaire dans _src/app/formulaire/definition/concrete_
 
-	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).
+	- Par ex : _FormulaireMaCalculette_ dans _src/app/formulaire/definition/concrete/form-ma-calculette.ts_
 
-* Composant CalculatorListComponent : ajouter une ligne à la methode _updateLocale()_ pour créer une nouvelle entrée dans la liste des calculettes disponibles.
+		Ces classes concrètes sont construites par composition des classes dans _src/app/formulaire/definition_ :
+		- _form-def-*_ : définition/description du formulaire.
+			- _FormDefSection_ : avec paramètre à varier
+			- _FormDefParamToCalculate_ : avec paramètre à calculer
+			- etc...
+		- _form-compute-*_ : aspects calculatoires
+		- _form-result-*_ : affichage des résultats
+
+		On peut soit composer la classe concrète directement avec ces classes, soient dériver ces dernières et composer avec.
 
 * _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.
-
 * Dans la méthode _FormulaireService.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()_
-
-* Compléter la méthode _FormulaireDefinition.doCompute()_.
-	En particulier, adapter les méthodes _getNubAndParameters()_ ou _getSectionNubAndParameters()_ (récupération des valeurs saisies dans l'interface).
diff --git a/package.json b/package.json
index f612aaad6bbfd547dbbfb8103327938c54a4243e..e40a1eb19b0f2311cacb0102d94953797a56b954 100644
--- a/package.json
+++ b/package.json
@@ -4,13 +4,14 @@
   "license": "MIT",
   "scripts": {
     "ng": "ng",
-    "start": "ng serve --host 0.0.0.0",
-    "prod": "ng serve --host 0.0.0.0 --env=prod",
-    "build": "ng build",
+    "start": "npm run mathjax; ng serve --host 0.0.0.0",
+    "prod": "npm run mathjax; ng serve --host 0.0.0.0 --env=prod",
+    "build": "npm run mathjax; ng build",
     "test": "ng test",
     "lint": "ng lint",
     "e2e": "ng e2e",
-    "jalhyd": "rm -rf node_modules/jalhyd; cd ../jalhyd; npm run package; cd ../nghyd; npm install ../jalhyd/jalhyd-1.0.0.tgz"
+    "jalhyd": "rm -rf node_modules/jalhyd; cd ../jalhyd; npm run package; cd ../nghyd; npm install ../jalhyd/jalhyd-1.0.0.tgz;",
+    "mathjax": "rm -rf src/assets/mathjax; cp -R node_modules/mathjax src/assets/mathjax;"
   },
   "private": true,
   "dependencies": {
@@ -29,6 +30,7 @@
     "file-saver": "^1.3.8",
     "he": "^1.1.1",
     "jalhyd": "file:../jalhyd/jalhyd-1.0.0.tgz",
+    "mathjax": "^2.7.4",
     "ngx-md": "^3.1.1",
     "rxjs": "^5.5.2",
     "zone.js": "^0.8.14"
diff --git a/src/app/calculators/dever/dever.config.json b/src/app/calculators/dever/dever.config.json
new file mode 100644
index 0000000000000000000000000000000000000000..99fe3d0268da196ee09be39173d3a65cf84e8b5d
--- /dev/null
+++ b/src/app/calculators/dever/dever.config.json
@@ -0,0 +1,224 @@
+[
+    {
+        "id": "fs_param_hydro",
+        "type": "fieldset",
+        "calcType": "Dever",
+        "option": "cal",
+        "fields": [
+            {
+                "type": "input",
+                "id": "Q",
+                "symbol": "Q",
+                "unit": "m³/s"
+            },
+            {
+                "type": "input",
+                "id": "Z1",
+                "unit": "m"
+            },
+            {
+                "type": "input",
+                "id": "BR",
+                "unit": "m"
+            },
+            {
+                "type": "input",
+                "id": "ZR",
+                "unit": "m"
+            }
+        ]
+    },
+    {
+        "id": "fs_ouvrage",
+        "type": "fieldset_template",
+        "calcType": "Structure",
+        "defaultNodeType": "StructureRectangle",
+        "defaultStructType": "SeuilRectangulaire",
+        "defaultLoiDebit": "WeirFree",
+        "option": "cal",
+        "fields": [
+            {
+                "id": "select_ouvrage",
+                "type": "select",
+                "select": [
+                    {
+                        "id": "select_ouvrage_seuil_rect",
+                        "enum": "StructureType.SeuilRectangulaire"
+                    },
+                    {
+                        "id": "select_ouvrage_seuil_triang",
+                        "enum": "StructureType.SeuilTriangulaire"
+                    },
+                    {
+                        "id": "select_ouvrage_seuil_triangtrunc",
+                        "enum": "StructureType.SeuilTriangulaireTrunc"
+                    }
+                ]
+            },
+            {
+                "id": "select_loidebit1",
+                "type": "select",
+                "select": [
+                   {
+                        "id": "select_loidebit1_seuildenoye",
+                        "enum": "LoiDebit.WeirFree"
+                    }
+                ],
+                "dep_exist": [
+                    {
+                        "refid": "select_ouvrage",
+                        "refvalue": "select_ouvrage_seuil_rect"
+                    }
+                ]
+            },
+            {
+                "id": "select_loidebit3",
+                "type": "select",
+                "select": [
+                    {
+                        "id": "select_loidebit3_seuiltriang",
+                        "enum": "LoiDebit.TriangularWeirFree"
+                    }
+                ],
+                "dep_exist": [
+                    {
+                        "refid": "select_ouvrage",
+                        "refvalue": "select_ouvrage_seuil_triang"
+                    }
+                ]
+            },
+            {
+                "id": "select_loidebit4",
+                "type": "select",
+                "select": [
+                    {
+                        "id": "select_loidebit4_seuiltriangtrunc",
+                        "enum": "LoiDebit.TriangularTruncWeirFree"
+                    }
+                ],
+                "dep_exist": [
+                    {
+                        "refid": "select_ouvrage",
+                        "refvalue": "select_ouvrage_seuil_triangtrunc"
+                    }
+                ]
+            },
+            {
+                "type": "input",
+                "id": "ZDV",
+                "unit": "m",
+                "nodeType": "StructureRectangle",
+                "dep_exist": [
+                    {
+                        "refid": "select_ouvrage",
+                        "refvalue": "select_ouvrage_seuil_rect"
+                    },
+                    {
+                        "refid": "select_ouvrage",
+                        "refvalue": "select_ouvrage_seuil_triang"
+                    },
+                    {
+                        "refid": "select_ouvrage",
+                        "refvalue": "select_ouvrage_seuil_triangtrunc"
+                    }
+                ]
+            },
+            {
+                "type": "input",
+                "id": "L",
+                "unit": "m",
+                "nodeType": "StructureRectangle",
+                "dep_exist": [
+                    {
+                        "refid": "select_ouvrage",
+                        "refvalue": "select_ouvrage_seuil_rect"
+                    }
+                ]
+            },
+            {
+                "type": "input",
+                "id": "Cd",
+                "unit": "",
+                "nodeType": "StructureRectangle",
+                "dep_exist": [
+                    {
+                        "refid": "select_loidebit1",
+                        "refvalue": "select_loidebit1_seuildenoye"
+                    },
+                    {
+                        "refid": "select_loidebit3",
+                        "refvalue": "select_loidebit3_seuiltriang"
+                    },
+                    {
+                        "refid": "select_loidebit3",
+                        "refvalue": "select_loidebit4_seuiltriangtrunc"
+                    }
+                ]
+            },
+            {
+                "type": "input",
+                "id": "alpha2",
+                "unit": "",
+                "nodeType": "StructureRectangle",
+                "dep_exist": [
+                    {
+                        "refid": "select_ouvrage",
+                        "refvalue": "select_ouvrage_seuil_triang"
+                    },
+                    {
+                        "refid": "select_ouvrage",
+                        "refvalue": "select_ouvrage_seuil_triangtrunc"
+                    }
+                ]
+            },
+            {
+                "type": "input",
+                "id": "BT",
+                "unit": "",
+                "nodeType": "StructureRectangle",
+                "dep_exist": [
+                    {
+                        "refid": "select_ouvrage",
+                        "refvalue": "select_ouvrage_seuil_triangtrunc"
+                    }
+                ]
+            },
+            {
+                "type": "input",
+                "id": "ZT",
+                "unit": "",
+                "nodeType": "StructureRectangle",
+                "dep_exist": [
+                    {
+                        "refid": "select_ouvrage",
+                        "refvalue": "select_ouvrage_seuil_triangtrunc"
+                    }
+                ]
+            }
+        ]
+    },
+    {
+        "id": "struct_container",
+        "type": "template_container",
+        "templates": [
+            "fs_ouvrage"
+        ]
+    },
+    {
+        "id": "fs_param_calc",
+        "type": "fieldset",
+        "calcType": "ParallelStructure",
+        "option": "fix",
+        "fields": [
+            {
+                "type": "input",
+                "id": "Pr"
+            }
+        ]
+    },
+    {
+        "type": "options",
+        "ouvrageSelectId": "select_ouvrage",
+        "idCal": "Q"
+    }
+]
\ No newline at end of file
diff --git a/src/app/calculators/dever/dever.fr.json b/src/app/calculators/dever/dever.fr.json
new file mode 100644
index 0000000000000000000000000000000000000000..7b6fb261a7f49764f729f5f6bd313e62c4de2793
--- /dev/null
+++ b/src/app/calculators/dever/dever.fr.json
@@ -0,0 +1,42 @@
+{
+    "fs_param_hydro": "Paramètres hydrauliques",
+    "Q": "Débit total",
+    "Z1": "Cote de l'eau amont",
+    "ZR": "Cote du lit amont",
+    "BR": "Largeur du lit amont",
+    "fs_ouvrage": "Ouvrage",
+    "select_ouvrage": "Ouvrage",
+    "select_ouvrage_vanne_circ": "Vanne circulaire",
+    "select_ouvrage_vanne_rect": "Vanne rectangulaire",
+    "select_ouvrage_seuil_rect": "Seuil rectangulaire",
+    "select_ouvrage_seuil_trap": "Seuil trapézoïdal",
+    "select_ouvrage_vanne_trap": "Vanne trapézoïdale",
+    "select_ouvrage_seuil_triang": "Seuil triangulaire",
+    "select_ouvrage_seuil_triangtrunc": "Seuil triangulaire tronqué",
+    "W": "Ouverture de vanne",
+    "select_loidebit1": "Loi de débit",
+    "select_loidebit1_seuildenoye": "Seuil dénoyé",
+    "select_loidebit1_cunge80": "Cunge 80",
+    "select_loidebit1_cem88d": "Déversoir/Orifice Cemagref 88",
+    "select_loidebit1_cem88v": "Déversoir/Vanne de fond Cemagref 88",
+    "select_loidebit1_kivi": "Kindsvater-Carter et Villemonte",
+    "select_loidebit2": "Loi de débit",
+    "select_loidebit2_vannedenoye": "Vanne dénoyé",
+    "select_loidebit2_vannenoye": "Vanne noyé",
+    "select_loidebit2_cunge80": "Cunge 80",
+    "select_loidebit2_cem88d": "Déversoir/Orifice Cemagref 88",
+    "select_loidebit2_cem88v": "Déversoir/Vanne de fond Cemagref 88",
+    "select_loidebit3": "Loi de débit",
+    "select_loidebit3_seuiltriang": "Seuil triangulaire",
+    "select_loidebit4": "Loi de débit",
+    "select_loidebit4_seuiltriangtrunc": "Seuil triangulaire tronqué",
+    "ZDV": "Cote de la crête du déversoir ou du radier de la vanne",
+    "L": "Largeur du déversoir",
+    "Cd": "Coefficient de débit",
+    "alpha": "Coefficient alpha",
+    "beta": "Coefficient béta",
+    "ZRAM": "Cote du radier amont",
+    "struct_container": "Ouvrages",
+    "fs_param_calc": "Paramètres de calcul",
+    "Pr": "Précision de calcul"
+}
\ No newline at end of file
diff --git a/src/app/calculators/parallel-structures/parallel-structures.config.json b/src/app/calculators/parallel-structures/parallel-structures.config.json
index 496e6114f9f943c3a1532cfa05ca2e5da0284bd6..6151865b570f671ba449a2e7cb6fa1f0b3c30dd4 100644
--- a/src/app/calculators/parallel-structures/parallel-structures.config.json
+++ b/src/app/calculators/parallel-structures/parallel-structures.config.json
@@ -43,6 +43,14 @@
                     {
                         "id": "select_ouvrage_seuil_rect",
                         "enum": "StructureType.SeuilRectangulaire"
+                    },
+                    {
+                        "id": "select_ouvrage_seuil_triang",
+                        "enum": "StructureType.SeuilTriangulaire"
+                    },
+                    {
+                        "id": "select_ouvrage_seuil_triangtrunc",
+                        "enum": "StructureType.SeuilTriangulaireTrunc"
                     }
                 ]
             },
@@ -110,6 +118,38 @@
                     }
                 ]
             },
+            {
+                "id": "select_loidebit3",
+                "type": "select",
+                "select": [
+                    {
+                        "id": "select_loidebit3_seuiltriang",
+                        "enum": "LoiDebit.TriangularWeirFree"
+                    }
+                ],
+                "dep_exist": [
+                    {
+                        "refid": "select_ouvrage",
+                        "refvalue": "select_ouvrage_seuil_triang"
+                    }
+                ]
+            },
+            {
+                "id": "select_loidebit4",
+                "type": "select",
+                "select": [
+                    {
+                        "id": "select_loidebit4_seuiltriangtrunc",
+                        "enum": "LoiDebit.TriangularTruncWeirFree"
+                    }
+                ],
+                "dep_exist": [
+                    {
+                        "refid": "select_ouvrage",
+                        "refvalue": "select_ouvrage_seuil_triangtrunc"
+                    }
+                ]
+            },
             {
                 "type": "input",
                 "id": "ZDV",
@@ -125,8 +165,12 @@
                         "refvalue": "select_ouvrage_seuil_rect"
                     },
                     {
-                        "refid": "select_loidebit1",
-                        "refvalue": "select_loidebit1_kivi"
+                        "refid": "select_ouvrage",
+                        "refvalue": "select_ouvrage_seuil_triang"
+                    },
+                    {
+                        "refid": "select_ouvrage",
+                        "refvalue": "select_ouvrage_seuil_triangtrunc"
                     }
                 ]
             },
@@ -203,6 +247,14 @@
                     {
                         "refid": "select_loidebit2",
                         "refvalue": "select_loidebit2_cem88v"
+                    },
+                    {
+                        "refid": "select_loidebit3",
+                        "refvalue": "select_loidebit3_seuiltriang"
+                    },
+                    {
+                        "refid": "select_loidebit3",
+                        "refvalue": "select_loidebit4_seuiltriangtrunc"
                     }
                 ]
             },
@@ -241,6 +293,46 @@
                         "refvalue": "select_loidebit1_kivi"
                     }
                 ]
+            },
+            {
+                "type": "input",
+                "id": "alpha2",
+                "unit": "",
+                "nodeType": "StructureRectangle",
+                "dep_exist": [
+                    {
+                        "refid": "select_ouvrage",
+                        "refvalue": "select_ouvrage_seuil_triang"
+                    },
+                    {
+                        "refid": "select_ouvrage",
+                        "refvalue": "select_ouvrage_seuil_triangtrunc"
+                    }
+                ]
+            },
+            {
+                "type": "input",
+                "id": "BT",
+                "unit": "",
+                "nodeType": "StructureRectangle",
+                "dep_exist": [
+                    {
+                        "refid": "select_ouvrage",
+                        "refvalue": "select_ouvrage_seuil_triangtrunc"
+                    }
+                ]
+            },
+            {
+                "type": "input",
+                "id": "ZT",
+                "unit": "",
+                "nodeType": "StructureRectangle",
+                "dep_exist": [
+                    {
+                        "refid": "select_ouvrage",
+                        "refvalue": "select_ouvrage_seuil_triangtrunc"
+                    }
+                ]
             }
         ]
     },
diff --git a/src/app/calculators/parallel-structures/parallel-structures.fr.json b/src/app/calculators/parallel-structures/parallel-structures.fr.json
index f683f20dfbef48cbd1c7e6b94c97831f1bc245fb..2264c6b499b0c69035b165bd7913f7eb01ac1ab6 100644
--- a/src/app/calculators/parallel-structures/parallel-structures.fr.json
+++ b/src/app/calculators/parallel-structures/parallel-structures.fr.json
@@ -8,6 +8,8 @@
     "select_ouvrage_vanne_circ": "Vanne circulaire",
     "select_ouvrage_vanne_rect": "Vanne rectangulaire",
     "select_ouvrage_seuil_rect": "Seuil rectangulaire",
+    "select_ouvrage_seuil_triang": "Seuil triangulaire",
+    "select_ouvrage_seuil_triangtrunc": "Seuil triangulaire tronqué",
     "select_ouvrage_seuil_trap": "Seuil trapézoïdal",
     "select_ouvrage_vanne_trap": "Vanne trapézoïdale",
     "W": "Ouverture de vanne",
@@ -18,17 +20,24 @@
     "select_loidebit1_cem88v": "Déversoir/Vanne de fond Cemagref 88",
     "select_loidebit1_kivi": "Kindsvater-Carter et Villemonte",
     "select_loidebit2": "Loi de débit",
+    "select_loidebit3": "Loi de débit",
+    "select_loidebit4": "Loi de débit",
     "select_loidebit2_vannedenoye": "Vanne dénoyé",
     "select_loidebit2_vannenoye": "Vanne noyé",
     "select_loidebit2_cunge80": "Cunge 80",
     "select_loidebit2_cem88d": "Déversoir/Orifice Cemagref 88",
     "select_loidebit2_cem88v": "Déversoir/Vanne de fond Cemagref 88",
+    "select_loidebit3_seuiltriang": "Déversoir triangulaire dénoyé",
+    "select_loidebit4_seuiltriangtrunc": "Déversoir triangulaire tronqué dénoyé",
     "ZDV": "Cote de la crête du déversoir ou du radier de la vanne",
-    "L": "Largeur du déversoir",
+    "L": "Largeur du déversoir (m)",
     "Cd": "Coefficient de débit",
     "alpha": "Coefficient alpha",
     "beta": "Coefficient béta",
-    "ZRAM": "Cote du radier amont",
+    "ZRAM": "Cote du radier amont (m)",
+    "alpha2": "Demi-angle au sommet (°)",
+    "BT": "Demi-ouverture du triangle (m)",
+    "ZT": "Cote haute du triangle (m)",
     "struct_container": "Ouvrages",
     "fs_param_calc": "Paramètres de calcul",
     "Pr": "Précision de calcul"
diff --git a/src/app/calculators/regime-uniforme/regime-uniforme.config.json b/src/app/calculators/regime-uniforme/regime-uniforme.config.json
index 7286a71d854c26253d79f644a1ee23f176901b13..0ef1396598aa2451def98876cfc22b23b3808f3e 100644
--- a/src/app/calculators/regime-uniforme/regime-uniforme.config.json
+++ b/src/app/calculators/regime-uniforme/regime-uniforme.config.json
@@ -152,6 +152,7 @@
     },
     {
         "type": "options",
+        "defaultNodeType": "SectionCercle",
         "idCal": "Q",
         "sectionSourceId": "fs_section"
     }
diff --git a/src/app/calculators/remous/remous.config.json b/src/app/calculators/remous/remous.config.json
index 289a274e1025d7b6fcda32c5556734efe79fba3c..592621d45ceafbaf28b1e91c907f114d5984796c 100644
--- a/src/app/calculators/remous/remous.config.json
+++ b/src/app/calculators/remous/remous.config.json
@@ -260,6 +260,7 @@
     },
     {
         "type": "options",
+        "defaultNodeType": "SectionPuissance",
         "sectionSourceId": "select_section",
         "targetSelectId": "select_target",
         "methodSelectId": "select_resolution"
diff --git a/src/app/calculators/section-param/section-param.config.json b/src/app/calculators/section-param/section-param.config.json
index 56ea1dd3cb265ab2e03c10c0fa9cd8689157168e..7c8a769ec32f0f93d9194b448edfa2958dc33587 100644
--- a/src/app/calculators/section-param/section-param.config.json
+++ b/src/app/calculators/section-param/section-param.config.json
@@ -274,6 +274,7 @@
     },
     {
         "type": "options",
+        "defaultNodeType": "SectionCercle",
         "sectionSourceId": "select_section",
         "targetSelectId": "select_target"
     }
diff --git a/src/app/formulaire/definition/concrete/form-cond-distri.ts b/src/app/formulaire/definition/concrete/form-cond-distri.ts
index c9e70be83fe041ed100de2532b4b64ff14f2303e..9229f2ce6e364acf9829ffde10c94f9e1cc40c77 100644
--- a/src/app/formulaire/definition/concrete/form-cond-distri.ts
+++ b/src/app/formulaire/definition/concrete/form-cond-distri.ts
@@ -23,10 +23,6 @@ export class FormulaireConduiteDistributrice extends FormulaireDefinition {
         this._formCompute = new FormComputeFixedVar(this, this._formResult);
     }
 
-    protected get defaultProperties(): {} {
-        return { "calcType": CalculatorType.ConduiteDistributrice, "nodeType": ComputeNodeType.None };
-    }
-
     protected initParse() {
         this._formParamCalc.initParse();
     }
diff --git a/src/app/formulaire/definition/concrete/form-courbe-remous.ts b/src/app/formulaire/definition/concrete/form-courbe-remous.ts
index d67e9bf24054149d46a542a767382dd6d4ede2ab..c4653bbace083e3b72966a065e931accb31f74b2 100644
--- a/src/app/formulaire/definition/concrete/form-courbe-remous.ts
+++ b/src/app/formulaire/definition/concrete/form-courbe-remous.ts
@@ -27,11 +27,8 @@ export class FormulaireCourbeRemous extends FormulaireDefinition {
         this._formCompute = new FormComputeCourbeRemous(this, this._formSection, this._formResult);
     }
 
-    protected get defaultProperties(): {} {
-        return { "calcType": CalculatorType.CourbeRemous, "nodeType": ComputeNodeType.SectionPuissance };
-    }
-
     protected parseOptions(json: {}) {
+        super.parseOptions(json);
         this._formSection.parseOptions(json);
 
         // id du select configurant la méthode de résolution
diff --git a/src/app/formulaire/definition/concrete/form-dever.ts b/src/app/formulaire/definition/concrete/form-dever.ts
new file mode 100644
index 0000000000000000000000000000000000000000..01543d811a6e4bcfe339a30468428352587a45f4
--- /dev/null
+++ b/src/app/formulaire/definition/concrete/form-dever.ts
@@ -0,0 +1,12 @@
+import { FormDefParallelStructures } from "../form-def-parallel-structures";
+import { FormDefParamToCalculate } from "../form-def-paramcalc";
+import { FormComputeParallelStructures } from "../form-compute-parallel-structures";
+import { FormResultFixedVar } from "../form-result-fixedvar";
+import { CalculatorType, ComputeNodeType, StructureType, LoiDebit } from "jalhyd";
+import { FormulaireParallelStructure } from "./form-parallel-structures";
+
+export class FormulaireDever extends FormulaireParallelStructure {
+    constructor() {
+        super();
+    }
+}
diff --git a/src/app/formulaire/definition/concrete/form-lechapt-calmon.ts b/src/app/formulaire/definition/concrete/form-lechapt-calmon.ts
index 96d6fad59683bc4d6cc15cd03e1ce2d7eeac1c0d..04427e3db3008c31e8955cc00ea4364916731526 100644
--- a/src/app/formulaire/definition/concrete/form-lechapt-calmon.ts
+++ b/src/app/formulaire/definition/concrete/form-lechapt-calmon.ts
@@ -25,10 +25,6 @@ export class FormulaireLechaptCalmon extends FormulaireDefinition implements Obs
         this._formCompute = new FormComputeFixedVar(this, this._formResult);
     }
 
-    protected get defaultProperties(): {} {
-        return { "calcType": CalculatorType.LechaptCalmon, "nodeType": ComputeNodeType.None };
-    }
-
     protected initParse() {
         this._formParamCalc.initParse();
     }
diff --git a/src/app/formulaire/definition/concrete/form-parallel-structures.ts b/src/app/formulaire/definition/concrete/form-parallel-structures.ts
index 64b83a279ce560209b0e082d6d5ec8400af48637..dae370e9809092225402365a3afe1ffb32514958 100644
--- a/src/app/formulaire/definition/concrete/form-parallel-structures.ts
+++ b/src/app/formulaire/definition/concrete/form-parallel-structures.ts
@@ -39,19 +39,18 @@ export class FormulaireParallelStructure extends FormulaireDefinition {
         this._formCompute = new FormComputeParallelStructures(this, this._formParallelStruct, this._formResult);
     }
 
-    protected get defaultProperties(): {} {
-        return {
-            "calcType": CalculatorType.ParallelStructure, "nodeType": ComputeNodeType.None,
-            "structureType": StructureType.SeuilRectangulaire, "loiDebit": LoiDebit.Cem88v
-        };
-    }
-
     private createStructNub(templ: FieldsetTemplate): SessionNub {
-        // valeurs par défaut de CalculatorType, ComputeNodeType, StructureType, LoiDebit
-        // !!! attention !!! pour l'instant, il doit y avoir cohérence entre ces valeurs et celles du fichier de conf
+        // !!! 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 = FieldSet.makeDefaultProps(templ.calcTypeFromConfig, templ.defaultNodeTypeFromConfig);
+
+        const params = {};
+        params["calcType"] = templ.calcTypeFromConfig;
+        params["nodeType"] = templ.defaultNodeTypeFromConfig;
+        params["structureType"] = templ.defaultStructTypeFromConfig;
+        params["loiDebit"] = templ.defaultLoiDebitFromConfig;
+
         return this.createSessionNub(params);
     }
 
@@ -96,6 +95,8 @@ export class FormulaireParallelStructure extends FormulaireDefinition {
     }
 
     protected parseOptions(json: {}) {
+        super.parseOptions(json);
+
         // id du select configurant le type d'ouvrage
         this.__ouvrageSelectId = this.getOption(json, "ouvrageSelectId");
     }
diff --git a/src/app/formulaire/definition/concrete/form-passe-bassin-dim.ts b/src/app/formulaire/definition/concrete/form-passe-bassin-dim.ts
index 64a5141cdb1703b8f874265783afcd5b9dfff25c..bb7de04b6cf375f3e3aad38d2e96834e34ead84f 100644
--- a/src/app/formulaire/definition/concrete/form-passe-bassin-dim.ts
+++ b/src/app/formulaire/definition/concrete/form-passe-bassin-dim.ts
@@ -24,10 +24,6 @@ export class FormulairePasseBassinDimensions extends FormulaireDefinition {
         this._formCompute = new FormComputeFixedVar(this, this._formResult);
     }
 
-    protected get defaultProperties(): {} {
-        return { "calcType": CalculatorType.PabDimensions, "nodeType": ComputeNodeType.None };
-    }
-
     protected initParse() {
         this._formParamCalc.initParse();
     }
diff --git a/src/app/formulaire/definition/concrete/form-passe-bassin-puissance.ts b/src/app/formulaire/definition/concrete/form-passe-bassin-puissance.ts
index 31d2a86390c4ffa51a2822bfbabee50653ad66d5..ba57242df8937f4a065fa58c74fc5a9dc46199d3 100644
--- a/src/app/formulaire/definition/concrete/form-passe-bassin-puissance.ts
+++ b/src/app/formulaire/definition/concrete/form-passe-bassin-puissance.ts
@@ -24,10 +24,6 @@ export class FormulairePasseBassinPuissance extends FormulaireDefinition {
         this._formCompute = new FormComputeFixedVar(this, this._formResult);
     }
 
-    protected get defaultProperties(): {} {
-        return { "calcType": CalculatorType.PabPuissance, "nodeType": ComputeNodeType.None };
-    }
-
     protected initParse() {
         this._formParamCalc.initParse();
     }
diff --git a/src/app/formulaire/definition/concrete/form-regime-uniforme.ts b/src/app/formulaire/definition/concrete/form-regime-uniforme.ts
index 50e7aeff7b5e5cc3f8f0eca81db18a7c88969f78..db3fd0e698109c5bdfe1fb55a1ef8e936ad96818 100644
--- a/src/app/formulaire/definition/concrete/form-regime-uniforme.ts
+++ b/src/app/formulaire/definition/concrete/form-regime-uniforme.ts
@@ -28,15 +28,16 @@ export class FormulaireRegimeUniforme extends FormulaireDefinition implements Ob
         this._formCompute = new FormComputeFixedVar(this, this._formResult);
     }
 
-    protected get defaultProperties(): {} {
-        return { "calcType": CalculatorType.RegimeUniforme, "nodeType": ComputeNodeType.SectionCercle };
-    }
+    // protected get defaultProperties(): {} {
+    //     return { "calcType": CalculatorType.RegimeUniforme, "nodeType": ComputeNodeType.SectionCercle };
+    // }
 
     protected initParse() {
         this._formParamCalc.initParse();
     }
 
     protected parseOptions(json: {}) {
+        super.parseOptions(json);
         this._formSection.parseOptions(json);
     }
 
diff --git a/src/app/formulaire/definition/concrete/form-section-parametree.ts b/src/app/formulaire/definition/concrete/form-section-parametree.ts
index 1f14c0f662e254bc5e3d81823e5e943f4362827d..6f3fa0391c21bfedfee2f5c1de7fe755abe4bd8a 100644
--- a/src/app/formulaire/definition/concrete/form-section-parametree.ts
+++ b/src/app/formulaire/definition/concrete/form-section-parametree.ts
@@ -29,11 +29,8 @@ export class FormulaireSectionParametree extends FormulaireDefinition {
         this._formCompute = new FormComputeSectionParametree(this, this._formSection, this._formSectionResult);
     }
 
-    protected get defaultProperties(): {} {
-        return { "calcType": CalculatorType.SectionParametree, "nodeType": ComputeNodeType.SectionCercle };
-    }
-
     protected parseOptions(json: {}) {
+        super.parseOptions(json);
         this._formSection.parseOptions(json);
     }
 
diff --git a/src/app/formulaire/definition/form-def-parallel-structures.ts b/src/app/formulaire/definition/form-def-parallel-structures.ts
index e26992be7e00ce71f7eff03a1de966de31d42cfd..a4856994d88a189b00a3d07e67a66a25113147b6 100644
--- a/src/app/formulaire/definition/form-def-parallel-structures.ts
+++ b/src/app/formulaire/definition/form-def-parallel-structures.ts
@@ -6,56 +6,4 @@ import { FieldSet } from "../fieldset";
  * gestion des formulaires "ouvrages parallèles"
  */
 export class FormDefParallelStructures {
-    /**
-     * dictionnaire des types d'ouvrages indexés par les valeurs de liste déroulante
-     * la clé est la chaîne utilisée dans le fichier de configuration de la calculette pour les valeurs de la liste déroulante
-     */
-    private static tsMap = {
-        "vanne_rect": StructureType.VanneRectangulaire,
-        "seuil_rect": StructureType.SeuilRectangulaire
-    }
-
-    /**
-     * dictionnaire des LoiDebit indexés par les valeurs de liste déroulante
-     * la clé est la chaîne utilisée dans le fichier de configuration de la calculette pour les valeurs de la liste déroulante
-     */
-    private static ldMap = {
-        "cem88d": LoiDebit.Cem88d,
-        "cem88v": LoiDebit.Cem88d,
-        "cunge80": LoiDebit.Cunge80,
-        "seuildenoye": LoiDebit.WeirFree,
-        "vannenoye": LoiDebit.OrificeSubmerged,
-        "vannedenoye": LoiDebit.OrificeFree,
-        "kivi": LoiDebit.KIVI
-    }
-
-    /**
-     * @return type d'ouvrage courant du FieldSet donné
-     */
-    public getStructureType(fs: FieldSet): StructureType {
-        let structType: string = fs.getSelectedValue("select_ouvrage");
-        if (structType == undefined)
-            throw new Error(`FormDefParallelStructures.getStructureType() : aucun ouvrage trouvé dans le FieldSet`);
-
-        const res = FormDefParallelStructures.tsMap[structType];
-        if (res == undefined)
-            throw new Error(`FormDefParallelStructures.getStructureType() : type d'ouvrage ${StructureType[structType]} non pris en charge`);
-        return res;
-    }
-
-    /**
-     * @return loi de débit courante du FieldSet donné
-     */
-    public getLoiDebit(fs: FieldSet): LoiDebit {
-        let loiDebit: string = fs.getSelectedValue("select_loidebit1");
-        if (loiDebit == undefined)
-            loiDebit = fs.getSelectedValue("select_loidebit2");
-        if (loiDebit == undefined)
-            throw new Error(`FormDefParallelStructures.getStructureType() : aucune loi de débit trouvée dans le FieldSet`);
-
-        const res = FormDefParallelStructures.ldMap[loiDebit];
-        if (res == undefined)
-            throw new Error(`FormDefParallelStructures.getStructureType() : loi de débit ${LoiDebit[loiDebit]} non prise en charge`);
-        return res;
-    }
 }
diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts
index 1a43403007d74910984da7d1ad9fdb08868d2e56..c9d0506967eeb3b97296704e826bfa8125904d6b 100644
--- a/src/app/formulaire/definition/form-definition.ts
+++ b/src/app/formulaire/definition/form-definition.ts
@@ -30,6 +30,11 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
      */
     protected _currentSessionNub: SessionNub;
 
+    /**
+     * propriétés par défaut (lues si _currentSessionNub === undefined )
+     */
+    private _props = {};
+
     /**
      * fichier de configuration
      */
@@ -69,7 +74,9 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
         return this._jsonConfig;
     }
 
-    protected abstract get defaultProperties(): {};
+    public get defaultProperties() {
+        return this._props;
+    }
 
     public initSessionNub(props?: {}) {
         this._currentSessionNub = this.createSessionNub(props === undefined ? this.defaultProperties : props);
@@ -79,6 +86,12 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
         return this._currentSessionNub;
     }
 
+    public set currentSessionNub(n: SessionNub) {
+        if (this._props["calcType"] !== n.properties.getPropValue("calcType"))
+            throw new Error(`Nub ${n.properties["calcType"]} incompatible avec le formulaire ${this._calculatorName} (${this._props["calcType"]})`);
+        this._currentSessionNub = n;
+    }
+
     private findNub(params: Props | {}) {
         return this._paramService.findSessionNub(params);
     }
@@ -99,7 +112,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
     }
 
     protected replaceCurrentSessionNub(params: Props) {
-        this._currentSessionNub = this._paramService.replaceSessionNub(this._currentSessionNub, params);
+        this.currentSessionNub = this._paramService.replaceSessionNub(this._currentSessionNub, params);
     }
 
     protected replaceSessionNub(sn: SessionNub, params: Props): SessionNub {
@@ -128,6 +141,8 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
     }
 
     protected parseOptions(json: {}) {
+        const dnt = json["defaultNodeType"];
+        this._props["nodeType"] = dnt === undefined ? ComputeNodeType.None : ComputeNodeType[dnt];
     }
 
     protected completeParse(json: {}) {
@@ -196,7 +211,10 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
         }
     }
 
-    public parseConfig(json: {}) {
+    /**
+     * 1ère passe d'analyse de la configuration
+     */
+    public preparseConfig(json: {}) {
         this._jsonConfig = json;
 
         this.initParse();
@@ -213,13 +231,21 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
                 break;
             }
         }
+    }
+
+    /**
+     * 2ème passe d'analyse de la configuration
+     */
+    public parseConfig(json: {}) {
+        if (json !== undefined)
+            this._jsonConfig = json;
 
         // analyse des éléments du formulaire
 
         const templates: any[] = [];
 
-        for (let conf_index in json) {
-            const conf = json[conf_index];
+        for (let conf_index in this._jsonConfig) {
+            const conf = this._jsonConfig[conf_index];
             const type: string = conf["type"];
 
             switch (type) {
@@ -244,7 +270,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
             }
         }
 
-        this.completeParse(json);
+        this.completeParse(this._jsonConfig);
 
         // console.log("-----");
 
@@ -257,7 +283,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
         // logObject(this._fieldSets, "fieldsets");
         // logObject(this._dependencies, "dependences");
 
-        this.parseDependencies(json);
+        this.parseDependencies(this._jsonConfig);
     }
 
     public hasParameter(symbol: string): boolean {
diff --git a/src/app/formulaire/fieldset-template.ts b/src/app/formulaire/fieldset-template.ts
index ce3fcf353158e5e5afb82accafa73bfeda2b1d08..8ba2da3baa568038c0bc654eb78ff2e84c8eb318 100644
--- a/src/app/formulaire/fieldset-template.ts
+++ b/src/app/formulaire/fieldset-template.ts
@@ -1,5 +1,5 @@
 import { FieldSet } from "./fieldset";
-import { CalculatorType, ComputeNodeType } from "jalhyd";
+import { CalculatorType, ComputeNodeType, StructureType, LoiDebit } from "jalhyd";
 import { FormulaireDefinition } from "./definition/form-definition";
 import { FieldsetContainer } from "./fieldset-container";
 
@@ -15,27 +15,23 @@ export class FieldsetTemplate {
     }
 
     public get calcTypeFromConfig(): CalculatorType {
-        for (const k in this._jsonConfig) {
-            if (k === "calcType") {
-                const ct: string = this._jsonConfig[k];
-                var calcType: CalculatorType = CalculatorType[ct];
-                break;
-            }
-        }
-
-        return calcType;
+        const ct: string = this._jsonConfig["calcType"];
+        return CalculatorType[ct];
     }
 
     public get defaultNodeTypeFromConfig(): ComputeNodeType {
-        for (const k in this._jsonConfig) {
-            if (k === "defaultNodeType") {
-                const nt: string = this._jsonConfig[k];
-                var nodeType: ComputeNodeType = ComputeNodeType[nt];
-                break;
-            }
-        }
-
-        return nodeType;
+        const nt: string = this._jsonConfig["defaultNodeType"];
+        return ComputeNodeType[nt];
+    }
+
+    public get defaultStructTypeFromConfig(): StructureType {
+        const st: string = this._jsonConfig["defaultStructType"];
+        return StructureType[st];
+    }
+
+    public get defaultLoiDebitFromConfig(): LoiDebit {
+        const ld: string = this._jsonConfig["defaultLoiDebit"];
+        return LoiDebit[ld];
     }
 
     /**
diff --git a/src/app/formulaire/fieldset.ts b/src/app/formulaire/fieldset.ts
index fefcb06c40b79cb44a24b99752aab5f3e4cf97a7..af553da83b6dd95dc4862dada03a2ecbeffe0d84 100644
--- a/src/app/formulaire/fieldset.ts
+++ b/src/app/formulaire/fieldset.ts
@@ -121,39 +121,6 @@ export class FieldSet extends FormulaireElement implements Observer {
         return this._props.setPropValue(key, val, this);
     }
 
-    /**
-     * valeurs par défaut pour StructureType, LoiDebit en fonction d'un ComputeNodeType
-     */
-    private static defaultProps(nodeType: ComputeNodeType): [StructureType, LoiDebit] {
-        let structType: StructureType;
-        let loiDebit: LoiDebit
-        switch (nodeType) {
-            case ComputeNodeType.StructureRectangle:
-                structType = StructureType.VanneRectangulaire;
-                loiDebit = LoiDebit.Cem88v;
-                break;
-        }
-        return [structType, loiDebit];
-    }
-
-    /**
-     * crée un objet Props servant de filtre pour sélectionner un Nub
-     * @param calcType
-     * @param nodeType 
-     */
-    public static makeDefaultProps(calcType: CalculatorType, nodeType: ComputeNodeType): Props {
-        const res: Props = new Props();
-
-        res.setPropValue("calcType", calcType);
-        res.setPropValue("nodeType", nodeType);
-
-        const p: [StructureType, LoiDebit] = FieldSet.defaultProps(nodeType);
-        res.setPropValue("structureType", p[0]);
-        res.setPropValue("loiDebit", p[1]);
-
-        return res;
-    }
-
     private getNubParamFromSymbol(symbol: string): ParamDefinition {
         return this._sessionNub.nub.getParameter(symbol);
     }
diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts
index 5984c3f9d0e22f1188115f91d312d87721ae8e9b..c51afc628ef2d2cffca040d64eca6d3e7ef6db65 100644
--- a/src/app/services/formulaire/formulaire.service.ts
+++ b/src/app/services/formulaire/formulaire.service.ts
@@ -3,7 +3,7 @@ import { Response } from "@angular/http";
 import { Observable as rxObservable } from "rxjs/Observable";
 import "rxjs/add/operator/toPromise";
 import { decode } from "he";
-import { saveAs } from "file-saver"
+import { saveAs } from "file-saver";
 
 import { CalculatorType, EnumEx, Observable } from "jalhyd";
 
@@ -24,6 +24,7 @@ import { FormulaireRegimeUniforme } from "../../formulaire/definition/concrete/f
 import { FormulairePasseBassinDimensions } from "../../formulaire/definition/concrete/form-passe-bassin-dim";
 import { FormulairePasseBassinPuissance } from "../../formulaire/definition/concrete/form-passe-bassin-puissance";
 import { FormulaireParallelStructure } from "../../formulaire/definition/concrete/form-parallel-structures";
+import { FormulaireDever } from "../../formulaire/definition/concrete/form-dever";
 
 @Injectable()
 export class FormulaireService extends Observable {
@@ -108,43 +109,13 @@ export class FormulaireService extends Observable {
     }
 
     public getLocalisedTitleFromCalculatorType(type: CalculatorType) {
-        switch (type) {
-            case CalculatorType.ConduiteDistributrice:
-                return this._intlService.localizeText("INFO_CONDDISTRI_TITRE");
-
-            case CalculatorType.LechaptCalmon:
-                return this._intlService.localizeText("INFO_LECHAPT_TITRE");
-
-            case CalculatorType.RegimeUniforme:
-                return this._intlService.localizeText("INFO_REGUNI_TITRE");
-
-            case CalculatorType.SectionParametree:
-                return this._intlService.localizeText("INFO_SECTPARAM_TITRE");
-
-            case CalculatorType.CourbeRemous:
-                return this._intlService.localizeText("INFO_REMOUS_TITRE")
-
-            case CalculatorType.PabDimensions:
-                return this._intlService.localizeText("INFO_PABDIM_TITRE")
-
-            case CalculatorType.PabPuissance:
-                return this._intlService.localizeText("INFO_PABPUISS_TITRE")
-
-            case CalculatorType.ParallelStructure:
-                return this._intlService.localizeText("INFO_OUVRAGEPARAL_TITRE")
-
-            default:
-                return "Invalid calculator type " + type;
-        }
+        const sCalculator: string = CalculatorType[type].toUpperCase();
+        return this._intlService.localizeText(`INFO_${sCalculator}_TITRE`);
     }
 
-    private loadConfig(form: FormulaireDefinition, ct: CalculatorType): Promise<Response> {
-        let processData = function (s: string) {
-            form.parseConfig(JSON.parse(s));
-        }
-
+    public loadConfig(ct: CalculatorType): Promise<any> {
         let f: string = this.getConfigPathPrefix(ct) + "config.json"
-        return this._httpService.httpGetRequest(undefined, undefined, undefined, f, processData);
+        return this._httpService.httpGetRequest2(undefined, undefined, undefined, f);
     }
 
     private newFormulaire(ct: CalculatorType, jsonState?: {}): FormulaireDefinition {
@@ -182,16 +153,15 @@ export class FormulaireService extends Observable {
                 f = new FormulaireParallelStructure();
                 break;
 
+            case CalculatorType.Dever:
+                f = new FormulaireDever();
+                break;
+
             default:
                 throw new Error(`FormulaireService.createFormulaire() : type de calculette ${ct} non pris en charge`)
         }
 
-        if (jsonState !== undefined) {
-            const props = jsonState["props"];
-            f.initSessionNub(props);
-        }
-        else
-            f.initSessionNub();
+        f.defaultProperties["calcType"] = ct;
 
         return f;
     }
@@ -199,18 +169,29 @@ export class FormulaireService extends Observable {
     /**
      * crée un formulaire d'un type donné
      * @param ct type de formulaire
-     * @param jsonState 
+     * @param jsonState
      */
     public createFormulaire(ct: CalculatorType, jsonState?: {}): Promise<FormulaireDefinition> {
-        const f: FormulaireDefinition = this.newFormulaire(ct, jsonState);
-
-        if (jsonState === undefined)
-            f.calculatorName = decode(this.getLocalisedTitleFromCalculatorType(ct) + " (" + f.uid + ")");
+        const f: FormulaireDefinition = this.newFormulaire(ct);
         this._formulaires.push(f);
-        let prom: Promise<Response> = this.loadConfig(f, ct);
-        return prom.then(_ => {
-            if (jsonState !== undefined)
+
+        let prom: Promise<any> = this.loadConfig(ct);
+        return prom.then(s => {
+            f.preparseConfig(JSON.parse(s));
+            return f;
+        }).then(f => {
+            if (jsonState === undefined) {
+                f.calculatorName = decode(this.getLocalisedTitleFromCalculatorType(ct) + " (" + f.uid + ")");
+                f.initSessionNub();
+            }
+            else {
                 f.deserialiseJSON(jsonState);
+                const props = jsonState["props"];
+                f.initSessionNub(props);
+            }
+            return f;
+        }).then(f => {
+            f.parseConfig(undefined);
             return f;
         }).then(f => {
             this.loadUpdateFormulaireLocalisation(f);
@@ -299,6 +280,9 @@ export class FormulaireService extends Observable {
             case CalculatorType.ParallelStructure:
                 return "app/calculators/parallel-structures/parallel-structures.";
 
+            case CalculatorType.Dever:
+                return "app/calculators/dever/dever.";
+
             default:
                 throw "FormulaireService.getConfigPathPrefix() : valeur de CalculatorType " + ct + " non implémentée"
         }
diff --git a/src/app/services/http/http.service.ts b/src/app/services/http/http.service.ts
index 74c4dae34078347f8f320cabb67f5563dd3dd9c4..d99733819768f37ca84de58164ca27253acf517e 100644
--- a/src/app/services/http/http.service.ts
+++ b/src/app/services/http/http.service.ts
@@ -18,11 +18,17 @@ export class HttpService {
         return s1 + s2;
     }
 
+    /**
+     * construit, lance une requête GET et applique un callback sur le résultat
+     * @param processDataCallback callback en cas de succès
+     * @param errorCallback callback en cas d'erreur
+     * @see httpGetRequestResponse
+     */
     public httpGetRequest(protocol: string, host: string, port: number, path: string,
         processDataCallback: (s: string) => void,
         errorCallback?: (err: any) => void,
         headers?: StringMap): Promise<Response> {
-        let resp: Observable<Response> = this.httpGetRequestResponse(protocol, host, port, path);
+        let resp: Observable<Response> = this.httpGetRequestResponse(protocol, host, port, path, headers);
 
         resp.map(res => res.text())
             .subscribe(
@@ -34,6 +40,22 @@ export class HttpService {
         return resp.toPromise();
     }
 
+    /**
+     * construit et lance une requête GET
+     */
+    public httpGetRequest2(protocol: string, host: string, port: number, path: string): Promise<any> {
+        let resp: Observable<Response> = this.httpGetRequestResponse(protocol, host, port, path);
+        return resp.map(res => res.text()).toPromise();
+    }
+
+    /**
+     * construit et lance une requête GET
+     * @param protocol type de protocole (http, ...)
+     * @param host nom d'hôte distant
+     * @param port numéro de port distant
+     * @param path chemin de la ressource
+     * @param headers entêtes de la requête
+     */
     public httpGetRequestResponse(protocol: string, host: string, port: number, path: string, headers?: StringMap): Observable<Response> {
         let url: string;
         if (protocol != undefined)
diff --git a/src/app/services/internationalisation/internationalisation.service.ts b/src/app/services/internationalisation/internationalisation.service.ts
index d5e3486b82e5b5517b97ff7e00e6f4c738895b36..00397c93119559fa0db87f5cb47b6c6a52cf117c 100644
--- a/src/app/services/internationalisation/internationalisation.service.ts
+++ b/src/app/services/internationalisation/internationalisation.service.ts
@@ -71,7 +71,7 @@ export class InternationalisationService extends Observable {
 
     private getLanguageFromCode(lc: LanguageCode) {
         for (let l of this._languages) {
-            if (l.code == lc)
+            if (l.code === lc)
                 return l;
         }
         throw new Message(MessageCode.ERROR_LANG_UNSUPPORTED);
@@ -88,7 +88,7 @@ export class InternationalisationService extends Observable {
     }
 
     public setLocale(lng: string | LanguageCode) {
-        if (this._currLang != undefined)
+        if (this._currLang !== undefined)
             var oldLang: LanguageCode = this._currLang.code;
 
         if (typeof lng === "string") {
@@ -162,8 +162,12 @@ export class InternationalisationService extends Observable {
      * @param code id du texte
      */
     public localizeText(code: string) {
-        if (this._Messages == undefined)
+        if (this._Messages === undefined) {
             return "<messages not loaded>";
+        }
+        if (this._Messages[code] === undefined) {
+            return `<message not exists: ${code}>`;
+        }
         return this._Messages[code];
     }
 
@@ -176,87 +180,37 @@ export class InternationalisationService extends Observable {
     }
 
     /**
-     * traduit un libellé qui peut être un code
+     * Traduit un libellé qui peut être un code
      */
-    public translateLabel(o: any) {
-        let res;
-        if (typeof o === "string") {
-            switch (o) {
-                case "flu":
-                    res = this.localizeText("INFO_REMOUSRESULTS_LIGNEFLUVIALE");
-                    break;
-
-                case "tor":
-                    res = this.localizeText("INFO_REMOUSRESULTS_LIGNETORRENTIELLE");
-                    break;
-
-                default:
-                    const match = this.parseLabel(o);
-                    if (match) {
-                        if (match[1] === "ouvrage")
-                            res = this.localizeText("INFO_OUVRAGE") + " n°" + (+match[2] + 1);
-
-                        const p = match[3];
-                        switch (p) {
-                            case "Q":
-                                res += " : " + this.localizeText("INFO_GRANDEUR_" + p);
-                                break;
-
-                            case "Q_Mode":
-                                res += " : " + this.localizeText("INFO_TYPE_ECOULEMENT");
-                                break;
-
-                            case "Q_Regime":
-                                res += " : " + this.localizeText("INFO_REGIME");
-                                break;
-                        }
-                    }
-                    else
-                        res = o;
-                    break;
-            }
+    public translateLabel(s: string) {
+        const key = "INFO_EXTRARES_LIB_";
+        const match = this.parseLabel(s);
+        if (match) {
+            // Code du type "Ouvrage[n].XXX"
+            // Les libellés correspondants sont INFO OUVRAGE et INFO_EXTRARES_LIB_OUVRAGE_XXX
+            return this.localizeText(`INFO_${match[1].toUpperCase()}`) + " n°" + (+match[2] + 1) + ": " +
+                this.localizeText(`${key}${match[1].toUpperCase()}_${match[3].toUpperCase()}`);
+        } else {
+            // Autres codes INFO_EXTRARES_LIB_XXX
+            return this.localizeText(`${key}${s.toUpperCase()}`);
         }
-        return res;
-    }
+     }
 
     /**
      * met en forme ou traduit un résultat en fonction du libellé qui l'accompagne
+     * @todo Il manque un formalisme clair permettant de différencier les valeurs numériques des ENUM
      */
     public formatResult(label: string, value: number): string {
         const match = this.parseLabel(label);
-        if (match)
-            switch (match[1]) {
-                case "ouvrage":
-                    switch (match[3]) {
-                        case "Q_Mode":
-                            switch (value) {
-                                case 0:
-                                case 1:
-                                case 2:
-                                    const key = `INFO_LIB_ENUM_RES_STRUCTURE_MODE_${value}`;
-                                    return this.localizeText(key);
-
-                                default:
-                                    throw new Error(`InternationalisationService.formatResult : valeur ${value} incorrecte pour STRUCTURE_MODE`);
-                            }
-
-                        case "Q_Regime":
-                            switch (value) {
-                                case 0:
-                                case 1:
-                                case 2:
-                                    const key = `INFO_LIB_ENUM_RES_STRUCTURE_REGIME_${value}`;
-                                    return this.localizeText(key);
-
-                                default:
-                                    throw new Error(`InternationalisationService.formatResult : valeur ${value} incorrecte pour STRUCTURE_REGIME`);
-                            }
-
-                    }
+        if (match) {
+            if (match[3] !== "Q") { // Le débit est une valeur numérique, tous les autres sont des ENUM ???
+                // Label du type ouvrage[n].XXX => message INFO_EXTRARES_ENUM_OUVRAGE_XXX_value
+                return this.localizeText(`INFO_EXTRARES_ENUM_${match[1].toUpperCase()}_${match[3].toUpperCase()}_${value}`);
             }
-
+        }
         const appSetupService = ServiceFactory.instance.applicationSetupService;
         const nDigits = appSetupService.displayDigits;
         return value.toFixed(nDigits);
     }
+
 }
diff --git a/src/index.html b/src/index.html
index afcc5e9ed34cda859b959477bafb9e8fa83afd89..e5c06f360f85c6444cafb6cde75a97e38907f3ba 100644
--- a/src/index.html
+++ b/src/index.html
@@ -47,7 +47,7 @@
   </script>
 
   <!-- récupération du code + configuration par défaut -->
-  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS_CHTML"></script>
+  <script type="text/javascript" src="assets/mathjax/MathJax.js?config=TeX-AMS_CHTML"></script>
   <!-- /MathJax-->
 </head>
 
diff --git a/src/locale/error_messages.fr.json b/src/locale/error_messages.fr.json
index 69c3b8f87818a462c62e51496a1492691a69e19f..270d66e42b75aa88a66a5195b4ee6f6c357b490f 100644
--- a/src/locale/error_messages.fr.json
+++ b/src/locale/error_messages.fr.json
@@ -45,10 +45,10 @@
     "INFO_CALCULATOR_PARAMFIXES": "Paramètres fixés",
     "INFO_CALCULATOR_VALEURS": "Valeurs",
     "INFO_CALCULATOR_CALCULER": "Calculer",
-    "INFO_CONDDISTRI_TITRE": "Conduite distributrice",
-    "INFO_LECHAPT_TITRE": "Lechapt-Calmon",
-    "INFO_REGUNI_TITRE": "Régime uniforme",
-    "INFO_SECTPARAM_TITRE": "Section paramétrée",
+    "INFO_CONDUITEDISTRIBUTRICE_TITRE": "Conduite distributrice",
+    "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)",
@@ -67,10 +67,8 @@
     "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_REMOUS_TITRE": "Courbes de remous",
+    "INFO_COURBEREMOUS_TITRE": "Courbes de remous",
     "INFO_REMOUSRESULTS_TITREJOURNAL": "Journal de calcul",
-    "INFO_REMOUSRESULTS_LIGNEFLUVIALE": "Ligne d'eau fluviale",
-    "INFO_REMOUSRESULTS_LIGNETORRENTIELLE": "Ligne d'eau torrentielle",
     "INFO_REMOUSRESULTS_ABSCISSE": "Abscisse (m)",
     "INFO_REMOUSRESULTS_TIRANT": "Tirant d'eau (m)",
     "INFO_REMOUSRESULTS_FOND": "Fond",
@@ -86,19 +84,31 @@
     "INFO_CLOSE_DIALOGUE_TEXT": "Attention&nbsp! Les paramètres et résultats de la calculette seront perdus. Vraiment fermer&nbsp;?",
     "INFO_OPTION_YES": "Oui",
     "INFO_OPTION_NO": "Non",
-    "INFO_PABDIM_TITRE": "Passe à bassin&nbsp;: dimensions",
-    "INFO_PABPUISS_TITRE": "Passe à bassin&nbsp;: puissance dissipée",
-    "INFO_OUVRAGEPARAL_TITRE": "Ouvrages en parallèle",
+    "INFO_PABDIMENSIONS_TITRE": "Passe à bassin&nbsp;: dimensions",
+    "INFO_PABPUISSANCE_TITRE": "Passe à bassin&nbsp;: puissance dissipée",
+    "INFO_PARALLELSTRUCTURE_TITRE": "Ouvrages en parallèle",
+    "INFO_DEVER_TITRE": "Outil dever",
     "INFO_OUVRAGE": "Ouvrage",
-    "INFO_TYPE_ECOULEMENT": "Type d'écoulement",
-    "INFO_REGIME": "Régime",
+
+    "INFO_EXTRARES_LIB_FLU": "Ligne d'eau fluviale",
+    "INFO_EXTRARES_LIB_TOR": "Ligne d'eau torrentielle",
+    "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_ENUM_OUVRAGE_Q_MODE_0": "Surface libre",
+    "INFO_EXTRARES_ENUM_OUVRAGE_Q_MODE_1": "En charge",
+    "INFO_EXTRARES_ENUM_OUVRAGE_Q_MODE_2": "Débit nul",
+    "INFO_EXTRARES_ENUM_OUVRAGE_Q_REGIME_0": "Dénoyé",
+    "INFO_EXTRARES_ENUM_OUVRAGE_Q_REGIME_1": "Partiellement noyé",
+    "INFO_EXTRARES_ENUM_OUVRAGE_Q_REGIME_2": "Noyé",
+    "INFO_EXTRARES_ENUM_OUVRAGE_Q_REGIME_3": "Débit nul",
+
     "WARNING_STRUCTUREKIVI_PELLE_TROP_FAIBLE": "La pelle du seuil doit mesurer au moins 0,1 m. Le coefficient béta est forcé à 0",
-    "WARNING_STRUCTUREKIVI_HP_TROP_ELEVE": "h/p ne doit pas être supérieur à 2,5. h/p est forcé à 2,5",
-    "INFO_LIB_ENUM_RES_STRUCTURE_MODE_0": "Surface libre",
-    "INFO_LIB_ENUM_RES_STRUCTURE_MODE_1": "En charge",
-    "INFO_LIB_ENUM_RES_STRUCTURE_MODE_2": "Débit nul",
-    "INFO_LIB_ENUM_RES_STRUCTURE_REGIME_0": "Dénoyé",
-    "INFO_LIB_ENUM_RES_STRUCTURE_REGIME_1": "Partiellement noyé",
-    "INFO_LIB_ENUM_RES_STRUCTURE_REGIME_2": "Noyé",
-    "INFO_LIB_ENUM_RES_STRUCTURE_REGIME_3": "Débit nul"
+    "WARNING_STRUCTUREKIVI_HP_TROP_ELEVE": "h/p ne doit pas être supérieur à 2,5. h/p est forcé à 2,5"
+
 }
\ No newline at end of file
diff --git a/tslint.json b/tslint.json
index 1c7b38bf2ea0d77bc88ca91fd6e572ceb698d38c..905005e4f2b7688d560a69878208c73c86b93e9a 100644
--- a/tslint.json
+++ b/tslint.json
@@ -83,7 +83,7 @@
     "prefer-const": true,
     "quotemark": [
       true,
-      "single"
+      "double"
     ],
     "radix": true,
     "semicolon": [