UNPKG

26.2 kBJavaScriptView Raw
1/**
2 * @license
3 * Copyright 2018 Google LLC. All Rights Reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 * =============================================================================
16 */
17import * as tf from '../index';
18import { ALL_ENVS, describeWithFlags } from '../jasmine_util';
19import { expectArraysClose } from '../test_util';
20import { PARALLELIZE_THRESHOLD } from './reduce_util';
21describeWithFlags('unsortedSegmentSum', ALL_ENVS, () => {
22 it('tensor1D', async () => {
23 const t = tf.tensor1d([1, 2, 3, 4]);
24 const segmentIds = tf.tensor1d([0, 2, 0, 1], 'int32');
25 const numSegments = 3;
26 const res = tf.unsortedSegmentSum(t, segmentIds, numSegments);
27 expect(res.shape).toEqual([numSegments]);
28 expectArraysClose(await res.data(), [4, 4, 2]);
29 });
30 it('tensor2D', async () => {
31 const t = tf.tensor2d([1, 2, 3, 4], [2, 2]);
32 const segmentIds = tf.tensor1d([0, 0], 'int32');
33 const numSegments = 2;
34 const res = tf.unsortedSegmentSum(t, segmentIds, numSegments);
35 expect(res.shape).toEqual([numSegments, 2]);
36 expectArraysClose(await res.data(), [4, 6, 0, 0]);
37 });
38 it('tensor3D', async () => {
39 const t = tf.tensor3d([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], [3, 2, 2]);
40 const segmentIds = tf.tensor1d([2, 1, 2], 'int32');
41 const numSegments = 3;
42 const res = tf.unsortedSegmentSum(t, segmentIds, numSegments);
43 expect(res.shape).toEqual([numSegments, 2, 2]);
44 expectArraysClose(await res.data(), [0, 0, 0, 0, 5, 6, 7, 8, 10, 12, 14, 16]);
45 });
46 it('N > than parallelization threshold, tensor1D', async () => {
47 const n = PARALLELIZE_THRESHOLD * 2;
48 const values = new Float32Array(n);
49 const numSegments = 5;
50 const segmentIdValues = new Float32Array(n);
51 const vals = new Float32Array(numSegments);
52 for (let i = 0; i < n; i++) {
53 values[i] = i;
54 segmentIdValues[i] = i % numSegments;
55 vals[i % numSegments] += i;
56 }
57 const t = tf.tensor1d(values);
58 const segmentIds = tf.tensor1d(segmentIdValues, 'int32');
59 const res = tf.unsortedSegmentSum(t, segmentIds, numSegments);
60 expect(res.shape).toEqual([numSegments]);
61 expectArraysClose(await res.data(), vals);
62 });
63 it('ignores negative segmentIds', async () => {
64 const t = tf.tensor1d([1, 2, 3, 4]);
65 const segmentIds = tf.tensor1d([0, 2, -1, 1], 'int32');
66 const numSegments = 3;
67 const res = tf.unsortedSegmentSum(t, segmentIds, numSegments);
68 expect(res.shape).toEqual([numSegments]);
69 expectArraysClose(await res.data(), [1, 4, 2]);
70 });
71 it('gradient ignores negative segmentIds', async () => {
72 const t = tf.tensor1d([1, 2, 3, 4]);
73 const segmentIds = tf.tensor1d([0, 2, -1, 1], 'int32');
74 const numSegments = 3;
75 const dy = tf.tensor1d([11, 2, 7]);
76 const gradient = tf.grad(a => tf.unsortedSegmentSum(a, segmentIds, numSegments))(t, dy);
77 expect(gradient.shape).toEqual(t.shape);
78 expectArraysClose(await gradient.data(), [11, 7, 0, 2]);
79 });
80 it('tensor1D gradient', async () => {
81 const t = tf.tensor1d([1, 2, 3, 4]);
82 const segmentIds = tf.tensor1d([0, 2, 0, 1], 'int32');
83 const numSegments = 3;
84 const dy = tf.tensor1d([11, 2, 7]);
85 const gradient = tf.grad(a => tf.unsortedSegmentSum(a, segmentIds, numSegments))(t, dy);
86 expect(gradient.shape).toEqual(t.shape);
87 expectArraysClose(await gradient.data(), [11, 7, 11, 2]);
88 });
89 it('gradient with clones', async () => {
90 const t = tf.tensor1d([1, 2, 3, 4]);
91 const segmentIds = tf.tensor1d([0, 2, 0, 1], 'int32');
92 const numSegments = 3;
93 const dy = tf.tensor1d([11, 2, 7]);
94 const gradient = tf.grad(a => tf.unsortedSegmentSum(a.clone(), segmentIds.clone(), numSegments)
95 .clone())(t, dy);
96 expect(gradient.shape).toEqual(t.shape);
97 expectArraysClose(await gradient.data(), [11, 7, 11, 2]);
98 });
99 it('tensor2D gradient', async () => {
100 const t = tf.tensor2d([1, 2, 3, 4], [2, 2]);
101 const segmentIds = tf.tensor1d([0, 0], 'int32');
102 const numSegments = 2;
103 const dy = tf.tensor2d([11, 2, 4, 5], [2, 2]);
104 const gradient = tf.grad(a => tf.unsortedSegmentSum(a, segmentIds, numSegments))(t, dy);
105 expect(gradient.shape).toEqual(t.shape);
106 expectArraysClose(await gradient.data(), [11, 2, 11, 2]);
107 });
108 it('tensor3D gradient', async () => {
109 const t = tf.tensor3d([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], [3, 2, 2]);
110 const segmentIds = tf.tensor1d([2, 1, 2], 'int32');
111 const numSegments = 3;
112 const dy = tf.tensor3d([11, 2, 4, 5, 17, 31, 1, 0, -1, 14, 3, 28], [3, 2, 2]);
113 const gradient = tf.grad(a => tf.unsortedSegmentSum(a, segmentIds, numSegments))(t, dy);
114 expect(gradient.shape).toEqual(t.shape);
115 expectArraysClose(await gradient.data(), [-1, 14, 3, 28, 17, 31, 1, 0, -1, 14, 3, 28]);
116 });
117 it('accepts a tensor-like object', async () => {
118 const x = [1, 2, 3, 4];
119 const segmentIds = [0, 2, 0, 1];
120 const numSegments = 3;
121 const res = tf.unsortedSegmentSum(x, segmentIds, numSegments);
122 expect(res.shape).toEqual([3]);
123 expectArraysClose(await res.data(), [4, 4, 2]);
124 });
125 it('accepts a tensor-like object chained', async () => {
126 const x = tf.tensor1d([1, 2, 3, 4]);
127 const segmentIds = [0, 2, 0, 1];
128 const numSegments = 3;
129 const res = x.unsortedSegmentSum(segmentIds, numSegments);
130 expect(res.shape).toEqual([3]);
131 expectArraysClose(await res.data(), [4, 4, 2]);
132 });
133});
134//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidW5zb3J0ZWRfc2VnbWVudF9zdW1fdGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3RmanMtY29yZS9zcmMvb3BzL3Vuc29ydGVkX3NlZ21lbnRfc3VtX3Rlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBRUgsT0FBTyxLQUFLLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDL0IsT0FBTyxFQUFDLFFBQVEsRUFBRSxpQkFBaUIsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQzVELE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLGNBQWMsQ0FBQztBQUMvQyxPQUFPLEVBQUMscUJBQXFCLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFFcEQsaUJBQWlCLENBQUMsb0JBQW9CLEVBQUUsUUFBUSxFQUFFLEdBQUcsRUFBRTtJQUNyRCxFQUFFLENBQUMsVUFBVSxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ3hCLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3BDLE1BQU0sVUFBVSxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUN0RCxNQUFNLFdBQVcsR0FBRyxDQUFDLENBQUM7UUFDdEIsTUFBTSxHQUFHLEdBQUcsRUFBRSxDQUFDLGtCQUFrQixDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFFOUQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO1FBQ3pDLGlCQUFpQixDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2pELENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLFVBQVUsRUFBRSxLQUFLLElBQUksRUFBRTtRQUN4QixNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM1QyxNQUFNLFVBQVUsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ2hELE1BQU0sV0FBVyxHQUFHLENBQUMsQ0FBQztRQUN0QixNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxFQUFFLFVBQVUsRUFBRSxXQUFXLENBQUMsQ0FBQztRQUU5RCxNQUFNLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzVDLGlCQUFpQixDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNwRCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxVQUFVLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDeEIsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDMUUsTUFBTSxVQUFVLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDbkQsTUFBTSxXQUFXLEdBQUcsQ0FBQyxDQUFDO1FBQ3RCLE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLEVBQUUsVUFBVSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBRTlELE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQy9DLGlCQUFpQixDQUNiLE1BQU0sR0FBRyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2xFLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLDhDQUE4QyxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQzVELE1BQU0sQ0FBQyxHQUFHLHFCQUFxQixHQUFHLENBQUMsQ0FBQztRQUNwQyxNQUFNLE1BQU0sR0FBRyxJQUFJLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNuQyxNQUFNLFdBQVcsR0FBRyxDQUFDLENBQUM7UUFDdEIsTUFBTSxlQUFlLEdBQUcsSUFBSSxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDNUMsTUFBTSxJQUFJLEdBQUcsSUFBSSxZQUFZLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDM0MsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUMxQixNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ2QsZUFBZSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxXQUFXLENBQUM7WUFDckMsSUFBSSxDQUFDLENBQUMsR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDNUI7UUFDRCxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzlCLE1BQU0sVUFBVSxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsZUFBZSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3pELE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLEVBQUUsVUFBVSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBRTlELE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztRQUN6QyxpQkFBaUIsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUM1QyxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyw2QkFBNkIsRUFBRSxLQUFLLElBQUksRUFBRTtRQUMzQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNwQyxNQUFNLFVBQVUsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUN2RCxNQUFNLFdBQVcsR0FBRyxDQUFDLENBQUM7UUFFdEIsTUFBTSxHQUFHLEdBQUcsRUFBRSxDQUFDLGtCQUFrQixDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFFOUQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO1FBQ3pDLGlCQUFpQixDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2pELENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLHNDQUFzQyxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ3BELE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3BDLE1BQU0sVUFBVSxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3ZELE1BQU0sV0FBVyxHQUFHLENBQUMsQ0FBQztRQUV0QixNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ25DLE1BQU0sUUFBUSxHQUNWLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxFQUFFLFVBQVUsRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUUzRSxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDeEMsaUJBQWlCLENBQUMsTUFBTSxRQUFRLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFELENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLG1CQUFtQixFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ2pDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3BDLE1BQU0sVUFBVSxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUN0RCxNQUFNLFdBQVcsR0FBRyxDQUFDLENBQUM7UUFFdEIsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNuQyxNQUFNLFFBQVEsR0FDVixFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLGtCQUFrQixDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFM0UsTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3hDLGlCQUFpQixDQUFDLE1BQU0sUUFBUSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzRCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxzQkFBc0IsRUFBRSxLQUFLLElBQUksRUFBRTtRQUNwQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNwQyxNQUFNLFVBQVUsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDdEQsTUFBTSxXQUFXLEdBQUcsQ0FBQyxDQUFDO1FBRXRCLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbkMsTUFBTSxRQUFRLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FDcEIsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLFVBQVUsQ0FBQyxLQUFLLEVBQUUsRUFBRSxXQUFXLENBQUM7YUFDNUQsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFOUIsTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3hDLGlCQUFpQixDQUFDLE1BQU0sUUFBUSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzRCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxtQkFBbUIsRUFBRSxLQUFLLElBQUksRUFBRTtRQUNqQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM1QyxNQUFNLFVBQVUsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ2hELE1BQU0sV0FBVyxHQUFHLENBQUMsQ0FBQztRQUV0QixNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5QyxNQUFNLFFBQVEsR0FDVixFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLGtCQUFrQixDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFM0UsTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3hDLGlCQUFpQixDQUFDLE1BQU0sUUFBUSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzRCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxtQkFBbUIsRUFBRSxLQUFLLElBQUksRUFBRTtRQUNqQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMxRSxNQUFNLFVBQVUsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNuRCxNQUFNLFdBQVcsR0FBRyxDQUFDLENBQUM7UUFFdEIsTUFBTSxFQUFFLEdBQ0osRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN2RSxNQUFNLFFBQVEsR0FDVixFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLGtCQUFrQixDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFM0UsTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3hDLGlCQUFpQixDQUNiLE1BQU0sUUFBUSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMzRSxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyw4QkFBOEIsRUFBRSxLQUFLLElBQUksRUFBRTtRQUM1QyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3ZCLE1BQU0sVUFBVSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDaEMsTUFBTSxXQUFXLEdBQUcsQ0FBQyxDQUFDO1FBQ3RCLE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLEVBQUUsVUFBVSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBQzlELE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMvQixpQkFBaUIsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNqRCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxzQ0FBc0MsRUFBRSxLQUFLLElBQUksRUFBRTtRQUNwRCxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNwQyxNQUFNLFVBQVUsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ2hDLE1BQU0sV0FBVyxHQUFHLENBQUMsQ0FBQztRQUN0QixNQUFNLEdBQUcsR0FBRyxDQUFDLENBQUMsa0JBQWtCLENBQUMsVUFBVSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBRTFELE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMvQixpQkFBaUIsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNqRCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTggR29vZ2xlIExMQy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqL1xuXG5pbXBvcnQgKiBhcyB0ZiBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQge0FMTF9FTlZTLCBkZXNjcmliZVdpdGhGbGFnc30gZnJvbSAnLi4vamFzbWluZV91dGlsJztcbmltcG9ydCB7ZXhwZWN0QXJyYXlzQ2xvc2V9IGZyb20gJy4uL3Rlc3RfdXRpbCc7XG5pbXBvcnQge1BBUkFMTEVMSVpFX1RIUkVTSE9MRH0gZnJvbSAnLi9yZWR1Y2VfdXRpbCc7XG5cbmRlc2NyaWJlV2l0aEZsYWdzKCd1bnNvcnRlZFNlZ21lbnRTdW0nLCBBTExfRU5WUywgKCkgPT4ge1xuICBpdCgndGVuc29yMUQnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgdCA9IHRmLnRlbnNvcjFkKFsxLCAyLCAzLCA0XSk7XG4gICAgY29uc3Qgc2VnbWVudElkcyA9IHRmLnRlbnNvcjFkKFswLCAyLCAwLCAxXSwgJ2ludDMyJyk7XG4gICAgY29uc3QgbnVtU2VnbWVudHMgPSAzO1xuICAgIGNvbnN0IHJlcyA9IHRmLnVuc29ydGVkU2VnbWVudFN1bSh0LCBzZWdtZW50SWRzLCBudW1TZWdtZW50cyk7XG5cbiAgICBleHBlY3QocmVzLnNoYXBlKS50b0VxdWFsKFtudW1TZWdtZW50c10pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHJlcy5kYXRhKCksIFs0LCA0LCAyXSk7XG4gIH0pO1xuXG4gIGl0KCd0ZW5zb3IyRCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB0ID0gdGYudGVuc29yMmQoWzEsIDIsIDMsIDRdLCBbMiwgMl0pO1xuICAgIGNvbnN0IHNlZ21lbnRJZHMgPSB0Zi50ZW5zb3IxZChbMCwgMF0sICdpbnQzMicpO1xuICAgIGNvbnN0IG51bVNlZ21lbnRzID0gMjtcbiAgICBjb25zdCByZXMgPSB0Zi51bnNvcnRlZFNlZ21lbnRTdW0odCwgc2VnbWVudElkcywgbnVtU2VnbWVudHMpO1xuXG4gICAgZXhwZWN0KHJlcy5zaGFwZSkudG9FcXVhbChbbnVtU2VnbWVudHMsIDJdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCByZXMuZGF0YSgpLCBbNCwgNiwgMCwgMF0pO1xuICB9KTtcblxuICBpdCgndGVuc29yM0QnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgdCA9IHRmLnRlbnNvcjNkKFsxLCAyLCAzLCA0LCA1LCA2LCA3LCA4LCA5LCAxMCwgMTEsIDEyXSwgWzMsIDIsIDJdKTtcbiAgICBjb25zdCBzZWdtZW50SWRzID0gdGYudGVuc29yMWQoWzIsIDEsIDJdLCAnaW50MzInKTtcbiAgICBjb25zdCBudW1TZWdtZW50cyA9IDM7XG4gICAgY29uc3QgcmVzID0gdGYudW5zb3J0ZWRTZWdtZW50U3VtKHQsIHNlZ21lbnRJZHMsIG51bVNlZ21lbnRzKTtcblxuICAgIGV4cGVjdChyZXMuc2hhcGUpLnRvRXF1YWwoW251bVNlZ21lbnRzLCAyLCAyXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoXG4gICAgICAgIGF3YWl0IHJlcy5kYXRhKCksIFswLCAwLCAwLCAwLCA1LCA2LCA3LCA4LCAxMCwgMTIsIDE0LCAxNl0pO1xuICB9KTtcblxuICBpdCgnTiA+IHRoYW4gcGFyYWxsZWxpemF0aW9uIHRocmVzaG9sZCwgdGVuc29yMUQnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgbiA9IFBBUkFMTEVMSVpFX1RIUkVTSE9MRCAqIDI7XG4gICAgY29uc3QgdmFsdWVzID0gbmV3IEZsb2F0MzJBcnJheShuKTtcbiAgICBjb25zdCBudW1TZWdtZW50cyA9IDU7XG4gICAgY29uc3Qgc2VnbWVudElkVmFsdWVzID0gbmV3IEZsb2F0MzJBcnJheShuKTtcbiAgICBjb25zdCB2YWxzID0gbmV3IEZsb2F0MzJBcnJheShudW1TZWdtZW50cyk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuOyBpKyspIHtcbiAgICAgIHZhbHVlc1tpXSA9IGk7XG4gICAgICBzZWdtZW50SWRWYWx1ZXNbaV0gPSBpICUgbnVtU2VnbWVudHM7XG4gICAgICB2YWxzW2kgJSBudW1TZWdtZW50c10gKz0gaTtcbiAgICB9XG4gICAgY29uc3QgdCA9IHRmLnRlbnNvcjFkKHZhbHVlcyk7XG4gICAgY29uc3Qgc2VnbWVudElkcyA9IHRmLnRlbnNvcjFkKHNlZ21lbnRJZFZhbHVlcywgJ2ludDMyJyk7XG4gICAgY29uc3QgcmVzID0gdGYudW5zb3J0ZWRTZWdtZW50U3VtKHQsIHNlZ21lbnRJZHMsIG51bVNlZ21lbnRzKTtcblxuICAgIGV4cGVjdChyZXMuc2hhcGUpLnRvRXF1YWwoW251bVNlZ21lbnRzXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgcmVzLmRhdGEoKSwgdmFscyk7XG4gIH0pO1xuXG4gIGl0KCdpZ25vcmVzIG5lZ2F0aXZlIHNlZ21lbnRJZHMnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgdCA9IHRmLnRlbnNvcjFkKFsxLCAyLCAzLCA0XSk7XG4gICAgY29uc3Qgc2VnbWVudElkcyA9IHRmLnRlbnNvcjFkKFswLCAyLCAtMSwgMV0sICdpbnQzMicpO1xuICAgIGNvbnN0IG51bVNlZ21lbnRzID0gMztcblxuICAgIGNvbnN0IHJlcyA9IHRmLnVuc29ydGVkU2VnbWVudFN1bSh0LCBzZWdtZW50SWRzLCBudW1TZWdtZW50cyk7XG5cbiAgICBleHBlY3QocmVzLnNoYXBlKS50b0VxdWFsKFtudW1TZWdtZW50c10pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHJlcy5kYXRhKCksIFsxLCA0LCAyXSk7XG4gIH0pO1xuXG4gIGl0KCdncmFkaWVudCBpZ25vcmVzIG5lZ2F0aXZlIHNlZ21lbnRJZHMnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgdCA9IHRmLnRlbnNvcjFkKFsxLCAyLCAzLCA0XSk7XG4gICAgY29uc3Qgc2VnbWVudElkcyA9IHRmLnRlbnNvcjFkKFswLCAyLCAtMSwgMV0sICdpbnQzMicpO1xuICAgIGNvbnN0IG51bVNlZ21lbnRzID0gMztcblxuICAgIGNvbnN0IGR5ID0gdGYudGVuc29yMWQoWzExLCAyLCA3XSk7XG4gICAgY29uc3QgZ3JhZGllbnQgPVxuICAgICAgICB0Zi5ncmFkKGEgPT4gdGYudW5zb3J0ZWRTZWdtZW50U3VtKGEsIHNlZ21lbnRJZHMsIG51bVNlZ21lbnRzKSkodCwgZHkpO1xuXG4gICAgZXhwZWN0KGdyYWRpZW50LnNoYXBlKS50b0VxdWFsKHQuc2hhcGUpO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IGdyYWRpZW50LmRhdGEoKSwgWzExLCA3LCAwLCAyXSk7XG4gIH0pO1xuXG4gIGl0KCd0ZW5zb3IxRCBncmFkaWVudCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB0ID0gdGYudGVuc29yMWQoWzEsIDIsIDMsIDRdKTtcbiAgICBjb25zdCBzZWdtZW50SWRzID0gdGYudGVuc29yMWQoWzAsIDIsIDAsIDFdLCAnaW50MzInKTtcbiAgICBjb25zdCBudW1TZWdtZW50cyA9IDM7XG5cbiAgICBjb25zdCBkeSA9IHRmLnRlbnNvcjFkKFsxMSwgMiwgN10pO1xuICAgIGNvbnN0IGdyYWRpZW50ID1cbiAgICAgICAgdGYuZ3JhZChhID0+IHRmLnVuc29ydGVkU2VnbWVudFN1bShhLCBzZWdtZW50SWRzLCBudW1TZWdtZW50cykpKHQsIGR5KTtcblxuICAgIGV4cGVjdChncmFkaWVudC5zaGFwZSkudG9FcXVhbCh0LnNoYXBlKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCBncmFkaWVudC5kYXRhKCksIFsxMSwgNywgMTEsIDJdKTtcbiAgfSk7XG5cbiAgaXQoJ2dyYWRpZW50IHdpdGggY2xvbmVzJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHQgPSB0Zi50ZW5zb3IxZChbMSwgMiwgMywgNF0pO1xuICAgIGNvbnN0IHNlZ21lbnRJZHMgPSB0Zi50ZW5zb3IxZChbMCwgMiwgMCwgMV0sICdpbnQzMicpO1xuICAgIGNvbnN0IG51bVNlZ21lbnRzID0gMztcblxuICAgIGNvbnN0IGR5ID0gdGYudGVuc29yMWQoWzExLCAyLCA3XSk7XG4gICAgY29uc3QgZ3JhZGllbnQgPSB0Zi5ncmFkKFxuICAgICAgICBhID0+IHRmLnVuc29ydGVkU2VnbWVudFN1bShhLmNsb25lKCksIHNlZ21lbnRJZHMuY2xvbmUoKSwgbnVtU2VnbWVudHMpXG4gICAgICAgICAgICAgICAgIC5jbG9uZSgpKSh0LCBkeSk7XG5cbiAgICBleHBlY3QoZ3JhZGllbnQuc2hhcGUpLnRvRXF1YWwodC5zaGFwZSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgZ3JhZGllbnQuZGF0YSgpLCBbMTEsIDcsIDExLCAyXSk7XG4gIH0pO1xuXG4gIGl0KCd0ZW5zb3IyRCBncmFkaWVudCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB0ID0gdGYudGVuc29yMmQoWzEsIDIsIDMsIDRdLCBbMiwgMl0pO1xuICAgIGNvbnN0IHNlZ21lbnRJZHMgPSB0Zi50ZW5zb3IxZChbMCwgMF0sICdpbnQzMicpO1xuICAgIGNvbnN0IG51bVNlZ21lbnRzID0gMjtcblxuICAgIGNvbnN0IGR5ID0gdGYudGVuc29yMmQoWzExLCAyLCA0LCA1XSwgWzIsIDJdKTtcbiAgICBjb25zdCBncmFkaWVudCA9XG4gICAgICAgIHRmLmdyYWQoYSA9PiB0Zi51bnNvcnRlZFNlZ21lbnRTdW0oYSwgc2VnbWVudElkcywgbnVtU2VnbWVudHMpKSh0LCBkeSk7XG5cbiAgICBleHBlY3QoZ3JhZGllbnQuc2hhcGUpLnRvRXF1YWwodC5zaGFwZSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgZ3JhZGllbnQuZGF0YSgpLCBbMTEsIDIsIDExLCAyXSk7XG4gIH0pO1xuXG4gIGl0KCd0ZW5zb3IzRCBncmFkaWVudCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB0ID0gdGYudGVuc29yM2QoWzEsIDIsIDMsIDQsIDUsIDYsIDcsIDgsIDksIDEwLCAxMSwgMTJdLCBbMywgMiwgMl0pO1xuICAgIGNvbnN0IHNlZ21lbnRJZHMgPSB0Zi50ZW5zb3IxZChbMiwgMSwgMl0sICdpbnQzMicpO1xuICAgIGNvbnN0IG51bVNlZ21lbnRzID0gMztcblxuICAgIGNvbnN0IGR5ID1cbiAgICAgICAgdGYudGVuc29yM2QoWzExLCAyLCA0LCA1LCAxNywgMzEsIDEsIDAsIC0xLCAxNCwgMywgMjhdLCBbMywgMiwgMl0pO1xuICAgIGNvbnN0IGdyYWRpZW50ID1cbiAgICAgICAgdGYuZ3JhZChhID0+IHRmLnVuc29ydGVkU2VnbWVudFN1bShhLCBzZWdtZW50SWRzLCBudW1TZWdtZW50cykpKHQsIGR5KTtcblxuICAgIGV4cGVjdChncmFkaWVudC5zaGFwZSkudG9FcXVhbCh0LnNoYXBlKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShcbiAgICAgICAgYXdhaXQgZ3JhZGllbnQuZGF0YSgpLCBbLTEsIDE0LCAzLCAyOCwgMTcsIDMxLCAxLCAwLCAtMSwgMTQsIDMsIDI4XSk7XG4gIH0pO1xuXG4gIGl0KCdhY2NlcHRzIGEgdGVuc29yLWxpa2Ugb2JqZWN0JywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHggPSBbMSwgMiwgMywgNF07XG4gICAgY29uc3Qgc2VnbWVudElkcyA9IFswLCAyLCAwLCAxXTtcbiAgICBjb25zdCBudW1TZWdtZW50cyA9IDM7XG4gICAgY29uc3QgcmVzID0gdGYudW5zb3J0ZWRTZWdtZW50U3VtKHgsIHNlZ21lbnRJZHMsIG51bVNlZ21lbnRzKTtcbiAgICBleHBlY3QocmVzLnNoYXBlKS50b0VxdWFsKFszXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgcmVzLmRhdGEoKSwgWzQsIDQsIDJdKTtcbiAgfSk7XG5cbiAgaXQoJ2FjY2VwdHMgYSB0ZW5zb3ItbGlrZSBvYmplY3QgY2hhaW5lZCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB4ID0gdGYudGVuc29yMWQoWzEsIDIsIDMsIDRdKTtcbiAgICBjb25zdCBzZWdtZW50SWRzID0gWzAsIDIsIDAsIDFdO1xuICAgIGNvbnN0IG51bVNlZ21lbnRzID0gMztcbiAgICBjb25zdCByZXMgPSB4LnVuc29ydGVkU2VnbWVudFN1bShzZWdtZW50SWRzLCBudW1TZWdtZW50cyk7XG5cbiAgICBleHBlY3QocmVzLnNoYXBlKS50b0VxdWFsKFszXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgcmVzLmRhdGEoKSwgWzQsIDQsIDJdKTtcbiAgfSk7XG59KTtcbiJdfQ==
\No newline at end of file