PHP WebShell
Текущая директория: /opt/BitGoJS/modules/sdk-coin-hbar/dist/test/unit
Просмотр файла: utils.js
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const assert_1 = __importDefault(require("assert"));
const should_1 = __importDefault(require("should"));
const stellar = __importStar(require("stellar-sdk"));
const Utils = __importStar(require("../../src/lib/utils"));
const testData = __importStar(require("../resources/hbar"));
const sdk_core_1 = require("@bitgo/sdk-core");
describe('HBAR util library', function () {
describe('address', function () {
it('should validate addresses', function () {
const validAddresses = ['0', '0.0.0', '99.99.99', '0.0.41098'];
const validAddressesWithMemo = ['0.0.41098?memoId=4'];
for (const address of validAddresses) {
Utils.isValidAddress(address).should.be.true();
}
for (const address of validAddressesWithMemo) {
Utils.isValidAddress(address).should.be.true();
}
});
it('should fail to validate invalid addresses', function () {
const invalidAddresses = ['0.0', '0.0.0.0', 'abc', 'a.b.c', '', '0x23C3E227BE97281A70A549c7dDB8d5Caad3E7C84'];
const invalidAddressesWithMemo = ['0.0.41098?memoId=m?memoId=4'];
for (const address of invalidAddresses) {
should_1.default.doesNotThrow(() => Utils.isValidAddress(address));
Utils.isValidAddress(address).should.be.false();
}
for (const address of invalidAddressesWithMemo) {
should_1.default.doesNotThrow(() => Utils.isValidAddress(address));
Utils.isValidAddress(address).should.be.false();
}
});
});
describe('transaction id', function () {
it('should validate tx ids', function () {
const validHashes = ['0.0.14621@1595374723.356981689'];
for (const hash of validHashes) {
Utils.isValidTransactionId(hash).should.be.true();
}
});
it('should fail to validate invalid tx ids', function () {
const invalidHashes = ['0.0.14621', 'invalid', ''];
for (const hash of invalidHashes) {
Utils.isValidTransactionId(hash).should.be.false();
}
});
});
describe('transaction timestamp', function () {
it('should validate tx timestamps', function () {
const validTimestamps = ['1595374723.356981689', '1595374723'];
for (const timestamp of validTimestamps) {
Utils.isValidTimeString(timestamp).should.be.true();
}
});
it('should fail to validate invalid tx timestamp', function () {
const invalidTimestamp = ['0.0.14621', 'invalid', ''];
for (const timestamp of invalidTimestamp) {
Utils.isValidTimeString(timestamp).should.be.false();
}
});
});
describe('should remove prefix', function () {
it('from a private key', function () {
const rawPrivateKey = Utils.removePrefix(testData.ed25519PrivKeyPrefix, testData.ACCOUNT_1.prvKeyWithPrefix);
should_1.default.deepEqual(rawPrivateKey, '62b0b669de0ab5e91b4328e1431859a5ca47e7426e701019272f5c2d52825b01');
});
it('from a public key', function () {
const rawPublicKey = Utils.removePrefix(testData.ed25519PubKeyPrefix, testData.ACCOUNT_1.pubKeyWithPrefix);
should_1.default.deepEqual(rawPublicKey, '5a9111b5e6881ff20b9243a42ac1a9a67fa16cd4f01e58bab30c1fe611ea8cf9');
});
});
describe('should convert a stellar pub', function () {
it('and get back a valid ed pub', function () {
const stellarPub = 'GBVEZT27ZUCMJABF76XIPPO7M3KUABVR4GZNPBAD3YTPXUSDA57ANRLD';
const newPub = Utils.convertFromStellarPub(stellarPub);
should_1.default.equal((0, sdk_core_1.isValidEd25519PublicKey)(newPub), true);
});
it('and get back a specific ed pub', function () {
const stellarPub = 'GBVEZT27ZUCMJABF76XIPPO7M3KUABVR4GZNPBAD3YTPXUSDA57ANRLD';
const newPub = Utils.convertFromStellarPub(stellarPub);
newPub.should.equal('6a4ccf5fcd04c48025ffae87bddf66d54006b1e1b2d78403de26fbd243077e06');
});
it('and create a valid ed pub that can be transformed back into a stellar pub', function () {
const stellarPub = 'GBVEZT27ZUCMJABF76XIPPO7M3KUABVR4GZNPBAD3YTPXUSDA57ANRLD';
const newPub = Utils.convertFromStellarPub(stellarPub);
const stellarDecoded = stellar.StrKey.encodeEd25519PublicKey(Buffer.from(newPub, 'hex'));
const beginStellarKeyPair = stellar.Keypair.fromPublicKey(stellarPub);
const endStellarKeyPair = stellar.Keypair.fromPublicKey(stellarDecoded);
should_1.default.equal(beginStellarKeyPair.publicKey(), endStellarKeyPair.publicKey());
});
});
describe('should return the same key', function () {
it('from a private key without the prefix', function () {
const rawPrivateKey = Utils.removePrefix(testData.ed25519PrivKeyPrefix, testData.ACCOUNT_2.privateKey);
should_1.default.deepEqual(rawPrivateKey, testData.ACCOUNT_2.privateKey);
});
it('from a public key without the prefix', function () {
const rawPublicKey = Utils.removePrefix(testData.ed25519PubKeyPrefix, testData.ACCOUNT_2.publicKey);
should_1.default.deepEqual(rawPublicKey, testData.ACCOUNT_2.publicKey);
});
it('from a public key with chars of prefix in the middle', function () {
const publicKey = '592a4fbb7263c59d450e651d' + testData.ed25519PubKeyPrefix + 'f96620dc9208ee7c';
const rawPublicKey = Utils.removePrefix(testData.ed25519PubKeyPrefix, publicKey);
should_1.default.deepEqual(rawPublicKey, publicKey);
});
it('from a private key with chars of prefix in the middle', function () {
const privateKey = '5bb72603f237c099' + testData.ed25519PrivKeyPrefix + '3f7973d37fdade3c';
const rawPrivateKey = Utils.removePrefix(testData.ed25519PrivKeyPrefix, privateKey);
should_1.default.deepEqual(rawPrivateKey, privateKey);
});
});
describe('getAddressDetails', function () {
it('should get memoId and address', async function () {
const addr = '0.0.41098?memoId=23233';
const details = Utils.getAddressDetails(addr);
details.address.should.equal('0.0.41098');
details.memoId?.should.equal('23233');
});
it('should throw when memoId=null', async function () {
const addr = '0.0.41098?memoId=';
assert_1.default.throws(() => Utils.getAddressDetails(addr), /invalid address: '0.0.41098\?memoId=', memoId is not valid/);
});
it('should get memoId and address when no memoId', async function () {
const addr = '0.0.41098';
const details = Utils.getAddressDetails(addr);
details.address.should.equal('0.0.41098');
details.memoId?.should.equal(undefined);
});
});
describe('normalizeAddress', function () {
it('should build without a memoId if its missing for an address', async function () {
const address = '0.0.41098';
let memoId = undefined;
let norm = Utils.normalizeAddress({ address, memoId });
norm.should.equal('0.0.41098');
memoId = '';
norm = Utils.normalizeAddress({ address, memoId });
norm.should.equal('0.0.41098');
});
});
describe('getBaseAddress', function () {
it('should return the base address', async function () {
const addressWithMemo = '0.0.41098?memoId=1';
const baseAddress = '0.0.41098';
Utils.getBaseAddress(addressWithMemo).should.equal(baseAddress);
Utils.getBaseAddress(baseAddress).should.equal(baseAddress);
});
});
describe('isSameBaseAddress', function () {
it('should validate if base address match', async function () {
const address = '0.0.41098?memoId=1';
const baseAddress = '0.0.41098';
Utils.isSameBaseAddress(address, baseAddress).should.true();
const address2 = '0.0.41098';
const baseAddress2 = '0.0.41098';
Utils.isSameBaseAddress(address2, baseAddress2).should.true();
const address3 = '0.0.41099?memoId=1';
const baseAddress3 = '0.0.41098';
Utils.isSameBaseAddress(address3, baseAddress3).should.false();
const address4 = '0.0.41099';
const baseAddress4 = '0.0.41098';
Utils.isSameBaseAddress(address4, baseAddress4).should.false();
const address5 = '0.0.0.0';
const baseAddress5 = '0.0.41098';
assert_1.default.throws(() => Utils.isSameBaseAddress(address5, baseAddress5).should.false(), new RegExp(`invalid address: ${address5}`));
});
});
describe('isValidMemoId', function () {
it('should validate memoId', async function () {
const memo1 = 'testmemo';
Utils.isValidMemo(memo1).should.true();
const memo2 = '';
Utils.isValidMemo(memo2).should.false();
const memo3 = undefined;
// @ts-expect-error testing for error
Utils.isValidMemo(memo3).should.false();
const memo4 = 'memoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo';
Utils.isValidMemo(memo4).should.false();
});
});
describe('isValidAddressWithPaymentId', function () {
it('should validate addresses with and without payment id', function () {
const validAddresses = ['0', '0.0.0', '99.99.99', '0.0.41098', '0.0.41098?memoId=4'];
for (const address of validAddresses) {
Utils.isValidAddressWithPaymentId(address).should.be.true();
}
});
it('should fail to validate invalid addresses', function () {
const invalidAddresses = [
'0.0.41098?memoId=memooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo',
'0.0.41098?memoId=',
'0.0',
'0.0.0.0',
'abc',
'a.b.c',
'',
'0x23C3E227BE97281A70A549c7dDB8d5Caad3E7C84',
];
for (const address of invalidAddresses) {
Utils.isValidAddressWithPaymentId(address).should.be.false();
}
});
});
describe('shouldBroadcastNow', function () {
const getTimestampInSeconds = (secondsToChange = 0) => (Date.now() / 1000 + secondsToChange).toFixed();
it('should return true if the timestamp is in the valid time window', function () {
const timestamp = getTimestampInSeconds(-6);
Utils.shouldBroadcastNow(timestamp).should.be.true();
const timestamp2 = getTimestampInSeconds(-173);
Utils.shouldBroadcastNow(timestamp2).should.be.true();
});
it('should throw if the timestamp is in the past', function () {
const timestamp = getTimestampInSeconds(-1000);
assert_1.default.throws(() => Utils.shouldBroadcastNow(timestamp), (error) => {
assert_1.default.ok(error.message.includes('startTime window expired'));
return true;
});
});
it('should return false if the timestamp is in the future', function () {
const timestamp = getTimestampInSeconds(1000);
Utils.shouldBroadcastNow(timestamp).should.be.false();
});
});
describe('normalizeStarttime', function () {
it('should return the same timestamp', function () {
const timestamp = '1595374723.356981689';
Utils.normalizeStarttime(timestamp).should.equal(timestamp);
});
it('should return the timestamp with nanoseconds', function () {
const timestamp = '1595374723';
Utils.normalizeStarttime(timestamp).should.equal(timestamp + '.000000000');
});
it('should return the timestamp with nanoseconds', function () {
const timestamp = '1595374723.0145';
Utils.normalizeStarttime(timestamp).should.equal(timestamp + '00000');
});
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90ZXN0L3VuaXQvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxvREFBNEI7QUFDNUIsb0RBQTRCO0FBQzVCLHFEQUF1QztBQUN2QywyREFBNkM7QUFDN0MsNERBQThDO0FBQzlDLDhDQUEwRDtBQUUxRCxRQUFRLENBQUMsbUJBQW1CLEVBQUU7SUFDNUIsUUFBUSxDQUFDLFNBQVMsRUFBRTtRQUNsQixFQUFFLENBQUMsMkJBQTJCLEVBQUU7WUFDOUIsTUFBTSxjQUFjLEdBQUcsQ0FBQyxHQUFHLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxXQUFXLENBQUMsQ0FBQztZQUMvRCxNQUFNLHNCQUFzQixHQUFHLENBQUMsb0JBQW9CLENBQUMsQ0FBQztZQUV0RCxLQUFLLE1BQU0sT0FBTyxJQUFJLGNBQWMsRUFBRSxDQUFDO2dCQUNyQyxLQUFLLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDakQsQ0FBQztZQUVELEtBQUssTUFBTSxPQUFPLElBQUksc0JBQXNCLEVBQUUsQ0FBQztnQkFDN0MsS0FBSyxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ2pELENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQywyQ0FBMkMsRUFBRTtZQUM5QyxNQUFNLGdCQUFnQixHQUFHLENBQUMsS0FBSyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSw0Q0FBNEMsQ0FBQyxDQUFDO1lBQzlHLE1BQU0sd0JBQXdCLEdBQUcsQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO1lBRWpFLEtBQUssTUFBTSxPQUFPLElBQUksZ0JBQWdCLEVBQUUsQ0FBQztnQkFDdkMsZ0JBQU0sQ0FBQyxZQUFZLENBQUMsR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO2dCQUN6RCxLQUFLLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDbEQsQ0FBQztZQUVELEtBQUssTUFBTSxPQUFPLElBQUksd0JBQXdCLEVBQUUsQ0FBQztnQkFDL0MsZ0JBQU0sQ0FBQyxZQUFZLENBQUMsR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO2dCQUN6RCxLQUFLLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDbEQsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMsZ0JBQWdCLEVBQUU7UUFDekIsRUFBRSxDQUFDLHdCQUF3QixFQUFFO1lBQzNCLE1BQU0sV0FBVyxHQUFHLENBQUMsZ0NBQWdDLENBQUMsQ0FBQztZQUV2RCxLQUFLLE1BQU0sSUFBSSxJQUFJLFdBQVcsRUFBRSxDQUFDO2dCQUMvQixLQUFLLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNwRCxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsd0NBQXdDLEVBQUU7WUFDM0MsTUFBTSxhQUFhLEdBQUcsQ0FBQyxXQUFXLEVBQUUsU0FBUyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBRW5ELEtBQUssTUFBTSxJQUFJLElBQUksYUFBYSxFQUFFLENBQUM7Z0JBQ2pDLEtBQUssQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3JELENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLHVCQUF1QixFQUFFO1FBQ2hDLEVBQUUsQ0FBQywrQkFBK0IsRUFBRTtZQUNsQyxNQUFNLGVBQWUsR0FBRyxDQUFDLHNCQUFzQixFQUFFLFlBQVksQ0FBQyxDQUFDO1lBRS9ELEtBQUssTUFBTSxTQUFTLElBQUksZUFBZSxFQUFFLENBQUM7Z0JBQ3hDLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ3RELENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyw4Q0FBOEMsRUFBRTtZQUNqRCxNQUFNLGdCQUFnQixHQUFHLENBQUMsV0FBVyxFQUFFLFNBQVMsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUV0RCxLQUFLLE1BQU0sU0FBUyxJQUFJLGdCQUFnQixFQUFFLENBQUM7Z0JBQ3pDLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3ZELENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLHNCQUFzQixFQUFFO1FBQy9CLEVBQUUsQ0FBQyxvQkFBb0IsRUFBRTtZQUN2QixNQUFNLGFBQWEsR0FBRyxLQUFLLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxvQkFBb0IsRUFBRSxRQUFRLENBQUMsU0FBUyxDQUFDLGdCQUFnQixDQUFDLENBQUM7WUFDN0csZ0JBQU0sQ0FBQyxTQUFTLENBQUMsYUFBYSxFQUFFLGtFQUFrRSxDQUFDLENBQUM7UUFDdEcsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsbUJBQW1CLEVBQUU7WUFDdEIsTUFBTSxZQUFZLEdBQUcsS0FBSyxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsbUJBQW1CLEVBQUUsUUFBUSxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1lBQzNHLGdCQUFNLENBQUMsU0FBUyxDQUFDLFlBQVksRUFBRSxrRUFBa0UsQ0FBQyxDQUFDO1FBQ3JHLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMsOEJBQThCLEVBQUU7UUFDdkMsRUFBRSxDQUFDLDZCQUE2QixFQUFFO1lBQ2hDLE1BQU0sVUFBVSxHQUFHLDBEQUEwRCxDQUFDO1lBQzlFLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUN2RCxnQkFBTSxDQUFDLEtBQUssQ0FBQyxJQUFBLGtDQUF1QixFQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ3RELENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLGdDQUFnQyxFQUFFO1lBQ25DLE1BQU0sVUFBVSxHQUFHLDBEQUEwRCxDQUFDO1lBQzlFLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUN2RCxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxrRUFBa0UsQ0FBQyxDQUFDO1FBQzFGLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLDJFQUEyRSxFQUFFO1lBQzlFLE1BQU0sVUFBVSxHQUFHLDBEQUEwRCxDQUFDO1lBRTlFLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUN2RCxNQUFNLGNBQWMsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLHNCQUFzQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFDekYsTUFBTSxtQkFBbUIsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUN0RSxNQUFNLGlCQUFpQixHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBRXhFLGdCQUFNLENBQUMsS0FBSyxDQUFDLG1CQUFtQixDQUFDLFNBQVMsRUFBRSxFQUFFLGlCQUFpQixDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUM7UUFDL0UsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyw0QkFBNEIsRUFBRTtRQUNyQyxFQUFFLENBQUMsdUNBQXVDLEVBQUU7WUFDMUMsTUFBTSxhQUFhLEdBQUcsS0FBSyxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsb0JBQW9CLEVBQUUsUUFBUSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUN2RyxnQkFBTSxDQUFDLFNBQVMsQ0FBQyxhQUFhLEVBQUUsUUFBUSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNqRSxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxzQ0FBc0MsRUFBRTtZQUN6QyxNQUFNLFlBQVksR0FBRyxLQUFLLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxtQkFBbUIsRUFBRSxRQUFRLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ3BHLGdCQUFNLENBQUMsU0FBUyxDQUFDLFlBQVksRUFBRSxRQUFRLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQy9ELENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLHNEQUFzRCxFQUFFO1lBQ3pELE1BQU0sU0FBUyxHQUFHLDBCQUEwQixHQUFHLFFBQVEsQ0FBQyxtQkFBbUIsR0FBRyxrQkFBa0IsQ0FBQztZQUNqRyxNQUFNLFlBQVksR0FBRyxLQUFLLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxtQkFBbUIsRUFBRSxTQUFTLENBQUMsQ0FBQztZQUNqRixnQkFBTSxDQUFDLFNBQVMsQ0FBQyxZQUFZLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDNUMsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsdURBQXVELEVBQUU7WUFDMUQsTUFBTSxVQUFVLEdBQUcsa0JBQWtCLEdBQUcsUUFBUSxDQUFDLG9CQUFvQixHQUFHLGtCQUFrQixDQUFDO1lBQzNGLE1BQU0sYUFBYSxHQUFHLEtBQUssQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLG9CQUFvQixFQUFFLFVBQVUsQ0FBQyxDQUFDO1lBQ3BGLGdCQUFNLENBQUMsU0FBUyxDQUFDLGFBQWEsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUM5QyxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLG1CQUFtQixFQUFFO1FBQzVCLEVBQUUsQ0FBQywrQkFBK0IsRUFBRSxLQUFLO1lBQ3ZDLE1BQU0sSUFBSSxHQUFHLHdCQUF3QixDQUFDO1lBQ3RDLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUU5QyxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDMUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3hDLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLCtCQUErQixFQUFFLEtBQUs7WUFDdkMsTUFBTSxJQUFJLEdBQUcsbUJBQW1CLENBQUM7WUFDakMsZ0JBQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxFQUFFLDREQUE0RCxDQUFDLENBQUM7UUFDbkgsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsOENBQThDLEVBQUUsS0FBSztZQUN0RCxNQUFNLElBQUksR0FBRyxXQUFXLENBQUM7WUFDekIsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFDO1lBRTlDLE9BQU8sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUMxQyxPQUFPLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDMUMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxrQkFBa0IsRUFBRTtRQUMzQixFQUFFLENBQUMsNkRBQTZELEVBQUUsS0FBSztZQUNyRSxNQUFNLE9BQU8sR0FBRyxXQUFXLENBQUM7WUFDNUIsSUFBSSxNQUFNLEdBQXVCLFNBQVMsQ0FBQztZQUMzQyxJQUFJLElBQUksR0FBRyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUN2RCxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUMvQixNQUFNLEdBQUcsRUFBRSxDQUFDO1lBQ1osSUFBSSxHQUFHLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO1lBQ25ELElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ2pDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMsZ0JBQWdCLEVBQUU7UUFDekIsRUFBRSxDQUFDLGdDQUFnQyxFQUFFLEtBQUs7WUFDeEMsTUFBTSxlQUFlLEdBQUcsb0JBQW9CLENBQUM7WUFDN0MsTUFBTSxXQUFXLEdBQUcsV0FBVyxDQUFDO1lBQ2hDLEtBQUssQ0FBQyxjQUFjLENBQUMsZUFBZSxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUNoRSxLQUFLLENBQUMsY0FBYyxDQUFDLFdBQVcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDOUQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxtQkFBbUIsRUFBRTtRQUM1QixFQUFFLENBQUMsdUNBQXVDLEVBQUUsS0FBSztZQUMvQyxNQUFNLE9BQU8sR0FBRyxvQkFBb0IsQ0FBQztZQUNyQyxNQUFNLFdBQVcsR0FBRyxXQUFXLENBQUM7WUFDaEMsS0FBSyxDQUFDLGlCQUFpQixDQUFDLE9BQU8sRUFBRSxXQUFXLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7WUFFNUQsTUFBTSxRQUFRLEdBQUcsV0FBVyxDQUFDO1lBQzdCLE1BQU0sWUFBWSxHQUFHLFdBQVcsQ0FBQztZQUNqQyxLQUFLLENBQUMsaUJBQWlCLENBQUMsUUFBUSxFQUFFLFlBQVksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUU5RCxNQUFNLFFBQVEsR0FBRyxvQkFBb0IsQ0FBQztZQUN0QyxNQUFNLFlBQVksR0FBRyxXQUFXLENBQUM7WUFDakMsS0FBSyxDQUFDLGlCQUFpQixDQUFDLFFBQVEsRUFBRSxZQUFZLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7WUFFL0QsTUFBTSxRQUFRLEdBQUcsV0FBVyxDQUFDO1lBQzdCLE1BQU0sWUFBWSxHQUFHLFdBQVcsQ0FBQztZQUNqQyxLQUFLLENBQUMsaUJBQWlCLENBQUMsUUFBUSxFQUFFLFlBQVksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUUvRCxNQUFNLFFBQVEsR0FBRyxTQUFTLENBQUM7WUFDM0IsTUFBTSxZQUFZLEdBQUcsV0FBVyxDQUFDO1lBQ2pDLGdCQUFNLENBQUMsTUFBTSxDQUNYLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLEVBQUUsWUFBWSxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxFQUNwRSxJQUFJLE1BQU0sQ0FBQyxvQkFBb0IsUUFBUSxFQUFFLENBQUMsQ0FDM0MsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMsZUFBZSxFQUFFO1FBQ3hCLEVBQUUsQ0FBQyx3QkFBd0IsRUFBRSxLQUFLO1lBQ2hDLE1BQU0sS0FBSyxHQUFHLFVBQVUsQ0FBQztZQUN6QixLQUFLLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUN2QyxNQUFNLEtBQUssR0FBRyxFQUFFLENBQUM7WUFDakIsS0FBSyxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDeEMsTUFBTSxLQUFLLEdBQUcsU0FBUyxDQUFDO1lBQ3hCLHFDQUFxQztZQUNyQyxLQUFLLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUN4QyxNQUFNLEtBQUssR0FDVCwrSUFBK0ksQ0FBQztZQUNsSixLQUFLLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUMxQyxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLDZCQUE2QixFQUFFO1FBQ3RDLEVBQUUsQ0FBQyx1REFBdUQsRUFBRTtZQUMxRCxNQUFNLGNBQWMsR0FBRyxDQUFDLEdBQUcsRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxvQkFBb0IsQ0FBQyxDQUFDO1lBRXJGLEtBQUssTUFBTSxPQUFPLElBQUksY0FBYyxFQUFFLENBQUM7Z0JBQ3JDLEtBQUssQ0FBQywyQkFBMkIsQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQzlELENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQywyQ0FBMkMsRUFBRTtZQUM5QyxNQUFNLGdCQUFnQixHQUFHO2dCQUN2QixtSUFBbUk7Z0JBQ25JLG1CQUFtQjtnQkFDbkIsS0FBSztnQkFDTCxTQUFTO2dCQUNULEtBQUs7Z0JBQ0wsT0FBTztnQkFDUCxFQUFFO2dCQUNGLDRDQUE0QzthQUM3QyxDQUFDO1lBRUYsS0FBSyxNQUFNLE9BQU8sSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO2dCQUN2QyxLQUFLLENBQUMsMkJBQTJCLENBQUMsT0FBTyxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUMvRCxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxvQkFBb0IsRUFBRTtRQUM3QixNQUFNLHFCQUFxQixHQUFHLENBQUMsZUFBZSxHQUFHLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxHQUFHLGVBQWUsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3ZHLEVBQUUsQ0FBQyxpRUFBaUUsRUFBRTtZQUNwRSxNQUFNLFNBQVMsR0FBRyxxQkFBcUIsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzVDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxTQUFTLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDO1lBRXJELE1BQU0sVUFBVSxHQUFHLHFCQUFxQixDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDL0MsS0FBSyxDQUFDLGtCQUFrQixDQUFDLFVBQVUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDeEQsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsOENBQThDLEVBQUU7WUFDakQsTUFBTSxTQUFTLEdBQUcscUJBQXFCLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUMvQyxnQkFBTSxDQUFDLE1BQU0sQ0FDWCxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUMsa0JBQWtCLENBQUMsU0FBUyxDQUFDLEVBQ3pDLENBQUMsS0FBVSxFQUFFLEVBQUU7Z0JBQ2IsZ0JBQU0sQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsMEJBQTBCLENBQUMsQ0FBQyxDQUFDO2dCQUM5RCxPQUFPLElBQUksQ0FBQztZQUNkLENBQUMsQ0FDRixDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsdURBQXVELEVBQUU7WUFDMUQsTUFBTSxTQUFTLEdBQUcscUJBQXFCLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDOUMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLFNBQVMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDeEQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxvQkFBb0IsRUFBRTtRQUM3QixFQUFFLENBQUMsa0NBQWtDLEVBQUU7WUFDckMsTUFBTSxTQUFTLEdBQUcsc0JBQXNCLENBQUM7WUFDekMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLFNBQVMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDOUQsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsOENBQThDLEVBQUU7WUFDakQsTUFBTSxTQUFTLEdBQUcsWUFBWSxDQUFDO1lBQy9CLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxTQUFTLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsR0FBRyxZQUFZLENBQUMsQ0FBQztRQUM3RSxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyw4Q0FBOEMsRUFBRTtZQUNqRCxNQUFNLFNBQVMsR0FBRyxpQkFBaUIsQ0FBQztZQUNwQyxLQUFLLENBQUMsa0JBQWtCLENBQUMsU0FBUyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLEdBQUcsT0FBTyxDQUFDLENBQUM7UUFDeEUsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGFzc2VydCBmcm9tICdhc3NlcnQnO1xuaW1wb3J0IHNob3VsZCBmcm9tICdzaG91bGQnO1xuaW1wb3J0ICogYXMgc3RlbGxhciBmcm9tICdzdGVsbGFyLXNkayc7XG5pbXBvcnQgKiBhcyBVdGlscyBmcm9tICcuLi8uLi9zcmMvbGliL3V0aWxzJztcbmltcG9ydCAqIGFzIHRlc3REYXRhIGZyb20gJy4uL3Jlc291cmNlcy9oYmFyJztcbmltcG9ydCB7IGlzVmFsaWRFZDI1NTE5UHVibGljS2V5IH0gZnJvbSAnQGJpdGdvL3Nkay1jb3JlJztcblxuZGVzY3JpYmUoJ0hCQVIgdXRpbCBsaWJyYXJ5JywgZnVuY3Rpb24gKCkge1xuICBkZXNjcmliZSgnYWRkcmVzcycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIGFkZHJlc3NlcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHZhbGlkQWRkcmVzc2VzID0gWycwJywgJzAuMC4wJywgJzk5Ljk5Ljk5JywgJzAuMC40MTA5OCddO1xuICAgICAgY29uc3QgdmFsaWRBZGRyZXNzZXNXaXRoTWVtbyA9IFsnMC4wLjQxMDk4P21lbW9JZD00J107XG5cbiAgICAgIGZvciAoY29uc3QgYWRkcmVzcyBvZiB2YWxpZEFkZHJlc3Nlcykge1xuICAgICAgICBVdGlscy5pc1ZhbGlkQWRkcmVzcyhhZGRyZXNzKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgICAgfVxuXG4gICAgICBmb3IgKGNvbnN0IGFkZHJlc3Mgb2YgdmFsaWRBZGRyZXNzZXNXaXRoTWVtbykge1xuICAgICAgICBVdGlscy5pc1ZhbGlkQWRkcmVzcyhhZGRyZXNzKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHRvIHZhbGlkYXRlIGludmFsaWQgYWRkcmVzc2VzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgaW52YWxpZEFkZHJlc3NlcyA9IFsnMC4wJywgJzAuMC4wLjAnLCAnYWJjJywgJ2EuYi5jJywgJycsICcweDIzQzNFMjI3QkU5NzI4MUE3MEE1NDljN2REQjhkNUNhYWQzRTdDODQnXTtcbiAgICAgIGNvbnN0IGludmFsaWRBZGRyZXNzZXNXaXRoTWVtbyA9IFsnMC4wLjQxMDk4P21lbW9JZD1tP21lbW9JZD00J107XG5cbiAgICAgIGZvciAoY29uc3QgYWRkcmVzcyBvZiBpbnZhbGlkQWRkcmVzc2VzKSB7XG4gICAgICAgIHNob3VsZC5kb2VzTm90VGhyb3coKCkgPT4gVXRpbHMuaXNWYWxpZEFkZHJlc3MoYWRkcmVzcykpO1xuICAgICAgICBVdGlscy5pc1ZhbGlkQWRkcmVzcyhhZGRyZXNzKS5zaG91bGQuYmUuZmFsc2UoKTtcbiAgICAgIH1cblxuICAgICAgZm9yIChjb25zdCBhZGRyZXNzIG9mIGludmFsaWRBZGRyZXNzZXNXaXRoTWVtbykge1xuICAgICAgICBzaG91bGQuZG9lc05vdFRocm93KCgpID0+IFV0aWxzLmlzVmFsaWRBZGRyZXNzKGFkZHJlc3MpKTtcbiAgICAgICAgVXRpbHMuaXNWYWxpZEFkZHJlc3MoYWRkcmVzcykuc2hvdWxkLmJlLmZhbHNlKCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCd0cmFuc2FjdGlvbiBpZCcsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIHR4IGlkcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHZhbGlkSGFzaGVzID0gWycwLjAuMTQ2MjFAMTU5NTM3NDcyMy4zNTY5ODE2ODknXTtcblxuICAgICAgZm9yIChjb25zdCBoYXNoIG9mIHZhbGlkSGFzaGVzKSB7XG4gICAgICAgIFV0aWxzLmlzVmFsaWRUcmFuc2FjdGlvbklkKGhhc2gpLnNob3VsZC5iZS50cnVlKCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgdG8gdmFsaWRhdGUgaW52YWxpZCB0eCBpZHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBpbnZhbGlkSGFzaGVzID0gWycwLjAuMTQ2MjEnLCAnaW52YWxpZCcsICcnXTtcblxuICAgICAgZm9yIChjb25zdCBoYXNoIG9mIGludmFsaWRIYXNoZXMpIHtcbiAgICAgICAgVXRpbHMuaXNWYWxpZFRyYW5zYWN0aW9uSWQoaGFzaCkuc2hvdWxkLmJlLmZhbHNlKCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCd0cmFuc2FjdGlvbiB0aW1lc3RhbXAnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCB2YWxpZGF0ZSB0eCB0aW1lc3RhbXBzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdmFsaWRUaW1lc3RhbXBzID0gWycxNTk1Mzc0NzIzLjM1Njk4MTY4OScsICcxNTk1Mzc0NzIzJ107XG5cbiAgICAgIGZvciAoY29uc3QgdGltZXN0YW1wIG9mIHZhbGlkVGltZXN0YW1wcykge1xuICAgICAgICBVdGlscy5pc1ZhbGlkVGltZVN0cmluZyh0aW1lc3RhbXApLnNob3VsZC5iZS50cnVlKCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgdG8gdmFsaWRhdGUgaW52YWxpZCB0eCB0aW1lc3RhbXAnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBpbnZhbGlkVGltZXN0YW1wID0gWycwLjAuMTQ2MjEnLCAnaW52YWxpZCcsICcnXTtcblxuICAgICAgZm9yIChjb25zdCB0aW1lc3RhbXAgb2YgaW52YWxpZFRpbWVzdGFtcCkge1xuICAgICAgICBVdGlscy5pc1ZhbGlkVGltZVN0cmluZyh0aW1lc3RhbXApLnNob3VsZC5iZS5mYWxzZSgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnc2hvdWxkIHJlbW92ZSBwcmVmaXgnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ2Zyb20gYSBwcml2YXRlIGtleScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJhd1ByaXZhdGVLZXkgPSBVdGlscy5yZW1vdmVQcmVmaXgodGVzdERhdGEuZWQyNTUxOVByaXZLZXlQcmVmaXgsIHRlc3REYXRhLkFDQ09VTlRfMS5wcnZLZXlXaXRoUHJlZml4KTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwocmF3UHJpdmF0ZUtleSwgJzYyYjBiNjY5ZGUwYWI1ZTkxYjQzMjhlMTQzMTg1OWE1Y2E0N2U3NDI2ZTcwMTAxOTI3MmY1YzJkNTI4MjViMDEnKTtcbiAgICB9KTtcblxuICAgIGl0KCdmcm9tIGEgcHVibGljIGtleScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJhd1B1YmxpY0tleSA9IFV0aWxzLnJlbW92ZVByZWZpeCh0ZXN0RGF0YS5lZDI1NTE5UHViS2V5UHJlZml4LCB0ZXN0RGF0YS5BQ0NPVU5UXzEucHViS2V5V2l0aFByZWZpeCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHJhd1B1YmxpY0tleSwgJzVhOTExMWI1ZTY4ODFmZjIwYjkyNDNhNDJhYzFhOWE2N2ZhMTZjZDRmMDFlNThiYWIzMGMxZmU2MTFlYThjZjknKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3Nob3VsZCBjb252ZXJ0IGEgc3RlbGxhciBwdWInLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ2FuZCBnZXQgYmFjayBhIHZhbGlkIGVkIHB1YicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHN0ZWxsYXJQdWIgPSAnR0JWRVpUMjdaVUNNSkFCRjc2WElQUE83TTNLVUFCVlI0R1pOUEJBRDNZVFBYVVNEQTU3QU5STEQnO1xuICAgICAgY29uc3QgbmV3UHViID0gVXRpbHMuY29udmVydEZyb21TdGVsbGFyUHViKHN0ZWxsYXJQdWIpO1xuICAgICAgc2hvdWxkLmVxdWFsKGlzVmFsaWRFZDI1NTE5UHVibGljS2V5KG5ld1B1YiksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2FuZCBnZXQgYmFjayBhIHNwZWNpZmljIGVkIHB1YicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHN0ZWxsYXJQdWIgPSAnR0JWRVpUMjdaVUNNSkFCRjc2WElQUE83TTNLVUFCVlI0R1pOUEJBRDNZVFBYVVNEQTU3QU5STEQnO1xuICAgICAgY29uc3QgbmV3UHViID0gVXRpbHMuY29udmVydEZyb21TdGVsbGFyUHViKHN0ZWxsYXJQdWIpO1xuICAgICAgbmV3UHViLnNob3VsZC5lcXVhbCgnNmE0Y2NmNWZjZDA0YzQ4MDI1ZmZhZTg3YmRkZjY2ZDU0MDA2YjFlMWIyZDc4NDAzZGUyNmZiZDI0MzA3N2UwNicpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2FuZCBjcmVhdGUgYSB2YWxpZCBlZCBwdWIgdGhhdCBjYW4gYmUgdHJhbnNmb3JtZWQgYmFjayBpbnRvIGEgc3RlbGxhciBwdWInLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzdGVsbGFyUHViID0gJ0dCVkVaVDI3WlVDTUpBQkY3NlhJUFBPN00zS1VBQlZSNEdaTlBCQUQzWVRQWFVTREE1N0FOUkxEJztcblxuICAgICAgY29uc3QgbmV3UHViID0gVXRpbHMuY29udmVydEZyb21TdGVsbGFyUHViKHN0ZWxsYXJQdWIpO1xuICAgICAgY29uc3Qgc3RlbGxhckRlY29kZWQgPSBzdGVsbGFyLlN0cktleS5lbmNvZGVFZDI1NTE5UHVibGljS2V5KEJ1ZmZlci5mcm9tKG5ld1B1YiwgJ2hleCcpKTtcbiAgICAgIGNvbnN0IGJlZ2luU3RlbGxhcktleVBhaXIgPSBzdGVsbGFyLktleXBhaXIuZnJvbVB1YmxpY0tleShzdGVsbGFyUHViKTtcbiAgICAgIGNvbnN0IGVuZFN0ZWxsYXJLZXlQYWlyID0gc3RlbGxhci5LZXlwYWlyLmZyb21QdWJsaWNLZXkoc3RlbGxhckRlY29kZWQpO1xuXG4gICAgICBzaG91bGQuZXF1YWwoYmVnaW5TdGVsbGFyS2V5UGFpci5wdWJsaWNLZXkoKSwgZW5kU3RlbGxhcktleVBhaXIucHVibGljS2V5KCkpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnc2hvdWxkIHJldHVybiB0aGUgc2FtZSBrZXknLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ2Zyb20gYSBwcml2YXRlIGtleSB3aXRob3V0IHRoZSBwcmVmaXgnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCByYXdQcml2YXRlS2V5ID0gVXRpbHMucmVtb3ZlUHJlZml4KHRlc3REYXRhLmVkMjU1MTlQcml2S2V5UHJlZml4LCB0ZXN0RGF0YS5BQ0NPVU5UXzIucHJpdmF0ZUtleSk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHJhd1ByaXZhdGVLZXksIHRlc3REYXRhLkFDQ09VTlRfMi5wcml2YXRlS2V5KTtcbiAgICB9KTtcblxuICAgIGl0KCdmcm9tIGEgcHVibGljIGtleSB3aXRob3V0IHRoZSBwcmVmaXgnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCByYXdQdWJsaWNLZXkgPSBVdGlscy5yZW1vdmVQcmVmaXgodGVzdERhdGEuZWQyNTUxOVB1YktleVByZWZpeCwgdGVzdERhdGEuQUNDT1VOVF8yLnB1YmxpY0tleSk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHJhd1B1YmxpY0tleSwgdGVzdERhdGEuQUNDT1VOVF8yLnB1YmxpY0tleSk7XG4gICAgfSk7XG5cbiAgICBpdCgnZnJvbSBhIHB1YmxpYyBrZXkgd2l0aCBjaGFycyBvZiBwcmVmaXggaW4gdGhlIG1pZGRsZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHB1YmxpY0tleSA9ICc1OTJhNGZiYjcyNjNjNTlkNDUwZTY1MWQnICsgdGVzdERhdGEuZWQyNTUxOVB1YktleVByZWZpeCArICdmOTY2MjBkYzkyMDhlZTdjJztcbiAgICAgIGNvbnN0IHJhd1B1YmxpY0tleSA9IFV0aWxzLnJlbW92ZVByZWZpeCh0ZXN0RGF0YS5lZDI1NTE5UHViS2V5UHJlZml4LCBwdWJsaWNLZXkpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbChyYXdQdWJsaWNLZXksIHB1YmxpY0tleSk7XG4gICAgfSk7XG5cbiAgICBpdCgnZnJvbSBhIHByaXZhdGUga2V5IHdpdGggY2hhcnMgb2YgcHJlZml4IGluIHRoZSBtaWRkbGUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwcml2YXRlS2V5ID0gJzViYjcyNjAzZjIzN2MwOTknICsgdGVzdERhdGEuZWQyNTUxOVByaXZLZXlQcmVmaXggKyAnM2Y3OTczZDM3ZmRhZGUzYyc7XG4gICAgICBjb25zdCByYXdQcml2YXRlS2V5ID0gVXRpbHMucmVtb3ZlUHJlZml4KHRlc3REYXRhLmVkMjU1MTlQcml2S2V5UHJlZml4LCBwcml2YXRlS2V5KTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwocmF3UHJpdmF0ZUtleSwgcHJpdmF0ZUtleSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdnZXRBZGRyZXNzRGV0YWlscycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGdldCBtZW1vSWQgYW5kIGFkZHJlc3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBhZGRyID0gJzAuMC40MTA5OD9tZW1vSWQ9MjMyMzMnO1xuICAgICAgY29uc3QgZGV0YWlscyA9IFV0aWxzLmdldEFkZHJlc3NEZXRhaWxzKGFkZHIpO1xuXG4gICAgICBkZXRhaWxzLmFkZHJlc3Muc2hvdWxkLmVxdWFsKCcwLjAuNDEwOTgnKTtcbiAgICAgIGRldGFpbHMubWVtb0lkPy5zaG91bGQuZXF1YWwoJzIzMjMzJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IHdoZW4gbWVtb0lkPW51bGwnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBhZGRyID0gJzAuMC40MTA5OD9tZW1vSWQ9JztcbiAgICAgIGFzc2VydC50aHJvd3MoKCkgPT4gVXRpbHMuZ2V0QWRkcmVzc0RldGFpbHMoYWRkciksIC9pbnZhbGlkIGFkZHJlc3M6ICcwLjAuNDEwOThcXD9tZW1vSWQ9JywgbWVtb0lkIGlzIG5vdCB2YWxpZC8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBnZXQgbWVtb0lkIGFuZCBhZGRyZXNzIHdoZW4gbm8gbWVtb0lkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYWRkciA9ICcwLjAuNDEwOTgnO1xuICAgICAgY29uc3QgZGV0YWlscyA9IFV0aWxzLmdldEFkZHJlc3NEZXRhaWxzKGFkZHIpO1xuXG4gICAgICBkZXRhaWxzLmFkZHJlc3Muc2hvdWxkLmVxdWFsKCcwLjAuNDEwOTgnKTtcbiAgICAgIGRldGFpbHMubWVtb0lkPy5zaG91bGQuZXF1YWwodW5kZWZpbmVkKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ25vcm1hbGl6ZUFkZHJlc3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBidWlsZCB3aXRob3V0IGEgbWVtb0lkIGlmIGl0cyBtaXNzaW5nIGZvciBhbiBhZGRyZXNzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYWRkcmVzcyA9ICcwLjAuNDEwOTgnO1xuICAgICAgbGV0IG1lbW9JZDogc3RyaW5nIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuICAgICAgbGV0IG5vcm0gPSBVdGlscy5ub3JtYWxpemVBZGRyZXNzKHsgYWRkcmVzcywgbWVtb0lkIH0pO1xuICAgICAgbm9ybS5zaG91bGQuZXF1YWwoJzAuMC40MTA5OCcpO1xuICAgICAgbWVtb0lkID0gJyc7XG4gICAgICBub3JtID0gVXRpbHMubm9ybWFsaXplQWRkcmVzcyh7IGFkZHJlc3MsIG1lbW9JZCB9KTtcbiAgICAgIG5vcm0uc2hvdWxkLmVxdWFsKCcwLjAuNDEwOTgnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2dldEJhc2VBZGRyZXNzJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRoZSBiYXNlIGFkZHJlc3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBhZGRyZXNzV2l0aE1lbW8gPSAnMC4wLjQxMDk4P21lbW9JZD0xJztcbiAgICAgIGNvbnN0IGJhc2VBZGRyZXNzID0gJzAuMC40MTA5OCc7XG4gICAgICBVdGlscy5nZXRCYXNlQWRkcmVzcyhhZGRyZXNzV2l0aE1lbW8pLnNob3VsZC5lcXVhbChiYXNlQWRkcmVzcyk7XG4gICAgICBVdGlscy5nZXRCYXNlQWRkcmVzcyhiYXNlQWRkcmVzcykuc2hvdWxkLmVxdWFsKGJhc2VBZGRyZXNzKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2lzU2FtZUJhc2VBZGRyZXNzJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgdmFsaWRhdGUgaWYgYmFzZSBhZGRyZXNzIG1hdGNoJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYWRkcmVzcyA9ICcwLjAuNDEwOTg/bWVtb0lkPTEnO1xuICAgICAgY29uc3QgYmFzZUFkZHJlc3MgPSAnMC4wLjQxMDk4JztcbiAgICAgIFV0aWxzLmlzU2FtZUJhc2VBZGRyZXNzKGFkZHJlc3MsIGJhc2VBZGRyZXNzKS5zaG91bGQudHJ1ZSgpO1xuXG4gICAgICBjb25zdCBhZGRyZXNzMiA9ICcwLjAuNDEwOTgnO1xuICAgICAgY29uc3QgYmFzZUFkZHJlc3MyID0gJzAuMC40MTA5OCc7XG4gICAgICBVdGlscy5pc1NhbWVCYXNlQWRkcmVzcyhhZGRyZXNzMiwgYmFzZUFkZHJlc3MyKS5zaG91bGQudHJ1ZSgpO1xuXG4gICAgICBjb25zdCBhZGRyZXNzMyA9ICcwLjAuNDEwOTk/bWVtb0lkPTEnO1xuICAgICAgY29uc3QgYmFzZUFkZHJlc3MzID0gJzAuMC40MTA5OCc7XG4gICAgICBVdGlscy5pc1NhbWVCYXNlQWRkcmVzcyhhZGRyZXNzMywgYmFzZUFkZHJlc3MzKS5zaG91bGQuZmFsc2UoKTtcblxuICAgICAgY29uc3QgYWRkcmVzczQgPSAnMC4wLjQxMDk5JztcbiAgICAgIGNvbnN0IGJhc2VBZGRyZXNzNCA9ICcwLjAuNDEwOTgnO1xuICAgICAgVXRpbHMuaXNTYW1lQmFzZUFkZHJlc3MoYWRkcmVzczQsIGJhc2VBZGRyZXNzNCkuc2hvdWxkLmZhbHNlKCk7XG5cbiAgICAgIGNvbnN0IGFkZHJlc3M1ID0gJzAuMC4wLjAnO1xuICAgICAgY29uc3QgYmFzZUFkZHJlc3M1ID0gJzAuMC40MTA5OCc7XG4gICAgICBhc3NlcnQudGhyb3dzKFxuICAgICAgICAoKSA9PiBVdGlscy5pc1NhbWVCYXNlQWRkcmVzcyhhZGRyZXNzNSwgYmFzZUFkZHJlc3M1KS5zaG91bGQuZmFsc2UoKSxcbiAgICAgICAgbmV3IFJlZ0V4cChgaW52YWxpZCBhZGRyZXNzOiAke2FkZHJlc3M1fWApXG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnaXNWYWxpZE1lbW9JZCcsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIG1lbW9JZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG1lbW8xID0gJ3Rlc3RtZW1vJztcbiAgICAgIFV0aWxzLmlzVmFsaWRNZW1vKG1lbW8xKS5zaG91bGQudHJ1ZSgpO1xuICAgICAgY29uc3QgbWVtbzIgPSAnJztcbiAgICAgIFV0aWxzLmlzVmFsaWRNZW1vKG1lbW8yKS5zaG91bGQuZmFsc2UoKTtcbiAgICAgIGNvbnN0IG1lbW8zID0gdW5kZWZpbmVkO1xuICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciB0ZXN0aW5nIGZvciBlcnJvclxuICAgICAgVXRpbHMuaXNWYWxpZE1lbW8obWVtbzMpLnNob3VsZC5mYWxzZSgpO1xuICAgICAgY29uc3QgbWVtbzQgPVxuICAgICAgICAnbWVtb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vJztcbiAgICAgIFV0aWxzLmlzVmFsaWRNZW1vKG1lbW80KS5zaG91bGQuZmFsc2UoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2lzVmFsaWRBZGRyZXNzV2l0aFBheW1lbnRJZCcsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIGFkZHJlc3NlcyB3aXRoIGFuZCB3aXRob3V0IHBheW1lbnQgaWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB2YWxpZEFkZHJlc3NlcyA9IFsnMCcsICcwLjAuMCcsICc5OS45OS45OScsICcwLjAuNDEwOTgnLCAnMC4wLjQxMDk4P21lbW9JZD00J107XG5cbiAgICAgIGZvciAoY29uc3QgYWRkcmVzcyBvZiB2YWxpZEFkZHJlc3Nlcykge1xuICAgICAgICBVdGlscy5pc1ZhbGlkQWRkcmVzc1dpdGhQYXltZW50SWQoYWRkcmVzcykuc2hvdWxkLmJlLnRydWUoKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB0byB2YWxpZGF0ZSBpbnZhbGlkIGFkZHJlc3NlcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGludmFsaWRBZGRyZXNzZXMgPSBbXG4gICAgICAgICcwLjAuNDEwOTg/bWVtb0lkPW1lbW9vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb28nLFxuICAgICAgICAnMC4wLjQxMDk4P21lbW9JZD0nLFxuICAgICAgICAnMC4wJyxcbiAgICAgICAgJzAuMC4wLjAnLFxuICAgICAgICAnYWJjJyxcbiAgICAgICAgJ2EuYi5jJyxcbiAgICAgICAgJycsXG4gICAgICAgICcweDIzQzNFMjI3QkU5NzI4MUE3MEE1NDljN2REQjhkNUNhYWQzRTdDODQnLFxuICAgICAgXTtcblxuICAgICAgZm9yIChjb25zdCBhZGRyZXNzIG9mIGludmFsaWRBZGRyZXNzZXMpIHtcbiAgICAgICAgVXRpbHMuaXNWYWxpZEFkZHJlc3NXaXRoUGF5bWVudElkKGFkZHJlc3MpLnNob3VsZC5iZS5mYWxzZSgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnc2hvdWxkQnJvYWRjYXN0Tm93JywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGdldFRpbWVzdGFtcEluU2Vjb25kcyA9IChzZWNvbmRzVG9DaGFuZ2UgPSAwKSA9PiAoRGF0ZS5ub3coKSAvIDEwMDAgKyBzZWNvbmRzVG9DaGFuZ2UpLnRvRml4ZWQoKTtcbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGlmIHRoZSB0aW1lc3RhbXAgaXMgaW4gdGhlIHZhbGlkIHRpbWUgd2luZG93JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdGltZXN0YW1wID0gZ2V0VGltZXN0YW1wSW5TZWNvbmRzKC02KTtcbiAgICAgIFV0aWxzLnNob3VsZEJyb2FkY2FzdE5vdyh0aW1lc3RhbXApLnNob3VsZC5iZS50cnVlKCk7XG5cbiAgICAgIGNvbnN0IHRpbWVzdGFtcDIgPSBnZXRUaW1lc3RhbXBJblNlY29uZHMoLTE3Myk7XG4gICAgICBVdGlscy5zaG91bGRCcm9hZGNhc3ROb3codGltZXN0YW1wMikuc2hvdWxkLmJlLnRydWUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgaWYgdGhlIHRpbWVzdGFtcCBpcyBpbiB0aGUgcGFzdCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHRpbWVzdGFtcCA9IGdldFRpbWVzdGFtcEluU2Vjb25kcygtMTAwMCk7XG4gICAgICBhc3NlcnQudGhyb3dzKFxuICAgICAgICAoKSA9PiBVdGlscy5zaG91bGRCcm9hZGNhc3ROb3codGltZXN0YW1wKSxcbiAgICAgICAgKGVycm9yOiBhbnkpID0+IHtcbiAgICAgICAgICBhc3NlcnQub2soZXJyb3IubWVzc2FnZS5pbmNsdWRlcygnc3RhcnRUaW1lIHdpbmRvdyBleHBpcmVkJykpO1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gZmFsc2UgaWYgdGhlIHRpbWVzdGFtcCBpcyBpbiB0aGUgZnV0dXJlJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdGltZXN0YW1wID0gZ2V0VGltZXN0YW1wSW5TZWNvbmRzKDEwMDApO1xuICAgICAgVXRpbHMuc2hvdWxkQnJvYWRjYXN0Tm93KHRpbWVzdGFtcCkuc2hvdWxkLmJlLmZhbHNlKCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdub3JtYWxpemVTdGFydHRpbWUnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdGhlIHNhbWUgdGltZXN0YW1wJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdGltZXN0YW1wID0gJzE1OTUzNzQ3MjMuMzU2OTgxNjg5JztcbiAgICAgIFV0aWxzLm5vcm1hbGl6ZVN0YXJ0dGltZSh0aW1lc3RhbXApLnNob3VsZC5lcXVhbCh0aW1lc3RhbXApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdGhlIHRpbWVzdGFtcCB3aXRoIG5hbm9zZWNvbmRzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdGltZXN0YW1wID0gJzE1OTUzNzQ3MjMnO1xuICAgICAgVXRpbHMubm9ybWFsaXplU3RhcnR0aW1lKHRpbWVzdGFtcCkuc2hvdWxkLmVxdWFsKHRpbWVzdGFtcCArICcuMDAwMDAwMDAwJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiB0aGUgdGltZXN0YW1wIHdpdGggbmFub3NlY29uZHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0aW1lc3RhbXAgPSAnMTU5NTM3NDcyMy4wMTQ1JztcbiAgICAgIFV0aWxzLm5vcm1hbGl6ZVN0YXJ0dGltZSh0aW1lc3RhbXApLnNob3VsZC5lcXVhbCh0aW1lc3RhbXAgKyAnMDAwMDAnKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==Выполнить команду
Для локальной разработки. Не используйте в интернете!