param-values.ts 7.39 KB
Newer Older
1
import { ExtensionStrategy } from "./param-definition";
2
import { INumberIterator, IterableValues, ParamValueIterator } from "./param-value-iterator";
3
import { ParamValueMode } from "./param-value-mode";
4

5
6
7
8
9
10
/**
 * Represents the value(s) taken by a Parameter, along with and depending on
 * the value mode; linked values are not managed here, only the LINK value
 * mode is defined here
 */
export class ParamValues implements IterableValues {
11

12
    /** usually set by enclosing ParamDefinition */
13
    public valueMode: ParamValueMode;
14

15
16
17
    /** usually set by enclosing ParamDefinition */
    public extensionStrategy: ExtensionStrategy;

18
    /** valeur min dans le cas ParamValueMode.MINMAX */
Mathias Chouet's avatar
Mathias Chouet committed
19
    public min: number;
20

21
    /** valeur max dans le cas ParamValueMode.MINMAX */
Mathias Chouet's avatar
Mathias Chouet committed
22
    public max: number;
23

24
    /** pas de progression dans le cas ParamValueMode.MINMAX */
Mathias Chouet's avatar
Mathias Chouet committed
25
    public step: number;
26

27
28
    /** liste de valeurs dans le cas ParamValueMode.LISTE */
    public valueList: number[];
29

30
31
    /** valeur numérique (éventuellement non définie) dans le mode "valeur unique" (ParamValueMode.SINGLE) */
    private _singleValue: number;
Grand Francois's avatar
Grand Francois committed
32

Mathias Chouet's avatar
Mathias Chouet committed
33
34
35
    /** valeur courante (éventuellement non définie) indépendemment du mode */
    private _currentValue: number;

36
37
38
    /**
     * itérateur courant
     */
Mathias Chouet's avatar
Mathias Chouet committed
39
    private _iterator: INumberIterator;
40

Mathias Chouet's avatar
Mathias Chouet committed
41
42
43
44
45
46
    public get singleValue(): number {
        return this._singleValue;
    }

    public set singleValue(v: number) {
        this._singleValue = v;
Mathias Chouet's avatar
Mathias Chouet committed
47
48
49
50
51
        this._currentValue = v;
    }

    public get currentValue() {
        return this._currentValue;
Mathias Chouet's avatar
Mathias Chouet committed
52
53
    }

54
55
56
57
    public count() {
        return this._iterator.count();
    }

58
    public setValues(o: number | any, max?: number, step?: number) {
59
        if (typeof (o) === "number") {
60
            if (max === undefined) {
61
                this.valueMode = ParamValueMode.SINGLE;
Mathias Chouet's avatar
Mathias Chouet committed
62
                this.singleValue = o;
63
            } else {
64
65
66
67
                this.valueMode = ParamValueMode.MINMAX;
                this.min = o;
                this.max = max;
                this.step = step;
68
            }
69
        } else if (Array.isArray(o)) {
70
71
            this.valueMode = ParamValueMode.LISTE;
            this.valueList = o;
72
        } else {
73
            throw new Error(`ParamValues.setValues() :  appel invalide`);
74
        }
75
76
    }

77
    public check() {
78
        switch (this.valueMode) {
79
            case ParamValueMode.SINGLE:
Mathias Chouet's avatar
Mathias Chouet committed
80
                if (this.singleValue === undefined) {
81
                    throw new Error(`ParamValues : valeur fixe non définie`);
82
                }
83
84
85
                break;

            case ParamValueMode.MINMAX:
86
                if (this.min === undefined) {
87
                    throw new Error(`ParamValues : valeur min non définie`);
88
                }
89
                if (this.max === undefined) {
90
                    throw new Error(`ParamValues : valeur max non définie`);
91
                }
92
                if (this.step === undefined) {
93
                    throw new Error(`ParamValues : valeur du pas non définie`);
94
                }
95
                if (this.min > this.max) {
96
                    throw new Error(`ParamValues : min > max`);
97
                }
98
99
100
                break;

            case ParamValueMode.LISTE:
101
                if (this.valueList === undefined) {
102
                    throw new Error(`ParamValues : liste de valeurs non définie`);
103
                }
104
105
                break;

106
            case ParamValueMode.LINK:
107
            case ParamValueMode.CALCUL:
108
            default:
109
                break;
110
111
112
        }
    }

113
    /**
Mathias Chouet's avatar
Mathias Chouet committed
114
115
     * Returns values as a number list by running through the iterator,
     * taking in account reverse, extendTo and addLastStep if defined
116
     */
Mathias Chouet's avatar
Mathias Chouet committed
117
    public getInferredValuesList(reverse: boolean = false, extendTo?: number, addLastStep: boolean = false) {
118
        if ([ ParamValueMode.MINMAX, ParamValueMode.LISTE ].includes(this.valueMode)) {
119
            // protection against infinite loops
120
121
122
123
124
            if (
                this.step !== undefined && this.step > 0
                && this.min !== undefined && this.min !== null
                && this.max !== undefined && this.max !== null
            ) {
125
126
127
128
129
130
131
132
                const it = this.initValuesIterator(reverse, extendTo, addLastStep);
                const values: number[] = [];
                for (const v of it) {
                    values.push(v);
                }
                return values;
            } else {
                return [];
133
134
135
136
137
            }
        }
        throw new Error("ParamValues.getInferredValuesList() : incorrect value mode" + ParamValueMode[this.valueMode]);
    }

138
    // -- iterator-related methods
139

140
    /**
141
142
143
144
145
     * Returns a ParamValueIterator over the current values
     * @param reverse if true, will iterate starting at the end
     * @param extendTo if defined, will extend values list until this boundary
     * @param addLastStep if true, if (max - min) is not a multiple of step, one more
     *                    iteration will be done return last value (max)
146
     */
147
148
149
150
151
152
    public getValuesIterator(
        reverse: boolean = false,
        extendTo?: number,
        addLastStep: boolean = false
    ): INumberIterator {
        return new ParamValueIterator(this, reverse, extendTo, addLastStep);
153
154
    }

155
156
    // interface IterableValues

Mathias Chouet's avatar
Mathias Chouet committed
157
    public get valuesIterator(): INumberIterator {
158
        return this.getValuesIterator(false, undefined, true);
159
    }
160
161

    public get hasMultipleValues(): boolean {
162
163
164
165
166
167
        try {
            // will throw an error if no value is defined at all
            this.check();
        } catch (e) {
            return false;
        }
168
169
170
171
172
173
174
175
        const it = this.getValuesIterator();
        if (it) {
            let n = 0;
            for (const v of it) {
                n++;
                if (n > 1) {
                    break;
                }
176
            }
177
178
            return n > 1;
        } else {
179
            return false;
180
        }
181
    }
182

183
184
185
186
187
188
189
190
191
192
193
194
    /**
     * Checks that values are in LIST or MINMAX mode, then retrieves an iterator
     * @param reverse if true, will iterate starting at the end
     * @param extendTo if defined, will extend values list until this boundary
     * @param addLastStep if true, if (max - min) is not a multiple of step, one more
     *                    iteration will be done return last value (max)
     */
    public initValuesIterator(
        reverse: boolean = false,
        extendTo?: number,
        addLastStep: boolean = false
    ): INumberIterator {
195
        switch (this.valueMode) {
Grand Francois's avatar
Grand Francois committed
196
197
            case ParamValueMode.LISTE:
            case ParamValueMode.MINMAX:
198
                this._iterator = this.getValuesIterator(reverse, extendTo, addLastStep);
Grand Francois's avatar
Grand Francois committed
199
200
201
                break;

            default:
202
                throw new Error(`ParamValues : mode de valeurs ${ParamValueMode[this.valueMode]} incorrect`);
203
        }
Grand Francois's avatar
Grand Francois committed
204
205
206
207
208
209
210
211
212

        return this._iterator;
    }

    /**
     * @return true si il reste des valeurs à parcourir par l'itérateur courant
     */
    public get hasNext(): boolean {
        return this._iterator.hasNext;
213
214
    }

Grand Francois's avatar
Grand Francois committed
215
216
217
218
219
    /**
     * fixe la valeur courante à la prochaine valeur à parcourir par l'itérateur courant
     * @return prochaine valeur à parcourir par l'itérateur courant
     */
    public next(): IteratorResult<number> {
220
        let res;
221
222
        res = this._iterator.next();
        if (!res.done) {
Mathias Chouet's avatar
Mathias Chouet committed
223
            this._currentValue = res.value;
Grand Francois's avatar
Grand Francois committed
224
225
226
227
228
229
230
        }
        return res;
    }

    public [Symbol.iterator](): IterableIterator<number> {
        return this;
    }
231
}