/** * @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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmFuZF90ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vdGZqcy1jb3JlL3NyYy9vcHMvcmFuZF90ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUVILE9BQU8sRUFBQyxJQUFJLEVBQUMsTUFBTSxJQUFJLENBQUM7QUFDeEIsT0FBTyxLQUFLLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDL0IsT0FBTyxFQUFDLFFBQVEsRUFBRSxpQkFBaUIsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQzVELE9BQU8sRUFBQyxtQkFBbUIsRUFBQyxNQUFNLGNBQWMsQ0FBQztBQUVqRCxPQUFPLEVBQUMsV0FBVyxFQUFFLFNBQVMsRUFBRSxhQUFhLEVBQUMsTUFBTSxhQUFhLENBQUM7QUFDbEUsT0FBTyxFQUFDLHlCQUF5QixFQUFFLHVCQUF1QixFQUFDLE1BQU0sYUFBYSxDQUFDO0FBRS9FLGlCQUFpQixDQUFDLE1BQU0sRUFBRSxRQUFRLEVBQUUsR0FBRyxFQUFFO0lBQ3ZDLEVBQUUsQ0FBQyx5Q0FBeUMsRUFBRSxLQUFLLElBQUksRUFBRTtRQUN2RCxNQUFNLEtBQUssR0FBYSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBRTdCLHVDQUF1QztRQUN2QyxJQUFJLE1BQU0sR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzFELE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3JDLG1CQUFtQixDQUFDLE1BQU0sTUFBTSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUUvQyxNQUFNLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUN4RCxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNyQyxtQkFBbUIsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDbkQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsdUNBQXVDLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDckQsTUFBTSxLQUFLLEdBQWEsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUM3QixNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNyRSxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNuQyxtQkFBbUIsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDakQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsc0NBQXNDLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDcEQsTUFBTSxLQUFLLEdBQWEsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUM3QixNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUNwRSxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNsQyxtQkFBbUIsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDakQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMseUNBQXlDLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDdkQsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFckIsdUNBQXVDO1FBQ3ZDLElBQUksTUFBTSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDNUQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDckMsbUJBQW1CLENBQUMsTUFBTSxNQUFNLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBRWpELE1BQU0sR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUNuRSxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNyQyxtQkFBbUIsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDbkQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsdUNBQXVDLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDckQsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDckIsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFD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QUFNLEtBQUssR0FBRyxTQUFTLENBQUM7UUFDeEIsTUFBTSxJQUFJLEdBQVcsSUFBSSxDQUFDO1FBQzFCLE1BQU0sSUFBSSxHQUFHLElBQUksYUFBYSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ3RELE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUMzQixNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDcEMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM1QixDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxvQkFBb0IsRUFBRSxHQUFHLEVBQUU7UUFDNUIsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDO1FBQ2QsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDO1FBQ2QsTUFBTSxLQUFLLEdBQUcsU0FBUyxDQUFDO1FBQ3hCLE1BQU0sSUFBSSxHQUFXLFNBQVMsQ0FBQztRQUMvQixNQUFNLElBQUksR0FBRyxJQUFJLGFBQWEsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztRQUN0RCxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDM0IsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLHNCQUFzQixDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3BDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDNUIsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTEMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKi9cblxuaW1wb3J0IHt1dGlsfSBmcm9tICcuLic7XG5pbXBvcnQgKiBhcyB0ZiBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQge0FMTF9FTlZTLCBkZXNjcmliZVdpdGhGbGFnc30gZnJvbSAnLi4vamFzbWluZV91dGlsJztcbmltcG9ydCB7ZXhwZWN0VmFsdWVzSW5SYW5nZX0gZnJvbSAnLi4vdGVzdF91dGlsJztcblxuaW1wb3J0IHtNUFJhbmRHYXVzcywgUmFuZEdhbW1hLCBVbmlmb3JtUmFuZG9tfSBmcm9tICcuL3JhbmRfdXRpbCc7XG5pbXBvcnQge2V4cGVjdEFycmF5SW5NZWFuU3RkUmFuZ2UsIGphcnF1ZUJlcmFOb3JtYWxpdHlUZXN0fSBmcm9tICcuL3JhbmRfdXRpbCc7XG5cbmRlc2NyaWJlV2l0aEZsYWdzKCdyYW5kJywgQUxMX0VOVlMsICgpID0+IHtcbiAgaXQoJ3Nob3VsZCByZXR1cm4gYSByYW5kb20gMUQgZmxvYXQzMiBhcnJheScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzaGFwZTogW251bWJlcl0gPSBbMTBdO1xuXG4gICAgLy8gRW51c3JlIGRlZmF1bHRzIHRvIGZsb2F0MzIgdy9vIHR5cGU6XG4gICAgbGV0IHJlc3VsdCA9IHRmLnJhbmQoc2hhcGUsICgpID0+IHV0aWwucmFuZFVuaWZvcm0oMCwgMikpO1xuICAgIGV4cGVjdChyZXN1bHQuZHR5cGUpLnRvQmUoJ2Zsb2F0MzInKTtcbiAgICBleHBlY3RWYWx1ZXNJblJhbmdlKGF3YWl0IHJlc3VsdC5kYXRhKCksIDAsIDIpO1xuXG4gICAgcmVzdWx0ID0gdGYucmFuZChzaGFwZSwgKCkgPT4gdXRpbC5yYW5kVW5pZm9ybSgwLCAxLjUpKTtcbiAgICBleHBlY3QocmVzdWx0LmR0eXBlKS50b0JlKCdmbG9hdDMyJyk7XG4gICAgZXhwZWN0VmFsdWVzSW5SYW5nZShhd2FpdCByZXN1bHQuZGF0YSgpLCAwLCAxLjUpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHJldHVybiBhIHJhbmRvbSAxRCBpbnQzMiBhcnJheScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzaGFwZTogW251bWJlcl0gPSBbMTBdO1xuICAgIGNvbnN0IHJlc3VsdCA9IHRmLnJhbmQoc2hhcGUsICgpID0+IHV0aWwucmFuZFVuaWZvcm0oMCwgMiksICdpbnQzMicpO1xuICAgIGV4cGVjdChyZXN1bHQuZHR5cGUpLnRvQmUoJ2ludDMyJyk7XG4gICAgZXhwZWN0VmFsdWVzSW5SYW5nZShhd2FpdCByZXN1bHQuZGF0YSgpLCAwLCAyKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByZXR1cm4gYSByYW5kb20gMUQgYm9vbCBhcnJheScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzaGFwZTogW251bWJlcl0gPSBbMTBdO1xuICAgIGNvbnN0IHJlc3VsdCA9IHRmLnJhbmQoc2hhcGUsICgpID0+IHV0aWwucmFuZFVuaWZvcm0oMCwgMSksICdib29sJyk7XG4gICAgZXhwZWN0KHJlc3VsdC5kdHlwZSkudG9CZSgnYm9vbCcpO1xuICAgIGV4cGVjdFZhbHVlc0luUmFuZ2UoYXdhaXQgcmVzdWx0LmRhdGEoKSwgMCwgMSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmV0dXJuIGEgcmFuZG9tIDJEIGZsb2F0MzIgYXJyYXknLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgc2hhcGUgPSBbMywgNF07XG5cbiAgICAvLyBFbnVzcmUgZGVmYXVsdHMgdG8gZmxvYXQzMiB3L28gdHlwZTpcbiAgICBsZXQgcmVzdWx0ID0gdGYucmFuZChzaGFwZSwgKCkgPT4gdXRpbC5yYW5kVW5pZm9ybSgwLCAyLjUpKTtcbiAgICBleHBlY3QocmVzdWx0LmR0eXBlKS50b0JlKCdmbG9hdDMyJyk7XG4gICAgZXhwZWN0VmFsdWVzSW5SYW5nZShhd2FpdCByZXN1bHQuZGF0YSgpLCAwLCAyLjUpO1xuXG4gICAgcmVzdWx0ID0gdGYucmFuZChzaGFwZSwgKCkgPT4gdXRpbC5yYW5kVW5pZm9ybSgwLCAxLjUpLCAnZmxvYXQzMicpO1xuICAgIGV4cGVjdChyZXN1bHQuZHR5cGUpLnRvQmUoJ2Zsb2F0MzInKTtcbiAgICBleHBlY3RWYWx1ZXNJblJhbmdlKGF3YWl0IHJlc3VsdC5kYXRhKCksIDAsIDEuNSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmV0dXJuIGEgcmFuZG9tIDJEIGludDMyIGFycmF5JywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHNoYXBlID0gWzMsIDRdO1xuICAgIGNvbnN0IHJlc3VsdCA9IHRmLnJhbmQoc2hhcGUsICgpID0+IHV0aWwucmFuZFVuaWZvcm0oMCwgMiksICdpbnQzMicpO1xuICAgIGV4cGVjdChyZXN1bHQuZHR5cGUpLnRvQmUoJ2ludDMyJyk7XG4gICAgZXhwZWN0VmFsdWVzSW5SYW5nZShhd2FpdCByZXN1bHQuZGF0YSgpLCAwLCAyKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByZXR1cm4gYSByYW5kb20gMkQgYm9vbCBhcnJheScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzaGFwZSA9IFszLCA0XTtcbiAgICBjb25zdCByZXN1bHQgPSB0Zi5yYW5kKHNoYXBlLCAoKSA9PiB1dGlsLnJhbmRVbmlmb3JtKDAsIDEpLCAnYm9vbCcpO1xuICAgIGV4cGVjdChyZXN1bHQuZHR5cGUpLnRvQmUoJ2Jvb2wnKTtcbiAgICBleHBlY3RWYWx1ZXNJblJhbmdlKGF3YWl0IHJlc3VsdC5kYXRhKCksIDAsIDEpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHJldHVybiBhIHJhbmRvbSAzRCBmbG9hdDMyIGFycmF5JywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHNoYXBlID0gWzMsIDQsIDVdO1xuXG4gICAgLy8gRW51c3JlIGRlZmF1bHRzIHRvIGZsb2F0MzIgdy9vIHR5cGU6XG4gICAgbGV0IHJlc3VsdCA9IHRmLnJhbmQoc2hhcGUsICgpID0+IHV0aWwucmFuZFVuaWZvcm0oMCwgMi41KSk7XG4gICAgZXhwZWN0KHJlc3VsdC5kdHlwZSkudG9CZSgnZmxvYXQzMicpO1xuICAgIGV4cGVjdFZhbHVlc0luUmFuZ2UoYXdhaXQgcmVzdWx0LmRhdGEoKSwgMCwgMi41KTtcblxuICAgIHJlc3VsdCA9IHRmLnJhbmQoc2hhcGUsICgpID0+IHV0aWwucmFuZFVuaWZvcm0oMCwgMS41KSwgJ2Zsb2F0MzInKTtcbiAgICBleHBlY3QocmVzdWx0LmR0eXBlKS50b0JlKCdmbG9hdDMyJyk7XG4gICAgZXhwZWN0VmFsdWVzSW5SYW5nZShhd2FpdCByZXN1bHQuZGF0YSgpLCAwLCAxLjUpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHJldHVybiBhIHJhbmRvbSAzRCBpbnQzMiBhcnJheScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzaGFwZSA9IFszLCA0LCA1XTtcbiAgICBjb25zdCByZXN1bHQgPSB0Zi5yYW5kKHNoYXBlLCAoKSA9PiB1dGlsLnJhbmRVbmlmb3JtKDAsIDIpLCAnaW50MzInKTtcbiAgICBleHBlY3QocmVzdWx0LmR0eXBlKS50b0JlKCdpbnQzMicpO1xuICAgIGV4cGVjdFZhbHVlc0luUmFuZ2UoYXdhaXQgcmVzdWx0LmRhdGEoKSwgMCwgMik7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmV0dXJuIGEgcmFuZG9tIDNEIGJvb2wgYXJyYXknLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgc2hhcGUgPSBbMywgNCwgNV07XG4gICAgY29uc3QgcmVzdWx0ID0gdGYucmFuZChzaGFwZSwgKCkgPT4gdXRpbC5yYW5kVW5pZm9ybSgwLCAxKSwgJ2Jvb2wnKTtcbiAgICBleHBlY3QocmVzdWx0LmR0eXBlKS50b0JlKCdib29sJyk7XG4gICAgZXhwZWN0VmFsdWVzSW5SYW5nZShhd2FpdCByZXN1bHQuZGF0YSgpLCAwLCAxKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByZXR1cm4gYSByYW5kb20gNEQgZmxvYXQzMiBhcnJheScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzaGFwZSA9IFszLCA0LCA1LCA2XTtcblxuICAgIC8vIEVudXNyZSBkZWZhdWx0cyB0byBmbG9hdDMyIHcvbyB0eXBlOlxuICAgIGxldCByZXN1bHQgPSB0Zi5yYW5kKHNoYXBlLCAoKSA9PiB1dGlsLnJhbmRVbmlmb3JtKDAsIDIuNSkpO1xuICAgIGV4cGVjdChyZXN1bHQuZHR5cGUpLnRvQmUoJ2Zsb2F0MzInKTtcbiAgICBleHBlY3RWYWx1ZXNJblJhbmdlKGF3YWl0IHJlc3VsdC5kYXRhKCksIDAsIDIuNSk7XG5cbiAgICByZXN1bHQgPSB0Zi5yYW5kKHNoYXBlLCAoKSA9PiB1dGlsLnJhbmRVbmlmb3JtKDAsIDEuNSkpO1xuICAgIGV4cGVjdChyZXN1bHQuZHR5cGUpLnRvQmUoJ2Zsb2F0MzInKTtcbiAgICBleHBlY3RWYWx1ZXNJblJhbmdlKGF3YWl0IHJlc3VsdC5kYXRhKCksIDAsIDEuNSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmV0dXJuIGEgcmFuZG9tIDREIGludDMyIGFycmF5JywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHNoYXBlID0gWzMsIDQsIDUsIDZdO1xuICAgIGNvbnN0IHJlc3VsdCA9IHRmLnJhbmQoc2hhcGUsICgpID0+IHV0aWwucmFuZFVuaWZvcm0oMCwgMiksICdpbnQzMicpO1xuICAgIGV4cGVjdChyZXN1bHQuZHR5cGUpLnRvQmUoJ2ludDMyJyk7XG4gICAgZXhwZWN0VmFsdWVzSW5SYW5nZShhd2FpdCByZXN1bHQuZGF0YSgpLCAwLCAyKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByZXR1cm4gYSByYW5kb20gNEQgYm9vbCBhcnJheScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzaGFwZSA9IFszLCA0LCA1LCA2XTtcbiAgICBjb25zdCByZXN1bHQgPSB0Zi5yYW5kKHNoYXBlLCAoKSA9PiB1dGlsLnJhbmRVbmlmb3JtKDAsIDEpLCAnYm9vbCcpO1xuICAgIGV4cGVjdChyZXN1bHQuZHR5cGUpLnRvQmUoJ2Jvb2wnKTtcbiAgICBleHBlY3RWYWx1ZXNJblJhbmdlKGF3YWl0IHJlc3VsdC5kYXRhKCksIDAsIDEpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHRocm93IGVycm9yIHdoZW4gc2hhcGUgaXMgbm90IGludGVnZXInLCAoKSA9PiB7XG4gICAgZXhwZWN0KCgpID0+IHRmLnJhbmQoWzIsIDIuMjIsIDMuMzNdLCAoKSA9PiB1dGlsLnJhbmRVbmlmb3JtKDAsIDIpKSlcbiAgICAgICAgLnRvVGhyb3coKTtcbiAgfSk7XG59KTtcblxuZnVuY3Rpb24gaXNGbG9hdChuOiBudW1iZXIpOiBib29sZWFuIHtcbiAgcmV0dXJuIE51bWJlcihuKSA9PT0gbiAmJiBuICUgMSAhPT0gMDtcbn1cblxuZGVzY3JpYmUoJ01QUmFuZEdhdXNzJywgKCkgPT4ge1xuICBjb25zdCBFUFNJTE9OID0gMC4wNTtcbiAgY29uc3QgU0VFRCA9IDIwMDI7XG5cbiAgaXQoJ3Nob3VsZCBkZWZhdWx0IHRvIGZsb2F0MzIgbnVtYmVycycsICgpID0+IHtcbiAgICBjb25zdCByYW5kID0gbmV3IE1QUmFuZEdhdXNzKDAsIDEuNSk7XG4gICAgZXhwZWN0KGlzRmxvYXQocmFuZC5uZXh0VmFsdWUoKSkpLnRvQmUodHJ1ZSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgaGFuZGxlIGEgbWVhbi9zdGR2IG9mIGZsb2F0MzIgbnVtYmVycycsICgpID0+IHtcbiAgICBjb25zdCByYW5kID1cbiAgICAgICAgbmV3IE1QUmFuZEdhdXNzKDAsIDEuNSwgJ2Zsb2F0MzInLCBmYWxzZSAvKiB0cnVuY2F0ZWQgKi8sIFNFRUQpO1xuICAgIGNvbnN0IHZhbHVlcyA9IFtdO1xuICAgIGNvbnN0IHNpemUgPSAxMDAwMDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNpemU7IGkrKykge1xuICAgICAgdmFsdWVzLnB1c2gocmFuZC5uZXh0VmFsdWUoKSk7XG4gICAgfVxuICAgIGV4cGVjdEFycmF5SW5NZWFuU3RkUmFuZ2UodmFsdWVzLCAwLCAxLjUsIEVQU0lMT04pO1xuICAgIGphcnF1ZUJlcmFOb3JtYWxpdHlUZXN0KHZhbHVlcyk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgaGFuZGxlIGludDMyIG51bWJlcnMnLCAoKSA9PiB7XG4gICAgY29uc3QgcmFuZCA9IG5ldyBNUFJhbmRHYXVzcygwLCAxLCAnaW50MzInKTtcbiAgICBleHBlY3QoaXNGbG9hdChyYW5kLm5leHRWYWx1ZSgpKSkudG9CZShmYWxzZSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgaGFuZGxlIGEgbWVhbi9zdGR2IG9mIGludDMyIG51bWJlcnMnLCAoKSA9PiB7XG4gICAgY29uc3QgcmFuZCA9IG5ldyBNUFJhbmRHYXVzcygwLCAyLCAnaW50MzInLCBmYWxzZSAvKiB0cnVuY2F0ZWQgKi8sIFNFRUQpO1xuICAgIGNvbnN0IHZhbHVlcyA9IFtdO1xuICAgIGNvbnN0IHNpemUgPSAxMDAwMDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNpemU7IGkrKykge1xuICAgICAgdmFsdWVzLnB1c2gocmFuZC5uZXh0VmFsdWUoKSk7XG4gICAgfVxuICAgIGV4cGVjdEFycmF5SW5NZWFuU3RkUmFuZ2UodmFsdWVzLCAwLCAyLCBFUFNJTE9OKTtcbiAgICBqYXJxdWVCZXJhTm9ybWFsaXR5VGVzdCh2YWx1ZXMpO1xuICB9KTtcblxuICBpdCgnU2hvdWxkIG5vdCBoYXZlIGEgbW9yZSB0aGFuIDJ4IHN0ZC1kIGZyb20gbWVhbiBmb3IgdHJ1bmNhdGVkIHZhbHVlcycsXG4gICAgICgpID0+IHtcbiAgICAgICBjb25zdCBzdGR2ID0gMS41O1xuICAgICAgIGNvbnN0IHJhbmQgPSBuZXcgTVBSYW5kR2F1c3MoMCwgc3RkdiwgJ2Zsb2F0MzInLCB0cnVlIC8qIHRydW5jYXRlZCAqLyk7XG4gICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAxMDAwOyBpKyspIHtcbiAgICAgICAgIGV4cGVjdChNYXRoLmFicyhyYW5kLm5leHRWYWx1ZSgpKSkudG9CZUxlc3NUaGFuKHN0ZHYgKiAyKTtcbiAgICAgICB9XG4gICAgIH0pO1xufSk7XG5cbmRlc2NyaWJlKCdSYW5kR2FtbWEnLCAoKSA9PiB7XG4gIGNvbnN0IFNFRUQgPSAyMDAyO1xuXG4gIGl0KCdzaG91bGQgZGVmYXVsdCB0byBmbG9hdDMyIG51bWJlcnMnLCAoKSA9PiB7XG4gICAgY29uc3QgcmFuZCA9IG5ldyBSYW5kR2FtbWEoMiwgMiwgJ2Zsb2F0MzInKTtcbiAgICBleHBlY3QoaXNGbG9hdChyYW5kLm5leHRWYWx1ZSgpKSkudG9CZSh0cnVlKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBoYW5kbGUgYW4gYWxwaGEvYmV0YSBvZiBmbG9hdDMyIG51bWJlcnMnLCAoKSA9PiB7XG4gICAgY29uc3QgcmFuZCA9IG5ldyBSYW5kR2FtbWEoMiwgMiwgJ2Zsb2F0MzInLCBTRUVEKTtcbiAgICBjb25zdCB2YWx1ZXMgPSBbXTtcbiAgICBjb25zdCBzaXplID0gMTAwMDA7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHtcbiAgICAgIHZhbHVlcy5wdXNoKHJhbmQubmV4dFZhbHVlKCkpO1xuICAgIH1cbiAgICBleHBlY3RWYWx1ZXNJblJhbmdlKHZhbHVlcywgMCwgMzApO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIGhhbmRsZSBpbnQzMiBudW1iZXJzJywgKCkgPT4ge1xuICAgIGNvbnN0IHJhbmQgPSBuZXcgUmFuZEdhbW1hKDIsIDIsICdpbnQzMicpO1xuICAgIGV4cGVjdChpc0Zsb2F0KHJhbmQubmV4dFZhbHVlKCkpKS50b0JlKGZhbHNlKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBoYW5kbGUgYW4gYWxwaGEvYmV0YSBvZiBpbnQzMiBudW1iZXJzJywgKCkgPT4ge1xuICAgIGNvbnN0IHJhbmQgPSBuZXcgUmFuZEdhbW1hKDIsIDIsICdpbnQzMicsIFNFRUQpO1xuICAgIGNvbnN0IHZhbHVlcyA9IFtdO1xuICAgIGNvbnN0IHNpemUgPSAxMDAwMDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNpemU7IGkrKykge1xuICAgICAgdmFsdWVzLnB1c2gocmFuZC5uZXh0VmFsdWUoKSk7XG4gICAgfVxuICAgIGV4cGVjdFZhbHVlc0luUmFuZ2UodmFsdWVzLCAwLCAzMCk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKCdVbmlmb3JtUmFuZG9tJywgKCkgPT4ge1xuICBpdCgnZmxvYXQzMiwgbm8gc2VlZCcsICgpID0+IHtcbiAgICBjb25zdCBtaW4gPSAwLjI7XG4gICAgY29uc3QgbWF4ID0gMC4yNDtcbiAgICBjb25zdCBkdHlwZSA9ICdmbG9hdDMyJztcbiAgICBjb25zdCB4czogbnVtYmVyW10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDEwOyArK2kpIHtcbiAgICAgIGNvbnN0IHJhbmQgPSBuZXcgVW5pZm9ybVJhbmRvbShtaW4sIG1heCwgZHR5cGUpO1xuICAgICAgY29uc3QgeCA9IHJhbmQubmV4dFZhbHVlKCk7XG4gICAgICB4cy5wdXNoKHgpO1xuICAgIH1cbiAgICBleHBlY3QoTWF0aC5taW4oLi4ueHMpKS50b0JlR3JlYXRlclRoYW5PckVxdWFsKG1pbik7XG4gICAgZXhwZWN0KE1hdGgubWF4KC4uLnhzKSkudG9CZUxlc3NUaGFuKG1heCk7XG4gIH0pO1xuXG4gIGl0KCdpbnQzMiwgbm8gc2VlZCcsICgpID0+IHtcbiAgICBjb25zdCBtaW4gPSAxMztcbiAgICBjb25zdCBtYXggPSAzNztcbiAgICBjb25zdCBkdHlwZSA9ICdpbnQzMic7XG4gICAgY29uc3QgeHM6IG51bWJlcltdID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCAxMDsgKytpKSB7XG4gICAgICBjb25zdCByYW5kID0gbmV3IFVuaWZvcm1SYW5kb20obWluLCBtYXgsIGR0eXBlKTtcbiAgICAgIGNvbnN0IHggPSByYW5kLm5leHRWYWx1ZSgpO1xuICAgICAgZXhwZWN0KE51bWJlci5pc0ludGVnZXIoeCkpLnRvRXF1YWwodHJ1ZSk7XG4gICAgICB4cy5wdXNoKHgpO1xuICAgIH1cbiAgICBleHBlY3QoTWF0aC5taW4oLi4ueHMpKS50b0JlR3JlYXRlclRoYW5PckVxdWFsKG1pbik7XG4gICAgZXhwZWN0KE1hdGgubWF4KC4uLnhzKSkudG9CZUxlc3NUaGFuT3JFcXVhbChtYXgpO1xuICB9KTtcblxuICBpdCgnc2VlZCBpcyBudW1iZXInLCAoKSA9PiB7XG4gICAgY29uc3QgbWluID0gLTEuMjtcbiAgICBjb25zdCBtYXggPSAtMC40O1xuICAgIGNvbnN0IGR0eXBlID0gJ2Zsb2F0MzInO1xuICAgIGNvbnN0IHNlZWQgPSAxMzM3O1xuICAgIGNvbnN0IHhzOiBudW1iZXJbXSA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMTA7ICsraSkge1xuICAgICAgY29uc3QgcmFuZCA9IG5ldyBVbmlmb3JtUmFuZG9tKG1pbiwgbWF4LCBkdHlwZSwgc2VlZCk7XG4gICAgICBjb25zdCB4ID0gcmFuZC5uZXh0VmFsdWUoKTtcbiAgICAgIGV4cGVjdCh4KS50b0JlR3JlYXRlclRoYW5PckVxdWFsKG1pbik7XG4gICAgICBleHBlY3QoeCkudG9CZUxlc3NUaGFuKG1heCk7XG4gICAgICB4cy5wdXNoKHgpO1xuICAgIH1cbiAgICAvLyBBc3NlcnQgZGV0ZXJtaW5pc3RpYyByZXN1bHRzLlxuICAgIGV4cGVjdChNYXRoLm1pbiguLi54cykpLnRvRXF1YWwoTWF0aC5tYXgoLi4ueHMpKTtcbiAgfSk7XG5cbiAgaXQoJ3NlZWQgPT09IG51bGwnLCAoKSA9PiB7XG4gICAgY29uc3QgbWluID0gMDtcbiAgICBjb25zdCBtYXggPSAxO1xuICAgIGNvbnN0IGR0eXBlID0gJ2Zsb2F0MzInO1xuICAgIGNvbnN0IHNlZWQ6IG51bWJlciA9IG51bGw7XG4gICAgY29uc3QgcmFuZCA9IG5ldyBVbmlmb3JtUmFuZG9tKG1pbiwgbWF4LCBkdHlwZSwgc2VlZCk7XG4gICAgY29uc3QgeCA9IHJhbmQubmV4dFZhbHVlKCk7XG4gICAgZXhwZWN0KHgpLnRvQmVHcmVhdGVyVGhhbk9yRXF1YWwoMCk7XG4gICAgZXhwZWN0KHgpLnRvQmVMZXNzVGhhbigxKTtcbiAgfSk7XG5cbiAgaXQoJ3NlZWQgPT09IHVuZGVmaW5lZCcsICgpID0+IHtcbiAgICBjb25zdCBtaW4gPSAwO1xuICAgIGNvbnN0IG1heCA9IDE7XG4gICAgY29uc3QgZHR5cGUgPSAnZmxvYXQzMic7XG4gICAgY29uc3Qgc2VlZDogbnVtYmVyID0gdW5kZWZpbmVkO1xuICAgIGNvbnN0IHJhbmQgPSBuZXcgVW5pZm9ybVJhbmRvbShtaW4sIG1heCwgZHR5cGUsIHNlZWQpO1xuICAgIGNvbnN0IHggPSByYW5kLm5leHRWYWx1ZSgpO1xuICAgIGV4cGVjdCh4KS50b0JlR3JlYXRlclRoYW5PckVxdWFsKDApO1xuICAgIGV4cGVjdCh4KS50b0JlTGVzc1RoYW4oMSk7XG4gIH0pO1xufSk7XG4iXX0=