From d070367e1c38cc4b9a11dce97d3894d509a6647e Mon Sep 17 00:00:00 2001
From: "francois.grand" <francois.grand@irstea.fr>
Date: Mon, 24 Jul 2017 16:11:39 +0200
Subject: [PATCH] =?UTF-8?q?d=C3=A9but=20de=20prise=20en=20charge=20de=20l'?=
 =?UTF-8?q?internationalisation?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 spec/regime_uniforme_puissance.spec.ts |   9 +-
 src/base.ts                            | 107 +++++----
 src/dichotomie.ts                      |  71 +++---
 src/internationalisation.ts            | 290 +++++++++++++++++++++++++
 src/param.ts                           |  80 +++++--
 src/util/error.ts                      | 116 ++++++++++
 src/util/numericalstring.ts            |   4 +-
 7 files changed, 576 insertions(+), 101 deletions(-)
 create mode 100644 src/internationalisation.ts
 create mode 100644 src/util/error.ts

diff --git a/spec/regime_uniforme_puissance.spec.ts b/spec/regime_uniforme_puissance.spec.ts
index d8b5d98d..053452eb 100644
--- a/spec/regime_uniforme_puissance.spec.ts
+++ b/spec/regime_uniforme_puissance.spec.ts
@@ -1,6 +1,7 @@
 /// <reference path="../node_modules/@types/jasmine/index.d.ts" />
 
-import { Result, ResultCode } from "../src/base";
+import { Result } from "../src/base";
+import { ErrorCode } from "../src/util/error";
 import { RegimeUniforme } from "../src/regime_uniforme";
 import { ParamsSectionPuiss, cSnPuiss } from "../src/section/section_puissance";
 import { precDigits, precDist } from "./nubtest";
@@ -128,7 +129,7 @@ describe('Class RegimeUniforme / section puissance :', () => {
 
             let res: Result = ru.Calc("k");
             expect(res.vCalc).toBeUndefined();
-            expect(res.code).toBe(ResultCode.ERROR_DICHO_INIT_DOMAIN);
+            expect(res.code).toBe(ErrorCode.ERROR_DICHO_INIT_DOMAIN);
         });
 
         it('k should be 0.635', () => {
@@ -199,7 +200,7 @@ describe('Class RegimeUniforme / section puissance :', () => {
 
             let res: Result = ru.Calc("Ks", 5000000);
             expect(res.vCalc).toBeUndefined();
-            expect(res.code).toBe(ResultCode.ERROR_DICHO_INITVALUE_HIGH);
+            expect(res.code).toBe(ErrorCode.ERROR_DICHO_INITVALUE_HIGH);
         });
 
         it('Ks should be undefined', () => {
@@ -219,7 +220,7 @@ describe('Class RegimeUniforme / section puissance :', () => {
 
             let res: Result = ru.Calc("Ks", 1e-8);
             expect(res.vCalc).toBeUndefined();
-            expect(res.code).toBe(ResultCode.ERROR_DICHO_INITVALUE_LOW);
+            expect(res.code).toBe(ErrorCode.ERROR_DICHO_INITVALUE_LOW);
         });
 
         it('If should be 0.001', () => {
diff --git a/src/base.ts b/src/base.ts
index f27633f6..c8b79b78 100644
--- a/src/base.ts
+++ b/src/base.ts
@@ -1,30 +1,60 @@
-export enum ResultCode {
-    OK = 0,
+import { ErrorMessage, ErrorCode } from "./util/error";
+
+// export enum ResultCode {
+//     OK = 0,
+
+//     /**
+//      * la dichotomie n'a pas pu trouver automatiquement d'intervalle de départ
+//      * car la valeur initiale de la variable est trop haute
+//      */
+//     ERROR_DICHO_INITVALUE_HIGH = -1,
+
+//     /**
+//      * la dichotomie n'a pas pu trouver automatiquement d'intervalle de départ
+//      * car la valeur initiale de la variable est trop basse
+//      */
+//     ERROR_DICHO_INITVALUE_LOW = -2,
+
+//     /**
+//      * la dichotomie n'a pas pu trouver automatiquement d'intervalle de départ
+//      * car la valeur cible de la fonction n'existe pas pour des valeurs de la
+//      * variable dans son domaine de définition, cad il n'existe pas de solution
+//      */
+//     ERROR_DICHO_INIT_DOMAIN = -3,
+
+//     /**
+//      * la dichotomie n'a pas pu converger
+//      */
+//     ERROR_DICHO_CONVERGE = -4,
+// }
+
+// /**
+//  * Résultat de calcul comprenant la valeur du résultat et des calculs annexes (flag, calculs intermédiaires...)
+//  */
+// export class Result {
+//     /** Valeur calculée */
+//     private _vCalc: number;
+
+//     /**
+//      * code d'erreur
+//      */
+//     private _code: ResultCode;
+
+//     /** Variables intermédiaires, flags d'erreur */
+//     // public extraVar: {};
+//     public extraVar: { [key: string]: any };
+
+//     constructor(v: number, c: ResultCode = ResultCode.OK) {
+//         this._vCalc = v
+//         this._code = c;
+//         this.extraVar = {}
+//     };
+
+//     get vCalc() { return this._vCalc; }
+
+//     get code() { return this._code; }
+// }
 
-    /**
-     * la dichotomie n'a pas pu trouver automatiquement d'intervalle de départ
-     * car la valeur initiale de la variable est trop haute
-     */
-    ERROR_DICHO_INITVALUE_HIGH = -1,
-
-    /**
-     * la dichotomie n'a pas pu trouver automatiquement d'intervalle de départ
-     * car la valeur initiale de la variable est trop basse
-     */
-    ERROR_DICHO_INITVALUE_LOW = -2,
-
-    /**
-     * la dichotomie n'a pas pu trouver automatiquement d'intervalle de départ
-     * car la valeur cible de la fonction n'existe pas pour des valeurs de la
-     * variable dans son domaine de définition, cad il n'existe pas de solution
-     */
-    ERROR_DICHO_INIT_DOMAIN = -3,
-
-    /**
-     * la dichotomie n'a pas pu converger
-     */
-    ERROR_DICHO_CONVERGE = -4,
-}
 
 /**
  * Résultat de calcul comprenant la valeur du résultat et des calculs annexes (flag, calculs intermédiaires...)
@@ -33,24 +63,19 @@ export class Result {
     /** Valeur calculée */
     private _vCalc: number;
 
-    /**
-     * code d'erreur
-     */
-    private _code: ResultCode;
-
-    /** Variables intermédiaires, flags d'erreur */
-    // public extraVar: {};
-    public extraVar: { [key: string]: any };
+    private _errorMessage: ErrorMessage;
 
-    constructor(v: number, c: ResultCode = ResultCode.OK) {
-        this._vCalc = v
-        this._code = c;
-        this.extraVar = {}
+    // constructor(v: number, c: ErrorCode = undefined) {
+    constructor(v: number, e: ErrorMessage = undefined) {
+        this._vCalc = v;
+        this._errorMessage = e;
     };
 
     get vCalc() { return this._vCalc; }
 
-    get code() { return this._code; }
+    get code() { return this._errorMessage.code; }
+
+    get errorMessage() { return this._errorMessage; }
 }
 
 /**
@@ -104,5 +129,5 @@ export function BoolIdentity(a: boolean, b: boolean): boolean {
     return (a && b) || (!a && !b);
 }
 
-export class UndefinedError extends Error {
-}
+// export class UndefinedError extends Error {
+// }
diff --git a/src/dichotomie.ts b/src/dichotomie.ts
index dea0f04b..fe2b49c8 100644
--- a/src/dichotomie.ts
+++ b/src/dichotomie.ts
@@ -1,4 +1,6 @@
-import { XOR, BoolIdentity, Debug, Result, ResultCode, UndefinedError } from "./base";
+// import { XOR, BoolIdentity, Debug, Result, ResultCode, UndefinedError } from "./base";
+import { XOR, BoolIdentity, Debug, Result } from "./base";
+import { ErrorMessage, ErrorCode } from "./util/error";
 import { Nub } from "./nub";
 import { ParamDefinition, ParamDomain, ParamDomainValue } from "./param"
 
@@ -57,11 +59,17 @@ class Interval extends Pair {
     }
 
     checkValue(v: number) {
-        if (v == undefined)
-            throw new UndefinedError("Interval.checkValue() : invalid undefined value");
+        if (v == undefined) {
+            let e = new ErrorMessage(ErrorCode.ERROR_INTERVAL_UNDEF);
+            throw e;
+        }
 
-        if (!this.intervalHasValue(v))
-            throw new RangeError("Interval : value " + v + " is outside of " + this.toString());
+        if (!this.intervalHasValue(v)) {
+            let e = new ErrorMessage(ErrorCode.ERROR_INTERVAL_OUTSIDE);
+            e.extraVar["value"] = v;
+            e.extraVar["interval"] = this.toString();
+            throw e;
+        }
     }
 
     get length(): number {
@@ -92,8 +100,10 @@ class SearchInterval extends Interval {
 
     constructor(d: Dichotomie, min: number, max: number, s: number) {
         super(min, max);
-        if (s == 0)
-            throw new RangeError("SearchInterval : invalid null step");
+        if (s == 0) {
+            let e = new ErrorMessage(ErrorCode.ERROR_DICHO_NULL_STEP);
+            throw e;
+        }
         this._step = s;
         this._dicho = d;
     }
@@ -103,8 +113,10 @@ class SearchInterval extends Interval {
     }
 
     growStep(k: number) {
-        if (k == 0)
-            throw new RangeError("SearchInterval : invalid null step grow");
+        if (k == 0) {
+            let e = new ErrorMessage(ErrorCode.ERROR_DICHO_INVALID_STEP_GROWTH);
+            throw e;
+        }
         this._step *= k;
     }
 
@@ -163,8 +175,8 @@ class SearchInterval extends Interval {
         return this.targets.intervalHasValue(targ);
     }
 
-    // non fiable : certaines fonctions (coef section puiss par ex) sont globalement monotones mais peuvent inverser localement leur sens de variation
     // isIncreasingFunction(): boolean {
+    // non fiable : certaines fonctions (coef section puiss par ex) sont globalement monotones mais peuvent inverser localement leur sens de variation
     //     return this.targetUpper > this.targetLower;
     // }
 }
@@ -174,18 +186,11 @@ class SearchInterval extends Interval {
  * calcul par dichotomie
  */
 export class Dichotomie extends Debug {
-    /**  Pas de parcours de l'intervalle pour initialisation dichotomie */
-    //   private readonly IDEFINT = 100;
-
-    /** Nombre d'itérations maximum de la dichotomie */
-    //  private readonly IDICMAX = 100;
-
     /**
      * définition de la variable de la fonction
      */
     private _paramX: ParamDefinition;
 
-
     /**
      * nombre d'étapes de recherche de l'intervalle de départ
      */
@@ -303,8 +308,10 @@ export class Dichotomie extends Debug {
             x += step;
         }
 
-        if (variation == 0)
-            throw "unable to determinate function direction of variation";
+        if (variation == 0) {
+            let e = new ErrorMessage(ErrorCode.ERROR_DICHO_FUNCTION_VARIATION);
+            throw e;
+        }
 
         return variation > 0;
     }
@@ -314,7 +321,7 @@ export class Dichotomie extends Debug {
      * @param rTarget valeur cible de la fonction
      * @param rInit  valeur initiale de la variable
      */
-    getStartInterval(rTarget: number, rInit: number): any {
+    private getStartInterval(rTarget: number, rInit: number): any {
         let prmDom: ParamDomain = this.paramX.getDomain();
         let min, max, step;
 
@@ -360,7 +367,6 @@ export class Dichotomie extends Debug {
 
         let intSearch: SearchInterval = new SearchInterval(this, rInit, rInit + step, step);
 
-        // let inc = intSearch.isIncreasingFunction();
         let inc = this.isIncreasingFunction(prmDom);
 
         let initTarget = this.CalculX(rInit).vCalc;
@@ -393,7 +399,7 @@ export class Dichotomie extends Debug {
         let aps: string = this.nub.getFirstAnalyticalParameter().symbol;
         let m;
 
-        let res: Result;
+        let res: ErrorMessage;
         let errDomain = false;
         switch (prmDom.domain) {
             case ParamDomainValue.INTERVAL:
@@ -415,24 +421,17 @@ export class Dichotomie extends Debug {
         }
 
         if (errDomain) {
-            //                    m = "Dichotomy : target " + aps + "=" + rTarget + " does not exist in interval " + intMax.toString() + " for variable " + this.paramX.symbol;
-            res = new Result(undefined, ResultCode.ERROR_DICHO_INIT_DOMAIN);
+            res = new ErrorMessage(ErrorCode.ERROR_DICHO_INIT_DOMAIN);
             res.extraVar["targetSymbol"] = aps; // symbole de la variable calculée par la fonction
             res.extraVar["targetValue"] = rTarget; // valeur cible pour la fonction
             res.extraVar["variableInterval"] = intMax.toString(); // valeur de la fonction pour la valeur initiale de la variable
             res.extraVar["variableSymbol"] = this.paramX.symbol; // symbole de la variable de la fonction
         }
         else {
-            // m = "Dichotomy : initial value " + this.paramX.symbol + "=" + rInit;
-            // if (intSearch.step < 0)
-            //     m += " is to high";
-            // else
-            //     m += " is to low";
-            // m += " (target is " + aps + "=" + rTarget + ", " + aps + "(" + this.paramX.symbol + "=" + rInit + ")=" + initTarget + ")";
             if (intSearch.step < 0)
-                res = new Result(undefined, ResultCode.ERROR_DICHO_INITVALUE_HIGH);
+                res = new ErrorMessage(ErrorCode.ERROR_DICHO_INITVALUE_HIGH);
             else
-                res = new Result(undefined, ResultCode.ERROR_DICHO_INITVALUE_LOW);
+                res = new ErrorMessage(ErrorCode.ERROR_DICHO_INITVALUE_LOW);
 
             res.extraVar["variableSymbol"] = this.paramX.symbol; // symbole de la variable de la fonction
             res.extraVar["variableInitValue"] = rInit; // valeur initiale de la variable
@@ -475,8 +474,6 @@ export class Dichotomie extends Debug {
     }
 
     Dichotomie(rTarget: number, rTol: number, rInit: number): Result {
-        let res: Result;
-
         // console.log("-----");
         // for (let x = 0; x <= 1; x += 0.1)
         //     console.log(this.CalculX(x).vCalc);
@@ -488,8 +485,10 @@ export class Dichotomie extends Debug {
         let r = this.getStartInterval(rTarget, rInit);
         if (r.ok)
             var interv: SearchInterval = r.intSearch;
-        else
-            return r.res;
+        else {
+            let result = new Result(undefined, r.res);
+            return result;
+        }
 
         // Dichotomie
 
diff --git a/src/internationalisation.ts b/src/internationalisation.ts
new file mode 100644
index 00000000..9b646a9a
--- /dev/null
+++ b/src/internationalisation.ts
@@ -0,0 +1,290 @@
+// import { Result, ResultCode } from "./base";
+import { Result } from "./base";
+import { ErrorMessage, ErrorCode } from "./util/error";
+
+export enum Language {
+    FRENCH,
+
+    ENGLISH,
+}
+
+export class Internationalisation {
+    private _lang: Language;
+    private _sLang: string;
+    private static _instance: Internationalisation;
+
+    private constructor() { }
+
+    public static getInstance(): Internationalisation {
+        if (this._instance == undefined)
+            this._instance = new Internationalisation();
+        return this._instance;
+    }
+
+    public get lang() {
+        return this._lang;
+    }
+
+    public set lang(l: Language) {
+        this._lang = l;
+        this._sLang = Language[l];
+    }
+
+    public localizeErrorMessage(r: ErrorMessage): string {
+        let m: string;
+        let sCode: string = ErrorCode[r.code];
+
+        switch (this.lang) {
+            case Language.ENGLISH:
+                switch (r.code) {
+                    case ErrorCode.ERROR_DICHO_INIT_DOMAIN:
+                        m = "Dichotomy : target " + r.extraVar["targetSymbol"];
+                        m += "=" + r.extraVar["targetValue"];
+                        m += " does not exist for variable " + r.extraVar["variableSymbol"];
+                        m += " valued in interval " + r.extraVar["variableInterval"];
+                        break;
+
+                    case ErrorCode.ERROR_DICHO_INITVALUE_HIGH:
+                    case ErrorCode.ERROR_DICHO_INITVALUE_LOW:
+                        m = "Dichotomy : initial value " + r.extraVar["variableSymbol"];
+                        m += "=" + r.extraVar["variableInitValue"];
+                        if (r.code == ErrorCode.ERROR_DICHO_INITVALUE_HIGH)
+                            m += " is too high";
+                        else if (r.code == ErrorCode.ERROR_DICHO_INITVALUE_LOW)
+                            m += " is too low";
+
+                        m += " (target is " + r.extraVar["targetSymbol"];
+                        m += "=" + r.extraVar["targetValue"];
+                        m += ", " + r.extraVar["targetSymbol"];
+                        m += "(" + r.extraVar["variableSymbol"];
+                        m += "=" + r.extraVar["variableInitValue"]
+                        m += ")=" + r.extraVar["initTarget"] + ")";
+                        break;
+
+
+                    case ErrorCode.ERROR_DICHO_NULL_STEP:
+                        m = "Dichotomy (initial interval search) : invalid null step";
+                        break;
+
+                    case ErrorCode.ERROR_DICHO_INVALID_STEP_GROWTH:
+                        m = "Dichotomy (initial interval search) : invalid null step growth";
+                        break;
+
+                    case ErrorCode.ERROR_DICHO_FUNCTION_VARIATION:
+                        m = "unable to determinate function direction of variation";
+                        break;
+
+                    case ErrorCode.ERROR_PARAMDOMAIN_INTERVAL_BOUNDS:
+                        m = "invalid ";
+                        m += String(r.extraVar["minValue"]);
+                        m += "/";
+                        m += String(r.extraVar["maxValue"]);
+                        m += " min/max boundaries for 'interval' parameter definition domain";
+                        break;
+
+                    case ErrorCode.ERROR_PARAMDEF_CALC_UNDEFINED:
+                        m = "calculability of '";
+                        m += r.extraVar["symbol"];
+                        m += "' parameter is undefined";
+                        break;
+
+                    case ErrorCode.ERROR_PARAMDEF_VALUE_UNDEFINED:
+                        m = "value of '";
+                        m += r.extraVar["symbol"];
+                        m += "' parameter is undefined";
+                        break;
+
+                    case ErrorCode.ERROR_PARAMDEF_VALUE_FIXED:
+                        m = "value of '";
+                        m += r.extraVar["symbol"];
+                        m += "' parameter cannot be changed";
+                        break;
+
+                    case ErrorCode.ERROR_PARAMDEF_VALUE_POS:
+                        m = "value ";
+                        m += String(r.extraVar["value"]);
+                        m += " of '";
+                        m += r.extraVar["symbol"];
+                        m += "' parameter is invalid ";
+                        m += " (cannot be <=0)";
+                        break;
+
+                    case ErrorCode.ERROR_PARAMDEF_VALUE_POSNULL:
+                        m = "value ";
+                        m += String(r.extraVar["value"]);
+                        m += " of '";
+                        m += r.extraVar["symbol"];
+                        m += "' parameter is invalid ";
+                        m += " (cannot be <0)";
+                        break;
+
+                    case ErrorCode.ERROR_PARAMDEF_VALUE_NULL:
+                        m = "value of '";
+                        m += r.extraVar["symbol"];
+                        m += "' parameter cannot be 0";
+                        break;
+
+                    case ErrorCode.ERROR_PARAMDEF_VALUE_INTERVAL:
+                        m = "parameter '";
+                        m += r.extraVar["symbol"];
+                        m += "' : value ";
+                        m += r.extraVar["value"];
+                        m += " is out of [";
+                        m += r.extraVar["minValue"];
+                        m += ", ";
+                        m += r.extraVar["maxValue"];
+                        m += "] interval";
+                        break;
+
+                    case ErrorCode.ERROR_PARAMDOMAIN_INVALID:
+                        m = "parameter '";
+                        m += r.extraVar["symbol"];
+                        m += "' : non supported '";
+                        m += r.extraVar["domain"];
+                        m += "' definition domain";
+                        break;
+
+                    case ErrorCode.ERROR_INTERVAL_UNDEF:
+                        m = "Interval : invalid 'undefined' value";
+                        break;
+
+                    case ErrorCode.ERROR_INTERVAL_OUTSIDE:
+                        m = "Interval : value ";
+                        m += r.extraVar["value"];
+                        m += " is outside of ";
+                        m += r.extraVar["interval"];
+                        break;
+
+                    default:
+                        throw "unprocessed ResultCode value " + sCode + " for language " + this._sLang;
+                }
+                break;
+
+            case Language.FRENCH:
+                switch (r.code) {
+                    case ErrorCode.ERROR_DICHO_INIT_DOMAIN:
+                        m = "Dichotomie : la valeur cible " + r.extraVar["targetSymbol"];
+                        m += "=" + r.extraVar["targetValue"];
+                        m += " n'existe pas pour la variable " + r.extraVar["variableSymbol"] + " prise dans l'intervalle " + r.extraVar["variableInterval"];
+                        break;
+
+                    case ErrorCode.ERROR_DICHO_INITVALUE_HIGH:
+                    case ErrorCode.ERROR_DICHO_INITVALUE_LOW:
+                        m = "Dichotomie : la valeur initiale " + r.extraVar["variableSymbol"];
+                        m += "=" + r.extraVar["variableInitValue"];
+                        if (r.code == ErrorCode.ERROR_DICHO_INITVALUE_HIGH)
+                            m += " est trop grande";
+                        else if (r.code == ErrorCode.ERROR_DICHO_INITVALUE_LOW)
+                            m += " est trop petite";
+
+                        m += " (la valeur cible est " + r.extraVar["targetSymbol"];
+                        m += "=" + r.extraVar["targetValue"];
+                        m += ", " + r.extraVar["targetSymbol"];
+                        m += "(" + r.extraVar["variableSymbol"];
+                        m += "=" + r.extraVar["variableInitValue"]
+                        m += ")=" + r.extraVar["initTarget"] + ")";
+                        break;
+
+                    case ErrorCode.ERROR_DICHO_NULL_STEP:
+                        m = "Dichotomie : le pas pour la recherche de l'intervalle de départ ne devrait pas être nul";
+                        break;
+
+                    case ErrorCode.ERROR_DICHO_INVALID_STEP_GROWTH:
+                        m = "Dichotomie : l'augmentation du pas pour la recherche de l'intervalle de départ est incorrecte (=0)";
+                        break;
+
+                    case ErrorCode.ERROR_DICHO_FUNCTION_VARIATION:
+                        m = "Dichotomie : impossible de determiner le sens de  variation de la fonction";
+                        break;
+
+                    case ErrorCode.ERROR_PARAMDOMAIN_INTERVAL_BOUNDS:
+                        m = "Les bornes (";
+                        m += String(r.extraVar["minValue"]);
+                        m += "/";
+                        m += String(r.extraVar["maxValue"]);
+                        m += ") de l'intervalle sont incorrectes";
+                        break;
+
+                    case ErrorCode.ERROR_PARAMDEF_CALC_UNDEFINED:
+                        m = "La calculabilité du paramètre ";
+                        m += r.extraVar["symbol"];
+                        m += " n'est pas définie";
+                        break;
+
+                    case ErrorCode.ERROR_PARAMDEF_VALUE_UNDEFINED:
+                        m = "La valeur du paramètre ";
+                        m += r.extraVar["symbol"];
+                        m += " n'est pas définie";
+                        break;
+
+                    case ErrorCode.ERROR_PARAMDEF_VALUE_FIXED:
+                        m = "La valeur du paramètre ";
+                        m += r.extraVar["symbol"];
+                        m += " ne peut pas être changée";
+                        break;
+
+                    case ErrorCode.ERROR_PARAMDEF_VALUE_POS:
+                        m = "La valeur ";
+                        m += String(r.extraVar["value"]);
+                        m += " du paramètre '";
+                        m += r.extraVar["symbol"];
+                        m += "' est incorrecte (<=0)";
+                        break;
+
+                    case ErrorCode.ERROR_PARAMDEF_VALUE_POSNULL:
+                        m = "La valeur ";
+                        m += String(r.extraVar["value"]);
+                        m += " du paramètre '";
+                        m += r.extraVar["symbol"];
+                        m += "' est incorrecte (<0)";
+                        break;
+
+                    case ErrorCode.ERROR_PARAMDEF_VALUE_NULL:
+                        m = "La valeur du paramètre '";
+                        m += r.extraVar["symbol"];
+                        m += "' ne peut pas être nulle";
+                        break;
+
+                    case ErrorCode.ERROR_PARAMDEF_VALUE_INTERVAL:
+                        m = "Paramètre '";
+                        m += r.extraVar["symbol"];
+                        m += "' : la valeur ";
+                        m += r.extraVar["value"];
+                        m += " est en dehors de l'intervalle [";
+                        m += r.extraVar["minValue"];
+                        m += ", ";
+                        m += r.extraVar["maxValue"];
+                        m += "]";
+                        break;
+
+                    case ErrorCode.ERROR_PARAMDOMAIN_INVALID:
+                        m = "Paramètre '";
+                        m += r.extraVar["symbol"];
+                        m += "' : le domaine de définition '";
+                        m += r.extraVar["domain"];
+                        m += "' est incorrect";
+                        break;
+
+                    case ErrorCode.ERROR_INTERVAL_UNDEF:
+                        m = "Interval : valeur 'undefined' incorrecte";
+                        break;
+
+                    case ErrorCode.ERROR_INTERVAL_OUTSIDE:
+                        m = "Interval : la valeur ";
+                        m += r.extraVar["value"];
+                        m += " est hors de l'intervalle ";
+                        m += r.extraVar["interval"];
+                        break;
+
+                    default:
+                        throw "unprocessed ResultCode value " + sCode + " for language " + this._sLang;
+                }
+                break;
+
+            default:
+                throw "unprocessed Language value " + this._sLang;
+        }
+
+        return m;
+    }
+}
diff --git a/src/param.ts b/src/param.ts
index 138b520b..4ff87c44 100644
--- a/src/param.ts
+++ b/src/param.ts
@@ -1,5 +1,7 @@
-import { Debug, UndefinedError } from './base';
+// import { Debug, UndefinedError } from './base';
+import { Debug } from './base';
 import { DefinedNumber } from './util/definedvalue';
+import { ErrorMessage, ErrorCode } from './util/error';
 
 /**
  * domaine de définition du paramètre
@@ -49,8 +51,13 @@ export class ParamDomain {
     private checkValue(val: number, min: number, max: number) {
         switch (val) {
             case ParamDomainValue.INTERVAL:
-                if (min == undefined || max == undefined || min > max)
-                    throw "invalid " + min + "/" + max + " min/max boundaries for 'interval' parameter definition domain"
+                if (min == undefined || max == undefined || min > max) {
+                    // throw "invalid " + min + "/" + max + " min/max boundaries for 'interval' parameter definition domain"
+                    let e: ErrorMessage = new ErrorMessage(ErrorCode.ERROR_PARAMDOMAIN_INTERVAL_BOUNDS);
+                    e.extraVar["minValue"] = min;
+                    e.extraVar["maxValue"] = max;
+                    throw e;
+                }
                 break;
 
             default:
@@ -178,8 +185,12 @@ export class ParamDefinition extends DefinedNumber {
     }
 
     get calculability(): ParamCalculability {
-        if (this._calc == undefined)
-            throw "value of parameter '" + this._symbol + "' calculability is not defined";
+        if (this._calc == undefined) {
+            //   throw "value of parameter '" + this._symbol + "' calculability is not defined";
+            let e = new ErrorMessage(ErrorCode.ERROR_PARAMDEF_CALC_UNDEFINED);
+            e.extraVar["symbol"] = this.symbol;
+            throw e;
+        }
 
         return this._calc;
     }
@@ -193,8 +204,12 @@ export class ParamDefinition extends DefinedNumber {
      */
     get v(): number {
         // if (this._value == undefined)
-        if (!this.isDefined)
-            throw new UndefinedError("value of '" + this._symbol + "' parameter is not defined");
+        if (!this.isDefined) {
+            //   throw new UndefinedError("value of '" + this._symbol + "' parameter is not defined");
+            let e = new ErrorMessage(ErrorCode.ERROR_PARAMDEF_VALUE_UNDEFINED);
+            e.extraVar["symbol"] = this.symbol;
+            throw e;
+        }
         // return this._value;
         return this.getValue();
     }
@@ -203,8 +218,12 @@ export class ParamDefinition extends DefinedNumber {
         //        if (val == undefined)
         //            console.log("warning : setting parameter '" + this._symbol + "' to undefined value (use undefine() instead)");
 
-        if (this.calculability == ParamCalculability.NONE)
-            throw "value of '" + this._symbol + "' parameter cannot be changed";
+        if (this.calculability == ParamCalculability.NONE) {
+            //   throw "value of '" + this._symbol + "' parameter cannot be changed";
+            let e = new ErrorMessage(ErrorCode.ERROR_PARAMDEF_VALUE_FIXED);
+            e.extraVar["symbol"] = this.symbol;
+            throw e;
+        }
         this.checkValue(val);
         // this._value = val;
         this.setValue(val);
@@ -224,29 +243,54 @@ export class ParamDefinition extends DefinedNumber {
                 break;
 
             case ParamDomainValue.POS:
-                if (v <= 0)
-                    throw "parameter '" + this._symbol + "' : invalid " + v + " value (cannot be <=0)";
+                if (v <= 0) {
+                    //   throw "parameter '" + this._symbol + "' : invalid " + v + " value (cannot be <=0)";
+                    let e = new ErrorMessage(ErrorCode.ERROR_PARAMDEF_VALUE_POS);
+                    e.extraVar["symbol"] = this.symbol;
+                    e.extraVar["value"] = v;
+                    throw e;
+                }
                 break;
 
             case ParamDomainValue.POS_NULL:
-                if (v < 0)
-                    throw "parameter '" + this._symbol + "' : invalid " + v + " value (cannot be <0)";
+                if (v < 0) {
+                    //   throw "parameter '" + this._symbol + "' : invalid " + v + " value (cannot be <0)";
+                    let e = new ErrorMessage(ErrorCode.ERROR_PARAMDEF_VALUE_POSNULL);
+                    e.extraVar["symbol"] = this.symbol;
+                    e.extraVar["value"] = v;
+                    throw e;
+                }
                 break;
 
             case ParamDomainValue.NOT_NULL:
-                if (v == 0)
-                    throw "parameter '" + this._symbol + "' : value cannot be 0";
+                if (v == 0) {
+                    //   throw "parameter '" + this._symbol + "' : value cannot be 0";
+                    let e = new ErrorMessage(ErrorCode.ERROR_PARAMDEF_VALUE_NULL);
+                    e.extraVar["symbol"] = this.symbol;
+                    throw e;
+                }
                 break;
 
             case ParamDomainValue.INTERVAL:
                 let min = this._domain.minValue;
                 let max = this._domain.maxValue;
-                if (v < min || v > max)
-                    throw "parameter '" + this._symbol + "' : value " + v + " is out of [" + min + ", " + max + "] interval";
+                if (v < min || v > max) {
+                    // throw "parameter '" + this._symbol + "' : value " + v + " is out of [" + min + ", " + max + "] interval";
+                    let e = new ErrorMessage(ErrorCode.ERROR_PARAMDEF_VALUE_INTERVAL);
+                    e.extraVar["symbol"] = this.symbol;
+                    e.extraVar["value"] = v;
+                    e.extraVar["minValue"] = min;
+                    e.extraVar["maxValue"] = max;
+                    throw e;
+                }
                 break;
 
             default:
-                throw "parameter '" + this._symbol + "' : non supported '" + sDomain + "' definition domain";
+                //throw "parameter '" + this._symbol + "' : non supported '" + sDomain + "' definition domain";
+                let e = new ErrorMessage(ErrorCode.ERROR_PARAMDOMAIN_INVALID);
+                e.extraVar["symbol"] = this.symbol;
+                e.extraVar["domain"] = sDomain;
+                throw e;
         }
     }
 
diff --git a/src/util/error.ts b/src/util/error.ts
new file mode 100644
index 00000000..a2c31ca7
--- /dev/null
+++ b/src/util/error.ts
@@ -0,0 +1,116 @@
+export enum ErrorCode {
+    /**
+     * la dichotomie n'a pas pu trouver automatiquement d'intervalle de départ
+     * car la valeur initiale de la variable est trop haute
+     */
+    ERROR_DICHO_INITVALUE_HIGH = -1,
+
+    /**
+     * la dichotomie n'a pas pu trouver automatiquement d'intervalle de départ
+     * car la valeur initiale de la variable est trop basse
+     */
+    ERROR_DICHO_INITVALUE_LOW = -2,
+
+    /**
+     * la dichotomie n'a pas pu trouver automatiquement d'intervalle de départ
+     * car la valeur cible de la fonction n'existe pas pour des valeurs de la
+     * variable dans son domaine de définition, cad il n'existe pas de solution
+     */
+    ERROR_DICHO_INIT_DOMAIN = -3,
+
+    /**
+     * la dichotomie n'a pas pu converger
+     */
+    ERROR_DICHO_CONVERGE = -4,
+
+    /**
+     * le pas pour la recherche de l'intervalle de départ est =0
+     */
+    ERROR_DICHO_NULL_STEP = -5,
+
+    /**
+     * l'augmentation du pas pour la recherche de l'intervalle de départ est incorrecte (=0)
+     */
+    ERROR_DICHO_INVALID_STEP_GROWTH = -6,
+
+    /**
+     * impossible de déterminer le sens de variation de la fonction
+     */
+    ERROR_DICHO_FUNCTION_VARIATION = -7,
+
+    /**
+     * les bornes de l'intervalle d'un ParamDomain sont incorrectes
+     */
+    ERROR_PARAMDOMAIN_INTERVAL_BOUNDS = -100,
+
+    /**
+     * la valeur du ParamDomain est incorrecte
+     */
+    ERROR_PARAMDOMAIN_INVALID = -101,
+
+    /**
+     * la calculabilité d'un ParamDefinition est non définie
+     */
+    ERROR_PARAMDEF_CALC_UNDEFINED = -200,
+
+    /**
+     * la valeur d'un ParamDefinition est non définie
+     */
+    ERROR_PARAMDEF_VALUE_UNDEFINED = -201,
+
+    /**
+     * la valeur d'un ParamDefinition ne peut pas être changée
+     */
+    ERROR_PARAMDEF_VALUE_FIXED = -202,
+
+    /**
+     * la valeur d'un ParamDefinition ne peut pas être > 0
+     */
+    ERROR_PARAMDEF_VALUE_POS = -203,
+
+    /**
+     * la valeur d'un ParamDefinition ne peut pas être >= 0
+     */
+    ERROR_PARAMDEF_VALUE_POSNULL = -204,
+
+    /**
+     * la valeur d'un ParamDefinition ne peut pas être = 0
+     */
+    ERROR_PARAMDEF_VALUE_NULL = -205,
+
+    /**
+     * la valeur d'un ParamDefinition est en dehors de son intervalle autorisé
+     */
+    ERROR_PARAMDEF_VALUE_INTERVAL = -206,
+
+    /**
+     * la valeur passée à une méthode de la classe Interval est undefined
+     */
+    ERROR_INTERVAL_UNDEF = -300,
+
+    /**
+     * la valeur passée à une méthode de la classe Interval est hors de l'intervalle défini
+     */
+    ERROR_INTERVAL_OUTSIDE = -301,
+}
+
+/**
+ * Résultat de calcul comprenant la valeur du résultat et des calculs annexes (flag, calculs intermédiaires...)
+ */
+export class ErrorMessage {
+    /**
+     * code d'erreur
+     */
+    private _code: ErrorCode;
+
+    /** Variables intermédiaires, flags d'erreur */
+    // public extraVar: {};
+    public extraVar: { [key: string]: any };
+
+    constructor(c: ErrorCode) {
+        this._code = c;
+        this.extraVar = {}
+    };
+
+    get code() { return this._code; }
+}
diff --git a/src/util/numericalstring.ts b/src/util/numericalstring.ts
index 650bb15d..c32e98c8 100644
--- a/src/util/numericalstring.ts
+++ b/src/util/numericalstring.ts
@@ -44,11 +44,11 @@ export class NumericalString extends DefinedString {
 
     get numericalValue(): number {
         if (!this.isNumerical)
-            throw "invalid NumericString '" + this.uncheckedValue + "' value";
+            throw "invalid NumericalString '" + this.uncheckedValue + "' value";
         return +this.value;
     }
 
-    get uncheckValueString(): string {
+    get uncheckedValueString(): string {
         if (this.isDefined)
             return this.uncheckedValue;
         return "";
-- 
GitLab