base.ts 4.04 KB
Newer Older
Dorchies David's avatar
Dorchies David committed
1
2
/**
 * Gestion des messages de debogage dans la console
3
 * @note Implémenter cette interface pour toutes les classes à debugguer
Dorchies David's avatar
Dorchies David committed
4
5
 * Dans le constructeur, utiliser super(true) pour debugger la classe, super(false) sinon.
 */
6
7
8
export interface IDebug {

    readonly DBG: boolean;
Dorchies David's avatar
lint    
Dorchies David committed
9
10

    debug(s: any): void;
11
12
13
}

export class Debug {
Dorchies David's avatar
Dorchies David committed
14
    /**
15
     * @param _DBG Flag de débuggage
Dorchies David's avatar
Dorchies David committed
16
     */
17
    constructor(private _DBG: boolean) { }
Dorchies David's avatar
Dorchies David committed
18

19
    /**
Dorchies David's avatar
Dorchies David committed
20
21
22
     * Affiche un message dans la console si le flag this.DBG est à true
     * @param s Message à afficher dans la console
     */
23
    public debug(...args: any[]) {
24
        // tslint:disable-next-line:no-console
25
        if (this._DBG) {
Mathias Chouet's avatar
Mathias Chouet committed
26
            // tslint:disable-next-line:no-console
27
28
            console.log(...args);
        }
Dorchies David's avatar
Dorchies David committed
29
    }
30
31

    get DBG() { return this._DBG; }
Dorchies David's avatar
Dorchies David committed
32
}
33
34
35
36
37

/**
 * Méthode simulant l'opérateur booléen xor
 * @see http://www.howtocreate.co.uk/xor.html
 */
38
export function XOR(a: boolean, b: boolean): boolean {
39
40
41
    return (a || b) && !(a && b);
}

42
43
44
45
46
47
48
/**
 * Méthode simulant l'opérateur booléen identité (vrai si a=b)
 */
export function BoolIdentity(a: boolean, b: boolean): boolean {
    return (a && b) || (!a && !b);
}

49
50
51
52
53
54
/**
 * arrondi d'un nombre avec une précision donnée
 * @param val nombre à arrondir
 * @param prec nombre de chiffres
 */
export function round(val: number, prec: number) {
55
    const m = Math.pow(10, prec || 0);
56
57
    return Math.round(val * m) / m;
}
58

59
export function isNumeric(s: any): boolean {
60
    if (s !== undefined && s !== null) {
61
62
63
64
65
66
        if (typeof s === "string") {
            const trimmed = s.trim();
            return trimmed !== "" && !isNaN(Number(trimmed));
        } else if (typeof s === "number") {
            return true;
        }
67
68
    }
    return false;
69
}
Mathias Chouet's avatar
Mathias Chouet committed
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95

/**
 * Retourne true si a et b sont égaux à e près (en gros)
 */
export function isEqual(a: number, b: number, e: number = 1E-7): boolean {
    if (a === 0 && b === 0) {
        return true;
    }
    if (b === 0) { // ne pas diviser par 0
        [ a, b ] = [ b, a ];
    }
    if (a === 0) { // éviter d'avoir un quotient toujours nul
        return (Math.abs(b) < e);
    }
    // cas général
    return (Math.abs((a / b) - 1) < e);
}

/**
 * Division entière de a par b, plus modulo, avec une tolérance e
 * pour gérer le cas des nombres réels
 */
export function floatDivAndMod(a: number, b: number, e: number = 1E-7): { q: number, r: number } {
    let q = Math.floor(a / b);
    let r = a % b;
    // si le modulo est bon à un pouïème, pas de reste
Mathias Chouet's avatar
Mathias Chouet committed
96
    if (isEqual(r, b, e)) {
Mathias Chouet's avatar
Mathias Chouet committed
97
98
99
100
101
102
        r = 0;
        // si la division entière n'est pas tombée juste, +1 au quotient
        if (q !== (a / b)) {
            q++;
        }
    }
103
    // si le modulo est nul à un pouïème, il est nul
Mathias Chouet's avatar
Mathias Chouet committed
104
    if (isEqual(r, 0, e)) {
105
106
        r = 0;
    }
Mathias Chouet's avatar
Mathias Chouet committed
107
108
    return { q, r };
}
109
110
111
112
113

/**
 * Formats (rounds) the given number (or the value of the given parameter) with the
 * number of decimals specified in app preferences; if given number is too low and
 * more decimals would be needed, keep as much significative digits as the number of
114
 * decimals specified in app preferences, except potential trailing zeroes;
Mathias Chouet's avatar
Typo    
Mathias Chouet committed
115
 * returns "ERR" if value is not a number or is undefined
116
117
118
119
120
121
122
 *
 * ex. with 3 decimals:
 * 1             => 1.000
 * 65431         => 65431.000
 * 0.002         => 0.002
 * 0.00004521684 => 0.0000452
 * 0.000001      => 0.000001
123
124
 * 5.00004521684 => 5.000
 * 5.000001      => 5.000
125
126
 */
export function formattedValue(value: number, nDigits: number) {
127
128
129
    // bulletproof
    nDigits = Math.max(nDigits, 1);
    nDigits = Math.min(nDigits, 100);
130
131
132
    if (typeof value !== "number" || value === undefined) {
        return "ERR";
    }
133
134
    const minRenderableNumber = Number("1E-" + nDigits);
    // if required precision is too low, avoid rendering only zeroes
135
136
    if (value < minRenderableNumber) {
        return String(Number(value.toPrecision(nDigits))); // double casting avoids trailing zeroes
137
138
139
140
    } else {
        return value.toFixed(nDigits);
    }
}
141

Mathias Chouet's avatar
Mathias Chouet committed
142
143
144
export function capitalize(s: string): string {
    return s.charAt(0).toUpperCase() + s.slice(1);
}