# ngHyd : Angular Component Library For Hydraulics using JaLHyd library

## All the things to know for developping the library

The library needs nodeJS installed.

The documentation of Cassiopee needs to install MkDocs and some extensions:

```sh
sudo apt install python3-pip python3-setuptools
python3 -m pip install mkdocs python-markdown-math mkdocs-material
```

### Install the necessary packages of the library

Clone or update the JalHyd project and in the JalHyd folder, run :

`npm run package`

Then, back to the ngHyd project folder, run :

`npm install`


### To compile the code and get a deployable Web app

`npm run build`


### To run compilation in watch mode as well as application execution in a browser

`npm start`


### To run end-to-end unit tests

`npm run e2e`


### To quickly end-to-end unit tests while watch mode is running

`npm run e2equick`


### To quickly try electron wrapping when code is already compiled

`npm run electron`


### To build a complete release for Linux (has to be run on Linux platform)

`npm run release-linux`

Find the .deb package in `/release`.

Running `dpkg -i cassiopee_*.deb` will install Cassiopée in `/opt/Cassiopee`

### To build a complete release for Windows (has to be run on Windows platform)

#### install dependencies
 * python for windows https://www.python.org/downloads/windows/
   * tick "add to path" option when installing
 * mkdocs: `pip install mkdocs`
 * mkdocs-material: `pip install mkdocs-material`
 * python-markdown-math: `pip install https://github.com/mitya57/python-markdown-math/archive/master.zip`
 * pygments: `pip install pygments`


#### build .exe installer

`npm run release-windows`

Find the generated installer in `/release`.

Running the generated installer will install Cassiopée in `C:\Users\YourUser\AppData\local\Programs\cassiopee`

### To build a complete release for Android


#### install dependencies
 * java (system wide) : for ex. `apt install oracle-java8-jdk`
 * gradle (system wide) : `apt install gradle`

#### install Android Studio and SDKs
 
 Download 
 Android Studio here and install it : https://developer.android.com/studio

 Run Android Studio, click "configure > SDK manager". Install at least one SDK, for ex. 7.0 Nougat.

#### build .apk package

`npm run release-android`.

Find the generated package in `/release`.


### To generate compodoc

`npm run compodoc`


### To flag suspicious language usage

`npm run lint`


### UML visualisation

The tsviz package can be used for drawing class diagram of the current code.

To install tsviz: `npm install -g tsviz`

There's currently a bug on debian like distribution due to a wrong declaration of graphviz path in the code: https://github.com/joaompneves/tsviz/issues/5
To work around, you can create a link to the good path: `sudo ln -s /usr/bin/dot /usr/local/bin/dot` 

To draw the diagram: `npm run viz`

# Caveats

## Deployment

Custom Material SVG Icons will only show up when the application is deployed on the domain root (no subfolders), see [this feature request](https://github.com/angular/material2/issues/4263)


# Procédure d'ajout d'un module de calcul

## 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(this, ComputeNodeType.LechaptCalmon, 'L', "m", ParamDomainValue.POS, rL);
					this._W = new ParamDefinition(this, ComputeNodeType.LechaptCalmon, 'W', "m", ParamDomainValue.POS, rW);
					this._A = new ParamDefinition(this, ComputeNodeType.LechaptCalmon, 'A', undefined, 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ètre à calculer par défaut
					this._defaultCalculatedParam = prms.A;
					this.resetDefaultCalculatedParam();
				}

				/**
				* 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, this);
				}
			}


* Créer les tests unitaires correspondants


* Ajouter une valeur à l'enum _CalculatorType_ pour identifier le type de module de calcul (par ex _MaCalculette_).


* Compléter la méthode _Session.createNub()_.


## ngHyd

1. Créer les fichiers de configuration du module de calcul
	- 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_ (1er paramètre du constructeur)

		Ne pas oublier de spécifier :
		- éventuellement le type de noeud par défaut du module de calcul 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 du module de calcul.

		- éventuellement le type de noeud de paramètres particuliers (objets comportant _"type":"input"_) avec le champ _"nodeType": "MaCalculetteBleue"_ (par défaut, "_ComputeNodeType.None_")

		- éventuellement l'URL de l'aide pour n'importe quel élément de l'interface graphique :
		  - pour un champ de saisie numérique : `{... "type": "input", "id": "ID", "help": "aide.html", ...}` (remplacer la forme courte `"ID"` si nécessaire)
		  - pour n'importe quelle entrée d'un champ de type "select" : `{... "type": "select", "help": "aide.html", ...}`
		  - pour des entrées spécifiques d'un champ de type "select" : `{... "type": "select", "help": { "IdDeLOption": "aide.html", ...}, ...}` (se référer au fichier de traduction du module pour la liste des ID des options, par exemple "SeuilTriangulaireTrunc_TriangularTruncWeirFree")
		  - pour un _fieldset_: `{... "type": "fieldset",
        "help": "aide.html", ...}`
		  - pour tous les _fieldset_ d'un _fieldset_template_: `{... "type": "fieldset_template",
        "help": "aide.html", ...}`
		  - pour l'entête d'un _template_container_: `{... "type": "template_container",
        "help": "aide.html", ...}`

		 - éventuellement l'URL de l'aide pour un résultat en particulier, dans le bloc d'options de la configuration :
		   - ```json
		   		{
						"type": "options",
						…
						"resultsHelp": {
							"HG": "devalaison/grille.html#hauteur-de-grille"
						}

	- dans _src/app/calculators/ma-calculette_ :

		Créer les fichiers d'internationalisation (_ma-calculette.&lt;langue&gt;.json_). Il doivent reprendre tous les ids utilisés dans le fichier de configuration et fournir leur traduction.

2. **Si nécessaire** créer la classe du formulaire dans _src/app/formulaire/definition/concrete_ . Une classe de base gérant la majorité des cas est déjà disponible, en général cette étape n'est pas nécessaire 

	- Par ex : _FormulaireMaCalculette_ dans _src/app/formulaire/definition/concrete/form-ma-calculette.ts_

		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.

3. _src/locale/messages.&lt;langue&gt;.json_ :
	Ajouter deux champs pour le titre et le titre court du module de calcul. Par exemple :
		 _"INFO_MACALC_TITRE": "Ma calculette"_,
		 _"INFO_MACALC_TITRE_COURT": "Ma calc."_

4. Dans le constructeur de _FormulaireService_, ajouter une entrée dans `this.calculatorPaths` pour fournir le préfixe des fichiers de configuration/internationalisation.

5. **Si une nouvelle classe a été créée à l'étape 2**, dans la méthode _FormulaireService.newFormulaire()_, compléter le _switch_ pour fournir la classe à instancier.

6. Dans `config.json`, ajouter si nécessaire le numéro de CalculatorType à un ou plusieurs thèmes afin de classer le module sur la page de liste; dans le cas contraire le nouveau module apparaîtra dans une section "Autres"

 # Create PDF from documentation

 ```sh
 sudo apt-get install texlive texlive-lang-french texlive-latex-extra pandoc
 ```
 
# Release policy

Use [semantic versioning](https://semver.org/).

Before releasing a new stable version, one should complete the following files
 - CHANGELOG.md
 - package.json (update `version`)
 - jalhyd_branch (be sure that it contains "master" or is empty)

Every stable version should be tagged with both
 - the `stable` tag
 - a version tag of the form `X.Y.Z` (semver)

The `stable` tag should be set **before** the version tag, so that `git describe` returns `X.Y.Z` (latest tag).

Here are the steps to follow for an example **4.5.0** version
 - git tag -fa stable
 - git tag -fa 4.5.0
 - git push --tags --force