chenyc
2025-05-29 92f69c57b920cf62ecc9f15f9ed196fa26dbf2ac
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
/**
 * @license
 * Copyright 2017 Google LLC. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * =============================================================================
 */
import { util } from '..';
import * as tf from '../index';
import { ALL_ENVS, describeWithFlags } from '../jasmine_util';
import { expectValuesInRange } from '../test_util';
import { MPRandGauss, RandGamma, UniformRandom } from './rand_util';
import { expectArrayInMeanStdRange, jarqueBeraNormalityTest } from './rand_util';
describeWithFlags('rand', ALL_ENVS, () => {
    it('should return a random 1D float32 array', async () => {
        const shape = [10];
        // Enusre defaults to float32 w/o type:
        let result = tf.rand(shape, () => util.randUniform(0, 2));
        expect(result.dtype).toBe('float32');
        expectValuesInRange(await result.data(), 0, 2);
        result = tf.rand(shape, () => util.randUniform(0, 1.5));
        expect(result.dtype).toBe('float32');
        expectValuesInRange(await result.data(), 0, 1.5);
    });
    it('should return a random 1D int32 array', async () => {
        const shape = [10];
        const result = tf.rand(shape, () => util.randUniform(0, 2), 'int32');
        expect(result.dtype).toBe('int32');
        expectValuesInRange(await result.data(), 0, 2);
    });
    it('should return a random 1D bool array', async () => {
        const shape = [10];
        const result = tf.rand(shape, () => util.randUniform(0, 1), 'bool');
        expect(result.dtype).toBe('bool');
        expectValuesInRange(await result.data(), 0, 1);
    });
    it('should return a random 2D float32 array', async () => {
        const shape = [3, 4];
        // Enusre defaults to float32 w/o type:
        let result = tf.rand(shape, () => util.randUniform(0, 2.5));
        expect(result.dtype).toBe('float32');
        expectValuesInRange(await result.data(), 0, 2.5);
        result = tf.rand(shape, () => util.randUniform(0, 1.5), 'float32');
        expect(result.dtype).toBe('float32');
        expectValuesInRange(await result.data(), 0, 1.5);
    });
    it('should return a random 2D int32 array', async () => {
        const shape = [3, 4];
        const result = tf.rand(shape, () => util.randUniform(0, 2), 'int32');
        expect(result.dtype).toBe('int32');
        expectValuesInRange(await result.data(), 0, 2);
    });
    it('should return a random 2D bool array', async () => {
        const shape = [3, 4];
        const result = tf.rand(shape, () => util.randUniform(0, 1), 'bool');
        expect(result.dtype).toBe('bool');
        expectValuesInRange(await result.data(), 0, 1);
    });
    it('should return a random 3D float32 array', async () => {
        const shape = [3, 4, 5];
        // Enusre defaults to float32 w/o type:
        let result = tf.rand(shape, () => util.randUniform(0, 2.5));
        expect(result.dtype).toBe('float32');
        expectValuesInRange(await result.data(), 0, 2.5);
        result = tf.rand(shape, () => util.randUniform(0, 1.5), 'float32');
        expect(result.dtype).toBe('float32');
        expectValuesInRange(await result.data(), 0, 1.5);
    });
    it('should return a random 3D int32 array', async () => {
        const shape = [3, 4, 5];
        const result = tf.rand(shape, () => util.randUniform(0, 2), 'int32');
        expect(result.dtype).toBe('int32');
        expectValuesInRange(await result.data(), 0, 2);
    });
    it('should return a random 3D bool array', async () => {
        const shape = [3, 4, 5];
        const result = tf.rand(shape, () => util.randUniform(0, 1), 'bool');
        expect(result.dtype).toBe('bool');
        expectValuesInRange(await result.data(), 0, 1);
    });
    it('should return a random 4D float32 array', async () => {
        const shape = [3, 4, 5, 6];
        // Enusre defaults to float32 w/o type:
        let result = tf.rand(shape, () => util.randUniform(0, 2.5));
        expect(result.dtype).toBe('float32');
        expectValuesInRange(await result.data(), 0, 2.5);
        result = tf.rand(shape, () => util.randUniform(0, 1.5));
        expect(result.dtype).toBe('float32');
        expectValuesInRange(await result.data(), 0, 1.5);
    });
    it('should return a random 4D int32 array', async () => {
        const shape = [3, 4, 5, 6];
        const result = tf.rand(shape, () => util.randUniform(0, 2), 'int32');
        expect(result.dtype).toBe('int32');
        expectValuesInRange(await result.data(), 0, 2);
    });
    it('should return a random 4D bool array', async () => {
        const shape = [3, 4, 5, 6];
        const result = tf.rand(shape, () => util.randUniform(0, 1), 'bool');
        expect(result.dtype).toBe('bool');
        expectValuesInRange(await result.data(), 0, 1);
    });
    it('should throw error when shape is not integer', () => {
        expect(() => tf.rand([2, 2.22, 3.33], () => util.randUniform(0, 2)))
            .toThrow();
    });
});
function isFloat(n) {
    return Number(n) === n && n % 1 !== 0;
}
describe('MPRandGauss', () => {
    const EPSILON = 0.05;
    const SEED = 2002;
    it('should default to float32 numbers', () => {
        const rand = new MPRandGauss(0, 1.5);
        expect(isFloat(rand.nextValue())).toBe(true);
    });
    it('should handle a mean/stdv of float32 numbers', () => {
        const rand = new MPRandGauss(0, 1.5, 'float32', false /* truncated */, SEED);
        const values = [];
        const size = 10000;
        for (let i = 0; i < size; i++) {
            values.push(rand.nextValue());
        }
        expectArrayInMeanStdRange(values, 0, 1.5, EPSILON);
        jarqueBeraNormalityTest(values);
    });
    it('should handle int32 numbers', () => {
        const rand = new MPRandGauss(0, 1, 'int32');
        expect(isFloat(rand.nextValue())).toBe(false);
    });
    it('should handle a mean/stdv of int32 numbers', () => {
        const rand = new MPRandGauss(0, 2, 'int32', false /* truncated */, SEED);
        const values = [];
        const size = 10000;
        for (let i = 0; i < size; i++) {
            values.push(rand.nextValue());
        }
        expectArrayInMeanStdRange(values, 0, 2, EPSILON);
        jarqueBeraNormalityTest(values);
    });
    it('Should not have a more than 2x std-d from mean for truncated values', () => {
        const stdv = 1.5;
        const rand = new MPRandGauss(0, stdv, 'float32', true /* truncated */);
        for (let i = 0; i < 1000; i++) {
            expect(Math.abs(rand.nextValue())).toBeLessThan(stdv * 2);
        }
    });
});
describe('RandGamma', () => {
    const SEED = 2002;
    it('should default to float32 numbers', () => {
        const rand = new RandGamma(2, 2, 'float32');
        expect(isFloat(rand.nextValue())).toBe(true);
    });
    it('should handle an alpha/beta of float32 numbers', () => {
        const rand = new RandGamma(2, 2, 'float32', SEED);
        const values = [];
        const size = 10000;
        for (let i = 0; i < size; i++) {
            values.push(rand.nextValue());
        }
        expectValuesInRange(values, 0, 30);
    });
    it('should handle int32 numbers', () => {
        const rand = new RandGamma(2, 2, 'int32');
        expect(isFloat(rand.nextValue())).toBe(false);
    });
    it('should handle an alpha/beta of int32 numbers', () => {
        const rand = new RandGamma(2, 2, 'int32', SEED);
        const values = [];
        const size = 10000;
        for (let i = 0; i < size; i++) {
            values.push(rand.nextValue());
        }
        expectValuesInRange(values, 0, 30);
    });
});
describe('UniformRandom', () => {
    it('float32, no seed', () => {
        const min = 0.2;
        const max = 0.24;
        const dtype = 'float32';
        const xs = [];
        for (let i = 0; i < 10; ++i) {
            const rand = new UniformRandom(min, max, dtype);
            const x = rand.nextValue();
            xs.push(x);
        }
        expect(Math.min(...xs)).toBeGreaterThanOrEqual(min);
        expect(Math.max(...xs)).toBeLessThan(max);
    });
    it('int32, no seed', () => {
        const min = 13;
        const max = 37;
        const dtype = 'int32';
        const xs = [];
        for (let i = 0; i < 10; ++i) {
            const rand = new UniformRandom(min, max, dtype);
            const x = rand.nextValue();
            expect(Number.isInteger(x)).toEqual(true);
            xs.push(x);
        }
        expect(Math.min(...xs)).toBeGreaterThanOrEqual(min);
        expect(Math.max(...xs)).toBeLessThanOrEqual(max);
    });
    it('seed is number', () => {
        const min = -1.2;
        const max = -0.4;
        const dtype = 'float32';
        const seed = 1337;
        const xs = [];
        for (let i = 0; i < 10; ++i) {
            const rand = new UniformRandom(min, max, dtype, seed);
            const x = rand.nextValue();
            expect(x).toBeGreaterThanOrEqual(min);
            expect(x).toBeLessThan(max);
            xs.push(x);
        }
        // Assert deterministic results.
        expect(Math.min(...xs)).toEqual(Math.max(...xs));
    });
    it('seed === null', () => {
        const min = 0;
        const max = 1;
        const dtype = 'float32';
        const seed = null;
        const rand = new UniformRandom(min, max, dtype, seed);
        const x = rand.nextValue();
        expect(x).toBeGreaterThanOrEqual(0);
        expect(x).toBeLessThan(1);
    });
    it('seed === undefined', () => {
        const min = 0;
        const max = 1;
        const dtype = 'float32';
        const seed = undefined;
        const rand = new UniformRandom(min, max, dtype, seed);
        const x = rand.nextValue();
        expect(x).toBeGreaterThanOrEqual(0);
        expect(x).toBeLessThan(1);
    });
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmFuZF90ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vdGZqcy1jb3JlL3NyYy9vcHMvcmFuZF90ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUVILE9BQU8sRUFBQyxJQUFJLEVBQUMsTUFBTSxJQUFJLENBQUM7QUFDeEIsT0FBTyxLQUFLLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDL0IsT0FBTyxFQUFDLFFBQVEsRUFBRSxpQkFBaUIsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQzVELE9BQU8sRUFBQyxtQkFBbUIsRUFBQyxNQUFNLGNBQWMsQ0FBQztBQUVqRCxPQUFPLEVBQUMsV0FBVyxFQUFFLFNBQVMsRUFBRSxhQUFhLEVBQUMsTUFBTSxhQUFhLENBQUM7QUFDbEUsT0FBTyxFQUFDLHlCQUF5QixFQUFFLHVCQUF1QixFQUFDLE1BQU0sYUFBYSxDQUFDO0FBRS9FLGlCQUFpQixDQUFDLE1BQU0sRUFBRSxRQUFRLEVBQUUsR0FBRyxFQUFFO0lBQ3ZDLEVBQUUsQ0FBQyx5Q0FBeUMsRUFBRSxLQUFLLElBQUksRUFBRTtRQUN2RCxNQUFNLEtBQUssR0FBYSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBRTdCLHVDQUF1QztRQUN2QyxJQUFJLE1BQU0sR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzFELE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3JDLG1CQUFtQixDQUFDLE1BQU0sTUFBTSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUUvQyxNQUFNLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUN4RCxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNyQyxtQkFBbUIsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDbkQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsdUNBQXVDLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDckQsTUFBTSxLQUFLLEdBQWEsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUM3QixNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNyRSxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNuQyxtQkFBbUIsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDakQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsc0NBQXNDLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDcEQsTUFBTSxLQUFLLEdBQWEsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUM3QixNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUNwRSxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNsQyxtQkFBbUIsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDakQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMseUNBQXlDLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDdkQsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFckIsdUNBQXVDO1FBQ3ZDLElBQUksTUFBTSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDNUQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDckMsbUJBQW1CLENBQUMsTUFBTSxNQUFNLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBRWpELE1BQU0sR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUNuRSxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNyQyxtQkFBbUIsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDbkQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsdUNBQXVDLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDckQsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDckIsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDckUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDbkMsbUJBQW1CLENBQUMsTUFBTSxNQUFNLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2pELENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLHNDQUFzQyxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ3BELE1BQU0sS0FBSyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3JCLE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3BFLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ2xDLG1CQUFtQixDQUFDLE1BQU0sTUFBTSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNqRCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyx5Q0FBeUMsRUFBRSxLQUFLLElBQUksRUFBRTtRQUN2RCxNQUFNLEtBQUssR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFeEIsdUNBQXVDO1FBQ3ZDLElBQUksTUFBTSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDNUQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDckMsbUJBQW1CLENBQUMsTUFBTSxNQUFNLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBRWpELE1BQU0sR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUNuRSxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNyQyxtQkFBbUIsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDbkQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsdUNBQXVDLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDckQsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3hCLE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3JFLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ25DLG1CQUFtQixDQUFDLE1BQU0sTUFBTSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNqRCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxzQ0FBc0MsRUFBRSxLQUFLLElBQUksRUFBRTtRQUNwRCxNQUFNLEtBQUssR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDeEIsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDcEUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDbEMsbUJBQW1CLENBQUMsTUFBTSxNQUFNLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2pELENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLHlDQUF5QyxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ3ZELE1BQU0sS0FBSyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFM0IsdUNBQXVDO1FBQ3ZDLElBQUksTUFBTSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDNUQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDckMsbUJBQW1CLENBQUMsTUFBTSxNQUFNLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBRWpELE1BQU0sR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3hELE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3JDLG1CQUFtQixDQUFDLE1BQU0sTUFBTSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUNuRCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyx1Q0FBdUMsRUFBRSxLQUFLLElBQUksRUFBRTtRQUNyRCxNQUFNLEtBQUssR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzNCLE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3JFLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ25DLG1CQUFtQixDQUFDLE1BQU0sTUFBTSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNqRCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxzQ0FBc0MsRUFBRSxLQUFLLElBQUksRUFBRTtRQUNwRCxNQUFNLEtBQUssR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzNCLE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3BFLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ2xDLG1CQUFtQixDQUFDLE1BQU0sTUFBTSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNqRCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyw4Q0FBOEMsRUFBRSxHQUFHLEVBQUU7UUFDdEQsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDL0QsT0FBTyxFQUFFLENBQUM7SUFDakIsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQztBQUVILFNBQVMsT0FBTyxDQUFDLENBQVM7SUFDeEIsT0FBTyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hDLENBQUM7QUFFRCxRQUFRLENBQUMsYUFBYSxFQUFFLEdBQUcsRUFBRTtJQUMzQixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUM7SUFDckIsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBRWxCLEVBQUUsQ0FBQyxtQ0FBbUMsRUFBRSxHQUFHLEVBQUU7UUFDM0MsTUFBTSxJQUFJLEdBQUcsSUFBSSxXQUFXLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ3JDLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDL0MsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsOENBQThDLEVBQUUsR0FBRyxFQUFFO1FBQ3RELE1BQU0sSUFBSSxHQUNOLElBQUksV0FBVyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLEtBQUssQ0FBQyxlQUFlLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDcEUsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDO1FBQ2xCLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQztRQUNuQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQzdCLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUM7U0FDL0I7UUFDRCx5QkFBeUIsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNuRCx1QkFBdUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNsQyxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyw2QkFBNkIsRUFBRSxHQUFHLEVBQUU7UUFDckMsTUFBTSxJQUFJLEdBQUcsSUFBSSxXQUFXLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUM1QyxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2hELENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLDRDQUE0QyxFQUFFLEdBQUcsRUFBRTtRQUNwRCxNQUFNLElBQUksR0FBRyxJQUFJLFdBQVcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxLQUFLLENBQUMsZUFBZSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ3pFLE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQztRQUNsQixNQUFNLElBQUksR0FBRyxLQUFLLENBQUM7UUFDbkIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUM3QixNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDO1NBQy9CO1FBQ0QseUJBQXlCLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDakQsdUJBQXVCLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDbEMsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMscUVBQXFFLEVBQ3JFLEdBQUcsRUFBRTtRQUNILE1BQU0sSUFBSSxHQUFHLEdBQUcsQ0FBQztRQUNqQixNQUFNLElBQUksR0FBRyxJQUFJLFdBQVcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7UUFDdkUsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUM3QixNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUM7U0FDM0Q7SUFDSCxDQUFDLENBQUMsQ0FBQztBQUNSLENBQUMsQ0FBQyxDQUFDO0FBRUgsUUFBUSxDQUFDLFdBQVcsRUFBRSxHQUFHLEVBQUU7SUFDekIsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBRWxCLEVBQUUsQ0FBQyxtQ0FBbUMsRUFBRSxHQUFHLEVBQUU7UUFDM0MsTUFBTSxJQUFJLEdBQUcsSUFBSSxTQUFTLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUM1QyxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQy9DLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLGdEQUFnRCxFQUFFLEdBQUcsRUFBRTtRQUN4RCxNQUFNLElBQUksR0FBRyxJQUFJLFNBQVMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNsRCxNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUM7UUFDbEIsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDO1FBQ25CLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDN0IsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQztTQUMvQjtRQUNELG1CQUFtQixDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDckMsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsNkJBQTZCLEVBQUUsR0FBRyxFQUFFO1FBQ3JDLE1BQU0sSUFBSSxHQUFHLElBQUksU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDMUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNoRCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyw4Q0FBOEMsRUFBRSxHQUFHLEVBQUU7UUFDdEQsTUFBTSxJQUFJLEdBQUcsSUFBSSxTQUFTLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDaEQsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDO1FBQ2xCLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQztRQUNuQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQzdCLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUM7U0FDL0I7UUFDRCxtQkFBbUIsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3JDLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUM7QUFFSCxRQUFRLENBQUMsZUFBZSxFQUFFLEdBQUcsRUFBRTtJQUM3QixFQUFFLENBQUMsa0JBQWtCLEVBQUUsR0FBRyxFQUFFO1FBQzFCLE1BQU0sR0FBRyxHQUFHLEdBQUcsQ0FBQztRQUNoQixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUM7UUFDakIsTUFBTSxLQUFLLEdBQUcsU0FBUyxDQUFDO1FBQ3hCLE1BQU0sRUFBRSxHQUFhLEVBQUUsQ0FBQztRQUN4QixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFO1lBQzNCLE1BQU0sSUFBSSxHQUFHLElBQUksYUFBYSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDaEQsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQzNCLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDWjtRQUNELE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxzQkFBc0IsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNwRCxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzVDLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLGdCQUFnQixFQUFFLEdBQUcsRUFBRTtRQUN4QixNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUM7UUFDZixNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUM7UUFDZixNQUFNLEtBQUssR0FBRyxPQUFPLENBQUM7UUFDdEIsTUFBTSxFQUFFLEdBQWEsRUFBRSxDQUFDO1FBQ3hCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUU7WUFDM0IsTUFBTSxJQUFJLEdBQUcsSUFBSSxhQUFhLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUNoRCxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDM0IsTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDMUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNaO1FBQ0QsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLHNCQUFzQixDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3BELE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNuRCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxnQkFBZ0IsRUFBRSxHQUFHLEVBQUU7UUFDeEIsTUFBTSxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUM7UUFDakIsTUFBTSxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUM7UUFDakIsTUFBTSxLQUFLLEdBQUcsU0FBUyxDQUFDO1FBQ3hCLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQztRQUNsQixNQUFNLEVBQUUsR0FBYSxFQUFFLENBQUM7UUFDeEIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRTtZQUMzQixNQUFNLElBQUksR0FBRyxJQUFJLGFBQWEsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztZQUN0RCxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDM0IsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLHNCQUFzQixDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3RDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDNUIsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNaO1FBQ0QsZ0NBQWdDO1FBQ2hDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbkQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsZUFBZSxFQUFFLEdBQUcsRUFBRTtRQUN2QixNQUFNLEdBQUcsR0FBRyxDQUFDLENBQUM7UUFDZCxNQUFNLEdBQUcsR0FBRyxDQUFDLENBQUM7UUFDZCxNQUFNLEtBQUssR0FBRyxTQUFTLENBQUM7UUFDeEIsTUFBTSxJQUFJLEdBQVcsSUFBSSxDQUFDO1FBQzFCLE1BQU0sSUFBSSxHQUFHLElBQUksYUFBYSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ3RELE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUMzQixNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDcEMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM1QixDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxvQkFBb0IsRUFBRSxHQUFHLEVBQUU7UUFDNUIsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDO1FBQ2QsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDO1FBQ2QsTUFBTSxLQUFLLEdBQUcsU0FBUyxDQUFDO1FBQ3hCLE1BQU0sSUFBSSxHQUFXLFNBQVMsQ0FBQztRQUMvQixNQUFNLElBQUksR0FBRyxJQUFJLGFBQWEsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztRQUN0RCxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDM0IsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLHNCQUFzQixDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3BDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDNUIsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTEMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKi9cblxuaW1wb3J0IHt1dGlsfSBmcm9tICcuLic7XG5pbXBvcnQgKiBhcyB0ZiBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQge0FMTF9FTlZTLCBkZXNjcmliZVdpdGhGbGFnc30gZnJvbSAnLi4vamFzbWluZV91dGlsJztcbmltcG9ydCB7ZXhwZWN0VmFsdWVzSW5SYW5nZX0gZnJvbSAnLi4vdGVzdF91dGlsJztcblxuaW1wb3J0IHtNUFJhbmRHYXVzcywgUmFuZEdhbW1hLCBVbmlmb3JtUmFuZG9tfSBmcm9tICcuL3JhbmRfdXRpbCc7XG5pbXBvcnQge2V4cGVjdEFycmF5SW5NZWFuU3RkUmFuZ2UsIGphcnF1ZUJlcmFOb3JtYWxpdHlUZXN0fSBmcm9tICcuL3JhbmRfdXRpbCc7XG5cbmRlc2NyaWJlV2l0aEZsYWdzKCdyYW5kJywgQUxMX0VOVlMsICgpID0+IHtcbiAgaXQoJ3Nob3VsZCByZXR1cm4gYSByYW5kb20gMUQgZmxvYXQzMiBhcnJheScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzaGFwZTogW251bWJlcl0gPSBbMTBdO1xuXG4gICAgLy8gRW51c3JlIGRlZmF1bHRzIHRvIGZsb2F0MzIgdy9vIHR5cGU6XG4gICAgbGV0IHJlc3VsdCA9IHRmLnJhbmQoc2hhcGUsICgpID0+IHV0aWwucmFuZFVuaWZvcm0oMCwgMikpO1xuICAgIGV4cGVjdChyZXN1bHQuZHR5cGUpLnRvQmUoJ2Zsb2F0MzInKTtcbiAgICBleHBlY3RWYWx1ZXNJblJhbmdlKGF3YWl0IHJlc3VsdC5kYXRhKCksIDAsIDIpO1xuXG4gICAgcmVzdWx0ID0gdGYucmFuZChzaGFwZSwgKCkgPT4gdXRpbC5yYW5kVW5pZm9ybSgwLCAxLjUpKTtcbiAgICBleHBlY3QocmVzdWx0LmR0eXBlKS50b0JlKCdmbG9hdDMyJyk7XG4gICAgZXhwZWN0VmFsdWVzSW5SYW5nZShhd2FpdCByZXN1bHQuZGF0YSgpLCAwLCAxLjUpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHJldHVybiBhIHJhbmRvbSAxRCBpbnQzMiBhcnJheScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzaGFwZTogW251bWJlcl0gPSBbMTBdO1xuICAgIGNvbnN0IHJlc3VsdCA9IHRmLnJhbmQoc2hhcGUsICgpID0+IHV0aWwucmFuZFVuaWZvcm0oMCwgMiksICdpbnQzMicpO1xuICAgIGV4cGVjdChyZXN1bHQuZHR5cGUpLnRvQmUoJ2ludDMyJyk7XG4gICAgZXhwZWN0VmFsdWVzSW5SYW5nZShhd2FpdCByZXN1bHQuZGF0YSgpLCAwLCAyKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByZXR1cm4gYSByYW5kb20gMUQgYm9vbCBhcnJheScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzaGFwZTogW251bWJlcl0gPSBbMTBdO1xuICAgIGNvbnN0IHJlc3VsdCA9IHRmLnJhbmQoc2hhcGUsICgpID0+IHV0aWwucmFuZFVuaWZvcm0oMCwgMSksICdib29sJyk7XG4gICAgZXhwZWN0KHJlc3VsdC5kdHlwZSkudG9CZSgnYm9vbCcpO1xuICAgIGV4cGVjdFZhbHVlc0luUmFuZ2UoYXdhaXQgcmVzdWx0LmRhdGEoKSwgMCwgMSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmV0dXJuIGEgcmFuZG9tIDJEIGZsb2F0MzIgYXJyYXknLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgc2hhcGUgPSBbMywgNF07XG5cbiAgICAvLyBFbnVzcmUgZGVmYXVsdHMgdG8gZmxvYXQzMiB3L28gdHlwZTpcbiAgICBsZXQgcmVzdWx0ID0gdGYucmFuZChzaGFwZSwgKCkgPT4gdXRpbC5yYW5kVW5pZm9ybSgwLCAyLjUpKTtcbiAgICBleHBlY3QocmVzdWx0LmR0eXBlKS50b0JlKCdmbG9hdDMyJyk7XG4gICAgZXhwZWN0VmFsdWVzSW5SYW5nZShhd2FpdCByZXN1bHQuZGF0YSgpLCAwLCAyLjUpO1xuXG4gICAgcmVzdWx0ID0gdGYucmFuZChzaGFwZSwgKCkgPT4gdXRpbC5yYW5kVW5pZm9ybSgwLCAxLjUpLCAnZmxvYXQzMicpO1xuICAgIGV4cGVjdChyZXN1bHQuZHR5cGUpLnRvQmUoJ2Zsb2F0MzInKTtcbiAgICBleHBlY3RWYWx1ZXNJblJhbmdlKGF3YWl0IHJlc3VsdC5kYXRhKCksIDAsIDEuNSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmV0dXJuIGEgcmFuZG9tIDJEIGludDMyIGFycmF5JywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHNoYXBlID0gWzMsIDRdO1xuICAgIGNvbnN0IHJlc3VsdCA9IHRmLnJhbmQoc2hhcGUsICgpID0+IHV0aWwucmFuZFVuaWZvcm0oMCwgMiksICdpbnQzMicpO1xuICAgIGV4cGVjdChyZXN1bHQuZHR5cGUpLnRvQmUoJ2ludDMyJyk7XG4gICAgZXhwZWN0VmFsdWVzSW5SYW5nZShhd2FpdCByZXN1bHQuZGF0YSgpLCAwLCAyKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByZXR1cm4gYSByYW5kb20gMkQgYm9vbCBhcnJheScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzaGFwZSA9IFszLCA0XTtcbiAgICBjb25zdCByZXN1bHQgPSB0Zi5yYW5kKHNoYXBlLCAoKSA9PiB1dGlsLnJhbmRVbmlmb3JtKDAsIDEpLCAnYm9vbCcpO1xuICAgIGV4cGVjdChyZXN1bHQuZHR5cGUpLnRvQmUoJ2Jvb2wnKTtcbiAgICBleHBlY3RWYWx1ZXNJblJhbmdlKGF3YWl0IHJlc3VsdC5kYXRhKCksIDAsIDEpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHJldHVybiBhIHJhbmRvbSAzRCBmbG9hdDMyIGFycmF5JywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHNoYXBlID0gWzMsIDQsIDVdO1xuXG4gICAgLy8gRW51c3JlIGRlZmF1bHRzIHRvIGZsb2F0MzIgdy9vIHR5cGU6XG4gICAgbGV0IHJlc3VsdCA9IHRmLnJhbmQoc2hhcGUsICgpID0+IHV0aWwucmFuZFVuaWZvcm0oMCwgMi41KSk7XG4gICAgZXhwZWN0KHJlc3VsdC5kdHlwZSkudG9CZSgnZmxvYXQzMicpO1xuICAgIGV4cGVjdFZhbHVlc0luUmFuZ2UoYXdhaXQgcmVzdWx0LmRhdGEoKSwgMCwgMi41KTtcblxuICAgIHJlc3VsdCA9IHRmLnJhbmQoc2hhcGUsICgpID0+IHV0aWwucmFuZFVuaWZvcm0oMCwgMS41KSwgJ2Zsb2F0MzInKTtcbiAgICBleHBlY3QocmVzdWx0LmR0eXBlKS50b0JlKCdmbG9hdDMyJyk7XG4gICAgZXhwZWN0VmFsdWVzSW5SYW5nZShhd2FpdCByZXN1bHQuZGF0YSgpLCAwLCAxLjUpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHJldHVybiBhIHJhbmRvbSAzRCBpbnQzMiBhcnJheScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzaGFwZSA9IFszLCA0LCA1XTtcbiAgICBjb25zdCByZXN1bHQgPSB0Zi5yYW5kKHNoYXBlLCAoKSA9PiB1dGlsLnJhbmRVbmlmb3JtKDAsIDIpLCAnaW50MzInKTtcbiAgICBleHBlY3QocmVzdWx0LmR0eXBlKS50b0JlKCdpbnQzMicpO1xuICAgIGV4cGVjdFZhbHVlc0luUmFuZ2UoYXdhaXQgcmVzdWx0LmRhdGEoKSwgMCwgMik7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmV0dXJuIGEgcmFuZG9tIDNEIGJvb2wgYXJyYXknLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgc2hhcGUgPSBbMywgNCwgNV07XG4gICAgY29uc3QgcmVzdWx0ID0gdGYucmFuZChzaGFwZSwgKCkgPT4gdXRpbC5yYW5kVW5pZm9ybSgwLCAxKSwgJ2Jvb2wnKTtcbiAgICBleHBlY3QocmVzdWx0LmR0eXBlKS50b0JlKCdib29sJyk7XG4gICAgZXhwZWN0VmFsdWVzSW5SYW5nZShhd2FpdCByZXN1bHQuZGF0YSgpLCAwLCAxKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByZXR1cm4gYSByYW5kb20gNEQgZmxvYXQzMiBhcnJheScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzaGFwZSA9IFszLCA0LCA1LCA2XTtcblxuICAgIC8vIEVudXNyZSBkZWZhdWx0cyB0byBmbG9hdDMyIHcvbyB0eXBlOlxuICAgIGxldCByZXN1bHQgPSB0Zi5yYW5kKHNoYXBlLCAoKSA9PiB1dGlsLnJhbmRVbmlmb3JtKDAsIDIuNSkpO1xuICAgIGV4cGVjdChyZXN1bHQuZHR5cGUpLnRvQmUoJ2Zsb2F0MzInKTtcbiAgICBleHBlY3RWYWx1ZXNJblJhbmdlKGF3YWl0IHJlc3VsdC5kYXRhKCksIDAsIDIuNSk7XG5cbiAgICByZXN1bHQgPSB0Zi5yYW5kKHNoYXBlLCAoKSA9PiB1dGlsLnJhbmRVbmlmb3JtKDAsIDEuNSkpO1xuICAgIGV4cGVjdChyZXN1bHQuZHR5cGUpLnRvQmUoJ2Zsb2F0MzInKTtcbiAgICBleHBlY3RWYWx1ZXNJblJhbmdlKGF3YWl0IHJlc3VsdC5kYXRhKCksIDAsIDEuNSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmV0dXJuIGEgcmFuZG9tIDREIGludDMyIGFycmF5JywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHNoYXBlID0gWzMsIDQsIDUsIDZdO1xuICAgIGNvbnN0IHJlc3VsdCA9IHRmLnJhbmQoc2hhcGUsICgpID0+IHV0aWwucmFuZFVuaWZvcm0oMCwgMiksICdpbnQzMicpO1xuICAgIGV4cGVjdChyZXN1bHQuZHR5cGUpLnRvQmUoJ2ludDMyJyk7XG4gICAgZXhwZWN0VmFsdWVzSW5SYW5nZShhd2FpdCByZXN1bHQuZGF0YSgpLCAwLCAyKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByZXR1cm4gYSByYW5kb20gNEQgYm9vbCBhcnJheScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzaGFwZSA9IFszLCA0LCA1LCA2XTtcbiAgICBjb25zdCByZXN1bHQgPSB0Zi5yYW5kKHNoYXBlLCAoKSA9PiB1dGlsLnJhbmRVbmlmb3JtKDAsIDEpLCAnYm9vbCcpO1xuICAgIGV4cGVjdChyZXN1bHQuZHR5cGUpLnRvQmUoJ2Jvb2wnKTtcbiAgICBleHBlY3RWYWx1ZXNJblJhbmdlKGF3YWl0IHJlc3VsdC5kYXRhKCksIDAsIDEpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHRocm93IGVycm9yIHdoZW4gc2hhcGUgaXMgbm90IGludGVnZXInLCAoKSA9PiB7XG4gICAgZXhwZWN0KCgpID0+IHRmLnJhbmQoWzIsIDIuMjIsIDMuMzNdLCAoKSA9PiB1dGlsLnJhbmRVbmlmb3JtKDAsIDIpKSlcbiAgICAgICAgLnRvVGhyb3coKTtcbiAgfSk7XG59KTtcblxuZnVuY3Rpb24gaXNGbG9hdChuOiBudW1iZXIpOiBib29sZWFuIHtcbiAgcmV0dXJuIE51bWJlcihuKSA9PT0gbiAmJiBuICUgMSAhPT0gMDtcbn1cblxuZGVzY3JpYmUoJ01QUmFuZEdhdXNzJywgKCkgPT4ge1xuICBjb25zdCBFUFNJTE9OID0gMC4wNTtcbiAgY29uc3QgU0VFRCA9IDIwMDI7XG5cbiAgaXQoJ3Nob3VsZCBkZWZhdWx0IHRvIGZsb2F0MzIgbnVtYmVycycsICgpID0+IHtcbiAgICBjb25zdCByYW5kID0gbmV3IE1QUmFuZEdhdXNzKDAsIDEuNSk7XG4gICAgZXhwZWN0KGlzRmxvYXQocmFuZC5uZXh0VmFsdWUoKSkpLnRvQmUodHJ1ZSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgaGFuZGxlIGEgbWVhbi9zdGR2IG9mIGZsb2F0MzIgbnVtYmVycycsICgpID0+IHtcbiAgICBjb25zdCByYW5kID1cbiAgICAgICAgbmV3IE1QUmFuZEdhdXNzKDAsIDEuNSwgJ2Zsb2F0MzInLCBmYWxzZSAvKiB0cnVuY2F0ZWQgKi8sIFNFRUQpO1xuICAgIGNvbnN0IHZhbHVlcyA9IFtdO1xuICAgIGNvbnN0IHNpemUgPSAxMDAwMDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNpemU7IGkrKykge1xuICAgICAgdmFsdWVzLnB1c2gocmFuZC5uZXh0VmFsdWUoKSk7XG4gICAgfVxuICAgIGV4cGVjdEFycmF5SW5NZWFuU3RkUmFuZ2UodmFsdWVzLCAwLCAxLjUsIEVQU0lMT04pO1xuICAgIGphcnF1ZUJlcmFOb3JtYWxpdHlUZXN0KHZhbHVlcyk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgaGFuZGxlIGludDMyIG51bWJlcnMnLCAoKSA9PiB7XG4gICAgY29uc3QgcmFuZCA9IG5ldyBNUFJhbmRHYXVzcygwLCAxLCAnaW50MzInKTtcbiAgICBleHBlY3QoaXNGbG9hdChyYW5kLm5leHRWYWx1ZSgpKSkudG9CZShmYWxzZSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgaGFuZGxlIGEgbWVhbi9zdGR2IG9mIGludDMyIG51bWJlcnMnLCAoKSA9PiB7XG4gICAgY29uc3QgcmFuZCA9IG5ldyBNUFJhbmRHYXVzcygwLCAyLCAnaW50MzInLCBmYWxzZSAvKiB0cnVuY2F0ZWQgKi8sIFNFRUQpO1xuICAgIGNvbnN0IHZhbHVlcyA9IFtdO1xuICAgIGNvbnN0IHNpemUgPSAxMDAwMDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNpemU7IGkrKykge1xuICAgICAgdmFsdWVzLnB1c2gocmFuZC5uZXh0VmFsdWUoKSk7XG4gICAgfVxuICAgIGV4cGVjdEFycmF5SW5NZWFuU3RkUmFuZ2UodmFsdWVzLCAwLCAyLCBFUFNJTE9OKTtcbiAgICBqYXJxdWVCZXJhTm9ybWFsaXR5VGVzdCh2YWx1ZXMpO1xuICB9KTtcblxuICBpdCgnU2hvdWxkIG5vdCBoYXZlIGEgbW9yZSB0aGFuIDJ4IHN0ZC1kIGZyb20gbWVhbiBmb3IgdHJ1bmNhdGVkIHZhbHVlcycsXG4gICAgICgpID0+IHtcbiAgICAgICBjb25zdCBzdGR2ID0gMS41O1xuICAgICAgIGNvbnN0IHJhbmQgPSBuZXcgTVBSYW5kR2F1c3MoMCwgc3RkdiwgJ2Zsb2F0MzInLCB0cnVlIC8qIHRydW5jYXRlZCAqLyk7XG4gICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAxMDAwOyBpKyspIHtcbiAgICAgICAgIGV4cGVjdChNYXRoLmFicyhyYW5kLm5leHRWYWx1ZSgpKSkudG9CZUxlc3NUaGFuKHN0ZHYgKiAyKTtcbiAgICAgICB9XG4gICAgIH0pO1xufSk7XG5cbmRlc2NyaWJlKCdSYW5kR2FtbWEnLCAoKSA9PiB7XG4gIGNvbnN0IFNFRUQgPSAyMDAyO1xuXG4gIGl0KCdzaG91bGQgZGVmYXVsdCB0byBmbG9hdDMyIG51bWJlcnMnLCAoKSA9PiB7XG4gICAgY29uc3QgcmFuZCA9IG5ldyBSYW5kR2FtbWEoMiwgMiwgJ2Zsb2F0MzInKTtcbiAgICBleHBlY3QoaXNGbG9hdChyYW5kLm5leHRWYWx1ZSgpKSkudG9CZSh0cnVlKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBoYW5kbGUgYW4gYWxwaGEvYmV0YSBvZiBmbG9hdDMyIG51bWJlcnMnLCAoKSA9PiB7XG4gICAgY29uc3QgcmFuZCA9IG5ldyBSYW5kR2FtbWEoMiwgMiwgJ2Zsb2F0MzInLCBTRUVEKTtcbiAgICBjb25zdCB2YWx1ZXMgPSBbXTtcbiAgICBjb25zdCBzaXplID0gMTAwMDA7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHtcbiAgICAgIHZhbHVlcy5wdXNoKHJhbmQubmV4dFZhbHVlKCkpO1xuICAgIH1cbiAgICBleHBlY3RWYWx1ZXNJblJhbmdlKHZhbHVlcywgMCwgMzApO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIGhhbmRsZSBpbnQzMiBudW1iZXJzJywgKCkgPT4ge1xuICAgIGNvbnN0IHJhbmQgPSBuZXcgUmFuZEdhbW1hKDIsIDIsICdpbnQzMicpO1xuICAgIGV4cGVjdChpc0Zsb2F0KHJhbmQubmV4dFZhbHVlKCkpKS50b0JlKGZhbHNlKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBoYW5kbGUgYW4gYWxwaGEvYmV0YSBvZiBpbnQzMiBudW1iZXJzJywgKCkgPT4ge1xuICAgIGNvbnN0IHJhbmQgPSBuZXcgUmFuZEdhbW1hKDIsIDIsICdpbnQzMicsIFNFRUQpO1xuICAgIGNvbnN0IHZhbHVlcyA9IFtdO1xuICAgIGNvbnN0IHNpemUgPSAxMDAwMDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNpemU7IGkrKykge1xuICAgICAgdmFsdWVzLnB1c2gocmFuZC5uZXh0VmFsdWUoKSk7XG4gICAgfVxuICAgIGV4cGVjdFZhbHVlc0luUmFuZ2UodmFsdWVzLCAwLCAzMCk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKCdVbmlmb3JtUmFuZG9tJywgKCkgPT4ge1xuICBpdCgnZmxvYXQzMiwgbm8gc2VlZCcsICgpID0+IHtcbiAgICBjb25zdCBtaW4gPSAwLjI7XG4gICAgY29uc3QgbWF4ID0gMC4yNDtcbiAgICBjb25zdCBkdHlwZSA9ICdmbG9hdDMyJztcbiAgICBjb25zdCB4czogbnVtYmVyW10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDEwOyArK2kpIHtcbiAgICAgIGNvbnN0IHJhbmQgPSBuZXcgVW5pZm9ybVJhbmRvbShtaW4sIG1heCwgZHR5cGUpO1xuICAgICAgY29uc3QgeCA9IHJhbmQubmV4dFZhbHVlKCk7XG4gICAgICB4cy5wdXNoKHgpO1xuICAgIH1cbiAgICBleHBlY3QoTWF0aC5taW4oLi4ueHMpKS50b0JlR3JlYXRlclRoYW5PckVxdWFsKG1pbik7XG4gICAgZXhwZWN0KE1hdGgubWF4KC4uLnhzKSkudG9CZUxlc3NUaGFuKG1heCk7XG4gIH0pO1xuXG4gIGl0KCdpbnQzMiwgbm8gc2VlZCcsICgpID0+IHtcbiAgICBjb25zdCBtaW4gPSAxMztcbiAgICBjb25zdCBtYXggPSAzNztcbiAgICBjb25zdCBkdHlwZSA9ICdpbnQzMic7XG4gICAgY29uc3QgeHM6IG51bWJlcltdID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCAxMDsgKytpKSB7XG4gICAgICBjb25zdCByYW5kID0gbmV3IFVuaWZvcm1SYW5kb20obWluLCBtYXgsIGR0eXBlKTtcbiAgICAgIGNvbnN0IHggPSByYW5kLm5leHRWYWx1ZSgpO1xuICAgICAgZXhwZWN0KE51bWJlci5pc0ludGVnZXIoeCkpLnRvRXF1YWwodHJ1ZSk7XG4gICAgICB4cy5wdXNoKHgpO1xuICAgIH1cbiAgICBleHBlY3QoTWF0aC5taW4oLi4ueHMpKS50b0JlR3JlYXRlclRoYW5PckVxdWFsKG1pbik7XG4gICAgZXhwZWN0KE1hdGgubWF4KC4uLnhzKSkudG9CZUxlc3NUaGFuT3JFcXVhbChtYXgpO1xuICB9KTtcblxuICBpdCgnc2VlZCBpcyBudW1iZXInLCAoKSA9PiB7XG4gICAgY29uc3QgbWluID0gLTEuMjtcbiAgICBjb25zdCBtYXggPSAtMC40O1xuICAgIGNvbnN0IGR0eXBlID0gJ2Zsb2F0MzInO1xuICAgIGNvbnN0IHNlZWQgPSAxMzM3O1xuICAgIGNvbnN0IHhzOiBudW1iZXJbXSA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMTA7ICsraSkge1xuICAgICAgY29uc3QgcmFuZCA9IG5ldyBVbmlmb3JtUmFuZG9tKG1pbiwgbWF4LCBkdHlwZSwgc2VlZCk7XG4gICAgICBjb25zdCB4ID0gcmFuZC5uZXh0VmFsdWUoKTtcbiAgICAgIGV4cGVjdCh4KS50b0JlR3JlYXRlclRoYW5PckVxdWFsKG1pbik7XG4gICAgICBleHBlY3QoeCkudG9CZUxlc3NUaGFuKG1heCk7XG4gICAgICB4cy5wdXNoKHgpO1xuICAgIH1cbiAgICAvLyBBc3NlcnQgZGV0ZXJtaW5pc3RpYyByZXN1bHRzLlxuICAgIGV4cGVjdChNYXRoLm1pbiguLi54cykpLnRvRXF1YWwoTWF0aC5tYXgoLi4ueHMpKTtcbiAgfSk7XG5cbiAgaXQoJ3NlZWQgPT09IG51bGwnLCAoKSA9PiB7XG4gICAgY29uc3QgbWluID0gMDtcbiAgICBjb25zdCBtYXggPSAxO1xuICAgIGNvbnN0IGR0eXBlID0gJ2Zsb2F0MzInO1xuICAgIGNvbnN0IHNlZWQ6IG51bWJlciA9IG51bGw7XG4gICAgY29uc3QgcmFuZCA9IG5ldyBVbmlmb3JtUmFuZG9tKG1pbiwgbWF4LCBkdHlwZSwgc2VlZCk7XG4gICAgY29uc3QgeCA9IHJhbmQubmV4dFZhbHVlKCk7XG4gICAgZXhwZWN0KHgpLnRvQmVHcmVhdGVyVGhhbk9yRXF1YWwoMCk7XG4gICAgZXhwZWN0KHgpLnRvQmVMZXNzVGhhbigxKTtcbiAgfSk7XG5cbiAgaXQoJ3NlZWQgPT09IHVuZGVmaW5lZCcsICgpID0+IHtcbiAgICBjb25zdCBtaW4gPSAwO1xuICAgIGNvbnN0IG1heCA9IDE7XG4gICAgY29uc3QgZHR5cGUgPSAnZmxvYXQzMic7XG4gICAgY29uc3Qgc2VlZDogbnVtYmVyID0gdW5kZWZpbmVkO1xuICAgIGNvbnN0IHJhbmQgPSBuZXcgVW5pZm9ybVJhbmRvbShtaW4sIG1heCwgZHR5cGUsIHNlZWQpO1xuICAgIGNvbnN0IHggPSByYW5kLm5leHRWYWx1ZSgpO1xuICAgIGV4cGVjdCh4KS50b0JlR3JlYXRlclRoYW5PckVxdWFsKDApO1xuICAgIGV4cGVjdCh4KS50b0JlTGVzc1RoYW4oMSk7XG4gIH0pO1xufSk7XG4iXX0=