/** * @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('logLoss', ALL_ENVS, () => { it('1D', async () => { const labels = tf.tensor1d([1, 2, 3]); const predictions = tf.tensor1d([0.3, 0.6, 0.1]); const y = tf.losses.logLoss(labels, predictions); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), 2.668788); }); it('1D - Check for negative values', async () => { const labels = tf.tensor1d([1, 2, 3]); const predictions = tf.tensor1d([0.3, -0.6, -0.1]); const y = tf.losses.logLoss(labels, predictions); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), NaN); }); it('1D - weighted - Reduction.SUM_BY_NONZERO_WEIGHTS', async () => { const labels = tf.tensor1d([1, 2, 3]); const predictions = tf.tensor1d([0.3, 0.6, 0.1]); const weights = tf.tensor1d([0.1, 0.2, 0.3]); const y = tf.losses.logLoss(labels, predictions, weights); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), 0.7168596); }); it('1D - weighted - Reduction.NONE', async () => { const labels = tf.tensor1d([1, 2, 3]); const predictions = tf.tensor1d([0.3, 0.6, 0.1]); const weights = tf.tensor1d([0.1, 0.2, 0.3]); const y = tf.losses.logLoss(labels, predictions, weights, undefined, tf.Reduction.NONE); expect(y.shape).toEqual([3]); expectArraysClose(await y.data(), [0.12039725, 0.02107204, 2.0091095]); }); it('1D - Reduction.MEAN', async () => { const labels = tf.tensor1d([1, 2, 3]); const predictions = tf.tensor1d([0.3, 0.6, 0.1]); const y = tf.losses.logLoss(labels, predictions, undefined, undefined, tf.Reduction.MEAN); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), 2.668788); }); it('1D - weighted - Reduction.MEAN', async () => { const labels = tf.tensor1d([1, 2, 3]); const predictions = tf.tensor1d([0.3, 0.6, 0.1]); const weights = tf.tensor1d([0.1, 0.2, 0.3]); const y = tf.losses.logLoss(labels, predictions, weights, undefined, tf.Reduction.MEAN); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), 3.5842977); }); it('2D', async () => { const labels = tf.tensor2d([0.4, 0.8, 0.12, 0.8, 0.1, 0.3], [2, 3]); const predictions = tf.tensor2d([0.1, 0.7, 0.1, 0.5, 0.05, 0.15], [2, 3]); const y = tf.losses.logLoss(labels, predictions); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), 0.60019904); }); it('2D - weighted - Reduction.SUM_BY_NONZERO_WEIGHTS', async () => { const labels = tf.tensor2d([0.4, 0.8, 0.12, 0.8, 0.1, 0.3], [2, 3]); const predictions = tf.tensor2d([0.1, 0.7, 0.1, 0.5, 0.05, 0.15], [2, 3]); const weights = tf.tensor2d([3, 0, 5, 0, 4, 2], [2, 3]); const y = tf.losses.logLoss(labels, predictions, weights); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), 1.8866577); }); it('2D - weighted - Reduction.NONE', async () => { const labels = tf.tensor2d([0.4, 0.8, 0.12, 0.8, 0.1, 0.3], [2, 3]); const predictions = tf.tensor2d([0.1, 0.7, 0.1, 0.5, 0.05, 0.15], [2, 3]); const weights = tf.tensor2d([3, 0, 5, 0, 4, 2], [2, 3]); const y = tf.losses.logLoss(labels, predictions, weights, undefined, tf.Reduction.NONE); expect(y.shape).toEqual([2, 3]); expectArraysClose(await y.data(), [2.9527497, 0., 1.8451363, 0., 1.3829476, 1.3657978]); }); it('2D - Reduction.MEAN', async () => { const labels = tf.tensor2d([0.4, 0.8, 0.12, 0.8, 0.1, 0.3], [2, 3]); const predictions = tf.tensor2d([0.1, 0.7, 0.1, 0.5, 0.05, 0.15], [2, 3]); const y = tf.losses.logLoss(labels, predictions, undefined, undefined, tf.Reduction.MEAN); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), 0.60019904); }); it('2D - weighted - Reduction.MEAN', async () => { const labels = tf.tensor2d([0.4, 0.8, 0.12, 0.8, 0.1, 0.3], [2, 3]); const predictions = tf.tensor2d([0.1, 0.7, 0.1, 0.5, 0.05, 0.15], [2, 3]); const weights = tf.tensor2d([3, 0, 5, 0, 4, 2], [2, 3]); const y = tf.losses.logLoss(labels, predictions, weights, undefined, tf.Reduction.MEAN); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), 0.53904504); }); it('throws when passed label as a non-tensor', () => { const predictions = tf.tensor2d([0.1, 0.7, 0.1, 0.5, 0.05, 0.15], [2, 3]); const weights = tf.tensor2d([3, 6, 5, 0, 4, 2], [2, 3]); const e = /Argument 'labels' passed to 'logLoss' must be a Tensor/; expect(() => tf.losses.logLoss({}, predictions, weights, tf.Reduction.MEAN)) .toThrowError(e); }); it('throws when passed label as a non-tensor', () => { const labels = tf.tensor2d([0.4, 0.8, 0.12, 0.8, 0.1, 0.3], [2, 3]); const weights = tf.tensor2d([3, 6, 5, 0, 4, 2], [2, 3]); const e = new RegExp('Argument \'predictions\' passed to \'logLoss\' ' + 'must be a Tensor'); expect(() => tf.losses.logLoss(labels, {}, weights, tf.Reduction.MEAN)) .toThrowError(e); }); it('throws when passed weights as a non-tensor', () => { const labels = tf.tensor2d([0.4, 0.8, 0.12, 0.8, 0.1, 0.3], [2, 3]); const predictions = tf.tensor2d([0.1, 0.7, 0.1, 0.5, 0.05, 0.15], [2, 3]); const e = /Argument 'weights' passed to 'logLoss' must be a Tensor/; expect(() => tf.losses.logLoss(labels, predictions, {}, tf.Reduction.MEAN)) .toThrowError(e); }); it('accepts a tensor-like object', async () => { const labels = [1, 2, 3]; const predictions = [0.3, 0.6, 0.1]; const weights = [0.1, 0.2, 0.3]; const y = tf.losses.logLoss(labels, predictions, weights, undefined, tf.Reduction.NONE); expect(y.shape).toEqual([3]); expectArraysClose(await y.data(), [0.12039725, 0.02107204, 2.0091095]); }); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nX2xvc3NfdGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3RmanMtY29yZS9zcmMvb3BzL2xvc3Nlcy9sb2dfbG9zc190ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUNILE9BQU8sS0FBSyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ2xDLE9BQU8sRUFBQyxRQUFRLEVBQUUsaUJBQWlCLEVBQUMsTUFBTSxvQkFBb0IsQ0FBQztBQUMvRCxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUVsRCxpQkFBaUIsQ0FBQyxTQUFTLEVBQUUsUUFBUSxFQUFFLEdBQUcsRUFBRTtJQUMxQyxFQUFFLENBQUMsSUFBSSxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ2xCLE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdEMsTUFBTSxXQUFXLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUVqRCxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFFakQsTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDNUIsaUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDOUMsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsZ0NBQWdDLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDOUMsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxD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Q0FBQyxDQUFDO1FBRXhELE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxXQUFXLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFFMUQsTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDNUIsaUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDL0MsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsZ0NBQWdDLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDOUMsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNwRSxNQUFNLFdBQVcsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzFFLE1BQU0sT0FBTyxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFeEQsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQ3ZCLE1BQU0sRUFBRSxXQUFXLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRWhFLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDaEMsaUJBQWlCLENBQ2IsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxTQUFTLEVBQUUsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDNUUsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMscUJBQXFCLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDbkMsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNwRSxNQUFNLFdBQVcsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRTFFLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUN2QixNQUFNLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsRUFBRSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUVsRSxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUM1QixpQkFBaUIsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxVQUFVLENBQUMsQ0FBQztJQUNoRCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxnQ0FBZ0MsRUFBRSxLQUFLLElBQUksRUFBRTtRQUM5QyxNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3BFLE1BQU0sV0FBVyxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDMUUsTUFBTSxPQUFPLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUV4RCxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FDdkIsTUFBTSxFQUFFLFdBQVcsRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLEVBQUUsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFaEUsTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDNUIsaUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDaEQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsMENBQTBDLEVBQUUsR0FBRyxFQUFFO1FBQ2xELE1BQU0sV0FBVyxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDMUUsTUFBTSxPQUFPLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUs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LE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDN0IsaUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxVQUFVLEVBQUUsVUFBVSxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDekUsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTEMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKi9cbmltcG9ydCAqIGFzIHRmIGZyb20gJy4uLy4uL2luZGV4JztcbmltcG9ydCB7QUxMX0VOVlMsIGRlc2NyaWJlV2l0aEZsYWdzfSBmcm9tICcuLi8uLi9qYXNtaW5lX3V0aWwnO1xuaW1wb3J0IHtleHBlY3RBcnJheXNDbG9zZX0gZnJvbSAnLi4vLi4vdGVzdF91dGlsJztcblxuZGVzY3JpYmVXaXRoRmxhZ3MoJ2xvZ0xvc3MnLCBBTExfRU5WUywgKCkgPT4ge1xuICBpdCgnMUQnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgbGFiZWxzID0gdGYudGVuc29yMWQoWzEsIDIsIDNdKTtcbiAgICBjb25zdCBwcmVkaWN0aW9ucyA9IHRmLnRlbnNvcjFkKFswLjMsIDAuNiwgMC4xXSk7XG5cbiAgICBjb25zdCB5ID0gdGYubG9zc2VzLmxvZ0xvc3MobGFiZWxzLCBwcmVkaWN0aW9ucyk7XG5cbiAgICBleHBlY3QoeS5zaGFwZSkudG9FcXVhbChbXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgeS5kYXRhKCksIDIuNjY4Nzg4KTtcbiAgfSk7XG5cbiAgaXQoJzFEIC0gQ2hlY2sgZm9yIG5lZ2F0aXZlIHZhbHVlcycsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBsYWJlbHMgPSB0Zi50ZW5zb3IxZChbMSwgMiwgM10pO1xuICAgIGNvbnN0IHByZWRpY3Rpb25zID0gdGYudGVuc29yMWQoWzAuMywgLTAuNiwgLTAuMV0pO1xuXG4gICAgY29uc3QgeSA9IHRmLmxvc3Nlcy5sb2dMb3NzKGxhYmVscywgcHJlZGljdGlvbnMpO1xuXG4gICAgZXhwZWN0KHkuc2hhcGUpLnRvRXF1YWwoW10pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHkuZGF0YSgpLCBOYU4pO1xuICB9KTtcblxuICBpdCgnMUQgLSB3ZWlnaHRlZCAtIFJlZHVjdGlvbi5TVU1fQllfTk9OWkVST19XRUlHSFRTJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGxhYmVscyA9IHRmLnRlbnNvcjFkKFsxLCAyLCAzXSk7XG4gICAgY29uc3QgcHJlZGljdGlvbnMgPSB0Zi50ZW5zb3IxZChbMC4zLCAwLjYsIDAuMV0pO1xuICAgIGNvbnN0IHdlaWdodHMgPSB0Zi50ZW5zb3IxZChbMC4xLCAwLjIsIDAuM10pO1xuXG4gICAgY29uc3QgeSA9IHRmLmxvc3Nlcy5sb2dMb3NzKGxhYmVscywgcHJlZGljdGlvbnMsIHdlaWdodHMpO1xuXG4gICAgZXhwZWN0KHkuc2hhcGUpLnRvRXF1YWwoW10pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHkuZGF0YSgpLCAwLjcxNjg1OTYpO1xuICB9KTtcblxuICBpdCgnMUQgLSB3ZWlnaHRlZCAtIFJlZHVjdGlvbi5OT05FJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGxhYmVscyA9IHRmLnRlbnNvcjFkKFsxLCAyLCAzXSk7XG4gICAgY29uc3QgcHJlZGljdGlvbnMgPSB0Zi50ZW5zb3IxZChbMC4zLCAwLjYsIDAuMV0pO1xuICAgIGNvbnN0IHdlaWdodHMgPSB0Zi50ZW5zb3IxZChbMC4xLCAwLjIsIDAuM10pO1xuXG4gICAgY29uc3QgeSA9IHRmLmxvc3Nlcy5sb2dMb3NzKFxuICAgICAgICBsYWJlbHMsIHByZWRpY3Rpb25zLCB3ZWlnaHRzLCB1bmRlZmluZWQsIHRmLlJlZHVjdGlvbi5OT05FKTtcblxuICAgIGV4cGVjdCh5LnNoYXBlKS50b0VxdWFsKFszXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgeS5kYXRhKCksIFswLjEyMDM5NzI1LCAwLjAyMTA3MjA0LCAyLjAwOTEwOTVdKTtcbiAgfSk7XG5cbiAgaXQoJzFEIC0gUmVkdWN0aW9uLk1FQU4nLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgbGFiZWxzID0gdGYudGVuc29yMWQoWzEsIDIsIDNdKTtcbiAgICBjb25zdCBwcmVkaWN0aW9ucyA9IHRmLnRlbnNvcjFkKFswLjMsIDAuNiwgMC4xXSk7XG5cbiAgICBjb25zdCB5ID0gdGYubG9zc2VzLmxvZ0xvc3MoXG4gICAgICAgIGxhYmVscywgcHJlZGljdGlvbnMsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCB0Zi5SZWR1Y3Rpb24uTUVBTik7XG5cbiAgICBleHBlY3QoeS5zaGFwZSkudG9FcXVhbChbXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgeS5kYXRhKCksIDIuNjY4Nzg4KTtcbiAgfSk7XG5cbiAgaXQoJzFEIC0gd2VpZ2h0ZWQgLSBSZWR1Y3Rpb24uTUVBTicsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBsYWJlbHMgPSB0Zi50ZW5zb3IxZChbMSwgMiwgM10pO1xuICAgIGNvbnN0IHByZWRpY3Rpb25zID0gdGYudGVuc29yMWQoWzAuMywgMC42LCAwLjFdKTtcbiAgICBjb25zdCB3ZWlnaHRzID0gdGYudGVuc29yMWQoWzAuMSwgMC4yLCAwLjNdKTtcblxuICAgIGNvbnN0IHkgPSB0Zi5sb3NzZXMubG9nTG9zcyhcbiAgICAgICAgbGFiZWxzLCBwcmVkaWN0aW9ucywgd2VpZ2h0cywgdW5kZWZpbmVkLCB0Zi5SZWR1Y3Rpb24uTUVBTik7XG5cbiAgICBleHBlY3QoeS5zaGFwZSkudG9FcXVhbChbXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgeS5kYXRhKCksIDMuNTg0Mjk3Nyk7XG4gIH0pO1xuXG4gIGl0KCcyRCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBsYWJlbHMgPSB0Zi50ZW5zb3IyZChbMC40LCAwLjgsIDAuMTIsIDAuOCwgMC4xLCAwLjNdLCBbMiwgM10pO1xuICAgIGNvbnN0IHByZWRpY3Rpb25zID0gdGYudGVuc29yMmQoWzAuMSwgMC43LCAwLjEsIDAuNSwgMC4wNSwgMC4xNV0sIFsyLCAzXSk7XG5cbiAgICBjb25zdCB5ID0gdGYubG9zc2VzLmxvZ0xvc3MobGFiZWxzLCBwcmVkaWN0aW9ucyk7XG5cbiAgICBleHBlY3QoeS5zaGFwZSkudG9FcXVhbChbXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgeS5kYXRhKCksIDAuNjAwMTk5MDQpO1xuICB9KTtcblxuICBpdCgnMkQgLSB3ZWlnaHRlZCAtIFJlZHVjdGlvbi5TVU1fQllfTk9OWkVST19XRUlHSFRTJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGxhYmVscyA9IHRmLnRlbnNvcjJkKFswLjQsIDAuOCwgMC4xMiwgMC44LCAwLjEsIDAuM10sIFsyLCAzXSk7XG4gICAgY29uc3QgcHJlZGljdGlvbnMgPSB0Zi50ZW5zb3IyZChbMC4xLCAwLjcsIDAuMSwgMC41LCAwLjA1LCAwLjE1XSwgWzIsIDNdKTtcbiAgICBjb25zdCB3ZWlnaHRzID0gdGYudGVuc29yMmQoWzMsIDAsIDUsIDAsIDQsIDJdLCBbMiwgM10pO1xuXG4gICAgY29uc3QgeSA9IHRmLmxvc3Nlcy5sb2dMb3NzKGxhYmVscywgcHJlZGljdGlvbnMsIHdlaWdodHMpO1xuXG4gICAgZXhwZWN0KHkuc2hhcGUpLnRvRXF1YWwoW10pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHkuZGF0YSgpLCAxLjg4NjY1NzcpO1xuICB9KTtcblxuICBpdCgnMkQgLSB3ZWlnaHRlZCAtIFJlZHVjdGlvbi5OT05FJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGxhYmVscyA9IHRmLnRlbnNvcjJkKFswLjQsIDAuOCwgMC4xMiwgMC44LCAwLjEsIDAuM10sIFsyLCAzXSk7XG4gICAgY29uc3QgcHJlZGljdGlvbnMgPSB0Zi50ZW5zb3IyZChbMC4xLCAwLjcsIDAuMSwgMC41LCAwLjA1LCAwLjE1XSwgWzIsIDNdKTtcbiAgICBjb25zdCB3ZWlnaHRzID0gdGYudGVuc29yMmQoWzMsIDAsIDUsIDAsIDQsIDJdLCBbMiwgM10pO1xuXG4gICAgY29uc3QgeSA9IHRmLmxvc3Nlcy5sb2dMb3NzKFxuICAgICAgICBsYWJlbHMsIHByZWRpY3Rpb25zLCB3ZWlnaHRzLCB1bmRlZmluZWQsIHRmLlJlZHVjdGlvbi5OT05FKTtcblxuICAgIGV4cGVjdCh5LnNoYXBlKS50b0VxdWFsKFsyLCAzXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoXG4gICAgICAgIGF3YWl0IHkuZGF0YSgpLCBbMi45NTI3NDk3LCAwLiwgMS44NDUxMzYzLCAwLiwgMS4zODI5NDc2LCAxLjM2NTc5NzhdKTtcbiAgfSk7XG5cbiAgaXQoJzJEIC0gUmVkdWN0aW9uLk1FQU4nLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgbGFiZWxzID0gdGYudGVuc29yMmQoWzAuNCwgMC44LCAwLjEyLCAwLjgsIDAuMSwgMC4zXSwgWzIsIDNdKTtcbiAgICBjb25zdCBwcmVkaWN0aW9ucyA9IHRmLnRlbnNvcjJkKFswLjEsIDAuNywgMC4xLCAwLjUsIDAuMDUsIDAuMTVdLCBbMiwgM10pO1xuXG4gICAgY29uc3QgeSA9IHRmLmxvc3Nlcy5sb2dMb3NzKFxuICAgICAgICBsYWJlbHMsIHByZWRpY3Rpb25zLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdGYuUmVkdWN0aW9uLk1FQU4pO1xuXG4gICAgZXhwZWN0KHkuc2hhcGUpLnRvRXF1YWwoW10pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHkuZGF0YSgpLCAwLjYwMDE5OTA0KTtcbiAgfSk7XG5cbiAgaXQoJzJEIC0gd2VpZ2h0ZWQgLSBSZWR1Y3Rpb24uTUVBTicsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBsYWJlbHMgPSB0Zi50ZW5zb3IyZChbMC40LCAwLjgsIDAuMTIsIDAuOCwgMC4xLCAwLjNdLCBbMiwgM10pO1xuICAgIGNvbnN0IHByZWRpY3Rpb25zID0gdGYudGVuc29yMmQoWzAuMSwgMC43LCAwLjEsIDAuNSwgMC4wNSwgMC4xNV0sIFsyLCAzXSk7XG4gICAgY29uc3Qgd2VpZ2h0cyA9IHRmLnRlbnNvcjJkKFszLCAwLCA1LCAwLCA0LCAyXSwgWzIsIDNdKTtcblxuICAgIGNvbnN0IHkgPSB0Zi5sb3NzZXMubG9nTG9zcyhcbiAgICAgICAgbGFiZWxzLCBwcmVkaWN0aW9ucywgd2VpZ2h0cywgdW5kZWZpbmVkLCB0Zi5SZWR1Y3Rpb24uTUVBTik7XG5cbiAgICBleHBlY3QoeS5zaGFwZSkudG9FcXVhbChbXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgeS5kYXRhKCksIDAuNTM5MDQ1MDQpO1xuICB9KTtcblxuICBpdCgndGhyb3dzIHdoZW4gcGFzc2VkIGxhYmVsIGFzIGEgbm9uLXRlbnNvcicsICgpID0+IHtcbiAgICBjb25zdCBwcmVkaWN0aW9ucyA9IHRmLnRlbnNvcjJkKFswLjEsIDAuNywgMC4xLCAwLjUsIDAuMDUsIDAuMTVdLCBbMiwgM10pO1xuICAgIGNvbnN0IHdlaWdodHMgPSB0Zi50ZW5zb3IyZChbMywgNiwgNSwgMCwgNCwgMl0sIFsyLCAzXSk7XG5cbiAgICBjb25zdCBlID0gL0FyZ3VtZW50ICdsYWJlbHMnIHBhc3NlZCB0byAnbG9nTG9zcycgbXVzdCBiZSBhIFRlbnNvci87XG4gICAgZXhwZWN0KFxuICAgICAgICAoKSA9PiB0Zi5sb3NzZXMubG9nTG9zcyhcbiAgICAgICAgICAgIHt9IGFzIHRmLlRlbnNvciwgcHJlZGljdGlvbnMsIHdlaWdodHMsIHRmLlJlZHVjdGlvbi5NRUFOKSlcbiAgICAgICAgLnRvVGhyb3dFcnJvcihlKTtcbiAgfSk7XG5cbiAgaXQoJ3Rocm93cyB3aGVuIHBhc3NlZCBsYWJlbCBhcyBhIG5vbi10ZW5zb3InLCAoKSA9PiB7XG4gICAgY29uc3QgbGFiZWxzID0gdGYudGVuc29yMmQoWzAuNCwgMC44LCAwLjEyLCAwLjgsIDAuMSwgMC4zXSwgWzIsIDNdKTtcbiAgICBjb25zdCB3ZWlnaHRzID0gdGYudGVuc29yMmQoWzMsIDYsIDUsIDAsIDQsIDJdLCBbMiwgM10pO1xuXG4gICAgY29uc3QgZSA9IG5ldyBSZWdFeHAoXG4gICAgICAgICdBcmd1bWVudCBcXCdwcmVkaWN0aW9uc1xcJyBwYXNzZWQgdG8gXFwnbG9nTG9zc1xcJyAnICtcbiAgICAgICAgJ211c3QgYmUgYSBUZW5zb3InKTtcbiAgICBleHBlY3QoXG4gICAgICAgICgpID0+IHRmLmxvc3Nlcy5sb2dMb3NzKFxuICAgICAgICAgICAgbGFiZWxzLCB7fSBhcyB0Zi5UZW5zb3IsIHdlaWdodHMsIHRmLlJlZHVjdGlvbi5NRUFOKSlcbiAgICAgICAgLnRvVGhyb3dFcnJvcihlKTtcbiAgfSk7XG5cbiAgaXQoJ3Rocm93cyB3aGVuIHBhc3NlZCB3ZWlnaHRzIGFzIGEgbm9uLXRlbnNvcicsICgpID0+IHtcbiAgICBjb25zdCBsYWJlbHMgPSB0Zi50ZW5zb3IyZChbMC40LCAwLjgsIDAuMTIsIDAuOCwgMC4xLCAwLjNdLCBbMiwgM10pO1xuICAgIGNvbnN0IHByZWRpY3Rpb25zID0gdGYudGVuc29yMmQoWzAuMSwgMC43LCAwLjEsIDAuNSwgMC4wNSwgMC4xNV0sIFsyLCAzXSk7XG5cbiAgICBjb25zdCBlID0gL0FyZ3VtZW50ICd3ZWlnaHRzJyBwYXNzZWQgdG8gJ2xvZ0xvc3MnIG11c3QgYmUgYSBUZW5zb3IvO1xuICAgIGV4cGVjdChcbiAgICAgICAgKCkgPT4gdGYubG9zc2VzLmxvZ0xvc3MoXG4gICAgICAgICAgICBsYWJlbHMsIHByZWRpY3Rpb25zLCB7fSBhcyB0Zi5UZW5zb3IsIHRmLlJlZHVjdGlvbi5NRUFOKSlcbiAgICAgICAgLnRvVGhyb3dFcnJvcihlKTtcbiAgfSk7XG5cbiAgaXQoJ2FjY2VwdHMgYSB0ZW5zb3ItbGlrZSBvYmplY3QnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgbGFiZWxzID0gWzEsIDIsIDNdO1xuICAgIGNvbnN0IHByZWRpY3Rpb25zID0gWzAuMywgMC42LCAwLjFdO1xuICAgIGNvbnN0IHdlaWdodHMgPSBbMC4xLCAwLjIsIDAuM107XG5cbiAgICBjb25zdCB5ID0gdGYubG9zc2VzLmxvZ0xvc3MoXG4gICAgICAgIGxhYmVscywgcHJlZGljdGlvbnMsIHdlaWdodHMsIHVuZGVmaW5lZCwgdGYuUmVkdWN0aW9uLk5PTkUpO1xuXG4gICAgZXhwZWN0KHkuc2hhcGUpLnRvRXF1YWwoWzNdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCB5LmRhdGEoKSwgWzAuMTIwMzk3MjUsIDAuMDIxMDcyMDQsIDIuMDA5MTA5NV0pO1xuICB9KTtcbn0pO1xuIl19