UNPKG

@tensorflow/tfjs-core

Version:

Hardware-accelerated JavaScript library for machine intelligence

363 lines 65.7 kB
/** * @license * Copyright 2021 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 { expectArraysEqual } from '../../test_util'; async function expectResult(result, nGrams, nGramsSplits) { expectArraysEqual(await result.nGrams.data(), nGrams); expectArraysEqual(await result.nGramsSplits.data(), nGramsSplits); expect(result.nGrams.shape).toEqual([nGrams.length]); expect(result.nGramsSplits.shape).toEqual([nGramsSplits.length]); expect(result.nGrams.dtype).toEqual('string'); expect(result.nGramsSplits.dtype).toEqual('int32'); } describeWithFlags('stringNGrams', ALL_ENVS, () => { it('padded trigrams', async () => { // Batch items are: // 0: "a", "b", "c", "d" // 1: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 4, 6], 'int32'), '|', [3], 'LP', 'RP', -1, false); const nGrams = [ 'LP|LP|a', 'LP|a|b', 'a|b|c', 'b|c|d', 'c|d|RP', 'd|RP|RP', 'LP|LP|e', 'LP|e|f', 'e|f|RP', 'f|RP|RP' // 1 ]; const nGramsSplits = [0, 6, 10]; await expectResult(result, nGrams, nGramsSplits); }); it('padded bigrams and trigrams', async () => { // Batch items are: // 0: "a", "b", "c", "d" // 1: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 4, 6], 'int32'), '|', [2, 3], 'LP', 'RP', -1, false); const nGrams = [ 'LP|a', 'a|b', 'b|c', 'c|d', 'd|RP', 'LP|LP|a', 'LP|a|b', 'a|b|c', 'b|c|d', 'c|d|RP', 'd|RP|RP', 'LP|e', 'e|f', 'f|RP', 'LP|LP|e', 'LP|e|f', 'e|f|RP', 'f|RP|RP' // 1 ]; const nGramsSplits = [0, 11, 18]; await expectResult(result, nGrams, nGramsSplits); }); it('padded bigrams', async () => { // Batch items are: // 0: "a", "b", "c", "d" // 1: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 4, 6], 'int32'), '|', [2], 'LP', 'RP', -1, false); const nGrams = [ 'LP|a', 'a|b', 'b|c', 'c|d', 'd|RP', 'LP|e', 'e|f', 'f|RP' // 1 ]; const nGramsSplits = [0, 5, 8]; await expectResult(result, nGrams, nGramsSplits); }); it('padding is at most nGramSize - 1', async () => { // Batch items are: // 0: "a", "b", "c", "d" // 1: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 4, 6], 'int32'), '|', [2], 'LP', 'RP', 4, false); const nGrams = [ 'LP|a', 'a|b', 'b|c', 'c|d', 'd|RP', 'LP|e', 'e|f', 'f|RP' // 1 ]; const nGramsSplits = [0, 5, 8]; await expectResult(result, nGrams, nGramsSplits); }); it('padded unigram and bigrams', async () => { // Batch items are: // 0: "a", "b", "c", "d" // 1: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 4, 6], 'int32'), '|', [1, 2], 'LP', 'RP', -1, false); const nGrams = [ 'a', 'b', 'c', 'd', 'LP|a', 'a|b', 'b|c', 'c|d', 'd|RP', 'e', 'f', 'LP|e', 'e|f', 'f|RP' // 1 ]; const nGramsSplits = [0, 9, 14]; await expectResult(result, nGrams, nGramsSplits); }); it('overlapping padded nGrams', async () => { // This test validates that n-grams with both left and right padding in a // single ngram token are created correctly. // Batch items are: // 0: "a" // 1: "b", "c", "d" // 2: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 1, 4, 6], 'int32'), '|', [3], 'LP', 'RP', -1, false); const nGrams = [ 'LP|LP|a', 'LP|a|RP', 'a|RP|RP', 'LP|LP|b', 'LP|b|c', 'b|c|d', 'c|d|RP', 'd|RP|RP', 'LP|LP|e', 'LP|e|f', 'e|f|RP', 'f|RP|RP' // 2 ]; const nGramsSplits = [0, 3, 8, 12]; await expectResult(result, nGrams, nGramsSplits); }); it('overlapping padded multi char nGrams', async () => { // Batch items are: // 0: "a" // 1: "b", "c", "d" // 2: "e", "f" const result = tf.string.stringNGrams(['aa', 'bb', 'cc', 'dd', 'ee', 'ff'], tf.tensor1d([0, 1, 4, 6], 'int32'), '|', [3], 'LP', 'RP', -1, false); const nGrams = [ 'LP|LP|aa', 'LP|aa|RP', 'aa|RP|RP', 'LP|LP|bb', 'LP|bb|cc', 'bb|cc|dd', 'cc|dd|RP', 'dd|RP|RP', 'LP|LP|ee', 'LP|ee|ff', 'ee|ff|RP', 'ff|RP|RP' // 2 ]; const nGramsSplits = [0, 3, 8, 12]; await expectResult(result, nGrams, nGramsSplits); }); it('multi overlapping padded nGrams', async () => { // This test validates that n-grams with more than 1 padding value on each // side are created correctly. // Batch items are: // 0: "a" const result = tf.string.stringNGrams(['a'], tf.tensor1d([0, 1], 'int32'), '|', [5], 'LP', 'RP', -1, false); const nGrams = [ 'LP|LP|LP|LP|a', 'LP|LP|LP|a|RP', 'LP|LP|a|RP|RP', 'LP|a|RP|RP|RP', 'a|RP|RP|RP|RP' ]; const nGramsSplits = [0, 5]; await expectResult(result, nGrams, nGramsSplits); }); it('unpadded trigrams', async () => { // Batch items are: // 0: "a", "b", "c", "d" // 1: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 4, 6], 'int32'), '|', [3], '', '', 0, false); const nGrams = ['a|b|c', 'b|c|d']; const nGramsSplits = [0, 2, 2]; await expectResult(result, nGrams, nGramsSplits); }); it('unpadded trigrams with empty sequence', async () => { // Batch items are: // 0: "a", "b", "c", "d" // 1: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 4, 4, 6], 'int32'), '|', [3], '', '', 0, false); const nGrams = ['a|b|c', 'b|c|d']; const nGramsSplits = [0, 2, 2, 2]; await expectResult(result, nGrams, nGramsSplits); }); it('unpadded trigrams with preserve short', async () => { // Batch items are: // 0: "a", "b", "c", "d" // 1: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 4, 6], 'int32'), '|', [3], '', '', 0, true); const nGrams = ['a|b|c', 'b|c|d', 'e|f']; const nGramsSplits = [0, 2, 3]; await expectResult(result, nGrams, nGramsSplits); }); it('unpadded trigrams with preserve short and empty sequence', async () => { // Batch items are: // 0: "a", "b", "c", "d" // 1: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 4, 4, 6], 'int32'), '|', [3], '', '', 0, true); const nGrams = ['a|b|c', 'b|c|d', 'e|f']; const nGramsSplits = [0, 2, 2, 3]; await expectResult(result, nGrams, nGramsSplits); }); it('unpadded trigrams and quad grams with preserve short', async () => { // Batch items are: // 0: "a", "b", "c", "d" // 1: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 4, 6], 'int32'), '|', [4, 3], '', '', 0, true); const nGrams = ['a|b|c|d', 'a|b|c', 'b|c|d', 'e|f']; const nGramsSplits = [0, 3, 4]; await expectResult(result, nGrams, nGramsSplits); }); it('unpadded bigrams and trigrams', async () => { // Batch items are: // 0: "a", "b", "c", "d" // 1: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 4, 6], 'int32'), '|', [2, 3], '', '', 0, false); const nGrams = ['a|b', 'b|c', 'c|d', 'a|b|c', 'b|c|d', 'e|f']; const nGramsSplits = [0, 5, 6]; await expectResult(result, nGrams, nGramsSplits); }); it('unpadded bigrams and trigrams with preserve short', async () => { // Batch items are: // 0: "a", "b", "c", "d" // 1: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 4, 6], 'int32'), '|', [2, 3], '', '', 0, true); // Note that in this case, because the bigram 'e|f' was already generated, // the op will not generate a special preserveShort bigram. const nGrams = ['a|b', 'b|c', 'c|d', 'a|b|c', 'b|c|d', 'e|f']; const nGramsSplits = [0, 5, 6]; await expectResult(result, nGrams, nGramsSplits); }); it('unpadded trigrams and bigrams with preserve short', async () => { // Batch items are: // 0: "a", "b", "c", "d" // 1: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 4, 6], 'int32'), '|', [3, 2], '', '', 0, true); // Note that in this case, because the bigram 'e|f' was already generated, // the op will not generate a special preserveShort bigram. const nGrams = ['a|b|c', 'b|c|d', 'a|b', 'b|c', 'c|d', 'e|f']; const nGramsSplits = [0, 5, 6]; await expectResult(result, nGrams, nGramsSplits); }); it('unpadded bigrams', async () => { // Batch items are: // 0: "a", "b", "c", "d" // 1: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 4, 6], 'int32'), '|', [2], '', '', 0, false); const nGrams = ['a|b', 'b|c', 'c|d', 'e|f']; const nGramsSplits = [0, 3, 4]; await expectResult(result, nGrams, nGramsSplits); }); it('overlapping unpadded nGrams', async () => { // Batch items are: // 0: "a" // 1: "b", "c", "d" // 2: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 1, 4, 6], 'int32'), '|', [3], '', '', 0, false); const nGrams = ['b|c|d']; const nGramsSplits = [0, 0, 1, 1]; await expectResult(result, nGrams, nGramsSplits); }); it('overlapping unpadded nGrams no output', async () => { // Batch items are: // 0: "a" // 1: "b", "c", "d" // 2: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 1, 4, 6], 'int32'), '|', [5], '', '', 0, false); const nGrams = []; const nGramsSplits = [0, 0, 0, 0]; await expectResult(result, nGrams, nGramsSplits); }); it('singly padded trigrams', async () => { // Batch items are: // 0: "a", "b", "c", "d" // 1: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 4, 6], 'int32'), '|', [3], 'LP', 'RP', 1, false); const nGrams = [ 'LP|a|b', 'a|b|c', 'b|c|d', 'c|d|RP', 'LP|e|f', 'e|f|RP' ]; const nGramsSplits = [0, 4, 6]; await expectResult(result, nGrams, nGramsSplits); }); it('singly padded bigrams', async () => { // Batch items are: // 0: "a", "b", "c", "d" // 1: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 4, 6], 'int32'), '|', [2], 'LP', 'RP', 1, false); const nGrams = [ 'LP|a', 'a|b', 'b|c', 'c|d', 'd|RP', 'LP|e', 'e|f', 'f|RP' ]; const nGramsSplits = [0, 5, 8]; await expectResult(result, nGrams, nGramsSplits); }); it('singly padded bigrams and 5grams', async () => { // Batch items are: // 0: "a", "b", "c", "d" // 1: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 4, 6], 'int32'), '|', [2, 5], 'LP', 'RP', 1, false); const nGrams = [ 'LP|a', 'a|b', 'b|c', 'c|d', 'd|RP', 'LP|a|b|c|d', 'a|b|c|d|RP', 'LP|e', 'e|f', 'f|RP' ]; const nGramsSplits = [0, 7, 10]; await expectResult(result, nGrams, nGramsSplits); }); it('singly padded 5grams with preserve short', async () => { // Batch items are: // 0: "a", "b", "c", "d" // 1: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 4, 6], 'int32'), '|', [5], 'LP', 'RP', 1, true); const nGrams = [ 'LP|a|b|c|d', 'a|b|c|d|RP', 'LP|e|f|RP' ]; const nGramsSplits = [0, 2, 3]; await expectResult(result, nGrams, nGramsSplits); }); it('overlapping singly padded nGrams', async () => { // Batch items are: // 0: "a" // 1: "b", "c", "d" // 2: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 1, 4, 6], 'int32'), '|', [3], 'LP', 'RP', 1, false); const nGrams = [ 'LP|a|RP', 'LP|b|c', 'b|c|d', 'c|d|RP', 'LP|e|f', 'e|f|RP' ]; const nGramsSplits = [0, 1, 4, 6]; await expectResult(result, nGrams, nGramsSplits); }); it('overlapping singly padded nGrams no output', async () => { // Batch items are: // 0: "a" // 1: "b", "c", "d" // 2: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 1, 4, 6], 'int32'), '|', [5], 'LP', 'RP', 1, false); const nGrams = ['LP|b|c|d|RP']; const nGramsSplits = [0, 0, 1, 1]; await expectResult(result, nGrams, nGramsSplits); }); it('singly padded unigrams', async () => { // Batch items are: // 0: "a", "b", "c", "d" // 1: "e", "f" const result = tf.string.stringNGrams(['a', 'b', 'c', 'd', 'e', 'f'], tf.tensor1d([0, 4, 6], 'int32'), '|', [1], 'LP', 'RP', 1, false); const nGrams = ['a', 'b', 'c', 'd', 'e', 'f']; const nGramsSplits = [0, 4, 6]; await expectResult(result, nGrams, nGramsSplits); }); it('empty input', async () => { const result = tf.string.stringNGrams(tf.tensor1d([], 'string'), tf.tensor1d([], 'int32'), '|', [1], 'LP', 'RP', 3, false); const nGrams = []; const nGramsSplits = []; await expectResult(result, nGrams, nGramsSplits); }); it('no tokens', async () => { // Batch items are: // 0: // 1: "a" const result = tf.string.stringNGrams(['a'], tf.tensor1d([0, 0, 1], 'int32'), '|', [3], 'L', 'R', -1, false); const nGrams = [ 'L|L|R', 'L|R|R', 'L|L|a', 'L|a|R', 'a|R|R' // second split ]; const nGramsSplits = [0, 2, 5]; await expectResult(result, nGrams, nGramsSplits); }); it('no tokens no pad', async () => { // Batch items are: // 0: // 1: "a" const result = tf.string.stringNGrams(['a'], tf.tensor1d([0, 0, 1], 'int32'), '|', [3], '', '', 0, false); const nGrams = []; const nGramsSplits = [0, 0, 0]; await expectResult(result, nGrams, nGramsSplits); }); it('throw error if first partition index is not 0', async () => { expect(() => tf.string.stringNGrams(['a'], tf.tensor1d([1, 1, 1], 'int32'), '|', [3], '', '', 0, false)) .toThrowError(/First split value must be 0/); }); it('throw error if partition indices are decreasing', async () => { expect(() => tf.string.stringNGrams(['a'], tf.tensor1d([0, 1, 0], 'int32'), '|', [3], '', '', 0, false)) .toThrowError(/must be in \[1, 1\]/); }); it('throw error if partition index is >= input size', async () => { expect(() => tf.string.stringNGrams(['a'], tf.tensor1d([0, 2, 1], 'int32'), '|', [3], '', '', 0, false)) .toThrowError(/must be in \[0, 1\]/); }); it('throw error if last partition index is !== input size', async () => { expect(() => tf.string.stringNGrams(['a'], tf.tensor1d([0, 0], 'int32'), '|', [3], '', '', 0, false)) .toThrowError(/Last split value must be data size/); }); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RyaW5nX25fZ3JhbXNfdGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3RmanMtY29yZS9zcmMvb3BzL3N0cmluZy9zdHJpbmdfbl9ncmFtc190ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUVILE9BQU8sS0FBSyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ2xDLE9BQU8sRUFBQyxRQUFRLEVBQUUsaUJBQWlCLEVBQUMsTUFBTSxvQkFBb0IsQ0FBQztBQUMvRCxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUVsRCxLQUFLLFVBQVUsWUFBWSxDQUN2QixNQUF5QixFQUFFLE1BQWdCLEVBQUUsWUFBc0I7SUFDckUsaUJBQWlCLENBQUMsTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ3RELGlCQUFpQixDQUFDLE1BQU0sTUFBTSxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsRUFBRSxZQUFZLENBQUMsQ0FBQztJQUVsRSxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNyRCxNQUFNLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUVqRSxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDOUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0FBQ3JELENBQUM7QUFFRCxpQkFBaUIsQ0FBQyxj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O0lBRUgsRUFBRSxDQUFDLHVEQUF1RCxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ3JFLE1BQU0sQ0FDRixHQUFHLEVBQUUsQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FDeEIsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO2FBQ3BFLFlBQVksQ0FBQyxvQ0FBb0MsQ0FBQyxDQUFDO0lBQzFELENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMSBHb29nbGUgTExDLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICovXG5cbmltcG9ydCAqIGFzIHRmIGZyb20gJy4uLy4uL2luZGV4JztcbmltcG9ydCB7QUxMX0VOVlMsIGRlc2NyaWJlV2l0aEZsYWdzfSBmcm9tICcuLi8uLi9qYXNtaW5lX3V0aWwnO1xuaW1wb3J0IHtleHBlY3RBcnJheXNFcXVhbH0gZnJvbSAnLi4vLi4vdGVzdF91dGlsJztcblxuYXN5bmMgZnVuY3Rpb24gZXhwZWN0UmVzdWx0KFxuICAgIHJlc3VsdDogdGYuTmFtZWRUZW5zb3JNYXAsIG5HcmFtczogc3RyaW5nW10sIG5HcmFtc1NwbGl0czogbnVtYmVyW10pIHtcbiAgZXhwZWN0QXJyYXlzRXF1YWwoYXdhaXQgcmVzdWx0Lm5HcmFtcy5kYXRhKCksIG5HcmFtcyk7XG4gIGV4cGVjdEFycmF5c0VxdWFsKGF3YWl0IHJlc3VsdC5uR3JhbXNTcGxpdHMuZGF0YSgpLCBuR3JhbXNTcGxpdHMpO1xuXG4gIGV4cGVjdChyZXN1bHQubkdyYW1zLnNoYXBlKS50b0VxdWFsKFtuR3JhbXMubGVuZ3RoXSk7XG4gIGV4cGVjdChyZXN1bHQubkdyYW1zU3BsaXRzLnNoYXBlKS50b0VxdWFsKFtuR3JhbXNTcGxpdHMubGVuZ3RoXSk7XG5cbiAgZXhwZWN0KHJlc3VsdC5uR3JhbXMuZHR5cGUpLnRvRXF1YWwoJ3N0cmluZycpO1xuICBleHBlY3QocmVzdWx0Lm5HcmFtc1NwbGl0cy5kdHlwZSkudG9FcXVhbCgnaW50MzInKTtcbn1cblxuZGVzY3JpYmVXaXRoRmxhZ3MoJ3N0cmluZ05HcmFtcycsIEFMTF9FTlZTLCAoKSA9PiB7XG4gIGl0KCdwYWRkZWQgdHJpZ3JhbXMnLCBhc3luYyAoKSA9PiB7XG4gICAgLy8gQmF0Y2ggaXRlbXMgYXJlOlxuICAgIC8vIDA6IFwiYVwiLCBcImJcIiwgXCJjXCIsIFwiZFwiXG4gICAgLy8gMTogXCJlXCIsIFwiZlwiXG4gICAgY29uc3QgcmVzdWx0ID0gdGYuc3RyaW5nLnN0cmluZ05HcmFtcyhcbiAgICAgICAgWydhJywgJ2InLCAnYycsICdkJywgJ2UnLCAnZiddLCB0Zi50ZW5zb3IxZChbMCwgNCwgNl0sICdpbnQzMicpLCAnfCcsXG4gICAgICAgIFszXSwgJ0xQJywgJ1JQJywgLTEsIGZhbHNlKTtcbiAgICBjb25zdCBuR3JhbXMgPSBbXG4gICAgICAnTFB8TFB8YScsICdMUHxhfGInLCAnYXxifGMnLCAnYnxjfGQnLCAnY3xkfFJQJywgJ2R8UlB8UlAnLCAgLy8gMFxuICAgICAgJ0xQfExQfGUnLCAnTFB8ZXxmJywgJ2V8ZnxSUCcsICdmfFJQfFJQJyAgICAgICAgICAgICAgICAgICAgIC8vIDFcbiAgICBdO1xuICAgIGNvbnN0IG5HcmFtc1NwbGl0cyA9IFswLCA2LCAxMF07XG4gICAgYXdhaXQgZXhwZWN0UmVzdWx0KHJlc3VsdCwgbkdyYW1zLCBuR3JhbXNTcGxpdHMpO1xuICB9KTtcblxuICBpdCgncGFkZGVkIGJpZ3JhbXMgYW5kIHRyaWdyYW1zJywgYXN5bmMgKCkgPT4ge1xuICAgIC8vIEJhdGNoIGl0ZW1zIGFyZTpcbiAgICAvLyAwOiBcImFcIiwgXCJiXCIsIFwiY1wiLCBcImRcIlxuICAgIC8vIDE6IFwiZVwiLCBcImZcIlxuICAgIGNvbnN0IHJlc3VsdCA9IHRmLnN0cmluZy5zdHJpbmdOR3JhbXMoXG4gICAgICAgIFsnYScsICdiJywgJ2MnLCAnZCcsICdlJywgJ2YnXSwgdGYudGVuc29yMWQoWzAsIDQsIDZdLCAnaW50MzInKSwgJ3wnLFxuICAgICAgICBbMiwgM10sICdMUCcsICdSUCcsIC0xLCBmYWxzZSk7XG4gICAgY29uc3QgbkdyYW1zID0gW1xuICAgICAgJ0xQfGEnLCAnYXxiJywgJ2J8YycsICdjfGQnLCAnZHxSUCcsICdMUHxMUHxhJywgJ0xQfGF8YicsICdhfGJ8YycsXG4gICAgICAnYnxjfGQnLCAnY3xkfFJQJywgJ2R8UlB8UlAnLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIDBcbiAgICAgICdMUHxlJywgJ2V8ZicsICdmfFJQJywgJ0xQfExQfGUnLCAnTFB8ZXxmJywgJ2V8ZnxSUCcsICdmfFJQfFJQJyAgLy8gMVxuICAgIF07XG4gICAgY29uc3QgbkdyYW1zU3BsaXRzID0gWzAsIDExLCAxOF07XG4gICAgYXdhaXQgZXhwZWN0UmVzdWx0KHJlc3VsdCwgbkdyYW1zLCBuR3JhbXNTcGxpdHMpO1xuICB9KTtcblxuICBpdCgncGFkZGVkIGJpZ3JhbXMnLCBhc3luYyAoKSA9PiB7XG4gICAgLy8gQmF0Y2ggaXRlbXMgYXJlOlxuICAgIC8vIDA6IFwiYVwiLCBcImJcIiwgXCJjXCIsIFwiZFwiXG4gICAgLy8gMTogXCJlXCIsIFwiZlwiXG4gICAgY29uc3QgcmVzdWx0ID0gdGYuc3RyaW5nLnN0cmluZ05HcmFtcyhcbiAgICAgICAgWydhJywgJ2InLCAnYycsICdkJywgJ2UnLCAnZiddLCB0Zi50ZW5zb3IxZChbMCwgNCwgNl0sICdpbnQzMicpLCAnfCcsXG4gICAgICAgIFsyXSwgJ0xQJywgJ1JQJywgLTEsIGZhbHNlKTtcbiAgICBjb25zdCBuR3JhbXMgPSBbXG4gICAgICAnTFB8YScsICdhfGInLCAnYnxjJywgJ2N8ZCcsICdkfFJQJywgIC8vIDBcbiAgICAgICdMUHxlJywgJ2V8ZicsICdmfFJQJyAgICAgICAgICAgICAgICAgLy8gMVxuICAgIF07XG4gICAgY29uc3QgbkdyYW1zU3BsaXRzID0gWzAsIDUsIDhdO1xuICAgIGF3YWl0IGV4cGVjdFJlc3VsdChyZXN1bHQsIG5HcmFtcywgbkdyYW1zU3BsaXRzKTtcbiAgfSk7XG5cbiAgaXQoJ3BhZGRpbmcgaXMgYXQgbW9zdCBuR3JhbVNpemUgLSAxJywgYXN5bmMgKCkgPT4ge1xuICAgIC8vIEJhdGNoIGl0ZW1zIGFyZTpcbiAgICAvLyAwOiBcImFcIiwgXCJiXCIsIFwiY1wiLCBcImRcIlxuICAgIC8vIDE6IFwiZVwiLCBcImZcIlxuICAgIGNvbnN0IHJlc3VsdCA9IHRmLnN0cmluZy5zdHJpbmdOR3JhbXMoXG4gICAgICAgIFsnYScsICdiJywgJ2MnLCAnZCcsICdlJywgJ2YnXSwgdGYudGVuc29yMWQoWzAsIDQsIDZdLCAnaW50MzInKSwgJ3wnLFxuICAgICAgICBbMl0sICdMUCcsICdSUCcsIDQsIGZhbHNlKTtcbiAgICBjb25zdCBuR3JhbXMgPSBbXG4gICAgICAnTFB8YScsICdhfGInLCAnYnxjJywgJ2N8ZCcsICdkfFJQJywgIC8vIDBcbiAgICAgICdMUHxlJywgJ2V8ZicsICdmfFJQJyAgICAgICAgICAgICAgICAgLy8gMVxuICAgIF07XG4gICAgY29uc3QgbkdyYW1zU3BsaXRzID0gWzAsIDUsIDhdO1xuICAgIGF3YWl0IGV4cGVjdFJlc3VsdChyZXN1bHQsIG5HcmFtcywgbkdyYW1zU3BsaXRzKTtcbiAgfSk7XG5cbiAgaXQoJ3BhZGRlZCB1bmlncmFtIGFuZCBiaWdyYW1zJywgYXN5bmMgKCkgPT4ge1xuICAgIC8vIEJhdGNoIGl0ZW1zIGFyZTpcbiAgICAvLyAwOiBcImFcIiwgXCJiXCIsIFwiY1wiLCBcImRcIlxuICAgIC8vIDE6IFwiZVwiLCBcImZcIlxuICAgIGNvbnN0IHJlc3VsdCA9IHRmLnN0cmluZy5zdHJpbmdOR3JhbXMoXG4gICAgICAgIFsnYScsICdiJywgJ2MnLCAnZCcsICdlJywgJ2YnXSwgdGYudGVuc29yMWQoWzAsIDQsIDZdLCAnaW50MzInKSwgJ3wnLFxuICAgICAgICBbMSwgMl0sICdMUCcsICdSUCcsIC0xLCBmYWxzZSk7XG4gICAgY29uc3QgbkdyYW1zID0gW1xuICAgICAgJ2EnLCAnYicsICdjJywgJ2QnLCAnTFB8YScsICdhfGInLCAnYnxjJywgJ2N8ZCcsICdkfFJQJywgIC8vIDBcbiAgICAgICdlJywgJ2YnLCAnTFB8ZScsICdlfGYnLCAnZnxSUCcgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAxXG4gICAgXTtcbiAgICBjb25zdCBuR3JhbXNTcGxpdHMgPSBbMCwgOSwgMTRdO1xuICAgIGF3YWl0IGV4cGVjdFJlc3VsdChyZXN1bHQsIG5HcmFtcywgbkdyYW1zU3BsaXRzKTtcbiAgfSk7XG5cbiAgaXQoJ292ZXJsYXBwaW5nIHBhZGRlZCBuR3JhbXMnLCBhc3luYyAoKSA9PiB7XG4gICAgLy8gVGhpcyB0ZXN0IHZhbGlkYXRlcyB0aGF0IG4tZ3JhbXMgd2l0aCBib3RoIGxlZnQgYW5kIHJpZ2h0IHBhZGRpbmcgaW4gYVxuICAgIC8vIHNpbmdsZSBuZ3JhbSB0b2tlbiBhcmUgY3JlYXRlZCBjb3JyZWN0bHkuXG5cbiAgICAvLyBCYXRjaCBpdGVtcyBhcmU6XG4gICAgLy8gMDogXCJhXCJcbiAgICAvLyAxOiBcImJcIiwgXCJjXCIsIFwiZFwiXG4gICAgLy8gMjogXCJlXCIsIFwiZlwiXG4gICAgY29uc3QgcmVzdWx0ID0gdGYuc3RyaW5nLnN0cmluZ05HcmFtcyhcbiAgICAgICAgWydhJywgJ2InLCAnYycsICdkJywgJ2UnLCAnZiddLCB0Zi50ZW5zb3IxZChbMCwgMSwgNCwgNl0sICdpbnQzMicpLCAnfCcsXG4gICAgICAgIFszXSwgJ0xQJywgJ1JQJywgLTEsIGZhbHNlKTtcbiAgICBjb25zdCBuR3JhbXMgPSBbXG4gICAgICAnTFB8TFB8YScsICdMUHxhfFJQJywgJ2F8UlB8UlAnLCAgICAgICAgICAgICAgICAgICAgLy8gMFxuICAgICAgJ0xQfExQfGInLCAnTFB8YnxjJywgJ2J8Y3xkJywgJ2N8ZHxSUCcsICdkfFJQfFJQJywgIC8vIDFcbiAgICAgICdMUHxMUHxlJywgJ0xQfGV8ZicsICdlfGZ8UlAnLCAnZnxSUHxSUCcgICAgICAgICAgICAvLyAyXG4gICAgXTtcbiAgICBjb25zdCBuR3JhbXNTcGxpdHMgPSBbMCwgMywgOCwgMTJdO1xuICAgIGF3YWl0IGV4cGVjdFJlc3VsdChyZXN1bHQsIG5HcmFtcywgbkdyYW1zU3BsaXRzKTtcbiAgfSk7XG5cbiAgaXQoJ292ZXJsYXBwaW5nIHBhZGRlZCBtdWx0aSBjaGFyIG5HcmFtcycsIGFzeW5jICgpID0+IHtcbiAgICAvLyBCYXRjaCBpdGVtcyBhcmU6XG4gICAgLy8gMDogXCJhXCJcbiAgICAvLyAxOiBcImJcIiwgXCJjXCIsIFwiZFwiXG4gICAgLy8gMjogXCJlXCIsIFwiZlwiXG4gICAgY29uc3QgcmVzdWx0ID0gdGYuc3RyaW5nLnN0cmluZ05HcmFtcyhcbiAgICAgICAgWydhYScsICdiYicsICdjYycsICdkZCcsICdlZScsICdmZiddLFxuICAgICAgICB0Zi50ZW5zb3IxZChbMCwgMSwgNCwgNl0sICdpbnQzMicpLCAnfCcsIFszXSwgJ0xQJywgJ1JQJywgLTEsIGZhbHNlKTtcbiAgICBjb25zdCBuR3JhbXMgPSBbXG4gICAgICAnTFB8TFB8YWEnLCAnTFB8YWF8UlAnLCAnYWF8UlB8UlAnLCAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gMFxuICAgICAgJ0xQfExQfGJiJywgJ0xQfGJifGNjJywgJ2JifGNjfGRkJywgJ2NjfGRkfFJQJywgJ2RkfFJQfFJQJywgIC8vIDFcbiAgICAgICdMUHxMUHxlZScsICdMUHxlZXxmZicsICdlZXxmZnxSUCcsICdmZnxSUHxSUCcgIC