@tensorflow/tfjs-core
Version:
Hardware-accelerated JavaScript library for machine intelligence
324 lines • 61.3 kB
JavaScript
/**
* @license
* Copyright 2020 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 * as tf from '../../index';
import { ALL_ENVS, describeWithFlags } from '../../jasmine_util';
import { expectArraysClose } from '../../test_util';
describeWithFlags('fused depthwiseConv2D', ALL_ENVS, () => {
it('basic', async () => {
const fSize = 2;
const pad = 'valid';
const strides = 1;
const chMul = 1;
const inDepth = 1;
const x = tf.tensor4d([
0.230664, 0.987388, 0.0685208, 0.419224, 0.887861, 0.731641,
0.0741907, 0.409265, 0.351377
], [1, 3, 3, inDepth]);
const w = tf.tensor4d([-0.303873, -0.229223, 0.144333, 0.803373], [fSize, fSize, inDepth, chMul]);
const result = tf.fused.depthwiseConv2d({ x, filter: w, strides, pad });
expect(result.shape).toEqual([1, 2, 2, 1]);
const expected = [0.47737, 0.40018, 0.00859, -0.09615];
expectArraysClose(await result.data(), expected);
});
it('basic with relu', async () => {
const fSize = 2;
const pad = 'valid';
const strides = 1;
const chMul = 1;
const inDepth = 1;
const x = tf.tensor4d([
0.230664, 0.987388, 0.0685208, 0.419224, 0.887861, 0.731641,
0.0741907, 0.409265, 0.351377
], [1, 3, 3, inDepth]);
const w = tf.tensor4d([-0.303873, -0.229223, 0.144333, 0.803373], [fSize, fSize, inDepth, chMul]);
const result = tf.fused.depthwiseConv2d({ x, filter: w, strides, pad, activation: 'relu' });
expect(result.shape).toEqual([1, 2, 2, 1]);
const expected = [0.47737, 0.40018, 0.00859, 0];
expectArraysClose(await result.data(), expected);
});
it('basic with channel-wise broadcasted bias and relu', async () => {
const strides = 1;
const pad = 'same';
const x = tf.tensor4d([
0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8
], [1, 3, 3, 4]);
const w = tf.tensor4d([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], [2, 2, 4, 1]);
const bias = tf.tensor1d([0, 1, 2, 3]);
const result = tf.fused.depthwiseConv2d({ x, filter: w, strides, pad, bias });
expect(result.shape).toEqual([1, 3, 3, 4]);
const expected = [
124, 167, 92, 142, 112, 117, 76, 124, 16, 28, 44, 64,
88, 134, 134, 88, 76, 120, 154, 205, 40, 58, 80, 106,
4, 18, 36, 31, 20, 33, 50, 71, 0, 7, 16, 27
];
expectArraysClose(await result.data(), expected);
});
it('basic with broadcasted bias and relu', async () => {
const fSize = 2;
const pad = 'valid';
const strides = 1;
const chMul = 1;
const inDepth = 1;
const x = tf.tensor4d([
0.230664, 0.987388, 0.0685208, 0.419224, 0.887861, 0.731641,
0.0741907, 0.409265, 0.351377
], [1, 3, 3, inDepth]);
const w = tf.tensor4d([-0.303873, -0.229223, 0.144333, 0.803373], [fSize, fSize, inDepth, chMul]);
const result = tf.fused.depthwiseConv2d({ x, filter: w, strides, pad, bias: tf.scalar(1), activation: 'relu' });
expect(result.shape).toEqual([1, 2, 2, 1]);
const expected = [1.47737, 1.40018, 1.00859, 0.90385];
expectArraysClose(await result.data(), expected);
});
// For WebGPU DepthwiseConv2D3x3Program.
it('basic with channel-wise broadcasted bias and relu filter 3x3', async () => {
const fSize = 3;
const pad = 'same';
const strides = 1;
const chMul = 1;
const inDepth = 4;
const x = tf.tensor4d([
0.230664, 0.987388, 0.0685208, 0.419224, 0.887861, 0.731641,
0.0741907, 0.409265, 0.351377, 0.230664, 0.987388, 0.0685208,
0.419224, 0.887861, 0.731641, 0.0741907, 0.409265, 0.351377,
0.230664, 0.987388, 0.0685208, 0.419224, 0.887861, 0.731641,
0.0741907, 0.409265, 0.351377, 0.230664, 0.987388, 0.0685208,
0.419224, 0.887861, 0.731641, 0.0741907, 0.409265, 0.351377
], [1, 3, 3, inDepth]);
const w = tf.tensor4d([
-0.303873, -0.229223, 0.144333, 0.803373, -0.303873, -0.229223,
0.144333, 0.803373, -0.303873, -0.229223, 0.144333, 0.803373,
-0.303873, -0.229223, 0.144333, 0.803373, -0.303873, -0.229223,
0.144333, 0.803373, -0.303873, -0.229223, 0.144333, 0.803373,
-0.303873, -0.229223, 0.144333, 0.803373, -0.303873, -0.229223,
0.144333, 0.803373, -0.303873, -0.229223, 0.144333, 0.803373
], [fSize, fSize, inDepth, chMul]);
const bias = tf.tensor1d([0, 1, 2, 3]);
const result = tf.fused.depthwiseConv2d({ x, filter: w, strides, pad, bias });
expect(result.shape).toEqual([1, 3, 3, 4]);
const expected = [
-0.5916450023651123, 0.32189714908599854, 2.1594903469085693,
4.518429279327393, -0.7192406058311462, 0.1729278564453125,
2.4301507472991943, 5.161257743835449, -0.521757185459137,
0.6027780771255493, 2.3146610260009766, 4.764861583709717,
-0.9142301082611084, 0.212377667427063, 2.2707135677337646,
5.417022228240967, -1.264151692390442, 0.046402156352996826,
2.6004443168640137, 6.342137336730957, -1.044123649597168,
0.5700653791427612, 2.434239149093628, 5.760432243347168,
-0.5743405818939209, 0.6064186692237854, 2.250115394592285,
4.751436233520508, -0.8174881339073181, 0.4933167099952698,
2.437333583831787, 5.621503829956055, -0.6675527095794678,
0.7906477451324463, 2.2810182571411133, 5.376591682434082
];
expectArraysClose(await result.data(), expected);
});
it('prelu', async () => {
const fSize = 3;
const pad = 'valid';
const strides = 1;
const chMul = 1;
const inDepth = 1;
const x = tf.tensor4d([
0.149194, 0.089009, 0.654891, 0.083324, 0.537043, 0.644331, 0.563037,
0.211859, 0.633501, 0.186427, 0.777034, 0.50001, 0.607341, 0.95303,
0.696479, 0.050387, 0.62045, 0.728049, 0.028043, 0.437009, 0.712881,
0.741935, 0.974474, 0.621102, 0.171411
], [1, 5, 5, inDepth]);
const alpha = tf.tensor4d([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9], [1, 3, 3, 1]);
const w = tf.tensor4d([
-0.125386, -0.975199, -0.640437, -0.281895, -0.990968, -0.347208,
-0.889702, -0.180695, -0.691992
], [fSize, fSize, inDepth, chMul]);
const result = tf.fused.depthwiseConv2d({
x,
filter: w,
strides,
pad,
activation: 'prelu',
preluActivationWeights: alpha
});
expect(result.shape).toEqual([1, 3, 3, 1]);
const expected = [
-0.25400, -0.50118, -0.73622, -0.94068, -1.2298, -1.84585, -2.3089,
-2.7499, -2.64077
];
expectArraysClose(await result.data(), expected);
});
it('leakyrelu', async () => {
const fSize = 3;
const pad = 'valid';
const strides = 1;
const chMul = 1;
const inDepth = 1;
const x = tf.tensor4d([
0.149194, 0.089009, 0.654891, 0.083324, 0.537043, 0.644331, 0.563037,
0.211859, 0.633501, 0.186427, 0.777034, 0.50001, 0.607341, 0.95303,
0.696479, 0.050387, 0.62045, 0.728049, 0.028043, 0.437009, 0.712881,
0.741935, 0.974474, 0.621102, 0.171411
], [1, 5, 5, inDepth]);
const alpha = 0.3;
const w = tf.tensor4d([
-0.125386, -0.975199, -0.640437, -0.281895, -0.990968, -0.347208,
-0.889702, -0.180695, -0.691992
], [fSize, fSize, inDepth, chMul]);
const result = tf.fused.depthwiseConv2d({
x,
filter: w,
strides,
pad,
activation: 'leakyrelu',
leakyreluAlpha: alpha
});
expect(result.shape).toEqual([1, 3, 3, 1]);
const expected = [
-0.7620067596435547, -0.7517655491828918, -0.7362186312675476,
-0.7055101990699768, -0.7378802299499512, -0.9229262471199036,
-0.9895440340042114, -1.031226396560669, -0.8802568912506104
];
expectArraysClose(await result.data(), expected);
});
it('sigmoid', async () => {
const fSize = 3;
const pad = 'valid';
const strides = 1;
const chMul = 1;
const inDepth = 1;
const x = tf.tensor4d([
0.149194, 0.089009, 0.654891, 0.083324, 0.537043, 0.644331, 0.563037,
0.211859, 0.633501, 0.186427, 0.777034, 0.50001, 0.607341, 0.95303,
0.696479, 0.050387, 0.62045, 0.728049, 0.028043, 0.437009, 0.712881,
0.741935, 0.974474, 0.621102, 0.171411
], [1, 5, 5, inDepth]);
const w = tf.tensor4d([
-0.125386, -0.975199, -0.640437, -0.281895, -0.990968, -0.347208,
-0.889702, -0.180695, -0.691992
], [fSize, fSize, inDepth, chMul]);
const result = tf.fused.depthwiseConv2d({ x, filter: w, strides, pad, activation: 'sigmoid' });
expect(result.shape).toEqual([1, 3, 3, 1]);
const expected = [
0.07309964, 0.07544667, 0.07914197, 0.08693069, 0.07873929, 0.04409045,
0.03562334, 0.0311462, 0.05048907
];
expectArraysClose(await result.data(), expected);
});
it('gradient x=[2,3,3,1] f=[2,2,1,1] s=1 p=0', async () => {
const inputDepth = 1;
const outputDepth = 1;
const inputShape = [2, 3, 3, inputDepth];
const filterSize = 2;
const strides = 1;
const pad = 0;
const filterShape = [filterSize, filterSize, inputDepth, outputDepth];
const filter = tf.tensor4d([-1, 1, -2, 0.5], filterShape);
const x = tf.tensor4d([1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9], inputShape);
const dy = tf.tensor4d([3, 1, 2, 0, 3, 1, 2, 0], [2, 2, 2, 1]);
const grads = tf.grads((x, filter) => tf.fused.depthwiseConv2d({ x, filter, strides, pad }));
const [dx, dfilter] = grads([x, filter], dy);
expect(dx.shape).toEqual(x.shape);
expectArraysClose(await dx.data(), [-3, 2, 1, -8, 1.5, 0.5, -4, 1, 0, -3, 2, 1, -8, 1.5, 0.5, -4, 1, 0]);
expect(dfilter.shape).toEqual(filterShape);
expectArraysClose(await dfilter.data(), [26, 38, 62, 74]);
});
it('gradient x=[2,3,3,1] f=[2,2,1,1] s=1 p=0 with bias', async () => {
const inputDepth = 1;
const outputDepth = 1;
const inputShape = [2, 3, 3, inputDepth];
const filterSize = 2;
const strides = 1;
const pad = 0;
const filterShape = [filterSize, filterSize, inputDepth, outputDepth];
const filter = tf.tensor4d([-1, 1, -2, 0.5], filterShape);
const bias = tf.ones([2, 2, 2, 1]);
const x = tf.tensor4d([1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9], inputShape);
const dy = tf.tensor4d([3, 1, 2, 0, 3, 1, 2, 0], [2, 2, 2, 1]);
const fusedGrads = tf.grads((x, w, b) => tf.fused.depthwiseConv2d({
x,
filter: w,
strides,
pad,
dataFormat: 'NHWC',
dilations: [1, 1],
bias: b
}));
const [dxFused, dfilterFused, dbiasFused] = fusedGrads([x, filter, bias], dy);
const grads = tf.grads((x, filter, bias) => {
const conv = tf.depthwiseConv2d(x, filter, strides, pad);
const sum = tf.add(conv, bias);
return sum;
});
const [dx, dfilter, dbias] = grads([x, filter, bias], dy);
expectArraysClose(await dxFused.array(), await dx.array());
expectArraysClose(await dfilterFused.array(), await dfilter.array());
expectArraysClose(await dbiasFused.array(), await dbias.array());
});
it('gradient x=[2,3,3,1] f=[2,2,1,1] s=1 p=0 with bias and activation', async () => {
const inputDepth = 1;
const outputDepth = 1;
const inputShape = [2, 3, 3, inputDepth];
const filterSize = 2;
const strides = 1;
const pad = 0;
const filterShape = [filterSize, filterSize, inputDepth, outputDepth];
const filter = tf.tensor4d([-1, 1, -2, 0.5], filterShape);
const bias = tf.ones([2, 2, 2, 1]);
const x = tf.tensor4d([1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9], inputShape);
const dy = tf.tensor4d([3, 1, 2, 0, 3, 1, 2, 0], [2, 2, 2, 1]);
const fusedGrads = tf.grads((x, w, b) => tf.fused.depthwiseConv2d({
x,
filter: w,
strides,
pad,
dataFormat: 'NHWC',
dilations: [1, 1],
bias: b,
activation: 'relu'
}));
const [dxFused, dfilterFused, dbiasFused] = fusedGrads([x, filter, bias], dy);
const grads = tf.grads((x, filter, bias) => {
const conv = tf.depthwiseConv2d(x, filter, strides, pad);
const sum = tf.add(conv, bias);
return tf.relu(sum);
});
const [dx, dfilter, dbias] = grads([x, filter, bias], dy);
expectArraysClose(await dxFused.array(), await dx.array());
expectArraysClose(await dfilterFused.array(), await dfilter.array());
expectArraysClose(await dbiasFused.array(), await dbias.array());
});
it('throws when input is int32', async () => {
const fSize = 2;
const pad = 'valid';
const strides = 1;
const chMul = 1;
const inDepth = 1;
const x = tf.tensor4d([1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 3, 3, inDepth], 'int32');
const w = tf.tensor4d([-0.303873, -0.229223, 0.144333, 0.803373], [fSize, fSize, inDepth, chMul]);
expect(() => tf.fused.depthwiseConv2d({ x, filter: w, strides, pad }))
.toThrowError(/Argument 'x' passed to 'depthwiseConv2d' must be float32/);
});
it('throws when filter is int32', async () => {
const fSize = 2;
const pad = 'valid';
const strides = 1;
const chMul = 1;
const inDepth = 1;
const x = tf.tensor4d([1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 3, 3, inDepth]);
const w = tf.tensor4d([1, 2, 3, 4], [fSize, fSize, inDepth, chMul], 'int32');
expect(() => tf.fused.depthwiseConv2d({ x, filter: w, strides, pad }))
.toThrowError(/Argument 'filter' passed to 'depthwiseConv2d' must be float32/);
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnVzZWRfZGVwdGh3aXNlX2NvbnYyZF90ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vdGZqcy1jb3JlL3NyYy9vcHMvZnVzZWQvZnVzZWRfZGVwdGh3aXNlX2NvbnYyZF90ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUVILE9BQU8sS0FBSyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ2xDLE9BQU8sRUFBQyxRQUFRLEVBQUUsaUJBQWlCLEVBQUMsTUFBTSxvQkFBb0IsQ0FBQztBQUMvRCxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUVsRCxpQkFBaUIsQ0FBQyx1QkFBdUIsRUFBRSxRQUFRLEVBQUUsR0FBRyxFQUFFO0lBQ3hELEVBQUUsQ0FBQyxPQUFPLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDckIsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDO1FBQ2hCLE1BQU0sR0FBRyxHQUFHLE9BQU8sQ0FBQztRQUNwQixNQUFNLE9BQU8sR0FBRyxDQUFDLENBQUM7UUFDbEIsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDO1FBQ2hCLE1BQU0sT0FBTyxHQUFHLENBQUMsQ0FBQztRQUVsQixNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUNqQjtZQUNFLFFBQVEsRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsUUFBUTtZQUMzRCxTQUFTLEVBQUUsUUFBUSxFQUFFLFFBQVE7U0FDOUIsRUFDRCxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7UUFDeEIsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FDakIsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLFFBQVEsRUFBRSxRQUFRLEVBQUUsUUFBUSxDQUFDLEVBQzFDLENBQUMsS0FBSyxF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Q0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO1NBQ3JELEVBQ0QsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xCLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQ2pCLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzFFLE1BQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRXZDLE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLEVBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUMsQ0FBQyxDQUFDO1FBQzVFLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMzQyxNQUFNLFFBQVEsR0FBRztZQUNmLEdBQUcsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFHLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRyxHQUFHLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRTtZQUN0RCxFQUFFLEVB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LEVBQUUsQ0FBQyxRQUFRLENBQ2pCLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUN4RSxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUUvRCxNQUFNLEtBQUssR0FBRyxFQUFFLENBQUMsS0FBSyxDQUNsQixDQUFDLENBQWMsRUFBRSxNQUFtQixFQUFFLEVBQUUsQ0FDcEMsRUFBRSxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsRUFBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUMsQ0FBQyxDQUFDLENBQUM7UUFDN0QsTUFBTSxDQUFDLEVBQUUsRUFBRSxPQUFPLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFN0MsTUFBTSxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2xDLGlCQUFpQixDQUNiLE1BQU0sRUFBRSxDQUFDLElBQUksRUFBRSxFQUNmLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFB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QyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBQ3ZFLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQ2pCLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQ1osQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxLQUFLLENBQUMsRUFDOUIsT0FBTyxDQUNWLENBQUM7UUFFRixNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsRUFBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFDLENBQUMsQ0FBQzthQUMvRCxZQUFZLENBQ1QsK0RBQStELENBQUMsQ0FBQztJQUMzRSxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqL1xuXG5pbXBvcnQgKiBhcyB0ZiBmcm9tICcuLi8uLi9pbmRleCc7XG5pbXBvcnQge0FMTF9FTlZTLCBkZXNjcmliZVdpdGhGbGFnc30gZnJvbSAnLi4vLi4vamFzbWluZV91dGlsJztcbmltcG9ydCB7ZXhwZWN0QXJyYXlzQ2xvc2V9IGZyb20gJy4uLy4uL3Rlc3RfdXRpbCc7XG5cbmRlc2NyaWJlV2l0aEZsYWdzKCdmdXNlZCBkZXB0aHdpc2VDb252MkQnLCBBTExfRU5WUywgKCkgPT4ge1xuICBpdCgnYmFzaWMnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZlNpemUgPSAyO1xuICAgIGNvbnN0IHBhZCA9ICd2YWxpZCc7XG4gICAgY29uc3Qgc3RyaWRlcyA9IDE7XG4gICAgY29uc3QgY2hNdWwgPSAxO1xuICAgIGNvbnN0IGluRGVwdGggPSAxO1xuXG4gICAgY29uc3QgeCA9IHRmLnRlbnNvcjRkKFxuICAgICAgICBbXG4gICAgICAgICAgMC4yMzA2NjQsIDAuOTg3Mzg4LCAwLjA2ODUyMDgsIDAuNDE5MjI0LCAwLjg4Nzg2MSwgMC43MzE2NDEsXG4gICAgICAgICAgMC4wNzQxOTA3LCAwLjQwOTI2NSwgMC4zNTEzNzdcbiAgICAgICAgXSxcbiAgICAgICAgWzEsIDMsIDMsIGluRGVwdGhdKTtcbiAgICBjb25zdCB3ID0gdGYudGVuc29yNGQoXG4gICAgICAgIFstMC4zMDM4NzMsIC0wLjIyOTIyMywgMC4xNDQzMzMsIDAuODAzMzczXSxcbiAgICAgICAgW2ZTaXplLCBmU2l6ZSwgaW5EZXB0aCwgY2hNdWxdLFxuICAgICk7XG5cbiAgICBjb25zdCByZXN1bHQgPSB0Zi5mdXNlZC5kZXB0aHdpc2VDb252MmQoe3gsIGZpbHRlcjogdywgc3RyaWRlcywgcGFkfSk7XG4gICAgZXhwZWN0KHJlc3VsdC5zaGFwZSkudG9FcXVhbChbMSwgMiwgMiwgMV0pO1xuICAgIGNvbnN0IGV4cGVjdGVkID0gWzAuNDc3MzcsIDAuNDAwMTgsIDAuMDA4NTksIC0wLjA5NjE1XTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCByZXN1bHQuZGF0YSgpLCBleHBlY3RlZCk7XG4gIH0pO1xuXG4gIGl0KCdiYXNpYyB3aXRoIHJlbHUnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZlNpemUgPSAyO1xuICAgIGNvbnN0IHBhZCA9ICd2YWxpZCc7XG4gICAgY29uc3Qgc3RyaWRlcyA9IDE7XG4gICAgY29uc3QgY2hNdWwgPSAxO1xuICAgIGNvbnN0IGluRGVwdGggPSAxO1xuXG4gICAgY29uc3QgeCA9IHRmLnRlbnNvcjRkKFxuICAgICAgICBbXG4gICAgICAgICAgMC4yMzA2NjQsIDAuOTg3Mzg4LCAwLjA2ODUyMDgsIDAuNDE5MjI0LCAwLjg4Nzg2MSwgMC43MzE2NDEsXG4gICAgICAgICAgMC4wNzQxOTA3LCAwLjQwOTI2NSwgMC4zNTEzNzdcbiAgICAgICAgXSxcbiAgICAgICAgWzEsIDMsIDMsIGluRGVwdGhdKTtcbiAgICBjb25zdCB3ID0gdGYudGVuc29yNGQoXG4gICAgICAgIFstMC4zMDM4NzMsIC0wLjIyOTIyMywgMC4xNDQzMzMsIDAuODAzMzczXSxcbiAgICAgICAgW2ZTaXplLCBmU2l6ZSwgaW5EZXB0aCwgY2hNdWxdLFxuICAgICk7XG5cbiAgICBjb25zdCByZXN1bHQgPSB0Zi5mdXNlZC5kZXB0aHdpc2VDb252MmQoXG4gICAgICAgIHt4LCBmaWx0ZXI6IHcsIHN0cmlkZXMsIHBhZCwgYWN0aXZhdGlvbjogJ3JlbHUnfSk7XG4gICAgZXhwZWN0KHJlc3VsdC5zaGFwZSkudG9FcXVhbChbMSwgMiwgMiwgMV0pO1xuICAgIGNvbnN0IGV4cGVjdGVkID0gWzAuNDc3MzcsIDAuNDAwMTgsIDAuMDA4NTksIDBdO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHJlc3VsdC5kYXRhKCksIGV4cGVjdGVkKTtcbiAgfSk7XG5cbiAgaXQoJ2Jhc2ljIHdpdGggY2hhbm5lbC13aXNlIGJyb2FkY2FzdGVkIGJpYXMgYW5kIHJlbHUnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgc3RyaWRlcyA9IDE7XG4gICAgY29uc3QgcGFkID0gJ3NhbWUnO1xuICAgIGNvbnN0IHggPSB0Zi50ZW5zb3I0ZChcbiAgICAgICAgW1xuICAgICAgICAgIDAsIDEsIDIsIDMsIDQsIDUsIDYsIDcsIDgsIDAsIDEsIDIsIDMsIDQsIDUsIDYsIDcsIDgsXG4gICAgICAgICAgMCwgMSwgMiwgMywgNCwgNSwgNiwgNywgOCwgMCwgMSwgMiwgMywgNCwgNSwgNiwgNywgOFxuICAgICAgICBdLFxuICAgICAgICBbMSwgMywgMywgNF0pO1xuICAgIGNvbnN0IHcgPSB0Zi50ZW5zb3I0ZChcbiAgICAgICAgWzAsIDEsIDIsIDMsIDQsIDUsIDYsIDcsIDgsIDksIDEwLCAxMSwgMTIsIDEzLCAxNCwgMTVdLCBbMiwgMiwgNCwgMV0pO1xuICAgIGNvbnN0IGJpYXMgPSB0Zi50ZW5zb3IxZChbMCwgMSwgMiwgM10pO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gdGYuZnVzZWQuZGVwdGh3aXNlQ29udjJkKHt4LCBmaWx0ZXI6IHcsIHN0cmlkZXMsIHBhZCwgYmlhc30pO1xuICAgIGV4cGVjdChyZXN1bHQuc2hhcGUpLnRvRXF1YWwoWzEsIDMsIDMsIDRdKTtcbiAgICBjb25zdCBleHBlY3RlZCA9IFtcbiAgICAgIDEyNCwgMTY3LCA5MiwgIDE0MiwgMTEyLCAxMTcsIDc2LCAgMTI0LCAxNiwgMjgsIDQ0LCA2NCxcbiAgICAgIDg4LCAgMTM0LCAxMzQsIDg4LCAgNzYsICAxMjAsIDE1NCwgMjA1LCA0MCwgNTgsIDgwLCAxMDYsXG4gICAgICA0LCAgIDE4LCAgMzYsICAzMSwgIDIwLCAgMzMsICA1MCwgIDcxLCAgMCwgIDcsICAxNiwgMjdcbiAgICBdO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHJlc3VsdC5kYXRhKCksIGV4cGVjdGVkKTtcbiAgfSk7XG5cbiAgaXQoJ2Jhc2ljIHdpdGggYnJvYWRjYXN0ZWQgYmlhcyBhbmQgcmVsdScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBmU2l6ZSA9IDI7XG4gICAgY29uc3QgcGFkID0gJ3ZhbGlkJztcbiAgICBjb25zdCBzdHJpZGVzID0gMTtcbiAgICBjb25zdCBjaE11bCA9IDE7XG4gICAgY29uc3QgaW5EZXB0aCA9IDE7XG5cbiAgICBjb25zdCB4ID0gdGYudGVuc29yNGQoXG4gICAgICAgIFtcbiAgICAgICAgICAwLjIzMDY2NCwgMC45ODczODgsIDAuMDY4NTIwOCwgMC40MTkyMjQsIDAuODg3ODYxLCAwLjczMTY0MSxcbiAgICAgICAgICAwLjA3NDE5MDcsIDAuNDA5MjY1LCAwLjM1MTM3N1xuICAgICAgICBdLFxuICAgICAgICBbMSwgMywgMywgaW5EZXB0aF0pO1xuICAgIGNvbnN0IHcgPSB0Zi50ZW5zb3I0ZChcbiAgICAgICAgWy0wLjMwMzg3MywgLTAuMjI5MjIzLCAwLjE0NDMzMywgMC44MDMzNzNdLFxuICAgICAgICBbZlNpemUsIGZTaXplLCBpbkRlcHRoLCBjaE11bF0sXG4gICAgKTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IHRmLmZ1c2VkLmRlcHRod2lzZUNvbnYyZChcbiAgICAgICAge3gsIGZpbHRlcjogdywgc3RyaWRlcywgcGFkLCBiaWFzOiB0Zi5zY2FsYXIoMSksIGFjdGl2YXRpb246ICdyZWx1J30pO1xuICAgIGV4cGVjdChyZXN1bHQuc2hhcGUpLnRvRXF1YWwoWzEsIDIsIDIsIDFdKTtcbiAgICBjb25zdCBleHBlY3RlZCA9IFsxLjQ3NzM3LCAxLjQwMDE4LCAxLjAwODU5LCAwLjkwMzg1XTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCByZXN1bHQuZGF0YSgpLCBleHBlY3RlZCk7XG4gIH0pO1xuXG4gIC8vIEZvciBXZWJHUFUgRGVwdGh3aXNlQ29udjJEM3gzUHJvZ3JhbS5cbiAgaXQoJ2Jhc2ljIHdpdGggY2hhbm5lbC13aXNlIGJyb2FkY2FzdGVkIGJpYXMgYW5kIHJlbHUgZmlsdGVyIDN4MycsXG4gICAgIGFzeW5jICgpID0+IHtcbiAgICAgICBjb25zdCBmU2l6ZSA9IDM7XG4gICAgICAgY29uc3QgcGFkID0gJ3NhbWUnO1xuICAgICAgIGNvbnN0IHN0cmlkZXMgPSAxO1xuICAgICAgIGNvbnN0IGNoTXVsID0gMTtcbiAgICAgICBjb25zdCBpbkRlcHRoID0gNDtcblxuICAgICAgIGNvbnN0IHggPSB0Zi50ZW5zb3I0ZChcbiAgICAgICAgICAgW1xuICAgICAgICAgICAgIDAuMjMwNjY0LCAgMC45ODczODgsIDAuMDY4NTIwOCwgMC40MTkyMjQsICAwLjg4Nzg2MSwgMC43MzE2NDEsXG4gICAgICAgICAgICAgMC4wNzQxOTA3LCAwLjQwOTI2NSwgMC4zNTEzNzcsICAwLjIzMDY2NCwgIDAuOTg3Mzg4LCAwLjA2ODUyMDgsXG4gICAgICAgICAgICAgMC40MTkyMjQsICAwLjg4Nzg2MSwgMC43MzE2NDEsICAwLjA3NDE5MDcsIDAuNDA5MjY1LCAwLjM1MTM3NyxcbiAgICAgICAgICAgICAwLjIzMDY2NCwgIDAuOTg3Mzg4LCAwLjA2ODUyMDgsIDAuNDE5MjI0LCAgMC44ODc4NjEsIDAuNzMxNjQxLFxuICAgICAgICAgICAgIDAuMDc0MTkwNywgMC40MDkyNjUsIDAuMzUxMzc3LCAgMC4yMzA2NjQsICAwLjk4NzM4OCwgMC4wNjg1MjA4LFxuICAgICAgICAgICAgIDAuNDE5MjI0LCAgMC44ODc4NjEsIDAuNzMxNjQxLCAgMC4wNzQxOTA3LCAwLjQwOTI2NSwgMC4zNTEzNzdcbiAgICAgICAgICAgXSxcbiAgICAgICAgICAgWzEsIDMsIDMsIGluRGVwdGhdKTtcbiAgICAgICBjb25zdCB3ID0gdGYudGVuc29yNGQoXG4gICAgICAgICAgIFtcbiAgICAgICAgICAgICAtMC4zMDM4NzMsIC0wLjIyOTIyMywgMC4xNDQzMzMsICAwLjgwMzM3MywgIC0wLjMwMzg3MywgLTAuMjI5MjIzLFxuICAgICAgICAgICAgIDAuMTQ0MzMzLCAgMC44MDMzNzMsICAtMC4zMDM4NzMsIC0wLjIyOTIyMywgMC4xNDQzMzMsICAwLjgwMzM3MyxcbiAgICAgICAgICAgICAtMC4zMDM4NzMsIC0wLjIyOTIyMywgMC4xNDQzMzMsICAwLjgwMzM3MywgIC0wLjMwMzg3MywgLTAuMjI5MjIzLFxuICAgICAgICAgICAgIDAuMTQ0MzMzLCAgMC44MDMzNzMsICAtMC4zMDM4NzMsIC0wLjIyOTIyMywgMC4xNDQzMzMsICAwLjgwMzM3MyxcbiAgICAgICAgICAgICAtMC4zMDM4NzMsIC0wLjIyOTIyMywgMC4xNDQzMzMsICAwLjgwMzM3MywgIC0wLjMwMzg3MywgLTAuMjI5MjIzLFxuICAgICAgICAgICAgIDAuMTQ0MzMzLCAgMC44MDMzNzMsICAtMC4zMDM4NzMsIC0wLjIyOTIyMywgMC4xNDQzMzMsICAwLjgwMzM3M1xuICAgICAgICAgICBdLFxuICAgICAgICAgICBbZlNpemUsIGZTaXplLCBpbkRlcHRoLCBjaE11bF0sXG4gICAgICAgKTtcbiAgICAgICBjb25zdCBiaWFzID0gdGYudGVuc29yMWQoWzAsIDEsIDIsIDNdKTtcbiAgICAgICBjb25zdCByZXN1bHQgPVxuICAgICAgICAgICB0Zi5mdXNlZC5kZXB0aHdpc2VDb252MmQoe3gsIGZpbHRlcjogdywgc3RyaWRlcywgcGFkLCBiaWFzfSk7XG4gICAgICAgZXhwZWN0KHJlc3VsdC5zaGFwZSkudG9FcXVhbChbMSwgMywgMywgNF0pO1xuICAgICAgIGNvbnN0IGV4cGVjdGVkID0gW1xuICAgICAgICAgLTAuNTkxNjQ1MDAyMzY1MTEyMywgMC4zMjE4OTcxNDkwODU5OTg1NCwgMi4xNTk0OTAzNDY5MDg1NjkzLFxuICAgICAgICAgNC41MTg0MjkyNzkzMjczOTMsICAgLTAuNzE5MjQwNjA1ODMxMTQ2MiwgMC4xNzI5Mjc4NTY0NDUzMTI1LFxuICAgICAgICAgMi40MzAxNTA3NDcyOTkxOTQzLCAgNS4xNjEyNTc3NDM4MzU0NDksICAgLTAuNTIxNzU3MTg1NDU5MTM3LFxuICAgICAgICAgMC42MDI3NzgwNzcxMjU1NDkzLCAgMi4zMTQ2NjEwMjYwMDA5NzY2LCAgNC43NjQ4NjE1ODM3MDk3MTcsXG4gICAgICAgICAtMC45MTQyMzAxMDgyNjExMDg0LCAwLjIxMjM3NzY2NzQyNzA2MywgICAyLjI3MDcxMzU2NzczMzc2NDYsXG4gICAgICAgICA1LjQxNzAyMjIyODI0MDk2NywgICAtMS4yNjQxNTE2OTIzOTA0NDIsICAwLjA0NjQwMjE1NjM1Mjk5NjgyNixcbiAgICAgICAgIDIuNjAwNDQ0MzE2ODY0MDEzNywgIDYuMzQyMTM3MzM2NzMwOTU3LCAgIC0xLjA0NDEyMzY0OTU5NzE2OCxcbiAgICAgICAgIDAuNTcwMDY1Mzc5MTQyNzYxMiwgIDIuNDM0MjM5MTQ5MDkzNjI4LCAgIDUuNzYwNDMyMjQzMzQ3MTY4LFxuICAgICAgICAgLTAuNTc0MzQwNTgxODkzOTIwOSwgMC42MDY0MTg2NjkyMjM3ODU0LCAgMi4yNTAxMTUzOTQ1OTIyODUsXG4gICAgICAgICA0Ljc1MTQzNjIzMzUyMDUwOCwgICAtMC44MTc0ODgxMzM5MDczMTgxLCAwLjQ5MzMxNjcwOTk5NTI2OTgsXG4gICAgICAgICAyLjQzNzMzMzU4MzgzMTc4NywgICA1LjYyMTUwMzgyOTk1NjA1NSwgICAtMC42Njc1NTI3MDk1Nzk0Njc4LFxuICAgICAgICAgMC43OTA2NDc3NDUxMzI0NDYzLCAgMi4yODEwMTgyNTcxNDExMTMzLCAgNS4zNzY1OTE2ODI0MzQwODJcbiAgICAgICBdO1xuICAgICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHJlc3VsdC5kYXRhKCksIGV4cGVjdGVkKTtcbiAgICAgfSk7XG5cbiAgaXQoJ3ByZWx1JywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGZTaXplID0gMztcbiAgICBjb25zdCBwYWQgPSAndmFsaWQnO1xuICAgIGNvbnN0IHN0cmlkZXMgPSAxO1xuICAgIGNvbnN0IGNoTXVsID0gMTtcbiAgICBjb25zdCBpbkRlcHRoID0gMTtcblxuICAgIGNvbnN0IHggPSB0Zi50ZW5zb3I0ZChcbiAgICAgICAgW1xuICAgICAgICAgIDAuMTQ5MTk0LCAwLjA4OTAwOSwgMC42NTQ4OTEsIDAuMDgzMzI0LCAwLjUzNzA0MywgMC42NDQzMzEsIDAuNTYzMDM3LFxuICAgICAgICAgIDAuMjExODU5LCAwLjYzMzUwMSwgMC4xODY0MjcsIDAuNzc3MDM0LCAwLjUwMDAxLCAgMC42MDczNDEsIDAuOTUzMDMsXG4gICAgICAgICAgMC42OTY0NzksIDAuMDUwMzg3LCAwLjYyMDQ1LCAgMC43MjgwNDksIDAuMDI4MDQzLCAwLjQzNzAwOSwgMC43MTI4ODEsXG4gICAgICAgICAgMC43NDE5MzUsIDAuOTc0NDc0LCAwLjYyMTEwMiwgMC4xNzE0MTFcbiAgICAgICAgXSxcbiAgICAgICAgWzEsIDUsIDUsIGluRGVwdGhdKTtcbiAgICBjb25zdCBhbHBoYSA9IHRmLnRlbnNvcjRkKFxuICAgICAgICBbMC4xLCAwLjIsIDAuMywgMC40LCAwLjUsIDAuNiwgMC43LCAwLjgsIDAuOV0sIFsxLCAzLCAzLCAxXSk7XG4gICAgY29uc3QgdyA9IHRmLnRlbnNvcjRkKFxuICAgICAgICBbXG4gICAgICAgICAgLTAuMTI1Mzg2LCAtMC45NzUxOTksIC0wLjY0MDQzNywgLTAuMjgxODk1LCAtMC45OTA5NjgsIC0wLjM0NzIwOCx