diff --git a/src/util/log.ts b/src/util/log.ts
index 401fbc9c9dbcdfe364ee600a4994eab1e1cbce0e..6770d31341730508c2dc93539bd8f5a33ef88b76 100644
--- a/src/util/log.ts
+++ b/src/util/log.ts
@@ -7,6 +7,19 @@ export class cLog {
         this._messages.push(m);
     }
 
+    public addLog(l: cLog) {
+        for (let m of l._messages)
+            this._messages.push(m);
+    }
+
+    /**
+    * insert un message en début de liste
+    */
+    public insert(m: Message) {
+        //arr.splice(index, 0, item); will insert item into arr at the specified index (deleting 0 items first, that is, it's just an insert).
+        this._messages.splice(0, 0, m);
+    }
+
     public get messages() {
         return this._messages;
     }
diff --git a/src/util/result.ts b/src/util/result.ts
index 1456888a9f224f429b49f43c7489a2d55f90ac1c..438e262046888b0ba1c7d2b845e28a84c962bbc3 100644
--- a/src/util/result.ts
+++ b/src/util/result.ts
@@ -1,15 +1,26 @@
 import { cLog } from "./log";
-import { Message, MessageCode } from "./message";
+import { Message, MessageCode, MessageSeverity } from "./message";
 
 /**
  * Résultat de calcul comprenant la valeur du résultat et des calculs annexes (flag, calculs intermédiaires...)
+ * Représente une valeur unique
  */
 export class Result {
-    /** Valeur calculée */
+    /**
+     * Valeur calculée
+     */
     private _vCalc: number;
 
+    /**
+     * Messages (erreurs, infos, ...)
+     */
     private _log: cLog;
 
+    /**
+     * résultats complémentaires
+     */
+    private _extraResults: { [key: string]: any };
+
     constructor(v: number | Message, d: {} = undefined) {
         this._log = new cLog();
         if (typeof v == "number") {
@@ -18,11 +29,12 @@ export class Result {
             m.extraVar = d;
             this._log.add(m);
         }
-        else {
+        else if (v instanceof Message) {
             if (d != undefined)
                 throw new Error("appel à Result.constructor() invalide");
             this._log.add(v);
         }
+        this._extraResults = {};
     };
 
     get vCalc() { return this._vCalc; }
@@ -43,6 +55,13 @@ export class Result {
         this._log.add(m);
     }
 
+    /**
+     * insert un message en début de liste
+     */
+    public insertMessage(m: Message) {
+        this._log.insert(m);
+    }
+
     public get log(): cLog {
         return this._log;
     }
@@ -51,12 +70,152 @@ export class Result {
         return this._log.messages.length;
     }
 
+    private get hasExtraResults(): boolean {
+        return Object.keys(this._extraResults).length > 0;
+    }
+
+    public get resultsOk(): boolean {
+        return this._vCalc != undefined || this.hasExtraResults;
+    }
+
+    public get hasErrorMessages(): boolean {
+        for (let m of this._log.messages)
+            if (m.code != MessageCode.ERROR_OK && m.getSeverity() == MessageSeverity.ERROR)
+                return true;
+        return false;
+    }
+
     public get ok(): boolean {
-        if (this._vCalc == undefined)
+        return this.resultsOk && !this.hasErrorMessages;
+    }
+
+    /**
+     * résultats complémentaires
+     */
+
+    public get extraResults() {
+        return this._extraResults;
+    }
+
+    public addExtraResult(name: string, value: any) {
+        this._extraResults[name] = value;
+    }
+
+    public getExtraResult(name: string): any {
+        for (let n in this._extraResults)
+            if (n == name)
+                return this._extraResults[n];
+        return undefined;
+    }
+
+    public toString(): string {
+        if (this._vCalc != undefined)
+            return String(this._vCalc);
+        return JSON.stringify(this);
+    }
+}
+
+/**
+ * Résultat global d'un calcul
+ * Peut comporter un ou plusieurs Result.
+ */
+export class CalcResult {
+    private _globalLog: cLog;
+
+    private _results: Result[];
+
+    constructor(v: number | Message | Result, d: {} = undefined) {
+        this._globalLog = new cLog();
+        this._results = [];
+        if (typeof (v) == "number" || v instanceof Message) {
+            const res = new Result(v, d);
+            this._results.push(res);
+        }
+        else if (v instanceof Result) {
+            this._results.push(v);
+        }
+    }
+
+    private get result(): Result {
+        if (this._results.length != 1)
+            throw new Error("appel à une méthode de CalcResult invalide, il n'y a pas exactement un 'Result'");
+
+        return this._results[0];
+    }
+
+    public addResult(r: Result) {
+        this._results.push(r);
+    }
+
+    public extraResultLength(name: string): number {
+        const r = this.getExtraResult(name);
+        if (r == undefined)
+            return 0;
+        return Object.keys(r).length;
+    }
+
+    public getExtraResult(name: string): any {
+        let res = [];
+        for (let r of this._results) {
+            let er = r.getExtraResult(name);
+            if (er != undefined)
+                res.push(er);
+        }
+
+        switch (res.length) {
+            case 0:
+                return undefined;
+
+            case 1:
+                return res[0];
+
+            default:
+                throw new Error("CalcResult.getExtraResult() : il existe plusieurs 'Result' avec le nom '" + name + "'");
+        }
+    }
+
+    public get log() {
+        return this._globalLog;
+    }
+
+    public addMessage(m: Message) {
+        this._globalLog.add(m);
+    }
+
+    public addLog(l: cLog) {
+        this._globalLog.addLog(l);
+    }
+
+    public get vCalc() {
+        return this.result.vCalc;
+    }
+
+    public get resultsOk(): boolean {
+        if (this._results.length == 0 && this._globalLog.messages.length == 0)
             return false;
-        for (let m of this._log.messages)
-            if (m.code != MessageCode.ERROR_OK)
+        for (let r of this._results)
+            if (!r.resultsOk)
                 return false;
         return true;
     }
+
+    public get hasErrorMessages(): boolean {
+        for (let m of this._globalLog.messages)
+            if (m.getSeverity() == MessageSeverity.ERROR)
+                return true;
+
+        for (let r of this._results)
+            if (r.hasErrorMessages)
+                return true;
+
+        return false;
+    }
+
+    public get ok(): boolean {
+        return this.resultsOk && !this.hasErrorMessages;
+    }
+
+    public get code(): MessageCode {
+        return this.result.code;
+    }
 }